[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v2 5/8] tools/hvmloader: Retrieve (x2)APIC IDs from the APs themselves
Make it so the APs expose their own APIC IDs in a LUT. We can use that LUT to populate the MADT, decoupling the algorithm that relates CPU IDs and APIC IDs from hvmloader. While at this also remove ap_callin, as writing the APIC ID may serve the same purpose. Signed-off-by: Alejandro Vallejo <alejandro.vallejo@xxxxxxxxx> --- v2: * New patch. Replaces adding cpu policy to hvmloader in v1. --- tools/firmware/hvmloader/config.h | 6 ++++- tools/firmware/hvmloader/hvmloader.c | 4 +-- tools/firmware/hvmloader/smp.c | 40 +++++++++++++++++++++++----- tools/firmware/hvmloader/util.h | 5 ++++ xen/arch/x86/include/asm/hvm/hvm.h | 1 + 5 files changed, 47 insertions(+), 9 deletions(-) diff --git a/tools/firmware/hvmloader/config.h b/tools/firmware/hvmloader/config.h index c82adf6dc508..edf6fa9c908c 100644 --- a/tools/firmware/hvmloader/config.h +++ b/tools/firmware/hvmloader/config.h @@ -4,6 +4,8 @@ #include <stdint.h> #include <stdbool.h> +#include <xen/hvm/hvm_info_table.h> + enum virtual_vga { VGA_none, VGA_std, VGA_cirrus, VGA_pt }; extern enum virtual_vga virtual_vga; @@ -49,8 +51,10 @@ extern uint8_t ioapic_version; #define IOAPIC_ID 0x01 +extern uint32_t CPU_TO_X2APICID[HVM_MAX_VCPUS]; + #define LAPIC_BASE_ADDRESS 0xfee00000 -#define LAPIC_ID(vcpu_id) ((vcpu_id) * 2) +#define LAPIC_ID(vcpu_id) (CPU_TO_X2APICID[(vcpu_id)]) #define PCI_ISA_DEVFN 0x08 /* dev 1, fn 0 */ #define PCI_ISA_IRQ_MASK 0x0c20U /* ISA IRQs 5,10,11 are PCI connected */ diff --git a/tools/firmware/hvmloader/hvmloader.c b/tools/firmware/hvmloader/hvmloader.c index c58841e5b556..1eba92229925 100644 --- a/tools/firmware/hvmloader/hvmloader.c +++ b/tools/firmware/hvmloader/hvmloader.c @@ -342,11 +342,11 @@ int main(void) printf("CPU speed is %u MHz\n", get_cpu_mhz()); + smp_initialise(); + apic_setup(); pci_setup(); - smp_initialise(); - perform_tests(); if ( bios->bios_info_setup ) diff --git a/tools/firmware/hvmloader/smp.c b/tools/firmware/hvmloader/smp.c index a668f15d7e1f..4d75f239c2f5 100644 --- a/tools/firmware/hvmloader/smp.c +++ b/tools/firmware/hvmloader/smp.c @@ -29,7 +29,34 @@ #include <xen/vcpu.h> -static int ap_callin, ap_cpuid; +static int ap_cpuid; + +/** + * Lookup table of x2APIC IDs. + * + * Each entry is populated its respective CPU as they come online. This is required + * for generating the MADT with minimal assumptions about ID relationships. + */ +uint32_t CPU_TO_X2APICID[HVM_MAX_VCPUS]; + +static uint32_t read_apic_id(void) +{ + uint32_t apic_id; + + cpuid(1, NULL, &apic_id, NULL, NULL); + apic_id >>= 24; + + /* + * APIC IDs over 255 are represented by 255 in leaf 1 and are meant to be + * read from topology leaves instead. Xen exposes x2APIC IDs in leaf 0xb, + * but only if the x2APIC feature is present. If there are that many CPUs + * it's guaranteed to be there so we can avoid checking for it specifically + */ + if ( apic_id == 255 ) + cpuid(0xb, NULL, NULL, NULL, &apic_id); + + return apic_id; +} static void ap_start(void) { @@ -37,12 +64,12 @@ static void ap_start(void) cacheattr_init(); printf("done.\n"); + wmb(); + ACCESS_ONCE(CPU_TO_X2APICID[ap_cpuid]) = read_apic_id(); + if ( !ap_cpuid ) return; - wmb(); - ap_callin = 1; - while ( 1 ) asm volatile ( "hlt" ); } @@ -86,10 +113,11 @@ static void boot_cpu(unsigned int cpu) BUG(); /* - * Wait for the secondary processor to complete initialisation. + * Wait for the secondary processor to complete initialisation, + * which is signaled by its x2APIC ID being writted to the LUT. * Do not touch shared resources meanwhile. */ - while ( !ap_callin ) + while ( !ACCESS_ONCE(CPU_TO_X2APICID[cpu]) ) cpu_relax(); /* Take the secondary processor offline. */ diff --git a/tools/firmware/hvmloader/util.h b/tools/firmware/hvmloader/util.h index 14078bde1e30..51e9003bc615 100644 --- a/tools/firmware/hvmloader/util.h +++ b/tools/firmware/hvmloader/util.h @@ -23,6 +23,11 @@ enum { #define __STR(...) #__VA_ARGS__ #define STR(...) __STR(__VA_ARGS__) +#define __ACCESS_ONCE(x) ({ \ + (void)(typeof(x))0; /* Scalar typecheck. */ \ + (volatile typeof(x) *)&(x); }) +#define ACCESS_ONCE(x) (*__ACCESS_ONCE(x)) + /* GDT selector values. */ #define SEL_CODE16 0x0008 #define SEL_DATA16 0x0010 diff --git a/xen/arch/x86/include/asm/hvm/hvm.h b/xen/arch/x86/include/asm/hvm/hvm.h index 84911f3ebcb4..6c005f0b0b38 100644 --- a/xen/arch/x86/include/asm/hvm/hvm.h +++ b/xen/arch/x86/include/asm/hvm/hvm.h @@ -16,6 +16,7 @@ #include <asm/current.h> #include <asm/x86_emulate.h> #include <asm/hvm/asid.h> +#include <asm/hvm/vlapic.h> struct pirq; /* needed by pi_update_irte */ -- 2.34.1
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |