All of lore.kernel.org
 help / color / mirror / Atom feed
From: Igor Mammedov <imammedo@redhat.com>
To: Roman Kagan <rkagan@virtuozzo.com>
Cc: qemu-devel@nongnu.org, Paolo Bonzini <pbonzini@redhat.com>,
	Eduardo Habkost <ehabkost@redhat.com>,
	Evgeny Yakovlev <eyakovlev@virtuozzo.com>,
	"Denis V . Lunev" <den@openvz.org>
Subject: Re: [Qemu-devel] [PATCH v2 07/23] hyperv: ensure VP index equal to QEMU cpu_index
Date: Wed, 28 Jun 2017 16:47:43 +0200	[thread overview]
Message-ID: <20170628164743.0df730a0@nial.brq.redhat.com> (raw)
In-Reply-To: <20170621162424.10462-8-rkagan@virtuozzo.com>

On Wed, 21 Jun 2017 19:24:08 +0300
Roman Kagan <rkagan@virtuozzo.com> wrote:

> Hyper-V identifies vCPUs by Virtual Processor (VP) index which can be
> queried by the guest via HV_X64_MSR_VP_INDEX msr.  It is defined by the
> spec as a sequential number which can't exceed the maximum number of
> vCPUs per VM.
> 
> It has to be owned by QEMU in order to preserve it across migration.
> 
> However, the initial implementation in KVM didn't allow to set this
> msr, and KVM used its own notion of VP index.  Fortunately, the way
> vCPUs are created in QEMU/KVM makes it likely that the KVM value is
> equal to QEMU cpu_index.
> 
> So choose cpu_index as the value for vp_index, and push that to KVM on
> kernels that support setting the msr.  On older ones that don't, query
> the kernel value and assert that it's in sync with QEMU.
> 
> Besides, since handling errors from vCPU init at hotplug time is
> impossible, disable vCPU hotplug.
proper place to check if cpu might be created is at 
pc_cpu_pre_plug() where you can gracefully abort cpu creation process. 

Also it's possible to create cold-plugged CPUs in out of order
sequence using
 -device cpu-foo on CLI
will be hyperv kvm/guest side ok with it?

