OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [orpsocv2/] [sw/] [tests/] [or1200/] [sim/] [or1200-mmu.c] - Blame information for rev 477

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 349 julius
//////////////////////////////////////////////////////////////////////
2
////                                                              ////
3
////                                                              ////
4
//// OR1200 MMU test                                              ////
5
////                                                              ////
6
////                                                              ////
7
//////////////////////////////////////////////////////////////////////
8
////                                                              ////
9
//// Copyright (C) 2010 Authors and OPENCORES.ORG                 ////
10
////                                                              ////
11
//// This source file may be used and distributed without         ////
12
//// restriction provided that this copyright statement is not    ////
13
//// removed from the file and that any derivative work contains  ////
14
//// the original copyright notice and the associated disclaimer. ////
15
////                                                              ////
16
//// This source file is free software; you can redistribute it   ////
17
//// and/or modify it under the terms of the GNU Lesser General   ////
18
//// Public License as published by the Free Software Foundation; ////
19
//// either version 2.1 of the License, or (at your option) any   ////
20
//// later version.                                               ////
21
////                                                              ////
22
//// This source is distributed in the hope that it will be       ////
23
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
24
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
25
//// PURPOSE.  See the GNU Lesser General Public License for more ////
26
//// details.                                                     ////
27
////                                                              ////
28
//// You should have received a copy of the GNU Lesser General    ////
29
//// Public License along with this source; if not, download it   ////
30
//// from http://www.opencores.org/lgpl.shtml                     ////
31
////                                                              ////
32
//////////////////////////////////////////////////////////////////////
33
 
34
// Tests most functions of the MMUs.
35
// The tests attempt to keep the areas of instruction and data memory working 
36
// as they should, while testing around them, higher in memory. Some linker 
37
// variables are relied upon by the interrupt routines for checking if areas 
38
// are within the expected text areas of memory, but usually we just keep 
39
// above the stack (also set in the linker script) and things go OK.
40
 
41
// The tests for translation setup address translation in the MMU from areas 
42
// in the 512kB - 1024kB region (64 sets in OR1200, 8kByte per set) to halfway
43
// through RAM. Usually the sets taht would encompass the actual program are 
44
// skipped (TLB_TEXT_SET_NB) ie, we say how many sets encompass the program 
45
// text for itlb tests and only do tests above it (so, on sets 8-64, meaning 
46
// when we enable the iMMU and say have the execution bits disabled to force a
47
// page fault the program gets to continue and is translated 1-1 while 
48
// accesses to the areas we are testing will cause a page fault) but it should
49
//  still work to test all sets.
50
 
51
// In essense, the tests are aware that they could be operating out of the 
52
// same memory the tests are being performed in and takes care of this.
53
 
54
// The use of the "match_space" variable is for the addresses we'll access 
55
// when a non-1-1 translation will occur, otherwise usually the 
56
// "translate_space" variable by itself is used (it's first setup to the 
57
// desired address, and either data or the return instructions are placed 
58
// where we expect the MMU to translate to)
59
 
60 393 julius
#include "cpu-utils.h"
61 349 julius
#include "spr-defs.h"
62
#include "board.h"
63 351 julius
// Uncomment uart.h include for UART output
64
//#include "uart.h"
65 393 julius
//#include "printf.h"
66 349 julius
 
67 351 julius
// Uncomment the following to completely remove all printfs, or comment them
68
// out to enable printf()s, but slows down RTL simulation a lot.
69
#undef printf
70
#define printf(a, ...)
71 349 julius
 
72
#include "or1200-defines.h"
73
 
74
#ifdef OR1200_NO_IMMU
75
# error
76 351 julius
# error Processor has no instruction MMU. Cannot run this test without it.
77 349 julius
# error
78
#endif
79
 
80
#ifdef OR1200_NO_DMMU
81
# error
82 351 julius
# error Processor has no data MMU. Cannot run this test without it.
83 349 julius
# error
84
#endif
85
 
86
 
87 477 julius
// Define to run only tests on SHORT_TEST_NUM TLB sets
88 349 julius
#define SHORT_TEST
89 477 julius
#define SHORT_TEST_NUM 4
90 349 julius
 
91 477 julius
// Defines useful when wishing to skip instruction or data MMU tests when doing
92
// development on one or the other.
93
 
94
// Set this to 1 to enable the IMMU tests
95
#define DO_IMMU_TESTS 1
96 349 julius
// Set this to 1 to enable the DMMU tests
97
#define DO_DMMU_TESTS 1
98
 
99
// Symbols defined in linker script
100 373 julius
extern unsigned long _endtext;
101
extern unsigned long _stext;
102
extern unsigned long _edata;
103
extern unsigned long _stack;
104 349 julius
 
105
unsigned long start_text_addr;
106
unsigned long end_text_addr;
107
unsigned long end_data_addr;
108
 
109
/* For shorter simulation run */
110
#define RTL_SIM 1
111
 
112
/* Define RAM physical location and size
113
Bottom half will be used for this program, the rest
114
will be used for testing */
115
#define RAM_START   0x00000000
116 462 julius
// Assume only 2MB memory
117
#define RAM_SIZE    0x00200000
118 349 julius
 
119
#define VM_BASE 0xc0000000
120
 
121
/* What is the last address in ram that is used by this program */
122
#define TEXT_START_ADD start_text_addr
123
#define TEXT_END_ADD end_text_addr
124
#define DATA_END_ADD end_data_addr
125
 
126 351 julius
// Pages to start tests at. This should correspond to where the stack is set. 
127
// We can set this by hand or figure it out at runtime.
128
// Uncomment the following 3 lines to hard-set the bottom page to test at:
129
//#define TLB_BOTTOM_TEST_PAGE_HARDSET
130
//#define TLB_TEXT_SET_NB 16
131
//#define TLB_DATA_SET_NB 16
132 349 julius
 
133 351 julius
// Uncomment the following to determine the page to test from at run-time
134
unsigned long TLB_TEXT_SET_NB;
135
unsigned long TLB_DATA_SET_NB;
136
 
137 349 julius
/* MMU page size */
138
#define PAGE_SIZE 8192
139
 
140
/* Number of DTLB sets used (power of 2, max is 256) */
141
#define DTLB_SETS 64
142
 
143
/* Number of DTLB ways (1, 2, 3 etc., max is 4). */
144
#define DTLB_WAYS 1
145
 
146
/* Number of ITLB sets used (power of 2, max is 256) */
147
#define ITLB_SETS 64
148
 
149
/* Number of ITLB ways (1, 2, 3 etc., max is 4). */
150
#define ITLB_WAYS 1
151
 
152
/* TLB mode codes */
153
#define TLB_CODE_ONE_TO_ONE     0x00000000
154
#define TLB_CODE_PLUS_ONE_PAGE  0x10000000
155
#define TLB_CODE_MINUS_ONE_PAGE 0x20000000
156
 
157
#define TLB_CODE_MASK   0xfffff000
158
#define TLB_PR_MASK     0x00000fff
159
 
160
 
161
 
162
/* fails if x is false */
163
#define ASSERT(x) ((x)?1: fail (__FUNCTION__, __LINE__))
164
 
165
// iMMU and dMMU enable functions
166
extern void lo_dmmu_en (void);
167
extern void lo_immu_en (void);
168
 
169
/* Local functions prototypes */
170
void dmmu_disable (void);
171
void immu_disable (void);
172
 
173
// Machine code for l.jr r9 and then l.nop
174
#define OR32_L_JR_R9 0x44004800
175
#define OR32_L_NOP 0x15000000
176
 
177
/* Global variables */
178
extern unsigned long ram_end;
179
 
180
/* DTLB mode status */
181
volatile unsigned long dtlb_val;
182
 
183
/* ITLB mode status */
184
volatile unsigned long itlb_val;
185
 
186
/* DTLB miss counter */
187
volatile int dtlb_miss_count;
188
 
189
/* Data page fault counter */
190
volatile int dpage_fault_count;
191
 
192
/* ITLB miss counter */
193
volatile int itlb_miss_count;
194
 
195
/* Instruction page fault counter */
196
volatile int ipage_fault_count;
197
 
198
/* EA of last DTLB miss exception */
199
unsigned long dtlb_miss_ea;
200
 
201
/* EA of last data page fault exception */
202
unsigned long dpage_fault_ea;
203
 
204
/* EA of last ITLB miss exception */
205
unsigned long itlb_miss_ea;
206
 
207
/* EA of last insn page fault exception */
208
unsigned long ipage_fault_ea;
209
 
210
 
211
#define sys_call() __asm__ __volatile__("l.sys\t0");
212
/*
213
void sys_call (void)
214
{
215
  asm("l.sys\t0");
216
}
217
*/
218
void fail (char *func, int line)
219
{
220
#ifndef __FUNCTION__
221
#define __FUNCTION__ "?"
222
#endif
223
 
224
  /* Trigger sys call exception to enable supervisor mode again */
225
  sys_call ();
226
 
227
  immu_disable ();
228
  dmmu_disable ();
229
 
230
  report(line);
231
  report (0xeeeeeeee);
232
  exit (1);
233
}
234
 
