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

handler for TLBmodified

parent 23de04fe
Branches
No related tags found
No related merge requests found
Pipeline #
# interrupt handlers # interrupt handlers
.include "cMIPS.s" .include "cMIPS.s"
.text .text
.set noreorder .set noreorder # do not reorder instructions
.set noat # do not use register $1 as $at
.align 2 .align 2
.set M_StatusIEn,0x0000ff11 # STATUS.intEn=1, user mode .set M_StatusIEn,0x0000ff11 # STATUS.intEn=1, user mode
#---------------------------------------------------------------- #================================================================
# interrupt handler for external counter attached to IP5=HW3 # interrupt handler for external counter attached to IP5=HW3
# for extCounter address see vhdl/packageMemory.vhd # for extCounter address see vhdl/packageMemory.vhd
.bss .bss
.align 2 .align 2
.set noreorder
.global _counter_val # accumulate number of interrupts .global _counter_val # accumulate number of interrupts
.comm _counter_val 4 .comm _counter_val 4
.comm _counter_saves 8*4 # area to save up to 8 registers .comm _counter_saves 8*4 # area to save up to 8 registers
...@@ -67,12 +67,11 @@ extCounter: ...@@ -67,12 +67,11 @@ extCounter:
#---------------------------------------------------------------- #----------------------------------------------------------------
#---------------------------------------------------------------- #================================================================
# interrupt handler for UART attached to IP6=HW4 # interrupt handler for UART attached to IP6=HW4
.bss .bss
.align 2 .align 2
.set noreorder
.global Ud .global Ud
Ud: .comm rx_queue 16 # reception queue and pointers Ud: .comm rx_queue 16 # reception queue and pointers
.comm rx_hd 4 .comm rx_hd 4
...@@ -138,15 +137,16 @@ UARTret: ...@@ -138,15 +137,16 @@ UARTret:
#---------------------------------------------------------------- #----------------------------------------------------------------
#---------------------------------------------------------------- #================================================================
# handler for COUNT-COMPARE registers -- IP7=HW5 # handler for COUNT-COMPARE registers -- IP7=HW5
.text .text
.set noreorder .set noreorder
.equ num_cycles, 64
.global countCompare .global countCompare
.ent countCompare .ent countCompare
countCompare: countCompare:
mfc0 $k1,c0_count # read COMPARE and clear IRQ mfc0 $k1,c0_count # read COMPARE and clear IRQ
addiu $k1,$k1,64 # set next interrupt in 64 ticks addiu $k1,$k1,num_cycles # set next interrupt in so many ticks
mtc0 $k1,c0_compare mtc0 $k1,c0_compare
mfc0 $k0, c0_status # Read STATUS register mfc0 $k0, c0_status # Read STATUS register
...@@ -160,7 +160,7 @@ countCompare: ...@@ -160,7 +160,7 @@ countCompare:
#---------------------------------------------------------------- #----------------------------------------------------------------
#---------------------------------------------------------------- #================================================================
# functions to enable and disable interrupts, both return STATUS # functions to enable and disable interrupts, both return STATUS
.text .text
.set noreorder .set noreorder
...@@ -188,7 +188,234 @@ disableInterr: ...@@ -188,7 +188,234 @@ disableInterr:
#---------------------------------------------------------------- #----------------------------------------------------------------
#================================================================
## TLB handlers
## page table entry is { EntryLo0 int0 EntryLo1 int1 }
## int{0,1} is
## { fill_31..6, Modified_5, Used_4, Writable_3, eXecutable_2,
## Status_10 },
## Status is 00=unmapped, 01=mapped, 10=secondary_storage
#================================================================
#================================================================
# handle TLB Modified exception (store to page with bit dirty=0)
#
.global _excp_saves
.global _excp_0180ret
.global handle_Mod
.set noreorder
.ent handle_Mod
handle_Mod: # EntryHi points to offending TLB entry
tlbp # what is the offender's index?
lui $k1, %hi(_excp_saves)
ori $k1, $k1, %lo(_excp_saves)
sw $a0, 9*4($k1) # save registers
sw $a1, 10*4($k1)
sw $a2, 11*4($k1)
mfc0 $a0, c0_badvaddr
andi $a0, $a0, 0x1000 # check if even or odd page
beq $a0, $zero, M_even
mfc0 $a0, c0_context
M_odd: addi $a2, $a0, 12 # address for odd entry
mfc0 $k0, c0_entrylo1
ori $k0, $k0, 0x0004 # mark TLB entry as dirty/writable
j M_test
mtc0 $k0, c0_entrylo1
M_even: addi $a2, $a0, 4 # address for even entry
mfc0 $k0, c0_entrylo0
ori $k0, $k0, 0x0004 # mark TLB entry as dirty/writable
mtc0 $k0, c0_entrylo0
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
beq $a0, $zero, M_seg_fault # no, abort simulation
nop
andi $a0, $a1, 0x0008 # check if page is writable
beq $a0, $zero, M_prot_viol # no, abort simulation
nop
andi $a0, $a1, 0x0002 # check if page is in secondary memory
bne $a0, $zero, M_sec_mem
nop
mfc0 $a0, c0_epc # check if fault is on an instruction
beq $a0, $k0, M_prot_viol # k0 is badVAddr
nop
ori $a1, $a1, 0x0030 # mark PT entry as modified, used
sw $a1, 0($a2)
tlbwi # write entry with dirty bit=1 back to TLB
lw $a0, 9*4($k1) # restore saved registers and return
lw $a1, 10*4($k1)
j _excp_0180ret
lw $a2, 11*4($k1)
M_seg_fault: # print message and abort simulation
la $k1, x_IO_BASE_ADDR
sw $k0, 0($k1)
jal cmips_kmsg
la $k1, 3 # segmentation fault
nop
nop
nop
wait 0x41
M_prot_viol: # print message and abort simulation
la $k1, x_IO_BASE_ADDR
sw $k0, 0($k1)
jal cmips_kmsg
la $k1, 2 # protection violation
nop
nop
nop
wait 0x41
M_sec_mem: # print message and abort simulation
la $k1, x_IO_BASE_ADDR
sw $k0, 0($k1)
jal cmips_kmsg
la $k1, 4 # secondary memory
nop
nop
nop
wait 0x41
.end handle_Mod
#----------------------------------------------------------------
#================================================================
# 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]
.global _excp_saves
.global _excp_0180ret
.global handle_TLBL
.global _PT
.set MIDDLE_RAM, (x_DATA_BASE_ADDR + (x_DATA_MEM_SZ/2))
.ent handle_TLBL
handle_TLBL: # EntryHi points to offending TLB entry
tlbp # what is the offender's index?
lui $k1, %hi(_excp_saves)
ori $k1, $k1, %lo(_excp_saves)
sw $a0, 9*4($k1)
sw $a1, 10*4($k1)
sw $a2, 11*4($k1)
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
nop
# this is same code as in start.s
# get physical page number for two pages at the bottom of PageTable
la $a0, ( MIDDLE_RAM >>13 )<<13
mtc0 $a0, c0_entryhi # tag for bottom double-page
la $a0, ( (MIDDLE_RAM + 0*4096) >>12 )<<6
ori $a1, $a0, 0b00000000000000000000000000000111 # ccc=0, d,v,g1
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)
# and write it to TLB[4]
li $k0, 4
mtc0 $k0, c0_index
tlbwi
j L_ret # all work done, return
nop
L_chks: andi $a0, $a0, 0x1000 # check if even or odd page
beq $a0, $zero, L_even
mfc0 $a0, c0_context
L_odd: j L_test
addi $a2, $a0, 12 # address for odd entry
L_even: addi $a2, $a0, 4 # address for even 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
nop
andi $a0, $a1, 0x0002 # check if page is in secondary memory
bne $a0, $zero, M_sec_mem
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??
lw $a1, 10*4($k1)
j _excp_0180ret
lw $a2, 11*4($k1)
.end handle_TLBL
#---------------------------------------------------------------- #----------------------------------------------------------------
#================================================================
# purge an entry from the TLB
# int TLB_purge(void *V_addr)
# returns 0 if V_addr purged, 1 if V_addr not in TLB (probe failure)
#
.text
.global TLB_purge
.set noreorder
.ent TLB_purge
TLB_purge:
srl $a0, $a0, 13 # clear out in-page address bits
sll $a0, $a0, 13 #
mtc0 $a0, c0_entryhi
nop
tlbp # probe the TLB
nop
mfc0 $a0, c0_index # check for hit
srl $a0, $a0, 31 # keeo only MSbit
bne $a0, $zero, pu_miss # address not in TLB
move $v0, $a0 # V_addr not in TLB
tlbr # read the entry
li $a0, -8192 # -8192 = 0xffff.e000
mtc0 $a0, c0_entryhi # and write an un-mapped address to tag
addi $v0, $zero, -3 # -3 = 0xffff.fffd to clear valid bit
mfc0 $a0, c0_entrylo0 # invalidate the mappings
and $a0, $v0, $a0
mtc0 $a0, c0_entrylo0
mfc0 $a0, c0_entrylo1
and $a0, $v0, $a0
mtc0 $a0, c0_entrylo1
move $v0, $zero # V_addr was purged from TLB
tlbwi # write invalid mappings to TLB
pu_miss: jr $ra
nop
.end TLB_purge
##---------------------------------------------------------------
#================================================================
# delays processing by approx 4*$a0 processor cycles # delays processing by approx 4*$a0 processor cycles
.text .text
.set noreorder .set noreorder
...@@ -205,7 +432,7 @@ cmips_delay: ...@@ -205,7 +432,7 @@ cmips_delay:
#---------------------------------------------------------------- #----------------------------------------------------------------
#---------------------------------------------------------------- #================================================================
# print a message from within "the kernel" # print a message from within "the kernel"
# void cmips_kmsg( $k1 ) # void cmips_kmsg( $k1 )
# this function preserves registers other than k0,k1 # this function preserves registers other than k0,k1
...@@ -219,10 +446,10 @@ cmips_delay: ...@@ -219,10 +446,10 @@ cmips_delay:
.align 2 .align 2
.set noreorder .set noreorder
.set noat .set noat
.global cmips_kmsg
.ent cmips_kmsg
.equ stdout,(x_IO_BASE_ADDR + 1*x_IO_ADDR_RANGE); .equ stdout,(x_IO_BASE_ADDR + 1*x_IO_ADDR_RANGE);
.global cmips_kmsg
.ent cmips_kmsg
cmips_kmsg: cmips_kmsg:
lui $k0, %hi(_kmsg_saves) lui $k0, %hi(_kmsg_saves)
ori $k0, $k0, %lo(_kmsg_saves) ori $k0, $k0, %lo(_kmsg_saves)
...@@ -257,13 +484,18 @@ k_for: lbu $a0, 0($a1) ...@@ -257,13 +484,18 @@ k_for: lbu $a0, 0($a1)
.data .data
.align 2 .align 2
_kmsg_interr: .asciiz "\n\tinterrupt\n\n" _kmsg_interr: .asciiz "\n\t00 - interrupt\n\n"
_kmsg_excep: .asciiz "\n\texception\n\n" _kmsg_excep: .asciiz "\n\t01 - exception\n\n"
_kmsg_prot_viol: .asciiz "\n\t02 - protection violation\n\n"
_kmsg_seg_fault: .asciiz "\n\t03 - segmentation fault\n\n"
_kmsg_sec_mem: .asciiz "\n\t04 - in secondary memory\n\n"
.global _kmsg_list .global _kmsg_list
.data .data
.align 2 .align 2
_kmsg_list: .word _kmsg_interr,_kmsg_excep _kmsg_list:
.word _kmsg_interr,_kmsg_excep, _kmsg_prot_viol, _kmsg_seg_fault
.word _kmsg_sec_mem
#---------------------------------------------------------------- #----------------------------------------------------------------
...@@ -161,6 +161,7 @@ _excp_0000: ...@@ -161,6 +161,7 @@ _excp_0000:
mtc0 $k1, c0_entrylo1 # EntryLo1 <- k1 = odd element mtc0 $k1, c0_entrylo1 # EntryLo1 <- k1 = odd element
ehb ehb
tlbwr # update TLB tlbwr # update TLB
mfc0 $zero, c0_cause # clear excCode in Cause
eret eret
.end _excp_0000 .end _excp_0000
...@@ -201,6 +202,9 @@ _excp_0100: ...@@ -201,6 +202,9 @@ _excp_0100:
.text .text
.set noreorder .set noreorder
.set noat .set noat
.global _excp_saves, _excp_0180ret
.global handle_Mod, handle_TLBL, handle_TLBS
.org x_EXCEPTION_0180,0 # exception vector_180 .org x_EXCEPTION_0180,0 # exception vector_180
.ent _excp_0180 .ent _excp_0180
_excp_0180: _excp_0180:
...@@ -223,10 +227,10 @@ excp_tbl: # see Table 8-25, pg 95,96 ...@@ -223,10 +227,10 @@ excp_tbl: # see Table 8-25, pg 95,96
wait 0x02 # interrupt, should never get here, abort simulation wait 0x02 # interrupt, should never get here, abort simulation
nop nop
j h_Mod # 1 j handle_Mod # 1
nop nop
j h_TLBL # 2 j handle_TLBL # 2
nop nop
j h_TLBS # 3 j h_TLBS # 3
...@@ -266,8 +270,6 @@ excp_tbl: # see Table 8-25, pg 95,96 ...@@ -266,8 +270,6 @@ excp_tbl: # see Table 8-25, pg 95,96
nop nop
h_Mod:
h_TLBL:
h_TLBS: h_TLBS:
h_syscall: h_syscall:
h_breakpoint: h_breakpoint:
...@@ -275,7 +277,7 @@ h_RI: ...@@ -275,7 +277,7 @@ h_RI:
h_CpU: h_CpU:
h_Ov: h_Ov:
excp_0180ret: _excp_0180ret:
lui $k1, %hi(_excp_saves) # Read previous contents of STATUS lui $k1, %hi(_excp_saves) # Read previous contents of STATUS
ori $k1, $k1, %lo(_excp_saves) ori $k1, $k1, %lo(_excp_saves)
lw $k0, 1*4($k1) lw $k0, 1*4($k1)
...@@ -390,75 +392,103 @@ _excp_BFC0: ...@@ -390,75 +392,103 @@ _excp_BFC0:
##--------------------------------------------------------------- ##---------------------------------------------------------------
## #================================================================
# modify the page table:
# void PT_update(void *V_addr, int component, int new_value)
# component is in {0=entrylo0, 1-int0, 2=entrylo1, 3=int1}
.text
.global PT_update
.set noreorder
.ent PT_update
PT_update:
srl $a0, $a0, 9 # (_PT + (V_addr >>13)*16)
la $v0, PTbase
add $a0, $v0, $a0
andi $a1, $a1, 0x0003 # make sure component is in range
sll $a1, $a1, 2 # component * 4
add $a0, $a0, $a1 # (_PT + (V_addr >>13)*16).component
jr $ra
sw $a2, 0($a0) # write to PT[V_addr].component
.end PT_update
##---------------------------------------------------------------
##=============================================================== ##===============================================================
## Page Table ## Page Table
## ##
## See EntryLo, pg 63 ## See EntryLo, pg 63
## ##
## intLo0 and intLo1 are:
## nil_31..6 Modified_5 Used_4 Writable_3 eXecutable_2 Status_1,0
## Status: 00=unmapped, 01=mapped, 10=in_secondary_storage, 11=undef
##
.section .PT,"aw",@progbits .section .PT,"aw",@progbits
.global _PT
## ( ( (x_INST_BASE_ADDR + n*4096) >>12 )<<6 ) || 0b000011 d,v,g ## ( ( (x_INST_BASE_ADDR + n*4096) >>12 )<<6 ) || 0b000011 d,v,g
_PT: _PT:
## ##
## ROM mappings ## ROM mappings, intLo{01} = U=M=W=0, X=1, S=10 (or 00) = 6 (or 4)
## ##
.org (_PT + (x_INST_BASE_ADDR >>13)*16) .org (_PT + (x_INST_BASE_ADDR >>13)*16)
# PT[0], ROM # PT[0], ROM
.word ( (x_INST_BASE_ADDR + 0*4096) >>6) | 0b000011 PTbase: .word ( (x_INST_BASE_ADDR + 0*4096) >>6) | 0b000011
.word 0 .word 0x00000006
.word ( (x_INST_BASE_ADDR + 1*4096) >>6) | 0b000011 .word ( (x_INST_BASE_ADDR + 1*4096) >>6) | 0b000011
.word 0 .word 0x00000006
# PT[1] # PT[1]
.word ( (x_INST_BASE_ADDR + 2*4096) >>6) | 0b000011 .word ( (x_INST_BASE_ADDR + 2*4096) >>6) | 0b000011
.word 0 .word 0x00000006
.word ( (x_INST_BASE_ADDR + 3*4096) >>6) | 0b000011 .word ( (x_INST_BASE_ADDR + 3*4096) >>6) | 0b000011
.word 0 .word 0x00000006
# PT[2] # PT[2] -- not mapped for simulation
.word ( (x_INST_BASE_ADDR + 4*4096) >>6) | 0b000011 .word ( (x_INST_BASE_ADDR + 4*4096) >>6) | 0b000011
.word 0 .word 0x00000004
.word ( (x_INST_BASE_ADDR + 5*4096) >>6) | 0b000011 .word ( (x_INST_BASE_ADDR + 5*4096) >>6) | 0b000011
.word 0 .word 0x00000004
# PT[3] # PT[3] -- not mapped for simulation
.word ( (x_INST_BASE_ADDR + 6*4096) >>6) | 0b000011 .word ( (x_INST_BASE_ADDR + 6*4096) >>6) | 0b000011
.word 0 .word 0x00000004
.word ( (x_INST_BASE_ADDR + 7*4096) >>6) | 0b000011 .word ( (x_INST_BASE_ADDR + 7*4096) >>6) | 0b000011
.word 0 .word 0x00000004
# PT[4] -- not mapped for simulation # PT[4] -- not mapped for simulation
.word ( (x_INST_BASE_ADDR + 8*4096) >>6) | 0b000001 .word ( (x_INST_BASE_ADDR + 8*4096) >>6) | 0b000001
.word 0 .word 0x00000004
.word ( (x_INST_BASE_ADDR + 9*4096) >>6) | 0b000001 .word ( (x_INST_BASE_ADDR + 9*4096) >>6) | 0b000001
.word 0 .word 0x00000004
# PT[5] -- not mapped for simulation # PT[5] -- not mapped for simulation
.word ( (x_INST_BASE_ADDR + 10*4096) >>6) | 0b000001 .word ( (x_INST_BASE_ADDR + 10*4096) >>6) | 0b000001
.word 0 .word 0x00000004
.word ( (x_INST_BASE_ADDR + 11*4096) >>6) | 0b000001 .word ( (x_INST_BASE_ADDR + 11*4096) >>6) | 0b000001
.word 0 .word 0x00000004
# PT[6] -- not mapped for simulation # PT[6] -- not mapped for simulation
.word ( (x_INST_BASE_ADDR + 12*4096) >>6) | 0b000001 .word ( (x_INST_BASE_ADDR + 12*4096) >>6) | 0b000001
.word 0 .word 0x00000004
.word ( (x_INST_BASE_ADDR + 13*4096) >>6) | 0b000001 .word ( (x_INST_BASE_ADDR + 13*4096) >>6) | 0b000001
.word 0 .word 0x00000004
# PT[7] -- not mapped for simulation # PT[7] -- not mapped for simulation
.word ( (x_INST_BASE_ADDR + 14*4096) >>6) | 0b000001 .word ( (x_INST_BASE_ADDR + 14*4096) >>6) | 0b000001
.word 0 .word 0x00000004
.word ( (x_INST_BASE_ADDR + 15*4096) >>6) | 0b000001 .word ( (x_INST_BASE_ADDR + 15*4096) >>6) | 0b000001
.word 0 .word 0x00000004
## all remaining ROM entries are invalid ## all remaining ROM entries are invalid and unmapped
## ##
## RAM mappings ## RAM mappings, intLo{01} = U=M=0, W=1, X=0, S=10 (or 00) = a (or 8)
## ##
.org (_PT + (x_DATA_BASE_ADDR >>13)*16) .org (_PT + (x_DATA_BASE_ADDR >>13)*16)
...@@ -466,54 +496,54 @@ _PT: ...@@ -466,54 +496,54 @@ _PT:
# PT[ram+0], RAM # PT[ram+0], RAM
.word ( (x_DATA_BASE_ADDR + 0*4096) >>6) | 0b000111 .word ( (x_DATA_BASE_ADDR + 0*4096) >>6) | 0b000111
.word 0 .word 0x0000000a
.word ( (x_DATA_BASE_ADDR + 1*4096) >>6) | 0b000111 .word ( (x_DATA_BASE_ADDR + 1*4096) >>6) | 0b000111
.word 0 .word 0x0000000a
# PT[ram+1] # PT[ram+1]
.word ( (x_DATA_BASE_ADDR + 2*4096) >>6) | 0b000111 .word ( (x_DATA_BASE_ADDR + 2*4096) >>6) | 0b000111
.word 0 .word 0x0000000a
.word ( (x_DATA_BASE_ADDR + 3*4096) >>6) | 0b000111 .word ( (x_DATA_BASE_ADDR + 3*4096) >>6) | 0b000111
.word 0 .word 0x0000000a
# PT[ram+2] # PT[ram+2]
.word ( (x_DATA_BASE_ADDR + 4*4096) >>6) | 0b000111 .word ( (x_DATA_BASE_ADDR + 4*4096) >>6) | 0b000111
.word 0 .word 0x0000000a
.word ( (x_DATA_BASE_ADDR + 5*4096) >>6) | 0b000111 .word ( (x_DATA_BASE_ADDR + 5*4096) >>6) | 0b000111
.word 0 .word 0x0000000a
# PT[ram+3] # PT[ram+3]
.word ( (x_DATA_BASE_ADDR + 6*4096) >>6) | 0b000111 .word ( (x_DATA_BASE_ADDR + 6*4096) >>6) | 0b000111
.word 0 .word 0x0000000a
.word ( (x_DATA_BASE_ADDR + 7*4096) >>6) | 0b000111 .word ( (x_DATA_BASE_ADDR + 7*4096) >>6) | 0b000111
.word 0 .word 0x0000000a
# PT[ram+4] # PT[ram+4]
.word ( (x_DATA_BASE_ADDR + 8*4096) >>6) | 0b000111 .word ( (x_DATA_BASE_ADDR + 8*4096) >>6) | 0b000111
.word 0 .word 0x0000000a
.word ( (x_DATA_BASE_ADDR + 9*4096) >>6) | 0b000111 .word ( (x_DATA_BASE_ADDR + 9*4096) >>6) | 0b000111
.word 0 .word 0x0000000a
# PT[ram+5] # PT[ram+5]
.word ( (x_DATA_BASE_ADDR + 10*4096) >>6) | 0b000111 .word ( (x_DATA_BASE_ADDR + 10*4096) >>6) | 0b000111
.word 0 .word 0x0000000a
.word ( (x_DATA_BASE_ADDR + 11*4096) >>6) | 0b000111 .word ( (x_DATA_BASE_ADDR + 11*4096) >>6) | 0b000111
.word 0 .word 0x0000000a
# PT[ram+6] # PT[ram+6]
.word ( (x_DATA_BASE_ADDR + 12*4096) >>6) | 0b000111 .word ( (x_DATA_BASE_ADDR + 12*4096) >>6) | 0b000111
.word 0 .word 0x0000000a
.word ( (x_DATA_BASE_ADDR + 13*4096) >>6) | 0b000111 .word ( (x_DATA_BASE_ADDR + 13*4096) >>6) | 0b000111
.word 0 .word 0x0000000a
# PT[ram+7] # PT[ram+7]
.word ( (x_DATA_BASE_ADDR + 14*4096) >>6) | 0b000111 .word ( (x_DATA_BASE_ADDR + 14*4096) >>6) | 0b000111
.word 0 .word 0x0000000a
.word ( (x_DATA_BASE_ADDR + 15*4096) >>6) | 0b000111 .word ( (x_DATA_BASE_ADDR + 15*4096) >>6) | 0b000111
.word 0 .word 0x0000000a
## all remaining RAM entries are invalid ## all remaining RAM entries are invalid and unmapped
_endPT: _endPT:
...@@ -15,8 +15,24 @@ ...@@ -15,8 +15,24 @@
// With this much memory, simulations run slowly. No free lunch. // With this much memory, simulations run slowly. No free lunch.
//-----------------------------------------------------------------------
// decide on the tests to run
#define WALK_THE_PT 0
#define TLB_MODIFIED 1
#define DOUBLE_FAULT 0
// these will abort the simulation when the fault is detected/handled
#define PROT_VIOL 0
#define SEG_FAULT 0
//-----------------------------------------------------------------------
#include "cMIPS.h" #include "cMIPS.h"
extern void PT_update(void *V_addr, int component, int new_value);
extern int TLB_purge(void *V_addr);
static void print_str(char *);
#define FALSE (0==1) #define FALSE (0==1)
#define TRUE !FALSE #define TRUE !FALSE
...@@ -25,11 +41,19 @@ ...@@ -25,11 +41,19 @@
#define NUM_RAM_PAGES ( (x_DATA_MEM_SZ / 2) / 4096 ) #define NUM_RAM_PAGES ( (x_DATA_MEM_SZ / 2) / 4096 )
void main(void) { void main(void) {
int i; int i, rsp, new_value;
int *walker; int *walker;
// write to the middle of all pages
#if WALK_THE_PT
//-----------------------------------------------------------------
// write to the middle of all datapages
// this will cause some TLB refill exceptions, which should be
// handled smoothly by the handler at excp_0000 (include/start/s)
//-----------------------------------------------------------------
walker = (int *)(x_DATA_BASE_ADDR + 1024); walker = (int *)(x_DATA_BASE_ADDR + 1024);
for( i = 0 ; i < NUM_RAM_PAGES; i++){ for( i = 0 ; i < NUM_RAM_PAGES; i++){
...@@ -45,10 +69,179 @@ void main(void) { ...@@ -45,10 +69,179 @@ void main(void) {
walker = (int *)((int)walker + 4096); walker = (int *)((int)walker + 4096);
} }
to_stdout('\n'); print_str("\twalked\n");
to_stdout('o'); #endif
to_stdout('k');
to_stdout('\n');
#define PG_NUM 10
#if TLB_MODIFIED
//-------------------------------------------------------------------
// 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;
// (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.
//-------------------------------------------------------------------
// ( ( (x_DATA_BASE_ADDR + n*4096) >>12 )<<6 ) || 0b000111 d,v,g
walker = (int *)(x_DATA_BASE_ADDR + PG_NUM*4096);
// first, remove V_addr from the TLB, to ensure the PT is searched
if ( TLB_purge((void *)walker) == 0 ) {
print_str("\n\tTLB entry purged\n");
} else {
print_str("\n\tTLB miss\n");
}
new_value = ( ((x_DATA_BASE_ADDR + PG_NUM*4096)>>12) <<6) | 0b000011; // d=0
PT_update( (int *)walker, 0, new_value);
new_value = 0x00000009; // writable, mapped
PT_update( (int *)walker, 1, new_value);
*walker = 0x99; // cause a TLBrefill, then a TLBmod
if ( *walker == 0x99 ) { // this load is optimized away by gcc
print( *walker );
print_str("\tMod ok\n");
} else {
print_str("\tMod err\n");
}
#endif
#if DOUBLE_FAULT
//--------------------------------------------------------------------
// let's remove a PT's mapping from the TLB 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.
//--------------------------------------------------------------------
// 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");
} else {
print_str("\n\twtf?\n");
}
// now reference a mapped page, to cause the double fault
walker = (int *)(x_DATA_BASE_ADDR + PG_NUM*4096 + 1024);
*walker = 0x77; // cause a TLBrefill then a TLBload
if ( *walker == 0x77 ) { // this load is optimized away by gcc
print( *walker );
print_str("\tdouble ok\n");
} else {
print_str("\tdouble err\n");
}
#endif
#if PROT_VIOL
//----------------------------------------------------------------------
// let's cause a protection violation -- write to a write-protected page
// this will abort the simulation
//----------------------------------------------------------------------
walker = (int *)(x_DATA_BASE_ADDR + PG_NUM*4096);
// first, remove V_addr from the TLB, to ensure the PT is searched
if ( TLB_purge((void *)walker) == 0 ) {
print_str("\n\tpurged\n");
} else {
print_str("\t\tTLB miss\n");
}
// change a PT element so it is data, NON-writable, page is mapped in PT
new_value = ( ((x_DATA_BASE_ADDR + PG_NUM*4096)>>12) <<6) | 0b000011; // d=0
PT_update( (int *)walker, 0, new_value);
new_value = 0x00000001; // NOT-writable, mapped
PT_update( (int *)walker, 1, new_value);
*walker = 0x88;
// will never get here -- protection violation on the store
if ( *walker == 0x88 ) { // this load is optimized away by gcc
print( *walker );
print_str("\tprot viol not ok\n");
} else {
print_str("\tprot viol err\n");
}
#endif
#if SEG_FAULT
//-----------------------------------------------------------------
// let's cause a segmentation fault -- reference to page not mapped
// this will abort the simulation
//-----------------------------------------------------------------
#define PG_UNMAPPED 20
// pick a page that is not mapped
walker = (int *)(x_DATA_BASE_ADDR + PG_UNMAPPED*4096); // page not mapped
// first, remove V_addr from the TLB, to ensure the PT will be searched
if ( TLB_purge((void *)walker) == 0 ) {
print_str("\n\tpurged\n");
} else {
print_str("\n\tTLB miss\n");
}
// add a new PT element for an address range with RAM but UN-mapped
// this address is above the page table
new_value =
(((x_DATA_BASE_ADDR + PG_UNMAPPED*4096)>>12) <<6) | 0b000011; // d=0
PT_update( (int *)walker, 0, new_value);
PT_update( (int *)walker, 1, 0); // mark as unmapped
new_value =
(((x_DATA_BASE_ADDR + (PG_UNMAPPED+1)*4096)>>12) <<6) | 0b000011; // d=0
PT_update( (int *)walker, 2, new_value);
PT_update( (int *)walker, 3, 0); // mark as unmapped
*walker = 0x44;
// will never get here -- seg fault on the store
if ( *walker == 0x44 ) { // this load is optimized away by gcc
print( *walker );
print_str("\tseg fault not ok\n");
} else {
print_str("\tseg fault err\n");
}
#endif
to_stdout('\n');
} }
void print_str(char *s) {
int i;
i = 0;
while (s[i] != '\0') {
to_stdout(s[i]);
i = i + 1;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment