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

[Xen-devel] [RFC PATCH 07/16] x86/xen: make vcpu_info part of xenhost_t



Abstract out xen_vcpu_id probing via (*probe_vcpu_id)(). Once that is
availab,e the vcpu_info registration happens via the VCPUOP hypercall.

Note that for the nested case, there are two vcpu_ids, and two vcpu_info
areas, one each for the default xenhost and the remote xenhost.
The vcpu_info is used via pv_irq_ops, and evtchn signaling.

The other VCPUOP hypercalls are used for management (and scheduling)
which is expected to be done purely in the default hypervisor.
However, scheduling of L1-guest does imply L0-Xen-vcpu_info switching,
which might mean that the remote hypervisor needs some visibility
into related events/hypercalls in the default hypervisor.

TODO:
  - percpu data structures for xen_vcpu

Signed-off-by: Ankur Arora <ankur.a.arora@xxxxxxxxxx>
---
 arch/x86/xen/enlighten.c         | 93 +++++++++++++-------------------
 arch/x86/xen/enlighten_hvm.c     | 87 ++++++++++++++++++------------
 arch/x86/xen/enlighten_pv.c      | 60 ++++++++++++++-------
 arch/x86/xen/enlighten_pvh.c     |  3 +-
 arch/x86/xen/irq.c               | 10 ++--
 arch/x86/xen/mmu_pv.c            |  6 +--
 arch/x86/xen/pci-swiotlb-xen.c   |  1 +
 arch/x86/xen/setup.c             |  1 +
 arch/x86/xen/smp.c               |  9 +++-
 arch/x86/xen/smp_hvm.c           | 17 +++---
 arch/x86/xen/smp_pv.c            | 12 ++---
 arch/x86/xen/time.c              | 23 ++++----
 arch/x86/xen/xen-ops.h           |  5 +-
 drivers/xen/events/events_base.c | 14 ++---
 drivers/xen/events/events_fifo.c |  2 +-
 drivers/xen/evtchn.c             |  2 +-
 drivers/xen/time.c               |  2 +-
 include/xen/xen-ops.h            |  7 +--
 include/xen/xenhost.h            | 47 ++++++++++++++++
 19 files changed, 240 insertions(+), 161 deletions(-)

diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 20e0de844442..0dafbbc838ef 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -20,35 +20,6 @@
 #include "smp.h"
 #include "pmu.h"
 
-/*
- * Pointer to the xen_vcpu_info structure or
- * &HYPERVISOR_shared_info->vcpu_info[cpu]. See xen_hvm_init_shared_info
- * and xen_vcpu_setup for details. By default it points to 
share_info->vcpu_info
- * but if the hypervisor supports VCPUOP_register_vcpu_info then it can point
- * to xen_vcpu_info. The pointer is used in __xen_evtchn_do_upcall to
- * acknowledge pending events.
- * Also more subtly it is used by the patched version of irq enable/disable
- * e.g. xen_irq_enable_direct and xen_iret in PV mode.
- *
- * The desire to be able to do those mask/unmask operations as a single
- * instruction by using the per-cpu offset held in %gs is the real reason
- * vcpu info is in a per-cpu pointer and the original reason for this
- * hypercall.
- *
- */
-DEFINE_PER_CPU(struct vcpu_info *, xen_vcpu);
-
-/*
- * Per CPU pages used if hypervisor supports VCPUOP_register_vcpu_info
- * hypercall. This can be used both in PV and PVHVM mode. The structure
- * overrides the default per_cpu(xen_vcpu, cpu) value.
- */
-DEFINE_PER_CPU(struct vcpu_info, xen_vcpu_info);
-
-/* Linux <-> Xen vCPU id mapping */
-DEFINE_PER_CPU(uint32_t, xen_vcpu_id);
-EXPORT_PER_CPU_SYMBOL(xen_vcpu_id);
-
 enum xen_domain_type xen_domain_type = XEN_NATIVE;
 EXPORT_SYMBOL_GPL(xen_domain_type);
 
@@ -112,12 +83,12 @@ int xen_cpuhp_setup(int (*cpu_up_prepare_cb)(unsigned int),
        return rc >= 0 ? 0 : rc;
 }
 
-static int xen_vcpu_setup_restore(int cpu)
+static int xen_vcpu_setup_restore(xenhost_t *xh, int cpu)
 {
        int rc = 0;
 
        /* Any per_cpu(xen_vcpu) is stale, so reset it */
-       xen_vcpu_info_reset(cpu);
+       xen_vcpu_info_reset(xh, cpu);
 
        /*
         * For PVH and PVHVM, setup online VCPUs only. The rest will
@@ -125,7 +96,7 @@ static int xen_vcpu_setup_restore(int cpu)
         */
        if (xen_pv_domain() ||
            (xen_hvm_domain() && cpu_online(cpu))) {
-               rc = xen_vcpu_setup(cpu);
+               rc = xen_vcpu_setup(xh, cpu);
        }
 
        return rc;
@@ -138,30 +109,42 @@ static int xen_vcpu_setup_restore(int cpu)
  */
 void xen_vcpu_restore(void)
 {
-       int cpu, rc;
+       int cpu, rc = 0;
 
+       /*
+        * VCPU management is primarily the responsibility of xh_default and
+        * xh_remote only needs VCPUOP_register_vcpu_info.
+        * So, we do VPUOP_down and VCPUOP_up only on xh_default.
+        *
+        * (Currently, however, VCPUOP_register_vcpu_info is allowed only
+        * on VCPUs that are self or down, so we might need a new model
+        * there.)
+        */
        for_each_possible_cpu(cpu) {
                bool other_cpu = (cpu != smp_processor_id());
                bool is_up;
+               xenhost_t **xh;
 
-               if (xen_vcpu_nr(cpu) == XEN_VCPU_ID_INVALID)
+               if (xen_vcpu_nr(xh_default, cpu) == XEN_VCPU_ID_INVALID)
                        continue;
 
                /* Only Xen 4.5 and higher support this. */
                is_up = HYPERVISOR_vcpu_op(VCPUOP_is_up,
-                                          xen_vcpu_nr(cpu), NULL) > 0;
+                                          xen_vcpu_nr(xh_default, cpu), NULL) 
> 0;
 
                if (other_cpu && is_up &&
-                   HYPERVISOR_vcpu_op(VCPUOP_down, xen_vcpu_nr(cpu), NULL))
+                   HYPERVISOR_vcpu_op(VCPUOP_down, xen_vcpu_nr(xh_default, 
cpu), NULL))
                        BUG();
 
                if (xen_pv_domain() || xen_feature(XENFEAT_hvm_safe_pvclock))
                        xen_setup_runstate_info(cpu);
 
-               rc = xen_vcpu_setup_restore(cpu);
-               if (rc)
-                       pr_emerg_once("vcpu restore failed for cpu=%d err=%d. "
-                                       "System will hang.\n", cpu, rc);
+               for_each_xenhost(xh) {
+                       rc = xen_vcpu_setup_restore(*xh, cpu);
+                       if (rc)
+                               pr_emerg_once("vcpu restore failed for cpu=%d 
err=%d. "
+                                               "System will hang.\n", cpu, rc);
+               }
                /*
                 * In case xen_vcpu_setup_restore() fails, do not bring up the
                 * VCPU. This helps us avoid the resulting OOPS when the VCPU
@@ -172,29 +155,29 @@ void xen_vcpu_restore(void)
                 * VCPUs to come up.
                 */
                if (other_cpu && is_up && (rc == 0) &&
-                   HYPERVISOR_vcpu_op(VCPUOP_up, xen_vcpu_nr(cpu), NULL))
+                   HYPERVISOR_vcpu_op(VCPUOP_up, xen_vcpu_nr(xh_default, cpu), 
NULL))
                        BUG();
        }
 }
 