> This patch also introduces accessor functions to wrap the mapping
> between a vCPU and its vp_index.  Besides, a few variables are renamed
> to avoid confusion of vp_index with vcpu_id (== apic_id).
> 
> Signed-off-by: Roman Kagan <rkagan@virtuozzo.com>
> ---
> v1 -> v2:
>  - were patches 5, 6 in v1
>  - move vp_index initialization to hyperv_init_vcpu
>  - check capability before trying to set the msr
>  - set the msr on the usual kvm_put_msrs path
>  - disable cpu hotplug if msr is not settable
> 
>  target/i386/hyperv.h |  5 ++++-
>  target/i386/hyperv.c | 16 +++++++++++++---
>  target/i386/kvm.c    | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 68 insertions(+), 4 deletions(-)
> 
> diff --git a/target/i386/hyperv.h b/target/i386/hyperv.h
> index 0c3b562..82f4757 100644
> --- a/target/i386/hyperv.h
> +++ b/target/i386/hyperv.h
> @@ -32,11 +32,14 @@ struct HvSintRoute {
>  
>  int kvm_hv_handle_exit(X86CPU *cpu, struct kvm_hyperv_exit *exit);
>  
> -HvSintRoute *kvm_hv_sint_route_create(uint32_t vcpu_id, uint32_t sint,
> +HvSintRoute *kvm_hv_sint_route_create(uint32_t vp_index, uint32_t sint,
>                                        HvSintAckClb sint_ack_clb);
>  
>  void kvm_hv_sint_route_destroy(HvSintRoute *sint_route);
>  
>  int kvm_hv_sint_route_set_sint(HvSintRoute *sint_route);
>  
> +uint32_t hyperv_vp_index(X86CPU *cpu);
> +X86CPU *hyperv_find_vcpu(uint32_t vp_index);
> +
>  #endif
> diff --git a/target/i386/hyperv.c b/target/i386/hyperv.c
> index 227185c..4f57447 100644
> --- a/target/i386/hyperv.c
> +++ b/target/i386/hyperv.c
> @@ -16,6 +16,16 @@
>  #include "hyperv.h"
>  #include "hyperv_proto.h"
>  
> +uint32_t hyperv_vp_index(X86CPU *cpu)
> +{
> +    return CPU(cpu)->cpu_index;
> +}


> +X86CPU *hyperv_find_vcpu(uint32_t vp_index)
> +{
> +    return X86_CPU(qemu_get_cpu(vp_index));
> +}
this helper isn't used in this patch, add it in the patch that would actually use it

also if  qemu_get_cpu() were called from each CPU init,
it would incur O(N^2) complexity, could you do without it?

> +
>  int kvm_hv_handle_exit(X86CPU *cpu, struct kvm_hyperv_exit *exit)
>  {
>      CPUX86State *env = &cpu->env;
> @@ -72,7 +82,7 @@ static void kvm_hv_sint_ack_handler(EventNotifier *notifier)
>      }
>  }
>  
> -HvSintRoute *kvm_hv_sint_route_create(uint32_t vcpu_id, uint32_t sint,
> +HvSintRoute *kvm_hv_sint_route_create(uint32_t vp_index, uint32_t sint,
>                                        HvSintAckClb sint_ack_clb)
>  {
>      HvSintRoute *sint_route;
> @@ -92,7 +102,7 @@ HvSintRoute *kvm_hv_sint_route_create(uint32_t vcpu_id, uint32_t sint,
>      event_notifier_set_handler(&sint_route->sint_ack_notifier,
>                                 kvm_hv_sint_ack_handler);
>  
> -    gsi = kvm_irqchip_add_hv_sint_route(kvm_state, vcpu_id, sint);
> +    gsi = kvm_irqchip_add_hv_sint_route(kvm_state, vp_index, sint);
>      if (gsi < 0) {
>          goto err_gsi;
>      }
> @@ -105,7 +115,7 @@ HvSintRoute *kvm_hv_sint_route_create(uint32_t vcpu_id, uint32_t sint,
>      }
>      sint_route->gsi = gsi;
>      sint_route->sint_ack_clb = sint_ack_clb;
> -    sint_route->vcpu_id = vcpu_id;
> +    sint_route->vcpu_id = vp_index;
                   ^^^ - shouldn't it also be re-named?

maybe split all renaming into separate patch ...

>      sint_route->sint = sint;
>  
>      return sint_route;
> diff --git a/target/i386/kvm.c b/target/i386/kvm.c
> index 2795b63..9bf7f08 100644
> --- a/target/i386/kvm.c
> +++ b/target/i386/kvm.c
> @@ -86,6 +86,7 @@ static bool has_msr_hv_hypercall;
>  static bool has_msr_hv_crash;
>  static bool has_msr_hv_reset;
>  static bool has_msr_hv_vpindex;
> +static bool is_hv_vpindex_settable;
>  static bool has_msr_hv_runtime;
>  static bool has_msr_hv_synic;
>  static bool has_msr_hv_stimer;
> @@ -665,6 +666,43 @@ static int hyperv_handle_properties(CPUState *cs)
>      return 0;
>  }
>  
> +static int hyperv_init_vcpu(X86CPU *cpu)
> +{
> +    if (cpu->hyperv_vpindex && !is_hv_vpindex_settable) {
> +        /*
> +         * the kernel doesn't support setting vp_index; assert that its value
> +         * is in sync
> +         */
> +        int ret;
> +        struct {
> +            struct kvm_msrs info;
> +            struct kvm_msr_entry entries[1];
> +        } msr_data = {
> +            .info.nmsrs = 1,
> +            .entries[0].index = HV_X64_MSR_VP_INDEX,
> +        };
> +
> +        /*
> +         * handling errors from vcpu init at hotplug time is impossible, so
> +         * disallow cpu hotplug
> +         */
> +        MACHINE_GET_CLASS(current_machine)->hot_add_cpu = NULL;
one shouldn't alter machine this way nor
it would disable cpu hotplug, it would disable only cpu-add interface
but device_add() would still work.


> +        ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, &msr_data);
> +        if (ret < 0) {
when this can fail?

> +            return ret;
> +        }
> +        assert(ret == 1);
> +
> +        if (msr_data.entries[0].data != hyperv_vp_index(cpu)) {
> +            fprintf(stderr, "kernel's vp_index != QEMU's vp_index\n");
error_report()

> +            return -ENXIO;
> +        }
> +    }
> +
> +    return 0;
> +}
> +
>  static Error *invtsc_mig_blocker;
>  
>  #define KVM_MAX_CPUID_ENTRIES  100
> @@ -1013,6 +1051,13 @@ int kvm_arch_init_vcpu(CPUState *cs)
>          has_msr_tsc_aux = false;
>      }
>  
> +    if (hyperv_enabled(cpu)) {
> +        r = hyperv_init_vcpu(cpu);
> +        if (r) {
> +            goto fail;
> +        }
> +    }
> +
>      return 0;
>  
>   fail:
> @@ -1204,6 +1249,8 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
>      has_pit_state2 = kvm_check_extension(s, KVM_CAP_PIT_STATE2);
>  #endif
>  
> +    is_hv_vpindex_settable = kvm_check_extension(s, KVM_CAP_HYPERV_VP_INDEX);
> +
>      ret = kvm_get_supported_msrs(s);
>      if (ret < 0) {
>          return ret;
> @@ -1748,6 +1795,10 @@ static int kvm_put_msrs(X86CPU *cpu, int level)
>          if (has_msr_hv_runtime) {
>              kvm_msr_entry_add(cpu, HV_X64_MSR_VP_RUNTIME, env->msr_hv_runtime);
>          }
> +        if (cpu->hyperv_vpindex && has_msr_hv_vpindex &&
> +            is_hv_vpindex_settable) {
> +            kvm_msr_entry_add(cpu, HV_X64_MSR_VP_INDEX, hyperv_vp_index(cpu));
> +        }
>          if (cpu->hyperv_synic) {
>              int j;
>  

  reply	other threads:[~2017-06-28 14:48 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-06-21 16:24 [Qemu-devel] [PATCH v2 00/23] hyperv fixes and enhancements Roman Kagan
2017-06-21 16:24 ` [Qemu-devel] [PATCH v2 01/23] hyperv: add header with protocol definitions Roman Kagan
2017-06-21 16:24 ` [Qemu-devel] [PATCH v2 02/23] update-linux-headers: prepare for hyperv.h removal Roman Kagan
2017-06-21 16:24 ` [Qemu-devel] [PATCH v2 03/23] hyperv: set partition-wide MSRs only on first vcpu Roman Kagan
2017-06-21 16:24 ` [Qemu-devel] [PATCH v2 04/23] hyperv: ensure SINTx msrs are reset properly Roman Kagan
2017-06-21 16:24 ` [Qemu-devel] [PATCH v2 05/23] hyperv: make SynIC version msr constant Roman Kagan
2017-06-21 16:24 ` [Qemu-devel] [PATCH v2 06/23] [not to commit] add new hyperv-related caps Roman Kagan
2017-06-21 16:24 ` [Qemu-devel] [PATCH v2 07/23] hyperv: ensure VP index equal to QEMU cpu_index Roman Kagan
2017-06-28 14:47   ` Igor Mammedov [this message]
2017-06-29  9:53     ` Roman Kagan
2017-06-29 11:53       ` Igor Mammedov
2017-06-29 13:10         ` Roman Kagan
2017-06-29 14:39           ` Igor Mammedov
2017-06-29 17:31             ` Roman Kagan
2017-06-21 16:24 ` [Qemu-devel] [PATCH v2 08/23] hyperv_testdev: refactor for readability Roman Kagan
2017-06-21 16:24 ` [Qemu-devel] [PATCH v2 09/23] hyperv: cosmetic: g_malloc -> g_new Roman Kagan
2017-06-21 16:24 ` [Qemu-devel] [PATCH v2 10/23] hyperv: synic: only setup ack notifier if there's a callback Roman Kagan
2017-06-21 16:24 ` [Qemu-devel] [PATCH v2 11/23] hyperv: allow passing arbitrary data to sint ack callback Roman Kagan
2017-06-21 16:24 ` [Qemu-devel] [PATCH v2 12/23] hyperv: address HvSintRoute by X86CPU pointer Roman Kagan
2017-06-21 16:24 ` [Qemu-devel] [PATCH v2 13/23] hyperv: make HvSintRoute reference-counted Roman Kagan
2017-06-21 16:24 ` [Qemu-devel] [PATCH v2 14/23] hyperv: qom-ify SynIC Roman Kagan
2017-06-29 15:05   ` Igor Mammedov
2017-06-29 17:51     ` Roman Kagan
2017-07-07 12:22       ` Igor Mammedov
2017-07-07 12:47         ` Roman Kagan
2017-07-07 13:27           ` Igor Mammedov
2017-06-21 16:24 ` [Qemu-devel] [PATCH v2 15/23] hyperv: block SynIC use in QEMU in incompatible configurations Roman Kagan
2017-06-21 16:24 ` [Qemu-devel] [PATCH v2 16/23] hyperv: make overlay pages for SynIC Roman Kagan
2017-06-21 16:24 ` [Qemu-devel] [PATCH v2 18/23] hyperv: add synic event flag signaling Roman Kagan
2017-06-21 16:24 ` [Qemu-devel] [PATCH v2 19/23] hyperv: process SIGNAL_EVENT hypercall Roman Kagan
2017-06-21 16:24 ` [Qemu-devel] [PATCH v2 20/23] hyperv: process POST_MESSAGE hypercall Roman Kagan
2017-06-21 16:24 ` [Qemu-devel] [PATCH v2 21/23] hyperv_testdev: add SynIC message and event testmodes Roman Kagan
2017-06-21 16:24 ` [Qemu-devel] [PATCH v2 22/23] MAINTAINERS: add myself and eyakovlev@ for hyperv* Roman Kagan
2017-06-21 16:24 ` [Qemu-devel] [PATCH v2 23/23] hyperv: update copyright notices Roman Kagan
2017-06-29 15:20 ` [Qemu-devel] [PATCH v2 00/23] hyperv fixes and enhancements Igor Mammedov
2017-06-29 17:58   ` Roman Kagan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170628164743.0df730a0@nial.brq.redhat.com \
    --to=imammedo@redhat.com \
    --cc=den@openvz.org \
    --cc=ehabkost@redhat.com \
    --cc=eyakovlev@virtuozzo.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=rkagan@virtuozzo.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.