Re: [patch V4 36/37] x86/smpboot: Support parallel startup of secondary CPUs
On 5/19/2023 10:57 AM, Andrew Cooper wrote: On 19/05/2023 5:28 pm, Jeffrey Hugo wrote: DESCEND objtool INSTALL libsubcmd_headers CALL scripts/checksyscalls.sh AS arch/x86/kernel/head_64.o arch/x86/kernel/head_64.S: Assembler messages: arch/x86/kernel/head_64.S:261: Error: missing ')' arch/x86/kernel/head_64.S:261: Error: junk `UL<<10)' after expression CC arch/x86/kernel/head64.o CC arch/x86/kernel/ebda.o CC arch/x86/kernel/platform-quirks.o scripts/Makefile.build:374: recipe for target 'arch/x86/kernel/head_64.o' failed make[3]: *** [arch/x86/kernel/head_64.o] Error 1 make[3]: *** Waiting for unfinished jobs scripts/Makefile.build:494: recipe for target 'arch/x86/kernel' failed make[2]: *** [arch/x86/kernel] Error 2 scripts/Makefile.build:494: recipe for target 'arch/x86' failed make[1]: *** [arch/x86] Error 2 make[1]: *** Waiting for unfinished jobs Makefile:2026: recipe for target '.' failed make: *** [.] Error 2 This is with GCC 5.4.0, if it matters. Reverting this change allows the build to move forward, although I also need to revert "x86/smpboot/64: Implement arch_cpuhp_init_parallel_bringup() and enable it" for the build to fully succeed. I'm not familiar with this code, and nothing obvious stands out to me. What can I do to help root cause this? Can you try: -#define XAPIC_ENABLE (1UL << 11) -#define X2APIC_ENABLE (1UL << 10) +#define XAPIC_ENABLE BIT(11) +#define X2APIC_ENABLE BIT(10) The UL suffix isn't understood by older binutils, and this patch adds the first use of these constants in assembly. Ah, makes sense. Your suggested change works for me. No more compile error. I assume you will be following up with a patch to address this. Feel free to add the following tags as you see fit: Reported-by: Jeffrey Hugo Tested-by: Jeffrey Hugo -Jeff
Re: [patch V4 36/37] x86/smpboot: Support parallel startup of secondary CPUs
On 5/12/2023 3:07 PM, Thomas Gleixner wrote: From: David Woodhouse In parallel startup mode the APs are kicked alive by the control CPU quickly after each other and run through the early startup code in parallel. The real-mode startup code is already serialized with a bit-spinlock to protect the real-mode stack. In parallel startup mode the smpboot_control variable obviously cannot contain the Linux CPU number so the APs have to determine their Linux CPU number on their own. This is required to find the CPUs per CPU offset in order to find the idle task stack and other per CPU data. To achieve this, export the cpuid_to_apicid[] array so that each AP can find its own CPU number by searching therein based on its APIC ID. Introduce a flag in the top bits of smpboot_control which indicates that the AP should find its CPU number by reading the APIC ID from the APIC. This is required because CPUID based APIC ID retrieval can only provide the initial APIC ID, which might have been overruled by the firmware. Some AMD APUs come up with APIC ID = initial APIC ID + 0x10, so the APIC ID to CPU number lookup would fail miserably if based on CPUID. Also virtualization can make its own APIC ID assignements. The only requirement is that the APIC IDs are consistent with the APCI/MADT table. For the boot CPU or in case parallel bringup is disabled the control bits are empty and the CPU number is directly available in bit 0-23 of smpboot_control. [ tglx: Initial proof of concept patch with bitlock and APIC ID lookup ] [ dwmw2: Rework and testing, commit message, CPUID 0x1 and CPU0 support ] [ seanc: Fix stray override of initial_gs in common_cpu_up() ] [ Oleksandr Natalenko: reported suspend/resume issue fixed in x86_acpi_suspend_lowlevel ] [ tglx: Make it read the APIC ID from the APIC instead of using CPUID, split the bitlock part out ] Co-developed-by: Thomas Gleixner Co-developed-by: Brian Gerst Signed-off-by: Thomas Gleixner Signed-off-by: Brian Gerst Signed-off-by: David Woodhouse Signed-off-by: Thomas Gleixner Tested-by: Michael Kelley --- I pulled in this change via the next tree, tag next-20230519 and I get a build failure using the x86_64_defconfig - DESCEND objtool INSTALL libsubcmd_headers CALLscripts/checksyscalls.sh AS arch/x86/kernel/head_64.o arch/x86/kernel/head_64.S: Assembler messages: arch/x86/kernel/head_64.S:261: Error: missing ')' arch/x86/kernel/head_64.S:261: Error: junk `UL<<10)' after expression CC arch/x86/kernel/head64.o CC arch/x86/kernel/ebda.o CC arch/x86/kernel/platform-quirks.o scripts/Makefile.build:374: recipe for target 'arch/x86/kernel/head_64.o' failed make[3]: *** [arch/x86/kernel/head_64.o] Error 1 make[3]: *** Waiting for unfinished jobs scripts/Makefile.build:494: recipe for target 'arch/x86/kernel' failed make[2]: *** [arch/x86/kernel] Error 2 scripts/Makefile.build:494: recipe for target 'arch/x86' failed make[1]: *** [arch/x86] Error 2 make[1]: *** Waiting for unfinished jobs Makefile:2026: recipe for target '.' failed make: *** [.] Error 2 This is with GCC 5.4.0, if it matters. Reverting this change allows the build to move forward, although I also need to revert "x86/smpboot/64: Implement arch_cpuhp_init_parallel_bringup() and enable it" for the build to fully succeed. I'm not familiar with this code, and nothing obvious stands out to me. What can I do to help root cause this? -Jeff
Re: [patch V4 36/37] x86/smpboot: Support parallel startup of secondary CPUs
On 19/05/2023 5:28 pm, Jeffrey Hugo wrote: > DESCEND objtool > INSTALL libsubcmd_headers > CALL scripts/checksyscalls.sh > AS arch/x86/kernel/head_64.o > arch/x86/kernel/head_64.S: Assembler messages: > arch/x86/kernel/head_64.S:261: Error: missing ')' > arch/x86/kernel/head_64.S:261: Error: junk `UL<<10)' after expression > CC arch/x86/kernel/head64.o > CC arch/x86/kernel/ebda.o > CC arch/x86/kernel/platform-quirks.o > scripts/Makefile.build:374: recipe for target > 'arch/x86/kernel/head_64.o' failed > make[3]: *** [arch/x86/kernel/head_64.o] Error 1 > make[3]: *** Waiting for unfinished jobs > scripts/Makefile.build:494: recipe for target 'arch/x86/kernel' failed > make[2]: *** [arch/x86/kernel] Error 2 > scripts/Makefile.build:494: recipe for target 'arch/x86' failed > make[1]: *** [arch/x86] Error 2 > make[1]: *** Waiting for unfinished jobs > Makefile:2026: recipe for target '.' failed > make: *** [.] Error 2 > > This is with GCC 5.4.0, if it matters. > > Reverting this change allows the build to move forward, although I > also need to revert "x86/smpboot/64: Implement > arch_cpuhp_init_parallel_bringup() and enable it" for the build to > fully succeed. > > I'm not familiar with this code, and nothing obvious stands out to me. > What can I do to help root cause this? Can you try: -#define XAPIC_ENABLE (1UL << 11) -#define X2APIC_ENABLE (1UL << 10) +#define XAPIC_ENABLE BIT(11) +#define X2APIC_ENABLE BIT(10) The UL suffix isn't understood by older binutils, and this patch adds the first use of these constants in assembly. ~Andrew
[patch V4 36/37] x86/smpboot: Support parallel startup of secondary CPUs
From: David Woodhouse In parallel startup mode the APs are kicked alive by the control CPU quickly after each other and run through the early startup code in parallel. The real-mode startup code is already serialized with a bit-spinlock to protect the real-mode stack. In parallel startup mode the smpboot_control variable obviously cannot contain the Linux CPU number so the APs have to determine their Linux CPU number on their own. This is required to find the CPUs per CPU offset in order to find the idle task stack and other per CPU data. To achieve this, export the cpuid_to_apicid[] array so that each AP can find its own CPU number by searching therein based on its APIC ID. Introduce a flag in the top bits of smpboot_control which indicates that the AP should find its CPU number by reading the APIC ID from the APIC. This is required because CPUID based APIC ID retrieval can only provide the initial APIC ID, which might have been overruled by the firmware. Some AMD APUs come up with APIC ID = initial APIC ID + 0x10, so the APIC ID to CPU number lookup would fail miserably if based on CPUID. Also virtualization can make its own APIC ID assignements. The only requirement is that the APIC IDs are consistent with the APCI/MADT table. For the boot CPU or in case parallel bringup is disabled the control bits are empty and the CPU number is directly available in bit 0-23 of smpboot_control. [ tglx: Initial proof of concept patch with bitlock and APIC ID lookup ] [ dwmw2: Rework and testing, commit message, CPUID 0x1 and CPU0 support ] [ seanc: Fix stray override of initial_gs in common_cpu_up() ] [ Oleksandr Natalenko: reported suspend/resume issue fixed in x86_acpi_suspend_lowlevel ] [ tglx: Make it read the APIC ID from the APIC instead of using CPUID, split the bitlock part out ] Co-developed-by: Thomas Gleixner Co-developed-by: Brian Gerst Signed-off-by: Thomas Gleixner Signed-off-by: Brian Gerst Signed-off-by: David Woodhouse Signed-off-by: Thomas Gleixner Tested-by: Michael Kelley --- V4: Remove the lock prefix in the error path - Peter Z. --- arch/x86/include/asm/apic.h|2 + arch/x86/include/asm/apicdef.h |5 ++- arch/x86/include/asm/smp.h |6 arch/x86/kernel/acpi/sleep.c |9 +- arch/x86/kernel/apic/apic.c|2 - arch/x86/kernel/head_64.S | 61 + arch/x86/kernel/smpboot.c |2 - 7 files changed, 83 insertions(+), 4 deletions(-) --- a/arch/x86/include/asm/apic.h +++ b/arch/x86/include/asm/apic.h @@ -55,6 +55,8 @@ extern int local_apic_timer_c2_ok; extern int disable_apic; extern unsigned int lapic_timer_period; +extern int cpuid_to_apicid[]; + extern enum apic_intr_mode_id apic_intr_mode; enum apic_intr_mode_id { APIC_PIC, --- a/arch/x86/include/asm/apicdef.h +++ b/arch/x86/include/asm/apicdef.h @@ -138,7 +138,8 @@ #defineAPIC_EILVT_MASKED (1 << 16) #define APIC_BASE (fix_to_virt(FIX_APIC_BASE)) -#define APIC_BASE_MSR 0x800 +#define APIC_BASE_MSR 0x800 +#define APIC_X2APIC_ID_MSR 0x802 #define XAPIC_ENABLE (1UL << 11) #define X2APIC_ENABLE (1UL << 10) @@ -162,6 +163,7 @@ #define APIC_CPUID(apicid) ((apicid) & XAPIC_DEST_CPUS_MASK) #define NUM_APIC_CLUSTERS ((BAD_APICID + 1) >> XAPIC_DEST_CPUS_SHIFT) +#ifndef __ASSEMBLY__ /* * the local APIC register structure, memory mapped. Not terribly well * tested, but we might eventually use this one in the future - the @@ -435,4 +437,5 @@ enum apic_delivery_modes { APIC_DELIVERY_MODE_EXTINT = 7, }; +#endif /* !__ASSEMBLY__ */ #endif /* _ASM_X86_APICDEF_H */ --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -200,4 +200,10 @@ extern unsigned long apic_mmio_base; #endif /* !__ASSEMBLY__ */ +/* Control bits for startup_64 */ +#define STARTUP_READ_APICID0x8000 + +/* Top 8 bits are reserved for control */ +#define STARTUP_PARALLEL_MASK 0xFF00 + #endif /* _ASM_X86_SMP_H */ --- a/arch/x86/kernel/acpi/sleep.c +++ b/arch/x86/kernel/acpi/sleep.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include "../../realmode/rm/wakeup.h" @@ -127,7 +128,13 @@ int x86_acpi_suspend_lowlevel(void) * value is in the actual %rsp register. */ current->thread.sp = (unsigned long)temp_stack + sizeof(temp_stack); - smpboot_control = smp_processor_id(); + /* +* Ensure the CPU knows which one it is when it comes back, if +* it isn't in parallel mode and expected to work that out for +* itself. +*/ + if (!(smpboot_control & STARTUP_PARALLEL_MASK)) + smpboot_control = smp_processor_id(); #endif initial_code = (unsigned long)wakeup_long64; saved_magic = 0x123456789abcdef0L; --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c @@ -2380,7 +2380,7 @@ static int nr_logical_cpuids = 1; /* * Used to