Pull x86 fixes from Ingo Molnar: - Fix a secondary CPUs enumeration regression caused by creative MADT APIC table entries on certain systems. - Fix a race in the NOP-patcher that can spuriously trigger crashes on bootup. - Fix a bootup failure regression caused by the parallel bringup code, caused by firmware inconsistency between the APIC initialization states of the boot and secondary CPUs, on certain systems. * tag 'x86-urgent-2023-12-23' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/acpi: Handle bogus MADT APIC tables gracefully x86/alternatives: Disable interrupts and sync when optimizing NOPs in place x86/alternatives: Sync core before enabling interrupts x86/smpboot/64: Handle X2APIC BIOS inconsistency gracefully
Unified · Split
| @@ -293,6 +293,7 @@ acpi_parse_lapic(union acpi_subtable_headers * header, const unsigned long end) · 292 unmodified lines | |||
| 293 | processor->processor_id, /* ACPI ID */ | 293 | processor->processor_id, /* ACPI ID */ |
| 294 | processor->lapic_flags & ACPI_MADT_ENABLED); | 294 | processor->lapic_flags & ACPI_MADT_ENABLED); |
| 295 | 295 | ||
| 296 | has_lapic_cpus = true; | ||
| 296 | return 0; | 297 | return 0; |
| 297 | } | 298 | } |
| 298 | 299 | ||
| @@ -1134,7 +1135,6 @@ static int __init acpi_parse_madt_lapic_entries(void) · 835 unmodified lines | |||
| 1134 | if (!count) { | 1135 | if (!count) { |
| 1135 | count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC, | 1136 | count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_APIC, |
| 1136 | acpi_parse_lapic, MAX_LOCAL_APIC); | 1137 | acpi_parse_lapic, MAX_LOCAL_APIC); |
| 1137 | has_lapic_cpus = count > 0; | ||
| 1138 | x2count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_X2APIC, | 1138 | x2count = acpi_table_parse_madt(ACPI_MADT_TYPE_LOCAL_X2APIC, |
| 1139 | acpi_parse_x2apic, MAX_LOCAL_APIC); | 1139 | acpi_parse_x2apic, MAX_LOCAL_APIC); |
| 1140 | } | 1140 | } |
| @@ -255,6 +255,16 @@ static void __init_or_module noinline optimize_nops(u8 *instr, size_t len) · 254 unmodified lines | |||
| 255 | } | 255 | } |
| 256 | } | 256 | } |
| 257 | 257 | ||
| 258 | static void __init_or_module noinline optimize_nops_inplace(u8 *instr, size_t len) | ||
| 259 | { | ||
| 260 | unsigned long flags; | ||
| 261 | |||
| 262 | local_irq_save(flags); | ||
| 263 | optimize_nops(instr, len); | ||
| 264 | sync_core(); | ||
| 265 | local_irq_restore(flags); | ||
| 266 | } | ||
| 267 | |||
| 258 | /* | 268 | /* |
| 259 | * In this context, "source" is where the instructions are placed in the | 269 | * In this context, "source" is where the instructions are placed in the |
| 260 | * section .altinstr_replacement, for example during kernel build by the | 270 | * section .altinstr_replacement, for example during kernel build by the |
| @@ -438,7 +448,7 @@ void __init_or_module noinline apply_alternatives(struct alt_instr *start, · 177 unmodified lines | |||
| 438 | * patch if feature is *NOT* present. | 448 | * patch if feature is *NOT* present. |
| 439 | */ | 449 | */ |
| 440 | if (!boot_cpu_has(a->cpuid) == !(a->flags & ALT_FLAG_NOT)) { | 450 | if (!boot_cpu_has(a->cpuid) == !(a->flags & ALT_FLAG_NOT)) { |
| 441 | optimize_nops(instr, a->instrlen); | 451 | optimize_nops_inplace(instr, a->instrlen); |
| 442 | continue; | 452 | continue; |
| 443 | } | 453 | } |
| 444 | 454 | ||
| @@ -1685,8 +1695,8 @@ void __init_or_module text_poke_early(void *addr, const void *opcode, · 1240 unmodified lines | |||
| 1685 | } else { | 1695 | } else { |
| 1686 | local_irq_save(flags); | 1696 | local_irq_save(flags); |
| 1687 | memcpy(addr, opcode, len); | 1697 | memcpy(addr, opcode, len); |
| 1688 | local_irq_restore(flags); | ||
| 1689 | sync_core(); | 1698 | sync_core(); |
| 1699 | local_irq_restore(flags); | ||
| 1690 | 1700 | ||
| 1691 | /* | 1701 | /* |
| 1692 | * Could also do a CLFLUSH here to speed up CPU recovery; but | 1702 | * Could also do a CLFLUSH here to speed up CPU recovery; but |
| @@ -255,6 +255,22 @@ SYM_INNER_LABEL(secondary_startup_64_no_verify, SYM_L_GLOBAL) · 254 unmodified lines | |||
| 255 | testl $X2APIC_ENABLE, %eax | 255 | testl $X2APIC_ENABLE, %eax |
| 256 | jnz .Lread_apicid_msr | 256 | jnz .Lread_apicid_msr |
| 257 | 257 | ||
| 258 | #ifdef CONFIG_X86_X2APIC | ||
| 259 | /* | ||
| 260 | * If system is in X2APIC mode then MMIO base might not be | ||
| 261 | * mapped causing the MMIO read below to fault. Faults can't | ||
| 262 | * be handled at that point. | ||
| 263 | */ | ||
| 264 | cmpl $0, x2apic_mode(%rip) | ||
| 265 | jz .Lread_apicid_mmio | ||
| 266 | |||
| 267 | /* Force the AP into X2APIC mode. */ | ||
| 268 | orl $X2APIC_ENABLE, %eax | ||
| 269 | wrmsr | ||
| 270 | jmp .Lread_apicid_msr | ||
| 271 | #endif | ||
| 272 | |||
| 273 | .Lread_apicid_mmio: | ||
| 258 | /* Read the APIC ID from the fix-mapped MMIO space. */ | 274 | /* Read the APIC ID from the fix-mapped MMIO space. */ |
| 259 | movq apic_mmio_base(%rip), %rcx | 275 | movq apic_mmio_base(%rip), %rcx |
| 260 | addq $APIC_ID, %rcx | 276 | addq $APIC_ID, %rcx |