The base address, id and number of pins of the vIO APICs exposed to PVHv2 Dom0
is the same as the values found on bare metal.

Signed-off-by: Roger Pau Monné <roger....@citrix.com>
---
Cc: Jan Beulich <jbeul...@suse.com>
Cc: Andrew Cooper <andrew.coop...@citrix.com>
---
 xen/arch/x86/domain_build.c | 33 +++++++++++------------------
 xen/arch/x86/hvm/vioapic.c  | 51 ++++++++++++++++++++++++++++++++++-----------
 2 files changed, 51 insertions(+), 33 deletions(-)

diff --git a/xen/arch/x86/domain_build.c b/xen/arch/x86/domain_build.c
index dad3b4e..b9062ee 100644
--- a/xen/arch/x86/domain_build.c
+++ b/xen/arch/x86/domain_build.c
@@ -2271,12 +2271,7 @@ static int __init pvh_setup_acpi_madt(struct domain *d, 
paddr_t *addr)
     max_vcpus = dom0_max_vcpus();
     /* Calculate the size of the crafted MADT. */
     size = sizeof(*madt);
-    /*
-     * FIXME: the current vIO-APIC code just supports one IO-APIC instance
-     * per domain. This must be fixed in order to provide the same amount of
-     * IO APICs as available on bare metal.
-     */
-    size += sizeof(*io_apic);
+    size += sizeof(*io_apic) * nr_ioapics;
     size += sizeof(*intsrcovr) * acpi_intr_overrides;
     size += sizeof(*nmisrc) * acpi_nmi_sources;
     size += sizeof(*x2apic) * max_vcpus;
@@ -2304,23 +2299,19 @@ static int __init pvh_setup_acpi_madt(struct domain *d, 
paddr_t *addr)
      */
     madt->header.revision = min_t(unsigned char, table->revision, 4);
 
-    /*
-     * Setup the IO APIC entry.
-     * FIXME: the current vIO-APIC code just supports one IO-APIC instance
-     * per domain. This must be fixed in order to provide the same amount of
-     * IO APICs as available on bare metal, and with the same IDs as found in
-     * the native IO APIC MADT entries.
-     */
-    if ( nr_ioapics > 1 )
-        printk("WARNING: found %d IO APICs, Dom0 will only have access to 1 
emulated IO APIC\n",
-               nr_ioapics);
+    /* Setup the IO APIC entries. */
     io_apic = (void *)(madt + 1);
-    io_apic->header.type = ACPI_MADT_TYPE_IO_APIC;
-    io_apic->header.length = sizeof(*io_apic);
-    io_apic->id = domain_vioapic(d, 0)->id;
-    io_apic->address = VIOAPIC_DEFAULT_BASE_ADDRESS;
+    for ( i = 0; i < nr_ioapics; i++ )
+    {
+        io_apic->header.type = ACPI_MADT_TYPE_IO_APIC;
+        io_apic->header.length = sizeof(*io_apic);
+        io_apic->id = domain_vioapic(d, i)->id;
+        io_apic->address = domain_vioapic(d, i)->base_address;
+        io_apic->global_irq_base = apic_gsi_base(i);
+        io_apic++;
+    }
 
-    x2apic = (void *)(io_apic + 1);
+    x2apic = (void *)io_apic;
     for ( i = 0; i < max_vcpus; i++ )
     {
         x2apic->header.type = ACPI_MADT_TYPE_LOCAL_X2APIC;
diff --git a/xen/arch/x86/hvm/vioapic.c b/xen/arch/x86/hvm/vioapic.c
index 6421971..1467b25 100644
--- a/xen/arch/x86/hvm/vioapic.c
+++ b/xen/arch/x86/hvm/vioapic.c
@@ -629,15 +629,25 @@ void vioapic_reset(struct domain *d)
                sizeof(*vioapic->redirtbl) * vioapic->nr_pins);
         for ( j = 0; j < vioapic->nr_pins; j++ )
             vioapic->redirtbl[j].fields.mask = 1;
-        vioapic->base_address = VIOAPIC_DEFAULT_BASE_ADDRESS +
-                                VIOAPIC_MEM_LENGTH * i;
-        vioapic->id = i;
+        if ( !is_hardware_domain(d) )
+        {
+            vioapic->base_address = VIOAPIC_DEFAULT_BASE_ADDRESS +
+                                    VIOAPIC_MEM_LENGTH * i;
+            vioapic->id = i;
+        }
+        else
+        {
+            vioapic->base_address = mp_ioapics[i].mpc_apicaddr;
+            vioapic->id = mp_ioapics[i].mpc_apicid;
+        }
         vioapic->ioregsel = 0;
     }
 }
 
 int vioapic_init(struct domain *d)
 {
+    unsigned int i, nr_vioapics = is_hardware_domain(d) ? nr_ioapics : 1;
+
     if ( !has_vioapic(d) )
     {
         d->arch.hvm_domain.nr_vioapics = 0;
@@ -646,24 +656,41 @@ int vioapic_init(struct domain *d)
 
     if ( (d->arch.hvm_domain.vioapic == NULL) &&
          ((d->arch.hvm_domain.vioapic =
-           xmalloc(struct hvm_hw_vioapic)) == NULL) )
+           xzalloc_array(struct hvm_hw_vioapic, nr_vioapics)) == NULL) )
         return -ENOMEM;
 
-    domain_vioapic(d, 0)->redirtbl = xmalloc_array(union vioapic_redir_entry,
-                                                   VIOAPIC_NUM_PINS);
-    if ( !domain_vioapic(d, 0)->redirtbl )
+    if ( !is_hardware_domain(d) )
     {
-        xfree(d->arch.hvm_domain.vioapic);
-        return -ENOMEM;
+        ASSERT(nr_vioapics == 1);
+        domain_vioapic(d, 0)->redirtbl =
+            xmalloc_array(union vioapic_redir_entry, VIOAPIC_NUM_PINS);
+        if ( !domain_vioapic(d, 0)->redirtbl )
+            goto error;
+        domain_vioapic(d, 0)->nr_pins = VIOAPIC_NUM_PINS;
+    }
+    else
+    {
+        for ( i = 0; i < nr_vioapics; i++ )
+        {
+            domain_vioapic(d, i)->redirtbl =
+                xmalloc_array(union vioapic_redir_entry, nr_ioapic_entries[i]);
+            if ( !domain_vioapic(d, i)->redirtbl )
+                goto error;
+            domain_vioapic(d, i)->nr_pins = nr_ioapic_entries[i];
+        }
     }
 
-    domain_vioapic(d, 0)->nr_pins = VIOAPIC_NUM_PINS;
-    d->arch.hvm_domain.nr_vioapics = 1;
+    d->arch.hvm_domain.nr_vioapics = nr_vioapics;
     vioapic_reset(d);
-
     register_mmio_handler(d, &vioapic_mmio_ops);
 
     return 0;
+
+ error:
+    for ( i = 0; i < nr_vioapics; i++ )
+        xfree(domain_vioapic(d, i)->redirtbl);
+    xfree(d->arch.hvm_domain.vioapic);
+    return -ENOMEM;
 }
 
 void vioapic_deinit(struct domain *d)
-- 
2.10.1 (Apple Git-78)


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

Reply via email to