Changes in kernel/arch/amd64/src/mm/page.c [c15b374:fabc883] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/amd64/src/mm/page.c
rc15b374 rfabc883 39 39 #include <mm/frame.h> 40 40 #include <mm/as.h> 41 #include <arch/interrupt.h> 41 42 #include <arch/asm.h> 42 43 #include <config.h> … … 47 48 #include <align.h> 48 49 50 /* Definitions for identity page mapper */ 51 pte_t helper_ptl1[512] __attribute__((aligned (PAGE_SIZE))); 52 pte_t helper_ptl2[512] __attribute__((aligned (PAGE_SIZE))); 53 pte_t helper_ptl3[512] __attribute__((aligned (PAGE_SIZE))); 54 extern pte_t ptl_0; /* From boot.S */ 55 56 #define PTL1_PRESENT(ptl0, page) (!(GET_PTL1_FLAGS_ARCH(ptl0, PTL0_INDEX_ARCH(page)) & PAGE_NOT_PRESENT)) 57 #define PTL2_PRESENT(ptl1, page) (!(GET_PTL2_FLAGS_ARCH(ptl1, PTL1_INDEX_ARCH(page)) & PAGE_NOT_PRESENT)) 58 #define PTL3_PRESENT(ptl2, page) (!(GET_PTL3_FLAGS_ARCH(ptl2, PTL2_INDEX_ARCH(page)) & PAGE_NOT_PRESENT)) 59 60 #define PTL1_ADDR(ptl0, page) ((pte_t *)PA2KA(GET_PTL1_ADDRESS_ARCH(ptl0, PTL0_INDEX_ARCH(page)))) 61 #define PTL2_ADDR(ptl1, page) ((pte_t *)PA2KA(GET_PTL2_ADDRESS_ARCH(ptl1, PTL1_INDEX_ARCH(page)))) 62 #define PTL3_ADDR(ptl2, page) ((pte_t *)PA2KA(GET_PTL3_ADDRESS_ARCH(ptl2, PTL2_INDEX_ARCH(page)))) 63 64 #define SETUP_PTL1(ptl0, page, tgt) { \ 65 SET_PTL1_ADDRESS_ARCH(ptl0, PTL0_INDEX_ARCH(page), (uintptr_t)KA2PA(tgt)); \ 66 SET_PTL1_FLAGS_ARCH(ptl0, PTL0_INDEX_ARCH(page), PAGE_WRITE | PAGE_EXEC); \ 67 } 68 #define SETUP_PTL2(ptl1, page, tgt) { \ 69 SET_PTL2_ADDRESS_ARCH(ptl1, PTL1_INDEX_ARCH(page), (uintptr_t)KA2PA(tgt)); \ 70 SET_PTL2_FLAGS_ARCH(ptl1, PTL1_INDEX_ARCH(page), PAGE_WRITE | PAGE_EXEC); \ 71 } 72 #define SETUP_PTL3(ptl2, page, tgt) { \ 73 SET_PTL3_ADDRESS_ARCH(ptl2, PTL2_INDEX_ARCH(page), (uintptr_t)KA2PA(tgt)); \ 74 SET_PTL3_FLAGS_ARCH(ptl2, PTL2_INDEX_ARCH(page), PAGE_WRITE | PAGE_EXEC); \ 75 } 76 #define SETUP_FRAME(ptl3, page, tgt) { \ 77 SET_FRAME_ADDRESS_ARCH(ptl3, PTL3_INDEX_ARCH(page), (uintptr_t)KA2PA(tgt)); \ 78 SET_FRAME_FLAGS_ARCH(ptl3, PTL3_INDEX_ARCH(page), PAGE_WRITE | PAGE_EXEC); \ 79 } 80 81 49 82 void page_arch_init(void) 50 83 { 84 uintptr_t cur; 85 unsigned int i; 86 int identity_flags = PAGE_CACHEABLE | PAGE_EXEC | PAGE_GLOBAL | PAGE_WRITE; 87 51 88 if (config.cpu_active == 1) { 52 uintptr_t cur;53 unsigned int identity_flags =54 PAGE_CACHEABLE | PAGE_EXEC | PAGE_GLOBAL | PAGE_WRITE;55 56 89 page_mapping_operations = &pt_mapping_operations; 57 58 page_table_lock(AS_KERNEL, true); 59 90 60 91 /* 61 92 * PA2KA(identity) mapping for all frames. 62 93 */ 63 for (cur = 0; cur < last_frame; cur += FRAME_SIZE) 94 for (cur = 0; cur < last_frame; cur += FRAME_SIZE) { 95 /* Standard identity mapping */ 64 96 page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, identity_flags); 97 } 65 98 66 page_table_unlock(AS_KERNEL, true); 99 /* Upper kernel mapping 100 * - from zero to top of kernel (include bottom addresses 101 * because some are needed for init) 102 */ 103 for (cur = PA2KA_CODE(0); cur < config.base + config.kernel_size; cur += FRAME_SIZE) 104 page_mapping_insert(AS_KERNEL, cur, KA2PA(cur), identity_flags); 67 105 68 exc_register(14, "page_fault", true, (iroutine_t) page_fault); 106 for (cur = config.stack_base; cur < config.stack_base + config.stack_size; cur += FRAME_SIZE) 107 page_mapping_insert(AS_KERNEL, cur, KA2PA(cur), identity_flags); 108 109 for (i = 0; i < init.cnt; i++) { 110 for (cur = init.tasks[i].addr; cur < init.tasks[i].addr + init.tasks[i].size; cur += FRAME_SIZE) 111 page_mapping_insert(AS_KERNEL, PA2KA_CODE(KA2PA(cur)), KA2PA(cur), identity_flags); 112 } 113 114 exc_register(14, "page_fault", (iroutine) page_fault); 69 115 write_cr3((uintptr_t) AS_KERNEL->genarch.page_table); 70 } else 116 } else 71 117 write_cr3((uintptr_t) AS_KERNEL->genarch.page_table); 72 118 } 73 119 74 void page_fault(unsigned int n, istate_t *istate) 75 { 76 uintptr_t page = read_cr2(); 120 121 /** Identity page mapper 122 * 123 * We need to map whole physical memory identically before the page subsystem 124 * is initializaed. This thing clears page table and fills in the specific 125 * items. 126 */ 127 void ident_page_fault(int n, istate_t *istate) 128 { 129 uintptr_t page; 130 static uintptr_t oldpage = 0; 131 pte_t *aptl_1, *aptl_2, *aptl_3; 132 133 page = read_cr2(); 134 if (oldpage) { 135 /* Unmap old address */ 136 aptl_1 = PTL1_ADDR(&ptl_0, oldpage); 137 aptl_2 = PTL2_ADDR(aptl_1, oldpage); 138 aptl_3 = PTL3_ADDR(aptl_2, oldpage); 139 140 SET_FRAME_FLAGS_ARCH(aptl_3, PTL3_INDEX_ARCH(oldpage), PAGE_NOT_PRESENT); 141 if (KA2PA(aptl_3) == KA2PA(helper_ptl3)) 142 SET_PTL3_FLAGS_ARCH(aptl_2, PTL2_INDEX_ARCH(oldpage), PAGE_NOT_PRESENT); 143 if (KA2PA(aptl_2) == KA2PA(helper_ptl2)) 144 SET_PTL2_FLAGS_ARCH(aptl_1, PTL1_INDEX_ARCH(oldpage), PAGE_NOT_PRESENT); 145 if (KA2PA(aptl_1) == KA2PA(helper_ptl1)) 146 SET_PTL1_FLAGS_ARCH(&ptl_0, PTL0_INDEX_ARCH(oldpage), PAGE_NOT_PRESENT); 147 } 148 if (PTL1_PRESENT(&ptl_0, page)) 149 aptl_1 = PTL1_ADDR(&ptl_0, page); 150 else { 151 SETUP_PTL1(&ptl_0, page, helper_ptl1); 152 aptl_1 = helper_ptl1; 153 } 154 155 if (PTL2_PRESENT(aptl_1, page)) 156 aptl_2 = PTL2_ADDR(aptl_1, page); 157 else { 158 SETUP_PTL2(aptl_1, page, helper_ptl2); 159 aptl_2 = helper_ptl2; 160 } 161 162 if (PTL3_PRESENT(aptl_2, page)) 163 aptl_3 = PTL3_ADDR(aptl_2, page); 164 else { 165 SETUP_PTL3(aptl_2, page, helper_ptl3); 166 aptl_3 = helper_ptl3; 167 } 168 169 SETUP_FRAME(aptl_3, page, page); 170 171 oldpage = page; 172 } 173 174 175 void page_fault(int n, istate_t *istate) 176 { 177 uintptr_t page; 178 pf_access_t access; 179 180 page = read_cr2(); 77 181 78 182 if (istate->error_word & PFERR_CODE_RSVD) 79 183 panic("Reserved bit set in page table entry."); 80 81 pf_access_t access;82 184 83 185 if (istate->error_word & PFERR_CODE_RW) … … 90 192 if (as_page_fault(page, access, istate) == AS_PF_FAULT) { 91 193 fault_if_from_uspace(istate, "Page fault: %#x.", page); 92 panic_memtrap(istate, access, page, NULL); 93 } 94 } 194 195 decode_istate(n, istate); 196 printf("Page fault address: %llx.\n", page); 197 panic("Page fault."); 198 } 199 } 200 95 201 96 202 uintptr_t hw_map(uintptr_t physaddr, size_t size) 97 203 { 98 204 if (last_frame + ALIGN_UP(size, PAGE_SIZE) > KA2PA(KERNEL_ADDRESS_SPACE_END_ARCH)) 99 panic("Unable to map physical memory %p (% " PRIs "bytes).", physaddr,205 panic("Unable to map physical memory %p (%d bytes).", physaddr, 100 206 size); 101 207 102 208 uintptr_t virtaddr = PA2KA(last_frame); 103 209 pfn_t i; 104 105 page_table_lock(AS_KERNEL, true);106 107 210 for (i = 0; i < ADDR2PFN(ALIGN_UP(size, PAGE_SIZE)); i++) 108 211 page_mapping_insert(AS_KERNEL, virtaddr + PFN2ADDR(i), physaddr + PFN2ADDR(i), PAGE_NOT_CACHEABLE | PAGE_WRITE); 109 212 110 page_table_unlock(AS_KERNEL, true);111 112 213 last_frame = ALIGN_UP(last_frame + size, FRAME_SIZE); 113 214
Note:
See TracChangeset
for help on using the changeset viewer.