source: rtems/c/src/lib/libbsp/powerpc/shared/startup/probeMemEnd.c @ 7e85bfbe

4.115
Last change on this file since 7e85bfbe was 7e85bfbe, checked in by Sebastian Huber <sebastian.huber@…>, on Aug 24, 2011 at 9:48:56 AM

2011-08-24 Sebastian Huber <sebastian.huber@…>

  • shared/bootloader/exception.S, shared/bootloader/misc.c, shared/bootloader/mm.c, shared/console/polled_io.c, shared/startup/probeMemEnd.c: Update due to API changes.
  • Property mode set to 100644
File size: 5.9 KB
Line 
1/* $Id$ */
2#include <rtems.h>
3#include <libcpu/spr.h>
4#include <libcpu/cpuIdent.h>
5#include <rtems/bspIo.h>
6
7/*
8 * Authorship
9 * ----------
10 * This software was created by
11 *     Till Straumann <strauman@slac.stanford.edu>, 2005,
12 *         Stanford Linear Accelerator Center, Stanford University.
13 *
14 * Acknowledgement of sponsorship
15 * ------------------------------
16 * This software was produced by
17 *     the Stanford Linear Accelerator Center, Stanford University,
18 *         under Contract DE-AC03-76SFO0515 with the Department of Energy.
19 *
20 * Government disclaimer of liability
21 * ----------------------------------
22 * Neither the United States nor the United States Department of Energy,
23 * nor any of their employees, makes any warranty, express or implied, or
24 * assumes any legal liability or responsibility for the accuracy,
25 * completeness, or usefulness of any data, apparatus, product, or process
26 * disclosed, or represents that its use would not infringe privately owned
27 * rights.
28 *
29 * Stanford disclaimer of liability
30 * --------------------------------
31 * Stanford University makes no representations or warranties, express or
32 * implied, nor assumes any liability for the use of this software.
33 *
34 * Stanford disclaimer of copyright
35 * --------------------------------
36 * Stanford University, owner of the copyright, hereby disclaims its
37 * copyright and all other rights in this software.  Hence, anyone may
38 * freely use it for any purpose without restriction.
39 *
40 * Maintenance of notices
41 * ----------------------
42 * In the interest of clarity regarding the origin and status of this
43 * SLAC software, this and all the preceding Stanford University notices
44 * are to remain affixed to any copy or derivative of this software made
45 * or distributed by the recipient and are to be affixed to any copy of
46 * software made or distributed by the recipient that contains a copy or
47 * derivative of this software.
48 *
49 * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
50 */
51
52
53/* Simple memory probing routine
54 *
55 *  - call from MMU-disabled section to avoid having to
56 *        set up mappings.
57 *    NOTE: this implies WIMG = 0011
58 *  - call AFTER image is at its destination and PRIOR
59 *    to setting up the heap or using any memory beyond
60 *    __rtems_end, i.e., the probing algorithm may safely
61 *    tamper with memory > __rtems_end.
62 *  - MUST lock caches since we're gonna hit space with
63 *    no memory attached.
64 *
65 * ASSUMPTIONS:
66 *              o image occupies addresses between 0..__rtems_end
67 *              o memory size is a multiple of 1<<LD_MEM_PROBE_STEP
68 *
69 * CAVEATS:
70 *      o all caches must be disabled or locked (some
71 *        boards really don't like it if you try to
72 *        cache physical addresses with nothing attached)
73 *        and this is highly CPU dependent :-(...
74 *
75 *      - RETURNS size of memory detected in bytes or 0 on
76 *    error.
77 */
78
79/* declare as an array so the compiler doesn't generate
80 * a reloc to .sdata & friends
81 */
82extern uint32_t __rtems_end[];
83
84#ifndef LD_MEM_PROBE_STEP
85#define LD_MEM_PROBE_STEP       (24) /* 16MB */
86#endif
87
88#define TAG 0xfeedcafe
89
90#define __DO_ALIGN(a, s)        (((uint32_t)(a) + (s)-1) & ~((s)-1))
91#define __ALIGN(a)      __DO_ALIGN(a, (1<<LD_MEM_PROBE_STEP))
92
93#define SWITCH_MSR(msr)         \
94        do {                                    \
95        register uint32_t __rr; \
96        asm volatile(                   \
97                "       mtsrr1  %0      \n"     \
98                "   bl 1f               \n"     \
99                "1:     mflr    %0      \n"     \
100                "       addi %0, %0, 1f-1b      \n"\
101                "       mtsrr0  %0      \n"     \
102                "       sync            \n"     \
103                "       rfi                     \n"     \
104                "1:                             \n"     \
105                :"=b&"(__rr)            \
106                :"0"(msr)                       \
107                :"lr","memory"          \
108        );                                              \
109        } while (0)
110
111SPR_RW(L2CR)
112SPR_RW(L3CR)
113SPR_RO(PPC_PVR)
114SPR_RW(HID0)
115
116
117/* Shouldn't matter if the caches are enabled or not... */
118
119/* FIXME: This should go into libcpu, really... */
120int
121CPU_lockUnlockCaches(register int doLock)
122{
123register uint32_t v, x;
124        if ( _read_MSR() & MSR_VE ) {
125#define DSSALL  0x7e00066c  /* dssall opcode */
126        __asm__ volatile("  .long %0"::"i"(DSSALL));
127#undef  DSSALL
128        }
129        asm volatile("sync");
130        switch ( _read_PPC_PVR()>>16 ) {
131                default:                printk(__FILE__" CPU_lockUnlockCaches(): unknown CPU (PVR = 0x%08x)\n",_read_PPC_PVR());
132                                                return -1;
133                case PPC_750:   printk("CPU_lockUnlockCaches(): Can't lock L2 on a mpc750, sorry :-(\n");
134                                                return -2;      /* cannot lock L2 :-( */
135                case PPC_7455:
136                case PPC_7457:
137                                                v = _read_L3CR();
138                                                x = 1<<(31-9);
139                                                v = doLock ? v | x : v & ~x;
140                                                _write_L3CR(v);
141
142                                                v = _read_L2CR();
143                                                x = 1<<(31-11);
144                                                v = doLock ? v | x : v & ~x;
145                                                _write_L2CR(v);
146                                break;
147
148                case PPC_7400:
149                                                v = _read_L2CR();
150                                                x = 1<<(31-21);
151                                                v = doLock ? v | x : v & ~x;
152                                                _write_L2CR(v);
153                                break;
154                case PPC_603:
155                case PPC_604:
156                case PPC_604e:
157                                break;
158        }
159
160        v = _read_HID0();
161        x = 1<<(31-19);
162        v = doLock ? v | x : v & ~x;
163        _write_HID0(v);
164        asm volatile("sync":::"memory");
165        return 0;
166}
167
168uint32_t
169probeMemoryEnd(void)
170{
171register volatile uint32_t *probe;
172register          uint32_t scratch;
173register          uint32_t tag = TAG;
174register          uint32_t flags;
175
176        probe = (volatile uint32_t *)__ALIGN(__rtems_end);
177
178        /* Start with some checks. We avoid using any services
179         * such as 'printk' so we can run at a very early stage.
180         * Also, we *try* to avoid to really rely on the memory
181         * being unused by restoring the probed locations and
182         * keeping everything in registers. Hence we could
183         * even probe our own stack :-)
184         */
185
186        if ( CPU_lockUnlockCaches(1) )
187                return 0;
188
189        _CPU_MSR_GET(flags);
190
191        SWITCH_MSR( flags & ~(MSR_EE|MSR_DR|MSR_IR) );
192
193        for ( ; (uint32_t)probe ;  probe += (1<<LD_MEM_PROBE_STEP)/sizeof(*probe) ) {
194
195                /* see if by chance our tag is already there */
196                if ( tag == (scratch = *probe) ) {
197                        /* try another tag */
198                        tag = ~tag;
199                }
200                *probe = tag;
201
202                /* make sure it's written out */
203                asm volatile ("sync":::"memory");
204
205                /* try to read back */
206                if ( tag != *probe ) {
207                                break;
208                }
209                /* restore */
210                *probe = scratch;
211                /* make sure the icache is not contaminated */
212                asm volatile ("sync; icbi 0, %0"::"r"(probe):"memory");
213        }
214
215        SWITCH_MSR(flags);
216
217        CPU_lockUnlockCaches(0);
218
219        return (uint32_t) probe;
220}
Note: See TracBrowser for help on using the repository browser.