📄 pte121.c
字号:
/* use 1:1 mapping */ vsid = VSID121(start); }#ifdef DEBUG PRINTF("Mapping %i (0x%x) pages at 0x%08x for VSID 0x%08x\n", (unsigned)numPages, (unsigned)numPages, (unsigned)start, (unsigned)vsid);#endif /* map in two passes. During the first pass, we try * to claim entries as needed. The 'slotFor()' routine * will 'mark' the claimed entries without 'valid'ating * them. * If the mapping fails, all claimed entries are unmarked * and we return the PI for which allocation failed. * * Once we know that the allocation would succeed, we * do a second pass; during the second pass, the PTE * is actually written. * */ for (pass=0; pass<2; pass++) { /* check if we would succeed during the first pass */ for (i=0, pi=PI121(start); i<numPages; i++,pi++) { /* leave alone existing mappings for this EA */ if (!alreadyMapped(pt, vsid, pi)) { if (!(pte=slotFor(pt, vsid, pi))) { /* no free slot found for page index 'pi' */ unmarkAll(pt); return pi; } else { /* have a free slot; marked by slotFor() */ if (pass) { /* second pass; do the real work */ pte->vsid=vsid; /* H was set by slotFor() */ pte->api =API(pi); /* set up 1:1 mapping */ pte->rpn =((((unsigned long)vsid)&((1<<(LD_PHYS_SIZE-LD_SEG_SIZE))-1))<<LD_PI_SIZE) | pi; pte->wimg=attributes & 0xf; pte->pp=protection&0x3; /* mark it valid */ pte->v=1; pte->marked=0;#ifdef DEBUG /* add paranoia */ assert(alreadyMapped(pt, vsid, pi) == pte);#endif } } } } unmarkAll(pt); }#ifdef DEBUG { unsigned long failedat; CONSCHECK(-1); /* double check that the requested range is mapped */ failedat=triv121IsRangeMapped(start, start + (1<<LD_PG_SIZE)*numPages); if (0x0C0C != failedat) { PRINTF("triv121 mapping failed at 0x%08x\n",(unsigned)failedat); return PI121(failedat); } }#endif return TRIV121_MAP_SUCCESS; /* -1 !! */}unsigned longtriv121PgTblSDR1(Triv121PgTbl pt){ return (((unsigned long)pt->base) & ~(LD_MIN_PT_SIZE-1)) | ( ((pt->size-1) >> LD_MIN_PT_SIZE) & ((1<<(LD_HASH_SIZE-(LD_MIN_PT_SIZE-LD_PTEG_SIZE)))-1) );}voidtriv121PgTblActivate(Triv121PgTbl pt){#ifndef DEBUG_MAINunsigned long sdr1=triv121PgTblSDR1(pt);#endif pt->active=1;#ifndef DEBUG_MAIN#ifdef DEBUG_EXC /* install our exception handler */ ohdl=globalExceptHdl; globalExceptHdl=myhdl; __asm__ __volatile__ ("sync");#endif /* This section of assembly code takes care of the * following: * - get MSR and switch interrupts + MMU off * * - load up the segment registers with a * 1:1 effective <-> virtual mapping; * give user & supervisor keys * * - flush all TLBs; * NOTE: the TLB flushing code is probably * CPU dependent! * * - setup SDR1 * * - restore original MSR */ __asm__ __volatile( " mtctr %0\n" /* Get MSR and switch interrupts off - just in case. * Also switch the MMU off; the book * says that SDR1 must not be changed with either * MSR_IR or MSR_DR set. I would guess that it could * be safe as long as the IBAT & DBAT mappings override * the page table... */ " mfmsr %0\n" " andc %6, %0, %6\n" " mtmsr %6\n" " isync \n" /* set up the segment registers */ " li %6, 0\n" "1: mtsrin %1, %6\n" " addis %6, %6, 0x1000\n" /* address next SR */ " addi %1, %1, 1\n" /* increment VSID */ " bdnz 1b\n" /* Now flush all TLBs, starting with the topmost index */ " lis %6, %2@h\n" "2: addic. %6, %6, -%3\n" /* address the next one (decrementing) */ " tlbie %6\n" /* invalidate & repeat */ " bgt 2b\n" " tlbsync\n" " sync\n" /* set up SDR1 */ " mtspr %4, %5\n" /* restore original MSR */ " mtmsr %0\n" " isync \n" ::"r"(16), "b"(KEY_USR | KEY_SUP), "i"(FLUSH_EA_RANGE), "i"(1<<LD_PG_SIZE), "i"(SDR1), "r"(sdr1), "b"(MSR_EE | MSR_IR | MSR_DR) : "ctr","cc"); /* At this point, BAT0 is probably still active; it's the * caller's job to deactivate it... */#endif}/************************** DEBUGGING ROUTINES *************************//* Exception handler to catch page faults */#ifdef DEBUG_EXC#define BAT_VALID_BOTH 3 /* allow user + super access */static voidmyhdl(BSP_Exception_frame* excPtr){if (3==excPtr->_EXC_number) { unsigned long dsisr; /* reactivate DBAT0 and read DSISR */ __asm__ __volatile__( "mfspr %0, %1\n" "ori %0,%0,3\n" "mtspr %1, %0\n" "sync\n" "mfspr %0, %2\n" :"=r"(dsisr) :"i"(DBAT0U),"i"(DSISR),"i"(BAT_VALID_BOTH) ); printk("Data Access Exception (DSI) # 3\n"); printk("Reactivated DBAT0 mapping\n"); printk("DSISR 0x%08x\n",dsisr); printk("revectoring to prevent default handler panic().\n"); printk("NOTE: exception number %i below is BOGUS\n", ASM_DEC_VECTOR); /* make this exception 'recoverable' for * the default handler by faking a decrementer * exception. * Note that the default handler's message will be * wrong about the exception number. */ excPtr->_EXC_number = ASM_DEC_VECTOR;}/* now call the original handler */((void(*)())ohdl)(excPtr);}#endif#ifdef DEBUG/* test the consistency of the page table * * 'pass' is merely a number which will be printed * by this routine, so the caller may give some * context information. * * 'expected' is the number of valid (plus 'marked') * entries the caller believes the page table should * have. This routine complains if its count differs. * * It basically verifies that the topmost 20bits * of all VSIDs as well as the unused bits are all * zero. Then it counts all valid and all 'marked' * entries, adding them up and comparing them to the * 'expected' number of occupied slots. * * RETURNS: total number of valid plus 'marked' slots. */unsigned longtriv121PgTblConsistency(Triv121PgTbl pt, int pass, int expected){PTE pte;int i;unsigned v,m;int warn=0;static int maxw=20; /* mute after detecting this many errors */ PRINTF("Checking page table at 0x%08x (size %i==0x%x)\n", (unsigned)pt->base, (unsigned)pt->size, (unsigned)pt->size); if (!pt->base || !pt->size) { PRINTF("Uninitialized Page Table!\n"); return 0; } v=m=0;#if 1 /* 10/9/2002: I had machine checks crashing after this loop * terminated. Maybe caused by speculative loads * from beyond the valid memory area (since the * page hash table sits at the top of physical * memory). * Very bizarre - the other loops in this file * seem to be fine. Maybe there is a compiler bug?? * For the moment, I let the loop run backwards... * * Also see the comment a couple of lines down. */ for (i=pt->size/sizeof(PTERec)-1, pte=pt->base + i; i>=0; i--,pte--)#else for (i=0, pte=pt->base; i<pt->size/sizeof(PTERec); i++,pte++)#endif { int err=0; char buf[500]; unsigned long *lp=(unsigned long*)pte;#if 0 /* If I put this bogus while statement here (the body is * never reached), the original loop works OK */ while (pte >= pt->base + pt->size/sizeof(PTERec)) /* never reached */;#endif if ( (*lp & (0xfffff0<<7)) || *(lp+1) & 0xe00 || (pte->v && pte->marked)) { /* check for vsid (without segment bits) == 0, unused bits == 0, valid && marked */ sprintf(buf,"invalid VSID , unused bits or v && m"); err=1; } else { if (pte->v) v++; if (pte->marked) m++; } if (err && maxw) { PRINTF("Pass %i -- strange PTE at 0x%08x found for page index %i == 0x%08x:\n", pass,(unsigned)pte,i,i); PRINTF("Reason: %s\n",buf); dumpPte(pte); warn++; maxw--; } } if (warn) { PRINTF("%i errors found; currently %i entries marked, %i are valid\n", warn, m, v); } v+=m; if (maxw && expected>=0 && expected != v) { /* number of occupied slots not what they expected */ PRINTF("Wrong # of occupied slots detected during pass"); PRINTF("%i; should be %i (0x%x) is %i (0x%x)\n", pass, expected, (unsigned)expected, v, (unsigned)v); maxw--; } return v;}/* Find the PTE for a EA and print its contents * RETURNS: pte for EA or NULL if no entry was found. */PTEtriv121DumpPte(unsigned long ea){PTE pte; pte=alreadyMapped(&pgTbl,TRIV121_121_VSID,ea); if (pte) dumpPte(pte); return pte;}/* Dump an entire PTEG */static voiddumpPteg(unsigned long vsid, unsigned long pi, unsigned long hash){PTE pte=ptegOf(&pgTbl,hash);int i; PRINTF("hash 0x%08x, pteg 0x%08x (vsid 0x%08x, pi 0x%08x)\n", (unsigned)hash, (unsigned)pte, (unsigned)vsid, (unsigned)pi); for (i=0; i<PTE_PER_PTEG; i++,pte++) { PRINTF("pte 0x%08x is 0x%08x : 0x%08x\n", (unsigned)pte, (unsigned)*(unsigned long*)pte, (unsigned)*(((unsigned long*)pte)+1)); }} /* Verify that a range of EAs is mapped the page table * * RETURNS: address of the first page for which no * PTE was found (i.e. page index * page size) * * ON SUCCESS, the special value 0x0C0C ("OKOK") * [which is not page aligned and hence is not * a valid page address]. */unsigned longtriv121IsRangeMapped(unsigned long start, unsigned long end){ start&=~((1<<LD_PG_SIZE)-1); while (start < end) { if (!alreadyMapped(&pgTbl,TRIV121_121_VSID,start)) return start; start+=1<<LD_PG_SIZE; } return 0x0C0C; /* OKOK - not on a page boundary */}#endif#if defined(DEBUG_MAIN) || defined(DEBUG)#include <stdlib.h>/* print a PTE */static voiddumpPte(PTE pte){ if (0==((unsigned long)pte & ((1<<LD_PTEG_SIZE)-1))) PRINTF("PTEG--"); else PRINTF("......"); if (pte->v) { PRINTF("VSID: 0x%08x H:%1i API: 0x%02x\n", pte->vsid, pte->h, pte->api); PRINTF(" "); PRINTF("RPN: 0x%08x WIMG: 0x%1x, (m %1i), pp: 0x%1x\n", pte->rpn, pte->wimg, pte->marked, pte->pp); } else { PRINTF("xxxxxx\n"); PRINTF(" "); PRINTF("xxxxxx\n"); }}/* dump page table entries from index 'from' to 'to' * The special values (unsigned)-1 are allowed which * cause the routine to dump the entire table. * * RETURNS 0 */inttriv121PgTblDump(Triv121PgTbl pt, unsigned from, unsigned to){int i;PTE pte; PRINTF("Dumping PT [size 0x%08x == %i] at 0x%08x\n", (unsigned)pt->size, (unsigned)pt->size, (unsigned)pt->base); if (from> pt->size>>LD_PTE_SIZE) from=0; if (to > pt->size>>LD_PTE_SIZE) to=(pt->size>>LD_PTE_SIZE); for (i=from,pte=pt->base+from; i<(long)to; i++, pte++) { dumpPte(pte); } return 0;}#if defined(DEBUG_MAIN)#define LD_DBG_PT_SIZE LD_MIN_PT_SIZEintmain(int argc, char **argv){unsigned long base,start,numPages;unsigned long size=1<<LD_DBG_PT_SIZE;Triv121PgTbl pt; base=(unsigned long)malloc(size<<1); assert(base); /* align pt */ base += size-1; base &= ~(size-1); assert(pt=triv121PgTblInit(base,LD_DBG_PT_SIZE)); triv121PgTblDump(pt,(unsigned)-1, (unsigned)-1); do { do { PRINTF("Start Address:"); fflush(stdout); } while (1!=scanf("%i",&start)); do { PRINTF("# pages:"); fflush(stdout); } while (1!=scanf("%i",&numPages)); } while (TRIV121_MAP_SUCCESS==triv121PgTblMap(pt,TRIV121_121_VSID,start,numPages, TRIV121_ATTR_IO_PAGE,2) && 0==triv121PgTblDump(pt,(unsigned)-1,(unsigned)-1));}#endif#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -