Skip to content
Snippets Groups Projects
Commit 0def435e authored by Roberto Hexsel's avatar Roberto Hexsel
Browse files

handler for TLBload e TLBstore

parent 7fb756c2
No related branches found
No related tags found
No related merge requests found
......@@ -199,7 +199,12 @@ disableInterr:
#================================================================
# handle TLB Modified exception (store to page with bit dirty=0)
# handle TLB Modified exception -- store to page with bit dirty=0
#
# (a) fix TLB entry, by setting dirty=1 ;
# (b) check permissions in PT entry and (maybe) kill the process
# OR mark PT entry as Used and Modified, then
# update TLB entry.
#
.global _excp_saves
.global _excp_0180ret
......@@ -233,7 +238,7 @@ M_even: addi $a2, $a0, 4 # address for even entry
M_test: lw $a1, 0($a2) # read PT[badVAddr]
mfc0 $k0, c0_badvaddr # get faulting address
andi $a0, $a1, 0x0003 # check if page is mapped
andi $a0, $a1, 0x0001 # check if page is mapped
beq $a0, $zero, M_seg_fault # no, abort simulation
nop
......@@ -242,11 +247,11 @@ M_test: lw $a1, 0($a2) # read PT[badVAddr]
nop
andi $a0, $a1, 0x0002 # check if page is in secondary memory
bne $a0, $zero, M_sec_mem
bne $a0, $zero, M_sec_mem # yes, abort simulation
nop
mfc0 $a0, c0_epc # check if fault is on an instruction
beq $a0, $k0, M_prot_viol # k0 is badVAddr
beq $a0, $k0, M_prot_viol # k0 is badVAddr, if so, abort
nop
ori $a1, $a1, 0x0030 # mark PT entry as modified, used
......@@ -277,7 +282,7 @@ M_prot_viol: # print message and abort simulation
nop
nop
nop
wait 0x41
wait 0x42
M_sec_mem: # print message and abort simulation
la $k1, x_IO_BASE_ADDR
......@@ -287,7 +292,7 @@ M_sec_mem: # print message and abort simulation
nop
nop
nop
wait 0x41
wait 0x43
.end handle_Mod
#----------------------------------------------------------------
......@@ -296,7 +301,10 @@ M_sec_mem: # print message and abort simulation
#================================================================
# handle TLB Load exception: double-fault caused by a TLB miss
# to the Page Table -- mapping pointing to PT is not on TLB
# so, fix the TLB by storing mapping onto TLB[4]
#
# (a) fix the fault by (re)loading the mapping into TLB[4];
# (b) check permissions in PT entry and (maybe) kill the process.
#
.global _excp_saves
.global _excp_0180ret
.global handle_TLBL
......@@ -305,7 +313,7 @@ M_sec_mem: # print message and abort simulation
.ent handle_TLBL
handle_TLBL: # EntryHi points to offending TLB entry
tlbp # what is the offender's index?
tlbp # probe it to find the offender's index
lui $k1, %hi(_excp_saves)
ori $k1, $k1, %lo(_excp_saves)
sw $a0, 9*4($k1)
......@@ -315,8 +323,8 @@ handle_TLBL: # EntryHi points to offending TLB entry
mfc0 $a0, c0_badvaddr
la $a1, (_PT + (x_INST_BASE_ADDR >>13)*16)
slt $a2, $a0, $a1 # a2 <- badVAddr <= PageTable
bne $a2, $zero, L_chks
slt $a2, $a0, $a1 # a2 <- (badVAddr <= PageTable)
bne $a2, $zero, L_chks # fault is not to PageTable
nop
# this is same code as in start.s
......@@ -344,24 +352,27 @@ L_chks: andi $a0, $a0, 0x1000 # check if even or odd page
mfc0 $a0, c0_context
L_odd: j L_test
addi $a2, $a0, 12 # address for odd entry
addi $a2, $a0, 12 # address for odd intLo1 entry
L_even: addi $a2, $a0, 4 # address for even entry
L_even: addi $a2, $a0, 4 # address for even intLo0 entry
L_test: lw $a1, 0($a2)
mfc0 $k0, c0_badvaddr # get faulting address
andi $a0, $a1, 0x0003 # check if page is mapped
beq $a0, $zero, M_seg_fault
L_test: lw $a1, 0($a2) # get intLo{0,1}
mfc0 $k0, c0_badvaddr # get faulting address for printing
andi $a0, $a1, 0x0001 # check if page is mapped
beq $a0, $zero, M_seg_fault # no, abort simulation
nop
andi $a0, $a1, 0x0002 # check if page is in secondary memory
bne $a0, $zero, M_sec_mem
bne $a0, $zero, M_sec_mem # yes, abort simulation
nop
ori $a1, $a1, 0x0010 # mark PT entry as used
sw $a1, 0($a2)
L_ret: lw $a0, 9*4($k1) # nothing else to do, return??
# if this were handler_TLBS, now is the time to also mark the
# PT entry as Modified
L_ret: lw $a0, 9*4($k1) # nothing else to do, return
lw $a1, 10*4($k1)
j _excp_0180ret
lw $a2, 11*4($k1)
......@@ -407,6 +418,7 @@ TLB_purge:
move $v0, $zero # V_addr was purged from TLB
tlbwi # write invalid mappings to TLB
ehb
pu_miss: jr $ra
nop
......
......@@ -100,14 +100,23 @@ _start:
mtc0 $a1, c0_entrylo0 # bottom page (even)
la $a0, ( (MIDDLE_RAM + 1*4096) >>12 )<<6
ori $a1, $a0, 0b00000000000000000000000000000111 # ccc=0, d,v,g1
mtc0 $a1, c0_entrylo1 # bottom page + 1 (odd)
ori $a2, $a0, 0b00000000000000000000000000000111 # ccc=0, d,v,g1
mtc0 $a2, c0_entrylo1 # bottom page + 1 (odd)
# and write it to TLB[4]
li $k0, 4
mtc0 $k0, c0_index
tlbwi
# create a PT entry for the Page Table itself
# in these simulations, only the first page is used
la $a0, MIDDLE_RAM
srl $a0, $a0, 9 # (_PT>>13)*16
la $v0, PTbase
add $a0, $v0, $a0
sw $a1, 0($a0) # write to PT[ _PTV ].entryLo0
sw $a2, 8($a0) # write to PT[ _PTV ].entryLo1
# pin down first five TLB entries: ROM[0], I/O, RAM[0], stack, PgTbl
li $k0, 5
......@@ -233,8 +242,8 @@ excp_tbl: # see Table 8-25, pg 95,96
j handle_TLBL # 2
nop
j h_TLBS # 3
nop
j handle_TLBL # 3 == TLBS if miss on PT, on the TLB, on a store
nop # should mark page as Modified on PT
wait 0x04 # 4 AdEL addr error -- abort simulation
nop
......@@ -449,15 +458,15 @@ PTbase: .word ( (x_INST_BASE_ADDR + 0*4096) >>6) | 0b000011
.word 0x00000006
# PT[2] -- not mapped for simulation
.word ( (x_INST_BASE_ADDR + 4*4096) >>6) | 0b000011
.word ( (x_INST_BASE_ADDR + 4*4096) >>6) | 0b000001
.word 0x00000004
.word ( (x_INST_BASE_ADDR + 5*4096) >>6) | 0b000011
.word ( (x_INST_BASE_ADDR + 5*4096) >>6) | 0b000001
.word 0x00000004
# PT[3] -- not mapped for simulation
.word ( (x_INST_BASE_ADDR + 6*4096) >>6) | 0b000011
.word ( (x_INST_BASE_ADDR + 6*4096) >>6) | 0b000001
.word 0x00000004
.word ( (x_INST_BASE_ADDR + 7*4096) >>6) | 0b000011
.word ( (x_INST_BASE_ADDR + 7*4096) >>6) | 0b000001
.word 0x00000004
# PT[4] -- not mapped for simulation
......
......@@ -17,9 +17,9 @@
//-----------------------------------------------------------------------
// decide on the tests to run
#define WALK_THE_PT 0
#define WALK_THE_PT 1
#define TLB_MODIFIED 1
#define DOUBLE_FAULT 0
#define DOUBLE_FAULT 1
// these will abort the simulation when the fault is detected/handled
#define PROT_VIOL 0
......@@ -83,8 +83,8 @@ void main(void) {
// let's change a mapping to cause a TLB-Modified exception
//
// in fact, there will be TWO exceptions:
// (1) a TLB-Refill will copu the write-protected mapping from the PT
// and retry the instruction;
// (1) a TLB-Refill will copy the mapping from the PT and retry the
// instruction;
// (2) when the sw is retried, it will cause a TLB-Modified
// exception, which checks PT's protection bits, then fixes the
// dirty bit in the TLB, and retries again, succeeding this time.
......@@ -110,9 +110,9 @@ void main(void) {
if ( *walker == 0x99 ) { // this load is optimized away by gcc
print( *walker );
print_str("\tMod ok\n");
print_str("\tMod ok\n\n");
} else {
print_str("\tMod err\n");
print_str("\tMod err\n\n");
}
#endif
......@@ -121,30 +121,41 @@ void main(void) {
#if DOUBLE_FAULT
//--------------------------------------------------------------------
// let's remove a PT's mapping from the TLB and cause a double-fault:
// let's remove from the TLB the mapping for the PT itself and cause
// a double-fault:
//
// (1) on the 1st reference, TLB-refill does not find a mapping for
// the PT on the TLB; this causes a TLBL (load) exception;
// (2) routine handle_TLBL writes a new mapping on the PT, refills
// the TLB, then retries the reference, which succeeds this time.
// the TLB, then retries the reference;
// (3) the page referenced is not on the TLB, so there is another
// TLB-refill, which loads the mapping, the store is retried
// and succeeds.
//--------------------------------------------------------------------
// remove the TLB entry for datum to be referenced
walker = (int *)(x_DATA_BASE_ADDR + PG_NUM*4096 + 1024);
if ( TLB_purge((void *)walker) == 0 ) {
print_str("\taddr purged from TLB\n");
} else {
print_str("\tTLB miss\n");
}
// this is the base of the page table
walker = (int *)(x_DATA_BASE_ADDR + (x_DATA_MEM_SZ/2));
// remove the TLB entry which points to the PT
if ( TLB_purge((void *)walker) == 0 ) {
print_str("\n\tPT purged from TLB\n");
print_str("\tPT purged from TLB\n");
} else {
print_str("\n\twtf?\n");
print_str("\twtf?\n");
}
// now reference a mapped page, to cause the double fault
walker = (int *)(x_DATA_BASE_ADDR + PG_NUM*4096 + 1024);
*walker = 0x88; // cause a TLBrefill then a TLBload
*walker = 0x77; // cause a TLBrefill then a TLBload
if ( *walker == 0x77 ) { // this load is optimized away by gcc
if ( *walker == 0x88 ) { // this load is optimized away by gcc
print( *walker );
print_str("\tdouble ok\n");
} else {
......@@ -176,10 +187,10 @@ void main(void) {
new_value = 0x00000001; // NOT-writable, mapped
PT_update( (int *)walker, 1, new_value);
*walker = 0x88;
*walker = 0x77;
// will never get here -- protection violation on the store
if ( *walker == 0x88 ) { // this load is optimized away by gcc
if ( *walker == 0x77 ) { // this load is optimized away by gcc
print( *walker );
print_str("\tprot viol not ok\n");
} else {
......@@ -219,10 +230,10 @@ void main(void) {
PT_update( (int *)walker, 2, new_value);
PT_update( (int *)walker, 3, 0); // mark as unmapped
*walker = 0x44;
*walker = 0x66;
// will never get here -- seg fault on the store
if ( *walker == 0x44 ) { // this load is optimized away by gcc
if ( *walker == 0x66 ) { // this load is optimized away by gcc
print( *walker );
print_str("\tseg fault not ok\n");
} else {
......@@ -231,10 +242,9 @@ void main(void) {
#endif
to_stdout('\n');
}
//----------------------------------------------------------------------
void print_str(char *s) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment