From e02f9cc2c8542dfb2306f092eab75ad8d343d414 Mon Sep 17 00:00:00 2001 From: David Harris Date: Thu, 24 Aug 2023 04:54:09 -0700 Subject: [PATCH 01/11] Some fixes for synthesis scripts after parameterization --- synthDC/Makefile | 32 ++++++++++++++++---------------- synthDC/scripts/synth.tcl | 6 ++++-- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/synthDC/Makefile b/synthDC/Makefile index 5a723d4c3..6fd185ffd 100755 --- a/synthDC/Makefile +++ b/synthDC/Makefile @@ -55,11 +55,11 @@ $(CONFIG): # adjust DTIM and IROM to reasonable values depending on config ifneq ($(filter $(CONFIG), $(DIRS32)),) - sed -i "s/DTIM_RANGE.*/DTIM_RANGE 34\'h01FF/g" $(CONFIGDIR)/config.vh - sed -i "s/IROM_RANGE.*/IROM_RANGE 34\'h01FF/g" $(CONFIGDIR)/config.vh + sed -i "s/DTIM_RANGE.*/DTIM_RANGE = 34\'h01FF;/g" $(CONFIGDIR)/config.vh + sed -i "s/IROM_RANGE.*/IROM_RANGE = 34\'h01FF;/g" $(CONFIGDIR)/config.vh else ifneq ($(filter $(CONFIG), $(DIRS64)),) - sed -i "s/DTIM_RANGE.*/DTIM_RANGE 56\'h01FF/g" $(CONFIGDIR)/config.vh - sed -i "s/IROM_RANGE.*/IROM_RANGE 56\'h01FF/g" $(CONFIGDIR)/config.vh + sed -i "s/DTIM_RANGE.*/DTIM_RANGE = 56\'h01FF;/g" $(CONFIGDIR)/config.vh + sed -i "s/IROM_RANGE.*/IROM_RANGE = 56\'h01FF;/g" $(CONFIGDIR)/config.vh else $(info $(CONFIG) does not exist in $(DIRS32) or $(DIRS64)) @echo "Config not in list, RAM_RANGE will be unmodified" @@ -67,18 +67,18 @@ endif # if USESRAM = 1, set that in the config file, otherwise reduce sizes ifeq ($(USESRAM), 1) - sed -i 's/USE_SRAM.*/USE_SRAM 1/g' $(CONFIGDIR)/config.vh + sed -i 's/USE_SRAM.*/USE_SRAM = 1;/g' $(CONFIGDIR)/config.vh else - sed -i 's/WAYSIZEINBYTES.*/WAYSIZEINBYTES 512/g' $(CONFIGDIR)/config.vh - sed -i 's/NUMWAYS.*/NUMWAYS 1/g' $(CONFIGDIR)/config.vh - sed -i 's/BPRED_SIZE.*/BPRED_SIZE 5/g' $(CONFIGDIR)/config.vh - sed -i 's/BTB_SIZE.*/BTB_SIZE 5/g' $(CONFIGDIR)/config.vh + sed -i 's/WAYSIZEINBYTES.*/WAYSIZEINBYTES = 512;/g' $(CONFIGDIR)/config.vh + sed -i 's/NUMWAYS.*/NUMWAYS = 1;/g' $(CONFIGDIR)/config.vh + sed -i 's/BPRED_SIZE.*/BPRED_SIZE = 5;/g' $(CONFIGDIR)/config.vh + sed -i 's/BTB_SIZE.*/BTB_SIZE = 5;/g' $(CONFIGDIR)/config.vh ifneq ($(filter $(CONFIG), $(DIRS32)),) - sed -i "s/BOOTROM_RANGE.*/BOOTROM_RANGE 34\'h01FF/g" $(CONFIGDIR)/config.vh - sed -i "s/UNCORE_RAM_RANGE.*/UNCORE_RAM_RANGE 34\'h01FF/g" $(CONFIGDIR)/config.vh + sed -i "s/BOOTROM_RANGE.*/BOOTROM_RANGE = 34\'h01FF;/g" $(CONFIGDIR)/config.vh + sed -i "s/UNCORE_RAM_RANGE.*/UNCORE_RAM_RANGE = 34\'h01FF;/g" $(CONFIGDIR)/config.vh else ifneq ($(filter $(CONFIG), $(DIRS64)),) - sed -i "s/BOOTROM_RANGE.*/BOOTROM_RANGE 56\'h01FF/g" $(CONFIGDIR)/config.vh - sed -i "s/UNCORE_RAM_RANGE.*/UNCORE_RAM_RANGE 56\'h01FF/g" $(CONFIGDIR)/config.vh + sed -i "s/BOOTROM_RANGE.*/BOOTROM_RANGE = 56\'h01FF;/g" $(CONFIGDIR)/config.vh + sed -i "s/UNCORE_RAM_RANGE.*/UNCORE_RAM_RANGE = 56\'h01FF;/g" $(CONFIGDIR)/config.vh endif endif @@ -94,10 +94,10 @@ endif ifneq ($(MOD), orig) # PMP 0 - sed -i 's/PMP_ENTRIES \(64\|16\|0\)/PMP_ENTRIES 0/' $(CONFIGDIR)/config.vh + sed -i 's/PMP_ENTRIES \(64\|16\|0\)/PMP_ENTRIES = 0;/' $(CONFIGDIR)/config.vh ifneq ($(MOD), PMP0) # no priv - sed -i 's/ZICSR_SUPPORTED *1/ZICSR_SUPPORTED 0/' $(CONFIGDIR)/config.vh + sed -i 's/ZICSR_SUPPORTED *1/ZICSR_SUPPORTED = 0;/' $(CONFIGDIR)/config.vh ifneq ($(MOD), noPriv) # turn off FPU sed -i 's/1 *<< *3/0 << 3/' $(CONFIGDIR)/config.vh @@ -128,7 +128,7 @@ mkdirecs: @mkdir -p $(OUTPUTDIR)/mapped @mkdir -p $(OUTPUTDIR)/unmapped -synth: mkdirecs configs rundc clean +synth: mkdirecs configs rundc # clean rundc: ifeq ($(TECH), tsmc28psyn) diff --git a/synthDC/scripts/synth.tcl b/synthDC/scripts/synth.tcl index a7ae6ef09..7a8c2e7bf 100755 --- a/synthDC/scripts/synth.tcl +++ b/synthDC/scripts/synth.tcl @@ -25,7 +25,9 @@ set maxopt $::env(MAXOPT) set drive $::env(DRIVE) eval file copy -force [glob ${cfg}/*.vh] {$outputDir/hdl/} -eval file copy -force [glob ${hdl_src}/*.sv] {$outputDir/hdl/} +eval file copy -force [glob ${cfg}/*.vh] {$outputDir/hdl/} +eval file copy -force [glob ${hdl_src}/cvw.sv] {$outputDir/hdl/} +eval file copy -force [glob ${hdl_src}/../fpga/src/wallypipelinedsocwrapper.sv] {$outputDir/hdl/} eval file copy -force [glob ${hdl_src}/*/*.sv] {$outputDir/hdl/} eval file copy -force [glob ${hdl_src}/*/*/*.sv] {$outputDir/hdl/} @@ -74,7 +76,7 @@ if { [shell_is_in_topographical_mode] } { #set alib_library_analysis_path ./$outputDir define_design_lib WORK -path ./$outputDir/WORK analyze -f sverilog -lib WORK $my_verilog_files -elaborate $my_toplevel -lib WORK +elaborate $my_toplevel -parameter P -lib WORK # Set the current_design current_design $my_toplevel From f5dab9f2fe626601750ceab0cd94456670da3462 Mon Sep 17 00:00:00 2001 From: David Harris Date: Thu, 24 Aug 2023 05:18:04 -0700 Subject: [PATCH 02/11] Check for legal SATP mode values --- src/privileged/csrs.sv | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/privileged/csrs.sv b/src/privileged/csrs.sv index fbe40c13c..95599e3a0 100644 --- a/src/privileged/csrs.sv +++ b/src/privileged/csrs.sv @@ -88,8 +88,12 @@ module csrs import cvw::*; #(parameter cvw_t P) ( assign WriteSEPCM = STrapM | (CSRSWriteM & (CSRAdrM == SEPC)); assign WriteSCAUSEM = STrapM | (CSRSWriteM & (CSRAdrM == SCAUSE)); assign WriteSTVALM = STrapM | (CSRSWriteM & (CSRAdrM == STVAL)); - if(P.XLEN == 64) assign WriteSATPM = CSRSWriteM & (CSRAdrM == SATP) & (PrivilegeModeW == P.M_MODE | ~STATUS_TVM) & (CSRWriteValM[63:60] != 4'hA); - else assign WriteSATPM = CSRSWriteM & (CSRAdrM == SATP) & (PrivilegeModeW == P.M_MODE | ~STATUS_TVM); + if(P.XLEN == 64) begin + logic LegalSatpModeM; + assign LegalSatpModeM = P.VIRTMEM_SUPPORTED & (CSRWriteValM[63:60] == 0 | CSRWriteValM[63:60] == 8 | CSRWriteValM[63:60] == 9); // supports SV39 and 48 + assign WriteSATPM = CSRSWriteM & (CSRAdrM == SATP) & (PrivilegeModeW == P.M_MODE | ~STATUS_TVM) & LegalSatpModeM; + end else // RV32 + assign WriteSATPM = CSRSWriteM & (CSRAdrM == SATP) & (PrivilegeModeW == P.M_MODE | ~STATUS_TVM) & P.VIRTMEM_SUPPORTED; assign WriteSCOUNTERENM = CSRSWriteM & (CSRAdrM == SCOUNTEREN); assign WriteSENVCFGM = CSRSWriteM & (CSRAdrM == SENVCFG); assign WriteSTIMECMPM = CSRSWriteM & (CSRAdrM == STIMECMP) & STCE; From d94a7392366b1e1563f0bb4d1df833bca411a077 Mon Sep 17 00:00:00 2001 From: David Harris Date: Thu, 24 Aug 2023 05:21:15 -0700 Subject: [PATCH 03/11] ??? on synthesis Makefile --- synthDC/Makefile | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/synthDC/Makefile b/synthDC/Makefile index ea3cdda47..64dd497a7 100755 --- a/synthDC/Makefile +++ b/synthDC/Makefile @@ -69,26 +69,15 @@ endif ifeq ($(USESRAM), 1) sed -i 's/USE_SRAM.*/USE_SRAM = 1;/g' $(CONFIGDIR)/config.vh else -<<<<<<< HEAD - sed -i 's/WAYSIZEINBYTES.*/WAYSIZEINBYTES = 512;/g' $(CONFIGDIR)/config.vh - sed -i 's/NUMWAYS.*/NUMWAYS = 1;/g' $(CONFIGDIR)/config.vh - sed -i 's/BPRED_SIZE.*/BPRED_SIZE = 5;/g' $(CONFIGDIR)/config.vh - sed -i 's/BTB_SIZE.*/BTB_SIZE = 5;/g' $(CONFIGDIR)/config.vh -======= sed -i "s/WAYSIZEINBYTES.*/WAYSIZEINBYTES = 32\'d512;/g" $(CONFIGDIR)/config.vh sed -i "s/NUMWAYS.*/NUMWAYS =32\'d1;/g" $(CONFIGDIR)/config.vh sed -i "s/BPRED_SIZE.*/BPRED_SIZE =32\'d5;/g" $(CONFIGDIR)/config.vh sed -i "s/BTB_SIZE.*/BTB_SIZE = 32\'d5;/g" $(CONFIGDIR)/config.vh ->>>>>>> dcef4cc9cee704ec78c6c5118bb769405cedc499 ifneq ($(filter $(CONFIG), $(DIRS32)),) sed -i "s/BOOTROM_RANGE.*/BOOTROM_RANGE = 34\'h01FF;/g" $(CONFIGDIR)/config.vh sed -i "s/UNCORE_RAM_RANGE.*/UNCORE_RAM_RANGE = 34\'h01FF;/g" $(CONFIGDIR)/config.vh else ifneq ($(filter $(CONFIG), $(DIRS64)),) -<<<<<<< HEAD - sed -i "s/BOOTROM_RANGE.*/BOOTROM_RANGE = 56\'h01FF;/g" $(CONFIGDIR)/config.vh -======= sed -i "s/BOOTROM_RANGE.*/BOOTROM_RANGE = 56\'h01FF;/g" $(CONFIGDIR)/config.vh ->>>>>>> dcef4cc9cee704ec78c6c5118bb769405cedc499 sed -i "s/UNCORE_RAM_RANGE.*/UNCORE_RAM_RANGE = 56\'h01FF;/g" $(CONFIGDIR)/config.vh endif endif From c9112ff18d1347a1bf430872f41a47485eb06b89 Mon Sep 17 00:00:00 2001 From: harshinisrinath Date: Thu, 24 Aug 2023 18:39:15 -0700 Subject: [PATCH 04/11] Improved testing of csri with priv.S --- src/privileged/csri.sv | 2 +- tests/coverage/priv.S | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/privileged/csri.sv b/src/privileged/csri.sv index 2e5488af7..ea7bf7afb 100644 --- a/src/privileged/csri.sv +++ b/src/privileged/csri.sv @@ -60,7 +60,7 @@ module csri import cvw::*; #(parameter cvw_t P) ( // SSIP is writable in SIP if S mode exists if (P.S_SUPPORTED) begin:mask if (P.SSTC_SUPPORTED) begin - assign MIP_WRITE_MASK = 12'h202; // SEIP and SSIP are writable, but STIP is not writable when STIMECMP is implemented (see SSTC spec) + assign MIP_WRITE_MASK = ENVCFG_STCE ? 12'h202 : 12'h222; // SEIP and SSIP are writable, but STIP is not writable when STIMECMP is implemented (see SSTC spec) assign STIP = ENVCFG_STCE ? STimerInt : MIP_REGW_writeable[5]; end else begin assign MIP_WRITE_MASK = 12'h222; // SEIP, STIP, SSIP are writeable in MIP (20210108-draft 3.1.9) diff --git a/tests/coverage/priv.S b/tests/coverage/priv.S index a8eacb9cc..cd5b54d33 100644 --- a/tests/coverage/priv.S +++ b/tests/coverage/priv.S @@ -72,7 +72,7 @@ sretdone: li a0, 3 ecall # in M-mode li t0, 32 - csrs sip, t0 + csrs mip, t0 li a0, 1 ecall # in S-mode and expects stimer interrupt to occur li a0, 3 From c6631ef8089ce753b2752b0f3484a5ce2430d235 Mon Sep 17 00:00:00 2001 From: David Harris Date: Thu, 24 Aug 2023 19:44:46 -0700 Subject: [PATCH 05/11] Added N and PBMT bits to MMU PTE --- config/buildroot/config.vh | 1 + config/fpga/config.vh | 1 + config/rv32e/config.vh | 1 + config/rv32gc/config.vh | 1 + config/rv32i/config.vh | 1 + config/rv32imc/config.vh | 1 + config/rv64fpquad/config.vh | 1 + config/rv64gc/config.vh | 1 + config/rv64i/config.vh | 1 + config/shared/config-shared.vh | 4 ++-- config/shared/parameter-defs.vh | 1 + src/cvw.sv | 1 + src/mmu/tlb/tlb.sv | 2 +- src/mmu/tlb/tlbcontrol.sv | 35 ++++++++++++++++------------- src/mmu/tlb/tlbram.sv | 18 +++++++-------- src/privileged/csrs.sv | 2 +- testbench/common/riscvassertions.sv | 8 ++++--- 17 files changed, 48 insertions(+), 32 deletions(-) diff --git a/config/buildroot/config.vh b/config/buildroot/config.vh index 6376904dc..b8d9608f1 100644 --- a/config/buildroot/config.vh +++ b/config/buildroot/config.vh @@ -47,6 +47,7 @@ localparam ZICBOM_SUPPORTED = 0; localparam ZICBOZ_SUPPORTED = 0; localparam ZICBOP_SUPPORTED = 0; localparam SVPBMT_SUPPORTED = 0; +localparam SVNAPOT_SUPPORTED = 0; localparam SVINVAL_SUPPORTED = 1; // LSU microarchitectural Features diff --git a/config/fpga/config.vh b/config/fpga/config.vh index 3551da010..bd08cd11d 100644 --- a/config/fpga/config.vh +++ b/config/fpga/config.vh @@ -49,6 +49,7 @@ localparam ZICBOM_SUPPORTED = 0; localparam ZICBOZ_SUPPORTED = 0; localparam ZICBOP_SUPPORTED = 0; localparam SVPBMT_SUPPORTED = 0; +localparam SVNAPOT_SUPPORTED = 0; localparam SVINVAL_SUPPORTED = 1; // LSU microarchitectural Features diff --git a/config/rv32e/config.vh b/config/rv32e/config.vh index 83c4efd52..e1cbdab0f 100644 --- a/config/rv32e/config.vh +++ b/config/rv32e/config.vh @@ -48,6 +48,7 @@ localparam ZICBOM_SUPPORTED = 0; localparam ZICBOZ_SUPPORTED = 0; localparam ZICBOP_SUPPORTED = 0; localparam SVPBMT_SUPPORTED = 0; +localparam SVNAPOT_SUPPORTED = 0; localparam SVINVAL_SUPPORTED = 0; // LSU microarchitectural Features diff --git a/config/rv32gc/config.vh b/config/rv32gc/config.vh index b08bf06d8..d5c718443 100644 --- a/config/rv32gc/config.vh +++ b/config/rv32gc/config.vh @@ -49,6 +49,7 @@ localparam ZICBOM_SUPPORTED = 1; localparam ZICBOZ_SUPPORTED = 0; localparam ZICBOP_SUPPORTED = 0; localparam SVPBMT_SUPPORTED = 0; +localparam SVNAPOT_SUPPORTED = 0; localparam SVINVAL_SUPPORTED = 1; // LSU microarchitectural Features diff --git a/config/rv32i/config.vh b/config/rv32i/config.vh index 1897ddeb2..e1c5a6a5d 100644 --- a/config/rv32i/config.vh +++ b/config/rv32i/config.vh @@ -48,6 +48,7 @@ localparam ZICBOM_SUPPORTED = 0; localparam ZICBOZ_SUPPORTED = 0; localparam ZICBOP_SUPPORTED = 0; localparam SVPBMT_SUPPORTED = 0; +localparam SVNAPOT_SUPPORTED = 0; localparam SVINVAL_SUPPORTED = 0; // LSU microarchitectural Features diff --git a/config/rv32imc/config.vh b/config/rv32imc/config.vh index 85d3597f9..a9123cbb4 100644 --- a/config/rv32imc/config.vh +++ b/config/rv32imc/config.vh @@ -47,6 +47,7 @@ localparam ZICBOM_SUPPORTED = 0; localparam ZICBOZ_SUPPORTED = 0; localparam ZICBOP_SUPPORTED = 0; localparam SVPBMT_SUPPORTED = 0; +localparam SVNAPOT_SUPPORTED = 0; localparam SVINVAL_SUPPORTED = 0; // LSU microarchitectural Features diff --git a/config/rv64fpquad/config.vh b/config/rv64fpquad/config.vh index f0c6cc6b2..2533dbc21 100644 --- a/config/rv64fpquad/config.vh +++ b/config/rv64fpquad/config.vh @@ -48,6 +48,7 @@ localparam ZICBOM_SUPPORTED = 0; localparam ZICBOZ_SUPPORTED = 0; localparam ZICBOP_SUPPORTED = 0; localparam SVPBMT_SUPPORTED = 0; +localparam SVNAPOT_SUPPORTED = 0; localparam SVINVAL_SUPPORTED = 1; // LSU microarchitectural Features diff --git a/config/rv64gc/config.vh b/config/rv64gc/config.vh index 939ce72c8..bd4e2f050 100644 --- a/config/rv64gc/config.vh +++ b/config/rv64gc/config.vh @@ -51,6 +51,7 @@ localparam ZICBOM_SUPPORTED = 1; localparam ZICBOZ_SUPPORTED = 0; localparam ZICBOP_SUPPORTED = 0; localparam SVPBMT_SUPPORTED = 0; +localparam SVNAPOT_SUPPORTED = 0; localparam SVINVAL_SUPPORTED = 1; // LSU microarchitectural Features diff --git a/config/rv64i/config.vh b/config/rv64i/config.vh index 3d7f33544..c27f7faf0 100644 --- a/config/rv64i/config.vh +++ b/config/rv64i/config.vh @@ -48,6 +48,7 @@ localparam ZICBOM_SUPPORTED = 0; localparam ZICBOZ_SUPPORTED = 0; localparam ZICBOP_SUPPORTED = 0; localparam SVPBMT_SUPPORTED = 0; +localparam SVNAPOT_SUPPORTED = 0; localparam SVINVAL_SUPPORTED = 0; // LSU microarchitectural Features diff --git a/config/shared/config-shared.vh b/config/shared/config-shared.vh index 96ef1e929..54a6675ee 100644 --- a/config/shared/config-shared.vh +++ b/config/shared/config-shared.vh @@ -101,10 +101,10 @@ localparam FPDUR = ((DIVN+1+(LOGR*DIVCOPIES))/(LOGR*DIVCOPIES)+(RADIX/4)); localparam DURLEN = ($clog2(FPDUR+1)); localparam DIVb = (FPDUR*LOGR*DIVCOPIES-1); // canonical fdiv size (b) localparam DIVBLEN = ($clog2(DIVb+1)-1); -localparam DIVa = (DIVb+1-XLEN); // used for idiv on fpu +localparam DIVa = (DIVb+1-XLEN); // used for idiv on fpu: Shift residual right by b - (XLEN-1) to put remainder in lsbs of integer result // largest length in IEU/FPU -localparam CVTLEN = ((NF(DIVb + 1 +NF+1) & (CVTLEN+NF+1)>(3*NF+6)) ? (CVTLEN+NF+1) : ((DIVb + 1 +NF+1) > (3*NF+6) ? (DIVb + 1 +NF+1) : (3*NF+6))); diff --git a/config/shared/parameter-defs.vh b/config/shared/parameter-defs.vh index 6e01aabb4..f63028a92 100644 --- a/config/shared/parameter-defs.vh +++ b/config/shared/parameter-defs.vh @@ -25,6 +25,7 @@ parameter cvw_t P = '{ ZICBOZ_SUPPORTED : ZICBOZ_SUPPORTED, ZICBOP_SUPPORTED : ZICBOP_SUPPORTED, SVPBMT_SUPPORTED : SVPBMT_SUPPORTED, + SVNAPOT_SUPPORTED : SVNAPOT_SUPPORTED, SVINVAL_SUPPORTED : SVINVAL_SUPPORTED, BUS_SUPPORTED : BUS_SUPPORTED, DCACHE_SUPPORTED : DCACHE_SUPPORTED, diff --git a/src/cvw.sv b/src/cvw.sv index 818773087..0c3e959fc 100644 --- a/src/cvw.sv +++ b/src/cvw.sv @@ -60,6 +60,7 @@ typedef struct packed { logic ZICBOZ_SUPPORTED; logic ZICBOP_SUPPORTED; logic SVPBMT_SUPPORTED; + logic SVNAPOT_SUPPORTED; logic SVINVAL_SUPPORTED; // Microarchitectural Features diff --git a/src/mmu/tlb/tlb.sv b/src/mmu/tlb/tlb.sv index c081b0925..c0468aede 100644 --- a/src/mmu/tlb/tlb.sv +++ b/src/mmu/tlb/tlb.sv @@ -79,7 +79,7 @@ module tlb import cvw::*; #(parameter cvw_t P, logic [P.VPN_BITS-1:0] VPN; logic [P.PPN_BITS-1:0] PPN; // Sections of the page table entry - logic [7:0] PTEAccessBits; + logic [10:0] PTEAccessBits; logic [1:0] HitPageType; logic CAMHit; logic SV39Mode; diff --git a/src/mmu/tlb/tlbcontrol.sv b/src/mmu/tlb/tlbcontrol.sv index 67d598038..f996ce55d 100644 --- a/src/mmu/tlb/tlbcontrol.sv +++ b/src/mmu/tlb/tlbcontrol.sv @@ -29,27 +29,28 @@ module tlbcontrol import cvw::*; #(parameter cvw_t P, ITLB = 0) ( input logic [P.SVMODE_BITS-1:0] SATP_MODE, input logic [P.XLEN-1:0] VAdr, - input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, - input logic [1:0] STATUS_MPP, - input logic [1:0] PrivilegeModeW, // Current privilege level of the processeor - input logic ReadAccess, WriteAccess, - input logic DisableTranslation, - input logic TLBFlush, // Invalidate all TLB entries - input logic [7:0] PTEAccessBits, - input logic CAMHit, - input logic Misaligned, - output logic TLBMiss, - output logic TLBHit, - output logic TLBPageFault, - output logic UpdateDA, - output logic SV39Mode, - output logic Translate + input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, + input logic [1:0] STATUS_MPP, + input logic [1:0] PrivilegeModeW, // Current privilege level of the processeor + input logic ReadAccess, WriteAccess, + input logic DisableTranslation, + input logic TLBFlush, // Invalidate all TLB entries + input logic [10:0] PTEAccessBits, + input logic CAMHit, + input logic Misaligned, + output logic TLBMiss, + output logic TLBHit, + output logic TLBPageFault, + output logic UpdateDA, + output logic SV39Mode, + output logic Translate ); // Sections of the page table entry logic [1:0] EffectivePrivilegeMode; - logic PTE_D, PTE_A, PTE_U, PTE_X, PTE_W, PTE_R, PTE_V; // Useful PTE Control Bits + logic PTE_N, PTE_D, PTE_A, PTE_U, PTE_X, PTE_W, PTE_R, PTE_V; // Useful PTE Control Bits + logic [1:0] PTE_PBMT; logic UpperBitsUnequal; logic TLBAccess; logic ImproperPrivilege; @@ -65,6 +66,8 @@ module tlbcontrol import cvw::*; #(parameter cvw_t P, ITLB = 0) ( vm64check #(P) vm64check(.SATP_MODE, .VAdr, .SV39Mode, .UpperBitsUnequal); // unswizzle useful PTE bits + assign PTE_N = PTEAccessBits[10] & P.SVNAPOT_SUPPORTED; + assign PTE_PBMT = PTEAccessBits[9:8] & {2{P.SVPBMT_SUPPORTED}}; assign {PTE_D, PTE_A} = PTEAccessBits[7:6]; assign {PTE_U, PTE_X, PTE_W, PTE_R, PTE_V} = PTEAccessBits[4:0]; diff --git a/src/mmu/tlb/tlbram.sv b/src/mmu/tlb/tlbram.sv index eb8dedca7..50f6883b3 100644 --- a/src/mmu/tlb/tlbram.sv +++ b/src/mmu/tlb/tlbram.sv @@ -32,23 +32,23 @@ module tlbram import cvw::*; #(parameter cvw_t P, parameter TLB_ENTRIES = 8) ( input logic clk, reset, - input logic [P.XLEN-1:0] PTE, + input logic [P.XLEN-1:0] PTE, input logic [TLB_ENTRIES-1:0] Matches, WriteEnables, - output logic [P.PPN_BITS-1:0] PPN, - output logic [7:0] PTEAccessBits, + output logic [P.PPN_BITS-1:0] PPN, + output logic [10:0] PTEAccessBits, output logic [TLB_ENTRIES-1:0] PTE_Gs ); - logic [P.PPN_BITS+9:0] RamRead[TLB_ENTRIES-1:0]; - logic [P.PPN_BITS+9:0] PageTableEntry; + logic [P.XLEN-1:0] RamRead[TLB_ENTRIES-1:0]; // stores the page table entries + logic [P.XLEN-1:0] PageTableEntry; // RAM implemented with array of flops and AND/OR read logic - tlbramline #(P.PPN_BITS+10) tlbramline[TLB_ENTRIES-1:0] + tlbramline #(P.XLEN) tlbramline[TLB_ENTRIES-1:0] (.clk, .reset, .re(Matches), .we(WriteEnables), - .d(PTE[P.PPN_BITS+9:0]), .q(RamRead), .PTE_G(PTE_Gs)); - or_rows #(TLB_ENTRIES, P.PPN_BITS+10) PTEOr(RamRead, PageTableEntry); + .d(PTE), .q(RamRead), .PTE_G(PTE_Gs)); + or_rows #(TLB_ENTRIES, P.XLEN) PTEOr(RamRead, PageTableEntry); // Rename the bits read from the TLB RAM - assign PTEAccessBits = PageTableEntry[7:0]; + assign PTEAccessBits = {PageTableEntry[P.XLEN-1:P.XLEN-3], PageTableEntry[7:0]}; // include N and PBMT bits assign PPN = PageTableEntry[P.PPN_BITS+9:10]; endmodule diff --git a/src/privileged/csrs.sv b/src/privileged/csrs.sv index 95599e3a0..fa329f363 100644 --- a/src/privileged/csrs.sv +++ b/src/privileged/csrs.sv @@ -90,7 +90,7 @@ module csrs import cvw::*; #(parameter cvw_t P) ( assign WriteSTVALM = STrapM | (CSRSWriteM & (CSRAdrM == STVAL)); if(P.XLEN == 64) begin logic LegalSatpModeM; - assign LegalSatpModeM = P.VIRTMEM_SUPPORTED & (CSRWriteValM[63:60] == 0 | CSRWriteValM[63:60] == 8 | CSRWriteValM[63:60] == 9); // supports SV39 and 48 + assign LegalSatpModeM = P.VIRTMEM_SUPPORTED & (CSRWriteValM[63:60] == 0 | CSRWriteValM[63:60] == P.SV39 | CSRWriteValM[63:60] == P.SV48); // supports SV39 and 48 assign WriteSATPM = CSRSWriteM & (CSRAdrM == SATP) & (PrivilegeModeW == P.M_MODE | ~STATUS_TVM) & LegalSatpModeM; end else // RV32 assign WriteSATPM = CSRSWriteM & (CSRAdrM == SATP) & (PrivilegeModeW == P.M_MODE | ~STATUS_TVM) & P.VIRTMEM_SUPPORTED; diff --git a/testbench/common/riscvassertions.sv b/testbench/common/riscvassertions.sv index d1007ec41..a6cee910e 100644 --- a/testbench/common/riscvassertions.sv +++ b/testbench/common/riscvassertions.sv @@ -58,9 +58,11 @@ module riscvassertions import cvw::*; #(parameter cvw_t P); assert ((P.ZMMUL_SUPPORTED == 0) || (P.M_SUPPORTED ==0)) else $error("At most one of ZMMUL_SUPPORTED and M_SUPPORTED can be enabled"); assert ((P.ZICNTR_SUPPORTED == 0) || (P.ZICSR_SUPPORTED == 1)) else $error("ZICNTR_SUPPORTED requires ZICSR_SUPPORTED"); assert ((P.ZIHPM_SUPPORTED == 0) || (P.ZICNTR_SUPPORTED == 1)) else $error("ZIPHM_SUPPORTED requires ZICNTR_SUPPORTED"); - assert ((P.ZICBOM_SUPPORTED == 0) || (P.DCACHE_SUPPORTED == 1)) else $error("ZICBOM required DCACHE_SUPPORTED"); - assert ((P.ZICBOZ_SUPPORTED == 0) || (P.DCACHE_SUPPORTED == 1)) else $error("ZICBOZ required DCACHE_SUPPORTED"); - assert ((P.ZICBOP_SUPPORTED == 0) || (P.DCACHE_SUPPORTED == 1)) else $error("ZICBOP required DCACHE_SUPPORTED"); + assert ((P.ZICBOM_SUPPORTED == 0) || (P.DCACHE_SUPPORTED == 1)) else $error("ZICBOM requires DCACHE_SUPPORTED"); + assert ((P.ZICBOZ_SUPPORTED == 0) || (P.DCACHE_SUPPORTED == 1)) else $error("ZICBOZ requires DCACHE_SUPPORTED"); + assert ((P.ZICBOP_SUPPORTED == 0) || (P.DCACHE_SUPPORTED == 1)) else $error("ZICBOP requires DCACHE_SUPPORTED"); + assert ((P.SVPBMT_SUPPORTED == 0) || (P.VIRTMEM_SUPPORTED == 1 && P.XLEN==64)) else $error("SVPBMT requires VIRTMEM_SUPPORTED and RV64"); + assert ((P.SVNAPOT_SUPPORTED == 0) || (P.VIRTMEM_SUPPORTED == 1 && P.XLEN==64)) else $error("SVNAPOT requires VIRTMEM_SUPPORTED and RV64"); end endmodule From bd6eef2a516d86d29f78a0ec0f6bea97f5ec42fe Mon Sep 17 00:00:00 2001 From: David Harris Date: Fri, 25 Aug 2023 18:33:08 -0700 Subject: [PATCH 06/11] Initial implementation of SVNAPOT and SVPBMT does not break regression --- src/ifu/ifu.sv | 3 +- src/lsu/lsu.sv | 3 +- src/mmu/mmu.sv | 11 ++++--- src/mmu/pmachecker.sv | 14 +++++--- src/mmu/tlb/tlb.sv | 30 +++++++++++------ src/mmu/tlb/tlbcam.sv | 5 +-- src/mmu/tlb/tlbcamline.sv | 7 ++-- src/mmu/tlb/tlbcontrol.sv | 33 ++++++++++++------- src/mmu/tlb/tlbmixer.sv | 57 ++++++++++++++++++++++++++------- src/mmu/tlb/tlbram.sv | 9 +++--- src/mmu/tlb/tlbramline.sv | 26 ++++++++++----- src/privileged/csr.sv | 2 +- src/privileged/privileged.sv | 3 +- src/wally/wallypipelinedcore.sv | 8 +++-- 14 files changed, 148 insertions(+), 63 deletions(-) diff --git a/src/ifu/ifu.sv b/src/ifu/ifu.sv index 2bceb6175..320b9e330 100644 --- a/src/ifu/ifu.sv +++ b/src/ifu/ifu.sv @@ -85,6 +85,7 @@ module ifu import cvw::*; #(parameter cvw_t P) ( input logic STATUS_SUM, // Status CSR: Supervisor access to user memory input logic STATUS_MPRV, // Status CSR: modify machine privilege input logic [1:0] STATUS_MPP, // Status CSR: previous machine privilege level + input logic ENVCFG_PBMTE, // Page-based memory types enabled input logic sfencevmaM, // Virtual memory address fence, invalidate TLB entries output logic ITLBMissF, // ITLB miss causes HPTW (hardware pagetable walker) walk output logic InstrUpdateDAF, // ITLB hit needs to update dirty or access bits @@ -170,7 +171,7 @@ module ifu import cvw::*; #(parameter cvw_t P) ( assign TLBFlush = sfencevmaM & ~StallMQ; mmu #(.P(P), .TLB_ENTRIES(P.ITLB_ENTRIES), .IMMU(1)) - immu(.clk, .reset, .SATP_REGW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, + immu(.clk, .reset, .SATP_REGW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .ENVCFG_PBMTE, .PrivilegeModeW, .DisableTranslation(1'b0), .VAdr(PCFExt), .Size(2'b10), diff --git a/src/lsu/lsu.sv b/src/lsu/lsu.sv index aeadec262..e120d454b 100644 --- a/src/lsu/lsu.sv +++ b/src/lsu/lsu.sv @@ -80,6 +80,7 @@ module lsu import cvw::*; #(parameter cvw_t P) ( input logic [P.XLEN-1:0] SATP_REGW, // SATP (supervisor address translation and protection) CSR input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, // STATUS CSR bits: make executable readable, supervisor user memory, machine privilege input logic [1:0] STATUS_MPP, // Machine previous privilege mode + input logic ENVCFG_PBMTE, // Page-based memory types enabled input logic [P.XLEN-1:0] PCSpillF, // Fetch PC input logic ITLBMissF, // ITLB miss causes HPTW (hardware pagetable walker) walk input logic InstrUpdateDAF, // ITLB hit needs to update dirty or access bits @@ -189,7 +190,7 @@ module lsu import cvw::*; #(parameter cvw_t P) ( assign DisableTranslation = SelHPTW | FlushDCacheM; assign WriteAccessM = PreLSURWM[0] | (|CMOpM); mmu #(.P(P), .TLB_ENTRIES(P.DTLB_ENTRIES), .IMMU(0)) - dmmu(.clk, .reset, .SATP_REGW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, + dmmu(.clk, .reset, .SATP_REGW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .ENVCFG_PBMTE, .PrivilegeModeW, .DisableTranslation, .VAdr(IHAdrM), .Size(LSUFunct3M[1:0]), .PTE, .PageTypeWriteVal(PageType), .TLBWrite(DTLBWriteM), .TLBFlush(sfencevmaM), .PhysicalAddress(PAdrM), .TLBMiss(DTLBMissM), .Cacheable(CacheableM), .Idempotent(), .SelTIM(SelDTIM), diff --git a/src/mmu/mmu.sv b/src/mmu/mmu.sv index f05073fcf..e8e06fde0 100644 --- a/src/mmu/mmu.sv +++ b/src/mmu/mmu.sv @@ -34,6 +34,7 @@ module mmu import cvw::*; #(parameter cvw_t P, input logic STATUS_SUM, // Status CSR: Supervisor access to user memory input logic STATUS_MPRV, // Status CSR: modify machine privilege input logic [1:0] STATUS_MPP, // Status CSR: previous machine privilege level + input logic ENVCFG_PBMTE, // Page-based memory types enabled input logic [1:0] PrivilegeModeW, // Current privilege level of the processeor input logic DisableTranslation, // virtual address translation disabled during D$ flush and HPTW walk that use physical addresses input logic [P.XLEN+1:0] VAdr, // virtual/physical address from IEU or physical address from HPTW @@ -70,6 +71,7 @@ module mmu import cvw::*; #(parameter cvw_t P, logic TLBHit; // Hit in TLB logic TLBPageFault; // Page fault from TLB logic ReadNoAmoAccessM; // Read that is not part of atomic operation causes Load faults. Otherwise StoreAmo faults + logic [1:0] PBMemoryType; // PBMT field of PTE during TLB hit, or 00 otherwise // only instantiate TLB if Virtual Memory is supported if (P.VIRTMEM_SUPPORTED) begin:tlb @@ -80,16 +82,17 @@ module mmu import cvw::*; #(parameter cvw_t P, .clk, .reset, .SATP_MODE(SATP_REGW[P.XLEN-1:P.XLEN-P.SVMODE_BITS]), .SATP_ASID(SATP_REGW[P.ASID_BASE+P.ASID_BITS-1:P.ASID_BASE]), - .VAdr(VAdr[P.XLEN-1:0]), .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, + .VAdr(VAdr[P.XLEN-1:0]), .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .ENVCFG_PBMTE, .PrivilegeModeW, .ReadAccess, .WriteAccess, .DisableTranslation, .PTE, .PageTypeWriteVal, .TLBWrite, .TLBFlush, .TLBPAdr, .TLBMiss, .TLBHit, - .Translate, .TLBPageFault, .UpdateDA); + .Translate, .TLBPageFault, .UpdateDA, .PBMemoryType); end else begin:tlb // just pass address through as physical assign Translate = 0; assign TLBMiss = 0; assign TLBHit = 1; // *** is this necessary assign TLBPageFault = 0; + assign PBMemoryType = 2'b00; end // If translation is occuring, select translated physical address from TLB @@ -103,8 +106,8 @@ module mmu import cvw::*; #(parameter cvw_t P, /////////////////////////////////////////// pmachecker #(P) pmachecker(.PhysicalAddress, .Size, - .AtomicAccessM, .ExecuteAccessF, .WriteAccessM, .ReadAccessM, - .Cacheable, .Idempotent, .SelTIM, + .AtomicAccessM, .ExecuteAccessF, .WriteAccessM, .ReadAccessM, .PBMemoryType, + .Cacheable, .Idempotent, .SelTIM, .PMAInstrAccessFaultF, .PMALoadAccessFaultM, .PMAStoreAmoAccessFaultM); if (P.PMP_ENTRIES > 0) begin : pmp diff --git a/src/mmu/pmachecker.sv b/src/mmu/pmachecker.sv index 41d8f9b74..ce129af51 100644 --- a/src/mmu/pmachecker.sv +++ b/src/mmu/pmachecker.sv @@ -35,6 +35,7 @@ module pmachecker import cvw::*; #(parameter cvw_t P) ( input logic ExecuteAccessF, // Execute access input logic WriteAccessM, // Write access input logic ReadAccessM, // Read access + input logic [1:0] PBMemoryType, // PBMT field of PTE during TLB hit, or 00 otherwise output logic Cacheable, Idempotent, SelTIM, output logic PMAInstrAccessFaultF, output logic PMALoadAccessFaultM, @@ -45,6 +46,7 @@ module pmachecker import cvw::*; #(parameter cvw_t P) ( logic AccessRW, AccessRWX, AccessRX; logic [10:0] SelRegions; logic AtomicAllowed; + logic CacheableRegion, IdempotentRegion; // Determine what type of access is being made assign AccessRW = ReadAccessM | WriteAccessM; @@ -54,11 +56,15 @@ module pmachecker import cvw::*; #(parameter cvw_t P) ( // Determine which region of physical memory (if any) is being accessed adrdecs #(P) adrdecs(PhysicalAddress, AccessRW, AccessRX, AccessRWX, Size, SelRegions); - // Only non-core RAM/ROM memory regions are cacheable - assign Cacheable = SelRegions[8] | SelRegions[7] | SelRegions[6]; // exclusion-tag: unused-cachable + // Only non-core RAM/ROM memory regions are cacheable. PBMT can override cachable; NC and IO are uncachable + assign CacheableRegion = SelRegions[8] | SelRegions[7] | SelRegions[6]; + assign Cacheable = (PBMemoryType == 2'b00) ? CacheableRegion : 0; // exclusion-tag: unused-cachable + // Nonidemdempotent means access could have side effect and must not be done speculatively or redundantly - // I/O is nonidempotent. - assign Idempotent = SelRegions[10] | SelRegions[9] | SelRegions[8] | SelRegions[7] | SelRegions[6]; // exclusion-tag: unused-idempotent + // I/O is nonidempotent. PBMT can override PMA; NC is idempotent and IO is non-idempotent + assign IdempotentRegion = SelRegions[10] | SelRegions[9] | SelRegions[8] | SelRegions[7] | SelRegions[6]; + assign Idempotent = (PBMemoryType == 2'b00) ? IdempotentRegion : (PBMemoryType == 2'b01); // exclusion-tag: unused-idempotent + // Atomic operations are only allowed on RAM assign AtomicAllowed = SelRegions[10] | SelRegions[8] | SelRegions[6]; // exclusion-tag: unused-atomic // Check if tightly integrated memories are selected diff --git a/src/mmu/tlb/tlb.sv b/src/mmu/tlb/tlb.sv index c0468aede..497a97fe5 100644 --- a/src/mmu/tlb/tlb.sv +++ b/src/mmu/tlb/tlb.sv @@ -57,12 +57,13 @@ module tlb import cvw::*; #(parameter cvw_t P, input logic [P.ASID_BITS-1:0] SATP_ASID, input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, input logic [1:0] STATUS_MPP, + input logic ENVCFG_PBMTE, // Page-based memory types enabled input logic [1:0] PrivilegeModeW, // Current privilege level of the processeor input logic ReadAccess, input logic WriteAccess, input logic DisableTranslation, input logic [P.XLEN-1:0] VAdr, // address input before translation (could be physical or virtual) - input logic [P.XLEN-1:0] PTE, + input logic [P.XLEN-1:0] PTE, // page table entry to write input logic [1:0] PageTypeWriteVal, input logic TLBWrite, input logic TLBFlush, @@ -71,10 +72,11 @@ module tlb import cvw::*; #(parameter cvw_t P, output logic TLBHit, output logic Translate, output logic TLBPageFault, - output logic UpdateDA + output logic UpdateDA, + output logic [1:0] PBMemoryType // PBMT field of PTE during TLB hit, or 00 otherwise ); - logic [TLB_ENTRIES-1:0] Matches, WriteEnables, PTE_Gs; // used as the one-hot encoding of WriteIndex + logic [TLB_ENTRIES-1:0] Matches, WriteEnables, PTE_Gs, PTE_NAPOTs; // used as the one-hot encoding of WriteIndex // Sections of the virtual and physical addresses logic [P.VPN_BITS-1:0] VPN; logic [P.PPN_BITS-1:0] PPN; @@ -84,7 +86,9 @@ module tlb import cvw::*; #(parameter cvw_t P, logic CAMHit; logic SV39Mode; logic Misaligned; + logic BadPTEWrite; // trying to write malformed PTE logic MegapageMisaligned; + logic PTE_N; // NAPOT page table entry if(P.XLEN == 32) begin assign MegapageMisaligned = |(PPN[9:0]); // must have zero PPN0 @@ -101,20 +105,28 @@ module tlb import cvw::*; #(parameter cvw_t P, assign VPN = VAdr[P.VPN_BITS+11:12]; - tlbcontrol #(P, ITLB) tlbcontrol(.SATP_MODE, .VAdr, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, + // check if reserved, N, or PBMT bits are malformed when PTE is written in RV64 + assign BadPTEWrite = (P.XLEN == 64) & TLBWrite & ( + PTE[P.XLEN-1] & ~P.SVNAPOT_SUPPORTED | // N must be 0 if SVNAPOT is not supported + PTE[P.XLEN-2:P.XLEN-3] != 0 & ~P.SVPBMT_SUPPORTED | // PBMT must be 0 if SVBPMT is not supported + PTE[P.XLEN-2:P.XLEN-3] == 3 | // PBMT of 3 is reserved and never legal + PTE[P.XLEN-4:P.XLEN-10] != 0 ); // Reserved bits must be 0 + + tlbcontrol #(P, ITLB) tlbcontrol(.SATP_MODE, .VAdr, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .ENVCFG_PBMTE, .PrivilegeModeW, .ReadAccess, .WriteAccess, .DisableTranslation, .TLBFlush, - .PTEAccessBits, .CAMHit, .Misaligned, .TLBMiss, .TLBHit, .TLBPageFault, - .UpdateDA, .SV39Mode, .Translate); + .PTEAccessBits, .CAMHit, .Misaligned, .BadPTEWrite, + .TLBMiss, .TLBHit, .TLBPageFault, + .UpdateDA, .SV39Mode, .Translate, .PTE_N, .PBMemoryType); tlblru #(TLB_ENTRIES) lru(.clk, .reset, .TLBWrite, .TLBFlush, .Matches, .CAMHit, .WriteEnables); tlbcam #(P, TLB_ENTRIES, P.VPN_BITS + P.ASID_BITS, P.VPN_SEGMENT_BITS) - tlbcam(.clk, .reset, .VPN, .PageTypeWriteVal, .SV39Mode, .TLBFlush, .WriteEnables, .PTE_Gs, + tlbcam(.clk, .reset, .VPN, .PageTypeWriteVal, .SV39Mode, .TLBFlush, .WriteEnables, .PTE_Gs, .PTE_NAPOTs, .SATP_ASID, .Matches, .HitPageType, .CAMHit); - tlbram #(P, TLB_ENTRIES) tlbram(.clk, .reset, .PTE, .Matches, .WriteEnables, .PPN, .PTEAccessBits, .PTE_Gs); + tlbram #(P, TLB_ENTRIES) tlbram(.clk, .reset, .PTE, .Matches, .WriteEnables, .PPN, .PTEAccessBits, .PTE_Gs, .PTE_NAPOTs); // Replace segments of the virtual page number with segments of the physical // page number. For 4 KB pages, the entire virtual page number is replaced. // For superpages, some segments are considered offsets into a larger page. - tlbmixer #(P) Mixer(.VPN, .PPN, .HitPageType, .Offset(VAdr[11:0]), .TLBHit, .TLBPAdr); + tlbmixer #(P) Mixer(.VPN, .PPN, .HitPageType, .Offset(VAdr[11:0]), .TLBHit, .PTE_N, .TLBPAdr); endmodule diff --git a/src/mmu/tlb/tlbcam.sv b/src/mmu/tlb/tlbcam.sv index 7a4100829..e591498c4 100644 --- a/src/mmu/tlb/tlbcam.sv +++ b/src/mmu/tlb/tlbcam.sv @@ -38,7 +38,8 @@ module tlbcam import cvw::*; #(parameter cvw_t P, input logic TLBFlush, input logic [TLB_ENTRIES-1:0] WriteEnables, input logic [TLB_ENTRIES-1:0] PTE_Gs, - input logic [P.ASID_BITS-1:0] SATP_ASID, + input logic [TLB_ENTRIES-1:0] PTE_NAPOTs, // entry is in NAPOT mode (N bit set and PPN[3:0] = 1000) + input logic [P.ASID_BITS-1:0] SATP_ASID, output logic [TLB_ENTRIES-1:0] Matches, output logic [1:0] HitPageType, output logic CAMHit @@ -53,7 +54,7 @@ module tlbcam import cvw::*; #(parameter cvw_t P, // page number segments. tlbcamline #(P, KEY_BITS, SEGMENT_BITS) camlines[TLB_ENTRIES-1:0]( - .clk, .reset, .VPN, .SATP_ASID, .SV39Mode, .PTE_G(PTE_Gs), .PageTypeWriteVal, .TLBFlush, + .clk, .reset, .VPN, .SATP_ASID, .SV39Mode, .PTE_G(PTE_Gs), .PTE_NAPOT(PTE_NAPOTs), .PageTypeWriteVal, .TLBFlush, .WriteEnable(WriteEnables), .PageTypeRead, .Match(Matches)); assign CAMHit = |Matches & ~TLBFlush; or_rows #(TLB_ENTRIES,2) PageTypeOr(PageTypeRead, HitPageType); diff --git a/src/mmu/tlb/tlbcamline.sv b/src/mmu/tlb/tlbcamline.sv index 55023006f..9471fb3d9 100644 --- a/src/mmu/tlb/tlbcamline.sv +++ b/src/mmu/tlb/tlbcamline.sv @@ -37,6 +37,7 @@ module tlbcamline import cvw::*; #(parameter cvw_t P, input logic SV39Mode, input logic WriteEnable, // Write a new entry to this line input logic PTE_G, + input logic PTE_NAPOT, // entry is in NAPOT mode (N bit set and PPN[3:0] = 1000) input logic [1:0] PageTypeWriteVal, input logic TLBFlush, // Flush this line (set valid to 0) output logic [1:0] PageTypeRead, // *** should this be the stored version or the always updated one? @@ -76,7 +77,7 @@ module tlbcamline import cvw::*; #(parameter cvw_t P, end else begin: match logic [SEGMENT_BITS-1:0] Key2, Key3, Query2, Query3; - logic Match2, Match3; + logic Match2, Match3, MatchNAPOT; assign {Query3, Query2, Query1, Query0} = VPN; assign {Key_ASID, Key3, Key2, Key1, Key0} = Key; @@ -84,7 +85,9 @@ module tlbcamline import cvw::*; #(parameter cvw_t P, // Calculate the actual match value based on the input vpn and the page type. // For example, a gigapage in SV39 only cares about VPN[2], so VPN[0] and VPN[1] // should automatically match. - assign Match0 = (Query0 == Key0) | (PageType > 2'd0); // least signifcant section + // In Svnapot, if N bit is set and bottom 4 bits of PPN = 1000, then these bits don't need to match + assign MatchNAPOT = P.SVNAPOT_SUPPORTED & PTE_NAPOT & (Query0[SEGMENT_BITS-1:4] == Key0[SEGMENT_BITS-1:4]); + assign Match0 = (Query0 == Key0) | (PageType > 2'd0) | MatchNAPOT; // least significant section assign Match1 = (Query1 == Key1) | (PageType > 2'd1); assign Match2 = (Query2 == Key2) | (PageType > 2'd2); assign Match3 = (Query3 == Key3) | SV39Mode; // this should always match in sv39 because they aren't used diff --git a/src/mmu/tlb/tlbcontrol.sv b/src/mmu/tlb/tlbcontrol.sv index f996ce55d..bfd8a9251 100644 --- a/src/mmu/tlb/tlbcontrol.sv +++ b/src/mmu/tlb/tlbcontrol.sv @@ -31,6 +31,7 @@ module tlbcontrol import cvw::*; #(parameter cvw_t P, ITLB = 0) ( input logic [P.XLEN-1:0] VAdr, input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, input logic [1:0] STATUS_MPP, + input logic ENVCFG_PBMTE, // Page-based memory types enabled input logic [1:0] PrivilegeModeW, // Current privilege level of the processeor input logic ReadAccess, WriteAccess, input logic DisableTranslation, @@ -38,22 +39,27 @@ module tlbcontrol import cvw::*; #(parameter cvw_t P, ITLB = 0) ( input logic [10:0] PTEAccessBits, input logic CAMHit, input logic Misaligned, + input logic BadPTEWrite, // trying to write malformed PTE output logic TLBMiss, output logic TLBHit, output logic TLBPageFault, output logic UpdateDA, output logic SV39Mode, - output logic Translate + output logic Translate, + output logic PTE_N, // NAPOT page table entry + output logic [1:0] PBMemoryType // PBMT field of PTE during TLB hit, or 00 otherwise ); // Sections of the page table entry logic [1:0] EffectivePrivilegeMode; - logic PTE_N, PTE_D, PTE_A, PTE_U, PTE_X, PTE_W, PTE_R, PTE_V; // Useful PTE Control Bits + logic PTE_D, PTE_A, PTE_U, PTE_X, PTE_W, PTE_R, PTE_V; // Useful PTE Control Bits logic [1:0] PTE_PBMT; logic UpperBitsUnequal; logic TLBAccess; logic ImproperPrivilege; + logic BadPBMT; + logic CausePageFault; // Grab the sv mode from SATP and determine whether translation should occur assign EffectivePrivilegeMode = (ITLB == 1) ? PrivilegeModeW : (STATUS_MPRV ? STATUS_MPP : PrivilegeModeW); // DTLB uses MPP mode when MPRV is 1 @@ -66,10 +72,16 @@ module tlbcontrol import cvw::*; #(parameter cvw_t P, ITLB = 0) ( vm64check #(P) vm64check(.SATP_MODE, .VAdr, .SV39Mode, .UpperBitsUnequal); // unswizzle useful PTE bits - assign PTE_N = PTEAccessBits[10] & P.SVNAPOT_SUPPORTED; - assign PTE_PBMT = PTEAccessBits[9:8] & {2{P.SVPBMT_SUPPORTED}}; + assign PTE_N = PTEAccessBits[10]; + assign PTE_PBMT = PTEAccessBits[9:8]; assign {PTE_D, PTE_A} = PTEAccessBits[7:6]; assign {PTE_U, PTE_X, PTE_W, PTE_R, PTE_V} = PTEAccessBits[4:0]; + + // Page fault if PBMT is nonzero when SVPBMT is not supported and enabled + assign BadPBMT = PTE_PBMT != 0 & ~(P.SVPBMT_SUPPORTED & ENVCFG_PBMTE); + + // Send PMA a 2-bit MemoryType that is PBMT during leaf page table accesses and 0 otherwise + assign PBMemoryType = PTE_PBMT & {2{Translate & TLBHit & P.SVPBMT_SUPPORTED}}; // Check whether the access is allowed, page faulting if not. if (ITLB == 1) begin:itlb // Instruction TLB fault checking @@ -77,14 +89,11 @@ module tlbcontrol import cvw::*; #(parameter cvw_t P, ITLB = 0) ( // only execute non-user mode pages. assign ImproperPrivilege = ((EffectivePrivilegeMode == P.U_MODE) & ~PTE_U) | ((EffectivePrivilegeMode == P.S_MODE) & PTE_U); - if(P.SVADU_SUPPORTED) begin : hptwwrites - assign UpdateDA = Translate & TLBHit & ~PTE_A & ~TLBPageFault; - assign TLBPageFault = Translate & TLBHit & (ImproperPrivilege | ~PTE_X | UpperBitsUnequal | Misaligned | ~PTE_V); - end else begin - // fault for software handling if access bit is off - assign UpdateDA = ~PTE_A; - assign TLBPageFault = Translate & TLBHit & (ImproperPrivilege | ~PTE_X | UpdateDA | UpperBitsUnequal | Misaligned | ~PTE_V); - end + assign CausePageFault = ImproperPrivilege | ~PTE_X | UpperBitsUnequal | BadPTEWrite | BadPBMT | Misaligned | ~PTE_V | (~PTE_A & P.SVADU_SUPPORTED); + assign TLBPageFault = Translate & TLBHit & CausePageFault; + // Determine wheter to update DA bits + if(P.SVADU_SUPPORTED) assign UpdateDA = Translate & TLBHit & ~PTE_A & ~TLBPageFault; + else assign UpdateDA = ~PTE_A; end else begin:dtlb // Data TLB fault checking logic InvalidRead, InvalidWrite; diff --git a/src/mmu/tlb/tlbmixer.sv b/src/mmu/tlb/tlbmixer.sv index 07d6eb985..a19d5a2eb 100644 --- a/src/mmu/tlb/tlbmixer.sv +++ b/src/mmu/tlb/tlbmixer.sv @@ -30,18 +30,19 @@ //////////////////////////////////////////////////////////////////////////////////////////////// module tlbmixer import cvw::*; #(parameter cvw_t P) ( - input logic [P.VPN_BITS-1:0] VPN, - input logic [P.PPN_BITS-1:0] PPN, - input logic [1:0] HitPageType, - input logic [11:0] Offset, - input logic TLBHit, - output logic [P.PA_BITS-1:0] TLBPAdr + input logic [P.VPN_BITS-1:0] VPN, + input logic [P.PPN_BITS-1:0] PPN, + input logic [1:0] HitPageType, + input logic [11:0] Offset, + input logic TLBHit, + input logic PTE_N, // NAPOT page table entry + output logic [P.PA_BITS-1:0] TLBPAdr ); localparam EXTRA_BITS = P.PPN_BITS - P.VPN_BITS; logic [P.PPN_BITS-1:0] ZeroExtendedVPN; logic [P.PPN_BITS-1:0] PageNumberMask; - logic [P.PPN_BITS-1:0] PPNMixed; + logic [P.PPN_BITS-1:0] PPNMixed, PPNMixed2; // produce PageNumberMask with 1s where virtual page number bits should be untranslaetd for superpages if (P.XLEN == 32) @@ -57,11 +58,45 @@ module tlbmixer import cvw::*; #(parameter cvw_t P) ( // merge low segments of VPN with high segments of PPN decided by the pagetype. assign ZeroExtendedVPN = {{EXTRA_BITS{1'b0}}, VPN}; // forces the VPN to be the same width as PPN. - assign PPNMixed = PPN | ZeroExtendedVPN & PageNumberMask; // - //mux2 #(1) mixmux[P.PPN_BITS-1:0](ZeroExtendedVPN, PPN, PageNumberMask, PPNMixed); - //assign PPNMixed = (ZeroExtendedVPN & ~PageNumberMask) | (PPN & PageNumberMask); + assign PPNMixed = PPN | ZeroExtendedVPN & PageNumberMask; // low bits of PPN are already zero + + // In Svnapot, when N=1, use bottom bits of VPN for contiugous translations + if (P.SVNAPOT_SUPPORTED) begin + // 64 KiB contiguous NAPOT translations suported + logic [3:0] PPNMixedBot; + mux2 #(4) napotmux(PPNMixed[3:0], VPN, PTE_N, PPNMixedBot); + assign PPNMixed2 = {PPNMixed[P.PPN_BITS-1:4], PPNMixedBot}; + + /* // Generalized NAPOT implementation supporting various sized contiguous regions + // This would also require a priority encoder in the tlbcam + // Not yet tested + logic [8:0] NAPOTMask, NAPOTPN, PPNMixedBot; + always_comb begin + casez(PPN[8:0]) + 9'b100000000: NAPOTMask = 9'b111111111; + 9'b?10000000: NAPOTMask = 9'b011111111; + 9'b??1000000: NAPOTMask = 9'b001111111; + 9'b???100000: NAPOTMask = 9'b000111111; + 9'b????10000: NAPOTMask = 9'b000011111; + 9'b?????1000: NAPOTMask = 9'b000001111; + 9'b??????100: NAPOTMask = 9'b000000111; + 9'b???????10: NAPOTMask = 9'b000000011; + 9'b????????1: NAPOTMask = 9'b000000001; + default: NAPOTMask = 9'b000000000; + endcase + end + // check malformed NAPOT PPN, which should cause page fault + // Replace PPN with VPN in lower bits of page number based on mask + assign NAPOTPN = VPN & NAPOTMask | PPN & ~NAPOTMask; + mux2 #(9) napotmux(PPNMixed[8:0], NAPOTPN, PTE_N, PPNMixedBot); + assign PPNMixed2 = {PPNMixed[PPN_BITS-1:9], PPNMixedBot}; */ + + end else begin // no Svnapot + assign PPNMixed2 = PPNMixed; + end + // Output the hit physical address if translation is currently on. // Provide physical address of zero if not TLBHits, to cause segmentation error if miss somehow percolated through signal - mux2 #(P.PA_BITS) hitmux('0, {PPNMixed, Offset}, TLBHit, TLBPAdr); // set PA to 0 if TLB misses, to cause segementation error if this miss somehow passes through system + mux2 #(P.PA_BITS) hitmux('0, {PPNMixed2, Offset}, TLBHit, TLBPAdr); // set PA to 0 if TLB misses, to cause segementation error if this miss somehow passes through system endmodule diff --git a/src/mmu/tlb/tlbram.sv b/src/mmu/tlb/tlbram.sv index 50f6883b3..07d9dd87c 100644 --- a/src/mmu/tlb/tlbram.sv +++ b/src/mmu/tlb/tlbram.sv @@ -36,19 +36,20 @@ module tlbram import cvw::*; #(parameter cvw_t P, input logic [TLB_ENTRIES-1:0] Matches, WriteEnables, output logic [P.PPN_BITS-1:0] PPN, output logic [10:0] PTEAccessBits, - output logic [TLB_ENTRIES-1:0] PTE_Gs + output logic [TLB_ENTRIES-1:0] PTE_Gs, + output logic [TLB_ENTRIES-1:0] PTE_NAPOTs // entry is in NAPOT mode (N bit set and PPN[3:0] = 1000) ); logic [P.XLEN-1:0] RamRead[TLB_ENTRIES-1:0]; // stores the page table entries logic [P.XLEN-1:0] PageTableEntry; // RAM implemented with array of flops and AND/OR read logic - tlbramline #(P.XLEN) tlbramline[TLB_ENTRIES-1:0] + tlbramline #(P) tlbramline[TLB_ENTRIES-1:0] (.clk, .reset, .re(Matches), .we(WriteEnables), - .d(PTE), .q(RamRead), .PTE_G(PTE_Gs)); + .d(PTE), .q(RamRead), .PTE_G(PTE_Gs), .PTE_NAPOT(PTE_NAPOTs)); or_rows #(TLB_ENTRIES, P.XLEN) PTEOr(RamRead, PageTableEntry); // Rename the bits read from the TLB RAM - assign PTEAccessBits = {PageTableEntry[P.XLEN-1:P.XLEN-3], PageTableEntry[7:0]}; // include N and PBMT bits + assign PTEAccessBits = {PageTableEntry[P.XLEN-1:P.XLEN-3] & {3{P.XLEN == 64}}, PageTableEntry[7:0]}; // include N and PBMT bits assign PPN = PageTableEntry[P.PPN_BITS+9:10]; endmodule diff --git a/src/mmu/tlb/tlbramline.sv b/src/mmu/tlb/tlbramline.sv index cc393f72a..971e804ac 100644 --- a/src/mmu/tlb/tlbramline.sv +++ b/src/mmu/tlb/tlbramline.sv @@ -26,16 +26,26 @@ // and limitations under the License. //////////////////////////////////////////////////////////////////////////////////////////////// -module tlbramline #(parameter WIDTH = 22) - (input logic clk, reset, - input logic re, we, - input logic [WIDTH-1:0] d, - output logic [WIDTH-1:0] q, - output logic PTE_G); +module tlbramline import cvw::*; #(parameter cvw_t P) + (input logic clk, reset, + input logic re, we, + input logic [P.XLEN-1:0] d, + output logic [P.XLEN-1:0] q, + output logic PTE_G, + output logic PTE_NAPOT // entry is in NAPOT mode (N bit set and PPN[3:0] = 1000) +); - logic [WIDTH-1:0] line; + logic [P.XLEN-1:0] line; + + if (P.XLEN == 64) begin // save 7 reserved bits + // could optimize out N and PBMT from d[63:61] if they aren't supported + logic [56:0] ptereg; + flopenr #(57) pteflop(clk, reset, we, {d[63:61], d[53:0]}, ptereg); + assign line = {ptereg[56:54], 7'b0, ptereg[53:0]}; + end else // rv32 + flopenr #(P.XLEN) pteflop(clk, reset, we, d, line); - flopenr #(WIDTH) pteflop(clk, reset, we, d, line); assign q = re ? line : 0; assign PTE_G = line[5]; // send global bit to CAM as part of ASID matching + assign PTE_NAPOT = P.SVNAPOT_SUPPORTED & line[P.XLEN-1] & (line[13:10] == 4'b1000); // send NAPOT bit to CAM as part of matching lsbs of VPN endmodule diff --git a/src/privileged/csr.sv b/src/privileged/csr.sv index ccca40a00..f99ee28b1 100644 --- a/src/privileged/csr.sv +++ b/src/privileged/csr.sv @@ -85,6 +85,7 @@ module csr import cvw::*; #(parameter cvw_t P) ( output var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW[P.PMP_ENTRIES-1:0], output logic [2:0] FRM_REGW, output logic [3:0] ENVCFG_CBE, + output logic ENVCFG_PBMTE, // Page-based memory type enable // output logic [P.XLEN-1:0] CSRReadValW, // value read from CSR output logic [P.XLEN-1:0] UnalignedPCNextF, // Next PC, accounting for traps and returns @@ -127,7 +128,6 @@ module csr import cvw::*; #(parameter cvw_t P) ( logic [63:0] MENVCFG_REGW; logic [P.XLEN-1:0] SENVCFG_REGW; logic ENVCFG_STCE; // supervisor timer counter enable - logic ENVCFG_PBMTE; // page-based memory types enable logic ENVCFG_FIOM; // fence implies io (presently not used) // only valid unflushed instructions can access CSRs diff --git a/src/privileged/privileged.sv b/src/privileged/privileged.sv index 46c69f17d..619ed2b32 100644 --- a/src/privileged/privileged.sv +++ b/src/privileged/privileged.sv @@ -83,6 +83,7 @@ module privileged import cvw::*; #(parameter cvw_t P) ( output var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW [P.PMP_ENTRIES-1:0], // PMP address entries to MMU output logic [2:0] FRM_REGW, // FPU rounding mode output logic [3:0] ENVCFG_CBE, // Cache block operation enables + output logic ENVCFG_PBMTE, // Page-based memory type enable // PC logic output in privileged unit output logic [P.XLEN-1:0] UnalignedPCNextF, // Next PC from trap/return PC logic // control outputs @@ -137,7 +138,7 @@ module privileged import cvw::*; #(parameter cvw_t P) ( .STATUS_MIE, .STATUS_SIE, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_TW, .STATUS_FS, .MEDELEG_REGW, .MIP_REGW, .MIE_REGW, .MIDELEG_REGW, .SATP_REGW, .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW, - .SetFflagsM, .FRM_REGW, .ENVCFG_CBE, + .SetFflagsM, .FRM_REGW, .ENVCFG_CBE, .ENVCFG_PBMTE, .CSRReadValW,.UnalignedPCNextF, .IllegalCSRAccessM, .BigEndianM); // pipeline early-arriving trap sources diff --git a/src/wally/wallypipelinedcore.sv b/src/wally/wallypipelinedcore.sv index 793ea5777..5fbc89a26 100644 --- a/src/wally/wallypipelinedcore.sv +++ b/src/wally/wallypipelinedcore.sv @@ -78,6 +78,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) ( logic LoadStallD, StoreStallD, MDUStallD, CSRRdStallD; logic SquashSCW; logic MDUActiveE; // Mul/Div instruction being executed + logic ENVCFG_PBMTE; // Page-based memory type enable logic [3:0] ENVCFG_CBE; // Cache Block operation enables logic [3:0] CMOpM; // 1: cbo.inval; 2: cbo.flush; 4: cbo.clean; 8: cbo.zero logic IFUPrefetchE, LSUPrefetchM; // instruction / data prefetch hints @@ -184,7 +185,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) ( .IllegalBaseInstrD, .IllegalFPUInstrD, .InstrPageFaultF, .IllegalIEUFPUInstrD, .InstrMisalignedFaultM, // mmu management .PrivilegeModeW, .PTE, .PageType, .SATP_REGW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, - .STATUS_MPP, .ITLBWriteF, .sfencevmaM, .ITLBMissF, + .STATUS_MPP, .ENVCFG_PBMTE, .ITLBWriteF, .sfencevmaM, .ITLBMissF, // pmp/pma (inside mmu) signals. .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW, .InstrAccessFaultF, .InstrUpdateDAF); @@ -231,7 +232,8 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) ( .STATUS_MXR, // from csr .STATUS_SUM, // from csr .STATUS_MPRV, // from csr - .STATUS_MPP, // from csr + .STATUS_MPP, // from csr + .ENVCFG_PBMTE, // from csr .sfencevmaM, // connects to privilege .DCacheStallM, // connects to privilege .LoadPageFaultM, // connects to privilege @@ -294,7 +296,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) ( .PrivilegeModeW, .SATP_REGW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .STATUS_FS, .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW, - .FRM_REGW, .ENVCFG_CBE, .BreakpointFaultM, .EcallFaultM, .wfiM, .IntPendingM, .BigEndianM); + .FRM_REGW, .ENVCFG_CBE, .ENVCFG_PBMTE, .BreakpointFaultM, .EcallFaultM, .wfiM, .IntPendingM, .BigEndianM); end else begin assign CSRReadValW = 0; assign UnalignedPCNextF = PC2NextF; From f7b50f4721e95f5a677416bcc4c4a10b3e310906 Mon Sep 17 00:00:00 2001 From: David Harris Date: Fri, 25 Aug 2023 18:41:03 -0700 Subject: [PATCH 07/11] Preparing to merge with CBO* changes --- config/buildroot/config.vh | 12 ++++++------ config/fpga/config.vh | 12 ++++++------ config/rv64gc/config.vh | 8 ++++---- src/ieu/controller.sv | 4 +++- src/mmu/tlb/tlbmixer.sv | 2 +- 5 files changed, 20 insertions(+), 18 deletions(-) diff --git a/config/buildroot/config.vh b/config/buildroot/config.vh index b8d9608f1..38960c735 100644 --- a/config/buildroot/config.vh +++ b/config/buildroot/config.vh @@ -42,12 +42,12 @@ localparam ZICNTR_SUPPORTED = 1; localparam ZIHPM_SUPPORTED = 1; localparam COUNTERS = 12'd32; localparam ZFH_SUPPORTED = 0; -localparam SSTC_SUPPORTED = 0; -localparam ZICBOM_SUPPORTED = 0; -localparam ZICBOZ_SUPPORTED = 0; -localparam ZICBOP_SUPPORTED = 0; -localparam SVPBMT_SUPPORTED = 0; -localparam SVNAPOT_SUPPORTED = 0; +localparam SSTC_SUPPORTED = 1; +localparam ZICBOM_SUPPORTED = 1; +localparam ZICBOZ_SUPPORTED = 1; +localparam ZICBOP_SUPPORTED = 1; +localparam SVPBMT_SUPPORTED = 1; +localparam SVNAPOT_SUPPORTED = 1; localparam SVINVAL_SUPPORTED = 1; // LSU microarchitectural Features diff --git a/config/fpga/config.vh b/config/fpga/config.vh index bd08cd11d..7e582fabb 100644 --- a/config/fpga/config.vh +++ b/config/fpga/config.vh @@ -44,12 +44,12 @@ localparam COUNTERS = 12'd32; localparam ZICNTR_SUPPORTED = 1; localparam ZIHPM_SUPPORTED = 1; localparam ZFH_SUPPORTED = 0; -localparam SSTC_SUPPORTED = 0; -localparam ZICBOM_SUPPORTED = 0; -localparam ZICBOZ_SUPPORTED = 0; -localparam ZICBOP_SUPPORTED = 0; -localparam SVPBMT_SUPPORTED = 0; -localparam SVNAPOT_SUPPORTED = 0; +localparam SSTC_SUPPORTED = 1; +localparam ZICBOM_SUPPORTED = 1; +localparam ZICBOZ_SUPPORTED = 1; +localparam ZICBOP_SUPPORTED = 1; +localparam SVPBMT_SUPPORTED = 1; +localparam SVNAPOT_SUPPORTED = 1; localparam SVINVAL_SUPPORTED = 1; // LSU microarchitectural Features diff --git a/config/rv64gc/config.vh b/config/rv64gc/config.vh index bd4e2f050..16e50b899 100644 --- a/config/rv64gc/config.vh +++ b/config/rv64gc/config.vh @@ -48,10 +48,10 @@ localparam ZIHPM_SUPPORTED = 1; localparam ZFH_SUPPORTED = 0; localparam SSTC_SUPPORTED = 1; localparam ZICBOM_SUPPORTED = 1; -localparam ZICBOZ_SUPPORTED = 0; -localparam ZICBOP_SUPPORTED = 0; -localparam SVPBMT_SUPPORTED = 0; -localparam SVNAPOT_SUPPORTED = 0; +localparam ZICBOZ_SUPPORTED = 1; +localparam ZICBOP_SUPPORTED = 1; +localparam SVPBMT_SUPPORTED = 1; +localparam SVNAPOT_SUPPORTED = 1; localparam SVINVAL_SUPPORTED = 1; // LSU microarchitectural Features diff --git a/src/ieu/controller.sv b/src/ieu/controller.sv index ecb1e6076..e923f1e3f 100644 --- a/src/ieu/controller.sv +++ b/src/ieu/controller.sv @@ -375,12 +375,14 @@ module controller import cvw::*; #(parameter cvw_t P) ( LSUPrefetchD = 1'b0; ImmSrcD = PreImmSrcD; if (P.ZICBOP_SUPPORTED & (InstrD[14:0] == 15'b110_00000_0010011)) begin // ori with destiation x0 is hint for Prefetch - case (Rs2D) // which type of prefectch? Note: prefetch.r and .w are handled the same in Wally + /* verilator lint_off CASEINCOMPLETE */ + case (Rs2D) // which type of prefectch? Note: prefetch.r and .w are handled the same in Wally 5'b00000: IFUPrefetchD = 1'b1; // prefetch.i 5'b00001: LSUPrefetchD = 1'b1; // prefetch.r 5'b00011: LSUPrefetchD = 1'b1; // prefetch.w // default: not a prefetch hint endcase + /* verilator lint_on CASEINCOMPLETE */ if (IFUPrefetchD | LSUPrefetchD) ImmSrcD = 3'b001; // use S-type immediate format for prefetches end end diff --git a/src/mmu/tlb/tlbmixer.sv b/src/mmu/tlb/tlbmixer.sv index a19d5a2eb..9652e21ef 100644 --- a/src/mmu/tlb/tlbmixer.sv +++ b/src/mmu/tlb/tlbmixer.sv @@ -64,7 +64,7 @@ module tlbmixer import cvw::*; #(parameter cvw_t P) ( if (P.SVNAPOT_SUPPORTED) begin // 64 KiB contiguous NAPOT translations suported logic [3:0] PPNMixedBot; - mux2 #(4) napotmux(PPNMixed[3:0], VPN, PTE_N, PPNMixedBot); + mux2 #(4) napotmux(PPNMixed[3:0], VPN[3:0], PTE_N, PPNMixedBot); assign PPNMixed2 = {PPNMixed[P.PPN_BITS-1:4], PPNMixedBot}; /* // Generalized NAPOT implementation supporting various sized contiguous regions From dabd15e029d2f3c6bac86fe2acc9caf04009c804 Mon Sep 17 00:00:00 2001 From: Kevin Kim Date: Sat, 26 Aug 2023 21:11:21 -0700 Subject: [PATCH 08/11] synth works --- config/shared/parameter-defs.vh | 2 +- src/wrappers/wallypipelinedcorewrapper.sv | 56 +++++++++++++++++++++++ synthDC/scripts/synth.tcl | 5 +- 3 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 src/wrappers/wallypipelinedcorewrapper.sv diff --git a/config/shared/parameter-defs.vh b/config/shared/parameter-defs.vh index f63028a92..340668466 100644 --- a/config/shared/parameter-defs.vh +++ b/config/shared/parameter-defs.vh @@ -3,7 +3,7 @@ `include "BranchPredictorType.vh" -parameter cvw_t P = '{ +localparam cvw_t P = '{ FPGA : FPGA, XLEN : XLEN, IEEE754 : IEEE754, diff --git a/src/wrappers/wallypipelinedcorewrapper.sv b/src/wrappers/wallypipelinedcorewrapper.sv new file mode 100644 index 000000000..09309bf0e --- /dev/null +++ b/src/wrappers/wallypipelinedcorewrapper.sv @@ -0,0 +1,56 @@ +/////////////////////////////////////////// +// wallypipelinedcorewrapper.sv +// +// Written: Kevin Kim kekim@hmc.edu 21 August 2023 +// Modified: +// +// Purpose: A wrapper to set parameters. Vivado cannot set the top level parameters because it only supports verilog, +// not system verilog. +// +// A component of the Wally configurable RISC-V project. +// +// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University +// +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 +// +// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file +// except in compliance with the License, or, at your option, the Apache License version 2.0. You +// may obtain a copy of the License at +// +// https://solderpad.org/licenses/SHL-2.1/ +// +// Unless required by applicable law or agreed to in writing, any work distributed under the +// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, +// either express or implied. See the License for the specific language governing permissions +// and limitations under the License. +//////////////////////////////////////////////////////////////////////////////////////////////// + +//`include "BranchPredictorType.vh" +`include "config.vh" + +import cvw::*; + +`include "parameter-defs.vh" +module wallypipelinedcorewrapper ( + input logic clk, reset, + // Privileged + input logic MTimerInt, MExtInt, SExtInt, MSwInt, + input logic [63:0] MTIME_CLINT, + // Bus Interface + input logic [P.XLEN-1:0] HRDATA, + input logic HREADY, HRESP, + output logic HCLK, HRESETn, + output logic [P.PA_BITS-1:0] HADDR, + output logic [32-1:0] HWDATA, + output logic [32/8-1:0] HWSTRB, + output logic HWRITE, + output logic [2:0] HSIZE, + output logic [2:0] HBURST, + output logic [3:0] HPROT, + output logic [1:0] HTRANS, + output logic HMASTLOCK +); + + wallypipelinedcore #(P) core(.*); + +endmodule diff --git a/synthDC/scripts/synth.tcl b/synthDC/scripts/synth.tcl index 7a8c2e7bf..e75557874 100755 --- a/synthDC/scripts/synth.tcl +++ b/synthDC/scripts/synth.tcl @@ -24,10 +24,9 @@ set saifpower $::env(SAIFPOWER) set maxopt $::env(MAXOPT) set drive $::env(DRIVE) -eval file copy -force [glob ${cfg}/*.vh] {$outputDir/hdl/} eval file copy -force [glob ${cfg}/*.vh] {$outputDir/hdl/} eval file copy -force [glob ${hdl_src}/cvw.sv] {$outputDir/hdl/} -eval file copy -force [glob ${hdl_src}/../fpga/src/wallypipelinedsocwrapper.sv] {$outputDir/hdl/} +#eval file copy -force [glob ${hdl_src}/../fpga/src/wallypipelinedsocwrapper.sv] {$outputDir/hdl/} eval file copy -force [glob ${hdl_src}/*/*.sv] {$outputDir/hdl/} eval file copy -force [glob ${hdl_src}/*/*/*.sv] {$outputDir/hdl/} @@ -76,7 +75,7 @@ if { [shell_is_in_topographical_mode] } { #set alib_library_analysis_path ./$outputDir define_design_lib WORK -path ./$outputDir/WORK analyze -f sverilog -lib WORK $my_verilog_files -elaborate $my_toplevel -parameter P -lib WORK +elaborate $my_toplevel -lib WORK # Set the current_design current_design $my_toplevel From 801ff63e243fac6811f951f6be6b50f79eeee487 Mon Sep 17 00:00:00 2001 From: Kevin Kim Date: Sun, 27 Aug 2023 14:00:10 -0700 Subject: [PATCH 09/11] started wrapper generation script --- synthDC/scripts/wrapperGen.py | 60 +++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 synthDC/scripts/wrapperGen.py diff --git a/synthDC/scripts/wrapperGen.py b/synthDC/scripts/wrapperGen.py new file mode 100644 index 000000000..76ae24a33 --- /dev/null +++ b/synthDC/scripts/wrapperGen.py @@ -0,0 +1,60 @@ +""" +wrapperGen.py + +kekim@hmc.edu + +script that generates top-level wrappers for verilog modules to synthesize +""" + +import argparse +import os + +#create argument parser +parser = argparse.ArgumentParser() + +parser.add_argument("fin") + +args=parser.parse_args() + +fin = open(args.fin, "r") + +lines = fin.readlines() + +# keeps track of what line number the module header begins +lineModuleStart = 0 + +# keeps track of what line number the module header ends +lineModuleEnd = 0 + +# keeps track of module name +moduleName = "" + +# string that will keep track of the running module header +buf = "`include \"config.vh\"\n`include \"parameter-defs.vh\"\nimport cvw::*;\n" + +# are we writing into the buffer +writeBuf=False + +index=0 + +# string copy logic +for l in lines: + if l.find("module") == 0: + lineModuleStart = index + moduleName = l.split()[1] + writeBuf = True + buf += f"module {moduleName}wrapper (\n" + continue + if (writeBuf): + buf += l + if l.find (");") == 0: + lineModuleEnd = index + break + index+=1 + +# post-processing buffer: add DUT and endmodule lines +buf += f"\t{moduleName} #(P) dut(.*);\nendmodule" + + + +print(buf) \ No newline at end of file From 62d71043982eb866c524753e865c3a15c49ff7ad Mon Sep 17 00:00:00 2001 From: Kevin Kim Date: Sun, 27 Aug 2023 14:13:29 -0700 Subject: [PATCH 10/11] wrapper generation works --- synthDC/scripts/wrapperGen.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/synthDC/scripts/wrapperGen.py b/synthDC/scripts/wrapperGen.py index 76ae24a33..84c04f1fd 100644 --- a/synthDC/scripts/wrapperGen.py +++ b/synthDC/scripts/wrapperGen.py @@ -30,7 +30,7 @@ lineModuleEnd = 0 moduleName = "" # string that will keep track of the running module header -buf = "`include \"config.vh\"\n`include \"parameter-defs.vh\"\nimport cvw::*;\n" +buf = "import cvw::*;\n`include \"config.vh\"\n`include \"parameter-defs.vh\"\n" # are we writing into the buffer writeBuf=False @@ -56,5 +56,19 @@ for l in lines: buf += f"\t{moduleName} #(P) dut(.*);\nendmodule" +# path to wrapper +wrapperPath = f"{os.getenv('WALLY')}/src/wrappers/{moduleName}wrapper.sv" + +# clear wrappers directory +os.system(f"rm {os.getenv('WALLY')}/src/wrappers/*") + +fout = open(wrapperPath, "w") + +fout.write(buf) + +fin.close() +fout.close() + + print(buf) \ No newline at end of file From 8d3ff5967391f3ec55eab2907128ae38c3c7ccf4 Mon Sep 17 00:00:00 2001 From: David Harris Date: Mon, 28 Aug 2023 06:57:35 -0700 Subject: [PATCH 11/11] Completed basic tests of svnapot and svpbmt --- src/mmu/hptw.sv | 2 +- src/mmu/tlb/tlb.sv | 12 +- src/mmu/tlb/tlbcontrol.sv | 64 ++++++++-- src/mmu/tlb/tlbram.sv | 4 +- src/mmu/tlb/tlbramline.sv | 12 +- testbench/tests.vh | 2 +- .../WALLY-mmu-sv32-01.reference_output | 6 +- .../WALLY-mmu-sv32-svadu-01.reference_output | 10 +- .../rv32i_m/privilege/src/WALLY-mmu-sv32-01.S | 78 ++++++------ .../privilege/src/WALLY-mmu-sv32-svadu-01.S | 76 +++++------ .../WALLY-mmu-sv39-01.reference_output | 38 +++--- ...-svadu-svnapot-svpbmt-01.reference_output} | 52 +++++--- .../WALLY-mmu-sv48-01.reference_output | 34 ++--- .../WALLY-mmu-sv48-svadu-01.reference_output | 34 ++--- .../rv64i_m/privilege/src/WALLY-TEST-LIB-64.h | 6 + .../rv64i_m/privilege/src/WALLY-mmu-sv39-01.S | 86 +++++++------ ... WALLY-mmu-sv39-svadu-svnapot-svpbmt-01.S} | 120 ++++++++++++------ .../rv64i_m/privilege/src/WALLY-mmu-sv48-01.S | 86 ++++++------- .../privilege/src/WALLY-mmu-sv48-svadu-01.S | 84 ++++++------ 19 files changed, 456 insertions(+), 350 deletions(-) rename tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/{WALLY-mmu-sv39-svadu-01.reference_output => WALLY-mmu-sv39-svadu-svnapot-svpbmt-01.reference_output} (57%) rename tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/{WALLY-mmu-sv39-svadu-01.S => WALLY-mmu-sv39-svadu-svnapot-svpbmt-01.S} (64%) diff --git a/src/mmu/hptw.sv b/src/mmu/hptw.sv index f38003f41..410d1bf91 100644 --- a/src/mmu/hptw.sv +++ b/src/mmu/hptw.sv @@ -155,7 +155,7 @@ module hptw import cvw::*; #(parameter cvw_t P) ( assign AccessedPTE = {PTE[P.XLEN-1:8], (SetDirty | PTE[7]), 1'b1, PTE[5:0]}; // set accessed bit, conditionally set dirty bit mux2 #(P.XLEN) NextPTEMux(ReadDataM, AccessedPTE, UpdatePTE, NextPTE); flopenr #(P.PA_BITS) HPTWAdrWriteReg(clk, reset, SaveHPTWAdr, HPTWReadAdr, HPTWWriteAdr); - + assign SaveHPTWAdr = WalkerState == L0_ADR; assign SelHPTWWriteAdr = UpdatePTE | HPTWRW[0]; mux2 #(P.PA_BITS) HPTWWriteAdrMux(HPTWReadAdr, HPTWWriteAdr, SelHPTWWriteAdr, HPTWAdr); diff --git a/src/mmu/tlb/tlb.sv b/src/mmu/tlb/tlb.sv index 497a97fe5..8910f7d53 100644 --- a/src/mmu/tlb/tlb.sv +++ b/src/mmu/tlb/tlb.sv @@ -81,12 +81,11 @@ module tlb import cvw::*; #(parameter cvw_t P, logic [P.VPN_BITS-1:0] VPN; logic [P.PPN_BITS-1:0] PPN; // Sections of the page table entry - logic [10:0] PTEAccessBits; + logic [11:0] PTEAccessBits; logic [1:0] HitPageType; logic CAMHit; logic SV39Mode; logic Misaligned; - logic BadPTEWrite; // trying to write malformed PTE logic MegapageMisaligned; logic PTE_N; // NAPOT page table entry @@ -105,16 +104,9 @@ module tlb import cvw::*; #(parameter cvw_t P, assign VPN = VAdr[P.VPN_BITS+11:12]; - // check if reserved, N, or PBMT bits are malformed when PTE is written in RV64 - assign BadPTEWrite = (P.XLEN == 64) & TLBWrite & ( - PTE[P.XLEN-1] & ~P.SVNAPOT_SUPPORTED | // N must be 0 if SVNAPOT is not supported - PTE[P.XLEN-2:P.XLEN-3] != 0 & ~P.SVPBMT_SUPPORTED | // PBMT must be 0 if SVBPMT is not supported - PTE[P.XLEN-2:P.XLEN-3] == 3 | // PBMT of 3 is reserved and never legal - PTE[P.XLEN-4:P.XLEN-10] != 0 ); // Reserved bits must be 0 - tlbcontrol #(P, ITLB) tlbcontrol(.SATP_MODE, .VAdr, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .ENVCFG_PBMTE, .PrivilegeModeW, .ReadAccess, .WriteAccess, .DisableTranslation, .TLBFlush, - .PTEAccessBits, .CAMHit, .Misaligned, .BadPTEWrite, + .PTEAccessBits, .CAMHit, .Misaligned, .TLBMiss, .TLBHit, .TLBPageFault, .UpdateDA, .SV39Mode, .Translate, .PTE_N, .PBMemoryType); diff --git a/src/mmu/tlb/tlbcontrol.sv b/src/mmu/tlb/tlbcontrol.sv index bfd8a9251..3c2f81697 100644 --- a/src/mmu/tlb/tlbcontrol.sv +++ b/src/mmu/tlb/tlbcontrol.sv @@ -36,10 +36,9 @@ module tlbcontrol import cvw::*; #(parameter cvw_t P, ITLB = 0) ( input logic ReadAccess, WriteAccess, input logic DisableTranslation, input logic TLBFlush, // Invalidate all TLB entries - input logic [10:0] PTEAccessBits, + input logic [11:0] PTEAccessBits, input logic CAMHit, input logic Misaligned, - input logic BadPTEWrite, // trying to write malformed PTE output logic TLBMiss, output logic TLBHit, output logic TLBPageFault, @@ -53,13 +52,14 @@ module tlbcontrol import cvw::*; #(parameter cvw_t P, ITLB = 0) ( // Sections of the page table entry logic [1:0] EffectivePrivilegeMode; - logic PTE_D, PTE_A, PTE_U, PTE_X, PTE_W, PTE_R, PTE_V; // Useful PTE Control Bits logic [1:0] PTE_PBMT; + logic PTE_RESERVED, PTE_D, PTE_A, PTE_U, PTE_X, PTE_W, PTE_R, PTE_V; // Useful PTE Control Bits logic UpperBitsUnequal; logic TLBAccess; logic ImproperPrivilege; - logic BadPBMT; - logic CausePageFault; + logic BadPBMT, BadNAPOT, BadReserved; + logic InvalidAccess; + logic PreUpdateDA, PrePageFault; // Grab the sv mode from SATP and determine whether translation should occur assign EffectivePrivilegeMode = (ITLB == 1) ? PrivilegeModeW : (STATUS_MPRV ? STATUS_MPP : PrivilegeModeW); // DTLB uses MPP mode when MPRV is 1 @@ -72,24 +72,63 @@ module tlbcontrol import cvw::*; #(parameter cvw_t P, ITLB = 0) ( vm64check #(P) vm64check(.SATP_MODE, .VAdr, .SV39Mode, .UpperBitsUnequal); // unswizzle useful PTE bits - assign PTE_N = PTEAccessBits[10]; - assign PTE_PBMT = PTEAccessBits[9:8]; + assign PTE_N = PTEAccessBits[11]; + assign PTE_PBMT = PTEAccessBits[10:9]; + assign PTE_RESERVED = PTEAccessBits[8]; assign {PTE_D, PTE_A} = PTEAccessBits[7:6]; assign {PTE_U, PTE_X, PTE_W, PTE_R, PTE_V} = PTEAccessBits[4:0]; - // Page fault if PBMT is nonzero when SVPBMT is not supported and enabled - assign BadPBMT = PTE_PBMT != 0 & ~(P.SVPBMT_SUPPORTED & ENVCFG_PBMTE); - // Send PMA a 2-bit MemoryType that is PBMT during leaf page table accesses and 0 otherwise assign PBMemoryType = PTE_PBMT & {2{Translate & TLBHit & P.SVPBMT_SUPPORTED}}; + // check if reserved, N, or PBMT bits are malformed w in RV64 + assign BadPBMT = PTE_PBMT != 0 & (~(P.SVPBMT_SUPPORTED & ENVCFG_PBMTE) | + {PTE_X, PTE_W, PTE_R} == 3'b000) | PTE_PBMT == 3; // PBMT must be zero if not supported or for non-leaf PTEs; + assign BadNAPOT = PTE_N & ~P.SVNAPOT_SUPPORTED; // N must be be 0 if CVNAPOT is not supported + assign BadReserved = PTE_RESERVED; // Reserved bits must be zero + // Check whether the access is allowed, page faulting if not. if (ITLB == 1) begin:itlb // Instruction TLB fault checking // User mode may only execute user mode pages, and supervisor mode may // only execute non-user mode pages. assign ImproperPrivilege = ((EffectivePrivilegeMode == P.U_MODE) & ~PTE_U) | ((EffectivePrivilegeMode == P.S_MODE) & PTE_U); - assign CausePageFault = ImproperPrivilege | ~PTE_X | UpperBitsUnequal | BadPTEWrite | BadPBMT | Misaligned | ~PTE_V | (~PTE_A & P.SVADU_SUPPORTED); + assign PreUpdateDA = ~PTE_A; + assign InvalidAccess = ~PTE_X; + end else begin:dtlb // Data TLB fault checking + logic InvalidRead, InvalidWrite; + + // User mode may only load/store from user mode pages, and supervisor mode + // may only access user mode pages when STATUS_SUM is low. + assign ImproperPrivilege = ((EffectivePrivilegeMode == P.U_MODE) & ~PTE_U) | + ((EffectivePrivilegeMode == P.S_MODE) & PTE_U & ~STATUS_SUM); + // Check for read error. Reads are invalid when the page is not readable + // (and executable pages are not readable) or when the page is neither + // readable nor executable (and executable pages are readable). + assign InvalidRead = ReadAccess & ~PTE_R & (~STATUS_MXR | ~PTE_X); + // Check for write error. Writes are invalid when the page's write bit is + // low. + assign InvalidWrite = WriteAccess & ~PTE_W; + assign InvalidAccess = InvalidRead | InvalidWrite; + assign PreUpdateDA = ~PTE_A | WriteAccess & ~PTE_D; + end + + // Determine wheter to update DA bits. With SVADU, it is done in hardware + if (P.SVADU_SUPPORTED) assign UpdateDA = PreUpdateDA & Translate & TLBHit & ~TLBPageFault; + else assign UpdateDA = PreUpdateDA; + + // Determine whether page fault occurs + assign PrePageFault = UpperBitsUnequal | Misaligned | ~PTE_V | ImproperPrivilege | (P.XLEN == 64 & (BadPBMT | BadNAPOT | BadReserved)) | (PreUpdateDA & ~P.SVADU_SUPPORTED); + assign TLBPageFault = Translate & TLBHit & (PrePageFault | InvalidAccess); + +/* + // Check whether the access is allowed, page faulting if not. + if (ITLB == 1) begin:itlb // Instruction TLB fault checking + // User mode may only execute user mode pages, and supervisor mode may + // only execute non-user mode pages. + assign ImproperPrivilege = ((EffectivePrivilegeMode == P.U_MODE) & ~PTE_U) | + ((EffectivePrivilegeMode == P.S_MODE) & PTE_U); + assign CausePageFault = ImproperPrivilege | ~PTE_X | UpperBitsUnequal | BadPTE | BadPBMT | Misaligned | ~PTE_V | (~PTE_A & P.SVADU_SUPPORTED); assign TLBPageFault = Translate & TLBHit & CausePageFault; // Determine wheter to update DA bits if(P.SVADU_SUPPORTED) assign UpdateDA = Translate & TLBHit & ~PTE_A & ~TLBPageFault; @@ -110,13 +149,14 @@ module tlbcontrol import cvw::*; #(parameter cvw_t P, ITLB = 0) ( assign InvalidWrite = WriteAccess & ~PTE_W; if(P.SVADU_SUPPORTED) begin : hptwwrites assign UpdateDA = Translate & TLBHit & (~PTE_A | WriteAccess & ~PTE_D) & ~TLBPageFault; - assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | InvalidRead | InvalidWrite | UpperBitsUnequal | Misaligned | ~PTE_V)); + assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | InvalidRead | InvalidWrite | UpperBitsUnequal | Misaligned | ~PTE_V)); // *** update to match end else begin // Fault for software handling if access bit is off or writing a page with dirty bit off assign UpdateDA = ~PTE_A | WriteAccess & ~PTE_D; assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | InvalidRead | InvalidWrite | UpdateDA | UpperBitsUnequal | Misaligned | ~PTE_V)); end end +*/ assign TLBHit = CAMHit & TLBAccess; assign TLBMiss = ~CAMHit & TLBAccess & Translate ; diff --git a/src/mmu/tlb/tlbram.sv b/src/mmu/tlb/tlbram.sv index 07d9dd87c..1a667d847 100644 --- a/src/mmu/tlb/tlbram.sv +++ b/src/mmu/tlb/tlbram.sv @@ -35,7 +35,7 @@ module tlbram import cvw::*; #(parameter cvw_t P, input logic [P.XLEN-1:0] PTE, input logic [TLB_ENTRIES-1:0] Matches, WriteEnables, output logic [P.PPN_BITS-1:0] PPN, - output logic [10:0] PTEAccessBits, + output logic [11:0] PTEAccessBits, output logic [TLB_ENTRIES-1:0] PTE_Gs, output logic [TLB_ENTRIES-1:0] PTE_NAPOTs // entry is in NAPOT mode (N bit set and PPN[3:0] = 1000) ); @@ -50,6 +50,6 @@ module tlbram import cvw::*; #(parameter cvw_t P, or_rows #(TLB_ENTRIES, P.XLEN) PTEOr(RamRead, PageTableEntry); // Rename the bits read from the TLB RAM - assign PTEAccessBits = {PageTableEntry[P.XLEN-1:P.XLEN-3] & {3{P.XLEN == 64}}, PageTableEntry[7:0]}; // include N and PBMT bits + assign PTEAccessBits = {PageTableEntry[P.XLEN-1:P.XLEN-4] & {4{P.XLEN == 64}}, PageTableEntry[7:0]}; // for RV64 include N and PBMT bits and OR of reserved bitss assign PPN = PageTableEntry[P.PPN_BITS+9:10]; endmodule diff --git a/src/mmu/tlb/tlbramline.sv b/src/mmu/tlb/tlbramline.sv index 971e804ac..5e17e86eb 100644 --- a/src/mmu/tlb/tlbramline.sv +++ b/src/mmu/tlb/tlbramline.sv @@ -39,11 +39,13 @@ module tlbramline import cvw::*; #(parameter cvw_t P) if (P.XLEN == 64) begin // save 7 reserved bits // could optimize out N and PBMT from d[63:61] if they aren't supported - logic [56:0] ptereg; - flopenr #(57) pteflop(clk, reset, we, {d[63:61], d[53:0]}, ptereg); - assign line = {ptereg[56:54], 7'b0, ptereg[53:0]}; - end else // rv32 - flopenr #(P.XLEN) pteflop(clk, reset, we, d, line); + logic [57:0] ptereg; + logic reserved; + assign reserved = |d[60:54]; // are any of the reserved bits nonzero? + flopenr #(58) pteflop(clk, reset, we, {d[63:61], reserved, d[53:0]}, ptereg); + assign line = {ptereg[57:54], 6'b0, ptereg[53:0]}; + end else // rv32 + flopenr #(P.XLEN) pteflop(clk, reset, we, d, line); assign q = re ? line : 0; assign PTE_G = line[5]; // send global bit to CAM as part of ASID matching diff --git a/testbench/tests.vh b/testbench/tests.vh index 88a862d0e..3229a6de7 100644 --- a/testbench/tests.vh +++ b/testbench/tests.vh @@ -1944,7 +1944,7 @@ string arch64zbs[] = '{ "rv64i_m/privilege/src/WALLY-misa-01.S", // "rv64i_m/privilege/src/WALLY-mmu-sv39-01.S", // run this if SVADU_SUPPORTED = 0 // "rv64i_m/privilege/src/WALLY-mmu-sv48-01.S", // run this if SVADU_SUPPORTED = 0 - "rv64i_m/privilege/src/WALLY-mmu-sv39-svadu-01.S", // run this if SVADU_SUPPORTED = 1 + "rv64i_m/privilege/src/WALLY-mmu-sv39-svadu-svnapot-svpbmt-01.S", // run this if SVADU_SUPPORTED = 1 "rv64i_m/privilege/src/WALLY-mmu-sv48-svadu-01.S", // run this if SVADU_SUPPORTED = 1 "rv64i_m/privilege/src/WALLY-mtvec-01.S", "rv64i_m/privilege/src/WALLY-pma-01.S", diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/references/WALLY-mmu-sv32-01.reference_output b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/references/WALLY-mmu-sv32-01.reference_output index 011aec866..eaab3127f 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/references/WALLY-mmu-sv32-01.reference_output +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/references/WALLY-mmu-sv32-01.reference_output @@ -41,11 +41,11 @@ beef0110 00000bad 0000000f beef0bb0 -beef0077 # Test 12.3.1.4.1: successful read back of saved value with new memory mapping -00000009 # Test 12.3.1.5.1: ecall from going to m mode from s mode +beef0077 # Test 11.3.1.4.1: successful read back of saved value with new memory mapping +00000009 # Test 11.3.1.5.1: ecall from going to m mode from s mode 00000000 # previous value of mprv before being set beef0099 # Read success from translated address when mprv=1, mpp=S and priv mode = m -0000000b # Test 12.3.1.5.2: ecall from going to S mode from m mode +0000000b # Test 11.3.1.5.2: ecall from going to S mode from m mode 00000009 # ecall from going straight back to m mode to access mstatus 00000000 # previous zeroed out value of mprv 0000000b # ecall from terminating tests in m mode diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/references/WALLY-mmu-sv32-svadu-01.reference_output b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/references/WALLY-mmu-sv32-svadu-01.reference_output index aa60ea214..9d88117e6 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/references/WALLY-mmu-sv32-svadu-01.reference_output +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/references/WALLY-mmu-sv32-svadu-01.reference_output @@ -35,13 +35,13 @@ beef0110 0000000f 0000000c 00000bad -beef0770 # Test 8.3.1.3.5: check successful read/write when A=0 and SVADU=1 -beef0aa0 # Test 8.3.1.3.6: check successful read/write when D=0 and SVADU=1 -beef0077 # Test 12.3.1.4.1: successful read back of saved value with new memory mapping -00000009 # Test 12.3.1.5.1: ecall from going to m mode from s mode +beef0770 # Test 11.3.1.3.5: check successful read/write when A=0 and SVADU=1 +beef0aa0 # Test 11.3.1.3.6: check successful read/write when D=0 and SVADU=1 +beef0077 # Test 11.3.1.4.1: successful read back of saved value with new memory mapping +00000009 # Test 11.3.1.5.1: ecall from going to m mode from s mode 00000000 # previous value of mprv before being set beef0099 # Read success from translated address when mprv=1, mpp=S and priv mode = m -0000000b # Test 12.3.1.5.2: ecall from going to S mode from m mode +0000000b # Test 11.3.1.5.2: ecall from going to S mode from m mode 00000009 # ecall from going straight back to m mode to access mstatus 00000000 # previous zeroed out value of mprv 0000000b # ecall from terminating tests in m mode diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-mmu-sv32-01.S b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-mmu-sv32-01.S index 4df3a9e0f..3f43f9950 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-mmu-sv32-01.S +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-mmu-sv32-01.S @@ -1,6 +1,6 @@ /////////////////////////////////////////// // -// WALLY-MMU +// WALLY-MMU-SV32 // // Author: David_Harris@hmc.edu and Kip Macsai-Goren // @@ -52,9 +52,9 @@ test_cases: # # --------------------------------------------------------------------------------------------- -# =========== test 8.3.1.1 Page Table Translation =========== +# =========== test 11.3.1.1 Page Table Translation =========== -# test 8.3.1.1.1 write page tables / entries to phyiscal memory +# test 11.3.1.1.1 write page tables / entries to phyiscal memory # sv32 Page table (See Figure 12.12***): # Level 1 page table, situated at 0x8000D000 .4byte 0x8000D000, 0x20004C01, write32_test # points to level 0 page table A @@ -78,19 +78,19 @@ test_cases: .4byte 0x8000F000, 0x200000CF, write32_test # Vaddr 0x0 Paddr 0x80000000: aligned megapage .4byte 0x8000F800, 0x200000CF, write32_test # Vaddr 0x80000000 Paddr 0x80000000: aligned megapage (program and data memory) -# test 8.3.1.1.2 write values to Paddrs in each page -# each of these values is used for 8.3.1.1.3 and some other tests, specified in the comments. +# test 11.3.1.1.2 write values to Paddrs in each page +# each of these values is used for 11.3.1.1.3 and some other tests, specified in the comments. # when a test is supposed to fault, nothing is written into where it'll be reading/executing since it should fault before getting there. -.4byte 0x800AAAA8, 0xBEEF0055, write32_test # 8.3.1.1.4 megapage -.4byte 0x800FFAC0, 0xBEEF0033, write32_test # 8.3.1.3.2 -.4byte 0x800E3130, 0xBEEF0077, write32_test # 8.3.1.3.2 -.4byte 0x808017E0, 0xBEEF0099, write32_test # 8.3.1.1.4 kilopage -.4byte 0x80805EA0, 0xBEEF0440, write32_test # 8.3.1.3.3 -.4byte 0x80803AA0, 0xBEEF0BB0, write32_test # 8.3.1.3.7 +.4byte 0x800AAAA8, 0xBEEF0055, write32_test # 11.3.1.1.4 megapage +.4byte 0x800FFAC0, 0xBEEF0033, write32_test # 11.3.1.3.2 +.4byte 0x800E3130, 0xBEEF0077, write32_test # 11.3.1.3.2 +.4byte 0x808017E0, 0xBEEF0099, write32_test # 11.3.1.1.4 kilopage +.4byte 0x80805EA0, 0xBEEF0440, write32_test # 11.3.1.3.3 +.4byte 0x80803AA0, 0xBEEF0BB0, write32_test # 11.3.1.3.7 .4byte 0x8000FFA0, 0x11100393, write32_test # write executable code for "li x7, 0x111; ret" to executable region. -.4byte 0x8000FFA4, 0x00008067, write32_test # Used for 8.3.1.3.1, 8.3.1.3.2 +.4byte 0x8000FFA4, 0x00008067, write32_test # Used for 11.3.1.3.1, 11.3.1.3.2 -# test 8.3.1.1.3 read values back from Paddrs without translation (this also verifies the previous test) +# test 11.3.1.1.3 read values back from Paddrs without translation (this also verifies the previous test) .4byte 0x0, 0x0, goto_baremetal # satp.MODE = baremetal / no translation. .4byte 0x0, 0x0, goto_s_mode # change to S mode, 0xb written to output .4byte 0x800AAAA8, 0xBEEF0055, read32_test @@ -102,38 +102,38 @@ test_cases: .4byte 0x8000FFA0, 0x11100393, read32_test .4byte 0x8000FFA4, 0x00008067, read32_test -# test 8.3.1.1.4 check translation works in sv48, read the same values from previous tests, this time with Vaddrs +# test 11.3.1.1.4 check translation works in sv48, read the same values from previous tests, this time with Vaddrs .4byte 0x8000D, 0x0, goto_sv32 # satp.MODE = sv32, Nothing written to output .4byte 0x4AAAA8, 0xBEEF0055, read32_test # megapage at Vaddr 0x400000, Paddr 0x80000000 .4byte 0xBFF7E0, 0xBEEF0099, read32_test # kilopage at Vaddr 0xBFF000, Paddr 0x80201000 -# =========== test 8.3.1.2 page fault tests =========== +# =========== test 11.3.1.2 page fault tests =========== -# test 8.3.1.2.1 load page fault if upper bits of Vaddr are not the same +# test 11.3.1.2.1 load page fault if upper bits of Vaddr are not the same # Not tested in rv32/sv32 -# test 8.3.1.2.2 load page fault when reading an address where the valid flag is zero +# test 11.3.1.2.2 load page fault when reading an address where the valid flag is zero .4byte 0x6000, 0x0, read32_test -# test 8.3.1.2.3 store page fault if PTE has W and ~R flags set +# test 11.3.1.2.3 store page fault if PTE has W and ~R flags set .4byte 0x2000, 0x0, write32_test -# test 8.3.1.2.4 Fault if last level PTE is a pointer +# test 11.3.1.2.4 Fault if last level PTE is a pointer .4byte 0x0200, 0x0, read32_test -# test 8.3.1.2.5 load page fault on misaligned pages +# test 11.3.1.2.5 load page fault on misaligned pages .4byte 0xC00000, 0x0, read32_test # misaligned megapage -# =========== test 8.3.1.3 PTE Protection flags =========== +# =========== test 11.3.1.3 PTE Protection flags =========== -# test 8.3.1.3.1 User flag == 0 -# *** reads on pages with U=0 already tested in 8.3.1.1.4 +# test 11.3.1.3.1 User flag == 0 +# *** reads on pages with U=0 already tested in 11.3.1.1.4 .4byte 0x40FFA0, 0x111, executable_test # fetch success when U=0, priv=S .4byte 0x80400000, 0x1, goto_u_mode # go to U mode, return to VPN 0x80400000 where PTE.U = 1. 0x9 written to output .4byte 0xBFFC80, 0xBEEF0550, read32_test # load page fault when U=0, priv=U .4byte 0x40FFA0, 0xbad, executable_test # instr page fault when U=0, priv=U -# test 8.3.1.3.2 User flag == 1 +# test 11.3.1.3.2 User flag == 1 .4byte 0x804FFAC0, 0xBEEF0033, read32_test # read success when U=1, priv=U .4byte 0x80000000, 0x1, goto_s_mode # go back to S mode, return to VPN 0x80000000 where PTE.U = 0. 0x8 written to output .4byte 0x0, 0x3, write_mxr_sum # set sstatus.[MXR, SUM] = 11 @@ -142,61 +142,61 @@ test_cases: .4byte 0x0, 0x2, write_mxr_sum # set sstatus.[MXR, SUM] = 10. .4byte 0x804FFAC0, 0xBEEF0033, read32_test # load page fault when U-1, priv=S, sstatus.SUM=0 -# test 8.3.1.3.3 Read flag -# *** reads on pages with R=1 already tested in 8.3.1.1.4 +# test 11.3.1.3.3 Read flag +# *** reads on pages with R=1 already tested in 11.3.1.1.4 .4byte 0x0, 0x1, write_mxr_sum # set sstatus.[MXR, SUM] = 01. .4byte 0x5EA0, 0xBEEF0440, read32_test # load page fault when R=0, sstatus.MXR=0 .4byte 0x0, 0x3, write_mxr_sum # set sstatus.[MXR, SUM] = 11. .4byte 0x5EA0, 0xBEEF0440, read32_test # read success when R=0, MXR=1, X=1 -# test 8.3.1.3.4 Write flag +# test 11.3.1.3.4 Write flag .4byte 0xBFF290, 0xBEEF0110, write32_test # write success when W=1 .4byte 0xBFF290, 0xBEEF0110, read32_test # check write success by reading .4byte 0x5B78, 0xBEEF0CC0, write32_test # store page fault when W=0 -# test 8.3.1.3.5 eXecute flag -# *** fetches on pages with X = 1 already tested in 8.3.1.3.1 +# test 11.3.1.3.5 eXecute flag +# *** fetches on pages with X = 1 already tested in 11.3.1.3.1 .4byte 0xBFFDE0, 0xbad, executable_test # instr page fault when X=0 # In the following two tests, SVADU is not supported, so the software handles the A/D bits # Since SVADU is 0, Accesses to A/D=0 causes a fault for the trap handler to fix those bits -# test 8.3.1.3.6 Accessed flag == 0 +# test 11.3.1.3.6 Accessed flag == 0 .4byte 0x3020, 0xBEEF0770, write32_test # store page fault when A=0 .4byte 0x3808, 0xBEEF0990, read32_test # load page fault when A=0 -# test 8.3.1.3.7 Dirty flag == 0 +# test 11.3.1.3.7 Dirty flag == 0 .4byte 0x4658, 0xBEEF0AA0, write32_test # store page fault when D=0 .4byte 0x4AA0, 0xBEEF0BB0, read32_test # read success when D=0 -# =========== test 8.3.1.4 SATP Register =========== +# =========== test 11.3.1.4 SATP Register =========== -# test 8.3.1.4.1 SATP ASID and PPN fields (test having two page tables with different ASID) +# test 11.3.1.4.1 SATP ASID and PPN fields (test having two page tables with different ASID) // *** .4byte 0xFFFFFFFFFFFFF888, 0x0220DEADBEEF0099, write32_test # write identical value to global PTE to make sure it's still in the TLB .4byte 0x8000F, 0x11, goto_sv32 # go to SV39 on a second, very minimal page table .4byte 0xE3130, 0xBEEF0077, read32_test # Read success of old written value from a new page table mapping -# test 8.3.1.4.2 Test Global mapping +# test 11.3.1.4.2 Test Global mapping // ***.4byte 0x7FFFFFF888, 0x0220DEADBEEF0099, read32_test # read success of global PTE undefined in current mapping. -# =========== test 8.3.1.5 STATUS Registers =========== +# =========== test 11.3.1.5 STATUS Registers =========== -# test 8.3.1.5.1 mstatus.mprv translation +# test 11.3.1.5.1 mstatus.mprv translation # *** mstatus.mprv = 0 tested on every one of the translated reads and writes before this. .4byte 0x8000D, 0x0, goto_sv32 // go back to old, extensive page table .4byte 0x80000000, 0x1, goto_m_mode // go to m mode to be able to write mstatus .4byte 0x1, 0x1, read_write_mprv // write 1 to mstatus.mprv and set mstatus.mpp to be 01=S .4byte 0xBFF7E0, 0xBEEF0099, read32_test // read test succeeds with translation even though we're in M mode since MPP=S and MPRV=1 -# test 8.3.1.5.2 mstatus.mprv clearing +# test 11.3.1.5.2 mstatus.mprv clearing # mstatus.mprv is already 1 from the last test so going to S mode should clear it with the mret .4byte 0x80000000, 0x1, goto_s_mode // This should zero out the mprv bit but now to read and write mstatus, we have to .4byte 0x80000000, 0x1, goto_m_mode // go back to m mode to allow us to reread mstatus. .4byte 0x0, 0x0, read_write_mprv // read what should be a zeroed out mprv value and then force it back to zero. -# test 8.3.1.5.3 sstatus.mxr read -# this bitfield already tested in 8.3.1.3.3 +# test 11.3.1.5.3 sstatus.mxr read +# this bitfield already tested in 11.3.1.3.3 # terminate tests .4byte 0x0, 0x0, terminate_test # brings us back into machine mode with a final ecall, writing 0x9 to the output. diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-mmu-sv32-svadu-01.S b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-mmu-sv32-svadu-01.S index f864d255c..1a4a32cba 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-mmu-sv32-svadu-01.S +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv32i_m/privilege/src/WALLY-mmu-sv32-svadu-01.S @@ -1,6 +1,6 @@ /////////////////////////////////////////// // -// WALLY-MMU +// WALLY-MMU-SV32 // // Author: David_Harris@hmc.edu and Kip Macsai-Goren // @@ -52,9 +52,9 @@ test_cases: # # --------------------------------------------------------------------------------------------- -# =========== test 8.3.1.1 Page Table Translation =========== +# =========== test 11.3.1.1 Page Table Translation =========== -# test 8.3.1.1.1 write page tables / entries to phyiscal memory +# test 11.3.1.1.1 write page tables / entries to phyiscal memory # sv32 Page table (See Figure 12.12***): # Level 1 page table, situated at 0x8000D000 .4byte 0x8000D000, 0x20004C01, write32_test # points to level 0 page table A @@ -78,18 +78,18 @@ test_cases: .4byte 0x8000F000, 0x200000CF, write32_test # Vaddr 0x0 Paddr 0x80000000: aligned megapage .4byte 0x8000F800, 0x200000CF, write32_test # Vaddr 0x80000000 Paddr 0x80000000: aligned megapage (program and data memory) -# test 8.3.1.1.2 write values to Paddrs in each page -# each of these values is used for 8.3.1.1.3 and some other tests, specified in the comments. +# test 11.3.1.1.2 write values to Paddrs in each page +# each of these values is used for 11.3.1.1.3 and some other tests, specified in the comments. # when a test is supposed to fault, nothing is written into where it'll be reading/executing since it should fault before getting there. -.4byte 0x800AAAA8, 0xBEEF0055, write32_test # 8.3.1.1.4 megapage -.4byte 0x800FFAC0, 0xBEEF0033, write32_test # 8.3.1.3.2 -.4byte 0x800E3130, 0xBEEF0077, write32_test # 8.3.1.3.2 -.4byte 0x808017E0, 0xBEEF0099, write32_test # 8.3.1.1.4 kilopage -.4byte 0x80805EA0, 0xBEEF0440, write32_test # 8.3.1.3.3 +.4byte 0x800AAAA8, 0xBEEF0055, write32_test # 11.3.1.1.4 megapage +.4byte 0x800FFAC0, 0xBEEF0033, write32_test # 11.3.1.3.2 +.4byte 0x800E3130, 0xBEEF0077, write32_test # 11.3.1.3.2 +.4byte 0x808017E0, 0xBEEF0099, write32_test # 11.3.1.1.4 kilopage +.4byte 0x80805EA0, 0xBEEF0440, write32_test # 11.3.1.3.3 .4byte 0x8000FFA0, 0x11100393, write32_test # write executable code for "li x7, 0x111; ret" to executable region. -.4byte 0x8000FFA4, 0x00008067, write32_test # Used for 8.3.1.3.1, 8.3.1.3.2 +.4byte 0x8000FFA4, 0x00008067, write32_test # Used for 11.3.1.3.1, 11.3.1.3.2 -# test 8.3.1.1.3 read values back from Paddrs without translation (this also verifies the previous test) +# test 11.3.1.1.3 read values back from Paddrs without translation (this also verifies the previous test) .4byte 0x0, 0x0, goto_baremetal # satp.MODE = baremetal / no translation. .4byte 0x0, 0x0, goto_s_mode # change to S mode, 0xb written to output .4byte 0x800AAAA8, 0xBEEF0055, read32_test @@ -100,38 +100,38 @@ test_cases: .4byte 0x8000FFA0, 0x11100393, read32_test .4byte 0x8000FFA4, 0x00008067, read32_test -# test 8.3.1.1.4 check translation works in sv48, read the same values from previous tests, this time with Vaddrs +# test 11.3.1.1.4 check translation works in sv48, read the same values from previous tests, this time with Vaddrs .4byte 0x8000D, 0x0, goto_sv32 # satp.MODE = sv32, Nothing written to output .4byte 0x4AAAA8, 0xBEEF0055, read32_test # megapage at Vaddr 0x400000, Paddr 0x80000000 .4byte 0xBFF7E0, 0xBEEF0099, read32_test # kilopage at Vaddr 0xBFF000, Paddr 0x80201000 -# =========== test 8.3.1.2 page fault tests =========== +# =========== test 11.3.1.2 page fault tests =========== -# test 8.3.1.2.1 load page fault if upper bits of Vaddr are not the same +# test 11.3.1.2.1 load page fault if upper bits of Vaddr are not the same # Not tested in rv32/sv32 -# test 8.3.1.2.2 load page fault when reading an address where the valid flag is zero +# test 11.3.1.2.2 load page fault when reading an address where the valid flag is zero .4byte 0x6000, 0x0, read32_test -# test 8.3.1.2.3 store page fault if PTE has W and ~R flags set +# test 11.3.1.2.3 store page fault if PTE has W and ~R flags set .4byte 0x2000, 0x0, write32_test -# test 8.3.1.2.4 Fault if last level PTE is a pointer +# test 11.3.1.2.4 Fault if last level PTE is a pointer .4byte 0x0200, 0x0, read32_test -# test 8.3.1.2.5 load page fault on misaligned pages +# test 11.3.1.2.5 load page fault on misaligned pages .4byte 0xC00000, 0x0, read32_test # misaligned megapage -# =========== test 8.3.1.3 PTE Protection flags =========== +# =========== test 11.3.1.3 PTE Protection flags =========== -# test 8.3.1.3.1 User flag == 0 -# *** reads on pages with U=0 already tested in 8.3.1.1.4 +# test 11.3.1.3.1 User flag == 0 +# *** reads on pages with U=0 already tested in 11.3.1.1.4 .4byte 0x40FFA0, 0x111, executable_test # fetch success when U=0, priv=S .4byte 0x80400000, 0x1, goto_u_mode # go to U mode, return to VPN 0x80400000 where PTE.U = 1. 0x9 written to output .4byte 0xBFFC80, 0xBEEF0550, read32_test # load page fault when U=0, priv=U .4byte 0x40FFA0, 0xbad, executable_test # instr page fault when U=0, priv=U -# test 8.3.1.3.2 User flag == 1 +# test 11.3.1.3.2 User flag == 1 .4byte 0x804FFAC0, 0xBEEF0033, read32_test # read success when U=1, priv=U .4byte 0x80000000, 0x1, goto_s_mode # go back to S mode, return to VPN 0x80000000 where PTE.U = 0. 0x8 written to output .4byte 0x0, 0x3, write_mxr_sum # set sstatus.[MXR, SUM] = 11 @@ -140,61 +140,61 @@ test_cases: .4byte 0x0, 0x2, write_mxr_sum # set sstatus.[MXR, SUM] = 10. .4byte 0x804FFAC0, 0xBEEF0033, read32_test # load page fault when U-1, priv=S, sstatus.SUM=0 -# test 8.3.1.3.3 Read flag -# *** reads on pages with R=1 already tested in 8.3.1.1.4 +# test 11.3.1.3.3 Read flag +# *** reads on pages with R=1 already tested in 11.3.1.1.4 .4byte 0x0, 0x1, write_mxr_sum # set sstatus.[MXR, SUM] = 01. .4byte 0x5EA0, 0xBEEF0440, read32_test # load page fault when R=0, sstatus.MXR=0 .4byte 0x0, 0x3, write_mxr_sum # set sstatus.[MXR, SUM] = 11. .4byte 0x5EA0, 0xBEEF0440, read32_test # read success when R=0, MXR=1, X=1 -# test 8.3.1.3.4 Write flag +# test 11.3.1.3.4 Write flag .4byte 0xBFF290, 0xBEEF0110, write32_test # write success when W=1 .4byte 0xBFF290, 0xBEEF0110, read32_test # check write success by reading .4byte 0x5B78, 0xBEEF0CC0, write32_test # store page fault when W=0 -# test 8.3.1.3.5 eXecute flag -# *** fetches on pages with X = 1 already tested in 8.3.1.3.1 +# test 11.3.1.3.5 eXecute flag +# *** fetches on pages with X = 1 already tested in 11.3.1.3.1 .4byte 0xBFFDE0, 0xbad, executable_test # instr page fault when X=0 # In the following two tests, SVADU is supported, so the hardware handles the A/D bits # Since SVADU is 1, there are no faults when A/D=0 -# test 8.3.1.3.6 Accessed flag == 0 +# test 11.3.1.3.6 Accessed flag == 0 .4byte 0x3020, 0xBEEF0770, write32_test # Write success when A=0 and SVADU is enabled .4byte 0x3020, 0xBEEF0770, read32_test # Read success when A=0 and SVADU is enabled -# test 8.3.1.3.7 Dirty flag == 0 +# test 11.3.1.3.7 Dirty flag == 0 .4byte 0x4658, 0xBEEF0AA0, write32_test # write successs when D=0 and SVADU is enabled .4byte 0x4658, 0xBEEF0AA0, read32_test # read success when D=0 -# =========== test 8.3.1.4 SATP Register =========== +# =========== test 11.3.1.4 SATP Register =========== -# test 8.3.1.4.1 SATP ASID and PPN fields (test having two page tables with different ASID) +# test 11.3.1.4.1 SATP ASID and PPN fields (test having two page tables with different ASID) // *** .4byte 0xFFFFFFFFFFFFF888, 0x0220DEADBEEF0099, write32_test # write identical value to global PTE to make sure it's still in the TLB .4byte 0x8000F, 0x11, goto_sv32 # go to SV39 on a second, very minimal page table .4byte 0xE3130, 0xBEEF0077, read32_test # Read success of old written value from a new page table mapping -# test 8.3.1.4.2 Test Global mapping +# test 11.3.1.4.2 Test Global mapping // ***.4byte 0x7FFFFFF888, 0x0220DEADBEEF0099, read32_test # read success of global PTE undefined in current mapping. -# =========== test 8.3.1.5 STATUS Registers =========== +# =========== test 11.3.1.5 STATUS Registers =========== -# test 8.3.1.5.1 mstatus.mprv translation +# test 11.3.1.5.1 mstatus.mprv translation # *** mstatus.mprv = 0 tested on every one of the translated reads and writes before this. .4byte 0x8000D, 0x0, goto_sv32 // go back to old, extensive page table .4byte 0x80000000, 0x1, goto_m_mode // go to m mode to be able to write mstatus .4byte 0x1, 0x1, read_write_mprv // write 1 to mstatus.mprv and set mstatus.mpp to be 01=S .4byte 0xBFF7E0, 0xBEEF0099, read32_test // read test succeeds with translation even though we're in M mode since MPP=S and MPRV=1 -# test 8.3.1.5.2 mstatus.mprv clearing +# test 11.3.1.5.2 mstatus.mprv clearing # mstatus.mprv is already 1 from the last test so going to S mode should clear it with the mret .4byte 0x80000000, 0x1, goto_s_mode // This should zero out the mprv bit but now to read and write mstatus, we have to .4byte 0x80000000, 0x1, goto_m_mode // go back to m mode to allow us to reread mstatus. .4byte 0x0, 0x0, read_write_mprv // read what should be a zeroed out mprv value and then force it back to zero. -# test 8.3.1.5.3 sstatus.mxr read -# this bitfield already tested in 8.3.1.3.3 +# test 11.3.1.5.3 sstatus.mxr read +# this bitfield already tested in 11.3.1.3.3 # terminate tests .4byte 0x0, 0x0, terminate_test # brings us back into machine mode with a final ecall, writing 0x9 to the output. diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-mmu-sv39-01.reference_output b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-mmu-sv39-01.reference_output index 001604246..360afba6b 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-mmu-sv39-01.reference_output +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-mmu-sv39-01.reference_output @@ -1,4 +1,4 @@ -0000000b # Test 12.3.1.1.3: ecall from going to S mode from M mode +0000000b # Test 11.3.1.1.3: ecall from going to S mode from M mode 00000000 beef0000 # Read test success from confirming writes of known values 0000dead @@ -14,13 +14,13 @@ beef0440 # Read test success from confirming writes of known values 0330dead beef0bb0 # Read test success from confirming writes of known values 0440dead -beef0000 # Test 12.3.1.1.4: Read test success from checking translation works +beef0000 # Test 11.3.1.1.4: Read test success from checking translation works 0000dead beef0055 # Read test success from checking translation works 0880dead beef0099 # Read test success from checking translation works 0220dead -0000000d # Test 12.3.1.2.1: Read test with page fault from upper vaddr bits not the same +0000000d # Test 11.3.1.2.1: Read test with page fault from upper vaddr bits not the same 00000000 00000bad 00000000 @@ -28,17 +28,17 @@ beef0099 # Read test success from checking translation works 00000000 00000bad 00000000 -0000000d # Test 12.3.1.2.2: read test with page fault +0000000d # Test 11.3.1.2.2: read test with page fault 00000000 00000bad 00000000 -0000000f # Test 12.3.1.2.3: write test with page fault +0000000f # Test 11.3.1.2.3: write test with page fault 00000000 -0000000d # Test 12.3.1.2.4: read test with page fault +0000000d # Test 11.3.1.2.4: read test with page fault 00000000 00000bad 00000000 -0000000d # Test 12.3.1.2.5: 2 read tests with page faults +0000000d # Test 11.3.1.2.5: 2 read tests with page faults 00000000 00000bad 00000000 @@ -46,7 +46,7 @@ beef0099 # Read test success from checking translation works 00000000 00000bad 00000000 -00000111 # Test 12.3.1.3.1: execute test success +00000111 # Test 11.3.1.3.1: execute test success 00000000 00000009 # ecall from going to U mode from S mode 00000000 @@ -58,7 +58,7 @@ beef0099 # Read test success from checking translation works 00000000 00000bad 00000000 -beef0033 # Test 12.3.1.3.2: read test success +beef0033 # Test 11.3.1.3.2: read test success 0990dead 00000008 # ecall from going to S mode from U mode 00000000 @@ -72,39 +72,43 @@ beef0077 # read test success 00000000 00000bad 00000000 -0000000d # Test 12.3.1.3.3: read test with page fault +0000000d # Test 11.3.1.3.3: read test with page fault 00000000 00000bad 00000000 beef0440 # read test success 0330dead -beef0110 # Test 12.3.1.3.4: read test success +beef0110 # Test 11.3.1.3.4: read test success 0440dead 0000000f # write test with page fault 00000000 -0000000c # Test 12.3.1.3.5: execute test with page fault +0000000c # Test 11.3.1.3.5: execute test with page fault 00000000 00000bad 00000000 -0000000f # Test 12.3.1.3.6: write test with page fault +0000000f # Test 11.3.1.3.6: write test with page fault 00000000 0000000d # read test with page fault 00000000 00000bad 00000000 -0000000f # Test 12.3.1.3.7: write test with page fault +0000000f # Test 11.3.1.3.7: write test with page fault 00000000 beef0bb0 # read test success 0440dead -beef0000 # Test 12.3.1.4.1: read test success from new page table mapping +0000000c # Test 11.3.1.3.8: read test with page fault for nonzero reserved bit +00000000 +00000bad +00000000 +beef0000 # Test 11.3.1.4.1: read test success from new page table mapping 0000dead -00000009 # Test 12.3.1.5.1: ecall from going to m mode from s mode +00000009 # Test 11.3.1.5.1: ecall from going to m mode from s mode 00000000 00000000 # previous mprv value before writing 1 to it. 00000000 beef0099 # Read test success when mprv=1 So translation should occur 0220dead # even though we're in M mode with translation off -0000000b # Test 12.3.1.5.2 ecall from going to s mode from m mode (zeroing mprv) +0000000b # Test 11.3.1.5.2 ecall from going to s mode from m mode (zeroing mprv) 00000000 00000009 # ecall from going to m mode from s mode (so we can access mstatus) 00000000 diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-mmu-sv39-svadu-01.reference_output b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-mmu-sv39-svadu-svnapot-svpbmt-01.reference_output similarity index 57% rename from tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-mmu-sv39-svadu-01.reference_output rename to tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-mmu-sv39-svadu-svnapot-svpbmt-01.reference_output index 64b2e79d8..93e4557a5 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-mmu-sv39-svadu-01.reference_output +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-mmu-sv39-svadu-svnapot-svpbmt-01.reference_output @@ -1,4 +1,4 @@ -0000000b # Test 12.3.1.1.3: ecall from going to S mode from M mode +0000000b # Test 11.3.1.1.3: ecall from going to S mode from M mode 00000000 beef0000 # Read test success from confirming writes of known values 0000dead @@ -12,13 +12,13 @@ beef0099 # Read test success from confirming writes of known values 0220dead beef0440 # Read test success from confirming writes of known values 0330dead -beef0000 # Test 12.3.1.1.4: Read test success from checking translation works +beef0000 # Test 11.3.1.1.4: Read test success from checking translation works 0000dead beef0055 # Read test success from checking translation works 0880dead beef0099 # Read test success from checking translation works 0220dead -0000000d # Test 12.3.1.2.1: Read test with page fault from upper vaddr bits not the same +0000000d # Test 11.3.1.2.1: Read test with page fault from upper vaddr bits not the same 00000000 00000bad 00000000 @@ -26,17 +26,17 @@ beef0099 # Read test success from checking translation works 00000000 00000bad 00000000 -0000000d # Test 12.3.1.2.2: read test with page fault +0000000d # Test 11.3.1.2.2: read test with page fault 00000000 00000bad 00000000 -0000000f # Test 12.3.1.2.3: write test with page fault +0000000f # Test 11.3.1.2.3: write test with page fault 00000000 -0000000d # Test 12.3.1.2.4: read test with page fault +0000000d # Test 11.3.1.2.4: read test with page fault 00000000 00000bad 00000000 -0000000d # Test 12.3.1.2.5: 2 read tests with page faults +0000000d # Test 11.3.1.2.5: 2 read tests with page faults 00000000 00000bad 00000000 @@ -44,7 +44,7 @@ beef0099 # Read test success from checking translation works 00000000 00000bad 00000000 -00000111 # Test 12.3.1.3.1: execute test success +00000111 # Test 11.3.1.3.1: execute test success 00000000 00000009 # ecall from going to U mode from S mode 00000000 @@ -56,7 +56,7 @@ beef0099 # Read test success from checking translation works 00000000 00000bad 00000000 -beef0033 # Test 12.3.1.3.2: read test success +beef0033 # Test 11.3.1.3.2: read test success 0990dead 00000008 # ecall from going to S mode from U mode 00000000 @@ -70,33 +70,51 @@ beef0077 # read test success 00000000 00000bad 00000000 -0000000d # Test 12.3.1.3.3: read test with page fault +0000000d # Test 11.3.1.3.3: read test with page fault 00000000 00000bad 00000000 beef0440 # read test success 0330dead -beef0110 # Test 12.3.1.3.4: read test success +beef0110 # Test 11.3.1.3.4: read test success 0440dead 0000000f # write test with page fault 00000000 -0000000c # Test 12.3.1.3.5: execute test with page fault +0000000c # Test 11.3.1.3.5: execute test with page fault 00000000 00000bad 00000000 -beef0770 # Test 8.3.1.3.5: check successful read/write when A=0 and SVADU=1 +beef0770 # Test 11.3.1.3.6: check successful read/write when A=0 and SVADU=1 0990dead -beef0aa0 # Test 8.3.1.3.6: check successful read/write when D=0 and SVADU=1 +beef0aa0 # Test 11.3.1.3.7: check successful read/write when D=0 and SVADU=1 0440dead -beef0000 # Test 12.3.1.4.1: read test success from new page table mapping +0000000d # Test 11.3.1.3.8: read test with page fault for nonzero reserved bit +00000000 +00000bad +00000000 +BEEF0660 # Test 11.3.1.3.9: NAPOT read +0550DEAD +0000000f # Test 11.3.1.3.10: PBMT; write page fault because menvcfg.PBMTE = 0 +00000000 +00000009 # ecall from going to M mode from S mode +00000000 +0000000B # ecall from going to S mode from M mode +00000000 +56567878 # write with PBMT = 1 +12123434 +56567878 # write with PBMT = 2 +23123434 +0000000f # write page fault because PBMT = 3 +00000000 +beef0000 # Test 11.3.1.4.1: read test success from new page table mapping 0000dead -00000009 # Test 12.3.1.5.1: ecall from going to m mode from s mode +00000009 # Test 11.3.1.5.1: ecall from going to m mode from s mode 00000000 00000000 # previous mprv value before writing 1 to it. 00000000 beef0099 # Read test success when mprv=1 So translation should occur 0220dead # even though we're in M mode with translation off -0000000b # Test 12.3.1.5.2 ecall from going to s mode from m mode (zeroing mprv) +0000000b # Test 11.3.1.5.2 ecall from going to s mode from m mode (zeroing mprv) 00000000 00000009 # ecall from going to m mode from s mode (so we can access mstatus) 00000000 diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-mmu-sv48-01.reference_output b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-mmu-sv48-01.reference_output index 6a53dd660..450713c52 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-mmu-sv48-01.reference_output +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-mmu-sv48-01.reference_output @@ -1,4 +1,4 @@ -0000000b # Test 12.3.1.1.3: ecall from going to S mode from M mode +0000000b # Test 11.3.1.1.3: ecall from going to S mode from M mode 00000000 beef0cc0 # 8 read test successes 0ee0dead @@ -16,7 +16,7 @@ beef0440 # read 7 0330dead beef0bb0 # read 8 0440dead -beef0cc0 # Test 12.3.1.1.4: 4 read test successes +beef0cc0 # Test 11.3.1.1.4: 4 read test successes 0ee0dead beef0000 # read 2 0000dead @@ -24,7 +24,7 @@ beef0055 # read 3 0880dead beef0099 # read 4 0220dead -0000000d # Test 12.3.1.2.1: 2 read tests with page fault +0000000d # Test 11.3.1.2.1: 2 read tests with page fault 00000000 00000bad 00000000 @@ -32,17 +32,17 @@ beef0099 # read 4 00000000 00000bad 00000000 -0000000d # Test 12.3.1.2.2: read test with page fault +0000000d # Test 11.3.1.2.2: read test with page fault 00000000 00000bad 00000000 -0000000f # Test 12.3.1.2.3: write test with page fault +0000000f # Test 11.3.1.2.3: write test with page fault 00000000 -0000000d # Test 12.3.1.2.4: read test with page fault +0000000d # Test 11.3.1.2.4: read test with page fault 00000000 00000bad 00000000 -0000000d # Test 12.3.1.2.5: 3 read tests with page fault +0000000d # Test 11.3.1.2.5: 3 read tests with page fault 00000000 00000bad 00000000 @@ -54,7 +54,7 @@ beef0099 # read 4 00000000 00000bad 00000000 -00000111 # Test 12.3.1.3.1: Execute test success +00000111 # Test 11.3.1.3.1: Execute test success 00000000 00000009 # ecall from going to U mode from S mode 00000000 @@ -66,7 +66,7 @@ beef0099 # read 4 00000000 00000bad 00000000 -beef0033 # Test 12.3.1.3.2: read test success +beef0033 # Test 11.3.1.3.2: read test success 0990dead 00000008 # ecall from going to S mode from U mode 00000000 @@ -80,39 +80,39 @@ beef0077 # read test success 00000000 00000bad 00000000 -0000000d # Test 12.3.1.3.3: read test with page fault +0000000d # Test 11.3.1.3.3: read test with page fault 00000000 00000bad 00000000 beef0440 # read test success 0330dead -beef0110 # Test 12.3.1.3.4: read test success +beef0110 # Test 11.3.1.3.4: read test success 0440dead 0000000f # write test with page fault 00000000 -0000000c # Test 12.3.1.3.5: executable test with page fault +0000000c # Test 11.3.1.3.5: executable test with page fault 00000000 00000bad 00000000 -0000000f # Test 12.3.1.3.6: write test with page fault +0000000f # Test 11.3.1.3.6: write test with page fault 00000000 0000000d # read test with page fault 00000000 00000bad 00000000 -0000000f # Test 12.3.1.3.7: write test with page fault +0000000f # Test 11.3.1.3.7: write test with page fault 00000000 beef0bb0 # read test success 0440dead -beef0000 # Test 12.3.1.4.1: read test success on new page table mapping +beef0000 # Test 11.3.1.4.1: read test success on new page table mapping 0000dead -00000009 # Test 12.3.1.5.1: ecall from going to m mode from s mode +00000009 # Test 11.3.1.5.1: ecall from going to m mode from s mode 00000000 00000000 # previous value of mprv before write 00000000 beef0099 # Read test success when mprv=1 So translation should occur 0220dead # even though we're in M mode with translation off -0000000b # Test 12.3.1.5.2 ecall from going to s mode from m mode (zeroing mprv) +0000000b # Test 11.3.1.5.2 ecall from going to s mode from m mode (zeroing mprv) 00000000 00000009 # ecall from going to m mode from s mode (so we can access mstatus) 00000000 diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-mmu-sv48-svadu-01.reference_output b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-mmu-sv48-svadu-01.reference_output index 7982cdebf..60fce42ef 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-mmu-sv48-svadu-01.reference_output +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/references/WALLY-mmu-sv48-svadu-01.reference_output @@ -1,4 +1,4 @@ -0000000b # Test 12.3.1.1.3: ecall from going to S mode from M mode +0000000b # Test 11.3.1.1.3: ecall from going to S mode from M mode 00000000 beef0cc0 # 8 read test successes 0ee0dead @@ -14,7 +14,7 @@ beef0099 # read 6 0220dead beef0440 # read 7 0330dead -beef0cc0 # Test 12.3.1.1.4: 4 read test successes +beef0cc0 # Test 11.3.1.1.4: 4 read test successes 0ee0dead beef0000 # read 2 0000dead @@ -22,7 +22,7 @@ beef0055 # read 3 0880dead beef0099 # read 4 0220dead -0000000d # Test 12.3.1.2.1: 2 read tests with page fault +0000000d # Test 11.3.1.2.1: 2 read tests with page fault 00000000 00000bad 00000000 @@ -30,17 +30,17 @@ beef0099 # read 4 00000000 00000bad 00000000 -0000000d # Test 12.3.1.2.2: read test with page fault +0000000d # Test 11.3.1.2.2: read test with page fault 00000000 00000bad 00000000 -0000000f # Test 12.3.1.2.3: write test with page fault +0000000f # Test 11.3.1.2.3: write test with page fault 00000000 -0000000d # Test 12.3.1.2.4: read test with page fault +0000000d # Test 11.3.1.2.4: read test with page fault 00000000 00000bad 00000000 -0000000d # Test 12.3.1.2.5: 3 read tests with page fault +0000000d # Test 11.3.1.2.5: 3 read tests with page fault 00000000 00000bad 00000000 @@ -52,7 +52,7 @@ beef0099 # read 4 00000000 00000bad 00000000 -00000111 # Test 12.3.1.3.1: Execute test success +00000111 # Test 11.3.1.3.1: Execute test success 00000000 00000009 # ecall from going to U mode from S mode 00000000 @@ -64,7 +64,7 @@ beef0099 # read 4 00000000 00000bad 00000000 -beef0033 # Test 12.3.1.3.2: read test success +beef0033 # Test 11.3.1.3.2: read test success 0990dead 00000008 # ecall from going to S mode from U mode 00000000 @@ -78,33 +78,33 @@ beef0077 # read test success 00000000 00000bad 00000000 -0000000d # Test 12.3.1.3.3: read test with page fault +0000000d # Test 11.3.1.3.3: read test with page fault 00000000 00000bad 00000000 beef0440 # read test success 0330dead -beef0110 # Test 12.3.1.3.4: read test success +beef0110 # Test 11.3.1.3.4: read test success 0440dead 0000000f # write test with page fault 00000000 -0000000c # Test 12.3.1.3.5: executable test with page fault +0000000c # Test 11.3.1.3.5: executable test with page fault 00000000 00000bad 00000000 -beef0770 # Test 8.3.1.3.5: check successful read/write when A=0 and SVADU=1 +beef0770 # Test 11.3.1.3.5: check successful read/write when A=0 and SVADU=1 0990dead -beef0aa0 # Test 8.3.1.3.6: check successful read/write when D=0 and SVADU=1 +beef0aa0 # Test 11.3.1.3.6: check successful read/write when D=0 and SVADU=1 0440dead -beef0000 # Test 12.3.1.4.1: read test success on new page table mapping +beef0000 # Test 11.3.1.4.1: read test success on new page table mapping 0000dead -00000009 # Test 12.3.1.5.1: ecall from going to m mode from s mode +00000009 # Test 11.3.1.5.1: ecall from going to m mode from s mode 00000000 00000000 # previous value of mprv before write 00000000 beef0099 # Read test success when mprv=1 So translation should occur 0220dead # even though we're in M mode with translation off -0000000b # Test 12.3.1.5.2 ecall from going to s mode from m mode (zeroing mprv) +0000000b # Test 11.3.1.5.2 ecall from going to s mode from m mode (zeroing mprv) 00000000 00000009 # ecall from going to m mode from s mode (so we can access mstatus) 00000000 diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-TEST-LIB-64.h b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-TEST-LIB-64.h index 1e887b9fb..23f105cbc 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-TEST-LIB-64.h +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-TEST-LIB-64.h @@ -1362,6 +1362,12 @@ write_mideleg: csrw mideleg, t4 j test_loop +write_menvcfg: + // writes the value in t4 to the menvcfg register + // Doesn't log anything + csrw menvcfg, t4 + j test_loop + executable_test: // Execute the code at the address in t3, returning the value in t2. // Assumes the code modifies t2, to become the value stored in t4 for this test. diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-mmu-sv39-01.S b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-mmu-sv39-01.S index 76ce91bfb..548911c0c 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-mmu-sv39-01.S +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-mmu-sv39-01.S @@ -1,6 +1,6 @@ /////////////////////////////////////////// // -// WALLY-MMU +// WALLY-MMU-SV39 // // Author: David_Harris@hmc.edu and Kip Macsai-Goren // @@ -52,9 +52,9 @@ test_cases: # # --------------------------------------------------------------------------------------------- -# =========== test 8.3.1.1 Page Table Translation =========== +# =========== test 11.3.1.1 Page Table Translation =========== -# test 8.3.1.1.1 write page tables / entries to phyiscal memory +# test 11.3.1.1.1 write page tables / entries to phyiscal memory # sv39 page table (See Figure 12.12***): # Level 2 page table, situated at 0x8000D000 .8byte 0x000000008000D000, 0x0000000020004C01, write64_test# points to level 1 page table A @@ -82,6 +82,7 @@ test_cases: .8byte 0x0000000080018020, 0x0000000020080C57, write64_test# Vaddr 0x4000 Paddr 0x80203000: D=0, should cause write fault .8byte 0x0000000080018028, 0x00000000200814C7, write64_test# Vaddr 0x5000 Paddr 0x80205000: X=0, fetches should fault .8byte 0x0000000080018030, 0x00000000200814C0, write64_test# Vaddr 0x6000: invalid page +.8byte 0x0000000080018038, 0x01000000200800DF, write64_test# Vaddr 0x7000, Paddr = 0x80200000, bad reserved bit # Level 0 page table B .8byte 0x0000000080016FF8, 0x00000000200804CF, write64_test# Vaddr 0xFFFFFFFFFFFFF000, Paddr 0x80201000 aligned kilopage @@ -89,20 +90,20 @@ test_cases: .8byte 0x8FFFF000, 0x200000CF, write64_test# Vaddr 0x0, Paddr 0x80000000 aligned gigapage .8byte 0x8FFFF010, 0x200000CF, write64_test# Vaddr 0x8000_0000, Paddr 0x80000000: aligned gigapage (program and data memory so we can execute without jumping around) -# test 8.3.1.1.2 write values to Paddrs in each page -# each of these values is used for 8.3.1.1.3 and some other tests, specified in the comments. +# test 11.3.1.1.2 write values to Paddrs in each page +# each of these values is used for 11.3.1.1.3 and some other tests, specified in the comments. # when a test is supposed to fault, nothing is written into where it'll be reading/executing since it shuold fault before getting there. -.8byte 0x80200AB0, 0x0000DEADBEEF0000, write64_test# 8.3.1.1.4 and 8.3.1.4.1 -.8byte 0x800FFAB8, 0x0880DEADBEEF0055, write64_test# 8.3.1.1.4 -.8byte 0x80200AC0, 0x0990DEADBEEF0033, write64_test# 8.3.1.3.2 -.8byte 0x80203130, 0x0110DEADBEEF0077, write64_test# 8.3.1.3.2 -.8byte 0x80099000, 0x0000806711100393, write64_test# 8.3.1.3.1 and 8.3.1.3.2 write executable code for "li x7, 0x111; ret" -.8byte 0x80205AA0, 0x0000806711100393, write64_test# 8.3.1.3.5 write same executable code -.8byte 0x80201888, 0x0220DEADBEEF0099, write64_test# 8.3.1.1.4 -.8byte 0x84212348, 0x0330DEADBEEF0440, write64_test# 8.3.1.3.3 -.8byte 0x80203AA0, 0x0440DEADBEEF0BB0, write64_test# 8.3.1.3.7 +.8byte 0x80200AB0, 0x0000DEADBEEF0000, write64_test# 11.3.1.1.4 and 11.3.1.4.1 +.8byte 0x800FFAB8, 0x0880DEADBEEF0055, write64_test# 11.3.1.1.4 +.8byte 0x80200AC0, 0x0990DEADBEEF0033, write64_test# 11.3.1.3.2 +.8byte 0x80203130, 0x0110DEADBEEF0077, write64_test# 11.3.1.3.2 +.8byte 0x80099000, 0x0000806711100393, write64_test# 11.3.1.3.1 and 11.3.1.3.2 write executable code for "li x7, 0x111; ret" +.8byte 0x80205AA0, 0x0000806711100393, write64_test# 11.3.1.3.5 write same executable code +.8byte 0x80201888, 0x0220DEADBEEF0099, write64_test# 11.3.1.1.4 +.8byte 0x84212348, 0x0330DEADBEEF0440, write64_test# 11.3.1.3.3 +.8byte 0x80203AA0, 0x0440DEADBEEF0BB0, write64_test# 11.3.1.3.7 -# test 8.3.1.1.3 read values back from Paddrs without translation (this also verifies the previous test) +# test 11.3.1.1.3 read values back from Paddrs without translation (this also verifies the previous test) .8byte 0x0, 0x0, goto_baremetal# satp.MODE = baremetal / no translation. .8byte 0x0, 0x0, goto_s_mode # change to S mode, 0xb written to output .8byte 0x80200AB0, 0x0000DEADBEEF0000, read64_test @@ -113,42 +114,42 @@ test_cases: .8byte 0x84212348, 0x0330DEADBEEF0440, read64_test .8byte 0x80203AA0, 0x0440DEADBEEF0BB0, read64_test -# test 8.3.1.1.4 check translation works in sv39, read the same values from previous tests, this time with Vaddrs +# test 11.3.1.1.4 check translation works in sv39, read the same values from previous tests, this time with Vaddrs .8byte 0x8000D, 0x0, goto_sv39 # satp.MODE = sv39, with base page table PPN = 0x8000D and ASID = 0. current VPN: gigapage at 0x80000000. .8byte 0x80200AB0, 0x0000DEADBEEF0000, read64_test # gigapage at Vaddr 0x80000000, Paddr 0x80000000 .8byte 0x400FFAB8, 0x0880DEADBEEF0055, read64_test # megapage at Vaddr 0x40400000, Paddr 0x80000000 .8byte 0xFFFFFFFFFFFFF888, 0x0220DEADBEEF0099, read64_test # kilopage at Vaddr 0xFFFFFFFFFFFFF000, Paddr 0x80201000 -# =========== test 8.3.1.2 page fault tests =========== +# =========== test 11.3.1.2 page fault tests =========== -# test 8.3.1.2.1 load page fault if upper bits of Vaddr are not the same +# test 11.3.1.2.1 load page fault if upper bits of Vaddr are not the same .8byte 0x0010000080000AB0, 0x0, read64_test# gigapage at Vaddr 0x80000000, Paddr 0x80000000, bad 1 in upper bits .8byte 0xFF0FFFFFFFFFF888, 0x0, read64_test# kilopage at Vaddr 0xFFFFFFFFFFFFF000, Paddr 0x80201000, bad 0000 in upper bits -# test 8.3.1.2.2 load page fault when reading an address where the valid flag is zero +# test 11.3.1.2.2 load page fault when reading an address where the valid flag is zero .8byte 0x6000, 0x0, read64_test -# test 8.3.1.2.3 store page fault if PTE has W and ~R flags set +# test 11.3.1.2.3 store page fault if PTE has W and ~R flags set .8byte 0x2000, 0x0, write64_test -# test 8.3.1.2.4 Fault if last level PTE is a pointer +# test 11.3.1.2.4 Fault if last level PTE is a pointer .8byte 0x0020, 0x0, read64_test -# test 8.3.1.2.5 load page fault on misaligned pages +# test 11.3.1.2.5 load page fault on misaligned pages .8byte 0xC0000000, 0x0, read64_test# misaligned gigapage .8byte 0x40200000, 0x0, read64_test# misaligned megapage -# =========== test 8.3.1.3 PTE Protection flags =========== +# =========== test 11.3.1.3 PTE Protection flags =========== -# test 8.3.1.3.1 User flag == 0 -# *** reads on pages with U=0 already tested in 8.3.1.1.4 +# test 11.3.1.3.1 User flag == 0 +# *** reads on pages with U=0 already tested in 11.3.1.1.4 .8byte 0x40099000, 0x111, executable_test # execute success when U=0, priv=S .8byte 0x40400000, 0x2, goto_u_mode # go to U mode, return to megapage at 0x40400000 where U = 1. 0x9 written to output .8byte 0xFFFFFFFFFFFFFC80, 0x0880DEADBEEF0550, read64_test # load page fault when U=0, priv=U .8byte 0x40099000, 0xbad, executable_test # execute fault when U=0, priv=U -# test 8.3.1.3.2 User flag == 1 +# test 11.3.1.3.2 User flag == 1 .8byte 0x1AC0, 0x0990DEADBEEF0033, read64_test # read success when U=1, priv=U .8byte 0x80000000, 0x1, goto_s_mode # go back to S mode, return to gigapage at 0x80000000 where U = 0. 0x8 written to output .8byte 0x0, 0x3, write_mxr_sum # set sstatus.[MXR, SUM] = 11 @@ -157,61 +158,64 @@ test_cases: .8byte 0x0, 0x2, write_mxr_sum # set sstatus.[MXR, SUM] = 10. .8byte 0x1AC0, 0x0990DEADBEEF0033, read64_test # load page fault when U-1, priv=S, sstatus.SUM=0 -# test 8.3.1.3.3 Read flag -# *** reads on pages with R=1 already tested in 8.3.1.1.4 +# test 11.3.1.3.3 Read flag +# *** reads on pages with R=1 already tested in 11.3.1.1.4 .8byte 0x0, 0x1, write_mxr_sum # set sstatus.[MXR, SUM] = 01. .8byte 0x40612348, 0x0330DEADBEEF0440, read64_test # load page fault when R=0, sstatus.MXR=0 .8byte 0x0, 0x3, write_mxr_sum # set sstatus.[MXR, SUM] = 11. .8byte 0x40612348, 0x0330DEADBEEF0440, read64_test # read success when MXR=1, X=1 -# test 8.3.1.3.4 Write flag +# test 11.3.1.3.4 Write flag .8byte 0x80AAAAA0, 0x0440DEADBEEF0110, write64_test# write success when W=1 .8byte 0x80AAAAA0, 0x0440DEADBEEF0110, read64_test# check write success by reading the same address .8byte 0x40000000, 0x0220DEADBEEF0BB0, write64_test# store page fault when W=0 -# test 8.3.1.3.5 eXecute flag -# *** fetches on pages with X = 1 already tested in 8.3.1.3.1 +# test 11.3.1.3.5 eXecute flag +# *** fetches on pages with X = 1 already tested in 11.3.1.3.1 .8byte 0x5AA0, 0x1, executable_test # instr page fault when X=0 # In the following two tests, SVADU is not supported, so the software handles the A/D bits # Since SVADU is 0, Accesses to A/D=0 causes a fault for the trap handler to fix those bits -# test 8.3.1.3.6 Accessed flag == 0 +# test 11.3.1.3.6 Accessed flag == 0 .8byte 0x36D0, 0x0990DEADBEEF0770, write64_test# store page fault when A=0 .8byte 0x3AB8, 0x0990DEADBEEF0990, read64_test# load page fault when A=0 -# test 8.3.1.3.7 Dirty flag == 0 +# test 11.3.1.3.7 Dirty flag == 0 .8byte 0x4658, 0x0440DEADBEEF0AA0, write64_test# store page fault when D=0 .8byte 0x4AA0, 0x0440DEADBEEF0BB0, read64_test# read success when D=0 -# =========== test 8.3.1.4 SATP Register =========== +# test 11.3.1.3.8 Reserved bits nonzero +.8byte 0x7AA0, 0x123456789ABCDEF, read64_test # load page fault because reserved is nonzero -# test 8.3.1.4.1 SATP ASID and PPN fields (test having two page tables with different ASID) +# =========== test 11.3.1.4 SATP Register =========== + +# test 11.3.1.4.1 SATP ASID and PPN fields (test having two page tables with different ASID) // *** .8byte 0xFFFFFFFFFFFFF888, 0x0220DEADBEEF0099, write64_test # write identical value to global PTE to make sure it's still in the TLB .8byte 0x8FFFF, 0x11, goto_sv39 # go to SV39 on a second, very minimal page table .8byte 0x200AB0, 0x0000DEADBEEF0000, read64_test # Read success of old written value from a new page table mapping -# test 8.3.1.4.2 Test Global mapping +# test 11.3.1.4.2 Test Global mapping // ***.8byte 0x7FFFFFF888, 0x0220DEADBEEF0099, read64_test # read success of global PTE undefined in current mapping. -# =========== test 8.3.1.5 STATUS Registers =========== +# =========== test 11.3.1.5 STATUS Registers =========== -# test 8.3.1.5.1 mstatus.mprv translation +# test 11.3.1.5.1 mstatus.mprv translation # *** mstatus.mprv = 0 tested on every one of the translated reads and writes before this. .8byte 0x8000D, 0x0, goto_sv39 // go back to old, extensive page table .8byte 0x80000000, 0x1, goto_m_mode // go to m mode to be able to write mstatus .8byte 0x1, 0x1, read_write_mprv // write 1 to mstatus.mprv and set mstatus.mpp to be 01=S .8byte 0xFFFFFFFFFFFFF888, 0x0220DEADBEEF0099, read64_test // read test succeeds with translation even though we're in M mode since MPP=S and MPRV=1 -# test 8.3.1.5.2 mstatus.mprv clearing +# test 11.3.1.5.2 mstatus.mprv clearing # mstatus.mprv is already 1 from the last test so going to S mode should clear it with the mret .8byte 0x80000000, 0x1, goto_s_mode // This should zero out the mprv bit but now to read and write mstatus, we have to .8byte 0x80000000, 0x1, goto_m_mode // go back to m mode to allow us to reread mstatus. .8byte 0x0, 0x0, read_write_mprv // read what should be a zeroed out mprv value and then force it back to zero. -# test 8.3.1.5.3 sstatus.mxr read -# this bitfield already tested in 8.3.1.3.3 +# test 11.3.1.5.3 sstatus.mxr read +# this bitfield already tested in 11.3.1.3.3 # terminate tests .8byte 0x0, 0x0, terminate_test # brings us back into machine mode with a final ecall, writing 0x9 to the output. diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-mmu-sv39-svadu-01.S b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-mmu-sv39-svadu-svnapot-svpbmt-01.S similarity index 64% rename from tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-mmu-sv39-svadu-01.S rename to tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-mmu-sv39-svadu-svnapot-svpbmt-01.S index 80df44a1a..aae04dd68 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-mmu-sv39-svadu-01.S +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-mmu-sv39-svadu-svnapot-svpbmt-01.S @@ -1,6 +1,6 @@ /////////////////////////////////////////// // -// WALLY-MMU +// WALLY-MMU-SV39-SVADU // // Author: David_Harris@hmc.edu and Kip Macsai-Goren // @@ -52,9 +52,9 @@ test_cases: # # --------------------------------------------------------------------------------------------- -# =========== test 8.3.1.1 Page Table Translation =========== +# =========== test 11.3.1.1 Page Table Translation =========== -# test 8.3.1.1.1 write page tables / entries to phyiscal memory +# test 11.3.1.1.1 write page tables / entries to phyiscal memory # sv39 page table (See Figure 12.12***): # Level 2 page table, situated at 0x8000D000 .8byte 0x000000008000D000, 0x0000000020004C01, write64_test# points to level 1 page table A @@ -82,6 +82,27 @@ test_cases: .8byte 0x0000000080018020, 0x0000000020080C57, write64_test# Vaddr 0x4000 Paddr 0x80203000: D=0, should cause write fault .8byte 0x0000000080018028, 0x00000000200814C7, write64_test# Vaddr 0x5000 Paddr 0x80205000: X=0, fetches should fault .8byte 0x0000000080018030, 0x00000000200814C0, write64_test# Vaddr 0x6000: invalid page +.8byte 0x0000000080018038, 0x01000000200800DF, write64_test# Vaddr 0x7000, Paddr = 0x80200000, bad reserved bit +.8byte 0x0000000080018040, 0x20000000200800DF, write64_test# Vaddr 0x8000, Paddr = 0x80200000, PBMT = 1 +.8byte 0x0000000080018048, 0x40000000200800DF, write64_test# Vaddr 0x9000, Paddr = 0x80200000, PMBT = 2 +.8byte 0x0000000080018050, 0x60000000200800DF, write64_test# Vaddr 0xA000, Paddr = 0x80200000, PMBT = 3 +.8byte 0x0000000080018080, 0x80000000200800DF, write64_test# Vaddr 0x10000, Paddr = 0x80200000, NAPOT +.8byte 0x0000000080018088, 0x80000000200800DF, write64_test# Vaddr 0x10000, Paddr = 0x80200000, NAPOT +.8byte 0x0000000080018090, 0x80000000200800DF, write64_test# Vaddr 0x10000, Paddr = 0x80200000, NAPOT +.8byte 0x0000000080018098, 0x80000000200800DF, write64_test# Vaddr 0x10000, Paddr = 0x80200000, NAPOT +.8byte 0x00000000800180A0, 0x80000000200800DF, write64_test# Vaddr 0x10000, Paddr = 0x80200000, NAPOT +.8byte 0x00000000800180A8, 0x80000000200800DF, write64_test# Vaddr 0x10000, Paddr = 0x80200000, NAPOT +.8byte 0x00000000800180B0, 0x80000000200800DF, write64_test# Vaddr 0x10000, Paddr = 0x80200000, NAPOT +.8byte 0x00000000800180B8, 0x80000000200800DF, write64_test# Vaddr 0x10000, Paddr = 0x80200000, NAPOT +.8byte 0x00000000800180C0, 0x80000000200800DF, write64_test# Vaddr 0x10000, Paddr = 0x80200000, NAPOT +.8byte 0x00000000800180C8, 0x80000000200800DF, write64_test# Vaddr 0x10000, Paddr = 0x80200000, NAPOT +.8byte 0x00000000800180D0, 0x80000000200800DF, write64_test# Vaddr 0x10000, Paddr = 0x80200000, NAPOT +.8byte 0x00000000800180D8, 0x80000000200800DF, write64_test# Vaddr 0x10000, Paddr = 0x80200000, NAPOT +.8byte 0x00000000800180E0, 0x80000000200800DF, write64_test# Vaddr 0x10000, Paddr = 0x80200000, NAPOT +.8byte 0x00000000800180E8, 0x80000000200800DF, write64_test# Vaddr 0x10000, Paddr = 0x80200000, NAPOT +.8byte 0x00000000800180F0, 0x80000000200800DF, write64_test# Vaddr 0x10000, Paddr = 0x80200000, NAPOT +.8byte 0x00000000800180F8, 0x80000000200800DF, write64_test# Vaddr 0x10000, Paddr = 0x80200000, NAPOT + # Level 0 page table B .8byte 0x0000000080016FF8, 0x00000000200804CF, write64_test# Vaddr 0xFFFFFFFFFFFFF000, Paddr 0x80201000 aligned kilopage @@ -89,19 +110,21 @@ test_cases: .8byte 0x8FFFF000, 0x200000CF, write64_test# Vaddr 0x0, Paddr 0x80000000 aligned gigapage .8byte 0x8FFFF010, 0x200000CF, write64_test# Vaddr 0x8000_0000, Paddr 0x80000000: aligned gigapage (program and data memory so we can execute without jumping around) -# test 8.3.1.1.2 write values to Paddrs in each page -# each of these values is used for 8.3.1.1.3 and some other tests, specified in the comments. +# test 11.3.1.1.2 write values to Paddrs in each page +# each of these values is used for 11.3.1.1.3 and some other tests, specified in the comments. # when a test is supposed to fault, nothing is written into where it'll be reading/executing since it shuold fault before getting there. -.8byte 0x80200AB0, 0x0000DEADBEEF0000, write64_test# 8.3.1.1.4 and 8.3.1.4.1 -.8byte 0x800FFAB8, 0x0880DEADBEEF0055, write64_test# 8.3.1.1.4 -.8byte 0x80200AC0, 0x0990DEADBEEF0033, write64_test# 8.3.1.3.2 -.8byte 0x80203130, 0x0110DEADBEEF0077, write64_test# 8.3.1.3.2 -.8byte 0x80099000, 0x0000806711100393, write64_test# 8.3.1.3.1 and 8.3.1.3.2 write executable code for "li x7, 0x111; ret" -.8byte 0x80205AA0, 0x0000806711100393, write64_test# 8.3.1.3.5 write same executable code -.8byte 0x80201888, 0x0220DEADBEEF0099, write64_test# 8.3.1.1.4 -.8byte 0x84212348, 0x0330DEADBEEF0440, write64_test# 8.3.1.3.3 +.8byte 0x80200AB0, 0x0000DEADBEEF0000, write64_test # 11.3.1.1.4 and 11.3.1.4.1 +.8byte 0x800FFAB8, 0x0880DEADBEEF0055, write64_test # 11.3.1.1.4 +.8byte 0x80200AC0, 0x0990DEADBEEF0033, write64_test # 11.3.1.3.2 +.8byte 0x80203130, 0x0110DEADBEEF0077, write64_test # 11.3.1.3.2 +.8byte 0x80099000, 0x0000806711100393, write64_test # 11.3.1.3.1 and 11.3.1.3.2 write executable code for "li x7, 0x111; ret" +.8byte 0x80205AA0, 0x0000806711100393, write64_test # 11.3.1.3.5 write same executable code +.8byte 0x80201888, 0x0220DEADBEEF0099, write64_test # 11.3.1.1.4 +.8byte 0x84212348, 0x0330DEADBEEF0440, write64_test # 11.3.1.3.3 +.8byte 0x8020A400, 0x0550DEADBEEF0660, write64_test # 11.3.1.3.9 +.8byte 0x80205000, 0x0770DEADBEEF0880, write64_test # 11.3.1.2.2 junk in memory location corresponding to invalid page -# test 8.3.1.1.3 read values back from Paddrs without translation (this also verifies the previous test) +# test 11.3.1.1.3 read values back from Paddrs without translation (this also verifies the previous test) .8byte 0x0, 0x0, goto_baremetal# satp.MODE = baremetal / no translation. .8byte 0x0, 0x0, goto_s_mode # change to S mode, 0xb written to output .8byte 0x80200AB0, 0x0000DEADBEEF0000, read64_test @@ -111,42 +134,42 @@ test_cases: .8byte 0x80201888, 0x0220DEADBEEF0099, read64_test .8byte 0x84212348, 0x0330DEADBEEF0440, read64_test -# test 8.3.1.1.4 check translation works in sv39, read the same values from previous tests, this time with Vaddrs +# test 11.3.1.1.4 check translation works in sv39, read the same values from previous tests, this time with Vaddrs .8byte 0x8000D, 0x0, goto_sv39 # satp.MODE = sv39, with base page table PPN = 0x8000D and ASID = 0. current VPN: gigapage at 0x80000000. .8byte 0x80200AB0, 0x0000DEADBEEF0000, read64_test # gigapage at Vaddr 0x80000000, Paddr 0x80000000 .8byte 0x400FFAB8, 0x0880DEADBEEF0055, read64_test # megapage at Vaddr 0x40400000, Paddr 0x80000000 .8byte 0xFFFFFFFFFFFFF888, 0x0220DEADBEEF0099, read64_test # kilopage at Vaddr 0xFFFFFFFFFFFFF000, Paddr 0x80201000 -# =========== test 8.3.1.2 page fault tests =========== +# =========== test 11.3.1.2 page fault tests =========== -# test 8.3.1.2.1 load page fault if upper bits of Vaddr are not the same +# test 11.3.1.2.1 load page fault if upper bits of Vaddr are not the same .8byte 0x0010000080000AB0, 0x0, read64_test# gigapage at Vaddr 0x80000000, Paddr 0x80000000, bad 1 in upper bits .8byte 0xFF0FFFFFFFFFF888, 0x0, read64_test# kilopage at Vaddr 0xFFFFFFFFFFFFF000, Paddr 0x80201000, bad 0000 in upper bits -# test 8.3.1.2.2 load page fault when reading an address where the valid flag is zero +# test 11.3.1.2.2 load page fault when reading an address where the valid flag is zero .8byte 0x6000, 0x0, read64_test -# test 8.3.1.2.3 store page fault if PTE has W and ~R flags set +# test 11.3.1.2.3 store page fault if PTE has W and ~R flags set .8byte 0x2000, 0x0, write64_test -# test 8.3.1.2.4 Fault if last level PTE is a pointer +# test 11.3.1.2.4 Fault if last level PTE is a pointer .8byte 0x0020, 0x0, read64_test -# test 8.3.1.2.5 load page fault on misaligned pages +# test 11.3.1.2.5 load page fault on misaligned pages .8byte 0xC0000000, 0x0, read64_test# misaligned gigapage .8byte 0x40200000, 0x0, read64_test# misaligned megapage -# =========== test 8.3.1.3 PTE Protection flags =========== +# =========== test 11.3.1.3 PTE Protection flags =========== -# test 8.3.1.3.1 User flag == 0 -# *** reads on pages with U=0 already tested in 8.3.1.1.4 +# test 11.3.1.3.1 User flag == 0 +# *** reads on pages with U=0 already tested in 11.3.1.1.4 .8byte 0x40099000, 0x111, executable_test # execute success when U=0, priv=S .8byte 0x40400000, 0x2, goto_u_mode # go to U mode, return to megapage at 0x40400000 where U = 1. 0x9 written to output .8byte 0xFFFFFFFFFFFFFC80, 0x0880DEADBEEF0550, read64_test # load page fault when U=0, priv=U .8byte 0x40099000, 0xbad, executable_test # execute fault when U=0, priv=U -# test 8.3.1.3.2 User flag == 1 +# test 11.3.1.3.2 User flag == 1 .8byte 0x1AC0, 0x0990DEADBEEF0033, read64_test # read success when U=1, priv=U .8byte 0x80000000, 0x1, goto_s_mode # go back to S mode, return to gigapage at 0x80000000 where U = 0. 0x8 written to output .8byte 0x0, 0x3, write_mxr_sum # set sstatus.[MXR, SUM] = 11 @@ -155,60 +178,77 @@ test_cases: .8byte 0x0, 0x2, write_mxr_sum # set sstatus.[MXR, SUM] = 10. .8byte 0x1AC0, 0x0990DEADBEEF0033, read64_test # load page fault when U-1, priv=S, sstatus.SUM=0 -# test 8.3.1.3.3 Read flag -# *** reads on pages with R=1 already tested in 8.3.1.1.4 +# test 11.3.1.3.3 Read flag +# *** reads on pages with R=1 already tested in 11.3.1.1.4 .8byte 0x0, 0x1, write_mxr_sum # set sstatus.[MXR, SUM] = 01. .8byte 0x40612348, 0x0330DEADBEEF0440, read64_test # load page fault when R=0, sstatus.MXR=0 .8byte 0x0, 0x3, write_mxr_sum # set sstatus.[MXR, SUM] = 11. .8byte 0x40612348, 0x0330DEADBEEF0440, read64_test # read success when MXR=1, X=1 -# test 8.3.1.3.4 Write flag +# test 11.3.1.3.4 Write flag .8byte 0x80AAAAA0, 0x0440DEADBEEF0110, write64_test# write success when W=1 .8byte 0x80AAAAA0, 0x0440DEADBEEF0110, read64_test# check write success by reading the same address .8byte 0x40000000, 0x0220DEADBEEF0BB0, write64_test# store page fault when W=0 -# test 8.3.1.3.5 eXecute flag -# *** fetches on pages with X = 1 already tested in 8.3.1.3.1 +# test 11.3.1.3.5 eXecute flag +# *** fetches on pages with X = 1 already tested in 11.3.1.3.1 .8byte 0x5AA0, 0x1, executable_test # instr page fault when X=0 # In the following two tests, SVADU is supported, so the hardware handles the A/D bits # Since SVADU is 1, there are no faults when A/D=0 -# test 8.3.1.3.6 Accessed flag == 0 +# test 11.3.1.3.6 Accessed flag == 0 .8byte 0x36D0, 0x0990DEADBEEF0770, write64_test # Write success when A=0 and SVADU is enabled .8byte 0x36D0, 0x0990DEADBEEF0770, read64_test # Read success when A=0 and SVADU is enabled -# test 8.3.1.3.7 Dirty flag == 0 +# test 11.3.1.3.7 Dirty flag == 0 .8byte 0x4658, 0x0440DEADBEEF0AA0, write64_test # Write success when D=0 and SVADU is enabled .8byte 0x4658, 0x0440DEADBEEF0AA0, read64_test # read success when D=0 -# =========== test 8.3.1.4 SATP Register =========== +# test 11.3.1.3.8 Reserved bits nonzero +.8byte 0x7AA0, 0x123456789ABCDEF, read64_test # load page fault because reserved is nonzero -# test 8.3.1.4.1 SATP ASID and PPN fields (test having two page tables with different ASID) +# test 11.3.1.3.9 NAPOT read +.8byte 0x1A400, 0x0550DEADBEEF0660, read64_test # read from NAPOT 64 KiB page + +# test 11.3.1.3.10 PBMT checks +.8byte 0x8040, 0x1212343456567878, write64_test # Write fault with PBMT when menvcfg.PBMTE = 0 +.8byte 0x0, 0x0, goto_m_mode # change to M mode, 0x9 written to output +.8byte 0x0, 0x4000000000000000, write_menvcfg # set menvcfg.PBMTE = 1 +.8byte 0x0, 0x0, goto_s_mode # change to S mode, 0xb written to output +.8byte 0x8040, 0x1212343456567878, write64_test # Write success with PBMT = 1 +.8byte 0x8040, 0x1212343456567878, read64_test # Read back success with PBMT = 1 +.8byte 0x9050, 0x2312343456567878, write64_test # Write success with PBMT = 2 +.8byte 0x9050, 0x2312343456567878, read64_test # Read back success with PBMT = 2 +.8byte 0xA060, 0x3412343456567878, write64_test # Write faults with PBMT = 3 + +# =========== test 11.3.1.4 SATP Register =========== + +# test 11.3.1.4.1 SATP ASID and PPN fields (test having two page tables with different ASID) // *** .8byte 0xFFFFFFFFFFFFF888, 0x0220DEADBEEF0099, write64_test # write identical value to global PTE to make sure it's still in the TLB .8byte 0x8FFFF, 0x11, goto_sv39 # go to SV39 on a second, very minimal page table .8byte 0x200AB0, 0x0000DEADBEEF0000, read64_test # Read success of old written value from a new page table mapping -# test 8.3.1.4.2 Test Global mapping +# test 11.3.1.4.2 Test Global mapping // ***.8byte 0x7FFFFFF888, 0x0220DEADBEEF0099, read64_test # read success of global PTE undefined in current mapping. -# =========== test 8.3.1.5 STATUS Registers =========== +# =========== test 11.3.1.5 STATUS Registers =========== -# test 8.3.1.5.1 mstatus.mprv translation +# test 11.3.1.5.1 mstatus.mprv translation # *** mstatus.mprv = 0 tested on every one of the translated reads and writes before this. .8byte 0x8000D, 0x0, goto_sv39 // go back to old, extensive page table .8byte 0x80000000, 0x1, goto_m_mode // go to m mode to be able to write mstatus .8byte 0x1, 0x1, read_write_mprv // write 1 to mstatus.mprv and set mstatus.mpp to be 01=S .8byte 0xFFFFFFFFFFFFF888, 0x0220DEADBEEF0099, read64_test // read test succeeds with translation even though we're in M mode since MPP=S and MPRV=1 -# test 8.3.1.5.2 mstatus.mprv clearing +# test 11.3.1.5.2 mstatus.mprv clearing # mstatus.mprv is already 1 from the last test so going to S mode should clear it with the mret .8byte 0x80000000, 0x1, goto_s_mode // This should zero out the mprv bit but now to read and write mstatus, we have to .8byte 0x80000000, 0x1, goto_m_mode // go back to m mode to allow us to reread mstatus. .8byte 0x0, 0x0, read_write_mprv // read what should be a zeroed out mprv value and then force it back to zero. -# test 8.3.1.5.3 sstatus.mxr read -# this bitfield already tested in 8.3.1.3.3 +# test 11.3.1.5.3 sstatus.mxr read +# this bitfield already tested in 11.3.1.3.3 # terminate tests .8byte 0x0, 0x0, terminate_test # brings us back into machine mode with a final ecall, writing 0x9 to the output. diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-mmu-sv48-01.S b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-mmu-sv48-01.S index ce2685428..bb49f3e7a 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-mmu-sv48-01.S +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-mmu-sv48-01.S @@ -1,6 +1,6 @@ /////////////////////////////////////////// // -// WALLY-MMU +// WALLY-MMU-SV48 // // Author: David_Harris@hmc.edu and Kip Macsai-Goren // @@ -54,9 +54,9 @@ test_cases: # --------------------------------------------------------------------------------------------- -# =========== test 8.3.1.1 Page Table Translation =========== +# =========== test 11.3.1.1 Page Table Translation =========== -# test 8.3.1.1.1 write page tables / entries to phyiscal memory +# test 11.3.1.1.1 write page tables / entries to phyiscal memory # sv48 page table (See Figure 12.12***): # Level 3 page table, situated at 0x8000D000 .8byte 0x000000008000D000, 0x0000000020004C01, write64_test # points to level 2 page table A @@ -101,22 +101,22 @@ test_cases: .8byte 0x8002F010, 0x200000CF, write64_test # Vaddr 0x80000000, Paddr 0x80000000: aligned gigapage (data and instr memory) -# test 8.3.1.1.2 write values to Paddrs in each page -# each of these values is used for 8.3.1.1.3 and some other tests, specified in the comments. +# test 11.3.1.1.2 write values to Paddrs in each page +# each of these values is used for 11.3.1.1.3 and some other tests, specified in the comments. # when a test is supposed to fault, nothing is written into where it'll be reading/executing since it should fault before getting there. -.8byte 0x82777778, 0x0EE0DEADBEEF0CC0, write64_test # 8.3.1.1.4 terapage -.8byte 0x85BC0AB0, 0x0000DEADBEEF0000, write64_test # 8.3.1.1.4 gigapage -.8byte 0x800F0AB8, 0x0880DEADBEEF0055, write64_test # 8.3.1.1.4 megapage -.8byte 0x80201888, 0x0220DEADBEEF0099, write64_test # 8.3.1.1.4 kilopage -.8byte 0x80099000, 0x0000806711100393, write64_test # 8.3.1.3.1 write executable code for "li x7, 0x111; ret" -.8byte 0x80200400, 0x0000806711100393, write64_test # 8.3.1.3.2 write same executable code -.8byte 0x80200AC0, 0x0990DEADBEEF0033, write64_test # 8.3.1.3.2 -.8byte 0x80200130, 0x0110DEADBEEF0077, write64_test # 8.3.1.3.2 -.8byte 0x85212348, 0x0330DEADBEEF0440, write64_test # 8.3.1.3.3 -.8byte 0x88888000, 0x0000806711100393, write64_test # 8.3.1.3.5 write same executable code -.8byte 0x80203AA0, 0x0440DEADBEEF0BB0, write64_test # 8.3.1.3.7 +.8byte 0x82777778, 0x0EE0DEADBEEF0CC0, write64_test # 11.3.1.1.4 terapage +.8byte 0x85BC0AB0, 0x0000DEADBEEF0000, write64_test # 11.3.1.1.4 gigapage +.8byte 0x800F0AB8, 0x0880DEADBEEF0055, write64_test # 11.3.1.1.4 megapage +.8byte 0x80201888, 0x0220DEADBEEF0099, write64_test # 11.3.1.1.4 kilopage +.8byte 0x80099000, 0x0000806711100393, write64_test # 11.3.1.3.1 write executable code for "li x7, 0x111; ret" +.8byte 0x80200400, 0x0000806711100393, write64_test # 11.3.1.3.2 write same executable code +.8byte 0x80200AC0, 0x0990DEADBEEF0033, write64_test # 11.3.1.3.2 +.8byte 0x80200130, 0x0110DEADBEEF0077, write64_test # 11.3.1.3.2 +.8byte 0x85212348, 0x0330DEADBEEF0440, write64_test # 11.3.1.3.3 +.8byte 0x88888000, 0x0000806711100393, write64_test # 11.3.1.3.5 write same executable code +.8byte 0x80203AA0, 0x0440DEADBEEF0BB0, write64_test # 11.3.1.3.7 -# test 8.3.1.1.3 read values back from Paddrs without translation (this also verifies the previous test) +# test 11.3.1.1.3 read values back from Paddrs without translation (this also verifies the previous test) .8byte 0x0, 0x0, goto_baremetal # satp.MODE = baremetal / no translation. .8byte 0x0, 0x0, goto_s_mode # change to S mode, 0xb written to output .8byte 0x82777778, 0x0EE0DEADBEEF0CC0, read64_test @@ -128,43 +128,43 @@ test_cases: .8byte 0x85212348, 0x0330DEADBEEF0440, read64_test .8byte 0x80203AA0, 0x0440DEADBEEF0BB0, read64_test -# test 8.3.1.1.4 check translation works in sv48, read the same values from previous tests, this time with Vaddrs +# test 11.3.1.1.4 check translation works in sv48, read the same values from previous tests, this time with Vaddrs .8byte 0x8000D, 0x0, goto_sv48 # satp.MODE = sv48, with base page table PPN = 0x8000D and ASID = 0. current VPN: megapage at 0x80000000. Nothing written to output .8byte 0x10082777778, 0x0EE0DEADBEEF0CC0, read64_test # terapage at Vaddr 0x010000000000, Paddr 0x0 .8byte 0x8005BC0AB0, 0x0000DEADBEEF0000, read64_test # gigapage at Vaddr 0x008000000000, Paddr 0x80000000 .8byte 0x800F0AB8, 0x0880DEADBEEF0055, read64_test # megapage at Vaddr 0x80000000, Paddr 0x80000000 .8byte 0xFFFFFFFFFFFFF888, 0x0220DEADBEEF0099, read64_test # kilopage at Vaddr 0xFFFFFFFFFFFFF000, Paddr 0x80201000 -# =========== test 8.3.1.2 page fault tests =========== +# =========== test 11.3.1.2 page fault tests =========== -# test 8.3.1.2.1 page fault if upper bits of Vaddr are not the same +# test 11.3.1.2.1 page fault if upper bits of Vaddr are not the same .8byte 0x001000800ABC0AB0, 0x0, read64_test# gigapage at Vaddr 0x008000000000, Paddr 0x80000000, bad 1 in upper bits .8byte 0xFF0FFFFFFFFFF888, 0x0, read64_test# kilopage at Vaddr 0xFFFFFFFFFFFFF000, Paddr 0x80201000, bad 0000 in upper bits -# test 8.3.1.2.2 read fault when reading an address where the valid flag is zero +# test 11.3.1.2.2 read fault when reading an address where the valid flag is zero .8byte 0x80205000, 0x0, read64_test -# test 8.3.1.2.3 write fault if PTE has W and ~R flags set +# test 11.3.1.2.3 write fault if PTE has W and ~R flags set .8byte 0x80202000, 0x0, write64_test -# test 8.3.1.2.4 Fault if last level PTE is a pointer +# test 11.3.1.2.4 Fault if last level PTE is a pointer .8byte 0x80200000, 0x0, read64_test -# test 8.3.1.2.5 read fault on misaligned pages +# test 11.3.1.2.5 read fault on misaligned pages .8byte 0x18000000000, 0x0, read64_test # misaligned terapage .8byte 0x8080000000, 0x0, read64_test # misaligned gigapage .8byte 0x80400000, 0x0, read64_test # misaligned megapage -# =========== test 8.3.1.3 PTE Protection flags =========== +# =========== test 11.3.1.3 PTE Protection flags =========== -# test 8.3.1.3.1 User flag == 0 -# reads on pages with U=0 already tested in 8.3.1.1.4 +# test 11.3.1.3.1 User flag == 0 +# reads on pages with U=0 already tested in 11.3.1.1.4 .8byte 0x008000099000, 0x111, executable_test # execute success when U=0, priv=S .8byte 0x008040000000, 0x1, goto_u_mode # go to U mode, return to gigapage at 0x008040000000 where PTE.U = 1. 0x9 written to output .8byte 0xFFFFFFFFFFFFFC80, 0x0880DEADBEEF0550, read64_test # read fault when U=0, priv=U .8byte 0x008000099000, 0xbad, executable_test # execute fault when U=0, priv=U -# test 8.3.1.3.2 User flag == 1 +# test 11.3.1.3.2 User flag == 1 .8byte 0x80201AC0, 0x0990DEADBEEF0033, read64_test # read success when U=1, priv=U .8byte 0x80000000, 0x2, goto_s_mode .8byte 0x0, 0x3, write_mxr_sum # set sstatus.[MXR, SUM] = 11 @@ -173,61 +173,61 @@ test_cases: .8byte 0x0, 0x2, write_mxr_sum # set sstatus.[MXR, SUM] = 10. .8byte 0x80201AC0, 0x0990DEADBEEF0033, read64_test # read fault when U=1, priv=S, sstatus.SUM=0 -# test 8.3.1.3.3 Read flag -# reads on pages with R=1 already tested in 8.3.1.1.4 +# test 11.3.1.3.3 Read flag +# reads on pages with R=1 already tested in 11.3.1.1.4 .8byte 0x0, 0x1, write_mxr_sum # set sstatus.[MXR, SUM] = 01. .8byte 0x80612348, 0x0330DEADBEEF0440, read64_test # read fault when R=0, sstatus.MXR=0 .8byte 0x0, 0x3, write_mxr_sum # set sstatus.[MXR, SUM] = 11. .8byte 0x80612348, 0x0330DEADBEEF0440, read64_test # read success when MXR=1, X=1 -# test 8.3.1.3.4 Write flag +# test 11.3.1.3.4 Write flag .8byte 0x10080BCDED8, 0x0440DEADBEEF0110, write64_test # write success when W=1 (corresponding Paddr = 0x80BCDED8) .8byte 0x10080BCDED8, 0x0440DEADBEEF0110, read64_test # check write success by reading value back .8byte 0x8000009E88, 0x0220DEADBEEF0BB0, write64_test # write fault when W=0 -# test 8.3.1.3.5 eXecute flag -# executes on pages with X = 1 already tested in 8.3.1.3.1 +# test 11.3.1.3.5 eXecute flag +# executes on pages with X = 1 already tested in 11.3.1.3.1 .8byte 0x010088888000, 0x2, executable_test # execute fault when X=0 # In the following two tests, SVADU is not supported, so the software handles the A/D bits # Since SVADU is 0, Accesses to A/D=0 causes a fault for the trap handler to fix those bits -# test 8.3.1.3.6 Accessed flag == 0 +# test 11.3.1.3.6 Accessed flag == 0 .8byte 0x802036D0, 0x0990DEADBEEF0770, write64_test # write fault when A=0 .8byte 0x80203AB8, 0x0990DEADBEEF0990, read64_test# read fault when A=0 -# test 8.3.1.3.7 Dirty flag == 0 +# test 11.3.1.3.7 Dirty flag == 0 .8byte 0x80204658, 0x0440DEADBEEF0AA0, write64_test # write fault when D=0 .8byte 0x80204AA0, 0x0440DEADBEEF0BB0, read64_test# read success when D=0 -# =========== test 8.3.1.4 SATP Register =========== +# =========== test 11.3.1.4 SATP Register =========== -# test 8.3.1.4.1 SATP ASID and PPN fields (test having two page tables with different ASID) +# test 11.3.1.4.1 SATP ASID and PPN fields (test having two page tables with different ASID) // *** .8byte 0xFFFFFFFFFFFFF888, 0x0220DEADBEEF0099, write64_test # write identical value to global PTE to make sure it's still in the TLB .8byte 0x8000F, 0x11, goto_sv48 # go to SV39 on a second, very minimal page table .8byte 0x5BC0AB0, 0x0000DEADBEEF0000, read64_test # Read success of old written value from a new page table mapping -# test 8.3.1.4.2 Test Global mapping +# test 11.3.1.4.2 Test Global mapping // ***.8byte 0x7FFFFFF888, 0x0220DEADBEEF0099, read64_test # read success of global PTE undefined in current mapping. -# =========== test 8.3.1.5 STATUS Registers =========== +# =========== test 11.3.1.5 STATUS Registers =========== -# test 8.3.1.5.1 mstatus.mprv translation +# test 11.3.1.5.1 mstatus.mprv translation # *** mstatus.mprv = 0 tested on every one of the translated reads and writes before this. .8byte 0x8000D, 0x0, goto_sv48 // go back to old, extensive page table .8byte 0x80000000, 0x1, goto_m_mode // go to m mode to be able to write mstatus .8byte 0x1, 0x1, read_write_mprv // write 1 to mstatus.mprv and set mstatus.mpp to be 01=S .8byte 0xFFFFFFFFFFFFF888, 0x0220DEADBEEF0099, read64_test // read test succeeds with translation even though we're in M mode since MPP=S and MPRV=1 -# test 8.3.1.5.2 mstatus.mprv clearing +# test 11.3.1.5.2 mstatus.mprv clearing # mstatus.mprv is already 1 from the last test so going to S mode should clear it with the mret .8byte 0x80000000, 0x1, goto_s_mode // This should zero out the mprv bit but now to read and write mstatus, we have to .8byte 0x80000000, 0x1, goto_m_mode // go back to m mode to allow us to reread mstatus. .8byte 0x0, 0x0, read_write_mprv // read what should be a zeroed out mprv value and then force it back to zero. -# test 8.3.1.5.3 sstatus.mxr read -# this bitfield already tested in 8.3.1.3.3 +# test 11.3.1.5.3 sstatus.mxr read +# this bitfield already tested in 11.3.1.3.3 # terminate tests .8byte 0x0, 0x0, terminate_test # brings us back into machine mode with a final ecall, writing 0x9 to the output. diff --git a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-mmu-sv48-svadu-01.S b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-mmu-sv48-svadu-01.S index 9b8925fb5..dc8424f14 100644 --- a/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-mmu-sv48-svadu-01.S +++ b/tests/wally-riscv-arch-test/riscv-test-suite/rv64i_m/privilege/src/WALLY-mmu-sv48-svadu-01.S @@ -1,6 +1,6 @@ /////////////////////////////////////////// // -// WALLY-MMU +// WALLY-MMU-SV48-SVADU // // Author: David_Harris@hmc.edu and Kip Macsai-Goren // @@ -54,9 +54,9 @@ test_cases: # --------------------------------------------------------------------------------------------- -# =========== test 8.3.1.1 Page Table Translation =========== +# =========== test 11.3.1.1 Page Table Translation =========== -# test 8.3.1.1.1 write page tables / entries to phyiscal memory +# test 11.3.1.1.1 write page tables / entries to phyiscal memory # sv48 page table (See Figure 12.12***): # Level 3 page table, situated at 0x8000D000 .8byte 0x000000008000D000, 0x0000000020004C01, write64_test # points to level 2 page table A @@ -101,21 +101,21 @@ test_cases: .8byte 0x8002F010, 0x200000CF, write64_test # Vaddr 0x80000000, Paddr 0x80000000: aligned gigapage (data and instr memory) -# test 8.3.1.1.2 write values to Paddrs in each page -# each of these values is used for 8.3.1.1.3 and some other tests, specified in the comments. +# test 11.3.1.1.2 write values to Paddrs in each page +# each of these values is used for 11.3.1.1.3 and some other tests, specified in the comments. # when a test is supposed to fault, nothing is written into where it'll be reading/executing since it should fault before getting there. -.8byte 0x82777778, 0x0EE0DEADBEEF0CC0, write64_test # 8.3.1.1.4 terapage -.8byte 0x85BC0AB0, 0x0000DEADBEEF0000, write64_test # 8.3.1.1.4 gigapage -.8byte 0x800F0AB8, 0x0880DEADBEEF0055, write64_test # 8.3.1.1.4 megapage -.8byte 0x80201888, 0x0220DEADBEEF0099, write64_test # 8.3.1.1.4 kilopage -.8byte 0x80099000, 0x0000806711100393, write64_test # 8.3.1.3.1 write executable code for "li x7, 0x111; ret" -.8byte 0x80200400, 0x0000806711100393, write64_test # 8.3.1.3.2 write same executable code -.8byte 0x80200AC0, 0x0990DEADBEEF0033, write64_test # 8.3.1.3.2 -.8byte 0x80200130, 0x0110DEADBEEF0077, write64_test # 8.3.1.3.2 -.8byte 0x85212348, 0x0330DEADBEEF0440, write64_test # 8.3.1.3.3 -.8byte 0x88888000, 0x0000806711100393, write64_test # 8.3.1.3.5 write same executable code +.8byte 0x82777778, 0x0EE0DEADBEEF0CC0, write64_test # 11.3.1.1.4 terapage +.8byte 0x85BC0AB0, 0x0000DEADBEEF0000, write64_test # 11.3.1.1.4 gigapage +.8byte 0x800F0AB8, 0x0880DEADBEEF0055, write64_test # 11.3.1.1.4 megapage +.8byte 0x80201888, 0x0220DEADBEEF0099, write64_test # 11.3.1.1.4 kilopage +.8byte 0x80099000, 0x0000806711100393, write64_test # 11.3.1.3.1 write executable code for "li x7, 0x111; ret" +.8byte 0x80200400, 0x0000806711100393, write64_test # 11.3.1.3.2 write same executable code +.8byte 0x80200AC0, 0x0990DEADBEEF0033, write64_test # 11.3.1.3.2 +.8byte 0x80200130, 0x0110DEADBEEF0077, write64_test # 11.3.1.3.2 +.8byte 0x85212348, 0x0330DEADBEEF0440, write64_test # 11.3.1.3.3 +.8byte 0x88888000, 0x0000806711100393, write64_test # 11.3.1.3.5 write same executable code -# test 8.3.1.1.3 read values back from Paddrs without translation (this also verifies the previous test) +# test 11.3.1.1.3 read values back from Paddrs without translation (this also verifies the previous test) .8byte 0x0, 0x0, goto_baremetal # satp.MODE = baremetal / no translation. .8byte 0x0, 0x0, goto_s_mode # change to S mode, 0xb written to output .8byte 0x82777778, 0x0EE0DEADBEEF0CC0, read64_test @@ -126,43 +126,43 @@ test_cases: .8byte 0x80201888, 0x0220DEADBEEF0099, read64_test .8byte 0x85212348, 0x0330DEADBEEF0440, read64_test -# test 8.3.1.1.4 check translation works in sv48, read the same values from previous tests, this time with Vaddrs +# test 11.3.1.1.4 check translation works in sv48, read the same values from previous tests, this time with Vaddrs .8byte 0x8000D, 0x0, goto_sv48 # satp.MODE = sv48, with base page table PPN = 0x8000D and ASID = 0. current VPN: megapage at 0x80000000. Nothing written to output .8byte 0x10082777778, 0x0EE0DEADBEEF0CC0, read64_test # terapage at Vaddr 0x010000000000, Paddr 0x0 .8byte 0x8005BC0AB0, 0x0000DEADBEEF0000, read64_test # gigapage at Vaddr 0x008000000000, Paddr 0x80000000 .8byte 0x800F0AB8, 0x0880DEADBEEF0055, read64_test # megapage at Vaddr 0x80000000, Paddr 0x80000000 .8byte 0xFFFFFFFFFFFFF888, 0x0220DEADBEEF0099, read64_test # kilopage at Vaddr 0xFFFFFFFFFFFFF000, Paddr 0x80201000 -# =========== test 8.3.1.2 page fault tests =========== +# =========== test 11.3.1.2 page fault tests =========== -# test 8.3.1.2.1 page fault if upper bits of Vaddr are not the same +# test 11.3.1.2.1 page fault if upper bits of Vaddr are not the same .8byte 0x001000800ABC0AB0, 0x0, read64_test# gigapage at Vaddr 0x008000000000, Paddr 0x80000000, bad 1 in upper bits .8byte 0xFF0FFFFFFFFFF888, 0x0, read64_test# kilopage at Vaddr 0xFFFFFFFFFFFFF000, Paddr 0x80201000, bad 0000 in upper bits -# test 8.3.1.2.2 read fault when reading an address where the valid flag is zero +# test 11.3.1.2.2 read fault when reading an address where the valid flag is zero .8byte 0x80205000, 0x0, read64_test -# test 8.3.1.2.3 write fault if PTE has W and ~R flags set +# test 11.3.1.2.3 write fault if PTE has W and ~R flags set .8byte 0x80202000, 0x0, write64_test -# test 8.3.1.2.4 Fault if last level PTE is a pointer +# test 11.3.1.2.4 Fault if last level PTE is a pointer .8byte 0x80200000, 0x0, read64_test -# test 8.3.1.2.5 read fault on misaligned pages +# test 11.3.1.2.5 read fault on misaligned pages .8byte 0x18000000000, 0x0, read64_test # misaligned terapage .8byte 0x8080000000, 0x0, read64_test # misaligned gigapage .8byte 0x80400000, 0x0, read64_test # misaligned megapage -# =========== test 8.3.1.3 PTE Protection flags =========== +# =========== test 11.3.1.3 PTE Protection flags =========== -# test 8.3.1.3.1 User flag == 0 -# reads on pages with U=0 already tested in 8.3.1.1.4 +# test 11.3.1.3.1 User flag == 0 +# reads on pages with U=0 already tested in 11.3.1.1.4 .8byte 0x008000099000, 0x111, executable_test # execute success when U=0, priv=S .8byte 0x008040000000, 0x1, goto_u_mode # go to U mode, return to gigapage at 0x008040000000 where PTE.U = 1. 0x9 written to output .8byte 0xFFFFFFFFFFFFFC80, 0x0880DEADBEEF0550, read64_test # read fault when U=0, priv=U .8byte 0x008000099000, 0xbad, executable_test # execute fault when U=0, priv=U -# test 8.3.1.3.2 User flag == 1 +# test 11.3.1.3.2 User flag == 1 .8byte 0x80201AC0, 0x0990DEADBEEF0033, read64_test # read success when U=1, priv=U .8byte 0x80000000, 0x2, goto_s_mode .8byte 0x0, 0x3, write_mxr_sum # set sstatus.[MXR, SUM] = 11 @@ -171,61 +171,61 @@ test_cases: .8byte 0x0, 0x2, write_mxr_sum # set sstatus.[MXR, SUM] = 10. .8byte 0x80201AC0, 0x0990DEADBEEF0033, read64_test # read fault when U=1, priv=S, sstatus.SUM=0 -# test 8.3.1.3.3 Read flag -# reads on pages with R=1 already tested in 8.3.1.1.4 +# test 11.3.1.3.3 Read flag +# reads on pages with R=1 already tested in 11.3.1.1.4 .8byte 0x0, 0x1, write_mxr_sum # set sstatus.[MXR, SUM] = 01. .8byte 0x80612348, 0x0330DEADBEEF0440, read64_test # read fault when R=0, sstatus.MXR=0 .8byte 0x0, 0x3, write_mxr_sum # set sstatus.[MXR, SUM] = 11. .8byte 0x80612348, 0x0330DEADBEEF0440, read64_test # read success when MXR=1, X=1 -# test 8.3.1.3.4 Write flag +# test 11.3.1.3.4 Write flag .8byte 0x10080BCDED8, 0x0440DEADBEEF0110, write64_test # write success when W=1 (corresponding Paddr = 0x80BCDED8) .8byte 0x10080BCDED8, 0x0440DEADBEEF0110, read64_test # check write success by reading value back .8byte 0x8000009E88, 0x0220DEADBEEF0BB0, write64_test # write fault when W=0 -# test 8.3.1.3.5 eXecute flag -# executes on pages with X = 1 already tested in 8.3.1.3.1 +# test 11.3.1.3.5 eXecute flag +# executes on pages with X = 1 already tested in 11.3.1.3.1 .8byte 0x010088888000, 0x2, executable_test # execute fault when X=0 # In the following two tests, SVADU is supported, so the hardware handles the A/D bits # Since SVADU is 1, there are no faults when A/D=0 -# test 8.3.1.3.6 Accessed flag == 0 +# test 11.3.1.3.6 Accessed flag == 0 .8byte 0x802036D0, 0x0990DEADBEEF0770, write64_test # Write success when A=0 and SVADU is enabled .8byte 0x802036D0, 0x0990DEADBEEF0770, read64_test # Read success when A=0 and SVADU is enabled -# test 8.3.1.3.7 Dirty flag == 0 +# test 11.3.1.3.7 Dirty flag == 0 .8byte 0x80204658, 0x0440DEADBEEF0AA0, write64_test # Write success when D=0 and SVADU is enabled .8byte 0x80204658, 0x0440DEADBEEF0AA0, read64_test # read success when D=0 -# =========== test 8.3.1.4 SATP Register =========== +# =========== test 11.3.1.4 SATP Register =========== -# test 8.3.1.4.1 SATP ASID and PPN fields (test having two page tables with different ASID) +# test 11.3.1.4.1 SATP ASID and PPN fields (test having two page tables with different ASID) // *** .8byte 0xFFFFFFFFFFFFF888, 0x0220DEADBEEF0099, write64_test # write identical value to global PTE to make sure it's still in the TLB .8byte 0x8000F, 0x11, goto_sv48 # go to SV39 on a second, very minimal page table .8byte 0x5BC0AB0, 0x0000DEADBEEF0000, read64_test # Read success of old written value from a new page table mapping -# test 8.3.1.4.2 Test Global mapping +# test 11.3.1.4.2 Test Global mapping // ***.8byte 0x7FFFFFF888, 0x0220DEADBEEF0099, read64_test # read success of global PTE undefined in current mapping. -# =========== test 8.3.1.5 STATUS Registers =========== +# =========== test 11.3.1.5 STATUS Registers =========== -# test 8.3.1.5.1 mstatus.mprv translation +# test 11.3.1.5.1 mstatus.mprv translation # *** mstatus.mprv = 0 tested on every one of the translated reads and writes before this. .8byte 0x8000D, 0x0, goto_sv48 // go back to old, extensive page table .8byte 0x80000000, 0x1, goto_m_mode // go to m mode to be able to write mstatus .8byte 0x1, 0x1, read_write_mprv // write 1 to mstatus.mprv and set mstatus.mpp to be 01=S .8byte 0xFFFFFFFFFFFFF888, 0x0220DEADBEEF0099, read64_test // read test succeeds with translation even though we're in M mode since MPP=S and MPRV=1 -# test 8.3.1.5.2 mstatus.mprv clearing +# test 11.3.1.5.2 mstatus.mprv clearing # mstatus.mprv is already 1 from the last test so going to S mode should clear it with the mret .8byte 0x80000000, 0x1, goto_s_mode // This should zero out the mprv bit but now to read and write mstatus, we have to .8byte 0x80000000, 0x1, goto_m_mode // go back to m mode to allow us to reread mstatus. .8byte 0x0, 0x0, read_write_mprv // read what should be a zeroed out mprv value and then force it back to zero. -# test 8.3.1.5.3 sstatus.mxr read -# this bitfield already tested in 8.3.1.3.3 +# test 11.3.1.5.3 sstatus.mxr read +# this bitfield already tested in 11.3.1.3.3 # terminate tests .8byte 0x0, 0x0, terminate_test # brings us back into machine mode with a final ecall, writing 0x9 to the output.