diff --git a/coverage/header_file.yaml b/coverage/header_file.yaml new file mode 100644 index 000000000..b7386d8f0 --- /dev/null +++ b/coverage/header_file.yaml @@ -0,0 +1,935 @@ +common: + MSTATUS_UIE: 0x00000001 + MSTATUS_SIE: 0x00000002 + MSTATUS_HIE: 0x00000004 + MSTATUS_MIE: 0x00000008 + MSTATUS_UPIE: 0x00000010 + MSTATUS_SPIE: 0x00000020 + MSTATUS_HPIE: 0x00000040 + MSTATUS_MPIE: 0x00000080 + MSTATUS_SPP: 0x00000100 + MSTATUS_HPP: 0x00000600 + MSTATUS_MPP: 0x00001800 + MSTATUS_FS: 0x00006000 + MSTATUS_VS: 0x00000600 + MSTATUS_XS: 0x00018000 + MSTATUS_MPRV: 0x00020000 + MSTATUS_SUM: 0x00040000 + MSTATUS_MXR: 0x00080000 + MSTATUS_TVM: 0x00100000 + MSTATUS_TW: 0x00200000 + MSTATUS_TSR: 0x00400000 + MSTATUS32_SD: 0x80000000 + MSTATUS_UXL: 0x0000000300000000 + MSTATUS_SXL: 0x0000000C00000000 + MSTATUS64_SD: 0x8000000000000000 + SSTATUS_UIE: 0x00000001 + SSTATUS_SIE: 0x00000002 + SSTATUS_UPIE: 0x00000010 + SSTATUS_SPIE: 0x00000020 + SSTATUS_SPP: 0x00000100 + SSTATUS_FS: 0x00006000 + SSTATUS_XS: 0x00018000 + SSTATUS_SUM: 0x00040000 + SSTATUS_MXR: 0x00080000 + SSTATUS32_SD: 0x80000000 + SSTATUS_UXL: 0x0000000300000000 + SSTATUS64_SD: 0x8000000000000000 + DCSR_CAUSE_NONE: 0 + DCSR_CAUSE_SWBP: 1 + DCSR_CAUSE_HWBP: 2 + DCSR_CAUSE_DEBUGINT: 3 + DCSR_CAUSE_STEP: 4 + DCSR_CAUSE_HALT: 5 + MCONTROL_TYPE_NONE: 0 + MCONTROL_TYPE_MATCH: 2 + MCONTROL_ACTION_DEBUG_EXCEPTION: 0 + MCONTROL_ACTION_DEBUG_MODE: 1 + MCONTROL_ACTION_TRACE_START: 2 + MCONTROL_ACTION_TRACE_STOP: 3 + MCONTROL_ACTION_TRACE_EMIT: 4 + MCONTROL_MATCH_EQUAL: 0 + MCONTROL_MATCH_NAPOT: 1 + MCONTROL_MATCH_GE: 2 + MCONTROL_MATCH_LT: 3 + MCONTROL_MATCH_MASK_LOW: 4 + MCONTROL_MATCH_MASK_HIGH: 5 + SIP_SSIP: MIP_SSIP + SIP_STIP: MIP_STIP + PRV_U: 0 + PRV_S: 1 + PRV_H: 2 + PRV_M: 3 + SATP32_MODE: 0x80000000 + SATP32_ASID: 0x7FC00000 + SATP32_PPN: 0x003FFFFF + SATP64_MODE: 0xF000000000000000 + SATP64_ASID: 0x0FFFF00000000000 + SATP64_PPN: 0x00000FFFFFFFFFFF + SATP_MODE_OFF: 0 + SATP_MODE_SV32: 1 + SATP_MODE_SV39: 8 + SATP_MODE_SV48: 9 + SATP_MODE_SV57: 10 + SATP_MODE_SV64: 11 + PMP_R: 0x01 + PMP_W: 0x02 + PMP_X: 0x04 + PMP_A: 0x18 + PMP_L: 0x80 + PMP_SHIFT: 2 + PMP_TOR: 0x08 + PMP_NA4: 0x10 + PMP_NAPOT: 0x18 + IRQ_S_SOFT: 1 + IRQ_H_SOFT: 2 + IRQ_M_SOFT: 3 + IRQ_S_TIMER: 5 + IRQ_H_TIMER: 6 + IRQ_M_TIMER: 7 + IRQ_S_EXT: 9 + IRQ_H_EXT: 10 + IRQ_M_EXT: 11 + IRQ_COP: 12 + IRQ_HOST: 13 + DEFAULT_RSTVEC: 0x00001000 + CLINT_BASE: 0x02000000 + CLINT_SIZE: 0x000c0000 + EXT_IO_BASE: 0x40000000 + DRAM_BASE: 0x80000000 + PTE_V: 0x001 + PTE_R: 0x002 + PTE_W: 0x004 + PTE_X: 0x008 + PTE_U: 0x010 + PTE_G: 0x020 + PTE_A: 0x040 + PTE_D: 0x080 + PTE_SOFT: 0x300 + PTE_PPN_SHIFT: 10 + RISCV_PGSHIFT: 12 + MATCH_BEQ: 0x63 + MASK_BEQ: 0x707f + MATCH_BNE: 0x1063 + MASK_BNE: 0x707f + MATCH_BLT: 0x4063 + MASK_BLT: 0x707f + MATCH_BGE: 0x5063 + MASK_BGE: 0x707f + MATCH_BLTU: 0x6063 + MASK_BLTU: 0x707f + MATCH_BGEU: 0x7063 + MASK_BGEU: 0x707f + MATCH_JALR: 0x67 + MASK_JALR: 0x707f + MATCH_JAL: 0x6f + MASK_JAL: 0x7f + MATCH_LUI: 0x37 + MASK_LUI: 0x7f + MATCH_AUIPC: 0x17 + MASK_AUIPC: 0x7f + MATCH_ADDI: 0x13 + MASK_ADDI: 0x707f + MATCH_SLLI: 0x1013 + MASK_SLLI: 0xfc00707f + MATCH_SLTI: 0x2013 + MASK_SLTI: 0x707f + MATCH_SLTIU: 0x3013 + MASK_SLTIU: 0x707f + MATCH_XORI: 0x4013 + MASK_XORI: 0x707f + MATCH_SRLI: 0x5013 + MASK_SRLI: 0xfc00707f + MATCH_SRAI: 0x40005013 + MASK_SRAI: 0xfc00707f + MATCH_ORI: 0x6013 + MASK_ORI: 0x707f + MATCH_ANDI: 0x7013 + MASK_ANDI: 0x707f + MATCH_ADD: 0x33 + MASK_ADD: 0xfe00707f + MATCH_SUB: 0x40000033 + MASK_SUB: 0xfe00707f + MATCH_SLL: 0x1033 + MASK_SLL: 0xfe00707f + MATCH_SLT: 0x2033 + MASK_SLT: 0xfe00707f + MATCH_SLTU: 0x3033 + MASK_SLTU: 0xfe00707f + MATCH_XOR: 0x4033 + MASK_XOR: 0xfe00707f + MATCH_SRL: 0x5033 + MASK_SRL: 0xfe00707f + MATCH_SRA: 0x40005033 + MASK_SRA: 0xfe00707f + MATCH_OR: 0x6033 + MASK_OR: 0xfe00707f + MATCH_AND: 0x7033 + MASK_AND: 0xfe00707f + MATCH_ADDIW: 0x1b + MASK_ADDIW: 0x707f + MATCH_SLLIW: 0x101b + MASK_SLLIW: 0xfe00707f + MATCH_SRLIW: 0x501b + MASK_SRLIW: 0xfe00707f + MATCH_SRAIW: 0x4000501b + MASK_SRAIW: 0xfe00707f + MATCH_ADDW: 0x3b + MASK_ADDW: 0xfe00707f + MATCH_SUBW: 0x4000003b + MASK_SUBW: 0xfe00707f + MATCH_SLLW: 0x103b + MASK_SLLW: 0xfe00707f + MATCH_SRLW: 0x503b + MASK_SRLW: 0xfe00707f + MATCH_SRAW: 0x4000503b + MASK_SRAW: 0xfe00707f + MATCH_LB: 0x3 + MASK_LB: 0x707f + MATCH_LH: 0x1003 + MASK_LH: 0x707f + MATCH_LW: 0x2003 + MASK_LW: 0x707f + MATCH_LD: 0x3003 + MASK_LD: 0x707f + MATCH_LBU: 0x4003 + MASK_LBU: 0x707f + MATCH_LHU: 0x5003 + MASK_LHU: 0x707f + MATCH_LWU: 0x6003 + MASK_LWU: 0x707f + MATCH_SB: 0x23 + MASK_SB: 0x707f + MATCH_SH: 0x1023 + MASK_SH: 0x707f + MATCH_SW: 0x2023 + MASK_SW: 0x707f + MATCH_SD: 0x3023 + MASK_SD: 0x707f + MATCH_FENCE: 0xf + MASK_FENCE: 0x707f + MATCH_FENCE_I: 0x100f + MASK_FENCE_I: 0x707f + MATCH_MUL: 0x2000033 + MASK_MUL: 0xfe00707f + MATCH_MULH: 0x2001033 + MASK_MULH: 0xfe00707f + MATCH_MULHSU: 0x2002033 + MASK_MULHSU: 0xfe00707f + MATCH_MULHU: 0x2003033 + MASK_MULHU: 0xfe00707f + MATCH_DIV: 0x2004033 + MASK_DIV: 0xfe00707f + MATCH_DIVU: 0x2005033 + MASK_DIVU: 0xfe00707f + MATCH_REM: 0x2006033 + MASK_REM: 0xfe00707f + MATCH_REMU: 0x2007033 + MASK_REMU: 0xfe00707f + MATCH_MULW: 0x200003b + MASK_MULW: 0xfe00707f + MATCH_DIVW: 0x200403b + MASK_DIVW: 0xfe00707f + MATCH_DIVUW: 0x200503b + MASK_DIVUW: 0xfe00707f + MATCH_REMW: 0x200603b + MASK_REMW: 0xfe00707f + MATCH_REMUW: 0x200703b + MASK_REMUW: 0xfe00707f + MATCH_AMOADD_W: 0x202f + MASK_AMOADD_W: 0xf800707f + MATCH_AMOXOR_W: 0x2000202f + MASK_AMOXOR_W: 0xf800707f + MATCH_AMOOR_W: 0x4000202f + MASK_AMOOR_W: 0xf800707f + MATCH_AMOAND_W: 0x6000202f + MASK_AMOAND_W: 0xf800707f + MATCH_AMOMIN_W: 0x8000202f + MASK_AMOMIN_W: 0xf800707f + MATCH_AMOMAX_W: 0xa000202f + MASK_AMOMAX_W: 0xf800707f + MATCH_AMOMINU_W: 0xc000202f + MASK_AMOMINU_W: 0xf800707f + MATCH_AMOMAXU_W: 0xe000202f + MASK_AMOMAXU_W: 0xf800707f + MATCH_AMOSWAP_W: 0x800202f + MASK_AMOSWAP_W: 0xf800707f + MATCH_LR_W: 0x1000202f + MASK_LR_W: 0xf9f0707f + MATCH_SC_W: 0x1800202f + MASK_SC_W: 0xf800707f + MATCH_AMOADD_D: 0x302f + MASK_AMOADD_D: 0xf800707f + MATCH_AMOXOR_D: 0x2000302f + MASK_AMOXOR_D: 0xf800707f + MATCH_AMOOR_D: 0x4000302f + MASK_AMOOR_D: 0xf800707f + MATCH_AMOAND_D: 0x6000302f + MASK_AMOAND_D: 0xf800707f + MATCH_AMOMIN_D: 0x8000302f + MASK_AMOMIN_D: 0xf800707f + MATCH_AMOMAX_D: 0xa000302f + MASK_AMOMAX_D: 0xf800707f + MATCH_AMOMINU_D: 0xc000302f + MASK_AMOMINU_D: 0xf800707f + MATCH_AMOMAXU_D: 0xe000302f + MASK_AMOMAXU_D: 0xf800707f + MATCH_AMOSWAP_D: 0x800302f + MASK_AMOSWAP_D: 0xf800707f + MATCH_LR_D: 0x1000302f + MASK_LR_D: 0xf9f0707f + MATCH_SC_D: 0x1800302f + MASK_SC_D: 0xf800707f + MATCH_ECALL: 0x73 + MASK_ECALL: 0xffffffff + MATCH_EBREAK: 0x100073 + MASK_EBREAK: 0xffffffff + MATCH_URET: 0x200073 + MASK_URET: 0xffffffff + MATCH_SRET: 0x10200073 + MASK_SRET: 0xffffffff + MATCH_MRET: 0x30200073 + MASK_MRET: 0xffffffff + MATCH_DRET: 0x7b200073 + MASK_DRET: 0xffffffff + MATCH_SFENCE_VMA: 0x12000073 + MASK_SFENCE_VMA: 0xfe007fff + MATCH_WFI: 0x10500073 + MASK_WFI: 0xffffffff + MATCH_CSRRW: 0x1073 + MASK_CSRRW: 0x707f + MATCH_CSRRS: 0x2073 + MASK_CSRRS: 0x707f + MATCH_CSRRC: 0x3073 + MASK_CSRRC: 0x707f + MATCH_CSRRWI: 0x5073 + MASK_CSRRWI: 0x707f + MATCH_CSRRSI: 0x6073 + MASK_CSRRSI: 0x707f + MATCH_CSRRCI: 0x7073 + MASK_CSRRCI: 0x707f + MATCH_FADD_S: 0x53 + MASK_FADD_S: 0xfe00007f + MATCH_FSUB_S: 0x8000053 + MASK_FSUB_S: 0xfe00007f + MATCH_FMUL_S: 0x10000053 + MASK_FMUL_S: 0xfe00007f + MATCH_FDIV_S: 0x18000053 + MASK_FDIV_S: 0xfe00007f + MATCH_FSGNJ_S: 0x20000053 + MASK_FSGNJ_S: 0xfe00707f + MATCH_FSGNJN_S: 0x20001053 + MASK_FSGNJN_S: 0xfe00707f + MATCH_FSGNJX_S: 0x20002053 + MASK_FSGNJX_S: 0xfe00707f + MATCH_FMIN_S: 0x28000053 + MASK_FMIN_S: 0xfe00707f + MATCH_FMAX_S: 0x28001053 + MASK_FMAX_S: 0xfe00707f + MATCH_FSQRT_S: 0x58000053 + MASK_FSQRT_S: 0xfff0007f + MATCH_FADD_D: 0x2000053 + MASK_FADD_D: 0xfe00007f + MATCH_FSUB_D: 0xa000053 + MASK_FSUB_D: 0xfe00007f + MATCH_FMUL_D: 0x12000053 + MASK_FMUL_D: 0xfe00007f + MATCH_FDIV_D: 0x1a000053 + MASK_FDIV_D: 0xfe00007f + MATCH_FSGNJ_D: 0x22000053 + MASK_FSGNJ_D: 0xfe00707f + MATCH_FSGNJN_D: 0x22001053 + MASK_FSGNJN_D: 0xfe00707f + MATCH_FSGNJX_D: 0x22002053 + MASK_FSGNJX_D: 0xfe00707f + MATCH_FMIN_D: 0x2a000053 + MASK_FMIN_D: 0xfe00707f + MATCH_FMAX_D: 0x2a001053 + MASK_FMAX_D: 0xfe00707f + MATCH_FCVT_S_D: 0x40100053 + MASK_FCVT_S_D: 0xfff0007f + MATCH_FCVT_D_S: 0x42000053 + MASK_FCVT_D_S: 0xfff0007f + MATCH_FSQRT_D: 0x5a000053 + MASK_FSQRT_D: 0xfff0007f + MATCH_FADD_Q: 0x6000053 + MASK_FADD_Q: 0xfe00007f + MATCH_FSUB_Q: 0xe000053 + MASK_FSUB_Q: 0xfe00007f + MATCH_FMUL_Q: 0x16000053 + MASK_FMUL_Q: 0xfe00007f + MATCH_FDIV_Q: 0x1e000053 + MASK_FDIV_Q: 0xfe00007f + MATCH_FSGNJ_Q: 0x26000053 + MASK_FSGNJ_Q: 0xfe00707f + MATCH_FSGNJN_Q: 0x26001053 + MASK_FSGNJN_Q: 0xfe00707f + MATCH_FSGNJX_Q: 0x26002053 + MASK_FSGNJX_Q: 0xfe00707f + MATCH_FMIN_Q: 0x2e000053 + MASK_FMIN_Q: 0xfe00707f + MATCH_FMAX_Q: 0x2e001053 + MASK_FMAX_Q: 0xfe00707f + MATCH_FCVT_S_Q: 0x40300053 + MASK_FCVT_S_Q: 0xfff0007f + MATCH_FCVT_Q_S: 0x46000053 + MASK_FCVT_Q_S: 0xfff0007f + MATCH_FCVT_D_Q: 0x42300053 + MASK_FCVT_D_Q: 0xfff0007f + MATCH_FCVT_Q_D: 0x46100053 + MASK_FCVT_Q_D: 0xfff0007f + MATCH_FSQRT_Q: 0x5e000053 + MASK_FSQRT_Q: 0xfff0007f + MATCH_FLE_S: 0xa0000053 + MASK_FLE_S: 0xfe00707f + MATCH_FLT_S: 0xa0001053 + MASK_FLT_S: 0xfe00707f + MATCH_FEQ_S: 0xa0002053 + MASK_FEQ_S: 0xfe00707f + MATCH_FLE_D: 0xa2000053 + MASK_FLE_D: 0xfe00707f + MATCH_FLT_D: 0xa2001053 + MASK_FLT_D: 0xfe00707f + MATCH_FEQ_D: 0xa2002053 + MASK_FEQ_D: 0xfe00707f + MATCH_FLE_Q: 0xa6000053 + MASK_FLE_Q: 0xfe00707f + MATCH_FLT_Q: 0xa6001053 + MASK_FLT_Q: 0xfe00707f + MATCH_FEQ_Q: 0xa6002053 + MASK_FEQ_Q: 0xfe00707f + MATCH_FCVT_W_S: 0xc0000053 + MASK_FCVT_W_S: 0xfff0007f + MATCH_FCVT_WU_S: 0xc0100053 + MASK_FCVT_WU_S: 0xfff0007f + MATCH_FCVT_L_S: 0xc0200053 + MASK_FCVT_L_S: 0xfff0007f + MATCH_FCVT_LU_S: 0xc0300053 + MASK_FCVT_LU_S: 0xfff0007f + MATCH_FMV_X_W: 0xe0000053 + MASK_FMV_X_W: 0xfff0707f + MATCH_FCLASS_S: 0xe0001053 + MASK_FCLASS_S: 0xfff0707f + MATCH_FCVT_W_D: 0xc2000053 + MASK_FCVT_W_D: 0xfff0007f + MATCH_FCVT_WU_D: 0xc2100053 + MASK_FCVT_WU_D: 0xfff0007f + MATCH_FCVT_L_D: 0xc2200053 + MASK_FCVT_L_D: 0xfff0007f + MATCH_FCVT_LU_D: 0xc2300053 + MASK_FCVT_LU_D: 0xfff0007f + MATCH_FMV_X_D: 0xe2000053 + MASK_FMV_X_D: 0xfff0707f + MATCH_FCLASS_D: 0xe2001053 + MASK_FCLASS_D: 0xfff0707f + MATCH_FCVT_W_Q: 0xc6000053 + MASK_FCVT_W_Q: 0xfff0007f + MATCH_FCVT_WU_Q: 0xc6100053 + MASK_FCVT_WU_Q: 0xfff0007f + MATCH_FCVT_L_Q: 0xc6200053 + MASK_FCVT_L_Q: 0xfff0007f + MATCH_FCVT_LU_Q: 0xc6300053 + MASK_FCVT_LU_Q: 0xfff0007f + MATCH_FMV_X_Q: 0xe6000053 + MASK_FMV_X_Q: 0xfff0707f + MATCH_FCLASS_Q: 0xe6001053 + MASK_FCLASS_Q: 0xfff0707f + MATCH_FCVT_S_W: 0xd0000053 + MASK_FCVT_S_W: 0xfff0007f + MATCH_FCVT_S_WU: 0xd0100053 + MASK_FCVT_S_WU: 0xfff0007f + MATCH_FCVT_S_L: 0xd0200053 + MASK_FCVT_S_L: 0xfff0007f + MATCH_FCVT_S_LU: 0xd0300053 + MASK_FCVT_S_LU: 0xfff0007f + MATCH_FMV_W_X: 0xf0000053 + MASK_FMV_W_X: 0xfff0707f + MATCH_FCVT_D_W: 0xd2000053 + MASK_FCVT_D_W: 0xfff0007f + MATCH_FCVT_D_WU: 0xd2100053 + MASK_FCVT_D_WU: 0xfff0007f + MATCH_FCVT_D_L: 0xd2200053 + MASK_FCVT_D_L: 0xfff0007f + MATCH_FCVT_D_LU: 0xd2300053 + MASK_FCVT_D_LU: 0xfff0007f + MATCH_FMV_D_X: 0xf2000053 + MASK_FMV_D_X: 0xfff0707f + MATCH_FCVT_Q_W: 0xd6000053 + MASK_FCVT_Q_W: 0xfff0007f + MATCH_FCVT_Q_WU: 0xd6100053 + MASK_FCVT_Q_WU: 0xfff0007f + MATCH_FCVT_Q_L: 0xd6200053 + MASK_FCVT_Q_L: 0xfff0007f + MATCH_FCVT_Q_LU: 0xd6300053 + MASK_FCVT_Q_LU: 0xfff0007f + MATCH_FMV_Q_X: 0xf6000053 + MASK_FMV_Q_X: 0xfff0707f + MATCH_FLW: 0x2007 + MASK_FLW: 0x707f + MATCH_FLD: 0x3007 + MASK_FLD: 0x707f + MATCH_FLQ: 0x4007 + MASK_FLQ: 0x707f + MATCH_FSW: 0x2027 + MASK_FSW: 0x707f + MATCH_FSD: 0x3027 + MASK_FSD: 0x707f + MATCH_FSQ: 0x4027 + MASK_FSQ: 0x707f + MATCH_FMADD_S: 0x43 + MASK_FMADD_S: 0x600007f + MATCH_FMSUB_S: 0x47 + MASK_FMSUB_S: 0x600007f + MATCH_FNMSUB_S: 0x4b + MASK_FNMSUB_S: 0x600007f + MATCH_FNMADD_S: 0x4f + MASK_FNMADD_S: 0x600007f + MATCH_FMADD_D: 0x2000043 + MASK_FMADD_D: 0x600007f + MATCH_FMSUB_D: 0x2000047 + MASK_FMSUB_D: 0x600007f + MATCH_FNMSUB_D: 0x200004b + MASK_FNMSUB_D: 0x600007f + MATCH_FNMADD_D: 0x200004f + MASK_FNMADD_D: 0x600007f + MATCH_FMADD_Q: 0x6000043 + MASK_FMADD_Q: 0x600007f + MATCH_FMSUB_Q: 0x6000047 + MASK_FMSUB_Q: 0x600007f + MATCH_FNMSUB_Q: 0x600004b + MASK_FNMSUB_Q: 0x600007f + MATCH_FNMADD_Q: 0x600004f + MASK_FNMADD_Q: 0x600007f + MATCH_C_NOP: 0x1 + MASK_C_NOP: 0xffff + MATCH_C_ADDI16SP: 0x6101 + MASK_C_ADDI16SP: 0xef83 + MATCH_C_JR: 0x8002 + MASK_C_JR: 0xf07f + MATCH_C_JALR: 0x9002 + MASK_C_JALR: 0xf07f + MATCH_C_EBREAK: 0x9002 + MASK_C_EBREAK: 0xffff + MATCH_C_LD: 0x6000 + MASK_C_LD: 0xe003 + MATCH_C_SD: 0xe000 + MASK_C_SD: 0xe003 + MATCH_C_ADDIW: 0x2001 + MASK_C_ADDIW: 0xe003 + MATCH_C_LDSP: 0x6002 + MASK_C_LDSP: 0xe003 + MATCH_C_SDSP: 0xe002 + MASK_C_SDSP: 0xe003 + MATCH_C_ADDI4SPN: 0x0 + MASK_C_ADDI4SPN: 0xe003 + MATCH_C_FLD: 0x2000 + MASK_C_FLD: 0xe003 + MATCH_C_LW: 0x4000 + MASK_C_LW: 0xe003 + MATCH_C_FLW: 0x6000 + MASK_C_FLW: 0xe003 + MATCH_C_FSD: 0xa000 + MASK_C_FSD: 0xe003 + MATCH_C_SW: 0xc000 + MASK_C_SW: 0xe003 + MATCH_C_FSW: 0xe000 + MASK_C_FSW: 0xe003 + MATCH_C_ADDI: 0x1 + MASK_C_ADDI: 0xe003 + MATCH_C_JAL: 0x2001 + MASK_C_JAL: 0xe003 + MATCH_C_LI: 0x4001 + MASK_C_LI: 0xe003 + MATCH_C_LUI: 0x6001 + MASK_C_LUI: 0xe003 + MATCH_C_SRLI: 0x8001 + MASK_C_SRLI: 0xec03 + MATCH_C_SRAI: 0x8401 + MASK_C_SRAI: 0xec03 + MATCH_C_ANDI: 0x8801 + MASK_C_ANDI: 0xec03 + MATCH_C_SUB: 0x8c01 + MASK_C_SUB: 0xfc63 + MATCH_C_XOR: 0x8c21 + MASK_C_XOR: 0xfc63 + MATCH_C_OR: 0x8c41 + MASK_C_OR: 0xfc63 + MATCH_C_AND: 0x8c61 + MASK_C_AND: 0xfc63 + MATCH_C_SUBW: 0x9c01 + MASK_C_SUBW: 0xfc63 + MATCH_C_ADDW: 0x9c21 + MASK_C_ADDW: 0xfc63 + MATCH_C_J: 0xa001 + MASK_C_J: 0xe003 + MATCH_C_BEQZ: 0xc001 + MASK_C_BEQZ: 0xe003 + MATCH_C_BNEZ: 0xe001 + MASK_C_BNEZ: 0xe003 + MATCH_C_SLLI: 0x2 + MASK_C_SLLI: 0xe003 + MATCH_C_FLDSP: 0x2002 + MASK_C_FLDSP: 0xe003 + MATCH_C_LWSP: 0x4002 + MASK_C_LWSP: 0xe003 + MATCH_C_FLWSP: 0x6002 + MASK_C_FLWSP: 0xe003 + MATCH_C_MV: 0x8002 + MASK_C_MV: 0xf003 + MATCH_C_ADD: 0x9002 + MASK_C_ADD: 0xf003 + MATCH_C_FSDSP: 0xa002 + MASK_C_FSDSP: 0xe003 + MATCH_C_SWSP: 0xc002 + MASK_C_SWSP: 0xe003 + MATCH_C_FSWSP: 0xe002 + MASK_C_FSWSP: 0xe003 + MATCH_CUSTOM0: 0xb + MASK_CUSTOM0: 0x707f + MATCH_CUSTOM0_RS1: 0x200b + MASK_CUSTOM0_RS1: 0x707f + MATCH_CUSTOM0_RS1_RS2: 0x300b + MASK_CUSTOM0_RS1_RS2: 0x707f + MATCH_CUSTOM0_RD: 0x400b + MASK_CUSTOM0_RD: 0x707f + MATCH_CUSTOM0_RD_RS1: 0x600b + MASK_CUSTOM0_RD_RS1: 0x707f + MATCH_CUSTOM0_RD_RS1_RS2: 0x700b + MASK_CUSTOM0_RD_RS1_RS2: 0x707f + MATCH_CUSTOM1: 0x2b + MASK_CUSTOM1: 0x707f + MATCH_CUSTOM1_RS1: 0x202b + MASK_CUSTOM1_RS1: 0x707f + MATCH_CUSTOM1_RS1_RS2: 0x302b + MASK_CUSTOM1_RS1_RS2: 0x707f + MATCH_CUSTOM1_RD: 0x402b + MASK_CUSTOM1_RD: 0x707f + MATCH_CUSTOM1_RD_RS1: 0x602b + MASK_CUSTOM1_RD_RS1: 0x707f + MATCH_CUSTOM1_RD_RS1_RS2: 0x702b + MASK_CUSTOM1_RD_RS1_RS2: 0x707f + MATCH_CUSTOM2: 0x5b + MASK_CUSTOM2: 0x707f + MATCH_CUSTOM2_RS1: 0x205b + MASK_CUSTOM2_RS1: 0x707f + MATCH_CUSTOM2_RS1_RS2: 0x305b + MASK_CUSTOM2_RS1_RS2: 0x707f + MATCH_CUSTOM2_RD: 0x405b + MASK_CUSTOM2_RD: 0x707f + MATCH_CUSTOM2_RD_RS1: 0x605b + MASK_CUSTOM2_RD_RS1: 0x707f + MATCH_CUSTOM2_RD_RS1_RS2: 0x705b + MASK_CUSTOM2_RD_RS1_RS2: 0x707f + MATCH_CUSTOM3: 0x7b + MASK_CUSTOM3: 0x707f + MATCH_CUSTOM3_RS1: 0x207b + MASK_CUSTOM3_RS1: 0x707f + MATCH_CUSTOM3_RS1_RS2: 0x307b + MASK_CUSTOM3_RS1_RS2: 0x707f + MATCH_CUSTOM3_RD: 0x407b + MASK_CUSTOM3_RD: 0x707f + MATCH_CUSTOM3_RD_RS1: 0x607b + MASK_CUSTOM3_RD_RS1: 0x707f + MATCH_CUSTOM3_RD_RS1_RS2: 0x707b + MASK_CUSTOM3_RD_RS1_RS2: 0x707f + CSR_FFLAGS: 0x1 + CSR_FRM: 0x2 + CSR_FCSR: 0x3 + CSR_CYCLE: 0xc00 + CSR_TIME: 0xc01 + CSR_INSTRET: 0xc02 + CSR_HEDELEG: 0x602 + CSR_HPMCOUNTER3: 0xc03 + CSR_HPMCOUNTER4: 0xc04 + CSR_HPMCOUNTER5: 0xc05 + CSR_HPMCOUNTER6: 0xc06 + CSR_HPMCOUNTER7: 0xc07 + CSR_HPMCOUNTER8: 0xc08 + CSR_HPMCOUNTER9: 0xc09 + CSR_HPMCOUNTER10: 0xc0a + CSR_HPMCOUNTER11: 0xc0b + CSR_HPMCOUNTER12: 0xc0c + CSR_HPMCOUNTER13: 0xc0d + CSR_HPMCOUNTER14: 0xc0e + CSR_HPMCOUNTER15: 0xc0f + CSR_HPMCOUNTER16: 0xc10 + CSR_HPMCOUNTER17: 0xc11 + CSR_HPMCOUNTER18: 0xc12 + CSR_HPMCOUNTER19: 0xc13 + CSR_HPMCOUNTER20: 0xc14 + CSR_HPMCOUNTER21: 0xc15 + CSR_HPMCOUNTER22: 0xc16 + CSR_HPMCOUNTER23: 0xc17 + CSR_HPMCOUNTER24: 0xc18 + CSR_HPMCOUNTER25: 0xc19 + CSR_HPMCOUNTER26: 0xc1a + CSR_HPMCOUNTER27: 0xc1b + CSR_HPMCOUNTER28: 0xc1c + CSR_HPMCOUNTER29: 0xc1d + CSR_HPMCOUNTER30: 0xc1e + CSR_HPMCOUNTER31: 0xc1f + CSR_VSATP: 0x280 + CSR_HSTATUS: 0x600 + CSR_SSTATUS: 0x100 + CSR_SIE: 0x104 + CSR_STVEC: 0x105 + CSR_SCOUNTEREN: 0x106 + CSR_SSCRATCH: 0x140 + CSR_SEPC: 0x141 + CSR_SCAUSE: 0x142 + CSR_STVAL: 0x143 + CSR_SIP: 0x144 + CSR_SATP: 0x180 + CSR_SEDELEG: 0x102 + CSR_MSTATUS: 0x300 + CSR_MSTATUSH: 0x310 + CSR_MISA: 0x301 + CSR_MEDELEG: 0x302 + CSR_MIDELEG: 0x303 + CSR_MIE: 0x304 + CSR_MTVEC: 0x305 + CSR_MCOUNTEREN: 0x306 + CSR_MSCRATCH: 0x340 + CSR_MEPC: 0x341 + CSR_MCAUSE: 0x342 + CSR_MTVAL: 0x343 + CSR_MIP: 0x344 + CSR_PMPCFG0: 0x3a0 + CSR_PMPCFG1: 0x3a1 + CSR_PMPCFG2: 0x3a2 + CSR_PMPCFG3: 0x3a3 + CSR_PMPADDR0: 0x3b0 + CSR_PMPADDR1: 0x3b1 + CSR_PMPADDR2: 0x3b2 + CSR_PMPADDR3: 0x3b3 + CSR_PMPADDR4: 0x3b4 + CSR_PMPADDR5: 0x3b5 + CSR_PMPADDR6: 0x3b6 + CSR_PMPADDR7: 0x3b7 + CSR_PMPADDR8: 0x3b8 + CSR_PMPADDR9: 0x3b9 + CSR_PMPADDR10: 0x3ba + CSR_PMPADDR11: 0x3bb + CSR_PMPADDR12: 0x3bc + CSR_PMPADDR13: 0x3bd + CSR_PMPADDR14: 0x3be + CSR_PMPADDR15: 0x3bf + CSR_TSELECT: 0x7a0 + CSR_TDATA1: 0x7a1 + CSR_TDATA2: 0x7a2 + CSR_TDATA3: 0x7a3 + CSR_DCSR: 0x7b0 + CSR_DPC: 0x7b1 + CSR_DSCRATCH: 0x7b2 + CSR_MCYCLE: 0xb00 + CSR_MINSTRET: 0xb02 + CSR_MHPMCOUNTER3: 0xb03 + CSR_MHPMCOUNTER4: 0xb04 + CSR_MHPMCOUNTER5: 0xb05 + CSR_MHPMCOUNTER6: 0xb06 + CSR_MHPMCOUNTER7: 0xb07 + CSR_MHPMCOUNTER8: 0xb08 + CSR_MHPMCOUNTER9: 0xb09 + CSR_MHPMCOUNTER10: 0xb0a + CSR_MHPMCOUNTER11: 0xb0b + CSR_MHPMCOUNTER12: 0xb0c + CSR_MHPMCOUNTER13: 0xb0d + CSR_MHPMCOUNTER14: 0xb0e + CSR_MHPMCOUNTER15: 0xb0f + CSR_MHPMCOUNTER16: 0xb10 + CSR_MHPMCOUNTER17: 0xb11 + CSR_MHPMCOUNTER18: 0xb12 + CSR_MHPMCOUNTER19: 0xb13 + CSR_MHPMCOUNTER20: 0xb14 + CSR_MHPMCOUNTER21: 0xb15 + CSR_MHPMCOUNTER22: 0xb16 + CSR_MHPMCOUNTER23: 0xb17 + CSR_MHPMCOUNTER24: 0xb18 + CSR_MHPMCOUNTER25: 0xb19 + CSR_MHPMCOUNTER26: 0xb1a + CSR_MHPMCOUNTER27: 0xb1b + CSR_MHPMCOUNTER28: 0xb1c + CSR_MHPMCOUNTER29: 0xb1d + CSR_MHPMCOUNTER30: 0xb1e + CSR_MHPMCOUNTER31: 0xb1f + CSR_MHPMEVENT3: 0x323 + CSR_MHPMEVENT4: 0x324 + CSR_MHPMEVENT5: 0x325 + CSR_MHPMEVENT6: 0x326 + CSR_MHPMEVENT7: 0x327 + CSR_MHPMEVENT8: 0x328 + CSR_MHPMEVENT9: 0x329 + CSR_MHPMEVENT10: 0x32a + CSR_MHPMEVENT11: 0x32b + CSR_MHPMEVENT12: 0x32c + CSR_MHPMEVENT13: 0x32d + CSR_MHPMEVENT14: 0x32e + CSR_MHPMEVENT15: 0x32f + CSR_MHPMEVENT16: 0x330 + CSR_MHPMEVENT17: 0x331 + CSR_MHPMEVENT18: 0x332 + CSR_MHPMEVENT19: 0x333 + CSR_MHPMEVENT20: 0x334 + CSR_MHPMEVENT21: 0x335 + CSR_MHPMEVENT22: 0x336 + CSR_MHPMEVENT23: 0x337 + CSR_MHPMEVENT24: 0x338 + CSR_MHPMEVENT25: 0x339 + CSR_MHPMEVENT26: 0x33a + CSR_MHPMEVENT27: 0x33b + CSR_MHPMEVENT28: 0x33c + CSR_MHPMEVENT29: 0x33d + CSR_MHPMEVENT30: 0x33e + CSR_MHPMEVENT31: 0x33f + CSR_MVENDORID: 0xf11 + CSR_MARCHID: 0xf12 + CSR_MIMPID: 0xf13 + CSR_MHARTID: 0xf14 + CSR_CYCLEH: 0xc80 + CSR_TIMEH: 0xc81 + CSR_INSTRETH: 0xc82 + CSR_HPMCOUNTER3H: 0xc83 + CSR_HPMCOUNTER4H: 0xc84 + CSR_HPMCOUNTER5H: 0xc85 + CSR_HPMCOUNTER6H: 0xc86 + CSR_HPMCOUNTER7H: 0xc87 + CSR_HPMCOUNTER8H: 0xc88 + CSR_HPMCOUNTER9H: 0xc89 + CSR_HPMCOUNTER10H: 0xc8a + CSR_HPMCOUNTER11H: 0xc8b + CSR_HPMCOUNTER12H: 0xc8c + CSR_HPMCOUNTER13H: 0xc8d + CSR_HPMCOUNTER14H: 0xc8e + CSR_HPMCOUNTER15H: 0xc8f + CSR_HPMCOUNTER16H: 0xc90 + CSR_HPMCOUNTER17H: 0xc91 + CSR_HPMCOUNTER18H: 0xc92 + CSR_HPMCOUNTER19H: 0xc93 + CSR_HPMCOUNTER20H: 0xc94 + CSR_HPMCOUNTER21H: 0xc95 + CSR_HPMCOUNTER22H: 0xc96 + CSR_HPMCOUNTER23H: 0xc97 + CSR_HPMCOUNTER24H: 0xc98 + CSR_HPMCOUNTER25H: 0xc99 + CSR_HPMCOUNTER26H: 0xc9a + CSR_HPMCOUNTER27H: 0xc9b + CSR_HPMCOUNTER28H: 0xc9c + CSR_HPMCOUNTER29H: 0xc9d + CSR_HPMCOUNTER30H: 0xc9e + CSR_HPMCOUNTER31H: 0xc9f + CSR_MCYCLEH: 0xb80 + CSR_MINSTRETH: 0xb82 + CSR_MHPMCOUNTER3H: 0xb83 + CSR_MHPMCOUNTER4H: 0xb84 + CSR_MHPMCOUNTER5H: 0xb85 + CSR_MHPMCOUNTER6H: 0xb86 + CSR_MHPMCOUNTER7H: 0xb87 + CSR_MHPMCOUNTER8H: 0xb88 + CSR_MHPMCOUNTER9H: 0xb89 + CSR_MHPMCOUNTER10H: 0xb8a + CSR_MHPMCOUNTER11H: 0xb8b + CSR_MHPMCOUNTER12H: 0xb8c + CSR_MHPMCOUNTER13H: 0xb8d + CSR_MHPMCOUNTER14H: 0xb8e + CSR_MHPMCOUNTER15H: 0xb8f + CSR_MHPMCOUNTER16H: 0xb90 + CSR_MHPMCOUNTER17H: 0xb91 + CSR_MHPMCOUNTER18H: 0xb92 + CSR_MHPMCOUNTER19H: 0xb93 + CSR_MHPMCOUNTER20H: 0xb94 + CSR_MHPMCOUNTER21H: 0xb95 + CSR_MHPMCOUNTER22H: 0xb96 + CSR_MHPMCOUNTER23H: 0xb97 + CSR_MHPMCOUNTER24H: 0xb98 + CSR_MHPMCOUNTER25H: 0xb99 + CSR_MHPMCOUNTER26H: 0xb9a + CSR_MHPMCOUNTER27H: 0xb9b + CSR_MHPMCOUNTER28H: 0xb9c + CSR_MHPMCOUNTER29H: 0xb9d + CSR_MHPMCOUNTER30H: 0xb9e + CSR_MHPMCOUNTER31H: 0xb9f + CAUSE_MISALIGNED_FETCH: 0x0 + CAUSE_FETCH_ACCESS: 0x1 + CAUSE_ILLEGAL_INSTRUCTION: 0x2 + CAUSE_BREAKPOINT: 0x3 + CAUSE_MISALIGNED_LOAD: 0x4 + CAUSE_LOAD_ACCESS: 0x5 + CAUSE_MISALIGNED_STORE: 0x6 + CAUSE_STORE_ACCESS: 0x7 + CAUSE_USER_ECALL: 0x8 + CAUSE_SUPERVISOR_ECALL: 0x9 + CAUSE_HYPERVISOR_ECALL: 0xa + CAUSE_MACHINE_ECALL: 0xb + CAUSE_FETCH_PAGE_FAULT: 0xc + CAUSE_LOAD_PAGE_FAULT: 0xd + CAUSE_STORE_PAGE_FAULT: 0xf + CSR_MENTROPY: 0xF15 + CSR_MNOISE: 0x7A9 + DCSR_XDEBUGVER: (3U<<30) + DCSR_NDRESET: (1<<29) + DCSR_FULLRESET: (1<<28) + DCSR_EBREAKM: (1<<15) + DCSR_EBREAKH: (1<<14) + DCSR_EBREAKS: (1<<13) + DCSR_EBREAKU: (1<<12) + DCSR_STOPCYCLE: (1<<10) + DCSR_STOPTIME: (1<<9) + DCSR_CAUSE: (7<<6) + DCSR_DEBUGINT: (1<<5) + DCSR_HALT: (1<<3) + DCSR_STEP: (1<<2) + DCSR_PRV: (3<<0) + MCONTROL_SELECT: (1<<19) + MCONTROL_TIMING: (1<<18) + MCONTROL_ACTION: (0x3f<<12) + MCONTROL_CHAIN: (1<<11) + MCONTROL_MATCH: (0xf<<7) + MCONTROL_M: (1<<6) + MCONTROL_H: (1<<5) + MCONTROL_S: (1<<4) + MCONTROL_U: (1<<3) + MCONTROL_EXECUTE: (1<<2) + MCONTROL_STORE: (1<<1) + MCONTROL_LOAD: (1<<0) + MIP_SSIP: (1 << IRQ_S_SOFT) + MIP_HSIP: (1 << IRQ_H_SOFT) + MIP_MSIP: (1 << IRQ_M_SOFT) + MIP_STIP: (1 << IRQ_S_TIMER) + MIP_HTIP: (1 << IRQ_H_TIMER) + MIP_MTIP: (1 << IRQ_M_TIMER) + MIP_SEIP: (1 << IRQ_S_EXT) + MIP_HEIP: (1 << IRQ_H_EXT) + MIP_MEIP: (1 << IRQ_M_EXT) + RISCV_PGSIZE: (1 << RISCV_PGSHIFT) + +PMP_MACROS: + PMPCFG_BIT_SET: 1 + PMPCFG_BIT_NOT_SET: 0 + PMPCFG_ONLY_R_SET: 0x01 + PMPCFG_ONLY_X_SET: 0x04 + PMPCFG_ONLY_RW_SET: 0x03 + PMPCFG_ONLY_RX_SET: 0x05 + PMPCFG_ONLY_RWX_SET: 0x07 + PMPCFG_OFF_MODE: 0x00 + PMPCFG_TOR_MODE: 0x08 + PMPCFG_NA4_MODE: 0x10 + PMPCFG_NAPOT_MODE: 0x18 + PMPCFG_R_BIT: 0x01 + PMPCFG_W_BIT: 0x02 + PMPCFG_X_BIT: 0x04 + PMPCFG_RWX_BIT: 0x07 + PMPCFG_A_BIT: 0x18 + PMPCFG_RW_BIT: 0x60 + PMPCFG_L_BIT: 0x80 + PMPCFG_ALL_BIT: 0xFF + +PMP_helper_Coverpoints: + NAPOT_REGION_ADDRESS_MATCH: ((rs1_val + imm_val) ^ (pmpaddr1<<2)) & ~(((pmpaddr1 ^ (pmpaddr1+1))<<2) | 3) ==0 and ((rs1_val+imm_val+access_len-1 ) ^ (pmpaddr1<<2)) & ~(((pmpaddr1 ^ (pmpaddr1+1))<<2) | 3) ==0 + NAPOT_PRIORITY_REGION_MATCH: ((rs1_val + imm_val) ^ (pmpaddr3<<2)) & ~(((pmpaddr3 ^ (pmpaddr3+1))<<2) | 3) ==0 and ((rs1_val+imm_val+access_len-1 ) ^ (pmpaddr3<<2)) & ~(((pmpaddr3 ^ (pmpaddr3+1))<<2) | 3) ==0 + NAPOT_PRIORITY_2_REGION_MATCH: ((rs1_val + imm_val) ^ (pmpaddr1<<2)) & ~(((pmpaddr1 ^ (pmpaddr1+1))<<2) | 3) ==0 and ((rs1_val+imm_val+access_len-1 ) ^ (pmpaddr1<<2)) & ~(((pmpaddr1 ^ (pmpaddr1+1))<<2) | 3) ==0 + TOR_REGION_ADDRESS_MATCH: (rs1_val + imm_val >= (pmpaddr1 << 2)) and (rs1_val + imm_val < (pmpaddr2 << 2)) + TOR_PRIORITY_REGION_MATCH: (rs1_val + imm_val >= (pmpaddr2 << 2)) and (rs1_val + imm_val < (pmpaddr3 << 2)) + TOR_PRIORITY_2_REGION_MATCH: (rs1_val + imm_val >= (pmpaddr0 << 2)) and (rs1_val + imm_val < (pmpaddr1 << 2)) + NA4_REGION_ADDRESS_MATCH: (rs1_val + imm_val == (pmpaddr1 << 2)) + NA4_PRIORITY_REGION_MATCH: (rs1_val + imm_val == (pmpaddr3 << 2)) + NA4_PRIORITY_2_REGION_MATCH: (rs1_val + imm_val == (pmpaddr1 << 2)) \ No newline at end of file diff --git a/coverage/rv32_pmp.cgf b/coverage/rv32_pmp.cgf new file mode 100644 index 000000000..1b65ddc5d --- /dev/null +++ b/coverage/rv32_pmp.cgf @@ -0,0 +1,836 @@ +# This coverpoint checks the coverage of Lock bit test. +# req = The old value of the pmpcfgs and pmpaddrs should be equal to the new one since the Lock bit is set and the new write try will fail. +pmp_cfg_locked_write_unrelated: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw}" : 0 + csr_comb: + # (Lock bit set) and (req) and (old_value_pmpcfg != 0) + (pmpcfg{{0 ... 15} >> 2} >> {0, 8, 16, 24}{[$2%4]} & 0x80 == 0x80) and (((old("pmpcfg$2") ^ pmpcfg$2) >> $3 & 0xFF) == 0x00) and old("pmpcfg$2") != 0: 0 + (pmpcfg{{0 ... 15} >> 2} >> {0, 8, 16, 24}{[$1%4]} & 0x80 == 0x80) and (old("pmpaddr$1") == (pmpaddr$1)) and (pmpcfg$2 != 0): 0 + +#This coverpoint checks the coverage of pmp-CSR-access.cgf (PMP CSRs accesses in different modes) +#Checks pmpcgf and pmpaddr are only accessible in M mode and gets fault in S and U mode when accessed. +PMP_access_permission: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw}" : 0 + csr_comb: + #Check successful update for pmpcfg in M Mode + mode == 'M' and ((old("pmpcfg{0 ... 3}") != (pmpcfg$1)) and pmpcfg$1 != 0x0): 0 + #Check successful update for pmpaddr in M Mode + mode == 'M' and ((old("pmpaddr{0 ... 15}") != (pmpaddr$1)) and pmpaddr$1 != 0x0): 0 #pmpaddr successfully updated in M mode + #Check for fault for pmpcfg, pmpaddr in S, U Mode + mode == {'S', 'U'} and mcause == ${CAUSE_ILLEGAL_INSTRUCTION}: 0 #check for illegal instruction fault + +# This coverpoint checks the coverage for the pmp-NAPOT-R.S +# R bit is set for pmpcfg but wx is not set for the region, so there should be store and fetch access fault. +PMP_NAPOT_r: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Check Lock bit is set, R bit is set, W bit not set, X bit not set, NAPOT Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NAPOT_MODE}+${PMPCFG_ONLY_R_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw instruction + mnemonic == {'sb', 'sh', 'sw'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check for execute fault + mode == 'M' and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_FETCH_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x99) and ${NAPOT_REGION_ADDRESS_MATCH}': 0 + +# This coverpoint checks the coverage for the pmp-NAPOT-X.S +# X bit is set for pmpcfg but RW is not set for the region, so there should be load and store access fault. +PMP_NAPOT_x: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Check Lock bit is set, R bit is set, W bit not set, X bit not set, NAPOT Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NAPOT_MODE}+${PMPCFG_ONLY_X_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw instruction + mnemonic == {'sb', 'sh', 'sw'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check for load fault on lb, lh, lw instruction + mnemonic == {'lb', 'lh', 'lw'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_LOAD_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x9C) and ${NAPOT_REGION_ADDRESS_MATCH}': 0 + +# This coverpoint checks the coverage for the pmp-NAPOT-RW.S +# RW bit is set for pmpcfg but X is not set for the region, so there should be fetch access fault. +PMP_NAPOT_rw: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Check Lock bit is set, R bit is set, W bit not set, X bit not set, NAPOT Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NAPOT_MODE}+${PMPCFG_ONLY_RW_SET}": 0 + val_comb: + #Check for execute fault + mode == 'M' and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_FETCH_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x9B) and ${NAPOT_REGION_ADDRESS_MATCH}': 0 + +# This coverpoint checks the coverage for the pmp-NAPOT-RX.S +# RX bit is set for pmpcfg but W is not set for the region, so there should be store access fault. +PMP_NAPOT_rx: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Check Lock bit is set, R bit is set, W bit not set, X bit not set, NAPOT Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NAPOT_MODE}+${PMPCFG_ONLY_RX_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw instruction + mnemonic == {'sb', 'sh', 'sw'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x9D) and ${NAPOT_REGION_ADDRESS_MATCH}': 0 + +# This coverpoint checks the coverage for the pmp-NAPOT-RWX.S +# R,W,X bit is set for pmpcfg, so there should be NO access fault. +PMP_NAPOT_rwx: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Check Lock bit is set, R bit is set, W bit not set, X bit not set, NAPOT Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NAPOT_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + val_comb: + #Check the napot region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x9F) and ${NAPOT_REGION_ADDRESS_MATCH}': 0 + +# This coverpoint checks the coverage for the pmp-TOR-R.S +# R bit is set for pmpcfg but wx is not set for the region, so there should be store and fetch access fault. +PMP_TOR_r: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Check Lock bit is set, R bit is set, W bit not set, X bit not set, NAPOT Mode is set + "(pmpcfg0 >> 16) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_R_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw instruction + mnemonic == {'sb', 'sh', 'sw'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check for execute fault + mode == 'M' and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_FETCH_ACCESS}): 0 + #Check the tor region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 16) & 0x9F == 0x89) and ${TOR_REGION_ADDRESS_MATCH}': 0 + +# This coverpoint checks the coverage for the pmp-TOR-X.S +# X bit is set for pmpcfg but RW is not set for the region, so there should be load and store access fault. +PMP_TOR_x: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Check Lock bit is set, R bit not set, W bit not set, X bit is set, NAPOT Mode is set + "(pmpcfg0 >> 16) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_X_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw instruction + mnemonic == {'sb', 'sh', 'sw'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check for load fault on lb, lh, lw instruction + mnemonic == {'lb', 'lh', 'lw'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_LOAD_ACCESS}): 0 + #Check the tor region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 16) & 0x9F == 0x8C) and ${TOR_REGION_ADDRESS_MATCH}': 0 + +# This coverpoint checks the coverage for the pmp-TOR-RW.S +# RW bit is set for pmpcfg but X is not set for the region, so there should be fetch access fault. +PMP_TOR_rw: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Check Lock bit is set, R bit is set, W bit is set, X bit not set, NAPOT Mode is set + "(pmpcfg0 >> 16) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RW_SET}": 0 + val_comb: + #Check for execute fault + mode == 'M' and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_FETCH_ACCESS}): 0 + #Check the tor region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 16) & 0x9F == 0x8B) and ${NAPOT_REGION_ADDRESS_MATCH}': 0 + +# This coverpoint checks the coverage for the pmp-TOR-RX.S +# RX bit is set for pmpcfg but W is not set for the region, so there should be store access fault. +PMP_TOR_rx: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Check Lock bit is set, R bit is set, W bit not set, X bit is set, TOR Mode is set + "(pmpcfg0 >> 16) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RX_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw instruction + mnemonic == {'sb', 'sh', 'sw'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check the tor region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 16) & 0x9F == 0x8D) and ${NAPOT_REGION_ADDRESS_MATCH}': 0 + +# This coverpoint checks the coverage for the pmp-TOR-RWX.S +# R,W,X bit is set for pmpcfg, so there should be NO access fault. +PMP_TOR_rwx: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg0 >> 16) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + val_comb: + #Check the tor region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 16) & 0x9F == 0x8F) and ${NAPOT_REGION_ADDRESS_MATCH}': 0 + +# This coverpoint checks the coverage for the pmp-NA4-R.S +# R bit is set for pmpcfg but wx is not set for the region, so there should be store and fetch access fault. +PMP_NA4_r: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Check Lock bit is set, R bit is set, W bit not set, X bit not set, NAPOT Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NA4_MODE}+${PMPCFG_ONLY_R_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw instruction + mnemonic == {'sb', 'sh', 'sw'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check for execute fault + mode == 'M' and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_FETCH_ACCESS}): 0 + #Check the na4 region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x91) and ${NA4_REGION_ADDRESS_MATCH}': 0 + +# This coverpoint checks the coverage for the pmp-NA4-X.S +# X bit is set for pmpcfg but RW is not set for the region, so there should be load and store access fault. +PMP_NA4_x: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Check Lock bit is set, R bit not set, W bit not set, X bit set, NA4 Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NA4_MODE}+${PMPCFG_ONLY_X_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw instruction + mnemonic == {'sb', 'sh', 'sw'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check for load fault on lb, lh, lw instruction + mnemonic == {'lb', 'lh', 'lw'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_LOAD_ACCESS}): 0 + #Check the na4 region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x94) and ${NA4_REGION_ADDRESS_MATCH}': 0 + +# This coverpoint checks the coverage for the pmp-NA4-RW.S +# RW bit is set for pmpcfg but X is not set for the region, so there should be fetch access fault. +PMP_NA4_rw: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Check Lock bit is set, R bit is set, W bit is set, X bit not set, NA4 Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NA4_MODE}+${PMPCFG_ONLY_RW_SET}": 0 + val_comb: + #Check for execute fault + mode == 'M' and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_FETCH_ACCESS}): 0 + #Check the na4 region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x93) and ${NA4_REGION_ADDRESS_MATCH}': 0 + +# This coverpoint checks the coverage for the pmp-NA4-RX.S +# RX bit is set for pmpcfg but W is not set for the region, so there should be store access fault. +PMP_NA4_rx: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Check Lock bit is set, R bit is set, W bit not set, X bit not set, NAPOT Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NA4_MODE}+${PMPCFG_ONLY_RX_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw instruction + mnemonic == {'sb', 'sh', 'sw'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x95) and ${NA4_REGION_ADDRESS_MATCH}': 0 + +# This coverpoint checks the coverage for the pmp-NA4-RWX.S +# R,W,X bit is set for pmpcfg, so there should be NO access fault. +PMP_NA4_rwx: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Check Lock bit is set, R bit is set, W bit not set, X bit not set, NAPOT Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NA4_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + val_comb: + #Check the napot region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x97) and ${NA4_REGION_ADDRESS_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_NAPOT_r_priority.S +# This is a priority test. +# pmpcfg3 --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0 --> high priority entry gets R permission -- NAPOT region selected +# R succeeds while we get Store fault and fetch access fault +PMP_NAPOT_priority_r: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg3 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit is set, W bit not set, X bit not set, NAPOT Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NAPOT_MODE}+${PMPCFG_ONLY_R_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw instruction + mnemonic == {'sb', 'sh', 'sw'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check for execute fault + mode == 'M' and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_FETCH_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 24) & 0x9F == 0x99) and ${NAPOT_PRIORITY_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_NAPOT_x_priority.S +# This is a priority test. +# pmpcfg3 --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0 --> high priority entry gets X permission -- NAPOT region selected +# fetch succeeds while we get read access fault and store access fault +PMP_NAPOT_priority_x: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg3 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit is set, W bit not set, X bit not set, NAPOT Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NAPOT_MODE}+${PMPCFG_ONLY_X_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw instruction + mnemonic == {'sb', 'sh', 'sw'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check for load fault on lb, lh, lw instruction + mnemonic == {'lb', 'lh', 'lw'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_LOAD_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 24) & 0x9F == 0x9C) and ${NAPOT_PRIORITY_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_NAPOT_rw_priority.S +# This is a priority test. +# pmpcfg3 --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0 --> high priority entry gets RW permission -- NAPOT region selected +# load, store succeeds while we get fetch access fault +PMP_NAPOT_priority_rw: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg3 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit not set, NAPOT Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NAPOT_MODE}+${PMPCFG_ONLY_RW_SET}": 0 + val_comb: + #Check for execute fault + mode == 'M' and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_FETCH_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 24) & 0x9F == 0x9B) and ${NAPOT_PRIORITY_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_NAPOT_rx_priority.S +# This is a priority test. +# pmpcfg3 --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0 --> high priority entry gets R X permission -- NAPOT region selected +# load, fetch succeeds while we get store access fault +PMP_NAPOT_priority_rx: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg3 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit is set, W bit not set, X bit is set, NAPOT Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NAPOT_MODE}+${PMPCFG_ONLY_RX_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw instruction + mnemonic == {'sb', 'sh', 'sw'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 24) & 0x9F == 0x9D) and ${NAPOT_PRIORITY_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_TOR_r_priority.S +# This is a priority test. +# pmpcfg3 --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0 --> high priority entry gets R permission -- TOR region selected +# R succeeds while we get Store fault and fetch access fault +PMP_TOR_priority_r: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg3 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit is set, W bit not set, X bit not set, TOR Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_R_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw instruction + mnemonic == {'sb', 'sh', 'sw'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check for execute fault + mode == 'M' and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_FETCH_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 24) & 0x9F == 0x89) and ${TOR_PRIORITY_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_TOR_x_priority.S +# This is a priority test. +# pmpcfg3 --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0 --> high priority entry gets X permission -- TOR region selected +# X succeeds while we get load and store access faults +PMP_TOR_priority_x: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg3 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit not set, TOR Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_X_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw instruction + mnemonic == {'sb', 'sh', 'sw'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check for load fault on lb, lh, lw instruction + mnemonic == {'lb', 'lh', 'lw'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_LOAD_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 24) & 0x9F == 0x8C) and ${TOR_PRIORITY_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_TOR_rw_priority.S +# This is a priority test. +# pmpcfg3 --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0 --> high priority entry gets RW permission -- TOR region selected +# R,W succeeds while we get fetch access fault +PMP_TOR_priority_rw: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg3 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit not set, TOR Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RW_SET}": 0 + val_comb: + #Check for execute fault + mode == 'M' and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_FETCH_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 24) & 0x9F == 0x8B) and ${TOR_PRIORITY_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_TOR_rx_priority.S +# This is a priority test. +# pmpcfg3 --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0 --> high priority entry gets R X permission -- TOR region selected +# R,X succeeds while we get store access faults +PMP_TOR_priority_rx: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg3 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit is set, W bit not set, X bit is set, TOR Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RX_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw instruction + mnemonic == {'sb', 'sh', 'sw'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 24) & 0x9F == 0x8D) and ${TOR_PRIORITY_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_NA4_r_priority.S +# This is a priority test. +# pmpcfg3 --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0 --> high priority entry gets R permission -- NA4 region selected +# R succeeds while we get store and fetch access fault +PMP_NA4_priority_r: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg3 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit is set, W bit not set, X bit not set, NA4 Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NA4_MODE}+${PMPCFG_ONLY_R_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw instruction + mnemonic == {'sb', 'sh', 'sw'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check for execute fault + mode == 'M' and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_FETCH_ACCESS}): 0 + #Check the na4 region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 24) & 0x9F == 0x91) and ${NA4_PRIORITY_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_NA4_x_priority.S +# This is a priority test. +# pmpcfg3 --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0 --> high priority entry gets X permission -- NA4 region selected +# X succeeds while we get load and store access fault +PMP_NA4_priority_x: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg3 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit not set, NA4 Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NA4_MODE}+${PMPCFG_ONLY_X_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw instruction + mnemonic == {'sb', 'sh', 'sw'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check for load fault on lb, lh, lw instruction + mnemonic == {'lb', 'lh', 'lw'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_LOAD_ACCESS}): 0 + #Check the na4 region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 24) & 0x9F == 0x94) and ${NA4_PRIORITY_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_NA4_rw_priority.S +# This is a priority test. +# pmpcfg3 --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0 --> high priority entry gets RW permission -- NA4 region selected +# R,W succeeds while we get fetch access fault +PMP_NA4_priority_rw: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg3 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit not set, NA4 Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NA4_MODE}+${PMPCFG_ONLY_RW_SET}": 0 + val_comb: + #Check for execute fault + mode == 'M' and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_FETCH_ACCESS}): 0 + #Check the na4 region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 24) & 0x9F == 0x93) and ${NA4_PRIORITY_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_NA4_rx_priority.S +# This is a priority test. +# pmpcfg3 --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0 --> high priority entry gets R X permission -- NA4 region selected +# R,X succeeds while we get store access fault +PMP_NA4_priority_rx: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg3 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit is set, W bit not set, X bit is set, NA4 Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NA4_MODE}+${PMPCFG_ONLY_RX_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw instruction + mnemonic == {'sb', 'sh', 'sw'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check the na4 region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 24) & 0x9F == 0x95) and ${NA4_PRIORITY_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_NAPOT_r_priority_level_2.S +# This is a priority test. +# pmpcfg3[31:24] --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0[31:24] --> high priority entry gets permission -- TOR region selected +# pmpcfg0[15:8] --> highest priority entry gets R permission -- NAPOT region selected +# R succeeds while we get Store fault and fetch access fault +PMP_NAPOT_priority_r_level_2: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg3 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit not set, W bit not set, X bit not set, TOR Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_BIT_NOT_SET}": 0 + # Higest priority entry -- Check Lock bit is set, R bit is set, W bit not set, X bit not set, NAPOT Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NAPOT_MODE}+${PMPCFG_ONLY_R_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw instruction + mnemonic == {'sb', 'sh', 'sw'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check for execute fault + mode == 'M' and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_FETCH_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x99) and ${NAPOT_PRIORITY_2_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_NAPOT_x_priority_level_2.S +# This is a priority test. +# pmpcfg3[31:24] --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0[31:24] --> high priority entry gets permission -- TOR region selected +# pmpcfg0[15:8] --> highest priority entry gets X permission -- NAPOT region selected +# X succeeds while we get load and store access fault +PMP_NAPOT_priority_x_level_2: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg3 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit not set, W bit not set, X bit not set, TOR Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_BIT_NOT_SET}": 0 + # Higest priority entry -- Check Lock bit is set, R bit not set, W bit not set, X bit is set, NAPOT Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NAPOT_MODE}+${PMPCFG_ONLY_X_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw instruction + mnemonic == {'sb', 'sh', 'sw'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check for load fault on lb, lh, lw instruction + mnemonic == {'lb', 'lh', 'lw'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_LOAD_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x9C) and ${NAPOT_PRIORITY_2_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_NAPOT_rw_priority_level_2.S +# This is a priority test. +# pmpcfg3[31:24] --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0[31:24] --> high priority entry gets permission -- TOR region selected +# pmpcfg0[15:8] --> highest priority entry gets RW permission -- NAPOT region selected +# R,W succeeds while we get fetch access fault +PMP_NAPOT_priority_rw_level_2: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg3 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit not set, W bit not set, X bit not set, TOR Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_BIT_NOT_SET}": 0 + # Higest priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit not set, NAPOT Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NAPOT_MODE}+${PMPCFG_ONLY_RW_SET}": 0 + val_comb: + #Check for execute fault + mode == 'M' and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_FETCH_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x9B) and ${NAPOT_PRIORITY_2_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_NAPOT_rx_priority_level_2.S +# This is a priority test. +# pmpcfg3[31:24] --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0[31:24] --> high priority entry gets permission -- TOR region selected +# pmpcfg0[15:8] --> highest priority entry gets R X permission -- NAPOT region selected +# R,X succeeds while we get store access fault +PMP_NAPOT_priority_rx_level_2: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg3 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit not set, W bit not set, X bit not set, TOR Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_BIT_NOT_SET}": 0 + # Higest priority entry -- Check Lock bit is set, R bit is set, W bit not set, X bit is set, NAPOT Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NAPOT_MODE}+${PMPCFG_ONLY_RX_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw instruction + mnemonic == {'sb', 'sh', 'sw'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x9D) and ${NAPOT_PRIORITY_2_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_TOR_r_priority_level_2.S +# This is a priority test. +# pmpcfg3[31:24] --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0[31:24] --> high priority entry gets permission -- TOR region selected +# pmpcfg0[15:8] --> highest priority entry gets R permission -- TOR region selected +# R succeeds while we get store and fetch access fault +PMP_TOR_priority_r_level_2: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg3 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit not set, W bit not set, X bit not set, TOR Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_BIT_NOT_SET}": 0 + # Higest priority entry -- Check Lock bit is set, R bit is set, W bit not set, X bit not set, TOR Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_R_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw instruction + mnemonic == {'sb', 'sh', 'sw'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check for execute fault + mode == 'M' and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_FETCH_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x89) and ${TOR_PRIORITY_2_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_TOR_x_priority_level_2.S +# This is a priority test. +# pmpcfg3[31:24] --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0[31:24] --> high priority entry gets permission -- TOR region selected +# pmpcfg0[15:8] --> highest priority entry gets X permission -- TOR region selected +# X succeeds while we get load and store access fault +PMP_TOR_priority_x_level_2: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg3 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit not set, W bit not set, X bit not set, TOR Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_BIT_NOT_SET}": 0 + # Higest priority entry -- Check Lock bit is set, R bit not set, W bit not set, X bit is set, TOR Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_X_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw instruction + mnemonic == {'sb', 'sh', 'sw'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check for load fault on lb, lh, lw instruction + mnemonic == {'lb', 'lh', 'lw'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_LOAD_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x8C) and ${TOR_PRIORITY_2_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_TOR_rw_priority_level_2.S +# This is a priority test. +# pmpcfg3[31:24] --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0[31:24] --> high priority entry gets permission -- TOR region selected +# pmpcfg0[15:8] --> highest priority entry gets RW permission -- TOR region selected +# R,W succeeds while we get fetch access fault +PMP_TOR_priority_rw_level_2: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg3 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit not set, W bit not set, X bit not set, TOR Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_BIT_NOT_SET}": 0 + # Higest priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit not set, TOR Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RW_SET}": 0 + val_comb: + #Check for execute fault + mode == 'M' and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_FETCH_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x8B) and ${TOR_PRIORITY_2_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_TOR_rx_priority_level_2.S +# This is a priority test. +# pmpcfg3[31:24] --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0[31:24] --> high priority entry gets permission -- TOR region selected +# pmpcfg0[15:8] --> highest priority entry gets R X permission -- TOR region selected +# R, X succeeds while we get store access fault +PMP_TOR_priority_rx_level_2: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg3 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit not set, W bit not set, X bit not set, TOR Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_BIT_NOT_SET}": 0 + # Higest priority entry -- Check Lock bit is set, R bit is set, W bit not set, X bit is set, TOR Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RX_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw instruction + mnemonic == {'sb', 'sh', 'sw'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x8D) and ${TOR_PRIORITY_2_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_NA4_r_priority_level_2.S +# This is a priority test. +# pmpcfg3[31:24] --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0[31:24] --> high priority entry gets permission -- TOR region selected +# pmpcfg0[15:8] --> highest priority entry gets R permission -- NA4 region selected +# R succeeds while we get store and fetch access fault +PMP_NA4_priority_r_level_2: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg3 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit not set, W bit not set, X bit not set, TOR Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_BIT_NOT_SET}": 0 + # Higest priority entry -- Check Lock bit is set, R bit is set, W bit not set, X bit not set, NA4 Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NA4_MODE}+${PMPCFG_ONLY_R_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw instruction + mnemonic == {'sb', 'sh', 'sw'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check for execute fault + mode == 'M' and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_FETCH_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x91) and ${NA4_PRIORITY_2_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_NA4_rw_priority_level_2.S +# This is a priority test. +# pmpcfg3[31:24] --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0[31:24] --> high priority entry gets permission -- TOR region selected +# pmpcfg0[15:8] --> highest priority entry gets RW permission -- NA4 region selected +# R,W succeeds while we get fetch access fault +PMP_NA4_priority_rw_level_2: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg3 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit not set, W bit not set, X bit not set, TOR Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_BIT_NOT_SET}": 0 + # Higest priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit not set, NA4 Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NA4_MODE}+${PMPCFG_ONLY_RW_SET}": 0 + val_comb: + #Check for execute fault + mode == 'M' and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_FETCH_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x93) and ${NA4_PRIORITY_2_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_NA4_x_priority_level_2.S +# This is a priority test. +# pmpcfg3[31:24] --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0[31:24] --> high priority entry gets permission -- TOR region selected +# pmpcfg0[15:8] --> highest priority entry gets X permission -- NA4 region selected +# X succeeds while we get load and store access fault +PMP_NA4_priority_x_level_2: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg3 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit not set, W bit not set, X bit not set, TOR Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_BIT_NOT_SET}": 0 + # Higest priority entry -- Check Lock bit is set, R bit not set, W bit not set, X bit is set, NA4 Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NA4_MODE}+${PMPCFG_ONLY_X_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw instruction + mnemonic == {'sb', 'sh', 'sw'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check for load fault on lb, lh, lw instruction + mnemonic == {'lb', 'lh', 'lw'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_LOAD_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x94) and ${NA4_PRIORITY_2_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_NA4_rx_priority_level_2.S +# This is a priority test. +# pmpcfg3[31:24] --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0[31:24] --> high priority entry gets permission -- TOR region selected +# pmpcfg0[15:8] --> highest priority entry gets R X permission -- NA4 region selected +# R,X succeeds while we get store access fault +PMP_NA4_priority_rx_level_2: + config: + - check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg3 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit not set, W bit not set, X bit not set, TOR Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_BIT_NOT_SET}": 0 + # Higest priority entry -- Check Lock bit is set, R bit is set, W bit not set, X bit is set, NA4 Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NA4_MODE}+${PMPCFG_ONLY_RX_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw instruction + mnemonic == {'sb', 'sh', 'sw'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"lw", "lh", "lb", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x95) and ${NA4_PRIORITY_2_REGION_MATCH}': 0 diff --git a/coverage/rv64_pmp.cgf b/coverage/rv64_pmp.cgf new file mode 100644 index 000000000..616dbad5f --- /dev/null +++ b/coverage/rv64_pmp.cgf @@ -0,0 +1,836 @@ +# This coverpoint checks the coverage of Lock bit test. +# req = The old value of the pmpcfgs and pmpaddrs should be equal to the new one since the Lock bit is set and the new write try will fail. +pmp_cfg_locked_write_unrelated: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw}" : 0 + csr_comb: + # (Lock bit set) and (req) and (old_value_pmpcfg != 0) + (old("pmpaddr{0 ... 15}") ^ (pmpaddr$1) == 0x00) and (pmpcfg{0,2}{[$1/8]} >> {[($1%8)*8]} & 0x80 == 0x80): 0 + (pmpcfg{0, 2} >> {[($1%8)*8]} & 0x80 == 0x80) and ((old("pmpcfg$1") & (0xFF << $2)) ^ (pmpcfg$1 & (0xFF << $2)) == 0x00) and old("pmpcfg$1") != 0: 0 + +#This coverpoint checks the coverage of pmp-CSR-access.cgf (PMP CSRs accesses in different modes) +#Checks pmpcgf and pmpaddr are only accessible in M mode and gets fault in S and U mode when accessed. +PMP_access_permission: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw}" : 0 + csr_comb: + #Check successful update for pmpcfg in M Mode + mode == 'M' and (((old("pmpcfg{0 , 2}") ^ (pmpcfg$1)) != 0x00) and pmpcfg$1 != 0x0): 0 #pmpcfg successfully updated in M mode + #Check successful update for pmpaddr in M Mode + mode == 'M' and (((old("pmpaddr{0 ... 15}") ^ (pmpaddr$1)) != 0x00) and pmpaddr$1 != 0x0): 0 #pmpaddr successfully updated in M mode + #Check for fault for pmpcfg, pmpaddr in S, U Mode + mode == {'S', 'U'} and mcause == ${CAUSE_ILLEGAL_INSTRUCTION}: 0 #check for illegal instruction fault + +# This coverpoint checks the coverage for the pmp-NAPOT-R.S +# R bit is set for pmpcfg but wx is not set for the region, so there should be store and fetch access fault. +PMP_NAPOT_r: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Check Lock bit is set, R bit is set, W bit not set, X bit not set, NAPOT Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NAPOT_MODE}+${PMPCFG_ONLY_R_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw, sd instruction + mnemonic == {'sb', 'sh', 'sw', 'sd'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check for execute fault + mode == 'M' and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_FETCH_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x99) and ${NAPOT_REGION_ADDRESS_MATCH}': 0 + +# This coverpoint checks the coverage for the pmp-NAPOT-X.S +# X bit is set for pmpcfg but RW is not set for the region, so there should be load and store access fault. +PMP_NAPOT_x: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Check Lock bit is set, R bit is set, W bit not set, X bit not set, NAPOT Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NAPOT_MODE}+${PMPCFG_ONLY_X_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw, sd instruction + mnemonic == {'sb', 'sh', 'sw', 'sd'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check for load fault on lb, lh, lw, ld instruction + mnemonic == {'lb', 'lh', 'lw', 'ld'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_LOAD_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x9C) and ${NAPOT_REGION_ADDRESS_MATCH}': 0 + +# This coverpoint checks the coverage for the pmp-NAPOT-RW.S +# RW bit is set for pmpcfg but X is not set for the region, so there should be fetch access fault. +PMP_NAPOT_rw: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Check Lock bit is set, R bit is set, W bit not set, X bit not set, NAPOT Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NAPOT_MODE}+${PMPCFG_ONLY_RW_SET}": 0 + val_comb: + #Check for execute fault + mode == 'M' and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_FETCH_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x9B) and ${NAPOT_REGION_ADDRESS_MATCH}': 0 + +# This coverpoint checks the coverage for the pmp-NAPOT-RX.S +# RX bit is set for pmpcfg but W is not set for the region, so there should be store access fault. +PMP_NAPOT_rx: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Check Lock bit is set, R bit is set, W bit not set, X bit not set, NAPOT Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NAPOT_MODE}+${PMPCFG_ONLY_RX_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw, sd instruction + mnemonic == {'sb', 'sh', 'sw', 'sd'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x9D) and ${NAPOT_REGION_ADDRESS_MATCH}': 0 + +# This coverpoint checks the coverage for the pmp-NAPOT-RWX.S +# R,W,X bit is set for pmpcfg, so there should be NO access fault. +PMP_NAPOT_rwx: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Check Lock bit is set, R bit is set, W bit not set, X bit not set, NAPOT Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NAPOT_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + val_comb: + #Check the napot region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x9F) and ${NAPOT_REGION_ADDRESS_MATCH}': 0 + +# This coverpoint checks the coverage for the pmp-TOR-R.S +# R bit is set for pmpcfg but wx is not set for the region, so there should be store and fetch access fault. +PMP_TOR_r: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Check Lock bit is set, R bit is set, W bit not set, X bit not set, NAPOT Mode is set + "(pmpcfg0 >> 16) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_R_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw, sd instruction + mnemonic == {'sb', 'sh', 'sw', 'sd'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check for execute fault + mode == 'M' and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_FETCH_ACCESS}): 0 + #Check the tor region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 16) & 0x9F == 0x89) and ${TOR_REGION_ADDRESS_MATCH}': 0 + +# This coverpoint checks the coverage for the pmp-TOR-X.S +# X bit is set for pmpcfg but RW is not set for the region, so there should be load and store access fault. +PMP_TOR_x: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Check Lock bit is set, R bit not set, W bit not set, X bit is set, NAPOT Mode is set + "(pmpcfg0 >> 16) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_X_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw, sd instruction + mnemonic == {'sb', 'sh', 'sw', 'sd'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check for load fault on lb, lh, lw, ld instruction + mnemonic == {'lb', 'lh', 'lw', 'ld'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_LOAD_ACCESS}): 0 + #Check the tor region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 16) & 0x9F == 0x8C) and ${TOR_REGION_ADDRESS_MATCH}': 0 + +# This coverpoint checks the coverage for the pmp-TOR-RW.S +# RW bit is set for pmpcfg but X is not set for the region, so there should be fetch access fault. +PMP_TOR_rw: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Check Lock bit is set, R bit is set, W bit is set, X bit not set, NAPOT Mode is set + "(pmpcfg0 >> 16) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RW_SET}": 0 + val_comb: + #Check for execute fault + mode == 'M' and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_FETCH_ACCESS}): 0 + #Check the tor region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 16) & 0x9F == 0x8B) and ${NAPOT_REGION_ADDRESS_MATCH}': 0 + +# This coverpoint checks the coverage for the pmp-TOR-RX.S +# RX bit is set for pmpcfg but W is not set for the region, so there should be store access fault. +PMP_TOR_rx: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Check Lock bit is set, R bit is set, W bit not set, X bit is set, TOR Mode is set + "(pmpcfg0 >> 16) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RX_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw, sd instruction + mnemonic == {'sb', 'sh', 'sw', 'sd'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check the tor region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 16) & 0x9F == 0x8D) and ${NAPOT_REGION_ADDRESS_MATCH}': 0 + +# This coverpoint checks the coverage for the pmp-TOR-RWX.S +# R,W,X bit is set for pmpcfg, so there should be NO access fault. +PMP_TOR_rwx: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg0 >> 16) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + val_comb: + #Check the tor region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 16) & 0x9F == 0x8F) and ${NAPOT_REGION_ADDRESS_MATCH}': 0 + +# This coverpoint checks the coverage for the pmp-NA4-R.S +# R bit is set for pmpcfg but wx is not set for the region, so there should be store and fetch access fault. +PMP_NA4_r: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Check Lock bit is set, R bit is set, W bit not set, X bit not set, NAPOT Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NA4_MODE}+${PMPCFG_ONLY_R_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw, sd instruction + mnemonic == {'sb', 'sh', 'sw', 'sd'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check for execute fault + mode == 'M' and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_FETCH_ACCESS}): 0 + #Check the na4 region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x91) and ${NA4_REGION_ADDRESS_MATCH}': 0 + +# This coverpoint checks the coverage for the pmp-NA4-X.S +# X bit is set for pmpcfg but RW is not set for the region, so there should be load and store access fault. +PMP_NA4_x: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Check Lock bit is set, R bit not set, W bit not set, X bit set, NA4 Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NA4_MODE}+${PMPCFG_ONLY_X_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw, sd instruction + mnemonic == {'sb', 'sh', 'sw', 'sd'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check for load fault on lb, lh, lw, ld instruction + mnemonic == {'lb', 'lh', 'lw', 'ld'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_LOAD_ACCESS}): 0 + #Check the na4 region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x94) and ${NA4_REGION_ADDRESS_MATCH}': 0 + +# This coverpoint checks the coverage for the pmp-NA4-RW.S +# RW bit is set for pmpcfg but X is not set for the region, so there should be fetch access fault. +PMP_NA4_rw: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Check Lock bit is set, R bit is set, W bit is set, X bit not set, NA4 Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NA4_MODE}+${PMPCFG_ONLY_RW_SET}": 0 + val_comb: + #Check for execute fault + mode == 'M' and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_FETCH_ACCESS}): 0 + #Check the na4 region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x93) and ${NA4_REGION_ADDRESS_MATCH}': 0 + +# This coverpoint checks the coverage for the pmp-NA4-RX.S +# RX bit is set for pmpcfg but W is not set for the region, so there should be store access fault. +PMP_NA4_rx: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Check Lock bit is set, R bit is set, W bit not set, X bit not set, NAPOT Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NA4_MODE}+${PMPCFG_ONLY_RX_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw, sd instruction + mnemonic == {'sb', 'sh', 'sw', 'sd'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x95) and ${NA4_REGION_ADDRESS_MATCH}': 0 + +# This coverpoint checks the coverage for the pmp-NA4-RWX.S +# R,W,X bit is set for pmpcfg, so there should be NO access fault. +PMP_NA4_rwx: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Check Lock bit is set, R bit is set, W bit not set, X bit not set, NAPOT Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NA4_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + val_comb: + #Check the napot region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x97) and ${NA4_REGION_ADDRESS_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_NAPOT_r_priority.S +# This is a priority test. +# pmpcfg3 --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0 --> high priority entry gets R permission -- NAPOT region selected +# R succeeds while we get Store fault and fetch access fault +PMP_NAPOT_priority_r: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg2 >> 56) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit is set, W bit not set, X bit not set, NAPOT Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NAPOT_MODE}+${PMPCFG_ONLY_R_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw, sd instruction + mnemonic == {'sb', 'sh', 'sw', 'sd'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check for execute fault + mode == 'M' and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_FETCH_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 24) & 0x9F == 0x99) and ${NAPOT_PRIORITY_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_NAPOT_x_priority.S +# This is a priority test. +# pmpcfg3 --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0 --> high priority entry gets X permission -- NAPOT region selected +# fetch succeeds while we get read access fault and store access fault +PMP_NAPOT_priority_x: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg2 >> 56) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit is set, W bit not set, X bit not set, NAPOT Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NAPOT_MODE}+${PMPCFG_ONLY_X_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw, sd instruction + mnemonic == {'sb', 'sh', 'sw', 'sd'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check for load fault on lb, lh, lw, ld instruction + mnemonic == {'lb', 'lh', 'lw', 'ld'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_LOAD_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 24) & 0x9F == 0x9C) and ${NAPOT_PRIORITY_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_NAPOT_rw_priority.S +# This is a priority test. +# pmpcfg3 --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0 --> high priority entry gets RW permission -- NAPOT region selected +# load, store succeeds while we get fetch access fault +PMP_NAPOT_priority_rw: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg2 >> 56) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit not set, NAPOT Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NAPOT_MODE}+${PMPCFG_ONLY_RW_SET}": 0 + val_comb: + #Check for execute fault + mode == 'M' and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_FETCH_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 24) & 0x9F == 0x9B) and ${NAPOT_PRIORITY_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_NAPOT_rx_priority.S +# This is a priority test. +# pmpcfg3 --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0 --> high priority entry gets R X permission -- NAPOT region selected +# load, fetch succeeds while we get store access fault +PMP_NAPOT_priority_rx: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg2 >> 56) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit is set, W bit not set, X bit is set, NAPOT Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NAPOT_MODE}+${PMPCFG_ONLY_RX_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw, sd instruction + mnemonic == {'sb', 'sh', 'sw', 'sd'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 24) & 0x9F == 0x9D) and ${NAPOT_PRIORITY_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_TOR_r_priority.S +# This is a priority test. +# pmpcfg3 --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0 --> high priority entry gets R permission -- TOR region selected +# R succeeds while we get Store fault and fetch access fault +PMP_TOR_priority_r: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg2 >> 56) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit is set, W bit not set, X bit not set, TOR Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_R_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw, sd instruction + mnemonic == {'sb', 'sh', 'sw', 'sd'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check for execute fault + mode == 'M' and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_FETCH_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 24) & 0x9F == 0x89) and ${TOR_PRIORITY_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_TOR_x_priority.S +# This is a priority test. +# pmpcfg3 --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0 --> high priority entry gets X permission -- TOR region selected +# X succeeds while we get load and store access faults +PMP_TOR_priority_x: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg2 >> 56) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit not set, TOR Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_X_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw, sd instruction + mnemonic == {'sb', 'sh', 'sw', 'sd'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check for load fault on lb, lh, lw, ld instruction + mnemonic == {'lb', 'lh', 'lw', 'ld'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_LOAD_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 24) & 0x9F == 0x8C) and ${TOR_PRIORITY_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_TOR_rw_priority.S +# This is a priority test. +# pmpcfg3 --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0 --> high priority entry gets RW permission -- TOR region selected +# R,W succeeds while we get fetch access fault +PMP_TOR_priority_rw: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg2 >> 56) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit not set, TOR Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RW_SET}": 0 + val_comb: + #Check for execute fault + mode == 'M' and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_FETCH_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 24) & 0x9F == 0x8B) and ${TOR_PRIORITY_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_TOR_rx_priority.S +# This is a priority test. +# pmpcfg3 --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0 --> high priority entry gets R X permission -- TOR region selected +# R,X succeeds while we get store access faults +PMP_TOR_priority_rx: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg2 >> 56) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit is set, W bit not set, X bit is set, TOR Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RX_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw, sd instruction + mnemonic == {'sb', 'sh', 'sw', 'sd'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 24) & 0x9F == 0x8D) and ${TOR_PRIORITY_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_NA4_r_priority.S +# This is a priority test. +# pmpcfg3 --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0 --> high priority entry gets R permission -- NA4 region selected +# R succeeds while we get store and fetch access fault +PMP_NA4_priority_r: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg2 >> 56) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit is set, W bit not set, X bit not set, NA4 Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NA4_MODE}+${PMPCFG_ONLY_R_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw, sd instruction + mnemonic == {'sb', 'sh', 'sw', 'sd'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check for execute fault + mode == 'M' and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_FETCH_ACCESS}): 0 + #Check the na4 region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 24) & 0x9F == 0x91) and ${NA4_PRIORITY_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_NA4_x_priority.S +# This is a priority test. +# pmpcfg3 --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0 --> high priority entry gets X permission -- NA4 region selected +# X succeeds while we get load and store access fault +PMP_NA4_priority_x: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg2 >> 56) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit not set, NA4 Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NA4_MODE}+${PMPCFG_ONLY_X_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw, sd instruction + mnemonic == {'sb', 'sh', 'sw', 'sd'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check for load fault on lb, lh, lw, ld instruction + mnemonic == {'lb', 'lh', 'lw', 'ld'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_LOAD_ACCESS}): 0 + #Check the na4 region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 24) & 0x9F == 0x94) and ${NA4_PRIORITY_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_NA4_rw_priority.S +# This is a priority test. +# pmpcfg3 --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0 --> high priority entry gets RW permission -- NA4 region selected +# R,W succeeds while we get fetch access fault +PMP_NA4_priority_rw: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg2 >> 56) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit not set, NA4 Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NA4_MODE}+${PMPCFG_ONLY_RW_SET}": 0 + val_comb: + #Check for execute fault + mode == 'M' and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_FETCH_ACCESS}): 0 + #Check the na4 region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 24) & 0x9F == 0x93) and ${NA4_PRIORITY_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_NA4_rx_priority.S +# This is a priority test. +# pmpcfg3 --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0 --> high priority entry gets R X permission -- NA4 region selected +# R,X succeeds while we get store access fault +PMP_NA4_priority_rx: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg2 >> 56) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit is set, W bit not set, X bit is set, NA4 Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NA4_MODE}+${PMPCFG_ONLY_RX_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw, sd instruction + mnemonic == {'sb', 'sh', 'sw', 'sd'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check the na4 region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 24) & 0x9F == 0x95) and ${NA4_PRIORITY_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_NAPOT_r_priority_level_2.S +# This is a priority test. +# pmpcfg3[31:24] --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0[31:24] --> high priority entry gets permission -- TOR region selected +# pmpcfg0[15:8] --> highest priority entry gets R permission -- NAPOT region selected +# R succeeds while we get Store fault and fetch access fault +PMP_NAPOT_priority_r_level_2: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg2 >> 56) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit not set, W bit not set, X bit not set, TOR Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_BIT_NOT_SET}": 0 + # Higest priority entry -- Check Lock bit is set, R bit is set, W bit not set, X bit not set, NAPOT Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NAPOT_MODE}+${PMPCFG_ONLY_R_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw, sd instruction + mnemonic == {'sb', 'sh', 'sw', 'sd'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check for execute fault + mode == 'M' and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_FETCH_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x99) and ${NAPOT_PRIORITY_2_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_NAPOT_x_priority_level_2.S +# This is a priority test. +# pmpcfg3[31:24] --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0[31:24] --> high priority entry gets permission -- TOR region selected +# pmpcfg0[15:8] --> highest priority entry gets X permission -- NAPOT region selected +# X succeeds while we get load and store access fault +PMP_NAPOT_priority_x_level_2: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg2 >> 56) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit not set, W bit not set, X bit not set, TOR Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_BIT_NOT_SET}": 0 + # Higest priority entry -- Check Lock bit is set, R bit not set, W bit not set, X bit is set, NAPOT Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NAPOT_MODE}+${PMPCFG_ONLY_X_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw, sd instruction + mnemonic == {'sb', 'sh', 'sw', 'sd'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check for load fault on lb, lh, lw, ld instruction + mnemonic == {'lb', 'lh', 'lw', 'ld'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_LOAD_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x9C) and ${NAPOT_PRIORITY_2_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_NAPOT_rw_priority_level_2.S +# This is a priority test. +# pmpcfg3[31:24] --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0[31:24] --> high priority entry gets permission -- TOR region selected +# pmpcfg0[15:8] --> highest priority entry gets RW permission -- NAPOT region selected +# R,W succeeds while we get fetch access fault +PMP_NAPOT_priority_rw_level_2: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg2 >> 56) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit not set, W bit not set, X bit not set, TOR Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_BIT_NOT_SET}": 0 + # Higest priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit not set, NAPOT Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NAPOT_MODE}+${PMPCFG_ONLY_RW_SET}": 0 + val_comb: + #Check for execute fault + mode == 'M' and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_FETCH_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x9B) and ${NAPOT_PRIORITY_2_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_NAPOT_rx_priority_level_2.S +# This is a priority test. +# pmpcfg3[31:24] --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0[31:24] --> high priority entry gets permission -- TOR region selected +# pmpcfg0[15:8] --> highest priority entry gets R X permission -- NAPOT region selected +# R,X succeeds while we get store access fault +PMP_NAPOT_priority_rx_level_2: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg2 >> 56) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit not set, W bit not set, X bit not set, TOR Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_BIT_NOT_SET}": 0 + # Higest priority entry -- Check Lock bit is set, R bit is set, W bit not set, X bit is set, NAPOT Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NAPOT_MODE}+${PMPCFG_ONLY_RX_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw, sd instruction + mnemonic == {'sb', 'sh', 'sw', 'sd'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x9D) and ${NAPOT_PRIORITY_2_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_TOR_r_priority_level_2.S +# This is a priority test. +# pmpcfg3[31:24] --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0[31:24] --> high priority entry gets permission -- TOR region selected +# pmpcfg0[15:8] --> highest priority entry gets R permission -- TOR region selected +# R succeeds while we get store and fetch access fault +PMP_TOR_priority_r_level_2: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg2 >> 56) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit not set, W bit not set, X bit not set, TOR Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_BIT_NOT_SET}": 0 + # Higest priority entry -- Check Lock bit is set, R bit is set, W bit not set, X bit not set, TOR Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_R_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw, sd instruction + mnemonic == {'sb', 'sh', 'sw', 'sd'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check for execute fault + mode == 'M' and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_FETCH_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x89) and ${TOR_PRIORITY_2_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_TOR_x_priority_level_2.S +# This is a priority test. +# pmpcfg3[31:24] --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0[31:24] --> high priority entry gets permission -- TOR region selected +# pmpcfg0[15:8] --> highest priority entry gets X permission -- TOR region selected +# X succeeds while we get load and store access fault +PMP_TOR_priority_x_level_2: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg2 >> 56) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit not set, W bit not set, X bit not set, TOR Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_BIT_NOT_SET}": 0 + # Higest priority entry -- Check Lock bit is set, R bit not set, W bit not set, X bit is set, TOR Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_X_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw, sd instruction + mnemonic == {'sb', 'sh', 'sw', 'sd'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check for load fault on lb, lh, lw, ld instruction + mnemonic == {'lb', 'lh', 'lw', 'ld'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_LOAD_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x8C) and ${TOR_PRIORITY_2_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_TOR_rw_priority_level_2.S +# This is a priority test. +# pmpcfg3[31:24] --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0[31:24] --> high priority entry gets permission -- TOR region selected +# pmpcfg0[15:8] --> highest priority entry gets RW permission -- TOR region selected +# R,W succeeds while we get fetch access fault +PMP_TOR_priority_rw_level_2: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg2 >> 56) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit not set, W bit not set, X bit not set, TOR Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_BIT_NOT_SET}": 0 + # Higest priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit not set, TOR Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RW_SET}": 0 + val_comb: + #Check for execute fault + mode == 'M' and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_FETCH_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x8B) and ${TOR_PRIORITY_2_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_TOR_rx_priority_level_2.S +# This is a priority test. +# pmpcfg3[31:24] --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0[31:24] --> high priority entry gets permission -- TOR region selected +# pmpcfg0[15:8] --> highest priority entry gets R X permission -- TOR region selected +# R, X succeeds while we get store access fault +PMP_TOR_priority_rx_level_2: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg2 >> 56) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit not set, W bit not set, X bit not set, TOR Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_BIT_NOT_SET}": 0 + # Higest priority entry -- Check Lock bit is set, R bit is set, W bit not set, X bit is set, TOR Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RX_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw, sd instruction + mnemonic == {'sb', 'sh', 'sw', 'sd'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x8D) and ${TOR_PRIORITY_2_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_NA4_r_priority_level_2.S +# This is a priority test. +# pmpcfg3[31:24] --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0[31:24] --> high priority entry gets permission -- TOR region selected +# pmpcfg0[15:8] --> highest priority entry gets R permission -- NA4 region selected +# R succeeds while we get store and fetch access fault +PMP_NA4_priority_r_level_2: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg2 >> 56) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit not set, W bit not set, X bit not set, TOR Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_BIT_NOT_SET}": 0 + # Higest priority entry -- Check Lock bit is set, R bit is set, W bit not set, X bit not set, NA4 Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NA4_MODE}+${PMPCFG_ONLY_R_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw, sd instruction + mnemonic == {'sb', 'sh', 'sw', 'sd'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check for execute fault + mode == 'M' and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_FETCH_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x91) and ${NA4_PRIORITY_2_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_NA4_rw_priority_level_2.S +# This is a priority test. +# pmpcfg3[31:24] --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0[31:24] --> high priority entry gets permission -- TOR region selected +# pmpcfg0[15:8] --> highest priority entry gets RW permission -- NA4 region selected +# R,W succeeds while we get fetch access fault +PMP_NA4_priority_rw_level_2: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg2 >> 56) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit not set, W bit not set, X bit not set, TOR Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_BIT_NOT_SET}": 0 + # Higest priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit not set, NA4 Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NA4_MODE}+${PMPCFG_ONLY_RW_SET}": 0 + val_comb: + #Check for execute fault + mode == 'M' and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_FETCH_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x93) and ${NA4_PRIORITY_2_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_NA4_x_priority_level_2.S +# This is a priority test. +# pmpcfg3[31:24] --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0[31:24] --> high priority entry gets permission -- TOR region selected +# pmpcfg0[15:8] --> highest priority entry gets X permission -- NA4 region selected +# X succeeds while we get load and store access fault +PMP_NA4_priority_x_level_2: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg2 >> 56) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit not set, W bit not set, X bit not set, TOR Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_BIT_NOT_SET}": 0 + # Higest priority entry -- Check Lock bit is set, R bit not set, W bit not set, X bit is set, NA4 Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NA4_MODE}+${PMPCFG_ONLY_X_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw, sd instruction + mnemonic == {'sb', 'sh', 'sw', 'sd'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check for load fault on lb, lh, lw, ld instruction + mnemonic == {'lb', 'lh', 'lw', 'ld'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_LOAD_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x94) and ${NA4_PRIORITY_2_REGION_MATCH}': 0 + +# This coverpoint checks the coverage for the PMP_NA4_rx_priority_level_2.S +# This is a priority test. +# pmpcfg3[31:24] --> low priority entry gets RWX permission -- TOR region selected +# pmpcfg0[31:24] --> high priority entry gets permission -- TOR region selected +# pmpcfg0[15:8] --> highest priority entry gets R X permission -- NA4 region selected +# R,X succeeds while we get store access fault +PMP_NA4_priority_rx_level_2: + config: + - check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; + mnemonics: + "{csrrs, csrrw, ld, sd, lw, sw, lb, sb, lh, sh}" : 0 + csr_comb: + # Low priority entry -- Check Lock bit is set, R bit is set, W bit is set, X bit is set, TOR Mode is set + "(pmpcfg2 >> 56) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_ONLY_RWX_SET}": 0 + # High priority entry -- Check Lock bit is set, R bit not set, W bit not set, X bit not set, TOR Mode is set + "(pmpcfg0 >> 24) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_TOR_MODE}+${PMPCFG_BIT_NOT_SET}": 0 + # Higest priority entry -- Check Lock bit is set, R bit is set, W bit not set, X bit is set, NA4 Mode is set + "(pmpcfg0 >> 8) & ${PMPCFG_ALL_BIT} == ${PMPCFG_L_BIT}+${PMPCFG_NA4_MODE}+${PMPCFG_ONLY_RX_SET}": 0 + val_comb: + #Check for store fault on sb , sh, sw, sd instruction + mnemonic == {'sb', 'sh', 'sw', 'sd'} and mode_change == {'M to M', 'U to M', 'S to M'} and (mcause == ${CAUSE_STORE_ACCESS}): 0 + #Check the napot region is accessed at least once + '(mnemonic == {"ld", "lw", "lh", "lb", "sd", "sw", "sh", "sb"}) and ((pmpcfg0 >> 8) & 0x9F == 0x95) and ${NA4_PRIORITY_2_REGION_MATCH}': 0 diff --git a/riscof-plugins/rv64/sail_cSim/__pycache__/__init__.cpython-38.pyc b/riscof-plugins/rv64/sail_cSim/__pycache__/__init__.cpython-38.pyc deleted file mode 100644 index 2094ccfbb..000000000 Binary files a/riscof-plugins/rv64/sail_cSim/__pycache__/__init__.cpython-38.pyc and /dev/null differ diff --git a/riscof-plugins/rv64/sail_cSim/__pycache__/riscof_sail_cSim.cpython-310.pyc b/riscof-plugins/rv64/sail_cSim/__pycache__/riscof_sail_cSim.cpython-310.pyc deleted file mode 100644 index bfa4e25e8..000000000 Binary files a/riscof-plugins/rv64/sail_cSim/__pycache__/riscof_sail_cSim.cpython-310.pyc and /dev/null differ diff --git a/riscof-plugins/rv64/sail_cSim/__pycache__/riscof_sail_cSim.cpython-38.pyc b/riscof-plugins/rv64/sail_cSim/__pycache__/riscof_sail_cSim.cpython-38.pyc deleted file mode 100644 index 1d13f1a89..000000000 Binary files a/riscof-plugins/rv64/sail_cSim/__pycache__/riscof_sail_cSim.cpython-38.pyc and /dev/null differ diff --git a/riscof-plugins/rv64/spike_simple/__pycache__/riscof_model.cpython-38.pyc b/riscof-plugins/rv64/spike_simple/__pycache__/riscof_model.cpython-38.pyc deleted file mode 100644 index 8ce4f473b..000000000 Binary files a/riscof-plugins/rv64/spike_simple/__pycache__/riscof_model.cpython-38.pyc and /dev/null differ diff --git a/riscof-plugins/rv64/spike_simple/__pycache__/riscof_spike.cpython-310.pyc b/riscof-plugins/rv64/spike_simple/__pycache__/riscof_spike.cpython-310.pyc deleted file mode 100644 index 8895634b1..000000000 Binary files a/riscof-plugins/rv64/spike_simple/__pycache__/riscof_spike.cpython-310.pyc and /dev/null differ diff --git a/riscof-plugins/rv64/spike_simple/__pycache__/riscof_spike.cpython-38.pyc b/riscof-plugins/rv64/spike_simple/__pycache__/riscof_spike.cpython-38.pyc deleted file mode 100644 index 62174dc94..000000000 Binary files a/riscof-plugins/rv64/spike_simple/__pycache__/riscof_spike.cpython-38.pyc and /dev/null differ diff --git a/riscof-plugins/rv64/spike_simple/__pycache__/riscof_spike_simple.cpython-310.pyc b/riscof-plugins/rv64/spike_simple/__pycache__/riscof_spike_simple.cpython-310.pyc deleted file mode 100644 index 12489fb7d..000000000 Binary files a/riscof-plugins/rv64/spike_simple/__pycache__/riscof_spike_simple.cpython-310.pyc and /dev/null differ diff --git a/riscof-plugins/rv64/spike_simple/__pycache__/riscof_spike_simple.cpython-38.pyc b/riscof-plugins/rv64/spike_simple/__pycache__/riscof_spike_simple.cpython-38.pyc deleted file mode 100755 index 9fa282a84..000000000 Binary files a/riscof-plugins/rv64/spike_simple/__pycache__/riscof_spike_simple.cpython-38.pyc and /dev/null differ diff --git a/riscv-isac/riscv_isac/coverage.py b/riscv-isac/riscv_isac/coverage.py index 6a95d42b2..2eb692e9a 100644 --- a/riscv-isac/riscv_isac/coverage.py +++ b/riscv-isac/riscv_isac/coverage.py @@ -166,7 +166,7 @@ class cross(): BASE_REG_DICT = { 'x'+str(i) : 'x'+str(i) for i in range(32)} - def __init__(self,label,coverpoint,xlen,flen,addr_pairs,sig_addrs,window_size): + def __init__(self,label,coverpoint,xlen,flen,addr_pairs,sig_addrs,window_size,inxFlg): self.label = label self.coverpoint = coverpoint @@ -1536,7 +1536,7 @@ def compute(trace_file, test_name, cgf, parser_name, decoder_name, detailed, xle if 'cross_comb' in value and len(value['cross_comb'])!=0: for coverpt in value['cross_comb'].keys(): if(isinstance(coverpt,str)): - new_obj = cross(cov_labels,coverpt,xlen,flen,addr_pairs,sig_addrs,window_size) + new_obj = cross(cov_labels,coverpt,xlen,flen,addr_pairs,sig_addrs,window_size,inxFlg) obj_dict[(cov_labels,coverpt)] = new_obj diff --git a/riscv-isac/riscv_isac/fp_dataset.py b/riscv-isac/riscv_isac/fp_dataset.py index 6a4a63fe5..b6b31304b 100644 --- a/riscv-isac/riscv_isac/fp_dataset.py +++ b/riscv-isac/riscv_isac/fp_dataset.py @@ -49,11 +49,11 @@ rounding_modes = ['0','1','2','3','4'] sanitise_cvpt = lambda rm,x,iflen,flen,c,inxFlg: x + ' fcsr == '+hex(rm<<5) + ' and rm_val == 7 ' \ - + ('' if iflen == flen or inxFlg else ''.join([' and rs'+str(x)+'_nan_prefix == 0x' \ + + ('' if iflen >= flen or inxFlg else ''.join([' and rs'+str(x)+'_nan_prefix == 0x' \ + 'f'*int((flen-iflen)/4) for x in range(1,c+1)])) sanitise_norm = lambda rm,x,iflen,flen,c,inxFlg: x + ' fcsr == 0'\ - + ('' if iflen == flen or inxFlg else ''.join([' and rs'+str(x)+'_nan_prefix == 0x' \ + + ('' if iflen >= flen or inxFlg else ''.join([' and rs'+str(x)+'_nan_prefix == 0x' \ + 'f'*int((flen-iflen)/4) for x in range(1,c+1)])) sanitise_norm_nopref = lambda rm,x,iflen,flen,c,inxFlg: x + ' fcsr == 0' diff --git a/riscv-test-suite/env/test_macros.h b/riscv-test-suite/env/test_macros.h index 384fc3730..6a1e291b8 100644 --- a/riscv-test-suite/env/test_macros.h +++ b/riscv-test-suite/env/test_macros.h @@ -906,13 +906,6 @@ ADDI(swreg, swreg, RVMODEL_CBZ_BLOCKSIZE) inst destreg, reg1, reg2, imm ;\ ) -//Tests for a instructions with register-register operand -#define TEST_RI_OP(inst, destreg, reg1, reg2, imm, correctval, val1, val2, swreg, offset, testreg) \ - TEST_CASE(testreg, destreg, correctval, swreg, offset, \ - LI(reg1, MASK_XLEN(val1)) ;\ - LI(reg2, MASK_XLEN(val2)) ;\ - inst destreg, reg1, reg2, imm ;\ - ) //Tests for a instructions with register-register operand #define TEST_RR_OP(inst, destreg, reg1, reg2, correctval, val1, val2, swreg, offset, testreg) \ diff --git a/riscv-test-suite/rv32i_m/pmp32/PMP-CFG-reg.S b/riscv-test-suite/rv32i_m/pmp32/PMP-CFG-reg.S new file mode 100644 index 000000000..a27d0d183 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/PMP-CFG-reg.S @@ -0,0 +1,146 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +// +// This assembly file tests access of pmp registers in M, S, and U mode. +// pmp csrs are accessable only in M-mode so it should trap in S, and U mode. +// +/* COVERPOINTS: (Explanation of updates in /coverage/rv32i_priv.cgf) + pmpcfg0 & 0x20 == 0 : 0 // CHECK IF pmpcfg0[5]==0 (Hard wired zero bit) + pmpcfg0 & 0x40 == 0 : 0 // CHECK IF pmpcfg0[6]==0 (Hard wired zero bit) + pmpcfg0 & 0x80 == 0x80 : 0 // CHECK IF pmpcfg0[7]==1 (Lock bit) + (pmpcfg0 >> 8) & 0x20 == 0 : 0 // CHECK IF pmpcfg0[13]==0 (Hard wired zero bit) + (pmpcfg0 >> 8) & 0x40 == 0 : 0 // CHECK IF pmpcfg0[14]==0 (Hard wired zero bit) + (pmpcfg0 >> 8) & 0x80 == 0x80 : 0 // CHECK IF pmpcfg0[15]==1 (Lock bit) + (pmpcfg0 >> 16) & 0x20 == 0 : 0 // CHECK IF pmpcfg0[21]==0 (Hard wired zero bit) + (pmpcfg0 >> 16) & 0x40 == 0 : 0 // CHECK IF pmpcfg0[22]==0 (Hard wired zero bit) + (pmpcfg0 >> 16) & 0x80 == 0x80 : 0 // CHECK IF pmpcfg0[23]==1 (Lock bit) + (pmpcfg0 >> 24) & 0x20 == 0 : 0 // CHECK IF pmpcfg0[29]==0 (Hard wired zero bit) + (pmpcfg0 >> 24) & 0x40 == 0 : 0 // CHECK IF pmpcfg0[30]==0 (Hard wired zero bit) + (pmpcfg0 >> 24) & 0x80 == 0x80 : 0 // CHECK IF pmpcfg0[31]==1 (Lock bit) +// Same coverpoints are defined for pmpcfg1, pmpcfg2, and pmpcfg3 +// Details are given in /coverage/rv32i_priv.cgf +*/ +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",pmp_cfg_locked_write_unrelated) +RVTEST_SIGBASE( x3,signature_x3_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x9,0) // The register to carry offset value + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrc pmpcfgi , a5 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrc pmpaddri, a5 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +//////////////////// Locked bit TEST 1 ///////////////////////////////////////////// + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi, a5 // WRITE pmpcfgi with ALL 1s, Locked the lock-bit [7,15,23,31] + nop // Added nop in case of trap + csrr a4, pmpcfgi // READ pmpcfgi + // THIS READ WILL ALSO CONFIRM THE ZERO BITs OF PMPCFGi REG. + // BIT 5-6, BIT 13-14, BIT 21-22, BIT 29-30 must be hardwired to zero + // Verify that LOCKED bits are HIGH, and ZERO bits are zero + RVTEST_SIGUPD(x3,a4) + // TRY TO WRITE CFG REGISTER AGAIN (TRAP in case of LOCKED bit is HIGH) + csrw pmpcfgi, x5 // WRITE pmpcfgi with some other values + nop // Added nop in case of trap + csrr a4, pmpcfgi // READ pmpcfgi + // Since Locked bit is high, so this should return the old value!!! + RVTEST_SIGUPD(x3,a4) + + .set pmpaddri, PMPADDR0+4*(pmpcfgi-PMPCFG0) +// Initialize an iterating variable with the address of pmpaddr0 in 1st iteration (when pmpcfgi=pmpcfg0) +// Initialize an iterating variable with the address of pmpaddr4 in 2nd iteration (when pmpcfgi=pmpcfg1) +// Initialize an iterating variable with the address of pmpaddr8 in 3rd iteration (when pmpcfgi=pmpcfg2) +// Initialize an iterating variable with the address of pmpaddr12 in 4th iteration (when pmpcfgi=pmpcfg3) + .rept 4 // START OF LOOP + // TRY TO WRITE ADDRESS REGISTER. + csrw pmpaddri, a5 // WRITE pmpaddri with some other values + // The updated write will give a trap!!! + nop // Added nop in case of trap + csrr a4, pmpaddri // READ pmpaddr0, value should not have been changed + nop // Added nop in case of trap + RVTEST_SIGUPD(x3,a4) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF INNER LOOP BODY + + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF OUTER LOOP BODY +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT + +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x3_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +RVMODEL_DATA_END diff --git a/riscv-test-suite/rv32i_m/pmp32/PMP-CSR-access.S b/riscv-test-suite/rv32i_m/pmp32/PMP-CSR-access.S new file mode 100644 index 000000000..c36838928 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/PMP-CSR-access.S @@ -0,0 +1,188 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +// +// This assembly file tests access of pmp registers in M, S, and U mode. +// pmp csrs are accessable only in M-mode so it should trap in S, and U mode. +// +/* COVERPOINTS: (Explanation of updates in /coverage/rv32i_priv.cgf) + +// Details are given in /coverage/rv32i_priv.cgf +*/ +// +#define rvtest_strap_routine +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def TEST_CASE_1=True",PMP_access_permission) +RVTEST_SIGBASE( x13,signature_x13_1) + .option nopic + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 +main: +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrc pmpcfgi , a5 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrc pmpaddri, a5 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrs pmpaddri, a5 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY +//////////////// VERIFICATION ///////////////////////////////////////// +// READING pmpaddr in M-mode ///////////////////////////////////////// + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrr a4, pmpaddri // READING pmpaddri (i is from 0-15) + nop // Added nop in case of trap + RVTEST_SIGUPD(x13,a4) // Storing into signature file + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY +// WRITING pmpcfg registers ////////////////////////////////////////// +// Write in M-mode will be valid, Write in other modes will cause trap + LI(a5, PMP_R| PMP_W | PMP_X | PMP_TOR) // LOCKED BIT IS NOT SET + // Loop to Write ALL pmpcfg regs + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi, a5 // Write pmpcfgi + nop // Added nop in case of trap + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY +//////////////// VERIFICATION ///////////////////////////////////////// +// READING pmpcfg in M-mode ///////////////////////////////////////// + // Loop to verify the contents of pmpcfg regs + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrr a4, pmpcfg0 // Read pmpcfg0 + nop // Added nop in case of trap + RVTEST_SIGUPD(x13,a4) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY +/////////////////// Switch to S-mode //////////////////////////////////////////// + csrw satp, zero // Disable address translation. + LI(t2, -1) + csrw pmpaddr0, t2 // Updated pmpaddr0 to define PMP region consisting + // of whole physical memory + csrr t0, pmpaddr0 // Verify its value by reading back + nop // Added nop in case of trap + RVTEST_SIGUPD(x13,t0) + nop // Added nop in case of trap + LI(a5, PMP_L| PMP_R| PMP_W | PMP_X | PMP_TOR) // LOCKED BIT IS SET + csrw pmpcfg0, a5 + + RVTEST_GOTO_LOWER_MODE Smode // GO into S mode +// REPEATING THE SAME TEST ////////////////////////////////////////// +// IN Smode now +/////////////////// TEST 01 //////////////////////////////////////////// +// WRITING pmpaddr registers ////////////////////////////////////////// +// Write in M-mode will be valid, Write in other modes will cause trap + csrw pmpaddr0, x2 // Write pmpaddr0 in S mode (TRAP) + nop // Added nop in case of trap +// READING pmpaddr in S-mode ///////////////////////////////////////// + csrr a4, pmpaddr0 // Reading pmpaddr0 in S mode (TRAP) + nop // Added nop in case of trap +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap + RVTEST_SIGUPD(x13,a4) +/////////////////// Switch to U-mode //////////////////////////////////////////// + csrw satp, zero // Disable address translation. + LI(t2, -1) + csrw pmpaddr0, t2 // Updated pmpaddr0 to define PMP region consisting + // of whole physical memory + csrr t0, pmpaddr0 // Verify its value by reading back + nop // Added nop in case of trap + RVTEST_SIGUPD(x13,t0) + nop // Added nop in case of trap + LI(a5, PMP_L| PMP_R| PMP_W | PMP_X | PMP_TOR) // LOCKED BIT IS SET + csrw pmpcfg0, a5 +// These steps are repeated and can be removed but it will make sure that you will switch mode +// with full access on physical memory + RVTEST_GOTO_LOWER_MODE Umode +// REPEATING THE SAME TEST ////////////////////////////////////////// +// IN U-mode now +/////////////////// TEST 01 //////////////////////////////////////////// +// WRITING pmpaddr registers ////////////////////////////////////////// +// Write in M-mode will be valid, Write in other modes will cause trap + csrw pmpaddr0, x2 // Write pmpaddr0 in u mode (TRAP) + nop // Added nop in case of trap +//////////////// VERIFICATION ///////////////////////////////////////// +// READING pmpaddr in S-mode ///////////////////////////////////////// + csrr a4, pmpaddr0 // Reading pmpaddr0 in U mode (TRAP) + nop // Added nop in case of trap + +#endif + + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT + +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-R-priority-level-2.S b/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-R-priority-level-2.S new file mode 100644 index 000000000..d8bc8e36e --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-R-priority-level-2.S @@ -0,0 +1,224 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NA4-priority-r-level-2.S +// Tests the priority by assigning only R permissions to the highest priority while no permissions to high priority region and R-W-X to low priority region +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints", PMP_NA4_priority_r_level_2) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg3 [31:24] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled. This is the low priority region +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with nothing enabled +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION). This is the high priority region +// in TOR Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION3 ((((PMP_R|PMP_L|PMP_NA4)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +// PMPADDRESS14 = value to be loaded pmpaddr14 to declare lower address of Region-1 +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr14 to declare region1 +// PMPADDRESS15 = value to be loaded pmpaddr15 to declare upper address of Region-1 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of Region-2 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of Region-2 +#define PMPADDRESS3 RETURN_INSTRUCTION +// PMPADDRESS3 = value to be loaded pmpaddr1 to declare upper address of Region-3 +#define PMPADDRESS1 TEST_FOR_EXECUTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration +/* PMP is configure in the following order: +1. Address 0x8000 0000 to Address RVMODEL_DATA_END => PMP TOR (Low Priority) Region with RWX enabled. For this purpose, pmpaddr14 has been given the value of 0 and pmpaddr15 is given address to RVMODEL_DATA_END to declare the region from 0->RVMODEL_DATA_END into a single PMP region. + +2. Address RAM_LOCATION_FOR_TEST to Address RETURN_INSTRUCTION => PMP region under test. This region has been declared by entering RAM_LOCATION_FOR_TEST into pmpaddr2 and address to RETURN_INSTRUCTION label into pmpaddr3. Then a PMP region is configure from pmpaddr2(RAM_LOCATION_FOR_TEST) to pmpaddr3(RETURN_INSTRUCTION) into TOR mode by setting pmpcfg0[31:24]=PMPREGION2 + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg3, x4 // Updated pmpcfg3 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION3) + // Value to be stored in pmpcfg register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 0*(XLEN/32),4,NOP +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-R-priority.S b/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-R-priority.S new file mode 100644 index 000000000..587abd94d --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-R-priority.S @@ -0,0 +1,202 @@ + +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NA4-priority-r.S +// PMP Test in NA4 address matching mode +// Description: +// Tests the priority by assigning only R permissions to the high priority while R-W-X to low priority region +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NA4_priority_r) +RVTEST_SIGBASE( x13,signature_x13_1) + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg3[31:24] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in NAPOT Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_R|PMP_NA4)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of region3 +#define PMPADDRESS2 TEST_FOR_EXECUTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg3, x4 // Updated pmpcfg3 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-R.S b/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-R.S new file mode 100644 index 000000000..e6756be13 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-R.S @@ -0,0 +1,239 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NA4-R.S +// PMP Test in NA4 address matching mode +// Description: +=> Foreach mode in MPP (including M), for Load/store instruction, perform the instruction referencing an address where the associated pmpcfg.W=0 and observe an access fault or not. +=> Foreach mode, perform instruction fetches to an address where the associated pmpcfg.X=0 and observe an access fault or not. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +=> Do the same for loads where pmpcfg.R=1 and pmpcfg.W=0 to make sure that the W bit only affects stores and AMOs. +*/ +/* COVERPOINTS: (Explanation of updates in /coverage/rv32i_priv.cgf) + (pmpcfg0 >> 8) & 0x18 == 0x10 : 0 // CHECK pmp2cfg in NA4 mode? + (pmpcfg0 >> 8) & 0x01 == 0x01 : 0 // CHECK R-bit in pmp2cfg was HIGH + (pmpcfg0 >> 8) & 0x02 == 0x02 : 0 // CHECK W-bit in pmp2cfg was HIGH + (pmpcfg0 >> 8) & 0x04 == 0x04 : 0 // CHECK X-bit in pmp2cfg was HIGH +// Details are given in /coverage/rv32i_priv.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NA4_r) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg0 [7:0] value to configure address 0->RAM_LOCATION_FOR_TEST in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in NA4 Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_R|PMP_L|PMP_NA4)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(rvtest_code_end) +// in TOR Mode with RWX enabled +// ALSO NOTE THAT PMPREGION2 IS INSIDE THIS REGION, so this test will also check the priority order of PMP regions +#define PMPREGION3 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg1[7:0] value to configure address (rvtest_code_end)->(PMP_region_High) +// in TOR Mode with RWX enabled +#define PMPREGION4 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS0 RAM_LOCATION_FOR_TEST // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS1 TEST_FOR_EXECUTION +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of region3 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of region3 +#define PMPADDRESS3 rvtest_code_end +// PMPADDRESS4 = value to be loaded pmpaddr4 to declare upper address of region4 +#define PMPADDRESS4 PMP_region_High + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration +/* PMP is configure in the following order: +1. Address 0x0000 0000 to Address RAM_LOCATION_FOR_TEST => PMP TOR Region with RWX enabled. This region is the part of the code memory containing our code. For this purpose, pmpaddr0 has been given the value of RAM_LOCATION_FOR_TEST to declare the region from 0->RAM_LOCATION_FOR_TEST into a single PMP region. + +2. Address TEST_FOR_EXECUTION to Address RETURN_INSTRUCTION =====> This is the PMP region under test (A 4byte region == Granularity of Sail. This region has been declared by entering TEST_FOR_EXECUTION into pmpaddr1 and RETURN_INSTRUCTION into pmpaddr2. Then a PMP region is configure into NA4 mode by setting pmpcfg0[15:8]=((PMP_R|PMP_L|PMP_NA4)&0xFF) + +3. Address RAM_LOCATION_FOR_TEST to Address rvtest_code_end => Another PMP region under test. This region has been declared by entering rvtest_code_end into pmpaddr3 and RAM_LOCATION_FOR_TEST into pmpaddr2. configure pmpaddr2(RAM_LOCATION_FOR_TEST) to pmpaddr3(rvtest_code_end) into TOR mode by setting pmpcfg0[31:24]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) + +4. Address rvtest_code_end to address PMP_region_High => PMP TOR Region with RWX enabled. This region is the part of the code memory containing trap handler, epilogs, and other important macro definitions. For this purpose, configure pmpaddr3(rvtest_code_end) to pmpaddr4(PMP_region_High) into TOR mode by setting pmpcfg1[7:0]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)). This PMP Region is mandatory to access signature area in S,U mode */ + /* Assigning addresses to PMP address registers */ + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS4) // Value to be stored in pmpaddr4 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr4, x4 // Updated pmpaddr4 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1 | PMPREGION2 | PMPREGION3) + // Value to be stored in pmpcfg register ; Setting Up PMP Region-1,2,3 + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION4) + // Value to be stored in pmpcfg1 register ; Setting up PMP Region-4 + csrs pmpcfg1, x4 // Updated pmpcfg1 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-RW-priority-level-2.S b/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-RW-priority-level-2.S new file mode 100644 index 000000000..2b84a4322 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-RW-priority-level-2.S @@ -0,0 +1,220 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-TOR-priority-rw-level-2.S +// Tests the priority by assigning only R,W permissions to the highest priority while no permissions to high priority region and R-W-X to low priority region +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NA4_priority_rw_level_2) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg3 [31:24] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled. This is the low priority region +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with nothing enabled +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION). This is the high priority region +// in TOR Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION3 ((((PMP_R|PMP_W|PMP_L|PMP_NA4)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +// PMPADDRESS14 = value to be loaded pmpaddr14 to declare lower address of Region-1 +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr14 to declare region1 +// PMPADDRESS15 = value to be loaded pmpaddr15 to declare upper address of Region-1 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of Region-2 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of Region-2 +#define PMPADDRESS3 RETURN_INSTRUCTION +// PMPADDRESS3 = value to be loaded pmpaddr1 to declare upper address of Region-3 +#define PMPADDRESS1 TEST_FOR_EXECUTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg3, x4 // Updated pmpcfg3 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION3) + // Value to be stored in pmpcfg register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 0*(XLEN/32),4,NOP +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-RW-priority.S b/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-RW-priority.S new file mode 100644 index 000000000..6ca157f61 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-RW-priority.S @@ -0,0 +1,201 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NA4-priority-rw.S +// PMP Test in NA4 address matching mode +// Description: +// Tests the priority by assigning only R,W permissions to the high priority while R-W-X to low priority region +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NA4_priority_rw) +RVTEST_SIGBASE( x13,signature_x13_1) + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg3[31:24] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in NAPOT Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_R|PMP_W|PMP_NA4)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of region3 +#define PMPADDRESS2 TEST_FOR_EXECUTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg3, x4 // Updated pmpcfg3 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-RW.S b/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-RW.S new file mode 100644 index 000000000..6d4137419 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-RW.S @@ -0,0 +1,240 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NA4-RW.S +// PMP Test in NA4 address matching mode +// Description: +=> Foreach mode in MPP (including M), for Load/store instruction, perform the instruction referencing an address where the associated pmpcfg.W=0 and observe an access fault or not. +=> Foreach mode, perform instruction fetches to an address where the associated pmpcfg.X=0 and observe an access fault or not. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +=> Do the same for loads where pmpcfg.R=1 and pmpcfg.W=0 to make sure that the W bit only affects stores and AMOs. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +*/ +/* COVERPOINTS: (Explanation of updates in /coverage/rv32i_priv.cgf) + (pmpcfg0 >> 8) & 0x18 == 0x10 : 0 // CHECK pmp2cfg in NA4 mode? + (pmpcfg0 >> 8) & 0x01 == 0x01 : 0 // CHECK R-bit in pmp2cfg was HIGH + (pmpcfg0 >> 8) & 0x02 == 0x02 : 0 // CHECK W-bit in pmp2cfg was HIGH + (pmpcfg0 >> 8) & 0x04 == 0x04 : 0 // CHECK X-bit in pmp2cfg was HIGH +// Details are given in /coverage/rv32i_priv.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NA4_rw) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg0 [7:0] value to configure address 0->RAM_LOCATION_FOR_TEST in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in NA4 Mode with RW enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_R|PMP_W|PMP_L|PMP_NA4)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(rvtest_code_end) +// in TOR Mode with RWX enabled +// ALSO NOTE THAT PMPREGION2 IS INSIDE THIS REGION, so this test will also check the priority order of PMP regions +#define PMPREGION3 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg1[7:0] value to configure address (rvtest_code_end)->(PMP_region_High) +// in TOR Mode with RWX enabled +#define PMPREGION4 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS0 RAM_LOCATION_FOR_TEST // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS1 TEST_FOR_EXECUTION +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of region3 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of region3 +#define PMPADDRESS3 rvtest_code_end +// PMPADDRESS4 = value to be loaded pmpaddr4 to declare upper address of region4 +#define PMPADDRESS4 PMP_region_High + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration +/* PMP is configure in the following order: +1. Address 0x0000 0000 to Address RAM_LOCATION_FOR_TEST => PMP TOR Region with RWX enabled. This region is the part of the code memory containing our code. For this purpose, pmpaddr0 has been given the value of RAM_LOCATION_FOR_TEST to declare the region from 0->RAM_LOCATION_FOR_TEST into a single PMP region. + +2. Address TEST_FOR_EXECUTION to Address RETURN_INSTRUCTION =====> This is the PMP region under test (A 4byte region == Granularity of Sail. This region has been declared by entering TEST_FOR_EXECUTION into pmpaddr1 and RETURN_INSTRUCTION into pmpaddr2. Then a PMP region is configure into NA4 mode by setting pmpcfg0[15:8]=((PMP_R|PMP_W|PMP_L|PMP_NA4)&0xFF) + +3. Address RAM_LOCATION_FOR_TEST to Address rvtest_code_end => Another PMP region under test. This region has been declared by entering rvtest_code_end into pmpaddr3 and RAM_LOCATION_FOR_TEST into pmpaddr2. configure pmpaddr2(RAM_LOCATION_FOR_TEST) to pmpaddr3(rvtest_code_end) into TOR mode by setting pmpcfg0[31:24]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) + +4. Address rvtest_code_end to address PMP_region_High => PMP TOR Region with RWX enabled. This region is the part of the code memory containing trap handler, epilogs, and other important macro definitions. For this purpose, configure pmpaddr3(rvtest_code_end) to pmpaddr4(PMP_region_High) into TOR mode by setting pmpcfg1[7:0]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)). This PMP Region is mandatory to access signature area in S,U mode */ + /* Assigning addresses to PMP address registers */ + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS4) // Value to be stored in pmpaddr4 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr4, x4 // Updated pmpaddr4 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1 | PMPREGION2 | PMPREGION3) + // Value to be stored in pmpcfg register ; Setting Up PMP Region-1,2,3 + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION4) + // Value to be stored in pmpcfg1 register ; Setting up PMP Region-4 + csrs pmpcfg1, x4 // Updated pmpcfg1 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-RWX.S b/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-RWX.S new file mode 100644 index 000000000..d9394d103 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-RWX.S @@ -0,0 +1,254 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NA4-RWX.S +// PMP Test in NA4 address matching mode +// Description: +=> Foreach mode in MPP (including M), for Load/store instruction, perform the instruction referencing an address where the associated pmpcfg.W=1 and observe an access fault or not. +=> Foreach mode, perform instruction fetches to an address where the associated pmpcfg.X=0 and observe an access fault or not. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +*/ +/* COVERPOINTS: (Explanation of updates in /coverage/rv32i_priv.cgf) + (pmpcfg0 >> 8) & 0x18 == 0x10 : 0 // CHECK pmp2cfg in NA4 mode? + (pmpcfg0 >> 8) & 0x01 == 0x01 : 0 // CHECK R-bit in pmp2cfg was HIGH + (pmpcfg0 >> 8) & 0x02 == 0x02 : 0 // CHECK W-bit in pmp2cfg was HIGH + (pmpcfg0 >> 8) & 0x04 == 0x04 : 0 // CHECK X-bit in pmp2cfg was HIGH +// Details are given in /coverage/rv32i_priv.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NA4_rwx) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrc pmpcfgi , a5 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrc pmpaddri, a5 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg0 [7:0] value to configure address 0->RAM_LOCATION_FOR_TEST in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in NA4 Mode with RW enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_NA4)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(rvtest_code_end) +// in TOR Mode with RWX enabled +// ALSO NOTE THAT PMPREGION2 IS INSIDE THIS REGION, so this test will also check the priority order of PMP regions +#define PMPREGION3 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg1[7:0] value to configure address (rvtest_code_end)->(PMP_region_High) +// in TOR Mode with RWX enabled +#define PMPREGION4 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS0 RAM_LOCATION_FOR_TEST // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS1 TEST_FOR_EXECUTION +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of region3 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of region3 +#define PMPADDRESS3 rvtest_code_end +// PMPADDRESS4 = value to be loaded pmpaddr4 to declare upper address of region4 +#define PMPADDRESS4 PMP_region_High + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration +/* PMP is configure in the following order: +1. Address 0x0000 0000 to Address RAM_LOCATION_FOR_TEST => PMP TOR Region with RWX enabled. +This region is the part of the code memory containing our code and the region between code_end to data_begin. +For this purpose, pmpaddr0 has been given the value of RAM_LOCATION_FOR_TEST to +declare the region from 0->RAM_LOCATION_FOR_TEST into a single PMP region. + +2. Address TEST_FOR_EXECUTION to Address RETURN_INSTRUCTION =====> This is the PMP region under test (A 4byte region == Granularity of Sail.) +This region has been declared by entering TEST_FOR_EXECUTION into pmpaddr1 and RETURN_INSTRUCTION into pmpaddr2. +Then a PMP region is configure into NA4 mode by setting pmpcfg0[15:8]=PMPREGION2 + +3. Address RAM_LOCATION_FOR_TEST to Address rvtest_code_end => Another PMP region under test. +This region has been declared by entering rvtest_code_end into pmpaddr3 and +RAM_LOCATION_FOR_TEST into pmpaddr2. configure pmpaddr2(RAM_LOCATION_FOR_TEST) +to pmpaddr3(rvtest_code_end) into TOR mode +by setting pmpcfg0[31:24]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) + +4. Address rvtest_code_end to address PMP_region_High => PMP TOR Region with RWX enabled. +This region is the part of the code memory containing trap handler, epilogs, and other important macro definitions. +For this purpose, configure pmpaddr3(rvtest_code_end) to pmpaddr4(PMP_region_High) +into TOR mode by setting pmpcfg1[7:0]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)). +This PMP Region is mandatory to access signature area in S,U mode */ + + /* Assigning addresses to PMP address registers */ + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS4) // Value to be stored in pmpaddr4 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr4, x4 // Updated pmpaddr4 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1 | PMPREGION2 | PMPREGION3) + // Value to be stored in pmpcfg register ; Setting Up PMP Region-1,2,3 + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION4) + // Value to be stored in pmpcfg1 register ; Setting up PMP Region-4 + csrs pmpcfg1, x4 // Updated pmpcfg1 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + nop + j exit +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + + + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-RX-priority-level-2.S b/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-RX-priority-level-2.S new file mode 100644 index 000000000..9e18144b3 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-RX-priority-level-2.S @@ -0,0 +1,220 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-TOR-priority-rx-level-2.S +// Tests the priority by assigning only R,X permissions to the highest priority while no permissions to high priority region and R-W-X to low priority region +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NA4_priority_rx_level_2) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg3 [31:24] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled. This is the low priority region +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with nothing enabled +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION). This is the high priority region +// in TOR Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION3 ((((PMP_R|PMP_X|PMP_L|PMP_NA4)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +// PMPADDRESS14 = value to be loaded pmpaddr14 to declare lower address of Region-1 +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr14 to declare region1 +// PMPADDRESS15 = value to be loaded pmpaddr15 to declare upper address of Region-1 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of Region-2 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of Region-2 +#define PMPADDRESS3 RETURN_INSTRUCTION +// PMPADDRESS3 = value to be loaded pmpaddr1 to declare upper address of Region-3 +#define PMPADDRESS1 TEST_FOR_EXECUTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg3, x4 // Updated pmpcfg3 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION3) + // Value to be stored in pmpcfg register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 0*(XLEN/32),4,NOP +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-RX-priority.S b/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-RX-priority.S new file mode 100644 index 000000000..6cfba0c46 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-RX-priority.S @@ -0,0 +1,201 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NA4-priority-rx.S +// PMP Test in NA4 address matching mode +// Description: +// Tests the priority by assigning only R,X permissions to the high priority while R-W-X to low priority region +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NA4_priority_rx) +RVTEST_SIGBASE( x13,signature_x13_1) + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg3[31:24] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in NAPOT Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_R|PMP_X|PMP_NA4)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of region3 +#define PMPADDRESS2 TEST_FOR_EXECUTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg3, x4 // Updated pmpcfg3 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-RX.S b/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-RX.S new file mode 100644 index 000000000..0fd809790 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-RX.S @@ -0,0 +1,238 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NA4-RX.S +// PMP Test in NA4 address matching mode +// Description: +=> Foreach mode in MPP (including M), for Load/store instruction, perform the instruction referencing an address where the associated pmpcfg.W=1 and observe an access fault or not. +=> Foreach mode, perform instruction fetches to an address where the associated pmpcfg.X=0 and observe an access fault or not. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +*/ +/* COVERPOINTS: (Explanation of updates in /coverage/rv32i_priv.cgf) + (pmpcfg0 >> 8) & 0x18 == 0x10 : 0 // CHECK pmp2cfg in NA4 mode? + (pmpcfg0 >> 8) & 0x01 == 0x01 : 0 // CHECK R-bit in pmp2cfg was HIGH + (pmpcfg0 >> 8) & 0x02 == 0x02 : 0 // CHECK W-bit in pmp2cfg was HIGH + (pmpcfg0 >> 8) & 0x04 == 0x04 : 0 // CHECK X-bit in pmp2cfg was HIGH +// Details are given in /coverage/rv32i_priv.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NA4_rx) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg0 [7:0] value to configure address 0->RAM_LOCATION_FOR_TEST in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in NA4 Mode with RX enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_R|PMP_X|PMP_L|PMP_NA4)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(rvtest_code_end) +// in TOR Mode with RWX enabled +// ALSO NOTE THAT PMPREGION2 IS INSIDE THIS REGION, so this test will also check the priority order of PMP regions +#define PMPREGION3 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg1[7:0] value to configure address (rvtest_code_end)->(PMP_region_High) +// in TOR Mode with RWX enabled +#define PMPREGION4 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS0 RAM_LOCATION_FOR_TEST // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS1 TEST_FOR_EXECUTION +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of region3 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of region3 +#define PMPADDRESS3 rvtest_code_end +// PMPADDRESS4 = value to be loaded pmpaddr4 to declare upper address of region4 +#define PMPADDRESS4 PMP_region_High + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration +/* PMP is configure in the following order: +1. Address 0x0000 0000 to Address RAM_LOCATION_FOR_TEST => PMP TOR Region with RWX enabled. This region is the part of the code memory containing our code. For this purpose, pmpaddr0 has been given the value of RAM_LOCATION_FOR_TEST to declare the region from 0->RAM_LOCATION_FOR_TEST into a single PMP region. + +2. Address TEST_FOR_EXECUTION to Address RETURN_INSTRUCTION =====> This is the PMP region under test (A 4byte region == Granularity of Sail. This region has been declared by entering TEST_FOR_EXECUTION into pmpaddr1 and RETURN_INSTRUCTION into pmpaddr2. Then a PMP region is configure into NA4 mode by setting pmpcfg0[15:8]=PMPREGION2 + +3. Address RAM_LOCATION_FOR_TEST to Address rvtest_code_end => Another PMP region under test. This region has been declared by entering rvtest_code_end into pmpaddr3 and RAM_LOCATION_FOR_TEST into pmpaddr2. configure pmpaddr2(RAM_LOCATION_FOR_TEST) to pmpaddr3(rvtest_code_end) into TOR mode by setting pmpcfg0[31:24]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) + +4. Address rvtest_code_end to address PMP_region_High => PMP TOR Region with RWX enabled. This region is the part of the code memory containing trap handler, epilogs, and other important macro definitions. For this purpose, configure pmpaddr3(rvtest_code_end) to pmpaddr4(PMP_region_High) into TOR mode by setting pmpcfg1[7:0]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)). This PMP Region is mandatory to access signature area in S,U mode */ + /* Assigning addresses to PMP address registers */ + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS4) // Value to be stored in pmpaddr4 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr4, x4 // Updated pmpaddr4 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1 | PMPREGION2 | PMPREGION3) + // Value to be stored in pmpcfg register ; Setting Up PMP Region-1,2,3 + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION4) + // Value to be stored in pmpcfg1 register ; Setting up PMP Region-4 + csrs pmpcfg1, x4 // Updated pmpcfg1 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-X-priority-level-2.S b/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-X-priority-level-2.S new file mode 100644 index 000000000..8b67ed450 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-X-priority-level-2.S @@ -0,0 +1,221 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-TOR-priority-x-level-2.S +// Tests the priority by assigning only X permissions to the highest priority while no permissions to high priority region and R-W-X to low priority region +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NA4_priority_x_level_2) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg3 [31:24] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled. This is the low priority region +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with nothing enabled +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION). This is the high priority region +// in TOR Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION3 ((((PMP_X|PMP_L|PMP_NA4)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +// PMPADDRESS14 = value to be loaded pmpaddr14 to declare lower address of Region-1 +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr14 to declare region1 +// PMPADDRESS15 = value to be loaded pmpaddr15 to declare upper address of Region-1 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of Region-2 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of Region-2 +#define PMPADDRESS3 RETURN_INSTRUCTION +// PMPADDRESS3 = value to be loaded pmpaddr1 to declare upper address of Region-3 +#define PMPADDRESS1 TEST_FOR_EXECUTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg3, x4 // Updated pmpcfg3 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION3) + // Value to be stored in pmpcfg register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 0*(XLEN/32),4,NOP +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-X-priority.S b/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-X-priority.S new file mode 100644 index 000000000..9e9f667e7 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-X-priority.S @@ -0,0 +1,201 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NA4-priority-x.S +// PMP Test in NA4 address matching mode +// Description: +// Tests the priority by assigning only X permissions to the high priority while R-W-X to low priority region +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NA4_priority_x) +RVTEST_SIGBASE( x13,signature_x13_1) + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg3[31:24] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in NAPOT Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_X|PMP_NA4)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of region3 +#define PMPADDRESS2 TEST_FOR_EXECUTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg3, x4 // Updated pmpcfg3 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-X.S b/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-X.S new file mode 100644 index 000000000..a9ca012f2 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-NA4-X.S @@ -0,0 +1,238 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NA4-X.S +// PMP Test in NA4 address matching mode +// Description: +=> Foreach mode in MPP (including M), for Load/store instruction, perform the instruction referencing an address where the associated pmpcfg.W=1 and observe an access fault or not. +=> Foreach mode, perform instruction fetches to an address where the associated pmpcfg.X=0 and observe an access fault or not. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +*/ +/* COVERPOINTS: (Explanation of updates in /coverage/rv32i_priv.cgf) + (pmpcfg0 >> 8) & 0x18 == 0x10 : 0 // CHECK pmp2cfg in NA4 mode? + (pmpcfg0 >> 8) & 0x01 == 0x01 : 0 // CHECK R-bit in pmp2cfg was HIGH + (pmpcfg0 >> 8) & 0x02 == 0x02 : 0 // CHECK W-bit in pmp2cfg was HIGH + (pmpcfg0 >> 8) & 0x04 == 0x04 : 0 // CHECK X-bit in pmp2cfg was HIGH +// Details are given in /coverage/rv32i_priv.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NA4_x) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg0 [7:0] value to configure address 0->RAM_LOCATION_FOR_TEST in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in NA4 Mode with X enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_X|PMP_L|PMP_NA4)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(rvtest_code_end) +// in TOR Mode with RWX enabled +// ALSO NOTE THAT PMPREGION2 IS INSIDE THIS REGION, so this test will also check the priority order of PMP regions +#define PMPREGION3 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg1[7:0] value to configure address (rvtest_code_end)->(PMP_region_High) +// in TOR Mode with RWX enabled +#define PMPREGION4 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS0 RAM_LOCATION_FOR_TEST // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS1 TEST_FOR_EXECUTION +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of region3 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of region3 +#define PMPADDRESS3 rvtest_code_end +// PMPADDRESS4 = value to be loaded pmpaddr4 to declare upper address of region4 +#define PMPADDRESS4 PMP_region_High + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration +/* PMP is configure in the following order: +1. Address 0x0000 0000 to Address RAM_LOCATION_FOR_TEST => PMP TOR Region with RWX enabled. This region is the part of the code memory containing our code. For this purpose, pmpaddr0 has been given the value of RAM_LOCATION_FOR_TEST to declare the region from 0->RAM_LOCATION_FOR_TEST into a single PMP region. + +2. Address TEST_FOR_EXECUTION to Address RETURN_INSTRUCTION =====> This is the PMP region under test (A 4byte region == Granularity of Sail. This region has been declared by entering TEST_FOR_EXECUTION into pmpaddr1 and RETURN_INSTRUCTION into pmpaddr2. Then a PMP region is configure into NA4 mode by setting pmpcfg0[15:8]=PMPREGION2 + +3. Address RAM_LOCATION_FOR_TEST to Address rvtest_code_end => Another PMP region under test. This region has been declared by entering rvtest_code_end into pmpaddr3 and RAM_LOCATION_FOR_TEST into pmpaddr2. configure pmpaddr2(RAM_LOCATION_FOR_TEST) to pmpaddr3(rvtest_code_end) into TOR mode by setting pmpcfg0[31:24]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) + +4. Address rvtest_code_end to address PMP_region_High => PMP TOR Region with RWX enabled. This region is the part of the code memory containing trap handler, epilogs, and other important macro definitions. For this purpose, configure pmpaddr3(rvtest_code_end) to pmpaddr4(PMP_region_High) into TOR mode by setting pmpcfg1[7:0]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)). This PMP Region is mandatory to access signature area in S,U mode */ + /* Assigning addresses to PMP address registers */ + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS4) // Value to be stored in pmpaddr4 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr4, x4 // Updated pmpaddr4 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1 | PMPREGION2 | PMPREGION3) + // Value to be stored in pmpcfg register ; Setting Up PMP Region-1,2,3 + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION4) + // Value to be stored in pmpcfg1 register ; Setting up PMP Region-4 + csrs pmpcfg1, x4 // Updated pmpcfg1 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-R-priority-level-2.S b/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-R-priority-level-2.S new file mode 100644 index 000000000..86d0dd365 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-R-priority-level-2.S @@ -0,0 +1,220 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NAPOT-priority-r-level-2.S +// Tests the priority by assigning only R permissions to the highest priority while no permissions to high priority region and R-W-X to low priority region +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NAPOT_priority_r_level_2) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg3 [31:24] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled. This is the low priority region +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with nothing enabled +#define PMPREGION2 ((((PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION3 ((((PMP_R|PMP_L|PMP_NAPOT)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +// PMPADDRESS14 = value to be loaded pmpaddr14 to declare lower address of Region-1 +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr14 to declare region1 +// PMPADDRESS15 = value to be loaded pmpaddr15 to declare upper address of Region-1 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of Region-2 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of Region-2 +#define PMPADDRESS3 RETURN_INSTRUCTION +// PMPADDRESS3 = value to be loaded pmpaddr1 to declare upper address of Region-3 +#define PMPADDRESS1 TEST_FOR_EXECUTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg3, x4 // Updated pmpcfg3 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION3) + // Value to be stored in pmpcfg register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,NOP +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-R-priority.S b/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-R-priority.S new file mode 100644 index 000000000..18f67cbc4 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-R-priority.S @@ -0,0 +1,201 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NAPOT-priority-r.S +// PMP Test in NAPOT address matching mode +// Description: +// Tests the priority by assigning only R permissions to the high priority while R-W-X to low priority region +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NAPOT_priority_r) +RVTEST_SIGBASE( x13,signature_x13_1) + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg3[31:24] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in NAPOT Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_R|PMP_NAPOT)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of region3 +#define PMPADDRESS2 TEST_FOR_EXECUTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg3, x4 // Updated pmpcfg3 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-R.S b/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-R.S new file mode 100644 index 000000000..83d71d904 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-R.S @@ -0,0 +1,239 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NAPOT-R.S +// PMP Test in NAPOT address matching mode +// Description: +=> Foreach mode in MPP (including M), for Load/store instruction, perform the instruction referencing an address where the associated pmpcfg.W=0 and observe an access fault or not. +=> Foreach mode, perform instruction fetches to an address where the associated pmpcfg.X=0 and observe an access fault or not. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +=> Do the same for loads where pmpcfg.R=1 and pmpcfg.W=0 to make sure that the W bit only affects stores and AMOs. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +*/ +/* COVERPOINTS: (Explanation of updates in /coverage/rv32i_priv.cgf) + (pmpcfg0 >> 16) & 0x18 == 0x18 : 0 // CHECK pmp2cfg in NAPOT mode? + (pmpcfg0 >> 16) & 0x01 == 0x01 : 0 // CHECK R-bit in pmp2cfg was HIGH + (pmpcfg0 >> 16) & 0x02 == 0x02 : 0 // CHECK W-bit in pmp2cfg was HIGH + (pmpcfg0 >> 16) & 0x04 == 0x04 : 0 // CHECK X-bit in pmp2cfg was HIGH +// Details are given in /coverage/rv32i_priv.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NAPOT_r) +RVTEST_SIGBASE( x13,signature_x13_1) + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg0 [7:0] value to configure address 0->RAM_LOCATION_FOR_TEST in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in NAPOT Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_R|PMP_L|PMP_NAPOT)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(rvtest_code_end) +// in TOR Mode with RWX enabled +// ALSO NOTE THAT PMPREGION2 IS INSIDE THIS REGION, so this test will also check the priority order of PMP regions +#define PMPREGION3 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg1[7:0] value to configure address (rvtest_code_end)->(PMP_region_High) +// in TOR Mode with RWX enabled +#define PMPREGION4 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS0 RAM_LOCATION_FOR_TEST // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS1 TEST_FOR_EXECUTION +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of region3 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of region3 +#define PMPADDRESS3 rvtest_code_end +// PMPADDRESS4 = value to be loaded pmpaddr4 to declare upper address of region4 +#define PMPADDRESS4 PMP_region_High + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration +/* PMP is configure in the following order: +1. Address 0x0000 0000 to Address RAM_LOCATION_FOR_TEST => PMP TOR Region with RWX enabled. This region is the part of the code memory containing our code. For this purpose, pmpaddr0 has been given the value of RAM_LOCATION_FOR_TEST to declare the region from 0->RAM_LOCATION_FOR_TEST into a single PMP region. + +2. Address TEST_FOR_EXECUTION to Address RETURN_INSTRUCTION =====> This is the PMP region under test (A 4byte region == Granularity of Sail. This region has been declared by entering TEST_FOR_EXECUTION into pmpaddr1. Then a PMP region is configure into NAPOT mode by setting pmpcfg0[15:8]=PMPREGION2 + +3. Address RAM_LOCATION_FOR_TEST to Address rvtest_code_end => Another PMP region under test. This region has been declared by entering rvtest_code_end into pmpaddr3 and RAM_LOCATION_FOR_TEST into pmpaddr2. configure pmpaddr2(RAM_LOCATION_FOR_TEST) to pmpaddr3(rvtest_code_end) into TOR mode by setting pmpcfg0[31:24]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) + +4. Address rvtest_code_end to address PMP_region_High => PMP TOR Region with RWX enabled. This region is the part of the code memory containing trap handler, epilogs, and other important macro definitions. For this purpose, configure pmpaddr3(rvtest_code_end) to pmpaddr4(PMP_region_High) into TOR mode by setting pmpcfg1[7:0]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)). This PMP Region is mandatory to access signature area in S,U mode */ + /* Assigning addresses to PMP address registers */ + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS4) // Value to be stored in pmpaddr4 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr4, x4 // Updated pmpaddr4 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1 | PMPREGION2 | PMPREGION3) + // Value to be stored in pmpcfg register ; Setting Up PMP Region-1,2,3 + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION4) + // Value to be stored in pmpcfg1 register ; Setting up PMP Region-4 + csrs pmpcfg1, x4 // Updated pmpcfg1 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-RW-priority-level-2.S b/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-RW-priority-level-2.S new file mode 100644 index 000000000..034021993 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-RW-priority-level-2.S @@ -0,0 +1,221 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NAPOT-priority-rw-level-2.S +// Tests the priority by assigning only R, w permissions to the highest priority while no permissions to high priority region and R-W-X to low priority region +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NAPOT_priority_rw_level_2) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg3 [31:24] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled. This is the low priority region +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with nothing enabled +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION3 ((((PMP_R|PMP_W|PMP_L|PMP_NAPOT)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +// PMPADDRESS14 = value to be loaded pmpaddr14 to declare lower address of Region-1 +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr14 to declare region1 +// PMPADDRESS15 = value to be loaded pmpaddr15 to declare upper address of Region-1 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of Region-2 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of Region-2 +#define PMPADDRESS3 RETURN_INSTRUCTION +// PMPADDRESS3 = value to be loaded pmpaddr1 to declare upper address of Region-3 +#define PMPADDRESS1 TEST_FOR_EXECUTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg3, x4 // Updated pmpcfg3 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION3) + // Value to be stored in pmpcfg register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,NOP +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-RW-priority.S b/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-RW-priority.S new file mode 100644 index 000000000..f1bebe5f0 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-RW-priority.S @@ -0,0 +1,201 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NAPOT-priority-rw.S +// PMP Test in NAPOT address matching mode +// Description: +// Tests the priority by assigning only R,W permissions to the high priority while R-W-X to low priority region +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NAPOT_priority_rw) +RVTEST_SIGBASE( x13,signature_x13_1) + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg3[31:24] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in NAPOT Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_R|PMP_W|PMP_NAPOT)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of region3 +#define PMPADDRESS2 TEST_FOR_EXECUTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg3, x4 // Updated pmpcfg3 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-RW.S b/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-RW.S new file mode 100644 index 000000000..b983e2cb9 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-RW.S @@ -0,0 +1,239 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NAPOT-RW.S +// PMP Test in NAPOT address matching mode +// Description: +=> Foreach mode in MPP (including M), for Load/store instruction, perform the instruction referencing an address where the associated pmpcfg.W=0 and observe an access fault or not. +=> Foreach mode, perform instruction fetches to an address where the associated pmpcfg.X=0 and observe an access fault or not. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +=> Do the same for loads where pmpcfg.R=1 and pmpcfg.W=0 to make sure that the W bit only affects stores and AMOs. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +*/ +/* COVERPOINTS: (Explanation of updates in /coverage/rv32i_priv.cgf) + (pmpcfg0 >> 16) & 0x18 == 0x18 : 0 // CHECK pmp2cfg in NAPOT mode? + (pmpcfg0 >> 16) & 0x01 == 0x01 : 0 // CHECK R-bit in pmp2cfg was HIGH + (pmpcfg0 >> 16) & 0x02 == 0x02 : 0 // CHECK W-bit in pmp2cfg was HIGH + (pmpcfg0 >> 16) & 0x04 == 0x04 : 0 // CHECK X-bit in pmp2cfg was HIGH +// Details are given in /coverage/rv32i_priv.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NAPOT_rw) +RVTEST_SIGBASE( x13,signature_x13_1) + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg0 [7:0] value to configure address 0->RAM_LOCATION_FOR_TEST in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in NAPOT Mode with RW enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_R|PMP_W|PMP_L|PMP_NAPOT)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(rvtest_code_end) +// in TOR Mode with RWX enabled +// ALSO NOTE THAT PMPREGION2 IS INSIDE THIS REGION, so this test will also check the priority order of PMP regions +#define PMPREGION3 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg1[7:0] value to configure address (rvtest_code_end)->(PMP_region_High) +// in TOR Mode with RWX enabled +#define PMPREGION4 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS0 RAM_LOCATION_FOR_TEST // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS1 TEST_FOR_EXECUTION +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of region3 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of region3 +#define PMPADDRESS3 rvtest_code_end +// PMPADDRESS4 = value to be loaded pmpaddr4 to declare upper address of region4 +#define PMPADDRESS4 PMP_region_High + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration +/* PMP is configure in the following order: +1. Address 0x0000 0000 to Address RAM_LOCATION_FOR_TEST => PMP TOR Region with RWX enabled. This region is the part of the code memory containing our code. For this purpose, pmpaddr0 has been given the value of RAM_LOCATION_FOR_TEST to declare the region from 0->RAM_LOCATION_FOR_TEST into a single PMP region. + +2. Address TEST_FOR_EXECUTION to Address RETURN_INSTRUCTION =====> This is the PMP region under test (A 4byte region == Granularity of Sail. This region has been declared by entering TEST_FOR_EXECUTION into pmpaddr1 and RETURN_INSTRUCTION into pmpaddr2. Then a PMP region is configure into NA4 mode by setting pmpcfg0[15:8]=PMPREGION2 + +3. Address RAM_LOCATION_FOR_TEST to Address rvtest_code_end => Another PMP region under test. This region has been declared by entering rvtest_code_end into pmpaddr3 and RAM_LOCATION_FOR_TEST into pmpaddr2. configure pmpaddr2(RAM_LOCATION_FOR_TEST) to pmpaddr3(rvtest_code_end) into TOR mode by setting pmpcfg0[31:24]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) + +4. Address rvtest_code_end to address PMP_region_High => PMP TOR Region with RWX enabled. This region is the part of the code memory containing trap handler, epilogs, and other important macro definitions. For this purpose, configure pmpaddr3(rvtest_code_end) to pmpaddr4(PMP_region_High) into TOR mode by setting pmpcfg1[7:0]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)). This PMP Region is mandatory to access signature area in S,U mode */ + /* Assigning addresses to PMP address registers */ + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS4) // Value to be stored in pmpaddr4 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr4, x4 // Updated pmpaddr4 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1 | PMPREGION2 | PMPREGION3) + // Value to be stored in pmpcfg register ; Setting Up PMP Region-1,2,3 + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION4) + // Value to be stored in pmpcfg1 register ; Setting up PMP Region-4 + csrs pmpcfg1, x4 // Updated pmpcfg1 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-RWX.S b/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-RWX.S new file mode 100644 index 000000000..98db31688 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-RWX.S @@ -0,0 +1,240 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NAPOT-RWX.S +// PMP Test in NAPOT address matching mode +// Description: +=> Foreach mode in MPP (including M), for Load/store instruction, perform the instruction referencing an address where the associated pmpcfg.W=0 and observe an access fault or not. +=> Foreach mode, perform instruction fetches to an address where the associated pmpcfg.X=0 and observe an access fault or not. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +=> Do the same for loads where pmpcfg.R=1 and pmpcfg.W=0 to make sure that the W bit only affects stores and AMOs. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +*/ +/* COVERPOINTS: (Explanation of updates in /coverage/rv32i_priv.cgf) + (pmpcfg0 >> 16) & 0x18 == 0x18 : 0 // CHECK pmp2cfg in NAPOT mode? + (pmpcfg0 >> 16) & 0x01 == 0x01 : 0 // CHECK R-bit in pmp2cfg was HIGH + (pmpcfg0 >> 16) & 0x02 == 0x02 : 0 // CHECK W-bit in pmp2cfg was HIGH + (pmpcfg0 >> 16) & 0x04 == 0x04 : 0 // CHECK X-bit in pmp2cfg was HIGH +// Details are given in /coverage/rv32i_priv.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NAPOT_rwx) +RVTEST_SIGBASE( x13,signature_x13_1) + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg0 [7:0] value to configure address 0->RAM_LOCATION_FOR_TEST in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in NAPOT Mode with RWX enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_NAPOT)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(rvtest_code_end) +// in TOR Mode with RWX enabled +// ALSO NOTE THAT PMPREGION2 IS INSIDE THIS REGION, so this test will also check the priority order of PMP regions +#define PMPREGION3 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg1[7:0] value to configure address (rvtest_code_end)->(PMP_region_High) +// in TOR Mode with RWX enabled +#define PMPREGION4 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS0 RAM_LOCATION_FOR_TEST // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS1 TEST_FOR_EXECUTION +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of region3 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of region3 +#define PMPADDRESS3 rvtest_code_end +// PMPADDRESS4 = value to be loaded pmpaddr4 to declare upper address of region4 +#define PMPADDRESS4 PMP_region_High + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration +/* PMP is configure in the following order: +1. Address 0x0000 0000 to Address RAM_LOCATION_FOR_TEST => PMP TOR Region with RWX enabled. This region is the part of the code memory containing our code. For this purpose, pmpaddr0 has been given the value of RAM_LOCATION_FOR_TEST to declare the region from 0->RAM_LOCATION_FOR_TEST into a single PMP region. + +2. Address TEST_FOR_EXECUTION to Address RETURN_INSTRUCTION =====> This is the PMP region under test (A 4byte region == Granularity of Sail. This region has been declared by entering TEST_FOR_EXECUTION into pmpaddr1 and RETURN_INSTRUCTION into pmpaddr2. Then a PMP region is configure into NA4 mode by setting pmpcfg0[15:8]=PMPREGION2 + +3. Address RAM_LOCATION_FOR_TEST to Address rvtest_code_end => Another PMP region under test. This region has been declared by entering rvtest_code_end into pmpaddr3 and RAM_LOCATION_FOR_TEST into pmpaddr2. configure pmpaddr2(RAM_LOCATION_FOR_TEST) to pmpaddr3(rvtest_code_end) into TOR mode by setting pmpcfg0[31:24]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) + +4. Address rvtest_code_end to address PMP_region_High => PMP TOR Region with RWX enabled. This region is the part of the code memory containing trap handler, epilogs, and other important macro definitions. For this purpose, configure pmpaddr3(rvtest_code_end) to pmpaddr4(PMP_region_High) into TOR mode by setting pmpcfg1[7:0]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)). This PMP Region is mandatory to access signature area in S,U mode */ + /* Assigning addresses to PMP address registers */ + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS4) // Value to be stored in pmpaddr4 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr4, x4 // Updated pmpaddr4 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1 | PMPREGION2 | PMPREGION3) + // Value to be stored in pmpcfg register ; Setting Up PMP Region-1,2,3 + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION4) + // Value to be stored in pmpcfg1 register ; Setting up PMP Region-4 + csrs pmpcfg1, x4 // Updated pmpcfg1 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +TEST_FOR_EXECUTION: + addi x0, x0, 0 + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-RX-priority-level-2.S b/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-RX-priority-level-2.S new file mode 100644 index 000000000..c0942070a --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-RX-priority-level-2.S @@ -0,0 +1,221 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NAPOT-priority-rx-level-2.S +// Tests the priority by assigning only R,X permissions to the highest priority while no permissions to high priority region and R-W-X to low priority region +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NAPOT_priority_rx_level_2) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg3 [31:24] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled. This is the low priority region +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with nothing enabled +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION3 ((((PMP_R|PMP_X|PMP_L|PMP_NAPOT)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +// PMPADDRESS14 = value to be loaded pmpaddr14 to declare lower address of Region-1 +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr14 to declare region1 +// PMPADDRESS15 = value to be loaded pmpaddr15 to declare upper address of Region-1 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of Region-2 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of Region-2 +#define PMPADDRESS3 RETURN_INSTRUCTION +// PMPADDRESS3 = value to be loaded pmpaddr1 to declare upper address of Region-3 +#define PMPADDRESS1 TEST_FOR_EXECUTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg3, x4 // Updated pmpcfg3 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION3) + // Value to be stored in pmpcfg register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,NOP +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-RX-priority.S b/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-RX-priority.S new file mode 100644 index 000000000..7f9ae80cb --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-RX-priority.S @@ -0,0 +1,201 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NAPOT-priority-rx.S +// PMP Test in NAPOT address matching mode +// Description: +// Tests the priority by assigning only R,X permissions to the high priority while R-W-X to low priority region +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NAPOT_priority_rx) +RVTEST_SIGBASE( x13,signature_x13_1) + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg3[31:24] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in NAPOT Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_R|PMP_X|PMP_NAPOT)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of region3 +#define PMPADDRESS2 TEST_FOR_EXECUTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg3, x4 // Updated pmpcfg3 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-RX.S b/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-RX.S new file mode 100644 index 000000000..1a24d6354 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-RX.S @@ -0,0 +1,239 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NAPOT-RX.S +// PMP Test in NAPOT address matching mode +// Description: +=> Foreach mode in MPP (including M), for Load/store instruction, perform the instruction referencing an address where the associated pmpcfg.W=0 and observe an access fault or not. +=> Foreach mode, perform instruction fetches to an address where the associated pmpcfg.X=0 and observe an access fault or not. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +=> Do the same for loads where pmpcfg.R=1 and pmpcfg.W=0 to make sure that the W bit only affects stores and AMOs. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +*/ +/* COVERPOINTS: (Explanation of updates in /coverage/rv32i_priv.cgf) + (pmpcfg0 >> 16) & 0x18 == 0x18 : 0 // CHECK pmp2cfg in NAPOT mode? + (pmpcfg0 >> 16) & 0x01 == 0x01 : 0 // CHECK R-bit in pmp2cfg was HIGH + (pmpcfg0 >> 16) & 0x02 == 0x02 : 0 // CHECK W-bit in pmp2cfg was HIGH + (pmpcfg0 >> 16) & 0x04 == 0x04 : 0 // CHECK X-bit in pmp2cfg was HIGH +// Details are given in /coverage/rv32i_priv.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NAPOT_rx) +RVTEST_SIGBASE( x13,signature_x13_1) + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg0 [7:0] value to configure address 0->RAM_LOCATION_FOR_TEST in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in NAPOT Mode with RX enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_R|PMP_X|PMP_L|PMP_NAPOT)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(rvtest_code_end) +// in TOR Mode with RWX enabled +// ALSO NOTE THAT PMPREGION2 IS INSIDE THIS REGION, so this test will also check the priority order of PMP regions +#define PMPREGION3 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg1[7:0] value to configure address (rvtest_code_end)->(PMP_region_High) +// in TOR Mode with RWX enabled +#define PMPREGION4 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS0 RAM_LOCATION_FOR_TEST // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS1 TEST_FOR_EXECUTION +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of region3 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of region3 +#define PMPADDRESS3 rvtest_code_end +// PMPADDRESS4 = value to be loaded pmpaddr4 to declare upper address of region4 +#define PMPADDRESS4 PMP_region_High + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration +/* PMP is configure in the following order: +1. Address 0x0000 0000 to Address RAM_LOCATION_FOR_TEST => PMP TOR Region with RWX enabled. This region is the part of the code memory containing our code. For this purpose, pmpaddr0 has been given the value of RAM_LOCATION_FOR_TEST to declare the region from 0->RAM_LOCATION_FOR_TEST into a single PMP region. + +2. Address TEST_FOR_EXECUTION to Address RETURN_INSTRUCTION =====> This is the PMP region under test (A 4byte region == Granularity of Sail. This region has been declared by entering TEST_FOR_EXECUTION into pmpaddr1 and RETURN_INSTRUCTION into pmpaddr2. Then a PMP region is configure into NA4 mode by setting pmpcfg0[15:8]=PMPREGION2 + +3. Address RAM_LOCATION_FOR_TEST to Address rvtest_code_end => Another PMP region under test. This region has been declared by entering rvtest_code_end into pmpaddr3 and RAM_LOCATION_FOR_TEST into pmpaddr2. configure pmpaddr2(RAM_LOCATION_FOR_TEST) to pmpaddr3(rvtest_code_end) into TOR mode by setting pmpcfg0[31:24]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) + +4. Address rvtest_code_end to address PMP_region_High => PMP TOR Region with RWX enabled. This region is the part of the code memory containing trap handler, epilogs, and other important macro definitions. For this purpose, configure pmpaddr3(rvtest_code_end) to pmpaddr4(PMP_region_High) into TOR mode by setting pmpcfg1[7:0]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)). This PMP Region is mandatory to access signature area in S,U mode */ + /* Assigning addresses to PMP address registers */ + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS4) // Value to be stored in pmpaddr4 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr4, x4 // Updated pmpaddr4 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1 | PMPREGION2 | PMPREGION3) + // Value to be stored in pmpcfg register ; Setting Up PMP Region-1,2,3 + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION4) + // Value to be stored in pmpcfg1 register ; Setting up PMP Region-4 + csrs pmpcfg1, x4 // Updated pmpcfg1 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-X-priority-level-2.S b/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-X-priority-level-2.S new file mode 100644 index 000000000..c2d00fc45 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-X-priority-level-2.S @@ -0,0 +1,221 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NAPOT-priority-x-level-2.S +// Tests the priority by assigning only X permissions to the highest priority while no permissions to high priority region and R-W-X to low priority region +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NAPOT_priority_x_level_2) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg3 [31:24] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled. This is the low priority region +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with nothing enabled +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION3 ((((PMP_X|PMP_L|PMP_NAPOT)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +// PMPADDRESS14 = value to be loaded pmpaddr14 to declare lower address of Region-1 +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr14 to declare region1 +// PMPADDRESS15 = value to be loaded pmpaddr15 to declare upper address of Region-1 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of Region-2 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of Region-2 +#define PMPADDRESS3 RETURN_INSTRUCTION +// PMPADDRESS3 = value to be loaded pmpaddr1 to declare upper address of Region-3 +#define PMPADDRESS1 TEST_FOR_EXECUTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg3, x4 // Updated pmpcfg3 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION3) + // Value to be stored in pmpcfg register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,NOP +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-X-priority.S b/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-X-priority.S new file mode 100644 index 000000000..3be250bb8 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-X-priority.S @@ -0,0 +1,201 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NAPOT-priority-x.S +// PMP Test in NAPOT address matching mode +// Description: +// Tests the priority by assigning only X permissions to the high priority while R-W-X to low priority region +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NAPOT_priority_x) +RVTEST_SIGBASE( x13,signature_x13_1) + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg3[31:24] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in NAPOT Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_X|PMP_NAPOT)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of region3 +#define PMPADDRESS2 TEST_FOR_EXECUTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg3, x4 // Updated pmpcfg3 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-X.S b/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-X.S new file mode 100644 index 000000000..874ae62dd --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-NAPOT-X.S @@ -0,0 +1,239 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NAPOT-X.S +// PMP Test in NAPOT address matching mode +// Description: +=> Foreach mode in MPP (including M), for Load/store instruction, perform the instruction referencing an address where the associated pmpcfg.W=0 and observe an access fault or not. +=> Foreach mode, perform instruction fetches to an address where the associated pmpcfg.X=0 and observe an access fault or not. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +=> Do the same for loads where pmpcfg.R=1 and pmpcfg.W=0 to make sure that the W bit only affects stores and AMOs. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +*/ +/* COVERPOINTS: (Explanation of updates in /coverage/rv32i_priv.cgf) + (pmpcfg0 >> 16) & 0x18 == 0x18 : 0 // CHECK pmp2cfg in NAPOT mode? + (pmpcfg0 >> 16) & 0x01 == 0x01 : 0 // CHECK R-bit in pmp2cfg was HIGH + (pmpcfg0 >> 16) & 0x02 == 0x02 : 0 // CHECK W-bit in pmp2cfg was HIGH + (pmpcfg0 >> 16) & 0x04 == 0x04 : 0 // CHECK X-bit in pmp2cfg was HIGH +// Details are given in /coverage/rv32i_priv.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NAPOT_x) +RVTEST_SIGBASE( x13,signature_x13_1) + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg0 [7:0] value to configure address 0->RAM_LOCATION_FOR_TEST in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in NAPOT Mode with X enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_X|PMP_L|PMP_NAPOT)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(rvtest_code_end) +// in TOR Mode with RWX enabled +// ALSO NOTE THAT PMPREGION2 IS INSIDE THIS REGION, so this test will also check the priority order of PMP regions +#define PMPREGION3 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg1[7:0] value to configure address (rvtest_code_end)->(PMP_region_High) +// in TOR Mode with RWX enabled +#define PMPREGION4 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS0 RAM_LOCATION_FOR_TEST // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS1 TEST_FOR_EXECUTION +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of region3 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of region3 +#define PMPADDRESS3 rvtest_code_end +// PMPADDRESS4 = value to be loaded pmpaddr4 to declare upper address of region4 +#define PMPADDRESS4 PMP_region_High + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration +/* PMP is configure in the following order: +1. Address 0x0000 0000 to Address RAM_LOCATION_FOR_TEST => PMP TOR Region with RWX enabled. This region is the part of the code memory containing our code. For this purpose, pmpaddr0 has been given the value of RAM_LOCATION_FOR_TEST to declare the region from 0->RAM_LOCATION_FOR_TEST into a single PMP region. + +2. Address TEST_FOR_EXECUTION to Address RETURN_INSTRUCTION =====> This is the PMP region under test (A 4byte region == Granularity of Sail. This region has been declared by entering TEST_FOR_EXECUTION into pmpaddr1 and RETURN_INSTRUCTION into pmpaddr2. Then a PMP region is configure into NA4 mode by setting pmpcfg0[15:8]=PMPREGION2 + +3. Address RAM_LOCATION_FOR_TEST to Address rvtest_code_end => Another PMP region under test. This region has been declared by entering rvtest_code_end into pmpaddr3 and RAM_LOCATION_FOR_TEST into pmpaddr2. configure pmpaddr2(RAM_LOCATION_FOR_TEST) to pmpaddr3(rvtest_code_end) into TOR mode by setting pmpcfg0[31:24]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) + +4. Address rvtest_code_end to address PMP_region_High => PMP TOR Region with RWX enabled. This region is the part of the code memory containing trap handler, epilogs, and other important macro definitions. For this purpose, configure pmpaddr3(rvtest_code_end) to pmpaddr4(PMP_region_High) into TOR mode by setting pmpcfg1[7:0]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)). This PMP Region is mandatory to access signature area in S,U mode */ + /* Assigning addresses to PMP address registers */ + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS4) // Value to be stored in pmpaddr4 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr4, x4 // Updated pmpaddr4 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1 | PMPREGION2 | PMPREGION3) + // Value to be stored in pmpcfg register ; Setting Up PMP Region-1,2,3 + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION4) + // Value to be stored in pmpcfg1 register ; Setting up PMP Region-4 + csrs pmpcfg1, x4 // Updated pmpcfg1 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-R-priority-level-2.S b/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-R-priority-level-2.S new file mode 100644 index 000000000..5c9fb450d --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-R-priority-level-2.S @@ -0,0 +1,227 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-TOR-priority-r-level-2.S +// Tests the priority by assigning only R permissions to the highest priority while no permissions to high priority region and R-W-X to low priority region +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_TOR_priority_r_level_2) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg3 [31:24] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled. This is the low priority region +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with nothing enabled +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION3 ((((PMP_R|PMP_L|PMP_TOR)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +// PMPADDRESS14 = value to be loaded pmpaddr14 to declare lower address of Region-1 +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr14 to declare region1 +// PMPADDRESS15 = value to be loaded pmpaddr15 to declare upper address of Region-1 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of Region-2 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of Region-2 +#define PMPADDRESS3 RETURN_INSTRUCTION +// PMPADDRESS2 = value to be loaded pmpaddr0 to declare lower address of Region-3 +#define PMPADDRESS0 TEST_FOR_EXECUTION +// PMPADDRESS3 = value to be loaded pmpaddr1 to declare upper address of Region-3 +#define PMPADDRESS1 RETURN_INSTRUCTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg3, x4 // Updated pmpcfg3 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION3) + // Value to be stored in pmpcfg register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 0*(XLEN/32),4,NOP +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-R-priority.S b/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-R-priority.S new file mode 100644 index 000000000..27e11d132 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-R-priority.S @@ -0,0 +1,206 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-TOR-priority-r.S +// Tests the priority by assigning only R permissions to the high priority while R-W-X to low priority region +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_TOR_priority_r) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg3 [31:24] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled. This is the low priority region +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_R|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +// PMPADDRESS14 = value to be loaded pmpaddr14 to declare lower address of Region-1 +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr14 to declare region1 +// PMPADDRESS15 = value to be loaded pmpaddr15 to declare upper address of Region-1 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr3 to declare lower address of Region-2 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of Region-2 +#define PMPADDRESS3 RETURN_INSTRUCTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg3, x4 // Updated pmpcfg3 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 0*(XLEN/32),4,NOP +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-R.S b/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-R.S new file mode 100644 index 000000000..354428982 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-R.S @@ -0,0 +1,245 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-tor-R.S +// PMP Test in TOR address matching mode +// Description: +=> Foreach mode in MPP (including M), for Load/store instruction, perform the instruction referencing an address where the associated pmpcfg.W=1 and observe an access fault or not. +=> Foreach mode, perform instruction fetches to an address where the associated pmpcfg.X=0 and observe an access fault or not. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +=> Do the same for loads where pmpcfg.R=1 and pmpcfg.W=0 to make sure that the W bit only affects stores and AMOs. +*/ +/* COVERPOINTS: (Explanation of updates in /coverage/rv32i_priv.cgf) + (pmpcfg0 >> 16) & 0x18 == 0x08 : 0 // CHECK pmp2cfg in TOR mode? + (pmpcfg0 >> 16) & 0x01 == 0x01 : 0 // CHECK R-bit in pmp2cfg was HIGH + (pmpcfg0 >> 16) & 0x02 == 0x02 : 0 // CHECK W-bit in pmp2cfg was HIGH + (pmpcfg0 >> 16) & 0x04 == 0x04 : 0 // CHECK X-bit in pmp2cfg was HIGH +// Details are given in /coverage/rv32i_priv.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_TOR_r) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg0 [7:0] value to configure address 0->RAM_LOCATION_FOR_TEST in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[23:16] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in TOR Mode with X enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_R|PMP_L|PMP_TOR)&0xFF) << PMP2_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg1[7:0] value to configure address (RAM_LOCATION_FOR_TEST)->(rvtest_code_end) +// in TOR Mode with RW enabled +// ALSO NOTE THAT PMPREGION2 IS INSIDE THIS REGION, so this test will also check the priority order of PMP regions +#define PMPREGION3 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg1[15:8] value to configure address (rvtest_code_end)->(PMP_region_High) +// in TOR Mode with RWX enabled +#define PMPREGION4 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS0 RAM_LOCATION_FOR_TEST // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS1 TEST_FOR_EXECUTION +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare upper address of region2 +#define PMPADDRESS2 RETURN_INSTRUCTION +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare lower address of region3 +#define PMPADDRESS3 RAM_LOCATION_FOR_TEST +// PMPADDRESS4 = value to be loaded pmpaddr4 to declare upper address of region3 +#define PMPADDRESS4 rvtest_code_end +// PMPADDRESS5 = value to be loaded pmpaddr5 to declare upper address of region4 +#define PMPADDRESS5 PMP_region_High + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration +/* PMP is configure in the following order: +1. Address 0x8000 0000 to Address RAM_LOCATION_FOR_TEST => PMP TOR Region with RWX enabled. This region is the part of the code memory containing our code. For this purpose, pmpaddr0 has been given the value of RAM_LOCATION_FOR_TEST to declare the region from 0->RAM_LOCATION_FOR_TEST into a single PMP region. + +2. Address TEST_FOR_EXECUTION to Address RETURN_INSTRUCTION => PMP region under test. This region has been declared by entering TEST_FOR_EXECUTION into pmpaddr1 and rvtest_code_end into pmpaddr2. Then a PMP region is configure from pmpaddr2(RETURN_INSTRUCTION) to pmpaddr1(TEST_FOR_EXECUTION) into TOR mode by setting pmpcfg0[23:16]=PMPREGION2 + +3. Address RAM_LOCATION_FOR_TEST to Address rvtest_code_end => PMP region under test. This region has been declared by entering rvtest_code_end into pmpaddr4 and RAM_LOCATION_FOR_TEST into pmpaddr3. configure pmpaddr4(RAM_LOCATION_FOR_TEST) to pmpaddr5(rvtest_code_end) into TOR mode by setting pmpcfg1[15:8]=PMPREGION3 + +4. Address rvtest_code_end to address PMP_region_High => PMP TOR Region with RWX enabled. This region is the part of the code memory containing trap handler, epilogs, and other important macro definitions. For this purpose, configure pmpaddr4(rvtest_code_end) to pmpaddr5(PMP_region_High) into TOR mode by setting pmpcfg1[15:8]=PMPREGION4. This PMP Region is mandatory to access signature area in S,U mode */ + /* Assigning addresses to PMP address registers */ + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS4) // Value to be stored in pmpaddr4 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr4, x4 // Updated pmpaddr4 + nop // Added nop in case of trap + LA(x4, PMPADDRESS5) // Value to be stored in pmpaddr5 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr5, x4 // Updated pmpaddr5 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1 | PMPREGION2) + // Value to be stored in pmpcfg register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION3 | PMPREGION4) + // Value to be stored in pmpcfg1 register + csrs pmpcfg1, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-RW-priority-level-2..S b/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-RW-priority-level-2..S new file mode 100644 index 000000000..ed328850f --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-RW-priority-level-2..S @@ -0,0 +1,229 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-TOR-priority-rw-level-2.S +// Tests the priority by assigning only R,W permissions to the highest priority while no permissions to high priority region and R-W-X to low priority region +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_TOR_priority_rw_level_2) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg3 [31:24] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled. This is the low priority region +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with nothing enabled +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with R,W enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION3 ((((PMP_R|PMP_W|PMP_L|PMP_TOR)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +// PMPADDRESS14 = value to be loaded pmpaddr14 to declare lower address of Region-1 +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr14 to declare region1 +// PMPADDRESS15 = value to be loaded pmpaddr15 to declare upper address of Region-1 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of Region-2 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of Region-2 +#define PMPADDRESS3 RETURN_INSTRUCTION +// PMPADDRESS2 = value to be loaded pmpaddr0 to declare lower address of Region-3 +#define PMPADDRESS0 TEST_FOR_EXECUTION +// PMPADDRESS3 = value to be loaded pmpaddr1 to declare upper address of Region-3 +#define PMPADDRESS1 RETURN_INSTRUCTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg3, x4 // Updated pmpcfg3 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION3) + // Value to be stored in pmpcfg register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 1*(XLEN/32),4,NOP //Single + +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-RW-priority.S b/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-RW-priority.S new file mode 100644 index 000000000..8b390e2e8 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-RW-priority.S @@ -0,0 +1,206 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-TOR-priority-rw.S +// Tests the priority by assigning only rw permissions to the high priority while R-W-X to low priority region +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_TOR_priority_rw) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg3 [31:24] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled. This is the low priority region +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_R|PMP_W|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +// PMPADDRESS14 = value to be loaded pmpaddr14 to declare lower address of Region-1 +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr14 to declare region1 +// PMPADDRESS15 = value to be loaded pmpaddr15 to declare upper address of Region-1 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr3 to declare lower address of Region-2 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of Region-2 +#define PMPADDRESS3 RETURN_INSTRUCTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg3, x4 // Updated pmpcfg3 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 0*(XLEN/32),4,NOP +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-RW.S b/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-RW.S new file mode 100644 index 000000000..7a0ad484e --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-RW.S @@ -0,0 +1,245 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-tor-RW.S +// PMP Test in TOR address matching mode +// Description: +=> Foreach mode in MPP (including M), for Load/store instruction, perform the instruction referencing an address where the associated pmpcfg.W=1 and observe an access fault or not. +=> Foreach mode, perform instruction fetches to an address where the associated pmpcfg.X=0 and observe an access fault or not. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +=> Do the same for loads where pmpcfg.R=1 and pmpcfg.W=0 to make sure that the W bit only affects stores and AMOs. +*/ +/* COVERPOINTS: (Explanation of updates in /coverage/rv32i_priv.cgf) + (pmpcfg0 >> 16) & 0x18 == 0x08 : 0 // CHECK pmp2cfg in TOR mode? + (pmpcfg0 >> 16) & 0x01 == 0x01 : 0 // CHECK R-bit in pmp2cfg was HIGH + (pmpcfg0 >> 16) & 0x02 == 0x02 : 0 // CHECK W-bit in pmp2cfg was HIGH + (pmpcfg0 >> 16) & 0x04 == 0x04 : 0 // CHECK X-bit in pmp2cfg was HIGH +// Details are given in /coverage/rv32i_priv.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_TOR_rw) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg0 [7:0] value to configure address 0->RAM_LOCATION_FOR_TEST in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[23:16] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in TOR Mode with X enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_R|PMP_W|PMP_L|PMP_TOR)&0xFF) << PMP2_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg1[7:0] value to configure address (RAM_LOCATION_FOR_TEST)->(rvtest_code_end) +// in TOR Mode with RW enabled +// ALSO NOTE THAT PMPREGION2 IS INSIDE THIS REGION, so this test will also check the priority order of PMP regions +#define PMPREGION3 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg1[15:8] value to configure address (rvtest_code_end)->(PMP_region_High) +// in TOR Mode with RWX enabled +#define PMPREGION4 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS0 RAM_LOCATION_FOR_TEST // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS1 TEST_FOR_EXECUTION +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare upper address of region2 +#define PMPADDRESS2 RETURN_INSTRUCTION +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare lower address of region3 +#define PMPADDRESS3 RAM_LOCATION_FOR_TEST +// PMPADDRESS4 = value to be loaded pmpaddr4 to declare upper address of region3 +#define PMPADDRESS4 rvtest_code_end +// PMPADDRESS5 = value to be loaded pmpaddr5 to declare upper address of region4 +#define PMPADDRESS5 PMP_region_High + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration +/* PMP is configure in the following order: +1. Address 0x8000 0000 to Address RAM_LOCATION_FOR_TEST => PMP TOR Region with RWX enabled. This region is the part of the code memory containing our code. For this purpose, pmpaddr0 has been given the value of RAM_LOCATION_FOR_TEST to declare the region from 0->RAM_LOCATION_FOR_TEST into a single PMP region. + +2. Address TEST_FOR_EXECUTION to Address RETURN_INSTRUCTION => PMP region under test. This region has been declared by entering TEST_FOR_EXECUTION into pmpaddr1 and rvtest_code_end into pmpaddr2. Then a PMP region is configure from pmpaddr2(RETURN_INSTRUCTION) to pmpaddr1(TEST_FOR_EXECUTION) into TOR mode by setting pmpcfg0[23:16]=PMPREGION2 + +3. Address RAM_LOCATION_FOR_TEST to Address rvtest_code_end => PMP region under test. This region has been declared by entering rvtest_code_end into pmpaddr4 and RAM_LOCATION_FOR_TEST into pmpaddr3. configure pmpaddr4(RAM_LOCATION_FOR_TEST) to pmpaddr5(rvtest_code_end) into TOR mode by setting pmpcfg1[15:8]=PMPREGION3 + +4. Address rvtest_code_end to address PMP_region_High => PMP TOR Region with RWX enabled. This region is the part of the code memory containing trap handler, epilogs, and other important macro definitions. For this purpose, configure pmpaddr4(rvtest_code_end) to pmpaddr5(PMP_region_High) into TOR mode by setting pmpcfg1[15:8]=PMPREGION4. This PMP Region is mandatory to access signature area in S,U mode */ + /* Assigning addresses to PMP address registers */ + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS4) // Value to be stored in pmpaddr4 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr4, x4 // Updated pmpaddr4 + nop // Added nop in case of trap + LA(x4, PMPADDRESS5) // Value to be stored in pmpaddr5 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr5, x4 // Updated pmpaddr5 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1 | PMPREGION2) + // Value to be stored in pmpcfg register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION3 | PMPREGION4) + // Value to be stored in pmpcfg1 register + csrs pmpcfg1, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-RWX.S b/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-RWX.S new file mode 100644 index 000000000..378903513 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-RWX.S @@ -0,0 +1,245 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-tor-RWX.S +// PMP Test in TOR address matching mode +// Description: +=> Foreach mode in MPP (including M), for Load/store instruction, perform the instruction referencing an address where the associated pmpcfg.W=1 and observe an access fault or not. +=> Foreach mode, perform instruction fetches to an address where the associated pmpcfg.X=0 and observe an access fault or not. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +=> Do the same for loads where pmpcfg.R=1 and pmpcfg.W=0 to make sure that the W bit only affects stores and AMOs. +*/ +/* COVERPOINTS: (Explanation of updates in /coverage/rv32i_priv.cgf) + (pmpcfg0 >> 16) & 0x18 == 0x08 : 0 // CHECK pmp2cfg in TOR mode? + (pmpcfg0 >> 16) & 0x01 == 0x01 : 0 // CHECK R-bit in pmp2cfg was HIGH + (pmpcfg0 >> 16) & 0x02 == 0x02 : 0 // CHECK W-bit in pmp2cfg was HIGH + (pmpcfg0 >> 16) & 0x04 == 0x04 : 0 // CHECK X-bit in pmp2cfg was HIGH +// Details are given in /coverage/rv32i_priv.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_TOR_rwx) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg0 [7:0] value to configure address 0->RAM_LOCATION_FOR_TEST in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[23:16] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in TOR Mode with RWX enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP2_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg1[7:0] value to configure address (RAM_LOCATION_FOR_TEST)->(rvtest_code_end) +// in TOR Mode with RW enabled +// ALSO NOTE THAT PMPREGION2 IS INSIDE THIS REGION, so this test will also check the priority order of PMP regions +#define PMPREGION3 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg1[15:8] value to configure address (rvtest_code_end)->(PMP_region_High) +// in TOR Mode with RWX enabled +#define PMPREGION4 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS0 RAM_LOCATION_FOR_TEST // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS1 TEST_FOR_EXECUTION +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare upper address of region2 +#define PMPADDRESS2 RETURN_INSTRUCTION +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare lower address of region3 +#define PMPADDRESS3 RAM_LOCATION_FOR_TEST +// PMPADDRESS4 = value to be loaded pmpaddr4 to declare upper address of region3 +#define PMPADDRESS4 rvtest_code_end +// PMPADDRESS5 = value to be loaded pmpaddr5 to declare upper address of region4 +#define PMPADDRESS5 PMP_region_High + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration +/* PMP is configure in the following order: +1. Address 0x8000 0000 to Address RAM_LOCATION_FOR_TEST => PMP TOR Region with RWX enabled. This region is the part of the code memory containing our code. For this purpose, pmpaddr0 has been given the value of RAM_LOCATION_FOR_TEST to declare the region from 0->RAM_LOCATION_FOR_TEST into a single PMP region. + +2. Address TEST_FOR_EXECUTION to Address RETURN_INSTRUCTION => PMP region under test. This region has been declared by entering TEST_FOR_EXECUTION into pmpaddr1 and rvtest_code_end into pmpaddr2. Then a PMP region is configure from pmpaddr2(RETURN_INSTRUCTION) to pmpaddr1(TEST_FOR_EXECUTION) into TOR mode by setting pmpcfg0[23:16]=PMPREGION2 + +3. Address RAM_LOCATION_FOR_TEST to Address rvtest_code_end => PMP region under test. This region has been declared by entering rvtest_code_end into pmpaddr4 and RAM_LOCATION_FOR_TEST into pmpaddr3. configure pmpaddr4(RAM_LOCATION_FOR_TEST) to pmpaddr5(rvtest_code_end) into TOR mode by setting pmpcfg1[15:8]=PMPREGION3 + +4. Address rvtest_code_end to address PMP_region_High => PMP TOR Region with RWX enabled. This region is the part of the code memory containing trap handler, epilogs, and other important macro definitions. For this purpose, configure pmpaddr4(rvtest_code_end) to pmpaddr5(PMP_region_High) into TOR mode by setting pmpcfg1[15:8]=PMPREGION4. This PMP Region is mandatory to access signature area in S,U mode */ + /* Assigning addresses to PMP address registers */ + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS4) // Value to be stored in pmpaddr4 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr4, x4 // Updated pmpaddr4 + nop // Added nop in case of trap + LA(x4, PMPADDRESS5) // Value to be stored in pmpaddr5 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr5, x4 // Updated pmpaddr5 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1 | PMPREGION2) + // Value to be stored in pmpcfg register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION3 | PMPREGION4) + // Value to be stored in pmpcfg1 register + csrs pmpcfg1, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-RX-priority-level-2.S b/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-RX-priority-level-2.S new file mode 100644 index 000000000..8a2b734c0 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-RX-priority-level-2.S @@ -0,0 +1,229 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-TOR-priority-rx-level-2.S +// Tests the priority by assigning only R, X permissions to the highest priority while no permissions to high priority region and R-W-X to low priority region +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_TOR_priority_rx_level_2) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg3 [31:24] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled. This is the low priority region +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with nothing enabled +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with R,W enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION3 ((((PMP_R|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +// PMPADDRESS14 = value to be loaded pmpaddr14 to declare lower address of Region-1 +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr14 to declare region1 +// PMPADDRESS15 = value to be loaded pmpaddr15 to declare upper address of Region-1 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of Region-2 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of Region-2 +#define PMPADDRESS3 RETURN_INSTRUCTION +// PMPADDRESS2 = value to be loaded pmpaddr0 to declare lower address of Region-3 +#define PMPADDRESS0 TEST_FOR_EXECUTION +// PMPADDRESS3 = value to be loaded pmpaddr1 to declare upper address of Region-3 +#define PMPADDRESS1 RETURN_INSTRUCTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg3, x4 // Updated pmpcfg3 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION3) + // Value to be stored in pmpcfg register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 1*(XLEN/32),4,NOP //Single + +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-RX-priority.S b/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-RX-priority.S new file mode 100644 index 000000000..97163d001 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-RX-priority.S @@ -0,0 +1,206 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-TOR-priority-rx.S +// Tests the priority by assigning only rx permissions to the high priority while R-W-X to low priority region +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_TOR_priority_rx) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg3 [31:24] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled. This is the low priority region +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_R|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +// PMPADDRESS14 = value to be loaded pmpaddr14 to declare lower address of Region-1 +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr14 to declare region1 +// PMPADDRESS15 = value to be loaded pmpaddr15 to declare upper address of Region-1 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr3 to declare lower address of Region-2 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of Region-2 +#define PMPADDRESS3 RETURN_INSTRUCTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg3, x4 // Updated pmpcfg3 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 0*(XLEN/32),4,NOP +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-RX.S b/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-RX.S new file mode 100644 index 000000000..4d649f194 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-RX.S @@ -0,0 +1,245 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-tor-RX.S +// PMP Test in TOR address matching mode +// Description: +=> Foreach mode in MPP (including M), for Load/store instruction, perform the instruction referencing an address where the associated pmpcfg.W=1 and observe an access fault or not. +=> Foreach mode, perform instruction fetches to an address where the associated pmpcfg.X=0 and observe an access fault or not. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +=> Do the same for loads where pmpcfg.R=1 and pmpcfg.W=0 to make sure that the W bit only affects stores and AMOs. +*/ +/* COVERPOINTS: (Explanation of updates in /coverage/rv32i_priv.cgf) + (pmpcfg0 >> 16) & 0x18 == 0x08 : 0 // CHECK pmp2cfg in TOR mode? + (pmpcfg0 >> 16) & 0x01 == 0x01 : 0 // CHECK R-bit in pmp2cfg was HIGH + (pmpcfg0 >> 16) & 0x02 == 0x02 : 0 // CHECK W-bit in pmp2cfg was HIGH + (pmpcfg0 >> 16) & 0x04 == 0x04 : 0 // CHECK X-bit in pmp2cfg was HIGH +// Details are given in /coverage/rv32i_priv.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_TOR_rx) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg0 [7:0] value to configure address 0->RAM_LOCATION_FOR_TEST in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[23:16] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in TOR Mode with RX enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_R|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP2_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg1[7:0] value to configure address (RAM_LOCATION_FOR_TEST)->(rvtest_code_end) +// in TOR Mode with RW enabled +// ALSO NOTE THAT PMPREGION2 IS INSIDE THIS REGION, so this test will also check the priority order of PMP regions +#define PMPREGION3 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg1[15:8] value to configure address (rvtest_code_end)->(PMP_region_High) +// in TOR Mode with RWX enabled +#define PMPREGION4 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS0 RAM_LOCATION_FOR_TEST // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS1 TEST_FOR_EXECUTION +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare upper address of region2 +#define PMPADDRESS2 RETURN_INSTRUCTION +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare lower address of region3 +#define PMPADDRESS3 RAM_LOCATION_FOR_TEST +// PMPADDRESS4 = value to be loaded pmpaddr4 to declare upper address of region3 +#define PMPADDRESS4 rvtest_code_end +// PMPADDRESS5 = value to be loaded pmpaddr5 to declare upper address of region4 +#define PMPADDRESS5 PMP_region_High + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration +/* PMP is configure in the following order: +1. Address 0x8000 0000 to Address RAM_LOCATION_FOR_TEST => PMP TOR Region with RWX enabled. This region is the part of the code memory containing our code. For this purpose, pmpaddr0 has been given the value of RAM_LOCATION_FOR_TEST to declare the region from 0->RAM_LOCATION_FOR_TEST into a single PMP region. + +2. Address TEST_FOR_EXECUTION to Address RETURN_INSTRUCTION => PMP region under test. This region has been declared by entering TEST_FOR_EXECUTION into pmpaddr1 and rvtest_code_end into pmpaddr2. Then a PMP region is configure from pmpaddr2(RETURN_INSTRUCTION) to pmpaddr1(TEST_FOR_EXECUTION) into TOR mode by setting pmpcfg0[23:16]=PMPREGION2 + +3. Address RAM_LOCATION_FOR_TEST to Address rvtest_code_end => PMP region under test. This region has been declared by entering rvtest_code_end into pmpaddr4 and RAM_LOCATION_FOR_TEST into pmpaddr3. configure pmpaddr4(RAM_LOCATION_FOR_TEST) to pmpaddr5(rvtest_code_end) into TOR mode by setting pmpcfg1[15:8]=PMPREGION3 + +4. Address rvtest_code_end to address PMP_region_High => PMP TOR Region with RWX enabled. This region is the part of the code memory containing trap handler, epilogs, and other important macro definitions. For this purpose, configure pmpaddr4(rvtest_code_end) to pmpaddr5(PMP_region_High) into TOR mode by setting pmpcfg1[15:8]=PMPREGION4. This PMP Region is mandatory to access signature area in S,U mode */ + /* Assigning addresses to PMP address registers */ + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS4) // Value to be stored in pmpaddr4 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr4, x4 // Updated pmpaddr4 + nop // Added nop in case of trap + LA(x4, PMPADDRESS5) // Value to be stored in pmpaddr5 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr5, x4 // Updated pmpaddr5 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1 | PMPREGION2) + // Value to be stored in pmpcfg register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION3 | PMPREGION4) + // Value to be stored in pmpcfg1 register + csrs pmpcfg1, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-X-priority-level-2.S b/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-X-priority-level-2.S new file mode 100644 index 000000000..e5ab4c0eb --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-X-priority-level-2.S @@ -0,0 +1,229 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-TOR-priority-x-level-2.S +// Tests the priority by assigning only X permissions to the highest priority while no permissions to high priority region and R-W-X to low priority region +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_TOR_priority_x_level_2) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg3 [31:24] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled. This is the low priority region +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with nothing enabled +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with R,W enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION3 ((((PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +// PMPADDRESS14 = value to be loaded pmpaddr14 to declare lower address of Region-1 +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr14 to declare region1 +// PMPADDRESS15 = value to be loaded pmpaddr15 to declare upper address of Region-1 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of Region-2 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of Region-2 +#define PMPADDRESS3 RETURN_INSTRUCTION +// PMPADDRESS2 = value to be loaded pmpaddr0 to declare lower address of Region-3 +#define PMPADDRESS0 TEST_FOR_EXECUTION +// PMPADDRESS3 = value to be loaded pmpaddr1 to declare upper address of Region-3 +#define PMPADDRESS1 RETURN_INSTRUCTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg3, x4 // Updated pmpcfg3 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION3) + // Value to be stored in pmpcfg register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 1*(XLEN/32),4,NOP //Single + +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-X-priority.S b/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-X-priority.S new file mode 100644 index 000000000..af7c92458 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-X-priority.S @@ -0,0 +1,206 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-TOR-priority-x.S +// Tests the priority by assigning only X permissions to the high priority while R-W-X to low priority region +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_TOR_priority_x) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg3 [31:24] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled. This is the low priority region +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +// PMPADDRESS14 = value to be loaded pmpaddr14 to declare lower address of Region-1 +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr14 to declare region1 +// PMPADDRESS15 = value to be loaded pmpaddr15 to declare upper address of Region-1 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr3 to declare lower address of Region-2 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of Region-2 +#define PMPADDRESS3 RETURN_INSTRUCTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg3, x4 // Updated pmpcfg3 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 0*(XLEN/32),4,NOP +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END diff --git a/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-X.S b/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-X.S new file mode 100644 index 000000000..4dc4e4fb9 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/pmp-TOR-X.S @@ -0,0 +1,245 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-tor-X.S +// PMP Test in TOR address matching mode +// Description: +=> Foreach mode in MPP (including M), for Load/store instruction, perform the instruction referencing an address where the associated pmpcfg.W=1 and observe an access fault or not. +=> Foreach mode, perform instruction fetches to an address where the associated pmpcfg.X=0 and observe an access fault or not. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +=> Do the same for loads where pmpcfg.R=1 and pmpcfg.W=0 to make sure that the W bit only affects stores and AMOs. +*/ +/* COVERPOINTS: (Explanation of updates in /coverage/rv32i_priv.cgf) + (pmpcfg0 >> 16) & 0x18 == 0x08 : 0 // CHECK pmp2cfg in TOR mode? + (pmpcfg0 >> 16) & 0x01 == 0x01 : 0 // CHECK R-bit in pmp2cfg was HIGH + (pmpcfg0 >> 16) & 0x02 == 0x02 : 0 // CHECK W-bit in pmp2cfg was HIGH + (pmpcfg0 >> 16) & 0x04 == 0x04 : 0 // CHECK X-bit in pmp2cfg was HIGH +// Details are given in /coverage/rv32i_priv.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV32I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*32.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_TOR_x) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 2 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 4 // START OF LOOP + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+1 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg0 [7:0] value to configure address 0->RAM_LOCATION_FOR_TEST in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[23:16] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in TOR Mode with RX enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP2_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg1[7:0] value to configure address (RAM_LOCATION_FOR_TEST)->(rvtest_code_end) +// in TOR Mode with RW enabled +// ALSO NOTE THAT PMPREGION2 IS INSIDE THIS REGION, so this test will also check the priority order of PMP regions +#define PMPREGION3 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg1[15:8] value to configure address (rvtest_code_end)->(PMP_region_High) +// in TOR Mode with RWX enabled +#define PMPREGION4 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS0 RAM_LOCATION_FOR_TEST // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS1 TEST_FOR_EXECUTION +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare upper address of region2 +#define PMPADDRESS2 RETURN_INSTRUCTION +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare lower address of region3 +#define PMPADDRESS3 RAM_LOCATION_FOR_TEST +// PMPADDRESS4 = value to be loaded pmpaddr4 to declare upper address of region3 +#define PMPADDRESS4 rvtest_code_end +// PMPADDRESS5 = value to be loaded pmpaddr5 to declare upper address of region4 +#define PMPADDRESS5 PMP_region_High + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration +/* PMP is configure in the following order: +1. Address 0x8000 0000 to Address RAM_LOCATION_FOR_TEST => PMP TOR Region with RWX enabled. This region is the part of the code memory containing our code. For this purpose, pmpaddr0 has been given the value of RAM_LOCATION_FOR_TEST to declare the region from 0->RAM_LOCATION_FOR_TEST into a single PMP region. + +2. Address TEST_FOR_EXECUTION to Address RETURN_INSTRUCTION => PMP region under test. This region has been declared by entering TEST_FOR_EXECUTION into pmpaddr1 and rvtest_code_end into pmpaddr2. Then a PMP region is configure from pmpaddr2(RETURN_INSTRUCTION) to pmpaddr1(TEST_FOR_EXECUTION) into TOR mode by setting pmpcfg0[23:16]=PMPREGION2 + +3. Address RAM_LOCATION_FOR_TEST to Address rvtest_code_end => PMP region under test. This region has been declared by entering rvtest_code_end into pmpaddr4 and RAM_LOCATION_FOR_TEST into pmpaddr3. configure pmpaddr4(RAM_LOCATION_FOR_TEST) to pmpaddr5(rvtest_code_end) into TOR mode by setting pmpcfg1[15:8]=PMPREGION3 + +4. Address rvtest_code_end to address PMP_region_High => PMP TOR Region with RWX enabled. This region is the part of the code memory containing trap handler, epilogs, and other important macro definitions. For this purpose, configure pmpaddr4(rvtest_code_end) to pmpaddr5(PMP_region_High) into TOR mode by setting pmpcfg1[15:8]=PMPREGION4. This PMP Region is mandatory to access signature area in S,U mode */ + /* Assigning addresses to PMP address registers */ + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS4) // Value to be stored in pmpaddr4 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr4, x4 // Updated pmpaddr4 + nop // Added nop in case of trap + LA(x4, PMPADDRESS5) // Value to be stored in pmpaddr5 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr5, x4 // Updated pmpaddr5 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1 | PMPREGION2) + // Value to be stored in pmpcfg register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION3 | PMPREGION4) + // Value to be stored in pmpcfg1 register + csrs pmpcfg1, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 64*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-CFG-reg.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-CFG-reg.S new file mode 100644 index 000000000..6cdf8785e --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-CFG-reg.S @@ -0,0 +1,132 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +// +// This assembly file tests access of pmp registers in M, S, and U mode. +// pmp csrs are accessable only in M-mode so it should trap in S, and U mode. +// +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",pmp_cfg_locked_write_unrelated) +RVTEST_SIGBASE( x3,signature_x3_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x9,0) // The register to carry offset value + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + csrc pmpcfgi , a5 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrc pmpaddri, a5 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +//////////////////// Locked bit TEST 1 ///////////////////////////////////////////// + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi, a5 // WRITE pmpcfgi with ALL 1s, Locked the lock-bit [7,15,23,31] + nop // Added nop in case of trap + csrr a4, pmpcfgi // READ pmpcfgi + // THIS READ WILL ALSO CONFIRM THE ZERO BITs OF PMPCFGi REG. + // BIT 5-6, BIT 13-14, BIT 21-22, BIT 29-30 must be hardwired to zero + // Verify that LOCKED bits are HIGH, and ZERO bits are zero + RVTEST_SIGUPD(x3,a4) + // TRY TO WRITE CFG REGISTER AGAIN (TRAP in case of LOCKED bit is HIGH) + csrw pmpcfgi, x5 // WRITE pmpcfgi with some other values + nop // Added nop in case of trap + csrr a4, pmpcfgi // READ pmpcfgi + // Since Locked bit is high, so this should return the old value!!! + RVTEST_SIGUPD(x3,a4) + + .set pmpaddri, PMPADDR0+4*(pmpcfgi-PMPCFG0) +// Initialize an iterating variable with the address of pmpaddr0 in 1st iteration (when pmpcfgi=pmpcfg0) +// Initialize an iterating variable with the address of pmpaddr4 in 2nd iteration (when pmpcfgi=pmpcfg1) +// Initialize an iterating variable with the address of pmpaddr8 in 3rd iteration (when pmpcfgi=pmpcfg2) +// Initialize an iterating variable with the address of pmpaddr12 in 4th iteration (when pmpcfgi=pmpcfg3) + .rept 8 // START OF LOOP + // TRY TO WRITE ADDRESS REGISTER. + csrw pmpaddri, a5 // WRITE pmpaddri with some other values + // The updated write will give a trap!!! + nop // Added nop in case of trap + csrr a4, pmpaddri // READ pmpaddr0, value should not have been changed + nop // Added nop in case of trap + RVTEST_SIGUPD(x3,a4) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF INNER LOOP BODY + + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg .endr // END OF OUTER LOOP BODY + .endr +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT + +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x3_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +RVMODEL_DATA_END diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-CSR-access.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-CSR-access.S new file mode 100644 index 000000000..44a7c240c --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-CSR-access.S @@ -0,0 +1,243 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +// +// This assembly file tests access of pmp registers in M, S, and U mode. +// pmp csrs are accessable only in M-mode so it should trap in S, and U mode. +// +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf +// +#define rvtest_strap_routine +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def TEST_CASE_1=True",PMP_access_permission) +RVTEST_SIGBASE( x13,signature_x13_1) + .option nopic + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 +main: +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + csrc pmpcfgi , a5 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrc pmpaddri, a5 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY +//////////////// VERIFICATION ///////////////////////////////////////// +// READING pmpaddr in M-mode ///////////////////////////////////////// + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrr a4, pmpaddri // READING pmpaddri (i is from 0-15) + nop // Added nop in case of trap + RVTEST_SIGUPD(x13,a4) // Storing into signature file + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY +// WRITING pmpaddr in M-mode ///////////////////////////////////////// + LI(a4,0x01) // RANDOM VALUE + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, a4 // WRITING pmpaddri (i is from 0-15) + nop // Added nop in case of trap + RVTEST_SIGUPD(x13,a4) // Storing into signature file + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY +// WRITING pmpcfg registers ////////////////////////////////////////// +// Write in M-mode will be valid, Write in other modes will cause trap + LI(a5, PMP_R| PMP_W | PMP_X | PMP_TOR) // LOCKED BIT IS NOT SET + // Loop to Write ALL pmpcfg regs + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + csrw pmpcfgi, a5 // Write pmpcfgi + nop // Added nop in case of trap + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY +//////////////// VERIFICATION ///////////////////////////////////////// +// READING pmpcfg in M-mode ///////////////////////////////////////// + // Loop to verify the contents of pmpcfg regs + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + csrr a4, pmpcfg0 // Read pmpcfg0 + nop // Added nop in case of trap + RVTEST_SIGUPD(x13,a4) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY +/////////////////// Switch to S-mode //////////////////////////////////////////// + csrw satp, zero // Disable address translation. + LI(t2, -1) + csrw pmpaddr0, t2 // Updated pmpaddr0 to define PMP region consisting + // of whole physical memory + csrr t0, pmpaddr0 // Verify its value by reading back + nop // Added nop in case of trap + LI(a5, PMP_L| PMP_R| PMP_W | PMP_X | PMP_TOR) // LOCKED BIT IS SET + csrw pmpcfg0, a5 + + RVTEST_GOTO_LOWER_MODE Smode // GO into S mode +// REPEATING THE SAME TEST ////////////////////////////////////////// +// IN Smode now +/////////////////// TEST 01 //////////////////////////////////////////// +// READING pmpaddr in S-mode ///////////////////////////////////////// + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 4 // START OF LOOP + csrr a4, pmpaddri // READING pmpaddri (i is from 0-15) + nop // Added nop in case of trap + RVTEST_SIGUPD(x13,a4) // Storing into signature file + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY +// WRITING pmpaddr in S-mode ///////////////////////////////////////// + LI(a4,0x01) // RANDOM VALUE + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 4 // START OF LOOP + csrw pmpaddri, a4 // WRITING pmpaddri (i is from 0-15) + nop // Added nop in case of trap + RVTEST_SIGUPD(x13,a4) // Storing into signature file + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY +// WRITING pmpcfg registers ////////////////////////////////////////// +// Write in M-mode will be valid, Write in other modes will cause trap + LI(a5, PMP_R| PMP_W | PMP_X | PMP_TOR) // LOCKED BIT IS NOT SET + // Loop to Write ALL pmpcfg regs + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + csrw pmpcfgi, a5 // Write pmpcfgi + nop // Added nop in case of trap + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY +//////////////// VERIFICATION ///////////////////////////////////////// +// READING pmpcfg in S-mode ///////////////////////////////////////// + // Loop to verify the contents of pmpcfg regs + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + csrr a4, pmpcfg0 // Read pmpcfg0 + nop // Added nop in case of trap + RVTEST_SIGUPD(x13,a4) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap + RVTEST_SIGUPD(x13,a4) +/////////////////// Switch to U-mode //////////////////////////////////////////// + csrw satp, zero // Disable address translation. + LI(t2, -1) + csrw pmpaddr0, t2 // Updated pmpaddr0 to define PMP region consisting + // of whole physical memory + csrr t0, pmpaddr0 // Verify its value by reading back + nop // Added nop in case of trap + LI(a5, PMP_L| PMP_R| PMP_W | PMP_X | PMP_TOR) // LOCKED BIT IS SET + csrw pmpcfg0, a5 +// These steps are repeated and can be removed but it will make sure that you will switch mode +// with full access on physical memory + RVTEST_GOTO_LOWER_MODE Umode +// REPEATING THE SAME TEST ////////////////////////////////////////// +// IN U-mode now +// READING pmpaddr in U-mode ///////////////////////////////////////// + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 4 // START OF LOOP + csrr a4, pmpaddri // READING pmpaddri (i is from 0-15) + nop // Added nop in case of trap + RVTEST_SIGUPD(x13,a4) // Storing into signature file + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY +// WRITING pmpaddr in U-mode ///////////////////////////////////////// + LI(a4,0x01) // RANDOM VALUE + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 4 // START OF LOOP + csrw pmpaddri, a4 // WRITING pmpaddri (i is from 0-15) + nop // Added nop in case of trap + RVTEST_SIGUPD(x13,a4) // Storing into signature file + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY +// WRITING pmpcfg registers ////////////////////////////////////////// +// Write in M-mode will be valid, Write in other modes will cause trap + LI(a5, PMP_R| PMP_W | PMP_X | PMP_TOR) // LOCKED BIT IS NOT SET + // Loop to Write ALL pmpcfg regs + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + csrw pmpcfgi, a5 // Write pmpcfgi + nop // Added nop in case of trap + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY +//////////////// VERIFICATION ///////////////////////////////////////// +// READING pmpcfg in U-mode ///////////////////////////////////////// + // Loop to verify the contents of pmpcfg regs + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + csrr a4, pmpcfg0 // Read pmpcfg0 + nop // Added nop in case of trap + RVTEST_SIGUPD(x13,a4) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + +#endif + + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT + +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 256*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-R-priority-level-2.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-R-priority-level-2.S new file mode 100644 index 000000000..7c8b443b6 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-R-priority-level-2.S @@ -0,0 +1,236 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NA4-priority-r-level-2.S +// Tests the priority by assigning only R permissions to the highest priority while no permissions to high priority region and R-W-X to low priority region +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints", PMP_NA4_priority_r_level_2) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP7_CFG_SHIFT 56 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg2 [63:56] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled. This is the low priority region +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP7_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with nothing enabled +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION). This is the high priority region +// in TOR Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION3 ((((PMP_R|PMP_L|PMP_NA4)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +// PMPADDRESS14 = value to be loaded pmpaddr14 to declare lower address of Region-1 +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr14 to declare region1 +// PMPADDRESS15 = value to be loaded pmpaddr15 to declare upper address of Region-1 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of Region-2 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of Region-2 +#define PMPADDRESS3 RETURN_INSTRUCTION +// PMPADDRESS3 = value to be loaded pmpaddr1 to declare upper address of Region-3 +#define PMPADDRESS1 TEST_FOR_EXECUTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration +/* PMP is configure in the following order: +1. Address 0x8000 0000 to Address RVMODEL_DATA_END => PMP TOR (Low Priority) Region with RWX enabled. For this purpose, pmpaddr14 has been given the value of 0 and pmpaddr15 is given address to RVMODEL_DATA_END to declare the region from 0->RVMODEL_DATA_END into a single PMP region. + +2. Address RAM_LOCATION_FOR_TEST to Address RETURN_INSTRUCTION => PMP region under test. This region has been declared by entering RAM_LOCATION_FOR_TEST into pmpaddr2 and address to RETURN_INSTRUCTION label into pmpaddr3. Then a PMP region is configure from pmpaddr2(RAM_LOCATION_FOR_TEST) to pmpaddr3(RETURN_INSTRUCTION) into TOR mode by setting pmpcfg0[31:24]=PMPREGION2 + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg2, x4 // Updated pmpcfg2 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION3) + // Value to be stored in pmpcfg register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 4*(XLEN/32),8,0x12345678 + .align 3 + +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-R-priority.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-R-priority.S new file mode 100644 index 000000000..d6750776c --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-R-priority.S @@ -0,0 +1,215 @@ + +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NA4-priority-r.S +// PMP Test in NA4 address matching mode +// Description: +// Tests the priority by assigning only R permissions to the high priority while R-W-X to low priority region +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NA4_priority_r) +RVTEST_SIGBASE( x13,signature_x13_1) + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP7_CFG_SHIFT 56 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg2[63:56] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP7_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in NAPOT Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_R|PMP_NA4)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of region3 +#define PMPADDRESS2 TEST_FOR_EXECUTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg2, x4 // Updated pmpcfg3 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 + .align 3 + +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-R.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-R.S new file mode 100644 index 000000000..2d1d7bdd0 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-R.S @@ -0,0 +1,240 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NA4-R.S +// PMP Test in NA4 address matching mode +// Description: +=> Foreach mode in MPP (including M), for Load/store instruction, perform the instruction referencing an address where the associated pmpcfg.W=0 and observe an access fault or not. +=> Foreach mode, perform instruction fetches to an address where the associated pmpcfg.X=0 and observe an access fault or not. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +=> Do the same for loads where pmpcfg.R=1 and pmpcfg.W=0 to make sure that the W bit only affects stores and AMOs. +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf +*/ +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NA4_r) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP4_CFG_SHIFT 32 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg0 [7:0] value to configure address 0->RAM_LOCATION_FOR_TEST in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in NA4 Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_R|PMP_L|PMP_NA4)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(rvtest_code_end) +// in TOR Mode with RWX enabled +// ALSO NOTE THAT PMPREGION2 IS INSIDE THIS REGION, so this test will also check the priority order of PMP regions +#define PMPREGION3 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[39:32] value to configure address (rvtest_code_end)->(PMP_region_High) +// in TOR Mode with RWX enabled +#define PMPREGION4 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP4_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS0 RAM_LOCATION_FOR_TEST // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS1 TEST_FOR_EXECUTION +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of region3 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of region3 +#define PMPADDRESS3 rvtest_code_end +// PMPADDRESS4 = value to be loaded pmpaddr4 to declare upper address of region4 +#define PMPADDRESS4 PMP_region_High + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration +/* PMP is configure in the following order: +1. Address 0x0000 0000 to Address RAM_LOCATION_FOR_TEST => PMP TOR Region with RWX enabled. This region is the part of the code memory containing our code. For this purpose, pmpaddr0 has been given the value of RAM_LOCATION_FOR_TEST to declare the region from 0->RAM_LOCATION_FOR_TEST into a single PMP region. + +2. Address TEST_FOR_EXECUTION to Address RETURN_INSTRUCTION =====> This is the PMP region under test (A 4byte region == Granularity of Sail. This region has been declared by entering TEST_FOR_EXECUTION into pmpaddr1 and RETURN_INSTRUCTION into pmpaddr2. Then a PMP region is configure into NA4 mode by setting pmpcfg0[15:8]=((PMP_R|PMP_L|PMP_NA4)&0xFF) + +3. Address RAM_LOCATION_FOR_TEST to Address rvtest_code_end => Another PMP region under test. This region has been declared by entering rvtest_code_end into pmpaddr3 and RAM_LOCATION_FOR_TEST into pmpaddr2. configure pmpaddr2(RAM_LOCATION_FOR_TEST) to pmpaddr3(rvtest_code_end) into TOR mode by setting pmpcfg0[31:24]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) + +4. Address rvtest_code_end to address PMP_region_High => PMP TOR Region with RWX enabled. This region is the part of the code memory containing trap handler, epilogs, and other important macro definitions. For this purpose, configure pmpaddr3(rvtest_code_end) to pmpaddr4(PMP_region_High) into TOR mode by setting pmpcfg1[7:0]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)). This PMP Region is mandatory to access signature area in S,U mode */ + /* Assigning addresses to PMP address registers */ + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS4) // Value to be stored in pmpaddr4 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr4, x4 // Updated pmpaddr4 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1 | PMPREGION2 | PMPREGION3 | PMPREGION4) + // Value to be stored in pmpcfg register ; Setting Up PMP Region-1,2,3,4 + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 + .align 3 + +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-RW-priority-level-2.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-RW-priority-level-2.S new file mode 100644 index 000000000..428559210 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-RW-priority-level-2.S @@ -0,0 +1,233 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-TOR-priority-rw-level-2.S +// Tests the priority by assigning only R,W permissions to the highest priority while no permissions to high priority region and R-W-X to low priority region +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NA4_priority_rw_level_2) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP7_CFG_SHIFT 56 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg2 [63:56] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled. This is the low priority region +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP7_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with nothing enabled +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION). This is the high priority region +// in TOR Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION3 ((((PMP_R|PMP_W|PMP_L|PMP_NA4)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +// PMPADDRESS14 = value to be loaded pmpaddr14 to declare lower address of Region-1 +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr14 to declare region1 +// PMPADDRESS15 = value to be loaded pmpaddr15 to declare upper address of Region-1 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of Region-2 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of Region-2 +#define PMPADDRESS3 RETURN_INSTRUCTION +// PMPADDRESS3 = value to be loaded pmpaddr1 to declare upper address of Region-3 +#define PMPADDRESS1 TEST_FOR_EXECUTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg2, x4 // Updated pmpcfg2 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION3) + // Value to be stored in pmpcfg register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 0*(XLEN/32),4,NOP + .align 3 + +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-RW-priority.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-RW-priority.S new file mode 100644 index 000000000..301155517 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-RW-priority.S @@ -0,0 +1,214 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NA4-priority-rw.S +// PMP Test in NA4 address matching mode +// Description: +// Tests the priority by assigning only R,W permissions to the high priority while R-W-X to low priority region +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NA4_priority_rw) +RVTEST_SIGBASE( x13,signature_x13_1) + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP7_CFG_SHIFT 56 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg2[63:56] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP7_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in NAPOT Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_R|PMP_W|PMP_NA4)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of region3 +#define PMPADDRESS2 TEST_FOR_EXECUTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg2, x4 // Updated pmpcfg2 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 + .align 3 + +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-RW.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-RW.S new file mode 100644 index 000000000..111b5b9b0 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-RW.S @@ -0,0 +1,242 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NA4-RW.S +// PMP Test in NA4 address matching mode +// Description: +=> Foreach mode in MPP (including M), for Load/store instruction, perform the instruction referencing an address where the associated pmpcfg.W=0 and observe an access fault or not. +=> Foreach mode, perform instruction fetches to an address where the associated pmpcfg.X=0 and observe an access fault or not. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +=> Do the same for loads where pmpcfg.R=1 and pmpcfg.W=0 to make sure that the W bit only affects stores and AMOs. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +*/ +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NA4_rw) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP4_CFG_SHIFT 32 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg0 [7:0] value to configure address 0->RAM_LOCATION_FOR_TEST in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in NA4 Mode with RW enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_R|PMP_W|PMP_L|PMP_NA4)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(rvtest_code_end) +// in TOR Mode with RWX enabled +// ALSO NOTE THAT PMPREGION2 IS INSIDE THIS REGION, so this test will also check the priority order of PMP regions +#define PMPREGION3 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[39:32] value to configure address (rvtest_code_end)->(PMP_region_High) +// in TOR Mode with RWX enabled +#define PMPREGION4 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP4_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS0 RAM_LOCATION_FOR_TEST // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS1 TEST_FOR_EXECUTION +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of region3 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of region3 +#define PMPADDRESS3 rvtest_code_end +// PMPADDRESS4 = value to be loaded pmpaddr4 to declare upper address of region4 +#define PMPADDRESS4 PMP_region_High + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration +/* PMP is configure in the following order: +1. Address 0x0000 0000 to Address RAM_LOCATION_FOR_TEST => PMP TOR Region with RWX enabled. This region is the part of the code memory containing our code. For this purpose, pmpaddr0 has been given the value of RAM_LOCATION_FOR_TEST to declare the region from 0->RAM_LOCATION_FOR_TEST into a single PMP region. + +2. Address TEST_FOR_EXECUTION to Address RETURN_INSTRUCTION =====> This is the PMP region under test (A 4byte region == Granularity of Sail. This region has been declared by entering TEST_FOR_EXECUTION into pmpaddr1 and RETURN_INSTRUCTION into pmpaddr2. Then a PMP region is configure into NA4 mode by setting pmpcfg0[15:8]=((PMP_R|PMP_W|PMP_L|PMP_NA4)&0xFF) + +3. Address RAM_LOCATION_FOR_TEST to Address rvtest_code_end => Another PMP region under test. This region has been declared by entering rvtest_code_end into pmpaddr3 and RAM_LOCATION_FOR_TEST into pmpaddr2. configure pmpaddr2(RAM_LOCATION_FOR_TEST) to pmpaddr3(rvtest_code_end) into TOR mode by setting pmpcfg0[31:24]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) + +4. Address rvtest_code_end to address PMP_region_High => PMP TOR Region with RWX enabled. This region is the part of the code memory containing trap handler, epilogs, and other important macro definitions. For this purpose, configure pmpaddr3(rvtest_code_end) to pmpaddr4(PMP_region_High) into TOR mode by setting pmpcfg1[7:0]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)). This PMP Region is mandatory to access signature area in S,U mode */ + /* Assigning addresses to PMP address registers */ + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS4) // Value to be stored in pmpaddr4 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr4, x4 // Updated pmpaddr4 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1 | PMPREGION2 | PMPREGION3 | PMPREGION4) + // Value to be stored in pmpcfg register ; Setting Up PMP Region-1,2,3 + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 + .align 3 + +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-RWX.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-RWX.S new file mode 100644 index 000000000..5b98683b0 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-RWX.S @@ -0,0 +1,255 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NA4-RWX.S +// PMP Test in NA4 address matching mode +// Description: +=> Foreach mode in MPP (including M), for Load/store instruction, perform the instruction referencing an address where the associated pmpcfg.W=1 and observe an access fault or not. +=> Foreach mode, perform instruction fetches to an address where the associated pmpcfg.X=0 and observe an access fault or not. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +*/ +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NA4_rwx) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP4_CFG_SHIFT 32 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + csrc pmpcfgi , a5 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrc pmpaddri, a5 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg0 [7:0] value to configure address 0->RAM_LOCATION_FOR_TEST in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in NA4 Mode with RW enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_NA4)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(rvtest_code_end) +// in TOR Mode with RWX enabled +// ALSO NOTE THAT PMPREGION2 IS INSIDE THIS REGION, so this test will also check the priority order of PMP regions +#define PMPREGION3 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[39:32] value to configure address (rvtest_code_end)->(PMP_region_High) +// in TOR Mode with RWX enabled +#define PMPREGION4 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP4_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS0 RAM_LOCATION_FOR_TEST // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS1 TEST_FOR_EXECUTION +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of region3 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of region3 +#define PMPADDRESS3 rvtest_code_end +// PMPADDRESS4 = value to be loaded pmpaddr4 to declare upper address of region4 +#define PMPADDRESS4 PMP_region_High + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration +/* PMP is configure in the following order: +1. Address 0x0000 0000 to Address RAM_LOCATION_FOR_TEST => PMP TOR Region with RWX enabled. +This region is the part of the code memory containing our code and the region between code_end to data_begin. +For this purpose, pmpaddr0 has been given the value of RAM_LOCATION_FOR_TEST to +declare the region from 0->RAM_LOCATION_FOR_TEST into a single PMP region. + +2. Address TEST_FOR_EXECUTION to Address RETURN_INSTRUCTION =====> This is the PMP region under test (A 4byte region == Granularity of Sail.) +This region has been declared by entering TEST_FOR_EXECUTION into pmpaddr1 and RETURN_INSTRUCTION into pmpaddr2. +Then a PMP region is configure into NA4 mode by setting pmpcfg0[15:8]=PMPREGION2 + +3. Address RAM_LOCATION_FOR_TEST to Address rvtest_code_end => Another PMP region under test. +This region has been declared by entering rvtest_code_end into pmpaddr3 and +RAM_LOCATION_FOR_TEST into pmpaddr2. configure pmpaddr2(RAM_LOCATION_FOR_TEST) +to pmpaddr3(rvtest_code_end) into TOR mode +by setting pmpcfg0[31:24]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) + +4. Address rvtest_code_end to address PMP_region_High => PMP TOR Region with RWX enabled. +This region is the part of the code memory containing trap handler, epilogs, and other important macro definitions. +For this purpose, configure pmpaddr3(rvtest_code_end) to pmpaddr4(PMP_region_High) +into TOR mode by setting pmpcfg1[7:0]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)). +This PMP Region is mandatory to access signature area in S,U mode */ + + /* Assigning addresses to PMP address registers */ + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS4) // Value to be stored in pmpaddr4 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr4, x4 // Updated pmpaddr4 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1 | PMPREGION2 | PMPREGION3 | PMPREGION4) + // Value to be stored in pmpcfg register ; Setting Up PMP Region-1,2,3 + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + nop + j exit +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 + .align 3 + +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + + + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-RX-priority-level-2.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-RX-priority-level-2.S new file mode 100644 index 000000000..403273b62 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-RX-priority-level-2.S @@ -0,0 +1,233 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-TOR-priority-rx-level-2.S +// Tests the priority by assigning only R,X permissions to the highest priority while no permissions to high priority region and R-W-X to low priority region +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NA4_priority_rx_level_2) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP7_CFG_SHIFT 56 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg2 [63:56] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled. This is the low priority region +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP7_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with nothing enabled +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION). This is the high priority region +// in TOR Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION3 ((((PMP_R|PMP_X|PMP_L|PMP_NA4)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +// PMPADDRESS14 = value to be loaded pmpaddr14 to declare lower address of Region-1 +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr14 to declare region1 +// PMPADDRESS15 = value to be loaded pmpaddr15 to declare upper address of Region-1 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of Region-2 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of Region-2 +#define PMPADDRESS3 RETURN_INSTRUCTION +// PMPADDRESS3 = value to be loaded pmpaddr1 to declare upper address of Region-3 +#define PMPADDRESS1 TEST_FOR_EXECUTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg2, x4 // Updated pmpcfg2 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION3) + // Value to be stored in pmpcfg register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 0*(XLEN/32),4,NOP + .align 3 + +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-RX-priority.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-RX-priority.S new file mode 100644 index 000000000..d7b16fa47 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-RX-priority.S @@ -0,0 +1,214 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NA4-priority-rx.S +// PMP Test in NA4 address matching mode +// Description: +// Tests the priority by assigning only R,X permissions to the high priority while R-W-X to low priority region +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NA4_priority_rx) +RVTEST_SIGBASE( x13,signature_x13_1) + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP7_CFG_SHIFT 56 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg2[63:56] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP7_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in NAPOT Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_R|PMP_X|PMP_NA4)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of region3 +#define PMPADDRESS2 TEST_FOR_EXECUTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg2, x4 // Updated pmpcfg2 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 + .align 3 + +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-RX.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-RX.S new file mode 100644 index 000000000..55d4a71b3 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-RX.S @@ -0,0 +1,240 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NA4-RX.S +// PMP Test in NA4 address matching mode +// Description: +=> Foreach mode in MPP (including M), for Load/store instruction, perform the instruction referencing an address where the associated pmpcfg.W=1 and observe an access fault or not. +=> Foreach mode, perform instruction fetches to an address where the associated pmpcfg.X=0 and observe an access fault or not. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +*/ +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NA4_rx) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP4_CFG_SHIFT 32 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg0 [7:0] value to configure address 0->RAM_LOCATION_FOR_TEST in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in NA4 Mode with RX enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_R|PMP_X|PMP_L|PMP_NA4)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(rvtest_code_end) +// in TOR Mode with RWX enabled +// ALSO NOTE THAT PMPREGION2 IS INSIDE THIS REGION, so this test will also check the priority order of PMP regions +#define PMPREGION3 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[39:32] value to configure address (rvtest_code_end)->(PMP_region_High) +// in TOR Mode with RWX enabled +#define PMPREGION4 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP4_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS0 RAM_LOCATION_FOR_TEST // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS1 TEST_FOR_EXECUTION +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of region3 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of region3 +#define PMPADDRESS3 rvtest_code_end +// PMPADDRESS4 = value to be loaded pmpaddr4 to declare upper address of region4 +#define PMPADDRESS4 PMP_region_High + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration +/* PMP is configure in the following order: +1. Address 0x0000 0000 to Address RAM_LOCATION_FOR_TEST => PMP TOR Region with RWX enabled. This region is the part of the code memory containing our code. For this purpose, pmpaddr0 has been given the value of RAM_LOCATION_FOR_TEST to declare the region from 0->RAM_LOCATION_FOR_TEST into a single PMP region. + +2. Address TEST_FOR_EXECUTION to Address RETURN_INSTRUCTION =====> This is the PMP region under test (A 4byte region == Granularity of Sail. This region has been declared by entering TEST_FOR_EXECUTION into pmpaddr1 and RETURN_INSTRUCTION into pmpaddr2. Then a PMP region is configure into NA4 mode by setting pmpcfg0[15:8]=PMPREGION2 + +3. Address RAM_LOCATION_FOR_TEST to Address rvtest_code_end => Another PMP region under test. This region has been declared by entering rvtest_code_end into pmpaddr3 and RAM_LOCATION_FOR_TEST into pmpaddr2. configure pmpaddr2(RAM_LOCATION_FOR_TEST) to pmpaddr3(rvtest_code_end) into TOR mode by setting pmpcfg0[31:24]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) + +4. Address rvtest_code_end to address PMP_region_High => PMP TOR Region with RWX enabled. This region is the part of the code memory containing trap handler, epilogs, and other important macro definitions. For this purpose, configure pmpaddr3(rvtest_code_end) to pmpaddr4(PMP_region_High) into TOR mode by setting pmpcfg1[7:0]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)). This PMP Region is mandatory to access signature area in S,U mode */ + /* Assigning addresses to PMP address registers */ + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS4) // Value to be stored in pmpaddr4 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr4, x4 // Updated pmpaddr4 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1 | PMPREGION2 | PMPREGION3 | PMPREGION4) + // Value to be stored in pmpcfg register ; Setting Up PMP Region-1,2,3 + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 + .align 3 + +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-X-priority-level-2.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-X-priority-level-2.S new file mode 100644 index 000000000..6d7c68faa --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-X-priority-level-2.S @@ -0,0 +1,234 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-TOR-priority-x-level-2.S +// Tests the priority by assigning only X permissions to the highest priority while no permissions to high priority region and R-W-X to low priority region +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NA4_priority_x_level_2) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP7_CFG_SHIFT 56 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg2 [63:56] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled. This is the low priority region +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP7_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with nothing enabled +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION). This is the high priority region +// in TOR Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION3 ((((PMP_X|PMP_L|PMP_NA4)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +// PMPADDRESS14 = value to be loaded pmpaddr14 to declare lower address of Region-1 +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr14 to declare region1 +// PMPADDRESS15 = value to be loaded pmpaddr15 to declare upper address of Region-1 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of Region-2 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of Region-2 +#define PMPADDRESS3 RETURN_INSTRUCTION +// PMPADDRESS3 = value to be loaded pmpaddr1 to declare upper address of Region-3 +#define PMPADDRESS1 TEST_FOR_EXECUTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg2, x4 // Updated pmpcfg2 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION3) + // Value to be stored in pmpcfg register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 0*(XLEN/32),4,NOP + .align 3 + +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-X-priority.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-X-priority.S new file mode 100644 index 000000000..a9c4d0a9b --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-X-priority.S @@ -0,0 +1,214 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NA4-priority-x.S +// PMP Test in NA4 address matching mode +// Description: +// Tests the priority by assigning only X permissions to the high priority while R-W-X to low priority region +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NA4_priority_x) +RVTEST_SIGBASE( x13,signature_x13_1) + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP7_CFG_SHIFT 56 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg2[63:56] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP7_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in NAPOT Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_X|PMP_NA4)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of region3 +#define PMPADDRESS2 TEST_FOR_EXECUTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg2, x4 // Updated pmpcfg2 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 4*(XLEN/32),8,0x12345678 + .align 3 + +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-X.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-X.S new file mode 100644 index 000000000..7eeffaa50 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-NA4-X.S @@ -0,0 +1,239 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NA4-X.S +// PMP Test in NA4 address matching mode +// Description: +=> Foreach mode in MPP (including M), for Load/store instruction, perform the instruction referencing an address where the associated pmpcfg.W=1 and observe an access fault or not. +=> Foreach mode, perform instruction fetches to an address where the associated pmpcfg.X=0 and observe an access fault or not. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +*/ +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NA4_x) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP4_CFG_SHIFT 32 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg0 [7:0] value to configure address 0->RAM_LOCATION_FOR_TEST in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in NA4 Mode with X enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_X|PMP_L|PMP_NA4)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(rvtest_code_end) +// in TOR Mode with RWX enabled +// ALSO NOTE THAT PMPREGION2 IS INSIDE THIS REGION, so this test will also check the priority order of PMP regions +#define PMPREGION3 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[39:32] value to configure address (rvtest_code_end)->(PMP_region_High) +// in TOR Mode with RWX enabled +#define PMPREGION4 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP4_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS0 RAM_LOCATION_FOR_TEST // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS1 TEST_FOR_EXECUTION +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of region3 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of region3 +#define PMPADDRESS3 rvtest_code_end +// PMPADDRESS4 = value to be loaded pmpaddr4 to declare upper address of region4 +#define PMPADDRESS4 PMP_region_High + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration +/* PMP is configure in the following order: +1. Address 0x0000 0000 to Address RAM_LOCATION_FOR_TEST => PMP TOR Region with RWX enabled. This region is the part of the code memory containing our code. For this purpose, pmpaddr0 has been given the value of RAM_LOCATION_FOR_TEST to declare the region from 0->RAM_LOCATION_FOR_TEST into a single PMP region. + +2. Address TEST_FOR_EXECUTION to Address RETURN_INSTRUCTION =====> This is the PMP region under test (A 4byte region == Granularity of Sail. This region has been declared by entering TEST_FOR_EXECUTION into pmpaddr1 and RETURN_INSTRUCTION into pmpaddr2. Then a PMP region is configure into NA4 mode by setting pmpcfg0[15:8]=PMPREGION2 + +3. Address RAM_LOCATION_FOR_TEST to Address rvtest_code_end => Another PMP region under test. This region has been declared by entering rvtest_code_end into pmpaddr3 and RAM_LOCATION_FOR_TEST into pmpaddr2. configure pmpaddr2(RAM_LOCATION_FOR_TEST) to pmpaddr3(rvtest_code_end) into TOR mode by setting pmpcfg0[31:24]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) + +4. Address rvtest_code_end to address PMP_region_High => PMP TOR Region with RWX enabled. This region is the part of the code memory containing trap handler, epilogs, and other important macro definitions. For this purpose, configure pmpaddr3(rvtest_code_end) to pmpaddr4(PMP_region_High) into TOR mode by setting pmpcfg1[7:0]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)). This PMP Region is mandatory to access signature area in S,U mode */ + /* Assigning addresses to PMP address registers */ + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS4) // Value to be stored in pmpaddr4 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr4, x4 // Updated pmpaddr4 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1 | PMPREGION2 | PMPREGION3 | PMPREGION4) + // Value to be stored in pmpcfg register ; Setting Up PMP Region-1,2,3 + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +.align 3 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-R-priority-level-2.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-R-priority-level-2.S new file mode 100644 index 000000000..63d4679cc --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-R-priority-level-2.S @@ -0,0 +1,233 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NAPOT-priority-r-level-2.S +// Tests the priority by assigning only R permissions to the highest priority while no permissions to high priority region and R-W-X to low priority region +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NAPOT_priority_r_level_2) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP7_CFG_SHIFT 56 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg2 [63:56] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled. This is the low priority region +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP7_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with nothing enabled +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION3 ((((PMP_R|PMP_L|PMP_NAPOT)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +// PMPADDRESS14 = value to be loaded pmpaddr14 to declare lower address of Region-1 +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr14 to declare region1 +// PMPADDRESS15 = value to be loaded pmpaddr15 to declare upper address of Region-1 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of Region-2 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of Region-2 +#define PMPADDRESS3 RETURN_INSTRUCTION +// PMPADDRESS3 = value to be loaded pmpaddr1 to declare upper address of Region-3 +#define PMPADDRESS1 TEST_FOR_EXECUTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg2, x4 // Updated pmpcfg2 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION3) + // Value to be stored in pmpcfg register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,NOP +.align 3 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-R-priority.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-R-priority.S new file mode 100644 index 000000000..8b7f641b1 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-R-priority.S @@ -0,0 +1,213 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NAPOT-priority-r.S +// PMP Test in NAPOT address matching mode +// Description: +// Tests the priority by assigning only R permissions to the high priority while R-W-X to low priority region +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NAPOT_priority_r) +RVTEST_SIGBASE( x13,signature_x13_1) + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP7_CFG_SHIFT 56 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg2[63:56] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP7_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in NAPOT Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_R|PMP_NAPOT)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of region3 +#define PMPADDRESS2 TEST_FOR_EXECUTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg2, x4 // Updated pmpcfg2 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +.align 3 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-R.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-R.S new file mode 100644 index 000000000..e72cb3802 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-R.S @@ -0,0 +1,241 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NAPOT-R.S +// PMP Test in NAPOT address matching mode +// Description: +=> Foreach mode in MPP (including M), for Load/store instruction, perform the instruction referencing an address where the associated pmpcfg.W=0 and observe an access fault or not. +=> Foreach mode, perform instruction fetches to an address where the associated pmpcfg.X=0 and observe an access fault or not. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +=> Do the same for loads where pmpcfg.R=1 and pmpcfg.W=0 to make sure that the W bit only affects stores and AMOs. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +*/ +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NAPOT_r) +RVTEST_SIGBASE( x13,signature_x13_1) + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP4_CFG_SHIFT 32 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg0 [7:0] value to configure address 0->RAM_LOCATION_FOR_TEST in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in NAPOT Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_R|PMP_L|PMP_NAPOT)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(rvtest_code_end) +// in TOR Mode with RWX enabled +// ALSO NOTE THAT PMPREGION2 IS INSIDE THIS REGION, so this test will also check the priority order of PMP regions +#define PMPREGION3 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[39:32] value to configure address (rvtest_code_end)->(PMP_region_High) +// in TOR Mode with RWX enabled +#define PMPREGION4 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP4_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS0 RAM_LOCATION_FOR_TEST // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS1 TEST_FOR_EXECUTION +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of region3 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of region3 +#define PMPADDRESS3 rvtest_code_end +// PMPADDRESS4 = value to be loaded pmpaddr4 to declare upper address of region4 +#define PMPADDRESS4 PMP_region_High + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration +/* PMP is configure in the following order: +1. Address 0x0000 0000 to Address RAM_LOCATION_FOR_TEST => PMP TOR Region with RWX enabled. This region is the part of the code memory containing our code. For this purpose, pmpaddr0 has been given the value of RAM_LOCATION_FOR_TEST to declare the region from 0->RAM_LOCATION_FOR_TEST into a single PMP region. + +2. Address TEST_FOR_EXECUTION to Address RETURN_INSTRUCTION =====> This is the PMP region under test (A 4byte region == Granularity of Sail. This region has been declared by entering TEST_FOR_EXECUTION into pmpaddr1. Then a PMP region is configure into NAPOT mode by setting pmpcfg0[15:8]=PMPREGION2 + +3. Address RAM_LOCATION_FOR_TEST to Address rvtest_code_end => Another PMP region under test. This region has been declared by entering rvtest_code_end into pmpaddr3 and RAM_LOCATION_FOR_TEST into pmpaddr2. configure pmpaddr2(RAM_LOCATION_FOR_TEST) to pmpaddr3(rvtest_code_end) into TOR mode by setting pmpcfg0[31:24]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) + +4. Address rvtest_code_end to address PMP_region_High => PMP TOR Region with RWX enabled. This region is the part of the code memory containing trap handler, epilogs, and other important macro definitions. For this purpose, configure pmpaddr3(rvtest_code_end) to pmpaddr4(PMP_region_High) into TOR mode by setting pmpcfg1[7:0]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)). This PMP Region is mandatory to access signature area in S,U mode */ + /* Assigning addresses to PMP address registers */ + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS4) // Value to be stored in pmpaddr4 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr4, x4 // Updated pmpaddr4 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1 | PMPREGION2 | PMPREGION3 | PMPREGION4) + // Value to be stored in pmpcfg register ; Setting Up PMP Region-1,2,3 + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +.align 3 + +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-RW-priority-level-2.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-RW-priority-level-2.S new file mode 100644 index 000000000..225acf70b --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-RW-priority-level-2.S @@ -0,0 +1,233 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NAPOT-priority-rw-level-2.S +// Tests the priority by assigning only R, w permissions to the highest priority while no permissions to high priority region and R-W-X to low priority region +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NAPOT_priority_rw_level_2) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP7_CFG_SHIFT 56 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg2 [63:56] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled. This is the low priority region +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP7_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with nothing enabled +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION3 ((((PMP_R|PMP_W|PMP_L|PMP_NAPOT)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +// PMPADDRESS14 = value to be loaded pmpaddr14 to declare lower address of Region-1 +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr14 to declare region1 +// PMPADDRESS15 = value to be loaded pmpaddr15 to declare upper address of Region-1 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of Region-2 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of Region-2 +#define PMPADDRESS3 RETURN_INSTRUCTION +// PMPADDRESS3 = value to be loaded pmpaddr1 to declare upper address of Region-3 +#define PMPADDRESS1 TEST_FOR_EXECUTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg2, x4 // Updated pmpcfg2 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION3) + // Value to be stored in pmpcfg register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,NOP +.align 3 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-RW-priority.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-RW-priority.S new file mode 100644 index 000000000..0441e30db --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-RW-priority.S @@ -0,0 +1,213 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NAPOT-priority-rw.S +// PMP Test in NAPOT address matching mode +// Description: +// Tests the priority by assigning only R,W permissions to the high priority while R-W-X to low priority region +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NAPOT_priority_rw) +RVTEST_SIGBASE( x13,signature_x13_1) + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP7_CFG_SHIFT 56 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg2[63:56] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP7_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in NAPOT Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_R|PMP_W|PMP_NAPOT)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of region3 +#define PMPADDRESS2 TEST_FOR_EXECUTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg2, x4 // Updated pmpcfg2 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +.align 3 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-RW.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-RW.S new file mode 100644 index 000000000..963a5436d --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-RW.S @@ -0,0 +1,240 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NAPOT-RW.S +// PMP Test in NAPOT address matching mode +// Description: +=> Foreach mode in MPP (including M), for Load/store instruction, perform the instruction referencing an address where the associated pmpcfg.W=0 and observe an access fault or not. +=> Foreach mode, perform instruction fetches to an address where the associated pmpcfg.X=0 and observe an access fault or not. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +=> Do the same for loads where pmpcfg.R=1 and pmpcfg.W=0 to make sure that the W bit only affects stores and AMOs. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +*/ +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NAPOT_rw) +RVTEST_SIGBASE( x13,signature_x13_1) + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP4_CFG_SHIFT 32 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg0 [7:0] value to configure address 0->RAM_LOCATION_FOR_TEST in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in NAPOT Mode with RW enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_R|PMP_W|PMP_L|PMP_NAPOT)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(rvtest_code_end) +// in TOR Mode with RWX enabled +// ALSO NOTE THAT PMPREGION2 IS INSIDE THIS REGION, so this test will also check the priority order of PMP regions +#define PMPREGION3 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[39:32] value to configure address (rvtest_code_end)->(PMP_region_High) +// in TOR Mode with RWX enabled +#define PMPREGION4 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP4_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS0 RAM_LOCATION_FOR_TEST // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS1 TEST_FOR_EXECUTION +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of region3 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of region3 +#define PMPADDRESS3 rvtest_code_end +// PMPADDRESS4 = value to be loaded pmpaddr4 to declare upper address of region4 +#define PMPADDRESS4 PMP_region_High + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration +/* PMP is configure in the following order: +1. Address 0x0000 0000 to Address RAM_LOCATION_FOR_TEST => PMP TOR Region with RWX enabled. This region is the part of the code memory containing our code. For this purpose, pmpaddr0 has been given the value of RAM_LOCATION_FOR_TEST to declare the region from 0->RAM_LOCATION_FOR_TEST into a single PMP region. + +2. Address TEST_FOR_EXECUTION to Address RETURN_INSTRUCTION =====> This is the PMP region under test (A 4byte region == Granularity of Sail. This region has been declared by entering TEST_FOR_EXECUTION into pmpaddr1 and RETURN_INSTRUCTION into pmpaddr2. Then a PMP region is configure into NA4 mode by setting pmpcfg0[15:8]=PMPREGION2 + +3. Address RAM_LOCATION_FOR_TEST to Address rvtest_code_end => Another PMP region under test. This region has been declared by entering rvtest_code_end into pmpaddr3 and RAM_LOCATION_FOR_TEST into pmpaddr2. configure pmpaddr2(RAM_LOCATION_FOR_TEST) to pmpaddr3(rvtest_code_end) into TOR mode by setting pmpcfg0[31:24]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) + +4. Address rvtest_code_end to address PMP_region_High => PMP TOR Region with RWX enabled. This region is the part of the code memory containing trap handler, epilogs, and other important macro definitions. For this purpose, configure pmpaddr3(rvtest_code_end) to pmpaddr4(PMP_region_High) into TOR mode by setting pmpcfg1[7:0]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)). This PMP Region is mandatory to access signature area in S,U mode */ + /* Assigning addresses to PMP address registers */ + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS4) // Value to be stored in pmpaddr4 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr4, x4 // Updated pmpaddr4 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1 | PMPREGION2 | PMPREGION3 | PMPREGION4) + // Value to be stored in pmpcfg register ; Setting Up PMP Region-1,2,3 + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +.align 3 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-RWX.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-RWX.S new file mode 100644 index 000000000..4d7885644 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-RWX.S @@ -0,0 +1,240 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NAPOT-RWX.S +// PMP Test in NAPOT address matching mode +// Description: +=> Foreach mode in MPP (including M), for Load/store instruction, perform the instruction referencing an address where the associated pmpcfg.W=0 and observe an access fault or not. +=> Foreach mode, perform instruction fetches to an address where the associated pmpcfg.X=0 and observe an access fault or not. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +=> Do the same for loads where pmpcfg.R=1 and pmpcfg.W=0 to make sure that the W bit only affects stores and AMOs. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +*/ +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NAPOT_rwx) +RVTEST_SIGBASE( x13,signature_x13_1) + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP4_CFG_SHIFT 32 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg0 [7:0] value to configure address 0->RAM_LOCATION_FOR_TEST in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in NAPOT Mode with RWX enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_NAPOT)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(rvtest_code_end) +// in TOR Mode with RWX enabled +// ALSO NOTE THAT PMPREGION2 IS INSIDE THIS REGION, so this test will also check the priority order of PMP regions +#define PMPREGION3 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[39:32] value to configure address (rvtest_code_end)->(PMP_region_High) +// in TOR Mode with RWX enabled +#define PMPREGION4 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP4_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS0 RAM_LOCATION_FOR_TEST // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS1 TEST_FOR_EXECUTION +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of region3 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of region3 +#define PMPADDRESS3 rvtest_code_end +// PMPADDRESS4 = value to be loaded pmpaddr4 to declare upper address of region4 +#define PMPADDRESS4 PMP_region_High + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration +/* PMP is configure in the following order: +1. Address 0x0000 0000 to Address RAM_LOCATION_FOR_TEST => PMP TOR Region with RWX enabled. This region is the part of the code memory containing our code. For this purpose, pmpaddr0 has been given the value of RAM_LOCATION_FOR_TEST to declare the region from 0->RAM_LOCATION_FOR_TEST into a single PMP region. + +2. Address TEST_FOR_EXECUTION to Address RETURN_INSTRUCTION =====> This is the PMP region under test (A 4byte region == Granularity of Sail. This region has been declared by entering TEST_FOR_EXECUTION into pmpaddr1 and RETURN_INSTRUCTION into pmpaddr2. Then a PMP region is configure into NA4 mode by setting pmpcfg0[15:8]=PMPREGION2 + +3. Address RAM_LOCATION_FOR_TEST to Address rvtest_code_end => Another PMP region under test. This region has been declared by entering rvtest_code_end into pmpaddr3 and RAM_LOCATION_FOR_TEST into pmpaddr2. configure pmpaddr2(RAM_LOCATION_FOR_TEST) to pmpaddr3(rvtest_code_end) into TOR mode by setting pmpcfg0[31:24]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) + +4. Address rvtest_code_end to address PMP_region_High => PMP TOR Region with RWX enabled. This region is the part of the code memory containing trap handler, epilogs, and other important macro definitions. For this purpose, configure pmpaddr3(rvtest_code_end) to pmpaddr4(PMP_region_High) into TOR mode by setting pmpcfg1[7:0]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)). This PMP Region is mandatory to access signature area in S,U mode */ + /* Assigning addresses to PMP address registers */ + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS4) // Value to be stored in pmpaddr4 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr4, x4 // Updated pmpaddr4 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1 | PMPREGION2 | PMPREGION3 | PMPREGION4) + // Value to be stored in pmpcfg register ; Setting Up PMP Region-1,2,3 + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +.align 3 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-RX-priority-level-2.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-RX-priority-level-2.S new file mode 100644 index 000000000..d666f4e94 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-RX-priority-level-2.S @@ -0,0 +1,233 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NAPOT-priority-rx-level-2.S +// Tests the priority by assigning only R,X permissions to the highest priority while no permissions to high priority region and R-W-X to low priority region +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NAPOT_priority_rx_level_2) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP7_CFG_SHIFT 56 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg2 [63:56] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled. This is the low priority region +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP7_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with nothing enabled +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION3 ((((PMP_R|PMP_X|PMP_L|PMP_NAPOT)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +// PMPADDRESS14 = value to be loaded pmpaddr14 to declare lower address of Region-1 +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr14 to declare region1 +// PMPADDRESS15 = value to be loaded pmpaddr15 to declare upper address of Region-1 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of Region-2 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of Region-2 +#define PMPADDRESS3 RETURN_INSTRUCTION +// PMPADDRESS3 = value to be loaded pmpaddr1 to declare upper address of Region-3 +#define PMPADDRESS1 TEST_FOR_EXECUTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg2, x4 // Updated pmpcfg2 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION3) + // Value to be stored in pmpcfg register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,NOP +.align 3 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-RX-priority.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-RX-priority.S new file mode 100644 index 000000000..1843d4d65 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-RX-priority.S @@ -0,0 +1,213 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NAPOT-priority-rx.S +// PMP Test in NAPOT address matching mode +// Description: +// Tests the priority by assigning only R,X permissions to the high priority while R-W-X to low priority region +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NAPOT_priority_rx) +RVTEST_SIGBASE( x13,signature_x13_1) + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP7_CFG_SHIFT 56 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg2[63:56] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP7_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in NAPOT Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_R|PMP_X|PMP_NAPOT)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of region3 +#define PMPADDRESS2 TEST_FOR_EXECUTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg2, x4 // Updated pmpcfg2 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +.align 3 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-RX.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-RX.S new file mode 100644 index 000000000..11b1eb837 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-RX.S @@ -0,0 +1,240 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NAPOT-RX.S +// PMP Test in NAPOT address matching mode +// Description: +=> Foreach mode in MPP (including M), for Load/store instruction, perform the instruction referencing an address where the associated pmpcfg.W=0 and observe an access fault or not. +=> Foreach mode, perform instruction fetches to an address where the associated pmpcfg.X=0 and observe an access fault or not. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +=> Do the same for loads where pmpcfg.R=1 and pmpcfg.W=0 to make sure that the W bit only affects stores and AMOs. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +*/ +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NAPOT_rx) +RVTEST_SIGBASE( x13,signature_x13_1) + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP4_CFG_SHIFT 32 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg0 [7:0] value to configure address 0->RAM_LOCATION_FOR_TEST in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in NAPOT Mode with RX enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_R|PMP_X|PMP_L|PMP_NAPOT)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(rvtest_code_end) +// in TOR Mode with RWX enabled +// ALSO NOTE THAT PMPREGION2 IS INSIDE THIS REGION, so this test will also check the priority order of PMP regions +#define PMPREGION3 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[39:32] value to configure address (rvtest_code_end)->(PMP_region_High) +// in TOR Mode with RWX enabled +#define PMPREGION4 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP4_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS0 RAM_LOCATION_FOR_TEST // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS1 TEST_FOR_EXECUTION +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of region3 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of region3 +#define PMPADDRESS3 rvtest_code_end +// PMPADDRESS4 = value to be loaded pmpaddr4 to declare upper address of region4 +#define PMPADDRESS4 PMP_region_High + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration +/* PMP is configure in the following order: +1. Address 0x0000 0000 to Address RAM_LOCATION_FOR_TEST => PMP TOR Region with RWX enabled. This region is the part of the code memory containing our code. For this purpose, pmpaddr0 has been given the value of RAM_LOCATION_FOR_TEST to declare the region from 0->RAM_LOCATION_FOR_TEST into a single PMP region. + +2. Address TEST_FOR_EXECUTION to Address RETURN_INSTRUCTION =====> This is the PMP region under test (A 4byte region == Granularity of Sail. This region has been declared by entering TEST_FOR_EXECUTION into pmpaddr1 and RETURN_INSTRUCTION into pmpaddr2. Then a PMP region is configure into NA4 mode by setting pmpcfg0[15:8]=PMPREGION2 + +3. Address RAM_LOCATION_FOR_TEST to Address rvtest_code_end => Another PMP region under test. This region has been declared by entering rvtest_code_end into pmpaddr3 and RAM_LOCATION_FOR_TEST into pmpaddr2. configure pmpaddr2(RAM_LOCATION_FOR_TEST) to pmpaddr3(rvtest_code_end) into TOR mode by setting pmpcfg0[31:24]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) + +4. Address rvtest_code_end to address PMP_region_High => PMP TOR Region with RWX enabled. This region is the part of the code memory containing trap handler, epilogs, and other important macro definitions. For this purpose, configure pmpaddr3(rvtest_code_end) to pmpaddr4(PMP_region_High) into TOR mode by setting pmpcfg1[7:0]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)). This PMP Region is mandatory to access signature area in S,U mode */ + /* Assigning addresses to PMP address registers */ + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS4) // Value to be stored in pmpaddr4 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr4, x4 // Updated pmpaddr4 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1 | PMPREGION2 | PMPREGION3 | PMPREGION4) + // Value to be stored in pmpcfg register ; Setting Up PMP Region-1,2,3 + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +.align 3 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-X-priority-level-2.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-X-priority-level-2.S new file mode 100644 index 000000000..9d2e5ea1e --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-X-priority-level-2.S @@ -0,0 +1,233 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NAPOT-priority-x-level-2.S +// Tests the priority by assigning only X permissions to the highest priority while no permissions to high priority region and R-W-X to low priority region +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NAPOT_priority_x_level_2) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP7_CFG_SHIFT 56 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg2 [63:56] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled. This is the low priority region +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP7_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with nothing enabled +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION3 ((((PMP_X|PMP_L|PMP_NAPOT)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +// PMPADDRESS14 = value to be loaded pmpaddr14 to declare lower address of Region-1 +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr14 to declare region1 +// PMPADDRESS15 = value to be loaded pmpaddr15 to declare upper address of Region-1 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of Region-2 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of Region-2 +#define PMPADDRESS3 RETURN_INSTRUCTION +// PMPADDRESS3 = value to be loaded pmpaddr1 to declare upper address of Region-3 +#define PMPADDRESS1 TEST_FOR_EXECUTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg2, x4 // Updated pmpcfg2 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION3) + // Value to be stored in pmpcfg register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,NOP +.align 3 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-X-priority.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-X-priority.S new file mode 100644 index 000000000..e23b39e7f --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-X-priority.S @@ -0,0 +1,213 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NAPOT-priority-x.S +// PMP Test in NAPOT address matching mode +// Description: +// Tests the priority by assigning only X permissions to the high priority while R-W-X to low priority region +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NAPOT_priority_x) +RVTEST_SIGBASE( x13,signature_x13_1) + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP7_CFG_SHIFT 56 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg2[63:56] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP7_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in NAPOT Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_X|PMP_NAPOT)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of region3 +#define PMPADDRESS2 TEST_FOR_EXECUTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg2, x4 // Updated pmpcfg2 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +.align 3 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-X.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-X.S new file mode 100644 index 000000000..a24570f8f --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-NAPOT-X.S @@ -0,0 +1,240 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-NAPOT-X.S +// PMP Test in NAPOT address matching mode +// Description: +=> Foreach mode in MPP (including M), for Load/store instruction, perform the instruction referencing an address where the associated pmpcfg.W=0 and observe an access fault or not. +=> Foreach mode, perform instruction fetches to an address where the associated pmpcfg.X=0 and observe an access fault or not. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +=> Do the same for loads where pmpcfg.R=1 and pmpcfg.W=0 to make sure that the W bit only affects stores and AMOs. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +*/ +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_NAPOT_x) +RVTEST_SIGBASE( x13,signature_x13_1) + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP4_CFG_SHIFT 32 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg0 [7:0] value to configure address 0->RAM_LOCATION_FOR_TEST in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in NAPOT Mode with X enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_X|PMP_L|PMP_NAPOT)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(rvtest_code_end) +// in TOR Mode with RWX enabled +// ALSO NOTE THAT PMPREGION2 IS INSIDE THIS REGION, so this test will also check the priority order of PMP regions +#define PMPREGION3 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[39:32] value to configure address (rvtest_code_end)->(PMP_region_High) +// in TOR Mode with RWX enabled +#define PMPREGION4 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP4_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS0 RAM_LOCATION_FOR_TEST // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS1 TEST_FOR_EXECUTION +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of region3 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of region3 +#define PMPADDRESS3 rvtest_code_end +// PMPADDRESS4 = value to be loaded pmpaddr4 to declare upper address of region4 +#define PMPADDRESS4 PMP_region_High + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration +/* PMP is configure in the following order: +1. Address 0x0000 0000 to Address RAM_LOCATION_FOR_TEST => PMP TOR Region with RWX enabled. This region is the part of the code memory containing our code. For this purpose, pmpaddr0 has been given the value of RAM_LOCATION_FOR_TEST to declare the region from 0->RAM_LOCATION_FOR_TEST into a single PMP region. + +2. Address TEST_FOR_EXECUTION to Address RETURN_INSTRUCTION =====> This is the PMP region under test (A 4byte region == Granularity of Sail. This region has been declared by entering TEST_FOR_EXECUTION into pmpaddr1 and RETURN_INSTRUCTION into pmpaddr2. Then a PMP region is configure into NA4 mode by setting pmpcfg0[15:8]=PMPREGION2 + +3. Address RAM_LOCATION_FOR_TEST to Address rvtest_code_end => Another PMP region under test. This region has been declared by entering rvtest_code_end into pmpaddr3 and RAM_LOCATION_FOR_TEST into pmpaddr2. configure pmpaddr2(RAM_LOCATION_FOR_TEST) to pmpaddr3(rvtest_code_end) into TOR mode by setting pmpcfg0[31:24]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) + +4. Address rvtest_code_end to address PMP_region_High => PMP TOR Region with RWX enabled. This region is the part of the code memory containing trap handler, epilogs, and other important macro definitions. For this purpose, configure pmpaddr3(rvtest_code_end) to pmpaddr4(PMP_region_High) into TOR mode by setting pmpcfg1[7:0]=((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)). This PMP Region is mandatory to access signature area in S,U mode */ + /* Assigning addresses to PMP address registers */ + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS4) // Value to be stored in pmpaddr4 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr4, x4 // Updated pmpaddr4 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1 | PMPREGION2 | PMPREGION3 | PMPREGION4) + // Value to be stored in pmpcfg register ; Setting Up PMP Region-1,2,3 + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +.align 3 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-R-priority-level-2.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-R-priority-level-2.S new file mode 100644 index 000000000..2967e6fd2 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-R-priority-level-2.S @@ -0,0 +1,239 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-TOR-priority-r-level-2.S +// Tests the priority by assigning only R permissions to the highest priority while no permissions to high priority region and R-W-X to low priority region +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_TOR_priority_r_level_2) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP7_CFG_SHIFT 56 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg2 [63:56] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled. This is the low priority region +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP7_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with nothing enabled +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION3 ((((PMP_R|PMP_L|PMP_TOR)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +// PMPADDRESS14 = value to be loaded pmpaddr14 to declare lower address of Region-1 +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr14 to declare region1 +// PMPADDRESS15 = value to be loaded pmpaddr15 to declare upper address of Region-1 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of Region-2 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of Region-2 +#define PMPADDRESS3 RETURN_INSTRUCTION +// PMPADDRESS2 = value to be loaded pmpaddr0 to declare lower address of Region-3 +#define PMPADDRESS0 TEST_FOR_EXECUTION +// PMPADDRESS3 = value to be loaded pmpaddr1 to declare upper address of Region-3 +#define PMPADDRESS1 RETURN_INSTRUCTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg2, x4 // Updated pmpcfg2 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION3) + // Value to be stored in pmpcfg register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 0*(XLEN/32),4,NOP +.align 3 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-R-priority.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-R-priority.S new file mode 100644 index 000000000..4f299be98 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-R-priority.S @@ -0,0 +1,218 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-TOR-priority-r.S +// Tests the priority by assigning only R permissions to the high priority while R-W-X to low priority region +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_TOR_priority_r) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP7_CFG_SHIFT 56 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg2 [63:56] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled. This is the low priority region +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP7_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_R|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +// PMPADDRESS14 = value to be loaded pmpaddr14 to declare lower address of Region-1 +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr14 to declare region1 +// PMPADDRESS15 = value to be loaded pmpaddr15 to declare upper address of Region-1 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr3 to declare lower address of Region-2 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of Region-2 +#define PMPADDRESS3 RETURN_INSTRUCTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg2, x4 // Updated pmpcfg2 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 0*(XLEN/32),4,NOP +.align 3 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-R.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-R.S new file mode 100644 index 000000000..a748d899d --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-R.S @@ -0,0 +1,248 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-tor-R.S +// PMP Test in TOR address matching mode +// Description: +=> Foreach mode in MPP (including M), for Load/store instruction, perform the instruction referencing an address where the associated pmpcfg.W=1 and observe an access fault or not. +=> Foreach mode, perform instruction fetches to an address where the associated pmpcfg.X=0 and observe an access fault or not. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +=> Do the same for loads where pmpcfg.R=1 and pmpcfg.W=0 to make sure that the W bit only affects stores and AMOs. +*/ +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_TOR_r) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP4_CFG_SHIFT 32 +#define PMP5_CFG_SHIFT 40 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg0 [7:0] value to configure address 0->RAM_LOCATION_FOR_TEST in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[23:16] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in TOR Mode with X enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_R|PMP_L|PMP_TOR)&0xFF) << PMP2_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[39:32] value to configure address (RAM_LOCATION_FOR_TEST)->(rvtest_code_end) +// in TOR Mode with RW enabled +// ALSO NOTE THAT PMPREGION2 IS INSIDE THIS REGION, so this test will also check the priority order of PMP regions +#define PMPREGION3 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP4_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[47:40] value to configure address (rvtest_code_end)->(PMP_region_High) +// in TOR Mode with RWX enabled +#define PMPREGION4 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP5_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS0 RAM_LOCATION_FOR_TEST // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS1 TEST_FOR_EXECUTION +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare upper address of region2 +#define PMPADDRESS2 RETURN_INSTRUCTION +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare lower address of region3 +#define PMPADDRESS3 RAM_LOCATION_FOR_TEST +// PMPADDRESS4 = value to be loaded pmpaddr4 to declare upper address of region3 +#define PMPADDRESS4 rvtest_code_end +// PMPADDRESS5 = value to be loaded pmpaddr5 to declare upper address of region4 +#define PMPADDRESS5 PMP_region_High + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration +/* PMP is configure in the following order: +1. Address 0x8000 0000 to Address RAM_LOCATION_FOR_TEST => PMP TOR Region with RWX enabled. This region is the part of the code memory containing our code. For this purpose, pmpaddr0 has been given the value of RAM_LOCATION_FOR_TEST to declare the region from 0->RAM_LOCATION_FOR_TEST into a single PMP region. + +2. Address TEST_FOR_EXECUTION to Address RETURN_INSTRUCTION => PMP region under test. This region has been declared by entering TEST_FOR_EXECUTION into pmpaddr1 and rvtest_code_end into pmpaddr2. Then a PMP region is configure from pmpaddr2(RETURN_INSTRUCTION) to pmpaddr1(TEST_FOR_EXECUTION) into TOR mode by setting pmpcfg0[23:16]=PMPREGION2 + +3. Address RAM_LOCATION_FOR_TEST to Address rvtest_code_end => PMP region under test. This region has been declared by entering rvtest_code_end into pmpaddr4 and RAM_LOCATION_FOR_TEST into pmpaddr3. configure pmpaddr4(RAM_LOCATION_FOR_TEST) to pmpaddr5(rvtest_code_end) into TOR mode by setting pmpcfg1[15:8]=PMPREGION3 + +4. Address rvtest_code_end to address PMP_region_High => PMP TOR Region with RWX enabled. This region is the part of the code memory containing trap handler, epilogs, and other important macro definitions. For this purpose, configure pmpaddr4(rvtest_code_end) to pmpaddr5(PMP_region_High) into TOR mode by setting pmpcfg1[15:8]=PMPREGION4. This PMP Region is mandatory to access signature area in S,U mode */ + /* Assigning addresses to PMP address registers */ + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS4) // Value to be stored in pmpaddr4 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr4, x4 // Updated pmpaddr4 + nop // Added nop in case of trap + LA(x4, PMPADDRESS5) // Value to be stored in pmpaddr5 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr5, x4 // Updated pmpaddr5 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1 | PMPREGION2 | PMPREGION3 | PMPREGION4) + // Value to be stored in pmpcfg register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +.align 3 + +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-RW-priority-level-2..S b/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-RW-priority-level-2..S new file mode 100644 index 000000000..e79816a64 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-RW-priority-level-2..S @@ -0,0 +1,240 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-TOR-priority-rw-level-2.S +// Tests the priority by assigning only R,W permissions to the highest priority while no permissions to high priority region and R-W-X to low priority region +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_TOR_priority_rw_level_2) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP7_CFG_SHIFT 56 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg2 [63:56] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled. This is the low priority region +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP7_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with nothing enabled +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with R,W enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION3 ((((PMP_R|PMP_W|PMP_L|PMP_TOR)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +// PMPADDRESS14 = value to be loaded pmpaddr14 to declare lower address of Region-1 +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr14 to declare region1 +// PMPADDRESS15 = value to be loaded pmpaddr15 to declare upper address of Region-1 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of Region-2 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of Region-2 +#define PMPADDRESS3 RETURN_INSTRUCTION +// PMPADDRESS2 = value to be loaded pmpaddr0 to declare lower address of Region-3 +#define PMPADDRESS0 TEST_FOR_EXECUTION +// PMPADDRESS3 = value to be loaded pmpaddr1 to declare upper address of Region-3 +#define PMPADDRESS1 RETURN_INSTRUCTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg2, x4 // Updated pmpcfg2 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION3) + // Value to be stored in pmpcfg register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 1*(XLEN/32),4,NOP //Single +.align 3 + +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-RW-priority.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-RW-priority.S new file mode 100644 index 000000000..076ffd6fb --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-RW-priority.S @@ -0,0 +1,218 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-TOR-priority-rw.S +// Tests the priority by assigning only rw permissions to the high priority while R-W-X to low priority region +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_TOR_priority_rw) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP7_CFG_SHIFT 56 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg2 [63:56] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled. This is the low priority region +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP7_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_R|PMP_W|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +// PMPADDRESS14 = value to be loaded pmpaddr14 to declare lower address of Region-1 +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr14 to declare region1 +// PMPADDRESS15 = value to be loaded pmpaddr15 to declare upper address of Region-1 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr3 to declare lower address of Region-2 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of Region-2 +#define PMPADDRESS3 RETURN_INSTRUCTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg2, x4 // Updated pmpcfg2 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 0*(XLEN/32),4,NOP +.align 3 +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-RW.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-RW.S new file mode 100644 index 000000000..e0d08d6ed --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-RW.S @@ -0,0 +1,248 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-tor-RW.S +// PMP Test in TOR address matching mode +// Description: +=> Foreach mode in MPP (including M), for Load/store instruction, perform the instruction referencing an address where the associated pmpcfg.W=1 and observe an access fault or not. +=> Foreach mode, perform instruction fetches to an address where the associated pmpcfg.X=0 and observe an access fault or not. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +=> Do the same for loads where pmpcfg.R=1 and pmpcfg.W=0 to make sure that the W bit only affects stores and AMOs. +*/ +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_TOR_rw) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP4_CFG_SHIFT 32 +#define PMP5_CFG_SHIFT 40 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg0 [7:0] value to configure address 0->RAM_LOCATION_FOR_TEST in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[23:16] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in TOR Mode with X enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_R|PMP_W|PMP_L|PMP_TOR)&0xFF) << PMP2_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[39:32] value to configure address (RAM_LOCATION_FOR_TEST)->(rvtest_code_end) +// in TOR Mode with RW enabled +// ALSO NOTE THAT PMPREGION2 IS INSIDE THIS REGION, so this test will also check the priority order of PMP regions +#define PMPREGION3 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP4_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[47:40] value to configure address (rvtest_code_end)->(PMP_region_High) +// in TOR Mode with RWX enabled +#define PMPREGION4 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP5_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS0 RAM_LOCATION_FOR_TEST // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS1 TEST_FOR_EXECUTION +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare upper address of region2 +#define PMPADDRESS2 RETURN_INSTRUCTION +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare lower address of region3 +#define PMPADDRESS3 RAM_LOCATION_FOR_TEST +// PMPADDRESS4 = value to be loaded pmpaddr4 to declare upper address of region3 +#define PMPADDRESS4 rvtest_code_end +// PMPADDRESS5 = value to be loaded pmpaddr5 to declare upper address of region4 +#define PMPADDRESS5 PMP_region_High + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration +/* PMP is configure in the following order: +1. Address 0x8000 0000 to Address RAM_LOCATION_FOR_TEST => PMP TOR Region with RWX enabled. This region is the part of the code memory containing our code. For this purpose, pmpaddr0 has been given the value of RAM_LOCATION_FOR_TEST to declare the region from 0->RAM_LOCATION_FOR_TEST into a single PMP region. + +2. Address TEST_FOR_EXECUTION to Address RETURN_INSTRUCTION => PMP region under test. This region has been declared by entering TEST_FOR_EXECUTION into pmpaddr1 and rvtest_code_end into pmpaddr2. Then a PMP region is configure from pmpaddr2(RETURN_INSTRUCTION) to pmpaddr1(TEST_FOR_EXECUTION) into TOR mode by setting pmpcfg0[23:16]=PMPREGION2 + +3. Address RAM_LOCATION_FOR_TEST to Address rvtest_code_end => PMP region under test. This region has been declared by entering rvtest_code_end into pmpaddr4 and RAM_LOCATION_FOR_TEST into pmpaddr3. configure pmpaddr4(RAM_LOCATION_FOR_TEST) to pmpaddr5(rvtest_code_end) into TOR mode by setting pmpcfg1[15:8]=PMPREGION3 + +4. Address rvtest_code_end to address PMP_region_High => PMP TOR Region with RWX enabled. This region is the part of the code memory containing trap handler, epilogs, and other important macro definitions. For this purpose, configure pmpaddr4(rvtest_code_end) to pmpaddr5(PMP_region_High) into TOR mode by setting pmpcfg1[15:8]=PMPREGION4. This PMP Region is mandatory to access signature area in S,U mode */ + /* Assigning addresses to PMP address registers */ + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS4) // Value to be stored in pmpaddr4 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr4, x4 // Updated pmpaddr4 + nop // Added nop in case of trap + LA(x4, PMPADDRESS5) // Value to be stored in pmpaddr5 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr5, x4 // Updated pmpaddr5 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1 | PMPREGION2 | PMPREGION3 | PMPREGION4) + // Value to be stored in pmpcfg register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +.align 3 + +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-RWX.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-RWX.S new file mode 100644 index 000000000..1e9b313d3 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-RWX.S @@ -0,0 +1,248 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-tor-RWX.S +// PMP Test in TOR address matching mode +// Description: +=> Foreach mode in MPP (including M), for Load/store instruction, perform the instruction referencing an address where the associated pmpcfg.W=1 and observe an access fault or not. +=> Foreach mode, perform instruction fetches to an address where the associated pmpcfg.X=0 and observe an access fault or not. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +=> Do the same for loads where pmpcfg.R=1 and pmpcfg.W=0 to make sure that the W bit only affects stores and AMOs. +*/ +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_TOR_rwx) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP4_CFG_SHIFT 32 +#define PMP5_CFG_SHIFT 40 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg0 [7:0] value to configure address 0->RAM_LOCATION_FOR_TEST in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[23:16] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in TOR Mode with RWX enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP2_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[39:32] value to configure address (RAM_LOCATION_FOR_TEST)->(rvtest_code_end) +// in TOR Mode with RW enabled +// ALSO NOTE THAT PMPREGION2 IS INSIDE THIS REGION, so this test will also check the priority order of PMP regions +#define PMPREGION3 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP4_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg1[47:40] value to configure address (rvtest_code_end)->(PMP_region_High) +// in TOR Mode with RWX enabled +#define PMPREGION4 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP5_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS0 RAM_LOCATION_FOR_TEST // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS1 TEST_FOR_EXECUTION +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare upper address of region2 +#define PMPADDRESS2 RETURN_INSTRUCTION +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare lower address of region3 +#define PMPADDRESS3 RAM_LOCATION_FOR_TEST +// PMPADDRESS4 = value to be loaded pmpaddr4 to declare upper address of region3 +#define PMPADDRESS4 rvtest_code_end +// PMPADDRESS5 = value to be loaded pmpaddr5 to declare upper address of region4 +#define PMPADDRESS5 PMP_region_High + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration +/* PMP is configure in the following order: +1. Address 0x8000 0000 to Address RAM_LOCATION_FOR_TEST => PMP TOR Region with RWX enabled. This region is the part of the code memory containing our code. For this purpose, pmpaddr0 has been given the value of RAM_LOCATION_FOR_TEST to declare the region from 0->RAM_LOCATION_FOR_TEST into a single PMP region. + +2. Address TEST_FOR_EXECUTION to Address RETURN_INSTRUCTION => PMP region under test. This region has been declared by entering TEST_FOR_EXECUTION into pmpaddr1 and rvtest_code_end into pmpaddr2. Then a PMP region is configure from pmpaddr2(RETURN_INSTRUCTION) to pmpaddr1(TEST_FOR_EXECUTION) into TOR mode by setting pmpcfg0[23:16]=PMPREGION2 + +3. Address RAM_LOCATION_FOR_TEST to Address rvtest_code_end => PMP region under test. This region has been declared by entering rvtest_code_end into pmpaddr4 and RAM_LOCATION_FOR_TEST into pmpaddr3. configure pmpaddr4(RAM_LOCATION_FOR_TEST) to pmpaddr5(rvtest_code_end) into TOR mode by setting pmpcfg1[15:8]=PMPREGION3 + +4. Address rvtest_code_end to address PMP_region_High => PMP TOR Region with RWX enabled. This region is the part of the code memory containing trap handler, epilogs, and other important macro definitions. For this purpose, configure pmpaddr4(rvtest_code_end) to pmpaddr5(PMP_region_High) into TOR mode by setting pmpcfg1[15:8]=PMPREGION4. This PMP Region is mandatory to access signature area in S,U mode */ + /* Assigning addresses to PMP address registers */ + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS4) // Value to be stored in pmpaddr4 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr4, x4 // Updated pmpaddr4 + nop // Added nop in case of trap + LA(x4, PMPADDRESS5) // Value to be stored in pmpaddr5 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr5, x4 // Updated pmpaddr5 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1 | PMPREGION2 | PMPREGION3 | PMPREGION4) + // Value to be stored in pmpcfg register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +.align 3 + +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-RX-priority-level-2.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-RX-priority-level-2.S new file mode 100644 index 000000000..67ddb001d --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-RX-priority-level-2.S @@ -0,0 +1,240 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-TOR-priority-rx-level-2.S +// Tests the priority by assigning only R, X permissions to the highest priority while no permissions to high priority region and R-W-X to low priority region +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_TOR_priority_rx_level_2) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP7_CFG_SHIFT 56 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg2 [63:56] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled. This is the low priority region +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP7_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with nothing enabled +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with R,W enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION3 ((((PMP_R|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +// PMPADDRESS14 = value to be loaded pmpaddr14 to declare lower address of Region-1 +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr14 to declare region1 +// PMPADDRESS15 = value to be loaded pmpaddr15 to declare upper address of Region-1 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of Region-2 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of Region-2 +#define PMPADDRESS3 RETURN_INSTRUCTION +// PMPADDRESS2 = value to be loaded pmpaddr0 to declare lower address of Region-3 +#define PMPADDRESS0 TEST_FOR_EXECUTION +// PMPADDRESS3 = value to be loaded pmpaddr1 to declare upper address of Region-3 +#define PMPADDRESS1 RETURN_INSTRUCTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg2, x4 // Updated pmpcfg2 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION3) + // Value to be stored in pmpcfg register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 1*(XLEN/32),4,NOP //Single +.align 3 + +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-RX-priority.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-RX-priority.S new file mode 100644 index 000000000..eed06bab0 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-RX-priority.S @@ -0,0 +1,219 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-TOR-priority-rx.S +// Tests the priority by assigning only rx permissions to the high priority while R-W-X to low priority region +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_TOR_priority_rx) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP7_CFG_SHIFT 56 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg2 [63:56] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled. This is the low priority region +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP7_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_R|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +// PMPADDRESS14 = value to be loaded pmpaddr14 to declare lower address of Region-1 +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr14 to declare region1 +// PMPADDRESS15 = value to be loaded pmpaddr15 to declare upper address of Region-1 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr3 to declare lower address of Region-2 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of Region-2 +#define PMPADDRESS3 RETURN_INSTRUCTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg2, x4 // Updated pmpcfg2 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 0*(XLEN/32),4,NOP +.align 3 + +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-RX.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-RX.S new file mode 100644 index 000000000..88c5649c3 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-RX.S @@ -0,0 +1,248 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-tor-RX.S +// PMP Test in TOR address matching mode +// Description: +=> Foreach mode in MPP (including M), for Load/store instruction, perform the instruction referencing an address where the associated pmpcfg.W=1 and observe an access fault or not. +=> Foreach mode, perform instruction fetches to an address where the associated pmpcfg.X=0 and observe an access fault or not. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +=> Do the same for loads where pmpcfg.R=1 and pmpcfg.W=0 to make sure that the W bit only affects stores and AMOs. +*/ +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_TOR_rx) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP4_CFG_SHIFT 32 +#define PMP5_CFG_SHIFT 40 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg0 [7:0] value to configure address 0->RAM_LOCATION_FOR_TEST in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[23:16] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in TOR Mode with RX enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_R|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP2_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[39:32] value to configure address (RAM_LOCATION_FOR_TEST)->(rvtest_code_end) +// in TOR Mode with RW enabled +// ALSO NOTE THAT PMPREGION2 IS INSIDE THIS REGION, so this test will also check the priority order of PMP regions +#define PMPREGION3 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP4_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[47:40] value to configure address (rvtest_code_end)->(PMP_region_High) +// in TOR Mode with RWX enabled +#define PMPREGION4 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP5_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS0 RAM_LOCATION_FOR_TEST // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS1 TEST_FOR_EXECUTION +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare upper address of region2 +#define PMPADDRESS2 RETURN_INSTRUCTION +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare lower address of region3 +#define PMPADDRESS3 RAM_LOCATION_FOR_TEST +// PMPADDRESS4 = value to be loaded pmpaddr4 to declare upper address of region3 +#define PMPADDRESS4 rvtest_code_end +// PMPADDRESS5 = value to be loaded pmpaddr5 to declare upper address of region4 +#define PMPADDRESS5 PMP_region_High + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration +/* PMP is configure in the following order: +1. Address 0x8000 0000 to Address RAM_LOCATION_FOR_TEST => PMP TOR Region with RWX enabled. This region is the part of the code memory containing our code. For this purpose, pmpaddr0 has been given the value of RAM_LOCATION_FOR_TEST to declare the region from 0->RAM_LOCATION_FOR_TEST into a single PMP region. + +2. Address TEST_FOR_EXECUTION to Address RETURN_INSTRUCTION => PMP region under test. This region has been declared by entering TEST_FOR_EXECUTION into pmpaddr1 and rvtest_code_end into pmpaddr2. Then a PMP region is configure from pmpaddr2(RETURN_INSTRUCTION) to pmpaddr1(TEST_FOR_EXECUTION) into TOR mode by setting pmpcfg0[23:16]=PMPREGION2 + +3. Address RAM_LOCATION_FOR_TEST to Address rvtest_code_end => PMP region under test. This region has been declared by entering rvtest_code_end into pmpaddr4 and RAM_LOCATION_FOR_TEST into pmpaddr3. configure pmpaddr4(RAM_LOCATION_FOR_TEST) to pmpaddr5(rvtest_code_end) into TOR mode by setting pmpcfg1[15:8]=PMPREGION3 + +4. Address rvtest_code_end to address PMP_region_High => PMP TOR Region with RWX enabled. This region is the part of the code memory containing trap handler, epilogs, and other important macro definitions. For this purpose, configure pmpaddr4(rvtest_code_end) to pmpaddr5(PMP_region_High) into TOR mode by setting pmpcfg1[15:8]=PMPREGION4. This PMP Region is mandatory to access signature area in S,U mode */ + /* Assigning addresses to PMP address registers */ + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS4) // Value to be stored in pmpaddr4 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr4, x4 // Updated pmpaddr4 + nop // Added nop in case of trap + LA(x4, PMPADDRESS5) // Value to be stored in pmpaddr5 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr5, x4 // Updated pmpaddr5 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1 | PMPREGION2 | PMPREGION3 | PMPREGION4) + // Value to be stored in pmpcfg register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +.align 3 + +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-X-priority-level-2.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-X-priority-level-2.S new file mode 100644 index 000000000..fe3550e5b --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-X-priority-level-2.S @@ -0,0 +1,240 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-TOR-priority-x-level-2.S +// Tests the priority by assigning only X permissions to the highest priority while no permissions to high priority region and R-W-X to low priority region +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_TOR_priority_x_level_2) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP7_CFG_SHIFT 56 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg2 [63:56] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled. This is the low priority region +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP7_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with nothing enabled +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[15:8] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with R,W enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION3 ((((PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP1_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +// PMPADDRESS14 = value to be loaded pmpaddr14 to declare lower address of Region-1 +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr14 to declare region1 +// PMPADDRESS15 = value to be loaded pmpaddr15 to declare upper address of Region-1 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare lower address of Region-2 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of Region-2 +#define PMPADDRESS3 RETURN_INSTRUCTION +// PMPADDRESS2 = value to be loaded pmpaddr0 to declare lower address of Region-3 +#define PMPADDRESS0 TEST_FOR_EXECUTION +// PMPADDRESS3 = value to be loaded pmpaddr1 to declare upper address of Region-3 +#define PMPADDRESS1 RETURN_INSTRUCTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg2, x4 // Updated pmpcfg2 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap + LI(x4, PMPREGION3) + // Value to be stored in pmpcfg register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 1*(XLEN/32),4,NOP //Single +.align 3 + +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-X-priority.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-X-priority.S new file mode 100644 index 000000000..17b1128c3 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-X-priority.S @@ -0,0 +1,219 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-TOR-priority-x.S +// Tests the priority by assigning only X permissions to the high priority while R-W-X to low priority region +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf +*/ + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_TOR_priority_x) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP7_CFG_SHIFT 56 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg2 [63:56] value to configure address 0->PMP_region_High in TOR Mode with RWX enabled. This is the low priority region +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP7_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[31:24] value to configure address (RAM_LOCATION_FOR_TEST)->(RETURN_INSTRUCTION). This is the high priority region +// in TOR Mode with R enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP3_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +// PMPADDRESS14 = value to be loaded pmpaddr14 to declare lower address of Region-1 +#define PMPADDRESS14 0x80000000 // value to be loaded pmpaddr14 to declare region1 +// PMPADDRESS15 = value to be loaded pmpaddr15 to declare upper address of Region-1 +#define PMPADDRESS15 PMP_region_High +// PMPADDRESS2 = value to be loaded pmpaddr3 to declare lower address of Region-2 +#define PMPADDRESS2 RAM_LOCATION_FOR_TEST +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare upper address of Region-2 +#define PMPADDRESS3 RETURN_INSTRUCTION + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration + + /* Assigning addresses to PMP address registers */ + LI(x4, PMPADDRESS14) // Value to be stored in pmpaddr14 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr14, x4 // Updated pmpaddr14 + nop // Added nop in case of trap + LA(x4, PMPADDRESS15) // Value to be stored in pmpaddr15 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr15, x4 // Updated pmpaddr15 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1) + // Value to be stored in pmpcfg register + csrs pmpcfg2, x4 // Updated pmpcfg2 + nop // Added nop in case of trap + LI(x4, PMPREGION2) + // Value to be stored in pmpcfg1 register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 0*(XLEN/32),4,NOP +.align 3 + +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END diff --git a/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-X.S b/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-X.S new file mode 100644 index 000000000..c2357734e --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/pmp64-TOR-X.S @@ -0,0 +1,248 @@ +// ----------- +// Copyright (c) 2020. RISC-V International. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// ----------- +// +// This test belongs to the test plan for RISC-V Privilege Arch Compliance developed by 10xEngineers +// which can be found here: https://docs.google.com/spreadsheets/d/1p13gic7BD6aq7n_dHrqti4QmlGpxY7FkF17RVbG4DC0/edit?usp=sharing +/* Test Name: pmp-tor-X.S +// PMP Test in TOR address matching mode +// Description: +=> Foreach mode in MPP (including M), for Load/store instruction, perform the instruction referencing an address where the associated pmpcfg.W=1 and observe an access fault or not. +=> Foreach mode, perform instruction fetches to an address where the associated pmpcfg.X=0 and observe an access fault or not. +=> Foreach mode in MPP (including M), Perform the instruction referencing an address where the associated pmpcfg.R=1 and observe an access fault or not. Do the same for stores where pmpcfg.R=1 and pmpcfg.W=1 to make sure that the R bit only affects loads while W bit only affect store. +=> Do the same for loads where pmpcfg.R=1 and pmpcfg.W=0 to make sure that the W bit only affects stores and AMOs. +*/ +// coverpoint definitions are given in coverage/pmp32_translated_coverpoints.cgf or coverage/pmp32_coverpoint_def_format.cgf + +#include "model_test.h" +#include "arch_test.h" +RVTEST_ISA("RV64I_Zicsr") +# Test code region +.section .text.init +.globl rvtest_entry_point +rvtest_entry_point: +RVMODEL_BOOT +RVTEST_CODE_BEGIN + +#ifdef TEST_CASE_1 + RVTEST_CASE(1,"//check ISA:=regex(.*64.*); check ISA:=regex(.*I.*Zicsr.*); def rvtest_mtrap_routine=True; def rvtest_strap_routine=True; def TEST_CASE_1=True; mac PMP_MACROS; mac PMP_helper_Coverpoints",PMP_TOR_x) +RVTEST_SIGBASE( x13,signature_x13_1) + + .attribute unaligned_access, 0 + .attribute stack_align, 16 + .align 3 + .option norvc +#define PMPCFG0 0x3A0 // Address of pmpcfg0 (HAS BEEN USED WHILE ITERATING THE LOOP) +#define PMPADDR0 0x3B0 // Address of pmpaddr0 (HAS BEEN USED WHILE ITERATING THE LOOP) +/* Define PMP Configuration Fields */ +#define PMP0_CFG_SHIFT 0 +#define PMP1_CFG_SHIFT 8 +#define PMP2_CFG_SHIFT 16 +#define PMP3_CFG_SHIFT 24 +#define PMP4_CFG_SHIFT 32 +#define PMP5_CFG_SHIFT 40 +#define NOP 0x13 +.macro VERIFICATION_RWX ADDRESS + LA(a5, \ADDRESS) // Fetch the address to be checked + LI(a4, NOP) // Load the new value (NOP Instruction ID) + sb a4,0(a5) // Store the new value (NOT TRAP => W enabled) + nop + nop + sh a4,0(a5) // store data + nop + nop + sw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + sd a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + lb a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) //verify that the data is stored successfuly + lh a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + lw a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + ld a4,0(a5) // Load data from it (CHECK FOR READ) ; (NOT TRAP => W enabled) + nop + nop + RVTEST_SIGUPD(x13,a4) + jal \ADDRESS // Test for execution, an instruction is placed at this address + nop + nop +jal \ADDRESS // Test for execution, an instruction is placed at this address + +.endm + +main: +//////////////////////// INITIAL VALUES //////////////////////////////// + LI(a5, -1) // SEtting up All locked bits (including everyother non-zero bit, which is redundent for this test) + LI(x5, 100) // A rondom number, to check if pmp regs get update after lock bit enable + // Loop to SET ALL pmpcfg REGs to zero + .set pmpcfgi, PMPCFG0 // Initialize an iterating variable with the address of pmpcfg0 + .rept 2 // START OF LOOP + + csrw pmpcfgi , x0 // Set all pmpcfg regs to zero (initial value) + .set pmpcfgi, pmpcfgi+2 // increment variable to next pmpcfg reg + .endr // END OF LOOP BODY + // Loop to SET ALL pmpaddr REGs to zero + .set pmpaddri, PMPADDR0 // Initialize an iterating variable with the address of pmpaddr0 + .rept 16 // START OF LOOP + csrw pmpaddri, x0 // Set all pmpaddr regs to zero (initial value) + .set pmpaddri, pmpaddri+1 // increment variable pmpaddri to the next pmpaddr reg + .endr // END OF LOOP BODY + +// pmpcfg0 [7:0] value to configure address 0->RAM_LOCATION_FOR_TEST in TOR Mode with RWX enabled +#define PMPREGION1 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP0_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[23:16] value to configure address (TEST_FOR_EXECUTION)->(RETURN_INSTRUCTION) +// in TOR Mode with RX enabled =========> THIS IS OUR REGION UNDER OBSERVATION. +// THIS REGION CONSISTS OF ONLY ONE INSTRUCTION +#define PMPREGION2 ((((PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP2_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[39:32] value to configure address (RAM_LOCATION_FOR_TEST)->(rvtest_code_end) +// in TOR Mode with RW enabled +// ALSO NOTE THAT PMPREGION2 IS INSIDE THIS REGION, so this test will also check the priority order of PMP regions +#define PMPREGION3 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP4_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// pmpcfg0[47:40] value to configure address (rvtest_code_end)->(PMP_region_High) +// in TOR Mode with RWX enabled +#define PMPREGION4 ((((PMP_R|PMP_W|PMP_X|PMP_L|PMP_TOR)&0xFF) << PMP5_CFG_SHIFT)) +// ------------------------------------------------------------------------------------------------ +// MACROS TO DECLARE THE VALUES TO BE STORED IN PMPADDR registers +#define PMPADDRESS0 RAM_LOCATION_FOR_TEST // value to be loaded pmpaddr0 to declare region1 +// PMPADDRESS1 = value to be loaded pmpaddr1 to declare lower address of region2 +#define PMPADDRESS1 TEST_FOR_EXECUTION +// PMPADDRESS2 = value to be loaded pmpaddr2 to declare upper address of region2 +#define PMPADDRESS2 RETURN_INSTRUCTION +// PMPADDRESS3 = value to be loaded pmpaddr3 to declare lower address of region3 +#define PMPADDRESS3 RAM_LOCATION_FOR_TEST +// PMPADDRESS4 = value to be loaded pmpaddr4 to declare upper address of region3 +#define PMPADDRESS4 rvtest_code_end +// PMPADDRESS5 = value to be loaded pmpaddr5 to declare upper address of region4 +#define PMPADDRESS5 PMP_region_High + + /* SET UP DATA IN THE MEMORY */ + csrw satp, x0 // Disable Address Translation +// PMP Configuration +/* PMP is configure in the following order: +1. Address 0x8000 0000 to Address RAM_LOCATION_FOR_TEST => PMP TOR Region with RWX enabled. This region is the part of the code memory containing our code. For this purpose, pmpaddr0 has been given the value of RAM_LOCATION_FOR_TEST to declare the region from 0->RAM_LOCATION_FOR_TEST into a single PMP region. + +2. Address TEST_FOR_EXECUTION to Address RETURN_INSTRUCTION => PMP region under test. This region has been declared by entering TEST_FOR_EXECUTION into pmpaddr1 and rvtest_code_end into pmpaddr2. Then a PMP region is configure from pmpaddr2(RETURN_INSTRUCTION) to pmpaddr1(TEST_FOR_EXECUTION) into TOR mode by setting pmpcfg0[23:16]=PMPREGION2 + +3. Address RAM_LOCATION_FOR_TEST to Address rvtest_code_end => PMP region under test. This region has been declared by entering rvtest_code_end into pmpaddr4 and RAM_LOCATION_FOR_TEST into pmpaddr3. configure pmpaddr4(RAM_LOCATION_FOR_TEST) to pmpaddr5(rvtest_code_end) into TOR mode by setting pmpcfg1[15:8]=PMPREGION3 + +4. Address rvtest_code_end to address PMP_region_High => PMP TOR Region with RWX enabled. This region is the part of the code memory containing trap handler, epilogs, and other important macro definitions. For this purpose, configure pmpaddr4(rvtest_code_end) to pmpaddr5(PMP_region_High) into TOR mode by setting pmpcfg1[15:8]=PMPREGION4. This PMP Region is mandatory to access signature area in S,U mode */ + /* Assigning addresses to PMP address registers */ + LA(x4, PMPADDRESS0) // Value to be stored in pmpaddr0 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr0, x4 // Updated pmpaddr0 + nop // Added nop in case of trap + LA(x4, PMPADDRESS1) // Value to be stored in pmpaddr1 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr1, x4 // Updated pmpaddr1 + nop // Added nop in case of trap + LA(x4, PMPADDRESS2) // Value to be stored in pmpaddr2 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr2, x4 // Updated pmpaddr2 + nop // Added nop in case of trap + LA(x4, PMPADDRESS3) // Value to be stored in pmpaddr3 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr3, x4 // Updated pmpaddr3 + nop // Added nop in case of trap + LA(x4, PMPADDRESS4) // Value to be stored in pmpaddr4 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr4, x4 // Updated pmpaddr4 + nop // Added nop in case of trap + LA(x4, PMPADDRESS5) // Value to be stored in pmpaddr5 + srl x4, x4, PMP_SHIFT // Shift right by 2 times + csrw pmpaddr5, x4 // Updated pmpaddr5 + nop // Added nop in case of trap + /* Decalring pmp configuration register */ + LI(x4, PMPREGION1 | PMPREGION2 | PMPREGION3 | PMPREGION4) + // Value to be stored in pmpcfg register + csrs pmpcfg0, x4 // Updated pmpcfg0 + nop // Added nop in case of trap +//////////// ALL PMP REGIONS DECLARED ////////////////////////////////////////////// + /* VERIFICATION in M-mode */ + VERIFICATION_RWX TEST_FOR_EXECUTION +// VERIFICATION IN S-Mode + RVTEST_GOTO_LOWER_MODE Smode // SWITCH TO S-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + +/////////////////// Switch back to M-mode //////////////////////////////////////////// + RVTEST_GOTO_MMODE + csrr a4, mstatus // VERIFICATION of M-mode + nop // Added nop in case of trap +// VERIFICATION IN U-Mode + RVTEST_GOTO_LOWER_MODE Umode // SWITCH TO U-mode + VERIFICATION_RWX TEST_FOR_EXECUTION + j exit + +RAM_LOCATION_FOR_TEST: + .fill 3*(XLEN/32),4,0x12345678 +.align 3 + +TEST_FOR_EXECUTION: + addi x9,x9,0x01 // A TEST INSTRUCTION TO TEST THE EXECUTION CHECK ON PMP REGION + nop +RETURN_INSTRUCTION: + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + nop // Added nop in case of trap + jr ra +// AN instruction to bring back PC to the address where TEST_FOR_EXECUTION was called to check for execution. +exit: +#endif + # --------------------------------------------------------------------------------------------- + # HALT +RVTEST_CODE_END +RVMODEL_HALT +RVTEST_DATA_BEGIN +.align 4 + +rvtest_data: +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +.word 0xbabecafe +RVTEST_DATA_END + + +RVMODEL_DATA_BEGIN +rvtest_sig_begin: +sig_begin_canary: +CANARY; +signature_x13_1: + .fill 32*(XLEN/32),4,0xdeadbeef + +#ifdef rvtest_mtrap_routine + +tsig_begin_canary: +CANARY; +mtrap_sigptr: + .fill 128*(XLEN/32),4,0xdeadbeef +tsig_end_canary: +CANARY; + +#endif + +#ifdef rvtest_gpr_save + +gpr_save: + .fill 32*(XLEN/32),4,0xdeadbeef + +#endif + +sig_end_canary: +CANARY; +rvtest_sig_end: +PMP_region_High: +RVMODEL_DATA_END \ No newline at end of file