Changes in kernel/arch/ppc32/src/mm/tlb.c [26aafe8:655f70b] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/ppc32/src/mm/tlb.c
r26aafe8 r655f70b 33 33 */ 34 34 35 #include <mm/tlb.h>36 35 #include <arch/mm/tlb.h> 37 #include <arch/interrupt.h>38 36 #include <interrupt.h> 39 #include <mm/as.h> 40 #include <mm/page.h> 41 #include <arch.h> 42 #include <print.h> 43 #include <macros.h> 44 #include <symtab.h> 45 46 static unsigned int seed = 42; 47 48 /** Try to find PTE for faulting address 49 * 50 * @param as Address space. 51 * @param lock Lock/unlock the address space. 52 * @param badvaddr Faulting virtual address. 53 * @param access Access mode that caused the fault. 54 * @param istate Pointer to interrupted state. 55 * @param pfrc Pointer to variable where as_page_fault() return code 56 * will be stored. 57 * 58 * @return PTE on success, NULL otherwise. 59 * 60 */ 61 static pte_t *find_mapping_and_check(as_t *as, uintptr_t badvaddr, int access, 62 istate_t *istate, int *pfrc) 63 { 64 ASSERT(mutex_locked(&as->lock)); 65 66 /* 67 * Check if the mapping exists in page tables. 68 */ 69 pte_t *pte = page_mapping_find(as, badvaddr); 70 if ((pte) && (pte->present)) { 71 /* 72 * Mapping found in page tables. 73 * Immediately succeed. 74 */ 75 return pte; 76 } else { 77 /* 78 * Mapping not found in page tables. 79 * Resort to higher-level page fault handler. 80 */ 81 page_table_unlock(as, true); 82 83 int rc = as_page_fault(badvaddr, access, istate); 84 switch (rc) { 85 case AS_PF_OK: 86 /* 87 * The higher-level page fault handler succeeded, 88 * The mapping ought to be in place. 89 */ 90 page_table_lock(as, true); 91 pte = page_mapping_find(as, badvaddr); 92 ASSERT((pte) && (pte->present)); 93 *pfrc = 0; 94 return pte; 95 case AS_PF_DEFER: 96 page_table_lock(as, true); 97 *pfrc = rc; 98 return NULL; 99 case AS_PF_FAULT: 100 page_table_lock(as, true); 101 *pfrc = rc; 102 return NULL; 103 default: 104 panic("Unexpected rc (%d).", rc); 105 } 106 } 107 } 108 109 static void pht_refill_fail(uintptr_t badvaddr, istate_t *istate) 110 { 111 fault_if_from_uspace(istate, "PHT Refill Exception on %p.", 112 (void *) badvaddr); 113 panic_memtrap(istate, PF_ACCESS_UNKNOWN, badvaddr, 114 "PHT Refill Exception."); 115 } 116 117 static void pht_insert(const uintptr_t vaddr, const pte_t *pte) 118 { 119 uint32_t page = (vaddr >> 12) & 0xffff; 120 uint32_t api = (vaddr >> 22) & 0x3f; 121 122 uint32_t vsid = sr_get(vaddr); 123 uint32_t sdr1 = sdr1_get(); 124 125 // FIXME: compute size of PHT exactly 126 phte_t *phte = (phte_t *) PA2KA(sdr1 & 0xffff0000); 127 128 /* Primary hash (xor) */ 129 uint32_t h = 0; 130 uint32_t hash = vsid ^ page; 131 uint32_t base = (hash & 0x3ff) << 3; 132 uint32_t i; 133 bool found = false; 134 135 /* Find colliding PTE in PTEG */ 136 for (i = 0; i < 8; i++) { 137 if ((phte[base + i].v) 138 && (phte[base + i].vsid == vsid) 139 && (phte[base + i].api == api) 140 && (phte[base + i].h == 0)) { 141 found = true; 142 break; 143 } 144 } 145 146 if (!found) { 147 /* Find unused PTE in PTEG */ 148 for (i = 0; i < 8; i++) { 149 if (!phte[base + i].v) { 150 found = true; 151 break; 152 } 153 } 154 } 155 156 if (!found) { 157 /* Secondary hash (not) */ 158 uint32_t base2 = (~hash & 0x3ff) << 3; 159 160 /* Find colliding PTE in PTEG */ 161 for (i = 0; i < 8; i++) { 162 if ((phte[base2 + i].v) 163 && (phte[base2 + i].vsid == vsid) 164 && (phte[base2 + i].api == api) 165 && (phte[base2 + i].h == 1)) { 166 found = true; 167 base = base2; 168 h = 1; 169 break; 170 } 171 } 172 173 if (!found) { 174 /* Find unused PTE in PTEG */ 175 for (i = 0; i < 8; i++) { 176 if (!phte[base2 + i].v) { 177 found = true; 178 base = base2; 179 h = 1; 180 break; 181 } 182 } 183 } 184 185 if (!found) 186 i = RANDI(seed) % 8; 187 } 188 189 phte[base + i].v = 1; 190 phte[base + i].vsid = vsid; 191 phte[base + i].h = h; 192 phte[base + i].api = api; 193 phte[base + i].rpn = pte->pfn; 194 phte[base + i].r = 0; 195 phte[base + i].c = 0; 196 phte[base + i].wimg = (pte->page_cache_disable ? WIMG_NO_CACHE : 0); 197 phte[base + i].pp = 2; // FIXME 198 } 199 200 /** Process Instruction/Data Storage Exception 201 * 202 * @param n Exception vector number. 203 * @param istate Interrupted register context. 204 * 205 */ 206 void pht_refill(unsigned int n, istate_t *istate) 207 { 208 as_t *as = (AS == NULL) ? AS_KERNEL : AS; 209 uintptr_t badvaddr; 210 211 if (n == VECTOR_DATA_STORAGE) 212 badvaddr = istate->dar; 213 else 214 badvaddr = istate->pc; 215 216 page_table_lock(as, true); 217 218 int pfrc; 219 pte_t *pte = find_mapping_and_check(as, badvaddr, 220 PF_ACCESS_READ /* FIXME */, istate, &pfrc); 221 222 if (!pte) { 223 switch (pfrc) { 224 case AS_PF_FAULT: 225 page_table_unlock(as, true); 226 pht_refill_fail(badvaddr, istate); 227 return; 228 case AS_PF_DEFER: 229 /* 230 * The page fault came during copy_from_uspace() 231 * or copy_to_uspace(). 232 */ 233 page_table_unlock(as, true); 234 return; 235 default: 236 panic("Unexpected pfrc (%d).", pfrc); 237 } 238 } 239 240 /* Record access to PTE */ 241 pte->accessed = 1; 242 pht_insert(badvaddr, pte); 243 244 page_table_unlock(as, true); 245 } 37 #include <typedefs.h> 246 38 247 39 void tlb_refill(unsigned int n, istate_t *istate) … … 289 81 void tlb_invalidate_all(void) 290 82 { 291 uint32_t index; 83 asm volatile ( 84 "sync\n" 85 ); 86 87 for (unsigned int i = 0; i < 0x00040000; i += 0x00001000) { 88 asm volatile ( 89 "tlbie %[i]\n" 90 :: [i] "r" (i) 91 ); 92 } 292 93 293 94 asm volatile ( 294 "li %[index], 0\n"295 "sync\n"296 297 ".rept 64\n"298 " tlbie %[index]\n"299 " addi %[index], %[index], 0x1000\n"300 ".endr\n"301 302 95 "eieio\n" 303 96 "tlbsync\n" 304 97 "sync\n" 305 : [index] "=r" (index)306 98 ); 307 99 } … … 309 101 void tlb_invalidate_asid(asid_t asid) 310 102 { 311 uint32_t sdr1 = sdr1_get();312 313 // FIXME: compute size of PHT exactly314 phte_t *phte = (phte_t *) PA2KA(sdr1 & 0xffff0000);315 316 size_t i;317 for (i = 0; i < 8192; i++) {318 if ((phte[i].v) && (phte[i].vsid >= (asid << 4)) &&319 (phte[i].vsid < ((asid << 4) + 16)))320 phte[i].v = 0;321 }322 323 103 tlb_invalidate_all(); 324 104 } … … 326 106 void tlb_invalidate_pages(asid_t asid, uintptr_t page, size_t cnt) 327 107 { 328 // TODO329 108 tlb_invalidate_all(); 330 109 }
Note:
See TracChangeset
for help on using the changeset viewer.