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