source: rtems/c/src/lib/libcpu/powerpc/e500/mmu/mmu.c @ b10be06

4.11
Last change on this file since b10be06 was b10be06, checked in by Sebastian Huber <sebastian.huber@…>, on Jan 31, 2011 at 3:48:22 PM

2011-01-31 Sebastian Huber <sebastian.huber@…>

  • e500/mmu/mmu.c: Use common defines.
  • Property mode set to 100644
File size: 17.3 KB
Line 
1/* $Id$ */
2
3/*
4 * Routines to manipulate e500 TLBs; TLB0 (fixed 4k page size)
5 * is not very useful so we mostly focus on TLB1 (variable page size).
6 *
7 * TLB0's 256 entries are 2-way set associative which means that
8 *        only 2 entries for page index numbers with matching 7 LSBs
9 *        are available.
10 *
11 *        E.g., look at EA = 0xAAAyy000. 0xAAAyy is the page index.
12 *
13 *        The least-significant 7 bits in 'yy' determine the 'way'
14 *        in the TLB 0 array. At most two EAs with matching 'yy' bits
15 *        (the 7 LSBs, that is) can be mapped with TLB0 since there
16 *        are only two entries per 'way'.
17 *
18 *        Since this is a real-time OS we want to stay away from
19 *        software TLB replacement.
20 */
21
22/*
23 * Authorship
24 * ----------
25 * This software was created by
26 *     Till Straumann <strauman@slac.stanford.edu>, 2005-2007,
27 *         Stanford Linear Accelerator Center, Stanford University.
28 *
29 * Acknowledgement of sponsorship
30 * ------------------------------
31 * This software was produced by
32 *     the Stanford Linear Accelerator Center, Stanford University,
33 *         under Contract DE-AC03-76SFO0515 with the Department of Energy.
34 *
35 * Government disclaimer of liability
36 * ----------------------------------
37 * Neither the United States nor the United States Department of Energy,
38 * nor any of their employees, makes any warranty, express or implied, or
39 * assumes any legal liability or responsibility for the accuracy,
40 * completeness, or usefulness of any data, apparatus, product, or process
41 * disclosed, or represents that its use would not infringe privately owned
42 * rights.
43 *
44 * Stanford disclaimer of liability
45 * --------------------------------
46 * Stanford University makes no representations or warranties, express or
47 * implied, nor assumes any liability for the use of this software.
48 *
49 * Stanford disclaimer of copyright
50 * --------------------------------
51 * Stanford University, owner of the copyright, hereby disclaims its
52 * copyright and all other rights in this software.  Hence, anyone may
53 * freely use it for any purpose without restriction.
54 *
55 * Maintenance of notices
56 * ----------------------
57 * In the interest of clarity regarding the origin and status of this
58 * SLAC software, this and all the preceding Stanford University notices
59 * are to remain affixed to any copy or derivative of this software made
60 * or distributed by the recipient and are to be affixed to any copy of
61 * software made or distributed by the recipient that contains a copy or
62 * derivative of this software.
63 *
64 * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
65 */
66
67/* 8450 MSR definitions; note that there are *substantial* differences
68 * compared to classic powerpc; in particular, IS/DS are *different*
69 * from IR/DR; the e500 MMU can not be switched off!
70 *
71 * Also: To disable/enable all external interrupts, CE and EE must both be
72 *       controlled.
73 */
74#include <rtems.h>
75#include <rtems/bspIo.h>
76#include <inttypes.h>
77#include <stdio.h>
78
79#include "e500_mmu.h"
80
81#define TLBIVAX_TLBSEL  (1<<(63-60))
82#define TLBIVAX_INV_ALL (1<<(63-61))
83
84#define E500_TLB_ATTR_WIMGE(x)      ((x)&0x7f)                          /* includes user bits */
85#define E500_TLB_ATTR_WIMGE_GET(x)  ((x)&0x7f)
86#define E500_TLB_ATTR_TS            (1<<7)
87#define E500_TLB_ATTR_PERM(x)           (((x)&0x3ff)<<8)
88#define E500_TLB_ATTR_PERM_GET(x)   (((x)>>8)&0x3ff)
89#define E500_TLB_ATTR_TID(x)        (((x)&0xfff)<<20)
90#define E500_TLB_ATTR_TID_GET(x)    (((x)>>20)&0xfff)
91
92
93#ifdef DEBUG
94#define STATIC
95#else
96#define STATIC static
97#endif
98
99/* Factory to generate inline macros for accessing the MAS registers */
100#define __RDWRMAS(mas,rmas)     \
101        static inline uint32_t _read_MAS##mas(void)                                      \
102        { uint32_t x; asm volatile("mfspr %0, %1": "=r"(x):"i"(rmas)); return x; } \
103        static inline void _write_MAS##mas(uint32_t x)                             \
104        {             asm volatile("mtspr %1, %0":: "r"(x),"i"(rmas)); }
105
106__RDWRMAS(0,FSL_EIS_MAS0)
107__RDWRMAS(1,FSL_EIS_MAS1)
108__RDWRMAS(2,FSL_EIS_MAS2)
109__RDWRMAS(3,FSL_EIS_MAS3)
110__RDWRMAS(4,FSL_EIS_MAS4)
111__RDWRMAS(6,FSL_EIS_MAS6)
112
113#undef __RDWRMAS
114
115static int initialized  = 0;
116
117E500_tlb_va_cache_t rtems_e500_tlb_va_cache[16];
118
119/* Since it is likely that these routines are used during
120 * early initialization when stdio is not available yet
121 * we provide a helper that resorts to 'printk()'
122 */
123static void
124myprintf(FILE *f, char *fmt, ...)
125{
126va_list ap;
127    va_start(ap, fmt);
128
129    if (!f || !_impure_ptr->__sdidinit) {
130        /*
131                 * Might be called at an early stage when
132         * stdio is not yet initialized.
133         */
134        vprintk(fmt,ap);
135    } else {
136        vfprintf(f,fmt,ap);
137    }
138    va_end(ap);
139}
140
141
142void
143rtems_e500_dmptlbc(FILE *f)
144{
145int i;
146        if ( !initialized ) {
147                myprintf(stderr,"TLB cache not initialized\n");
148                return;
149        }
150        for ( i=0; i<16; i++ ) {
151                if ( !rtems_e500_tlb_va_cache[i].att.v )
152                        continue;
153                myprintf(f,"#%2i: TID 0x%03x, TS %i, ea 0x%08x .. 0x%08x\n",
154                        i,
155                        rtems_e500_tlb_va_cache[i].va.va_tid,
156                        rtems_e500_tlb_va_cache[i].att.ts,
157                        rtems_e500_tlb_va_cache[i].va.va_epn<<12,
158                        (rtems_e500_tlb_va_cache[i].va.va_epn<<12) + (1024<<(2*rtems_e500_tlb_va_cache[i].att.sz))-1);
159                myprintf(f,"PA 0x%08"PRIx32", PERM 0x%03x, WIMGE 0x%02x\n",
160                        rtems_e500_tlb_va_cache[i].rpn<<12,
161                        rtems_e500_tlb_va_cache[i].att.perm,
162                        rtems_e500_tlb_va_cache[i].att.wimge);
163        }
164}
165
166#define E500_SELTLB_1   0x1000
167
168static void seltlb(rtems_e500_tlb_idx key)
169{
170int idx = key & ~E500_SELTLB_1;
171
172        if ( key & E500_SELTLB_1 ) {
173                _write_MAS0( FSL_EIS_MAS0_TLBSEL | FSL_EIS_MAS0_ESEL(idx) );
174        } else {
175                _write_MAS0( (idx & 128) ? FSL_EIS_MAS0_ESEL(1) : FSL_EIS_MAS0_ESEL(0) );
176                _write_MAS2( FSL_EIS_MAS2_EPN( idx & 127 ) );
177        }
178}
179
180/*
181 * Read a TLB entry from the hardware; if it is a TLB1 entry
182 * then the current settings are stored in the
183 * rtems_e500_tlb_va_cache[] structure.
184 *
185 * The routine can perform this operation quietly or
186 * print information to a file.
187 *
188 *   'sel': which TLB array to use; TLB0 (4k) if zero,
189 *          TLB1 (variable) if nonzero.
190 *   'idx': which TLB entry to access.
191 * 'quiet': perform operation silently (no info printed)
192 *          if nonzero.
193 *     'f': open FILE where to print information. May be
194 *          NULL in which case 'stdout' is used.
195 *
196 * RETURNS:
197 *       0: success; TLB entry is VALID
198 *      +1: success but TLB entry is INVALID
199 *     < 0: error (-1: invalid argument)
200 */
201int
202rtems_e500_prtlb(rtems_e500_tlb_idx key, int quiet, FILE *f)
203{
204uint32_t               mas0, mas1, mas2, mas3;
205rtems_interrupt_level  lvl;
206E500_tlb_va_cache_t   *tlb;
207E500_tlb_va_cache_t    buf;
208int                    sel, idx;
209
210        sel = (key &  E500_SELTLB_1) ? 1 : 0;
211        idx = key & ~E500_SELTLB_1;
212
213        if ( idx < 0 || idx > 255 || ( idx > 15 && sel ) )
214                return -1;
215
216        rtems_interrupt_disable(lvl);
217
218        seltlb( key );
219
220        asm volatile("tlbre");
221
222        mas0 = _read_MAS0();
223        mas1 = _read_MAS1();
224        mas2 = _read_MAS2();
225        mas3 = _read_MAS3();
226
227        rtems_interrupt_enable(lvl);
228
229        tlb = sel ? rtems_e500_tlb_va_cache + idx : &buf;
230
231        if ( (tlb->att.= (FSL_EIS_MAS1_V & mas1) ? 1 : 0) ) {
232                tlb->va.va_epn = FSL_EIS_MAS2_EPN_GET(mas2);
233                tlb->rpn       = FSL_EIS_MAS3_RPN_GET(mas3);
234                tlb->va.va_tid = FSL_EIS_MAS1_TID_GET(mas1);
235                tlb->att.ts    = (FSL_EIS_MAS1_TS & mas1) ? 1 : 0;
236                tlb->att.sz    = sel ? FSL_EIS_MAS1_TSIZE_GET(mas1) : 1 /* 4k size */;
237                tlb->att.wimge = FSL_EIS_MAS2_ATTR_GET(mas2);
238                tlb->att.perm  = FSL_EIS_MAS3_PERM_GET(mas3);
239        }
240
241        if ( tlb->att.v ) {
242                if ( !quiet ) {
243/*
244                        "TLB[1] Entry # 0 spans EA range     0x00000000 .. 0x00000000
245                        "Mapping:    VA     [TS 0/TID 0x00/EPN 0x00000] -> RPN 0x00000"
246                        "Size:       TSIZE  0x0 ( 4^ts KiB = 000000 KiB = 0x00000000 B)
247                        "Attributes: PERM 0x000 (ux/sx/uw/sw/ur/sr) WIMGE 0x00 IPROT 0"
248*/
249                        myprintf(f,
250                                "TLB[%i] Entry # %d spans EA range     0x%08x .. 0x%08x\r\n",
251                                sel,
252                                idx,
253                                (tlb->va.va_epn << 12),
254                                (tlb->va.va_epn << 12) + (1024<<(2*tlb->att.sz)) - 1
255                        );
256
257                        myprintf(f,
258                                "Mapping:    VA     [TS %d/TID 0x%02x/EPN 0x%05x] -> RPN 0x%05"PRIx32"\r\n",
259                                tlb->att.ts, tlb->va.va_tid, tlb->va.va_epn, tlb->rpn
260                        );
261                        myprintf(f,
262                                "Size:       TSIZE  0x%x ( 4^ts KiB = %6d KiB = 0x%08x B)\r\n",
263                                tlb->att.sz, (1<<(2*tlb->att.sz)), (1024<<(2*tlb->att.sz))
264                        );
265                        myprintf(f,
266                                "Attributes: PERM 0x%03x (ux/sx/uw/sw/ur/sr) WIMGE 0x%02x IPROT %i\r\n",
267                                tlb->att.perm, tlb->att.wimge, (sel && (mas1 & FSL_EIS_MAS1_IPROT) ? 1 : 0)
268                        );
269                        myprintf(f,
270                                "EA range 0x%08x .. 0x%08x\r\n",
271                                (tlb->va.va_epn << 12),
272                                (tlb->va.va_epn << 12) + (1024<<(2*tlb->att.sz)) - 1
273                        );
274                }
275        } else {
276                if ( !quiet ) {
277                        myprintf(f, "TLB[%i] Entry #%i <OFF> (size 0x%x = 0x%xb)\n", sel, idx, tlb->att.sz, (1024<<(2*tlb->att.sz)));
278                }
279                return 1;
280        }
281        return 0;
282}
283
284/* Initialize cache; verify that TLB0 is unused;
285 *
286 * RETURNS: zero on success, nonzero on error (TLB0
287 *          seems to be in use); in this case the
288 *          driver will refuse to change TLB1 entries
289 *          (other than disabling them).
290 */
291int rtems_e500_initlb()
292{
293int i;
294int rval = 0;
295        for (i=0; i<16; i++)
296                rtems_e500_prtlb(E500_SELTLB_1 | i, 1, 0);
297        for (i=0; i<256; i++) {
298                /* refuse to enable operations that change TLB entries
299         * if anything in TLB[0] is valid (because we currently
300                 * don't check against overlap with TLB[0] when we
301                 * write a new entry).
302                 */
303                if ( rtems_e500_prtlb(E500_SELTLB_0 | i, 1, 0) <=0 ) {
304                        myprintf(stderr,"WARNING: 4k TLB #%i seems to be valid; UNSUPPORTED configuration\n", i);
305                        rval = -1;
306                }
307        }
308        if ( !rval )
309                initialized = 1;
310        return rval;
311}
312
313/*
314 * Write TLB1 entry (can also be used to disable an entry).
315 *
316 * The routine checks against the cached data in
317 * rtems_e500_tlb_va[] to prevent the user from generating
318 * overlapping entries.
319 *
320 *   'idx': TLB 1 entry # to manipulate
321 *    'ea': Effective address (must be page aligned)
322 *    'pa': Physical  address (must be page aligned)
323 *    'sz': Page size selector; page size is
324 *          1024 * 2^(2*sz) bytes.
325 *          'sz' may also be one of the following:
326 *          - page size in bytes ( >= 1024 ); the selector
327 *            value is then computed by this routine.
328 *            However, 'sz' must be a valid page size
329 *            or -1 will be returned.
330 *          - a value < 0 to invalidate/disable the
331 *            TLB entry.
332 *  'attr': Page attributes; ORed combination of WIMGE,
333 *          PERMissions, TID and TS. Use ATTR_xxx macros
334 *
335 * RETURNS: 0 on success, nonzero on error:
336 *
337 *         >0: requested mapping would overlap with
338 *             existing mapping in other entry. Return
339 *             value gives conflicting entry + 1; i.e.,
340 *             if a value of 4 is returned then the request
341 *             conflicts with existing mapping in entry 3.
342 *         -1: invalid argument
343 *         -3: driver not initialized (or initialization
344 *             failed because TLB0 is in use).
345 *         <0: other error
346 *
347 */
348#define E500_TLB_ATTR_WIMGE(x)      ((x)&0x7f)                          /* includes user bits */
349#define E500_TLB_ATTR_WIMGE_GET(x)  ((x)&0x7f)
350#define E500_TLB_ATTR_TS            (1<<7)
351#define E500_TLB_ATTR_PERM(x)              (((x)&0x3ff)<<8)
352#define E500_TLB_ATTR_PERM_GET(x)   (((x)>>8)&0x3ff)
353#define E500_TLB_ATTR_TID(x)        (((x)&0xfff)<<20)
354#define E500_TLB_ATTR_TID_GET(x)    (((x)>>20)&0xfff)
355
356int
357rtems_e500_wrtlb(int idx, uint32_t ea, uint32_t pa, int sz, uint32_t attr)
358{
359uint32_t              mas1, mas2, mas3, mas4;
360uint32_t              tid, msk;
361int                   lkup;
362rtems_interrupt_level lvl;
363
364        if ( sz >= 1024 ) {
365                /* Assume they literally specify a size */
366                msk = sz;
367                sz  = 0;
368                while ( msk != (1024<<(2*sz)) ) {
369                        if ( ++sz > 15 ) {
370                                return -1;
371                        }
372                }
373                /* OK, acceptable */
374        }
375
376        msk = sz > 0 ? (1024<<(2*sz)) - 1 : 0;
377
378        if ( !initialized && sz > 0 ) {
379                myprintf(stderr,"TLB driver not initialized; refuse to enable any entry\n");
380                return -3;
381        }
382
383        if ( (ea & msk) || (pa & msk) ) {
384                myprintf(stderr,"Misaligned ea or pa\n");
385                return -1;
386        }
387
388        if ( idx < 0 || idx > 15 )
389                return -1;
390
391        if ( sz > 15 ) {
392                /* but e500v1 doesn't support all 16 sizes!! */
393                /* FIXME: we should inquire about this CPU's
394                 *        capabilities...
395                 */
396                return -1;
397        }
398
399        tid = E500_TLB_ATTR_TID_GET(attr);
400
401        mas1 = (attr & E500_TLB_ATTR_TS) ? FSL_EIS_MAS1_TS : 0;
402
403        if ( sz >=0 ) {
404                lkup = rtems_e500_matchtlb(ea, tid, mas1, sz);
405
406                if ( lkup < -1 ) {
407                        /* some error */
408                        return lkup;
409                }
410
411                if ( lkup >= 0 && lkup != idx ) {
412                        myprintf(stderr,"TLB[1] #%i overlaps with requested mapping\n", lkup);
413                        rtems_e500_prtlb( E500_SELTLB_1 | lkup, 0, stderr);
414                        return lkup+1;
415                }
416        }
417
418        /* OK to proceed */
419        mas1 |= FSL_EIS_MAS1_IPROT | FSL_EIS_MAS1_TID(tid);
420
421        if ( sz >= 0 )
422                mas1 |= FSL_EIS_MAS1_V | FSL_EIS_MAS1_TSIZE(sz);
423
424        mas2 = FSL_EIS_MAS2_EPN( ea>>12 ) | E500_TLB_ATTR_WIMGE(attr);
425        mas3 = FSL_EIS_MAS3_RPN( pa>>12 ) | E500_TLB_ATTR_PERM_GET(attr);
426        /* mas4 is not really relevant; we don't use TLB replacement */
427        mas4 = FSL_EIS_MAS4_TLBSELD | FSL_EIS_MAS4_TIDSELD(0) | FSL_EIS_MAS4_TSIZED(9) | FSL_EIS_MAS4_ID | FSL_EIS_MAS4_GD;
428
429        rtems_interrupt_disable(lvl);
430
431        seltlb(idx | E500_SELTLB_1);
432
433        _write_MAS1(mas1);
434        _write_MAS2(mas2);
435        _write_MAS3(mas3);
436        _write_MAS4(mas4);
437
438        asm volatile(
439                "       sync            \n"
440                "       isync           \n"
441                "       tlbwe       \n"
442                "       sync        \n"
443                "       isync           \n"
444        );
445
446        rtems_interrupt_enable(lvl);
447
448        /* update cache */
449        rtems_e500_prtlb( E500_SELTLB_1 | idx, 1, 0);
450
451        return 0;
452}
453
454/*
455 * Check if a ts/tid/ea/sz mapping overlaps
456 * with an existing entry.
457 *
458 * ASSUMPTION: all TLB0 (fixed 4k pages) are invalid and always unused.
459 *
460 * NOTE: 'sz' is the 'logarithmic' size selector; the page size
461 *       is 1024*2^(2*sz).
462 *
463 * RETURNS:
464 *     >= 0: index of TLB1 entry that already provides a mapping
465 *           which overlaps within the ea range.
466 *       -1: SUCCESS (no conflicting entry found)
467 *     <=-2: ERROR (invalid input)
468 */
469int rtems_e500_matchtlb(uint32_t ea, uint32_t tid, int ts, int sz)
470{
471int                  i;
472uint32_t             m,a;
473E500_tlb_va_cache_t *tlb;
474
475        if ( sz < 0 || sz > 15 )
476                return -4;
477
478        sz = (1024<<(2*sz));
479
480        if ( !initialized ) {
481                /* cache not initialized */
482                return -3;
483        }
484
485        if ( ea & (sz-1) ) {
486                /* misaligned ea */
487                return -2;
488        }
489
490        if ( ts )
491                ts = 1;
492
493        for ( i=0, tlb=rtems_e500_tlb_va_cache; i<16; i++, tlb++ ) {
494                if ( ! tlb->att.v )
495                        continue;
496                if ( tlb->att.ts != ts )
497                        continue;
498                if ( tlb->va.va_tid && tlb->va.va_tid != tid )
499                        continue;
500                /* TID and TS match a valid entry */
501                m  = (1024<<(2*tlb->att.sz)) - 1;
502                /* calculate starting address of this entry */
503                a  = tlb->va.va_epn<<12;
504                if ( ea <= a + m && ea + sz -1 >= a ) {
505                        /* overlap */
506                        return i;
507                }
508        }
509        return -1;
510}
511
512/* Find TLB index that maps 'ea/as' combination
513 *
514 * RETURNS: index 'key'; i.e., the index number plus
515 *          a bit (E500_SELTLB_1) which indicates whether
516 *          the mapping was found in TLB0 (4k fixed page
517 *          size) or in TLB1 (variable page size).
518 *
519 *          On error (no mapping) -1 is returned.
520 */
521rtems_e500_tlb_idx
522rtems_e500_ftlb(uint32_t ea, int as)
523{
524uint32_t              pid, mas0, mas1;
525int                   i, rval = -1;
526rtems_interrupt_level lvl;
527
528        rtems_interrupt_disable(lvl);
529
530        for ( i=0; i<3; i++ ) {
531                switch (i) {
532                        case 0: asm volatile("mfspr %0, %1":"=r"(pid):"i"(FSL_EIS_PID0)); break;
533                        case 1: asm volatile("mfspr %0, %1":"=r"(pid):"i"(FSL_EIS_PID1)); break;
534                        case 2: asm volatile("mfspr %0, %1":"=r"(pid):"i"(FSL_EIS_PID2)); break;
535                        default:
536                                goto bail;
537                }
538
539                _write_MAS6( FSL_EIS_MAS6_SPID0(pid) | (as ? FSL_EIS_MAS6_SAS : 0 ) );
540
541                asm volatile("tlbsx 0, %0"::"r"(ea));
542
543                mas1 = _read_MAS1();
544
545                if ( (FSL_EIS_MAS1_V & mas1) ) {
546                        mas0 = _read_MAS0();
547                        if ( FSL_EIS_MAS0_TLBSEL & mas0 ) {
548                                /* TLB1 */
549                                rval = FSL_EIS_MAS0_ESEL_GET(mas0) | E500_SELTLB_1;
550                        } else {
551                                rval = (ea >> (63-51)) | (( FSL_EIS_MAS0_NV & mas0 ) ? 180 : 0 ) ;
552                        }
553                        break;
554                }
555        }
556
557bail:
558        rtems_interrupt_enable(lvl);
559        return rval;
560}
561
562/* Mark TLB entry as invalid ('disabled'). Unlike
563 * rtems_e500_wrtlb() with a negative size argument
564 * this routine also can disable TLB0 entries.
565 *
566 * 'key': TLB entry (index) ORed with selector bit
567 *        (0 for TLB0, E500_SELTLB_1 for TLB1).
568 *
569 * RETURNS: zero on success, nonzero on error (TLB
570 *          unchanged).
571 *
572 * NOTE:  If a TLB1 entry is disabled the associated
573 *        entry in rtems_e500_va_cache[] is also
574 *        marked as disabled.
575 */
576int
577rtems_e500_clrtlb(rtems_e500_tlb_idx key)
578{
579rtems_e500_tlb_idx    k0;
580rtems_interrupt_level lvl;
581
582        /* minimal guard against bad key */
583        if ( key < 0 )
584                return -1;
585
586        if ( (key & E500_SELTLB_1) ) {
587                if ( (key & ~E500_SELTLB_1) > 15 ) {
588                        myprintf(stderr,"Invalid TLB index; TLB1 index must be < 16\n");
589                        return -1;
590                }
591        } else if ( key > 255 ) {
592                        myprintf(stderr,"Invalid TLB index; TLB0 index must be < 256\n");
593                        return -1;
594        }
595
596        /* Must not invalidate page 0 which holds vectors, text etc...  */
597        k0 = rtems_e500_ftlb(0, 0);
598        if ( -1 == k0 ) {
599                myprintf(stderr,"tlbivax; something's fishy - I don't find mapping for addr. 0\n");
600                return -1;
601        }
602
603        /* NOTE: we assume PID is ignored, and AS is 0 */
604        if ( k0 == key ) {
605                myprintf(stderr,"Refuse to invalidate page holding addr 0 (always needed)\n");
606                return -1;
607        }
608
609        rtems_interrupt_disable(lvl);
610
611        seltlb(key);
612
613        asm volatile("tlbre");
614
615        /* read old entries */
616        _write_MAS1( _read_MAS1() & ~FSL_EIS_MAS1_V );
617
618        asm volatile(
619                "       sync            \n"
620                "       isync           \n"
621                "       tlbwe       \n"
622                "       sync        \n"
623                "       isync           \n"
624        );
625
626        /* update cache */
627        if ( E500_SELTLB_1 & key )
628                rtems_e500_tlb_va_cache[ (~E500_SELTLB_1 & key) ].att.v = 0;
629
630        rtems_interrupt_enable(lvl);
631
632        return 0;
633}
Note: See TracBrowser for help on using the repository browser.