235
void call(unsigned long add)
236
{
237
  asm("l.jalr\t\t%0" : : "r" (add) : "r9", "r11");
238
  asm("l.nop" : :);
239
}
240
 
241
void jump(void)
242
{
243
  return;
244
  /*asm("_jr:");
245
  asm("l.jr\t\tr9") ;
246
  asm("l.nop" : :);*/
247
}
248
 
249
void copy_jump(unsigned long phy_add)
250
{
251
  memcpy((void *)phy_add, (void *)&jump, (8*4));
252
}
253
 
254
/* Bus error exception handler */
255
void bus_err_handler (void)
256
{
257
  /* This shouldn't happend */
258
  printf("Test failed: Bus error\n");
259
  report (0xeeeeeeee);
260
  exit (1);
261
}
262
 
263
/* Illegal insn exception handler */
264
void ill_insn_handler (void)
265
{
266
  /* This shouldn't happend */
267
  printf("Test failed: Illegal insn\n");
268
  report (0xeeeeeeee);
269
  exit (1);
270
}
271
 
272
/* Sys call exception handler */
273
void sys_call_handler (void)
274
{
275
  /* Set supervisor mode */
276
  mtspr (SPR_ESR_BASE, mfspr (SPR_ESR_BASE) | SPR_SR_SM);
277
}
278
 
279
/* DTLB miss exception handler */
280
void dtlb_miss_handler (void)
281
{
282
  unsigned long ea, ta, tlbtr;
283
  int set, way = 0;
284
  int i;
285
 
286
  /* Get EA that cause the exception */
287
  ea = mfspr (SPR_EEAR_BASE);
288
 
289
  /* Find TLB set and LRU way */
290
  set = (ea / PAGE_SIZE) % DTLB_SETS;
291
  for (i = 0; i < DTLB_WAYS; i++) {
292
    if ((mfspr (SPR_DTLBMR_BASE(i) + set) & SPR_DTLBMR_LRU) == 0) {
293
      way = i;
294
      break;
295
    }
296
  }
297
 
298
  printf("dtlb miss ea = %.8lx set = %d way = %d\n", ea, set, way);
299
 
300
  // Anything under the stack belongs to the program, direct tranlsate it
301 373 julius
  if (ea < (unsigned long)&_stack){
302 349 julius
    /* If this is acces to data of this program set one to one translation */
303
    mtspr (SPR_DTLBMR_BASE(way) + set, (ea & SPR_DTLBMR_VPN) | SPR_DTLBMR_V);
304
    mtspr (SPR_DTLBTR_BASE(way) + set, (ea & SPR_DTLBTR_PPN) | DTLB_PR_NOLIMIT);
305
    return;
306
  }
307
 
308
  /* Update DTLB miss counter and EA */
309
  dtlb_miss_count++;
310
  dtlb_miss_ea = ea;
311
 
312
  // Everything gets translated back to the space halfway through RAM
313
  ta = (set*PAGE_SIZE) + RAM_START + (RAM_SIZE/2);
314
  tlbtr = (ta & SPR_DTLBTR_PPN) | (dtlb_val & TLB_PR_MASK);
315
  printf("ta = %.8lx tlbtr = %.8lx dtlb_val = %.8lx\n",ta, tlbtr, dtlb_val);
316
 
317
  /* Set DTLB entry */
318
  mtspr (SPR_DTLBMR_BASE(way) + set, (ea & SPR_DTLBMR_VPN) | SPR_DTLBMR_V);
319
  mtspr (SPR_DTLBTR_BASE(way) + set, tlbtr);
320
}
321
 
322
/* Data page fault exception handler */
323
void dpage_fault_handler (void)
324
{
325
  unsigned long ea;
326
  int set, way = 0;
327
  int i;
328
 
329
  /* Get EA that cause the exception */
330
  ea = mfspr (SPR_EEAR_BASE);
331
 
332
  /* Find TLB set and way */
333
  set = (ea / PAGE_SIZE) % DTLB_SETS;
334
  for (i = 0; i < DTLB_WAYS; i++) {
335
    if ((mfspr (SPR_DTLBMR_BASE(i) + set) & SPR_DTLBMR_VPN) ==
336
        (ea & SPR_DTLBMR_VPN)) {
337
      way = i;
338
      break;
339
    }
340
  }
341
 
342
  printf("ea = %.8lx set = %d way = %d\n", ea, set, way);
343
 
344
  if (((RAM_START <= ea) & (ea < DATA_END_ADD) ) |
345
      ((TEXT_START_ADD <= ea) & (ea < TEXT_END_ADD))) {
346
    /* If this is acces to data of this program set one to one translation */
347
    mtspr (SPR_DTLBTR_BASE(way) + set, (ea & SPR_DTLBTR_PPN) | DTLB_PR_NOLIMIT);
348
    return;
349
  }
350
 
351
  /* Update data page fault counter and EA */
352
  dpage_fault_count++;
353
  dpage_fault_ea = ea;
354
 
355
  /* Give permission */
356
  mtspr (SPR_DTLBTR_BASE(way) + set,
357
         (mfspr (SPR_DTLBTR_BASE(way) + set) & ~DTLB_PR_NOLIMIT) | dtlb_val);
358
}
359
 
360
 
361
/* ITLB miss exception handler */
362
void itlb_miss_handler (void)
363
{
364
  unsigned long ea, ta, tlbtr;
365
  int set, way = 0;
366
  int i;
367
 
368
  /* Get EA that cause the exception */
369
  ea = mfspr (SPR_EEAR_BASE);
370
 
371
  /* Find TLB set and LRU way */
372
  set = (ea / PAGE_SIZE) % ITLB_SETS;
373
  for (i = 0; i < ITLB_WAYS; i++) {
374
    if ((mfspr (SPR_ITLBMR_BASE(i) + set) & SPR_ITLBMR_LRU) == 0) {
375
      way = i;
376
      break;
377
    }
378
  }
379
 
380
  printf("itlb miss ea = %.8lx set = %d way = %d\n", ea, set, way);
381
 
382
  if ((TEXT_START_ADD <= ea) && (ea < TEXT_END_ADD)) {
383
    /* If this is acces to data of this program set one to one translation */
384
    mtspr (SPR_ITLBMR_BASE(way) + set, (ea & SPR_ITLBMR_VPN) | SPR_ITLBMR_V);
385
    mtspr (SPR_ITLBTR_BASE(way) + set, (ea & SPR_ITLBTR_PPN) | ITLB_PR_NOLIMIT);
386
    return;
387
  }
388
 
389
  /* Update ITLB miss counter and EA */
390
  itlb_miss_count++;
391
  itlb_miss_ea = ea;
392
 
393
  /* Whatever access is in progress, translated address have to point to
394
     physical RAM */
395
 
396
  ta = RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE);
397
  tlbtr = (ta & SPR_ITLBTR_PPN) | (itlb_val & TLB_PR_MASK);
398
 
399
  printf("ta = %.8lx\n", ta);
400
 
401
  /* Set ITLB entry */
402
  mtspr (SPR_ITLBMR_BASE(way) + set, (ea & SPR_ITLBMR_VPN) | SPR_ITLBMR_V);
403
  mtspr (SPR_ITLBTR_BASE(way) + set, tlbtr);
404
}
405
 
406
/* Intstruction page fault exception handler */
407
void ipage_fault_handler (void)
408
{
409
  unsigned long ea;
410
  int set, way = 0;
411
  int i;
412
 
413
  /* Get EA that cause the exception */
414
  ea = mfspr (SPR_EEAR_BASE);
415
 
416
  /* Find TLB set and way */
417
  set = (ea / PAGE_SIZE) % ITLB_SETS;
418
  for (i = 0; i < ITLB_WAYS; i++) {
419
    if ((mfspr (SPR_ITLBMR_BASE(i) + set) & SPR_ITLBMR_VPN) == (ea & SPR_ITLBMR_VPN)) {
420
      way = i;
421
      break;
422
    }
423
  }
424
 
425
  printf("ipage fault: ea = %.8lx set = %d way = %d\n", ea, set, way);
426
 
427
  if ((TEXT_START_ADD <= ea) && (ea < TEXT_END_ADD)) {
428
    /* If this is acces to data of this program set one to one translation */
429
    mtspr (SPR_DTLBTR_BASE(way) + set, (ea & SPR_DTLBTR_PPN) | ITLB_PR_NOLIMIT);
430
    return;
431
  }
432
 
433
  printf("ipage fault was outside of code area\n", ea, set, way);
434
 
435
  /* Update instruction page fault counter and EA */
436
  ipage_fault_count++;
437
  ipage_fault_ea = ea;
438
 
439
  /* Give permission */
440
  mtspr (SPR_ITLBTR_BASE(way) + set, (mfspr (SPR_ITLBTR_BASE(way) + set) & ~ITLB_PR_NOLIMIT) | itlb_val);
441
}
442
 
