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

Subversion Repositories openrisc

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

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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