diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 040b71581..1f4515823 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -29,12 +29,9 @@ - [ ] Ran the new tests on RISCOF with SAIL/Spike as reference model successfully ? - [ ] Ran the new tests on RISCOF in [coverage mode](https://riscof.readthedocs.io/en/stable/commands.html#coverage) - [ ] Link to Google-Drive folder containing the new coverage reports ([See this](https://github.com/riscv-non-isa/riscv-arch-test/blob/main/CONTRIBUTION.md#uploading-test-stats) for more info): < SPECIFY HERE > - - [ ] Link to PR in RISCV-ISAC from which the reports were generated : < SPECIFY HERE > - - [ ] Changelog entry created with a minor patch ### Optional Checklist: - - [ ] RISCV-V CTG PR link if tests were generated using it : < SPECIFY HERE > - [ ] Were the tests hand-written/modified ? - [ ] Have you run these on any hard DUT model ? Please specify name and provide link if possible in the description - [ ] If you have modified arch\_test.h Please provide a detailed description of the changes in the Description section above. diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index b3dcca29f..d5e9fb7e4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -27,8 +27,8 @@ jobs: ACT-sail-spike: name: ACT-sail-spike (RV${{ matrix.xlen }}) runs-on: ubuntu-22.04 - # Set a 15-minute time limit for this job - timeout-minutes: 30 + # Set a 60-minute time limit for this job + timeout-minutes: 60 strategy: fail-fast: false matrix: @@ -137,30 +137,40 @@ jobs: cd riscof-plugins/rv${{ matrix.xlen }} riscof run --config config.ini --suite ../../riscv-test-suite/rv${{ matrix.xlen }}i_m/ --env ../../riscv-test-suite/env - - - name: Check size of riscof_work folder + #Check the existance of the riscof work folder, and add the PATH to environment variable + - name: Check size and determine upload path + if: always() id: check_size run: | - folder_size=$(du -sm /home/runner/work/riscv-arch-test/riscv-arch-test/riscof-plugins/rv${{ matrix.xlen }}/riscof_work | cut -f1) - echo "Folder size: ${folder_size} MB" - if [ "$folder_size" -gt 1000 ]; then - echo "Size exceeds 1 GB. Skipping upload." - echo "upload=false" >> $GITHUB_ENV # Set an environment variable to skip upload + work_folder="${{ github.workspace }}/riscof-plugins/rv${{ matrix.xlen }}/riscof_work/" + report_file="$work_folder/report.html" + if [ -d "$work_folder" ]; then + folder_size=$(du -sm "$work_folder" | cut -f1) + echo "Folder size: ${folder_size} MB" + if [ "$folder_size" -gt 1000 ]; then + echo "Size exceeds 1 GB. Checking if report exists." + if [ -f "$report_file" ]; then + echo "Uploading RISCOF generated report only." + echo "upload_path=$report_file" >> $GITHUB_ENV + else + echo "No report found. Skipping upload." + echo "upload_path=" >> $GITHUB_ENV + fi + else + echo "Size is within limit. Uploading complete RISCOF_WORK Folder." + echo "upload_path=$work_folder" >> $GITHUB_ENV + fi else - echo "Size is within limit. Proceeding with upload." - echo "upload=true" >> $GITHUB_ENV # Set an environment variable to proceed with upload + echo "Folder does not exist. Skipping upload." + echo "upload_path=" >> $GITHUB_ENV fi - # Upload the riscof_work for rv${{ matrix.xlen }} folder if size check passes - - name: Upload the riscof_work for rv${{ matrix.xlen }} folder - # Proceed with upload only if the size is within limit - if: ${{ env.upload == 'true' }} + # Upload the appropriate artifact (folder or report) and skip in case not exists + - name: Upload riscof artifact for rv${{ matrix.xlen }} + if: always() && env.upload_path != '' uses: actions/upload-artifact@v4 with: - name: riscof-test-report-rv${{ matrix.xlen }} - path: /home/runner/work/riscv-arch-test/riscv-arch-test/riscof-plugins/rv${{ matrix.xlen }}/riscof_work/ - if-no-files-found: warn - retention-days: 3 + name: riscof-artifact-rv${{ matrix.xlen }} + path: ${{ env.upload_path }} compression-level: 6 - overwrite: true - include-hidden-files: false \ No newline at end of file + overwrite: true \ No newline at end of file diff --git a/.gitignore b/.gitignore index 3203a4378..2d37bc349 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,9 @@ *.DS_Store riscv-target/ + +#ignore venv +riscv-isac/riscv-env + +__pycache__ +riscof_work diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a31a62d5..97be2378f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # CHANGELOG +## [3.10.0] - 2024-11-04 +- Add support for Zvk* extensions +- Split float and double test cases into smaller ones +- Merged riscv-ctg and riscv-isac into riscv-arch-test, and updated README +- Updates crypto scalar instructions +- Physical Memory Protection (32/64) Tests and Covergroups +- CI updates: and updated Sail and Spike in CI +- Bug fixes + + ## [3.9.1] - 2024-07-01 - Converted one of the CANARY words to a delta instret count (there is a variable that will enable that) - Converted CODE/DATA/SIG_BEGIN/END to include all the little incidental code, so the tests template improves 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/requirements.txt b/requirements.txt old mode 100644 new mode 100755 index 8961b1b99..40b8fe2b0 --- a/requirements.txt +++ b/requirements.txt @@ -34,7 +34,7 @@ PyYAML>=5.1.1 requests>=2.22.0 restructuredtext-lint>=1.3.0 riscv_isac>=0.14.0 -ruamel.yaml>=0.16.0 +ruamel.yaml>=0.18.0 six>=1.12.0 smmap2>=2.0.5 snowballstemmer>=1.2.1 diff --git a/riscof-plugins/rv32/sail_cSim/__pycache__/riscof_sail_cSim.cpython-310.pyc b/riscof-plugins/rv32/sail_cSim/__pycache__/riscof_sail_cSim.cpython-310.pyc deleted file mode 100644 index eb7e0f53f..000000000 Binary files a/riscof-plugins/rv32/sail_cSim/__pycache__/riscof_sail_cSim.cpython-310.pyc and /dev/null differ diff --git a/riscof-plugins/rv32/spike_simple/__pycache__/riscof_spike_simple.cpython-310.pyc b/riscof-plugins/rv32/spike_simple/__pycache__/riscof_spike_simple.cpython-310.pyc deleted file mode 100644 index f4d1ac5c7..000000000 Binary files a/riscof-plugins/rv32/spike_simple/__pycache__/riscof_spike_simple.cpython-310.pyc and /dev/null differ 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-ctg/riscv_ctg/cross_comb.py b/riscv-ctg/riscv_ctg/cross_comb.py index 25112a264..e5a69ae77 100644 --- a/riscv-ctg/riscv_ctg/cross_comb.py +++ b/riscv-ctg/riscv_ctg/cross_comb.py @@ -102,7 +102,7 @@ def __init__(self, base_isa_str, xlen_in, randomize, label): global base_isa # Template dictionary - self.OP_TEMPLATE = utils.load_yamls(const.template_files) + self.OP_TEMPLATE = utils.load_yaml(const.template_files) xlen = xlen_in base_isa = base_isa_str diff --git a/riscv-ctg/riscv_ctg/ctg.py b/riscv-ctg/riscv_ctg/ctg.py index ea9fadf8f..b69ea8007 100644 --- a/riscv-ctg/riscv_ctg/ctg.py +++ b/riscv-ctg/riscv_ctg/ctg.py @@ -131,7 +131,7 @@ def ctg(verbose, out, random ,xlen_arg,flen_arg, cgf_file,num_procs,base_isa, ma const.template_files.remove([fd for fd in const.template_files if "fd.yaml" in fd][0]) else: const.template_files.remove([fd for fd in const.template_files if "inx.yaml" in fd][0]) - op_template = utils.load_yamls(const.template_files) + op_template = utils.load_yaml(const.template_files) cgf = expand_cgf(cgf_file,xlen,flen) pool = mp.Pool(num_procs) results = pool.starmap(create_test, [(usage_str, node,label,base_isa,max_inst, op_template, diff --git a/riscv-ctg/riscv_ctg/utils.py b/riscv-ctg/riscv_ctg/utils.py index d3dd53127..2dfcdb525 100644 --- a/riscv-ctg/riscv_ctg/utils.py +++ b/riscv-ctg/riscv_ctg/utils.py @@ -17,7 +17,13 @@ yaml.allow_unicode = True def load_yaml(foo): + """ + Loads the template file or file list and returns the data in a dictionary. + """ try: + if isinstance(foo, list): + with combineReader(foo) as fp: + return dict(yaml.load(fp)) with open(foo, "r") as file: return dict(yaml.load(file)) except ruamel.yaml.constructor.DuplicateKeyError as msg: @@ -33,7 +39,7 @@ def gen_format_data(): - ISA - Mnemonics ''' - op_template = load_yaml(const.template_file) + op_template = load_yaml(const.template_files) # Initialize nested dictionary nested_dict = lambda: defaultdict(nested_dict) @@ -60,9 +66,6 @@ def get_instr_list(): return instr_lst -def load_yamls(foo): - with combineReader(foo) as fp: - return dict(yaml.load(fp)) class makeUtil(): """ diff --git a/riscv-isac/docs/source/cgf.rst b/riscv-isac/docs/source/cgf.rst index 07d745143..ef6c8a5c8 100644 --- a/riscv-isac/docs/source/cgf.rst +++ b/riscv-isac/docs/source/cgf.rst @@ -647,6 +647,8 @@ syntax for the Translator: Operations can be performed on the *number_placeholder_index* to get the required value. Consider another example: + .. tip:: Use the modulus operator represented by % in python if you want to traverse over the length of the list !!! + .. code-block:: python csr_comb: diff --git a/riscv-isac/riscv_isac/InstructionObject.py b/riscv-isac/riscv_isac/InstructionObject.py index 08a10601e..ad4971dbb 100644 --- a/riscv-isac/riscv_isac/InstructionObject.py +++ b/riscv-isac/riscv_isac/InstructionObject.py @@ -186,6 +186,18 @@ def evaluate_instr_vars(self, xlen, flen, arch_state, csr_regfile, instr_vars): imm_val = instr_vars.get('imm_val', None) + #update the variable for the length of the load or store: + if self.instr_name in ['ld','lw','lb','lh','sd','sw','sb','sh']: + if self.instr_name in ['ld','sd']: + instr_vars['access_len'] = 8 + if self.instr_name in ['lw','sw']: + instr_vars['access_len'] = 4 + if self.instr_name in ['lh','sh']: + instr_vars['access_len'] = 2 + if self.instr_name in ['lb','sb']: + instr_vars['access_len'] = 1 + else: + instr_vars['access_len'] = None #Update the values for the trap registers self.trap_registers_update(instr_vars,self.trap_dict) @@ -487,21 +499,24 @@ def trap_registers_update(self, instr_vars, trap_dict): instr_vars['mtval'] = trap_dict['tval'] #only update on the initialization if "scause" not in instr_vars: - instr_vars['scause'] = '0' - instr_vars['stval'] = '0' + instr_vars['scause'] = None + instr_vars['stval'] = None elif trap_dict["mode_change"].split()[2] == "S": instr_vars['scause'] = trap_dict['exc_num'] instr_vars['stval'] = trap_dict['tval'] #only update on the initialization if "mcause" not in instr_vars: - instr_vars['mcause'] = '0' - instr_vars['mtval'] = '0' + instr_vars['mcause'] = None + instr_vars['mtval'] = None + else: - instr_vars['mcause'] = '0' - instr_vars['mtval'] = '0' - instr_vars['scause'] = '0' - instr_vars['stval'] = '0' + #initialize them to None for the first time in the instr_vars + #reset them to None in case the mode change is ret + instr_vars['mcause'] = None + instr_vars['mtval'] = None + instr_vars['scause'] = None + instr_vars['stval'] = None return None diff --git a/riscv-isac/riscv_isac/coverage.py b/riscv-isac/riscv_isac/coverage.py index 9d01af5b0..b906473de 100644 --- a/riscv-isac/riscv_isac/coverage.py +++ b/riscv-isac/riscv_isac/coverage.py @@ -159,14 +159,17 @@ 940: 'pmpcfg12', 941: 'pmpcfg13', 942: 'pmpcfg14', - 943: 'pmpcfg15' + 943: 'pmpcfg15', + 266: 'senvcfg', + 778: 'menvcfg', + 1863: 'mseccfg' } 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 @@ -571,7 +574,10 @@ def __init__ (self, xlen): "vxsat": int('009',16), "fflags":int('1',16), "frm":int('2',16), - "fcsr":int('3',16) + "fcsr":int('3',16), + "menvcfg":int('30A', 16), + "senvcfg":int('10A', 16), + "mseccfg":int('747', 16) } for i in range(16): self.csr_regs["pmpaddr"+str(i)] = int('3B0',16)+i @@ -687,9 +693,9 @@ def __add__(self, o): return temp -def pretty_print_yaml(yaml): +def pretty_print_yaml(yaml_obj): res = '''''' - for line in ruamel.yaml.round_trip_dump(yaml, indent=5, block_seq_indent=3).splitlines(True): + for line in utils.dump_yaml(yaml_obj, indent=5, block_seq_indent=3).splitlines(True): res += line return res @@ -951,7 +957,10 @@ def compute_per_line(queue, event, cgf_queue, stats_queue, cgf, xlen, flen, addr #csr regfile track for the previous instruction(old_csr_regfile) old_csr_regfile = {} for i in csr_regfile.csr_regs: - old_csr_regfile[i] = int(csr_regfile[i],16) + if isinstance(csr_regfile[i], str): + old_csr_regfile[i] = int(csr_regfile[i],16) + else: + old_csr_regfile[i] = csr_regfile[i] def old_fn_csr_comb_covpt(csr_reg): return old_csr_regfile[csr_reg] @@ -961,11 +970,11 @@ def old_fn_csr_comb_covpt(csr_reg): instr.evaluate_instr_vars(xlen, flen, arch_state, csr_regfile, instr_vars) #update the state of trap registers in csr_reg file using instr_vars - if instr_vars["mode_change"] is not None: #change the state only on the instruction - csr_regfile["mcause"] = instr_vars["mcause"] - csr_regfile["scause"] = instr_vars["scause"] - csr_regfile["mtval"] = instr_vars["mtval"] - csr_regfile["stval"] = instr_vars["stval"] + # if instr_vars["mode_change"] is not None: #change the state only on the instruction + csr_regfile["mcause"] = instr_vars["mcause"] + csr_regfile["scause"] = instr_vars["scause"] + csr_regfile["mtval"] = instr_vars["mtval"] + csr_regfile["stval"] = instr_vars["stval"] if 'rs1' in instr_vars: rs1 = instr_vars['rs1'] @@ -980,8 +989,10 @@ def old_fn_csr_comb_covpt(csr_reg): is_rd_valid = False for i in csr_regfile.csr_regs: - instr_vars[i] = int(csr_regfile[i],16) - + if isinstance(csr_regfile[i], str): + instr_vars[i] = int(csr_regfile[i],16) + else: + instr_vars[i] = csr_regfile[i] instr.iptw_update(instr_vars, iptw_dict) instr.ptw_update(instr_vars) @@ -1026,32 +1037,30 @@ def get_pte(pa, pte_addr, pgtb_addr): else: return None - def get_pte_prop(prop_name,pa, pte_addr, pgtb_addr): - pte_per = get_pte(pa, pte_addr, pgtb_addr) - if pte_per is not None: - pte_per = get_pte(pa, pte_addr, pgtb_addr) & 0x3FF - prop_name_lower = prop_name.lower() - if prop_name_lower == 'v' and (pte_per & 0x01 != 0): - return 1 - elif prop_name_lower == 'r' and (pte_per & 0x02 != 0): - return 1 - elif prop_name_lower == 'w' and (pte_per & 0x04 != 0): - return 1 - elif prop_name_lower == 'x' and (pte_per & 0x08 != 0): - return 1 - elif prop_name_lower == 'u' and (pte_per & 0x10 != 0): - return 1 - elif prop_name_lower == 'g' and (pte_per & 0x20 != 0): - return 1 - elif prop_name_lower == 'a' and (pte_per & 0x40 != 0): - return 1 - elif prop_name_lower == 'd' and (pte_per & 0x80 != 0): - return 1 - else: - return 0 - + def get_pte_prop(prop_name, pte_addr): + ''' + Function to return whether a specific Permission is given to the PTE or not + :param prop_name: an input property ., example: 'U' for U bit or 'RWX' for a combination of bits + :param pte_addr: PTE address for which we want to get the information + + :type prop_name: str + :type pte_addr: hex/int + + :return: 1 or 0 depending whether the specific (or combination of) permission/s is set or not respectively. + ''' + bitmask_dict = {'v': 0x01, 'r': 0x02, 'w': 0x04, 'x': 0x08, 'u': 0x10, 'g': 0x20, 'a': 0x40, 'd': 0x80} + + if pte_addr is not None: + # Get the permissions bit out of the pte_addr + pte_per = pte_addr & 0x3FF + + # Check each character in prop_name + for char in prop_name.lower(): + if char in bitmask_dict and (pte_per & bitmask_dict[char] == 0): + return 0 + return 1 else: - return None + return 0 globals()['get_addr'] = check_label_address globals()['get_mem_val'] = get_mem_val @@ -1059,7 +1068,6 @@ def get_pte_prop(prop_name,pa, pte_addr, pgtb_addr): globals()['get_pte_prop'] = get_pte_prop if enable : - print(instr_vars) ucovpt = [] covpt = [] csr_covpt = [] @@ -1136,7 +1144,6 @@ def get_pte_prop(prop_name,pa, pte_addr, pgtb_addr): value['rs3'][rs3] += 1 if 'op_comb' in value and len(value['op_comb']) != 0 : - for coverpoints in value['op_comb']: if eval(coverpoints, globals(), instr_vars): if cgf[cov_labels]['op_comb'][coverpoints] == 0: @@ -1150,10 +1157,10 @@ def get_pte_prop(prop_name,pa, pte_addr, pgtb_addr): lcls={} if instr.is_rvp and "rs1" in value: op_width = 64 if instr.rs1_nregs == 2 else xlen - simd_val_unpack(value['val_comb'], op_width, "rs1", rs1_val, lcls) + simd_val_unpack(value['val_comb'], op_width, "rs1", instr_vars['rs1_val'], lcls) if instr.is_rvp and "rs2" in value: op_width = 64 if instr.rs2_nregs == 2 else xlen - simd_val_unpack(value['val_comb'], op_width, "rs2", rs2_val, lcls) + simd_val_unpack(value['val_comb'], op_width, "rs2", instr_vars['rs2_val'], lcls) instr_vars.update(lcls) for coverpoints in value['val_comb']: if eval(coverpoints, globals(), instr_vars): @@ -1517,7 +1524,7 @@ def compute(trace_file, test_name, cgf, parser_name, decoder_name, detailed, xle if dump is not None: dump_f = open(dump, 'w') - dump_f.write(ruamel.yaml.round_trip_dump(cgf, indent=5, block_seq_indent=3)) + dump_f.write(utils.dump_yaml(cgf, indent=5, block_seq_indent=3)) dump_f.close() sys.exit(0) @@ -1536,7 +1543,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 @@ -1679,7 +1686,7 @@ def compute(trace_file, test_name, cgf, parser_name, decoder_name, detailed, xle rpt_str = gen_report(rcgf, detailed) logger.info('Writing out updated cgf : ' + test_name + '.cgf') dump_file = open(test_name+'.cgf', 'w') - dump_file.write(ruamel.yaml.round_trip_dump(rcgf, indent=5, block_seq_indent=3)) + dump_file.write(utils.dump_yaml(rcgf, indent=5, block_seq_indent=3)) dump_file.close() if sig_addrs: 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-isac/riscv_isac/plugins/c_sail.py b/riscv-isac/riscv_isac/plugins/c_sail.py index a45f83842..981efc2ab 100644 --- a/riscv-isac/riscv_isac/plugins/c_sail.py +++ b/riscv-isac/riscv_isac/plugins/c_sail.py @@ -20,6 +20,7 @@ def setup(self, trace, arch): instr_pattern_c_sail_csr_reg_val = re.compile('(?PCSR|clint::tick)\s(?P[a-z0-9]+)\s<-\s(?P[0-9xABCDEF]+)(?:\s\(input:\s(?P[0-9xABCDEF]+)\))?') instr_pattern_c_sail_mem_val = re.compile('mem\[(?P[0-9xABCDEF]+)\]\s<-\s(?P[0-9xABCDEF]+)') instr_pattern_c_sail_trap = re.compile(r'trapping\sfrom\s(?P\w+\sto\s\w+)\sto\shandle\s(?P\w+.*)\shandling\sexc#(?P0x[0-9a-fA-F]+)\sat\spriv\s\w\swith\stval\s(?P0x[0-9a-fA-F]+)') + instr_pattern_c_sail_ret = re.compile(r'ret-ing\sfrom\s(?P\w+\sto\s\w+)') def extractInstruction(self, line): instr_pattern = self.instr_pattern_c_sail re_search = instr_pattern.search(line) @@ -60,6 +61,13 @@ def extractVirtualMemory(self, line): mem_r_pattern = re.compile(r'mem\[R,([0-9xABCDEF]+)\] -> 0x([0-9xABCDEF]+)') mem_x_pattern = re.compile(r'mem\[X,([0-9xABCDEF]+)\] -> 0x([0-9xABCDEF]+)') mem_depa_pattern = re.compile(r'mem\[([0-9xABCDEF]+)\]') + instr_trap_pattern = self.instr_pattern_c_sail_trap.search(line) + + #in case of a trap + if instr_trap_pattern: + trap = 1 + else: + trap = 0 match_search_mnemonic = self.instr_pattern_c_sail.search(line) depa, ieva, ieva_align, depa_align, iepa, iepa_align = None, None, None, None, None, None @@ -78,14 +86,19 @@ def extractVirtualMemory(self, line): iptw_list=(mem_r_pattern.findall(line_upper_part)) dptw_list=(mem_r_pattern.findall(line_lower_part)) + #Update the data physical address only when there is no trap else it will not be present in the log. if dptw_list is not None: - if "lw" in match_search_mnemonic.group('mnemonic') and dptw_list: - depa_list=dptw_list.pop() - depa=int(depa_list[0],16) - else: - depa_list=mem_depa_pattern.findall(line_lower_part) - if len(depa_list) != 0: + if trap == 0: + #Since, the load has the same pattern as the page table walk, skip the last one as it is a false positive. + loads_exception_list = {"lw", "ld", "lh", "lb", "lr.w", "lr.d", "lbu", "lhu", "lwu", "c.lw", "c.ld", "c.lwsp", "c.ldsp", "flw", "fld"} + if match_search_mnemonic.group('mnemonic').split()[0] in loads_exception_list and dptw_list: + depa_list=dptw_list.pop() depa=int(depa_list[0],16) + #Stores and other page table walks are normal + else: + depa_list=mem_depa_pattern.findall(line_lower_part) + if len(depa_list) != 0: + depa=int(depa_list[0],16) ieva_align = 1 if ieva is not None and ieva & 0b11 == 0 else 0 iepa_align = 1 if iepa is not None and iepa & 0b11 == 0 else 0 @@ -114,6 +127,8 @@ def extracttrapvals(self, line): instr_trap_pattern = self.instr_pattern_c_sail_trap.search(line) trap_dict = {"mode_change": None, "call_type": None, "exc_num": None, "tval": None} + #ret will tell us to delete the previous state of the cause registers + instr_ret_pattern = self.instr_pattern_c_sail_ret.search(line) if instr_trap_pattern: trap_dict["mode_change"] = instr_trap_pattern.group("mode_change") trap_dict["call_type"] = instr_trap_pattern.group("call_type") @@ -121,8 +136,13 @@ def extracttrapvals(self, line): trap_dict["tval"] = instr_trap_pattern.group("tval") self.old_trap_dict = trap_dict - #maintain the value if None - if instr_trap_pattern is None: + elif instr_ret_pattern: + #if ret_signal is 1 then clear the values of the mode_change, call_type, exc_num, tval + trap_dict = {"mode_change": None, "call_type": None, "exc_num": None, "tval": None} + self.old_trap_dict = trap_dict + + #maintain the values if None unit the new trap appears + if instr_trap_pattern is None or instr_ret_pattern is None: trap_dict = self.old_trap_dict return trap_dict diff --git a/riscv-isac/riscv_isac/plugins/translator_cgf.py b/riscv-isac/riscv_isac/plugins/translator_cgf.py index 1f10aa04d..b70e91a09 100644 --- a/riscv-isac/riscv_isac/plugins/translator_cgf.py +++ b/riscv-isac/riscv_isac/plugins/translator_cgf.py @@ -27,10 +27,12 @@ def __init__(self): self.macro_brace_resolver = re.compile(r'(\%\d+)') # self.repeat_brace_index = re.compile(r'(\*\d+)') self.list_brace_finder = re.compile(r'\{([^}]*)\}\{(\[[^\]]+\])\}') + self.list_with_index_finder = re.compile(r'\{(?:\s*\$\{[\w\d]+\}\s*,?)*\}\{\[\$[\w\d]+\]\}') self.list_index_brace_finder = re.compile(r'(\{\[.*?\]\})') self.list_index_number_finder = re.compile(r'(\<\<[^>]*\>\>\{\[[^\]]+\]\})') + self.temp_replacement_finder = re.compile(r'<>') self.placeholder_pattern = re.compile(r'<>|<>|<>|<>') - self.resolve_back_order = re.compile(r'<>|<>|<>') + self.resolve_back_order = re.compile(r'<>|<>|<>|<>') def translate_using_path(self, input_path, output_path): """Translate YAML data from the input file and dump it into the output file. @@ -173,11 +175,26 @@ def replace_macros(self, instr): Returns: str: The instruction string with macros replaced. """ + #Don't resolve the macros inside the list as they are difficult to replace back + list_with_index = self.list_with_index_finder.findall(instr) + if len(list_with_index) != 0: + for index, values in enumerate(list_with_index): + instr = instr.replace(values, f'<>') + + #Find the other macros inside the instr macros = self.macro_def_finder.findall(instr) macro_dict = {macro: f'<>' for index, macro in enumerate(macros)} instr, replacements = self.replace_using_dict(instr, macro_dict) self.replacement_dict.update(replacements) + + #replace the Temp replacement back with the actual list + temp_replacement_finds = self.temp_replacement_finder.findall(instr) + + if len(temp_replacement_finds) != 0: + for index, values in enumerate(list_with_index): + instr = instr.replace(f'<>', values) + return instr def replace_multibraces(self, instr): @@ -264,8 +281,19 @@ def replace_list_braces(self, instr): Returns: str: The instruction string with list braces and their contents replaced. """ - list_braces = self.list_brace_finder.findall(instr) + #This pattern includes all the normal pattern inside the list + list_braces_pattern_anything = self.list_brace_finder.findall(instr) + #This pattern checks the all macros pattern inside the list + list_macros_braces_pattern = re.compile(r'\{((?:\s*\$\{[\w\d]+\}\s*,?)*)\}\{(\[\$[\w\d]+\])\}') + list_braces_pattern_macros = list_macros_braces_pattern.findall(instr) + + if len(list_braces_pattern_anything) != 0: + list_braces = list_braces_pattern_anything + else: + list_braces = list_braces_pattern_macros + replacements = {} + for index, brace in enumerate(list_braces): brace_content, brace_index = brace[0], brace[1] @@ -278,7 +306,7 @@ def replace_list_braces(self, instr): # Update the replacement dictionary self.replacement_dict.update(replacements) - + # print("instr after list", instr) return instr @@ -419,12 +447,7 @@ def resolve_lists(self, instr_lst, replacement_dict, place_holder_pattern): for index, (key, val) in enumerate(replacement_dict.items()): if "LIST" in key: - try: - req_element_list.append(val[resolved_list_index[index]]) - except IndexError as e: - logging.error(f"Error: list index out of range. The index {resolved_list_index[index - 1]} is out of the size of the list {val} whose length is {len(val)}") - break - + req_element_list.append(val[resolved_list_index[0]]) #Replace the list index with No space for index, val in enumerate(req_element_list): if list_index_matches[index] in instr: @@ -433,8 +456,8 @@ def resolve_lists(self, instr_lst, replacement_dict, place_holder_pattern): temp_element_dict = {} for index, (key, val) in enumerate(replacement_dict.items()): if "LIST" in key: - temp_element_dict[key] = req_element_list[index] - instr = instr.replace(key, req_element_list[index]) + temp_element_dict[key] = req_element_list[0] + instr = instr.replace(key, req_element_list[0]) for (key, val) in replacement_dict.items(): if "NUMBER" in key: @@ -463,9 +486,15 @@ def loop_controller(self, instr, replacement_dict, place_holder_pattern): final_cov_list.append(instr) else: for curr_resolve in placeholders: + #create a req_fn_list which will help in resolving the Number placeholder req_fn_list = [placeholders[current_cov_track]] + #always include MULTI_INTER as it is not explicitly present in the instr + for value in place_holder_pattern: + if "MULTI_INTER" in value: + req_fn_list.append(value) temp_gen_cov_list = [] + #This will generate required number of coverpoints using the current instructions for instr in gen_cov_list: curr_generated_cov_list = self.calculate_coverpoints(instr, replacement_dict, place_holder_pattern, req_fn_list) temp_gen_cov_list.extend(curr_generated_cov_list) @@ -537,7 +566,7 @@ def generate_current_cov(self, instr, track_dict, replacement_dict, place_holder Returns: str: The generated coverpoint. """ - + number_pattern = re.compile(r'\d+') for key, val in replacement_dict.items(): @@ -570,18 +599,27 @@ def generate_current_cov(self, instr, track_dict, replacement_dict, place_holder list_index_pattern = self.list_index_number_finder.findall(instr) result = int(number_pattern.findall(val)[0]) -1 var = place_holder_pattern[result] - curr_index = track_dict[var][2] - - for index, val in enumerate(list_index_pattern): - internal_list__index_pattern = internal_list_index_number_finder.findall(val) - if key in internal_list__index_pattern[0][1]: - req_val = f"<<{internal_list__index_pattern[0][0]}>>{{[{curr_index}{internal_list__index_pattern[0][1].replace(key, '')}]}}" - instr = instr.replace(list_index_pattern[index], req_val) - if "MULTI_INTER" in var and "MULTI" in req_fn_list[0]: - instr = instr.replace(key, str(replacement_dict[var][curr_index])) - if req_fn_list[0] in var: - instr = instr.replace(key, str(replacement_dict[var][curr_index])) + #only replace the NUMBER Placeholder when we have the required Structure + if var in req_fn_list: + curr_index = track_dict[var][2] + multi_index_repeat_for_list = replacement_dict[var].count(replacement_dict[var][curr_index]) + multi_index_for_list = math.floor((replacement_dict[var].index(replacement_dict[var][curr_index]))/multi_index_repeat_for_list) + #replace the number placeholder in the List with the required index + for index, val in enumerate(list_index_pattern): + internal_list__index_pattern = internal_list_index_number_finder.findall(val) + if key in internal_list__index_pattern[0][1]: + if "MULTI" in var: + temp_index = multi_index_for_list + else: + temp_index = curr_index + req_val = f'<<{internal_list__index_pattern[0][0]}>>{{[{temp_index}{internal_list__index_pattern[0][1].replace(key, "")}]}}' + instr = instr.replace(list_index_pattern[index], req_val) + + if "MULTI_INTER" in var and "MULTI" in req_fn_list[0]: + instr = instr.replace(key, str(replacement_dict[var][curr_index])) + if req_fn_list[0] in var: + instr = instr.replace(key, str(replacement_dict[var][curr_index])) # Resolve back the macros for key, val in replacement_dict.items(): @@ -728,7 +766,11 @@ def list_index_resolver(self, list_indices): result_list = [] for list_index in list_indices: value_inside_index = values_finder.findall(list_index) - resolved_val = math.floor(eval(value_inside_index[0])) + macro_def_find = self.macro_def_finder.findall(value_inside_index[0]) + if macro_def_find: + resolved_val = value_inside_index[0] + else: + resolved_val = math.floor(eval(value_inside_index[0])) result_list.append(resolved_val) return result_list @@ -743,7 +785,7 @@ def Translate_cgf(input_cgf): # if __name__ == "__main__": -# defs_path = '/home/hammad/wrapper_cgf/Wrapper-cgf/config.defs' -# cgf_path = '/home/hammad/wrapper_cgf/Wrapper-cgf/output.cgf' +# defs_path = '/home/input_cgf_file.cgf' +# cgf_path = '/home/output.cgf' # trans = Translator() # trans.translate_using_path(defs_path, cgf_path) \ No newline at end of file diff --git a/riscv-isac/riscv_isac/utils.py b/riscv-isac/riscv_isac/utils.py index 200a6267e..bfa652954 100644 --- a/riscv-isac/riscv_isac/utils.py +++ b/riscv-isac/riscv_isac/utils.py @@ -1,6 +1,7 @@ # See LICENSE.incore for details """Common Utils """ +import io import sys import os import subprocess @@ -13,17 +14,21 @@ import yaml as pyyaml from elftools.elf.elffile import ELFFile -yaml = YAML(typ="rt") -yaml.default_flow_style = False -yaml.explicit_start = True -yaml.allow_unicode = True -yaml.allow_duplicate_keys = False +def create_yaml(typ="rt", indent=None, block_seq_indent=None): + yaml = YAML(typ=typ) + yaml.default_flow_style = False + yaml.explicit_start = True + yaml.allow_unicode = True + yaml.allow_duplicate_keys = False + if indent is not None: + yaml.indent = indent + if block_seq_indent is not None: + yaml.block_seq_indent = block_seq_indent + return yaml -safe_yaml = YAML(typ="safe") -safe_yaml.default_flow_style = False -safe_yaml.explicit_start = True -safe_yaml.allow_unicode = True -safe_yaml.allow_duplicate_keys = False +yaml = create_yaml() + +safe_yaml = create_yaml(typ="safe") def collect_label_address(elf, label): with open(elf, 'rb') as f: @@ -47,8 +52,27 @@ def get_value_at_location(elf_path, location, bytes): return int.from_bytes(value, byteorder='little', signed=False) return None -def dump_yaml(foo, outfile): - yaml.dump(foo, outfile) +def dump_yaml(foo, outfile=None, indent=None, block_seq_indent=None): + """ + Dump yaml to outfile. If outfile is None, dump to string. If indent or + block_seq_indent is set, create a new yaml object with such config. + """ + # Create a default yaml object if no custom settings are provided + yaml = create_yaml() if indent is None and block_seq_indent is None else create_yaml(indent=indent, block_seq_indent=block_seq_indent) + + if outfile is None: + buf = io.StringIO() + yaml.dump(foo, buf) + return buf.getvalue() + return yaml.dump(foo, outfile) + +def create_yaml(indent=None, block_seq_indent=None): + yaml = ruamel.yaml.YAML() + if indent is not None: + yaml.indent = indent + if block_seq_indent is not None: + yaml.block_seq_indent = block_seq_indent + return yaml def load_yaml_file(foo): try: diff --git a/riscv-test-suite/env/test_macros.h b/riscv-test-suite/env/test_macros.h index 0b5cca2ec..4ed2bc010 100644 --- a/riscv-test-suite/env/test_macros.h +++ b/riscv-test-suite/env/test_macros.h @@ -888,13 +888,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/Zvk/src/vsha2ms-e32.vv-01.S b/riscv-test-suite/rv32i_m/Zvk/src/vsha2ms-e32.vv-01.S index 69eb7d71e..5f79acf7e 100644 --- a/riscv-test-suite/rv32i_m/Zvk/src/vsha2ms-e32.vv-01.S +++ b/riscv-test-suite/rv32i_m/Zvk/src/vsha2ms-e32.vv-01.S @@ -70,7 +70,7 @@ TEST_CASE_WVV(4, 32, VINST, v15, 2*4, v14, 3*4, v18, 8*4) //sig[116*4] inst_8: -TEST_CASE_WVV(4, 32, VINST, v16, 0*4, v17, 4*4, v16, 0*4) +TEST_CASE_WVV(4, 32, VINST, v18, 0*4, v17, 4*4, v16, 0*4) //sig[120*4] inst_9: diff --git a/riscv-test-suite/rv32i_m/pmp32/src/pmp-CFG-reg.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-CFG-reg.S new file mode 100644 index 000000000..4d374826c --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-CSR-access.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-CSR-access.S new file mode 100644 index 000000000..f72f92ab0 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-NA4-R-priority-level-2.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-NA4-R-priority-level-2.S new file mode 100644 index 000000000..b89d009b6 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-NA4-R-priority.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-NA4-R-priority.S new file mode 100644 index 000000000..7bf071761 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-NA4-R.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-NA4-R.S new file mode 100644 index 000000000..79e9b746e --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-NA4-RW-priority-level-2.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-NA4-RW-priority-level-2.S new file mode 100644 index 000000000..6b9b829af --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-NA4-RW-priority.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-NA4-RW-priority.S new file mode 100644 index 000000000..9f54cbae0 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-NA4-RW.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-NA4-RW.S new file mode 100644 index 000000000..eb9aae7b7 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-NA4-RWX.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-NA4-RWX.S new file mode 100644 index 000000000..49e92599f --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-NA4-RX-priority-level-2.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-NA4-RX-priority-level-2.S new file mode 100644 index 000000000..e698951ea --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-NA4-RX-priority.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-NA4-RX-priority.S new file mode 100644 index 000000000..6dccb401e --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-NA4-RX.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-NA4-RX.S new file mode 100644 index 000000000..688faee1d --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-NA4-X-priority-level-2.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-NA4-X-priority-level-2.S new file mode 100644 index 000000000..4d75a48d2 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-NA4-X-priority.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-NA4-X-priority.S new file mode 100644 index 000000000..f01c135b8 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-NA4-X.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-NA4-X.S new file mode 100644 index 000000000..c54defce5 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-NAPOT-R-priority-level-2.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-NAPOT-R-priority-level-2.S new file mode 100644 index 000000000..d61ca06ad --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-NAPOT-R-priority.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-NAPOT-R-priority.S new file mode 100644 index 000000000..558ef5414 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-NAPOT-R.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-NAPOT-R.S new file mode 100644 index 000000000..203a9b207 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-NAPOT-RW-priority-level-2.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-NAPOT-RW-priority-level-2.S new file mode 100644 index 000000000..54e638441 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-NAPOT-RW-priority.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-NAPOT-RW-priority.S new file mode 100644 index 000000000..8511e6bd9 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-NAPOT-RW.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-NAPOT-RW.S new file mode 100644 index 000000000..14f35e8bb --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-NAPOT-RWX.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-NAPOT-RWX.S new file mode 100644 index 000000000..fd0250038 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-NAPOT-RX-priority-level-2.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-NAPOT-RX-priority-level-2.S new file mode 100644 index 000000000..5666270af --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-NAPOT-RX-priority.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-NAPOT-RX-priority.S new file mode 100644 index 000000000..dea8855b0 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-NAPOT-RX.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-NAPOT-RX.S new file mode 100644 index 000000000..719ee224c --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-NAPOT-X-priority-level-2.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-NAPOT-X-priority-level-2.S new file mode 100644 index 000000000..7c52bf945 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-NAPOT-X-priority.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-NAPOT-X-priority.S new file mode 100644 index 000000000..c9f409455 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-NAPOT-X.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-NAPOT-X.S new file mode 100644 index 000000000..67bb63f76 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-TOR-R-priority-level-2.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-TOR-R-priority-level-2.S new file mode 100644 index 000000000..9f9c1c83d --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-TOR-R-priority.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-TOR-R-priority.S new file mode 100644 index 000000000..a88bd1544 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-TOR-R.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-TOR-R.S new file mode 100644 index 000000000..3007a1d50 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-TOR-RW-priority-level-2..S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-TOR-RW-priority-level-2..S new file mode 100644 index 000000000..73a71eeb1 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-TOR-RW-priority.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-TOR-RW-priority.S new file mode 100644 index 000000000..58203fde8 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-TOR-RW.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-TOR-RW.S new file mode 100644 index 000000000..5f87066d6 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-TOR-RWX.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-TOR-RWX.S new file mode 100644 index 000000000..88fe419fc --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-TOR-RX-priority-level-2.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-TOR-RX-priority-level-2.S new file mode 100644 index 000000000..85927c768 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-TOR-RX-priority.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-TOR-RX-priority.S new file mode 100644 index 000000000..17e89e391 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-TOR-RX.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-TOR-RX.S new file mode 100644 index 000000000..87dbc4034 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-TOR-X-priority-level-2.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-TOR-X-priority-level-2.S new file mode 100644 index 000000000..f0d32f399 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-TOR-X-priority.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-TOR-X-priority.S new file mode 100644 index 000000000..c3a475dc3 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp-TOR-X.S b/riscv-test-suite/rv32i_m/pmp32/src/pmp-TOR-X.S new file mode 100644 index 000000000..ac13b7c92 --- /dev/null +++ b/riscv-test-suite/rv32i_m/pmp32/src/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.*S.*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/src/pmp64-CFG-reg.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-CFG-reg.S new file mode 100644 index 000000000..4099f98f2 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-CSR-access.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-CSR-access.S new file mode 100644 index 000000000..ca50a5dbe --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-NA4-R-priority-level-2.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-NA4-R-priority-level-2.S new file mode 100644 index 000000000..dec017412 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-NA4-R-priority.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-NA4-R-priority.S new file mode 100644 index 000000000..c735ca79e --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-NA4-R.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-NA4-R.S new file mode 100644 index 000000000..a971c1b94 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-NA4-RW-priority-level-2.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-NA4-RW-priority-level-2.S new file mode 100644 index 000000000..52d4ba97f --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-NA4-RW-priority.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-NA4-RW-priority.S new file mode 100644 index 000000000..fa1f8323d --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-NA4-RW.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-NA4-RW.S new file mode 100644 index 000000000..1ebdb02ec --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-NA4-RWX.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-NA4-RWX.S new file mode 100644 index 000000000..f1cf211aa --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-NA4-RX-priority-level-2.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-NA4-RX-priority-level-2.S new file mode 100644 index 000000000..252d86974 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-NA4-RX-priority.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-NA4-RX-priority.S new file mode 100644 index 000000000..c2d5b8040 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-NA4-RX.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-NA4-RX.S new file mode 100644 index 000000000..539404253 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-NA4-X-priority-level-2.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-NA4-X-priority-level-2.S new file mode 100644 index 000000000..4da604019 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-NA4-X-priority.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-NA4-X-priority.S new file mode 100644 index 000000000..da13df8b8 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-NA4-X.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-NA4-X.S new file mode 100644 index 000000000..8bbb2a769 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-NAPOT-R-priority-level-2.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-NAPOT-R-priority-level-2.S new file mode 100644 index 000000000..4a01c5444 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-NAPOT-R-priority.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-NAPOT-R-priority.S new file mode 100644 index 000000000..ae15e7f45 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-NAPOT-R.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-NAPOT-R.S new file mode 100644 index 000000000..3406367a1 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-NAPOT-RW-priority-level-2.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-NAPOT-RW-priority-level-2.S new file mode 100644 index 000000000..cd2784e08 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-NAPOT-RW-priority.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-NAPOT-RW-priority.S new file mode 100644 index 000000000..5f502901a --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-NAPOT-RW.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-NAPOT-RW.S new file mode 100644 index 000000000..4130f6dde --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-NAPOT-RWX.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-NAPOT-RWX.S new file mode 100644 index 000000000..7181860da --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-NAPOT-RX-priority-level-2.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-NAPOT-RX-priority-level-2.S new file mode 100644 index 000000000..d46b66309 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-NAPOT-RX-priority.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-NAPOT-RX-priority.S new file mode 100644 index 000000000..f215ce3c8 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-NAPOT-RX.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-NAPOT-RX.S new file mode 100644 index 000000000..7e93a25d4 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-NAPOT-X-priority-level-2.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-NAPOT-X-priority-level-2.S new file mode 100644 index 000000000..c07815348 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-NAPOT-X-priority.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-NAPOT-X-priority.S new file mode 100644 index 000000000..aba622635 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-NAPOT-X.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-NAPOT-X.S new file mode 100644 index 000000000..f19c5af4a --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-TOR-R-priority-level-2.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-TOR-R-priority-level-2.S new file mode 100644 index 000000000..7ad823cdf --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-TOR-R-priority.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-TOR-R-priority.S new file mode 100644 index 000000000..29a122fb0 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-TOR-R.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-TOR-R.S new file mode 100644 index 000000000..79765c52d --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-TOR-RW-priority-level-2..S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-TOR-RW-priority-level-2..S new file mode 100644 index 000000000..605d76fb5 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-TOR-RW-priority.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-TOR-RW-priority.S new file mode 100644 index 000000000..86b2b7a6e --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-TOR-RW.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-TOR-RW.S new file mode 100644 index 000000000..38d4c4483 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-TOR-RWX.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-TOR-RWX.S new file mode 100644 index 000000000..3732258b8 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-TOR-RX-priority-level-2.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-TOR-RX-priority-level-2.S new file mode 100644 index 000000000..35d3f1edb --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-TOR-RX-priority.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-TOR-RX-priority.S new file mode 100644 index 000000000..9632e6a4f --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-TOR-RX.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-TOR-RX.S new file mode 100644 index 000000000..64daa166e --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-TOR-X-priority-level-2.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-TOR-X-priority-level-2.S new file mode 100644 index 000000000..b49c621f1 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-TOR-X-priority.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-TOR-X-priority.S new file mode 100644 index 000000000..f1d9d474c --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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/src/pmp64-TOR-X.S b/riscv-test-suite/rv64i_m/pmp64/src/pmp64-TOR-X.S new file mode 100644 index 000000000..39df71528 --- /dev/null +++ b/riscv-test-suite/rv64i_m/pmp64/src/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.*S.*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