Barrelfish
|
ARM kernel page-table structures. More...
Functions | |
void | paging_init (lpaddr_t ram_base, size_t ram_size, struct arm_core_data *boot_core_data) |
void | enable_mmu (lpaddr_t ttbr0, lpaddr_t ttbr1) |
void | paging_map_vectors (void) |
lvaddr_t | paging_map_device (lpaddr_t base, size_t size) |
Map a device into the kernel's address space. More... | |
bool | paging_mmu_enabled (void) |
Return whether we have enabled the MMU. Useful for initialization assertions. | |
void | paging_map_user_pages_l1 (lvaddr_t table_addr, lvaddr_t vaddr, lpaddr_t paddr) |
Install a page table pointer in a level 1 page table located at 'table_base' to map addresses starting at virtual address 'va'. The level 2 page table to be used is assumed to be located at physical address 'pa'. | |
void | paging_set_l2_entry (uintptr_t *l2entry, lpaddr_t paddr, uintptr_t flags) |
void | paging_context_switch (lpaddr_t table_addr) |
ARM kernel page-table structures.
void enable_mmu | ( | lpaddr_t | ttbr0, |
lpaddr_t | ttbr1 | ||
) |
TTBCR: Translation Table Base Control register. TTBCR.N is bits[2:0] In a TLB miss TTBCR.N determines whether TTBR0 or TTBR1 is used as the base address for the translation table walk in memory: N == 0 -> always use TTBR0 N > 0 -> if VA[31:32-N] > 0 use TTBR1 else use TTBR0
TTBR0 is typically used for processes-specific addresses TTBR1 is typically used for OS addresses that do not change on context switch
set TTBCR.N = 1 to use TTBR1 for VAs >= MEMORY_OFFSET (=2GB)
void paging_context_switch | ( | lpaddr_t | ttbr | ) |
/brief Perform a context switch. Reload TTBR0 with the new address, and invalidate the TLBs and caches.
void paging_init | ( | lpaddr_t | ram_base, |
size_t | ram_size, | ||
struct arm_core_data * | boot_core_data | ||
) |
Create kernel page tables.
We use 1MB (ARM_L1_SECTION_BYTES) pages (sections) with a single-level table. This allows 1MB*4k (ARM_L1_MAX_ENTRIES) = 4G per pagetable.
Hardware details can be found in: ARM Architecture Reference Manual, ARMv7-A and ARMv7-R edition B3: Virtual Memory System Architecture (VMSA)
Make sure our page tables are correctly aligned in memory
On many ARMv7-A platforms, physical RAM (phys_memory_start) is the same as the offset of mapped physical memory within virtual address space (phys_memory_start). Some platforms (such as the Zynq) break this rule, and thus we need to be very careful about how we enable the MMU.
Zero the page tables: this has the effect of marking every PTE as invalid.
Now we lay out the kernel's virtual address space.
00000000-7FFFFFFFF: 1-1 mappings (hardware we have not mapped into high kernel space yet, and the init code that is currently executing, in case RAM doesn't start at 80000000). 80000000-BFFFFFFFF: 1-1 mappings (this is 1GB of RAM). C0000000-FEFFFFFFF: On-demand mappings of hardware devices, allocated descending from DEVICE_OFFSET. FF000000-FFEFFFFFF: Unallocated. FFF00000-FFFFFFFFF: L2 table, containing: FFF00000-FFFEFFFF: Unallocated FFFF0000-FFFFFFFF: Exception vectors
lvaddr_t paging_map_device | ( | lpaddr_t | dev_base, |
size_t | dev_size | ||
) |
Map a device into the kernel's address space.
device_base | is the physical address of the device |
device_size | is the number of bytes of physical address space the device occupies. |
void paging_map_vectors | ( | void | ) |
Install a single small page mapping to cover the vectors.
The mapping fields are set exactly as for the kernel's RAM sections - see make_ram_section() for details.
Map the L2 table to hold the high vectors mapping.
void paging_set_l2_entry | ( | uintptr_t * | l2e, |
lpaddr_t | addr, | ||
uintptr_t | flags | ||
) |
/brief Install a level 2 page table entry located at l2e, to map physical address 'pa', with flags 'flags'. 'flags' here is in the form of a prototype 32-bit L2 invalid PTE with address 0.