blob: 4d535cc8169508e7dfd1ae1ace66472f0604f848 [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};
Alice Wangcee2c652023-07-05 09:16:52 +000028use aarch64_paging::paging::MemoryRegion;
Pierre-Clément Tosi9d9cf182024-08-07 16:28:53 +010029use aarch64_paging::paging::VirtualAddress;
Alice Wangcee2c652023-07-05 09:16:52 +000030use aarch64_paging::MapError;
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000031use alloc::{vec, vec::Vec};
Chariseee5b78342024-04-08 17:59:31 +000032use core::ptr::addr_of_mut;
Pierre-Clément Tosi1bf532b2023-11-13 11:06:20 +000033use cstr::cstr;
Andrew Walbran730375d2022-12-21 14:04:34 +000034use fdtpci::PciInfo;
David Brazdil1baa9a92022-06-28 14:47:50 +010035use libfdt::Fdt;
Jakob Vukalovicef996292023-04-13 14:28:34 +000036use log::{debug, error, info, trace, warn, LevelFilter};
Alice Wanga3931aa2023-07-05 12:52:09 +000037use vmbase::{
Pierre-Clément Tosi1f7c5232024-08-13 19:51:25 +010038 bionic, configure_heap, generate_image_header,
Pierre-Clément Tosi9d9cf182024-08-07 16:28:53 +010039 layout::{
40 crosvm::{FDT_MAX_SIZE, MEM_START},
41 rodata_range, scratch_range, text_range,
42 },
Pierre-Clément Tosi67108c32023-06-30 11:04:02 +000043 linker, logger, main,
Alice Wangcee2c652023-07-05 09:16:52 +000044 memory::{PageTable, SIZE_64KB},
Alice Wanga3931aa2023-07-05 12:52:09 +000045};
Andrew Walbraneef98202022-04-27 16:23:06 +000046
Andrew Walbran5d4e1c92022-04-12 14:30:54 +000047static INITIALISED_DATA: [u32; 4] = [1, 2, 3, 4];
48static mut ZEROED_DATA: [u32; 10] = [0; 10];
49static mut MUTABLE_DATA: [u32; 4] = [1, 2, 3, 4];
50
Pierre-Clément Tosi1f7c5232024-08-13 19:51:25 +010051generate_image_header!();
Andrew Walbraneef98202022-04-27 16:23:06 +000052main!(main);
Pierre-Clément Tosi6a4808c2023-06-29 09:19:38 +000053configure_heap!(SIZE_64KB);
Andrew Walbraneef98202022-04-27 16:23:06 +000054
Pierre-Clément Tosi9d9cf182024-08-07 16:28:53 +010055fn init_page_table(dtb: &MemoryRegion, pci_bar_range: &MemoryRegion) -> Result<(), MapError> {
Alice Wangcee2c652023-07-05 09:16:52 +000056 let mut page_table = PageTable::default();
57
58 page_table.map_device(&DEVICE_REGION)?;
59 page_table.map_code(&text_range().into())?;
60 page_table.map_rodata(&rodata_range().into())?;
61 page_table.map_data(&scratch_range().into())?;
62 page_table.map_data(&boot_stack_range().into())?;
Pierre-Clément Tosi9d9cf182024-08-07 16:28:53 +010063 page_table.map_rodata(dtb)?;
Alice Wangcee2c652023-07-05 09:16:52 +000064 page_table.map_device(pci_bar_range)?;
65
66 info!("Activating IdMap...");
67 // SAFETY: page_table duplicates the static mappings for everything that the Rust code is
68 // aware of so activating it shouldn't have any visible effect.
69 unsafe {
70 page_table.activate();
71 }
72 info!("Activated.");
73
74 Ok(())
75}
76
Andrew Walbraneef98202022-04-27 16:23:06 +000077/// Entry point for VM bootloader.
Andrew Walbrane03395a2022-04-29 15:15:49 +000078pub fn main(arg0: u64, arg1: u64, arg2: u64, arg3: u64) {
Pierre-Clément Tosid3305482023-06-29 15:03:48 +000079 log::set_max_level(LevelFilter::Debug);
David Brazdilb41aa8f2022-07-05 12:41:00 +010080
Jakob Vukalovicef996292023-04-13 14:28:34 +000081 info!("Hello world");
David Brazdilb41aa8f2022-07-05 12:41:00 +010082 info!("x0={:#018x}, x1={:#018x}, x2={:#018x}, x3={:#018x}", arg0, arg1, arg2, arg3);
Andrew Walbran6261cf42022-04-12 13:26:52 +000083 print_addresses();
Andrew Walbran5d4e1c92022-04-12 14:30:54 +000084 check_data();
David Brazdila51c6f02022-10-12 09:51:48 +000085 check_stack_guard();
Andrew Walbran8217d062022-11-22 16:56:18 +000086
87 info!("Checking FDT...");
Pierre-Clément Tosi9d9cf182024-08-07 16:28:53 +010088 let fdt_addr = usize::try_from(arg0).unwrap();
89 // We are about to access the region so check that it matches our page tables in idmap.S.
90 assert_eq!(fdt_addr, MEM_START);
Andrew Walbran47842802023-07-05 16:56:08 +000091 // 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 +010092 let fdt = unsafe { core::slice::from_raw_parts_mut(fdt_addr as *mut u8, FDT_MAX_SIZE) };
93 let fdt_region = (VirtualAddress(fdt_addr)..VirtualAddress(fdt_addr + fdt.len())).into();
Andrew Walbran8217d062022-11-22 16:56:18 +000094 let fdt = Fdt::from_mut_slice(fdt).unwrap();
95 info!("FDT passed verification.");
96 check_fdt(fdt);
97
Andrew Walbran730375d2022-12-21 14:04:34 +000098 let pci_info = PciInfo::from_fdt(fdt).unwrap();
99 debug!("Found PCI CAM at {:#x}-{:#x}", pci_info.cam_range.start, pci_info.cam_range.end);
Andrew Walbran8217d062022-11-22 16:56:18 +0000100
101 modify_fdt(fdt);
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000102
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000103 check_alloc();
Andrew Walbran13564542022-04-20 16:29:45 +0000104
Pierre-Clément Tosi9d9cf182024-08-07 16:28:53 +0100105 init_page_table(&fdt_region, &get_bar_region(&pci_info)).unwrap();
Andrew Walbran13564542022-04-20 16:29:45 +0000106
107 check_data();
David Brazdil9a83e612022-09-27 17:38:10 +0000108 check_dice();
Andrew Walbran8217d062022-11-22 16:56:18 +0000109
Andrew Walbran47842802023-07-05 16:56:08 +0000110 // SAFETY: This is the only place where `make_pci_root` is called.
Andrew Walbran730375d2022-12-21 14:04:34 +0000111 let mut pci_root = unsafe { pci_info.make_pci_root() };
112 check_pci(&mut pci_root);
Jakob Vukalovicef996292023-04-13 14:28:34 +0000113
114 emit_suppressed_log();
Andrew Walbran13564542022-04-20 16:29:45 +0000115}
116
David Brazdila51c6f02022-10-12 09:51:48 +0000117fn check_stack_guard() {
David Brazdila51c6f02022-10-12 09:51:48 +0000118 info!("Testing stack guard");
Pierre-Clément Tosi67108c32023-06-30 11:04:02 +0000119 // SAFETY: No concurrency issue should occur when running these tests.
120 let stack_guard = unsafe { bionic::TLS.stack_guard };
121 assert_ne!(stack_guard, 0);
Pierre-Clément Tosi62ffc0d2023-06-30 09:31:56 +0000122 // Check that a NULL-terminating value is added for C functions consuming strings from stack.
123 assert_eq!(stack_guard.to_ne_bytes().last(), Some(&0));
Pierre-Clément Tosi67108c32023-06-30 11:04:02 +0000124 // Check that the TLS and guard are properly accessible from the dedicated register.
125 assert_eq!(stack_guard, bionic::__get_tls().stack_guard);
126 // Check that the LLVM __stack_chk_guard alias is also properly set up.
127 assert_eq!(
128 stack_guard,
129 // SAFETY: No concurrency issue should occur when running these tests.
130 unsafe { linker::__stack_chk_guard },
131 );
David Brazdila51c6f02022-10-12 09:51:48 +0000132}
133
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000134fn check_data() {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +0100135 info!("INITIALISED_DATA: {:?}", INITIALISED_DATA.as_ptr());
Andrew Walbran47842802023-07-05 16:56:08 +0000136 // SAFETY: We only print the addresses of the static mutable variable, not actually access it.
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000137 info!("ZEROED_DATA: {:?}", unsafe { ZEROED_DATA.as_ptr() });
Andrew Walbran47842802023-07-05 16:56:08 +0000138 // SAFETY: We only print the addresses of the static mutable variable, not actually access it.
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000139 info!("MUTABLE_DATA: {:?}", unsafe { MUTABLE_DATA.as_ptr() });
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000140
141 assert_eq!(INITIALISED_DATA[0], 1);
142 assert_eq!(INITIALISED_DATA[1], 2);
143 assert_eq!(INITIALISED_DATA[2], 3);
144 assert_eq!(INITIALISED_DATA[3], 4);
145
Andrew Walbran47842802023-07-05 16:56:08 +0000146 // SAFETY: Nowhere else in the program accesses this static mutable variable, so there is no
147 // chance of concurrent access.
Chariseee5b78342024-04-08 17:59:31 +0000148 let zeroed_data = unsafe { &mut *addr_of_mut!(ZEROED_DATA) };
Andrew Walbran47842802023-07-05 16:56:08 +0000149 // SAFETY: Nowhere else in the program accesses this static mutable variable, so there is no
150 // chance of concurrent access.
Chariseeb59cda42024-04-12 19:13:36 +0000151 let mutable_data = unsafe { &mut *addr_of_mut!(MUTABLE_DATA) };
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000152
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000153 for element in zeroed_data.iter() {
154 assert_eq!(*element, 0);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000155 }
Chariseee5b78342024-04-08 17:59:31 +0000156
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000157 zeroed_data[0] = 13;
158 assert_eq!(zeroed_data[0], 13);
159 zeroed_data[0] = 0;
160 assert_eq!(zeroed_data[0], 0);
161
162 assert_eq!(mutable_data[0], 1);
163 assert_eq!(mutable_data[1], 2);
164 assert_eq!(mutable_data[2], 3);
165 assert_eq!(mutable_data[3], 4);
166 mutable_data[0] += 41;
167 assert_eq!(mutable_data[0], 42);
168 mutable_data[0] -= 41;
169 assert_eq!(mutable_data[0], 1);
170
David Brazdilb41aa8f2022-07-05 12:41:00 +0100171 info!("Data looks good");
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000172}
173
Andrew Walbran8217d062022-11-22 16:56:18 +0000174fn check_fdt(reader: &Fdt) {
Alice Wang2422bdc2023-06-12 08:37:55 +0000175 for reg in reader.memory().unwrap() {
David Brazdil1baa9a92022-06-28 14:47:50 +0100176 info!("memory @ {reg:#x?}");
177 }
178
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000179 let compatible = cstr!("ns16550a");
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000180
181 for c in reader.compatible_nodes(compatible).unwrap() {
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000182 let reg = c.reg().unwrap().unwrap().next().unwrap();
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000183 info!("node compatible with '{}' at {reg:?}", compatible.to_str().unwrap());
184 }
Andrew Walbran8217d062022-11-22 16:56:18 +0000185}
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000186
Andrew Walbran8217d062022-11-22 16:56:18 +0000187fn modify_fdt(writer: &mut Fdt) {
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000188 writer.unpack().unwrap();
189 info!("FDT successfully unpacked.");
190
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000191 let path = cstr!("/memory");
Pierre-Clément Tosia3c4ec32024-02-15 20:05:15 +0000192 let node = writer.node_mut(path).unwrap().unwrap();
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000193 let name = cstr!("child");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000194 let mut child = node.add_subnode(name).unwrap();
195 info!("Created subnode '{}/{}'.", path.to_str().unwrap(), name.to_str().unwrap());
196
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000197 let name = cstr!("str-property");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000198 child.appendprop(name, b"property-value\0").unwrap();
199 info!("Appended property '{}'.", name.to_str().unwrap());
200
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000201 let name = cstr!("pair-property");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000202 let addr = 0x0123_4567u64;
203 let size = 0x89ab_cdefu64;
204 child.appendprop_addrrange(name, addr, size).unwrap();
205 info!("Appended property '{}'.", name.to_str().unwrap());
206
207 let writer = child.fdt();
208 writer.pack().unwrap();
209 info!("FDT successfully packed.");
210
David Brazdil1baa9a92022-06-28 14:47:50 +0100211 info!("FDT checks done.");
212}
213
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000214fn check_alloc() {
David Brazdilb41aa8f2022-07-05 12:41:00 +0100215 info!("Allocating a Vec...");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000216 let mut vector: Vec<u32> = vec![1, 2, 3, 4];
217 assert_eq!(vector[0], 1);
218 assert_eq!(vector[1], 2);
219 assert_eq!(vector[2], 3);
220 assert_eq!(vector[3], 4);
221 vector[2] = 42;
222 assert_eq!(vector[2], 42);
David Brazdilb41aa8f2022-07-05 12:41:00 +0100223 info!("Vec seems to work.");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000224}
David Brazdil9a83e612022-09-27 17:38:10 +0000225
226fn check_dice() {
227 info!("Testing DICE integration...");
Alice Wangcb9d2f92023-02-06 10:29:00 +0000228 let hash = diced_open_dice::hash("hello world".as_bytes()).expect("DiceHash failed");
David Brazdil9a83e612022-09-27 17:38:10 +0000229 assert_eq!(
230 hash,
231 [
232 0x30, 0x9e, 0xcc, 0x48, 0x9c, 0x12, 0xd6, 0xeb, 0x4c, 0xc4, 0x0f, 0x50, 0xc9, 0x02,
233 0xf2, 0xb4, 0xd0, 0xed, 0x77, 0xee, 0x51, 0x1a, 0x7c, 0x7a, 0x9b, 0xcd, 0x3c, 0xa8,
234 0x6d, 0x4c, 0xd8, 0x6f, 0x98, 0x9d, 0xd3, 0x5b, 0xc5, 0xff, 0x49, 0x96, 0x70, 0xda,
235 0x34, 0x25, 0x5b, 0x45, 0xb0, 0xcf, 0xd8, 0x30, 0xe8, 0x1f, 0x60, 0x5d, 0xcf, 0x7d,
236 0xc5, 0x54, 0x2e, 0x93, 0xae, 0x9c, 0xd7, 0x6f
237 ]
238 );
239}
Jakob Vukalovicef996292023-04-13 14:28:34 +0000240
241macro_rules! log_all_levels {
242 ($msg:literal) => {{
243 error!($msg);
244 warn!($msg);
245 info!($msg);
246 debug!($msg);
247 trace!($msg);
248 }};
249}
250
251fn emit_suppressed_log() {
252 {
253 let _guard = logger::suppress();
254 log_all_levels!("Suppressed message");
255 }
256 log_all_levels!("Unsuppressed message");
257}