diff options
Diffstat (limited to 'threads/pte.h')
| -rw-r--r-- | threads/pte.h | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/threads/pte.h b/threads/pte.h new file mode 100644 index 0000000..1660727 --- /dev/null +++ b/threads/pte.h | |||
| @@ -0,0 +1,107 @@ | |||
| 1 | #ifndef THREADS_PTE_H | ||
| 2 | #define THREADS_PTE_H | ||
| 3 | |||
| 4 | #include "threads/vaddr.h" | ||
| 5 | |||
| 6 | /* Functions and macros for working with x86 hardware page | ||
| 7 | tables. | ||
| 8 | |||
| 9 | See vaddr.h for more generic functions and macros for virtual | ||
| 10 | addresses. | ||
| 11 | |||
| 12 | Virtual addresses are structured as follows: | ||
| 13 | |||
| 14 | 31 22 21 12 11 0 | ||
| 15 | +----------------------+----------------------+----------------------+ | ||
| 16 | | Page Directory Index | Page Table Index | Page Offset | | ||
| 17 | +----------------------+----------------------+----------------------+ | ||
| 18 | */ | ||
| 19 | |||
| 20 | /* Page table index (bits 12:21). */ | ||
| 21 | #define PTSHIFT PGBITS /* First page table bit. */ | ||
| 22 | #define PTBITS 10 /* Number of page table bits. */ | ||
| 23 | #define PTSPAN (1 << PTBITS << PGBITS) /* Bytes covered by a page table. */ | ||
| 24 | #define PTMASK BITMASK(PTSHIFT, PTBITS) /* Page table bits (12:21). */ | ||
| 25 | |||
| 26 | /* Page directory index (bits 22:31). */ | ||
| 27 | #define PDSHIFT (PTSHIFT + PTBITS) /* First page directory bit. */ | ||
| 28 | #define PDBITS 10 /* Number of page dir bits. */ | ||
| 29 | #define PDMASK BITMASK(PDSHIFT, PDBITS) /* Page directory bits (22:31). */ | ||
| 30 | |||
| 31 | /* Obtains page table index from a virtual address. */ | ||
| 32 | static inline unsigned pt_no (const void *va) { | ||
| 33 | return ((uintptr_t) va & PTMASK) >> PTSHIFT; | ||
| 34 | } | ||
| 35 | |||
| 36 | /* Obtains page directory index from a virtual address. */ | ||
| 37 | static inline uintptr_t pd_no (const void *va) { | ||
| 38 | return (uintptr_t) va >> PDSHIFT; | ||
| 39 | } | ||
| 40 | |||
| 41 | /* Page directory and page table entries. | ||
| 42 | |||
| 43 | For more information see the section on page tables in the | ||
| 44 | Pintos reference guide chapter, or [IA32-v3a] 3.7.6 | ||
| 45 | "Page-Directory and Page-Table Entries". | ||
| 46 | |||
| 47 | PDEs and PTEs share a common format: | ||
| 48 | |||
| 49 | 31 12 11 0 | ||
| 50 | +------------------------------------+------------------------+ | ||
| 51 | | Physical Address | Flags | | ||
| 52 | +------------------------------------+------------------------+ | ||
| 53 | |||
| 54 | In a PDE, the physical address points to a page table. | ||
| 55 | In a PTE, the physical address points to a data or code page. | ||
| 56 | The important flags are listed below. | ||
| 57 | When a PDE or PTE is not "present", the other flags are | ||
| 58 | ignored. | ||
| 59 | A PDE or PTE that is initialized to 0 will be interpreted as | ||
| 60 | "not present", which is just fine. */ | ||
| 61 | #define PTE_FLAGS 0x00000fff /* Flag bits. */ | ||
| 62 | #define PTE_ADDR 0xfffff000 /* Address bits. */ | ||
| 63 | #define PTE_AVL 0x00000e00 /* Bits available for OS use. */ | ||
| 64 | #define PTE_P 0x1 /* 1=present, 0=not present. */ | ||
| 65 | #define PTE_W 0x2 /* 1=read/write, 0=read-only. */ | ||
| 66 | #define PTE_U 0x4 /* 1=user/kernel, 0=kernel only. */ | ||
| 67 | #define PTE_A 0x20 /* 1=accessed, 0=not acccessed. */ | ||
| 68 | #define PTE_D 0x40 /* 1=dirty, 0=not dirty (PTEs only). */ | ||
| 69 | |||
| 70 | /* Returns a PDE that points to page table PT. */ | ||
| 71 | static inline uint32_t pde_create (uint32_t *pt) { | ||
| 72 | ASSERT (pg_ofs (pt) == 0); | ||
| 73 | return vtop (pt) | PTE_U | PTE_P | PTE_W; | ||
| 74 | } | ||
| 75 | |||
| 76 | /* Returns a pointer to the page table that page directory entry | ||
| 77 | PDE, which must "present", points to. */ | ||
| 78 | static inline uint32_t *pde_get_pt (uint32_t pde) { | ||
| 79 | ASSERT (pde & PTE_P); | ||
| 80 | return ptov (pde & PTE_ADDR); | ||
| 81 | } | ||
| 82 | |||
| 83 | /* Returns a PTE that points to PAGE. | ||
| 84 | The PTE's page is readable. | ||
| 85 | If WRITABLE is true then it will be writable as well. | ||
| 86 | The page will be usable only by ring 0 code (the kernel). */ | ||
| 87 | static inline uint32_t pte_create_kernel (void *page, bool writable) { | ||
| 88 | ASSERT (pg_ofs (page) == 0); | ||
| 89 | return vtop (page) | PTE_P | (writable ? PTE_W : 0); | ||
| 90 | } | ||
| 91 | |||
| 92 | /* Returns a PTE that points to PAGE. | ||
| 93 | The PTE's page is readable. | ||
| 94 | If WRITABLE is true then it will be writable as well. | ||
| 95 | The page will be usable by both user and kernel code. */ | ||
| 96 | static inline uint32_t pte_create_user (void *page, bool writable) { | ||
| 97 | return pte_create_kernel (page, writable) | PTE_U; | ||
| 98 | } | ||
| 99 | |||
| 100 | /* Returns a pointer to the page that page table entry PTE points | ||
| 101 | to. */ | ||
| 102 | static inline void *pte_get_page (uint32_t pte) { | ||
| 103 | return ptov (pte & PTE_ADDR); | ||
| 104 | } | ||
| 105 | |||
| 106 | #endif /* threads/pte.h */ | ||
| 107 | |||
