diff mbox series

[v4,10/10] tools/libguest: Set topologically correct x2APIC IDs for each vCPU

Message ID 94a6d0ff6ce8d0e5be9546efba7aa50d2a21a2b8.1719416329.git.alejandro.vallejo@cloud.com (mailing list archive)
State New
Headers show
Series x86: Expose consistent topology to guests | expand

Commit Message

Alejandro Vallejo June 26, 2024, 4:28 p.m. UTC
Have toolstack populate the new x2APIC ID in the LAPIC save record with the
proper IDs intended for each vCPU.

Signed-off-by: Alejandro Vallejo <alejandro.vallejo@cloud.com>
---
v4:
  * New patch. Replaced v3's method of letting Xen find out via the same
    algorithm toolstack uses.
---
 tools/libs/guest/xg_dom_x86.c | 37 ++++++++++++++++++++++++++++++++++-
 1 file changed, 36 insertions(+), 1 deletion(-)
diff mbox series

Patch

diff --git a/tools/libs/guest/xg_dom_x86.c b/tools/libs/guest/xg_dom_x86.c
index 82ea3e2aab0b..2ae3a779b016 100644
--- a/tools/libs/guest/xg_dom_x86.c
+++ b/tools/libs/guest/xg_dom_x86.c
@@ -1004,19 +1004,40 @@  static int vcpu_hvm(struct xc_dom_image *dom)
         HVM_SAVE_TYPE(HEADER) header;
         struct hvm_save_descriptor mtrr_d;
         HVM_SAVE_TYPE(MTRR) mtrr;
+        struct hvm_save_descriptor lapic_d;
+        HVM_SAVE_TYPE(LAPIC) lapic;
         struct hvm_save_descriptor end_d;
         HVM_SAVE_TYPE(END) end;
     } vcpu_ctx;
-    /* Context from full_ctx */
+    /* Contexts from full_ctx */
     const HVM_SAVE_TYPE(MTRR) *mtrr_record;
+    const HVM_SAVE_TYPE(LAPIC) *lapic_record;
     /* Raw context as taken from Xen */
     uint8_t *full_ctx = NULL;
+    xc_cpu_policy_t *policy = xc_cpu_policy_init();
     int rc;
 
     DOMPRINTF_CALLED(dom->xch);
 
     assert(dom->max_vcpus);
 
+    /*
+     * Fetch the CPU policy of this domain. We need it to determine the APIC IDs
+     * each of vCPU in a manner consistent with the exported topology.
+     *
+     * TODO: It's silly to query a policy we have ourselves created. It should
+     *       instead be part of xc_dom_image
+     */
+
+    rc = xc_cpu_policy_get_domain(dom->xch, dom->guest_domid, policy);
+    if ( rc != 0 )
+    {
+        xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
+                     "%s: unable to fetch cpu policy for dom%u (rc=%d)",
+                     __func__, dom->guest_domid, rc);
+        goto out;
+    }
+
     /*
      * Get the full HVM context in order to have the header, it is not
      * possible to get the header with getcontext_partial, and crafting one
@@ -1111,6 +1132,8 @@  static int vcpu_hvm(struct xc_dom_image *dom)
     vcpu_ctx.mtrr_d.typecode = HVM_SAVE_CODE(MTRR);
     vcpu_ctx.mtrr_d.length = HVM_SAVE_LENGTH(MTRR);
     vcpu_ctx.mtrr = *mtrr_record;
+    vcpu_ctx.lapic_d.typecode = HVM_SAVE_CODE(LAPIC);
+    vcpu_ctx.lapic_d.length = HVM_SAVE_LENGTH(LAPIC);
     vcpu_ctx.end_d = bsp_ctx.end_d;
     vcpu_ctx.end = bsp_ctx.end;
 
@@ -1124,6 +1147,17 @@  static int vcpu_hvm(struct xc_dom_image *dom)
     {
         vcpu_ctx.mtrr_d.instance = i;
 
+        lapic_record = hvm_get_save_record(full_ctx, HVM_SAVE_CODE(LAPIC), i);
+        if ( !lapic_record )
+        {
+            xc_dom_panic(dom->xch, XC_INTERNAL_ERROR,
+                         "%s: unable to get LAPIC[%d] save record", __func__, i);
+            goto out;
+        }
+        vcpu_ctx.lapic = *lapic_record;
+        vcpu_ctx.lapic.x2apic_id = x86_x2apic_id_from_vcpu_id(&policy->policy, i);
+        vcpu_ctx.lapic_d.instance = i;
+
         rc = xc_domain_hvm_setcontext(dom->xch, dom->guest_domid,
                                           (uint8_t *)&vcpu_ctx, sizeof(vcpu_ctx));
         if ( rc != 0 )
@@ -1146,6 +1180,7 @@  static int vcpu_hvm(struct xc_dom_image *dom)
 
  out:
     free(full_ctx);
+    xc_cpu_policy_destroy(policy);
     return rc;
 }