Commit acd05785 authored by David Matlack's avatar David Matlack Committed by Paolo Bonzini

kvm: add capability for halt polling

KVM_CAP_HALT_POLL is a per-VM capability that lets userspace
control the halt-polling time, allowing halt-polling to be tuned or
disabled on particular VMs.

With dynamic halt-polling, a VM's VCPUs can poll from anywhere from
[0, halt_poll_ns] on each halt. KVM_CAP_HALT_POLL sets the
upper limit on the poll time.
Signed-off-by: default avatarDavid Matlack <dmatlack@google.com>
Signed-off-by: default avatarJon Cargille <jcargill@google.com>
Reviewed-by: default avatarJim Mattson <jmattson@google.com>
Message-Id: <20200417221446.108733-1-jcargill@google.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 87796555
...@@ -5802,6 +5802,23 @@ If present, this capability can be enabled for a VM, meaning that KVM ...@@ -5802,6 +5802,23 @@ If present, this capability can be enabled for a VM, meaning that KVM
will allow the transition to secure guest mode. Otherwise KVM will will allow the transition to secure guest mode. Otherwise KVM will
veto the transition. veto the transition.
7.20 KVM_CAP_HALT_POLL
----------------------
:Architectures: all
:Target: VM
:Parameters: args[0] is the maximum poll time in nanoseconds
:Returns: 0 on success; -1 on error
This capability overrides the kvm module parameter halt_poll_ns for the
target VM.
VCPU polling allows a VCPU to poll for wakeup events instead of immediately
scheduling during guest halts. The maximum time a VCPU can spend polling is
controlled by the kvm module parameter halt_poll_ns. This capability allows
the maximum halt time to specified on a per-VM basis, effectively overriding
the module parameter for the target VM.
8. Other capabilities. 8. Other capabilities.
====================== ======================
......
...@@ -503,6 +503,7 @@ struct kvm { ...@@ -503,6 +503,7 @@ struct kvm {
struct srcu_struct srcu; struct srcu_struct srcu;
struct srcu_struct irq_srcu; struct srcu_struct irq_srcu;
pid_t userspace_pid; pid_t userspace_pid;
unsigned int max_halt_poll_ns;
}; };
#define kvm_err(fmt, ...) \ #define kvm_err(fmt, ...) \
......
...@@ -1017,6 +1017,7 @@ struct kvm_ppc_resize_hpt { ...@@ -1017,6 +1017,7 @@ struct kvm_ppc_resize_hpt {
#define KVM_CAP_S390_VCPU_RESETS 179 #define KVM_CAP_S390_VCPU_RESETS 179
#define KVM_CAP_S390_PROTECTED 180 #define KVM_CAP_S390_PROTECTED 180
#define KVM_CAP_PPC_SECURE_GUEST 181 #define KVM_CAP_PPC_SECURE_GUEST 181
#define KVM_CAP_HALT_POLL 182
#ifdef KVM_CAP_IRQ_ROUTING #ifdef KVM_CAP_IRQ_ROUTING
......
...@@ -710,6 +710,8 @@ static struct kvm *kvm_create_vm(unsigned long type) ...@@ -710,6 +710,8 @@ static struct kvm *kvm_create_vm(unsigned long type)
goto out_err_no_arch_destroy_vm; goto out_err_no_arch_destroy_vm;
} }
kvm->max_halt_poll_ns = halt_poll_ns;
r = kvm_arch_init_vm(kvm, type); r = kvm_arch_init_vm(kvm, type);
if (r) if (r)
goto out_err_no_arch_destroy_vm; goto out_err_no_arch_destroy_vm;
...@@ -2713,15 +2715,16 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu) ...@@ -2713,15 +2715,16 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
if (!kvm_arch_no_poll(vcpu)) { if (!kvm_arch_no_poll(vcpu)) {
if (!vcpu_valid_wakeup(vcpu)) { if (!vcpu_valid_wakeup(vcpu)) {
shrink_halt_poll_ns(vcpu); shrink_halt_poll_ns(vcpu);
} else if (halt_poll_ns) { } else if (vcpu->kvm->max_halt_poll_ns) {
if (block_ns <= vcpu->halt_poll_ns) if (block_ns <= vcpu->halt_poll_ns)
; ;
/* we had a long block, shrink polling */ /* we had a long block, shrink polling */
else if (vcpu->halt_poll_ns && block_ns > halt_poll_ns) else if (vcpu->halt_poll_ns &&
block_ns > vcpu->kvm->max_halt_poll_ns)
shrink_halt_poll_ns(vcpu); shrink_halt_poll_ns(vcpu);
/* we had a short halt and our poll time is too small */ /* we had a short halt and our poll time is too small */
else if (vcpu->halt_poll_ns < halt_poll_ns && else if (vcpu->halt_poll_ns < vcpu->kvm->max_halt_poll_ns &&
block_ns < halt_poll_ns) block_ns < vcpu->kvm->max_halt_poll_ns)
grow_halt_poll_ns(vcpu); grow_halt_poll_ns(vcpu);
} else { } else {
vcpu->halt_poll_ns = 0; vcpu->halt_poll_ns = 0;
...@@ -3510,6 +3513,7 @@ static long kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg) ...@@ -3510,6 +3513,7 @@ static long kvm_vm_ioctl_check_extension_generic(struct kvm *kvm, long arg)
case KVM_CAP_IOEVENTFD_ANY_LENGTH: case KVM_CAP_IOEVENTFD_ANY_LENGTH:
case KVM_CAP_CHECK_EXTENSION_VM: case KVM_CAP_CHECK_EXTENSION_VM:
case KVM_CAP_ENABLE_CAP_VM: case KVM_CAP_ENABLE_CAP_VM:
case KVM_CAP_HALT_POLL:
return 1; return 1;
#ifdef CONFIG_KVM_MMIO #ifdef CONFIG_KVM_MMIO
case KVM_CAP_COALESCED_MMIO: case KVM_CAP_COALESCED_MMIO:
...@@ -3560,6 +3564,13 @@ static int kvm_vm_ioctl_enable_cap_generic(struct kvm *kvm, ...@@ -3560,6 +3564,13 @@ static int kvm_vm_ioctl_enable_cap_generic(struct kvm *kvm,
return 0; return 0;
} }
#endif #endif
case KVM_CAP_HALT_POLL: {
if (cap->flags || cap->args[0] != (unsigned int)cap->args[0])
return -EINVAL;
kvm->max_halt_poll_ns = cap->args[0];
return 0;
}
default: default:
return kvm_vm_ioctl_enable_cap(kvm, cap); return kvm_vm_ioctl_enable_cap(kvm, cap);
} }
......
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