Merge branch kvm-arm64/generic-entry into kvmarm-master/next
Switch KVM/arm64 to the generic entry code, courtesy of Oliver Upton * kvm-arm64/generic-entry: KVM: arm64: Use generic KVM xfer to guest work function entry: KVM: Allow use of generic KVM entry w/o full generic support KVM: arm64: Record number of signal exits as a vCPU stat Signed-off-by: Marc Zyngier <maz@kernel.org>
This commit is contained in:
commit
ca3385a507
|
@ -575,6 +575,7 @@ struct kvm_vcpu_stat {
|
|||
u64 wfi_exit_stat;
|
||||
u64 mmio_exit_user;
|
||||
u64 mmio_exit_kernel;
|
||||
u64 signal_exits;
|
||||
u64 exits;
|
||||
};
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ menuconfig KVM
|
|||
select HAVE_KVM_ARCH_TLB_FLUSH_ALL
|
||||
select KVM_MMIO
|
||||
select KVM_GENERIC_DIRTYLOG_READ_PROTECT
|
||||
select KVM_XFER_TO_GUEST_WORK
|
||||
select SRCU
|
||||
select KVM_VFIO
|
||||
select HAVE_KVM_EVENTFD
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <linux/bug.h>
|
||||
#include <linux/cpu_pm.h>
|
||||
#include <linux/entry-kvm.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/kvm_host.h>
|
||||
|
@ -715,6 +716,45 @@ static bool vcpu_mode_is_bad_32bit(struct kvm_vcpu *vcpu)
|
|||
static_branch_unlikely(&arm64_mismatched_32bit_el0);
|
||||
}
|
||||
|
||||
/**
|
||||
* kvm_vcpu_exit_request - returns true if the VCPU should *not* enter the guest
|
||||
* @vcpu: The VCPU pointer
|
||||
* @ret: Pointer to write optional return code
|
||||
*
|
||||
* Returns: true if the VCPU needs to return to a preemptible + interruptible
|
||||
* and skip guest entry.
|
||||
*
|
||||
* This function disambiguates between two different types of exits: exits to a
|
||||
* preemptible + interruptible kernel context and exits to userspace. For an
|
||||
* exit to userspace, this function will write the return code to ret and return
|
||||
* true. For an exit to preemptible + interruptible kernel context (i.e. check
|
||||
* for pending work and re-enter), return true without writing to ret.
|
||||
*/
|
||||
static bool kvm_vcpu_exit_request(struct kvm_vcpu *vcpu, int *ret)
|
||||
{
|
||||
struct kvm_run *run = vcpu->run;
|
||||
|
||||
/*
|
||||
* If we're using a userspace irqchip, then check if we need
|
||||
* to tell a userspace irqchip about timer or PMU level
|
||||
* changes and if so, exit to userspace (the actual level
|
||||
* state gets updated in kvm_timer_update_run and
|
||||
* kvm_pmu_update_run below).
|
||||
*/
|
||||
if (static_branch_unlikely(&userspace_irqchip_in_use)) {
|
||||
if (kvm_timer_should_notify_user(vcpu) ||
|
||||
kvm_pmu_should_notify_user(vcpu)) {
|
||||
*ret = -EINTR;
|
||||
run->exit_reason = KVM_EXIT_INTR;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return kvm_request_pending(vcpu) ||
|
||||
need_new_vmid_gen(&vcpu->arch.hw_mmu->vmid) ||
|
||||
xfer_to_guest_mode_work_pending();
|
||||
}
|
||||
|
||||
/**
|
||||
* kvm_arch_vcpu_ioctl_run - the main VCPU run function to execute guest code
|
||||
* @vcpu: The VCPU pointer
|
||||
|
@ -758,7 +798,9 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
|
|||
/*
|
||||
* Check conditions before entering the guest
|
||||
*/
|
||||
cond_resched();
|
||||
ret = xfer_to_guest_mode_handle_work(vcpu);
|
||||
if (!ret)
|
||||
ret = 1;
|
||||
|
||||
update_vmid(&vcpu->arch.hw_mmu->vmid);
|
||||
|
||||
|
@ -777,30 +819,6 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
|
|||
|
||||
kvm_vgic_flush_hwstate(vcpu);
|
||||
|
||||
/*
|
||||
* Exit if we have a signal pending so that we can deliver the
|
||||
* signal to user space.
|
||||
*/
|
||||
if (signal_pending(current)) {
|
||||
ret = -EINTR;
|
||||
run->exit_reason = KVM_EXIT_INTR;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're using a userspace irqchip, then check if we need
|
||||
* to tell a userspace irqchip about timer or PMU level
|
||||
* changes and if so, exit to userspace (the actual level
|
||||
* state gets updated in kvm_timer_update_run and
|
||||
* kvm_pmu_update_run below).
|
||||
*/
|
||||
if (static_branch_unlikely(&userspace_irqchip_in_use)) {
|
||||
if (kvm_timer_should_notify_user(vcpu) ||
|
||||
kvm_pmu_should_notify_user(vcpu)) {
|
||||
ret = -EINTR;
|
||||
run->exit_reason = KVM_EXIT_INTR;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure we set mode to IN_GUEST_MODE after we disable
|
||||
* interrupts and before the final VCPU requests check.
|
||||
|
@ -809,8 +827,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
|
|||
*/
|
||||
smp_store_mb(vcpu->mode, IN_GUEST_MODE);
|
||||
|
||||
if (ret <= 0 || need_new_vmid_gen(&vcpu->arch.hw_mmu->vmid) ||
|
||||
kvm_request_pending(vcpu)) {
|
||||
if (ret <= 0 || kvm_vcpu_exit_request(vcpu, &ret)) {
|
||||
vcpu->mode = OUTSIDE_GUEST_MODE;
|
||||
isb(); /* Ensure work in x_flush_hwstate is committed */
|
||||
kvm_pmu_sync_hwstate(vcpu);
|
||||
|
|
|
@ -50,6 +50,7 @@ const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
|
|||
STATS_DESC_COUNTER(VCPU, wfi_exit_stat),
|
||||
STATS_DESC_COUNTER(VCPU, mmio_exit_user),
|
||||
STATS_DESC_COUNTER(VCPU, mmio_exit_kernel),
|
||||
STATS_DESC_COUNTER(VCPU, signal_exits),
|
||||
STATS_DESC_COUNTER(VCPU, exits)
|
||||
};
|
||||
static_assert(ARRAY_SIZE(kvm_vcpu_stats_desc) ==
|
||||
|
|
|
@ -2,7 +2,11 @@
|
|||
#ifndef __LINUX_ENTRYKVM_H
|
||||
#define __LINUX_ENTRYKVM_H
|
||||
|
||||
#include <linux/entry-common.h>
|
||||
#include <linux/static_call_types.h>
|
||||
#include <linux/tracehook.h>
|
||||
#include <linux/syscalls.h>
|
||||
#include <linux/seccomp.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/tick.h>
|
||||
|
||||
/* Transfer to guest mode work */
|
||||
|
|
Loading…
Reference in New Issue