summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libcpu/powerpc
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-03-26 06:18:51 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-03-26 10:40:48 +0200
commit11fe8c59c6c145bca52e977363183add0fbe1b59 (patch)
treeaa9810f50d832df7cd5af8befd9acc05e430fb14 /c/src/lib/libcpu/powerpc
parentbsp/tqm8xx: Move libcpu content to bsps (diff)
downloadrtems-11fe8c59c6c145bca52e977363183add0fbe1b59.tar.bz2
bsps/powerpc: Move MMU support to bsps
This patch is a part of the BSP source reorganization. Update #3285.
Diffstat (limited to 'c/src/lib/libcpu/powerpc')
-rw-r--r--c/src/lib/libcpu/powerpc/Makefile.am16
-rw-r--r--c/src/lib/libcpu/powerpc/e500/mmu/mmu.c631
-rw-r--r--c/src/lib/libcpu/powerpc/mpc6xx/mmu/bat.c545
-rw-r--r--c/src/lib/libcpu/powerpc/mpc6xx/mmu/mmuAsm.S530
-rw-r--r--c/src/lib/libcpu/powerpc/mpc6xx/mmu/pte121.c1139
5 files changed, 0 insertions, 2861 deletions
diff --git a/c/src/lib/libcpu/powerpc/Makefile.am b/c/src/lib/libcpu/powerpc/Makefile.am
index 5f5813d350..f61524f496 100644
--- a/c/src/lib/libcpu/powerpc/Makefile.am
+++ b/c/src/lib/libcpu/powerpc/Makefile.am
@@ -41,14 +41,6 @@ endif # ppc405
if mpc6xx
-# mpc6xx/mmu
-noinst_PROGRAMS += mpc6xx/mmu.rel
-mpc6xx_mmu_rel_SOURCES = mpc6xx/mmu/bat.c mpc6xx/mmu/bat.h \
- mpc6xx/mmu/pte121.c mpc6xx/mmu/pte121.h \
- mpc6xx/mmu/mmuAsm.S
-mpc6xx_mmu_rel_CPPFLAGS = $(AM_CPPFLAGS)
-mpc6xx_mmu_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
-
# mpc6xx/clock
noinst_PROGRAMS += mpc6xx/clock.rel
mpc6xx_clock_rel_SOURCES = mpc6xx/clock/c_clock.c mpc6xx/clock/c_clock.h
@@ -71,12 +63,4 @@ e500_clock_rel_CPPFLAGS = $(AM_CPPFLAGS)
e500_clock_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
endif
-# e500/mmu
-if e500_mmu
-noinst_PROGRAMS += e500/mmu.rel
-e500_mmu_rel_SOURCES = e500/mmu/mmu.c e500/mmu/e500_mmu.h
-e500_mmu_rel_CPPFLAGS = $(AM_CPPFLAGS)
-e500_mmu_rel_LDFLAGS = $(RTEMS_RELLDFLAGS)
-endif
-
include $(top_srcdir)/../../../automake/local.am
diff --git a/c/src/lib/libcpu/powerpc/e500/mmu/mmu.c b/c/src/lib/libcpu/powerpc/e500/mmu/mmu.c
deleted file mode 100644
index 15fe88f91a..0000000000
--- a/c/src/lib/libcpu/powerpc/e500/mmu/mmu.c
+++ /dev/null
@@ -1,631 +0,0 @@
-/*
- * Routines to manipulate e500 TLBs; TLB0 (fixed 4k page size)
- * is not very useful so we mostly focus on TLB1 (variable page size).
- *
- * TLB0's 256 entries are 2-way set associative which means that
- * only 2 entries for page index numbers with matching 7 LSBs
- * are available.
- *
- * E.g., look at EA = 0xAAAyy000. 0xAAAyy is the page index.
- *
- * The least-significant 7 bits in 'yy' determine the 'way'
- * in the TLB 0 array. At most two EAs with matching 'yy' bits
- * (the 7 LSBs, that is) can be mapped with TLB0 since there
- * are only two entries per 'way'.
- *
- * Since this is a real-time OS we want to stay away from
- * software TLB replacement.
- */
-
-/*
- * Authorship
- * ----------
- * This software was created by
- * Till Straumann <strauman@slac.stanford.edu>, 2005-2007,
- * Stanford Linear Accelerator Center, Stanford University.
- *
- * Acknowledgement of sponsorship
- * ------------------------------
- * This software was produced by
- * the Stanford Linear Accelerator Center, Stanford University,
- * under Contract DE-AC03-76SFO0515 with the Department of Energy.
- *
- * Government disclaimer of liability
- * ----------------------------------
- * Neither the United States nor the United States Department of Energy,
- * nor any of their employees, makes any warranty, express or implied, or
- * assumes any legal liability or responsibility for the accuracy,
- * completeness, or usefulness of any data, apparatus, product, or process
- * disclosed, or represents that its use would not infringe privately owned
- * rights.
- *
- * Stanford disclaimer of liability
- * --------------------------------
- * Stanford University makes no representations or warranties, express or
- * implied, nor assumes any liability for the use of this software.
- *
- * Stanford disclaimer of copyright
- * --------------------------------
- * Stanford University, owner of the copyright, hereby disclaims its
- * copyright and all other rights in this software. Hence, anyone may
- * freely use it for any purpose without restriction.
- *
- * Maintenance of notices
- * ----------------------
- * In the interest of clarity regarding the origin and status of this
- * SLAC software, this and all the preceding Stanford University notices
- * are to remain affixed to any copy or derivative of this software made
- * or distributed by the recipient and are to be affixed to any copy of
- * software made or distributed by the recipient that contains a copy or
- * derivative of this software.
- *
- * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
- */
-
-/* 8450 MSR definitions; note that there are *substantial* differences
- * compared to classic powerpc; in particular, IS/DS are *different*
- * from IR/DR; the e500 MMU can not be switched off!
- *
- * Also: To disable/enable all external interrupts, CE and EE must both be
- * controlled.
- */
-#include <rtems.h>
-#include <rtems/bspIo.h>
-#include <inttypes.h>
-#include <stdio.h>
-
-#include <libcpu/e500_mmu.h>
-
-#define TLBIVAX_TLBSEL (1<<(63-60))
-#define TLBIVAX_INV_ALL (1<<(63-61))
-
-#define E500_TLB_ATTR_WIMGE(x) ((x)&0x7f) /* includes user bits */
-#define E500_TLB_ATTR_WIMGE_GET(x) ((x)&0x7f)
-#define E500_TLB_ATTR_TS (1<<7)
-#define E500_TLB_ATTR_PERM(x) (((x)&0x3ff)<<8)
-#define E500_TLB_ATTR_PERM_GET(x) (((x)>>8)&0x3ff)
-#define E500_TLB_ATTR_TID(x) (((x)&0xfff)<<20)
-#define E500_TLB_ATTR_TID_GET(x) (((x)>>20)&0xfff)
-
-
-#ifdef DEBUG
-#define STATIC
-#else
-#define STATIC static
-#endif
-
-/* Factory to generate inline macros for accessing the MAS registers */
-#define __RDWRMAS(mas,rmas) \
- static inline uint32_t _read_MAS##mas(void) \
- { uint32_t x; __asm__ volatile("mfspr %0, %1": "=r"(x):"i"(rmas)); return x; } \
- static inline void _write_MAS##mas(uint32_t x) \
- { __asm__ volatile("mtspr %1, %0":: "r"(x),"i"(rmas)); }
-
-__RDWRMAS(0,FSL_EIS_MAS0)
-__RDWRMAS(1,FSL_EIS_MAS1)
-__RDWRMAS(2,FSL_EIS_MAS2)
-__RDWRMAS(3,FSL_EIS_MAS3)
-__RDWRMAS(4,FSL_EIS_MAS4)
-__RDWRMAS(6,FSL_EIS_MAS6)
-
-#undef __RDWRMAS
-
-static int initialized = 0;
-
-E500_tlb_va_cache_t rtems_e500_tlb_va_cache[16];
-
-/* Since it is likely that these routines are used during
- * early initialization when stdio is not available yet
- * we provide a helper that resorts to 'printk()'
- */
-static void
-myprintf(FILE *f, char *fmt, ...)
-{
- va_list ap;
- va_start(ap, fmt);
-
- if (!f || !_impure_ptr->__sdidinit) {
- /*
- * Might be called at an early stage when
- * stdio is not yet initialized.
- */
- vprintk(fmt,ap);
- } else {
- vfprintf(f,fmt,ap);
- }
- va_end(ap);
-}
-
-
-void
-rtems_e500_dmptlbc(FILE *f)
-{
-int i;
- if ( !initialized ) {
- myprintf(stderr,"TLB cache not initialized\n");
- return;
- }
- for ( i=0; i<16; i++ ) {
- if ( !rtems_e500_tlb_va_cache[i].att.v )
- continue;
- myprintf(f,"#%2i: TID 0x%03x, TS %i, ea 0x%08x .. 0x%08x\n",
- i,
- rtems_e500_tlb_va_cache[i].va.va_tid,
- rtems_e500_tlb_va_cache[i].att.ts,
- rtems_e500_tlb_va_cache[i].va.va_epn<<12,
- (rtems_e500_tlb_va_cache[i].va.va_epn<<12) + (1024<<(2*rtems_e500_tlb_va_cache[i].att.sz))-1);
- myprintf(f,"PA 0x%08"PRIx32", PERM 0x%03x, WIMGE 0x%02x\n",
- rtems_e500_tlb_va_cache[i].rpn<<12,
- rtems_e500_tlb_va_cache[i].att.perm,
- rtems_e500_tlb_va_cache[i].att.wimge);
- }
-}
-
-#define E500_SELTLB_1 0x1000
-
-static void seltlb(rtems_e500_tlb_idx key)
-{
-int idx = key & ~E500_SELTLB_1;
-
- if ( key & E500_SELTLB_1 ) {
- _write_MAS0( FSL_EIS_MAS0_TLBSEL | FSL_EIS_MAS0_ESEL(idx) );
- } else {
- _write_MAS0( (idx & 128) ? FSL_EIS_MAS0_ESEL(1) : FSL_EIS_MAS0_ESEL(0) );
- _write_MAS2( FSL_EIS_MAS2_EPN( idx & 127 ) );
- }
-}
-
-/*
- * Read a TLB entry from the hardware; if it is a TLB1 entry
- * then the current settings are stored in the
- * rtems_e500_tlb_va_cache[] structure.
- *
- * The routine can perform this operation quietly or
- * print information to a file.
- *
- * 'sel': which TLB array to use; TLB0 (4k) if zero,
- * TLB1 (variable) if nonzero.
- * 'idx': which TLB entry to access.
- * 'quiet': perform operation silently (no info printed)
- * if nonzero.
- * 'f': open FILE where to print information. May be
- * NULL in which case 'stdout' is used.
- *
- * RETURNS:
- * 0: success; TLB entry is VALID
- * +1: success but TLB entry is INVALID
- * < 0: error (-1: invalid argument)
- */
-int
-rtems_e500_prtlb(rtems_e500_tlb_idx key, int quiet, FILE *f)
-{
- uint32_t mas1, mas2, mas3;
- rtems_interrupt_level lvl;
- E500_tlb_va_cache_t *tlb;
- E500_tlb_va_cache_t buf;
- int sel, idx;
-
- sel = (key & E500_SELTLB_1) ? 1 : 0;
- idx = key & ~E500_SELTLB_1;
-
- if ( idx < 0 || idx > 255 || ( idx > 15 && sel ) )
- return -1;
-
- rtems_interrupt_disable(lvl);
-
- seltlb( key );
-
- asm volatile("tlbre");
-
- /* not manipulating MAS0, skip reading it */
- mas1 = _read_MAS1();
- mas2 = _read_MAS2();
- mas3 = _read_MAS3();
-
- rtems_interrupt_enable(lvl);
-
- tlb = sel ? rtems_e500_tlb_va_cache + idx : &buf;
-
- if ( (tlb->att.v = (FSL_EIS_MAS1_V & mas1) ? 1 : 0) ) {
- tlb->va.va_epn = FSL_EIS_MAS2_EPN_GET(mas2);
- tlb->rpn = FSL_EIS_MAS3_RPN_GET(mas3);
- tlb->va.va_tid = FSL_EIS_MAS1_TID_GET(mas1);
- tlb->att.ts = (FSL_EIS_MAS1_TS & mas1) ? 1 : 0;
- tlb->att.sz = sel ? FSL_EIS_MAS1_TSIZE_GET(mas1) : 1 /* 4k size */;
- tlb->att.wimge = FSL_EIS_MAS2_ATTR_GET(mas2);
- tlb->att.perm = FSL_EIS_MAS3_PERM_GET(mas3);
- }
-
- if ( tlb->att.v ) {
- if ( !quiet ) {
-/*
- "TLB[1] Entry # 0 spans EA range 0x00000000 .. 0x00000000
- "Mapping: VA [TS 0/TID 0x00/EPN 0x00000] -> RPN 0x00000"
- "Size: TSIZE 0x0 ( 4^ts KiB = 000000 KiB = 0x00000000 B)
- "Attributes: PERM 0x000 (ux/sx/uw/sw/ur/sr) WIMGE 0x00 IPROT 0"
-*/
- myprintf(f,
- "TLB[%i] Entry # %d spans EA range 0x%08x .. 0x%08x\r\n",
- sel,
- idx,
- (tlb->va.va_epn << 12),
- (tlb->va.va_epn << 12) + (1024<<(2*tlb->att.sz)) - 1
- );
-
- myprintf(f,
- "Mapping: VA [TS %d/TID 0x%02x/EPN 0x%05x] -> RPN 0x%05"PRIx32"\r\n",
- tlb->att.ts, tlb->va.va_tid, tlb->va.va_epn, tlb->rpn
- );
- myprintf(f,
- "Size: TSIZE 0x%x ( 4^ts KiB = %6d KiB = 0x%08x B)\r\n",
- tlb->att.sz, (1<<(2*tlb->att.sz)), (1024<<(2*tlb->att.sz))
- );
- myprintf(f,
- "Attributes: PERM 0x%03x (ux/sx/uw/sw/ur/sr) WIMGE 0x%02x IPROT %i\r\n",
- tlb->att.perm, tlb->att.wimge, (sel && (mas1 & FSL_EIS_MAS1_IPROT) ? 1 : 0)
- );
- myprintf(f,
- "EA range 0x%08x .. 0x%08x\r\n",
- (tlb->va.va_epn << 12),
- (tlb->va.va_epn << 12) + (1024<<(2*tlb->att.sz)) - 1
- );
- }
- } else {
- if ( !quiet ) {
- myprintf(f, "TLB[%i] Entry #%i <OFF> (size 0x%x = 0x%xb)\n", sel, idx, tlb->att.sz, (1024<<(2*tlb->att.sz)));
- }
- return 1;
- }
- return 0;
-}
-
-/* Initialize cache; verify that TLB0 is unused;
- *
- * RETURNS: zero on success, nonzero on error (TLB0
- * seems to be in use); in this case the
- * driver will refuse to change TLB1 entries
- * (other than disabling them).
- */
-int rtems_e500_initlb()
-{
-int i;
-int rval = 0;
- for (i=0; i<16; i++)
- rtems_e500_prtlb(E500_SELTLB_1 | i, 1, 0);
- for (i=0; i<256; i++) {
- /* refuse to enable operations that change TLB entries
- * if anything in TLB[0] is valid (because we currently
- * don't check against overlap with TLB[0] when we
- * write a new entry).
- */
- if ( rtems_e500_prtlb(E500_SELTLB_0 | i, 1, 0) <=0 ) {
- myprintf(stderr,"WARNING: 4k TLB #%i seems to be valid; UNSUPPORTED configuration\n", i);
- rval = -1;
- }
- }
- if ( !rval )
- initialized = 1;
- return rval;
-}
-
-/*
- * Write TLB1 entry (can also be used to disable an entry).
- *
- * The routine checks against the cached data in
- * rtems_e500_tlb_va[] to prevent the user from generating
- * overlapping entries.
- *
- * 'idx': TLB 1 entry # to manipulate
- * 'ea': Effective address (must be page aligned)
- * 'pa': Physical address (must be page aligned)
- * 'sz': Page size selector; page size is
- * 1024 * 2^(2*sz) bytes.
- * 'sz' may also be one of the following:
- * - page size in bytes ( >= 1024 ); the selector
- * value is then computed by this routine.
- * However, 'sz' must be a valid page size
- * or -1 will be returned.
- * - a value < 0 to invalidate/disable the
- * TLB entry.
- * 'attr': Page attributes; ORed combination of WIMGE,
- * PERMissions, TID and TS. Use ATTR_xxx macros
- *
- * RETURNS: 0 on success, nonzero on error:
- *
- * >0: requested mapping would overlap with
- * existing mapping in other entry. Return
- * value gives conflicting entry + 1; i.e.,
- * if a value of 4 is returned then the request
- * conflicts with existing mapping in entry 3.
- * -1: invalid argument
- * -3: driver not initialized (or initialization
- * failed because TLB0 is in use).
- * <0: other error
- *
- */
-#define E500_TLB_ATTR_WIMGE(x) ((x)&0x7f) /* includes user bits */
-#define E500_TLB_ATTR_WIMGE_GET(x) ((x)&0x7f)
-#define E500_TLB_ATTR_TS (1<<7)
-#define E500_TLB_ATTR_PERM(x) (((x)&0x3ff)<<8)
-#define E500_TLB_ATTR_PERM_GET(x) (((x)>>8)&0x3ff)
-#define E500_TLB_ATTR_TID(x) (((x)&0xfff)<<20)
-#define E500_TLB_ATTR_TID_GET(x) (((x)>>20)&0xfff)
-
-int
-rtems_e500_wrtlb(int idx, uint32_t ea, uint32_t pa, int sz, uint32_t attr)
-{
-uint32_t mas1, mas2, mas3, mas4;
-uint32_t tid, msk;
-int lkup;
-rtems_interrupt_level lvl;
-
- if ( sz >= 1024 ) {
- /* Assume they literally specify a size */
- msk = sz;
- sz = 0;
- while ( msk != (1024<<(2*sz)) ) {
- if ( ++sz > 15 ) {
- return -1;
- }
- }
- /* OK, acceptable */
- }
-
- msk = sz > 0 ? (1024<<(2*sz)) - 1 : 0;
-
- if ( !initialized && sz > 0 ) {
- myprintf(stderr,"TLB driver not initialized; refuse to enable any entry\n");
- return -3;
- }
-
- if ( (ea & msk) || (pa & msk) ) {
- myprintf(stderr,"Misaligned ea or pa\n");
- return -1;
- }
-
- if ( idx < 0 || idx > 15 )
- return -1;
-
- if ( sz > 15 ) {
- /* but e500v1 doesn't support all 16 sizes!! */
- /* FIXME: we should inquire about this CPU's
- * capabilities...
- */
- return -1;
- }
-
- tid = E500_TLB_ATTR_TID_GET(attr);
-
- mas1 = (attr & E500_TLB_ATTR_TS) ? FSL_EIS_MAS1_TS : 0;
-
- if ( sz >=0 ) {
- lkup = rtems_e500_matchtlb(ea, tid, mas1, sz);
-
- if ( lkup < -1 ) {
- /* some error */
- return lkup;
- }
-
- if ( lkup >= 0 && lkup != idx ) {
- myprintf(stderr,"TLB[1] #%i overlaps with requested mapping\n", lkup);
- rtems_e500_prtlb( E500_SELTLB_1 | lkup, 0, stderr);
- return lkup+1;
- }
- }
-
- /* OK to proceed */
- mas1 |= FSL_EIS_MAS1_IPROT | FSL_EIS_MAS1_TID(tid);
-
- if ( sz >= 0 )
- mas1 |= FSL_EIS_MAS1_V | FSL_EIS_MAS1_TSIZE(sz);
-
- mas2 = FSL_EIS_MAS2_EPN( ea>>12 ) | E500_TLB_ATTR_WIMGE(attr);
- mas3 = FSL_EIS_MAS3_RPN( pa>>12 ) | E500_TLB_ATTR_PERM_GET(attr);
- /* mas4 is not really relevant; we don't use TLB replacement */
- mas4 = FSL_EIS_MAS4_TLBSELD | FSL_EIS_MAS4_TIDSELD(0) | FSL_EIS_MAS4_TSIZED(9) | FSL_EIS_MAS4_ID | FSL_EIS_MAS4_GD;
-
- rtems_interrupt_disable(lvl);
-
- seltlb(idx | E500_SELTLB_1);
-
- _write_MAS1(mas1);
- _write_MAS2(mas2);
- _write_MAS3(mas3);
- _write_MAS4(mas4);
-
- asm volatile(
- " sync\n"
- " isync\n"
- " tlbwe\n"
- " sync\n"
- " isync\n"
- );
-
- rtems_interrupt_enable(lvl);
-
- /* update cache */
- rtems_e500_prtlb( E500_SELTLB_1 | idx, 1, 0);
-
- return 0;
-}
-
-/*
- * Check if a ts/tid/ea/sz mapping overlaps
- * with an existing entry.
- *
- * ASSUMPTION: all TLB0 (fixed 4k pages) are invalid and always unused.
- *
- * NOTE: 'sz' is the 'logarithmic' size selector; the page size
- * is 1024*2^(2*sz).
- *
- * RETURNS:
- * >= 0: index of TLB1 entry that already provides a mapping
- * which overlaps within the ea range.
- * -1: SUCCESS (no conflicting entry found)
- * <=-2: ERROR (invalid input)
- */
-int rtems_e500_matchtlb(uint32_t ea, uint32_t tid, int ts, int sz)
-{
-int i;
-uint32_t m,a;
-E500_tlb_va_cache_t *tlb;
-
- if ( sz < 0 || sz > 15 )
- return -4;
-
- sz = (1024<<(2*sz));
-
- if ( !initialized ) {
- /* cache not initialized */
- return -3;
- }
-
- if ( ea & (sz-1) ) {
- /* misaligned ea */
- return -2;
- }
-
- if ( ts )
- ts = 1;
-
- for ( i=0, tlb=rtems_e500_tlb_va_cache; i<16; i++, tlb++ ) {
- if ( ! tlb->att.v )
- continue;
- if ( tlb->att.ts != ts )
- continue;
- if ( tlb->va.va_tid && tlb->va.va_tid != tid )
- continue;
- /* TID and TS match a valid entry */
- m = (1024<<(2*tlb->att.sz)) - 1;
- /* calculate starting address of this entry */
- a = tlb->va.va_epn<<12;
- if ( ea <= a + m && ea + sz -1 >= a ) {
- /* overlap */
- return i;
- }
- }
- return -1;
-}
-
-/* Find TLB index that maps 'ea/as' combination
- *
- * RETURNS: index 'key'; i.e., the index number plus
- * a bit (E500_SELTLB_1) which indicates whether
- * the mapping was found in TLB0 (4k fixed page
- * size) or in TLB1 (variable page size).
- *
- * On error (no mapping) -1 is returned.
- */
-rtems_e500_tlb_idx
-rtems_e500_ftlb(uint32_t ea, int as)
-{
-uint32_t pid, mas0, mas1;
-int i, rval = -1;
-rtems_interrupt_level lvl;
-
- rtems_interrupt_disable(lvl);
-
- for ( i=0; i<3; i++ ) {
- switch (i) {
- case 0: asm volatile("mfspr %0, %1":"=r"(pid):"i"(FSL_EIS_PID0)); break;
- case 1: asm volatile("mfspr %0, %1":"=r"(pid):"i"(FSL_EIS_PID1)); break;
- case 2: asm volatile("mfspr %0, %1":"=r"(pid):"i"(FSL_EIS_PID2)); break;
- default:
- goto bail;
- }
-
- _write_MAS6( FSL_EIS_MAS6_SPID0(pid) | (as ? FSL_EIS_MAS6_SAS : 0 ) );
-
- asm volatile("tlbsx 0, %0"::"r"(ea));
-
- mas1 = _read_MAS1();
-
- if ( (FSL_EIS_MAS1_V & mas1) ) {
- mas0 = _read_MAS0();
- if ( FSL_EIS_MAS0_TLBSEL & mas0 ) {
- /* TLB1 */
- rval = FSL_EIS_MAS0_ESEL_GET(mas0) | E500_SELTLB_1;
- } else {
- rval = (ea >> (63-51)) | (( FSL_EIS_MAS0_NV & mas0 ) ? 180 : 0 ) ;
- }
- break;
- }
- }
-
-bail:
- rtems_interrupt_enable(lvl);
- return rval;
-}
-
-/* Mark TLB entry as invalid ('disabled'). Unlike
- * rtems_e500_wrtlb() with a negative size argument
- * this routine also can disable TLB0 entries.
- *
- * 'key': TLB entry (index) ORed with selector bit
- * (0 for TLB0, E500_SELTLB_1 for TLB1).
- *
- * RETURNS: zero on success, nonzero on error (TLB
- * unchanged).
- *
- * NOTE: If a TLB1 entry is disabled the associated
- * entry in rtems_e500_va_cache[] is also
- * marked as disabled.
- */
-int
-rtems_e500_clrtlb(rtems_e500_tlb_idx key)
-{
-rtems_e500_tlb_idx k0;
-rtems_interrupt_level lvl;
-
- /* minimal guard against bad key */
- if ( key < 0 )
- return -1;
-
- if ( (key & E500_SELTLB_1) ) {
- if ( (key & ~E500_SELTLB_1) > 15 ) {
- myprintf(stderr,"Invalid TLB index; TLB1 index must be < 16\n");
- return -1;
- }
- } else if ( key > 255 ) {
- myprintf(stderr,"Invalid TLB index; TLB0 index must be < 256\n");
- return -1;
- }
-
- /* Must not invalidate page 0 which holds vectors, text etc... */
- k0 = rtems_e500_ftlb(0, 0);
- if ( -1 == k0 ) {
- myprintf(stderr,"tlbivax; something's fishy - I don't find mapping for addr. 0\n");
- return -1;
- }
-
- /* NOTE: we assume PID is ignored, and AS is 0 */
- if ( k0 == key ) {
- myprintf(stderr,"Refuse to invalidate page holding addr 0 (always needed)\n");
- return -1;
- }
-
- rtems_interrupt_disable(lvl);
-
- seltlb(key);
-
- asm volatile("tlbre");
-
- /* read old entries */
- _write_MAS1( _read_MAS1() & ~FSL_EIS_MAS1_V );
-
- asm volatile(
- " sync\n"
- " isync\n"
- " tlbwe\n"
- " sync\n"
- " isync\n"
- );
-
- /* update cache */
- if ( E500_SELTLB_1 & key )
- rtems_e500_tlb_va_cache[ (~E500_SELTLB_1 & key) ].att.v = 0;
-
- rtems_interrupt_enable(lvl);
-
- return 0;
-}
diff --git a/c/src/lib/libcpu/powerpc/mpc6xx/mmu/bat.c b/c/src/lib/libcpu/powerpc/mpc6xx/mmu/bat.c
deleted file mode 100644
index 7a9487b9ff..0000000000
--- a/c/src/lib/libcpu/powerpc/mpc6xx/mmu/bat.c
+++ /dev/null
@@ -1,545 +0,0 @@
-/*
- * bat.c
- *
- * This file contains the implementation of C function to
- * Instantiate 60x/7xx ppc Block Address Translation (BAT) registers.
- * More detailed information can be found on motorola
- * site and more precisely in the following book :
- *
- * MPC750
- * Risc Microporcessor User's Manual
- * Mtorola REF : MPC750UM/AD 8/97
- *
- * Copyright (C) 1999 Eric Valette (valette@crf.canon.fr)
- * Canon Centre Recherche France.
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
- */
-#include <rtems.h>
-#include <libcpu/bat.h>
-#include <libcpu/spr.h>
-#include <rtems/bspIo.h>
-
-#include <libcpu/cpuIdent.h>
-
-#define TYP_I 1
-#define TYP_D 0
-
-typedef union
-{ /* BAT register values to be loaded */
- BAT bat;
- struct
- {
- unsigned int u, l;
- } words;
-} ubat;
-
-typedef struct batrange
-{ /* stores address ranges mapped by BATs */
- unsigned long start;
- unsigned long limit;
- unsigned long phys;
-} batrange;
-
-batrange bat_addrs[2][8] = { { {0,} } };
-
-/* could encode this in bat_addrs but I don't touch that one for bwds compat. reasons */
-/* bitmask of used bats */
-static unsigned bat_in_use[2] = { 0, 0 };
-
-/* define a few macros */
-
-#define CLRBAT_ASM(batu,r) \
- " sync \n" \
- " isync \n" \
- " li "#r ", 0 \n" \
- " mtspr "#batu ", "#r "\n" \
- " sync \n" \
- " isync \n"
-
-#define SETBAT_ASM(batu, batl, u, l)\
- " mtspr "#batl ", "#l " \n" \
- " sync \n" \
- " isync \n" \
- " mtspr "#batu ", "#u " \n" \
- " sync \n" \
- " isync \n"
-
-#define CLRBAT(bat) \
- asm volatile( \
- CLRBAT_ASM(%0, 0) \
- : \
- :"i"(bat##U) \
- :"0")
-
-#define GETBAT(bat,u,l) \
- asm volatile( \
- " mfspr %0, %2 \n" \
- " mfspr %1, %3 \n" \
- :"=r"(u),"=r"(l) \
- :"i"(bat##U),"i"(bat##L) \
- )
-
-#define DECL_SETBAT(lcbat,bat) \
-void \
-asm_set##lcbat(unsigned int upper, unsigned int lower) \
-{ \
-asm volatile( \
- CLRBAT_ASM(%0,0) \
- SETBAT_ASM(%0,%1,%2,%3) \
- : \
- :"i"(bat##U), \
- "i"(bat##L), \
- "r"(upper),"r"(lower) \
- :"0"); \
-}
-
-/* export the 'asm' versions for historic reasons */
-DECL_SETBAT (dbat0, DBAT0)
-DECL_SETBAT (dbat1, DBAT1)
-DECL_SETBAT (dbat2, DBAT2)
-DECL_SETBAT (dbat3, DBAT3)
-
-static DECL_SETBAT (dbat4, DBAT4)
-static DECL_SETBAT (dbat5, DBAT5)
-static DECL_SETBAT (dbat6, DBAT6)
-static DECL_SETBAT (dbat7, DBAT7)
-
-static DECL_SETBAT (ibat0, IBAT0)
-static DECL_SETBAT (ibat1, IBAT1)
-static DECL_SETBAT (ibat2, IBAT2)
-static DECL_SETBAT (ibat3, IBAT3)
-static DECL_SETBAT (ibat4, IBAT4)
-static DECL_SETBAT (ibat5, IBAT5)
-static DECL_SETBAT (ibat6, IBAT6)
-static DECL_SETBAT (ibat7, IBAT7)
-
-
-SPR_RO (HID0);
-
-static void
-set_hid0_sync (unsigned long val)
-{
- __asm__ volatile (
- " sync \n"
- " isync \n"
- " mtspr %0, %1 \n"
- " sync \n"
- " isync \n"
- :
- :"i" (HID0), "r" (val)
- :"memory" /* paranoia */
- );
-}
-
-static void
-bat_addrs_put (ubat * bat, int typ, int idx)
-{
- unsigned long bl;
- if (bat->bat.batu.vp || bat->bat.batu.vs) {
- bat_addrs[typ][idx].start = bat->bat.batu.bepi << 17;
- bat_addrs[typ][idx].phys = bat->bat.batl.brpn << 17;
-
- /* extended BL cannot be extracted using BAT union
- * - let's just hope the upper bits read 0 on pre 745x
- * CPUs.
- */
- bl = (bat->words.u << 15) | ((1 << 17) - 1);
- bat_addrs[typ][idx].limit = bat_addrs[typ][idx].start + bl;
-
- bat_in_use[typ] |= (1 << idx);
- }
-}
-
-/* We don't know how the board was initialized. Therefore,
- * when 'setdbat' is first used we must initialize our
- * cache.
- */
-static void
-bat_addrs_init (void)
-{
- ubat bat;
-
- GETBAT (DBAT0, bat.words.u, bat.words.l);
- bat_addrs_put (&bat, TYP_D, 0);
- GETBAT (DBAT1, bat.words.u, bat.words.l);
- bat_addrs_put (&bat, TYP_D, 1);
- GETBAT (DBAT2, bat.words.u, bat.words.l);
- bat_addrs_put (&bat, TYP_D, 2);
- GETBAT (DBAT3, bat.words.u, bat.words.l);
- bat_addrs_put (&bat, TYP_D, 3);
-
- GETBAT (IBAT0, bat.words.u, bat.words.l);
- bat_addrs_put (&bat, TYP_I, 0);
- GETBAT (IBAT1, bat.words.u, bat.words.l);
- bat_addrs_put (&bat, TYP_I, 1);
- GETBAT (IBAT2, bat.words.u, bat.words.l);
- bat_addrs_put (&bat, TYP_I, 2);
- GETBAT (IBAT3, bat.words.u, bat.words.l);
- bat_addrs_put (&bat, TYP_I, 3);
-
-
- if ( ppc_cpu_has_8_bats() && (HID0_7455_HIGH_BAT_EN & _read_HID0 ())) {
- GETBAT (DBAT4, bat.words.u, bat.words.l);
- bat_addrs_put (&bat, TYP_D, 4);
- GETBAT (DBAT5, bat.words.u, bat.words.l);
- bat_addrs_put (&bat, TYP_D, 5);
- GETBAT (DBAT6, bat.words.u, bat.words.l);
- bat_addrs_put (&bat, TYP_D, 6);
- GETBAT (DBAT7, bat.words.u, bat.words.l);
- bat_addrs_put (&bat, TYP_D, 7);
- GETBAT (IBAT4, bat.words.u, bat.words.l);
- bat_addrs_put (&bat, TYP_I, 4);
- GETBAT (IBAT5, bat.words.u, bat.words.l);
- bat_addrs_put (&bat, TYP_I, 5);
- GETBAT (IBAT6, bat.words.u, bat.words.l);
- bat_addrs_put (&bat, TYP_I, 6);
- GETBAT (IBAT7, bat.words.u, bat.words.l);
- bat_addrs_put (&bat, TYP_I, 7);
- }
-}
-
-static void
-do_dssall (void)
-{
- /* Before changing BATs, 'dssall' must be issued.
- * We check MSR for MSR_VE and issue a 'dssall' if
- * MSR_VE is set hoping that
- * a) on non-altivec CPUs MSR_VE reads as zero
- * b) all altivec CPUs use the same bit
- * NOTE: psim doesn't implement dssall so we skip if we run on psim
- */
- if ( (_read_MSR () & MSR_VE) && PPC_PSIM != get_ppc_cpu_type() ) {
- /* this construct is needed because we don't know
- * if this file is compiled with -maltivec.
- * (I plan to add altivec support outside of
- * RTEMS core and hence I'd rather not
- * rely on consistent compiler flags).
- */
-#define DSSALL 0x7e00066c /* dssall opcode */
- __asm__ volatile (" .long %0"::"i" (DSSALL));
-#undef DSSALL
- }
-}
-
-/* Clear I/D bats 4..7 ONLY ON 7455 etc. */
-static void
-clear_hi_bats (void)
-{
- do_dssall ();
- CLRBAT (DBAT4);
- CLRBAT (DBAT5);
- CLRBAT (DBAT6);
- CLRBAT (DBAT7);
- CLRBAT (IBAT4);
- CLRBAT (IBAT5);
- CLRBAT (IBAT6);
- CLRBAT (IBAT7);
-}
-
-static int
-check_bat_index (int i)
-{
- unsigned long hid0;
-
- if (i >= 0 && i < 4)
- return 0;
- if (i >= 4 && i < 8) {
- if ( ! ppc_cpu_has_8_bats() )
- return -1;
- /* OK, we're on the right hardware;
- * check if we are already enabled
- */
- hid0 = _read_HID0 ();
- if (HID0_7455_HIGH_BAT_EN & hid0)
- return 0;
- /* No; enable now */
- clear_hi_bats ();
- set_hid0_sync (hid0 | HID0_7455_HIGH_BAT_EN);
- return 0;
- }
- return -1;
-}
-
-/* size argument check:
- * - must be a power of two or zero
- * - must be <= 1<<28 ( non 745x cpu )
- * - can be 1<<29..1<31 or 0xffffffff on 745x
- * - size < 1<<17 means 0
- * computes and returns the block mask
- * RETURNS:
- * block mask on success or -1 on error
- */
-static int
-check_bat_size (unsigned long size)
-{
- unsigned long bit;
- unsigned long hid0;
-
- /* First of all, it must be a power of two */
- if (0 == size)
- return 0;
-
- if (0xffffffff == size) {
- bit = 32;
- } else {
- __asm__ volatile (" cntlzw %0, %1":"=r" (bit):"r" (size));
- bit = 31 - bit;
- if (1 << bit != size)
- return -1;
- }
- /* bit < 17 is not really legal but we aliased it to 0 in the past */
- if (bit > (11 + 17)) {
- if ( ! ppc_cpu_has_8_bats() )
- return -1;
-
- hid0 = _read_HID0 ();
- /* Let's enable the larger block size if necessary */
- if (!(HID0_7455_XBSEN & hid0))
- set_hid0_sync (hid0 | HID0_7455_XBSEN);
- }
-
- return (1 << (bit - 17)) - 1;
-}
-
-static int
-check_overlap (int typ, unsigned long start, unsigned long size)
-{
- int i;
- unsigned long limit = start + size - 1;
- for (i = 0; i < sizeof (bat_addrs[typ]) / sizeof (bat_addrs[typ][0]); i++) {
- if (!((1 << i) & bat_in_use[typ]))
- continue; /* unused bat */
- /* safe is 'limit < bat_addrs[t][i].start || start > bat_addrs[t][i].limit */
- if (limit >= bat_addrs[typ][i].start && start <= bat_addrs[typ][i].limit)
- return i;
- }
- return -1;
-}
-
-
-/* Take no risks -- the essential parts of this routine run with
- * interrupts disabled!
- */
-
-static int
-setbat (int typ, int bat_index, unsigned long virt, unsigned long phys,
- unsigned int size, int flags)
-{
- unsigned long level;
- unsigned int bl;
- int err;
- int wimgxpp;
- ubat bat;
-
- if (check_bat_index (bat_index)) {
- printk ("Invalid BAT index %d\n", bat_index);
- return -1;
- }
-
- if ((int) (bl = check_bat_size (size)) < 0) {
- printk ("Invalid BAT size %u\n", size);
- return -1;
- }
-
- if (virt & (size - 1)) {
- printk ("BAT effective address 0x%08lx misaligned (size is 0x%08x)\n",
- virt, size);
- return -1;
- }
-
- if (phys & (size - 1)) {
- printk ("BAT physical address 0x%08lx misaligned (size is 0x%08x)\n", phys,
- size);
- return -1;
- }
-
- if (virt + size - 1 < virt) {
- printk ("BAT range invalid: wraps around zero 0x%08lx..0x%08lx\n", virt,
- virt + size - 1);
- return -1;
- }
-
- if ( TYP_I == typ && ( ( _PAGE_GUARDED | _PAGE_WRITETHRU ) & flags ) ) {
- printk("IBAT must not have 'guarded' or 'writethrough' attribute\n");
- return -1;
- }
-
-/* must protect the bat_addrs table -- since this routine is only used for board setup
- * or similar special purposes we don't bother about interrupt latency too much.
- */
- rtems_interrupt_disable (level);
-
- { /* might have to initialize our cached data */
- static char init_done = 0;
- if (!init_done) {
- bat_addrs_init ();
- init_done = 1;
- }
- }
-
- err = check_overlap (typ, virt, size);
- if ((size >= (1 << 17)) && (err >= 0) && (err != bat_index)) {
- rtems_interrupt_enable (level);
- printk ("BATs must not overlap; area 0x%08lx..0x%08lx hits %cBAT %i\n",
- virt, virt + size, (TYP_I == typ ? 'I' : 'D'), err);
- return -1;
- }
-
- /* 603, 604, etc. */
- wimgxpp = flags & (_PAGE_WRITETHRU | _PAGE_NO_CACHE
- | _PAGE_COHERENT | _PAGE_GUARDED);
- wimgxpp |= (flags & _PAGE_RW) ? BPP_RW : BPP_RX;
- bat.words.u = virt | (bl << 2) | 2; /* Vs=1, Vp=0 */
- bat.words.l = phys | wimgxpp;
- if (flags & _PAGE_USER)
- bat.bat.batu.vp = 1;
- bat_addrs[typ][bat_index].start = virt;
- bat_addrs[typ][bat_index].limit = virt + ((bl + 1) << 17) - 1;
- bat_addrs[typ][bat_index].phys = phys;
- bat_in_use[typ] |= 1 << bat_index;
- if (size < (1 << 17)) {
- /* size of 0 tells us to switch it off */
- bat.bat.batu.vp = 0;
- bat.bat.batu.vs = 0;
- bat_in_use[typ] &= ~(1 << bat_index);
- /* mimic old behavior when bl was 0 (bs==0 is actually legal; it doesnt
- * indicate a size of zero. We now accept bl==0 and look at the size.
- */
- bat_addrs[typ][bat_index].limit = virt;
- }
- do_dssall ();
- if ( TYP_I == typ ) {
- switch (bat_index) {
- case 0: asm_setibat0 (bat.words.u, bat.words.l); break;
- case 1: asm_setibat1 (bat.words.u, bat.words.l); break;
- case 2: asm_setibat2 (bat.words.u, bat.words.l); break;
- case 3: asm_setibat3 (bat.words.u, bat.words.l); break;
- /* cpu check already done in check_index */
- case 4: asm_setibat4 (bat.words.u, bat.words.l); break;
- case 5: asm_setibat5 (bat.words.u, bat.words.l); break;
- case 6: asm_setibat6 (bat.words.u, bat.words.l); break;
- case 7: asm_setibat7 (bat.words.u, bat.words.l); break;
- default: /* should never get here anyways */
- break;
- }
- } else {
- switch (bat_index) {
- case 0: asm_setdbat0 (bat.words.u, bat.words.l); break;
- case 1: asm_setdbat1 (bat.words.u, bat.words.l); break;
- case 2: asm_setdbat2 (bat.words.u, bat.words.l); break;
- case 3: asm_setdbat3 (bat.words.u, bat.words.l); break;
- /* cpu check already done in check_index */
- case 4: asm_setdbat4 (bat.words.u, bat.words.l); break;
- case 5: asm_setdbat5 (bat.words.u, bat.words.l); break;
- case 6: asm_setdbat6 (bat.words.u, bat.words.l); break;
- case 7: asm_setdbat7 (bat.words.u, bat.words.l); break;
- default: /* should never get here anyways */
- break;
- }
- }
- rtems_interrupt_enable (level);
-
- return 0;
-}
-
-static int
-getbat (int typ, int idx, unsigned long *pu, unsigned long *pl)
-{
- unsigned long u, l;
-
- if (check_bat_index (idx)) {
- printk ("Invalid BAT #%i\n", idx);
- return -1;
- }
- if ( TYP_I == typ ) {
- switch (idx) {
- case 0: GETBAT (IBAT0, u, l); break;
- case 1: GETBAT (IBAT1, u, l); break;
- case 2: GETBAT (IBAT2, u, l); break;
- case 3: GETBAT (IBAT3, u, l); break;
- /* cpu check already done in check_index */
- case 4: GETBAT (IBAT4, u, l); break;
- case 5: GETBAT (IBAT5, u, l); break;
- case 6: GETBAT (IBAT6, u, l); break;
- case 7: GETBAT (IBAT7, u, l); break;
- default: /* should never get here anyways */
- return -1;
- }
- } else {
- switch (idx) {
- case 0: GETBAT (DBAT0, u, l); break;
- case 1: GETBAT (DBAT1, u, l); break;
- case 2: GETBAT (DBAT2, u, l); break;
- case 3: GETBAT (DBAT3, u, l); break;
- /* cpu check already done in check_index */
- case 4: GETBAT (DBAT4, u, l); break;
- case 5: GETBAT (DBAT5, u, l); break;
- case 6: GETBAT (DBAT6, u, l); break;
- case 7: GETBAT (DBAT7, u, l); break;
- default: /* should never get here anyways */
- return -1;
- }
- }
- if (pu) {
- *pu = u;
- }
- if (pl) {
- *pl = l;
- }
-
- if (!pu && !pl) {
- /* dump */
- ubat b;
- b.words.u = u;
- b.words.l = l;
- printk ("Raw %cBAT %i contents; UPPER: (0x%08lx)", (TYP_I == typ ? 'I' : 'D'), idx, u);
- printk (" BEPI: 0x%08x", b.bat.batu.bepi);
- printk (" BL: 0x%08lx", (u >> 2) & ((1 << 15) - 1));
- printk (" VS: 0b%i", b.bat.batu.vs);
- printk (" VP: 0b%i", b.bat.batu.vp);
- printk ("\n");
- printk (" LOWER: (0x%08lx)", l);
- printk (" RPN: 0x%08x", b.bat.batl.brpn);
- printk (" wimg: 0b%1i%1i%1i%1i", b.bat.batl.w, b.bat.batl.i,
- b.bat.batl.m, b.bat.batl.g);
- printk (" PP: 0x%1x", b.bat.batl.pp);
- printk ("\n");
- printk ("Covering EA Range: ");
- if (bat_in_use[typ] & (1 << idx))
- printk ("0x%08lx .. 0x%08lx\n", bat_addrs[typ][idx].start,
- bat_addrs[typ][idx].limit);
- else
- printk ("<none> (BAT off)\n");
-
- }
- return u;
-}
-
-int
-setdbat (int bat_index, unsigned long virt, unsigned long phys,
- unsigned int size, int flags)
-{
- return setbat(TYP_D, bat_index, virt, phys, size, flags);
-}
-
-int
-setibat (int bat_index, unsigned long virt, unsigned long phys,
- unsigned int size, int flags)
-{
- return setbat(TYP_I, bat_index, virt, phys, size, flags);
-}
-
-int
-getdbat (int idx, unsigned long *pu, unsigned long *pl)
-{
- return getbat (TYP_D, idx, pu, pl);
-}
-
-int
-getibat (int idx, unsigned long *pu, unsigned long *pl)
-{
- return getbat (TYP_I, idx, pu, pl);
-}
diff --git a/c/src/lib/libcpu/powerpc/mpc6xx/mmu/mmuAsm.S b/c/src/lib/libcpu/powerpc/mpc6xx/mmu/mmuAsm.S
deleted file mode 100644
index e64a5dfe89..0000000000
--- a/c/src/lib/libcpu/powerpc/mpc6xx/mmu/mmuAsm.S
+++ /dev/null
@@ -1,530 +0,0 @@
-/*
- * mmuAsm.S
- *
- * Copyright (C) 1999 Eric Valette (valette@crf.canon.fr)
- *
- * This file contains the low-level support for various MMU
- * features.
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
- *
- * T. Straumann - 11/2001: added support for 7400 (no AltiVec yet)
- * S.K. Feng - 10/2003: added support for 7455 (no AltiVec yet)
- *
- */
-
-#include <rtems/asm.h>
-#include <rtems/score/cpu.h>
-#include <libcpu/io.h>
-#include <libcpu/bat.h>
-
-/* Unfortunately, the CPU types defined in cpu.h are
- * an 'enum' type and hence not available :-(
- */
-#define PPC_601 0x1
-#define PPC_603 0x3
-#define PPC_604 0x4
-#define PPC_603e 0x6
-#define PPC_603ev 0x7
-#define PPC_750 0x8
-#define PPC_604e 0x9
-#define PPC_604r 0xA
-#define PPC_7400 0xC
-#define PPC_7455 0x8001
-#define PPC_7457 0x8002
-#define PPC_620 0x16
-#define PPC_860 0x50
-#define PPC_821 PPC_860
-#define PPC_8260 0x81
-#define PPC_8240 PPC_8260
-
-/* ALTIVEC instructions (not recognized by off-the shelf gcc yet) */
-#define DSSALL .long 0x7e00066c /* DSSALL altivec instruction opcode */
-
-/* A couple of defines to make the code more readable */
-#define CACHE_LINE_SIZE 32
-
-#ifndef MSSCR0
-#define MSSCR0 1014
-#endif
-
-#define DL1HWF (1<<(31-8))
-#define L2HWF (1<<(31-20))
-
-#FIXME Should really move this to C code
-
- .globl L1_caches_enables
- .type L1_caches_enables, @function
-
-L1_caches_enables:
- /*
- * Enable caches and 604-specific features if necessary.
- */
- mfspr r9,PPC_PVR
- rlwinm r9,r9,16,16,31
- cmpi 0,r9,PPC_601
- beq 4f /* not needed for 601 */
- mfspr r11,HID0
- andi. r0,r11,HID0_DCE
- ori r11,r11,HID0_ICE|HID0_DCE
- ori r8,r11,HID0_ICFI
- bne 3f /* don't invalidate the D-cache */
- ori r8,r8,HID0_DCI /* unless it wasn't enabled */
-3:
- sync
- mtspr HID0,r8 /* enable and invalidate caches */
- sync
- mtspr HID0,r11 /* enable caches */
- sync
- isync
- cmpi 1,r9,PPC_604 /* check for 604 */
- cmpi 2,r9,PPC_604e /* or 604e */
- cmpi 3,r9,PPC_604r /* or mach5 */
- cror 6,6,10
- cror 6,6,14
- cmpi 2,r9,PPC_750 /* or 750 */
- cror 6,6,10
- cmpi 2,r9,PPC_7400 /* or 7400 */
- cror 6,6,10
- cmpli 0,r9,PPC_7455 /* or 7455 */
- beq 1f
- cmpli 0,r9,PPC_7457 /* or 7457 */
- bne 2f
-1:
- /* 7455:link register stack,branch folding &
- * TBEN : enable the time base and decrementer.
- * EMCP bit is defined in HID1. However, it's not used
- * in mvme5500 board because of GT64260 (e.g. it's connected
- * pull-up).
- */
- oris r11,r11,(HID0_LRSTK|HID0_FOLD|HID0_TBEN)@h
- ori r11,r11,(HID0_LRSTK|HID0_FOLD|HID0_TBEN)@l
-2: cror 2,2,10
- bne 3f
- ori r11,r11,HID0_BTIC /* enable branch tgt cache on 7400 , 7455 , 7457 */
-3: cror 2,2,6
- bne 4f
- /* on 7400 SIED is actually SGE (store gathering enable) */
- ori r11,r11,HID0_SIED|HID0_BHTE /* for 604[e], enable */
- bne 2,5f
- ori r11,r11,HID0_BTCD
-5: mtspr HID0,r11 /* superscalar exec & br history tbl */
- sync /* for SGE bit */
- isync /* P2-17 to 2-22 in MPC7450UM */
-4:
- blr
-
- .globl get_L1CR
-.type get_L1CR, @function
-get_L1CR:
- mfspr r3,HID0
- blr
-
- .globl get_L2CR
- .type get_L2CR, @function
-get_L2CR:
- /* Make sure this is a > 750 chip */
- mfspr r3,PPC_PVR
- rlwinm r3,r3,16,16,31
- cmplwi r3,PPC_750 /* it's a 750 */
- beq 1f
- cmplwi r3,PPC_7400 /* it's a 7400 */
- beq 1f
- cmplwi r3,PPC_7455 /* it's a 7455 */
- beq 1f
- cmplwi r3,PPC_7457 /* it's a 7457 */
- beq 1f
- li r3,-1
- blr
-
-1:
- /* Return the L2CR contents */
- mfspr r3,L2CR
- blr
-
- .globl set_L2CR
- .type set_L2CR, @function
-set_L2CR:
- /* Usage:
- * When setting the L2CR register, you must do a few special things.
- * If you are enabling the cache, you must perform a global invalidate.
- * If you are disabling the cache, you must flush the cache contents first.
- * This routine takes care of doing these things. When first
- * enabling the cache, make sure you pass in the L2CR you want, as well as
- * passing in the global invalidate bit set. A global invalidate will
- * only be performed if the L2I bit is set in applyThis. When enabling
- * the cache, you should also set the L2E bit in applyThis. If you
- * want to modify the L2CR contents after the cache has been enabled,
- * the recommended procedure is to first call __setL2CR(0) to disable
- * the cache and then call it again with the new values for L2CR. Examples:
- *
- * _setL2CR(0) - disables the cache
- * _setL2CR(0xb9A14000) - enables my G3 MCP750 card:
- * - L2E set to turn on the cache
- * - L2SIZ set to 1MB
- * - L2CLK set to %2
- * - L2RAM set to pipelined syncronous late-write
- * - L2I set to perform a global invalidation
- * - L2OH set to 1 nS
- *
- * A similar call should work for your card. You need to know the correct
- * setting for your card and then place them in the fields I have outlined
- * above. Other fields support optional features, such as L2DO which caches
- * only data, or L2TS which causes cache pushes from the L1 cache to go to
- *the L2 cache instead of to main memory.
- */
-
- /* Make sure this is a > 750 chip */
- mfspr r0,PPC_PVR
- rlwinm r0,r0,16,16,31
- cmplwi r0,PPC_750
- beq thisIs750
- cmplwi r0,PPC_7400
- beq thisIs750
- cmplwi r0,PPC_7455
- beq thisIs750
- cmplwi r0,PPC_7457
- beq thisIs750
- li r3,-1
- blr
-
-thisIs750:
- /* Get the current enable bit of the L2CR into r4 */
- mfspr r4,L2CR
- rlwinm r4,r4,0,0,0
-
- /* See if we want to perform a global inval this time. */
- rlwinm r6,r3,0,10,10 /* r6 contains the new invalidate bit */
- rlwinm. r5,r3,0,0,0 /* r5 contains the new enable bit */
- rlwinm r3,r3,0,11,9 /* Turn off the invalidate bit */
- rlwinm r3,r3,0,1,31 /* Turn off the enable bit */
- or r3,r3,r4 /* Keep the enable bit the same as it was for now. */
- mfmsr r7 /* shut off interrupts around critical flush/invalidate sections */
- rlwinm r4,r7,0,17,15 /* Turn off EE bit - an external exception while we are flushing
- the cache is fatal (comment this line and see!) */
- mtmsr r4
- bne dontDisableCache /* Only disable the cache if L2CRApply has the enable bit off */
-
- cmplwi r0,PPC_7400 /* 7400 ? */
- bne disableCache /* use traditional method */
-
- /* On the 7400, they recommend using the hardware flush feature */
- DSSALL /* stop all data streams */
- sync
- /* we wouldn't have to flush L1, but for sake of consistency with the other code we do it anyway */
- mfspr r4, MSSCR0
- oris r4, r4, DL1HWF@h
- mtspr MSSCR0, r4
- sync
- /* L1 flushed */
- mfspr r4, L2CR
- ori r4, r4, L2HWF
- mtspr L2CR, r4
- sync
- /* L2 flushed */
- b flushDone
-
-disableCache:
- /* Disable the cache. First, we turn off data relocation. */
- rlwinm r4,r4,0,28,26 /* Turn off DR bit */
- cmplwi r0,PPC_7455 /* 7455 ? */
- beq 1f
- cmplwi r0,PPC_7457 /* 7457 ? */
- bne not745x
-1:
- /* 745x:L1 Load/Flush, L2, L3 : hardware flush */
- DSSALL
- mtmsr r4
- sync
- isync
- mfspr r4, MSSCR0
- rlwinm r4,r4,0,29,0 /* Turn off the L2PFE bits */
- mtspr MSSCR0, r4
- sync
- /* flush L1 first */
- lis r4,0x0001
- mtctr r4
- li r4,0
- li r0,0
-loadFlush:
- lwzx r0,r0,r4
- dcbf r0,r4
- addi r4,r4,CACHE_LINE_SIZE /* Go to start of next cache line */
- bdnz loadFlush
- sync
- /* Set the L2CR[L2IO & L2DO] bits to completely lock the L2 cache */
- mfspr r0, L2CR
- lis r4,L2CR_LOCK_745x@h
- ori r4,r4,L2CR_LOCK_745x@l
- or r4,r0,r4
- rlwinm r4,r4,0,11,9 /* make sure the invalidate bit off */
- mtspr L2CR, r4
- sync
- ori r4, r4, L2HWF
- mtspr L2CR, r4
- sync
- /* L2 flushed,L2IO & L2DO got cleared in the dontDisableCache: */
- b reenableDR
-
-not745x:
- sync
- mtmsr r4
- isync
- /*
- Now, read the first 2MB of memory to put new data in the cache.
- (Actually we only need the size of the L2 cache plus
- the size of the L1 cache, but 2MB will cover everything just to be safe).
- */
- lis r4,0x0001
- mtctr r4
- li r4,0
-loadLoop:
- lwzx r0,r0,r4
- addi r4,r4,CACHE_LINE_SIZE /* Go to start of next cache line */
- bdnz loadLoop
-
- /* Now, flush the first 2MB of memory */
- lis r4,0x0001
- mtctr r4
- li r4,0
- sync
-flushLoop:
- dcbf r0,r4
- addi r4,r4,CACHE_LINE_SIZE /* Go to start of next cache line */
- bdnz flushLoop
-reenableDR:
- rlwinm r4,r7,0,17,15 /* still mask EE but reenable data relocation */
- sync
- mtmsr r4
- isync
-
-flushDone:
-
- /* Turn off the L2CR enable bit. */
- rlwinm r3,r3,0,1,31
-
-dontDisableCache:
- /* Set up the L2CR configuration bits */
- sync
- mtspr L2CR,r3
- sync
- cmplwi r6,0
- beq noInval
-
- /* Perform a global invalidation */
- oris r3,r3,0x0020
- sync
- mtspr L2CR,r3
- sync
-invalCompleteLoop: /* Wait for the invalidation to complete */
- mfspr r3,L2CR
- rlwinm. r4,r3,0,31,31
- bne invalCompleteLoop
-
- rlwinm r3,r3,0,11,9; /* Turn off the L2I bit */
- sync
- mtspr L2CR,r3
-
-noInval:
- sync
- /* re-enable interrupts, i.e. restore original MSR */
- mtmsr r7 /* (no sync needed) */
- /* See if we need to enable the cache */
- cmplwi r5,0
- beqlr
-
-enableCache:
- /* Enable the cache */
- oris r3,r3,0x8000
- mtspr L2CR,r3
- sync
- blr
-
-
- .globl get_L3CR
- .type get_L3CR, @function
-get_L3CR:
- /* Make sure this is a 7455 chip */
- mfspr r3,PPC_PVR
- rlwinm r3,r3,16,16,31
- cmplwi r3,PPC_7455 /* it's a 7455 */
- beq 1f
- cmplwi r3,PPC_7457 /* it's a 7457 */
- beq 1f
- li r3,-1
- blr
-
-1:
- /* Return the L3CR contents */
- mfspr r3,L3CR
- blr
-
- .globl set_L3CR
- .type set_L3CR, @function
-set_L3CR:
- /* Usage:
- * When setting the L3CR register, you must do a few special things.
- * If you are enabling the cache, you must perform a global invalidate.
- * Then call cpu_enable_l3cr(l3cr).
- * If you are disabling the cache, you must flush the cache contents first.
- * This routine takes care of doing these things. If you
- * want to modify the L3CR contents after the cache has been enabled,
- * the recommended procedure is to first call __setL3CR(0) to disable
- * the cache and then call cpu_enable_l3cr with the new values for
- * L3CR.
- */
-
- /* Make sure this is a 7455 chip */
- mfspr r0,PPC_PVR
- rlwinm r0,r0,16,16,31
- cmplwi r0,PPC_7455
- beq thisIs7455
- cmplwi r0,PPC_7457
- beq thisIs7455
- li r3,-1
- blr
-
-thisIs7455:
- /* Get the current enable bit of the L3CR into r4 */
- mfspr r4,L3CR
- rlwinm r4,r4,0,0,0
-
- /* See if we want to perform a global inval this time. */
- rlwinm r6,r3,0,10,10 /* r6 contains the new invalidate bit */
- rlwinm. r5,r3,0,0,0 /* r5 contains the new enable bit */
- rlwinm r3,r3,0,11,9 /* Turn off the invalidate bit */
- rlwinm r3,r3,0,1,31 /* Turn off the enable bit */
- or r3,r3,r4 /* Keep the enable bit the same as it was for now. */
- mfmsr r7 /* shut off interrupts around critical flush/invalidate sections */
- rlwinm r4,r7,0,17,15 /* Turn off EE bit - an external exception while we are flushing
- the cache is fatal (comment this line and see!) */
- mtmsr r4
- bne dontDisableL3Cache /* Only disable the cache if L3CRApply has the enable bit off */
- /* Before the L3 is disabled, it must be flused to prevent coherency problems */
- /* First, we turn off data relocation. */
- rlwinm r4,r4,0,28,26 /* Turn off DR bit */
- DSSALL
- sync
- mtmsr r4
- isync /* make sure memory accesses have completed */
- /* 7455: L3 : hardware flush
- * Set the L3CR[L3IO & L3DO] bits to completely lock the L3 cache */
- mfspr r0, L3CR
- lis r4, L3CR_LOCK_745x@h
- ori r4,r4, L3CR_LOCK_745x@l
- or r4,r0,r4
- rlwinm r4,r4,0,11,9 /* make sure the invalidate bit off */
- mtspr L3CR, r4
- sync
- ori r4, r4, L3CR_L3HWF
- mtspr L3CR, r4
- sync
- /* L3 flushed,L3IO & L3DO got cleared in the dontDisableL3Cache: */
- rlwinm r4,r7,0,17,15 /* still mask EE but reenable data relocation */
- sync
- mtmsr r4
- isync
-
- /* Turn off the L3CR enable bit. */
- rlwinm r3,r3,0,1,31
-
-dontDisableL3Cache:
- /* Set up the L3CR configuration bits */
- sync
- mtspr L3CR,r3
- sync
-ifL3Inval:
- cmplwi r6,0
- beq noL3Inval
-
- /* Perform a global invalidation */
- oris r3,r3,0x0020
- sync
- mtspr L3CR,r3
- sync
-invalCompleteL3: /* Wait for the invalidation to complete */
- mfspr r3,L3CR
- rlwinm. r4,r3,0,31,31
- bne invalCompleteL3
-
- rlwinm r3,r3,0,11,9; /* Turn off the L3I bit */
- sync
- mtspr L3CR,r3
- sync
-
-noL3Inval:
- /* re-enable interrupts, i.e. restore original MSR */
- mtmsr r7 /* (no sync needed) */
- /* See if we need to enable the cache */
- cmplwi r5,0
- beqlr
-
-enableL3Cache:
- /* Enable the cache */
- oris r3,r3,0x8000
- mtspr L3CR,r3
- sync
- blr
-
-/*
- * An undocumented "feature" of 604e requires that the v bit
- * be cleared before changing BAT values.
- *
- * Also, newer IBM firmware does not clear bat3 and 4 so
- * this makes sure it's done.
- * -- Cort
- */
- .globl CPU_clear_bats_early
- .type CPU_clear_bats_early,@function
-CPU_clear_bats_early:
- li r3,0
- mfspr r4,PPC_PVR
- rlwinm r4,r4,16,16,31 /* r4 = 1 for 601, 4 for 604 */
- cmpwi r4, 1
- sync
- isync
- beq 1f
- cmplwi r4,0x8001 /* 7445, 7455 (0x8001), 7447, 7457 (0x8002) */
- blt 2f /* 7447a (0x8003) and 7448 (0x8004) have 16 bats */
- cmplwi r4,0x8004
- bgt 2f
- mtspr DBAT4U,r3
- mtspr DBAT4L,r3
- mtspr DBAT5U,r3
- mtspr DBAT5L,r3
- mtspr DBAT6U,r3
- mtspr DBAT6L,r3
- mtspr DBAT7U,r3
- mtspr DBAT7L,r3
- mtspr IBAT4U,r3
- mtspr IBAT4L,r3
- mtspr IBAT5U,r3
- mtspr IBAT5L,r3
- mtspr IBAT6U,r3
- mtspr IBAT6L,r3
- mtspr IBAT7U,r3
- mtspr IBAT7L,r3
-2:
- mtspr DBAT0U,r3
- mtspr DBAT0L,r3
- mtspr DBAT1U,r3
- mtspr DBAT1L,r3
- mtspr DBAT2U,r3
- mtspr DBAT2L,r3
- mtspr DBAT3U,r3
- mtspr DBAT3L,r3
-1:
- mtspr IBAT0U,r3
- mtspr IBAT0L,r3
- mtspr IBAT1U,r3
- mtspr IBAT1L,r3
- mtspr IBAT2U,r3
- mtspr IBAT2L,r3
- mtspr IBAT3U,r3
- mtspr IBAT3L,r3
- sync
- isync
- blr
-
diff --git a/c/src/lib/libcpu/powerpc/mpc6xx/mmu/pte121.c b/c/src/lib/libcpu/powerpc/mpc6xx/mmu/pte121.c
deleted file mode 100644
index 93ef909776..0000000000
--- a/c/src/lib/libcpu/powerpc/mpc6xx/mmu/pte121.c
+++ /dev/null
@@ -1,1139 +0,0 @@
-/*
- * Trivial page table setup for RTEMS
- * Purpose: allow write protection of text/RO-data
- */
-
-/*
- * Authorship
- * ----------
- * This software was created by
- * Till Straumann <strauman@slac.stanford.edu>, 4/2002, 2003, 2004,
- * Stanford Linear Accelerator Center, Stanford University.
- *
- * Acknowledgement of sponsorship
- * ------------------------------
- * This software was produced by
- * the Stanford Linear Accelerator Center, Stanford University,
- * under Contract DE-AC03-76SFO0515 with the Department of Energy.
- *
- * Government disclaimer of liability
- * ----------------------------------
- * Neither the United States nor the United States Department of Energy,
- * nor any of their employees, makes any warranty, express or implied, or
- * assumes any legal liability or responsibility for the accuracy,
- * completeness, or usefulness of any data, apparatus, product, or process
- * disclosed, or represents that its use would not infringe privately owned
- * rights.
- *
- * Stanford disclaimer of liability
- * --------------------------------
- * Stanford University makes no representations or warranties, express or
- * implied, nor assumes any liability for the use of this software.
- *
- * Stanford disclaimer of copyright
- * --------------------------------
- * Stanford University, owner of the copyright, hereby disclaims its
- * copyright and all other rights in this software. Hence, anyone may
- * freely use it for any purpose without restriction.
- *
- * Maintenance of notices
- * ----------------------
- * In the interest of clarity regarding the origin and status of this
- * SLAC software, this and all the preceding Stanford University notices
- * are to remain affixed to any copy or derivative of this software made
- * or distributed by the recipient and are to be affixed to any copy of
- * software made or distributed by the recipient that contains a copy or
- * derivative of this software.
- *
- * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
- */
-
-/* Chose debugging options */
-#undef DEBUG_MAIN /* create a standalone (host) program for basic testing */
-#undef DEBUG /* target debugging and consistency checking */
-#undef DEBUG_EXC /* add exception handler which reenables BAT0 and recovers from a page fault */
-
-#ifdef DEBUG_MAIN
-#undef DEBUG /* must not use these together with DEBUG_MAIN */
-#undef DEBUG_EXC
-#endif
-
-/***************************** INCLUDE HEADERS ****************************/
-
-#ifndef DEBUG_MAIN
-#include <rtems.h>
-#include <rtems/bspIo.h>
-#include <rtems/score/percpu.h>
-#include <libcpu/cpuIdent.h>
-#include <libcpu/spr.h>
-#ifdef DEBUG_EXC
-#include <bsp.h>
-#include <bsp/vectors.h>
-#endif
-#endif
-
-#include <stdio.h>
-#include <assert.h>
-#include <string.h>
-
-#include <libcpu/pte121.h>
-
-/************************** CONSTANT DEFINITIONS **************************/
-
-/* Base 2 logs of some sizes */
-
-#ifndef DEBUG_MAIN
-
-#define LD_PHYS_SIZE 32 /* physical address space */
-#define LD_PG_SIZE 12 /* page size */
-#define LD_PTEG_SIZE 6 /* PTEG size */
-#define LD_PTE_SIZE 3 /* PTE size */
-#define LD_SEG_SIZE 28 /* segment size */
-#define LD_MIN_PT_SIZE 16 /* minimal size of a page table */
-#define LD_HASH_SIZE 19 /* lengh of a hash */
-#define LD_VSID_SIZE 24 /* vsid bits in seg. register */
-
-#else /* DEBUG_MAIN */
-
-/* Reduced 'fantasy' sizes for testing */
-#define LD_PHYS_SIZE 32 /* physical address space */
-#define LD_PG_SIZE 6 /* page size */
-#define LD_PTEG_SIZE 5 /* PTEG size */
-#define LD_PTE_SIZE 3 /* PTE size */
-#define LD_SEG_SIZE 28 /* segment size */
-#define LD_MIN_PT_SIZE 7 /* minimal size of a page table */
-#define LD_HASH_SIZE 19 /* lengh of a hash */
-
-#endif /* DEBUG_MAIN */
-
-/* Derived sizes */
-
-/* Size of a page index */
-#define LD_PI_SIZE ((LD_SEG_SIZE) - (LD_PG_SIZE))
-
-/* Number of PTEs in a PTEG */
-#define PTE_PER_PTEG (1<<((LD_PTEG_SIZE)-(LD_PTE_SIZE)))
-
-/* Segment register bits */
-#define KEY_SUP (1<<30) /* supervisor mode key */
-#define KEY_USR (1<<29) /* user mode key */
-
-/* The range of effective addresses to scan with 'tlbie'
- * instructions in order to flush all TLBs.
- * On the 750 and 7400, there are 128 two way I and D TLBs,
- * indexed by EA[14:19]. Hence calling
- * tlbie rx
- * where rx scans 0x00000, 0x01000, 0x02000, ... 0x3f000
- * is sufficient to do the job
- */
-#define NUM_TLB_PER_WAY 64 /* 750 and 7400 have 128 two way TLBs */
-#define FLUSH_EA_RANGE (NUM_TLB_PER_WAY<<LD_PG_SIZE)
-
-/*************************** MACRO DEFINITIONS ****************************/
-
-/* Macros to split a (32bit) 'effective' address into
- * VSID (virtual segment id) and PI (page index)
- * using a 1:1 mapping of 'effective' to 'virtual'
- * addresses.
- *
- * For 32bit addresses this looks like follows
- * (each 'x' or '0' stands for a 'nibble' [4bits]):
- *
- * 32bit effective address (EA)
- *
- * x x x x x x x x
- * | |
- * 0 0 0 0 0 x|x x x x|x x x
- * VSID | PI | PO (page offset)
- * | |
- */
-/* 1:1 VSID of an EA */
-#define VSID121(ea) (((ea)>>LD_SEG_SIZE) & ((1<<(LD_PHYS_SIZE-LD_SEG_SIZE))-1))
-/* page index of an EA */
-#define PI121(ea) (((ea)>>LD_PG_SIZE) & ((1<<LD_PI_SIZE)-1))
-
-/* read VSID from segment register */
-#ifndef DEBUG_MAIN
-static uint32_t
-seg2vsid (uint32_t ea)
-{
- __asm__ volatile ("mfsrin %0, %0":"=r" (ea):"0" (ea));
- return ea & ((1 << LD_VSID_SIZE) - 1);
-}
-#else
-#define seg2vsid(ea) VSID121(ea)
-#endif
-
-/* Primary and secondary PTE hash functions */
-
-/* Compute the primary hash from a VSID and a PI */
-#define PTE_HASH1(vsid, pi) (((vsid)^(pi))&((1<<LD_HASH_SIZE)-1))
-
-/* Compute the secondary hash from a primary hash */
-#define PTE_HASH2(hash1) ((~(hash1))&((1<<LD_HASH_SIZE)-1))
-
-/* Extract the abbreviated page index (which is the
- * part of the PI which does not go into the hash
- * under all circumstances [10 bits to -> 6bit API])
- */
-#define API(pi) ((pi)>>((LD_MIN_PT_SIZE)-(LD_PTEG_SIZE)))
-
-
-/* Horrible Macros */
-#ifdef __rtems__
-/* must not use printf until multitasking is up */
-typedef int (*PrintF) (const char *, ...);
-static PrintF
-whatPrintf (void)
-{
- return _Thread_Executing ? printf : printk;
-}
-
-#define PRINTF(args...) ((void)(whatPrintf())(args))
-#else
-#define PRINTF(args...) printf(args)
-#endif
-
-#ifdef DEBUG
-static unsigned long triv121PgTblConsistency(
- Triv121PgTbl pt, int pass, int expect);
-
-static int consistencyPass = 0;
-#define CONSCHECK(expect) triv121PgTblConsistency(&pgTbl,consistencyPass++,(expect))
-#else
-#define CONSCHECK(expect) do {} while (0)
-#endif
-
-/**************************** TYPE DEFINITIONS ****************************/
-
-/* internal description of a trivial page table */
-typedef struct Triv121PgTblRec_
-{
- APte base;
- unsigned long size;
- int active;
-} Triv121PgTblRec;
-
-
-/************************** FORWARD DECLARATIONS *************************/
-
-#ifdef DEBUG_EXC
-static void myhdl (BSP_Exception_frame * excPtr);
-#endif
-
-static void dumpPte (APte pte);
-
-#ifdef DEBUG
-static void
-dumpPteg (unsigned long vsid, unsigned long pi, unsigned long hash);
-#endif
-
-unsigned long
-triv121IsRangeMapped (long vsid, unsigned long start, unsigned long end);
-
-static void do_dssall (void);
-
-/**************************** STATIC VARIABLES ****************************/
-
-/* dont malloc - we might have to use this before
- * we have malloc or even RTEMS workspace available
- */
-static Triv121PgTblRec pgTbl = { 0 };
-
-#ifdef DEBUG_EXC
-static void *ohdl; /* keep a pointer to the original handler */
-#endif
-
-/*********************** INLINES & PRIVATE ROUTINES ***********************/
-
-/* compute the page table entry group (PTEG) of a hash */
-static inline APte
-ptegOf (Triv121PgTbl pt, unsigned long hash)
-{
- hash &= ((1 << LD_HASH_SIZE) - 1);
- return (APte) (((unsigned long) pt->
- base) | ((hash << LD_PTEG_SIZE) & (pt->size - 1)));
-}
-
-/* see if a vsid/pi combination is already mapped
- *
- * RETURNS: PTE of mapping / NULL if none exists
- *
- * NOTE: a vsid<0 is legal and will tell this
- * routine that 'pi' is actually an EA to
- * be split into vsid and pi...
- */
-static APte
-alreadyMapped (Triv121PgTbl pt, long vsid, unsigned long pi)
-{
- int i;
- unsigned long hash, api;
- APte pte;
-
- if (!pt->size)
- return 0;
-
- if (TRIV121_121_VSID == vsid) {
- vsid = VSID121 (pi);
- pi = PI121 (pi);
- } else if (TRIV121_SEG_VSID == vsid) {
- vsid = seg2vsid (pi);
- pi = PI121 (pi);
- }
-
- hash = PTE_HASH1 (vsid, pi);
- api = API (pi);
- for (i = 0, pte = ptegOf (pt, hash); i < PTE_PER_PTEG; i++, pte++)
- if (pte->v && pte->vsid == vsid && pte->api == api && 0 == pte->h)
- return pte;
- /* try the secondary hash table */
- hash = PTE_HASH2 (hash);
- for (i = 0, pte = ptegOf (pt, hash); i < PTE_PER_PTEG; i++, pte++)
- if (pte->v && pte->vsid == vsid && pte->api == api && 1 == pte->h)
- return pte;
- return 0;
-}
-
-/* find the first available slot for vsid/pi
- *
- * NOTE: it is NOT legal to pass a vsid<0 / EA combination.
- *
- * RETURNS free slot with the 'marked' field set. The 'h'
- * field is set to 0 or one, depending on whether
- * the slot was allocated by using the primary or
- * the secondary hash, respectively.
- */
-static APte
-slotFor (Triv121PgTbl pt, unsigned long vsid, unsigned long pi)
-{
- int i;
- unsigned long hash;
- APte pte;
-
- /* primary hash */
- hash = PTE_HASH1 (vsid, pi);
- /* linear search thru all buckets for this hash */
- for (i = 0, pte = ptegOf (pt, hash); i < PTE_PER_PTEG; i++, pte++) {
- if (!pte->v && !pte->marked) {
- /* found a free PTE; mark it as potentially used and return */
- pte->h = 0; /* found by the primary hash fn */
- pte->marked = 1;
- return pte;
- }
- }
-
-#ifdef DEBUG
- /* Strange: if the hash table was allocated big enough,
- * this should not happen (when using a 1:1 mapping)
- * Give them some information...
- */
- PRINTF ("## First hash bucket full - ");
- dumpPteg (vsid, pi, hash);
-#endif
-
- hash = PTE_HASH2 (hash);
-#ifdef DEBUG
- PRINTF (" Secondary pteg is 0x%08x\n", (unsigned) ptegOf (pt, hash));
-#endif
- for (i = 0, pte = ptegOf (pt, hash); i < PTE_PER_PTEG; i++, pte++) {
- if (!pte->v && !pte->marked) {
- /* mark this pte as potentially used */
- pte->marked = 1;
- pte->h = 1;
- return pte;
- }
- }
-#ifdef DEBUG
- /* Even more strange - most likely, something is REALLY messed up */
- PRINTF ("## Second hash bucket full - ");
- dumpPteg (vsid, pi, hash);
-#endif
- return 0;
-}
-
-/* unmark all entries */
-static void
-unmarkAll (Triv121PgTbl pt)
-{
- unsigned long n = pt->size / sizeof (PTERec);
- unsigned long i;
- APte pte;
- for (i = 0, pte = pt->base; i < n; i++, pte++)
- pte->marked = 0;
-
-}
-
-/* calculate the minimal size of a page/hash table
- * to map a range of 'size' bytes in EA space.
- *
- * RETURNS: size in 'number of bits', i.e. the
- * integer part of LOGbase2(minsize)
- * is returned.
- * NOTE: G3/G4 machines need at least 16 bits
- * (64k).
- */
-unsigned long
-triv121PgTblLdMinSize (unsigned long size)
-{
- unsigned long i;
- /* round 'size' up to the next page boundary */
- size += (1 << LD_PG_SIZE) - 1;
- size &= ~((1 << LD_PG_SIZE) - 1);
- /* divide by number of PTEs and multiply
- * by the size of a PTE.
- */
- size >>= LD_PG_SIZE - LD_PTE_SIZE;
- /* find the next power of 2 >= size */
- for (i = 0; i < LD_PHYS_SIZE; i++) {
- if ((1 << i) >= size)
- break;
- }
- /* pop up to the allowed minimum, if necessary */
- if (i < LD_MIN_PT_SIZE)
- i = LD_MIN_PT_SIZE;
- return i;
-}
-
-/* initialize a trivial page table of 2^ldSize bytes
- * at 'base' in memory.
- *
- * RETURNS: OPAQUE HANDLE (not the hash table address)
- * or NULL on failure.
- */
-Triv121PgTbl
-triv121PgTblInit (unsigned long base, unsigned ldSize)
-{
- if (pgTbl.size) {
- /* already initialized */
- return 0;
- }
-
- if (ldSize < LD_MIN_PT_SIZE)
- return 0; /* too small */
-
- if (base & ((1 << ldSize) - 1))
- return 0; /* misaligned */
-
- /* This was tested on 604r, 750 and 7400.
- * On other CPUs, verify that the TLB invalidation works
- * for a new CPU variant and that it has hardware PTE lookup/
- * TLB replacement before adding it to this list.
- *
- * NOTE: The 603 features no hardware PTE lookup - and
- * hence the page tables should NOT be used.
- * Although lookup could be implemented in
- * software this is probably not desirable
- * as it could have an impact on hard realtime
- * performance, screwing deterministic latency!
- * (Could still be useful for debugging, though)
- */
- if ( ! ppc_cpu_has_hw_ptbl_lkup() )
- return 0; /* unsupported by this CPU */
-
- pgTbl.base = (APte) base;
- pgTbl.size = 1 << ldSize;
- /* clear all page table entries */
- memset (pgTbl.base, 0, pgTbl.size);
-
- CONSCHECK (0);
-
- /* map the page table itself 'm' and 'readonly' */
- if (triv121PgTblMap (&pgTbl,
- TRIV121_121_VSID,
- base,
- (pgTbl.size >> LD_PG_SIZE),
- TRIV121_ATTR_M, TRIV121_PP_RO_PAGE) >= 0)
- return 0;
-
- CONSCHECK ((pgTbl.size >> LD_PG_SIZE));
-
- return &pgTbl;
-}
-
-/* return the handle of the (one and only) page table
- * or NULL if none has been initialized yet.
- */
-Triv121PgTbl
-triv121PgTblGet (void)
-{
- return pgTbl.size ? &pgTbl : 0;
-}
-
-/* NOTE: this routine returns -1 on success;
- * on failure, the page table index for
- * which no PTE could be allocated is returned
- *
- * (Consult header about argument/return value
- * description)
- */
-long
-triv121PgTblMap (Triv121PgTbl pt,
- long ovsid,
- unsigned long start,
- unsigned long numPages,
- unsigned attributes, unsigned protection)
-{
- int i, pass;
- unsigned long pi;
- APte pte;
- long vsid;
-#ifdef DEBUG
- long saved_vsid = ovsid;
-#endif
-
- if (TRIV121_121_VSID == ovsid) {
- /* use 1:1 mapping */
- ovsid = VSID121 (start);
- } else if (TRIV121_SEG_VSID == ovsid) {
- ovsid = seg2vsid (start);
- }
-
-#ifdef DEBUG
- PRINTF ("Mapping %i (0x%x) pages at 0x%08x for VSID 0x%08x\n",
- (unsigned) numPages, (unsigned) numPages,
- (unsigned) start, (unsigned) ovsid);
-#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), vsid = ovsid; i < numPages; i++, pi++) {
- if (pi >= 1 << LD_PI_SIZE) {
- vsid++;
- pi = 0;
- }
- /* 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->marked = 0;
- if (pt->active) {
- uint32_t flags;
- rtems_interrupt_disable (flags);
- /* order setting 'v' after writing everything else */
- __asm__ volatile ("eieio":::"memory");
- pte->v = 1;
- __asm__ volatile ("sync":::"memory");
- rtems_interrupt_enable (flags);
- } else {
- pte->v = 1;
- }
-
-#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 (saved_vsid, 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 long
-triv121PgTblSDR1 (Triv121PgTbl pt)
-{
- return (((unsigned long) pt->base) & ~((1 << LD_MIN_PT_SIZE) - 1)) |
- (((pt->size - 1) >> LD_MIN_PT_SIZE) &
- ((1 << (LD_HASH_SIZE - (LD_MIN_PT_SIZE - LD_PTEG_SIZE))) - 1)
- );
-}
-
-void
-triv121PgTblActivate (Triv121PgTbl pt)
-{
-#ifndef DEBUG_MAIN
- unsigned long sdr1 = triv121PgTblSDR1 (pt);
- register unsigned long tmp0 = 16; /* initial counter value (#segment regs) */
- register unsigned long tmp1 = (KEY_USR | KEY_SUP);
- register unsigned long tmp2 = (MSR_EE | MSR_IR | MSR_DR);
-#endif
- pt->active = 1;
-
-#ifndef DEBUG_MAIN
-#ifdef DEBUG_EXC
- /* install our exception handler */
- ohdl = globalExceptHdl;
- globalExceptHdl = myhdl;
- __asm__ __volatile__ ("sync"::"memory");
-#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 %[tmp0]\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 %[tmp0]\n"
- " andc %[tmp2], %[tmp0], %[tmp2]\n"
- " mtmsr %[tmp2]\n"
- " isync \n"
- /* set up the segment registers */
- " li %[tmp2], 0\n"
- "1: mtsrin %[tmp1], %[tmp2]\n"
- " addis %[tmp2], %[tmp2], 0x1000\n" /* address next SR */
- " addi %[tmp1], %[tmp1], 1\n" /* increment VSID */
- " bdnz 1b\n"
- /* Now flush all TLBs, starting with the topmost index */
- " lis %[tmp2], %[ea_range]@h\n"
- "2: addic. %[tmp2], %[tmp2], -%[pg_sz]\n" /* address the next one (decrementing) */
- " tlbie %[tmp2]\n" /* invalidate & repeat */
- " bgt 2b\n"
- " eieio \n"
- " tlbsync \n"
- " sync \n"
- /* set up SDR1 */
- " mtspr %[sdr1], %[sdr1val]\n"
- /* restore original MSR */
- " mtmsr %[tmp0]\n"
- " isync \n"
- :[tmp0]"+r&"(tmp0), [tmp1]"+b&"(tmp1), [tmp2]"+b&"(tmp2)
- :[ea_range]"i"(FLUSH_EA_RANGE), [pg_sz]"i" (1 << LD_PG_SIZE),
- [sdr1]"i"(SDR1), [sdr1val]"r" (sdr1)
- :"ctr", "cc", "memory"
- );
-
- /* 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 void
-myhdl (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.
- */
-static unsigned long
-triv121PgTblConsistency (Triv121PgTbl pt, int pass, int expected)
-{
- APte pte;
- int i;
- unsigned v, m;
- int warn = 0;
- int errs = 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 ( /* T.S: allow any VSID... (*lp & (0xfffff0 << 7)) || */ (*(lp + 1) & 0xe00)
- || (pte->v && pte->marked)) {
- /* check for vsid (without segment bits) == 0, unused bits == 0, valid && marked */
- sprintf (buf, "unused bits or v && m");
- err = 1;
- } else {
- if ( (*lp & (0xfffff0 << 7)) ) {
- sprintf(buf,"(warning) non-1:1 VSID found");
- err = 2;
- }
- 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);
- if ( err & 2 ) {
- warn++;
- } else {
- errs++;
- }
- maxw--;
- }
- }
- if (errs) {
- PRINTF ("%i errors %s", errs, warn ? "and ":"");
- }
- if (warn) {
- PRINTF ("%i warnings ",warn);
- }
- if (errs || warn) {
- PRINTF ("found; currently %i entries marked, %i are valid\n",
- 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;
-}
-#endif
-
-/* Find the PTE for a EA and print its contents
- * RETURNS: pte for EA or NULL if no entry was found.
- */
-APte
-triv121DumpEa (unsigned long ea)
-{
- APte pte;
-
- pte =
- alreadyMapped (&pgTbl, pgTbl.active ? TRIV121_SEG_VSID : TRIV121_121_VSID,
- ea);
-
- if (pte)
- dumpPte (pte);
- return pte;
-}
-
-APte
-triv121FindPte (unsigned long vsid, unsigned long pi)
-{
- return alreadyMapped (&pgTbl, vsid, pi);
-}
-
-APte
-triv121UnmapEa (unsigned long ea)
-{
- uint32_t flags;
- APte pte;
-
- if (!pgTbl.active) {
- pte = alreadyMapped (&pgTbl, TRIV121_121_VSID, ea);
- if (pte) /* alreadyMapped checks for pte->v */
- pte->v = 0;
- return pte;
- }
-
- pte = alreadyMapped (&pgTbl, TRIV121_SEG_VSID, ea);
-
- if (!pte)
- return 0;
-
- rtems_interrupt_disable (flags);
- pte->v = 0;
- do_dssall ();
- __asm__ volatile (" sync \n\t"
- " tlbie %0 \n\t"
- " eieio \n\t"
- " tlbsync \n\t"
- " sync \n\t"::"r" (ea):"memory");
- rtems_interrupt_enable (flags);
- return pte;
-}
-
-/* A context synchronizing jump */
-#define SYNC_LONGJMP(msr) \
- asm volatile( \
- " mtsrr1 %0 \n\t" \
- " bl 1f \n\t" \
- "1: mflr 3 \n\t" \
- " addi 3,3,1f-1b \n\t" \
- " mtsrr0 3 \n\t" \
- " rfi \n\t" \
- "1: \n\t" \
- : \
- :"r"(msr) \
- :"3","lr","memory")
-
-/* The book doesn't mention dssall when changing PTEs
- * but they require it for BAT changes and I guess
- * it makes sense in the case of PTEs as well.
- * Just do it to be on the safe side...
- */
-static void
-do_dssall (void)
-{
- /* Before changing BATs, 'dssall' must be issued.
- * We check MSR for MSR_VE and issue a 'dssall' if
- * MSR_VE is set hoping that
- * a) on non-altivec CPUs MSR_VE reads as zero
- * b) all altivec CPUs use the same bit
- *
- * NOTE: psim doesn't implement dssall so we skip if we run on psim
- */
- if ( (_read_MSR () & MSR_VE) && PPC_PSIM != get_ppc_cpu_type() ) {
- /* this construct is needed because we don't know
- * if this file is compiled with -maltivec.
- * (I plan to add altivec support outside of
- * RTEMS core and hence I'd rather not
- * rely on consistent compiler flags).
- */
-#define DSSALL 0x7e00066c /* dssall opcode */
- __asm__ volatile (" .long %0"::"i" (DSSALL));
-#undef DSSALL
- }
-}
-
-APte
-triv121ChangeEaAttributes (unsigned long ea, int wimg, int pp)
-{
- APte pte;
- unsigned long msr;
-
- if (!pgTbl.active) {
- pte = alreadyMapped (&pgTbl, TRIV121_121_VSID, ea);
- if (!pte)
- return 0;
- if (wimg > 0)
- pte->wimg = wimg;
- if (pp > 0)
- pte->pp = pp;
- return pte;
- }
-
- pte = alreadyMapped (&pgTbl, TRIV121_SEG_VSID, ea);
-
- if (!pte)
- return 0;
-
- if (wimg < 0 && pp < 0)
- return pte;
-
- __asm__ volatile ("mfmsr %0":"=r" (msr));
-
- /* switch MMU and IRQs off */
- SYNC_LONGJMP (msr & ~(MSR_EE | MSR_DR | MSR_IR));
-
- pte->v = 0;
- do_dssall ();
- __asm__ volatile ("sync":::"memory");
- if (wimg >= 0)
- pte->wimg = wimg;
- if (pp >= 0)
- pte->pp = pp;
- __asm__ volatile ("tlbie %0; eieio"::"r" (ea):"memory");
- pte->v = 1;
- __asm__ volatile ("tlbsync; sync":::"memory");
-
- /* restore, i.e., switch MMU and IRQs back on */
- SYNC_LONGJMP (msr);
-
- return pte;
-}
-
-static void
-pgtblChangePP (Triv121PgTbl pt, int pp)
-{
- unsigned long n = pt->size >> LD_PG_SIZE;
- unsigned long b, i;
-
- for (i = 0, b = (unsigned long) pt->base; i < n;
- i++, b += (1 << LD_PG_SIZE)) {
- triv121ChangeEaAttributes (b, -1, pp);
- }
-}
-
-void
-triv121MakePgTblRW ()
-{
- pgtblChangePP (&pgTbl, TRIV121_PP_RW_PAGE);
-}
-
-void
-triv121MakePgTblRO ()
-{
- pgtblChangePP (&pgTbl, TRIV121_PP_RO_PAGE);
-}
-
-long
-triv121DumpPte (APte pte)
-{
- if (pte)
- dumpPte (pte);
- return 0;
-}
-
-
-#ifdef DEBUG
-/* Dump an entire PTEG */
-
-static void
-dumpPteg (unsigned long vsid, unsigned long pi, unsigned long hash)
-{
- APte 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));
- }
-}
-#endif
-
-/* Verify that a range of addresses is mapped the page table.
- * start/end are segment offsets or EAs (if vsid has one of
- * the special values), respectively.
- *
- * 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 long
-triv121IsRangeMapped (long vsid, unsigned long start, unsigned long end)
-{
-unsigned pi;
-
- start &= ~((1 << LD_PG_SIZE) - 1);
- while (start < end) {
- if ( TRIV121_SEG_VSID != vsid && TRIV121_121_VSID != vsid )
- pi = PI121(start);
- else
- pi = start;
- if (!alreadyMapped (&pgTbl, vsid, pi))
- return start;
- start += 1 << LD_PG_SIZE;
- }
- return 0x0C0C; /* OKOK - not on a page boundary */
-}
-
-
-#include <stdlib.h>
-
-/* print a PTE */
-static void
-dumpPte (APte 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");
- }
-}
-
-
-#if defined(DEBUG_MAIN)
-/* 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
- */
-int
-triv121PgTblDump (Triv121PgTbl pt, unsigned from, unsigned to)
-{
- int i;
- APte 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;
-}
-
-
-
-#define LD_DBG_PT_SIZE LD_MIN_PT_SIZE
-
-int
-main (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