443
/* Invalidate all entries in DTLB and enable DMMU */
444
void dmmu_enable (void)
445
{
446
  /* Register DTLB miss handler */
447
  add_handler(0x9, dtlb_miss_handler);
448
  //excpt_dtlbmiss = (unsigned long)dtlb_miss_handler;
449
 
450
  /* Register data page fault handler */
451
  add_handler(0x3, dpage_fault_handler);
452
  //excpt_dpfault = (unsigned long)dpage_fault_handler;
453
 
454
  /* Enable DMMU */
455
  lo_dmmu_en ();
456
 
457
}
458
 
459
/* Disable DMMU */
460
void dmmu_disable (void)
461
{
462
  mtspr (SPR_SR, mfspr (SPR_SR) & ~SPR_SR_DME);
463
}
464
 
465
/* Invalidate all entries in ITLB and enable IMMU */
466
void immu_enable (void)
467
{
468
  /* Register ITLB miss handler */
469
  add_handler(0xa, itlb_miss_handler);
470
  //excpt_itlbmiss = (unsigned long)itlb_miss_handler;
471
 
472
  /* Register instruction page fault handler */
473
  add_handler(0x4, ipage_fault_handler);
474
  //excpt_ipfault = (unsigned long)ipage_fault_handler;
475
 
476
  /* Enable IMMU */
477
  lo_immu_en ();
478
 
479
}
480
 
481
/* Disable IMMU */
482
void immu_disable (void)
483
{
484
  mtspr (SPR_SR, mfspr (SPR_SR) & ~SPR_SR_IME);
485
}
486
 
487
void write_pattern(unsigned long start, unsigned long end)
488
{
489
  unsigned long add;
490
 
491
  add = start;
492
  while (add < end) {
493
    REG32(add) = add;
494
    add += PAGE_SIZE;
495
  }
496
 
497
}
498
 
499
/* Translation address register test
500
Set various translation and check the pattern */
501
int dtlb_translation_test (void)
502
{
503
  int i, j;
504
  unsigned long ea, ta;
505
 
506
  /* Disable DMMU */
507
  dmmu_disable();
508
 
509
  printf("dtlb translation test set\n");
510
 
511
  /* Invalidate all entries in DTLB */
512
  for (i = 0; i < DTLB_WAYS; i++) {
513
    for (j = 0; j < DTLB_SETS; j++) {
514
      mtspr (SPR_DTLBMR_BASE(i) + j, 0);
515
      mtspr (SPR_DTLBTR_BASE(i) + j, 0);
516
    }
517
  }
518
 
519
  /* Set one to one translation for program's data space */
520
  for (i = 0; i < TLB_DATA_SET_NB; i++) {
521
    ea = RAM_START + (i*PAGE_SIZE);
522
    ta = RAM_START + (i*PAGE_SIZE);
523
    mtspr (SPR_DTLBMR_BASE(0) + i, ea | SPR_DTLBMR_V);
524
    mtspr (SPR_DTLBTR_BASE(0) + i, ta | (DTLB_PR_NOLIMIT));
525
  }
526
 
527
  /* Set dtlb permisions */
528
  dtlb_val = DTLB_PR_NOLIMIT;
529
 
530
  /* Write test pattern */
531
  for (i = 0; i < DTLB_SETS; i++) {
532
    ea = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
533
    REG32(ea) = i;
534
    ea = RAM_START + (RAM_SIZE/2) + ((i + 1)*PAGE_SIZE) - 4;
535
    REG32(ea) = 0xffffffff - i;
536
  }
537
 
538
  /* Set one to one translation */
539
  for (i = TLB_DATA_SET_NB; i < DTLB_SETS; i++) {
540
    ea = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
541
    ta = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
542
    mtspr (SPR_DTLBMR_BASE(DTLB_WAYS - 1) + i, ea | SPR_DTLBMR_V);
543
    mtspr (SPR_DTLBTR_BASE(DTLB_WAYS - 1) + i, ta | DTLB_PR_NOLIMIT);
544
  }
545
 
546
  /* Enable DMMU */
547
  dmmu_enable();
548
 
549
  /* Check the pattern */
550
  for (i = TLB_DATA_SET_NB; i < DTLB_SETS; i++) {
551
    ea = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
552
    ASSERT(REG32(ea) == i);
553
    ea = RAM_START + (RAM_SIZE/2) + ((i + 1)*PAGE_SIZE) - 4;
554
    ASSERT(REG32(ea) == (0xffffffff - i));
555
  }
556
 
557
  /* Write new pattern */
558
  for (i = TLB_DATA_SET_NB; i < DTLB_SETS; i++) {
559
    ea = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
560
    REG32(ea) = 0xffffffff - i;
561
    ea = RAM_START + (RAM_SIZE/2) + ((i + 1)*PAGE_SIZE) - 4;
562
    REG32(ea) = i;
563
  }
564
 
565
  /* Set 0 -> RAM_START + (RAM_SIZE/2) translation */
566
  for (i = TLB_DATA_SET_NB; i < DTLB_SETS; i++) {
567
    ea = i*PAGE_SIZE;
568
    ta = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
569
    mtspr (SPR_DTLBMR_BASE(DTLB_WAYS - 1) + i, ea | SPR_DTLBMR_V);
570
    mtspr (SPR_DTLBTR_BASE(DTLB_WAYS - 1) + i, ta | DTLB_PR_NOLIMIT);
571
  }
572
 
573
  /* Check the pattern */
574
  for (i = TLB_DATA_SET_NB; i < DTLB_SETS; i++) {
575
    ea = i*PAGE_SIZE;
576
    ASSERT(REG32(ea) == (0xffffffff - i));
577
    ea = ((i + 1)*PAGE_SIZE) - 4;
578
    ASSERT(REG32(ea) == i);
579
  }
580
 
581
  /* Write new pattern */
582
  for (i = TLB_DATA_SET_NB; i < DTLB_SETS; i++) {
583
    REG32(i*PAGE_SIZE) = i;
584 351 julius
    REG32(((i + 1)*PAGE_SIZE) - 4) = 0xffffffff - i;
585 349 julius
  }
586
 
587
  /* Set hi -> lo, lo -> hi translation */
588
  for (i = TLB_DATA_SET_NB; i < DTLB_SETS; i++) {
589
    ea = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
590 351 julius
    ta = RAM_START + (RAM_SIZE/2) + ((DTLB_SETS - i - 1 + TLB_DATA_SET_NB)*
591
                                     PAGE_SIZE);
592 349 julius
    mtspr (SPR_DTLBMR_BASE(DTLB_WAYS - 1) + i, ea | SPR_DTLBMR_V);
593
    mtspr (SPR_DTLBTR_BASE(DTLB_WAYS - 1) + i, ta | DTLB_PR_NOLIMIT);
594
  }
595
 
596
  /* Check the pattern */
597
  for (i = TLB_DATA_SET_NB; i < DTLB_SETS; i++) {
598
    ea = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
599
    ASSERT(REG32(ea) == (DTLB_SETS - i - 1 + TLB_DATA_SET_NB));
600
    ea = RAM_START + (RAM_SIZE/2) + ((i + 1)*PAGE_SIZE) - 4;
601
    ASSERT(REG32(ea) == (0xffffffff - DTLB_SETS + i + 1 - TLB_DATA_SET_NB));
602
  }
603
 
604
  /* Write new pattern */
605
  for (i = TLB_DATA_SET_NB; i < DTLB_SETS; i++) {
606
    REG32(RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE)) = 0xffffffff - i;
607
    REG32(RAM_START + (RAM_SIZE/2) + ((i + 1)*PAGE_SIZE) - 4) = i;
608
  }
609
 
610
  /* Disable DMMU */
611
  dmmu_disable();
612
 
613
  /* Check the pattern */
614
  for (i = TLB_DATA_SET_NB; i < DTLB_SETS; i++) {
615
    ea = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
616
    ASSERT(REG32(ea) == (0xffffffff - DTLB_SETS + i + 1 - TLB_DATA_SET_NB));
617
    ea = RAM_START + (RAM_SIZE/2) + ((i + 1)*PAGE_SIZE) - 4;
618
    ASSERT(REG32(ea) == (DTLB_SETS - i - 1 + TLB_DATA_SET_NB));
619
  }
620
 
621
  printf("-------------------------------------------\n");
622
 
623
  return 0;
624
}
625
 
