blob: 39320fd0046014e9d8f617db20b5a367f98092ed [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;
22
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000023extern crate alloc;
24
Andrew Walbran13564542022-04-20 16:29:45 +000025use aarch64_paging::{
26 idmap::IdMap,
27 paging::{Attributes, MemoryRegion},
28};
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000029use alloc::{vec, vec::Vec};
30use buddy_system_allocator::LockedHeap;
Andrew Walbraneef98202022-04-27 16:23:06 +000031use vmbase::{main, println};
32
Andrew Walbran5d4e1c92022-04-12 14:30:54 +000033static INITIALISED_DATA: [u32; 4] = [1, 2, 3, 4];
34static mut ZEROED_DATA: [u32; 10] = [0; 10];
35static mut MUTABLE_DATA: [u32; 4] = [1, 2, 3, 4];
36
Andrew Walbran13564542022-04-20 16:29:45 +000037const ASID: usize = 1;
38const ROOT_LEVEL: usize = 1;
39
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000040#[global_allocator]
41static HEAP_ALLOCATOR: LockedHeap<32> = LockedHeap::<32>::new();
42
43static mut HEAP: [u8; 65536] = [0; 65536];
44
Andrew Walbran13564542022-04-20 16:29:45 +000045/// The first 1 GiB of memory are used for MMIO.
46const DEVICE_REGION: MemoryRegion = MemoryRegion::new(0, 0x40000000);
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) {
Andrew Walbraneef98202022-04-27 16:23:06 +000052 println!("Hello world");
Andrew Walbrane03395a2022-04-29 15:15:49 +000053 println!("x0={:#010x}, x1={:#010x}, x2={:#010x}, x3={:#010x}", arg0, arg1, arg2, arg3);
Andrew Walbran6261cf42022-04-12 13:26:52 +000054 print_addresses();
Andrew Walbran06cba032022-05-05 15:49:53 +000055 unsafe {
56 assert_eq!(arg0, &dtb_begin as *const u8 as u64);
57 }
Andrew Walbran5d4e1c92022-04-12 14:30:54 +000058 check_data();
Andrew Walbranf7b6dc82022-04-20 16:24:30 +000059
60 unsafe {
61 HEAP_ALLOCATOR.lock().init(&mut HEAP as *mut u8 as usize, HEAP.len());
62 }
63
64 check_alloc();
Andrew Walbran13564542022-04-20 16:29:45 +000065
66 let mut idmap = IdMap::new(ASID, ROOT_LEVEL);
67 idmap.map_range(&DEVICE_REGION, Attributes::DEVICE_NGNRE | Attributes::EXECUTE_NEVER).unwrap();
68 idmap
69 .map_range(
70 &text_region(),
71 Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::READ_ONLY,
72 )
73 .unwrap();
74 idmap
75 .map_range(
76 &rodata_region(),
77 Attributes::NORMAL
78 | Attributes::NON_GLOBAL
79 | Attributes::READ_ONLY
80 | Attributes::EXECUTE_NEVER,
81 )
82 .unwrap();
83 idmap
84 .map_range(
85 &writable_region(),
86 Attributes::NORMAL | Attributes::NON_GLOBAL | Attributes::EXECUTE_NEVER,
87 )
88 .unwrap();
89
90 println!("Activating IdMap...");
91 println!("{:?}", idmap);
92 idmap.activate();
93 println!("Activated.");
94
95 check_data();
96}
97
98/// Executable code.
99fn text_region() -> MemoryRegion {
100 unsafe { MemoryRegion::new(&text_begin as *const u8 as usize, &text_end as *const u8 as usize) }
101}
102
103/// Read-only data.
104fn rodata_region() -> MemoryRegion {
105 unsafe {
106 MemoryRegion::new(&rodata_begin as *const u8 as usize, &rodata_end as *const u8 as usize)
107 }
108}
109
110/// Writable data, including the stack.
111fn writable_region() -> MemoryRegion {
112 unsafe {
113 MemoryRegion::new(&data_begin as *const u8 as usize, &boot_stack_end as *const u8 as usize)
114 }
Andrew Walbran6261cf42022-04-12 13:26:52 +0000115}
116
117fn print_addresses() {
118 unsafe {
119 println!(
120 "dtb: {:#010x}-{:#010x} ({} bytes)",
121 &dtb_begin as *const u8 as usize,
122 &dtb_end as *const u8 as usize,
123 &dtb_end as *const u8 as usize - &dtb_begin as *const u8 as usize,
124 );
125 println!(
126 "text: {:#010x}-{:#010x} ({} bytes)",
127 &text_begin as *const u8 as usize,
128 &text_end as *const u8 as usize,
129 &text_end as *const u8 as usize - &text_begin as *const u8 as usize,
130 );
131 println!(
132 "rodata: {:#010x}-{:#010x} ({} bytes)",
133 &rodata_begin as *const u8 as usize,
134 &rodata_end as *const u8 as usize,
135 &rodata_end as *const u8 as usize - &rodata_begin as *const u8 as usize,
136 );
137 println!(
138 "data: {:#010x}-{:#010x} ({} bytes, loaded at {:#010x})",
139 &data_begin as *const u8 as usize,
140 &data_end as *const u8 as usize,
141 &data_end as *const u8 as usize - &data_begin as *const u8 as usize,
142 &data_lma as *const u8 as usize,
143 );
144 println!(
145 "bss: {:#010x}-{:#010x} ({} bytes)",
146 &bss_begin as *const u8 as usize,
147 &bss_end as *const u8 as usize,
148 &bss_end as *const u8 as usize - &bss_begin as *const u8 as usize,
149 );
150 println!(
151 "boot_stack: {:#010x}-{:#010x} ({} bytes)",
152 &boot_stack_begin as *const u8 as usize,
153 &boot_stack_end as *const u8 as usize,
154 &boot_stack_end as *const u8 as usize - &boot_stack_begin as *const u8 as usize,
155 );
156 }
157}
158
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000159fn check_data() {
160 println!("INITIALISED_DATA: {:#010x}", &INITIALISED_DATA as *const u32 as usize);
161 unsafe {
162 println!("ZEROED_DATA: {:#010x}", &ZEROED_DATA as *const u32 as usize);
163 println!("MUTABLE_DATA: {:#010x}", &MUTABLE_DATA as *const u32 as usize);
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000164 println!("HEAP: {:#010x}", &HEAP as *const u8 as usize);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000165 }
166
167 assert_eq!(INITIALISED_DATA[0], 1);
168 assert_eq!(INITIALISED_DATA[1], 2);
169 assert_eq!(INITIALISED_DATA[2], 3);
170 assert_eq!(INITIALISED_DATA[3], 4);
171
172 unsafe {
173 for element in ZEROED_DATA.iter() {
174 assert_eq!(*element, 0);
175 }
176 ZEROED_DATA[0] = 13;
177 assert_eq!(ZEROED_DATA[0], 13);
178 ZEROED_DATA[0] = 0;
179 assert_eq!(ZEROED_DATA[0], 0);
180
181 assert_eq!(MUTABLE_DATA[0], 1);
182 assert_eq!(MUTABLE_DATA[1], 2);
183 assert_eq!(MUTABLE_DATA[2], 3);
184 assert_eq!(MUTABLE_DATA[3], 4);
185 MUTABLE_DATA[0] += 41;
186 assert_eq!(MUTABLE_DATA[0], 42);
Andrew Walbran13564542022-04-20 16:29:45 +0000187 MUTABLE_DATA[0] -= 41;
188 assert_eq!(MUTABLE_DATA[0], 1);
Andrew Walbran5d4e1c92022-04-12 14:30:54 +0000189 }
190 println!("Data looks good");
191}
192
Andrew Walbranf7b6dc82022-04-20 16:24:30 +0000193fn check_alloc() {
194 println!("Allocating a Vec...");
195 let mut vector: Vec<u32> = vec![1, 2, 3, 4];
196 assert_eq!(vector[0], 1);
197 assert_eq!(vector[1], 2);
198 assert_eq!(vector[2], 3);
199 assert_eq!(vector[3], 4);
200 vector[2] = 42;
201 assert_eq!(vector[2], 42);
202 println!("Vec seems to work.");
203}
204
Andrew Walbran6261cf42022-04-12 13:26:52 +0000205extern "C" {
206 static dtb_begin: u8;
207 static dtb_end: u8;
208 static text_begin: u8;
209 static text_end: u8;
210 static rodata_begin: u8;
211 static rodata_end: u8;
212 static data_begin: u8;
213 static data_end: u8;
214 static data_lma: u8;
215 static bss_begin: u8;
216 static bss_end: u8;
217 static boot_stack_begin: u8;
218 static boot_stack_end: u8;
Andrew Walbraneef98202022-04-27 16:23:06 +0000219}