In order to test external interrupts using a destination ID > 255. Also start vCPUs with the APIC in x2APIC mode. --- xen/arch/x86/cpuid.c | 12 +++++++++++- xen/arch/x86/hvm/dom0_build.c | 3 ++- xen/arch/x86/hvm/vlapic.c | 14 ++++++++++++-- xen/arch/x86/include/asm/hvm/vlapic.h | 2 ++ 4 files changed, 27 insertions(+), 4 deletions(-)
diff --git a/xen/arch/x86/cpuid.c b/xen/arch/x86/cpuid.c index 0407a54626..01dcd474e8 100644 --- a/xen/arch/x86/cpuid.c +++ b/xen/arch/x86/cpuid.c @@ -8,6 +8,7 @@ #include <asm/hvm/nestedhvm.h> #include <asm/hvm/svm/svm.h> #include <asm/hvm/viridian.h> +#include <asm/hvm/vlapic.h> #include <asm/hvm/vmx/vmcs.h> #include <asm/paging.h> #include <asm/processor.h> @@ -876,7 +877,14 @@ void guest_cpuid(const struct vcpu *v, uint32_t leaf, /* TODO: Rework topology logic. */ res->b &= 0x00ffffffu; if ( is_hvm_domain(d) ) - res->b |= (v->vcpu_id * 2) << 24; + { + unsigned int id = v->vcpu_id * 2; + + if ( id ) + id += opt_x2apic_id_offset; + + res->b |= id << 24; + } /* TODO: Rework vPMU control in terms of toolstack choices. */ if ( vpmu_available(v) && @@ -1058,6 +1066,8 @@ void guest_cpuid(const struct vcpu *v, uint32_t leaf, /* Fix the x2APIC identifier. */ res->d = v->vcpu_id * 2; + if ( res->d ) + res->d += opt_x2apic_id_offset; } break; diff --git a/xen/arch/x86/hvm/dom0_build.c b/xen/arch/x86/hvm/dom0_build.c index 43e1bf1248..b00e45885c 100644 --- a/xen/arch/x86/hvm/dom0_build.c +++ b/xen/arch/x86/hvm/dom0_build.c @@ -30,6 +30,7 @@ #include <asm/bzimage.h> #include <asm/dom0_build.h> #include <asm/hvm/support.h> +#include <asm/hvm/vlapic.h> #include <asm/io_apic.h> #include <asm/p2m.h> #include <asm/paging.h> @@ -845,7 +846,7 @@ static int __init pvh_setup_acpi_madt(struct domain *d, paddr_t *addr) x2apic->header.type = ACPI_MADT_TYPE_LOCAL_X2APIC; x2apic->header.length = sizeof(*x2apic); x2apic->uid = i; - x2apic->local_apic_id = i * 2; + x2apic->local_apic_id = i * 2 + (i ? opt_x2apic_id_offset : 0); x2apic->lapic_flags = ACPI_MADT_ENABLED; x2apic++; } diff --git a/xen/arch/x86/hvm/vlapic.c b/xen/arch/x86/hvm/vlapic.c index b8c84458ff..34209d5378 100644 --- a/xen/arch/x86/hvm/vlapic.c +++ b/xen/arch/x86/hvm/vlapic.c @@ -24,6 +24,7 @@ #include <xen/domain_page.h> #include <xen/event.h> #include <xen/nospec.h> +#include <xen/param.h> #include <xen/trace.h> #include <xen/lib.h> #include <xen/sched.h> @@ -53,6 +54,9 @@ (LVT_MASK | APIC_MODE_MASK | APIC_INPUT_POLARITY |\ APIC_LVT_REMOTE_IRR | APIC_LVT_LEVEL_TRIGGER) +unsigned int opt_x2apic_id_offset; +integer_param("x2apic_id_offset", opt_x2apic_id_offset); + static const unsigned int vlapic_lvt_mask[VLAPIC_LVT_NUM] = { /* LVTT */ @@ -1073,7 +1077,7 @@ static void set_x2apic_id(struct vlapic *vlapic) u32 id = vlapic_vcpu(vlapic)->vcpu_id; u32 ldr = ((id & ~0xf) << 12) | (1 << (id & 0xf)); - vlapic_set_reg(vlapic, APIC_ID, id * 2); + vlapic_set_reg(vlapic, APIC_ID, id * 2 + (id ? opt_x2apic_id_offset : 0)); vlapic_set_reg(vlapic, APIC_LDR, ldr); } @@ -1443,7 +1447,13 @@ void vlapic_reset(struct vlapic *vlapic) if ( v->vcpu_id == 0 ) vlapic->hw.apic_base_msr |= APIC_BASE_BSP; - vlapic_set_reg(vlapic, APIC_ID, (v->vcpu_id * 2) << 24); + /* start in x2APIC mode. */ + vlapic->hw.apic_base_msr |= APIC_BASE_EXTD; + set_x2apic_id(vlapic); +#if 0 + vlapic_set_reg(vlapic, APIC_ID, id << 24); +#endif + vlapic_do_init(vlapic); } diff --git a/xen/arch/x86/include/asm/hvm/vlapic.h b/xen/arch/x86/include/asm/hvm/vlapic.h index 8f908928c3..6e837cb5bf 100644 --- a/xen/arch/x86/include/asm/hvm/vlapic.h +++ b/xen/arch/x86/include/asm/hvm/vlapic.h @@ -91,6 +91,8 @@ struct vlapic { } init_sipi; }; +extern unsigned int opt_x2apic_id_offset; + /* vlapic's frequence is 100 MHz */ #define APIC_BUS_CYCLE_NS 10 -- 2.34.1