blob: 1466d1ecb0d4cc61fe758ae5b4e76b5bb9b79513 [file] [log] [blame]
Andrew Walbraneef98202022-04-27 16:23:06 +00001// 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
20mod exceptions;
Andrew Walbran153aad92022-06-28 15:51:13 +000021mod layout;
Andrew Walbran8217d062022-11-22 16:56:18 +000022mod pci;
Andrew Walbraneef98202022-04-27 16:23:06 +000023
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000024extern crate alloc;
25
Pierre-Clément Tosi67108c32023-06-30 11:04:02 +000026use crate::layout::{boot_stack_range, print_addresses, DEVICE_REGION};
Andrew Walbran730375d2022-12-21 14:04:34 +000027use crate::pci::{check_pci, get_bar_region};
Pierre-Clément Tosi9d9cf182024-08-07 16:28:53 +010028use aarch64_paging::paging::VirtualAddress;
Alice Wangcee2c652023-07-05 09:16:52 +000029use aarch64_paging::MapError;
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000030use alloc::{vec, vec::Vec};
Pierre-Clément Tosi5c4bef62024-08-13 22:07:55 +010031use core::mem;
Chariseee5b78342024-04-08 17:59:31 +000032use core::ptr::addr_of_mut;
Pierre-Clément Tosi1bf532b2023-11-13 11:06:20 +000033use cstr::cstr;
David Brazdil1baa9a92022-06-28 14:47:50 +010034use libfdt::Fdt;
Jakob Vukalovicef996292023-04-13 14:28:34 +000035use log::{debug, error, info, trace, warn, LevelFilter};
Alice Wanga3931aa2023-07-05 12:52:09 +000036use vmbase::{
Pierre-Clément Tosif2c19d42024-10-01 17:42:04 +010037 bionic, configure_heap,
38 fdt::pci::PciInfo,
39 generate_image_header,
Pierre-Clément Tosi3d1c2e42024-08-13 22:29:46 +010040 layout::{crosvm::FDT_MAX_SIZE, rodata_range, scratch_range, text_range},
Pierre-Clément Tosi67108c32023-06-30 11:04:02 +000041 linker, logger, main,
Alice Wangcee2c652023-07-05 09:16:52 +000042 memory::{PageTable, SIZE_64KB},
Pierre-Clément Tosi3d1c2e42024-08-13 22:29:46 +010043 util::RangeExt as _,
Alice Wanga3931aa2023-07-05 12:52:09 +000044};
Andrew Walbraneef98202022-04-27 16:23:06 +000045
Andrew Walbran5d4e1c92022-04-12 14:30:54 +000046static INITIALISED_DATA: [u32; 4] = [1, 2, 3, 4];
47static mut ZEROED_DATA: [u32; 10] = [0; 10];
48static mut MUTABLE_DATA: [u32; 4] = [1, 2, 3, 4];
49
Pierre-Clément Tosi1f7c5232024-08-13 19:51:25 +010050generate_image_header!();
Andrew Walbraneef98202022-04-27 16:23:06 +000051main!(main);
Pierre-Clément Tosi6a4808c2023-06-29 09:19:38 +000052configure_heap!(SIZE_64KB);
Andrew Walbraneef98202022-04-27 16:23:06 +000053
Pierre-Clément Tosi5c4bef62024-08-13 22:07:55 +010054fn init_page_table(page_table: &mut PageTable) -> Result<(), MapError> {
Alice Wangcee2c652023-07-05 09:16:52 +000055 page_table.map_device(&DEVICE_REGION)?;
56 page_table.map_code(&text_range().into())?;
57 page_table.map_rodata(&rodata_range().into())?;
58 page_table.map_data(&scratch_range().into())?;
59 page_table.map_data(&boot_stack_range().into())?;
Alice Wangcee2c652023-07-05 09:16:52 +000060
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 Walbraneef98202022-04-27 16:23:06 +000072/// Entry point for VM bootloader.
Andrew Walbrane03395a2022-04-29 15:15:49 +000073pub fn main(arg0: u64, arg1: u64, arg2: u64, arg3: u64) {
Pierre-Clément Tosid3305482023-06-29 15:03:48 +000074 log::set_max_level(LevelFilter::Debug);
David Brazdilb41aa8f2022-07-05 12:41:00 +010075
Jakob Vukalovicef996292023-04-13 14:28:34 +000076 info!("Hello world");
David Brazdilb41aa8f2022-07-05 12:41:00 +010077 info!("x0={:#018x}, x1={:#018x}, x2={:#018x}, x3={:#018x}", arg0, arg1, arg2, arg3);
Andrew Walbran6261cf42022-04-12 13:26:52 +000078 print_addresses();
Andrew Walbran5d4e1c92022-04-12 14:30:54 +000079 check_data();
David Brazdila51c6f02022-10-12 09:51:48 +000080 check_stack_guard();
Andrew Walbran8217d062022-11-22 16:56:18 +000081
Pierre-Clément Tosi3d1c2e42024-08-13 22:29:46 +010082 let mut page_table = PageTable::default();
83 init_page_table(&mut page_table).unwrap();
84
Andrew Walbran8217d062022-11-22 16:56:18 +000085 info!("Checking FDT...");
Pierre-Clément Tosi9d9cf182024-08-07 16:28:53 +010086 let fdt_addr = usize::try_from(arg0).unwrap();
Andrew Walbran47842802023-07-05 16:56:08 +000087 // SAFETY: The DTB range is valid, writable memory, and we don't construct any aliases to it.
Pierre-Clément Tosi9d9cf182024-08-07 16:28:53 +010088 let fdt = unsafe { core::slice::from_raw_parts_mut(fdt_addr as *mut u8, FDT_MAX_SIZE) };
89 let fdt_region = (VirtualAddress(fdt_addr)..VirtualAddress(fdt_addr + fdt.len())).into();
Pierre-Clément Tosi3d1c2e42024-08-13 22:29:46 +010090 page_table.map_data(&fdt_region).unwrap();
Andrew Walbran8217d062022-11-22 16:56:18 +000091 let fdt = Fdt::from_mut_slice(fdt).unwrap();
92 info!("FDT passed verification.");
93 check_fdt(fdt);
94
Andrew Walbran730375d2022-12-21 14:04:34 +000095 let pci_info = PciInfo::from_fdt(fdt).unwrap();
96 debug!("Found PCI CAM at {:#x}-{:#x}", pci_info.cam_range.start, pci_info.cam_range.end);
Andrew Walbran8217d062022-11-22 16:56:18 +000097
98 modify_fdt(fdt);
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000099
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000100 check_alloc();
Andrew Walbran13564542022-04-20 16:29:45 +0000101
Pierre-Clément Tosi3d1c2e42024-08-13 22:29:46 +0100102 let bar_region = get_bar_region(&pci_info);
103 if bar_region.is_within(&DEVICE_REGION) {
104 // Avoid a MapError::BreakBeforeMakeViolation.
105 info!("BAR region is within already mapped device region: skipping page table ops.");
106 } else {
107 page_table.map_device(&bar_region).unwrap();
108 }
Andrew Walbran13564542022-04-20 16:29:45 +0000109
110 check_data();
David Brazdil9a83e612022-09-27 17:38:10 +0000111 check_dice();
Andrew Walbran8217d062022-11-22 16:56:18 +0000112
Andrew Walbran47842802023-07-05 16:56:08 +0000113 // SAFETY: This is the only place where `make_pci_root` is called.
Andrew Walbran730375d2022-12-21 14:04:34 +0000114 let mut pci_root = unsafe { pci_info.make_pci_root() };
115 check_pci(&mut pci_root);
Jakob Vukalovicef996292023-04-13 14:28:34 +0000116
117 emit_suppressed_log();
Pierre-Clément Tosi3d1c2e42024-08-13 22:29:46 +0100118
119 info!("De-activating IdMap...");
120 mem::drop(page_table); // Release PageTable and switch back to idmap.S
121 info!("De-activated.");
Andrew Walbran13564542022-04-20 16:29:45 +0000122}
123
David Brazdila51c6f02022-10-12 09:51:48 +0000124fn check_stack_guard() {
David Brazdila51c6f02022-10-12 09:51:48 +0000125 info!("Testing stack guard");
Pierre-Clément Tosi67108c32023-06-30 11:04:02 +0000126 // SAFETY: No concurrency issue should occur when running these tests.
127 let stack_guard = unsafe { bionic::TLS.stack_guard };
128 assert_ne!(stack_guard, 0);
Pierre-Clément Tosi62ffc0d2023-06-30 09:31:56 +0000129 // Check that a NULL-terminating value is added for C functions consuming strings from stack.
130 assert_eq!(stack_guard.to_ne_bytes().last(), Some(&0));
Pierre-Clément Tosi67108c32023-06-30 11:04:02 +0000131 // Check that the TLS and guard are properly accessible from the dedicated register.
132 assert_eq!(stack_guard, bionic::__get_tls().stack_guard);
133 // Check that the LLVM __stack_chk_guard alias is also properly set up.
134 assert_eq!(
135 stack_guard,
136 // SAFETY: No concurrency issue should occur when running these tests.
137 unsafe { linker::__stack_chk_guard },
138 );
David Brazdila51c6f02022-10-12 09:51:48 +0000139}
140
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000141fn check_data() {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +0100142 info!("INITIALISED_DATA: {:?}", INITIALISED_DATA.as_ptr());
Andrew Walbran47842802023-07-05 16:56:08 +0000143 // SAFETY: We only print the addresses of the static mutable variable, not actually access it.
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000144 info!("ZEROED_DATA: {:?}", unsafe { ZEROED_DATA.as_ptr() });
Andrew Walbran47842802023-07-05 16:56:08 +0000145 // SAFETY: We only print the addresses of the static mutable variable, not actually access it.
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000146 info!("MUTABLE_DATA: {:?}", unsafe { MUTABLE_DATA.as_ptr() });
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000147
148 assert_eq!(INITIALISED_DATA[0], 1);
149 assert_eq!(INITIALISED_DATA[1], 2);
150 assert_eq!(INITIALISED_DATA[2], 3);
151 assert_eq!(INITIALISED_DATA[3], 4);
152
Andrew Walbran47842802023-07-05 16:56:08 +0000153 // SAFETY: Nowhere else in the program accesses this static mutable variable, so there is no
154 // chance of concurrent access.
Chariseee5b78342024-04-08 17:59:31 +0000155 let zeroed_data = unsafe { &mut *addr_of_mut!(ZEROED_DATA) };
Andrew Walbran47842802023-07-05 16:56:08 +0000156 // SAFETY: Nowhere else in the program accesses this static mutable variable, so there is no
157 // chance of concurrent access.
Chariseeb59cda42024-04-12 19:13:36 +0000158 let mutable_data = unsafe { &mut *addr_of_mut!(MUTABLE_DATA) };
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000159
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000160 for element in zeroed_data.iter() {
161 assert_eq!(*element, 0);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000162 }
Chariseee5b78342024-04-08 17:59:31 +0000163
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000164 zeroed_data[0] = 13;
165 assert_eq!(zeroed_data[0], 13);
166 zeroed_data[0] = 0;
167 assert_eq!(zeroed_data[0], 0);
168
169 assert_eq!(mutable_data[0], 1);
170 assert_eq!(mutable_data[1], 2);
171 assert_eq!(mutable_data[2], 3);
172 assert_eq!(mutable_data[3], 4);
173 mutable_data[0] += 41;
174 assert_eq!(mutable_data[0], 42);
175 mutable_data[0] -= 41;
176 assert_eq!(mutable_data[0], 1);
177
David Brazdilb41aa8f2022-07-05 12:41:00 +0100178 info!("Data looks good");
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000179}
180
Andrew Walbran8217d062022-11-22 16:56:18 +0000181fn check_fdt(reader: &Fdt) {
Alice Wang2422bdc2023-06-12 08:37:55 +0000182 for reg in reader.memory().unwrap() {
David Brazdil1baa9a92022-06-28 14:47:50 +0100183 info!("memory @ {reg:#x?}");
184 }
185
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000186 let compatible = cstr!("ns16550a");
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000187
188 for c in reader.compatible_nodes(compatible).unwrap() {
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000189 let reg = c.reg().unwrap().unwrap().next().unwrap();
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000190 info!("node compatible with '{}' at {reg:?}", compatible.to_str().unwrap());
191 }
Andrew Walbran8217d062022-11-22 16:56:18 +0000192}
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000193
Andrew Walbran8217d062022-11-22 16:56:18 +0000194fn modify_fdt(writer: &mut Fdt) {
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000195 writer.unpack().unwrap();
196 info!("FDT successfully unpacked.");
197
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000198 let path = cstr!("/memory");
Pierre-Clément Tosia3c4ec32024-02-15 20:05:15 +0000199 let node = writer.node_mut(path).unwrap().unwrap();
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000200 let name = cstr!("child");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000201 let mut child = node.add_subnode(name).unwrap();
202 info!("Created subnode '{}/{}'.", path.to_str().unwrap(), name.to_str().unwrap());
203
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000204 let name = cstr!("str-property");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000205 child.appendprop(name, b"property-value\0").unwrap();
206 info!("Appended property '{}'.", name.to_str().unwrap());
207
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000208 let name = cstr!("pair-property");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000209 let addr = 0x0123_4567u64;
210 let size = 0x89ab_cdefu64;
211 child.appendprop_addrrange(name, addr, size).unwrap();
212 info!("Appended property '{}'.", name.to_str().unwrap());
213
214 let writer = child.fdt();
215 writer.pack().unwrap();
216 info!("FDT successfully packed.");
217
David Brazdil1baa9a92022-06-28 14:47:50 +0100218 info!("FDT checks done.");
219}
220
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000221fn check_alloc() {
David Brazdilb41aa8f2022-07-05 12:41:00 +0100222 info!("Allocating a Vec...");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000223 let mut vector: Vec<u32> = vec![1, 2, 3, 4];
224 assert_eq!(vector[0], 1);
225 assert_eq!(vector[1], 2);
226 assert_eq!(vector[2], 3);
227 assert_eq!(vector[3], 4);
228 vector[2] = 42;
229 assert_eq!(vector[2], 42);
David Brazdilb41aa8f2022-07-05 12:41:00 +0100230 info!("Vec seems to work.");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000231}
David Brazdil9a83e612022-09-27 17:38:10 +0000232
233fn check_dice() {
234 info!("Testing DICE integration...");
Alice Wangcb9d2f92023-02-06 10:29:00 +0000235 let hash = diced_open_dice::hash("hello world".as_bytes()).expect("DiceHash failed");
David Brazdil9a83e612022-09-27 17:38:10 +0000236 assert_eq!(
237 hash,
238 [
239 0x30, 0x9e, 0xcc, 0x48, 0x9c, 0x12, 0xd6, 0xeb, 0x4c, 0xc4, 0x0f, 0x50, 0xc9, 0x02,
240 0xf2, 0xb4, 0xd0, 0xed, 0x77, 0xee, 0x51, 0x1a, 0x7c, 0x7a, 0x9b, 0xcd, 0x3c, 0xa8,
241 0x6d, 0x4c, 0xd8, 0x6f, 0x98, 0x9d, 0xd3, 0x5b, 0xc5, 0xff, 0x49, 0x96, 0x70, 0xda,
242 0x34, 0x25, 0x5b, 0x45, 0xb0, 0xcf, 0xd8, 0x30, 0xe8, 0x1f, 0x60, 0x5d, 0xcf, 0x7d,
243 0xc5, 0x54, 0x2e, 0x93, 0xae, 0x9c, 0xd7, 0x6f
244 ]
245 );
246}
Jakob Vukalovicef996292023-04-13 14:28:34 +0000247
248macro_rules! log_all_levels {
249 ($msg:literal) => {{
250 error!($msg);
251 warn!($msg);
252 info!($msg);
253 debug!($msg);
254 trace!($msg);
255 }};
256}
257
258fn emit_suppressed_log() {
259 {
260 let _guard = logger::suppress();
261 log_all_levels!("Suppressed message");
262 }
263 log_all_levels!("Unsuppressed message");
264}