Changeset 35f3b8c in mainline for arch/ppc32/src/mm/page.c
- Timestamp:
- 2006-05-18T23:24:40Z (19 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- c0bc189
- Parents:
- 8424198
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
arch/ppc32/src/mm/page.c
r8424198 r35f3b8c 30 30 #include <genarch/mm/page_pt.h> 31 31 #include <arch/mm/frame.h> 32 #include <arch/asm.h> 32 33 #include <mm/frame.h> 33 34 #include <mm/page.h> 35 #include <mm/as.h> 36 #include <arch.h> 34 37 #include <arch/types.h> 38 #include <arch/exception.h> 39 #include <config.h> 40 #include <print.h> 41 #include <symtab.h> 42 43 static phte_t *phte; 44 45 46 /** Try to find PTE for faulting address 47 * 48 * Try to find PTE for faulting address. 49 * The AS->lock must be held on entry to this function. 50 * 51 * @param badvaddr Faulting virtual address. 52 * @param istate Pointer to interrupted state. 53 * @param pfrc Pointer to variable where as_page_fault() return code will be stored. 54 * @return PTE on success, NULL otherwise. 55 * 56 */ 57 static pte_t *find_mapping_and_check(__address badvaddr, istate_t *istate, int *pfcr) 58 { 59 /* 60 * Check if the mapping exists in page tables. 61 */ 62 pte_t *pte = page_mapping_find(AS, badvaddr); 63 if ((pte) && (pte->p)) { 64 /* 65 * Mapping found in page tables. 66 * Immediately succeed. 67 */ 68 return pte; 69 } else { 70 int rc; 71 72 /* 73 * Mapping not found in page tables. 74 * Resort to higher-level page fault handler. 75 */ 76 page_table_unlock(AS, true); 77 switch (rc = as_page_fault(badvaddr, istate)) { 78 case AS_PF_OK: 79 /* 80 * The higher-level page fault handler succeeded, 81 * The mapping ought to be in place. 82 */ 83 page_table_lock(AS, true); 84 pte = page_mapping_find(AS, badvaddr); 85 ASSERT((pte) && (pte->p)); 86 return pte; 87 case AS_PF_DEFER: 88 page_table_lock(AS, true); 89 *pfcr = rc; 90 return NULL; 91 case AS_PF_FAULT: 92 page_table_lock(AS, true); 93 printf("Page fault.\n"); 94 *pfcr = rc; 95 return NULL; 96 default: 97 panic("unexpected rc (%d)\n", rc); 98 } 99 } 100 } 101 102 103 static void pht_refill_fail(__address badvaddr, istate_t *istate) 104 { 105 char *symbol = ""; 106 char *sym2 = ""; 107 108 char *s = get_symtab_entry(istate->pc); 109 if (s) 110 symbol = s; 111 s = get_symtab_entry(istate->lr); 112 if (s) 113 sym2 = s; 114 panic("%p: PHT Refill Exception at %p (%s<-%s)\n", badvaddr, istate->pc, symbol, sym2); 115 } 116 117 static void pht_insert(const __address vaddr, const pfn_t pfn) 118 { 119 __u32 page = (vaddr >> 12) & 0xffff; 120 __u32 api = (vaddr >> 22) & 0x3f; 121 __u32 vsid; 122 123 asm volatile ( 124 "mfsrin %0, %1\n" 125 : "=r" (vsid) 126 : "r" (vaddr) 127 ); 128 129 /* Primary hash (xor) */ 130 __u32 hash = ((vsid ^ page) & 0x3ff) << 3; 131 132 __u32 i; 133 /* Find unused PTE in PTEG */ 134 for (i = 0; i < 8; i++) { 135 if (!phte[hash + i].v) 136 break; 137 } 138 139 // TODO: Check access/change bits, secondary hash 140 141 if (i == 8) 142 i = page % 8; 143 144 phte[hash + i].v = 1; 145 phte[hash + i].vsid = vsid; 146 phte[hash + i].h = 0; 147 phte[hash + i].api = api; 148 phte[hash + i].rpn = pfn; 149 phte[hash + i].r = 0; 150 phte[hash + i].c = 0; 151 phte[hash + i].pp = 2; // FIXME 152 } 153 154 155 /** Process Instruction/Data Storage Interrupt 156 * 157 * @param data True if Data Storage Interrupt. 158 * @param istate Interrupted register context. 159 * 160 */ 161 void pht_refill(bool data, istate_t *istate) 162 { 163 asid_t asid; 164 __address badvaddr; 165 pte_t *pte; 166 167 int pfcr; 168 169 if (data) { 170 asm volatile ( 171 "mfdar %0\n" 172 : "=r" (badvaddr) 173 ); 174 } else 175 badvaddr = istate->pc; 176 177 spinlock_lock(&AS->lock); 178 asid = AS->asid; 179 spinlock_unlock(&AS->lock); 180 181 page_table_lock(AS, true); 182 183 pte = find_mapping_and_check(badvaddr, istate, &pfcr); 184 if (!pte) { 185 switch (pfcr) { 186 case AS_PF_FAULT: 187 goto fail; 188 break; 189 case AS_PF_DEFER: 190 /* 191 * The page fault came during copy_from_uspace() 192 * or copy_to_uspace(). 193 */ 194 page_table_unlock(AS, true); 195 return; 196 default: 197 panic("Unexpected pfrc (%d)\n", pfcr); 198 break; 199 } 200 } 201 202 pte->a = 1; /* Record access to PTE */ 203 pht_insert(badvaddr, pte->pfn); 204 205 page_table_unlock(AS, true); 206 return; 207 208 fail: 209 page_table_unlock(AS, true); 210 pht_refill_fail(badvaddr, istate); 211 } 212 213 214 void pht_init(void) 215 { 216 memsetb((__address) phte, 1 << PHT_BITS, 0); 217 218 /* Insert global kernel mapping */ 219 220 __address cur; 221 for (cur = 0; cur < last_frame; cur += FRAME_SIZE) { 222 pte_t *pte = page_mapping_find(AS_KERNEL, PA2KA(cur)); 223 if ((pte) && (pte->p) && (pte->g)) 224 pht_insert(PA2KA(cur), pte->pfn); 225 } 226 } 227 35 228 36 229 void page_arch_init(void) 37 230 { 38 page_mapping_operations = &pt_mapping_operations; 39 } 231 if (config.cpu_active == 1) { 232 page_mapping_operations = &pt_mapping_operations; 233 234 /* 235 * PA2KA(identity) mapping for all frames until last_frame. 236 */ 237 __address cur; 238 int flags; 239 240 for (cur = 0; cur < last_frame; cur += FRAME_SIZE) { 241 flags = PAGE_CACHEABLE; 242 if ((PA2KA(cur) >= config.base) && (PA2KA(cur) < config.base + config.kernel_size)) 243 flags |= PAGE_GLOBAL; 244 page_mapping_insert(AS_KERNEL, PA2KA(cur), cur, flags); 245 } 246 247 /* Allocate page hash table */ 248 phte_t *physical_phte = (phte_t *) PFN2ADDR(frame_alloc(PHT_ORDER, FRAME_KA | FRAME_PANIC)); 249 phte = (phte_t *) PA2KA((__address) physical_phte); 250 251 ASSERT((__address) physical_phte % (1 << PHT_BITS) == 0); 252 pht_init(); 253 254 asm volatile ( 255 "mtsdr1 %0\n" 256 : 257 : "r" ((__address) physical_phte) 258 ); 259 260 /* Invalidate block address translation registers, 261 thus remove the temporary mapping */ 262 // invalidate_bat(); 263 } 264 }
Note:
See TracChangeset
for help on using the changeset viewer.