Commit 6aef266c authored by Srivatsa Vaddagiri's avatar Srivatsa Vaddagiri Committed by Gleb Natapov

kvm hypervisor : Add a hypercall to KVM hypervisor to support pv-ticketlocks

kvm_hc_kick_cpu allows the calling vcpu to kick another vcpu out of halt state.
the presence of these hypercalls is indicated to guest via
kvm_feature_pv_unhalt.

Fold pv_unhalt flag into GET_MP_STATE ioctl to aid migration
During migration, any vcpu that got kicked but did not become runnable
(still in halted state) should be runnable after migration.
Signed-off-by: default avatarSrivatsa Vaddagiri <vatsa@linux.vnet.ibm.com>
Signed-off-by: default avatarSuzuki Poulose <suzuki@in.ibm.com>
[Raghu: Apic related changes, folding pvunhalted into vcpu_runnable
 Added flags for future use (suggested by Gleb)]
[ Raghu: fold pv_unhalt flag as suggested by Eric Northup]
Signed-off-by: default avatarRaghavendra K T <raghavendra.kt@linux.vnet.ibm.com>
Acked-by: default avatarGleb Natapov <gleb@redhat.com>
Acked-by: default avatarIngo Molnar <mingo@kernel.org>
Signed-off-by: default avatarGleb Natapov <gleb@redhat.com>
parent 4b0a8670
...@@ -516,6 +516,11 @@ struct kvm_vcpu_arch { ...@@ -516,6 +516,11 @@ struct kvm_vcpu_arch {
/* set at EPT violation at this point */ /* set at EPT violation at this point */
unsigned long exit_qualification; unsigned long exit_qualification;
/* pv related host specific info */
struct {
bool pv_unhalted;
} pv;
}; };
struct kvm_lpage_info { struct kvm_lpage_info {
......
...@@ -413,7 +413,8 @@ static int do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function, ...@@ -413,7 +413,8 @@ static int do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
(1 << KVM_FEATURE_CLOCKSOURCE2) | (1 << KVM_FEATURE_CLOCKSOURCE2) |
(1 << KVM_FEATURE_ASYNC_PF) | (1 << KVM_FEATURE_ASYNC_PF) |
(1 << KVM_FEATURE_PV_EOI) | (1 << KVM_FEATURE_PV_EOI) |
(1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT); (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT) |
(1 << KVM_FEATURE_PV_UNHALT);
if (sched_info_on()) if (sched_info_on())
entry->eax |= (1 << KVM_FEATURE_STEAL_TIME); entry->eax |= (1 << KVM_FEATURE_STEAL_TIME);
......
...@@ -5588,6 +5588,36 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu) ...@@ -5588,6 +5588,36 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
return 1; return 1;
} }
/*
* kvm_pv_kick_cpu_op: Kick a vcpu.
*
* @apicid - apicid of vcpu to be kicked.
*/
static void kvm_pv_kick_cpu_op(struct kvm *kvm, unsigned long flags, int apicid)
{
struct kvm_vcpu *vcpu = NULL;
int i;
kvm_for_each_vcpu(i, vcpu, kvm) {
if (!kvm_apic_present(vcpu))
continue;
if (kvm_apic_match_dest(vcpu, 0, 0, apicid, 0))
break;
}
if (vcpu) {
/*
* Setting unhalt flag here can result in spurious runnable
* state when unhalt reset does not happen in vcpu_block.
* But that is harmless since that should soon result in halt.
*/
vcpu->arch.pv.pv_unhalted = true;
/* We need everybody see unhalt before vcpu unblocks */
smp_wmb();
kvm_vcpu_kick(vcpu);
}
}
int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
{ {
unsigned long nr, a0, a1, a2, a3, ret; unsigned long nr, a0, a1, a2, a3, ret;
...@@ -5621,6 +5651,10 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu) ...@@ -5621,6 +5651,10 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
case KVM_HC_VAPIC_POLL_IRQ: case KVM_HC_VAPIC_POLL_IRQ:
ret = 0; ret = 0;
break; break;
case KVM_HC_KICK_CPU:
kvm_pv_kick_cpu_op(vcpu->kvm, a0, a1);
ret = 0;
break;
default: default:
ret = -KVM_ENOSYS; ret = -KVM_ENOSYS;
break; break;
...@@ -6043,6 +6077,7 @@ static int __vcpu_run(struct kvm_vcpu *vcpu) ...@@ -6043,6 +6077,7 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
kvm_apic_accept_events(vcpu); kvm_apic_accept_events(vcpu);
switch(vcpu->arch.mp_state) { switch(vcpu->arch.mp_state) {
case KVM_MP_STATE_HALTED: case KVM_MP_STATE_HALTED:
vcpu->arch.pv.pv_unhalted = false;
vcpu->arch.mp_state = vcpu->arch.mp_state =
KVM_MP_STATE_RUNNABLE; KVM_MP_STATE_RUNNABLE;
case KVM_MP_STATE_RUNNABLE: case KVM_MP_STATE_RUNNABLE:
...@@ -6342,7 +6377,12 @@ int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu, ...@@ -6342,7 +6377,12 @@ int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
struct kvm_mp_state *mp_state) struct kvm_mp_state *mp_state)
{ {
kvm_apic_accept_events(vcpu); kvm_apic_accept_events(vcpu);
mp_state->mp_state = vcpu->arch.mp_state; if (vcpu->arch.mp_state == KVM_MP_STATE_HALTED &&
vcpu->arch.pv.pv_unhalted)
mp_state->mp_state = KVM_MP_STATE_RUNNABLE;
else
mp_state->mp_state = vcpu->arch.mp_state;
return 0; return 0;
} }
...@@ -6863,6 +6903,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) ...@@ -6863,6 +6903,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
BUG_ON(vcpu->kvm == NULL); BUG_ON(vcpu->kvm == NULL);
kvm = vcpu->kvm; kvm = vcpu->kvm;
vcpu->arch.pv.pv_unhalted = false;
vcpu->arch.emulate_ctxt.ops = &emulate_ops; vcpu->arch.emulate_ctxt.ops = &emulate_ops;
if (!irqchip_in_kernel(kvm) || kvm_vcpu_is_bsp(vcpu)) if (!irqchip_in_kernel(kvm) || kvm_vcpu_is_bsp(vcpu))
vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE; vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
...@@ -7200,6 +7241,7 @@ int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu) ...@@ -7200,6 +7241,7 @@ int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
!vcpu->arch.apf.halted) !vcpu->arch.apf.halted)
|| !list_empty_careful(&vcpu->async_pf.done) || !list_empty_careful(&vcpu->async_pf.done)
|| kvm_apic_has_events(vcpu) || kvm_apic_has_events(vcpu)
|| vcpu->arch.pv.pv_unhalted
|| atomic_read(&vcpu->arch.nmi_queued) || || atomic_read(&vcpu->arch.nmi_queued) ||
(kvm_arch_interrupt_allowed(vcpu) && (kvm_arch_interrupt_allowed(vcpu) &&
kvm_cpu_has_interrupt(vcpu)); kvm_cpu_has_interrupt(vcpu));
......
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