blob: a01f619c0f47e4d30b5416b68633193e12b59f25 [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 Tosi1bf532b2023-11-13 11:06:20 +000038 bionic, configure_heap,
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
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 Tosi9d9cf182024-08-07 16:28:53 +010054fn init_page_table(dtb: &MemoryRegion, pci_bar_range: &MemoryRegion) -> Result<(), MapError> {
Alice Wangcee2c652023-07-05 09:16:52 +000055 let mut page_table = PageTable::default();
56
57 page_table.map_device(&DEVICE_REGION)?;
58 page_table.map_code(&text_range().into())?;
59 page_table.map_rodata(&rodata_range().into())?;
60 page_table.map_data(&scratch_range().into())?;
61 page_table.map_data(&boot_stack_range().into())?;
Pierre-Clément Tosi9d9cf182024-08-07 16:28:53 +010062 page_table.map_rodata(dtb)?;
Alice Wangcee2c652023-07-05 09:16:52 +000063 page_table.map_device(pci_bar_range)?;
64
65 info!("Activating IdMap...");
66 // SAFETY: page_table duplicates the static mappings for everything that the Rust code is
67 // aware of so activating it shouldn't have any visible effect.
68 unsafe {
69 page_table.activate();
70 }
71 info!("Activated.");
72
73 Ok(())
74}
75
Andrew Walbraneef98202022-04-27 16:23:06 +000076/// Entry point for VM bootloader.
Andrew Walbrane03395a2022-04-29 15:15:49 +000077pub fn main(arg0: u64, arg1: u64, arg2: u64, arg3: u64) {
Pierre-Clément Tosid3305482023-06-29 15:03:48 +000078 log::set_max_level(LevelFilter::Debug);
David Brazdilb41aa8f2022-07-05 12:41:00 +010079
Jakob Vukalovicef996292023-04-13 14:28:34 +000080 info!("Hello world");
David Brazdilb41aa8f2022-07-05 12:41:00 +010081 info!("x0={:#018x}, x1={:#018x}, x2={:#018x}, x3={:#018x}", arg0, arg1, arg2, arg3);
Andrew Walbran6261cf42022-04-12 13:26:52 +000082 print_addresses();
Andrew Walbran5d4e1c92022-04-12 14:30:54 +000083 check_data();
David Brazdila51c6f02022-10-12 09:51:48 +000084 check_stack_guard();
Andrew Walbran8217d062022-11-22 16:56:18 +000085
86 info!("Checking FDT...");
Pierre-Clément Tosi9d9cf182024-08-07 16:28:53 +010087 let fdt_addr = usize::try_from(arg0).unwrap();
88 // We are about to access the region so check that it matches our page tables in idmap.S.
89 assert_eq!(fdt_addr, MEM_START);
Andrew Walbran47842802023-07-05 16:56:08 +000090 // 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 +010091 let fdt = unsafe { core::slice::from_raw_parts_mut(fdt_addr as *mut u8, FDT_MAX_SIZE) };
92 let fdt_region = (VirtualAddress(fdt_addr)..VirtualAddress(fdt_addr + fdt.len())).into();
Andrew Walbran8217d062022-11-22 16:56:18 +000093 let fdt = Fdt::from_mut_slice(fdt).unwrap();
94 info!("FDT passed verification.");
95 check_fdt(fdt);
96
Andrew Walbran730375d2022-12-21 14:04:34 +000097 let pci_info = PciInfo::from_fdt(fdt).unwrap();
98 debug!("Found PCI CAM at {:#x}-{:#x}", pci_info.cam_range.start, pci_info.cam_range.end);
Andrew Walbran8217d062022-11-22 16:56:18 +000099
100 modify_fdt(fdt);
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000101
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000102 check_alloc();
Andrew Walbran13564542022-04-20 16:29:45 +0000103
Pierre-Clément Tosi9d9cf182024-08-07 16:28:53 +0100104 init_page_table(&fdt_region, &get_bar_region(&pci_info)).unwrap();
Andrew Walbran13564542022-04-20 16:29:45 +0000105
106 check_data();
David Brazdil9a83e612022-09-27 17:38:10 +0000107 check_dice();
Andrew Walbran8217d062022-11-22 16:56:18 +0000108
Andrew Walbran47842802023-07-05 16:56:08 +0000109 // SAFETY: This is the only place where `make_pci_root` is called.
Andrew Walbran730375d2022-12-21 14:04:34 +0000110 let mut pci_root = unsafe { pci_info.make_pci_root() };
111 check_pci(&mut pci_root);
Jakob Vukalovicef996292023-04-13 14:28:34 +0000112
113 emit_suppressed_log();
Andrew Walbran13564542022-04-20 16:29:45 +0000114}
115
David Brazdila51c6f02022-10-12 09:51:48 +0000116fn check_stack_guard() {
David Brazdila51c6f02022-10-12 09:51:48 +0000117 info!("Testing stack guard");
Pierre-Clément Tosi67108c32023-06-30 11:04:02 +0000118 // SAFETY: No concurrency issue should occur when running these tests.
119 let stack_guard = unsafe { bionic::TLS.stack_guard };
120 assert_ne!(stack_guard, 0);
Pierre-Clément Tosi62ffc0d2023-06-30 09:31:56 +0000121 // Check that a NULL-terminating value is added for C functions consuming strings from stack.
122 assert_eq!(stack_guard.to_ne_bytes().last(), Some(&0));
Pierre-Clément Tosi67108c32023-06-30 11:04:02 +0000123 // Check that the TLS and guard are properly accessible from the dedicated register.
124 assert_eq!(stack_guard, bionic::__get_tls().stack_guard);
125 // Check that the LLVM __stack_chk_guard alias is also properly set up.
126 assert_eq!(
127 stack_guard,
128 // SAFETY: No concurrency issue should occur when running these tests.
129 unsafe { linker::__stack_chk_guard },
130 );
David Brazdila51c6f02022-10-12 09:51:48 +0000131}
132
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000133fn check_data() {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +0100134 info!("INITIALISED_DATA: {:?}", INITIALISED_DATA.as_ptr());
Andrew Walbran47842802023-07-05 16:56:08 +0000135 // SAFETY: We only print the addresses of the static mutable variable, not actually access it.
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000136 info!("ZEROED_DATA: {:?}", unsafe { ZEROED_DATA.as_ptr() });
Andrew Walbran47842802023-07-05 16:56:08 +0000137 // SAFETY: We only print the addresses of the static mutable variable, not actually access it.
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000138 info!("MUTABLE_DATA: {:?}", unsafe { MUTABLE_DATA.as_ptr() });
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000139
140 assert_eq!(INITIALISED_DATA[0], 1);
141 assert_eq!(INITIALISED_DATA[1], 2);
142 assert_eq!(INITIALISED_DATA[2], 3);
143 assert_eq!(INITIALISED_DATA[3], 4);
144
Andrew Walbran47842802023-07-05 16:56:08 +0000145 // SAFETY: Nowhere else in the program accesses this static mutable variable, so there is no
146 // chance of concurrent access.
Chariseee5b78342024-04-08 17:59:31 +0000147 let zeroed_data = unsafe { &mut *addr_of_mut!(ZEROED_DATA) };
Andrew Walbran47842802023-07-05 16:56:08 +0000148 // SAFETY: Nowhere else in the program accesses this static mutable variable, so there is no
149 // chance of concurrent access.
Chariseeb59cda42024-04-12 19:13:36 +0000150 let mutable_data = unsafe { &mut *addr_of_mut!(MUTABLE_DATA) };
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000151
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000152 for element in zeroed_data.iter() {
153 assert_eq!(*element, 0);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000154 }
Chariseee5b78342024-04-08 17:59:31 +0000155
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000156 zeroed_data[0] = 13;
157 assert_eq!(zeroed_data[0], 13);
158 zeroed_data[0] = 0;
159 assert_eq!(zeroed_data[0], 0);
160
161 assert_eq!(mutable_data[0], 1);
162 assert_eq!(mutable_data[1], 2);
163 assert_eq!(mutable_data[2], 3);
164 assert_eq!(mutable_data[3], 4);
165 mutable_data[0] += 41;
166 assert_eq!(mutable_data[0], 42);
167 mutable_data[0] -= 41;
168 assert_eq!(mutable_data[0], 1);
169
David Brazdilb41aa8f2022-07-05 12:41:00 +0100170 info!("Data looks good");
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000171}
172
Andrew Walbran8217d062022-11-22 16:56:18 +0000173fn check_fdt(reader: &Fdt) {
Alice Wang2422bdc2023-06-12 08:37:55 +0000174 for reg in reader.memory().unwrap() {
David Brazdil1baa9a92022-06-28 14:47:50 +0100175 info!("memory @ {reg:#x?}");
176 }
177
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000178 let compatible = cstr!("ns16550a");
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000179
180 for c in reader.compatible_nodes(compatible).unwrap() {
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000181 let reg = c.reg().unwrap().unwrap().next().unwrap();
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000182 info!("node compatible with '{}' at {reg:?}", compatible.to_str().unwrap());
183 }
Andrew Walbran8217d062022-11-22 16:56:18 +0000184}
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000185
Andrew Walbran8217d062022-11-22 16:56:18 +0000186fn modify_fdt(writer: &mut Fdt) {
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000187 writer.unpack().unwrap();
188 info!("FDT successfully unpacked.");
189
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000190 let path = cstr!("/memory");
Pierre-Clément Tosia3c4ec32024-02-15 20:05:15 +0000191 let node = writer.node_mut(path).unwrap().unwrap();
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000192 let name = cstr!("child");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000193 let mut child = node.add_subnode(name).unwrap();
194 info!("Created subnode '{}/{}'.", path.to_str().unwrap(), name.to_str().unwrap());
195
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000196 let name = cstr!("str-property");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000197 child.appendprop(name, b"property-value\0").unwrap();
198 info!("Appended property '{}'.", name.to_str().unwrap());
199
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000200 let name = cstr!("pair-property");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000201 let addr = 0x0123_4567u64;
202 let size = 0x89ab_cdefu64;
203 child.appendprop_addrrange(name, addr, size).unwrap();
204 info!("Appended property '{}'.", name.to_str().unwrap());
205
206 let writer = child.fdt();
207 writer.pack().unwrap();
208 info!("FDT successfully packed.");
209
David Brazdil1baa9a92022-06-28 14:47:50 +0100210 info!("FDT checks done.");
211}
212
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000213fn check_alloc() {
David Brazdilb41aa8f2022-07-05 12:41:00 +0100214 info!("Allocating a Vec...");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000215 let mut vector: Vec<u32> = vec![1, 2, 3, 4];
216 assert_eq!(vector[0], 1);
217 assert_eq!(vector[1], 2);
218 assert_eq!(vector[2], 3);
219 assert_eq!(vector[3], 4);
220 vector[2] = 42;
221 assert_eq!(vector[2], 42);
David Brazdilb41aa8f2022-07-05 12:41:00 +0100222 info!("Vec seems to work.");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000223}
David Brazdil9a83e612022-09-27 17:38:10 +0000224
225fn check_dice() {
226 info!("Testing DICE integration...");
Alice Wangcb9d2f92023-02-06 10:29:00 +0000227 let hash = diced_open_dice::hash("hello world".as_bytes()).expect("DiceHash failed");
David Brazdil9a83e612022-09-27 17:38:10 +0000228 assert_eq!(
229 hash,
230 [
231 0x30, 0x9e, 0xcc, 0x48, 0x9c, 0x12, 0xd6, 0xeb, 0x4c, 0xc4, 0x0f, 0x50, 0xc9, 0x02,
232 0xf2, 0xb4, 0xd0, 0xed, 0x77, 0xee, 0x51, 0x1a, 0x7c, 0x7a, 0x9b, 0xcd, 0x3c, 0xa8,
233 0x6d, 0x4c, 0xd8, 0x6f, 0x98, 0x9d, 0xd3, 0x5b, 0xc5, 0xff, 0x49, 0x96, 0x70, 0xda,
234 0x34, 0x25, 0x5b, 0x45, 0xb0, 0xcf, 0xd8, 0x30, 0xe8, 0x1f, 0x60, 0x5d, 0xcf, 0x7d,
235 0xc5, 0x54, 0x2e, 0x93, 0xae, 0x9c, 0xd7, 0x6f
236 ]
237 );
238}
Jakob Vukalovicef996292023-04-13 14:28:34 +0000239
240macro_rules! log_all_levels {
241 ($msg:literal) => {{
242 error!($msg);
243 warn!($msg);
244 info!($msg);
245 debug!($msg);
246 trace!($msg);
247 }};
248}
249
250fn emit_suppressed_log() {
251 {
252 let _guard = logger::suppress();
253 log_all_levels!("Suppressed message");
254 }
255 log_all_levels!("Unsuppressed message");
256}