lkml.org 
[lkml]   [2020]   [Jul]   [10]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v13 08/17] RISC-V: KVM: Handle WFI exits for VCPU
    Date
    We get illegal instruction trap whenever Guest/VM executes WFI
    instruction.

    This patch handles WFI trap by blocking the trapped VCPU using
    kvm_vcpu_block() API. The blocked VCPU will be automatically
    resumed whenever a VCPU interrupt is injected from user-space
    or from in-kernel IRQCHIP emulation.

    Signed-off-by: Anup Patel <anup.patel@wdc.com>
    Acked-by: Paolo Bonzini <pbonzini@redhat.com>
    Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
    ---
    arch/riscv/kvm/vcpu_exit.c | 76 ++++++++++++++++++++++++++++++++++++++
    1 file changed, 76 insertions(+)

    diff --git a/arch/riscv/kvm/vcpu_exit.c b/arch/riscv/kvm/vcpu_exit.c
    index 7fd603acd97a..6ef833e29e71 100644
    --- a/arch/riscv/kvm/vcpu_exit.c
    +++ b/arch/riscv/kvm/vcpu_exit.c
    @@ -12,6 +12,13 @@
    #include <linux/kvm_host.h>
    #include <asm/csr.h>

    +#define INSN_OPCODE_MASK 0x007c
    +#define INSN_OPCODE_SHIFT 2
    +#define INSN_OPCODE_SYSTEM 28
    +
    +#define INSN_MASK_WFI 0xffffff00
    +#define INSN_MATCH_WFI 0x10500000
    +
    #define INSN_MATCH_LB 0x3
    #define INSN_MASK_LB 0x707f
    #define INSN_MATCH_LH 0x1003
    @@ -116,6 +123,71 @@
    (s32)(((insn) >> 7) & 0x1f))
    #define MASK_FUNCT3 0x7000

    +static int truly_illegal_insn(struct kvm_vcpu *vcpu,
    + struct kvm_run *run,
    + ulong insn)
    +{
    + struct kvm_cpu_trap utrap = { 0 };
    +
    + /* Redirect trap to Guest VCPU */
    + utrap.sepc = vcpu->arch.guest_context.sepc;
    + utrap.scause = EXC_INST_ILLEGAL;
    + utrap.stval = insn;
    + kvm_riscv_vcpu_trap_redirect(vcpu, &utrap);
    +
    + return 1;
    +}
    +
    +static int system_opcode_insn(struct kvm_vcpu *vcpu,
    + struct kvm_run *run,
    + ulong insn)
    +{
    + if ((insn & INSN_MASK_WFI) == INSN_MATCH_WFI) {
    + vcpu->stat.wfi_exit_stat++;
    + if (!kvm_arch_vcpu_runnable(vcpu)) {
    + srcu_read_unlock(&vcpu->kvm->srcu, vcpu->arch.srcu_idx);
    + kvm_vcpu_block(vcpu);
    + vcpu->arch.srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
    + kvm_clear_request(KVM_REQ_UNHALT, vcpu);
    + }
    + vcpu->arch.guest_context.sepc += INSN_LEN(insn);
    + return 1;
    + }
    +
    + return truly_illegal_insn(vcpu, run, insn);
    +}
    +
    +static int virtual_inst_fault(struct kvm_vcpu *vcpu, struct kvm_run *run,
    + struct kvm_cpu_trap *trap)
    +{
    + unsigned long insn = trap->stval;
    + struct kvm_cpu_trap utrap = { 0 };
    + struct kvm_cpu_context *ct;
    +
    + if (unlikely(INSN_IS_16BIT(insn))) {
    + if (insn == 0) {
    + ct = &vcpu->arch.guest_context;
    + insn = kvm_riscv_vcpu_unpriv_read(vcpu, true,
    + ct->sepc,
    + &utrap);
    + if (utrap.scause) {
    + utrap.sepc = ct->sepc;
    + kvm_riscv_vcpu_trap_redirect(vcpu, &utrap);
    + return 1;
    + }
    + }
    + if (INSN_IS_16BIT(insn))
    + return truly_illegal_insn(vcpu, run, insn);
    + }
    +
    + switch ((insn & INSN_OPCODE_MASK) >> INSN_OPCODE_SHIFT) {
    + case INSN_OPCODE_SYSTEM:
    + return system_opcode_insn(vcpu, run, insn);
    + default:
    + return truly_illegal_insn(vcpu, run, insn);
    + }
    +}
    +
    static int emulate_load(struct kvm_vcpu *vcpu, struct kvm_run *run,
    unsigned long fault_addr, unsigned long htinst)
    {
    @@ -565,6 +637,10 @@ int kvm_riscv_vcpu_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
    ret = -EFAULT;
    run->exit_reason = KVM_EXIT_UNKNOWN;
    switch (trap->scause) {
    + case EXC_VIRTUAL_INST_FAULT:
    + if (vcpu->arch.guest_context.hstatus & HSTATUS_SPV)
    + ret = virtual_inst_fault(vcpu, run, trap);
    + break;
    case EXC_INST_GUEST_PAGE_FAULT:
    case EXC_LOAD_GUEST_PAGE_FAULT:
    case EXC_STORE_GUEST_PAGE_FAULT:
    --
    2.25.1
    \
     
     \ /
      Last update: 2020-07-10 10:28    [W:6.488 / U:0.108 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site