Commit cb4f0843 authored by Paolo Bonzini's avatar Paolo Bonzini

Merge tag 'kvm-riscv-fixes-5.17-1' of https://github.com/kvm-riscv/linux into HEAD

KVM/riscv fixes for 5.17, take #1

- Rework guest entry logic

- Make CY, TM, and IR counters accessible in VU mode

- Fix SBI implementation version
parents 8cfe148a 40327154
...@@ -90,6 +90,7 @@ int kvm_arch_vcpu_precreate(struct kvm *kvm, unsigned int id) ...@@ -90,6 +90,7 @@ int kvm_arch_vcpu_precreate(struct kvm *kvm, unsigned int id)
int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu) int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
{ {
struct kvm_cpu_context *cntx; struct kvm_cpu_context *cntx;
struct kvm_vcpu_csr *reset_csr = &vcpu->arch.guest_reset_csr;
/* Mark this VCPU never ran */ /* Mark this VCPU never ran */
vcpu->arch.ran_atleast_once = false; vcpu->arch.ran_atleast_once = false;
...@@ -106,6 +107,9 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu) ...@@ -106,6 +107,9 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
cntx->hstatus |= HSTATUS_SPVP; cntx->hstatus |= HSTATUS_SPVP;
cntx->hstatus |= HSTATUS_SPV; cntx->hstatus |= HSTATUS_SPV;
/* By default, make CY, TM, and IR counters accessible in VU mode */
reset_csr->scounteren = 0x7;
/* Setup VCPU timer */ /* Setup VCPU timer */
kvm_riscv_vcpu_timer_init(vcpu); kvm_riscv_vcpu_timer_init(vcpu);
...@@ -699,6 +703,20 @@ static void kvm_riscv_update_hvip(struct kvm_vcpu *vcpu) ...@@ -699,6 +703,20 @@ static void kvm_riscv_update_hvip(struct kvm_vcpu *vcpu)
csr_write(CSR_HVIP, csr->hvip); csr_write(CSR_HVIP, csr->hvip);
} }
/*
* Actually run the vCPU, entering an RCU extended quiescent state (EQS) while
* the vCPU is running.
*
* This must be noinstr as instrumentation may make use of RCU, and this is not
* safe during the EQS.
*/
static void noinstr kvm_riscv_vcpu_enter_exit(struct kvm_vcpu *vcpu)
{
guest_state_enter_irqoff();
__kvm_riscv_switch_to(&vcpu->arch);
guest_state_exit_irqoff();
}
int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
{ {
int ret; int ret;
...@@ -790,9 +808,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) ...@@ -790,9 +808,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
continue; continue;
} }
guest_enter_irqoff(); guest_timing_enter_irqoff();
__kvm_riscv_switch_to(&vcpu->arch); kvm_riscv_vcpu_enter_exit(vcpu);
vcpu->mode = OUTSIDE_GUEST_MODE; vcpu->mode = OUTSIDE_GUEST_MODE;
vcpu->stat.exits++; vcpu->stat.exits++;
...@@ -812,25 +830,21 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu) ...@@ -812,25 +830,21 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
kvm_riscv_vcpu_sync_interrupts(vcpu); kvm_riscv_vcpu_sync_interrupts(vcpu);
/* /*
* We may have taken a host interrupt in VS/VU-mode (i.e. * We must ensure that any pending interrupts are taken before
* while executing the guest). This interrupt is still * we exit guest timing so that timer ticks are accounted as
* pending, as we haven't serviced it yet! * guest time. Transiently unmask interrupts so that any
* pending interrupts are taken.
* *
* We're now back in HS-mode with interrupts disabled * There's no barrier which ensures that pending interrupts are
* so enabling the interrupts now will have the effect * recognised, so we just hope that the CPU takes any pending
* of taking the interrupt again, in HS-mode this time. * interrupts between the enable and disable.
*/ */
local_irq_enable(); local_irq_enable();
local_irq_disable();
/* guest_timing_exit_irqoff();
* We do local_irq_enable() before calling guest_exit() so
* that if a timer interrupt hits while running the guest local_irq_enable();
* we account that tick as being spent in the guest. We
* enable preemption after calling guest_exit() so that if
* we get preempted we make sure ticks after that is not
* counted as guest time.
*/
guest_exit();
preempt_enable(); preempt_enable();
......
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/kvm_host.h> #include <linux/kvm_host.h>
#include <linux/version.h>
#include <asm/csr.h> #include <asm/csr.h>
#include <asm/sbi.h> #include <asm/sbi.h>
#include <asm/kvm_vcpu_timer.h> #include <asm/kvm_vcpu_timer.h>
...@@ -32,7 +33,7 @@ static int kvm_sbi_ext_base_handler(struct kvm_vcpu *vcpu, struct kvm_run *run, ...@@ -32,7 +33,7 @@ static int kvm_sbi_ext_base_handler(struct kvm_vcpu *vcpu, struct kvm_run *run,
*out_val = KVM_SBI_IMPID; *out_val = KVM_SBI_IMPID;
break; break;
case SBI_EXT_BASE_GET_IMP_VERSION: case SBI_EXT_BASE_GET_IMP_VERSION:
*out_val = 0; *out_val = LINUX_VERSION_CODE;
break; break;
case SBI_EXT_BASE_PROBE_EXT: case SBI_EXT_BASE_PROBE_EXT:
if ((cp->a0 >= SBI_EXT_EXPERIMENTAL_START && if ((cp->a0 >= SBI_EXT_EXPERIMENTAL_START &&
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment