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 //! Low-level allocation and tracking of main memory.
16 
17 use crate::helpers::PVMFW_PAGE_SIZE;
18 use aarch64_paging::paging::VirtualAddress;
19 use aarch64_paging::MapError;
20 use core::ops::Range;
21 use core::result;
22 use log::error;
23 use vmbase::{
24     layout,
25     memory::{PageTable, SIZE_2MB, SIZE_4KB},
26     util::align_up,
27 };
28 
29 /// Returns memory range reserved for the appended payload.
appended_payload_range() -> Range<VirtualAddress>30 pub fn appended_payload_range() -> Range<VirtualAddress> {
31     let start = align_up(layout::binary_end().0, SIZE_4KB).unwrap();
32     // pvmfw is contained in a 2MiB region so the payload can't be larger than the 2MiB alignment.
33     let end = align_up(start, SIZE_2MB).unwrap();
34     VirtualAddress(start)..VirtualAddress(end)
35 }
36 
37 /// Region allocated for the stack.
stack_range() -> Range<VirtualAddress>38 pub fn stack_range() -> Range<VirtualAddress> {
39     const STACK_PAGES: usize = 12;
40 
41     layout::stack_range(STACK_PAGES * PVMFW_PAGE_SIZE)
42 }
43 
init_page_table() -> result::Result<PageTable, MapError>44 pub fn init_page_table() -> result::Result<PageTable, MapError> {
45     let mut page_table = PageTable::default();
46 
47     // Stack and scratch ranges are explicitly zeroed and flushed before jumping to payload,
48     // so dirty state management can be omitted.
49     page_table.map_data(&layout::scratch_range().into())?;
50     page_table.map_data(&stack_range().into())?;
51     page_table.map_code(&layout::text_range().into())?;
52     page_table.map_rodata(&layout::rodata_range().into())?;
53     page_table.map_data_dbm(&appended_payload_range().into())?;
54     if let Err(e) = page_table.map_device(&layout::console_uart_range().into()) {
55         error!("Failed to remap the UART as a dynamic page table entry: {e}");
56         return Err(e);
57     }
58     Ok(page_table)
59 }
60