Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:58

0001 /*
0002  * Authorship
0003  * ----------
0004  * This software was created by
0005  *     Till Straumann <strauman@slac.stanford.edu>, 2005,
0006  *     Stanford Linear Accelerator Center, Stanford University.
0007  *
0008  * Acknowledgement of sponsorship
0009  * ------------------------------
0010  * This software was produced by
0011  *     the Stanford Linear Accelerator Center, Stanford University,
0012  *     under Contract DE-AC03-76SFO0515 with the Department of Energy.
0013  *
0014  * Government disclaimer of liability
0015  * ----------------------------------
0016  * Neither the United States nor the United States Department of Energy,
0017  * nor any of their employees, makes any warranty, express or implied, or
0018  * assumes any legal liability or responsibility for the accuracy,
0019  * completeness, or usefulness of any data, apparatus, product, or process
0020  * disclosed, or represents that its use would not infringe privately owned
0021  * rights.
0022  *
0023  * Stanford disclaimer of liability
0024  * --------------------------------
0025  * Stanford University makes no representations or warranties, express or
0026  * implied, nor assumes any liability for the use of this software.
0027  *
0028  * Stanford disclaimer of copyright
0029  * --------------------------------
0030  * Stanford University, owner of the copyright, hereby disclaims its
0031  * copyright and all other rights in this software.  Hence, anyone may
0032  * freely use it for any purpose without restriction.
0033  *
0034  * Maintenance of notices
0035  * ----------------------
0036  * In the interest of clarity regarding the origin and status of this
0037  * SLAC software, this and all the preceding Stanford University notices
0038  * are to remain affixed to any copy or derivative of this software made
0039  * or distributed by the recipient and are to be affixed to any copy of
0040  * software made or distributed by the recipient that contains a copy or
0041  * derivative of this software.
0042  *
0043  * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
0044  */
0045 
0046 #include <bsp.h>
0047 #include <libcpu/spr.h>
0048 #include <libcpu/cpuIdent.h>
0049 #include <rtems/bspIo.h>
0050 #include <inttypes.h>
0051 
0052 /* Simple memory probing routine
0053  *
0054  *  - call from MMU-disabled section to avoid having to
0055  *    set up mappings.
0056  *    NOTE: this implies WIMG = 0011
0057  *  - call AFTER image is at its destination and PRIOR
0058  *    to setting up the heap or using any memory beyond
0059  *    __rtems_end, i.e., the probing algorithm may safely
0060  *    tamper with memory > __rtems_end.
0061  *  - MUST lock caches since we're gonna hit space with
0062  *    no memory attached.
0063  *
0064  * ASSUMPTIONS:
0065  *      o image occupies addresses between 0..__rtems_end
0066  *      o memory size is a multiple of 1<<LD_MEM_PROBE_STEP
0067  *
0068  * CAVEATS:
0069  *      o all caches must be disabled or locked (some
0070  *        boards really don't like it if you try to
0071  *        cache physical addresses with nothing attached)
0072  *        and this is highly CPU dependent :-(...
0073  *
0074  *  - RETURNS size of memory detected in bytes or 0 on
0075  *    error.
0076  */
0077 
0078 /* declare as an array so the compiler doesn't generate
0079  * a reloc to .sdata & friends
0080  */
0081 extern uint32_t __rtems_end[];
0082 
0083 #ifndef LD_MEM_PROBE_STEP
0084 #define LD_MEM_PROBE_STEP   (24) /* 16MB */
0085 #endif
0086 
0087 #define TAG 0xfeedcafe
0088 
0089 #define __DO_ALIGN(a, s)    (((uint32_t)(a) + (s)-1) & ~((s)-1))
0090 #define __ALIGN(a)  __DO_ALIGN(a, (1<<LD_MEM_PROBE_STEP))
0091 
0092 #define SWITCH_MSR(msr)     \
0093     do {                    \
0094     register uint32_t __rr; \
0095     asm volatile(           \
0096         "   mtsrr1  %0  \n" \
0097         "   bl 1f       \n" \
0098         "1: mflr    %0  \n" \
0099         "   addi %0, %0, 1f-1b  \n"\
0100         "   mtsrr0  %0  \n" \
0101         "   sync        \n" \
0102         "   rfi         \n" \
0103         "1:             \n" \
0104         :"=b&"(__rr)        \
0105         :"0"(msr)           \
0106         :"lr","memory"      \
0107     );                      \
0108     } while (0)
0109 
0110 SPR_RW(L2CR)
0111 SPR_RW(L3CR)
0112 SPR_RO(PPC_PVR)
0113 SPR_RW(HID0)
0114 
0115 
0116 /* Shouldn't matter if the caches are enabled or not... */
0117 
0118 /* FIXME: This should go into libcpu, really... */
0119 static int
0120 CPU_lockUnlockCaches(register int doLock)
0121 {
0122 register uint32_t v, x;
0123     if ( _read_MSR() & MSR_VE ) {
0124 #define DSSALL  0x7e00066c  /* dssall opcode */
0125         __asm__ volatile("  .long %0"::"i"(DSSALL));
0126 #undef  DSSALL
0127     }
0128     asm volatile("sync");
0129     switch ( _read_PPC_PVR()>>16 ) {
0130         default:        printk(__FILE__" CPU_lockUnlockCaches(): unknown CPU (PVR = 0x%08" PRIx32 ")\n",_read_PPC_PVR());
0131                         return -1;
0132         case PPC_750:   printk("CPU_lockUnlockCaches(): Can't lock L2 on a mpc750, sorry :-(\n");
0133                         return -2;  /* cannot lock L2 :-( */
0134         case PPC_7455:
0135         case PPC_7457:
0136                         v = _read_L3CR();
0137                         x = 1<<(31-9);
0138                         v = doLock ? v | x : v & ~x;
0139                         _write_L3CR(v);
0140 
0141                         v = _read_L2CR();
0142                         x = 1<<(31-11);
0143                         v = doLock ? v | x : v & ~x;
0144                         _write_L2CR(v);
0145                 break;
0146 
0147         case PPC_7400:
0148                         v = _read_L2CR();
0149                         x = 1<<(31-21);
0150                         v = doLock ? v | x : v & ~x;
0151                         _write_L2CR(v);
0152                 break;
0153         case PPC_603:
0154         case PPC_604:
0155         case PPC_604e:
0156                 break;
0157     }
0158 
0159     v = _read_HID0();
0160     x = 1<<(31-19);
0161     v = doLock ? v | x : v & ~x;
0162     _write_HID0(v);
0163     asm volatile("sync":::"memory");
0164     return 0;
0165 }
0166 
0167 uint32_t
0168 probeMemoryEnd(void)
0169 {
0170 register volatile uint32_t *probe;
0171 register          uint32_t scratch;
0172 register          uint32_t tag = TAG;
0173 register          uint32_t flags;
0174 
0175     probe = (volatile uint32_t *)__ALIGN(__rtems_end);
0176 
0177     /* Start with some checks. We avoid using any services
0178      * such as 'printk' so we can run at a very early stage.
0179      * Also, we *try* to avoid to really rely on the memory
0180      * being unused by restoring the probed locations and
0181      * keeping everything in registers. Hence we could
0182      * even probe our own stack :-)
0183      */
0184 
0185     if ( CPU_lockUnlockCaches(1) )
0186         return 0;
0187 
0188     _CPU_MSR_GET(flags);
0189 
0190     SWITCH_MSR( flags & ~(MSR_EE|MSR_DR|MSR_IR) );
0191 
0192     for ( ; (uint32_t)probe ;  probe += (1<<LD_MEM_PROBE_STEP)/sizeof(*probe) ) {
0193 
0194         /* see if by chance our tag is already there */
0195         if ( tag == (scratch = *probe) ) {
0196             /* try another tag */
0197             tag = ~tag;
0198         }
0199         *probe = tag;
0200 
0201         /* make sure it's written out */
0202         asm volatile ("sync":::"memory");
0203 
0204         /* try to read back */
0205         if ( tag != *probe ) {
0206                 break;
0207         }
0208         /* restore */
0209         *probe = scratch;
0210         /* make sure the icache is not contaminated */
0211         asm volatile ("sync; icbi 0, %0"::"r"(probe):"memory");
0212     }
0213 
0214     SWITCH_MSR(flags);
0215 
0216     CPU_lockUnlockCaches(0);
0217 
0218     return (uint32_t) probe;
0219 }