/** * \file * \brief ARMv8 kernel page-table structures. */ /* * Copyright (c) 2015, ETH Zurich. * All rights reserved. * * This file is distributed under the terms in the attached LICENSE file. * If you do not find this file, copies can be found by writing to: * ETH Zurich D-INFK, Universitaetstr 6, CH-8092 Zurich. Attn: Systems Group. */ #ifndef KERNEL_ARCH_ARMv8_PAGING_H #define KERNEL_ARCH_ARMv8_PAGING_H // XXX: Not sure if these includes are required #include #include #include #include // Resolves to the required number of entries in Ln to map `limit' number of bytes. #define ARMv8_L0_ENTRIES(limit) (VMSAv8_64_L0_INDEX((limit) - 1) + 1) #define ARMv8_L1_ENTRIES(limit) (VMSAv8_64_L1_INDEX((limit) - 1) + 1) #define ARMv8_L2_ENTRIES(limit) (VMSAv8_64_L2_INDEX((limit) - 1) + 1) #define ARMv8_L3_ENTRIES(limit) (VMSAv8_64_L3_INDEX((limit) - 1) + 1) /** * A translation table entry for VMSAv8-64 stage 1. */ union armv8_ttable_entry { uint64_t raw; struct { uint64_t valid :1; uint64_t mb1 :1; // 1 -> table, 0 -> block uint64_t ignored1 :10; // lower block attrs, ignored for table uint64_t base :36; // base address of next level table uint64_t reserved1 :4; uint64_t ignored2 :7; uint64_t pxntable :1; // only stage 1, executable from EL1 uint64_t uxntable :1; // only stage 1, executable from EL0 uint64_t aptable :2; // only stage 1, access from EL0 uint64_t nstable :1; // only stage 1, access from secure state } d; struct { uint64_t valid :1; uint64_t mb0 :1; // 1 -> table, 0 -> block uint64_t attrindex :3; // mem attr index field, D4-1798 uint64_t ns :1; // non-secure bit uint64_t ap :2; // access permissions bits uint64_t sh :2; // shareability field uint64_t af :1; // accessed flag uint64_t ng :1; // not global bit uint64_t reserved1 :18; uint64_t base :18; uint64_t reserved2 :4; uint64_t contiguous :1; // hint that entry is part of set // of contiguous entries, D4-1811 uint64_t pxn :1; // privileged execute never bit uint64_t uxn :1; // (user) execute never bit uint64_t avail1 :4; // available for SW use uint64_t ignored1 :5; } block_l1; struct { uint64_t valid :1; uint64_t mb0 :1; // 1 -> table, 0 -> block uint64_t attrindex :3; // mem attr index field, D4-1798 uint64_t ns :1; // non-secure bit uint64_t ap :2; // access permissions bits uint64_t sh :2; // shareability field uint64_t af :1; // accessed flag uint64_t ng :1; // not global bit uint64_t reserved1 :9; uint64_t base :27; uint64_t reserved2 :4; uint64_t contiguous :1; // hint that entry is part of set // of contiguous entries, D4-1811 uint64_t pxn :1; // privileged execute never bit uint64_t uxn :1; // (user) execute never bit uint64_t avail1 :4; // available for SW use uint64_t ignored1 :5; } block_l2; struct { uint64_t valid :1; uint64_t mb1 :1; // 0 -> makes entry invalid uint64_t attrindex :3; // mem attr index field, D4-1798 uint64_t ns :1; // non-secure bit uint64_t ap :2; // access permissions bits uint64_t sh :2; // shareability field uint64_t af :1; // accessed flag uint64_t ng :1; // not global bit uint64_t base :36; uint64_t reserved1 :4; uint64_t contiguous :1; // hint that entry is part of set // of contiguous entries, D4-1811 uint64_t pxn :1; // privileged execute never bit uint64_t uxn :1; // (user) execute never bit uint64_t avail1 :4; // available for SW use uint64_t ignored1 :5; } page; }; STATIC_ASSERT_SIZEOF(union armv8_ttable_entry, sizeof(uint64_t)); /** * Setup bootstrap page table with direct and relocated mappings for kernel. * * This function does not enable paging. * * @param initial_base * @param initial_size */ void paging_map_kernel(uintptr_t initial_base, size_t initial_size); lvaddr_t paging_map_device(lpaddr_t base, size_t size); /** * \brief Return whether we have enabled the MMU. Useful for * initialization assertions */ extern bool paging_mmu_enabled(void); /** * Maps a device to a l2 page. * Assumption: corresponding L1 entry already set * */ void paging_map_device_page(uintptr_t l1_table, lvaddr_t device_vbase, lpaddr_t device_pbase, size_t device_bytes); /** * Add kernel mappings to newly constructed page table. * * @param new_table_addr address of newly constructed page table. * @param new_table_bytes size of newly constructed page table. */ void paging_make_good(lpaddr_t base); void paging_map_table_l0(union armv8_ttable_entry *table_addr, lvaddr_t vaddr, lpaddr_t paddr); void paging_map_table_l1(union armv8_ttable_entry *table_addr, lvaddr_t vaddr, lpaddr_t paddr); void paging_map_table_l2(union armv8_ttable_entry *table_addr, lvaddr_t vaddr, lpaddr_t paddr); void paging_map_block_l1(union armv8_ttable_entry *table_addr, lvaddr_t vaddr, lpaddr_t paddr, uintptr_t flags); void paging_map_block_l2(union armv8_ttable_entry *table_addr, lvaddr_t vaddr, lpaddr_t paddr, uintptr_t flags); void paging_map_page_l3(union armv8_ttable_entry *table_addr, lvaddr_t vaddr, lpaddr_t paddr, uintptr_t flags); void paging_set_l3_entry(union armv8_ttable_entry *l3_entry, lpaddr_t pa, uintptr_t flags); //void paging_set_l2_entry(union armv8_ttable_entry *l2entry, lpaddr_t paddr, uintptr_t flags); // //void paging_set_l3_entry(union armv8_ttable_entry *l2entry, lpaddr_t paddr, uintptr_t flags); // void paging_context_switch(lpaddr_t table_addr); void paging_arm_reset(lpaddr_t paddr, size_t bytes); // REVIEW: [2010-05-04 orion] // these were deprecated in churn, enabling now to get system running again. void paging_map_kernel_section(union armv8_ttable_entry *ttbase,lvaddr_t vbase, lpaddr_t pbase); void paging_map_kernel_l1_block(union armv8_ttable_entry *ttbase,lvaddr_t vbase, lpaddr_t pbase); void paging_map_memory(union armv8_ttable_entry *ttbase, lpaddr_t paddr, size_t bytes); static inline bool is_root_pt(enum objtype type) { return type == ObjType_VNode_AARCH64_l0; } static inline size_t get_pte_size(void) { return PTABLE_ENTRY_SIZE; } static inline void do_one_tlb_flush(genvaddr_t vaddr) { // TODO: figure out selective flushing for ARMv8 sysreg_invalidate_tlb(); } static inline void do_selective_tlb_flush(genvaddr_t vaddr, genvaddr_t vend) { // TODO: figure out selective flushing for ARMv8 sysreg_invalidate_tlb(); } static inline void do_full_tlb_flush(void) { sysreg_invalidate_tlb(); } #endif // KERNEL_ARCH_ARMv8_PAGING_H