Changeset 10e0cee in mainline for arch/ppc32/src/mm/tlb.c


Ignore:
Timestamp:
2006-06-18T00:31:14Z (19 years ago)
Author:
Martin Decky <martin@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
1bb2e7a
Parents:
8e3bf3e2
Message:

ppc32: BAT-less memory mapping (broken yet)
VSID support (broken yet)
boot API change
cleanup

File:
1 edited

Legend:

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

    r8e3bf3e2 r10e0cee  
    2727 */
    2828
    29  /** @addtogroup ppc32mm       
     29/** @addtogroup ppc32mm
    3030 * @{
    3131 */
     
    3434
    3535#include <mm/tlb.h>
    36 
    37 
    38 /** Initialize Page Hash Table.
    39  *
    40  * Setup the Page Hash Table with no entries.
    41  *
    42  */
     36#include <arch/mm/tlb.h>
     37#include <arch/interrupt.h>
     38#include <mm/as.h>
     39#include <arch.h>
     40#include <print.h>
     41#include <symtab.h>
     42
     43
     44/** Try to find PTE for faulting address
     45 *
     46 * Try to find PTE for faulting address.
     47 * The as->lock must be held on entry to this function
     48 * if lock is true.
     49 *
     50 * @param as       Address space.
     51 * @param lock     Lock/unlock the address space.
     52 * @param badvaddr Faulting virtual address.
     53 * @param access   Access mode that caused the fault.
     54 * @param istate   Pointer to interrupted state.
     55 * @param pfrc     Pointer to variable where as_page_fault() return code will be stored.
     56 * @return         PTE on success, NULL otherwise.
     57 *
     58 */
     59static pte_t *find_mapping_and_check(as_t *as, bool lock, __address badvaddr, int access, istate_t *istate, int *pfrc)
     60{
     61        /*
     62         * Check if the mapping exists in page tables.
     63         */     
     64        pte_t *pte = page_mapping_find(as, badvaddr);
     65        if ((pte) && (pte->p)) {
     66                /*
     67                 * Mapping found in page tables.
     68                 * Immediately succeed.
     69                 */
     70                return pte;
     71        } else {
     72                int rc;
     73       
     74                /*
     75                 * Mapping not found in page tables.
     76                 * Resort to higher-level page fault handler.
     77                 */
     78                page_table_unlock(as, lock);
     79                switch (rc = as_page_fault(badvaddr, access, istate)) {
     80                        case AS_PF_OK:
     81                                /*
     82                                 * The higher-level page fault handler succeeded,
     83                                 * The mapping ought to be in place.
     84                                 */
     85                                page_table_lock(as, lock);
     86                                pte = page_mapping_find(as, badvaddr);
     87                                ASSERT((pte) && (pte->p));
     88                                return pte;
     89                        case AS_PF_DEFER:
     90                                page_table_lock(as, lock);
     91                                *pfrc = rc;
     92                                return NULL;
     93                        case AS_PF_FAULT:
     94                                page_table_lock(as, lock);
     95                                printf("Page fault.\n");
     96                                *pfrc = rc;
     97                                return NULL;
     98                        default:
     99                                panic("unexpected rc (%d)\n", rc);
     100                }       
     101        }
     102}
     103
     104
     105static void pht_refill_fail(__address badvaddr, istate_t *istate)
     106{
     107        char *symbol = "";
     108        char *sym2 = "";
     109
     110        char *s = get_symtab_entry(istate->pc);
     111        if (s)
     112                symbol = s;
     113        s = get_symtab_entry(istate->lr);
     114        if (s)
     115                sym2 = s;
     116        panic("%p: PHT Refill Exception at %p (%s<-%s)\n", badvaddr, istate->pc, symbol, sym2);
     117}
     118
     119
     120static void pht_insert(const __address vaddr, const pfn_t pfn)
     121{
     122        __u32 page = (vaddr >> 12) & 0xffff;
     123        __u32 api = (vaddr >> 22) & 0x3f;
     124       
     125        __u32 vsid;
     126        asm volatile (
     127                "mfsrin %0, %1\n"
     128                : "=r" (vsid)
     129                : "r" (vaddr)
     130        );
     131       
     132        __u32 sdr1;
     133        asm volatile (
     134                "mfsdr1 %0\n"
     135                : "=r" (sdr1)
     136        );
     137        phte_t *phte = (phte_t *) PA2KA(sdr1 & 0xffff0000);
     138       
     139        /* Primary hash (xor) */
     140        __u32 h = 0;
     141        __u32 hash = vsid ^ page;
     142        __u32 base = (hash & 0x3ff) << 3;
     143        __u32 i;
     144        bool found = false;
     145       
     146        /* Find unused or colliding
     147           PTE in PTEG */
     148        for (i = 0; i < 8; i++) {
     149                if ((!phte[base + i].v) || ((phte[base + i].vsid == vsid) && (phte[base + i].api == api))) {
     150                        found = true;
     151                        break;
     152                }
     153        }
     154       
     155        if (!found) {
     156                /* Secondary hash (not) */
     157                __u32 base2 = (~hash & 0x3ff) << 3;
     158               
     159                /* Find unused or colliding
     160                   PTE in PTEG */
     161                for (i = 0; i < 8; i++) {
     162                        if ((!phte[base2 + i].v) || ((phte[base2 + i].vsid == vsid) && (phte[base2 + i].api == api))) {
     163                                found = true;
     164                                base = base2;
     165                                h = 1;
     166                                break;
     167                        }
     168                }
     169               
     170                if (!found) {
     171                        // TODO: A/C precedence groups
     172                        i = page % 8;
     173                }
     174        }
     175       
     176        phte[base + i].v = 1;
     177        phte[base + i].vsid = vsid;
     178        phte[base + i].h = h;
     179        phte[base + i].api = api;
     180        phte[base + i].rpn = pfn;
     181        phte[base + i].r = 0;
     182        phte[base + i].c = 0;
     183        phte[base + i].pp = 2; // FIXME
     184}
     185
     186
     187static void pht_real_insert(const __address vaddr, const pfn_t pfn)
     188{
     189        __u32 page = (vaddr >> 12) & 0xffff;
     190        __u32 api = (vaddr >> 22) & 0x3f;
     191       
     192        __u32 vsid;
     193        asm volatile (
     194                "mfsrin %0, %1\n"
     195                : "=r" (vsid)
     196                : "r" (vaddr)
     197        );
     198       
     199        __u32 sdr1;
     200        asm volatile (
     201                "mfsdr1 %0\n"
     202                : "=r" (sdr1)
     203        );
     204        phte_t *phte_physical = (phte_t *) (sdr1 & 0xffff0000);
     205       
     206        /* Primary hash (xor) */
     207        __u32 h = 0;
     208        __u32 hash = vsid ^ page;
     209        __u32 base = (hash & 0x3ff) << 3;
     210        __u32 i;
     211        bool found = false;
     212       
     213        /* Find unused or colliding
     214           PTE in PTEG */
     215        for (i = 0; i < 8; i++) {
     216                if ((!phte_physical[base + i].v) || ((phte_physical[base + i].vsid == vsid) && (phte_physical[base + i].api == api))) {
     217                        found = true;
     218                        break;
     219                }
     220        }
     221       
     222        if (!found) {
     223                /* Secondary hash (not) */
     224                __u32 base2 = (~hash & 0x3ff) << 3;
     225               
     226                /* Find unused or colliding
     227                   PTE in PTEG */
     228                for (i = 0; i < 8; i++) {
     229                        if ((!phte_physical[base2 + i].v) || ((phte_physical[base2 + i].vsid == vsid) && (phte_physical[base2 + i].api == api))) {
     230                                found = true;
     231                                base = base2;
     232                                h = 1;
     233                                break;
     234                        }
     235                }
     236               
     237                if (!found) {
     238                        // TODO: A/C precedence groups
     239                        i = page % 8;
     240                }
     241        }
     242       
     243        phte_physical[base + i].v = 1;
     244        phte_physical[base + i].vsid = vsid;
     245        phte_physical[base + i].h = h;
     246        phte_physical[base + i].api = api;
     247        phte_physical[base + i].rpn = pfn;
     248        phte_physical[base + i].r = 0;
     249        phte_physical[base + i].c = 0;
     250        phte_physical[base + i].pp = 2; // FIXME
     251}
     252
     253
     254/** Process Instruction/Data Storage Interrupt
     255 *
     256 * @param n Interrupt vector number.
     257 * @param istate Interrupted register context.
     258 *
     259 */
     260void pht_refill(int n, istate_t *istate)
     261{
     262        __address badvaddr;
     263        pte_t *pte;
     264        int pfrc;
     265        as_t *as;
     266        bool lock;
     267       
     268        if (AS == NULL) {
     269                as = AS_KERNEL;
     270                lock = false;
     271        } else {
     272                as = AS;
     273                lock = true;
     274        }
     275       
     276        if (n == VECTOR_DATA_STORAGE) {
     277                asm volatile (
     278                        "mfdar %0\n"
     279                        : "=r" (badvaddr)
     280                );
     281        } else
     282                badvaddr = istate->pc;
     283               
     284        page_table_lock(as, lock);
     285       
     286        pte = find_mapping_and_check(as, lock, badvaddr, PF_ACCESS_READ /* FIXME */, istate, &pfrc);
     287        if (!pte) {
     288                switch (pfrc) {
     289                        case AS_PF_FAULT:
     290                                goto fail;
     291                                break;
     292                        case AS_PF_DEFER:
     293                                /*
     294                                 * The page fault came during copy_from_uspace()
     295                                 * or copy_to_uspace().
     296                                 */
     297                                page_table_unlock(as, lock);
     298                                return;
     299                        default:
     300                                panic("Unexpected pfrc (%d)\n", pfrc);
     301                }
     302        }
     303       
     304        pte->a = 1; /* Record access to PTE */
     305        pht_insert(badvaddr, pte->pfn);
     306       
     307        page_table_unlock(as, lock);
     308        return;
     309       
     310fail:
     311        page_table_unlock(as, lock);
     312        pht_refill_fail(badvaddr, istate);
     313}
     314
     315
     316/** Process Instruction/Data Storage Interrupt in Real Mode
     317 *
     318 * @param n Interrupt vector number.
     319 * @param istate Interrupted register context.
     320 *
     321 */
     322bool pht_real_refill(int n, istate_t *istate)
     323{
     324        __address badvaddr;
     325       
     326        if (n == VECTOR_DATA_STORAGE) {
     327                asm volatile (
     328                        "mfdar %0\n"
     329                        : "=r" (badvaddr)
     330                );
     331        } else
     332                badvaddr = istate->pc;
     333       
     334        __u32 physmem;
     335        asm volatile (
     336                "mfsprg3 %0\n"
     337                : "=r" (physmem)
     338        );
     339       
     340        if ((badvaddr >= PA2KA(0)) && (badvaddr < PA2KA(physmem))) {
     341                pht_real_insert(badvaddr, KA2PA(badvaddr) >> 12);
     342                return true;
     343        }
     344       
     345        return false;
     346}
     347
     348
    43349void tlb_arch_init(void)
    44350{
     
    56362
    57363
    58 /** Invalidate all entries in TLB that belong to specified address space.
    59  *
    60  * @param asid This parameter is ignored as the architecture doesn't support it.
    61  */
    62364void tlb_invalidate_asid(asid_t asid)
    63365{
     366        // TODO
    64367        tlb_invalidate_all();
    65368}
    66369
    67 /** Invalidate TLB entries for specified page range belonging to specified address space.
    68  *
    69  * @param asid This parameter is ignored as the architecture doesn't support it.
    70  * @param page Address of the first page whose entry is to be invalidated.
    71  * @param cnt Number of entries to invalidate.
    72  */
     370
    73371void tlb_invalidate_pages(asid_t asid, __address page, count_t cnt)
    74372{
     373        // TODO
    75374        tlb_invalidate_all();
    76375}
    77376
    78377
    79 
    80 /** Print contents of Page Hash Table. */
    81378void tlb_print(void)
    82379{
    83 }
    84 
    85  /** @}
    86  */
    87 
     380        // TODO
     381}
     382
     383/** @}
     384 */
Note: See TracChangeset for help on using the changeset viewer.