Skip to content

Commit 0a23fb2

Browse files
committed
Merge tag 'x86_microcode_for_v6.7_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 microcode loading updates from Borislac Petkov: "Major microcode loader restructuring, cleanup and improvements by Thomas Gleixner: - Restructure the code needed for it and add a temporary initrd mapping on 32-bit so that the loader can access the microcode blobs. This in itself is a preparation for the next major improvement: - Do not load microcode on 32-bit before paging has been enabled. Handling this has caused an endless stream of headaches, issues, ugly code and unnecessary hacks in the past. And there really wasn't any sensible reason to do that in the first place. So switch the 32-bit loading to happen after paging has been enabled and turn the loader code "real purrty" again - Drop mixed microcode steppings loading on Intel - there, a single patch loaded on the whole system is sufficient - Rework late loading to track which CPUs have updated microcode successfully and which haven't, act accordingly - Move late microcode loading on Intel in NMI context in order to guarantee concurrent loading on all threads - Make the late loading CPU-hotplug-safe and have the offlined threads be woken up for the purpose of the update - Add support for a minimum revision which determines whether late microcode loading is safe on a machine and the microcode does not change software visible features which the machine cannot use anyway since feature detection has happened already. Roughly, the minimum revision is the smallest revision number which must be loaded currently on the system so that late updates can be allowed - Other nice leanups, fixess, etc all over the place" * tag 'x86_microcode_for_v6.7_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (40 commits) x86/microcode/intel: Add a minimum required revision for late loading x86/microcode: Prepare for minimal revision check x86/microcode: Handle "offline" CPUs correctly x86/apic: Provide apic_force_nmi_on_cpu() x86/microcode: Protect against instrumentation x86/microcode: Rendezvous and load in NMI x86/microcode: Replace the all-in-one rendevous handler x86/microcode: Provide new control functions x86/microcode: Add per CPU control field x86/microcode: Add per CPU result state x86/microcode: Sanitize __wait_for_cpus() x86/microcode: Clarify the late load logic x86/microcode: Handle "nosmt" correctly x86/microcode: Clean up mc_cpu_down_prep() x86/microcode: Get rid of the schedule work indirection x86/microcode: Mop up early loading leftovers x86/microcode/amd: Use cached microcode for AP load x86/microcode/amd: Cache builtin/initrd microcode early x86/microcode/amd: Cache builtin microcode too x86/microcode/amd: Use correct per CPU ucode_cpu_info ...
2 parents 5c5e048 + cf5ab01 commit 0a23fb2

File tree

21 files changed

+905
-910
lines changed

21 files changed

+905
-910
lines changed

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3333,6 +3333,11 @@
33333333

33343334
mga= [HW,DRM]
33353335

3336+
microcode.force_minrev= [X86]
3337+
Format: <bool>
3338+
Enable or disable the microcode minimal revision
3339+
enforcement for the runtime microcode loader.
3340+
33363341
min_addr=nn[KMG] [KNL,BOOT,IA-64] All physical memory below this
33373342
physical address is ignored.
33383343

arch/x86/Kconfig

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1313,16 +1313,41 @@ config MICROCODE
13131313
def_bool y
13141314
depends on CPU_SUP_AMD || CPU_SUP_INTEL
13151315

