blob: b7d2f95a396bbf6b139f51e1c034c59007cd750f [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};
David Brazdil1baa9a92022-06-28 14:47:50 +010029use libfdt::Fdt;
Jakob Vukalovicef996292023-04-13 14:28:34 +000030use log::{debug, error, info, trace, warn, LevelFilter};
Andrew Walbranfb49a412025-01-15 12:14:24 +000031use spin::mutex::SpinMutex;
Alice Wanga3931aa2023-07-05 12:52:09 +000032use vmbase::{
Pierre-Clément Tosif2c19d42024-10-01 17:42:04 +010033 bionic, configure_heap,
34 fdt::pci::PciInfo,
35 generate_image_header,
Pierre-Clément Tosiae071612024-11-02 13:13:34 +000036 layout::crosvm::FDT_MAX_SIZE,
Pierre-Clément Tosi67108c32023-06-30 11:04:02 +000037 linker, logger, main,
Pierre-Clément Tosiae071612024-11-02 13:13:34 +000038 memory::{deactivate_dynamic_page_tables, map_data, SIZE_64KB},
Alice Wanga3931aa2023-07-05 12:52:09 +000039};
Andrew Walbraneef98202022-04-27 16:23:06 +000040
Andrew Walbran5d4e1c92022-04-12 14:30:54 +000041static INITIALISED_DATA: [u32; 4] = [1, 2, 3, 4];
Andrew Walbranfb49a412025-01-15 12:14:24 +000042static ZEROED_DATA: SpinMutex<[u32; 10]> = SpinMutex::new([0; 10]);
43static MUTABLE_DATA: SpinMutex<[u32; 4]> = SpinMutex::new([1, 2, 3, 4]);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +000044
Pierre-Clément Tosi1f7c5232024-08-13 19:51:25 +010045generate_image_header!();
Andrew Walbraneef98202022-04-27 16:23:06 +000046main!(main);
Pierre-Clément Tosi6a4808c2023-06-29 09:19:38 +000047configure_heap!(SIZE_64KB);
Andrew Walbraneef98202022-04-27 16:23:06 +000048
49/// Entry point for VM bootloader.
Andrew Walbrane03395a2022-04-29 15:15:49 +000050pub fn main(arg0: u64, arg1: u64, arg2: u64, arg3: u64) {
Pierre-Clément Tosid3305482023-06-29 15:03:48 +000051 log::set_max_level(LevelFilter::Debug);
David Brazdilb41aa8f2022-07-05 12:41:00 +010052
Jakob Vukalovicef996292023-04-13 14:28:34 +000053 info!("Hello world");
David Brazdilb41aa8f2022-07-05 12:41:00 +010054 info!("x0={:#018x}, x1={:#018x}, x2={:#018x}, x3={:#018x}", arg0, arg1, arg2, arg3);
Andrew Walbran6261cf42022-04-12 13:26:52 +000055 print_addresses();
Andrew Walbran5d4e1c92022-04-12 14:30:54 +000056 check_data();
David Brazdila51c6f02022-10-12 09:51:48 +000057 check_stack_guard();
Andrew Walbran8217d062022-11-22 16:56:18 +000058
59 info!("Checking FDT...");
Pierre-Clément Tosi9d9cf182024-08-07 16:28:53 +010060 let fdt_addr = usize::try_from(arg0).unwrap();
Andrew Walbran47842802023-07-05 16:56:08 +000061 // 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 +010062 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 +000063 map_data(fdt_addr, FDT_MAX_SIZE.try_into().unwrap()).unwrap();
Andrew Walbran8217d062022-11-22 16:56:18 +000064 let fdt = Fdt::from_mut_slice(fdt).unwrap();
65 info!("FDT passed verification.");
66 check_fdt(fdt);
67
Andrew Walbran730375d2022-12-21 14:04:34 +000068 let pci_info = PciInfo::from_fdt(fdt).unwrap();
69 debug!("Found PCI CAM at {:#x}-{:#x}", pci_info.cam_range.start, pci_info.cam_range.end);
Andrew Walbran8217d062022-11-22 16:56:18 +000070
71 modify_fdt(fdt);
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000072
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000073 check_alloc();
Andrew Walbran13564542022-04-20 16:29:45 +000074 check_data();
David Brazdil9a83e612022-09-27 17:38:10 +000075 check_dice();
Andrew Walbran8217d062022-11-22 16:56:18 +000076
Pierre-Clément Tosid2c54722024-11-02 12:54:40 +000077 let mut pci_root = vmbase::virtio::pci::initialize(pci_info).unwrap();
Andrew Walbran730375d2022-12-21 14:04:34 +000078 check_pci(&mut pci_root);
Jakob Vukalovicef996292023-04-13 14:28:34 +000079
80 emit_suppressed_log();
Pierre-Clément Tosi3d1c2e42024-08-13 22:29:46 +010081
82 info!("De-activating IdMap...");
Pierre-Clément Tosid2c54722024-11-02 12:54:40 +000083 deactivate_dynamic_page_tables();
Pierre-Clément Tosi3d1c2e42024-08-13 22:29:46 +010084 info!("De-activated.");
Andrew Walbran13564542022-04-20 16:29:45 +000085}
86
David Brazdila51c6f02022-10-12 09:51:48 +000087fn check_stack_guard() {
David Brazdila51c6f02022-10-12 09:51:48 +000088 info!("Testing stack guard");
Pierre-Clément Tosi67108c32023-06-30 11:04:02 +000089 // SAFETY: No concurrency issue should occur when running these tests.
90 let stack_guard = unsafe { bionic::TLS.stack_guard };
91 assert_ne!(stack_guard, 0);
Pierre-Clément Tosi62ffc0d2023-06-30 09:31:56 +000092 // Check that a NULL-terminating value is added for C functions consuming strings from stack.
93 assert_eq!(stack_guard.to_ne_bytes().last(), Some(&0));
Pierre-Clément Tosi67108c32023-06-30 11:04:02 +000094 // Check that the TLS and guard are properly accessible from the dedicated register.
95 assert_eq!(stack_guard, bionic::__get_tls().stack_guard);
96 // Check that the LLVM __stack_chk_guard alias is also properly set up.
97 assert_eq!(
98 stack_guard,
99 // SAFETY: No concurrency issue should occur when running these tests.
100 unsafe { linker::__stack_chk_guard },
101 );
David Brazdila51c6f02022-10-12 09:51:48 +0000102}
103
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000104fn check_data() {
Pierre-Clément Tosi581e9b62022-10-27 16:21:13 +0100105 info!("INITIALISED_DATA: {:?}", INITIALISED_DATA.as_ptr());
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000106
107 assert_eq!(INITIALISED_DATA[0], 1);
108 assert_eq!(INITIALISED_DATA[1], 2);
109 assert_eq!(INITIALISED_DATA[2], 3);
110 assert_eq!(INITIALISED_DATA[3], 4);
111
Andrew Walbranfb49a412025-01-15 12:14:24 +0000112 let zeroed_data = &mut *ZEROED_DATA.lock();
113 let mutable_data = &mut *MUTABLE_DATA.lock();
114 info!("ZEROED_DATA: {:?}", zeroed_data.as_ptr());
115 info!("MUTABLE_DATA: {:?}", mutable_data.as_ptr());
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000116
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000117 for element in zeroed_data.iter() {
118 assert_eq!(*element, 0);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000119 }
Chariseee5b78342024-04-08 17:59:31 +0000120
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000121 zeroed_data[0] = 13;
122 assert_eq!(zeroed_data[0], 13);
123 zeroed_data[0] = 0;
124 assert_eq!(zeroed_data[0], 0);
125
126 assert_eq!(mutable_data[0], 1);
127 assert_eq!(mutable_data[1], 2);
128 assert_eq!(mutable_data[2], 3);
129 assert_eq!(mutable_data[3], 4);
130 mutable_data[0] += 41;
131 assert_eq!(mutable_data[0], 42);
132 mutable_data[0] -= 41;
133 assert_eq!(mutable_data[0], 1);
134
David Brazdilb41aa8f2022-07-05 12:41:00 +0100135 info!("Data looks good");
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000136}
137
Andrew Walbran8217d062022-11-22 16:56:18 +0000138fn check_fdt(reader: &Fdt) {
Alice Wang2422bdc2023-06-12 08:37:55 +0000139 for reg in reader.memory().unwrap() {
David Brazdil1baa9a92022-06-28 14:47:50 +0100140 info!("memory @ {reg:#x?}");
141 }
142
Alan Stokesf46a17c2025-01-05 15:50:18 +0000143 let compatible = c"ns16550a";
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000144
145 for c in reader.compatible_nodes(compatible).unwrap() {
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000146 let reg = c.reg().unwrap().unwrap().next().unwrap();
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000147 info!("node compatible with '{}' at {reg:?}", compatible.to_str().unwrap());
148 }
Andrew Walbran8217d062022-11-22 16:56:18 +0000149}
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000150
Andrew Walbran8217d062022-11-22 16:56:18 +0000151fn modify_fdt(writer: &mut Fdt) {
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000152 writer.unpack().unwrap();
153 info!("FDT successfully unpacked.");
154
Alan Stokesf46a17c2025-01-05 15:50:18 +0000155 let path = c"/memory";
Pierre-Clément Tosia3c4ec32024-02-15 20:05:15 +0000156 let node = writer.node_mut(path).unwrap().unwrap();
Alan Stokesf46a17c2025-01-05 15:50:18 +0000157 let name = c"child";
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000158 let mut child = node.add_subnode(name).unwrap();
159 info!("Created subnode '{}/{}'.", path.to_str().unwrap(), name.to_str().unwrap());
160
Alan Stokesf46a17c2025-01-05 15:50:18 +0000161 let name = c"str-property";
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000162 child.appendprop(name, b"property-value\0").unwrap();
163 info!("Appended property '{}'.", name.to_str().unwrap());
164
Alan Stokesf46a17c2025-01-05 15:50:18 +0000165 let name = c"pair-property";
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000166 let addr = 0x0123_4567u64;
167 let size = 0x89ab_cdefu64;
168 child.appendprop_addrrange(name, addr, size).unwrap();
169 info!("Appended property '{}'.", name.to_str().unwrap());
170
171 let writer = child.fdt();
172 writer.pack().unwrap();
173 info!("FDT successfully packed.");
174
David Brazdil1baa9a92022-06-28 14:47:50 +0100175 info!("FDT checks done.");
176}
177
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000178fn check_alloc() {
David Brazdilb41aa8f2022-07-05 12:41:00 +0100179 info!("Allocating a Vec...");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000180 let mut vector: Vec<u32> = vec![1, 2, 3, 4];
181 assert_eq!(vector[0], 1);
182 assert_eq!(vector[1], 2);
183 assert_eq!(vector[2], 3);
184 assert_eq!(vector[3], 4);
185 vector[2] = 42;
186 assert_eq!(vector[2], 42);
David Brazdilb41aa8f2022-07-05 12:41:00 +0100187 info!("Vec seems to work.");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000188}
David Brazdil9a83e612022-09-27 17:38:10 +0000189
190fn check_dice() {
191 info!("Testing DICE integration...");
Alice Wangcb9d2f92023-02-06 10:29:00 +0000192 let hash = diced_open_dice::hash("hello world".as_bytes()).expect("DiceHash failed");
David Brazdil9a83e612022-09-27 17:38:10 +0000193 assert_eq!(
194 hash,
195 [
196 0x30, 0x9e, 0xcc, 0x48, 0x9c, 0x12, 0xd6, 0xeb, 0x4c, 0xc4, 0x0f, 0x50, 0xc9, 0x02,
197 0xf2, 0xb4, 0xd0, 0xed, 0x77, 0xee, 0x51, 0x1a, 0x7c, 0x7a, 0x9b, 0xcd, 0x3c, 0xa8,
198 0x6d, 0x4c, 0xd8, 0x6f, 0x98, 0x9d, 0xd3, 0x5b, 0xc5, 0xff, 0x49, 0x96, 0x70, 0xda,
199 0x34, 0x25, 0x5b, 0x45, 0xb0, 0xcf, 0xd8, 0x30, 0xe8, 0x1f, 0x60, 0x5d, 0xcf, 0x7d,
200 0xc5, 0x54, 0x2e, 0x93, 0xae, 0x9c, 0xd7, 0x6f
201 ]
202 );
203}
Jakob Vukalovicef996292023-04-13 14:28:34 +0000204
205macro_rules! log_all_levels {
206 ($msg:literal) => {{
207 error!($msg);
208 warn!($msg);
209 info!($msg);
210 debug!($msg);
211 trace!($msg);
212 }};
213}
214
215fn emit_suppressed_log() {
216 {
217 let _guard = logger::suppress();
218 log_all_levels!("Suppressed message");
219 }
220 log_all_levels!("Unsuppressed message");
221}