|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH 1/1] x86: centralize default APIC id definition
On 24.09.2021 21:39, Alex Olson wrote:
> Inspired by an earlier attempt by Chao Gao <chao.gao@xxxxxxxxx>,
> this revision aims to put the hypervisor in control of x86 APIC identifier
> definition instead of hard-coding a formula in multiple places
> (libxl, hvmloader, hypervisor).
>
> This is intended as a first step toward exposing/altering CPU topology
> seen by guests.
>
> Changes:
>
> - Add field to vlapic for holding default ID (on reset)
>
> - add HVMOP_get_vcpu_topology_id hypercall so libxl (for PVH domains)
> can access APIC ids needed for ACPI table definition prior to domain start.
>
> - For HVM guests, hvmloader now also uses the same hypercall.
>
> - Make CPUID code use vlapic ID instead of hard-coded formula
> for runtime reporting to guests
I'm afraid a primary question from back at the time remains: How is
migration of a guest from an old hypervisor to one with this change
in place going to work?
> --- a/tools/libs/light/libxl_x86_acpi.c
> +++ b/tools/libs/light/libxl_x86_acpi.c
> @@ -79,9 +79,13 @@ static void acpi_mem_free(struct acpi_ctxt *ctxt,
> {
> }
>
> -static uint32_t acpi_lapic_id(unsigned cpu)
> +static uint32_t acpi_lapic_id(unsigned cpu, void *arg)
> {
> - return cpu * 2;
> + struct xc_dom_image *dom = (struct xc_dom_image *)arg;
No need for the cast.
> + uint32_t ret = 0xdeadbeef;
> + int rc;
> + rc = xc_get_vcpu_topology_id(dom->xch, dom->guest_domid, cpu, &ret);
> + return ret;
> }
No need for the local variable "rc" if you don't evaluate it.
> --- a/xen/arch/x86/cpuid.c
> +++ b/xen/arch/x86/cpuid.c
> @@ -867,8 +867,10 @@ void guest_cpuid(const struct vcpu *v, uint32_t leaf,
> case 0x1:
> /* TODO: Rework topology logic. */
> res->b &= 0x00ffffffu;
> - if ( is_hvm_domain(d) )
> - res->b |= (v->vcpu_id * 2) << 24;
> +
> +#ifdef CONFIG_HVM
> + res->b |= vlapic_get_default_id(v) << 24;
> +#endif
How come you drop the is_hvm_domain() here? There also should be no
need for such an #ifdef here ...
> @@ -1049,7 +1051,13 @@ void guest_cpuid(const struct vcpu *v, uint32_t leaf,
> *(uint8_t *)&res->c = subleaf;
>
> /* Fix the x2APIC identifier. */
> - res->d = v->vcpu_id * 2;
> +#ifdef CONFIG_HVM
> + res->d = vlapic_get_default_id(v);
> +#endif
... or here.
> + }
> + else
> + {
> + *res = EMPTY_LEAF;
> }
No need for braces in such a case.
> --- a/xen/arch/x86/hvm/hvm.c
> +++ b/xen/arch/x86/hvm/hvm.c
> @@ -1555,7 +1555,7 @@ int hvm_vcpu_initialise(struct vcpu *v)
> goto fail1;
>
> /* NB: vlapic_init must be called before hvm_funcs.vcpu_initialise */
> - rc = vlapic_init(v);
> + rc = vlapic_init(v, v->vcpu_id * 2);
Now that's odd: The goal of the patch is to eliminate such, and
here's you're adding a new instance?
> @@ -5084,6 +5084,40 @@ long do_hvm_op(unsigned long op,
> XEN_GUEST_HANDLE_PARAM(void) arg)
> rc = current->hcall_compat ? compat_altp2m_op(arg) :
> do_altp2m_op(arg);
> break;
>
> + case HVMOP_get_vcpu_topology_id:
> + {
> + struct domain *d;
> + struct xen_vcpu_topology_id tid;
> +
> + if ( copy_from_guest(&tid, arg, 1) )
> + return -EFAULT;
> +
> + if (tid.domid != DOMID_SELF && !is_hardware_domain(current->domain))
This wants to be a proper XSM check, I suppose, and allow more than
just the hardware domain to access this in case the controller of
the domain doesn't run in Dom0 (see XSM_TARGET).
Also, nit: Style (see all the other if()s).
> + return -EPERM;
> +
> + if ( (d = rcu_lock_domain_by_any_id(tid.domid)) == NULL )
> + return -ESRCH;
> +
> + if ( !is_hvm_domain(d))
Nit: Style again.
> + {
> + rc = -EOPNOTSUPP;
> + goto get_cpu_topology_failed;
> + }
> +
> + if ( tid.vcpu_id >= d->max_vcpus )
Please use domain_vcpu() ...
> + {
> + rc = -EINVAL;
> + goto get_cpu_topology_failed;
> + }
> + tid.topology_id = vlapic_get_default_id(d->vcpu[tid.vcpu_id]);
... to guard this array access.
> @@ -1508,7 +1514,7 @@ static void lapic_load_fixup(struct vlapic *vlapic)
> * here, but can be dropped as soon as it is found to conflict with
> * other (future) changes.
> */
> - if ( GET_xAPIC_ID(id) != vlapic_vcpu(vlapic)->vcpu_id * 2 ||
> + if ( GET_xAPIC_ID(id) != vlapic->hw.default_id ||
> id != SET_xAPIC_ID(GET_xAPIC_ID(id)) )
> printk(XENLOG_G_WARNING "%pv: bogus APIC ID %#x loaded\n",
> vlapic_vcpu(vlapic), id);
As to my initial comment - I expect this warning will trigger for
about every vCPU of a guest migrating in from an older hypervisor.
> --- a/xen/include/public/hvm/hvm_op.h
> +++ b/xen/include/public/hvm/hvm_op.h
> @@ -183,6 +183,23 @@ struct xen_hvm_get_mem_type {
> typedef struct xen_hvm_get_mem_type xen_hvm_get_mem_type_t;
> DEFINE_XEN_GUEST_HANDLE(xen_hvm_get_mem_type_t);
>
> +/*
> + * HVMOP_get_cpu_topology is used by guest to acquire vcpu topology from
> + * hypervisor.
> + */
> +#define HVMOP_get_vcpu_topology_id 16
Careful with the number choice here - 16 used to be HVMOP_inject_msi
until dm-op was introduced. Interfaces exposed to guests themselves
need to not invoke unexpected operations on older hypervisors.
> +struct xen_vcpu_topology_id {
> + /* IN */
> + domid_t domid;
> + uint32_t vcpu_id;
Please make padding explict, checking it to be zero on input.
Jan
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |