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 #![allow(unused_unsafe)]
18
19 pub mod crosvm;
20
21 use crate::linker::__stack_chk_guard;
22 use crate::memory::{max_stack_size, page_4kb_of, PAGE_SIZE};
23 use aarch64_paging::paging::VirtualAddress;
24 use core::ops::Range;
25 use core::ptr::addr_of;
26 use static_assertions::const_assert_eq;
27
28 /// First address that can't be translated by a level 1 TTBR0_EL1.
29 pub const MAX_VIRT_ADDR: usize = 1 << 40;
30
31 /// Base memory-mapped addresses of the UART devices.
32 ///
33 /// See SERIAL_ADDR in https://crosvm.dev/book/appendix/memory_layout.html#common-layout.
34 pub const UART_ADDRESSES: [usize; 4] = [0x3f8, 0x2f8, 0x3e8, 0x2e8];
35
36 /// Address of the single page containing all the UART devices.
37 pub const UART_PAGE_ADDR: usize = 0;
38 const_assert_eq!(UART_PAGE_ADDR, page_4kb_of(UART_ADDRESSES[0]));
39 const_assert_eq!(UART_PAGE_ADDR, page_4kb_of(UART_ADDRESSES[1]));
40 const_assert_eq!(UART_PAGE_ADDR, page_4kb_of(UART_ADDRESSES[2]));
41 const_assert_eq!(UART_PAGE_ADDR, page_4kb_of(UART_ADDRESSES[3]));
42
43 /// Get an address from a linker-defined symbol.
44 #[macro_export]
45 macro_rules! linker_addr {
46 ($symbol:ident) => {{
47 // SAFETY: We're just getting the address of an extern static symbol provided by the linker,
48 // not dereferencing it.
49 let addr = unsafe { addr_of!($crate::linker::$symbol) as usize };
50 VirtualAddress(addr)
51 }};
52 }
53
54 /// Gets the virtual address range between a pair of linker-defined symbols.
55 #[macro_export]
56 macro_rules! linker_region {
57 ($begin:ident,$end:ident) => {{
58 let start = linker_addr!($begin);
59 let end = linker_addr!($end);
60
61 start..end
62 }};
63 }
64
65 /// Executable code.
text_range() -> Range<VirtualAddress>66 pub fn text_range() -> Range<VirtualAddress> {
67 linker_region!(text_begin, text_end)
68 }
69
70 /// Read-only data.
rodata_range() -> Range<VirtualAddress>71 pub fn rodata_range() -> Range<VirtualAddress> {
72 linker_region!(rodata_begin, rodata_end)
73 }
74
75 /// Region which may contain a footer appended to the binary at load time.
image_footer_range() -> Range<VirtualAddress>76 pub fn image_footer_range() -> Range<VirtualAddress> {
77 linker_region!(image_footer_begin, image_footer_end)
78 }
79
80 /// Initialised writable data.
data_range() -> Range<VirtualAddress>81 pub fn data_range() -> Range<VirtualAddress> {
82 linker_region!(data_begin, data_end)
83 }
84
85 /// Zero-initialized writable data.
bss_range() -> Range<VirtualAddress>86 pub fn bss_range() -> Range<VirtualAddress> {
87 linker_region!(bss_begin, bss_end)
88 }
89
90 /// Writable data region for .data and .bss.
data_bss_range() -> Range<VirtualAddress>91 pub fn data_bss_range() -> Range<VirtualAddress> {
92 linker_region!(data_begin, bss_end)
93 }
94
95 /// Writable data region for the stack.
stack_range() -> Range<VirtualAddress>96 pub fn stack_range() -> Range<VirtualAddress> {
97 let end = linker_addr!(init_stack_pointer);
98 let start = if let Some(stack_size) = max_stack_size() {
99 assert_eq!(stack_size % PAGE_SIZE, 0);
100 let start = VirtualAddress(end.0.checked_sub(stack_size).unwrap());
101 assert!(start >= linker_addr!(stack_limit));
102 start
103 } else {
104 linker_addr!(stack_limit)
105 };
106
107 start..end
108 }
109
110 /// Writable data region for the exception handler stack.
eh_stack_range() -> Range<VirtualAddress>111 pub fn eh_stack_range() -> Range<VirtualAddress> {
112 linker_region!(eh_stack_limit, init_eh_stack_pointer)
113 }
114
115 /// Range of the page at UART_PAGE_ADDR of PAGE_SIZE.
console_uart_page() -> Range<VirtualAddress>116 pub fn console_uart_page() -> Range<VirtualAddress> {
117 VirtualAddress(UART_PAGE_ADDR)..VirtualAddress(UART_PAGE_ADDR + PAGE_SIZE)
118 }
119
120 /// Read-write data (original).
data_load_address() -> VirtualAddress121 pub fn data_load_address() -> VirtualAddress {
122 linker_addr!(data_lma)
123 }
124
125 /// End of the binary image.
binary_end() -> VirtualAddress126 pub fn binary_end() -> VirtualAddress {
127 linker_addr!(bin_end)
128 }
129
130 /// Value of __stack_chk_guard.
stack_chk_guard() -> u64131 pub fn stack_chk_guard() -> u64 {
132 // SAFETY: __stack_chk_guard shouldn't have any mutable aliases unless the stack overflows. If
133 // it does, then there could be undefined behaviour all over the program, but we want to at
134 // least have a chance at catching it.
135 unsafe { addr_of!(__stack_chk_guard).read_volatile() }
136 }
137