-void xen_vcpu_info_reset(int cpu)
+void xen_vcpu_info_reset(xenhost_t *xh, int cpu)
 {
-       if (xen_vcpu_nr(cpu) < MAX_VIRT_CPUS) {
-               per_cpu(xen_vcpu, cpu) =
-                       
&xh_default->HYPERVISOR_shared_info->vcpu_info[xen_vcpu_nr(cpu)];
+       if (xen_vcpu_nr(xh, cpu) < MAX_VIRT_CPUS) {
+               xh->xen_vcpu[cpu] =
+                       &xh->HYPERVISOR_shared_info->vcpu_info[xen_vcpu_nr(xh, 
cpu)];
        } else {
                /* Set to NULL so that if somebody accesses it we get an OOPS */
-               per_cpu(xen_vcpu, cpu) = NULL;
+               xh->xen_vcpu[cpu] = NULL;
        }
 }
 
-int xen_vcpu_setup(int cpu)
+int xen_vcpu_setup(xenhost_t *xh, int cpu)
 {
        struct vcpu_register_vcpu_info info;
        int err;
        struct vcpu_info *vcpup;
 
-       BUG_ON(xh_default->HYPERVISOR_shared_info == &xen_dummy_shared_info);
+       BUG_ON(xh->HYPERVISOR_shared_info == &xen_dummy_shared_info);
 
        /*
         * This path is called on PVHVM at bootup (xen_hvm_smp_prepare_boot_cpu)
@@ -208,12 +191,12 @@ int xen_vcpu_setup(int cpu)
         * use this function.
         */
        if (xen_hvm_domain()) {
-               if (per_cpu(xen_vcpu, cpu) == &per_cpu(xen_vcpu_info, cpu))
+               if (xh->xen_vcpu[cpu] == &xh->xen_vcpu_info[cpu])
                        return 0;
        }
 
        if (xen_have_vcpu_info_placement) {
-               vcpup = &per_cpu(xen_vcpu_info, cpu);
+               vcpup = &xh->xen_vcpu_info[cpu];
                info.mfn = arbitrary_virt_to_mfn(vcpup);
                info.offset = offset_in_page(vcpup);
 
@@ -227,8 +210,8 @@ int xen_vcpu_setup(int cpu)
                 * hypercall does not allow to over-write info.mfn and
                 * info.offset.
                 */
-               err = HYPERVISOR_vcpu_op(VCPUOP_register_vcpu_info,
-                                        xen_vcpu_nr(cpu), &info);
+               err = hypervisor_vcpu_op(xh, VCPUOP_register_vcpu_info,
+                                        xen_vcpu_nr(xh, cpu), &info);
 
                if (err) {
                        pr_warn_once("register_vcpu_info failed: cpu=%d 
err=%d\n",
@@ -239,14 +222,14 @@ int xen_vcpu_setup(int cpu)
                         * This cpu is using the registered vcpu info, even if
                         * later ones fail to.
                         */
-                       per_cpu(xen_vcpu, cpu) = vcpup;
+                       xh->xen_vcpu[cpu] = vcpup;
                }
        }
 
        if (!xen_have_vcpu_info_placement)
-               xen_vcpu_info_reset(cpu);
+               xen_vcpu_info_reset(xh, cpu);
 
-       return ((per_cpu(xen_vcpu, cpu) == NULL) ? -ENODEV : 0);
+       return ((xh->xen_vcpu[cpu] == NULL) ? -ENODEV : 0);
 }
 
 void xen_reboot(int reason)
diff --git a/arch/x86/xen/enlighten_hvm.c b/arch/x86/xen/enlighten_hvm.c
index 0e53363f9d1f..c1981a3e4989 100644
--- a/arch/x86/xen/enlighten_hvm.c
+++ b/arch/x86/xen/enlighten_hvm.c
@@ -5,6 +5,7 @@
 #include <linux/kexec.h>
 #include <linux/memblock.h>
 
+#include <xen/interface/xen.h>
 #include <xen/xenhost.h>
 #include <xen/features.h>
 #include <xen/events.h>
@@ -72,22 +73,22 @@ static void __init xen_hvm_init_mem_mapping(void)
 {
        xenhost_t **xh;
 
-       for_each_xenhost(xh)
+       for_each_xenhost(xh) {
                xenhost_reset_shared_info(*xh);
 
-       /*
-        * The virtual address of the shared_info page has changed, so
-        * the vcpu_info pointer for VCPU 0 is now stale.
-        *
-        * The prepare_boot_cpu callback will re-initialize it via
-        * xen_vcpu_setup, but we can't rely on that to be called for
-        * old Xen versions (xen_have_vector_callback == 0).
-        *
-        * It is, in any case, bad to have a stale vcpu_info pointer
-        * so reset it now.
-        * For now, this uses xh_default implictly.
-        */
-       xen_vcpu_info_reset(0);
+               /*
+                * The virtual address of the shared_info page has changed, so
+                * the vcpu_info pointer for VCPU 0 is now stale.
+                *
+                * The prepare_boot_cpu callback will re-initialize it via
+                * xen_vcpu_setup, but we can't rely on that to be called for
+                * old Xen versions (xen_have_vector_callback == 0).
+                *
+                * It is, in any case, bad to have a stale vcpu_info pointer
+                * so reset it now.
+                */
+               xen_vcpu_info_reset(*xh, 0);
+       }
 }
 
 extern uint32_t xen_pv_cpuid_base(xenhost_t *xh);
@@ -103,11 +104,32 @@ void xen_hvm_setup_hypercall_page(xenhost_t *xh)
        xh->hypercall_page = xen_hypercall_page;
 }
 
+static void xen_hvm_probe_vcpu_id(xenhost_t *xh, int cpu)
+{
+       uint32_t eax, ebx, ecx, edx, base;
+
+       base = xenhost_cpuid_base(xh);
+
+       if (cpu == 0) {
+               cpuid(base + 4, &eax, &ebx, &ecx, &edx);
+               if (eax & XEN_HVM_CPUID_VCPU_ID_PRESENT)
+                       xh->xen_vcpu_id[cpu] = ebx;
+               else
+                       xh->xen_vcpu_id[cpu] = smp_processor_id();
+       } else {
+               if (cpu_acpi_id(cpu) != U32_MAX)
+                       xh->xen_vcpu_id[cpu] = cpu_acpi_id(cpu);
+               else
+                       xh->xen_vcpu_id[cpu] = cpu;
+       }
+}
+
 xenhost_ops_t xh_hvm_ops = {
        .cpuid_base = xen_pv_cpuid_base,
        .setup_hypercall_page = xen_hvm_setup_hypercall_page,
        .setup_shared_info = xen_hvm_init_shared_info,
        .reset_shared_info = xen_hvm_reset_shared_info,
+       .probe_vcpu_id = xen_hvm_probe_vcpu_id,
 };
 
 xenhost_ops_t xh_hvm_nested_ops = {
@@ -116,7 +138,7 @@ xenhost_ops_t xh_hvm_nested_ops = {
 static void __init init_hvm_pv_info(void)
 {
        int major, minor;
-       uint32_t eax, ebx, ecx, edx, base;
+       uint32_t eax, base;
        xenhost_t **xh;
 
        base = xenhost_cpuid_base(xh_default);
@@ -147,11 +169,8 @@ static void __init init_hvm_pv_info(void)
        if (xen_validate_features() == false)
                __xenhost_unregister(xenhost_r2);
 
-       cpuid(base + 4, &eax, &ebx, &ecx, &edx);
-       if (eax & XEN_HVM_CPUID_VCPU_ID_PRESENT)
-               this_cpu_write(xen_vcpu_id, ebx);
-       else
-               this_cpu_write(xen_vcpu_id, smp_processor_id());
+       for_each_xenhost(xh)
+               xenhost_probe_vcpu_id(*xh, smp_processor_id());
 }
 
 #ifdef CONFIG_KEXEC_CORE
@@ -172,6 +191,7 @@ static void xen_hvm_crash_shutdown(struct pt_regs *regs)
 static int xen_cpu_up_prepare_hvm(unsigned int cpu)
 {
        int rc = 0;
+       xenhost_t **xh;
 
        /*
         * This can happen if CPU was offlined earlier and
@@ -182,13 +202,12 @@ static int xen_cpu_up_prepare_hvm(unsigned int cpu)
                xen_uninit_lock_cpu(cpu);
        }
 
-       if (cpu_acpi_id(cpu) != U32_MAX)
-               per_cpu(xen_vcpu_id, cpu) = cpu_acpi_id(cpu);
-       else
-               per_cpu(xen_vcpu_id, cpu) = cpu;
-       rc = xen_vcpu_setup(cpu);
-       if (rc)
-               return rc;
+       for_each_xenhost(xh) {
+               xenhost_probe_vcpu_id(*xh, cpu);
+               rc = xen_vcpu_setup(*xh, cpu);
+               if (rc)
+                       return rc;
+       }
 
        if (xen_have_vector_callback && xen_feature(XENFEAT_hvm_safe_pvclock))
                xen_setup_timer(cpu);
@@ -229,15 +248,15 @@ static void __init xen_hvm_guest_init(void)
        for_each_xenhost(xh) {
                reserve_shared_info(*xh);
                xenhost_setup_shared_info(*xh);
+
+               /*
+                * xen_vcpu is a pointer to the vcpu_info struct in the
+                * shared_info page, we use it in the event channel upcall
+                * and in some pvclock related functions.
+                */
+               xen_vcpu_info_reset(*xh, 0);
        }
 
-       /*
-        * xen_vcpu is a pointer to the vcpu_info struct in the shared_info
-        * page, we use it in the event channel upcall and in some pvclock
-        * related functions.
-        * For now, this uses xh_default implictly.
-        */
-       xen_vcpu_info_reset(0);
 
        xen_panic_handler_init();
 
diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
index 1a9eded4b76b..5f6a1475ec0c 100644
--- a/arch/x86/xen/enlighten_pv.c
+++ b/arch/x86/xen/enlighten_pv.c
@@ -36,8 +36,8 @@
 
 #include <xen/xen.h>
 #include <xen/events.h>
-#include <xen/xenhost.h>
 #include <xen/interface/xen.h>
+#include <xen/xenhost.h>
 #include <xen/interface/version.h>
 #include <xen/interface/physdev.h>
 #include <xen/interface/vcpu.h>
@@ -126,12 +126,12 @@ static void __init xen_pv_init_platform(void)
 
        populate_extra_pte(fix_to_virt(FIX_PARAVIRT_BOOTMAP));
 
-       for_each_xenhost(xh)
+       for_each_xenhost(xh) {
                xenhost_setup_shared_info(*xh);
 
-       /* xen clock uses per-cpu vcpu_info, need to init it for boot cpu */
-       /* For now this uses xh_default implicitly. */
-       xen_vcpu_info_reset(0);
+               /* xen clock uses per-cpu vcpu_info, need to init it for boot 
cpu */
+               xen_vcpu_info_reset(*xh, 0);
+       }
 
        /* pvclock is in shared info area */
        xen_init_time_ops();
@@ -973,28 +973,31 @@ static void xen_write_msr(unsigned int msr, unsigned low, 
unsigned high)
 /* This is called once we have the cpu_possible_mask */
 void __init xen_setup_vcpu_info_placement(void)
 {
+       xenhost_t **xh;
        int cpu;
 
        for_each_possible_cpu(cpu) {
-               /* Set up direct vCPU id mapping for PV guests. */
-               per_cpu(xen_vcpu_id, cpu) = cpu;
+               for_each_xenhost(xh) {
+                       xenhost_probe_vcpu_id(*xh, cpu);
 
-               /*
-                * xen_vcpu_setup(cpu) can fail  -- in which case it
-                * falls back to the shared_info version for cpus
-                * where xen_vcpu_nr(cpu) < MAX_VIRT_CPUS.
-                *
-                * xen_cpu_up_prepare_pv() handles the rest by failing
-                * them in hotplug.
-                */
-               (void) xen_vcpu_setup(cpu);
+                       /*
+                        * xen_vcpu_setup(cpu) can fail  -- in which case it
+                        * falls back to the shared_info version for cpus
+                        * where xen_vcpu_nr(cpu) < MAX_VIRT_CPUS.
+                        *
+                        * xen_cpu_up_prepare_pv() handles the rest by failing
+                        * them in hotplug.
+                        */
+                       (void) xen_vcpu_setup(*xh, cpu);
+               }
        }
 
        /*
         * xen_vcpu_setup managed to place the vcpu_info within the
         * percpu area for all cpus, so make use of it.
         */
-       if (xen_have_vcpu_info_placement) {
+       if (xen_have_vcpu_info_placement && false) {
+               /* Disable direct access until we have proper pcpu data 
structures. */
                pv_ops.irq.save_fl = __PV_IS_CALLEE_SAVE(xen_save_fl_direct);
                pv_ops.irq.restore_fl =
                        __PV_IS_CALLEE_SAVE(xen_restore_fl_direct);
@@ -1110,6 +1113,11 @@ static unsigned char xen_get_nmi_reason(void)
 {
        unsigned char reason = 0;
 
+       /*
+        * We could get this information from all the xenhosts and OR it.
+        * But, the remote xenhost isn't really expected to send us NMIs.
+        */
+
        /* Construct a value which looks like it came from port 0x61. */
        if (test_bit(_XEN_NMIREASON_io_error,
                     &xh_default->HYPERVISOR_shared_info->arch.nmi_reason))
@@ -1222,6 +1230,12 @@ static void xen_pv_reset_shared_info(xenhost_t *xh)
                BUG();
 }
 
+void xen_pv_probe_vcpu_id(xenhost_t *xh, int cpu)
+{
+       /* Set up direct vCPU id mapping for PV guests. */
+       xh->xen_vcpu_id[cpu] = cpu;
+}
+
 xenhost_ops_t xh_pv_ops = {
        .cpuid_base = xen_pv_cpuid_base,
 
@@ -1229,6 +1243,8 @@ xenhost_ops_t xh_pv_ops = {
 
        .setup_shared_info = xen_pv_setup_shared_info,
        .reset_shared_info = xen_pv_reset_shared_info,
+
+       .probe_vcpu_id = xen_pv_probe_vcpu_id,
 };
 
 xenhost_ops_t xh_pv_nested_ops = {
@@ -1283,7 +1299,9 @@ asmlinkage __visible void __init xen_start_kernel(void)
         * Don't do the full vcpu_info placement stuff until we have
         * the cpu_possible_mask and a non-dummy shared_info.
         */
-       xen_vcpu_info_reset(0);
+       for_each_xenhost(xh) {
+               xen_vcpu_info_reset(*xh, 0);
+       }
 
        x86_platform.get_nmi_reason = xen_get_nmi_reason;
 
@@ -1328,7 +1346,9 @@ asmlinkage __visible void __init xen_start_kernel(void)
        get_cpu_address_sizes(&boot_cpu_data);
 
        /* Let's presume PV guests always boot on vCPU with id 0. */
-       per_cpu(xen_vcpu_id, 0) = 0;
+       /* Note: we should be doing this before xen_vcpu_info_reset above. */
+       for_each_xenhost(xh)
+               xenhost_probe_vcpu_id(*xh, 0);
 
        idt_setup_early_handler();
 
@@ -1485,7 +1505,7 @@ static int xen_cpu_up_prepare_pv(unsigned int cpu)
 {
        int rc;
 
-       if (per_cpu(xen_vcpu, cpu) == NULL)
+       if (xh_default->xen_vcpu[cpu] == NULL)
                return -ENODEV;
 
        xen_setup_timer(cpu);
diff --git a/arch/x86/xen/enlighten_pvh.c b/arch/x86/xen/enlighten_pvh.c
index 50277dfbdf30..3f98526dd041 100644
--- a/arch/x86/xen/enlighten_pvh.c
+++ b/arch/x86/xen/enlighten_pvh.c
@@ -2,13 +2,14 @@
 #include <linux/acpi.h>
 
 #include <xen/hvc-console.h>
+#include <xen/interface/xen.h>
 
 #include <asm/io_apic.h>
 #include <asm/hypervisor.h>
 #include <asm/e820/api.h>
 
-#include <xen/xen.h>
 #include <xen/xenhost.h>
+#include <xen/xen.h>
 #include <asm/xen/interface.h>
 #include <asm/xen/hypercall.h>
 
diff --git a/arch/x86/xen/irq.c b/arch/x86/xen/irq.c
index 850c93f346c7..38ad1a1c4763 100644
--- a/arch/x86/xen/irq.c
+++ b/arch/x86/xen/irq.c
@@ -29,7 +29,7 @@ asmlinkage __visible unsigned long xen_save_fl(void)
        struct vcpu_info *vcpu;
        unsigned long flags;
 
-       vcpu = this_cpu_read(xen_vcpu);
+       vcpu = xh_default->xen_vcpu[smp_processor_id()];
 
        /* flag has opposite sense of mask */
        flags = !vcpu->evtchn_upcall_mask;
@@ -51,7 +51,7 @@ __visible void xen_restore_fl(unsigned long flags)
 
        /* See xen_irq_enable() for why preemption must be disabled. */
        preempt_disable();
-       vcpu = this_cpu_read(xen_vcpu);
+       vcpu = xh_default->xen_vcpu[smp_processor_id()];
        vcpu->evtchn_upcall_mask = flags;
 
        if (flags == 0) {
@@ -70,7 +70,7 @@ asmlinkage __visible void xen_irq_disable(void)
           make sure we're don't switch CPUs between getting the vcpu
           pointer and updating the mask. */
        preempt_disable();
-       this_cpu_read(xen_vcpu)->evtchn_upcall_mask = 1;
+       xh_default->xen_vcpu[smp_processor_id()]->evtchn_upcall_mask = 1;
        preempt_enable_no_resched();
 }
 PV_CALLEE_SAVE_REGS_THUNK(xen_irq_disable);
@@ -86,7 +86,7 @@ asmlinkage __visible void xen_irq_enable(void)
         */
        preempt_disable();
 
-       vcpu = this_cpu_read(xen_vcpu);
+       vcpu = xh_default->xen_vcpu[smp_processor_id()];
        vcpu->evtchn_upcall_mask = 0;
 
        /* Doesn't matter if we get preempted here, because any
@@ -111,7 +111,7 @@ static void xen_halt(void)
 {
        if (irqs_disabled())
                HYPERVISOR_vcpu_op(VCPUOP_down,
-                                  xen_vcpu_nr(smp_processor_id()), NULL);
+                                  xen_vcpu_nr(xh_default, smp_processor_id()), 
NULL);
        else
                xen_safe_halt();
 }
diff --git a/arch/x86/xen/mmu_pv.c b/arch/x86/xen/mmu_pv.c
index 0f4fe206dcc2..e99af51ab481 100644
--- a/arch/x86/xen/mmu_pv.c
+++ b/arch/x86/xen/mmu_pv.c
@@ -1304,17 +1304,17 @@ static void __init xen_pagetable_init(void)
 }
 static void xen_write_cr2(unsigned long cr2)
 {
-       this_cpu_read(xen_vcpu)->arch.cr2 = cr2;
+       xh_default->xen_vcpu[smp_processor_id()]->arch.cr2 = cr2;
 }
 
 static unsigned long xen_read_cr2(void)
 {
-       return this_cpu_read(xen_vcpu)->arch.cr2;
+       return xh_default->xen_vcpu[smp_processor_id()]->arch.cr2;
 }
 
 unsigned long xen_read_cr2_direct(void)
 {
-       return this_cpu_read(xen_vcpu_info.arch.cr2);
+       return xh_default->xen_vcpu_info[smp_processor_id()].arch.cr2;
 }
 
 static noinline void xen_flush_tlb(void)
diff --git a/arch/x86/xen/pci-swiotlb-xen.c b/arch/x86/xen/pci-swiotlb-xen.c
index 33293ce01d8d..04f9b2e92f06 100644
--- a/arch/x86/xen/pci-swiotlb-xen.c
+++ b/arch/x86/xen/pci-swiotlb-xen.c
@@ -4,6 +4,7 @@
 
 #include <linux/dma-mapping.h>
 #include <linux/pci.h>
+#include <xen/interface/xen.h>
 #include <xen/swiotlb-xen.h>
 
 #include <asm/xen/hypervisor.h>
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
index d5f303c0e656..ec8f22a54f6e 100644
--- a/arch/x86/xen/setup.c
+++ b/arch/x86/xen/setup.c
@@ -19,6 +19,7 @@
 #include <asm/setup.h>
 #include <asm/acpi.h>
 #include <asm/numa.h>
+#include <xen/interface/xen.h>
 #include <asm/xen/hypervisor.h>
 #include <asm/xen/hypercall.h>
 
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
index 7a43b2ae19f1..867524be0065 100644
--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -6,6 +6,7 @@
 #include <linux/percpu.h>
 
 #include <xen/events.h>
+#include <xen/xenhost.h>
 
 #include <xen/hvc-console.h>
 #include "xen-ops.h"
@@ -129,7 +130,10 @@ void __init xen_smp_cpus_done(unsigned int max_cpus)
                return;
 
        for_each_online_cpu(cpu) {
-               if (xen_vcpu_nr(cpu) < MAX_VIRT_CPUS)
+               xenhost_t **xh;
+
+               if ((xen_vcpu_nr(xh_default, cpu) < MAX_VIRT_CPUS) &&
+                       (!xh_remote || (xen_vcpu_nr(xh_remote, cpu) < 
MAX_VIRT_CPUS)))
                        continue;
 
                rc = cpu_down(cpu);
@@ -138,7 +142,8 @@ void __init xen_smp_cpus_done(unsigned int max_cpus)
                        /*
                         * Reset vcpu_info so this cpu cannot be onlined again.
                         */
-                       xen_vcpu_info_reset(cpu);
+                       for_each_xenhost(xh)
+                               xen_vcpu_info_reset(*xh, cpu);
                        count++;
                } else {
                        pr_warn("%s: failed to bring CPU %d down, error %d\n",
diff --git a/arch/x86/xen/smp_hvm.c b/arch/x86/xen/smp_hvm.c
index f8d39440b292..5e7f591bfdd9 100644
--- a/arch/x86/xen/smp_hvm.c
+++ b/arch/x86/xen/smp_hvm.c
@@ -9,6 +9,7 @@
 
 static void __init xen_hvm_smp_prepare_boot_cpu(void)
 {
+       xenhost_t **xh;
        BUG_ON(smp_processor_id() != 0);
        native_smp_prepare_boot_cpu();
 
@@ -16,7 +17,8 @@ static void __init xen_hvm_smp_prepare_boot_cpu(void)
         * Setup vcpu_info for boot CPU. Secondary CPUs get their vcpu_info
         * in xen_cpu_up_prepare_hvm().
         */
-       xen_vcpu_setup(0);
+       for_each_xenhost(xh)
+               xen_vcpu_setup(*xh, 0);
 
        /*
         * The alternative logic (which patches the unlock/lock) runs before
@@ -29,6 +31,7 @@ static void __init xen_hvm_smp_prepare_boot_cpu(void)
 
 static void __init xen_hvm_smp_prepare_cpus(unsigned int max_cpus)
 {
+       xenhost_t **xh;
        int cpu;
 
        native_smp_prepare_cpus(max_cpus);
@@ -36,12 +39,14 @@ static void __init xen_hvm_smp_prepare_cpus(unsigned int 
max_cpus)
 
        xen_init_lock_cpu(0);
 
-       for_each_possible_cpu(cpu) {
-               if (cpu == 0)
-                       continue;
+       for_each_xenhost(xh) {
+               for_each_possible_cpu(cpu) {
+                       if (cpu == 0)
+                               continue;
 
-               /* Set default vcpu_id to make sure that we don't use cpu-0's */
-               per_cpu(xen_vcpu_id, cpu) = XEN_VCPU_ID_INVALID;
+                       /* Set default vcpu_id to make sure that we don't use 
cpu-0's */
+                       (*xh)->xen_vcpu_id[cpu] = XEN_VCPU_ID_INVALID;
+               }
        }
 }
 
diff --git a/arch/x86/xen/smp_pv.c b/arch/x86/xen/smp_pv.c
index 145506f9fdbe..6d9c3e6611ef 100644
--- a/arch/x86/xen/smp_pv.c
+++ b/arch/x86/xen/smp_pv.c
@@ -350,7 +350,7 @@ cpu_initialize_context(unsigned int cpu, struct task_struct 
*idle)
        per_cpu(xen_cr3, cpu) = __pa(swapper_pg_dir);
 
        ctxt->ctrlreg[3] = xen_pfn_to_cr3(virt_to_gfn(swapper_pg_dir));
-       if (HYPERVISOR_vcpu_op(VCPUOP_initialise, xen_vcpu_nr(cpu), ctxt))
+       if (HYPERVISOR_vcpu_op(VCPUOP_initialise, xen_vcpu_nr(xh_default, cpu), 
ctxt))
                BUG();
 
        kfree(ctxt);
@@ -374,7 +374,7 @@ static int xen_pv_cpu_up(unsigned int cpu, struct 
task_struct *idle)
                return rc;
 
        /* make sure interrupts start blocked */
-       per_cpu(xen_vcpu, cpu)->evtchn_upcall_mask = 1;
+       xh_default->xen_vcpu[cpu]->evtchn_upcall_mask = 1;
 
        rc = cpu_initialize_context(cpu, idle);
        if (rc)
@@ -382,7 +382,7 @@ static int xen_pv_cpu_up(unsigned int cpu, struct 
task_struct *idle)
 
        xen_pmu_init(cpu);
 
-       rc = HYPERVISOR_vcpu_op(VCPUOP_up, xen_vcpu_nr(cpu), NULL);
+       rc = HYPERVISOR_vcpu_op(VCPUOP_up, xen_vcpu_nr(xh_default, cpu), NULL);
        BUG_ON(rc);
 
        while (cpu_report_state(cpu) != CPU_ONLINE)
@@ -407,7 +407,7 @@ static int xen_pv_cpu_disable(void)
 static void xen_pv_cpu_die(unsigned int cpu)
 {
        while (HYPERVISOR_vcpu_op(VCPUOP_is_up,
-                                 xen_vcpu_nr(cpu), NULL)) {
+                                 xen_vcpu_nr(xh_default, cpu), NULL)) {
                __set_current_state(TASK_UNINTERRUPTIBLE);
                schedule_timeout(HZ/10);
        }
@@ -423,7 +423,7 @@ static void xen_pv_cpu_die(unsigned int cpu)
 static void xen_pv_play_dead(void) /* used only with HOTPLUG_CPU */
 {
        play_dead_common();
-       HYPERVISOR_vcpu_op(VCPUOP_down, xen_vcpu_nr(smp_processor_id()), NULL);
+       HYPERVISOR_vcpu_op(VCPUOP_down, xen_vcpu_nr(xh_default, 
smp_processor_id()), NULL);
        cpu_bringup();
        /*
         * commit 4b0c0f294 (tick: Cleanup NOHZ per cpu data on cpu down)
@@ -464,7 +464,7 @@ static void stop_self(void *v)
 
        set_cpu_online(cpu, false);
 
-       HYPERVISOR_vcpu_op(VCPUOP_down, xen_vcpu_nr(cpu), NULL);
+       HYPERVISOR_vcpu_op(VCPUOP_down, xen_vcpu_nr(xh_default, cpu), NULL);
        BUG();
 }
 
diff --git a/arch/x86/xen/time.c b/arch/x86/xen/time.c
index d4bb1f8b4f58..217bc4de07ee 100644
--- a/arch/x86/xen/time.c
+++ b/arch/x86/xen/time.c
@@ -18,12 +18,12 @@
 #include <linux/timekeeper_internal.h>
 
 #include <asm/pvclock.h>
+#include <xen/interface/xen.h>
 #include <asm/xen/hypervisor.h>
 #include <asm/xen/hypercall.h>
 
 #include <xen/events.h>
 #include <xen/features.h>
-#include <xen/interface/xen.h>
 #include <xen/interface/vcpu.h>
 
 #include "xen-ops.h"
@@ -48,7 +48,7 @@ static u64 xen_clocksource_read(void)
        u64 ret;
 
        preempt_disable_notrace();
-       src = &__this_cpu_read(xen_vcpu)->time;
+       src = &xh_default->xen_vcpu[smp_processor_id()]->time;
        ret = pvclock_clocksource_read(src);
        preempt_enable_notrace();
        return ret;
@@ -70,9 +70,10 @@ static void xen_read_wallclock(struct timespec64 *ts)
        struct pvclock_wall_clock *wall_clock = &(s->wc);
         struct pvclock_vcpu_time_info *vcpu_time;
 
-       vcpu_time = &get_cpu_var(xen_vcpu)->time;
+       preempt_disable_notrace();
+       vcpu_time = &xh_default->xen_vcpu[smp_processor_id()]->time;
        pvclock_read_wallclock(wall_clock, vcpu_time, ts);
-       put_cpu_var(xen_vcpu);
+       preempt_enable_notrace();
 }
 
 static void xen_get_wallclock(struct timespec64 *now)
@@ -233,9 +234,9 @@ static int xen_vcpuop_shutdown(struct clock_event_device 
*evt)
 {
        int cpu = smp_processor_id();
 
-       if (HYPERVISOR_vcpu_op(VCPUOP_stop_singleshot_timer, xen_vcpu_nr(cpu),
+       if (HYPERVISOR_vcpu_op(VCPUOP_stop_singleshot_timer, 
xen_vcpu_nr(xh_default, cpu),
                               NULL) ||
-           HYPERVISOR_vcpu_op(VCPUOP_stop_periodic_timer, xen_vcpu_nr(cpu),
+           HYPERVISOR_vcpu_op(VCPUOP_stop_periodic_timer, 
xen_vcpu_nr(xh_default, cpu),
                               NULL))
                BUG();
 
@@ -246,7 +247,7 @@ static int xen_vcpuop_set_oneshot(struct clock_event_device 
*evt)
 {
        int cpu = smp_processor_id();
 
-       if (HYPERVISOR_vcpu_op(VCPUOP_stop_periodic_timer, xen_vcpu_nr(cpu),
+       if (HYPERVISOR_vcpu_op(VCPUOP_stop_periodic_timer, 
xen_vcpu_nr(xh_default, cpu),
                               NULL))
                BUG();
 
@@ -266,7 +267,7 @@ static int xen_vcpuop_set_next_event(unsigned long delta,
        /* Get an event anyway, even if the timeout is already expired */
        single.flags = 0;
 
-       ret = HYPERVISOR_vcpu_op(VCPUOP_set_singleshot_timer, xen_vcpu_nr(cpu),
+       ret = HYPERVISOR_vcpu_op(VCPUOP_set_singleshot_timer, 
xen_vcpu_nr(xh_default, cpu),
                                 &single);
        BUG_ON(ret != 0);
 
@@ -366,7 +367,7 @@ void xen_timer_resume(void)
 
        for_each_online_cpu(cpu) {
                if (HYPERVISOR_vcpu_op(VCPUOP_stop_periodic_timer,
-                                      xen_vcpu_nr(cpu), NULL))
+                                      xen_vcpu_nr(xh_default, cpu), NULL))
                        BUG();
        }
 }
@@ -482,7 +483,7 @@ static void __init xen_time_init(void)
 
        clocksource_register_hz(&xen_clocksource, NSEC_PER_SEC);
 
-       if (HYPERVISOR_vcpu_op(VCPUOP_stop_periodic_timer, xen_vcpu_nr(cpu),
+       if (HYPERVISOR_vcpu_op(VCPUOP_stop_periodic_timer, 
xen_vcpu_nr(xh_default, cpu),
                               NULL) == 0) {
                /* Successfully turned off 100Hz tick, so we have the
                   vcpuop-based timer interface */
@@ -500,7 +501,7 @@ static void __init xen_time_init(void)
         * We check ahead on the primary time info if this
         * bit is supported hence speeding up Xen clocksource.
         */
-       pvti = &__this_cpu_read(xen_vcpu)->time;
+       pvti = &xh_default->xen_vcpu[smp_processor_id()]->time;
        if (pvti->flags & PVCLOCK_TSC_STABLE_BIT) {
                pvclock_set_flags(PVCLOCK_TSC_STABLE_BIT);
                xen_setup_vsyscall_time_info();
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
index 5085ce88a8d7..96fd7edea7e9 100644
--- a/arch/x86/xen/xen-ops.h
+++ b/arch/x86/xen/xen-ops.h
@@ -22,7 +22,6 @@ extern void *xen_initial_gdt;
 struct trap_info;
 void xen_copy_trap_info(struct trap_info *traps);
 
-DECLARE_PER_CPU(struct vcpu_info, xen_vcpu_info);
 DECLARE_PER_CPU(unsigned long, xen_cr3);
 DECLARE_PER_CPU(unsigned long, xen_current_cr3);
 
@@ -76,8 +75,8 @@ bool xen_vcpu_stolen(int vcpu);
 
 extern int xen_have_vcpu_info_placement;
 
-int xen_vcpu_setup(int cpu);
-void xen_vcpu_info_reset(int cpu);
+int xen_vcpu_setup(xenhost_t *xh, int cpu);
+void xen_vcpu_info_reset(xenhost_t *xh, int cpu);
 void xen_setup_vcpu_info_placement(void);
 
 #ifdef CONFIG_SMP
diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c
index 117e76b2f939..ae497876fe41 100644
--- a/drivers/xen/events/events_base.c
+++ b/drivers/xen/events/events_base.c
@@ -884,7 +884,7 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int 
cpu)
                irq_set_chip_and_handler_name(irq, &xen_percpu_chip,
                                              handle_percpu_irq, "ipi");
 
-               bind_ipi.vcpu = xen_vcpu_nr(cpu);
+               bind_ipi.vcpu = xen_vcpu_nr(xh_default, cpu);
                if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi,
                                                &bind_ipi) != 0)
                        BUG();
@@ -937,7 +937,7 @@ static int find_virq(unsigned int virq, unsigned int cpu)
                        continue;
                if (status.status != EVTCHNSTAT_virq)
                        continue;
-               if (status.u.virq == virq && status.vcpu == xen_vcpu_nr(cpu)) {
+               if (status.u.virq == virq && status.vcpu == 
xen_vcpu_nr(xh_default, cpu)) {
                        rc = port;
                        break;
                }
@@ -980,7 +980,7 @@ int bind_virq_to_irq(unsigned int virq, unsigned int cpu, 
bool percpu)
                                                      handle_edge_irq, "virq");
 
                bind_virq.virq = virq;
-               bind_virq.vcpu = xen_vcpu_nr(cpu);
+               bind_virq.vcpu = xen_vcpu_nr(xh_default, cpu);
                ret = HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq,
                                                &bind_virq);
                if (ret == 0)
@@ -1200,7 +1200,7 @@ void xen_send_IPI_one(unsigned int cpu, enum ipi_vector 
vector)
 
 #ifdef CONFIG_X86
        if (unlikely(vector == XEN_NMI_VECTOR)) {
-               int rc =  HYPERVISOR_vcpu_op(VCPUOP_send_nmi, xen_vcpu_nr(cpu),
+               int rc =  HYPERVISOR_vcpu_op(VCPUOP_send_nmi, 
xen_vcpu_nr(xh_default, cpu),
                                             NULL);
                if (rc < 0)
                        printk(KERN_WARNING "Sending nmi to CPU%d failed 
(rc:%d)\n", cpu, rc);
@@ -1306,7 +1306,7 @@ int xen_rebind_evtchn_to_cpu(int evtchn, unsigned tcpu)
 
        /* Send future instances of this interrupt to other vcpu. */
        bind_vcpu.port = evtchn;
-       bind_vcpu.vcpu = xen_vcpu_nr(tcpu);
+       bind_vcpu.vcpu = xen_vcpu_nr(xh_default, tcpu);
 
        /*
         * Mask the event while changing the VCPU binding to prevent
@@ -1451,7 +1451,7 @@ static void restore_cpu_virqs(unsigned int cpu)
 
                /* Get a new binding from Xen. */
                bind_virq.virq = virq;
-               bind_virq.vcpu = xen_vcpu_nr(cpu);
+               bind_virq.vcpu = xen_vcpu_nr(xh_default, cpu);
                if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq,
                                                &bind_virq) != 0)
                        BUG();
@@ -1475,7 +1475,7 @@ static void restore_cpu_ipis(unsigned int cpu)
                BUG_ON(ipi_from_irq(irq) != ipi);
 
                /* Get a new binding from Xen. */
-               bind_ipi.vcpu = xen_vcpu_nr(cpu);
+               bind_ipi.vcpu = xen_vcpu_nr(xh_default, cpu);
                if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_ipi,
                                                &bind_ipi) != 0)
                        BUG();
diff --git a/drivers/xen/events/events_fifo.c b/drivers/xen/events/events_fifo.c
index 76b318e88382..eed766219dd0 100644
--- a/drivers/xen/events/events_fifo.c
+++ b/drivers/xen/events/events_fifo.c
@@ -113,7 +113,7 @@ static int init_control_block(int cpu,
 
        init_control.control_gfn = virt_to_gfn(control_block);
        init_control.offset      = 0;
-       init_control.vcpu        = xen_vcpu_nr(cpu);
+       init_control.vcpu        = xen_vcpu_nr(xh_default, cpu);
 
        return HYPERVISOR_event_channel_op(EVTCHNOP_init_control, 
&init_control);
 }
diff --git a/drivers/xen/evtchn.c b/drivers/xen/evtchn.c
index 6d1a5e58968f..66622109f2be 100644
--- a/drivers/xen/evtchn.c
+++ b/drivers/xen/evtchn.c
@@ -475,7 +475,7 @@ static long evtchn_ioctl(struct file *file,
                        break;
 
                bind_virq.virq = bind.virq;
-               bind_virq.vcpu = xen_vcpu_nr(0);
+               bind_virq.vcpu = xen_vcpu_nr(xh_default, 0);
                rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq,
                                                 &bind_virq);
                if (rc != 0)
diff --git a/drivers/xen/time.c b/drivers/xen/time.c
index 0968859c29d0..feee74bbab0a 100644
--- a/drivers/xen/time.c
+++ b/drivers/xen/time.c
@@ -164,7 +164,7 @@ void xen_setup_runstate_info(int cpu)
        area.addr.v = &per_cpu(xen_runstate, cpu);
 
        if (HYPERVISOR_vcpu_op(VCPUOP_register_runstate_memory_area,
-                              xen_vcpu_nr(cpu), &area))
+                              xen_vcpu_nr(xh_default, cpu), &area))
                BUG();
 }
 
diff --git a/include/xen/xen-ops.h b/include/xen/xen-ops.h
index 4969817124a8..75be9059893f 100644
--- a/include/xen/xen-ops.h
+++ b/include/xen/xen-ops.h
@@ -9,12 +9,9 @@
 #include <asm/xen/interface.h>
 #include <xen/interface/vcpu.h>
 
-DECLARE_PER_CPU(struct vcpu_info *, xen_vcpu);
-
-DECLARE_PER_CPU(uint32_t, xen_vcpu_id);
-static inline uint32_t xen_vcpu_nr(int cpu)
+static inline uint32_t xen_vcpu_nr(xenhost_t *xh, int cpu)
 {
-       return per_cpu(xen_vcpu_id, cpu);
+       return xh->xen_vcpu_id[cpu];
 }
 
 #define XEN_VCPU_ID_INVALID U32_MAX
diff --git a/include/xen/xenhost.h b/include/xen/xenhost.h
index 7c19c361d16e..f6092a8987f1 100644
--- a/include/xen/xenhost.h
+++ b/include/xen/xenhost.h
@@ -90,6 +90,28 @@ typedef struct {
                struct shared_info *HYPERVISOR_shared_info;
                unsigned long shared_info_pfn;
        };
+
+       struct {
+               /*
+                * Events on xen-evtchn ports show up in struct vcpu_info.
+                * With multiple xenhosts, the evtchn-port numbering space that
+                * was global so far is now attached to a xenhost.
+                *
+                * So, now we allocate vcpu_info for each processor (we had 
space
+                * for only MAX_VIRT_CPUS in the shared_info above.)
+                *
+                * FIXME we statically allocate for NR_CPUS because 
alloc_percpu()
+                * isn't available at PV boot time but this is slow.
+                */
+               struct vcpu_info xen_vcpu_info[NR_CPUS];
+               struct vcpu_info *xen_vcpu[NR_CPUS];
+
+               /*
+                * Different xenhosts might have different Linux <-> Xen vCPU-id
+                * mapping.
+                */
+               uint32_t xen_vcpu_id[NR_CPUS];
+       };
 } xenhost_t;
 
 typedef struct xenhost_ops {
@@ -139,6 +161,26 @@ typedef struct xenhost_ops {
         */
        void (*setup_shared_info)(xenhost_t *xenhost);
        void (*reset_shared_info)(xenhost_t *xenhost);
+
+       /*
+        * vcpu_info, vcpu_id: needs to be setup early -- all IRQ code accesses
+        * relevant bits.
+        *
+        * vcpu_id is probed on PVH/PVHVM via xen_cpuid(). For PV, its direct
+        * mapped to smp_processor_id().
+        *
+        * This is part of xenhost_t because we might be registered with two
+        * different xenhosts and both of those might have their own vcpu
+        * numbering.
+        *
+        * After the vcpu numbering is identified, we can go ahead and register
+        * vcpu_info with the xenhost; on the default xenhost this happens via
+        * the register_vcpu_info hypercall.
+        *
+        * Once vcpu_info is setup (this or the shared_info version), it would
+        * get accessed via pv_ops.irq.* and the evtchn logic.
+        */
+       void (*probe_vcpu_id)(xenhost_t *xenhost, int cpu);
 } xenhost_ops_t;
 
 extern xenhost_t *xh_default, *xh_remote;
@@ -185,4 +227,9 @@ static inline void xenhost_reset_shared_info(xenhost_t *xh)
        (xh->ops->reset_shared_info)(xh);
 }
 
+static inline void xenhost_probe_vcpu_id(xenhost_t *xh, int cpu)
+{
+       (xh->ops->probe_vcpu_id)(xh, cpu);
+}
+
 #endif /* __XENHOST_H */
-- 
2.20.1


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

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