blob: 4c5e880f1682bd956a948c2bfda3e2fd3cf681be [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;
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000028use alloc::{vec, vec::Vec};
Chariseee5b78342024-04-08 17:59:31 +000029use core::ptr::addr_of_mut;
Pierre-Clément Tosi1bf532b2023-11-13 11:06:20 +000030use cstr::cstr;
David Brazdil1baa9a92022-06-28 14:47:50 +010031use libfdt::Fdt;
Jakob Vukalovicef996292023-04-13 14:28:34 +000032use log::{debug, error, info, trace, warn, LevelFilter};
Alice Wanga3931aa2023-07-05 12:52:09 +000033use vmbase::{
Pierre-Clément Tosif2c19d42024-10-01 17:42:04 +010034 bionic, configure_heap,
35 fdt::pci::PciInfo,
36 generate_image_header,
Pierre-Clément Tosiae071612024-11-02 13:13:34 +000037 layout::crosvm::FDT_MAX_SIZE,
Pierre-Clément Tosi67108c32023-06-30 11:04:02 +000038 linker, logger, main,
Pierre-Clément Tosiae071612024-11-02 13:13:34 +000039 memory::{deactivate_dynamic_page_tables, map_data, SIZE_64KB},
Alice Wanga3931aa2023-07-05 12:52:09 +000040};
Andrew Walbraneef98202022-04-27 16:23:06 +000041
Andrew Walbran5d4e1c92022-04-12 14:30:54 +000042static INITIALISED_DATA: [u32; 4] = [1, 2, 3, 4];
43static mut ZEROED_DATA: [u32; 10] = [0; 10];
44static mut MUTABLE_DATA: [u32; 4] = [1, 2, 3, 4];
45
Pierre-Clément Tosi1f7c5232024-08-13 19:51:25 +010046generate_image_header!();
Andrew Walbraneef98202022-04-27 16:23:06 +000047main!(main);
Pierre-Clément Tosi6a4808c2023-06-29 09:19:38 +000048configure_heap!(SIZE_64KB);
Andrew Walbraneef98202022-04-27 16:23:06 +000049
50/// Entry point for VM bootloader.
Andrew Walbrane03395a2022-04-29 15:15:49 +000051pub fn main(arg0: u64, arg1: u64, arg2: u64, arg3: u64) {
Pierre-Clément Tosid3305482023-06-29 15:03:48 +000052 log::set_max_level(LevelFilter::Debug);
David Brazdilb41aa8f2022-07-05 12:41:00 +010053
Jakob Vukalovicef996292023-04-13 14:28:34 +000054 info!("Hello world");
David Brazdilb41aa8f2022-07-05 12:41:00 +010055 info!("x0={:#018x}, x1={:#018x}, x2={:#018x}, x3={:#018x}", arg0, arg1, arg2, arg3);
Andrew Walbran6261cf42022-04-12 13:26:52 +000056 print_addresses();
Andrew Walbran5d4e1c92022-04-12 14:30:54 +000057 check_data();
David Brazdila51c6f02022-10-12 09:51:48 +000058 check_stack_guard();
Andrew Walbran8217d062022-11-22 16:56:18 +000059
60 info!("Checking FDT...");
Pierre-Clément Tosi9d9cf182024-08-07 16:28:53 +010061 let fdt_addr = usize::try_from(arg0).unwrap();
Andrew Walbran47842802023-07-05 16:56:08 +000062 // 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 +010063 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 +000064 map_data(fdt_addr, FDT_MAX_SIZE.try_into().unwrap()).unwrap();
Andrew Walbran8217d062022-11-22 16:56:18 +000065 let fdt = Fdt::from_mut_slice(fdt).unwrap();
66 info!("FDT passed verification.");
67 check_fdt(fdt);
68
Andrew Walbran730375d2022-12-21 14:04:34 +000069 let pci_info = PciInfo::from_fdt(fdt).unwrap();
70 debug!("Found PCI CAM at {:#x}-{:#x}", pci_info.cam_range.start, pci_info.cam_range.end);
Andrew Walbran8217d062022-11-22 16:56:18 +000071
72 modify_fdt(fdt);
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000073
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000074 check_alloc();
Andrew Walbran13564542022-04-20 16:29:45 +000075 check_data();
David Brazdil9a83e612022-09-27 17:38:10 +000076 check_dice();
Andrew Walbran8217d062022-11-22 16:56:18 +000077
Pierre-Clément Tosid2c54722024-11-02 12:54:40 +000078 let mut pci_root = vmbase::virtio::pci::initialize(pci_info).unwrap();
Andrew Walbran730375d2022-12-21 14:04:34 +000079 check_pci(&mut pci_root);
Jakob Vukalovicef996292023-04-13 14:28:34 +000080
81 emit_suppressed_log();
Pierre-Clément Tosi3d1c2e42024-08-13 22:29:46 +010082
83 info!("De-activating IdMap...");
Pierre-Clément Tosid2c54722024-11-02 12:54:40 +000084 deactivate_dynamic_page_tables();
Pierre-Clément Tosi3d1c2e42024-08-13 22:29:46 +010085 info!("De-activated.");
Andrew Walbran13564542022-04-20 16:29:45 +000086}
87
David Brazdila51c6f02022-10-12 09:51:48 +000088fn check_stack_guard() {
David Brazdila51c6f02022-10-12 09:51:48 +000089 info!("Testing stack guard");
Pierre-Clément Tosi67108c32023-06-30 11:04:02 +000090 // SAFETY: No concurrency issue should occur when running these tests.
91 let stack_guard = unsafe { bionic::TLS.stack_guard };
92 assert_ne!(stack_guard, 0);
Pierre-Clément Tosi62ffc0d2023-06-30 09:31:56 +000093 // Check that a NULL-terminating value is added for C functions consuming strings from stack.
94 assert_eq!(stack_guard.to_ne_bytes().last(), Some(&0));
Pierre-Clément Tosi67108c32023-06-30 11:04:02 +000095 // Check that the TLS and guard are properly accessible from the dedicated register.
96 assert_eq!(stack_guard, bionic::__get_tls().stack_guard);
97 // Check that the LLVM __stack_chk_guard alias is also properly set up.
98 assert_eq!(
99 stack_guard,
100 // SAFETY: No concurrency issue should occur when running these tests.
101 unsafe { linker::__stack_chk_guard },
102 );
David Brazdila51c6f02022-10-12 09:51:48 +0000103}
104
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000105fn check_data() {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +0100106 info!("INITIALISED_DATA: {:?}", INITIALISED_DATA.as_ptr());
Andrew Walbran47842802023-07-05 16:56:08 +0000107 // SAFETY: We only print the addresses of the static mutable variable, not actually access it.
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000108 info!("ZEROED_DATA: {:?}", unsafe { ZEROED_DATA.as_ptr() });
Andrew Walbran47842802023-07-05 16:56:08 +0000109 // SAFETY: We only print the addresses of the static mutable variable, not actually access it.
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000110 info!("MUTABLE_DATA: {:?}", unsafe { MUTABLE_DATA.as_ptr() });
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000111
112 assert_eq!(INITIALISED_DATA[0], 1);
113 assert_eq!(INITIALISED_DATA[1], 2);
114 assert_eq!(INITIALISED_DATA[2], 3);
115 assert_eq!(INITIALISED_DATA[3], 4);
116
Andrew Walbran47842802023-07-05 16:56:08 +0000117 // SAFETY: Nowhere else in the program accesses this static mutable variable, so there is no
118 // chance of concurrent access.
Chariseee5b78342024-04-08 17:59:31 +0000119 let zeroed_data = unsafe { &mut *addr_of_mut!(ZEROED_DATA) };
Andrew Walbran47842802023-07-05 16:56:08 +0000120 // SAFETY: Nowhere else in the program accesses this static mutable variable, so there is no
121 // chance of concurrent access.
Chariseeb59cda42024-04-12 19:13:36 +0000122 let mutable_data = unsafe { &mut *addr_of_mut!(MUTABLE_DATA) };
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000123
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000124 for element in zeroed_data.iter() {
125 assert_eq!(*element, 0);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000126 }
Chariseee5b78342024-04-08 17:59:31 +0000127
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000128 zeroed_data[0] = 13;
129 assert_eq!(zeroed_data[0], 13);
130 zeroed_data[0] = 0;
131 assert_eq!(zeroed_data[0], 0);
132
133 assert_eq!(mutable_data[0], 1);
134 assert_eq!(mutable_data[1], 2);
135 assert_eq!(mutable_data[2], 3);
136 assert_eq!(mutable_data[3], 4);
137 mutable_data[0] += 41;
138 assert_eq!(mutable_data[0], 42);
139 mutable_data[0] -= 41;
140 assert_eq!(mutable_data[0], 1);
141
David Brazdilb41aa8f2022-07-05 12:41:00 +0100142 info!("Data looks good");
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000143}
144
Andrew Walbran8217d062022-11-22 16:56:18 +0000145fn check_fdt(reader: &Fdt) {
Alice Wang2422bdc2023-06-12 08:37:55 +0000146 for reg in reader.memory().unwrap() {
David Brazdil1baa9a92022-06-28 14:47:50 +0100147 info!("memory @ {reg:#x?}");
148 }
149
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000150 let compatible = cstr!("ns16550a");
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000151
152 for c in reader.compatible_nodes(compatible).unwrap() {
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000153 let reg = c.reg().unwrap().unwrap().next().unwrap();
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000154 info!("node compatible with '{}' at {reg:?}", compatible.to_str().unwrap());
155 }
Andrew Walbran8217d062022-11-22 16:56:18 +0000156}
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000157
Andrew Walbran8217d062022-11-22 16:56:18 +0000158fn modify_fdt(writer: &mut Fdt) {
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000159 writer.unpack().unwrap();
160 info!("FDT successfully unpacked.");
161
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000162 let path = cstr!("/memory");
Pierre-Clément Tosia3c4ec32024-02-15 20:05:15 +0000163 let node = writer.node_mut(path).unwrap().unwrap();
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000164 let name = cstr!("child");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000165 let mut child = node.add_subnode(name).unwrap();
166 info!("Created subnode '{}/{}'.", path.to_str().unwrap(), name.to_str().unwrap());
167
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000168 let name = cstr!("str-property");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000169 child.appendprop(name, b"property-value\0").unwrap();
170 info!("Appended property '{}'.", name.to_str().unwrap());
171
Pierre-Clément Tosi8ecc78b2023-06-13 12:41:13 +0000172 let name = cstr!("pair-property");
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000173 let addr = 0x0123_4567u64;
174 let size = 0x89ab_cdefu64;
175 child.appendprop_addrrange(name, addr, size).unwrap();
176 info!("Appended property '{}'.", name.to_str().unwrap());
177
178 let writer = child.fdt();
179 writer.pack().unwrap();
180 info!("FDT successfully packed.");
181
David Brazdil1baa9a92022-06-28 14:47:50 +0100182 info!("FDT checks done.");
183}
184
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000185fn check_alloc() {
David Brazdilb41aa8f2022-07-05 12:41:00 +0100186 info!("Allocating a Vec...");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000187 let mut vector: Vec<u32> = vec![1, 2, 3, 4];
188 assert_eq!(vector[0], 1);
189 assert_eq!(vector[1], 2);
190 assert_eq!(vector[2], 3);
191 assert_eq!(vector[3], 4);
192 vector[2] = 42;
193 assert_eq!(vector[2], 42);
David Brazdilb41aa8f2022-07-05 12:41:00 +0100194 info!("Vec seems to work.");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000195}
David Brazdil9a83e612022-09-27 17:38:10 +0000196
197fn check_dice() {
198 info!("Testing DICE integration...");
Alice Wangcb9d2f92023-02-06 10:29:00 +0000199 let hash = diced_open_dice::hash("hello world".as_bytes()).expect("DiceHash failed");
David Brazdil9a83e612022-09-27 17:38:10 +0000200 assert_eq!(
201 hash,
202 [
203 0x30, 0x9e, 0xcc, 0x48, 0x9c, 0x12, 0xd6, 0xeb, 0x4c, 0xc4, 0x0f, 0x50, 0xc9, 0x02,
204 0xf2, 0xb4, 0xd0, 0xed, 0x77, 0xee, 0x51, 0x1a, 0x7c, 0x7a, 0x9b, 0xcd, 0x3c, 0xa8,
205 0x6d, 0x4c, 0xd8, 0x6f, 0x98, 0x9d, 0xd3, 0x5b, 0xc5, 0xff, 0x49, 0x96, 0x70, 0xda,
206 0x34, 0x25, 0x5b, 0x45, 0xb0, 0xcf, 0xd8, 0x30, 0xe8, 0x1f, 0x60, 0x5d, 0xcf, 0x7d,
207 0xc5, 0x54, 0x2e, 0x93, 0xae, 0x9c, 0xd7, 0x6f
208 ]
209 );
210}
Jakob Vukalovicef996292023-04-13 14:28:34 +0000211
212macro_rules! log_all_levels {
213 ($msg:literal) => {{
214 error!($msg);
215 warn!($msg);
216 info!($msg);
217 debug!($msg);
218 trace!($msg);
219 }};
220}
221
222fn emit_suppressed_log() {
223 {
224 let _guard = logger::suppress();
225 log_all_levels!("Suppressed message");
226 }
227 log_all_levels!("Unsuppressed message");
228}