57 lines
1.4 KiB
C
57 lines
1.4 KiB
C
#include <zinnia/pmap.h>
|
|
#include <zinnia/types.h>
|
|
|
|
enum : pte_t {
|
|
ARCH_FLAG_PRESENT = 1 << 0,
|
|
ARCH_FLAG_READ_WRITE = 1 << 1,
|
|
ARCH_FLAG_USER_MODE = 1 << 2,
|
|
ARCH_FLAG_WRITE_THROUGH = 1 << 3,
|
|
ARCH_FLAG_CACHE_DISABLE = 1 << 4,
|
|
ARCH_FLAG_ACCESSED = 1 << 5,
|
|
ARCH_FLAG_DIRTY = 1 << 6,
|
|
ARCH_FLAG_SIZE = 1 << 7,
|
|
ARCH_FLAG_GLOBAL = 1 << 8,
|
|
ARCH_FLAG_AVAILABLE = 1 << 9,
|
|
ARCH_FLAG_ATTRIBUTE_TABLE = 1 << 10,
|
|
ARCH_FLAG_EXECUTE_DISABLE = 1LU << 63,
|
|
|
|
ARCH_PTE_ADDR_MASK = 0x000F'FFFF'FFFF'F000,
|
|
};
|
|
|
|
void pte_clear(pte_t* pte) {
|
|
*pte = 0;
|
|
}
|
|
|
|
pte_t pte_build(phys_t addr, enum pte_flags flags, enum cache_mode cache) {
|
|
pte_t result = ((pte_t)addr & ARCH_PTE_ADDR_MASK) | ARCH_FLAG_PRESENT;
|
|
|
|
if (flags & PTE_USER)
|
|
result |= ARCH_FLAG_USER_MODE;
|
|
|
|
if (flags & PTE_DIR)
|
|
result |= ARCH_FLAG_READ_WRITE;
|
|
else {
|
|
if (flags & PTE_WRITE)
|
|
result |= ARCH_FLAG_READ_WRITE;
|
|
if (!(flags & PTE_EXEC))
|
|
result |= ARCH_FLAG_EXECUTE_DISABLE;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
bool pte_is_present(pte_t* pte) {
|
|
return *pte & ARCH_FLAG_PRESENT;
|
|
}
|
|
|
|
bool pte_is_dir(pte_t* pte) {
|
|
return *pte & ARCH_FLAG_SIZE;
|
|
}
|
|
|
|
phys_t pte_address(pte_t* pte) {
|
|
return (phys_t)(*pte & ARCH_PTE_ADDR_MASK);
|
|
}
|
|
|
|
void pmap_set(struct pmap* pt) {
|
|
asm volatile("mov cr3, %0" ::"r"(pt->root) : "memory");
|
|
}
|