00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00035 #include <arch/mm/page.h>
00036 #include <genarch/mm/page_pt.h>
00037 #include <arch/mm/frame.h>
00038 #include <mm/page.h>
00039 #include <mm/frame.h>
00040 #include <mm/as.h>
00041 #include <arch/interrupt.h>
00042 #include <arch/asm.h>
00043 #include <config.h>
00044 #include <memstr.h>
00045 #include <interrupt.h>
00046 #include <print.h>
00047 #include <panic.h>
00048 #include <align.h>
00049
00050
00051 pte_t helper_ptl1[512] __attribute__((aligned (PAGE_SIZE)));
00052 pte_t helper_ptl2[512] __attribute__((aligned (PAGE_SIZE)));
00053 pte_t helper_ptl3[512] __attribute__((aligned (PAGE_SIZE)));
00054 extern pte_t ptl_0;
00055
00056 #define PTL1_PRESENT(ptl0, page) (!(GET_PTL1_FLAGS_ARCH(ptl0, PTL0_INDEX_ARCH(page)) & PAGE_NOT_PRESENT))
00057 #define PTL2_PRESENT(ptl1, page) (!(GET_PTL2_FLAGS_ARCH(ptl1, PTL1_INDEX_ARCH(page)) & PAGE_NOT_PRESENT))
00058 #define PTL3_PRESENT(ptl2, page) (!(GET_PTL3_FLAGS_ARCH(ptl2, PTL2_INDEX_ARCH(page)) & PAGE_NOT_PRESENT))
00059
00060 #define PTL1_ADDR(ptl0, page) ((pte_t *)PA2KA(GET_PTL1_ADDRESS_ARCH(ptl0, PTL0_INDEX_ARCH(page))))
00061 #define PTL2_ADDR(ptl1, page) ((pte_t *)PA2KA(GET_PTL2_ADDRESS_ARCH(ptl1, PTL1_INDEX_ARCH(page))))
00062 #define PTL3_ADDR(ptl2, page) ((pte_t *)PA2KA(GET_PTL3_ADDRESS_ARCH(ptl2, PTL2_INDEX_ARCH(page))))
00063
00064 #define SETUP_PTL1(ptl0, page, tgt) { \
00065 SET_PTL1_ADDRESS_ARCH(ptl0, PTL0_INDEX_ARCH(page), (__address)KA2PA(tgt)); \
00066 SET_PTL1_FLAGS_ARCH(ptl0, PTL0_INDEX_ARCH(page), PAGE_WRITE | PAGE_EXEC); \
00067 }
00068 #define SETUP_PTL2(ptl1, page, tgt) { \
00069 SET_PTL2_ADDRESS_ARCH(ptl1, PTL1_INDEX_ARCH(page), (__address)KA2PA(tgt)); \
00070 SET_PTL2_FLAGS_ARCH(ptl1, PTL1_INDEX_ARCH(page), PAGE_WRITE | PAGE_EXEC); \
00071 }
00072 #define SETUP_PTL3(ptl2, page, tgt) { \
00073 SET_PTL3_ADDRESS_ARCH(ptl2, PTL2_INDEX_ARCH(page), (__address)KA2PA(tgt)); \
00074 SET_PTL3_FLAGS_ARCH(ptl2, PTL2_INDEX_ARCH(page), PAGE_WRITE | PAGE_EXEC); \
00075 }
00076 #define SETUP_FRAME(ptl3, page, tgt) { \
00077 SET_FRAME_ADDRESS_ARCH(ptl3, PTL3_INDEX_ARCH(page), (__address)KA2PA(tgt)); \
00078 SET_FRAME_FLAGS_ARCH(ptl3, PTL3_INDEX_ARCH(page), PAGE_WRITE | PAGE_EXEC); \
00079 }
00080
00081
00082 void page_arch_init(void)
00083 {
00084 __address cur;
00085 int i;
00086 int identity_flags = PAGE_CACHEABLE | PAGE_EXEC | PAGE_GLOBAL;
00087
00088 if (config.cpu_active == 1) {
00089 page_mapping_operations = &pt_mapping_operations;
00090
00091
00092
00093
00094 for (cur = 0; cur < last_frame; cur += FRAME_SIZE) {
00095
00096 page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, identity_flags);
00097 }
00098
00099
00100
00101
00102 for (cur = PA2KA_CODE(0); cur < config.base+config.kernel_size; cur += FRAME_SIZE) {
00103 page_mapping_insert(AS_KERNEL, cur, KA2PA(cur), identity_flags);
00104 }
00105 for (i=0; i < init.cnt; i++) {
00106 for (cur=init.tasks[i].addr;cur < init.tasks[i].size; cur += FRAME_SIZE) {
00107 page_mapping_insert(AS_KERNEL, PA2KA_CODE(KA2PA(cur)), KA2PA(cur), identity_flags);
00108 }
00109 }
00110
00111 exc_register(14, "page_fault", (iroutine)page_fault);
00112 write_cr3((__address) AS_KERNEL->page_table);
00113 }
00114 else {
00115 write_cr3((__address) AS_KERNEL->page_table);
00116 }
00117 }
00118
00119
00126 void ident_page_fault(int n, istate_t *istate)
00127 {
00128 __address page;
00129 static __address oldpage = 0;
00130 pte_t *aptl_1, *aptl_2, *aptl_3;
00131
00132 page = read_cr2();
00133 if (oldpage) {
00134
00135 aptl_1 = PTL1_ADDR(&ptl_0, oldpage);
00136 aptl_2 = PTL2_ADDR(aptl_1, oldpage);
00137 aptl_3 = PTL3_ADDR(aptl_2, oldpage);
00138
00139 SET_FRAME_FLAGS_ARCH(aptl_3, PTL3_INDEX_ARCH(oldpage), PAGE_NOT_PRESENT);
00140 if (KA2PA(aptl_3) == KA2PA(helper_ptl3))
00141 SET_PTL3_FLAGS_ARCH(aptl_2, PTL2_INDEX_ARCH(oldpage), PAGE_NOT_PRESENT);
00142 if (KA2PA(aptl_2) == KA2PA(helper_ptl2))
00143 SET_PTL2_FLAGS_ARCH(aptl_1, PTL1_INDEX_ARCH(oldpage), PAGE_NOT_PRESENT);
00144 if (KA2PA(aptl_1) == KA2PA(helper_ptl1))
00145 SET_PTL1_FLAGS_ARCH(&ptl_0, PTL0_INDEX_ARCH(oldpage), PAGE_NOT_PRESENT);
00146 }
00147 if (PTL1_PRESENT(&ptl_0, page))
00148 aptl_1 = PTL1_ADDR(&ptl_0, page);
00149 else {
00150 SETUP_PTL1(&ptl_0, page, helper_ptl1);
00151 aptl_1 = helper_ptl1;
00152 }
00153
00154 if (PTL2_PRESENT(aptl_1, page))
00155 aptl_2 = PTL2_ADDR(aptl_1, page);
00156 else {
00157 SETUP_PTL2(aptl_1, page, helper_ptl2);
00158 aptl_2 = helper_ptl2;
00159 }
00160
00161 if (PTL3_PRESENT(aptl_2, page))
00162 aptl_3 = PTL3_ADDR(aptl_2, page);
00163 else {
00164 SETUP_PTL3(aptl_2, page, helper_ptl3);
00165 aptl_3 = helper_ptl3;
00166 }
00167
00168 SETUP_FRAME(aptl_3, page, page);
00169
00170 oldpage = page;
00171 }
00172
00173
00174 void page_fault(int n, istate_t *istate)
00175 {
00176 __address page;
00177 pf_access_t access;
00178
00179 page = read_cr2();
00180
00181 if (istate->error_word & PFERR_CODE_RSVD)
00182 panic("Reserved bit set in page table entry.\n");
00183
00184 if (istate->error_word & PFERR_CODE_RW)
00185 access = PF_ACCESS_WRITE;
00186 else if (istate->error_word & PFERR_CODE_ID)
00187 access = PF_ACCESS_EXEC;
00188 else
00189 access = PF_ACCESS_READ;
00190
00191 if (as_page_fault(page, access, istate) == AS_PF_FAULT) {
00192 fault_if_from_uspace(istate, "Page fault: %#x", page);
00193
00194 print_info_errcode(n, istate);
00195 printf("Page fault address: %llx\n", page);
00196 panic("page fault\n");
00197 }
00198 }
00199
00200
00201 __address hw_map(__address physaddr, size_t size)
00202 {
00203 if (last_frame + ALIGN_UP(size, PAGE_SIZE) > KA2PA(KERNEL_ADDRESS_SPACE_END_ARCH))
00204 panic("Unable to map physical memory %p (%d bytes)", physaddr, size)
00205
00206 __address virtaddr = PA2KA(last_frame);
00207 pfn_t i;
00208 for (i = 0; i < ADDR2PFN(ALIGN_UP(size, PAGE_SIZE)); i++)
00209 page_mapping_insert(AS_KERNEL, virtaddr + PFN2ADDR(i), physaddr + PFN2ADDR(i), PAGE_NOT_CACHEABLE);
00210
00211 last_frame = ALIGN_UP(last_frame + size, FRAME_SIZE);
00212
00213 return virtaddr;
00214 }
00215