[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH RFC V5 2/6] kvm hypervisor : Add a hypercall to KVM hypervisor to support pv-ticketlocks



On Fri, Mar 23, 2012 at 01:37:04PM +0530, Raghavendra K T wrote:
> From: Srivatsa Vaddagiri <vatsa@xxxxxxxxxxxxxxxxxx>
> 
> 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/KVM_CAP_PV_UNHALT.
> 
> Signed-off-by: Srivatsa Vaddagiri <vatsa@xxxxxxxxxxxxxxxxxx>
> Signed-off-by: Suzuki Poulose <suzuki@xxxxxxxxxx>
> Signed-off-by: Raghavendra K T <raghavendra.kt@xxxxxxxxxxxxxxxxxx>
> ---
> diff --git a/arch/x86/include/asm/kvm_para.h b/arch/x86/include/asm/kvm_para.h
> index 734c376..9234f13 100644
> --- a/arch/x86/include/asm/kvm_para.h
> +++ b/arch/x86/include/asm/kvm_para.h
> @@ -16,12 +16,14 @@
>  #define KVM_FEATURE_CLOCKSOURCE              0
>  #define KVM_FEATURE_NOP_IO_DELAY     1
>  #define KVM_FEATURE_MMU_OP           2
> +
>  /* This indicates that the new set of kvmclock msrs
>   * are available. The use of 0x11 and 0x12 is deprecated
>   */
>  #define KVM_FEATURE_CLOCKSOURCE2        3
>  #define KVM_FEATURE_ASYNC_PF         4
>  #define KVM_FEATURE_STEAL_TIME               5
> +#define KVM_FEATURE_PV_UNHALT                6
>  
>  /* The last 8 bits are used to indicate how to interpret the flags field
>   * in pvclock structure. If no bits are set, all flags are ignored.
> @@ -32,6 +34,7 @@
>  #define MSR_KVM_SYSTEM_TIME 0x12
>  
>  #define KVM_MSR_ENABLED 1
> +
>  /* Custom MSRs falls in the range 0x4b564d00-0x4b564dff */
>  #define MSR_KVM_WALL_CLOCK_NEW  0x4b564d00
>  #define MSR_KVM_SYSTEM_TIME_NEW 0x4b564d01
> diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
> index 89b02bf..61388b9 100644
> --- a/arch/x86/kvm/cpuid.c
> +++ b/arch/x86/kvm/cpuid.c
> @@ -408,7 +408,8 @@ static int do_cpuid_ent(struct kvm_cpuid_entry2 *entry, 
> u32 function,
>                            (1 << KVM_FEATURE_NOP_IO_DELAY) |
>                            (1 << KVM_FEATURE_CLOCKSOURCE2) |
>                            (1 << KVM_FEATURE_ASYNC_PF) |
> -                          (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT);
> +                          (1 << KVM_FEATURE_CLOCKSOURCE_STABLE_BIT) |
> +                          (1 << KVM_FEATURE_PV_UNHALT);
>  
>               if (sched_info_on())
>                       entry->eax |= (1 << KVM_FEATURE_STEAL_TIME);
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 9cbfc06..bd5ef91 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -2079,6 +2079,7 @@ int kvm_dev_ioctl_check_extension(long ext)
>       case KVM_CAP_XSAVE:
>       case KVM_CAP_ASYNC_PF:
>       case KVM_CAP_GET_TSC_KHZ:
> +     case KVM_CAP_PV_UNHALT:
>               r = 1;
>               break;
>       case KVM_CAP_COALESCED_MMIO:
> @@ -4913,6 +4914,30 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
>       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, 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) {
> +             vcpu->pv_unhalted = 1;
> +             smp_mb();
> +             kvm_vcpu_kick(vcpu);
> +     }
> +}
> +
>  int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
>  {
>       unsigned long nr, a0, a1, a2, a3, ret;
> @@ -4946,6 +4971,10 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
>       case KVM_HC_VAPIC_POLL_IRQ:
>               ret = 0;
>               break;
> +     case KVM_HC_KICK_CPU:
> +             kvm_pv_kick_cpu_op(vcpu->kvm, a0);
> +             ret = 0;
> +             break;
>       default:
>               ret = -KVM_ENOSYS;
>               break;
> @@ -6174,6 +6203,7 @@ int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
>               !vcpu->arch.apf.halted)
>               || !list_empty_careful(&vcpu->async_pf.done)
>               || vcpu->arch.mp_state == KVM_MP_STATE_SIPI_RECEIVED
> +             || vcpu->pv_unhalted
>               || atomic_read(&vcpu->arch.nmi_queued) ||
>               (kvm_arch_interrupt_allowed(vcpu) &&
>                kvm_cpu_has_interrupt(vcpu));
> diff --git a/include/linux/kvm.h b/include/linux/kvm.h
> index 68e67e5..e822d96 100644
> --- a/include/linux/kvm.h
> +++ b/include/linux/kvm.h
> @@ -558,6 +558,7 @@ struct kvm_ppc_pvinfo {
>  #define KVM_CAP_PPC_PAPR 68
>  #define KVM_CAP_S390_GMAP 71
>  #define KVM_CAP_TSC_DEADLINE_TIMER 72
> +#define KVM_CAP_PV_UNHALT 73
>  
>  #ifdef KVM_CAP_IRQ_ROUTING
>  
> diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> index 900c763..433ae97 100644
> --- a/include/linux/kvm_host.h
> +++ b/include/linux/kvm_host.h
> @@ -158,6 +158,7 @@ struct kvm_vcpu {
>  #endif
>  
>       struct kvm_vcpu_arch arch;
> +     int pv_unhalted;
>  };
>  
>  static inline int kvm_vcpu_exiting_guest_mode(struct kvm_vcpu *vcpu)
> diff --git a/include/linux/kvm_para.h b/include/linux/kvm_para.h
> index ff476dd..38226e1 100644
> --- a/include/linux/kvm_para.h
> +++ b/include/linux/kvm_para.h
> @@ -19,6 +19,7 @@
>  #define KVM_HC_MMU_OP                        2
>  #define KVM_HC_FEATURES                      3
>  #define KVM_HC_PPC_MAP_MAGIC_PAGE    4
> +#define KVM_HC_KICK_CPU                      5
>  
>  /*
>   * hypercalls use architecture specific
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index a91f980..d3b98b1 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -226,6 +226,7 @@ int kvm_vcpu_init(struct kvm_vcpu *vcpu, struct kvm *kvm, 
> unsigned id)
>       vcpu->kvm = kvm;
>       vcpu->vcpu_id = id;
>       vcpu->pid = NULL;
> +     vcpu->pv_unhalted = 0;
>       init_waitqueue_head(&vcpu->wq);
>       kvm_async_pf_vcpu_init(vcpu);
>  
> @@ -1567,6 +1568,9 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
>               prepare_to_wait(&vcpu->wq, &wait, TASK_INTERRUPTIBLE);
>  
>               if (kvm_arch_vcpu_runnable(vcpu)) {
> +                     vcpu->pv_unhalted = 0;
> +                     /* preventing reordering should be enough here */
> +                     barrier();

Is it always OK to erase the notification, even in case an unrelated
event such as interrupt was the source of wakeup?

It would be easier to verify that notifications are not lost with atomic

test_and_clear(pv_unhalted).

Also x86 specific code should remain in arch/x86/kvm/


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.