[PATCH v3 15/17] riscv: kvm: Use generated instruction headers for csr emulation
Charlie Jenkins
thecharlesjenkins at gmail.com
Tue Jul 7 20:34:38 PDT 2026
Migrate the csr emulation code to use the generated instruction headers
instead of the hand-written instruction composition functions.
Signed-off-by: Charlie Jenkins <thecharlesjenkins at gmail.com>
---
This can be tested with the introduced csr_test selftest.
---
arch/riscv/include/asm/kvm_vcpu_insn.h | 3 +-
arch/riscv/kvm/vcpu_insn.c | 59 +++++++++++++++++-----------------
2 files changed, 31 insertions(+), 31 deletions(-)
diff --git a/arch/riscv/include/asm/kvm_vcpu_insn.h b/arch/riscv/include/asm/kvm_vcpu_insn.h
index 106fb4c45108..01efdaaede21 100644
--- a/arch/riscv/include/asm/kvm_vcpu_insn.h
+++ b/arch/riscv/include/asm/kvm_vcpu_insn.h
@@ -19,7 +19,8 @@ struct kvm_mmio_decode {
};
struct kvm_csr_decode {
- unsigned long insn;
+ unsigned long rd;
+ unsigned long insn_len;
int return_handled;
};
diff --git a/arch/riscv/kvm/vcpu_insn.c b/arch/riscv/kvm/vcpu_insn.c
index c3e4cf2cd44b..51eb2c717bff 100644
--- a/arch/riscv/kvm/vcpu_insn.c
+++ b/arch/riscv/kvm/vcpu_insn.c
@@ -13,8 +13,7 @@
#include <asm/kvm_vcpu_test_csr.h>
struct insn_func {
- unsigned long mask;
- unsigned long match;
+ bool (*cmp)(u32 insn);
/*
* Possible return values are as follows:
* 1) Returns < 0 for error case
@@ -131,20 +130,17 @@ static const struct csr_func csr_funcs[] = {
*/
int kvm_riscv_vcpu_csr_return(struct kvm_vcpu *vcpu, struct kvm_run *run)
{
- ulong insn;
-
if (vcpu->arch.csr_decode.return_handled)
return 0;
vcpu->arch.csr_decode.return_handled = 1;
/* Update destination register for CSR reads */
- insn = vcpu->arch.csr_decode.insn;
- if ((insn >> SH_RD) & MASK_RX)
- SET_RD(insn, &vcpu->arch.guest_context,
- run->riscv_csr.ret_value);
+ if (vcpu->arch.csr_decode.rd)
+ *((ulong *)&vcpu->arch.guest_context +
+ vcpu->arch.csr_decode.rd) = run->riscv_csr.ret_value;
/* Move to next instruction */
- vcpu->arch.guest_context.sepc += INSN_LEN(insn);
+ vcpu->arch.guest_context.sepc += vcpu->arch.csr_decode.insn_len;
return 0;
}
@@ -157,7 +153,7 @@ static inline unsigned long get_reg(struct kvm_cpu_context *context, unsigned in
static int csr_insn(struct kvm_vcpu *vcpu, struct kvm_run *run, ulong insn)
{
int i, rc = KVM_INSN_ILLEGAL_TRAP;
- unsigned int csr_num;
+ unsigned int csr_num, rd;
const struct csr_func *tcfn, *cfn = NULL;
ulong val = 0, wr_mask = 0, new_val = 0;
@@ -166,26 +162,32 @@ static int csr_insn(struct kvm_vcpu *vcpu, struct kvm_run *run, ulong insn)
wr_mask = -1UL;
new_val = get_reg(&vcpu->arch.guest_context, riscv_insn_csrrw_extract_xs1(insn));
csr_num = riscv_insn_csrrw_extract_csr(insn);
+ rd = riscv_insn_csrrw_extract_xd(insn);
} else if (riscv_insn_is_csrrs(insn)) {
wr_mask = get_reg(&vcpu->arch.guest_context, riscv_insn_csrrs_extract_xs1(insn));
new_val = -1UL;
csr_num = riscv_insn_csrrs_extract_csr(insn);
+ rd = riscv_insn_csrrs_extract_xd(insn);
} else if (riscv_insn_is_csrrc(insn)) {
wr_mask = get_reg(&vcpu->arch.guest_context, riscv_insn_csrrc_extract_xs1(insn));
new_val = 0;
csr_num = riscv_insn_csrrc_extract_csr(insn);
+ rd = riscv_insn_csrrc_extract_xd(insn);
} else if (riscv_insn_is_csrrwi(insn)) {
wr_mask = -1UL;
new_val = riscv_insn_csrrwi_extract_imm(insn);
csr_num = riscv_insn_csrrwi_extract_csr(insn);
+ rd = riscv_insn_csrrwi_extract_xd(insn);
} else if (riscv_insn_is_csrrsi(insn)) {
wr_mask = riscv_insn_csrrwi_extract_imm(insn);
new_val = -1UL;
csr_num = riscv_insn_csrrsi_extract_csr(insn);
+ rd = riscv_insn_csrrsi_extract_xd(insn);
} else if (riscv_insn_is_csrrci(insn)) {
- wr_mask = GET_REG(riscv_insn_csrrwi_extract_imm(insn));
+ wr_mask = riscv_insn_csrrci_extract_imm(insn);
new_val = 0;
- csr_num = riscv_insn_csrrwi_extract_csr(insn);
+ csr_num = riscv_insn_csrrci_extract_csr(insn);
+ rd = riscv_insn_csrrci_extract_xd(insn);
} else {
return rc;
}
@@ -193,7 +195,8 @@ static int csr_insn(struct kvm_vcpu *vcpu, struct kvm_run *run, ulong insn)
#undef GET_REG
/* Save instruction decode info */
- vcpu->arch.csr_decode.insn = insn;
+ vcpu->arch.csr_decode.rd = rd;
+ vcpu->arch.csr_decode.insn_len = INSN_LEN(insn);
vcpu->arch.csr_decode.return_handled = 0;
/* Update CSR details in kvm_run struct */
@@ -237,43 +240,39 @@ static int csr_insn(struct kvm_vcpu *vcpu, struct kvm_run *run, ulong insn)
static const struct insn_func system_opcode_funcs[] = {
{
- .mask = INSN_MASK_CSRRW,
- .match = INSN_MATCH_CSRRW,
+ .cmp = riscv_insn_is_csrrw,
.func = csr_insn,
},
{
- .mask = INSN_MASK_CSRRS,
- .match = INSN_MATCH_CSRRS,
+ .cmp = riscv_insn_is_csrrs,
.func = csr_insn,
},
{
- .mask = INSN_MASK_CSRRC,
- .match = INSN_MATCH_CSRRC,
+ .cmp = riscv_insn_is_csrrc,
.func = csr_insn,
},
{
- .mask = INSN_MASK_CSRRWI,
- .match = INSN_MATCH_CSRRWI,
+ .cmp = riscv_insn_is_csrrwi,
.func = csr_insn,
},
{
- .mask = INSN_MASK_CSRRSI,
- .match = INSN_MATCH_CSRRSI,
+ .cmp = riscv_insn_is_csrrsi,
.func = csr_insn,
},
{
- .mask = INSN_MASK_CSRRCI,
- .match = INSN_MATCH_CSRRCI,
+ .cmp = riscv_insn_is_csrrci,
.func = csr_insn,
},
{
- .mask = INSN_MASK_WFI,
- .match = INSN_MATCH_WFI,
+ .cmp = riscv_insn_is_wfi,
.func = wfi_insn,
},
{
- .mask = INSN_MASK_WRS,
- .match = INSN_MATCH_WRS,
+ .cmp = riscv_insn_is_wrs_nto,
+ .func = wrs_insn,
+ },
+ {
+ .cmp = riscv_insn_is_wrs_sto,
.func = wrs_insn,
},
};
@@ -286,7 +285,7 @@ static int system_opcode_insn(struct kvm_vcpu *vcpu, struct kvm_run *run,
for (i = 0; i < ARRAY_SIZE(system_opcode_funcs); i++) {
ifn = &system_opcode_funcs[i];
- if ((insn & ifn->mask) == ifn->match) {
+ if (ifn->cmp(insn)) {
rc = ifn->func(vcpu, run, insn);
break;
}
--
2.54.0
More information about the linux-riscv
mailing list