626
/* EA match register test
627
Shifting one in DTLBMR and performing accesses to boundaries
628
of the page, checking the triggering of exceptions */
629
int dtlb_match_test (int way, int set)
630
{
631
  int i, j, tmp;
632
  unsigned long add, t_add;
633
  unsigned long ea, ta;
634
 
635
  /* Disable DMMU */
636
  dmmu_disable();
637
 
638
  printf("dtlb_match_test - way %d set %d\n",way, set);
639
 
640
  /* Invalidate all entries in DTLB */
641
  for (i = 0; i < DTLB_WAYS; i++) {
642
    for (j = 0; j < DTLB_SETS; j++) {
643
      mtspr (SPR_DTLBMR_BASE(i) + j, 0);
644
      mtspr (SPR_DTLBTR_BASE(i) + j, 0);
645
    }
646
  }
647
 
648
  // Program text/data pages should be 1-1 translation
649
  for (i = 0; i < TLB_DATA_SET_NB; i++) {
650
    ea = RAM_START + (i*PAGE_SIZE);
651
    ta = RAM_START + (i*PAGE_SIZE);
652
    mtspr (SPR_DTLBMR_BASE(0) + i, ea | SPR_DTLBMR_V);
653
    mtspr (SPR_DTLBTR_BASE(0) + i, ta | DTLB_PR_NOLIMIT);
654
  }
655
 
656
  /* Set dtlb permisions */
657
  dtlb_val = DTLB_PR_NOLIMIT;
658
 
659
  // Setup match area address - based at halfway through RAM, 
660
  // and then offset by the area encompassed by the set we wish to test.
661
  unsigned long translate_space = RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE);
662
 
663
  /* Set pattern */
664
  // Last word of page before the one covered by this set
665
  REG32(translate_space - 4) = 0x00112233;
666
  //printf("pattern0 @ 0x%.8lx = 0x%.8lx\n", translate_space-4, REG32(translate_space - 4) );
667
  // First word of page covered by this set
668
  REG32(translate_space) = 0x44556677;
669
  // Last word of page covered by this set
670
  REG32(translate_space + PAGE_SIZE - 4) = 0x8899aabb;
671
  // First word of page covered by next set
672
  REG32(translate_space + PAGE_SIZE) = 0xccddeeff;
673
 
674
  /* Enable DMMU */
675
  dmmu_enable();
676
 
677
  /* Shifting one in DTLBMR */
678
  i = 0;
679
 
680
  // Setup match space - place we will do accesses to, and have them
681
  // tranlsated into the translate space addresses
682
  unsigned long match_space = (PAGE_SIZE*DTLB_SETS) + (set*PAGE_SIZE);  // 
683
 
684
  //add = (PAGE_SIZE*DTLB_SETS); // 8kB * 64, 512KB
685
  //t_add = add + (set*PAGE_SIZE); // 
686
  while (add != 0x00000000) {
687
    // Set MATCH register for the areas we will access explicitly, and validate it
688
    mtspr (SPR_DTLBMR_BASE(way) + set, match_space | SPR_DTLBMR_V);
689
    // Set TRANSLATE register to the areas where we have set our data
690
    mtspr (SPR_DTLBTR_BASE(way) + set, translate_space | DTLB_PR_NOLIMIT);
691
 
692
    /* Reset DTLB miss counter and EA */
693
    dtlb_miss_count = 0;
694
    dtlb_miss_ea = 0;
695
 
696
    //if (((match_space < RAM_START) || (t_add >= DATA_END_ADD)) && 
697
    //  ((t_add < TEXT_START_ADD) || (t_add >= TEXT_END_ADD))) {
698
    if (match_space > DATA_END_ADD){
699
 
700
      /* Read last address of previous page */
701
      tmp = REG32(match_space - 4);
702
      ASSERT(tmp == 0x00112233);
703
      ASSERT(dtlb_miss_count == 1);
704
 
705
      /* Read first address of the page */
706
      tmp = REG32(match_space);
707
      ASSERT(tmp == 0x44556677);
708
      ASSERT(dtlb_miss_count == 1);
709
 
710
      /* Read last address of the page */
711
      tmp = REG32(match_space + PAGE_SIZE - 4);
712
      ASSERT(tmp == 0x8899aabb);
713
      ASSERT(dtlb_miss_count == 1);
714
 
715
      /* Read first address of next page */
716
      tmp = REG32(match_space + PAGE_SIZE);
717
      ASSERT(tmp == 0xccddeeff);
718
      ASSERT(dtlb_miss_count == 2);
719
    }
720
 
721
    i++;
722
    add = (PAGE_SIZE*DTLB_SETS) << i;
723
    match_space = add + (set*PAGE_SIZE);
724
 
725
    for (j = 0; j < DTLB_WAYS; j++) {
726
      mtspr (SPR_DTLBMR_BASE(j) + ((set - 1) & (DTLB_SETS - 1)), 0);
727
      mtspr (SPR_DTLBMR_BASE(j) + ((set + 1) & (DTLB_SETS - 1)), 0);
728
    }
729
  }
730
 
731
  /* Disable DMMU */
732
  dmmu_disable();
733
 
734
  printf("-------------------------------------------\n");
735
 
736
  return 0;
737
}
738
 
739
/* Valid bit test
740
Set all ways of one set to be invalid, perform
741
access so miss handler will set them to valid,
742
try access again - there should be no miss exceptions */
743
int dtlb_valid_bit_test (int set)
744
{
745
  int i, j;
746
  unsigned long ea, ta;
747
 
748
  /* Disable DMMU */
749
  dmmu_disable();
750
 
751
  printf("dtlb_valid_bit_test, set %d\n", set);
752
 
753
  /* Invalidate all entries in DTLB */
754
  for (i = 0; i < DTLB_WAYS; i++) {
755
    for (j = 0; j < DTLB_SETS; j++) {
756
      mtspr (SPR_DTLBMR_BASE(i) + j, 0);
757
      mtspr (SPR_DTLBTR_BASE(i) + j, 0);
758
    }
759
  }
760
 
761
  /* Set one to one translation for the use of this program */
762
  for (i = 0; i < TLB_DATA_SET_NB; i++) {
763
    ea = RAM_START + (i*PAGE_SIZE);
764
    ta = RAM_START + (i*PAGE_SIZE);
765
    mtspr (SPR_DTLBMR_BASE(0) + i, ea | SPR_DTLBMR_V);
766
    mtspr (SPR_DTLBTR_BASE(0) + i, ta | DTLB_PR_NOLIMIT);
767
  }
768
 
769
  /* Reset DTLB miss counter and EA */
770
  dtlb_miss_count = 0;
771
  dtlb_miss_ea = 0;
772
 
773
  /* Set dtlb permisions */
774
  dtlb_val = DTLB_PR_NOLIMIT;
775
 
776
  /* Resetv DTLBMR for every way */
777
  for (i = 0; i < DTLB_WAYS; i++) {
778
    mtspr (SPR_DTLBMR_BASE(i) + set, 0);
779
  }
780
 
781
  /* Enable DMMU */
782
  dmmu_enable();
783
 
784
  /* Perform writes to address, that is not in DTLB */
785
  for (i = 0; i < DTLB_WAYS; i++) {
786
    REG32(RAM_START + RAM_SIZE + (i*DTLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)) = i;
787
 
788
    /* Check if there was DTLB miss */
789
    ASSERT(dtlb_miss_count == (i + 1));
790
    ASSERT(dtlb_miss_ea == (RAM_START + RAM_SIZE + (i*DTLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)));
791
  }
792
 
793
  /* Reset DTLB miss counter and EA */
794
  dtlb_miss_count = 0;
795
  dtlb_miss_ea = 0;
796
 
797
  /* Perform reads to address, that is now in DTLB */
798
  for (i = 0; i < DTLB_WAYS; i++) {
799
    ASSERT(REG32(RAM_START + RAM_SIZE + (i*DTLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)) == i);
800
 
801
    /* Check if there was DTLB miss */
802
    ASSERT(dtlb_miss_count == 0);
803
  }
804
 
805
  /* Reset valid bits */
806
  for (i = 0; i < DTLB_WAYS; i++) {
807
    mtspr (SPR_DTLBMR_BASE(i) + set, mfspr (SPR_DTLBMR_BASE(i) + set) & ~SPR_DTLBMR_V);
808
  }
809
 
810
  /* Perform reads to address, that is now in DTLB but is invalid */
811
  for (i = 0; i < DTLB_WAYS; i++) {
812
    ASSERT(REG32(RAM_START + RAM_SIZE + (i*DTLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)) == i);
813
 
814
    /* Check if there was DTLB miss */
815
    ASSERT(dtlb_miss_count == (i + 1));
816
    ASSERT(dtlb_miss_ea == (RAM_START + RAM_SIZE + (i*DTLB_SETS*PAGE_SIZE) + (set*PAGE_SIZE)));
817
  }
818
 
819
  /* Disable DMMU */
820
  dmmu_disable();
821
 
822
  printf("-------------------------------------------\n");
823
 
824
  return 0;
825
}
826
 
