@@ -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;
}
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(-)