blob: 138c90ec3b585ba986af4a7bbd52e3ec8029de50 [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 Tosieba83162024-11-02 12:11:48 +000026use crate::layout::print_addresses;
Pierre-Clément Tosid2c54722024-11-02 12:54:40 +000027use crate::pci::check_pci;
Alice Wangcee2c652023-07-05 09:16:52 +000028use aarch64_paging::MapError;
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000029use alloc::{vec, vec::Vec};
Chariseee5b78342024-04-08 17:59:31 +000030use core::ptr::addr_of_mut;
Pierre-Clément Tosi1bf532b2023-11-13 11:06:20 +000031use cstr::cstr;
David Brazdil1baa9a92022-06-28 14:47:50 +010032use libfdt::Fdt;
Jakob Vukalovicef996292023-04-13 14:28:34 +000033use log::{debug, error, info, trace, warn, LevelFilter};
Alice Wanga3931aa2023-07-05 12:52:09 +000034use vmbase::{
Pierre-Clément Tosif2c19d42024-10-01 17:42:04 +010035 bionic, configure_heap,
36 fdt::pci::PciInfo,
37 generate_image_header,
Pierre-Clément Tosi0b02a2b2024-11-28 22:48:27 +000038 layout::{
39 console_uart_page, crosvm::FDT_MAX_SIZE, data_bss_range, eh_stack_range, rodata_range,
Pierre-Clément Tosieba83162024-11-02 12:11:48 +000040 stack_range, text_range,
Pierre-Clément Tosi0b02a2b2024-11-28 22:48:27 +000041 },
Pierre-Clément Tosi67108c32023-06-30 11:04:02 +000042 linker, logger, main,
Pierre-Clément Tosid2c54722024-11-02 12:54:40 +000043 memory::{
44 deactivate_dynamic_page_tables, map_data, switch_to_dynamic_page_tables, PageTable,
45 SIZE_64KB,
46 },
Alice Wanga3931aa2023-07-05 12:52:09 +000047};
Andrew Walbraneef98202022-04-27 16:23:06 +000048
Andrew Walbran5d4e1c92022-04-12 14:30:54 +000049static INITIALISED_DATA: [u32; 4] = [1, 2, 3, 4];
50static mut ZEROED_DATA: [u32; 10] = [0; 10];
51static mut MUTABLE_DATA: [u32; 4] = [1, 2, 3, 4];
52
Pierre-Clément Tosi1f7c5232024-08-13 19:51:25 +010053generate_image_header!();
Andrew Walbraneef98202022-04-27 16:23:06 +000054main!(main);
Pierre-Clément Tosi6a4808c2023-06-29 09:19:38 +000055configure_heap!(SIZE_64KB);
Andrew Walbraneef98202022-04-27 16:23:06 +000056
Pierre-Clément Tosi5c4bef62024-08-13 22:07:55 +010057fn init_page_table(page_table: &mut PageTable) -> Result<(), MapError> {
Pierre-Clément Tosi1ea25a62024-11-02 12:54:40 +000058 page_table.map_device(&console_uart_page().into())?;
Alice Wangcee2c652023-07-05 09:16:52 +000059 page_table.map_code(&text_range().into())?;
60 page_table.map_rodata(&rodata_range().into())?;
Pierre-Clément Tosi0b02a2b2024-11-28 22:48:27 +000061 page_table.map_data(&data_bss_range().into())?;
62 page_table.map_data(&eh_stack_range().into())?;
Pierre-Clément Tosieba83162024-11-02 12:11:48 +000063 page_table.map_data(&stack_range().into())?;
Alice Wangcee2c652023-07-05 09:16:52 +000064
Alice Wangcee2c652023-07-05 09:16:52 +000065 Ok(())
66}
67
Andrew Walbraneef98202022-04-27 16:23:06 +000068/// Entry point for VM bootloader.
Andrew Walbrane03395a2022-04-29 15:15:49 +000069pub fn main(arg0: u64, arg1: u64, arg2: u64, arg3: u64) {
Pierre-Clément Tosid3305482023-06-29 15:03:48 +000070 log::set_max_level(LevelFilter::Debug);
David Brazdilb41aa8f2022-07-05 12:41:00 +010071
Jakob Vukalovicef996292023-04-13 14:28:34 +000072 info!("Hello world");
David Brazdilb41aa8f2022-07-05 12:41:00 +010073 info!("x0={:#018x}, x1={:#018x}, x2={:#018x}, x3={:#018x}", arg0, arg1, arg2, arg3);
Andrew Walbran6261cf42022-04-12 13:26:52 +000074 print_addresses();
Andrew Walbran5d4e1c92022-04-12 14:30:54 +000075 check_data();
David Brazdila51c6f02022-10-12 09:51:48 +000076 check_stack_guard();
Andrew Walbran8217d062022-11-22 16:56:18 +000077
Pierre-Clément Tosi3d1c2e42024-08-13 22:29:46 +010078 let mut page_table = PageTable::default();
79 init_page_table(&mut page_table).unwrap();
Pierre-Clément Tosid2c54722024-11-02 12:54:40 +000080 info!("Activating IdMap...");
81 switch_to_dynamic_page_tables(page_table);
82 info!("Activated.");
Pierre-Clément Tosi3d1c2e42024-08-13 22:29:46 +010083
Andrew Walbran8217d062022-11-22 16:56:18 +000084 info!("Checking FDT...");
Pierre-Clément Tosi9d9cf182024-08-07 16:28:53 +010085 let fdt_addr = usize::try_from(arg0).unwrap();
Andrew Walbran47842802023-07-05 16:56:08 +000086 // 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 +010087 let fdt = unsafe { core::slice::from_raw_parts_mut(fdt_addr as *mut u8, FDT_MAX_SIZE) };
Pierre-Clément Tosid2c54722024-11-02 12:54:40 +000088 map_data(fdt_addr, FDT_MAX_SIZE.try_into().unwrap()).unwrap();
Andrew Walbran8217d062022-11-22 16:56:18 +000089 let fdt = Fdt::from_mut_slice(fdt).unwrap();
90 info!("FDT passed verification.");
91 check_fdt(fdt);
92
Andrew Walbran730375d2022-12-21 14:04:34 +000093 let pci_info = PciInfo::from_fdt(fdt).unwrap();
94 debug!("Found PCI CAM at {:#x}-{:#x}", pci_info.cam_range.start, pci_info.cam_range.end);
Andrew Walbran8217d062022-11-22 16:56:18 +000095
96 modify_fdt(fdt);
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000097
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000098 check_alloc();
Andrew Walbran13564542022-04-20 16:29:45 +000099 check_data();
David Brazdil9a83e612022-09-27 17:38:10 +0000100 check_dice();
Andrew Walbran8217d062022-11-22 16:56:18 +0000101
Pierre-Clément Tosid2c54722024-11-02 12:54:40 +0000102 let mut pci_root = vmbase::virtio::pci::initialize(pci_info).unwrap();
Andrew Walbran730375d2022-12-21 14:04:34 +0000103 check_pci(&mut pci_root);
Jakob Vukalovicef996292023-04-13 14:28:34 +0000104
105 emit_suppressed_log();
Pierre-Clément Tosi3d1c2e42024-08-13 22:29:46 +0100106
107 info!("De-activating IdMap...");
Pierre-Clément Tosid2c54722024-11-02 12:54:40 +0000108 deactivate_dynamic_page_tables();
Pierre-Clément Tosi3d1c2e42024-08-13 22:29:46 +0100109 info!("De-activated.");
Andrew Walbran13564542022-04-20 16:29:45 +0000110}
111
David Brazdila51c6f02022-10-12 09:51:48 +0000112fn check_stack_guard() {
David Brazdila51c6f02022-10-12 09:51:48 +0000113 info!("Testing stack guard");
Pierre-Clément Tosi67108c32023-06-30 11:04:02 +0000114 // SAFETY: No concurrency issue should occur when running these tests.
115 let stack_guard = unsafe { bionic::TLS.stack_guard };
116 assert_ne!(stack_guard, 0);
Pierre-Clément Tosi62ffc0d2023-06-30 09:31:56 +0000117 // Check that a NULL-terminating value is added for C functions consuming strings from stack.
118 assert_eq!(stack_guard.to_ne_bytes().last(), Some(&0));
Pierre-Clément Tosi67108c32023-06-30 11:04:02 +0000119 // Check that the TLS and guard are properly accessible from the dedicated register.
120 assert_eq!(stack_guard, bionic::__get_tls().stack_guard);
121 // Check that the LLVM __stack_chk_guard alias is also properly set up.
122 assert_eq!(
123 stack_guard,
124 // SAFETY: No concurrency issue should occur when running these tests.
125 unsafe { linker::__stack_chk_guard },
126 );
David Brazdila51c6f02022-10-12 09:51:48 +0000127}
128
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000129fn check_data() {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +0100130 info!("INITIALISED_DATA: {:?}", INITIALISED_DATA.as_ptr());
Andrew Walbran47842802023-07-05 16:56:08 +0000131 // SAFETY: We only print the addresses of the static mutable variable, not actually access it.
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000132 info!("ZEROED_DATA: {:?}", unsafe { ZEROED_DATA.as_ptr() });
Andrew Walbran47842802023-07-05 16:56:08 +0000133 // SAFETY: We only print the addresses of the static mutable variable, not actually access it.
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000134 info!("MUTABLE_DATA: {:?}", unsafe { MUTABLE_DATA.as_ptr() });
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000135
136 assert_eq!(INITIALISED_DATA[0], 1);
137 assert_eq!(INITIALISED_DATA[1], 2);
138 assert_eq!(INITIALISED_DATA[2], 3);
139 assert_eq!(INITIALISED_DATA[3], 4);
140
Andrew Walbran47842802023-07-05 16:56:08 +0000141 // SAFETY: Nowhere else in the program accesses this static mutable variable, so there is no
142 // chance of concurrent access.
Chariseee5b78342024-04-08 17:59:31 +0000143 let zeroed_data = unsafe { &mut *addr_of_mut!(ZEROED_DATA) };
Andrew Walbran47842802023-07-05 16:56:08 +0000144 // SAFETY: Nowhere else in the program accesses this static mutable variable, so there is no
145 // chance of concurrent access.
Chariseeb59cda42024-04-12 19:13:36 +0000146 let mutable_data = unsafe { &mut *addr_of_mut!(MUTABLE_DATA) };
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000147
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000148 for element in zeroed_data.iter() {
149 assert_eq!(*element, 0);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000150 }
Chariseee5b78342024-04-08 17:59:31 +0000151
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000152 zeroed_data[0] = 13;
153 assert_eq!(zeroed_data[0], 13);
154 zeroed_data[0] = 0;
155 assert_eq!(zeroed_data[0], 0);
156
157 assert_eq!(mutable_data[0], 1);
158 assert_eq!(mutable_data[1], 2);
159 assert_eq!(mutable_data[2], 3);
160 assert_eq!(mutable_data[3], 4);
161 mutable_data[0] += 41;
162 assert_eq!(mutable_data[0], 42);
163 mutable_data[0] -= 41;
164 assert_eq!(mutable_data[0], 1);
165
David Brazdilb41aa8f2022-07-05 12:41:00 +0100166 info!("Data looks good");
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000167}
168
Andrew Walbran8217d062022-11-22 16:56:18 +0000169fn check_fdt(reader: &Fdt) {
Alice Wang2422bdc2023-06-12 08:37:55 +0000170 for reg in reader.memory().unwrap() {
David Brazdil1baa9a92022-06-28 14:47:50 +0100171 info!("memory @ {reg:#x?}");
172 }
173
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000174 let compatible = cstr!("ns16550a");
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000175
176 for c in reader.compatible_nodes(compatible).unwrap() {
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000177 let reg = c.reg().unwrap().unwrap().next().unwrap();
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000178 info!("node compatible with '{}' at {reg:?}", compatible.to_str().unwrap());
179 }
Andrew Walbran8217d062022-11-22 16:56:18 +0000180}
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000181
Andrew Walbran8217d062022-11-22 16:56:18 +0000182fn modify_fdt(writer: &mut Fdt) {
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000183 writer.unpack().unwrap();
184 info!("FDT successfully unpacked.");
185
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000186 let path = cstr!("/memory");
Pierre-Clément Tosia3c4ec32024-02-15 20:05:15 +0000187 let node = writer.node_mut(path).unwrap().unwrap();
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000188 let name = cstr!("child");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000189 let mut child = node.add_subnode(name).unwrap();
190 info!("Created subnode '{}/{}'.", path.to_str().unwrap(), name.to_str().unwrap());
191
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000192 let name = cstr!("str-property");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000193 child.appendprop(name, b"property-value\0").unwrap();
194 info!("Appended property '{}'.", name.to_str().unwrap());
195
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000196 let name = cstr!("pair-property");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000197 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 Brazdil1baa9a92022-06-28 14:47:50 +0100206 info!("FDT checks done.");
207}
208
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000209fn check_alloc() {
David Brazdilb41aa8f2022-07-05 12:41:00 +0100210 info!("Allocating a Vec...");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000211 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 Brazdilb41aa8f2022-07-05 12:41:00 +0100218 info!("Vec seems to work.");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000219}
David Brazdil9a83e612022-09-27 17:38:10 +0000220
221fn check_dice() {
222 info!("Testing DICE integration...");
Alice Wangcb9d2f92023-02-06 10:29:00 +0000223 let hash = diced_open_dice::hash("hello world".as_bytes()).expect("DiceHash failed");
David Brazdil9a83e612022-09-27 17:38:10 +0000224 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 Vukalovicef996292023-04-13 14:28:34 +0000235
236macro_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
246fn emit_suppressed_log() {
247 {
248 let _guard = logger::suppress();
249 log_all_levels!("Suppressed message");
250 }
251 log_all_levels!("Unsuppressed message");
252}