827
/* Permission test
828
Set various permissions, perform r/w access
829
in user and supervisor mode and chack triggering
830
of page fault exceptions */
831
int dtlb_permission_test (int set)
832
{
833
  int i, j;
834
  unsigned long ea, ta, tmp;
835
 
836
  printf("dtlb_permission_test, set %d\n", set);
837
 
838
  /* Disable DMMU */
839
  dmmu_disable();
840
 
841
  /* Invalidate all entries in DTLB */
842
  for (i = 0; i < DTLB_WAYS; i++) {
843
    for (j = 0; j < DTLB_SETS; j++) {
844
      mtspr (SPR_DTLBMR_BASE(i) + j, 0);
845
      mtspr (SPR_DTLBTR_BASE(i) + j, 0);
846
    }
847
  }
848
 
849
  /* Set one to one translation for the use of this program */
850
  for (i = 0; i < TLB_DATA_SET_NB; i++) {
851
    ea = RAM_START + (i*PAGE_SIZE);
852
    ta = RAM_START + (i*PAGE_SIZE);
853
    mtspr (SPR_DTLBMR_BASE(0) + i, ea | SPR_DTLBMR_V);
854
    mtspr (SPR_DTLBTR_BASE(0) + i, ta | DTLB_PR_NOLIMIT);
855
  }
856
 
857
  /* Testing page */
858
  ea = RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE);
859
 
860
  /* Set match register */
861
  mtspr (SPR_DTLBMR_BASE(DTLB_WAYS - 1) + set, ea | SPR_DTLBMR_V);
862
 
863
  /* Reset page fault counter and EA */
864
  dpage_fault_count = 0;
865
  dpage_fault_ea = 0;
866
 
867
  /* Enable DMMU */
868
  dmmu_enable();
869
 
870
  /* Write supervisor */
871
  dtlb_val = DTLB_PR_NOLIMIT | SPR_DTLBTR_SWE;
872
  mtspr (SPR_DTLBTR_BASE(DTLB_WAYS - 1) + set, ea | (DTLB_PR_NOLIMIT & ~SPR_DTLBTR_SWE));
873
  REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 0) = 0x00112233;
874
  ASSERT(dpage_fault_count == 1);
875
  REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 4) = 0x44556677;
876
  ASSERT(dpage_fault_count == 1);
877
  REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 8) = 0x8899aabb;
878
  ASSERT(dpage_fault_count == 1);
879
  REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 12) = 0xccddeeff;
880
  ASSERT(dpage_fault_count == 1);
881
 
882
  /* Read supervisor */
883
  dtlb_val = DTLB_PR_NOLIMIT | SPR_DTLBTR_SRE;
884
  mtspr (SPR_DTLBTR_BASE(DTLB_WAYS - 1) + set, ea | (DTLB_PR_NOLIMIT & ~SPR_DTLBTR_SRE));
885
  tmp = REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 0);
886
  ASSERT(dpage_fault_count == 2);
887
  ASSERT(tmp == 0x00112233);
888
  tmp = REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 4);
889
  ASSERT(dpage_fault_count == 2);
890
  ASSERT(tmp == 0x44556677);
891
  tmp = REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 8);
892
  ASSERT(dpage_fault_count == 2);
893
  ASSERT(tmp == 0x8899aabb);
894
  tmp = REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 12);
895
  ASSERT(dpage_fault_count == 2);
896
  ASSERT(tmp == 0xccddeeff);
897
 
898
  /* Write user */
899
  dtlb_val = DTLB_PR_NOLIMIT | SPR_DTLBTR_UWE;
900
  mtspr (SPR_DTLBTR_BASE(DTLB_WAYS - 1) + set, ea | (DTLB_PR_NOLIMIT & ~SPR_DTLBTR_UWE));
901
 
902
  /* Set user mode */
903
  mtspr (SPR_SR, mfspr (SPR_SR) & ~SPR_SR_SM);
904
 
905
  REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 0) = 0xffeeddcc;
906
  ASSERT(dpage_fault_count == 3);
907
  REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 4) = 0xbbaa9988;
908
  ASSERT(dpage_fault_count == 3);
909
  REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 8) = 0x77665544;
910
  ASSERT(dpage_fault_count == 3);
911
  REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 12) = 0x33221100;
912
  ASSERT(dpage_fault_count == 3);
913
 
914
  /* Trigger sys call exception to enable supervisor mode again */
915
  sys_call ();
916
 
917
  /* Read user mode */
918
  dtlb_val = DTLB_PR_NOLIMIT | SPR_DTLBTR_URE;
919
  mtspr (SPR_DTLBTR_BASE(DTLB_WAYS - 1) + set, ea | (DTLB_PR_NOLIMIT & ~SPR_DTLBTR_URE));
920
 
921
  /* Set user mode */
922
  mtspr (SPR_SR, mfspr (SPR_SR) & ~SPR_SR_SM);
923
 
924
  tmp = REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 0);
925
  ASSERT(dpage_fault_count == 4);
926
  ASSERT(tmp == 0xffeeddcc);
927
  tmp = REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 4);
928
  ASSERT(dpage_fault_count == 4);
929
  ASSERT(tmp == 0xbbaa9988);
930
  tmp = REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 8);
931
  ASSERT(dpage_fault_count == 4);
932
  ASSERT(tmp == 0x77665544);
933
  tmp = REG32(RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) + 12);
934
  ASSERT(dpage_fault_count == 4);
935
  ASSERT(tmp == 0x33221100);
936
 
937
  /* Trigger sys call exception to enable supervisor mode again */
938
  sys_call ();
939
 
940
  /* Disable DMMU */
941
  dmmu_disable();
942
 
943
  printf("-------------------------------------------\n");
944
 
945
  return 0;
946
}
947
 
948
 
949
/* Dcache test - check inhibit
950 477 julius
   Write data with cache inhibit on and off, check for coherency
951 349 julius
 */
952
int dtlb_dcache_test (int set)
953
{
954
  int i, j;
955
  unsigned long ea, ta, vmea;
956 477 julius
  unsigned long testwrite_to_be_cached, testwrite_not_to_be_cached;
957 349 julius
 
958 477 julius
  // This test can't be run if set==DTLB_SETS-1
959
  if (set==(DTLB_SETS-1))
960
    return 0;
961
 
962 349 julius
  // Check data cache is present and enabled
963
  if (!(mfspr(SPR_UPR)& SPR_UPR_DCP))
964
    return 0;
965
 
966
  if (!(mfspr(SPR_SR) & SPR_SR_DCE))
967
    return 0;
968
 
969
  printf("dtlb_dcache_test, set %d\n", set);
970
 
971
  /* Disable DMMU */
972
  dmmu_disable();
973
 
974
  /* Invalidate all entries in DTLB */
975
  for (i = 0; i < DTLB_WAYS; i++) {
976
    for (j = 0; j < DTLB_SETS; j++) {
977
      mtspr (SPR_DTLBMR_BASE(i) + j, 0);
978
      mtspr (SPR_DTLBTR_BASE(i) + j, 0);
979
    }
980
  }
981
 
982
  /* Set one to one translation for the use of this program */
983
  for (i = 0; i < TLB_DATA_SET_NB; i++) {
984
    ea = RAM_START + (i*PAGE_SIZE);
985
    ta = RAM_START + (i*PAGE_SIZE);
986
    mtspr (SPR_DTLBMR_BASE(0) + i, ea | SPR_DTLBMR_V);
987
    mtspr (SPR_DTLBTR_BASE(0) + i, ta | DTLB_PR_NOLIMIT);
988
  }
989
 
990 477 julius
  /* Use (RAM_START + (RAM_SIZE/2)) as location we'll poke via MMUs */
991
  /* Configure a 1-1 mapping for it, and a high->low mapping for it */
992
 
993 349 julius
  /* Testing page */
994
  ea = RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE);
995
 
996 477 julius
  /* Ultimate physical address */
997 349 julius
  ta = RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE);
998
 
999 477 julius
  /* Set a virtual address to translate via last TLB cache set */
1000 349 julius
  vmea = VM_BASE + RAM_START + (RAM_SIZE/2) + ((DTLB_SETS-1)*PAGE_SIZE);
1001
 
1002
  // Set a 1-1 translation for this page without cache inhibited
1003
  /* Set match register */
1004
  mtspr (SPR_DTLBMR_BASE(0) + set, ea | SPR_DTLBMR_V);
1005
  /* Set translate register */
1006
  mtspr (SPR_DTLBTR_BASE(0) + set, ta | DTLB_PR_NOLIMIT);
1007
 
1008 477 julius
  /* Now set a far-off translation, VM_BASE, for this page with cache
1009
     using the last set */
1010 349 julius
 
1011
  /* Set match register */
1012 477 julius
  mtspr (SPR_DTLBMR_BASE(0) + (DTLB_SETS-1), vmea | SPR_DTLBMR_V);
1013 349 julius
  /* Set translate register */
1014 477 julius
  mtspr (SPR_DTLBTR_BASE(0) + (DTLB_SETS-1), ta | DTLB_PR_NOLIMIT |
1015
         SPR_DTLBTR_CI);
1016
 
1017
  /* Invalidate this location in cache, to force reload when we read */
1018
  mtspr (/*SPR_DCR_BASE(0) +*/ SPR_DCBIR, ea);
1019 349 julius
 
1020
  /* Enable DMMU */
1021
  dmmu_enable();
1022
 
1023
  // First do a write with the cache inhibited mapping
1024 477 julius
  testwrite_to_be_cached = 0xfeca1d0d ^ set;
1025
 
1026 349 julius
  REG32((vmea)) = testwrite_to_be_cached;
1027 477 julius
 
1028 349 julius
  // Read it back to check that it's the same, this read should get cached
1029
  ASSERT(REG32(ea) == testwrite_to_be_cached);
1030 477 julius
 
1031 349 julius
  // Now write again to the cache inhibited location
1032 477 julius
  testwrite_not_to_be_cached = 0xbaadbeef ^ set;
1033
 
1034 349 julius
  REG32((vmea)) = testwrite_not_to_be_cached;
1035 477 julius
 
1036 349 julius
  // Now check that the cached mapping doesn't read this value back
1037
  ASSERT(REG32(ea) == testwrite_to_be_cached);
1038
 
1039
  // Now disable cache inhibition on the 1-1 mapping
1040
  /* Set translate register */
1041
  mtspr (SPR_DTLBTR_BASE(0) + set,
1042
         ea | DTLB_PR_NOLIMIT | SPR_DTLBTR_CI);
1043
 
1044
  // Check that we now get the second value we wrote
1045
  testwrite_to_be_cached = testwrite_not_to_be_cached;
1046 477 julius
 
1047 349 julius
  ASSERT(REG32(ea) == testwrite_to_be_cached);
1048
 
1049
  /* Disable DMMU */
1050
  dmmu_disable();
1051
 
1052
  printf("-------------------------------------------\n");
1053
 
1054
  return 0;
1055
 
1056
}
1057
 
1058
/* Translation address register test
1059
Set various translation and check the pattern */
1060
int itlb_translation_test (void)
1061
{
1062
  int i, j;
1063
  //unsigned long ea, ta;
1064
  unsigned long translate_space;
1065
  unsigned long match_space;
1066
  printf("itlb_translation_test\n");
1067
 
1068
  /* Disable IMMU */
1069
  immu_disable();
1070
 
1071
  /* Invalidate all entries in DTLB */
1072
  for (i = 0; i < ITLB_WAYS; i++) {
1073
    for (j = 0; j < ITLB_SETS; j++) {
1074
      mtspr (SPR_ITLBMR_BASE(i) + j, 0);
1075
      mtspr (SPR_ITLBTR_BASE(i) + j, 0);
1076
    }
1077
  }
1078
 
1079
  /* Set one to one translation for the use of this program */
1080
  for (i = 0; i < TLB_TEXT_SET_NB; i++) {
1081
    match_space = TEXT_START_ADD + (i*PAGE_SIZE);
1082
    translate_space = TEXT_START_ADD + (i*PAGE_SIZE);
1083
    mtspr (SPR_ITLBMR_BASE(0) + i, match_space | SPR_ITLBMR_V);
1084
    mtspr (SPR_ITLBTR_BASE(0) + i, translate_space | ITLB_PR_NOLIMIT);
1085
  }
1086
 
1087
  /* Set itlb permisions */
1088
  itlb_val = ITLB_PR_NOLIMIT;
1089
 
1090
 
1091
  /* Write test program */
1092
  for (i = TLB_TEXT_SET_NB; i < ITLB_SETS; i++) {
1093
    translate_space = (RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE) + (i*0x10));
1094
    //printf("writing app to 0x%.8lx to be translated in set %d\n",translate_space, i);
1095
    REG32(translate_space) = OR32_L_JR_R9;
1096
    REG32(translate_space + 4) = OR32_L_NOP;
1097
    // Now flush this in case DC isn't on write-through
1098
    mtspr(SPR_DCBFR, translate_space);
1099
    mtspr(SPR_DCBFR, translate_space+4);
1100
 
1101
  }
1102
 
1103
  /* Set one to one translation of the last way of ITLB */
1104
  for (i = TLB_TEXT_SET_NB; i < ITLB_SETS; i++) {
1105
    translate_space = (RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE) + (i*0x10));
1106
    mtspr (SPR_ITLBMR_BASE(ITLB_WAYS - 1) + i, translate_space | SPR_ITLBMR_V);
1107
    mtspr (SPR_ITLBTR_BASE(ITLB_WAYS - 1) + i,
1108
           translate_space | ITLB_PR_NOLIMIT);
1109
  }
1110
 
1111
  /* Enable IMMU */
1112
  immu_enable();
1113
 
1114
  /* Check the tranlsation works by jumping there */
1115
  for (i = TLB_TEXT_SET_NB; i < ITLB_SETS; i++) {
1116
    translate_space = (RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE) + (i*0x10));
1117
    //printf("calling 0x%.8lx - should use set %d\n",translate_space, i);
1118
    call (translate_space);
1119
  }
1120
 
1121
  /* Set hi -> lo, lo -> hi translation */
1122
  for (i = TLB_TEXT_SET_NB; i < ITLB_SETS; i++) {
1123
    match_space = RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE);
1124
    translate_space = RAM_START + (RAM_SIZE/2) +
1125
      (((ITLB_SETS-1)+TLB_TEXT_SET_NB - i)*PAGE_SIZE);
1126
    printf("setting itlb set %d match -> trans = 0x%.8lx -> 0x%.8lx\n",
1127
           i, match_space, translate_space);
1128
    mtspr (SPR_ITLBMR_BASE(ITLB_WAYS - 1) + i, match_space | SPR_ITLBMR_V);
1129
    mtspr (SPR_ITLBTR_BASE(ITLB_WAYS - 1) + i, translate_space|ITLB_PR_NOLIMIT);
1130
  }
1131
 
1132
  /* Check the pattern */
1133
  for (i = TLB_TEXT_SET_NB; i < ITLB_SETS; i++) {
1134
    match_space = RAM_START + (RAM_SIZE/2) + (((ITLB_SETS-1)+TLB_TEXT_SET_NB - i)*PAGE_SIZE) + (i*0x10);
1135
    printf("immu hi->lo check - calling 0x%.8lx\n",match_space);
1136
    call(match_space);
1137
  }
1138
 
1139
  /* Disable IMMU */
1140
  immu_disable ();
1141
 
1142
  /* Check the pattern */
1143
  for (i = TLB_TEXT_SET_NB; i < ITLB_SETS; i++) {
1144
    translate_space = (RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE) + (i*0x10));
1145
    //call (RAM_START + (RAM_SIZE/2) + (i*PAGE_SIZE) + (i*0x10));
1146
    //printf("immu disabled check of set %d - calling 0x%.8lx\n",i, translate_space);
1147
    call (translate_space);
1148
  }
1149
 
1150
  printf("-------------------------------------------\n");
1151
 
1152
  return 0;
1153
}
1154
 
1155
/* EA match register test
1156
Shifting one in ITLBMR and performing accesses to boundaries
1157
of the page, checking the triggering of exceptions */
1158
int itlb_match_test (int way, int set)
1159
{
1160
  int i, j;
1161
  unsigned long add, t_add;
1162
  unsigned long ea, ta;
1163
 
1164
  printf("itlb_match_test\n");
1165
 
1166
  /* Disable IMMU */
1167
  immu_disable();
1168
 
1169
  /* Invalidate all entries in ITLB */
1170
  for (i = 0; i < ITLB_WAYS; i++) {
1171
    for (j = 0; j < ITLB_SETS; j++) {
1172
      mtspr (SPR_ITLBMR_BASE(i) + j, 0);
1173
      mtspr (SPR_ITLBTR_BASE(i) + j, 0);
1174
    }
1175
  }
1176
 
1177
  /* Set one to one translation for the use of this program */
1178
  for (i = 0; i < TLB_TEXT_SET_NB; i++) {
1179
    ea = TEXT_START_ADD + (i*PAGE_SIZE);
1180
    ta = TEXT_START_ADD + (i*PAGE_SIZE);
1181
    mtspr (SPR_ITLBMR_BASE(0) + i, ea | SPR_ITLBMR_V);
1182
    mtspr (SPR_ITLBTR_BASE(0) + i, ta | ITLB_PR_NOLIMIT);
1183
  }
1184
 
1185
  /* Set dtlb permisions */
1186
  itlb_val = ITLB_PR_NOLIMIT;
1187
 
1188
 
1189
  // Write program which will just return into these places
1190
  unsigned long translate_space = RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE);
1191
  //copy_jump (RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE) - 8);
1192
  REG32(translate_space-8) = OR32_L_JR_R9;
1193
  REG32(translate_space-4) = OR32_L_NOP;
1194
  //copy_jump (RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE));
1195
  REG32(translate_space) = OR32_L_JR_R9;
1196
  REG32(translate_space+4) = OR32_L_NOP;
1197
  //copy_jump (RAM_START + (RAM_SIZE/2) + (set + 1)*PAGE_SIZE - 8);
