source: rtems/bsps/powerpc/shared/mmu/e500-mmu.c @ 9b3b33d

Last change on this file since 9b3b33d was 9b3b33d, checked in by Sebastian Huber <sebastian.huber@…>, on 04/07/20 at 06:26:00

bsps/powerpc: Fix inline assembly

GCC 10 no longer passes -many to the assembler. This enables more
checks in the assembler.

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