Changeset 35f3b8c in mainline for arch/ppc32/src/mm/tlb.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/tlb.c
r8424198 r35f3b8c 27 27 */ 28 28 29 #include <arch/mm/tlb.h>30 #include <arch/types.h>31 29 #include <mm/tlb.h> 32 #include <mm/frame.h>33 #include <mm/page.h>34 #include <mm/as.h>35 #include <arch.h>36 #include <print.h>37 #include <symtab.h>38 39 40 static phte_t *phte;41 30 42 31 … … 48 37 void tlb_arch_init(void) 49 38 { 50 phte_t *physical_phte = (phte_t *) PFN2ADDR(frame_alloc(PHT_ORDER, FRAME_KA | FRAME_PANIC));51 phte =(phte_t *) PA2KA((__address) physical_phte);52 53 ASSERT((__address) physical_phte % (1 << PHT_BITS) == 0);54 55 memsetb((__address) phte, 1 << PHT_BITS, 0);56 57 39 asm volatile ( 58 "mtsdr1 %0\n" 59 : 60 : "r" ((__address) physical_phte) 40 "tlbia\n" 61 41 ); 62 }63 64 65 /** Try to find PTE for faulting address66 *67 * Try to find PTE for faulting address.68 * The AS->lock must be held on entry to this function.69 *70 * @param badvaddr Faulting virtual address.71 * @param istate Pointer to interrupted state.72 * @param pfrc Pointer to variable where as_page_fault() return code will be stored.73 * @return PTE on success, NULL otherwise.74 *75 */76 static pte_t *find_mapping_and_check(__address badvaddr, istate_t *istate, int *pfcr)77 {78 /*79 * Check if the mapping exists in page tables.80 */81 pte_t *pte = page_mapping_find(AS, badvaddr);82 if ((pte) && (pte->p)) {83 /*84 * Mapping found in page tables.85 * Immediately succeed.86 */87 return pte;88 } else {89 int rc;90 91 /*92 * Mapping not found in page tables.93 * Resort to higher-level page fault handler.94 */95 page_table_unlock(AS, true);96 switch (rc = as_page_fault(badvaddr, istate)) {97 case AS_PF_OK:98 /*99 * The higher-level page fault handler succeeded,100 * The mapping ought to be in place.101 */102 page_table_lock(AS, true);103 pte = page_mapping_find(AS, badvaddr);104 ASSERT((pte) && (pte->p));105 return pte;106 break;107 case AS_PF_DEFER:108 page_table_lock(AS, true);109 *pfcr = rc;110 return NULL;111 break;112 case AS_PF_FAULT:113 page_table_lock(AS, true);114 printf("Page fault.\n");115 *pfcr = rc;116 return NULL;117 break;118 default:119 panic("unexpected rc (%d)\n", rc);120 break;121 }122 }123 }124 125 126 static void pht_refill_fail(__address badvaddr, istate_t *istate)127 {128 char *symbol = "";129 char *sym2 = "";130 131 char *s = get_symtab_entry(istate->pc);132 if (s)133 symbol = s;134 s = get_symtab_entry(istate->lr);135 if (s)136 sym2 = s;137 panic("%p: PHT Refill Exception at %p (%s<-%s)\n", badvaddr, istate->pc, symbol, sym2);138 }139 140 141 /** Process Instruction/Data Storage Interrupt142 *143 * @param data True if Data Storage Interrupt.144 * @param istate Interrupted register context.145 *146 */147 void pht_refill(bool data, istate_t *istate)148 {149 asid_t asid;150 __address badvaddr;151 pte_t *pte;152 __u32 page;153 __u32 api;154 __u32 vsid;155 __u32 hash;156 __u32 i;157 int pfcr;158 159 if (data) {160 asm volatile (161 "mfdar %0\n"162 : "=r" (badvaddr)163 );164 } else165 badvaddr = istate->pc;166 167 spinlock_lock(&AS->lock);168 asid = AS->asid;169 spinlock_unlock(&AS->lock);170 171 page_table_lock(AS, true);172 173 pte = find_mapping_and_check(badvaddr, istate, &pfcr);174 if (!pte) {175 switch (pfcr) {176 case AS_PF_FAULT:177 goto fail;178 break;179 case AS_PF_DEFER:180 /*181 * The page fault came during copy_from_uspace()182 * or copy_to_uspace().183 */184 page_table_unlock(AS, true);185 return;186 default:187 panic("Unexpected pfrc (%d)\n", pfcr);188 break;189 }190 }191 192 /* Record access to PTE */193 pte->a = 1;194 195 page = (badvaddr >> 12) & 0xffff;196 api = (badvaddr >> 22) & 0x3f;197 asm volatile (198 "mfsrin %0, %1\n"199 : "=r" (vsid)200 : "r" (badvaddr)201 );202 203 /* Primary hash (xor) */204 hash = ((vsid ^ page) & 0x3ff) << 3;205 206 /* Find invalid PTE in PTEG */207 for (i = 0; i < 8; i++) {208 if (!phte[hash + i].v)209 break;210 }211 212 // TODO: Check access/change bits, secondary hash213 214 if (i == 8)215 i = page % 8;216 217 phte[hash + i].v = 1;218 phte[hash + i].vsid = vsid;219 phte[hash + i].h = 0;220 phte[hash + i].api = api;221 phte[hash + i].rpn = pte->pfn;222 phte[hash + i].r = 0;223 phte[hash + i].c = 0;224 phte[hash + i].pp = 2; // FIXME225 226 page_table_unlock(AS, true);227 return;228 229 fail:230 page_table_unlock(AS, true);231 pht_refill_fail(badvaddr, istate);232 42 } 233 43 … … 235 45 void tlb_invalidate_all(void) 236 46 { 237 ipl_t ipl;238 239 ipl = interrupts_disable();240 memsetb((__address) phte, 1 << PHT_BITS, 0);241 interrupts_restore(ipl);242 47 } 243 48
Note:
See TracChangeset
for help on using the changeset viewer.