Changeset eef1b031 in mainline


Ignore:
Timestamp:
2011-05-23T15:51:46Z (13 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
b372015
Parents:
366b148
Message:

ppc32: page hash table should be no longer interpreted as a TLB, it is really closer to the TSB on sparc64
this fixes ticket #344 for ppc32

Location:
kernel
Files:
2 added
7 edited

Legend:

Unmodified
Added
Removed
  • kernel/arch/ppc32/Makefile.inc

    r366b148 reef1b031  
    5555        arch/$(KARCH)/src/mm/frame.c \
    5656        arch/$(KARCH)/src/mm/page.c \
     57        arch/$(KARCH)/src/mm/pht.c \
    5758        arch/$(KARCH)/src/mm/tlb.c \
    5859        arch/$(KARCH)/src/drivers/pic.c
  • kernel/arch/ppc32/include/mm/as.h

    r366b148 reef1b031  
    3636#define KERN_ppc32_AS_H_
    3737
     38#include <arch/mm/pht.h>
     39
    3840#define KERNEL_ADDRESS_SPACE_SHADOWED_ARCH  0
    3941
     
    5254#define as_create_arch(as, flags)       (as != as)
    5355#define as_deinstall_arch(as)
    54 #define as_invalidate_translation_cache(as, page, cnt)
     56
     57#define as_invalidate_translation_cache(as, page, cnt) \
     58        pht_invalidate((as), (page), (cnt))
    5559
    5660extern void as_arch_init(void);
  • kernel/arch/ppc32/include/mm/tlb.h

    r366b148 reef1b031  
    3737
    3838#include <arch/interrupt.h>
    39 #include <typedefs.h>
    4039
    4140#define WIMG_GUARDED    0x01
     
    7574} ptelo_t;
    7675
    77 extern void pht_init(void);
    78 extern void pht_refill(unsigned int, istate_t *);
    7976extern void tlb_refill(unsigned int, istate_t *);
    8077
  • kernel/arch/ppc32/src/interrupt.c

    r366b148 reef1b031  
    4242#include <arch/drivers/pic.h>
    4343#include <arch/mm/tlb.h>
     44#include <arch/mm/pht.h>
    4445#include <print.h>
    4546
  • kernel/arch/ppc32/src/mm/tlb.c

    r366b148 reef1b031  
    3333 */
    3434
    35 #include <mm/tlb.h>
    3635#include <arch/mm/tlb.h>
    37 #include <arch/interrupt.h>
    3836#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>
    23238
    23339void tlb_refill(unsigned int n, istate_t *istate)
     
    295101void tlb_invalidate_asid(asid_t asid)
    296102{
    297         uint32_t sdr1 = sdr1_get();
    298        
    299         // FIXME: compute size of PHT exactly
    300         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        
    309103        tlb_invalidate_all();
    310104}
     
    312106void tlb_invalidate_pages(asid_t asid, uintptr_t page, size_t cnt)
    313107{
    314         // TODO
    315108        tlb_invalidate_all();
    316109}
  • kernel/generic/include/mm/tlb.h

    r366b148 reef1b031  
    8686extern void tlb_invalidate_asid(asid_t);
    8787extern void tlb_invalidate_pages(asid_t, uintptr_t, size_t);
     88
    8889#endif
    8990
  • kernel/generic/src/mm/as.c

    r366b148 reef1b031  
    675675               
    676676                /*
    677                  * Invalidate software translation caches (e.g. TSB on sparc64).
     677                 * Invalidate software translation caches
     678                 * (e.g. TSB on sparc64, PHT on ppc32).
    678679                 */
    679680                as_invalidate_translation_cache(as, area->base + P2SZ(pages),
     
    823824       
    824825        /*
    825          * Invalidate potential software translation caches (e.g. TSB on
    826          * sparc64).
     826         * Invalidate potential software translation caches
     827         * (e.g. TSB on sparc64, PHT on ppc32).
    827828         */
    828829        as_invalidate_translation_cache(as, area->base, area->pages);
     
    11261127       
    11271128        /*
    1128          * Invalidate potential software translation caches (e.g. TSB on
    1129          * sparc64).
     1129         * Invalidate potential software translation caches
     1130         * (e.g. TSB on sparc64, PHT on ppc32).
    11301131         */
    11311132        as_invalidate_translation_cache(as, area->base, area->pages);
Note: See TracChangeset for help on using the changeset viewer.