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 393

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

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

powered by: WebSVN 2.1.0

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