HelenOS sources
This source file includes following definitions.
- get_pt_level012_flags
- get_pt_level3_flags
- set_pt_level012_flags
- set_pt_level3_flags
- set_pt_present
- get_pt_executable
- get_pt_writable
#ifndef KERN_arm64_PAGE_H_
#define KERN_arm64_PAGE_H_
#include <arch/mm/frame.h>
#include <mm/mm.h>
#include <trace.h>
#ifndef __ASSEMBLER__
#include <typedefs.h>
#endif
#define PAGE_WIDTH FRAME_WIDTH
#define PAGE_SIZE FRAME_SIZE
#ifndef __ASSEMBLER__
extern uintptr_t physmem_base;
#define KA2PA(x) \
(((uintptr_t) (x)) - UINT64_C(0xffffffff00000000) + physmem_base)
#define PA2KA(x) \
(((uintptr_t) (x)) + UINT64_C(0xffffffff00000000) - physmem_base)
#endif
#define PTL_ENTRY_SIZE_SHIFT 3
#define PTL0_ENTRIES_ARCH 512
#define PTL1_ENTRIES_ARCH 512
#define PTL2_ENTRIES_ARCH 512
#define PTL3_ENTRIES_ARCH 512
#define PTL0_FRAMES_ARCH 1
#define PTL1_FRAMES_ARCH 1
#define PTL2_FRAMES_ARCH 1
#define PTL3_FRAMES_ARCH 1
#define PTL0_VA_SHIFT 39
#define PTL1_VA_SHIFT 30
#define PTL2_VA_SHIFT 21
#define PTL3_VA_SHIFT 12
#define PTL0_VA_MASK 0x1ff
#define PTL1_VA_MASK 0x1ff
#define PTL2_VA_MASK 0x1ff
#define PTL3_VA_MASK 0x1ff
#define PTL0_INDEX_ARCH(vaddr) (((vaddr) >> PTL0_VA_SHIFT) & PTL0_VA_MASK)
#define PTL1_INDEX_ARCH(vaddr) (((vaddr) >> PTL1_VA_SHIFT) & PTL1_VA_MASK)
#define PTL2_INDEX_ARCH(vaddr) (((vaddr) >> PTL2_VA_SHIFT) & PTL2_VA_MASK)
#define PTL3_INDEX_ARCH(vaddr) (((vaddr) >> PTL3_VA_SHIFT) & PTL3_VA_MASK)
#define GET_PTL1_ADDRESS_ARCH(ptl0, i) \
((pte_t *) (((uintptr_t) ((pte_t *) (ptl0))[(i)].output_address) << 12))
#define GET_PTL2_ADDRESS_ARCH(ptl1, i) \
((pte_t *) (((uintptr_t) ((pte_t *) (ptl1))[(i)].output_address) << 12))
#define GET_PTL3_ADDRESS_ARCH(ptl2, i) \
((pte_t *) (((uintptr_t) ((pte_t *) (ptl2))[(i)].output_address) << 12))
#define GET_FRAME_ADDRESS_ARCH(ptl3, i) \
(((uintptr_t) ((pte_t *) (ptl3))[(i)].output_address) << 12)
#define SET_PTL0_ADDRESS_ARCH(ptl0)
#define SET_PTL1_ADDRESS_ARCH(ptl0, i, a) \
(((pte_t *) (ptl0))[(i)].output_address = (a) >> 12)
#define SET_PTL2_ADDRESS_ARCH(ptl1, i, a) \
(((pte_t *) (ptl1))[(i)].output_address = (a) >> 12)
#define SET_PTL3_ADDRESS_ARCH(ptl2, i, a) \
(((pte_t *) (ptl2))[(i)].output_address = (a) >> 12)
#define SET_FRAME_ADDRESS_ARCH(ptl3, i, a) \
(((pte_t *) (ptl3))[(i)].output_address = (a) >> 12)
#define GET_PTL1_FLAGS_ARCH(ptl0, i) \
get_pt_level012_flags((pte_t *) (ptl0), (size_t) (i))
#define GET_PTL2_FLAGS_ARCH(ptl1, i) \
get_pt_level012_flags((pte_t *) (ptl1), (size_t) (i))
#define GET_PTL3_FLAGS_ARCH(ptl2, i) \
get_pt_level012_flags((pte_t *) (ptl2), (size_t) (i))
#define GET_FRAME_FLAGS_ARCH(ptl3, i) \
get_pt_level3_flags((pte_t *) (ptl3), (size_t) (i))
#define SET_PTL1_FLAGS_ARCH(ptl0, i, x) \
set_pt_level012_flags((pte_t *) (ptl0), (size_t) (i), (x))
#define SET_PTL2_FLAGS_ARCH(ptl1, i, x) \
set_pt_level012_flags((pte_t *) (ptl1), (size_t) (i), (x))
#define SET_PTL3_FLAGS_ARCH(ptl2, i, x) \
set_pt_level012_flags((pte_t *) (ptl2), (size_t) (i), (x))
#define SET_FRAME_FLAGS_ARCH(ptl3, i, x) \
set_pt_level3_flags((pte_t *) (ptl3), (size_t) (i), (x))
#define SET_PTL1_PRESENT_ARCH(ptl0, i) \
set_pt_present((pte_t *) (ptl0), (size_t) (i))
#define SET_PTL2_PRESENT_ARCH(ptl1, i) \
set_pt_present((pte_t *) (ptl1), (size_t) (i))
#define SET_PTL3_PRESENT_ARCH(ptl2, i) \
set_pt_present((pte_t *) (ptl2), (size_t) (i))
#define SET_FRAME_PRESENT_ARCH(ptl3, i) \
set_pt_present((pte_t *) (ptl3), (size_t) (i))
#define PTE_VALID_ARCH(pte) \
(((pte_t *) (pte))->valid != 0)
#define PTE_PRESENT_ARCH(pte) \
(((pte_t *) (pte))->valid != 0)
#define PTE_GET_FRAME_ARCH(pte) \
(((uintptr_t) ((pte_t *) (pte))->output_address) << FRAME_WIDTH)
#define PTE_WRITABLE_ARCH(pte) \
get_pt_writable((pte_t *) (pte))
#define PTE_EXECUTABLE_ARCH(pte) \
get_pt_executable((pte_t *) (pte))
#define PTE_AP_USER_NO_KERNEL_FULL 0
#define PTE_AP_USER_FULL_KERNEL_FULL 1
#define PTE_AP_USER_NO_KERNEL_LIMITED 2
#define PTE_AP_USER_LIMITED_KERNEL_LIMITED 3
#define MAIR_EL1_NORMAL_MEMORY_ATTR 0xff
#define MAIR_EL1_NORMAL_MEMORY_INDEX 1
#define MAIR_EL1_DEVICE_MEMORY_ATTR 0x04
#define MAIR_EL1_DEVICE_MEMORY_INDEX 2
#define MAIR_EL1_ATTR_SHIFT 8
#define PTE_L012_TYPE_BLOCK 0
#define PTE_L012_TYPE_TABLE 1
#define PTE_L3_TYPE_PAGE 1
#define PTE_L0123_TYPE_HELENOS 1
#define PTE_NEXT_LEVEL_ADDRESS_SHIFT 12
#define PTE_OUTPUT_ADDRESS_SHIFT 12
#define PTE_ACCESS_SHIFT 10
#define PTE_ATTR_INDEX_SHIFT 2
#define PTE_TYPE_SHIFT 1
#define PTE_PRESENT_SHIFT 0
#define PTE_PRESENT_FLAG (1 << PTE_PRESENT_SHIFT)
#ifndef __ASSEMBLER__
#include <arch/interrupt.h>
typedef struct {
unsigned valid : 1;
unsigned type : 1;
unsigned attr_index : 3;
unsigned non_secure : 1;
unsigned access_permission : 2;
unsigned shareability : 2;
unsigned access : 1;
unsigned not_global : 1;
uint64_t output_address : 36;
unsigned : 4;
unsigned contiguous : 1;
unsigned privileged_execute_never : 1;
unsigned unprivileged_execute_never : 1;
unsigned : 4;
unsigned privileged_execute_never_table : 1;
unsigned unprivileged_execute_never_table : 1;
unsigned access_permission_table : 2;
unsigned non_secure_table : 1;
} __attribute__((packed)) pte_t;
_NO_TRACE static inline unsigned int get_pt_level012_flags(pte_t *pt, size_t i)
{
pte_t *p = &pt[i];
return (1 << PAGE_CACHEABLE_SHIFT) |
(!p->valid << PAGE_PRESENT_SHIFT) | (1 << PAGE_USER_SHIFT) |
(1 << PAGE_READ_SHIFT) | (1 << PAGE_WRITE_SHIFT) |
(1 << PAGE_EXEC_SHIFT);
}
_NO_TRACE static inline unsigned int get_pt_level3_flags(pte_t *pt, size_t i)
{
pte_t *p = &pt[i];
int cacheable = (p->attr_index == MAIR_EL1_NORMAL_MEMORY_INDEX);
int user = (p->access_permission == PTE_AP_USER_FULL_KERNEL_FULL ||
p->access_permission == PTE_AP_USER_LIMITED_KERNEL_LIMITED);
int write = (p->access_permission == PTE_AP_USER_FULL_KERNEL_FULL ||
p->access_permission == PTE_AP_USER_NO_KERNEL_FULL);
int exec = ((user && !p->unprivileged_execute_never) ||
(!user && !p->privileged_execute_never));
return (cacheable << PAGE_CACHEABLE_SHIFT) |
(!p->valid << PAGE_PRESENT_SHIFT) | (user << PAGE_USER_SHIFT) |
(1 << PAGE_READ_SHIFT) | (write << PAGE_WRITE_SHIFT) |
(exec << PAGE_EXEC_SHIFT) | (!p->not_global << PAGE_GLOBAL_SHIFT);
}
_NO_TRACE static inline void set_pt_level012_flags(pte_t *pt, size_t i,
int flags)
{
pte_t *p = &pt[i];
p->valid = (flags & PAGE_PRESENT) != 0;
p->type = PTE_L012_TYPE_TABLE;
}
_NO_TRACE static inline void set_pt_level3_flags(pte_t *pt, size_t i,
int flags)
{
pte_t *p = &pt[i];
if (flags & PAGE_CACHEABLE)
p->attr_index = MAIR_EL1_NORMAL_MEMORY_INDEX;
else
p->attr_index = MAIR_EL1_DEVICE_MEMORY_INDEX;
p->valid = (flags & PAGE_PRESENT) != 0;
p->type = PTE_L3_TYPE_PAGE;
if (flags & PAGE_USER) {
if (flags & PAGE_WRITE)
p->access_permission = PTE_AP_USER_FULL_KERNEL_FULL;
else
p->access_permission =
PTE_AP_USER_LIMITED_KERNEL_LIMITED;
} else {
if (flags & PAGE_WRITE)
p->access_permission = PTE_AP_USER_NO_KERNEL_FULL;
else
p->access_permission = PTE_AP_USER_NO_KERNEL_LIMITED;
}
p->access = 1;
p->unprivileged_execute_never = p->privileged_execute_never =
(flags & PAGE_EXEC) == 0;
p->not_global = (flags & PAGE_GLOBAL) == 0;
}
_NO_TRACE static inline void set_pt_present(pte_t *pt, size_t i)
{
pte_t *p = &pt[i];
p->valid = 1;
}
_NO_TRACE static inline bool get_pt_executable(pte_t *pte)
{
if (pte->access_permission == PTE_AP_USER_NO_KERNEL_FULL ||
pte->access_permission == PTE_AP_USER_NO_KERNEL_LIMITED)
return pte->privileged_execute_never;
else
return pte->unprivileged_execute_never;
}
_NO_TRACE static inline bool get_pt_writable(pte_t *pte)
{
return pte->access_permission == PTE_AP_USER_FULL_KERNEL_FULL ||
pte->access_permission == PTE_AP_USER_NO_KERNEL_FULL;
}
extern void page_arch_init(void);
#endif
#endif
HelenOS homepage, sources at GitHub