Skip to content

Commit a5dbd76

Browse files
committed
Merge tag 'x86-urgent-2024-08-04' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 fixes from Thomas Gleixner: - Prevent a deadlock on cpu_hotplug_lock in the aperf/mperf driver. A recent change in the ACPI code which consolidated code pathes moved the invocation of init_freq_invariance_cppc() to be moved to a CPU hotplug handler. The first invocation on AMD CPUs ends up enabling a static branch which dead locks because the static branch enable tries to acquire cpu_hotplug_lock but that lock is already held write by the hotplug machinery. Use static_branch_enable_cpuslocked() instead and take the hotplug lock read for the Intel code path which is invoked from the architecture code outside of the CPU hotplug operations. - Fix the number of reserved bits in the sev_config structure bit field so that the bitfield does not exceed 64 bit. - Add missing Zen5 model numbers - Fix the alignment assumptions of pti_clone_pgtable() and clone_entry_text() on 32-bit: The code assumes PMD aligned code sections, but on 32-bit the kernel entry text is not PMD aligned. So depending on the code size and location, which is configuration and compiler dependent, entry text can cross a PMD boundary. As the start is not PMD aligned adding PMD size to the start address is larger than the end address which results in partially mapped entry code for user space. That causes endless recursion on the first entry from userspace (usually #PF). Cure this by aligning the start address in the addition so it ends up at the next PMD start address. clone_entry_text() enforces PMD mapping, but on 32-bit the tail might eventually be PTE mapped, which causes a map fail because the PMD for the tail is not a large page mapping. Use PTI_LEVEL_KERNEL_IMAGE for the clone() invocation which resolves to PTE on 32-bit and PMD on 64-bit. - Zero the 8-byte case for get_user() on range check failure on 32-bit The recend consolidation of the 8-byte get_user() case broke the zeroing in the failure case again. Establish it by clearing ECX before the range check and not afterwards as that obvioulsy can't be reached when the range check fails * tag 'x86-urgent-2024-08-04' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/uaccess: Zero the 8-byte get_range case on failure on 32-bit x86/mm: Fix pti_clone_entry_text() for i386 x86/mm: Fix pti_clone_pgtable() alignment assumption x86/setup: Parse the builtin command line before merging x86/CPU/AMD: Add models 0x60-0x6f to the Zen5 range x86/sev: Fix __reserved field in sev_config x86/aperfmperf: Fix deadlock on cpu_hotplug_lock
2 parents 61ca6c7 + dd35a09 commit a5dbd76

File tree

8 files changed

+36
-17
lines changed

8 files changed

+36
-17
lines changed

arch/x86/coco/sev/core.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ struct sev_config {
163163
*/
164164
use_cas : 1,
165165

166-
__reserved : 62;
166+
__reserved : 61;
167167
};
168168

169169
static struct sev_config sev_cfg __read_mostly;

arch/x86/include/asm/cmdline.h

+4
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22
#ifndef _ASM_X86_CMDLINE_H
33
#define _ASM_X86_CMDLINE_H
44

5+
#include <asm/setup.h>
6+
7+
extern char builtin_cmdline[COMMAND_LINE_SIZE];
8+
59
int cmdline_find_option_bool(const char *cmdline_ptr, const char *option);
610
int cmdline_find_option(const char *cmdline_ptr, const char *option,
711
char *buffer, int bufsize);

arch/x86/kernel/cpu/amd.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,7 @@ static void bsp_init_amd(struct cpuinfo_x86 *c)
462462
switch (c->x86_model) {
463463
case 0x00 ... 0x2f:
464464
case 0x40 ... 0x4f:
465-
case 0x70 ... 0x7f:
465+
case 0x60 ... 0x7f:
466466
setup_force_cpu_cap(X86_FEATURE_ZEN5);
467467
break;
468468
default:

arch/x86/kernel/cpu/aperfmperf.c

+4-2
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ static void freq_invariance_enable(void)
306306
WARN_ON_ONCE(1);
307307
return;
308308
}
309-
static_branch_enable(&arch_scale_freq_key);
309+
static_branch_enable_cpuslocked(&arch_scale_freq_key);
310310
register_freq_invariance_syscore_ops();
311311
pr_info("Estimated ratio of average max frequency by base frequency (times 1024): %llu\n", arch_max_freq_ratio);
312312
}
@@ -323,8 +323,10 @@ static void __init bp_init_freq_invariance(void)
323323
if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)
324324
return;
325325

326-
if (intel_set_max_freq_ratio())
326+
if (intel_set_max_freq_ratio()) {
327+
guard(cpus_read_lock)();
327328
freq_invariance_enable();
329+
}
328330
}
329331

