From: Charlie Jenkins <[email protected]>

Migrate the csr emulation code to use the generated instruction headers
instead of the hand-written instruction composition functions.

Signed-off-by: Charlie Jenkins <[email protected]>

---
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             | 61 +++++++++++++++++-----------------
 2 files changed, 32 insertions(+), 32 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 c5a70de4a579..d666cd24f8c0 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;
 }
@@ -154,7 +150,7 @@ static int csr_insn(struct kvm_vcpu *vcpu, struct kvm_run 
*run, ulong insn)
        #define GET_REG(_rd) (*((unsigned long *)(&vcpu->arch.guest_context) + 
_rd))
 
        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;
 
@@ -163,26 +159,32 @@ static int csr_insn(struct kvm_vcpu *vcpu, struct kvm_run 
*run, ulong insn)
                wr_mask = -1UL;
                new_val = GET_REG(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(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(riscv_insn_csrrs_extract_xs1(insn));
+               wr_mask = GET_REG(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;
        }
@@ -190,7 +192,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 */
@@ -234,43 +237,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,
        },
 };
@@ -283,7 +282,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.52.0



Reply via email to