00001 #ifndef THREADS_PTE_H 00002 //106988699 00003 #define THREADS_PTE_H 00004 00005 #include "threads/vaddr.h" 00006 00007 /* Functions and macros for working with x86 hardware page 00008 tables. 00009 00010 See vaddr.h for more generic functions and macros for virtual 00011 addresses. 00012 00013 Virtual addresses are structured as follows: 00014 00015 31 22 21 12 11 0 00016 +----------------------+----------------------+----------------------+ 00017 | Page Directory Index | Page Table Index | Page Offset | 00018 +----------------------+----------------------+----------------------+ 00019 */ 00020 00021 /* Page table index (bits 12:21). */ 00022 #define PTSHIFT PGBITS /* First page table bit. */ 00023 #define PTBITS 10 /* Number of page table bits. */ 00024 #define PTSPAN (1 << PTBITS << PGBITS) /* Bytes covered by a page table. */ 00025 #define PTMASK BITMASK(PTSHIFT, PTBITS) /* Page table bits (12:21). */ 00026 00027 /* Page directory index (bits 22:31). */ 00028 #define PDSHIFT (PTSHIFT + PTBITS) /* First page directory bit. */ 00029 #define PDBITS 10 /* Number of page dir bits. */ 00030 #define PDMASK BITMASK(PDSHIFT, PDBITS) /* Page directory bits (22:31). */ 00031 00032 /* memory dedicated to PCI - make sure this is 4MB aligned */ 00033 #define PCI_ADDR_ZONE_BEGIN 0xe0000000 00034 #define PCI_ADDR_ZONE_END 0xe0800000 00035 #define PCI_ADDR_ZONE_PDES 2 00036 #define PCI_ADDR_ZONE_PAGES (PCI_ADDR_ZONE_END-PCI_ADDR_ZONE_BEGIN)/PGSIZE 00037 00038 00039 00040 /* Obtains page table index from a virtual address. */ 00041 static inline unsigned pt_no (const void *va) { 00042 return ((uintptr_t) va & PTMASK) >> PTSHIFT; 00043 } 00044 00045 /* Obtains page directory index from a virtual address. */ 00046 static inline uintptr_t pd_no (const void *va) { 00047 return (uintptr_t) va >> PDSHIFT; 00048 } 00049 00050 /* Page directory and page table entries. 00051 00052 For more information see the section on page tables in the 00053 Pintos reference guide chapter, or [IA32-v3a] 3.7.6 00054 "Page-Directory and Page-Table Entries". 00055 00056 PDEs and PTEs share a common format: 00057 00058 31 12 11 0 00059 +------------------------------------+------------------------+ 00060 | Physical Address | Flags | 00061 +------------------------------------+------------------------+ 00062 00063 In a PDE, the physical address points to a page table. 00064 In a PTE, the physical address points to a data or code page. 00065 The important flags are listed below. 00066 When a PDE or PTE is not "present", the other flags are 00067 ignored. 00068 A PDE or PTE that is initialized to 0 will be interpreted as 00069 "not present", which is just fine. */ 00070 #define PTE_FLAGS 0x00000fff /* Flag bits. */ 00071 #define PTE_ADDR 0xfffff000 /* Address bits. */ 00072 #define PTE_AVL 0x00000e00 /* Bits available for OS use. */ 00073 #define PTE_P 0x1 /* 1=present, 0=not present. */ 00074 #define PTE_W 0x2 /* 1=read/write, 0=read-only. */ 00075 #define PTE_U 0x4 /* 1=user/kernel, 0=kernel only. */ 00076 #define PTE_WT (1 << 3) /* 1=write-through, 0=write-back */ 00077 #define PTE_CD (1 << 4) /* 1=cache disabled, 0=cache enabled. */ 00078 #define PTE_A 0x20 /* 1=accessed, 0=not acccessed. */ 00079 #define PTE_D 0x40 /* 1=dirty, 0=not dirty (PTEs only). */ 00080 #define PTE_G (1 << 8) /* 1=global page, do not flush */ 00081 00082 /* Returns a PDE that points to page table PT. */ 00083 static inline uint32_t pde_create_user (uint32_t *pt) { 00084 ASSERT (pg_ofs (pt) == 0); 00085 return vtop (pt) | PTE_U | PTE_P | PTE_W; 00086 } 00087 00088 /* Returns a PDE that points to page table PT. */ 00089 static inline uint32_t pde_create_kernel (uint32_t *pt) { 00090 ASSERT (pg_ofs (pt) == 0); 00091 return vtop (pt) | PTE_P | PTE_W | PTE_G; 00092 } 00093 00094 /* Returns a pointer to the page table that page directory entry 00095 PDE, which must "present", points to. */ 00096 static inline uint32_t *pde_get_pt (uint32_t pde) { 00097 ASSERT (pde & PTE_P); 00098 return ptov (pde & PTE_ADDR); 00099 } 00100 00101 /* Returns a PTE that points to PAGE. 00102 The PTE's page is readable. 00103 If WRITABLE is true then it will be writable as well. 00104 The page will be usable only by ring 0 code (the kernel). */ 00105 static inline uint32_t pte_create_kernel (void *page, bool writable) { 00106 ASSERT (pg_ofs (page) == 0); 00107 return vtop (page) | PTE_P | (writable ? PTE_W : 0) | PTE_G; 00108 } 00109 00110 /* Returns a PTE that points to PAGE. 00111 The PTE's page is readable. 00112 If WRITABLE is true then it will be writable as well. 00113 The page will be usable by both user and kernel code. */ 00114 static inline uint32_t pte_create_user (void *page, bool writable) { 00115 ASSERT (pg_ofs (page) == 0); 00116 return vtop (page) | PTE_P | (writable ? PTE_W : 0) | PTE_U; 00117 } 00118 00119 /* Returns a pointer to the page that page table entry PTE points 00120 to. */ 00121 static inline void *pte_get_page (uint32_t pte) { 00122 return ptov (pte & PTE_ADDR); 00123 } 00124 00125 #endif /* threads/pte.h */ 00126