330332
static void disable_freq_invariance_workfn(struct work_struct *work)

arch/x86/kernel/setup.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ unsigned long saved_video_mode;
164164

165165
static char __initdata command_line[COMMAND_LINE_SIZE];
166166
#ifdef CONFIG_CMDLINE_BOOL
167-
static char __initdata builtin_cmdline[COMMAND_LINE_SIZE] = CONFIG_CMDLINE;
167+
char builtin_cmdline[COMMAND_LINE_SIZE] = CONFIG_CMDLINE;
168168
bool builtin_cmdline_added __ro_after_init;
169169
#endif
170170

arch/x86/lib/cmdline.c

+18-7
Original file line numberDiff line numberDiff line change
@@ -207,18 +207,29 @@ __cmdline_find_option(const char *cmdline, int max_cmdline_size,
207207

208208
int cmdline_find_option_bool(const char *cmdline, const char *option)
209209
{
210-
if (IS_ENABLED(CONFIG_CMDLINE_BOOL))
211-
WARN_ON_ONCE(!builtin_cmdline_added);
210+
int ret;
212211

213-
return __cmdline_find_option_bool(cmdline, COMMAND_LINE_SIZE, option);
212+
ret = __cmdline_find_option_bool(cmdline, COMMAND_LINE_SIZE, option);
213+
if (ret > 0)
214+
return ret;
215+
216+
if (IS_ENABLED(CONFIG_CMDLINE_BOOL) && !builtin_cmdline_added)
217+
return __cmdline_find_option_bool(builtin_cmdline, COMMAND_LINE_SIZE, option);
218+
219+
return ret;
214220
}
215221

216222
int cmdline_find_option(const char *cmdline, const char *option, char *buffer,
217223
int bufsize)
218224
{
219-
if (IS_ENABLED(CONFIG_CMDLINE_BOOL))
220-
WARN_ON_ONCE(!builtin_cmdline_added);
225+
int ret;
226+
227+
ret = __cmdline_find_option(cmdline, COMMAND_LINE_SIZE, option, buffer, bufsize);
228+
if (ret > 0)
229+
return ret;
230+
231+
if (IS_ENABLED(CONFIG_CMDLINE_BOOL) && !builtin_cmdline_added)
232+
return __cmdline_find_option(builtin_cmdline, COMMAND_LINE_SIZE, option, buffer, bufsize);
221233

222-
return __cmdline_find_option(cmdline, COMMAND_LINE_SIZE, option,
223-
buffer, bufsize);
234+
return ret;
224235
}

arch/x86/lib/getuser.S

+3-1
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,14 @@ SYM_FUNC_END(__get_user_4)
8888
EXPORT_SYMBOL(__get_user_4)
8989

9090
SYM_FUNC_START(__get_user_8)
91+
#ifndef CONFIG_X86_64
92+
xor %ecx,%ecx
93+
#endif
9194
check_range size=8
9295
ASM_STAC
9396
#ifdef CONFIG_X86_64
9497
UACCESS movq (%_ASM_AX),%rdx
9598
#else
96-
xor %ecx,%ecx
9799
UACCESS movl (%_ASM_AX),%edx
98100
UACCESS movl 4(%_ASM_AX),%ecx
99101
#endif

arch/x86/mm/pti.c

+4-4
Original file line numberDiff line numberDiff line change
@@ -374,14 +374,14 @@ pti_clone_pgtable(unsigned long start, unsigned long end,
374374
*/
375375
*target_pmd = *pmd;
376376

377-
addr += PMD_SIZE;
377+
addr = round_up(addr + 1, PMD_SIZE);
378378

379379
} else if (level == PTI_CLONE_PTE) {
380380

381381
/* Walk the page-table down to the pte level */
382382
pte = pte_offset_kernel(pmd, addr);
383383
if (pte_none(*pte)) {
384-
addr += PAGE_SIZE;
384+
addr = round_up(addr + 1, PAGE_SIZE);
385385
continue;
386386
}
387387

@@ -401,7 +401,7 @@ pti_clone_pgtable(unsigned long start, unsigned long end,
401401
/* Clone the PTE */
402402
*target_pte = *pte;
403403

404-
addr += PAGE_SIZE;
404+
addr = round_up(addr + 1, PAGE_SIZE);
405405

406406
} else {
407407
BUG();
@@ -496,7 +496,7 @@ static void pti_clone_entry_text(void)
496496
{
497497
pti_clone_pgtable((unsigned long) __entry_text_start,
498498
(unsigned long) __entry_text_end,
499-
PTI_CLONE_PMD);
499+
PTI_LEVEL_KERNEL_IMAGE);
500500
}
501501

502502
/*

0 commit comments

Comments
 (0)