blob: 9b362b2ae69a1f1e5ddfff01d5fbfa68e5d4e541 [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]
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000019#![feature(default_alloc_error_handler)]
Andrew Walbraneef98202022-04-27 16:23:06 +000020
21mod exceptions;
Andrew Walbran153aad92022-06-28 15:51:13 +000022mod layout;
Andrew Walbraneef98202022-04-27 16:23:06 +000023
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000024extern crate alloc;
25
Andrew Walbran153aad92022-06-28 15:51:13 +000026use crate::layout::{
David Brazdila51c6f02022-10-12 09:51:48 +000027 bionic_tls, dtb_range, print_addresses, rodata_range, stack_chk_guard, text_range,
28 writable_region, DEVICE_REGION,
Andrew Walbran13564542022-04-20 16:29:45 +000029};
Andrew Walbran153aad92022-06-28 15:51:13 +000030use aarch64_paging::{idmap::IdMap, paging::Attributes};
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000031use alloc::{vec, vec::Vec};
32use buddy_system_allocator::LockedHeap;
David Brazdilb41aa8f2022-07-05 12:41:00 +010033use log::{info, LevelFilter};
34use vmbase::{logger, main, println};
Andrew Walbraneef98202022-04-27 16:23:06 +000035
Andrew Walbran5d4e1c92022-04-12 14:30:54 +000036static INITIALISED_DATA: [u32; 4] = [1, 2, 3, 4];
37static mut ZEROED_DATA: [u32; 10] = [0; 10];
38static mut MUTABLE_DATA: [u32; 4] = [1, 2, 3, 4];
39
Andrew Walbran13564542022-04-20 16:29:45 +000040const ASID: usize = 1;
41const ROOT_LEVEL: usize = 1;
42
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000043#[global_allocator]
44static HEAP_ALLOCATOR: LockedHeap<32> = LockedHeap::<32>::new();
45
46static mut HEAP: [u8; 65536] = [0; 65536];
47
Andrew Walbraneef98202022-04-27 16:23:06 +000048main!(main);
49
50/// Entry point for VM bootloader.
Andrew Walbrane03395a2022-04-29 15:15:49 +000051pub fn main(arg0: u64, arg1: u64, arg2: u64, arg3: u64) {
David Brazdilb41aa8f2022-07-05 12:41:00 +010052 logger::init(LevelFilter::Debug).unwrap();
53
Andrew Walbraneef98202022-04-27 16:23:06 +000054 println!("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 Walbran153aad92022-06-28 15:51:13 +000057 assert_eq!(arg0, dtb_range().start.0 as u64);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +000058 check_data();
David Brazdila51c6f02022-10-12 09:51:48 +000059 check_stack_guard();
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000060
61 unsafe {
62 HEAP_ALLOCATOR.lock().init(&mut HEAP as *mut u8 as usize, HEAP.len());
63 }
64
65 check_alloc();
Andrew Walbran13564542022-04-20 16:29:45 +000066
67 let mut idmap = IdMap::new(ASID, ROOT_LEVEL);
68 idmap.map_range(&DEVICE_REGION, Attributes::DEVICE_NGNRE | Attributes::EXECUTE_NEVER).unwrap();
69 idmap
70 .map_range(
Andrew Walbran153aad92022-06-28 15:51:13 +000071 &text_range().into(),
Andrew Walbran13564542022-04-20 16:29:45 +000072 Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::READ_ONLY,
73 )
74 .unwrap();
75 idmap
76 .map_range(
Andrew Walbran153aad92022-06-28 15:51:13 +000077 &rodata_range().into(),
Andrew Walbran13564542022-04-20 16:29:45 +000078 Attributes::NORMAL
79 | Attributes::NON_GLOBAL
80 | Attributes::READ_ONLY
81 | Attributes::EXECUTE_NEVER,
82 )
83 .unwrap();
84 idmap
85 .map_range(
86 &writable_region(),
87 Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::EXECUTE_NEVER,
88 )
89 .unwrap();
90
David Brazdilb41aa8f2022-07-05 12:41:00 +010091 info!("Activating IdMap...");
92 info!("{:?}", idmap);
Andrew Walbran13564542022-04-20 16:29:45 +000093 idmap.activate();
David Brazdilb41aa8f2022-07-05 12:41:00 +010094 info!("Activated.");
Andrew Walbran13564542022-04-20 16:29:45 +000095
96 check_data();
97}
98
David Brazdila51c6f02022-10-12 09:51:48 +000099fn check_stack_guard() {
100 const BIONIC_TLS_STACK_GRD_OFF: usize = 40;
101
102 info!("Testing stack guard");
103 assert_eq!(bionic_tls(BIONIC_TLS_STACK_GRD_OFF), stack_chk_guard());
104}
105
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000106fn check_data() {
David Brazdilb41aa8f2022-07-05 12:41:00 +0100107 info!("INITIALISED_DATA: {:#010x}", &INITIALISED_DATA as *const u32 as usize);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000108 unsafe {
David Brazdilb41aa8f2022-07-05 12:41:00 +0100109 info!("ZEROED_DATA: {:#010x}", &ZEROED_DATA as *const u32 as usize);
110 info!("MUTABLE_DATA: {:#010x}", &MUTABLE_DATA as *const u32 as usize);
111 info!("HEAP: {:#010x}", &HEAP as *const u8 as usize);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000112 }
113
114 assert_eq!(INITIALISED_DATA[0], 1);
115 assert_eq!(INITIALISED_DATA[1], 2);
116 assert_eq!(INITIALISED_DATA[2], 3);
117 assert_eq!(INITIALISED_DATA[3], 4);
118
119 unsafe {
120 for element in ZEROED_DATA.iter() {
121 assert_eq!(*element, 0);
122 }
123 ZEROED_DATA[0] = 13;
124 assert_eq!(ZEROED_DATA[0], 13);
125 ZEROED_DATA[0] = 0;
126 assert_eq!(ZEROED_DATA[0], 0);
127
128 assert_eq!(MUTABLE_DATA[0], 1);
129 assert_eq!(MUTABLE_DATA[1], 2);
130 assert_eq!(MUTABLE_DATA[2], 3);
131 assert_eq!(MUTABLE_DATA[3], 4);
132 MUTABLE_DATA[0] += 41;
133 assert_eq!(MUTABLE_DATA[0], 42);
Andrew Walbran13564542022-04-20 16:29:45 +0000134 MUTABLE_DATA[0] -= 41;
135 assert_eq!(MUTABLE_DATA[0], 1);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000136 }
David Brazdilb41aa8f2022-07-05 12:41:00 +0100137 info!("Data looks good");
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000138}
139
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000140fn check_alloc() {
David Brazdilb41aa8f2022-07-05 12:41:00 +0100141 info!("Allocating a Vec...");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000142 let mut vector: Vec<u32> = vec![1, 2, 3, 4];
143 assert_eq!(vector[0], 1);
144 assert_eq!(vector[1], 2);
145 assert_eq!(vector[2], 3);
146 assert_eq!(vector[3], 4);
147 vector[2] = 42;
148 assert_eq!(vector[2], 42);
David Brazdilb41aa8f2022-07-05 12:41:00 +0100149 info!("Vec seems to work.");
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000150}