1316+
config MICROCODE_INITRD32
1317+
def_bool y
1318+
depends on MICROCODE && X86_32 && BLK_DEV_INITRD
1319+
13161320
config MICROCODE_LATE_LOADING
13171321
bool "Late microcode loading (DANGEROUS)"
13181322
default n
1319-
depends on MICROCODE
1323+
depends on MICROCODE && SMP
13201324
help
13211325
Loading microcode late, when the system is up and executing instructions
13221326
is a tricky business and should be avoided if possible. Just the sequence
13231327
of synchronizing all cores and SMT threads is one fragile dance which does
13241328
not guarantee that cores might not softlock after the loading. Therefore,
1325-
use this at your own risk. Late loading taints the kernel too.
1329+
use this at your own risk. Late loading taints the kernel unless the
1330+
microcode header indicates that it is safe for late loading via the
1331+
minimal revision check. This minimal revision check can be enforced on
1332+
the kernel command line with "microcode.minrev=Y".
1333+
1334+
config MICROCODE_LATE_FORCE_MINREV
1335+
bool "Enforce late microcode loading minimal revision check"
1336+
default n
1337+
depends on MICROCODE_LATE_LOADING
1338+
help
1339+
To prevent that users load microcode late which modifies already
1340+
in use features, newer microcode patches have a minimum revision field
1341+
in the microcode header, which tells the kernel which minimum
1342+
revision must be active in the CPU to safely load that new microcode
1343+
late into the running system. If disabled the check will not
1344+
be enforced but the kernel will be tainted when the minimal
1345+
revision check fails.
1346+
1347+
This minimal revision check can also be controlled via the
1348+
"microcode.minrev" parameter on the kernel command line.
1349+
1350+
If unsure say Y.
13261351

13271352
config X86_MSR
13281353
tristate "/dev/cpu/*/msr - Model-specific register support"

