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
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEZdn75s5e6LHDQ+f/rUjsVaLHLAcFAmH6i38ACgkQrUjsVaLH
 LAeBmQ/+JRDlbGe+7iHMeZKvgqFuhFRnK+1U8Kmq/7jJI5gR6/POPhL0H1dCyOGa
 c64wB+E3btoOt5mHyD6lOYG+1LUN7B4dw2jBa2pBOOolzdHcGATcAQ4s2085lAK/
 gEwqD8CBbHIJjE3RnUBJ03aUVIrGPZ2XPKkJZmQgaKAfpEgLHrLeSnXrgC29ELal
 2LNJKlfh8lU5CLkB3Xfw+cTR7CBmk12WlXmL+nIYfmzgPt7dRUyvtxyIv3kyFTso
 8mNnXFrAxHNszVjooe/7EQPcOEd7W+QN0Dx/m8fzcy5R1KUBEbFiKuwYw/1PPm6X
 21v0ijQovzA5p9VmCLRGF4u9RjuB7Iyd/LaiqArXRuyDA+X+ogbmElDdc0N9ckol
 s+aMPafgQApXyoxzEXpolAtO2NQ8jg42UaO1Bvvi5I67MQq9VnB+jos+T79Qz2Cz
 KBEy5jBe73+x+rdwx78+Ixnx955MX2YGDCKcX5I8vN3NhuS4Zt57VEEmHMV4z3Hv
 uFUeCgDB1cJEOO7UE6WmUshxoO83hLYNgQlo5DZ963ZtD7bDgs4DXZCdXIt8ai8f
 h66EO2wInLviyxAromWB42dbKoR6UsDirceGZwCldEwHHDtJkTFh/FhChK+iAQp2
 X6rgMJPpvdeYahmtOdxawEsjx1pkXr6bX9nZEc0DG77Nym1fdXM=
 =JtDG
 -----END PGP SIGNATURE-----

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
This commit is contained in:
Paolo Bonzini 2022-02-02 09:58:10 -05:00
commit cb4f084342
2 changed files with 33 additions and 18 deletions

View File

@ -90,6 +90,7 @@ int kvm_arch_vcpu_precreate(struct kvm *kvm, unsigned int id)
int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
{
struct kvm_cpu_context *cntx;
struct kvm_vcpu_csr *reset_csr = &vcpu->arch.guest_reset_csr;
/* Mark this VCPU never ran */
vcpu->arch.ran_atleast_once = false;
@ -106,6 +107,9 @@ int kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
cntx->hstatus |= HSTATUS_SPVP;
cntx->hstatus |= HSTATUS_SPV;
/* By default, make CY, TM, and IR counters accessible in VU mode */
reset_csr->scounteren = 0x7;
/* Setup VCPU timer */
kvm_riscv_vcpu_timer_init(vcpu);
@ -699,6 +703,20 @@ static void kvm_riscv_update_hvip(struct kvm_vcpu *vcpu)
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 ret;
@ -790,9 +808,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
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->stat.exits++;
@ -812,25 +830,21 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
kvm_riscv_vcpu_sync_interrupts(vcpu);
/*
* We may have taken a host interrupt in VS/VU-mode (i.e.
* while executing the guest). This interrupt is still
* pending, as we haven't serviced it yet!
* We must ensure that any pending interrupts are taken before
* we exit guest timing so that timer ticks are accounted as
* guest time. Transiently unmask interrupts so that any
* pending interrupts are taken.
*
* We're now back in HS-mode with interrupts disabled
* so enabling the interrupts now will have the effect
* of taking the interrupt again, in HS-mode this time.
* There's no barrier which ensures that pending interrupts are
* recognised, so we just hope that the CPU takes any pending
* interrupts between the enable and disable.
*/
local_irq_enable();
local_irq_disable();
/*
* We do local_irq_enable() before calling guest_exit() so
* that if a timer interrupt hits while running the guest
* 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();
guest_timing_exit_irqoff();
local_irq_enable();
preempt_enable();

View File

@ -9,6 +9,7 @@
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/kvm_host.h>
#include <linux/version.h>
#include <asm/csr.h>
#include <asm/sbi.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,
*out_val = KVM_SBI_IMPID;
break;
case SBI_EXT_BASE_GET_IMP_VERSION:
*out_val = 0;
*out_val = LINUX_VERSION_CODE;
break;
case SBI_EXT_BASE_PROBE_EXT:
if ((cp->a0 >= SBI_EXT_EXPERIMENTAL_START &&