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 485

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

powered by: WebSVN 2.1.0

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