Changeset 10e0cee in mainline for arch/ppc32/src/mm/tlb.c
- Timestamp:
- 2006-06-18T00:31:14Z (19 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- 1bb2e7a
- Parents:
- 8e3bf3e2
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
arch/ppc32/src/mm/tlb.c
r8e3bf3e2 r10e0cee 27 27 */ 28 28 29 29 /** @addtogroup ppc32mm 30 30 * @{ 31 31 */ … … 34 34 35 35 #include <mm/tlb.h> 36 37 38 /** Initialize Page Hash Table. 39 * 40 * Setup the Page Hash Table with no entries. 41 * 42 */ 36 #include <arch/mm/tlb.h> 37 #include <arch/interrupt.h> 38 #include <mm/as.h> 39 #include <arch.h> 40 #include <print.h> 41 #include <symtab.h> 42 43 44 /** Try to find PTE for faulting address 45 * 46 * Try to find PTE for faulting address. 47 * The as->lock must be held on entry to this function 48 * if lock is true. 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 will be stored. 56 * @return PTE on success, NULL otherwise. 57 * 58 */ 59 static pte_t *find_mapping_and_check(as_t *as, bool lock, __address badvaddr, int access, istate_t *istate, int *pfrc) 60 { 61 /* 62 * Check if the mapping exists in page tables. 63 */ 64 pte_t *pte = page_mapping_find(as, badvaddr); 65 if ((pte) && (pte->p)) { 66 /* 67 * Mapping found in page tables. 68 * Immediately succeed. 69 */ 70 return pte; 71 } else { 72 int rc; 73 74 /* 75 * Mapping not found in page tables. 76 * Resort to higher-level page fault handler. 77 */ 78 page_table_unlock(as, lock); 79 switch (rc = as_page_fault(badvaddr, access, istate)) { 80 case AS_PF_OK: 81 /* 82 * The higher-level page fault handler succeeded, 83 * The mapping ought to be in place. 84 */ 85 page_table_lock(as, lock); 86 pte = page_mapping_find(as, badvaddr); 87 ASSERT((pte) && (pte->p)); 88 return pte; 89 case AS_PF_DEFER: 90 page_table_lock(as, lock); 91 *pfrc = rc; 92 return NULL; 93 case AS_PF_FAULT: 94 page_table_lock(as, lock); 95 printf("Page fault.\n"); 96 *pfrc = rc; 97 return NULL; 98 default: 99 panic("unexpected rc (%d)\n", rc); 100 } 101 } 102 } 103 104 105 static void pht_refill_fail(__address badvaddr, istate_t *istate) 106 { 107 char *symbol = ""; 108 char *sym2 = ""; 109 110 char *s = get_symtab_entry(istate->pc); 111 if (s) 112 symbol = s; 113 s = get_symtab_entry(istate->lr); 114 if (s) 115 sym2 = s; 116 panic("%p: PHT Refill Exception at %p (%s<-%s)\n", badvaddr, istate->pc, symbol, sym2); 117 } 118 119 120 static void pht_insert(const __address vaddr, const pfn_t pfn) 121 { 122 __u32 page = (vaddr >> 12) & 0xffff; 123 __u32 api = (vaddr >> 22) & 0x3f; 124 125 __u32 vsid; 126 asm volatile ( 127 "mfsrin %0, %1\n" 128 : "=r" (vsid) 129 : "r" (vaddr) 130 ); 131 132 __u32 sdr1; 133 asm volatile ( 134 "mfsdr1 %0\n" 135 : "=r" (sdr1) 136 ); 137 phte_t *phte = (phte_t *) PA2KA(sdr1 & 0xffff0000); 138 139 /* Primary hash (xor) */ 140 __u32 h = 0; 141 __u32 hash = vsid ^ page; 142 __u32 base = (hash & 0x3ff) << 3; 143 __u32 i; 144 bool found = false; 145 146 /* Find unused or colliding 147 PTE in PTEG */ 148 for (i = 0; i < 8; i++) { 149 if ((!phte[base + i].v) || ((phte[base + i].vsid == vsid) && (phte[base + i].api == api))) { 150 found = true; 151 break; 152 } 153 } 154 155 if (!found) { 156 /* Secondary hash (not) */ 157 __u32 base2 = (~hash & 0x3ff) << 3; 158 159 /* Find unused or colliding 160 PTE in PTEG */ 161 for (i = 0; i < 8; i++) { 162 if ((!phte[base2 + i].v) || ((phte[base2 + i].vsid == vsid) && (phte[base2 + i].api == api))) { 163 found = true; 164 base = base2; 165 h = 1; 166 break; 167 } 168 } 169 170 if (!found) { 171 // TODO: A/C precedence groups 172 i = page % 8; 173 } 174 } 175 176 phte[base + i].v = 1; 177 phte[base + i].vsid = vsid; 178 phte[base + i].h = h; 179 phte[base + i].api = api; 180 phte[base + i].rpn = pfn; 181 phte[base + i].r = 0; 182 phte[base + i].c = 0; 183 phte[base + i].pp = 2; // FIXME 184 } 185 186 187 static void pht_real_insert(const __address vaddr, const pfn_t pfn) 188 { 189 __u32 page = (vaddr >> 12) & 0xffff; 190 __u32 api = (vaddr >> 22) & 0x3f; 191 192 __u32 vsid; 193 asm volatile ( 194 "mfsrin %0, %1\n" 195 : "=r" (vsid) 196 : "r" (vaddr) 197 ); 198 199 __u32 sdr1; 200 asm volatile ( 201 "mfsdr1 %0\n" 202 : "=r" (sdr1) 203 ); 204 phte_t *phte_physical = (phte_t *) (sdr1 & 0xffff0000); 205 206 /* Primary hash (xor) */ 207 __u32 h = 0; 208 __u32 hash = vsid ^ page; 209 __u32 base = (hash & 0x3ff) << 3; 210 __u32 i; 211 bool found = false; 212 213 /* Find unused or colliding 214 PTE in PTEG */ 215 for (i = 0; i < 8; i++) { 216 if ((!phte_physical[base + i].v) || ((phte_physical[base + i].vsid == vsid) && (phte_physical[base + i].api == api))) { 217 found = true; 218 break; 219 } 220 } 221 222 if (!found) { 223 /* Secondary hash (not) */ 224 __u32 base2 = (~hash & 0x3ff) << 3; 225 226 /* Find unused or colliding 227 PTE in PTEG */ 228 for (i = 0; i < 8; i++) { 229 if ((!phte_physical[base2 + i].v) || ((phte_physical[base2 + i].vsid == vsid) && (phte_physical[base2 + i].api == api))) { 230 found = true; 231 base = base2; 232 h = 1; 233 break; 234 } 235 } 236 237 if (!found) { 238 // TODO: A/C precedence groups 239 i = page % 8; 240 } 241 } 242 243 phte_physical[base + i].v = 1; 244 phte_physical[base + i].vsid = vsid; 245 phte_physical[base + i].h = h; 246 phte_physical[base + i].api = api; 247 phte_physical[base + i].rpn = pfn; 248 phte_physical[base + i].r = 0; 249 phte_physical[base + i].c = 0; 250 phte_physical[base + i].pp = 2; // FIXME 251 } 252 253 254 /** Process Instruction/Data Storage Interrupt 255 * 256 * @param n Interrupt vector number. 257 * @param istate Interrupted register context. 258 * 259 */ 260 void pht_refill(int n, istate_t *istate) 261 { 262 __address badvaddr; 263 pte_t *pte; 264 int pfrc; 265 as_t *as; 266 bool lock; 267 268 if (AS == NULL) { 269 as = AS_KERNEL; 270 lock = false; 271 } else { 272 as = AS; 273 lock = true; 274 } 275 276 if (n == VECTOR_DATA_STORAGE) { 277 asm volatile ( 278 "mfdar %0\n" 279 : "=r" (badvaddr) 280 ); 281 } else 282 badvaddr = istate->pc; 283 284 page_table_lock(as, lock); 285 286 pte = find_mapping_and_check(as, lock, badvaddr, PF_ACCESS_READ /* FIXME */, istate, &pfrc); 287 if (!pte) { 288 switch (pfrc) { 289 case AS_PF_FAULT: 290 goto fail; 291 break; 292 case AS_PF_DEFER: 293 /* 294 * The page fault came during copy_from_uspace() 295 * or copy_to_uspace(). 296 */ 297 page_table_unlock(as, lock); 298 return; 299 default: 300 panic("Unexpected pfrc (%d)\n", pfrc); 301 } 302 } 303 304 pte->a = 1; /* Record access to PTE */ 305 pht_insert(badvaddr, pte->pfn); 306 307 page_table_unlock(as, lock); 308 return; 309 310 fail: 311 page_table_unlock(as, lock); 312 pht_refill_fail(badvaddr, istate); 313 } 314 315 316 /** Process Instruction/Data Storage Interrupt in Real Mode 317 * 318 * @param n Interrupt vector number. 319 * @param istate Interrupted register context. 320 * 321 */ 322 bool pht_real_refill(int n, istate_t *istate) 323 { 324 __address badvaddr; 325 326 if (n == VECTOR_DATA_STORAGE) { 327 asm volatile ( 328 "mfdar %0\n" 329 : "=r" (badvaddr) 330 ); 331 } else 332 badvaddr = istate->pc; 333 334 __u32 physmem; 335 asm volatile ( 336 "mfsprg3 %0\n" 337 : "=r" (physmem) 338 ); 339 340 if ((badvaddr >= PA2KA(0)) && (badvaddr < PA2KA(physmem))) { 341 pht_real_insert(badvaddr, KA2PA(badvaddr) >> 12); 342 return true; 343 } 344 345 return false; 346 } 347 348 43 349 void tlb_arch_init(void) 44 350 { … … 56 362 57 363 58 /** Invalidate all entries in TLB that belong to specified address space.59 *60 * @param asid This parameter is ignored as the architecture doesn't support it.61 */62 364 void tlb_invalidate_asid(asid_t asid) 63 365 { 366 // TODO 64 367 tlb_invalidate_all(); 65 368 } 66 369 67 /** Invalidate TLB entries for specified page range belonging to specified address space. 68 * 69 * @param asid This parameter is ignored as the architecture doesn't support it. 70 * @param page Address of the first page whose entry is to be invalidated. 71 * @param cnt Number of entries to invalidate. 72 */ 370 73 371 void tlb_invalidate_pages(asid_t asid, __address page, count_t cnt) 74 372 { 373 // TODO 75 374 tlb_invalidate_all(); 76 375 } 77 376 78 377 79 80 /** Print contents of Page Hash Table. */81 378 void tlb_print(void) 82 379 { 83 } 84 85 /** @} 86 */ 87 380 // TODO 381 } 382 383 /** @} 384 */
Note:
See TracChangeset
for help on using the changeset viewer.