1198
  REG32(translate_space + PAGE_SIZE - 8) = OR32_L_JR_R9;
1199
  REG32(translate_space + PAGE_SIZE - 4) = OR32_L_NOP;
1200
  //copy_jump (RAM_START + (RAM_SIZE/2) + (set + 1)*PAGE_SIZE);
1201
  REG32(translate_space + PAGE_SIZE) = OR32_L_JR_R9;
1202
  REG32(translate_space + PAGE_SIZE + 4) = OR32_L_NOP;
1203
  // Flush these areas incase cache doesn't write them through immediately
1204
  mtspr(SPR_DCBFR, translate_space-8);
1205
  mtspr(SPR_DCBFR, translate_space);
1206
  mtspr(SPR_DCBFR, translate_space+4);
1207
  mtspr(SPR_DCBFR, translate_space + PAGE_SIZE - 8);
1208
  mtspr(SPR_DCBFR, translate_space + PAGE_SIZE - 4);
1209
  mtspr(SPR_DCBFR, translate_space + PAGE_SIZE);
1210
  mtspr(SPR_DCBFR, translate_space + PAGE_SIZE + 4);
1211
 
1212
  /* Enable IMMU */
1213
  immu_enable();
1214
 
1215
  /* Shifting one in ITLBMR */
1216
  i = 0;
1217
  //add = (PAGE_SIZE*ITLB_SETS);
1218
  //t_add = add + (set*PAGE_SIZE);
1219
  // Space we'll access and expect the MMU to translate our requests
1220
  unsigned long match_space = (PAGE_SIZE*DTLB_SETS) + (set*PAGE_SIZE);
1221
  while (add != 0x00000000) {
1222
    mtspr (SPR_ITLBMR_BASE(way) + set,  match_space | SPR_ITLBMR_V);
1223
    mtspr (SPR_ITLBTR_BASE(way) + set,  translate_space | ITLB_PR_NOLIMIT);
1224
 
1225
    /* Reset ITLB miss counter and EA */
1226
    itlb_miss_count = 0;
1227
    itlb_miss_ea = 0;
1228
 
1229
    //if (((t_add < RAM_START) || (t_add >= DATA_END_ADD)) && ((t_add < TEXT_START_ADD) || (t_add >= TEXT_END_ADD))) {
1230
 
1231
      /* Jump on last address of previous page */
1232
      call (match_space - 8);
1233
      ASSERT(itlb_miss_count == 1);
1234
 
1235
      /* Jump on first address of the page */
1236
      call (match_space);
1237
      ASSERT(itlb_miss_count == 1);
1238
 
1239
      /* Jump on last address of the page */
1240
      call (match_space + PAGE_SIZE - 8);
1241
      ASSERT(itlb_miss_count == 1);
1242
 
1243
      /* Jump on first address of next page */
1244
      call (match_space + PAGE_SIZE);
1245
      ASSERT(itlb_miss_count == 2);
1246
      //}
1247
 
1248
    i++;
1249
    add = (PAGE_SIZE*ITLB_SETS) << i;
1250
    match_space = add + (set*PAGE_SIZE);
1251
 
1252
    for (j = 0; j < ITLB_WAYS; j++) {
1253
      mtspr (SPR_ITLBMR_BASE(j) + ((set - 1) & (ITLB_SETS - 1)), 0);
1254
      mtspr (SPR_ITLBMR_BASE(j) + ((set + 1) & (ITLB_SETS - 1)), 0);
1255
    }
1256
  }
1257
 
1258
  printf("-------------------------------------------\n");
1259
 
1260
  /* Disable IMMU */
1261
  immu_disable();
1262
 
1263
  return 0;
1264
}
1265
 
1266
/* Valid bit test
1267
Set all ways of one set to be invalid, perform
1268
access so miss handler will set them to valid,
1269
try access again - there should be no miss exceptions */
1270
int itlb_valid_bit_test (int set)
1271
{
1272
  int i, j;
1273
  unsigned long ea, ta;
1274
 
1275
  printf("itlb_valid_bit_test set = %d\n", set);
1276
 
1277
  /* Disable IMMU */
1278
  immu_disable();
1279
 
1280
  /* Invalidate all entries in ITLB */
1281
  for (i = 0; i < ITLB_WAYS; i++) {
1282
    for (j = 0; j < ITLB_SETS; j++) {
1283
      mtspr (SPR_ITLBMR_BASE(i) + j, 0);
1284
      mtspr (SPR_ITLBTR_BASE(i) + j, 0);
1285
    }
1286
  }
1287
 
1288
  /* Set one to one translation for the use of this program */
1289
  for (i = 0; i < TLB_TEXT_SET_NB; i++) {
1290
    ea = TEXT_START_ADD + (i*PAGE_SIZE);
1291
    ta = TEXT_START_ADD + (i*PAGE_SIZE);
1292
    mtspr (SPR_ITLBMR_BASE(0) + i, ea | SPR_ITLBMR_V);
1293
    mtspr (SPR_ITLBTR_BASE(0) + i, ta | ITLB_PR_NOLIMIT);
1294
  }
1295
 
1296
  /* Reset ITLB miss counter and EA */
1297
  itlb_miss_count = 0;
1298
  itlb_miss_ea = 0;
1299
 
1300
  /* Set itlb permisions */
1301
  itlb_val = ITLB_PR_NOLIMIT;
1302
 
1303
  /* Resetv ITLBMR for every way after the program code */
1304
  for (i = TLB_TEXT_SET_NB; i < ITLB_WAYS; i++) {
1305
    mtspr (SPR_ITLBMR_BASE(i) + set, 0);
1306
  }
1307
 
1308
  /* Enable IMMU */
1309
  immu_enable();
1310
  // Address we'll jump to and expect it to be translated
1311
  unsigned long match_space = (PAGE_SIZE*ITLB_SETS) + (set*PAGE_SIZE);
1312
  // Address that we will actually access
1313
  unsigned long translate_space = RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE);
1314
  /* Perform jumps to address, that is not in ITLB */
1315
  printf("writing program to 0x%.8lx\n", translate_space);
1316
  REG32(translate_space) = OR32_L_JR_R9;
1317
  REG32(translate_space+4) = OR32_L_NOP;
1318
  mtspr(SPR_DCBFR, translate_space);
1319
  mtspr(SPR_DCBFR, translate_space+4);
1320
  printf("jumping to 0x%.8lx, should be itlb miss\n",match_space);
1321
  call (match_space);
1322
 
1323
  /* Check if there was ITLB miss */
1324
  ASSERT(itlb_miss_count == 1);
1325
  ASSERT(itlb_miss_ea == match_space);
1326
 
1327
  /* Reset ITLB miss counter and EA */
1328
  itlb_miss_count = 0;
1329
  itlb_miss_ea = 0;
1330
  printf("jumping to 0x%.8lx again - should not be a miss\n", match_space);
1331
  /* Perform jumps to address, that is now in ITLB */
1332
  call (match_space);
1333
 
1334
  /* Check if there was ITLB miss */
1335
  ASSERT(itlb_miss_count == 0);
1336
 
1337
  /* Reset valid bits */
1338
  for (i = 0; i < ITLB_WAYS; i++) {
1339
    mtspr (SPR_ITLBMR_BASE(i) + set, mfspr (SPR_ITLBMR_BASE(i) + set) & ~SPR_ITLBMR_V);
1340
  }
1341
  printf("jumping to 0x%.8lx again - mmu entries invalidated, so should be a miss\n", match_space);
1342
  /* Perform jumps to address, that is now in ITLB but is invalid */
1343
  call (match_space);
1344
 
1345
  /* Check if there was ITLB miss */
1346
  ASSERT(itlb_miss_count == 1);
1347
  ASSERT(itlb_miss_ea == match_space);
1348
 
1349
  /* Disable IMMU */
1350
  immu_disable ();
1351
 
1352
  printf("-------------------------------------------\n");
1353
 
1354
  return 0;
1355
}
1356
 
