2021-11-15 19:23:22 +01:00
|
|
|
/* Copyright (C) 2021 fef <owo@fef.moe>. All rights reserved. */
|
2021-11-12 06:13:10 +01:00
|
|
|
|
|
|
|
#pragma once
|
|
|
|
#ifndef _ARCH_PAGE_H_
|
|
|
|
#error "This file is not meant to be included directly, use <arch/page.h>"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/** @brief Binary logarithm of `HUGEPAGE_SIZE`. */
|
|
|
|
#define HUGEPAGE_SHIFT 21
|
|
|
|
|
|
|
|
#include <arch/vmparam.h>
|
|
|
|
|
|
|
|
#define X86_PT_SHIFT PAGE_SHIFT
|
|
|
|
#define X86_PD_SHIFT (X86_PT_SHIFT + 9)
|
|
|
|
#define X86_PDP_SHIFT (X86_PD_SHIFT + 9)
|
|
|
|
#define X86_PML4_SHIFT (X86_PDP_SHIFT + 9)
|
|
|
|
|
|
|
|
#ifndef _ASM_SOURCE
|
|
|
|
|
|
|
|
#include <gay/cdefs.h>
|
|
|
|
#include <gay/types.h>
|
|
|
|
|
2021-11-15 19:23:22 +01:00
|
|
|
#define __HAVE_NOEXEC
|
|
|
|
|
2021-11-12 06:13:10 +01:00
|
|
|
/**
|
|
|
|
* @brief A single 64-bit Page Table Entry.
|
|
|
|
* The layout matches that of the Intel SDM, vol 3, sect 4.3, fig 4-4.
|
|
|
|
* Bits 9 and 10 (`slab` and `atomic`) are marked as AVL in the manual and
|
|
|
|
* ignored by the MMU. We only use them for `get_pflags()`/`set_pflags()`.
|
|
|
|
*/
|
|
|
|
struct x86_page_flags {
|
|
|
|
/* 0 */bool present:1; /**< Page Fault on access if 0 */
|
|
|
|
/* 1 */bool rw:1; /**< Page Fault on write if 0 */
|
|
|
|
/* 2 */bool user:1; /**< Page Fault on user mode access if 0 */
|
|
|
|
/* 3 */bool write_through:1; /**< Enable write-through caching */
|
|
|
|
/* 4 */bool cache_disabled:1; /**< Disable caching in TLB */
|
|
|
|
/* 5 */bool accessed:1; /**< 1 if page has been accessed */
|
|
|
|
/* 6 */bool dirty:1; /**< 1 if page has been written to */
|
|
|
|
/* 7 */bool huge:1; /**< only valid for PDPTEs and PDEs */
|
|
|
|
/* 8 */bool global:1; /**< Don't update the TLB on table swap if 1 */
|
|
|
|
/* 9 */bool slab:1; /**< Used by the slab allocator */
|
|
|
|
/* 10 */bool atomic:1; /**< Allocated atomically */
|
|
|
|
/* 11 */unsigned _unused:1;
|
|
|
|
/* 12 */uintptr_t shifted_address:51;
|
|
|
|
/* 63 */bool noexec:1;
|
|
|
|
} __packed;
|
|
|
|
|
|
|
|
#define __PFLAG_PRESENT (1 << 0)
|
|
|
|
#define __PFLAG_RW (1 << 1)
|
|
|
|
#define __PFLAG_USER (1 << 2)
|
|
|
|
#define __PFLAG_WRITE_THROUGH (1 << 3)
|
|
|
|
#define __PFLAG_NOCACHE (1 << 4)
|
|
|
|
#define __PFLAG_ACCESSED (1 << 5)
|
|
|
|
#define __PFLAG_DIRTY (1 << 6)
|
|
|
|
#define __PFLAG_HUGE (1 << 7)
|
|
|
|
#define __PFLAG_GLOBAL (1 << 8)
|
|
|
|
#define __PFLAG_SLAB (1 << 9)
|
|
|
|
#define __PFLAG_ATOMIC (1 << 10)
|
|
|
|
#define __PFLAG_NOEXEC (1 << 63)
|
|
|
|
|
|
|
|
/*
|
|
|
|
* these types are deliberately not merged into one so that the
|
|
|
|
* compiler can catch accidental assignments to the wrong type
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define __pmap_entry_union union { \
|
|
|
|
struct x86_page_flags flags; \
|
|
|
|
uintptr_t val; \
|
|
|
|
}
|
|
|
|
typedef __pmap_entry_union x86_pte_t;
|
|
|
|
typedef __pmap_entry_union x86_pde_t;
|
|
|
|
typedef __pmap_entry_union x86_pdpe_t;
|
|
|
|
typedef __pmap_entry_union x86_pml4e_t;
|
|
|
|
|
|
|
|
typedef struct { x86_pte_t entries[512]; } __aligned(PAGE_SIZE) x86_pt_t;
|
|
|
|
typedef struct { x86_pde_t entries[512]; } __aligned(PAGE_SIZE) x86_pd_t;
|
|
|
|
typedef struct { x86_pdpe_t entries[512]; } __aligned(PAGE_SIZE) x86_pdp_t;
|
|
|
|
typedef struct { x86_pml4e_t entries[512]; } __aligned(PAGE_SIZE) x86_pml4_t;
|
|
|
|
|
|
|
|
#define X86_PMAP_MASK 0x7ffffffffffff000
|
|
|
|
|
|
|
|
/* you aren't expected to understand any of these, they're just nasty offset calculations */
|
|
|
|
|
|
|
|
/** @brief Get the linear 48-bit address */
|
|
|
|
#define __V48ADDR(ptr) ((uintptr_t)(ptr) & 0x0000ffffffffffff)
|
|
|
|
|
|
|
|
#define X86_PT_INDEX(ptr) (( __V48ADDR(ptr) >> X86_PT_SHIFT ) % 512)
|
|
|
|
#define X86_PD_INDEX(ptr) (( __V48ADDR(ptr) >> X86_PD_SHIFT ) % 512)
|
|
|
|
#define X86_PDP_INDEX(ptr) (( __V48ADDR(ptr) >> X86_PDP_SHIFT ) % 512)
|
|
|
|
#define X86_PML4_INDEX(ptr) ( __V48ADDR(ptr) >> X86_PML4_SHIFT )
|
|
|
|
|
|
|
|
#define __PT_BASE X86_PMAP_OFFSET
|
|
|
|
#define __PD_BASE (__PT_BASE + (__V48ADDR(X86_PMAP_OFFSET) >> X86_PT_SHIFT))
|
|
|
|
#define __PDP_BASE (__PD_BASE + (__V48ADDR(X86_PMAP_OFFSET) >> X86_PD_SHIFT))
|
|
|
|
#define __PML4_BASE (__PDP_BASE + (__V48ADDR(X86_PMAP_OFFSET) >> X86_PDP_SHIFT))
|
|
|
|
|
|
|
|
#define X86_PTE(ptr) ((x86_pte_t *)( __PT_BASE + (__V48ADDR(ptr) >> X86_PT_SHIFT) ))
|
|
|
|
#define X86_PDE(ptr) ((x86_pde_t *)( __PD_BASE + (__V48ADDR(ptr) >> X86_PD_SHIFT) ))
|
|
|
|
#define X86_PDPE(ptr) ((x86_pdpe_t *)( __PDP_BASE + (__V48ADDR(ptr) >> X86_PDP_SHIFT) ))
|
|
|
|
#define X86_PML4E(ptr) ((x86_pml4e_t *)( __PML4_BASE + (__V48ADDR(ptr) >> X86_PML4_SHIFT) ))
|
|
|
|
|
|
|
|
#endif /* not _ASM_SOURCE */
|