Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
C
cMIPS
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Harbor Registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Roberto Hexsel
cMIPS
Commits
7fb756c2
There was a problem fetching the pipeline summary.
Commit
7fb756c2
authored
9 years ago
by
Roberto Hexsel
Browse files
Options
Downloads
Patches
Plain Diff
handler for TLBmodified
parent
23de04fe
Branches
Branches containing commit
No related tags found
No related merge requests found
Pipeline
#
Changes
3
Pipelines
1
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
cMIPS/include/handlers.s
+249
-17
249 additions, 17 deletions
cMIPS/include/handlers.s
cMIPS/include/start.s
+82
-52
82 additions, 52 deletions
cMIPS/include/start.s
cMIPS/tests/pt_walk.c
+200
-7
200 additions, 7 deletions
cMIPS/tests/pt_walk.c
with
531 additions
and
76 deletions
cMIPS/include/handlers.s
+
249
−
17
View file @
7fb756c2
#
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
,
0
b00000000000000000000000000000111
#
ccc
=
0
,
d
,
v
,
g1
mtc0
$a1
,
c0_entrylo0
#
bottom
page
(
even
)
la
$a0
,
(
(
MIDDLE_RAM
+
1
*
4096
)
>>
12
)<<
6
ori
$a1
,
$a0
,
0
b00000000000000000000000000000111
#
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
#----------------------------------------------------------------
#----------------------------------------------------------------
This diff is collapsed.
Click to expand it.
cMIPS/include/start.s
+
82
−
52
View file @
7fb756c2
...
@@ -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
h
andle
_Mod
#
1
nop
nop
j
h_TLBL
#
2
j
h
andle
_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
)
||
0
b000011
d
,
v
,
g
#
#
(
(
(
x_INST_BASE_ADDR
+
n
*
4096
)
>>
12
)<<
6
)
||
0
b000011
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
)
|
0
b000011
PTbase
:
.
word
(
(
x_INST_BASE_ADDR
+
0
*
4096
)
>>
6
)
|
0
b000011
.
word
0
.
word
0
x00000006
.
word
(
(
x_INST_BASE_ADDR
+
1
*
4096
)
>>
6
)
|
0
b000011
.
word
(
(
x_INST_BASE_ADDR
+
1
*
4096
)
>>
6
)
|
0
b000011
.
word
0
.
word
0
x00000006
#
PT
[
1
]
#
PT
[
1
]
.
word
(
(
x_INST_BASE_ADDR
+
2
*
4096
)
>>
6
)
|
0
b000011
.
word
(
(
x_INST_BASE_ADDR
+
2
*
4096
)
>>
6
)
|
0
b000011
.
word
0
.
word
0
x00000006
.
word
(
(
x_INST_BASE_ADDR
+
3
*
4096
)
>>
6
)
|
0
b000011
.
word
(
(
x_INST_BASE_ADDR
+
3
*
4096
)
>>
6
)
|
0
b000011
.
word
0
.
word
0
x00000006
#
PT
[
2
]
#
PT
[
2
]
--
not
mapped
for
simulation
.
word
(
(
x_INST_BASE_ADDR
+
4
*
4096
)
>>
6
)
|
0
b000011
.
word
(
(
x_INST_BASE_ADDR
+
4
*
4096
)
>>
6
)
|
0
b000011
.
word
0
.
word
0
x00000004
.
word
(
(
x_INST_BASE_ADDR
+
5
*
4096
)
>>
6
)
|
0
b000011
.
word
(
(
x_INST_BASE_ADDR
+
5
*
4096
)
>>
6
)
|
0
b000011
.
word
0
.
word
0
x00000004
#
PT
[
3
]
#
PT
[
3
]
--
not
mapped
for
simulation
.
word
(
(
x_INST_BASE_ADDR
+
6
*
4096
)
>>
6
)
|
0
b000011
.
word
(
(
x_INST_BASE_ADDR
+
6
*
4096
)
>>
6
)
|
0
b000011
.
word
0
.
word
0
x00000004
.
word
(
(
x_INST_BASE_ADDR
+
7
*
4096
)
>>
6
)
|
0
b000011
.
word
(
(
x_INST_BASE_ADDR
+
7
*
4096
)
>>
6
)
|
0
b000011
.
word
0
.
word
0
x00000004
#
PT
[
4
]
--
not
mapped
for
simulation
#
PT
[
4
]
--
not
mapped
for
simulation
.
word
(
(
x_INST_BASE_ADDR
+
8
*
4096
)
>>
6
)
|
0
b000001
.
word
(
(
x_INST_BASE_ADDR
+
8
*
4096
)
>>
6
)
|
0
b000001
.
word
0
.
word
0
x00000004
.
word
(
(
x_INST_BASE_ADDR
+
9
*
4096
)
>>
6
)
|
0
b000001
.
word
(
(
x_INST_BASE_ADDR
+
9
*
4096
)
>>
6
)
|
0
b000001
.
word
0
.
word
0
x00000004
#
PT
[
5
]
--
not
mapped
for
simulation
#
PT
[
5
]
--
not
mapped
for
simulation
.
word
(
(
x_INST_BASE_ADDR
+
10
*
4096
)
>>
6
)
|
0
b000001
.
word
(
(
x_INST_BASE_ADDR
+
10
*
4096
)
>>
6
)
|
0
b000001
.
word
0
.
word
0
x00000004
.
word
(
(
x_INST_BASE_ADDR
+
11
*
4096
)
>>
6
)
|
0
b000001
.
word
(
(
x_INST_BASE_ADDR
+
11
*
4096
)
>>
6
)
|
0
b000001
.
word
0
.
word
0
x00000004
#
PT
[
6
]
--
not
mapped
for
simulation
#
PT
[
6
]
--
not
mapped
for
simulation
.
word
(
(
x_INST_BASE_ADDR
+
12
*
4096
)
>>
6
)
|
0
b000001
.
word
(
(
x_INST_BASE_ADDR
+
12
*
4096
)
>>
6
)
|
0
b000001
.
word
0
.
word
0
x00000004
.
word
(
(
x_INST_BASE_ADDR
+
13
*
4096
)
>>
6
)
|
0
b000001
.
word
(
(
x_INST_BASE_ADDR
+
13
*
4096
)
>>
6
)
|
0
b000001
.
word
0
.
word
0
x00000004
#
PT
[
7
]
--
not
mapped
for
simulation
#
PT
[
7
]
--
not
mapped
for
simulation
.
word
(
(
x_INST_BASE_ADDR
+
14
*
4096
)
>>
6
)
|
0
b000001
.
word
(
(
x_INST_BASE_ADDR
+
14
*
4096
)
>>
6
)
|
0
b000001
.
word
0
.
word
0
x00000004
.
word
(
(
x_INST_BASE_ADDR
+
15
*
4096
)
>>
6
)
|
0
b000001
.
word
(
(
x_INST_BASE_ADDR
+
15
*
4096
)
>>
6
)
|
0
b000001
.
word
0
.
word
0
x00000004
#
#
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
)
|
0
b000111
.
word
(
(
x_DATA_BASE_ADDR
+
0
*
4096
)
>>
6
)
|
0
b000111
.
word
0
.
word
0
x0000000a
.
word
(
(
x_DATA_BASE_ADDR
+
1
*
4096
)
>>
6
)
|
0
b000111
.
word
(
(
x_DATA_BASE_ADDR
+
1
*
4096
)
>>
6
)
|
0
b000111
.
word
0
.
word
0
x0000000a
#
PT
[
ram
+
1
]
#
PT
[
ram
+
1
]
.
word
(
(
x_DATA_BASE_ADDR
+
2
*
4096
)
>>
6
)
|
0
b000111
.
word
(
(
x_DATA_BASE_ADDR
+
2
*
4096
)
>>
6
)
|
0
b000111
.
word
0
.
word
0
x0000000a
.
word
(
(
x_DATA_BASE_ADDR
+
3
*
4096
)
>>
6
)
|
0
b000111
.
word
(
(
x_DATA_BASE_ADDR
+
3
*
4096
)
>>
6
)
|
0
b000111
.
word
0
.
word
0
x0000000a
#
PT
[
ram
+
2
]
#
PT
[
ram
+
2
]
.
word
(
(
x_DATA_BASE_ADDR
+
4
*
4096
)
>>
6
)
|
0
b000111
.
word
(
(
x_DATA_BASE_ADDR
+
4
*
4096
)
>>
6
)
|
0
b000111
.
word
0
.
word
0
x0000000a
.
word
(
(
x_DATA_BASE_ADDR
+
5
*
4096
)
>>
6
)
|
0
b000111
.
word
(
(
x_DATA_BASE_ADDR
+
5
*
4096
)
>>
6
)
|
0
b000111
.
word
0
.
word
0
x0000000a
#
PT
[
ram
+
3
]
#
PT
[
ram
+
3
]
.
word
(
(
x_DATA_BASE_ADDR
+
6
*
4096
)
>>
6
)
|
0
b000111
.
word
(
(
x_DATA_BASE_ADDR
+
6
*
4096
)
>>
6
)
|
0
b000111
.
word
0
.
word
0
x0000000a
.
word
(
(
x_DATA_BASE_ADDR
+
7
*
4096
)
>>
6
)
|
0
b000111
.
word
(
(
x_DATA_BASE_ADDR
+
7
*
4096
)
>>
6
)
|
0
b000111
.
word
0
.
word
0
x0000000a
#
PT
[
ram
+
4
]
#
PT
[
ram
+
4
]
.
word
(
(
x_DATA_BASE_ADDR
+
8
*
4096
)
>>
6
)
|
0
b000111
.
word
(
(
x_DATA_BASE_ADDR
+
8
*
4096
)
>>
6
)
|
0
b000111
.
word
0
.
word
0
x0000000a
.
word
(
(
x_DATA_BASE_ADDR
+
9
*
4096
)
>>
6
)
|
0
b000111
.
word
(
(
x_DATA_BASE_ADDR
+
9
*
4096
)
>>
6
)
|
0
b000111
.
word
0
.
word
0
x0000000a
#
PT
[
ram
+
5
]
#
PT
[
ram
+
5
]
.
word
(
(
x_DATA_BASE_ADDR
+
10
*
4096
)
>>
6
)
|
0
b000111
.
word
(
(
x_DATA_BASE_ADDR
+
10
*
4096
)
>>
6
)
|
0
b000111
.
word
0
.
word
0
x0000000a
.
word
(
(
x_DATA_BASE_ADDR
+
11
*
4096
)
>>
6
)
|
0
b000111
.
word
(
(
x_DATA_BASE_ADDR
+
11
*
4096
)
>>
6
)
|
0
b000111
.
word
0
.
word
0
x0000000a
#
PT
[
ram
+
6
]
#
PT
[
ram
+
6
]
.
word
(
(
x_DATA_BASE_ADDR
+
12
*
4096
)
>>
6
)
|
0
b000111
.
word
(
(
x_DATA_BASE_ADDR
+
12
*
4096
)
>>
6
)
|
0
b000111
.
word
0
.
word
0
x0000000a
.
word
(
(
x_DATA_BASE_ADDR
+
13
*
4096
)
>>
6
)
|
0
b000111
.
word
(
(
x_DATA_BASE_ADDR
+
13
*
4096
)
>>
6
)
|
0
b000111
.
word
0
.
word
0
x0000000a
#
PT
[
ram
+
7
]
#
PT
[
ram
+
7
]
.
word
(
(
x_DATA_BASE_ADDR
+
14
*
4096
)
>>
6
)
|
0
b000111
.
word
(
(
x_DATA_BASE_ADDR
+
14
*
4096
)
>>
6
)
|
0
b000111
.
word
0
.
word
0
x0000000a
.
word
(
(
x_DATA_BASE_ADDR
+
15
*
4096
)
>>
6
)
|
0
b000111
.
word
(
(
x_DATA_BASE_ADDR
+
15
*
4096
)
>>
6
)
|
0
b000111
.
word
0
.
word
0
x0000000a
#
#
all
remaining
RAM
entries
are
invalid
#
#
all
remaining
RAM
entries
are
invalid
and
unmapped
_endPT
:
_endPT
:
This diff is collapsed.
Click to expand it.
cMIPS/tests/pt_walk.c
+
200
−
7
View file @
7fb756c2
...
@@ -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
(
"
\t
walked
\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\t
TLB entry purged
\n
"
);
}
else
{
print_str
(
"
\n\t
TLB miss
\n
"
);
}
new_value
=
(
((
x_DATA_BASE_ADDR
+
PG_NUM
*
4096
)
>>
12
)
<<
6
)
|
0
b000011
;
// 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
(
"
\t
Mod ok
\n
"
);
}
else
{
print_str
(
"
\t
Mod 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\t
PT purged from TLB
\n
"
);
}
else
{
print_str
(
"
\n\t
wtf?
\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
(
"
\t
double ok
\n
"
);
}
else
{
print_str
(
"
\t
double 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\t
purged
\n
"
);
}
else
{
print_str
(
"
\t\t
TLB 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
)
|
0
b000011
;
// 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
(
"
\t
prot viol not ok
\n
"
);
}
else
{
print_str
(
"
\t
prot 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\t
purged
\n
"
);
}
else
{
print_str
(
"
\n\t
TLB 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
)
|
0
b000011
;
// 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
)
|
0
b000011
;
// 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
(
"
\t
seg fault not ok
\n
"
);
}
else
{
print_str
(
"
\t
seg 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
;
}
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment