forked from Imagelibrary/rtems
libcpu/powerpc/e500/mmu/mmu.c: Fix warnings
This commit is contained in:
@@ -22,13 +22,13 @@
|
|||||||
* ----------
|
* ----------
|
||||||
* This software was created by
|
* This software was created by
|
||||||
* Till Straumann <strauman@slac.stanford.edu>, 2005-2007,
|
* Till Straumann <strauman@slac.stanford.edu>, 2005-2007,
|
||||||
* Stanford Linear Accelerator Center, Stanford University.
|
* Stanford Linear Accelerator Center, Stanford University.
|
||||||
*
|
*
|
||||||
* Acknowledgement of sponsorship
|
* Acknowledgement of sponsorship
|
||||||
* ------------------------------
|
* ------------------------------
|
||||||
* This software was produced by
|
* This software was produced by
|
||||||
* the Stanford Linear Accelerator Center, Stanford University,
|
* the Stanford Linear Accelerator Center, Stanford University,
|
||||||
* under Contract DE-AC03-76SFO0515 with the Department of Energy.
|
* under Contract DE-AC03-76SFO0515 with the Department of Energy.
|
||||||
*
|
*
|
||||||
* Government disclaimer of liability
|
* Government disclaimer of liability
|
||||||
* ----------------------------------
|
* ----------------------------------
|
||||||
@@ -76,13 +76,13 @@
|
|||||||
|
|
||||||
#include "e500_mmu.h"
|
#include "e500_mmu.h"
|
||||||
|
|
||||||
#define TLBIVAX_TLBSEL (1<<(63-60))
|
#define TLBIVAX_TLBSEL (1<<(63-60))
|
||||||
#define TLBIVAX_INV_ALL (1<<(63-61))
|
#define TLBIVAX_INV_ALL (1<<(63-61))
|
||||||
|
|
||||||
#define E500_TLB_ATTR_WIMGE(x) ((x)&0x7f) /* includes user bits */
|
#define E500_TLB_ATTR_WIMGE(x) ((x)&0x7f) /* includes user bits */
|
||||||
#define E500_TLB_ATTR_WIMGE_GET(x) ((x)&0x7f)
|
#define E500_TLB_ATTR_WIMGE_GET(x) ((x)&0x7f)
|
||||||
#define E500_TLB_ATTR_TS (1<<7)
|
#define E500_TLB_ATTR_TS (1<<7)
|
||||||
#define E500_TLB_ATTR_PERM(x) (((x)&0x3ff)<<8)
|
#define E500_TLB_ATTR_PERM(x) (((x)&0x3ff)<<8)
|
||||||
#define E500_TLB_ATTR_PERM_GET(x) (((x)>>8)&0x3ff)
|
#define E500_TLB_ATTR_PERM_GET(x) (((x)>>8)&0x3ff)
|
||||||
#define E500_TLB_ATTR_TID(x) (((x)&0xfff)<<20)
|
#define E500_TLB_ATTR_TID(x) (((x)&0xfff)<<20)
|
||||||
#define E500_TLB_ATTR_TID_GET(x) (((x)>>20)&0xfff)
|
#define E500_TLB_ATTR_TID_GET(x) (((x)>>20)&0xfff)
|
||||||
@@ -95,11 +95,11 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Factory to generate inline macros for accessing the MAS registers */
|
/* Factory to generate inline macros for accessing the MAS registers */
|
||||||
#define __RDWRMAS(mas,rmas) \
|
#define __RDWRMAS(mas,rmas) \
|
||||||
static inline uint32_t _read_MAS##mas(void) \
|
static inline uint32_t _read_MAS##mas(void) \
|
||||||
{ uint32_t x; __asm__ volatile("mfspr %0, %1": "=r"(x):"i"(rmas)); return x; } \
|
{ uint32_t x; __asm__ volatile("mfspr %0, %1": "=r"(x):"i"(rmas)); return x; } \
|
||||||
static inline void _write_MAS##mas(uint32_t x) \
|
static inline void _write_MAS##mas(uint32_t x) \
|
||||||
{ __asm__ volatile("mtspr %1, %0":: "r"(x),"i"(rmas)); }
|
{ __asm__ volatile("mtspr %1, %0":: "r"(x),"i"(rmas)); }
|
||||||
|
|
||||||
__RDWRMAS(0,FSL_EIS_MAS0)
|
__RDWRMAS(0,FSL_EIS_MAS0)
|
||||||
__RDWRMAS(1,FSL_EIS_MAS1)
|
__RDWRMAS(1,FSL_EIS_MAS1)
|
||||||
@@ -121,19 +121,19 @@ E500_tlb_va_cache_t rtems_e500_tlb_va_cache[16];
|
|||||||
static void
|
static void
|
||||||
myprintf(FILE *f, char *fmt, ...)
|
myprintf(FILE *f, char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
|
|
||||||
if (!f || !_impure_ptr->__sdidinit) {
|
if (!f || !_impure_ptr->__sdidinit) {
|
||||||
/*
|
/*
|
||||||
* Might be called at an early stage when
|
* Might be called at an early stage when
|
||||||
* stdio is not yet initialized.
|
* stdio is not yet initialized.
|
||||||
*/
|
*/
|
||||||
vprintk(fmt,ap);
|
vprintk(fmt,ap);
|
||||||
} else {
|
} else {
|
||||||
vfprintf(f,fmt,ap);
|
vfprintf(f,fmt,ap);
|
||||||
}
|
}
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -141,38 +141,38 @@ void
|
|||||||
rtems_e500_dmptlbc(FILE *f)
|
rtems_e500_dmptlbc(FILE *f)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
if ( !initialized ) {
|
if ( !initialized ) {
|
||||||
myprintf(stderr,"TLB cache not initialized\n");
|
myprintf(stderr,"TLB cache not initialized\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for ( i=0; i<16; i++ ) {
|
for ( i=0; i<16; i++ ) {
|
||||||
if ( !rtems_e500_tlb_va_cache[i].att.v )
|
if ( !rtems_e500_tlb_va_cache[i].att.v )
|
||||||
continue;
|
continue;
|
||||||
myprintf(f,"#%2i: TID 0x%03x, TS %i, ea 0x%08x .. 0x%08x\n",
|
myprintf(f,"#%2i: TID 0x%03x, TS %i, ea 0x%08x .. 0x%08x\n",
|
||||||
i,
|
i,
|
||||||
rtems_e500_tlb_va_cache[i].va.va_tid,
|
rtems_e500_tlb_va_cache[i].va.va_tid,
|
||||||
rtems_e500_tlb_va_cache[i].att.ts,
|
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,
|
||||||
(rtems_e500_tlb_va_cache[i].va.va_epn<<12) + (1024<<(2*rtems_e500_tlb_va_cache[i].att.sz))-1);
|
(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",
|
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].rpn<<12,
|
||||||
rtems_e500_tlb_va_cache[i].att.perm,
|
rtems_e500_tlb_va_cache[i].att.perm,
|
||||||
rtems_e500_tlb_va_cache[i].att.wimge);
|
rtems_e500_tlb_va_cache[i].att.wimge);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define E500_SELTLB_1 0x1000
|
#define E500_SELTLB_1 0x1000
|
||||||
|
|
||||||
static void seltlb(rtems_e500_tlb_idx key)
|
static void seltlb(rtems_e500_tlb_idx key)
|
||||||
{
|
{
|
||||||
int idx = key & ~E500_SELTLB_1;
|
int idx = key & ~E500_SELTLB_1;
|
||||||
|
|
||||||
if ( key & E500_SELTLB_1 ) {
|
if ( key & E500_SELTLB_1 ) {
|
||||||
_write_MAS0( FSL_EIS_MAS0_TLBSEL | FSL_EIS_MAS0_ESEL(idx) );
|
_write_MAS0( FSL_EIS_MAS0_TLBSEL | FSL_EIS_MAS0_ESEL(idx) );
|
||||||
} else {
|
} else {
|
||||||
_write_MAS0( (idx & 128) ? FSL_EIS_MAS0_ESEL(1) : FSL_EIS_MAS0_ESEL(0) );
|
_write_MAS0( (idx & 128) ? FSL_EIS_MAS0_ESEL(1) : FSL_EIS_MAS0_ESEL(0) );
|
||||||
_write_MAS2( FSL_EIS_MAS2_EPN( idx & 127 ) );
|
_write_MAS2( FSL_EIS_MAS2_EPN( idx & 127 ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -199,84 +199,84 @@ int idx = key & ~E500_SELTLB_1;
|
|||||||
int
|
int
|
||||||
rtems_e500_prtlb(rtems_e500_tlb_idx key, int quiet, FILE *f)
|
rtems_e500_prtlb(rtems_e500_tlb_idx key, int quiet, FILE *f)
|
||||||
{
|
{
|
||||||
uint32_t mas0, mas1, mas2, mas3;
|
uint32_t mas1, mas2, mas3;
|
||||||
rtems_interrupt_level lvl;
|
rtems_interrupt_level lvl;
|
||||||
E500_tlb_va_cache_t *tlb;
|
E500_tlb_va_cache_t *tlb;
|
||||||
E500_tlb_va_cache_t buf;
|
E500_tlb_va_cache_t buf;
|
||||||
int sel, idx;
|
int sel, idx;
|
||||||
|
|
||||||
sel = (key & E500_SELTLB_1) ? 1 : 0;
|
sel = (key & E500_SELTLB_1) ? 1 : 0;
|
||||||
idx = key & ~E500_SELTLB_1;
|
idx = key & ~E500_SELTLB_1;
|
||||||
|
|
||||||
if ( idx < 0 || idx > 255 || ( idx > 15 && sel ) )
|
if ( idx < 0 || idx > 255 || ( idx > 15 && sel ) )
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
rtems_interrupt_disable(lvl);
|
rtems_interrupt_disable(lvl);
|
||||||
|
|
||||||
seltlb( key );
|
seltlb( key );
|
||||||
|
|
||||||
asm volatile("tlbre");
|
asm volatile("tlbre");
|
||||||
|
|
||||||
mas0 = _read_MAS0();
|
/* not manipulating MAS0, skip reading it */
|
||||||
mas1 = _read_MAS1();
|
mas1 = _read_MAS1();
|
||||||
mas2 = _read_MAS2();
|
mas2 = _read_MAS2();
|
||||||
mas3 = _read_MAS3();
|
mas3 = _read_MAS3();
|
||||||
|
|
||||||
rtems_interrupt_enable(lvl);
|
rtems_interrupt_enable(lvl);
|
||||||
|
|
||||||
tlb = sel ? rtems_e500_tlb_va_cache + idx : &buf;
|
tlb = sel ? rtems_e500_tlb_va_cache + idx : &buf;
|
||||||
|
|
||||||
if ( (tlb->att.v = (FSL_EIS_MAS1_V & mas1) ? 1 : 0) ) {
|
if ( (tlb->att.v = (FSL_EIS_MAS1_V & mas1) ? 1 : 0) ) {
|
||||||
tlb->va.va_epn = FSL_EIS_MAS2_EPN_GET(mas2);
|
tlb->va.va_epn = FSL_EIS_MAS2_EPN_GET(mas2);
|
||||||
tlb->rpn = FSL_EIS_MAS3_RPN_GET(mas3);
|
tlb->rpn = FSL_EIS_MAS3_RPN_GET(mas3);
|
||||||
tlb->va.va_tid = FSL_EIS_MAS1_TID_GET(mas1);
|
tlb->va.va_tid = FSL_EIS_MAS1_TID_GET(mas1);
|
||||||
tlb->att.ts = (FSL_EIS_MAS1_TS & mas1) ? 1 : 0;
|
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.sz = sel ? FSL_EIS_MAS1_TSIZE_GET(mas1) : 1 /* 4k size */;
|
||||||
tlb->att.wimge = FSL_EIS_MAS2_ATTR_GET(mas2);
|
tlb->att.wimge = FSL_EIS_MAS2_ATTR_GET(mas2);
|
||||||
tlb->att.perm = FSL_EIS_MAS3_PERM_GET(mas3);
|
tlb->att.perm = FSL_EIS_MAS3_PERM_GET(mas3);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( tlb->att.v ) {
|
if ( tlb->att.v ) {
|
||||||
if ( !quiet ) {
|
if ( !quiet ) {
|
||||||
/*
|
/*
|
||||||
"TLB[1] Entry # 0 spans EA range 0x00000000 .. 0x00000000
|
"TLB[1] Entry # 0 spans EA range 0x00000000 .. 0x00000000
|
||||||
"Mapping: VA [TS 0/TID 0x00/EPN 0x00000] -> RPN 0x00000"
|
"Mapping: VA [TS 0/TID 0x00/EPN 0x00000] -> RPN 0x00000"
|
||||||
"Size: TSIZE 0x0 ( 4^ts KiB = 000000 KiB = 0x00000000 B)
|
"Size: TSIZE 0x0 ( 4^ts KiB = 000000 KiB = 0x00000000 B)
|
||||||
"Attributes: PERM 0x000 (ux/sx/uw/sw/ur/sr) WIMGE 0x00 IPROT 0"
|
"Attributes: PERM 0x000 (ux/sx/uw/sw/ur/sr) WIMGE 0x00 IPROT 0"
|
||||||
*/
|
*/
|
||||||
myprintf(f,
|
myprintf(f,
|
||||||
"TLB[%i] Entry # %d spans EA range 0x%08x .. 0x%08x\r\n",
|
"TLB[%i] Entry # %d spans EA range 0x%08x .. 0x%08x\r\n",
|
||||||
sel,
|
sel,
|
||||||
idx,
|
idx,
|
||||||
(tlb->va.va_epn << 12),
|
(tlb->va.va_epn << 12),
|
||||||
(tlb->va.va_epn << 12) + (1024<<(2*tlb->att.sz)) - 1
|
(tlb->va.va_epn << 12) + (1024<<(2*tlb->att.sz)) - 1
|
||||||
);
|
);
|
||||||
|
|
||||||
myprintf(f,
|
myprintf(f,
|
||||||
"Mapping: VA [TS %d/TID 0x%02x/EPN 0x%05x] -> RPN 0x%05"PRIx32"\r\n",
|
"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
|
tlb->att.ts, tlb->va.va_tid, tlb->va.va_epn, tlb->rpn
|
||||||
);
|
);
|
||||||
myprintf(f,
|
myprintf(f,
|
||||||
"Size: TSIZE 0x%x ( 4^ts KiB = %6d KiB = 0x%08x B)\r\n",
|
"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))
|
tlb->att.sz, (1<<(2*tlb->att.sz)), (1024<<(2*tlb->att.sz))
|
||||||
);
|
);
|
||||||
myprintf(f,
|
myprintf(f,
|
||||||
"Attributes: PERM 0x%03x (ux/sx/uw/sw/ur/sr) WIMGE 0x%02x IPROT %i\r\n",
|
"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)
|
tlb->att.perm, tlb->att.wimge, (sel && (mas1 & FSL_EIS_MAS1_IPROT) ? 1 : 0)
|
||||||
);
|
);
|
||||||
myprintf(f,
|
myprintf(f,
|
||||||
"EA range 0x%08x .. 0x%08x\r\n",
|
"EA range 0x%08x .. 0x%08x\r\n",
|
||||||
(tlb->va.va_epn << 12),
|
(tlb->va.va_epn << 12),
|
||||||
(tlb->va.va_epn << 12) + (1024<<(2*tlb->att.sz)) - 1
|
(tlb->va.va_epn << 12) + (1024<<(2*tlb->att.sz)) - 1
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ( !quiet ) {
|
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)));
|
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 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize cache; verify that TLB0 is unused;
|
/* Initialize cache; verify that TLB0 is unused;
|
||||||
@@ -290,22 +290,22 @@ int rtems_e500_initlb()
|
|||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
int rval = 0;
|
int rval = 0;
|
||||||
for (i=0; i<16; i++)
|
for (i=0; i<16; i++)
|
||||||
rtems_e500_prtlb(E500_SELTLB_1 | i, 1, 0);
|
rtems_e500_prtlb(E500_SELTLB_1 | i, 1, 0);
|
||||||
for (i=0; i<256; i++) {
|
for (i=0; i<256; i++) {
|
||||||
/* refuse to enable operations that change TLB entries
|
/* refuse to enable operations that change TLB entries
|
||||||
* if anything in TLB[0] is valid (because we currently
|
* if anything in TLB[0] is valid (because we currently
|
||||||
* don't check against overlap with TLB[0] when we
|
* don't check against overlap with TLB[0] when we
|
||||||
* write a new entry).
|
* write a new entry).
|
||||||
*/
|
*/
|
||||||
if ( rtems_e500_prtlb(E500_SELTLB_0 | i, 1, 0) <=0 ) {
|
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);
|
myprintf(stderr,"WARNING: 4k TLB #%i seems to be valid; UNSUPPORTED configuration\n", i);
|
||||||
rval = -1;
|
rval = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( !rval )
|
if ( !rval )
|
||||||
initialized = 1;
|
initialized = 1;
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -343,10 +343,10 @@ int rval = 0;
|
|||||||
* <0: other error
|
* <0: other error
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#define E500_TLB_ATTR_WIMGE(x) ((x)&0x7f) /* includes user bits */
|
#define E500_TLB_ATTR_WIMGE(x) ((x)&0x7f) /* includes user bits */
|
||||||
#define E500_TLB_ATTR_WIMGE_GET(x) ((x)&0x7f)
|
#define E500_TLB_ATTR_WIMGE_GET(x) ((x)&0x7f)
|
||||||
#define E500_TLB_ATTR_TS (1<<7)
|
#define E500_TLB_ATTR_TS (1<<7)
|
||||||
#define E500_TLB_ATTR_PERM(x) (((x)&0x3ff)<<8)
|
#define E500_TLB_ATTR_PERM(x) (((x)&0x3ff)<<8)
|
||||||
#define E500_TLB_ATTR_PERM_GET(x) (((x)>>8)&0x3ff)
|
#define E500_TLB_ATTR_PERM_GET(x) (((x)>>8)&0x3ff)
|
||||||
#define E500_TLB_ATTR_TID(x) (((x)&0xfff)<<20)
|
#define E500_TLB_ATTR_TID(x) (((x)&0xfff)<<20)
|
||||||
#define E500_TLB_ATTR_TID_GET(x) (((x)>>20)&0xfff)
|
#define E500_TLB_ATTR_TID_GET(x) (((x)>>20)&0xfff)
|
||||||
@@ -359,94 +359,94 @@ uint32_t tid, msk;
|
|||||||
int lkup;
|
int lkup;
|
||||||
rtems_interrupt_level lvl;
|
rtems_interrupt_level lvl;
|
||||||
|
|
||||||
if ( sz >= 1024 ) {
|
if ( sz >= 1024 ) {
|
||||||
/* Assume they literally specify a size */
|
/* Assume they literally specify a size */
|
||||||
msk = sz;
|
msk = sz;
|
||||||
sz = 0;
|
sz = 0;
|
||||||
while ( msk != (1024<<(2*sz)) ) {
|
while ( msk != (1024<<(2*sz)) ) {
|
||||||
if ( ++sz > 15 ) {
|
if ( ++sz > 15 ) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* OK, acceptable */
|
/* OK, acceptable */
|
||||||
}
|
}
|
||||||
|
|
||||||
msk = sz > 0 ? (1024<<(2*sz)) - 1 : 0;
|
msk = sz > 0 ? (1024<<(2*sz)) - 1 : 0;
|
||||||
|
|
||||||
if ( !initialized && sz > 0 ) {
|
if ( !initialized && sz > 0 ) {
|
||||||
myprintf(stderr,"TLB driver not initialized; refuse to enable any entry\n");
|
myprintf(stderr,"TLB driver not initialized; refuse to enable any entry\n");
|
||||||
return -3;
|
return -3;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( (ea & msk) || (pa & msk) ) {
|
if ( (ea & msk) || (pa & msk) ) {
|
||||||
myprintf(stderr,"Misaligned ea or pa\n");
|
myprintf(stderr,"Misaligned ea or pa\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( idx < 0 || idx > 15 )
|
if ( idx < 0 || idx > 15 )
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if ( sz > 15 ) {
|
if ( sz > 15 ) {
|
||||||
/* but e500v1 doesn't support all 16 sizes!! */
|
/* but e500v1 doesn't support all 16 sizes!! */
|
||||||
/* FIXME: we should inquire about this CPU's
|
/* FIXME: we should inquire about this CPU's
|
||||||
* capabilities...
|
* capabilities...
|
||||||
*/
|
*/
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
tid = E500_TLB_ATTR_TID_GET(attr);
|
tid = E500_TLB_ATTR_TID_GET(attr);
|
||||||
|
|
||||||
mas1 = (attr & E500_TLB_ATTR_TS) ? FSL_EIS_MAS1_TS : 0;
|
mas1 = (attr & E500_TLB_ATTR_TS) ? FSL_EIS_MAS1_TS : 0;
|
||||||
|
|
||||||
if ( sz >=0 ) {
|
if ( sz >=0 ) {
|
||||||
lkup = rtems_e500_matchtlb(ea, tid, mas1, sz);
|
lkup = rtems_e500_matchtlb(ea, tid, mas1, sz);
|
||||||
|
|
||||||
if ( lkup < -1 ) {
|
if ( lkup < -1 ) {
|
||||||
/* some error */
|
/* some error */
|
||||||
return lkup;
|
return lkup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( lkup >= 0 && lkup != idx ) {
|
if ( lkup >= 0 && lkup != idx ) {
|
||||||
myprintf(stderr,"TLB[1] #%i overlaps with requested mapping\n", lkup);
|
myprintf(stderr,"TLB[1] #%i overlaps with requested mapping\n", lkup);
|
||||||
rtems_e500_prtlb( E500_SELTLB_1 | lkup, 0, stderr);
|
rtems_e500_prtlb( E500_SELTLB_1 | lkup, 0, stderr);
|
||||||
return lkup+1;
|
return lkup+1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* OK to proceed */
|
/* OK to proceed */
|
||||||
mas1 |= FSL_EIS_MAS1_IPROT | FSL_EIS_MAS1_TID(tid);
|
mas1 |= FSL_EIS_MAS1_IPROT | FSL_EIS_MAS1_TID(tid);
|
||||||
|
|
||||||
if ( sz >= 0 )
|
if ( sz >= 0 )
|
||||||
mas1 |= FSL_EIS_MAS1_V | FSL_EIS_MAS1_TSIZE(sz);
|
mas1 |= FSL_EIS_MAS1_V | FSL_EIS_MAS1_TSIZE(sz);
|
||||||
|
|
||||||
mas2 = FSL_EIS_MAS2_EPN( ea>>12 ) | E500_TLB_ATTR_WIMGE(attr);
|
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);
|
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 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;
|
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);
|
rtems_interrupt_disable(lvl);
|
||||||
|
|
||||||
seltlb(idx | E500_SELTLB_1);
|
seltlb(idx | E500_SELTLB_1);
|
||||||
|
|
||||||
_write_MAS1(mas1);
|
_write_MAS1(mas1);
|
||||||
_write_MAS2(mas2);
|
_write_MAS2(mas2);
|
||||||
_write_MAS3(mas3);
|
_write_MAS3(mas3);
|
||||||
_write_MAS4(mas4);
|
_write_MAS4(mas4);
|
||||||
|
|
||||||
asm volatile(
|
asm volatile(
|
||||||
" sync \n"
|
" sync\n"
|
||||||
" isync \n"
|
" isync\n"
|
||||||
" tlbwe \n"
|
" tlbwe\n"
|
||||||
" sync \n"
|
" sync\n"
|
||||||
" isync \n"
|
" isync\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
rtems_interrupt_enable(lvl);
|
rtems_interrupt_enable(lvl);
|
||||||
|
|
||||||
/* update cache */
|
/* update cache */
|
||||||
rtems_e500_prtlb( E500_SELTLB_1 | idx, 1, 0);
|
rtems_e500_prtlb( E500_SELTLB_1 | idx, 1, 0);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -470,41 +470,41 @@ int i;
|
|||||||
uint32_t m,a;
|
uint32_t m,a;
|
||||||
E500_tlb_va_cache_t *tlb;
|
E500_tlb_va_cache_t *tlb;
|
||||||
|
|
||||||
if ( sz < 0 || sz > 15 )
|
if ( sz < 0 || sz > 15 )
|
||||||
return -4;
|
return -4;
|
||||||
|
|
||||||
sz = (1024<<(2*sz));
|
sz = (1024<<(2*sz));
|
||||||
|
|
||||||
if ( !initialized ) {
|
if ( !initialized ) {
|
||||||
/* cache not initialized */
|
/* cache not initialized */
|
||||||
return -3;
|
return -3;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ea & (sz-1) ) {
|
if ( ea & (sz-1) ) {
|
||||||
/* misaligned ea */
|
/* misaligned ea */
|
||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( ts )
|
if ( ts )
|
||||||
ts = 1;
|
ts = 1;
|
||||||
|
|
||||||
for ( i=0, tlb=rtems_e500_tlb_va_cache; i<16; i++, tlb++ ) {
|
for ( i=0, tlb=rtems_e500_tlb_va_cache; i<16; i++, tlb++ ) {
|
||||||
if ( ! tlb->att.v )
|
if ( ! tlb->att.v )
|
||||||
continue;
|
continue;
|
||||||
if ( tlb->att.ts != ts )
|
if ( tlb->att.ts != ts )
|
||||||
continue;
|
continue;
|
||||||
if ( tlb->va.va_tid && tlb->va.va_tid != tid )
|
if ( tlb->va.va_tid && tlb->va.va_tid != tid )
|
||||||
continue;
|
continue;
|
||||||
/* TID and TS match a valid entry */
|
/* TID and TS match a valid entry */
|
||||||
m = (1024<<(2*tlb->att.sz)) - 1;
|
m = (1024<<(2*tlb->att.sz)) - 1;
|
||||||
/* calculate starting address of this entry */
|
/* calculate starting address of this entry */
|
||||||
a = tlb->va.va_epn<<12;
|
a = tlb->va.va_epn<<12;
|
||||||
if ( ea <= a + m && ea + sz -1 >= a ) {
|
if ( ea <= a + m && ea + sz -1 >= a ) {
|
||||||
/* overlap */
|
/* overlap */
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find TLB index that maps 'ea/as' combination
|
/* Find TLB index that maps 'ea/as' combination
|
||||||
@@ -523,38 +523,38 @@ uint32_t pid, mas0, mas1;
|
|||||||
int i, rval = -1;
|
int i, rval = -1;
|
||||||
rtems_interrupt_level lvl;
|
rtems_interrupt_level lvl;
|
||||||
|
|
||||||
rtems_interrupt_disable(lvl);
|
rtems_interrupt_disable(lvl);
|
||||||
|
|
||||||
for ( i=0; i<3; i++ ) {
|
for ( i=0; i<3; i++ ) {
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case 0: asm volatile("mfspr %0, %1":"=r"(pid):"i"(FSL_EIS_PID0)); break;
|
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 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;
|
case 2: asm volatile("mfspr %0, %1":"=r"(pid):"i"(FSL_EIS_PID2)); break;
|
||||||
default:
|
default:
|
||||||
goto bail;
|
goto bail;
|
||||||
}
|
}
|
||||||
|
|
||||||
_write_MAS6( FSL_EIS_MAS6_SPID0(pid) | (as ? FSL_EIS_MAS6_SAS : 0 ) );
|
_write_MAS6( FSL_EIS_MAS6_SPID0(pid) | (as ? FSL_EIS_MAS6_SAS : 0 ) );
|
||||||
|
|
||||||
asm volatile("tlbsx 0, %0"::"r"(ea));
|
asm volatile("tlbsx 0, %0"::"r"(ea));
|
||||||
|
|
||||||
mas1 = _read_MAS1();
|
mas1 = _read_MAS1();
|
||||||
|
|
||||||
if ( (FSL_EIS_MAS1_V & mas1) ) {
|
if ( (FSL_EIS_MAS1_V & mas1) ) {
|
||||||
mas0 = _read_MAS0();
|
mas0 = _read_MAS0();
|
||||||
if ( FSL_EIS_MAS0_TLBSEL & mas0 ) {
|
if ( FSL_EIS_MAS0_TLBSEL & mas0 ) {
|
||||||
/* TLB1 */
|
/* TLB1 */
|
||||||
rval = FSL_EIS_MAS0_ESEL_GET(mas0) | E500_SELTLB_1;
|
rval = FSL_EIS_MAS0_ESEL_GET(mas0) | E500_SELTLB_1;
|
||||||
} else {
|
} else {
|
||||||
rval = (ea >> (63-51)) | (( FSL_EIS_MAS0_NV & mas0 ) ? 180 : 0 ) ;
|
rval = (ea >> (63-51)) | (( FSL_EIS_MAS0_NV & mas0 ) ? 180 : 0 ) ;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bail:
|
bail:
|
||||||
rtems_interrupt_enable(lvl);
|
rtems_interrupt_enable(lvl);
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mark TLB entry as invalid ('disabled'). Unlike
|
/* Mark TLB entry as invalid ('disabled'). Unlike
|
||||||
@@ -577,55 +577,55 @@ rtems_e500_clrtlb(rtems_e500_tlb_idx key)
|
|||||||
rtems_e500_tlb_idx k0;
|
rtems_e500_tlb_idx k0;
|
||||||
rtems_interrupt_level lvl;
|
rtems_interrupt_level lvl;
|
||||||
|
|
||||||
/* minimal guard against bad key */
|
/* minimal guard against bad key */
|
||||||
if ( key < 0 )
|
if ( key < 0 )
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if ( (key & E500_SELTLB_1) ) {
|
if ( (key & E500_SELTLB_1) ) {
|
||||||
if ( (key & ~E500_SELTLB_1) > 15 ) {
|
if ( (key & ~E500_SELTLB_1) > 15 ) {
|
||||||
myprintf(stderr,"Invalid TLB index; TLB1 index must be < 16\n");
|
myprintf(stderr,"Invalid TLB index; TLB1 index must be < 16\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} else if ( key > 255 ) {
|
} else if ( key > 255 ) {
|
||||||
myprintf(stderr,"Invalid TLB index; TLB0 index must be < 256\n");
|
myprintf(stderr,"Invalid TLB index; TLB0 index must be < 256\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Must not invalidate page 0 which holds vectors, text etc... */
|
/* Must not invalidate page 0 which holds vectors, text etc... */
|
||||||
k0 = rtems_e500_ftlb(0, 0);
|
k0 = rtems_e500_ftlb(0, 0);
|
||||||
if ( -1 == k0 ) {
|
if ( -1 == k0 ) {
|
||||||
myprintf(stderr,"tlbivax; something's fishy - I don't find mapping for addr. 0\n");
|
myprintf(stderr,"tlbivax; something's fishy - I don't find mapping for addr. 0\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* NOTE: we assume PID is ignored, and AS is 0 */
|
/* NOTE: we assume PID is ignored, and AS is 0 */
|
||||||
if ( k0 == key ) {
|
if ( k0 == key ) {
|
||||||
myprintf(stderr,"Refuse to invalidate page holding addr 0 (always needed)\n");
|
myprintf(stderr,"Refuse to invalidate page holding addr 0 (always needed)\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
rtems_interrupt_disable(lvl);
|
rtems_interrupt_disable(lvl);
|
||||||
|
|
||||||
seltlb(key);
|
seltlb(key);
|
||||||
|
|
||||||
asm volatile("tlbre");
|
asm volatile("tlbre");
|
||||||
|
|
||||||
/* read old entries */
|
/* read old entries */
|
||||||
_write_MAS1( _read_MAS1() & ~FSL_EIS_MAS1_V );
|
_write_MAS1( _read_MAS1() & ~FSL_EIS_MAS1_V );
|
||||||
|
|
||||||
asm volatile(
|
asm volatile(
|
||||||
" sync \n"
|
" sync\n"
|
||||||
" isync \n"
|
" isync\n"
|
||||||
" tlbwe \n"
|
" tlbwe\n"
|
||||||
" sync \n"
|
" sync\n"
|
||||||
" isync \n"
|
" isync\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
/* update cache */
|
/* update cache */
|
||||||
if ( E500_SELTLB_1 & key )
|
if ( E500_SELTLB_1 & key )
|
||||||
rtems_e500_tlb_va_cache[ (~E500_SELTLB_1 & key) ].att.v = 0;
|
rtems_e500_tlb_va_cache[ (~E500_SELTLB_1 & key) ].att.v = 0;
|
||||||
|
|
||||||
rtems_interrupt_enable(lvl);
|
rtems_interrupt_enable(lvl);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user