Changeset 35f3b8c in mainline for arch/ppc32/src/mm/tlb.c


Ignore:
Timestamp:
2006-05-18T23:24:40Z (19 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
c0bc189
Parents:
8424198
Message:

ppc32 work
update framebuffer
get rid of the BAT memory mapping (not finished yet)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • arch/ppc32/src/mm/tlb.c

    r8424198 r35f3b8c  
    2727 */
    2828
    29 #include <arch/mm/tlb.h>
    30 #include <arch/types.h>
    3129#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;
    4130
    4231
     
    4837void tlb_arch_init(void)
    4938{
    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        
    5739        asm volatile (
    58                 "mtsdr1 %0\n"
    59                 :
    60                 : "r" ((__address) physical_phte)
     40                "tlbia\n"
    6141        );
    62 }
    63 
    64 
    65 /** Try to find PTE for faulting address
    66  *
    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 Interrupt
    142  *
    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         } else
    165                 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 hash
    213        
    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; // FIXME
    225        
    226         page_table_unlock(AS, true);
    227         return;
    228        
    229 fail:
    230         page_table_unlock(AS, true);
    231         pht_refill_fail(badvaddr, istate);
    23242}
    23343
     
    23545void tlb_invalidate_all(void)
    23646{
    237         ipl_t ipl;
    238 
    239         ipl = interrupts_disable();
    240         memsetb((__address) phte, 1 << PHT_BITS, 0);
    241         interrupts_restore(ipl);
    24247}
    24348
Note: See TracChangeset for help on using the changeset viewer.