arch/x86/include/asm/apic.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,8 @@ struct apic {
276276

277277
u32 disable_esr : 1,
278278
dest_mode_logical : 1,
279-
x2apic_set_max_apicid : 1;
279+
x2apic_set_max_apicid : 1,
280+
nmi_to_offline_cpu : 1;
280281

281282
u32 (*calc_dest_apicid)(unsigned int cpu);
282283

@@ -531,6 +532,8 @@ extern u32 apic_flat_calc_apicid(unsigned int cpu);
531532
extern void default_ioapic_phys_id_map(physid_mask_t *phys_map, physid_mask_t *retmap);
532533
extern u32 default_cpu_present_to_apicid(int mps_cpu);
533534

535+
void apic_send_nmi_to_offline_cpu(unsigned int cpu);
536+
534537
#else /* CONFIG_X86_LOCAL_APIC */
535538

536539
static inline u32 read_apic_id(void) { return 0; }

arch/x86/include/asm/cpu.h

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -71,26 +71,12 @@ static inline void init_ia32_feat_ctl(struct cpuinfo_x86 *c) {}
7171

7272
extern __noendbr void cet_disable(void);
7373

74-
struct ucode_cpu_info;
74+
struct cpu_signature;
7575

76-
int intel_cpu_collect_info(struct ucode_cpu_info *uci);
77-
78-
static inline bool intel_cpu_signatures_match(unsigned int s1, unsigned int p1,
79-
unsigned int s2, unsigned int p2)
80-
{
81-
if (s1 != s2)
82-
return false;
83-
84-
/* Processor flags are either both 0 ... */
85-
if (!p1 && !p2)
86-
return true;
87-
88-
/* ... or they intersect. */
89-
return p1 & p2;
90-
}
76+
void intel_collect_cpu_info(struct cpu_signature *sig);
9177

9278
extern u64 x86_read_arch_cap_msr(void);
93-
int intel_find_matching_signature(void *mc, unsigned int csig, int cpf);
79+
bool intel_find_matching_signature(void *mc, struct cpu_signature *sig);
9480
int intel_microcode_sanity_check(void *mc, bool print_err, int hdr_type);
9581

9682
extern struct cpumask cpus_stop_mask;

arch/x86/include/asm/microcode.h

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ static inline void load_ucode_ap(void) { }
2323
static inline void microcode_bsp_resume(void) { }
2424
#endif
2525

26+
extern unsigned long initrd_start_early;
27+
2628
#ifdef CONFIG_CPU_SUP_INTEL
2729
/* Intel specific microcode defines. Public for IFS */
2830
struct microcode_header_intel {
@@ -36,7 +38,8 @@ struct microcode_header_intel {
3638
unsigned int datasize;
3739
unsigned int totalsize;
3840
unsigned int metasize;
39-
unsigned int reserved[2];
41+
unsigned int min_req_ver;
42+
unsigned int reserved;
4043
};
4144

4245
struct microcode_intel {
@@ -68,11 +71,19 @@ static inline u32 intel_get_microcode_revision(void)
6871

6972
return rev;
7073
}
74+
#endif /* !CONFIG_CPU_SUP_INTEL */
7175

72-
void show_ucode_info_early(void);
76+
bool microcode_nmi_handler(void);
77+
void microcode_offline_nmi_handler(void);
7378

74-
#else /* CONFIG_CPU_SUP_INTEL */
75-
static inline void show_ucode_info_early(void) { }
76-
#endif /* !CONFIG_CPU_SUP_INTEL */
79+
#ifdef CONFIG_MICROCODE_LATE_LOADING
80+
DECLARE_STATIC_KEY_FALSE(microcode_nmi_handler_enable);
81+
static __always_inline bool microcode_nmi_handler_enabled(void)
82+
{
83+
return static_branch_unlikely(&microcode_nmi_handler_enable);
84+
}
85+
#else
86+
static __always_inline bool microcode_nmi_handler_enabled(void) { return false; }
87+
#endif
7788

7889
#endif /* _ASM_X86_MICROCODE_H */

arch/x86/include/asm/setup.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ void clear_bss(void);
126126
#ifdef __i386__
127127

128128
asmlinkage void __init __noreturn i386_start_kernel(void);
129+
void __init mk_early_pgtbl_32(void);
129130

130131
#else
131132
asmlinkage void __init __noreturn x86_64_start_kernel(char *real_mode);

arch/x86/kernel/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ CFLAGS_REMOVE_kvmclock.o = -pg
1616
CFLAGS_REMOVE_ftrace.o = -pg
1717
CFLAGS_REMOVE_early_printk.o = -pg
1818
CFLAGS_REMOVE_head64.o = -pg
19+
CFLAGS_REMOVE_head32.o = -pg
1920
CFLAGS_REMOVE_sev.o = -pg
2021
CFLAGS_REMOVE_rethook.o = -pg
2122
endif

arch/x86/kernel/apic/apic_flat_64.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ static struct apic apic_flat __ro_after_init = {
103103
.send_IPI_allbutself = default_send_IPI_allbutself,
104104
.send_IPI_all = default_send_IPI_all,
105105
.send_IPI_self = default_send_IPI_self,
106+
.nmi_to_offline_cpu = true,
106107

107108
.read = native_apic_mem_read,
108109
.write = native_apic_mem_write,
@@ -173,6 +174,7 @@ static struct apic apic_physflat __ro_after_init = {
173174
.send_IPI_allbutself = default_send_IPI_allbutself,
174175
.send_IPI_all = default_send_IPI_all,
175176
.send_IPI_self = default_send_IPI_self,
177+
.nmi_to_offline_cpu = true,
176178

177179
.read = native_apic_mem_read,
178180
.write = native_apic_mem_write,

arch/x86/kernel/apic/ipi.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,14 @@ void native_send_call_func_ipi(const struct cpumask *mask)
9797
__apic_send_IPI_mask(mask, CALL_FUNCTION_VECTOR);
9898
}
9999

100+
void apic_send_nmi_to_offline_cpu(unsigned int cpu)
101+
{
102+
if (WARN_ON_ONCE(!apic->nmi_to_offline_cpu))
103+
return;
104+
if (WARN_ON_ONCE(!cpumask_test_cpu(cpu, &cpus_booted_once_mask)))
105+
return;
106+
apic->send_IPI(cpu, NMI_VECTOR);
107+
}
100108
#endif /* CONFIG_SMP */
101109

102110
static inline int __prepare_ICR2(unsigned int mask)

arch/x86/kernel/apic/x2apic_cluster.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ static struct apic apic_x2apic_cluster __ro_after_init = {
251251
.send_IPI_allbutself = x2apic_send_IPI_allbutself,
252252
.send_IPI_all = x2apic_send_IPI_all,
253253
.send_IPI_self = x2apic_send_IPI_self,
254+
.nmi_to_offline_cpu = true,
254255

255256
.read = native_apic_msr_read,
256257
.write = native_apic_msr_write,

0 commit comments

Comments
 (0)