Changes in kernel/arch/mips32/src/mm/tlb.c [1dbc43f:976c434] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/arch/mips32/src/mm/tlb.c
r1dbc43f r976c434 48 48 #include <symtab.h> 49 49 50 static pte_t *find_mapping_and_check(uintptr_t, int, istate_t *); 50 #define VPN_SHIFT 12 51 #define ADDR2VPN(a) ((a) >> VPN_SHIFT) 52 #define ADDR2VPN2(a) (ADDR2VPN((a)) >> 1) 53 #define VPN2ADDR(vpn) ((vpn) << VPN_SHIFT) 54 #define VPN22ADDR(vpn2) (VPN2ADDR(vpn2) << 1) 55 56 #define BANK_SELECT_BIT(a) (((a) >> PAGE_WIDTH) & 1) 57 51 58 52 59 /** Initialize TLB. … … 84 91 { 85 92 entry_lo_t lo; 86 entry_hi_t hi;87 asid_t asid;88 93 uintptr_t badvaddr; 89 94 pte_t *pte; 90 95 91 96 badvaddr = cp0_badvaddr_read(); 92 asid = AS->asid; 93 94 pte = find_mapping_and_check(badvaddr, PF_ACCESS_READ, istate); 95 if (pte) { 97 98 pte = page_mapping_find(AS, badvaddr, true); 99 if (pte && pte->p) { 96 100 /* 97 101 * Record access to PTE. … … 99 103 pte->a = 1; 100 104 101 tlb_prepare_entry_hi(&hi, asid, badvaddr);102 105 tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->d, 103 106 pte->cacheable, pte->pfn); … … 106 109 * New entry is to be inserted into TLB 107 110 */ 108 cp0_entry_hi_write(hi.value); 109 if ((badvaddr / PAGE_SIZE) % 2 == 0) { 111 if (BANK_SELECT_BIT(badvaddr) == 0) { 110 112 cp0_entry_lo0_write(lo.value); 111 113 cp0_entry_lo1_write(0); … … 116 118 cp0_pagemask_write(TLB_PAGE_MASK_16K); 117 119 tlbwr(); 118 } 120 return; 121 } 122 123 (void) as_page_fault(badvaddr, PF_ACCESS_READ, istate); 119 124 } 120 125 … … 125 130 void tlb_invalid(istate_t *istate) 126 131 { 132 entry_lo_t lo; 127 133 tlb_index_t index; 128 134 uintptr_t badvaddr; 129 entry_lo_t lo;130 entry_hi_t hi;131 135 pte_t *pte; 132 133 badvaddr = cp0_badvaddr_read();134 136 135 137 /* 136 138 * Locate the faulting entry in TLB. 137 139 */ 138 hi.value = cp0_entry_hi_read();139 tlb_prepare_entry_hi(&hi, hi.asid, badvaddr);140 cp0_entry_hi_write(hi.value);141 140 tlbp(); 142 141 index.value = cp0_index_read(); 143 142 143 #if defined(PROCESSOR_4Kc) 144 /* 145 * This can happen on a 4Kc when Status.EXL is 1 and there is a TLB miss. 146 * EXL is 1 when interrupts are disabled. The combination of a TLB miss 147 * and disabled interrupts is possible in copy_to/from_uspace(). 148 */ 149 if (index.p) { 150 tlb_refill(istate); 151 return; 152 } 153 #endif 154 144 155 ASSERT(!index.p); 145 156 146 pte = find_mapping_and_check(badvaddr, PF_ACCESS_READ, istate); 147 if (pte) { 157 badvaddr = cp0_badvaddr_read(); 158 159 pte = page_mapping_find(AS, badvaddr, true); 160 if (pte && pte->p) { 148 161 /* 149 162 * Read the faulting TLB entry. … … 162 175 * The entry is to be updated in TLB. 163 176 */ 164 if ( (badvaddr / PAGE_SIZE) % 2== 0)177 if (BANK_SELECT_BIT(badvaddr) == 0) 165 178 cp0_entry_lo0_write(lo.value); 166 179 else 167 180 cp0_entry_lo1_write(lo.value); 168 cp0_pagemask_write(TLB_PAGE_MASK_16K);169 181 tlbwi(); 170 } 182 return; 183 } 184 185 (void) as_page_fault(badvaddr, PF_ACCESS_READ, istate); 171 186 } 172 187 … … 177 192 void tlb_modified(istate_t *istate) 178 193 { 194 entry_lo_t lo; 179 195 tlb_index_t index; 180 196 uintptr_t badvaddr; 181 entry_lo_t lo;182 entry_hi_t hi;183 197 pte_t *pte; 184 185 badvaddr = cp0_badvaddr_read();186 198 187 199 /* 188 200 * Locate the faulting entry in TLB. 189 201 */ 190 hi.value = cp0_entry_hi_read();191 tlb_prepare_entry_hi(&hi, hi.asid, badvaddr);192 cp0_entry_hi_write(hi.value);193 202 tlbp(); 194 203 index.value = cp0_index_read(); … … 199 208 ASSERT(!index.p); 200 209 201 pte = find_mapping_and_check(badvaddr, PF_ACCESS_WRITE, istate); 202 if (pte) { 210 badvaddr = cp0_badvaddr_read(); 211 212 pte = page_mapping_find(AS, badvaddr, true); 213 if (pte && pte->p && pte->w) { 203 214 /* 204 215 * Read the faulting TLB entry. … … 218 229 * The entry is to be updated in TLB. 219 230 */ 220 if ( (badvaddr / PAGE_SIZE) % 2== 0)231 if (BANK_SELECT_BIT(badvaddr) == 0) 221 232 cp0_entry_lo0_write(lo.value); 222 233 else 223 234 cp0_entry_lo1_write(lo.value); 224 cp0_pagemask_write(TLB_PAGE_MASK_16K);225 235 tlbwi(); 226 } 227 } 228 229 /** Try to find PTE for faulting address. 230 * 231 * @param badvaddr Faulting virtual address. 232 * @param access Access mode that caused the fault. 233 * @param istate Pointer to interrupted state. 234 * 235 * @return PTE on success, NULL otherwise. 236 */ 237 pte_t *find_mapping_and_check(uintptr_t badvaddr, int access, istate_t *istate) 238 { 239 entry_hi_t hi; 240 pte_t *pte; 241 242 hi.value = cp0_entry_hi_read(); 243 244 ASSERT(hi.asid == AS->asid); 245 246 /* 247 * Check if the mapping exists in page tables. 248 */ 249 pte = page_mapping_find(AS, badvaddr, true); 250 if (pte && pte->p && (pte->w || access != PF_ACCESS_WRITE)) { 251 /* 252 * Mapping found in page tables. 253 * Immediately succeed. 254 */ 255 return pte; 256 } 257 258 /* 259 * Mapping not found in page tables. 260 * Resort to higher-level page fault handler. 261 */ 262 if (as_page_fault(badvaddr, access, istate) == AS_PF_OK) { 263 pte = page_mapping_find(AS, badvaddr, true); 264 ASSERT(pte && pte->p); 265 ASSERT(pte->w || access != PF_ACCESS_WRITE); 266 return pte; 267 } 268 269 return NULL; 236 return; 237 } 238 239 (void) as_page_fault(badvaddr, PF_ACCESS_WRITE, istate); 270 240 } 271 241 … … 284 254 void tlb_prepare_entry_hi(entry_hi_t *hi, asid_t asid, uintptr_t addr) 285 255 { 286 hi->value = ALIGN_DOWN(addr, PAGE_SIZE * 2); 256 hi->value = 0; 257 hi->vpn2 = ADDR2VPN2(ALIGN_DOWN(addr, PAGE_SIZE)); 287 258 hi->asid = asid; 288 259 } … … 291 262 void tlb_print(void) 292 263 { 293 page_mask_t mask ;294 entry_lo_t lo0, lo 1;264 page_mask_t mask, mask_save; 265 entry_lo_t lo0, lo0_save, lo1, lo1_save; 295 266 entry_hi_t hi, hi_save; 296 267 unsigned int i; 297 268 298 269 hi_save.value = cp0_entry_hi_read(); 299 300 printf("[nr] [asid] [vpn2] [mask] [gvdc] [pfn ]\n"); 270 lo0_save.value = cp0_entry_lo0_read(); 271 lo1_save.value = cp0_entry_lo1_read(); 272 mask_save.value = cp0_pagemask_read(); 273 274 printf("[nr] [asid] [vpn2 ] [mask] [gvdc] [pfn ]\n"); 301 275 302 276 for (i = 0; i < TLB_ENTRY_COUNT; i++) { … … 309 283 lo1.value = cp0_entry_lo1_read(); 310 284 311 printf("%-4u %-6u % #6x %#6x %1u%1u%1u%1u %#6x\n",312 i, hi.asid, hi.vpn2, mask.mask,313 lo0.g, lo0.v, lo0.d, lo0.c, lo0.pfn );314 printf(" %1u%1u%1u%1u %#6x\n",315 lo1.g, lo1.v, lo1.d, lo1.c, lo1.pfn );285 printf("%-4u %-6u %0#10x %-#6x %1u%1u%1u%1u %0#10x\n", 286 i, hi.asid, VPN22ADDR(hi.vpn2), mask.mask, 287 lo0.g, lo0.v, lo0.d, lo0.c, lo0.pfn << FRAME_WIDTH); 288 printf(" %1u%1u%1u%1u %0#10x\n", 289 lo1.g, lo1.v, lo1.d, lo1.c, lo1.pfn << FRAME_WIDTH); 316 290 } 317 291 318 292 cp0_entry_hi_write(hi_save.value); 293 cp0_entry_lo0_write(lo0_save.value); 294 cp0_entry_lo1_write(lo1_save.value); 295 cp0_pagemask_write(mask_save.value); 319 296 } 320 297 … … 322 299 void tlb_invalidate_all(void) 323 300 { 324 ipl_t ipl;325 301 entry_lo_t lo0, lo1; 326 302 entry_hi_t hi_save; 327 303 int i; 328 304 305 ASSERT(interrupts_disabled()); 306 329 307 hi_save.value = cp0_entry_hi_read(); 330 ipl = interrupts_disable();331 308 332 309 for (i = TLB_WIRED; i < TLB_ENTRY_COUNT; i++) { … … 346 323 } 347 324 348 interrupts_restore(ipl);349 325 cp0_entry_hi_write(hi_save.value); 350 326 } … … 356 332 void tlb_invalidate_asid(asid_t asid) 357 333 { 358 ipl_t ipl;359 334 entry_lo_t lo0, lo1; 360 335 entry_hi_t hi, hi_save; 361 336 int i; 362 337 338 ASSERT(interrupts_disabled()); 363 339 ASSERT(asid != ASID_INVALID); 364 340 365 341 hi_save.value = cp0_entry_hi_read(); 366 ipl = interrupts_disable();367 342 368 343 for (i = 0; i < TLB_ENTRY_COUNT; i++) { … … 386 361 } 387 362 388 interrupts_restore(ipl);389 363 cp0_entry_hi_write(hi_save.value); 390 364 } … … 400 374 { 401 375 unsigned int i; 402 ipl_t ipl;403 376 entry_lo_t lo0, lo1; 404 377 entry_hi_t hi, hi_save; 405 378 tlb_index_t index; 379 380 ASSERT(interrupts_disabled()); 406 381 407 382 if (asid == ASID_INVALID) … … 409 384 410 385 hi_save.value = cp0_entry_hi_read(); 411 ipl = interrupts_disable();412 386 413 387 for (i = 0; i < cnt + 1; i += 2) { 414 hi.value = 0;415 388 tlb_prepare_entry_hi(&hi, asid, page + i * PAGE_SIZE); 416 389 cp0_entry_hi_write(hi.value); … … 439 412 } 440 413 441 interrupts_restore(ipl);442 414 cp0_entry_hi_write(hi_save.value); 443 415 }
Note:
See TracChangeset
for help on using the changeset viewer.