From 25787041cf14b1e5237ef9539cd81c8090a8ba9f Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Wed, 25 Apr 2018 10:22:18 +0200 Subject: bsp/virtex5: Move mmu.c to bsps This patch is a part of the BSP source reorganization. Update #3285. --- c/src/lib/libbsp/powerpc/virtex5/Makefile.am | 2 +- c/src/lib/libbsp/powerpc/virtex5/mmu/mmu.c | 581 --------------------------- 2 files changed, 1 insertion(+), 582 deletions(-) delete mode 100644 c/src/lib/libbsp/powerpc/virtex5/mmu/mmu.c (limited to 'c/src/lib/libbsp/powerpc') diff --git a/c/src/lib/libbsp/powerpc/virtex5/Makefile.am b/c/src/lib/libbsp/powerpc/virtex5/Makefile.am index 543eb22800..59eeb66f75 100644 --- a/c/src/lib/libbsp/powerpc/virtex5/Makefile.am +++ b/c/src/lib/libbsp/powerpc/virtex5/Makefile.am @@ -40,7 +40,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/serial/printk-dummy.c librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/virtex5/irq/irq_init.c # mmu -librtemsbsp_a_SOURCES += mmu/mmu.c +librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/virtex5/start/mmu.c librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/shared/cache/cache.c librtemsbsp_a_SOURCES += ../../../../../../bsps/powerpc/shared/clock/clock-ppc-dec.c diff --git a/c/src/lib/libbsp/powerpc/virtex5/mmu/mmu.c b/c/src/lib/libbsp/powerpc/virtex5/mmu/mmu.c deleted file mode 100644 index 990cb99bd0..0000000000 --- a/c/src/lib/libbsp/powerpc/virtex5/mmu/mmu.c +++ /dev/null @@ -1,581 +0,0 @@ -/** - * @file - * - * @ingroup Virtex5MMU - * - * @brief Implementation of routines to manipulate the PPC 440 MMU. - * - * Since this is a real-time OS we want to stay away from - * software TLB replacement. - */ -/* - * Authorship - * ---------- - * This software was created by - * Till Straumann , 2005-2007, - * Stanford Linear Accelerator Center, Stanford University. - * and was transcribed for the PPC 440 by - * R. Claus , 2012, - * 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 - */ - -/* 440 MSR definitions; note that there are *substantial* differences - * compared to classic powerpc; in particular, IS/DS are *different* - * from IR/DR; the ppc440 MMU cannot be switched off! - * - * Also: To disable/enable all external interrupts, CE and EE must both be - * controlled. - */ -#include -#include -#include -#include -#include - -#include - - -#ifdef DEBUG -#define STATIC -#else -#define STATIC static -#endif - - -bsp_tlb_entry_t* bsp_mmu_cache = 0; - - -/* 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 -bsp_mmu_dump_cache(FILE *f) -{ - bsp_tlb_idx_t idx; - if ( !bsp_mmu_cache ) { - myprintf(stderr,"MMU TLB cache not initialized\n"); - return; - } - for ( idx=0; idxw0.v ) - continue; - myprintf(f, "#%2i: EA 0x%08x .. 0x%08x, TID 0x%03x, TS %i\n", - idx, - tlb->w0.epn<<10, - (tlb->w0.epn<<10) + (1024<<(2*tlb->w0.size))-1, - tlb->id.tid, - tlb->w0.ts); - myprintf(f, " PA 0x%08"PRIx32", U0-3 0x%01x, WIMGE 0x%02x, PERM 0x%03x\n", - tlb->w1.rpn<<10, - tlb->w2.att, - tlb->w2.wimge, - tlb->w2.perm); - } -} - -static void -fetch(bsp_tlb_idx_t key, bsp_tlb_entry_t* tlb) -{ - register uint32_t tmp; - __asm__ volatile ("mfpid %[tmp] \n\t" - "stw %[tmp],0(%[tlb]) \n\t" - "tlbre %[tmp],%[key],0 \n\t" - "stw %[tmp],4(%[tlb]) \n\t" - "tlbre %[tmp],%[key],1 \n\t" - "stw %[tmp],8(%[tlb]) \n\t" - "tlbre %[tmp],%[key],2 \n\t" - "stw %[tmp],12(%[tlb]) \n\t" - "sync \n\t" - : [tmp]"=&r"(tmp) - : [key]"r"(key), - [tlb]"b"(tlb) - ); -} - - -static void -store(bsp_tlb_idx_t key, bsp_tlb_entry_t* tlb) -{ - register uint32_t tmp; - __asm__ volatile ("lwz %[tmp],0(%[tlb]) \n\t" - "mtpid %[tmp] \n\t" - "lwz %[tmp],4(%[tlb]) \n\t" - "tlbwe %[tmp],%[idx],0 \n\t" - "lwz %[tmp],8(%[tlb]) \n\t" - "tlbwe %[tmp],%[idx],1 \n\t" - "lwz %[tmp],12(%[tlb]) \n\t" - "tlbwe %[tmp],%[idx],2 \n\t" - : [tmp]"=&r"(tmp) - : [tlb]"b"(tlb), - [idx]"r"(key) - ); -} - - -static void -commit(void) -{ - __asm__ volatile("isync \n\t"); -} - - -/* - * Read a TLB entry from the hardware store the current settings in the - * bsp_mmu_cache[] structure. - * - * The routine can perform this operation quietly or - * print information to a file. - * - * '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) - * (-2: driver not initialized) - */ -int -bsp_mmu_update(bsp_tlb_idx_t key, bool quiet, FILE *f) -{ - rtems_interrupt_level lvl; - bsp_tlb_entry_t* tlb; - int idx; - - idx = key; - - if ( idx < 0 || idx > NTLBS-1 ) - return -1; - - if (!bsp_mmu_cache) - return -2; - - tlb = bsp_mmu_cache + idx; - - rtems_interrupt_disable(lvl); - - fetch(idx, tlb); - - rtems_interrupt_enable(lvl); - - if ( tlb->w0.v ) { - if ( !quiet ) { -/* - "TLB Entry # 0 spans EA range 0x00000000 - 0x00000000 - "Mapping: VA [TS 0 / TID 0x00 / EPN 0x00000] -> RPN 0x00000" - "Size: TSIZE 0x0 (4^sz KB = 000000 KB = 0x00000000 B) - "Attributes: PERM 0x000 (ux/uw/ur/sx/sw/sr) WIMGE 0x00 U0-3 0x0" -*/ - myprintf(f, - "TLB Entry # %2d spans EA range 0x%08x - 0x%08x\n", - idx, - (tlb->w0.epn << 10), - (tlb->w0.epn << 10) + (1024<<(2*tlb->w0.size)) - 1 - ); - - myprintf(f, - "Mapping: VA [TS %d / TID 0x%02x / EPN 0x%05x] -> RPN 0x%05"PRIx32"\n", - tlb->w0.ts, tlb->id.tid, tlb->w0.epn, tlb->w1.rpn - ); - myprintf(f, - "Size: TSIZE 0x%x (4^sz KB = %6d KB = 0x%08x B)\n", - tlb->w0.size, (1<<(2*tlb->w0.size)), (1024<<(2*tlb->w0.size)) - ); - myprintf(f, - "Properties: PERM 0x%03x (ux/uw/ur/sx/sw/sr) WIMGE 0x%02x U0-3 0x%01x\n", - tlb->w2.perm, tlb->w2.wimge, tlb->w2.att - ); - } - } else { - if ( !quiet ) { - myprintf(f, "TLB Entry # %2d (size 0x%x = 0x%xb)\n", - idx, tlb->w0.size, (1024<<(2*tlb->w0.size))); - } - return 1; - } - return 0; -} - -/* Initialize cache. Should be done only once although this is not enforced. - * - * RETURNS: zero on success, nonzero on error; in this case the driver will - * refuse to change TLB entries (other than disabling them). - */ -int -bsp_mmu_initialize() -{ - static bsp_tlb_entry_t mmu_cache[NTLBS]; - bsp_tlb_entry_t* tlb = mmu_cache; /* Should malloc if it's not too early */ - rtems_interrupt_level lvl; - - bsp_tlb_idx_t idx; - rtems_interrupt_disable(lvl); - for (idx=0; idx= 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. - * 'flgs': Page's User-defined flags, permissions and WIMGE page attributes - * 'tid': Translation ID - * 'ts': Translation Space - * 'erpn': Extended Real Page Number - * - * 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). - * <0: other error - */ -bsp_tlb_idx_t -bsp_mmu_write(bsp_tlb_idx_t idx, uint32_t ea, uint32_t pa, int sz, - uint32_t flgs, uint32_t tid, uint32_t ts, uint32_t erpn) -{ - bsp_tlb_entry_t tlb; - uint32_t msk; - bsp_tlb_idx_t lkup; - rtems_interrupt_level lvl; - - if ( sz >= 1024 ) { - /* Assume they literally specify a size */ - msk = sz; - sz = 0; - while ( msk != (1024<<(sz+sz)) ) { - if ( ++sz > 15 ) { - return -1; - } - } - /* OK, acceptable */ - } - - msk = sz > 0 ? (1024<<(sz+sz)) - 1 : 0; - - if ( !bsp_mmu_cache && sz > 0 ) { - myprintf(stderr,"MMU driver not initialized; refusing to enable any entry\n"); - return -3; - } - - if ( (ea & msk) || (pa & msk) ) { - myprintf(stderr,"Misaligned EA (%08x) or PA (%08x) (mask is %08x)\n", ea, pa, msk); - return -1; - } - - if ( idx < 0 || idx > NTLBS-1 ) - return -1; - - /* Not all 16 possible sizes are supported */ - if ( sz == 6 || sz == 8 || sz > 9 ) { - myprintf(stderr,"Invalid size %u = %08x = %u KB\n", sz, 1024<<(sz+sz), (1024<<(sz+sz))/1024); - return -1; - } - - if ( sz >=0 ) { - lkup = bsp_mmu_match(ea, sz, tid, ts); - - if ( lkup < -1 ) { - /* some error */ - return lkup; - } - - if ( lkup >= 0 && lkup != idx && (bsp_mmu_cache[lkup].w0.v != 0) ) { - myprintf(stderr,"TLB #%i overlaps with requested mapping\n", lkup); - bsp_mmu_update( lkup, false, stderr); - return lkup+1; - } - } - - /* OK to proceed */ - tlb.id.tid = tid; - tlb.w0.v = sz >= 0; - tlb.w0.ts = ts; - tlb.w0.size = sz; - tlb.w0.epn = (ea & (0xfffffc00 << (sz+sz))) >> 10; - if (sz < 11) { - tlb.w1.rpn = (pa & (0xfffffc00 << (sz+sz))) >> 10; - tlb.w1.erpn = erpn; - } - else { - sz -= 11; - tlb.w1.rpn = 0; - tlb.w1.erpn = (erpn & (0xf << (sz+sz))) & 0xf; - } - tlb.w2.att = (flgs & MMU_M_ATTR) >> MMU_V_ATTR; - tlb.w2.wimge = (flgs & MMU_M_PROP) >> MMU_V_PROP; - tlb.w2.perm = (flgs & MMU_M_PERM) >> MMU_V_PERM; - - rtems_interrupt_disable(lvl); - - store(idx, &tlb); - - commit(); - - rtems_interrupt_enable(lvl); - - /* update cache */ - bsp_mmu_update(idx, true, 0); - - return 0; -} - -/* - * Check if a ea/tid/ts/sz mapping overlaps with an existing entry. - * - * 'ea': The Effective Address to match against - * 'sz': The 'logarithmic' size selector; the page size - * is 1024*2^(2*sz). - * 'tid': Translation ID - * 'ts': Translation Space - * - * RETURNS: - * >= 0: index of the TLB entry that already provides a mapping - * which overlaps within the ea range. - * -1: SUCCESS (no conflicting entry found) - * <=-2: ERROR (invalid input) - */ -bsp_tlb_idx_t -bsp_mmu_match(uint32_t ea, int sz, uint32_t tid, uint32_t ts) -{ - bsp_tlb_idx_t idx; - uint32_t m,a; - bsp_tlb_entry_t* tlb; - - if ( sz < 0 || sz == 6 || sz == 8 || sz > 9 ) - return -4; - - sz = (1024<<(2*sz)); - - if ( !bsp_mmu_cache ) { - /* cache not initialized */ - return -3; - } - - if ( ea & (sz-1) ) { - /* misaligned ea */ - return -2; - } - - for ( idx=0, tlb=bsp_mmu_cache; idxw0.v ) - continue; - if ( tlb->id.tid && tlb->id.tid != tid ) - continue; - if ( tlb->w0.ts != ts ) - continue; - /* TID and TS match a valid entry */ - m = (1024<<(2*tlb->w0.size)) - 1; - /* calculate starting address of this entry */ - a = tlb->w0.epn<<10; - if ( ea <= a + m && ea + sz -1 >= a ) { - /* overlap */ - return idx; - } - } - return -1; -} - -/* Find TLB index that maps 'ea/tid/ts' combination - * - * 'ea': Effective address to match against - * 'tid': Translation ID - * 'ts': Translation Space - * - * RETURNS: index 'key' which indicates whether - * the mapping was found. - * - * On error (no mapping) -1 is returned. - */ -bsp_tlb_idx_t -bsp_mmu_find(uint32_t ea, uint32_t tid, uint32_t ts) -{ - rtems_interrupt_level lvl; - register uint32_t mmucr; - register bsp_tlb_idx_t idx; - register int failure; - - rtems_interrupt_disable(lvl); - - __asm__ volatile ("mfspr %[mmucr],0x3b2 \n\t" /* Save MMUCR */ - : [mmucr]"=r"(mmucr) - ); - __asm__ volatile ("mtspr 0x3b2,%[tid] \n\t" - "tlbsx. %[idx],0,%[ea] \n\t" /* Failure changes the index reg randomly. */ - "mfcr %[failure] \n\t" - "mtspr 0x3b2,%[mmucr] \n\t" /* Restore MMUCR */ - : [idx]"=&r"(idx), - [failure]"=&r"(failure) - : [tid]"r"((mmucr & 0xfffeff00) | (ts << 16) | tid), - [ea]"r"(ea), - [mmucr]"r"(mmucr) - : "cc" - ); - - rtems_interrupt_enable(lvl); - - return (failure & 0x20000000) ? idx : -1; -} - -/* Mark TLB entry as invalid ('disabled'). - * - * 'key': TLB entry (index). - * - * RETURNS: zero on success, nonzero on error (TLB unchanged). - * - * NOTE: If a TLB entry is disabled the associated - * entry in bsp_mmu_cache[] is also - * marked as disabled. - */ -int -bsp_mmu_invalidate(bsp_tlb_idx_t key) -{ - bsp_tlb_idx_t k0; - rtems_interrupt_level lvl; - bsp_tlb_entry_t tlb; - - /* minimal guard against bad key */ - if ( key < 0 || key > NTLBS-1 ) - return -1; - - /* Must not invalidate page 0 which holds vectors, text etc... */ - k0 = bsp_mmu_find(0, 0, 0); - if ( -1 == k0 ) { - myprintf(stderr,"No mapping for address 0 found\n"); - return -2; - } - - /* NOTE: we assume PID is ignored */ - if ( k0 == key ) { - myprintf(stderr,"Cannot invalidate page holding address 0 (always needed)\n"); - return -3; - } - - rtems_interrupt_disable(lvl); - - fetch(key, &tlb); - - /* Invalidate old entries */ - tlb.w0.v = 0; - - store(key, &tlb); - - commit(); - - /* Update cache */ - bsp_mmu_cache[ key ].w0.v = tlb.w0.v; - - rtems_interrupt_enable(lvl); - - return 0; -} -- cgit v1.2.3