Andrew Walbran | eef9820 | 2022-04-27 16:23:06 +0000 | [diff] [blame] | 1 | // Copyright 2022, The Android Open Source Project |
| 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | // you may not use this file except in compliance with the License. |
| 5 | // You may obtain a copy of the License at |
| 6 | // |
| 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | // See the License for the specific language governing permissions and |
| 13 | // limitations under the License. |
| 14 | |
| 15 | //! VM bootloader example. |
| 16 | |
| 17 | #![no_main] |
| 18 | #![no_std] |
| 19 | |
| 20 | mod exceptions; |
Andrew Walbran | 153aad9 | 2022-06-28 15:51:13 +0000 | [diff] [blame] | 21 | mod layout; |
Andrew Walbran | 8217d06 | 2022-11-22 16:56:18 +0000 | [diff] [blame] | 22 | mod pci; |
Andrew Walbran | eef9820 | 2022-04-27 16:23:06 +0000 | [diff] [blame] | 23 | |
Andrew Walbran | f7b6dc8 | 2022-04-20 16:24:30 +0000 | [diff] [blame] | 24 | extern crate alloc; |
| 25 | |
Pierre-Clément Tosi | 67108c3 | 2023-06-30 11:04:02 +0000 | [diff] [blame] | 26 | use crate::layout::{boot_stack_range, print_addresses, DEVICE_REGION}; |
Andrew Walbran | 730375d | 2022-12-21 14:04:34 +0000 | [diff] [blame] | 27 | use crate::pci::{check_pci, get_bar_region}; |
Alice Wang | cee2c65 | 2023-07-05 09:16:52 +0000 | [diff] [blame] | 28 | use aarch64_paging::paging::MemoryRegion; |
| 29 | use aarch64_paging::MapError; |
Andrew Walbran | f7b6dc8 | 2022-04-20 16:24:30 +0000 | [diff] [blame] | 30 | use alloc::{vec, vec::Vec}; |
Charisee | e5b7834 | 2024-04-08 17:59:31 +0000 | [diff] [blame] | 31 | use core::ptr::addr_of_mut; |
Pierre-Clément Tosi | 1bf532b | 2023-11-13 11:06:20 +0000 | [diff] [blame] | 32 | use cstr::cstr; |
Andrew Walbran | 730375d | 2022-12-21 14:04:34 +0000 | [diff] [blame] | 33 | use fdtpci::PciInfo; |
David Brazdil | 1baa9a9 | 2022-06-28 14:47:50 +0100 | [diff] [blame] | 34 | use libfdt::Fdt; |
Jakob Vukalovic | ef99629 | 2023-04-13 14:28:34 +0000 | [diff] [blame] | 35 | use log::{debug, error, info, trace, warn, LevelFilter}; |
Alice Wang | a3931aa | 2023-07-05 12:52:09 +0000 | [diff] [blame] | 36 | use vmbase::{ |
Pierre-Clément Tosi | 1bf532b | 2023-11-13 11:06:20 +0000 | [diff] [blame] | 37 | bionic, configure_heap, |
Pierre-Clément Tosi | 67108c3 | 2023-06-30 11:04:02 +0000 | [diff] [blame] | 38 | layout::{dtb_range, rodata_range, scratch_range, text_range}, |
| 39 | linker, logger, main, |
Alice Wang | cee2c65 | 2023-07-05 09:16:52 +0000 | [diff] [blame] | 40 | memory::{PageTable, SIZE_64KB}, |
Alice Wang | a3931aa | 2023-07-05 12:52:09 +0000 | [diff] [blame] | 41 | }; |
Andrew Walbran | eef9820 | 2022-04-27 16:23:06 +0000 | [diff] [blame] | 42 | |
Andrew Walbran | 5d4e1c9 | 2022-04-12 14:30:54 +0000 | [diff] [blame] | 43 | static INITIALISED_DATA: [u32; 4] = [1, 2, 3, 4]; |
| 44 | static mut ZEROED_DATA: [u32; 10] = [0; 10]; |
| 45 | static mut MUTABLE_DATA: [u32; 4] = [1, 2, 3, 4]; |
| 46 | |
Andrew Walbran | eef9820 | 2022-04-27 16:23:06 +0000 | [diff] [blame] | 47 | main!(main); |
Pierre-Clément Tosi | 6a4808c | 2023-06-29 09:19:38 +0000 | [diff] [blame] | 48 | configure_heap!(SIZE_64KB); |
Andrew Walbran | eef9820 | 2022-04-27 16:23:06 +0000 | [diff] [blame] | 49 | |
Alice Wang | cee2c65 | 2023-07-05 09:16:52 +0000 | [diff] [blame] | 50 | fn init_page_table(pci_bar_range: &MemoryRegion) -> Result<(), MapError> { |
| 51 | let mut page_table = PageTable::default(); |
| 52 | |
| 53 | page_table.map_device(&DEVICE_REGION)?; |
| 54 | page_table.map_code(&text_range().into())?; |
| 55 | page_table.map_rodata(&rodata_range().into())?; |
| 56 | page_table.map_data(&scratch_range().into())?; |
| 57 | page_table.map_data(&boot_stack_range().into())?; |
| 58 | page_table.map_rodata(&dtb_range().into())?; |
| 59 | page_table.map_device(pci_bar_range)?; |
| 60 | |
| 61 | info!("Activating IdMap..."); |
| 62 | // SAFETY: page_table duplicates the static mappings for everything that the Rust code is |
| 63 | // aware of so activating it shouldn't have any visible effect. |
| 64 | unsafe { |
| 65 | page_table.activate(); |
| 66 | } |
| 67 | info!("Activated."); |
| 68 | |
| 69 | Ok(()) |
| 70 | } |
| 71 | |
Andrew Walbran | eef9820 | 2022-04-27 16:23:06 +0000 | [diff] [blame] | 72 | /// Entry point for VM bootloader. |
Andrew Walbran | e03395a | 2022-04-29 15:15:49 +0000 | [diff] [blame] | 73 | pub fn main(arg0: u64, arg1: u64, arg2: u64, arg3: u64) { |
Pierre-Clément Tosi | d330548 | 2023-06-29 15:03:48 +0000 | [diff] [blame] | 74 | log::set_max_level(LevelFilter::Debug); |
David Brazdil | b41aa8f | 2022-07-05 12:41:00 +0100 | [diff] [blame] | 75 | |
Jakob Vukalovic | ef99629 | 2023-04-13 14:28:34 +0000 | [diff] [blame] | 76 | info!("Hello world"); |
David Brazdil | b41aa8f | 2022-07-05 12:41:00 +0100 | [diff] [blame] | 77 | info!("x0={:#018x}, x1={:#018x}, x2={:#018x}, x3={:#018x}", arg0, arg1, arg2, arg3); |
Andrew Walbran | 6261cf4 | 2022-04-12 13:26:52 +0000 | [diff] [blame] | 78 | print_addresses(); |
Andrew Walbran | 153aad9 | 2022-06-28 15:51:13 +0000 | [diff] [blame] | 79 | assert_eq!(arg0, dtb_range().start.0 as u64); |
Andrew Walbran | 5d4e1c9 | 2022-04-12 14:30:54 +0000 | [diff] [blame] | 80 | check_data(); |
David Brazdil | a51c6f0 | 2022-10-12 09:51:48 +0000 | [diff] [blame] | 81 | check_stack_guard(); |
Andrew Walbran | 8217d06 | 2022-11-22 16:56:18 +0000 | [diff] [blame] | 82 | |
| 83 | info!("Checking FDT..."); |
| 84 | let fdt = dtb_range(); |
Andrew Walbran | 4784280 | 2023-07-05 16:56:08 +0000 | [diff] [blame] | 85 | let fdt_size = fdt.end.0 - fdt.start.0; |
| 86 | // SAFETY: The DTB range is valid, writable memory, and we don't construct any aliases to it. |
| 87 | let fdt = unsafe { core::slice::from_raw_parts_mut(fdt.start.0 as *mut u8, fdt_size) }; |
Andrew Walbran | 8217d06 | 2022-11-22 16:56:18 +0000 | [diff] [blame] | 88 | let fdt = Fdt::from_mut_slice(fdt).unwrap(); |
| 89 | info!("FDT passed verification."); |
| 90 | check_fdt(fdt); |
| 91 | |
Andrew Walbran | 730375d | 2022-12-21 14:04:34 +0000 | [diff] [blame] | 92 | let pci_info = PciInfo::from_fdt(fdt).unwrap(); |
| 93 | debug!("Found PCI CAM at {:#x}-{:#x}", pci_info.cam_range.start, pci_info.cam_range.end); |
Andrew Walbran | 8217d06 | 2022-11-22 16:56:18 +0000 | [diff] [blame] | 94 | |
| 95 | modify_fdt(fdt); |
Andrew Walbran | f7b6dc8 | 2022-04-20 16:24:30 +0000 | [diff] [blame] | 96 | |
Andrew Walbran | f7b6dc8 | 2022-04-20 16:24:30 +0000 | [diff] [blame] | 97 | check_alloc(); |
Andrew Walbran | 1356454 | 2022-04-20 16:29:45 +0000 | [diff] [blame] | 98 | |
Alice Wang | cee2c65 | 2023-07-05 09:16:52 +0000 | [diff] [blame] | 99 | init_page_table(&get_bar_region(&pci_info)).unwrap(); |
Andrew Walbran | 1356454 | 2022-04-20 16:29:45 +0000 | [diff] [blame] | 100 | |
| 101 | check_data(); |
David Brazdil | 9a83e61 | 2022-09-27 17:38:10 +0000 | [diff] [blame] | 102 | check_dice(); |
Andrew Walbran | 8217d06 | 2022-11-22 16:56:18 +0000 | [diff] [blame] | 103 | |
Andrew Walbran | 4784280 | 2023-07-05 16:56:08 +0000 | [diff] [blame] | 104 | // SAFETY: This is the only place where `make_pci_root` is called. |
Andrew Walbran | 730375d | 2022-12-21 14:04:34 +0000 | [diff] [blame] | 105 | let mut pci_root = unsafe { pci_info.make_pci_root() }; |
| 106 | check_pci(&mut pci_root); |
Jakob Vukalovic | ef99629 | 2023-04-13 14:28:34 +0000 | [diff] [blame] | 107 | |
| 108 | emit_suppressed_log(); |
Andrew Walbran | 1356454 | 2022-04-20 16:29:45 +0000 | [diff] [blame] | 109 | } |
| 110 | |
David Brazdil | a51c6f0 | 2022-10-12 09:51:48 +0000 | [diff] [blame] | 111 | fn check_stack_guard() { |
David Brazdil | a51c6f0 | 2022-10-12 09:51:48 +0000 | [diff] [blame] | 112 | info!("Testing stack guard"); |
Pierre-Clément Tosi | 67108c3 | 2023-06-30 11:04:02 +0000 | [diff] [blame] | 113 | // SAFETY: No concurrency issue should occur when running these tests. |
| 114 | let stack_guard = unsafe { bionic::TLS.stack_guard }; |
| 115 | assert_ne!(stack_guard, 0); |
Pierre-Clément Tosi | 62ffc0d | 2023-06-30 09:31:56 +0000 | [diff] [blame] | 116 | // Check that a NULL-terminating value is added for C functions consuming strings from stack. |
| 117 | assert_eq!(stack_guard.to_ne_bytes().last(), Some(&0)); |
Pierre-Clément Tosi | 67108c3 | 2023-06-30 11:04:02 +0000 | [diff] [blame] | 118 | // Check that the TLS and guard are properly accessible from the dedicated register. |
| 119 | assert_eq!(stack_guard, bionic::__get_tls().stack_guard); |
| 120 | // Check that the LLVM __stack_chk_guard alias is also properly set up. |
| 121 | assert_eq!( |
| 122 | stack_guard, |
| 123 | // SAFETY: No concurrency issue should occur when running these tests. |
| 124 | unsafe { linker::__stack_chk_guard }, |
| 125 | ); |
David Brazdil | a51c6f0 | 2022-10-12 09:51:48 +0000 | [diff] [blame] | 126 | } |
| 127 | |
Andrew Walbran | 5d4e1c9 | 2022-04-12 14:30:54 +0000 | [diff] [blame] | 128 | fn check_data() { |
Pierre-Clément Tosi | 581e9b6 | 2022-10-27 16:21:13 +0100 | [diff] [blame] | 129 | info!("INITIALISED_DATA: {:?}", INITIALISED_DATA.as_ptr()); |
Andrew Walbran | 4784280 | 2023-07-05 16:56:08 +0000 | [diff] [blame] | 130 | // SAFETY: We only print the addresses of the static mutable variable, not actually access it. |
Pierre-Clément Tosi | 70b580c | 2023-07-07 16:26:45 +0000 | [diff] [blame] | 131 | info!("ZEROED_DATA: {:?}", unsafe { ZEROED_DATA.as_ptr() }); |
Andrew Walbran | 4784280 | 2023-07-05 16:56:08 +0000 | [diff] [blame] | 132 | // SAFETY: We only print the addresses of the static mutable variable, not actually access it. |
Pierre-Clément Tosi | 70b580c | 2023-07-07 16:26:45 +0000 | [diff] [blame] | 133 | info!("MUTABLE_DATA: {:?}", unsafe { MUTABLE_DATA.as_ptr() }); |
Andrew Walbran | 5d4e1c9 | 2022-04-12 14:30:54 +0000 | [diff] [blame] | 134 | |
| 135 | assert_eq!(INITIALISED_DATA[0], 1); |
| 136 | assert_eq!(INITIALISED_DATA[1], 2); |
| 137 | assert_eq!(INITIALISED_DATA[2], 3); |
| 138 | assert_eq!(INITIALISED_DATA[3], 4); |
| 139 | |
Andrew Walbran | 4784280 | 2023-07-05 16:56:08 +0000 | [diff] [blame] | 140 | // SAFETY: Nowhere else in the program accesses this static mutable variable, so there is no |
| 141 | // chance of concurrent access. |
Charisee | e5b7834 | 2024-04-08 17:59:31 +0000 | [diff] [blame] | 142 | let zeroed_data = unsafe { &mut *addr_of_mut!(ZEROED_DATA) }; |
Andrew Walbran | 4784280 | 2023-07-05 16:56:08 +0000 | [diff] [blame] | 143 | // SAFETY: Nowhere else in the program accesses this static mutable variable, so there is no |
| 144 | // chance of concurrent access. |
Charisee | e5b7834 | 2024-04-08 17:59:31 +0000 | [diff] [blame] | 145 | let mutable_data = unsafe {&mut *addr_of_mut!(MUTABLE_DATA) }; |
Andrew Walbran | 5d4e1c9 | 2022-04-12 14:30:54 +0000 | [diff] [blame] | 146 | |
Pierre-Clément Tosi | 70b580c | 2023-07-07 16:26:45 +0000 | [diff] [blame] | 147 | for element in zeroed_data.iter() { |
| 148 | assert_eq!(*element, 0); |
Andrew Walbran | 5d4e1c9 | 2022-04-12 14:30:54 +0000 | [diff] [blame] | 149 | } |
Charisee | e5b7834 | 2024-04-08 17:59:31 +0000 | [diff] [blame] | 150 | |
Pierre-Clément Tosi | 70b580c | 2023-07-07 16:26:45 +0000 | [diff] [blame] | 151 | zeroed_data[0] = 13; |
| 152 | assert_eq!(zeroed_data[0], 13); |
| 153 | zeroed_data[0] = 0; |
| 154 | assert_eq!(zeroed_data[0], 0); |
| 155 | |
| 156 | assert_eq!(mutable_data[0], 1); |
| 157 | assert_eq!(mutable_data[1], 2); |
| 158 | assert_eq!(mutable_data[2], 3); |
| 159 | assert_eq!(mutable_data[3], 4); |
| 160 | mutable_data[0] += 41; |
| 161 | assert_eq!(mutable_data[0], 42); |
| 162 | mutable_data[0] -= 41; |
| 163 | assert_eq!(mutable_data[0], 1); |
| 164 | |
David Brazdil | b41aa8f | 2022-07-05 12:41:00 +0100 | [diff] [blame] | 165 | info!("Data looks good"); |
Charisee | e5b7834 | 2024-04-08 17:59:31 +0000 | [diff] [blame] | 166 | |
Andrew Walbran | 5d4e1c9 | 2022-04-12 14:30:54 +0000 | [diff] [blame] | 167 | } |
| 168 | |
Andrew Walbran | 8217d06 | 2022-11-22 16:56:18 +0000 | [diff] [blame] | 169 | fn check_fdt(reader: &Fdt) { |
Alice Wang | 2422bdc | 2023-06-12 08:37:55 +0000 | [diff] [blame] | 170 | for reg in reader.memory().unwrap() { |
David Brazdil | 1baa9a9 | 2022-06-28 14:47:50 +0100 | [diff] [blame] | 171 | info!("memory @ {reg:#x?}"); |
| 172 | } |
| 173 | |
Pierre-Clément Tosi | 8ecc78b | 2023-06-13 12:41:13 +0000 | [diff] [blame] | 174 | let compatible = cstr!("ns16550a"); |
Pierre-Clément Tosi | 41c158e | 2022-11-21 19:16:25 +0000 | [diff] [blame] | 175 | |
| 176 | for c in reader.compatible_nodes(compatible).unwrap() { |
Pierre-Clément Tosi | b244d93 | 2022-11-24 16:45:53 +0000 | [diff] [blame] | 177 | let reg = c.reg().unwrap().unwrap().next().unwrap(); |
Pierre-Clément Tosi | 41c158e | 2022-11-21 19:16:25 +0000 | [diff] [blame] | 178 | info!("node compatible with '{}' at {reg:?}", compatible.to_str().unwrap()); |
| 179 | } |
Andrew Walbran | 8217d06 | 2022-11-22 16:56:18 +0000 | [diff] [blame] | 180 | } |
Pierre-Clément Tosi | 41c158e | 2022-11-21 19:16:25 +0000 | [diff] [blame] | 181 | |
Andrew Walbran | 8217d06 | 2022-11-22 16:56:18 +0000 | [diff] [blame] | 182 | fn modify_fdt(writer: &mut Fdt) { |
Pierre-Clément Tosi | 1b0d890 | 2022-11-21 18:16:59 +0000 | [diff] [blame] | 183 | writer.unpack().unwrap(); |
| 184 | info!("FDT successfully unpacked."); |
| 185 | |
Pierre-Clément Tosi | 8ecc78b | 2023-06-13 12:41:13 +0000 | [diff] [blame] | 186 | let path = cstr!("/memory"); |
Pierre-Clément Tosi | a3c4ec3 | 2024-02-15 20:05:15 +0000 | [diff] [blame] | 187 | let node = writer.node_mut(path).unwrap().unwrap(); |
Pierre-Clément Tosi | 8ecc78b | 2023-06-13 12:41:13 +0000 | [diff] [blame] | 188 | let name = cstr!("child"); |
Pierre-Clément Tosi | 1b0d890 | 2022-11-21 18:16:59 +0000 | [diff] [blame] | 189 | let mut child = node.add_subnode(name).unwrap(); |
| 190 | info!("Created subnode '{}/{}'.", path.to_str().unwrap(), name.to_str().unwrap()); |
| 191 | |
Pierre-Clément Tosi | 8ecc78b | 2023-06-13 12:41:13 +0000 | [diff] [blame] | 192 | let name = cstr!("str-property"); |
Pierre-Clément Tosi | 1b0d890 | 2022-11-21 18:16:59 +0000 | [diff] [blame] | 193 | child.appendprop(name, b"property-value\0").unwrap(); |
| 194 | info!("Appended property '{}'.", name.to_str().unwrap()); |
| 195 | |
Pierre-Clément Tosi | 8ecc78b | 2023-06-13 12:41:13 +0000 | [diff] [blame] | 196 | let name = cstr!("pair-property"); |
Pierre-Clément Tosi | 1b0d890 | 2022-11-21 18:16:59 +0000 | [diff] [blame] | 197 | let addr = 0x0123_4567u64; |
| 198 | let size = 0x89ab_cdefu64; |
| 199 | child.appendprop_addrrange(name, addr, size).unwrap(); |
| 200 | info!("Appended property '{}'.", name.to_str().unwrap()); |
| 201 | |
| 202 | let writer = child.fdt(); |
| 203 | writer.pack().unwrap(); |
| 204 | info!("FDT successfully packed."); |
| 205 | |
David Brazdil | 1baa9a9 | 2022-06-28 14:47:50 +0100 | [diff] [blame] | 206 | info!("FDT checks done."); |
| 207 | } |
| 208 | |
Andrew Walbran | f7b6dc8 | 2022-04-20 16:24:30 +0000 | [diff] [blame] | 209 | fn check_alloc() { |
David Brazdil | b41aa8f | 2022-07-05 12:41:00 +0100 | [diff] [blame] | 210 | info!("Allocating a Vec..."); |
Andrew Walbran | f7b6dc8 | 2022-04-20 16:24:30 +0000 | [diff] [blame] | 211 | let mut vector: Vec<u32> = vec![1, 2, 3, 4]; |
| 212 | assert_eq!(vector[0], 1); |
| 213 | assert_eq!(vector[1], 2); |
| 214 | assert_eq!(vector[2], 3); |
| 215 | assert_eq!(vector[3], 4); |
| 216 | vector[2] = 42; |
| 217 | assert_eq!(vector[2], 42); |
David Brazdil | b41aa8f | 2022-07-05 12:41:00 +0100 | [diff] [blame] | 218 | info!("Vec seems to work."); |
Andrew Walbran | f7b6dc8 | 2022-04-20 16:24:30 +0000 | [diff] [blame] | 219 | } |
David Brazdil | 9a83e61 | 2022-09-27 17:38:10 +0000 | [diff] [blame] | 220 | |
| 221 | fn check_dice() { |
| 222 | info!("Testing DICE integration..."); |
Alice Wang | cb9d2f9 | 2023-02-06 10:29:00 +0000 | [diff] [blame] | 223 | let hash = diced_open_dice::hash("hello world".as_bytes()).expect("DiceHash failed"); |
David Brazdil | 9a83e61 | 2022-09-27 17:38:10 +0000 | [diff] [blame] | 224 | assert_eq!( |
| 225 | hash, |
| 226 | [ |
| 227 | 0x30, 0x9e, 0xcc, 0x48, 0x9c, 0x12, 0xd6, 0xeb, 0x4c, 0xc4, 0x0f, 0x50, 0xc9, 0x02, |
| 228 | 0xf2, 0xb4, 0xd0, 0xed, 0x77, 0xee, 0x51, 0x1a, 0x7c, 0x7a, 0x9b, 0xcd, 0x3c, 0xa8, |
| 229 | 0x6d, 0x4c, 0xd8, 0x6f, 0x98, 0x9d, 0xd3, 0x5b, 0xc5, 0xff, 0x49, 0x96, 0x70, 0xda, |
| 230 | 0x34, 0x25, 0x5b, 0x45, 0xb0, 0xcf, 0xd8, 0x30, 0xe8, 0x1f, 0x60, 0x5d, 0xcf, 0x7d, |
| 231 | 0xc5, 0x54, 0x2e, 0x93, 0xae, 0x9c, 0xd7, 0x6f |
| 232 | ] |
| 233 | ); |
| 234 | } |
Jakob Vukalovic | ef99629 | 2023-04-13 14:28:34 +0000 | [diff] [blame] | 235 | |
| 236 | macro_rules! log_all_levels { |
| 237 | ($msg:literal) => {{ |
| 238 | error!($msg); |
| 239 | warn!($msg); |
| 240 | info!($msg); |
| 241 | debug!($msg); |
| 242 | trace!($msg); |
| 243 | }}; |
| 244 | } |
| 245 | |
| 246 | fn emit_suppressed_log() { |
| 247 | { |
| 248 | let _guard = logger::suppress(); |
| 249 | log_all_levels!("Suppressed message"); |
| 250 | } |
| 251 | log_all_levels!("Unsuppressed message"); |
| 252 | } |