1 // 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 //! Memory layout.
16
17 pub mod crosvm;
18
19 use crate::console::BASE_ADDRESS;
20 use crate::linker::__stack_chk_guard;
21 use aarch64_paging::paging::VirtualAddress;
22 use core::ops::Range;
23 use core::ptr::addr_of;
24
25 /// First address that can't be translated by a level 1 TTBR0_EL1.
26 pub const MAX_VIRT_ADDR: usize = 1 << 40;
27
28 /// Get an address from a linker-defined symbol.
29 #[macro_export]
30 macro_rules! linker_addr {
31 ($symbol:ident) => {{
32 // SAFETY: We're just getting the address of an extern static symbol provided by the linker,
33 // not dereferencing it.
34 let addr = unsafe { addr_of!($crate::linker::$symbol) as usize };
35 VirtualAddress(addr)
36 }};
37 }
38
39 /// Gets the virtual address range between a pair of linker-defined symbols.
40 #[macro_export]
41 macro_rules! linker_region {
42 ($begin:ident,$end:ident) => {{
43 let start = linker_addr!($begin);
44 let end = linker_addr!($end);
45
46 start..end
47 }};
48 }
49
50 /// Memory reserved for the DTB.
dtb_range() -> Range<VirtualAddress>51 pub fn dtb_range() -> Range<VirtualAddress> {
52 linker_region!(dtb_begin, dtb_end)
53 }
54
55 /// Executable code.
text_range() -> Range<VirtualAddress>56 pub fn text_range() -> Range<VirtualAddress> {
57 linker_region!(text_begin, text_end)
58 }
59
60 /// Read-only data.
rodata_range() -> Range<VirtualAddress>61 pub fn rodata_range() -> Range<VirtualAddress> {
62 linker_region!(rodata_begin, rodata_end)
63 }
64
65 /// Initialised writable data.
data_range() -> Range<VirtualAddress>66 pub fn data_range() -> Range<VirtualAddress> {
67 linker_region!(data_begin, data_end)
68 }
69
70 /// Zero-initialized writable data.
bss_range() -> Range<VirtualAddress>71 pub fn bss_range() -> Range<VirtualAddress> {
72 linker_region!(bss_begin, bss_end)
73 }
74
75 /// Writable data region for the stack.
stack_range(stack_size: usize) -> Range<VirtualAddress>76 pub fn stack_range(stack_size: usize) -> Range<VirtualAddress> {
77 let end = linker_addr!(init_stack_pointer);
78 let start = VirtualAddress(end.0.checked_sub(stack_size).unwrap());
79 assert!(start >= linker_addr!(stack_limit));
80
81 start..end
82 }
83
84 /// All writable sections, excluding the stack.
scratch_range() -> Range<VirtualAddress>85 pub fn scratch_range() -> Range<VirtualAddress> {
86 linker_region!(eh_stack_limit, bss_end)
87 }
88
89 /// UART console range.
console_uart_range() -> Range<VirtualAddress>90 pub fn console_uart_range() -> Range<VirtualAddress> {
91 const CONSOLE_LEN: usize = 1; // `uart::Uart` only uses one u8 register.
92
93 VirtualAddress(BASE_ADDRESS)..VirtualAddress(BASE_ADDRESS + CONSOLE_LEN)
94 }
95
96 /// Read-write data (original).
data_load_address() -> VirtualAddress97 pub fn data_load_address() -> VirtualAddress {
98 linker_addr!(data_lma)
99 }
100
101 /// End of the binary image.
binary_end() -> VirtualAddress102 pub fn binary_end() -> VirtualAddress {
103 linker_addr!(bin_end)
104 }
105
106 /// Value of __stack_chk_guard.
stack_chk_guard() -> u64107 pub fn stack_chk_guard() -> u64 {
108 // SAFETY: __stack_chk_guard shouldn't have any mutable aliases unless the stack overflows. If
109 // it does, then there could be undefined behaviour all over the program, but we want to at
110 // least have a chance at catching it.
111 unsafe { addr_of!(__stack_chk_guard).read_volatile() }
112 }
113