1357
/* Permission test
1358
Set various permissions, perform r/w access
1359
in user and supervisor mode and chack triggering
1360
of page fault exceptions */
1361
int itlb_permission_test (int set)
1362
{
1363
  int i, j;
1364
  unsigned long ea, ta;
1365
 
1366
  printf("itlb_permission_test set = %d\n", set);
1367
 
1368
  /* Disable IMMU */
1369
  immu_disable();
1370
 
1371
  /* Invalidate all entries in ITLB */
1372
  for (i = 0; i < ITLB_WAYS; i++) {
1373
    for (j = 0; j < ITLB_SETS; j++) {
1374
      mtspr (SPR_ITLBMR_BASE(i) + j, 0);
1375
      mtspr (SPR_ITLBTR_BASE(i) + j, 0);
1376
    }
1377
  }
1378
 
1379
  /* Set one to one translation for the use of this program */
1380
  for (i = 0; i < TLB_TEXT_SET_NB; i++) {
1381
    ea = TEXT_START_ADD + (i*PAGE_SIZE);
1382
    ta = TEXT_START_ADD + (i*PAGE_SIZE);
1383
    mtspr (SPR_ITLBMR_BASE(0) + i, ea | SPR_ITLBMR_V);
1384
    mtspr (SPR_ITLBTR_BASE(0) + i, ta | ITLB_PR_NOLIMIT);
1385
  }
1386
 
1387
  // Address that we will actually access
1388
  unsigned long match_space = RAM_START + (RAM_SIZE/2) + (set*PAGE_SIZE);
1389
 
1390
  /* Set match register */
1391
  mtspr (SPR_ITLBMR_BASE(ITLB_WAYS - 1) + set, match_space | SPR_ITLBMR_V);
1392
 
1393
  /* Reset page fault counter and EA */
1394
  ipage_fault_count = 0;
1395
  ipage_fault_ea = 0;
1396
 
1397
  /* Copy the code */
1398
  REG32(match_space+0x0) = OR32_L_JR_R9;
1399
  REG32(match_space+0x4) = OR32_L_NOP;
1400
  REG32(match_space+0x8) = OR32_L_JR_R9;
1401
  REG32(match_space+0xc) = OR32_L_NOP;
1402
  mtspr(SPR_DCBFR, match_space);
1403
  mtspr(SPR_DCBFR, match_space+4);
1404
  mtspr(SPR_DCBFR, match_space+8);
1405
  mtspr(SPR_DCBFR, match_space+12);
1406
 
1407
  /* Enable IMMU */
1408
  immu_enable ();
1409
 
1410
  /* Execute supervisor */
1411
  printf("execute disable for supervisor - should cause ipage fault\n");
1412
  itlb_val = SPR_ITLBTR_CI | SPR_ITLBTR_SXE;
1413
  mtspr (SPR_ITLBTR_BASE(ITLB_WAYS - 1) + set, match_space | (ITLB_PR_NOLIMIT & ~SPR_ITLBTR_SXE));
1414
  printf("calling address 0x%.8lx\n", match_space);
1415
  call (match_space);
1416
  ASSERT(ipage_fault_count == 1);
1417
  call (match_space + 8);
1418
  ASSERT(ipage_fault_count == 1);
1419
 
1420
  /* Execute user */
1421
  printf("execute disable for user - should cause ipage fault\n");
1422
  itlb_val = SPR_ITLBTR_CI | SPR_ITLBTR_UXE;
1423
  mtspr (SPR_ITLBTR_BASE(ITLB_WAYS - 1) + set, match_space | (ITLB_PR_NOLIMIT & ~SPR_ITLBTR_UXE));
1424
 
1425
  /* Set user mode */
1426
  printf("disabling supervisor mode\n");
1427
  mtspr (SPR_SR, mfspr (SPR_SR) & ~SPR_SR_SM);
1428
  printf("calling address 0x%.8lx\n", match_space);
1429
  printf("instruction at jump space: 0x%.8lx\n",REG32(match_space));
1430
  call (match_space);
1431
  ASSERT(ipage_fault_count == 2);
1432
  call (match_space + 8);
1433
  ASSERT(ipage_fault_count == 2);
1434
 
1435
  /* Trigger sys call exception to enable supervisor mode again */
1436
  sys_call ();
1437
 
1438
  /* Disable IMMU */
1439
  immu_disable ();
1440
 
1441
  printf("-------------------------------------------\n");
1442
 
1443
  return 0;
1444
}
1445
 
1446
int main (void)
1447
{
1448
  int i, j;
1449
 
1450 477 julius
  start_text_addr = (unsigned long)&_stext;
1451
  end_text_addr = (unsigned long)&_endtext;
1452
  end_data_addr = (unsigned long)&_stack;
1453 439 julius
  end_data_addr += 4;
1454 351 julius
 
1455
#ifndef TLB_BOTTOM_TEST_PAGE_HARDSET
1456 477 julius
  /* Set the botom MMU page (and thus TLB set) we'll begin tests at, hopefully
1457
     avoiding pages with program text, data and stack. Determined by
1458
     determining page after one top of stack is on. */
1459 351 julius
  TLB_TEXT_SET_NB =  TLB_DATA_SET_NB = (end_data_addr+PAGE_SIZE) / PAGE_SIZE;
1460
#endif
1461 349 julius
 
1462
#ifdef _UART_H_
1463
  uart_init(DEFAULT_UART);
1464
#endif
1465
 
1466
  i = j = 0; /* Get rid of warnings */
1467
 
1468
  /* Register bus error handler */
1469
  add_handler(0x2, bus_err_handler);
1470
 
1471
  /* Register illegal insn handler */
1472
  add_handler(0x7, ill_insn_handler);
1473
 
1474
  /* Register sys call handler */
1475
  add_handler(0xc, sys_call_handler);
1476
  // Skip all DTLB tests for now while we tweak itlb ones...
1477
 
1478
#if DO_DMMU_TESTS==1
1479
 
1480
  /* Translation test */
1481
  dtlb_translation_test ();
1482
 
1483
  /* Virtual address match test */
1484
  for (j = 0; j < DTLB_WAYS; j++) {
1485
#ifdef SHORT_TEST
1486 477 julius
    for (i = TLB_DATA_SET_NB; i < (TLB_DATA_SET_NB + SHORT_TEST_NUM - 1); i++)
1487 349 julius
#else
1488
    for (i = TLB_DATA_SET_NB; i < (DTLB_SETS - 1); i++)
1489
#endif
1490
      dtlb_match_test (j, i);
1491
  }
1492
 
1493
  /* Valid bit testing */
1494
 
1495
#ifdef SHORT_TEST
1496 477 julius
  for (i = TLB_DATA_SET_NB; i < (TLB_DATA_SET_NB + SHORT_TEST_NUM - 1); i++)
1497 349 julius
#else
1498
  for (i = TLB_DATA_SET_NB; i < (DTLB_SETS - 1); i++)
1499
#endif
1500
      dtlb_valid_bit_test (i);
1501
 
1502
  /* Permission test */
1503
#ifdef SHORT_TEST
1504 477 julius
  for (i = TLB_DATA_SET_NB; i < (TLB_DATA_SET_NB + SHORT_TEST_NUM - 1); i++)
1505 349 julius
#else
1506
  for (i = TLB_DATA_SET_NB; i < (DTLB_SETS - 1); i++)
1507
#endif
1508
    dtlb_permission_test (i);
1509
 
1510
  /* Data cache test */
1511 351 julius
 
1512 349 julius
#ifndef OR1200_NO_DC
1513
#ifdef SHORT_TEST
1514 477 julius
  for (i = TLB_DATA_SET_NB; i < (TLB_DATA_SET_NB + SHORT_TEST_NUM - 1); i++)
1515 349 julius
#else
1516
  for (i = TLB_DATA_SET_NB; i < (DTLB_SETS - 2); i++)
1517
#endif
1518
    dtlb_dcache_test (i);
1519
#endif // ifndef OR1200_NO_DC
1520
 
1521 351 julius
 
1522 349 julius
#endif
1523
 
1524 477 julius
#if DO_IMMU_TESTS==1
1525 349 julius
 
1526
  /* Translation test */
1527
  itlb_translation_test ();
1528
 
1529
  /* Virtual address match test */
1530
 
1531
  for (j = 0; j < DTLB_WAYS; j++) {
1532
#ifdef SHORT_TEST
1533 477 julius
  for (i = TLB_DATA_SET_NB + 1; i < (TLB_DATA_SET_NB + SHORT_TEST_NUM - 1); i++)
1534 349 julius
#else
1535
  for (i = TLB_DATA_SET_NB + 1; i < (ITLB_SETS - 1); i++)
1536
#endif
1537
      itlb_match_test (j, i);
1538
  }
1539
 
1540
  /* Valid bit testing */
1541
#ifdef SHORT_TEST
1542 477 julius
  for (i = TLB_DATA_SET_NB; i < (TLB_DATA_SET_NB + SHORT_TEST_NUM - 1); i++)
1543 349 julius
#else
1544
  for (i = TLB_DATA_SET_NB; i < (ITLB_SETS - 1); i++)
1545
#endif
1546
    itlb_valid_bit_test (i);
1547
 
1548
 
1549
 
1550
  /* Permission test */
1551
#ifdef SHORT_TEST
1552 477 julius
  for (i = TLB_TEXT_SET_NB; i < (TLB_TEXT_SET_NB + SHORT_TEST_NUM); i++)
1553 349 julius
#else
1554
  for (i = TLB_TEXT_SET_NB; i < (ITLB_SETS - 1); i++)
1555
#endif
1556
    itlb_permission_test (i);
1557
 
1558 477 julius
#endif
1559 349 julius
 
1560
  printf("Tests completed\n");
1561
  report (0xdeaddead);
1562
  report (0x8000000d);
1563 425 julius
  exit (0);
1564 349 julius
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.