mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2025-01-06 12:09:26 +08:00
402 lines
9.6 KiB
ArmAsm
402 lines
9.6 KiB
ArmAsm
|
//Original:/proj/frio/dv/testcases/lmu/lmu_excpt_prot1/lmu_excpt_prot1.dsp
|
||
|
// Description: LMU protection exceptions
|
||
|
# mach: bfin
|
||
|
# sim: --environment operating
|
||
|
|
||
|
#include "test.h"
|
||
|
.include "testutils.inc"
|
||
|
start
|
||
|
|
||
|
include(selfcheck.inc)
|
||
|
include(std.inc)
|
||
|
include(mmrs.inc)
|
||
|
|
||
|
//-------------------------------------
|
||
|
|
||
|
// Test LMU/CPLB exceptions
|
||
|
|
||
|
// Basic outline:
|
||
|
// Set exception handler
|
||
|
// program CPLB Entries
|
||
|
// Enable CPLB in DMEM_CNTL
|
||
|
// perform access
|
||
|
// verify exception occurred
|
||
|
|
||
|
CHECK_INIT(p5, 0xEFFFFFFC);
|
||
|
|
||
|
A0 = 0;
|
||
|
|
||
|
//-------------------------
|
||
|
// Zero the CPLB Address and Data regs.
|
||
|
|
||
|
LD32(p0, DCPLB_ADDR0);
|
||
|
R0 = 0;
|
||
|
[ P0 ++ ] = R0; // 0
|
||
|
[ P0 ++ ] = R0; // 1
|
||
|
[ P0 ++ ] = R0; // 2
|
||
|
[ P0 ++ ] = R0; // 3
|
||
|
[ P0 ++ ] = R0; // 4
|
||
|
[ P0 ++ ] = R0; // 5
|
||
|
[ P0 ++ ] = R0; // 6
|
||
|
[ P0 ++ ] = R0; // 7
|
||
|
[ P0 ++ ] = R0; // 8
|
||
|
[ P0 ++ ] = R0; // 9
|
||
|
[ P0 ++ ] = R0; // 10
|
||
|
[ P0 ++ ] = R0; // 11
|
||
|
[ P0 ++ ] = R0; // 12
|
||
|
[ P0 ++ ] = R0; // 13
|
||
|
[ P0 ++ ] = R0; // 14
|
||
|
[ P0 ++ ] = R0; // 15
|
||
|
|
||
|
LD32(p0, DCPLB_DATA0);
|
||
|
[ P0 ++ ] = R0; // 0
|
||
|
[ P0 ++ ] = R0; // 1
|
||
|
[ P0 ++ ] = R0; // 2
|
||
|
[ P0 ++ ] = R0; // 3
|
||
|
[ P0 ++ ] = R0; // 4
|
||
|
[ P0 ++ ] = R0; // 5
|
||
|
[ P0 ++ ] = R0; // 6
|
||
|
[ P0 ++ ] = R0; // 7
|
||
|
[ P0 ++ ] = R0; // 8
|
||
|
[ P0 ++ ] = R0; // 9
|
||
|
[ P0 ++ ] = R0; // 10
|
||
|
[ P0 ++ ] = R0; // 11
|
||
|
[ P0 ++ ] = R0; // 12
|
||
|
[ P0 ++ ] = R0; // 13
|
||
|
[ P0 ++ ] = R0; // 14
|
||
|
[ P0 ++ ] = R0; // 15
|
||
|
|
||
|
// Now set the CPLB entries we will need
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
// Data area for the desired error
|
||
|
WR_MMR(DCPLB_ADDR0, 0x800, p0, r0);
|
||
|
WR_MMR(DCPLB_ADDR1, 0x1000, p0, r0);
|
||
|
WR_MMR(DCPLB_DATA0, PAGE_SIZE_1K|CPLB_VALID|CPLB_DIRTY|CPLB_L1_CACHABLE, p0, r0);
|
||
|
WR_MMR(DCPLB_ADDR2, 0x2000, p0, r0);
|
||
|
WR_MMR(DCPLB_ADDR3, 0x3000, p0, r0);
|
||
|
WR_MMR(DCPLB_ADDR4, 0x4000, p0, r0);
|
||
|
WR_MMR(DCPLB_ADDR5, 0x5000, p0, r0);
|
||
|
WR_MMR(DCPLB_ADDR6, 0x6000, p0, r0);
|
||
|
WR_MMR(DCPLB_ADDR7, 0x7000, p0, r0);
|
||
|
|
||
|
// CHECKREG segment
|
||
|
WR_MMR(DCPLB_ADDR14, 0xEFFFFC00, p0, r0);
|
||
|
WR_MMR(DCPLB_DATA14, PAGE_SIZE_1K|CPLB_VALID|CPLB_DIRTY|CPLB_WT|CPLB_L1_CACHABLE|CPLB_SUPV_WR|CPLB_USER_RW, p0, r0);
|
||
|
|
||
|
// MMR space
|
||
|
WR_MMR(DCPLB_ADDR15, 0xFFC00000, p0, r0);
|
||
|
WR_MMR(DCPLB_DATA15, PAGE_SIZE_4M|CPLB_VALID|CPLB_DIRTY|CPLB_SUPV_WR, p0, r0);
|
||
|
|
||
|
// setup interrupt controller with exception handler address
|
||
|
WR_MMR_LABEL(EVT3, handler, p0, r1);
|
||
|
WR_MMR_LABEL(EVT15, int_15, p0, r1);
|
||
|
WR_MMR(EVT_IMASK, 0xFFFFFFFF, p0, r0);
|
||
|
WR_MMR(EVT_OVERRIDE, 0x00000000, p0, r0);
|
||
|
|
||
|
// enable CPLB
|
||
|
WR_MMR(DMEM_CONTROL, ENDM | ENDCPLB | DMC_AB_CACHE, p0, r0);
|
||
|
NOP;NOP;NOP;NOP;NOP; // in lieu of CSYNC
|
||
|
|
||
|
// Address for slot 0 accesses
|
||
|
// LD32(p4, 0xEFFFFFF8);
|
||
|
|
||
|
// go to user mode. and enable exceptions
|
||
|
LD32_LABEL(r0, User);
|
||
|
RETI = R0;
|
||
|
|
||
|
// But first raise interrupt 15 so we can do one test
|
||
|
// in supervisor mode.
|
||
|
RAISE 15;
|
||
|
NOP;
|
||
|
|
||
|
RTI;
|
||
|
|
||
|
// Nops to work around ICache bug
|
||
|
NOP;NOP;NOP;NOP;NOP;
|
||
|
NOP;NOP;NOP;NOP;NOP;
|
||
|
|
||
|
|
||
|
int_15:
|
||
|
// Interrupt 15 handler - needed to try supervisor access with exceptions enabled
|
||
|
//-------------------------------------------------------
|
||
|
// Protection violation - Illegal Supervisor Write Access
|
||
|
R0 = 0;R1 = 0;R2 = 0;R3 = 0;R4 = 0;R5 = 0;R6 = 0;R7 = 0;
|
||
|
|
||
|
LD32(i1, 0x800);
|
||
|
LD32(r1, 0xDEADBEEF);
|
||
|
|
||
|
LD32(p2, DCPLB_DATA0);
|
||
|
LD32(r2, PAGE_SIZE_1K|CPLB_VALID|CPLB_DIRTY|CPLB_L1_CACHABLE|CPLB_SUPV_WR);
|
||
|
|
||
|
LD32(p3, DCPLB_DATA1);
|
||
|
LD32(r3, PAGE_SIZE_1K|CPLB_VALID|CPLB_DIRTY|CPLB_L1_CACHABLE|CPLB_SUPV_WR);
|
||
|
|
||
|
|
||
|
X0: //[p1] = r1; // Exception should occur here
|
||
|
A0 = 0 || NOP || [ I1 ] = R1; // test access with DAG1
|
||
|
|
||
|
|
||
|
// Now check that handler read correct values
|
||
|
CHECKREG(r4,0x23); // supv and EXCPT_PROT
|
||
|
CHECKREG(r5, 0x800);
|
||
|
CHECKREG(r6, (FAULT_SUPV|FAULT_WRITE|FAULT_DAG1 | FAULT_CPLB0));
|
||
|
CHECKREG_SYM(r7, X0, r0); // RETX should be value of X0 (HARDCODED ADDR!!)
|
||
|
|
||
|
// go to user mode. and enable exceptions
|
||
|
LD32_LABEL(r0, User);
|
||
|
RTI;
|
||
|
NOP;NOP;NOP;NOP;NOP;
|
||
|
NOP;NOP;NOP;NOP;NOP;
|
||
|
|
||
|
|
||
|
User:
|
||
|
NOP;NOP;NOP;NOP;NOP;
|
||
|
|
||
|
//-------------------------------------------------------
|
||
|
// Protection violation - Illegal User Write Access
|
||
|
R0 = 0;R1 = 0;R2 = 0;R3 = 0;R4 = 0;R5 = 0;R6 = 0;R7 = 0;
|
||
|
|
||
|
LD32(i1, 0x1000);
|
||
|
LD32(r1, 0xDEADBEEF);
|
||
|
|
||
|
|
||
|
// values to fix up current test
|
||
|
LD32(p2, DCPLB_DATA1);
|
||
|
LD32(r2, PAGE_SIZE_1K|CPLB_VALID|CPLB_DIRTY|CPLB_L1_CACHABLE|CPLB_USER_RW|CPLB_SUPV_WR);
|
||
|
|
||
|
// values for next test
|
||
|
LD32(p3, DCPLB_DATA2);
|
||
|
LD32(r3, PAGE_SIZE_1K|CPLB_VALID|CPLB_DIRTY|CPLB_L1_CACHABLE);
|
||
|
|
||
|
X1: //[p1] = r1; // Exception should occur here
|
||
|
A0 = 0 || NOP || [ I1 ] = R1; // test access with DAG1
|
||
|
|
||
|
// Now check that handler read correct values
|
||
|
|
||
|
CHECKREG(r4,0x23); // supv and EXCPT_PROT
|
||
|
CHECKREG(r5, 0x1000);
|
||
|
CHECKREG(r6, (FAULT_USER|FAULT_WRITE|FAULT_DAG1 | FAULT_CPLB1));
|
||
|
CHECKREG_SYM(r7, X1, r0); // RETX should be value of X1 (HARDCODED ADDR!!)
|
||
|
|
||
|
|
||
|
//-------------------------------------------------------
|
||
|
// Protection violation - Illegal User Read Access
|
||
|
R0 = 0;R1 = 0;R2 = 0;R3 = 0;R4 = 0;R5 = 0;R6 = 0;R7 = 0;
|
||
|
|
||
|
LD32(i1, 0x2000);
|
||
|
LD32(r1, 0xDEADBEEF);
|
||
|
|
||
|
LD32(p2, DCPLB_DATA2);
|
||
|
LD32(r2, PAGE_SIZE_1K|CPLB_VALID|CPLB_DIRTY|CPLB_L1_CACHABLE|CPLB_USER_RO|CPLB_SUPV_WR);
|
||
|
|
||
|
LD32(p3, DCPLB_DATA3);
|
||
|
LD32(r3, PAGE_SIZE_1K|CPLB_VALID|CPLB_L1_CACHABLE|CPLB_USER_RW|CPLB_SUPV_WR);
|
||
|
|
||
|
X2: //[p1] = r1; // Exception should occur here
|
||
|
A0 = 0 || NOP || R0 = [ I1 ]; // test access with DAG1
|
||
|
|
||
|
|
||
|
// Now check that handler read correct values
|
||
|
CHECKREG(r4,0x23); // supv and EXCPT_PROT
|
||
|
CHECKREG(r5, 0x2000);
|
||
|
CHECKREG(r6, (FAULT_USER|FAULT_READ|FAULT_DAG1 | FAULT_CPLB2));
|
||
|
CHECKREG_SYM(r7, X2, r0); // RETX should be value of X2 (HARDCODED ADDR!!)
|
||
|
|
||
|
//-------------------------------------------------------
|
||
|
// Protection violation - Illegal Dirty Page Access
|
||
|
R0 = 0;R1 = 0;R2 = 0;R3 = 0;R4 = 0;R5 = 0;R6 = 0;R7 = 0;
|
||
|
|
||
|
LD32(i1, 0x3000);
|
||
|
LD32(r1, 0xDEADBEEF);
|
||
|
|
||
|
LD32(p2, DCPLB_DATA3);
|
||
|
LD32(r2, PAGE_SIZE_1K|CPLB_VALID|CPLB_DIRTY|CPLB_L1_CACHABLE|CPLB_USER_RW|CPLB_SUPV_WR);
|
||
|
|
||
|
LD32(p3, DCPLB_DATA4);
|
||
|
LD32(r3, PAGE_SIZE_1K|CPLB_VALID|CPLB_DA0ACC|CPLB_DIRTY|CPLB_L1_CACHABLE|CPLB_SUPV_WR);
|
||
|
|
||
|
|
||
|
X3: //[p1] = r1; // Exception should occur here
|
||
|
A0 = 0 || NOP || [ I1 ] = R1; // test access with DAG1
|
||
|
|
||
|
|
||
|
// Now check that handler read correct values
|
||
|
CHECKREG(r4,0x23); // supv and EXCPT_PROT
|
||
|
CHECKREG(r5, 0x3000);
|
||
|
CHECKREG(r6, (FAULT_USER|FAULT_WRITE|FAULT_DAG1 | FAULT_CPLB3));
|
||
|
CHECKREG_SYM(r7, X3, r0); // RETX should be value of X3 (HARDCODED ADDR!!)
|
||
|
|
||
|
//-------------------------------------------------------
|
||
|
// Protection violation - Illegal DAG1 Access
|
||
|
R0 = 0;R1 = 0;R2 = 0;R3 = 0;R4 = 0;R5 = 0;R6 = 0;R7 = 0;
|
||
|
|
||
|
LD32(i1, 0x4000);
|
||
|
LD32(r1, 0xDEADBEEF);
|
||
|
|
||
|
LD32(p2, DCPLB_DATA4);
|
||
|
LD32(r2, PAGE_SIZE_1K|CPLB_VALID|CPLB_DIRTY|CPLB_L1_CACHABLE|CPLB_USER_RW|CPLB_SUPV_WR);
|
||
|
|
||
|
LD32(p3, DCPLB_DATA5);
|
||
|
LD32(r3, PAGE_SIZE_1K|CPLB_VALID|CPLB_DIRTY|CPLB_L1_CACHABLE|CPLB_USER_RW|CPLB_SUPV_WR);
|
||
|
|
||
|
|
||
|
X4: //[p1] = r1; // Exception should occur here
|
||
|
A0 = 0 || NOP || [ I1 ] = R1; // test access with DAG1
|
||
|
|
||
|
|
||
|
// Now check that handler read correct values
|
||
|
CHECKREG(r4,0x23); // supv and EXCPT_PROT
|
||
|
CHECKREG(r5, 0x4000);
|
||
|
CHECKREG(r6, (FAULT_USER|FAULT_WRITE|FAULT_DAG1 | FAULT_CPLB4));
|
||
|
CHECKREG_SYM(r7, X4, r0); // RETX should be value of X4 (HARDCODED ADDR!!)
|
||
|
|
||
|
//-------------------------------------------------------
|
||
|
// L1Miss not implemented yet - skip for now....
|
||
|
|
||
|
// //-------------------------------------------------------
|
||
|
// // Protection violation - L1 Miss
|
||
|
// r0=0;r1=0;r2=0;r3=0;r4=0;r5=0;r6=0;r7=0;
|
||
|
//
|
||
|
// LD32(p1, 0x6000);
|
||
|
// LD32(r1, 0xDEADBEEF);
|
||
|
//
|
||
|
// LD32(p2, DCPLB_DATA6);
|
||
|
// LD32(r2, PAGE_SIZE_1K|CPLB_VALID|CPLB_DIRTY|CPLB_L1_CACHABLE|CPLB_USER_RW|CPLB_SUPV_WR);
|
||
|
//
|
||
|
// LD32(p3, DCPLB_DATA7);
|
||
|
// LD32(r3, PAGE_SIZE_1K|CPLB_VALID|CPLB_DIRTY|CPLB_USER_RW|CPLB_SUPV_WR);
|
||
|
//
|
||
|
//
|
||
|
//X6: //[p1] = r1; // Exception should occur here
|
||
|
// r0 = [p1];
|
||
|
//
|
||
|
//
|
||
|
// // Now check that handler read correct values
|
||
|
// CHECKREG(r4,0x23); // supv and EXCPT_PROT
|
||
|
// CHECKREG(r5, 0x6000);
|
||
|
// // CHECKREG(r6, FAULT_USER|FAULT_WRITE|FAULT_DAG1 | FAULT_CPLB6);
|
||
|
// CHECKREG_SYM(r7, X6, r0); // RETX should be value of X6 (HARDCODED ADDR!!)
|
||
|
|
||
|
|
||
|
//-------------------------------------------------------
|
||
|
dbg_pass;
|
||
|
|
||
|
|
||
|
handler:
|
||
|
// generic protection exception handler
|
||
|
// Inputs:
|
||
|
// p2: addr of CPLB entry to be modified ( current test)
|
||
|
// r2: new data for CPLB entry
|
||
|
//
|
||
|
// p3: addr of CPLB entry to be modified ( next test)
|
||
|
// r3: new data for CPLB entry
|
||
|
//
|
||
|
// Outputs:
|
||
|
// r4: SEQSTAT
|
||
|
// r5: DCPLB_FAULT_ADDR
|
||
|
// r6: DCPLB_STATUS
|
||
|
// r7: RETX (instruction addr where exception occurred)
|
||
|
|
||
|
|
||
|
R4 = SEQSTAT; // Get exception cause
|
||
|
|
||
|
// read data addr which caused exception
|
||
|
RD_MMR(DCPLB_FAULT_ADDR, p0, r5);
|
||
|
RD_MMR(DCPLB_STATUS, p0, r6);
|
||
|
|
||
|
// Reset status regs
|
||
|
WR_MMR(DCPLB_FAULT_ADDR, 0, p0, r0);
|
||
|
WR_MMR(DCPLB_STATUS, 0, p0, r0);
|
||
|
|
||
|
R7 = RETX; // get address of excepting instruction
|
||
|
|
||
|
|
||
|
// modify CPLB to allow access. Main pgm passes in addr and data
|
||
|
[ P2 ] = R2;
|
||
|
|
||
|
// Set up for next test
|
||
|
[ P3 ] = R3;
|
||
|
|
||
|
NOP;NOP;NOP;NOP;NOP;NOP;NOP; // in lieu of CSYNC;
|
||
|
|
||
|
// return from exception and re-execute offending instruction
|
||
|
RTX;
|
||
|
|
||
|
// Nops to work around ICache bug
|
||
|
NOP;NOP;NOP;NOP;NOP;
|
||
|
NOP;NOP;NOP;NOP;NOP;
|
||
|
|
||
|
|
||
|
.section MEM_0x800,"aw"
|
||
|
.dd 0x00000000
|
||
|
.dd 0x00000000
|
||
|
.dd 0x00000000
|
||
|
.dd 0x00000000
|
||
|
|
||
|
.section MEM_0x1000,"aw"
|
||
|
.dd 0x00000000
|
||
|
.dd 0x00000000
|
||
|
.dd 0x00000000
|
||
|
.dd 0x00000000
|
||
|
|
||
|
.section MEM_0x2000,"aw"
|
||
|
.dd 0x00000000
|
||
|
.dd 0x00000000
|
||
|
.dd 0x00000000
|
||
|
.dd 0x00000000
|
||
|
|
||
|
.section MEM_0x3000,"aw"
|
||
|
.dd 0x00000000
|
||
|
.dd 0x00000000
|
||
|
.dd 0x00000000
|
||
|
.dd 0x00000000
|
||
|
|
||
|
.section MEM_0x4000,"aw"
|
||
|
.dd 0x00000000
|
||
|
.dd 0x00000000
|
||
|
.dd 0x00000000
|
||
|
.dd 0x00000000
|
||
|
|
||
|
.section MEM_0x5000,"aw"
|
||
|
.dd 0x00000000
|
||
|
.dd 0x00000000
|
||
|
.dd 0x00000000
|
||
|
.dd 0x00000000
|
||
|
|
||
|
// Need a cache miss to test CPLB_L1REF
|
||
|
//.data 0x6000
|
||
|
// .dd 0x00000000
|
||
|
// .dd 0x00000000
|
||
|
// .dd 0x00000000
|
||
|
// .dd 0x00000000
|
||
|
|
||
|
.section MEM_0x7000,"aw"
|
||
|
.dd 0x00000000
|
||
|
.dd 0x00000000
|
||
|
.dd 0x00000000
|
||
|
.dd 0x00000000
|