All of lore.kernel.org
 help / color / mirror / Atom feed
* [XEN PATCH] tools: add x2APIC entries in MADT based on APIC ID
@ 2024-03-13 15:35 Matthew Barnes
  2024-03-14 13:50 ` Jan Beulich
  0 siblings, 1 reply; 7+ messages in thread
From: Matthew Barnes @ 2024-03-13 15:35 UTC (permalink / raw)
  To: Xen-devel; +Cc: Matthew Barnes, Jan Beulich, Wei Liu, Anthony PERARD

libacpi is a tool that is used by libxl (for PVH guests) and hvmloader
(for HVM guests) to construct ACPI tables for guests.

Currently, libacpi only uses APIC entries to enumerate processors for
guests in the MADT.

The APIC ID field in APIC entries is an octet big, which is fine for
xAPIC IDs, but not so for sufficiently large x2APIC IDs.

This patch scans each APIC ID before constructing the MADT, and uses the
x2APIC entry for each vCPU whose APIC ID exceeds the size limit imposed
by regular APIC entries.

Signed-off-by: Matthew Barnes <matthew.barnes@cloud.com>
---
 tools/libacpi/acpi2_0.h | 13 +++++++
 tools/libacpi/build.c   | 75 ++++++++++++++++++++++++++++++-----------
 2 files changed, 68 insertions(+), 20 deletions(-)

diff --git a/tools/libacpi/acpi2_0.h b/tools/libacpi/acpi2_0.h
index 6dfa939a8c0c..10e567686fe6 100644
--- a/tools/libacpi/acpi2_0.h
+++ b/tools/libacpi/acpi2_0.h
@@ -344,6 +344,7 @@ struct acpi_20_waet {
 #define ACPI_IO_SAPIC                       0x06
 #define ACPI_PROCESSOR_LOCAL_SAPIC          0x07
 #define ACPI_PLATFORM_INTERRUPT_SOURCES     0x08
+#define ACPI_PROCESSOR_LOCAL_X2APIC         0x09
 
 /*
  * APIC Structure Definitions.
@@ -360,6 +361,18 @@ struct acpi_20_madt_lapic {
     uint32_t flags;
 };
 
+/*
+ * Processor Local x2APIC Structure Definition.
+ */
+struct acpi_20_madt_x2apic {
+    uint8_t  type;              /* Must refer to x2APIC type (0x09) */
+    uint8_t  length;            /* Must be length of x2APIC struct in bytes (0x10) */
+    uint16_t reserved;          /* Must be zero */
+    uint32_t apic_id;           /* Processor's local x2APIC ID */
+    uint32_t flags;             /* Same as Local APIC flags */
+    uint32_t acpi_processor_id; /* Refers to a processor device used to associate the X2APIC structure with */
+};
+
 /*
  * Local APIC Flags.  All other bits are reserved and must be 0.
  */
diff --git a/tools/libacpi/build.c b/tools/libacpi/build.c
index 2f29863db154..5b0fd6584b30 100644
--- a/tools/libacpi/build.c
+++ b/tools/libacpi/build.c
@@ -63,6 +63,27 @@ static void set_checksum(
     p[checksum_offset] = -sum;
 }
 
+static unsigned calculate_madt_size(const struct acpi_config *config)
+{
+    uint32_t apic_id;
+    unsigned i, size;
+
+    size  = sizeof(struct acpi_20_madt);
+    size += sizeof(struct acpi_20_madt_intsrcovr) * 16;
+    size += sizeof(struct acpi_20_madt_ioapic);
+
+    for ( i = 0; i < config->hvminfo->nr_vcpus; i++ )
+    {
+        apic_id = config->lapic_id(i);
+        if ( apic_id < 255 )
+            size += sizeof(struct acpi_20_madt_lapic);
+        else
+            size += sizeof(struct acpi_20_madt_x2apic);
+    }
+
+    return size;
+}
+
 static struct acpi_20_madt *construct_madt(struct acpi_ctxt *ctxt,
                                            const struct acpi_config *config,
                                            struct acpi_info *info)
@@ -70,18 +91,14 @@ static struct acpi_20_madt *construct_madt(struct acpi_ctxt *ctxt,
     struct acpi_20_madt           *madt;
     struct acpi_20_madt_intsrcovr *intsrcovr;
     struct acpi_20_madt_ioapic    *io_apic;
-    struct acpi_20_madt_lapic     *lapic;
+    void                          *apicid_entry;
     const struct hvm_info_table   *hvminfo = config->hvminfo;
-    int i, sz;
+    unsigned i, sz;
 
     if ( config->lapic_id == NULL )
         return NULL;
 
-    sz  = sizeof(struct acpi_20_madt);
-    sz += sizeof(struct acpi_20_madt_intsrcovr) * 16;
-    sz += sizeof(struct acpi_20_madt_ioapic);
-    sz += sizeof(struct acpi_20_madt_lapic) * hvminfo->nr_vcpus;
-
+    sz = calculate_madt_size(config);
     madt = ctxt->mem_ops.alloc(ctxt, sz, 16);
     if (!madt) return NULL;
 
@@ -134,27 +151,45 @@ static struct acpi_20_madt *construct_madt(struct acpi_ctxt *ctxt,
         io_apic->ioapic_id   = config->ioapic_id;
         io_apic->ioapic_addr = config->ioapic_base_address;
 
-        lapic = (struct acpi_20_madt_lapic *)(io_apic + 1);
+        apicid_entry = io_apic + 1;
     }
     else
-        lapic = (struct acpi_20_madt_lapic *)(madt + 1);
+        apicid_entry = madt + 1;
 
     info->nr_cpus = hvminfo->nr_vcpus;
-    info->madt_lapic0_addr = ctxt->mem_ops.v2p(ctxt, lapic);
+    info->madt_lapic0_addr = ctxt->mem_ops.v2p(ctxt, apicid_entry);
     for ( i = 0; i < hvminfo->nr_vcpus; i++ )
     {
-        memset(lapic, 0, sizeof(*lapic));
-        lapic->type    = ACPI_PROCESSOR_LOCAL_APIC;
-        lapic->length  = sizeof(*lapic);
-        /* Processor ID must match processor-object IDs in the DSDT. */
-        lapic->acpi_processor_id = i;
-        lapic->apic_id = config->lapic_id(i);
-        lapic->flags = (test_bit(i, hvminfo->vcpu_online)
-                        ? ACPI_LOCAL_APIC_ENABLED : 0);
-        lapic++;
+        uint32_t apic_id = config->lapic_id(i);
+        if ( apic_id < 255 )
+        {
+            struct acpi_20_madt_lapic *lapic = apicid_entry;
+            memset(lapic, 0, sizeof(*lapic));
+            lapic->type    = ACPI_PROCESSOR_LOCAL_APIC;
+            lapic->length  = sizeof(*lapic);
+            /* Processor ID must match processor-object IDs in the DSDT. */
+            lapic->acpi_processor_id = i;
+            lapic->apic_id = apic_id;
+            lapic->flags = (test_bit(i, hvminfo->vcpu_online)
+                            ? ACPI_LOCAL_APIC_ENABLED : 0);
+            apicid_entry = lapic + 1;
+        }
+        else
+        {
+            struct acpi_20_madt_x2apic *x2apic = apicid_entry;
+            memset(x2apic, 0, sizeof(*x2apic));
+            x2apic->type    = ACPI_PROCESSOR_LOCAL_X2APIC;
+            x2apic->length  = sizeof(*x2apic);
+            x2apic->apic_id = apic_id;
+            x2apic->flags   = (test_bit(i, hvminfo->vcpu_online)
+                                ? ACPI_LOCAL_APIC_ENABLED : 0);
+            /* Processor ID must match processor-object IDs in the DSDT. */
+            x2apic->acpi_processor_id = i;
+            apicid_entry = x2apic + 1;
+        }
     }
 
-    madt->header.length = (unsigned char *)lapic - (unsigned char *)madt;
+    madt->header.length = (unsigned char *)apicid_entry - (unsigned char *)madt;
     set_checksum(madt, offsetof(struct acpi_header, checksum),
                  madt->header.length);
     info->madt_csum_addr =
-- 
2.34.1



^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2024-03-26 16:51 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-03-13 15:35 [XEN PATCH] tools: add x2APIC entries in MADT based on APIC ID Matthew Barnes
2024-03-14 13:50 ` Jan Beulich
2024-03-25 14:30   ` Alejandro Vallejo
2024-03-26 16:51     ` Roger Pau Monné
2024-03-26 15:57   ` Matthew Barnes
2024-03-26 16:15     ` Jan Beulich
2024-03-26 16:38       ` Matthew Barnes

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.