184 lines
3.1 KiB
ArmAsm
184 lines
3.1 KiB
ArmAsm
# See LICENSE for license details.
|
|
|
|
#*****************************************************************************
|
|
# napot.S
|
|
#-----------------------------------------------------------------------------
|
|
#
|
|
# Test Svnapot
|
|
#
|
|
|
|
#include "riscv_test.h"
|
|
#include "test_macros.h"
|
|
|
|
#if (DRAM_BASE >> 30 << 30) != DRAM_BASE
|
|
# error This test requires DRAM_BASE be SV39 superpage-aligned
|
|
#endif
|
|
|
|
#if __riscv_xlen != 64
|
|
# error This test requires RV64
|
|
#endif
|
|
|
|
RVTEST_RV64M
|
|
RVTEST_CODE_BEGIN
|
|
|
|
# Construct the page table
|
|
|
|
#define MY_VA 0x40201010
|
|
# VPN 2 == VPN 1 == VPN 0 == 0x1
|
|
# Page offset == 0x10
|
|
|
|
####
|
|
|
|
# Level 0 PTE contents
|
|
|
|
# PPN
|
|
la a0, my_data
|
|
srl a0, a0, 12
|
|
|
|
# adjust the PPN to be in NAPOT form
|
|
li a1, ~0xF
|
|
and a0, a0, a1
|
|
ori a0, a0, 0x8
|
|
|
|
# attributes
|
|
sll a0, a0, PTE_PPN_SHIFT
|
|
li a1, PTE_V | PTE_U | PTE_R | PTE_W | PTE_X | PTE_A | PTE_D | PTE_N
|
|
or a0, a0, a1
|
|
|
|
# Level 0 PTE address
|
|
la a1, page_table
|
|
addi a1, a1, ((MY_VA >> 12) & 0x1FF) * 8
|
|
|
|
# Level 0 PTE store
|
|
sd a0, (a1)
|
|
|
|
####
|
|
|
|
# Level 1 PTE contents
|
|
la a0, page_table
|
|
srl a0, a0, 12
|
|
sll a0, a0, PTE_PPN_SHIFT
|
|
li a1, PTE_V
|
|
or a0, a0, a1
|
|
|
|
# Level 1 PTE address
|
|
la a1, page_table
|
|
addi a1, a1, ((MY_VA >> 21) & 0x1FF) * 8
|
|
li a2, 1 << 12
|
|
add a1, a1, a2
|
|
|
|
# Level 1 PTE store
|
|
sd a0, (a1)
|
|
|
|
####
|
|
|
|
# Level 2 PTE contents
|
|
la a0, page_table
|
|
li a1, 1 << 12
|
|
add a0, a0, a1
|
|
srl a0, a0, 12
|
|
sll a0, a0, PTE_PPN_SHIFT
|
|
li a1, PTE_V
|
|
or a0, a0, a1
|
|
|
|
# Level 2 PTE address
|
|
la a1, page_table
|
|
addi a1, a1, ((MY_VA >> 30) & 0x1FF) * 8
|
|
li a2, 2 << 12
|
|
add a1, a1, a2
|
|
|
|
# Level 2 PTE store
|
|
sd a0, (a1)
|
|
|
|
####
|
|
|
|
# Do a load from the PA that would be written if the PTE were misinterpreted as non-NAPOT
|
|
la a0, my_data
|
|
li a1, ~0xFFFF
|
|
and a0, a0, a1
|
|
li a1, 0x8000 | (MY_VA & 0xFFF)
|
|
or a3, a0, a1
|
|
li a1, 0
|
|
sw a1, (a3)
|
|
|
|
####
|
|
li TESTNUM, 1
|
|
|
|
## Turn on VM
|
|
la a1, page_table
|
|
li a2, 2 << 12
|
|
add a1, a1, a2
|
|
srl a1, a1, 12
|
|
li a0, (SATP_MODE & ~(SATP_MODE<<1)) * SATP_MODE_SV39
|
|
or a0, a0, a1
|
|
csrw satp, a0
|
|
sfence.vma
|
|
|
|
# Set up MPRV with MPP=S and SUM=1, so loads and stores use S-mode and S can access U pages
|
|
li a1, ((MSTATUS_MPP & ~(MSTATUS_MPP<<1)) * PRV_S) | MSTATUS_MPRV | MSTATUS_SUM
|
|
csrs mstatus, a1
|
|
|
|
# Do a store to MY_VA
|
|
li a0, MY_VA
|
|
li a1, 42
|
|
napot_store:
|
|
sw a1, (a0)
|
|
|
|
# Clear MPRV
|
|
li a1, MSTATUS_MPRV
|
|
csrc mstatus, a1
|
|
|
|
# Do a load from the PA that would be written if the PTE were misinterpreted as non-NAPOT
|
|
lw a1, (a3)
|
|
|
|
# Check the result
|
|
li a0, 42
|
|
beq a1, a0, die
|
|
|
|
# Do a load from the PA for MY_VA
|
|
la a0, my_data
|
|
li a1, MY_VA & 0xFFFF
|
|
add a0, a0, a1
|
|
lw a1, (a0)
|
|
li a2, 42
|
|
|
|
# Check the result
|
|
bne a1, a2, die
|
|
|
|
####
|
|
|
|
RVTEST_PASS
|
|
|
|
TEST_PASSFAIL
|
|
|
|
.align 2
|
|
.global mtvec_handler
|
|
mtvec_handler:
|
|
# Skip if Svnapot is not implemented.
|
|
csrr t5, mcause
|
|
li t6, CAUSE_STORE_PAGE_FAULT
|
|
bne t5, t6, die
|
|
csrr t5, mepc
|
|
la t6, napot_store
|
|
bne t5, t6, die
|
|
csrr t5, mtval
|
|
li t6, MY_VA
|
|
beq t5, t6, pass
|
|
die:
|
|
RVTEST_FAIL
|
|
|
|
RVTEST_CODE_END
|
|
|
|
.data
|
|
RVTEST_DATA_BEGIN
|
|
|
|
TEST_DATA
|
|
|
|
.align 20
|
|
page_table: .dword 0
|
|
|
|
.align 20
|
|
my_data: .dword 0
|
|
|
|
RVTEST_DATA_END
|