blob: 52a5f3e95f70271a2c053b4dda22dcbb18afdd7c [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};
Alice Wanga3931aa2023-07-05 12:52:09 +000031use vmbase::{
Pierre-Clément Tosif2c19d42024-10-01 17:42:04 +010032 bionic, configure_heap,
33 fdt::pci::PciInfo,
34 generate_image_header,
Pierre-Clément Tosiae071612024-11-02 13:13:34 +000035 layout::crosvm::FDT_MAX_SIZE,
Pierre-Clément Tosi67108c32023-06-30 11:04:02 +000036 linker, logger, main,
Pierre-Clément Tosiae071612024-11-02 13:13:34 +000037 memory::{deactivate_dynamic_page_tables, map_data, SIZE_64KB},
Alice Wanga3931aa2023-07-05 12:52:09 +000038};
Andrew Walbraneef98202022-04-27 16:23:06 +000039
Andrew Walbran5d4e1c92022-04-12 14:30:54 +000040static INITIALISED_DATA: [u32; 4] = [1, 2, 3, 4];
41static mut ZEROED_DATA: [u32; 10] = [0; 10];
42static mut MUTABLE_DATA: [u32; 4] = [1, 2, 3, 4];
43
Pierre-Clément Tosi1f7c5232024-08-13 19:51:25 +010044generate_image_header!();
Andrew Walbraneef98202022-04-27 16:23:06 +000045main!(main);
Pierre-Clément Tosi6a4808c2023-06-29 09:19:38 +000046configure_heap!(SIZE_64KB);
Andrew Walbraneef98202022-04-27 16:23:06 +000047
48/// Entry point for VM bootloader.
Andrew Walbrane03395a2022-04-29 15:15:49 +000049pub fn main(arg0: u64, arg1: u64, arg2: u64, arg3: u64) {
Pierre-Clément Tosid3305482023-06-29 15:03:48 +000050 log::set_max_level(LevelFilter::Debug);
David Brazdilb41aa8f2022-07-05 12:41:00 +010051
Jakob Vukalovicef996292023-04-13 14:28:34 +000052 info!("Hello world");
David Brazdilb41aa8f2022-07-05 12:41:00 +010053 info!("x0={:#018x}, x1={:#018x}, x2={:#018x}, x3={:#018x}", arg0, arg1, arg2, arg3);
Andrew Walbran6261cf42022-04-12 13:26:52 +000054 print_addresses();
Andrew Walbran5d4e1c92022-04-12 14:30:54 +000055 check_data();
David Brazdila51c6f02022-10-12 09:51:48 +000056 check_stack_guard();
Andrew Walbran8217d062022-11-22 16:56:18 +000057
58 info!("Checking FDT...");
Pierre-Clément Tosi9d9cf182024-08-07 16:28:53 +010059 let fdt_addr = usize::try_from(arg0).unwrap();
Andrew Walbran47842802023-07-05 16:56:08 +000060 // 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 +010061 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 +000062 map_data(fdt_addr, FDT_MAX_SIZE.try_into().unwrap()).unwrap();
Andrew Walbran8217d062022-11-22 16:56:18 +000063 let fdt = Fdt::from_mut_slice(fdt).unwrap();
64 info!("FDT passed verification.");
65 check_fdt(fdt);
66
Andrew Walbran730375d2022-12-21 14:04:34 +000067 let pci_info = PciInfo::from_fdt(fdt).unwrap();
68 debug!("Found PCI CAM at {:#x}-{:#x}", pci_info.cam_range.start, pci_info.cam_range.end);
Andrew Walbran8217d062022-11-22 16:56:18 +000069
70 modify_fdt(fdt);
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000071
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000072 check_alloc();
Andrew Walbran13564542022-04-20 16:29:45 +000073 check_data();
David Brazdil9a83e612022-09-27 17:38:10 +000074 check_dice();
Andrew Walbran8217d062022-11-22 16:56:18 +000075
Pierre-Clément Tosid2c54722024-11-02 12:54:40 +000076 let mut pci_root = vmbase::virtio::pci::initialize(pci_info).unwrap();
Andrew Walbran730375d2022-12-21 14:04:34 +000077 check_pci(&mut pci_root);
Jakob Vukalovicef996292023-04-13 14:28:34 +000078
79 emit_suppressed_log();
Pierre-Clément Tosi3d1c2e42024-08-13 22:29:46 +010080
81 info!("De-activating IdMap...");
Pierre-Clément Tosid2c54722024-11-02 12:54:40 +000082 deactivate_dynamic_page_tables();
Pierre-Clément Tosi3d1c2e42024-08-13 22:29:46 +010083 info!("De-activated.");
Andrew Walbran13564542022-04-20 16:29:45 +000084}
85
David Brazdila51c6f02022-10-12 09:51:48 +000086fn check_stack_guard() {
David Brazdila51c6f02022-10-12 09:51:48 +000087 info!("Testing stack guard");
Pierre-Clément Tosi67108c32023-06-30 11:04:02 +000088 // SAFETY: No concurrency issue should occur when running these tests.
89 let stack_guard = unsafe { bionic::TLS.stack_guard };
90 assert_ne!(stack_guard, 0);
Pierre-Clément Tosi62ffc0d2023-06-30 09:31:56 +000091 // Check that a NULL-terminating value is added for C functions consuming strings from stack.
92 assert_eq!(stack_guard.to_ne_bytes().last(), Some(&0));
Pierre-Clément Tosi67108c32023-06-30 11:04:02 +000093 // Check that the TLS and guard are properly accessible from the dedicated register.
94 assert_eq!(stack_guard, bionic::__get_tls().stack_guard);
95 // Check that the LLVM __stack_chk_guard alias is also properly set up.
96 assert_eq!(
97 stack_guard,
98 // SAFETY: No concurrency issue should occur when running these tests.
99 unsafe { linker::__stack_chk_guard },
100 );
David Brazdila51c6f02022-10-12 09:51:48 +0000101}
102
Andrew Walbran72e4e122025-01-15 12:12:33 +0000103#[allow(static_mut_refs)]
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 Walbran47842802023-07-05 16:56:08 +0000106 // SAFETY: We only print the addresses of the static mutable variable, not actually access it.
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000107 info!("ZEROED_DATA: {:?}", unsafe { ZEROED_DATA.as_ptr() });
Andrew Walbran47842802023-07-05 16:56:08 +0000108 // SAFETY: We only print the addresses of the static mutable variable, not actually access it.
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000109 info!("MUTABLE_DATA: {:?}", unsafe { MUTABLE_DATA.as_ptr() });
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000110
111 assert_eq!(INITIALISED_DATA[0], 1);
112 assert_eq!(INITIALISED_DATA[1], 2);
113 assert_eq!(INITIALISED_DATA[2], 3);
114 assert_eq!(INITIALISED_DATA[3], 4);
115
Andrew Walbran47842802023-07-05 16:56:08 +0000116 // SAFETY: Nowhere else in the program accesses this static mutable variable, so there is no
117 // chance of concurrent access.
Andrew Walbran72e4e122025-01-15 12:12:33 +0000118 let zeroed_data = unsafe { &mut ZEROED_DATA };
Andrew Walbran47842802023-07-05 16:56:08 +0000119 // SAFETY: Nowhere else in the program accesses this static mutable variable, so there is no
120 // chance of concurrent access.
Andrew Walbran72e4e122025-01-15 12:12:33 +0000121 let mutable_data = unsafe { &mut MUTABLE_DATA };
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000122
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000123 for element in zeroed_data.iter() {
124 assert_eq!(*element, 0);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000125 }
Chariseee5b78342024-04-08 17:59:31 +0000126
Pierre-Clément Tosi70b580c2023-07-07 16:26:45 +0000127 zeroed_data[0] = 13;
128 assert_eq!(zeroed_data[0], 13);
129 zeroed_data[0] = 0;
130 assert_eq!(zeroed_data[0], 0);
131
132 assert_eq!(mutable_data[0], 1);
133 assert_eq!(mutable_data[1], 2);
134 assert_eq!(mutable_data[2], 3);
135 assert_eq!(mutable_data[3], 4);
136 mutable_data[0] += 41;
137 assert_eq!(mutable_data[0], 42);
138 mutable_data[0] -= 41;
139 assert_eq!(mutable_data[0], 1);
140
David Brazdilb41aa8f2022-07-05 12:41:00 +0100141 info!("Data looks good");
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000142}
143
Andrew Walbran8217d062022-11-22 16:56:18 +0000144fn check_fdt(reader: &Fdt) {
Alice Wang2422bdc2023-06-12 08:37:55 +0000145 for reg in reader.memory().unwrap() {
David Brazdil1baa9a92022-06-28 14:47:50 +0100146 info!("memory @ {reg:#x?}");
147 }
148
Alan Stokesf46a17c2025-01-05 15:50:18 +0000149 let compatible = c"ns16550a";
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000150
151 for c in reader.compatible_nodes(compatible).unwrap() {
Pierre-Clément Tosib244d932022-11-24 16:45:53 +0000152 let reg = c.reg().unwrap().unwrap().next().unwrap();
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000153 info!("node compatible with '{}' at {reg:?}", compatible.to_str().unwrap());
154 }
Andrew Walbran8217d062022-11-22 16:56:18 +0000155}
Pierre-Clément Tosi41c158e2022-11-21 19:16:25 +0000156
Andrew Walbran8217d062022-11-22 16:56:18 +0000157fn modify_fdt(writer: &mut Fdt) {
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000158 writer.unpack().unwrap();
159 info!("FDT successfully unpacked.");
160
Alan Stokesf46a17c2025-01-05 15:50:18 +0000161 let path = c"/memory";
Pierre-Clément Tosia3c4ec32024-02-15 20:05:15 +0000162 let node = writer.node_mut(path).unwrap().unwrap();
Alan Stokesf46a17c2025-01-05 15:50:18 +0000163 let name = c"child";
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000164 let mut child = node.add_subnode(name).unwrap();
165 info!("Created subnode '{}/{}'.", path.to_str().unwrap(), name.to_str().unwrap());
166
Alan Stokesf46a17c2025-01-05 15:50:18 +0000167 let name = c"str-property";
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000168 child.appendprop(name, b"property-value\0").unwrap();
169 info!("Appended property '{}'.", name.to_str().unwrap());
170
Alan Stokesf46a17c2025-01-05 15:50:18 +0000171 let name = c"pair-property";
Pierre-Clément Tosi1b0d8902022-11-21 18:16:59 +0000172 let addr = 0x0123_4567u64;
173 let size = 0x89ab_cdefu64;
174 child.appendprop_addrrange(name, addr, size).unwrap();
175 info!("Appended property '{}'.", name.to_str().unwrap());
176
177 let writer = child.fdt();
178 writer.pack().unwrap();
179 info!("FDT successfully packed.");
180
David Brazdil1baa9a92022-06-28 14:47:50 +0100181 info!("FDT checks done.");
182}
183
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000184fn check_alloc() {
David Brazdilb41aa8f2022-07-05 12:41:00 +0100185 info!("Allocating a Vec...");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000186 let mut vector: Vec<u32> = vec![1, 2, 3, 4];
187 assert_eq!(vector[0], 1);
188 assert_eq!(vector[1], 2);
189 assert_eq!(vector[2], 3);
190 assert_eq!(vector[3], 4);
191 vector[2] = 42;
192 assert_eq!(vector[2], 42);
David Brazdilb41aa8f2022-07-05 12:41:00 +0100193 info!("Vec seems to work.");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000194}
David Brazdil9a83e612022-09-27 17:38:10 +0000195
196fn check_dice() {
197 info!("Testing DICE integration...");
Alice Wangcb9d2f92023-02-06 10:29:00 +0000198 let hash = diced_open_dice::hash("hello world".as_bytes()).expect("DiceHash failed");
David Brazdil9a83e612022-09-27 17:38:10 +0000199 assert_eq!(
200 hash,
201 [
202 0x30, 0x9e, 0xcc, 0x48, 0x9c, 0x12, 0xd6, 0xeb, 0x4c, 0xc4, 0x0f, 0x50, 0xc9, 0x02,
203 0xf2, 0xb4, 0xd0, 0xed, 0x77, 0xee, 0x51, 0x1a, 0x7c, 0x7a, 0x9b, 0xcd, 0x3c, 0xa8,
204 0x6d, 0x4c, 0xd8, 0x6f, 0x98, 0x9d, 0xd3, 0x5b, 0xc5, 0xff, 0x49, 0x96, 0x70, 0xda,
205 0x34, 0x25, 0x5b, 0x45, 0xb0, 0xcf, 0xd8, 0x30, 0xe8, 0x1f, 0x60, 0x5d, 0xcf, 0x7d,
206 0xc5, 0x54, 0x2e, 0x93, 0xae, 0x9c, 0xd7, 0x6f
207 ]
208 );
209}
Jakob Vukalovicef996292023-04-13 14:28:34 +0000210
211macro_rules! log_all_levels {
212 ($msg:literal) => {{
213 error!($msg);
214 warn!($msg);
215 info!($msg);
216 debug!($msg);
217 trace!($msg);
218 }};
219}
220
221fn emit_suppressed_log() {
222 {
223 let _guard = logger::suppress();
224 log_all_levels!("Suppressed message");
225 }
226 log_all_levels!("Unsuppressed message");
227}