|
|
@ -99,8 +99,7 @@ static mut SINGLE_LVL3_TABLE: PageTable = PageTable {
|
|
|
|
entries: [0; NUM_ENTRIES_4KIB],
|
|
|
|
entries: [0; NUM_ENTRIES_4KIB],
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/// Set up identity mapped page tables for the first 1 gigabyte of address
|
|
|
|
/// Set up identity mapped page tables for the first 1 GiB of address space.
|
|
|
|
/// space.
|
|
|
|
|
|
|
|
pub unsafe fn init() {
|
|
|
|
pub unsafe fn init() {
|
|
|
|
// First, define the three memory types that we will map. Cacheable and
|
|
|
|
// First, define the three memory types that we will map. Cacheable and
|
|
|
|
// non-cacheable normal DRAM, and device.
|
|
|
|
// non-cacheable normal DRAM, and device.
|
|
|
@ -125,14 +124,27 @@ pub unsafe fn init() {
|
|
|
|
pub const NORMAL_NON_CACHEABLE: u64 = 2;
|
|
|
|
pub const NORMAL_NON_CACHEABLE: u64 = 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Set up the first LVL2 entry, pointing to a 4KiB table base address.
|
|
|
|
// The first 2 MiB.
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// Set up the first LVL2 entry, pointing to the base address of a follow-up
|
|
|
|
|
|
|
|
// table containing 4 KiB pages.
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// 0x0000_0000_0000_0000 |
|
|
|
|
|
|
|
|
// |> 2 MiB
|
|
|
|
|
|
|
|
// 0x0000_0000_001F_FFFF |
|
|
|
|
let lvl3_base: u64 = SINGLE_LVL3_TABLE.entries.base_addr() >> 12;
|
|
|
|
let lvl3_base: u64 = SINGLE_LVL3_TABLE.entries.base_addr() >> 12;
|
|
|
|
LVL2_TABLE.entries[0] = (STAGE1_DESCRIPTOR::VALID::True
|
|
|
|
LVL2_TABLE.entries[0] = (STAGE1_DESCRIPTOR::VALID::True
|
|
|
|
+ STAGE1_DESCRIPTOR::TYPE::Table
|
|
|
|
+ STAGE1_DESCRIPTOR::TYPE::Table
|
|
|
|
+ STAGE1_DESCRIPTOR::NEXT_LVL_TABLE_ADDR_4KiB.val(lvl3_base))
|
|
|
|
+ STAGE1_DESCRIPTOR::NEXT_LVL_TABLE_ADDR_4KiB.val(lvl3_base))
|
|
|
|
.value;
|
|
|
|
.value;
|
|
|
|
|
|
|
|
|
|
|
|
// The second 2 MiB block.
|
|
|
|
// The second 2 MiB as block entry.
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// Mapped as non-cacheable.
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// 0x0000_0000_0020_0000 |
|
|
|
|
|
|
|
|
// |> 2 MiB
|
|
|
|
|
|
|
|
// 0x0000_0000_003F_FFFF |
|
|
|
|
LVL2_TABLE.entries[1] = (STAGE1_DESCRIPTOR::VALID::True
|
|
|
|
LVL2_TABLE.entries[1] = (STAGE1_DESCRIPTOR::VALID::True
|
|
|
|
+ STAGE1_DESCRIPTOR::TYPE::Block
|
|
|
|
+ STAGE1_DESCRIPTOR::TYPE::Block
|
|
|
|
+ STAGE1_DESCRIPTOR::AttrIndx.val(mair::NORMAL_NON_CACHEABLE)
|
|
|
|
+ STAGE1_DESCRIPTOR::AttrIndx.val(mair::NORMAL_NON_CACHEABLE)
|
|
|
@ -148,9 +160,22 @@ pub unsafe fn init() {
|
|
|
|
+ STAGE1_DESCRIPTOR::XN::True)
|
|
|
|
+ STAGE1_DESCRIPTOR::XN::True)
|
|
|
|
.value;
|
|
|
|
.value;
|
|
|
|
|
|
|
|
|
|
|
|
// Fill the rest of the LVL2 (2MiB) entries as block
|
|
|
|
// Fill the rest of the LVL2 (2 MiB) entries as block descriptors.
|
|
|
|
// descriptors. Differentiate between normal and device mem.
|
|
|
|
//
|
|
|
|
let mmio_base: u64 = (super::MMIO_BASE >> 21).into();
|
|
|
|
// Differentiate between
|
|
|
|
|
|
|
|
// - cacheable DRAM
|
|
|
|
|
|
|
|
// - device memory
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// Ranges are stored in memory.rs.
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// 0x0000_0000_0040_0000 |
|
|
|
|
|
|
|
|
// |> 1004 MiB cacheable DRAM
|
|
|
|
|
|
|
|
// 0x0000_0000_3EFF_FFFF |
|
|
|
|
|
|
|
|
// 0x0000_0000_3F00_0000 |
|
|
|
|
|
|
|
|
// |> 16 MiB device (MMIO)
|
|
|
|
|
|
|
|
// 0x0000_0000_4000_0000 |
|
|
|
|
|
|
|
|
let mmio_first_block_index: u64 = (super::MMIO_BASE >> 21).into();
|
|
|
|
|
|
|
|
|
|
|
|
let common = STAGE1_DESCRIPTOR::VALID::True
|
|
|
|
let common = STAGE1_DESCRIPTOR::VALID::True
|
|
|
|
+ STAGE1_DESCRIPTOR::TYPE::Block
|
|
|
|
+ STAGE1_DESCRIPTOR::TYPE::Block
|
|
|
|
+ STAGE1_DESCRIPTOR::AP::RW_EL1
|
|
|
|
+ STAGE1_DESCRIPTOR::AP::RW_EL1
|
|
|
@ -162,7 +187,7 @@ pub unsafe fn init() {
|
|
|
|
for (i, entry) in LVL2_TABLE.entries.iter_mut().enumerate().skip(2) {
|
|
|
|
for (i, entry) in LVL2_TABLE.entries.iter_mut().enumerate().skip(2) {
|
|
|
|
let j: u64 = i as u64;
|
|
|
|
let j: u64 = i as u64;
|
|
|
|
|
|
|
|
|
|
|
|
let mem_attr = if j >= mmio_base {
|
|
|
|
let mem_attr = if j >= mmio_first_block_index {
|
|
|
|
STAGE1_DESCRIPTOR::SH::OuterShareable + STAGE1_DESCRIPTOR::AttrIndx.val(mair::DEVICE)
|
|
|
|
STAGE1_DESCRIPTOR::SH::OuterShareable + STAGE1_DESCRIPTOR::AttrIndx.val(mair::DEVICE)
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
STAGE1_DESCRIPTOR::SH::InnerShareable + STAGE1_DESCRIPTOR::AttrIndx.val(mair::NORMAL)
|
|
|
|
STAGE1_DESCRIPTOR::SH::InnerShareable + STAGE1_DESCRIPTOR::AttrIndx.val(mair::NORMAL)
|
|
|
@ -202,10 +227,10 @@ pub unsafe fn init() {
|
|
|
|
for (i, entry) in SINGLE_LVL3_TABLE.entries.iter_mut().enumerate() {
|
|
|
|
for (i, entry) in SINGLE_LVL3_TABLE.entries.iter_mut().enumerate() {
|
|
|
|
let j: u64 = i as u64;
|
|
|
|
let j: u64 = i as u64;
|
|
|
|
|
|
|
|
|
|
|
|
let mem_attr = if j < ro_first_page_index || j > ro_last_page_index {
|
|
|
|
let mem_attr = if (ro_first_page_index..=ro_last_page_index).contains(&j) {
|
|
|
|
STAGE1_DESCRIPTOR::AP::RW_EL1 + STAGE1_DESCRIPTOR::XN::True
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
STAGE1_DESCRIPTOR::AP::RO_EL1 + STAGE1_DESCRIPTOR::XN::False
|
|
|
|
STAGE1_DESCRIPTOR::AP::RO_EL1 + STAGE1_DESCRIPTOR::XN::False
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
STAGE1_DESCRIPTOR::AP::RW_EL1 + STAGE1_DESCRIPTOR::XN::True
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
*entry = (common + mem_attr + STAGE1_DESCRIPTOR::NEXT_LVL_TABLE_ADDR_4KiB.val(j)).value;
|
|
|
|
*entry = (common + mem_attr + STAGE1_DESCRIPTOR::NEXT_LVL_TABLE_ADDR_4KiB.val(j)).value;
|
|
|
|