Changeset 35f3b8c in mainline for arch/ppc32/src/mm/page.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/page.c

    r8424198 r35f3b8c  
    3030#include <genarch/mm/page_pt.h>
    3131#include <arch/mm/frame.h>
     32#include <arch/asm.h>
    3233#include <mm/frame.h>
    3334#include <mm/page.h>
     35#include <mm/as.h>
     36#include <arch.h>
    3437#include <arch/types.h>
     38#include <arch/exception.h>
     39#include <config.h>
     40#include <print.h>
     41#include <symtab.h>
     42
     43static 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 */
     57static 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
     103static 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
     117static 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 */
     161void 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       
     208fail:
     209        page_table_unlock(AS, true);
     210        pht_refill_fail(badvaddr, istate);
     211}
     212
     213
     214void 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
    35228
    36229void page_arch_init(void)
    37230{
    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.