mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Merge branch 'main' of https://github.com/openhwgroup/cvw
This commit is contained in:
commit
b22350fcd7
@ -42,11 +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 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
|
||||
|
@ -44,11 +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 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
|
||||
|
@ -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
|
||||
|
@ -49,6 +49,7 @@ localparam ZICBOM_SUPPORTED = 1;
|
||||
localparam ZICBOZ_SUPPORTED = 1;
|
||||
localparam ZICBOP_SUPPORTED = 0;
|
||||
localparam SVPBMT_SUPPORTED = 0;
|
||||
localparam SVNAPOT_SUPPORTED = 0;
|
||||
localparam SVINVAL_SUPPORTED = 1;
|
||||
|
||||
// LSU microarchitectural Features
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -49,8 +49,9 @@ localparam ZFH_SUPPORTED = 0;
|
||||
localparam SSTC_SUPPORTED = 1;
|
||||
localparam ZICBOM_SUPPORTED = 1;
|
||||
localparam ZICBOZ_SUPPORTED = 1;
|
||||
localparam ZICBOP_SUPPORTED = 0;
|
||||
localparam SVPBMT_SUPPORTED = 0;
|
||||
localparam ZICBOP_SUPPORTED = 1;
|
||||
localparam SVPBMT_SUPPORTED = 1;
|
||||
localparam SVNAPOT_SUPPORTED = 1;
|
||||
localparam SVINVAL_SUPPORTED = 1;
|
||||
|
||||
// LSU microarchitectural Features
|
||||
|
@ -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
|
||||
|
@ -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<XLEN) ? (XLEN) : (NF));
|
||||
localparam CVTLEN = ((NF<XLEN) ? (XLEN) : (NF)); // max(XLEN, NF)
|
||||
localparam LLEN = (($unsigned(FLEN)<$unsigned(XLEN)) ? ($unsigned(XLEN)) : ($unsigned(FLEN)));
|
||||
localparam LOGCVTLEN = $unsigned($clog2(CVTLEN+1));
|
||||
localparam NORMSHIFTSZ = (((CVTLEN+NF+1)>(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)));
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
`include "BranchPredictorType.vh"
|
||||
|
||||
parameter cvw_t P = '{
|
||||
localparam cvw_t P = '{
|
||||
FPGA : FPGA,
|
||||
XLEN : XLEN,
|
||||
IEEE754 : IEEE754,
|
||||
@ -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,
|
||||
|
@ -60,6 +60,7 @@ typedef struct packed {
|
||||
logic ZICBOZ_SUPPORTED;
|
||||
logic ZICBOP_SUPPORTED;
|
||||
logic SVPBMT_SUPPORTED;
|
||||
logic SVNAPOT_SUPPORTED;
|
||||
logic SVINVAL_SUPPORTED;
|
||||
|
||||
// Microarchitectural Features
|
||||
|
@ -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
|
||||
|
@ -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),
|
||||
|
@ -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),
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,20 +72,22 @@ 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;
|
||||
// Sections of the page table entry
|
||||
logic [7:0] PTEAccessBits;
|
||||
logic [11:0] PTEAccessBits;
|
||||
logic [1:0] HitPageType;
|
||||
logic CAMHit;
|
||||
logic SV39Mode;
|
||||
logic Misaligned;
|
||||
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 +104,21 @@ 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,
|
||||
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,
|
||||
.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
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -29,30 +29,37 @@
|
||||
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 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,
|
||||
input logic TLBFlush, // Invalidate all TLB entries
|
||||
input logic [11: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,
|
||||
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_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, 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
|
||||
@ -65,8 +72,20 @@ 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[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];
|
||||
|
||||
// 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
|
||||
@ -74,14 +93,46 @@ 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 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;
|
||||
else assign UpdateDA = ~PTE_A;
|
||||
end else begin:dtlb // Data TLB fault checking
|
||||
logic InvalidRead, InvalidWrite;
|
||||
|
||||
@ -98,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 ;
|
||||
|
@ -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[3:0], 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
|
||||
|
@ -32,23 +32,24 @@
|
||||
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 [TLB_ENTRIES-1:0] PTE_Gs
|
||||
output logic [P.PPN_BITS-1:0] PPN,
|
||||
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)
|
||||
);
|
||||
|
||||
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) 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), .PTE_NAPOT(PTE_NAPOTs));
|
||||
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-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
|
||||
|
@ -26,16 +26,28 @@
|
||||
// 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 [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);
|
||||
|
||||
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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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] == 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;
|
||||
assign WriteSCOUNTERENM = CSRSWriteM & (CSRAdrM == SCOUNTEREN);
|
||||
assign WriteSENVCFGM = CSRSWriteM & (CSRAdrM == SENVCFG);
|
||||
assign WriteSTIMECMPM = CSRSWriteM & (CSRAdrM == STIMECMP) & STCE;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
56
src/wrappers/wallypipelinedcorewrapper.sv
Normal file
56
src/wrappers/wallypipelinedcorewrapper.sv
Normal file
@ -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
|
@ -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)
|
||||
|
@ -25,7 +25,8 @@ 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 ${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
synthDC/scripts/wrapperGen.py
Normal file
74
synthDC/scripts/wrapperGen.py
Normal file
@ -0,0 +1,74 @@
|
||||
"""
|
||||
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 = "import cvw::*;\n`include \"config.vh\"\n`include \"parameter-defs.vh\"\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"
|
||||
|
||||
|
||||
# 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)
|
@ -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
|
||||
|
@ -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",
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -1,6 +1,6 @@
|
||||
///////////////////////////////////////////
|
||||
//
|
||||
// WALLY-MMU
|
||||
// WALLY-MMU-SV32
|
||||
//
|
||||
// Author: David_Harris@hmc.edu and Kip Macsai-Goren <kmacsaigoren@g.hmc.edu>
|
||||
//
|
||||
@ -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.
|
||||
|
@ -1,6 +1,6 @@
|
||||
///////////////////////////////////////////
|
||||
//
|
||||
// WALLY-MMU
|
||||
// WALLY-MMU-SV32
|
||||
//
|
||||
// Author: David_Harris@hmc.edu and Kip Macsai-Goren <kmacsaigoren@g.hmc.edu>
|
||||
//
|
||||
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -1,6 +1,6 @@
|
||||
///////////////////////////////////////////
|
||||
//
|
||||
// WALLY-MMU
|
||||
// WALLY-MMU-SV39
|
||||
//
|
||||
// Author: David_Harris@hmc.edu and Kip Macsai-Goren <kmacsaigoren@g.hmc.edu>
|
||||
//
|
||||
@ -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.
|
||||
|
@ -1,6 +1,6 @@
|
||||
///////////////////////////////////////////
|
||||
//
|
||||
// WALLY-MMU
|
||||
// WALLY-MMU-SV39-SVADU
|
||||
//
|
||||
// Author: David_Harris@hmc.edu and Kip Macsai-Goren <kmacsaigoren@g.hmc.edu>
|
||||
//
|
||||
@ -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.
|
@ -1,6 +1,6 @@
|
||||
///////////////////////////////////////////
|
||||
//
|
||||
// WALLY-MMU
|
||||
// WALLY-MMU-SV48
|
||||
//
|
||||
// Author: David_Harris@hmc.edu and Kip Macsai-Goren <kmacsaigoren@g.hmc.edu>
|
||||
//
|
||||
@ -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.
|
||||
|
@ -1,6 +1,6 @@
|
||||
///////////////////////////////////////////
|
||||
//
|
||||
// WALLY-MMU
|
||||
// WALLY-MMU-SV48-SVADU
|
||||
//
|
||||
// Author: David_Harris@hmc.edu and Kip Macsai-Goren <kmacsaigoren@g.hmc.edu>
|
||||
//
|
||||
@ -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.
|
||||
|
Loading…
Reference in New Issue
Block a user