Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: riscv: selftests: Decode stval to identify exact exception type

Currently, the sbi_pmu_test continues if the exception type is illegal
instruction because access to hpmcounter will generate that. However
illegal instruction exception may occur due to the other reasons
which should result in test assertion.

Use the stval to decode the exact type of instructions and which csrs are
being accessed if it is csr access instructions. Assert in all cases
except if it is a csr access instructions that access valid PMU related
registers.

Take this opportunity to remove the CSR_CYCLEH reference as the test is
compiled for RV64 only.

Reviewed-by: Anup Patel <anup@brainfault.org>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Signed-off-by: Atish Patra <atishp@rivosinc.com>
Link: https://lore.kernel.org/r/20250430-kvm_selftest_improve-v3-2-eea270ff080b@rivosinc.com
Signed-off-by: Anup Patel <anup@brainfault.org>

authored by

Atish Patra and committed by
Anup Patel
3608b174 e23bb06b

+32 -1
+13
tools/testing/selftests/kvm/include/riscv/processor.h
··· 11 11 #include <asm/csr.h> 12 12 #include "kvm_util.h" 13 13 14 + #define INSN_OPCODE_MASK 0x007c 15 + #define INSN_OPCODE_SHIFT 2 16 + #define INSN_OPCODE_SYSTEM 28 17 + 18 + #define INSN_MASK_FUNCT3 0x7000 19 + #define INSN_SHIFT_FUNCT3 12 20 + 21 + #define INSN_CSR_MASK 0xfff00000 22 + #define INSN_CSR_SHIFT 20 23 + 24 + #define GET_RM(insn) (((insn) & INSN_MASK_FUNCT3) >> INSN_SHIFT_FUNCT3) 25 + #define GET_CSR_NUM(insn) (((insn) & INSN_CSR_MASK) >> INSN_CSR_SHIFT) 26 + 14 27 static inline uint64_t __kvm_reg_id(uint64_t type, uint64_t subtype, 15 28 uint64_t idx, uint64_t size) 16 29 {
+19 -1
tools/testing/selftests/kvm/riscv/sbi_pmu_test.c
··· 73 73 74 74 switch (csr_num) { 75 75 switchcase_csr_read_32(CSR_CYCLE, ret) 76 - switchcase_csr_read_32(CSR_CYCLEH, ret) 77 76 default : 78 77 break; 79 78 } ··· 129 130 130 131 static void guest_illegal_exception_handler(struct pt_regs *regs) 131 132 { 133 + unsigned long insn; 134 + int opcode, csr_num, funct3; 135 + 132 136 __GUEST_ASSERT(regs->cause == EXC_INST_ILLEGAL, 133 137 "Unexpected exception handler %lx\n", regs->cause); 138 + 139 + insn = regs->badaddr; 140 + opcode = (insn & INSN_OPCODE_MASK) >> INSN_OPCODE_SHIFT; 141 + __GUEST_ASSERT(opcode == INSN_OPCODE_SYSTEM, 142 + "Unexpected instruction with opcode 0x%x insn 0x%lx\n", opcode, insn); 143 + 144 + csr_num = GET_CSR_NUM(insn); 145 + funct3 = GET_RM(insn); 146 + /* Validate if it is a CSR read/write operation */ 147 + __GUEST_ASSERT(funct3 <= 7 && (funct3 != 0 && funct3 != 4), 148 + "Unexpected system opcode with funct3 0x%x csr_num 0x%x\n", 149 + funct3, csr_num); 150 + 151 + /* Validate if it is a HPMCOUNTER CSR operation */ 152 + __GUEST_ASSERT((csr_num >= CSR_CYCLE && csr_num <= CSR_HPMCOUNTER31), 153 + "Unexpected csr_num 0x%x\n", csr_num); 134 154 135 155 illegal_handler_invoked = true; 136 156 /* skip the trapping instruction */