summaryrefslogtreecommitdiff
path: root/include/vm.h
diff options
context:
space:
mode:
authorFreya Murphy <freya@freyacat.org>2025-03-27 11:39:12 -0400
committerFreya Murphy <freya@freyacat.org>2025-03-27 11:39:12 -0400
commit0ff301cda68669c59351e5854ce98f2cf460543f (patch)
treecfe8f976261962420ada64b821559b9da0a56841 /include/vm.h
parentadd compile_flags.txt for clangd lsp (diff)
downloadcomus-0ff301cda68669c59351e5854ce98f2cf460543f.tar.gz
comus-0ff301cda68669c59351e5854ce98f2cf460543f.tar.bz2
comus-0ff301cda68669c59351e5854ce98f2cf460543f.zip
pull upstream changes, add auto formatting
Diffstat (limited to 'include/vm.h')
-rw-r--r--include/vm.h333
1 files changed, 172 insertions, 161 deletions
diff --git a/include/vm.h b/include/vm.h
index d557d5e..6c4441f 100644
--- a/include/vm.h
+++ b/include/vm.h
@@ -64,134 +64,145 @@
*/
// user virtual addresses
-#define USER_TEXT 0x00001000
-#define USER_STACK 0x003fe000
-#define USER_STK_END 0x00400000
+#define USER_TEXT 0x00001000
+#define USER_STACK 0x003fe000
+#define USER_STK_END 0x00400000
// how to find the addresses of the stack pages in the VM hierarchy
// user address space is the first 4MB of virtual memory
-#define USER_PDE 0
+#define USER_PDE 0
// the stack occupies the last two pages of the address space
-#define USER_STK_PTE1 1022
-#define USER_STK_PTE2 1023
+#define USER_STK_PTE1 1022
+#define USER_STK_PTE2 1023
// some important memory addresses
-#define KERN_BASE 0x80000000 // start of "kernel" memory
-#define EXT_BASE 0x00100000 // start of "extended" memory (1MB)
-#define DEV_BASE 0xfe000000 // "device" memory
-#define PHYS_TOP 0x7fffffff // last usable physical address
+#define KERN_BASE 0x80000000 // start of "kernel" memory
+#define EXT_BASE 0x00100000 // start of "extended" memory (1MB)
+#define DEV_BASE 0xfe000000 // "device" memory
+#define PHYS_TOP 0x3fffffff // last usable physical address (1GB - 1)
// where the kernel actually lives
-#define KERN_PLINK 0x00010000
-#define KERN_VLINK (KERN_BASE + KERN_PLINK)
-
-// physical/virtual converters
-#ifndef ASM_SRC
-// uses casting
-#define V2P(a) (((uint_t)(a)) - KERN_BASE)
-#define P2V(a) ((void *)(((uint_t)(a)) + KERN_BASE))
-#else
-// doesn't use casting
-#define V2P(a) ((a) - KERN_BASE)
-#define P2V(a) ((a) + KERN_BASE)
-#endif /* !ASM_SRC */
+#define KERN_PLINK 0x00010000
+#define KERN_VLINK (KERN_BASE + KERN_PLINK)
// number of entries in a page directory or page table
-#define N_PDE 1024
-#define N_PTE 1024
+#define N_PDE 1024
+#define N_PTE 1024
// index field shift counts and masks
-#define PDIX_SHIFT 22
-#define PTIX_SHIFT 12
-#define PIX2I_MASK 0x3ff
+#define PDIX_SHIFT 22
+#define PTIX_SHIFT 12
+#define PIX2I_MASK 0x3ff
-#ifndef ASM_SRC
-// 4KB frame numbers are 20 bits wide
-#define FRAME_4K_SHIFT 12
-#define F2I_4K_MASK 0x000fffff
-#define TO_4KFRAME(n) (((n)&F2I_4K_MASK) << FRAME_4K_SHIFT)
-#define GET_4KFRAME(n) (((n) >> FRAME_4K_SHIFT)&F2I_4K_MASK)
+// physical/virtual converters that don't use casting
+// (usable from anywhere)
+#define V2PNC(a) ((a) - KERN_BASE)
+#define P2VNC(a) ((a) + KERN_BASE)
-// 4MB frame numbers are 10 bits wide
-#define FRAME_4M_SHIFT 22
-#define F2I_4M_MASK 0x000003ff
-#define TO_4MFRAME(n) (((n)&F2I_4M_MASK) << FRAME_4M_SHIFT)
-#define GET_4MFRAME(n) (((n) >> FRAME_4M_SHIFT)&F2I_4M_MASK)
+// page-size address rounding macros
+#define SZ_PG_M1 MOD4K_BITS
+#define SZ_PG_MASK MOD4K_MASK
+#define PGUP(a) (((a) + SZ_PG_M1) & SZ_PG_MASK)
+#define PGDOWN(a) ((a) & SZ_PG_MASK)
-// extract the PMT address or frame address from a table entry
-#define FRAME_MASK MOD4K_MASK
-#define PERM_MASK MOD4K_BITS
-#define PDE_ADDR(p) (((uint32_t)(p))&FRAME_MASK)
-#define PTE_ADDR(p) (((uint32_t)(p))&FRAME_MASK)
-#define PERMS(p) (((uint32_t)(p))&PERM_MASK)
+// page directory entry bit fields
+#define PDE_P 0x00000001 // 1 = present
+#define PDE_RW 0x00000002 // 1 = writable
+#define PDE_US 0x00000004 // 1 = user and system usable
+#define PDE_PWT 0x00000008 // cache: 1 = write-through
+#define PDE_PCD 0x00000010 // cache: 1 = disabled
+#define PDE_A 0x00000020 // accessed
+#define PDE_D 0x00000040 // dirty (4MB pages)
+#define PDE_AVL1 0x00000040 // ignored (4KB pages)
+#define PDE_PS 0x00000080 // 1 = 4MB page size
+#define PDE_G 0x00000100 // global
+#define PDE_AVL2 0x00000e00 // ignored
+#define PDE_PAT 0x00001000 // (4MB pages) use page attribute table
+#define PDE_PTA 0xfffff000 // page table address field (4KB pages)
+#define PDE_FA 0xffc00000 // frame address field (4MB pages)
-// extract the table indices from a 32-bit address
-#define PDIX(v) ((((uint32_t)(v)) >> PDIX_SHIFT) & PIX2I_MASK)
-#define PTIX(v) ((((uint32_t)(v)) >> PTIX_SHIFT) & PIX2I_MASK)
+// page table entry bit fields
+#define PTE_P 0x00000001 // present
+#define PTE_RW 0x00000002 // 1 = writable
+#define PTE_US 0x00000004 // 1 = user and system usable
+#define PTE_PWT 0x00000008 // cache: 1 = write-through
+#define PTE_PCD 0x00000010 // cache: 1 = disabled
+#define PTE_A 0x00000020 // accessed
+#define PTE_D 0x00000040 // dirty
+#define PTE_PAT 0x00000080 // use page attribute table
+#define PTE_G 0x00000100 // global
+#define PTE_AVL2 0x00000e00 // ignored
+#define PTE_FA 0xfffff000 // frame address field
-// page-size address rounding macros
-#define SZ_PG_M1 MOD4K_BITS
-#define SZ_PG_MASK MOD4K_MASK
-#define PGUP(a) (((a)+SZ_PG_M1) & SZ_PG_MASK)
-#define PGDOWN(a) ((a) & SZ_PG_MASK)
-
-// page directory entry fields
-#define PDE_P 0x00000001
-#define PDE_RW 0x00000002
-#define PDE_US 0x00000004
-#define PDE_PWT 0x00000008
-#define PDE_PCD 0x00000010
-#define PDE_A 0x00000020
-#define PDE_AVL1 0x00000040
-#define PDE_PS 0x00000080
-#define PDE_AVL2 0x00000f00
-#define PDE_BA 0xfffff000
+// error code bit assignments for page faults
+#define PFLT_P 0x00000001
+#define PFLT_W 0x00000002
+#define PFLT_US 0x00000004
+#define PFLT_RSVD 0x00000008
+#define PFLT_ID 0x00000010
+#define PFLT_PK 0x00000020
+#define PFLT_SS 0x00000040
+#define PFLT_HLAT 0x00000080
+#define PFLT_SGX 0x00008000
+#define PFLT_UNUSED 0xffff7f00
-// page table entry fields
-#define PTE_P 0x00000001
-#define PTE_RW 0x00000002
-#define PTE_US 0x00000004
-#define PTE_PWT 0x00000008
-#define PTE_PCD 0x00000010
-#define PTE_A 0x00000020
-#define PTE_D 0x00000040
-#define PTE_PAT 0x00000080
-#define PTE_G 0x00000100
-#define PTE_AVL2 0x00000e00
-#define PTE_FA 0xfffff000
+#ifndef ASM_SRC
-#define PG_CODE (PTE_USER | PTE_PRESENT)
-#define PG_DATA (PTE_USER | PTE_RW | PTE_PRESENT)
+/*
+** Start of C-only definitions
+*/
-// error code bit assignments for page faults
-#define PFLT_P 0x00000001
-#define PFLT_W 0x00000002
-#define PFLT_US 0x00000004
-#define PFLT_RSVD 0x00000008
-#define PFLT_ID 0x00000010
-#define PFLT_PK 0x00000020
-#define PFLT_SS 0x00000040
-#define PFLT_HLAT 0x00000080
-#define PFLT_SGX 0x00008000
-#define PFLT_UNUSED 0xffff7f00
+// physical/virtual converters that do use casting
+// (not usable from assembly)
+#define V2P(a) (((uint32_t)(a)) - KERN_BASE)
+#define P2V(a) (((uint32_t)(a)) + KERN_BASE)
// create a pde/pte from an integer frame number and permission bits
-#define MKPDE(f,p) ((pde_t)( TO_FRAME((f)) | (p) ))
-#define MKPTE(f,p) ((pte_t)( TO_FRAME((f)) | (p) ))
+#define MKPDE(f, p) ((pde_t)(TO_FRAME((f)) | (p)))
+#define MKPTE(f, p) ((pte_t)(TO_FRAME((f)) | (p)))
// is a PDE/PTE present?
// (P bit is in the same place in both)
-#define IS_PRESENT(entry) (((entry) & PDE_P) != 0 )
+#define IS_PRESENT(entry) (((entry) & PDE_P) != 0)
// is a PDE a 4MB page entry?
-#define IS_LARGE(pde) (((pde) & PDE_PS) != 0 )
-#endif /* !ASM_SRC */
+#define IS_LARGE(pde) (((pde) & PDE_PS) != 0)
-#ifndef ASM_SRC
+// is this entry "system only" or "system and user"?
+#define IS_SYSTEM(entry) (((entry) & PDE_US) == 0)
+#define IS_USER(entry) (((entry) & PDE_US) != 0)
-/*
-** Start of C-only definitions
-*/
+// low-order nine bits of PDEs and PTEs hold "permission" flag bits
+#define PERMS_MASK MOD4K_MASK
+
+// 4KB frame numbers are 20 bits wide
+#define FRAME_4K_SHIFT 12
+#define FRAME2I_4K_MASK 0x000fffff
+#define TO_4KFRAME(n) (((n) & FRAME2I_4K_MASK) << FRAME_4K_SHIFT)
+#define GET_4KFRAME(n) (((n) >> FRAME_4K_SHIFT) & FRAME2I_4K_MASK)
+#define PDE_4K_ADDR(n) ((n) & MOD4K_MASK)
+#define PTE_4K_ADDR(n) ((n) & MOD4K_MASK)
+
+// 4MB frame numbers are 10 bits wide
+#define FRAME_4M_SHIFT 22
+#define FRAME2I_4M_MASK 0x000003ff
+#define TO_4MFRAME(n) (((n) & FRAME2I_4M_MASK) << FRAME_4M_SHIFT)
+#define GET_4MFRAME(n) (((n) >> FRAME_4M_SHIFT) & FRAME2I_4M_MASK)
+#define PDE_4M_ADDR(n) ((n) & MOD4M_MASK)
+#define PTE_4M_ADDR(n) ((n) & MOD4M_MASK)
+
+// extract the PMT address or frame address from a table entry
+// PDEs could point to 4MB pages, or 4KB PMTs
+#define PDE_ADDR(p) \
+ (IS_LARGE(p) ? (((uint32_t)p) & PDE_FA) : (((uint32_t)p) & PDE_PTA))
+// PTEs always point to 4KB pages
+#define PTE_ADDR(p) (((uint32_t)(p)) & PTE_FA)
+// everything has nine bits of permission flags
+#define PERMS(p) (((uint32_t)(p)) & PERMS_MASK)
+
+// extract the table indices from a 32-bit address
+#define PDIX(v) ((((uint32_t)(v)) >> PDIX_SHIFT) & PIX2I_MASK)
+#define PTIX(v) ((((uint32_t)(v)) >> PTIX_SHIFT) & PIX2I_MASK)
/*
** Types
@@ -204,31 +215,31 @@
// PDE for 4KB pages
typedef struct pdek_s {
- uint_t p :1; // present
- uint_t rw :1; // writable
- uint_t us :1; // user/supervisor
- uint_t pwt :1; // cache write-through
- uint_t pcd :1; // cache disable
- uint_t a :1; // accessed
- uint_t avl1 :1; // ignored (available)
- uint_t ps :1; // page size (must be 0)
- uint_t avl2 :4; // ignored (available)
- uint_t fa :20; // frame address
+ uint_t p : 1; // present
+ uint_t rw : 1; // writable
+ uint_t us : 1; // user/supervisor
+ uint_t pwt : 1; // cache write-through
+ uint_t pcd : 1; // cache disable
+ uint_t a : 1; // accessed
+ uint_t avl1 : 1; // ignored (available)
+ uint_t ps : 1; // page size (must be 0)
+ uint_t avl2 : 4; // ignored (available)
+ uint_t fa : 20; // frame address
} pdek_f_t;
// PDE for 4MB pages
typedef struct pdem_s {
- uint_t p :1; // present
- uint_t rw :1; // writable
- uint_t us :1; // user/supervisor
- uint_t pwt :1; // cache write-through
- uint_t pcd :1; // cache disable
- uint_t a :1; // accessed
- uint_t d :1; // dirty
- uint_t ps :1; // page size (must be 1)
- uint_t g :1; // global
- uint_t avl :3; // ignored (available)
- uint_t fa :20; // frame address
+ uint_t p : 1; // present
+ uint_t rw : 1; // writable
+ uint_t us : 1; // user/supervisor
+ uint_t pwt : 1; // cache write-through
+ uint_t pcd : 1; // cache disable
+ uint_t a : 1; // accessed
+ uint_t d : 1; // dirty
+ uint_t ps : 1; // page size (must be 1)
+ uint_t g : 1; // global
+ uint_t avl : 3; // ignored (available)
+ uint_t fa : 20; // frame address
} pdem_f_t;
// page table entries
@@ -238,33 +249,33 @@ typedef struct pdem_s {
// broken out into fields
typedef struct pte_s {
- uint_t p :1; // present
- uint_t rw :1; // writable
- uint_t us :1; // user/supervisor
- uint_t pwt :1; // cache write-through
- uint_t pcd :1; // cache disable
- uint_t a :1; // accessed
- uint_t d :1; // dirty
- uint_t pat :1; // page attribute table in use
- uint_t g :1; // global
- uint_t avl :3; // ignored (available)
- uint_t fa :20; // frame address
+ uint_t p : 1; // present
+ uint_t rw : 1; // writable
+ uint_t us : 1; // user/supervisor
+ uint_t pwt : 1; // cache write-through
+ uint_t pcd : 1; // cache disable
+ uint_t a : 1; // accessed
+ uint_t d : 1; // dirty
+ uint_t pat : 1; // page attribute table in use
+ uint_t g : 1; // global
+ uint_t avl : 3; // ignored (available)
+ uint_t fa : 20; // frame address
} ptef_t;
// page fault error code bits
// comment: meaning when 1 / meaning when 0
struct pfec_s {
- uint_t p :1; // page-level protection violation / !present
- uint_t w :1; // write / read
- uint_t us :1; // user-mode access / supervisor-mode access
- uint_t rsvd :1; // reserved bit violation / not
- uint_t id :1; // instruction fetch / data fetch
- uint_t pk :1; // protection-key violation / !pk
- uint_t ss :1; // shadow stack access / !ss
- uint_t hlat :1; // HLAT paging / ordinary paging or access rights
- uint_t xtr1 :7; // unused
- uint_t sgz :1; // SGX-specific access control violation / !SGX
- uint_t xtr2 :16; // more unused
+ uint_t p : 1; // page-level protection violation / !present
+ uint_t w : 1; // write / read
+ uint_t us : 1; // user-mode access / supervisor-mode access
+ uint_t rsvd : 1; // reserved bit violation / not
+ uint_t id : 1; // instruction fetch / data fetch
+ uint_t pk : 1; // protection-key violation / !pk
+ uint_t ss : 1; // shadow stack access / !ss
+ uint_t hlat : 1; // HLAT paging / ordinary paging or access rights
+ uint_t xtr1 : 7; // unused
+ uint_t sgz : 1; // SGX-specific access control violation / !SGX
+ uint_t xtr2 : 16; // more unused
};
typedef union pfec_u {
@@ -274,10 +285,10 @@ typedef union pfec_u {
// Mapping descriptor for VA::PA mappings
typedef struct mapping_t {
- uint32_t va_start; // starting virtual address for this range
- uint32_t pa_start; // first physical address in the range
- uint32_t pa_end; // last physical address in the range
- uint32_t perm; // access control
+ uint32_t va_start; // starting virtual address for this range
+ uint32_t pa_start; // first physical address in the range
+ uint32_t pa_end; // last physical address in the range
+ uint32_t perm; // access control
} mapping_t;
/*
@@ -299,7 +310,7 @@ extern pde_t *kpdir;
** Note: should not be called until after the memory free list has
** been set up.
*/
-void vm_init( void );
+void vm_init(void);
/**
** Name: vm_pagedup
@@ -310,7 +321,7 @@ void vm_init( void );
**
** @return a pointer to the new, duplicate page, or NULL
*/
-void *vm_pagedup( void *old );
+void *vm_pagedup(void *old);
/**
** Name: vm_ptdup
@@ -322,7 +333,7 @@ void *vm_pagedup( void *old );
**
** @return true on success, else false
*/
-bool_t vm_ptdup( pde_t *dst, pde_t *curr );
+bool_t vm_ptdup(pde_t *dst, pde_t *curr);
/**
** Name: vm_getpte
@@ -338,28 +349,28 @@ bool_t vm_ptdup( pde_t *dst, pde_t *curr );
**
** @return A pointer to the page table entry for this VA, or NULL
*/
-pte_t *vm_getpte( pde_t *pdir, const void *va, bool_t alloc );
+pte_t *vm_getpte(pde_t *pdir, const void *va, bool_t alloc);
/**
** Name: vm_mkkvm
**
** Create the kernel's page table hierarchy
*/
-pde_t *vm_mkkvm( void );
+pde_t *vm_mkkvm(void);
/**
** Name: vm_mkuvm
**
** Create the page table hierarchy for a user process
*/
-pde_t *vm_mkuvm( void );
+pde_t *vm_mkuvm(void);
/**
** Name: vm_set_kvm
**
** Switch the page table register to the kernel's page directory
*/
-void vm_set_kvm( void );
+void vm_set_kvm(void);
/**
** Name: vm_set_uvm
@@ -368,7 +379,7 @@ void vm_set_kvm( void );
**
** @param p The PCB of the user process
*/
-void vm_set_uvm( pcb_t *p );
+void vm_set_uvm(pcb_t *p);
/**
** Name: vm_add
@@ -386,8 +397,8 @@ void vm_set_uvm( pcb_t *p );
**
** @return status of the allocation attempt
*/
-int vm_add( pde_t *pdir, bool_t wr, bool_t sys,
- void *va, uint32_t size, char *data, uint32_t bytes );
+int vm_add(pde_t *pdir, bool_t wr, bool_t sys, void *va, uint32_t size,
+ char *data, uint32_t bytes);
/**
** Name: vm_free
@@ -397,7 +408,7 @@ int vm_add( pde_t *pdir, bool_t wr, bool_t sys,
**
** @param pdir Pointer to the page directory
*/
-void vm_free( pde_t *pdir );
+void vm_free(pde_t *pdir);
/*
** Name: vm_map
@@ -408,11 +419,11 @@ void vm_free( pde_t *pdir );
**
** @param pdir Page directory for this address space
** @param va The starting virtual address
-** @param size Length of the range to be mapped
** @param pa The starting physical address
+** @param size Length of the range to be mapped
** @param perm Permission bits for the PTEs
*/
-int vm_map( pde_t *pdir, void *va, uint_t size, uint_t pa, int perm );
+int vm_map(pde_t *pdir, void *va, uint32_t pa, uint32_t size, int perm);
/**
** Name: vm_uvmdup
@@ -426,8 +437,8 @@ int vm_map( pde_t *pdir, void *va, uint_t size, uint_t pa, int perm );
**
** @return status of the duplication attempt
*/
-int vm_uvmdup( pde_t *old, pde_t *new );
+int vm_uvmdup(pde_t *old, pde_t *new);
-#endif /* !ASM_SRC */
+#endif /* !ASM_SRC */
#endif