mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-19 08:14:25 +00:00
Pull core x86 updates from Ingo Molnar:
"x86 CPU features support:
- Generate the <asm/cpufeaturemasks.h> header based on build config
(H. Peter Anvin, Xin Li)
- x86 CPUID parsing updates and fixes (Ahmed S. Darwish)
- Introduce the 'setcpuid=' boot parameter (Brendan Jackman)
- Enable modifying CPU bug flags with '{clear,set}puid=' (Brendan
Jackman)
- Utilize CPU-type for CPU matching (Pawan Gupta)
- Warn about unmet CPU feature dependencies (Sohil Mehta)
- Prepare for new Intel Family numbers (Sohil Mehta)
Percpu code:
- Standardize & reorganize the x86 percpu layout and related cleanups
(Brian Gerst)
- Convert the stackprotector canary to a regular percpu variable
(Brian Gerst)
- Add a percpu subsection for cache hot data (Brian Gerst)
- Unify __pcpu_op{1,2}_N() macros to __pcpu_op_N() (Uros Bizjak)
- Construct __percpu_seg_override from __percpu_seg (Uros Bizjak)
MM:
- Add support for broadcast TLB invalidation using AMD's INVLPGB
instruction (Rik van Riel)
- Rework ROX cache to avoid writable copy (Mike Rapoport)
- PAT: restore large ROX pages after fragmentation (Kirill A.
Shutemov, Mike Rapoport)
- Make memremap(MEMREMAP_WB) map memory as encrypted by default
(Kirill A. Shutemov)
- Robustify page table initialization (Kirill A. Shutemov)
- Fix flush_tlb_range() when used for zapping normal PMDs (Jann Horn)
- Clear _PAGE_DIRTY for kernel mappings when we clear _PAGE_RW
(Matthew Wilcox)
KASLR:
- x86/kaslr: Reduce KASLR entropy on most x86 systems, to support PCI
BAR space beyond the 10TiB region (CONFIG_PCI_P2PDMA=y) (Balbir
Singh)
CPU bugs:
- Implement FineIBT-BHI mitigation (Peter Zijlstra)
- speculation: Simplify and make CALL_NOSPEC consistent (Pawan Gupta)
- speculation: Add a conditional CS prefix to CALL_NOSPEC (Pawan
Gupta)
- RFDS: Exclude P-only parts from the RFDS affected list (Pawan
Gupta)
System calls:
- Break up entry/common.c (Brian Gerst)
- Move sysctls into arch/x86 (Joel Granados)
Intel LAM support updates: (Maciej Wieczor-Retman)
- selftests/lam: Move cpu_has_la57() to use cpuinfo flag
- selftests/lam: Skip test if LAM is disabled
- selftests/lam: Test get_user() LAM pointer handling
AMD SMN access updates:
- Add SMN offsets to exclusive region access (Mario Limonciello)
- Add support for debugfs access to SMN registers (Mario Limonciello)
- Have HSMP use SMN through AMD_NODE (Yazen Ghannam)
Power management updates: (Patryk Wlazlyn)
- Allow calling mwait_play_dead with an arbitrary hint
- ACPI/processor_idle: Add FFH state handling
- intel_idle: Provide the default enter_dead() handler
- Eliminate mwait_play_dead_cpuid_hint()
Build system:
- Raise the minimum GCC version to 8.1 (Brian Gerst)
- Raise the minimum LLVM version to 15.0.0 (Nathan Chancellor)
Kconfig: (Arnd Bergmann)
- Add cmpxchg8b support back to Geode CPUs
- Drop 32-bit "bigsmp" machine support
- Rework CONFIG_GENERIC_CPU compiler flags
- Drop configuration options for early 64-bit CPUs
- Remove CONFIG_HIGHMEM64G support
- Drop CONFIG_SWIOTLB for PAE
- Drop support for CONFIG_HIGHPTE
- Document CONFIG_X86_INTEL_MID as 64-bit-only
- Remove old STA2x11 support
- Only allow CONFIG_EISA for 32-bit
Headers:
- Replace __ASSEMBLY__ with __ASSEMBLER__ in UAPI and non-UAPI
headers (Thomas Huth)
Assembly code & machine code patching:
- x86/alternatives: Simplify alternative_call() interface (Josh
Poimboeuf)
- x86/alternatives: Simplify callthunk patching (Peter Zijlstra)
- KVM: VMX: Use named operands in inline asm (Josh Poimboeuf)
- x86/hyperv: Use named operands in inline asm (Josh Poimboeuf)
- x86/traps: Cleanup and robustify decode_bug() (Peter Zijlstra)
- x86/kexec: Merge x86_32 and x86_64 code using macros from
<asm/asm.h> (Uros Bizjak)
- Use named operands in inline asm (Uros Bizjak)
- Improve performance by using asm_inline() for atomic locking
instructions (Uros Bizjak)
Earlyprintk:
- Harden early_serial (Peter Zijlstra)
NMI handler:
- Add an emergency handler in nmi_desc & use it in
nmi_shootdown_cpus() (Waiman Long)
Miscellaneous fixes and cleanups:
- by Ahmed S. Darwish, Andy Shevchenko, Ard Biesheuvel, Artem
Bityutskiy, Borislav Petkov, Brendan Jackman, Brian Gerst, Dan
Carpenter, Dr. David Alan Gilbert, H. Peter Anvin, Ingo Molnar,
Josh Poimboeuf, Kevin Brodsky, Mike Rapoport, Lukas Bulwahn, Maciej
Wieczor-Retman, Max Grobecker, Patryk Wlazlyn, Pawan Gupta, Peter
Zijlstra, Philip Redkin, Qasim Ijaz, Rik van Riel, Thomas Gleixner,
Thorsten Blum, Tom Lendacky, Tony Luck, Uros Bizjak, Vitaly
Kuznetsov, Xin Li, liuye"
* tag 'x86-core-2025-03-22' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (211 commits)
zstd: Increase DYNAMIC_BMI2 GCC version cutoff from 4.8 to 11.0 to work around compiler segfault
x86/asm: Make asm export of __ref_stack_chk_guard unconditional
x86/mm: Only do broadcast flush from reclaim if pages were unmapped
perf/x86/intel, x86/cpu: Replace Pentium 4 model checks with VFM ones
perf/x86/intel, x86/cpu: Simplify Intel PMU initialization
x86/headers: Replace __ASSEMBLY__ with __ASSEMBLER__ in non-UAPI headers
x86/headers: Replace __ASSEMBLY__ with __ASSEMBLER__ in UAPI headers
x86/locking/atomic: Improve performance by using asm_inline() for atomic locking instructions
x86/asm: Use asm_inline() instead of asm() in clwb()
x86/asm: Use CLFLUSHOPT and CLWB mnemonics in <asm/special_insns.h>
x86/hweight: Use asm_inline() instead of asm()
x86/hweight: Use ASM_CALL_CONSTRAINT in inline asm()
x86/hweight: Use named operands in inline asm()
x86/stackprotector/64: Only export __ref_stack_chk_guard on CONFIG_SMP
x86/head/64: Avoid Clang < 17 stack protector in startup code
x86/kexec: Merge x86_32 and x86_64 code using macros from <asm/asm.h>
x86/runtime-const: Add the RUNTIME_CONST_PTR assembly macro
x86/cpu/intel: Limit the non-architectural constant_tsc model checks
x86/mm/pat: Replace Intel x86_model checks with VFM ones
x86/cpu/intel: Fix fast string initialization for extended Families
...
366 lines
12 KiB
C
366 lines
12 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef _ASM_X86_ALTERNATIVE_H
|
|
#define _ASM_X86_ALTERNATIVE_H
|
|
|
|
#include <linux/types.h>
|
|
#include <linux/stringify.h>
|
|
#include <linux/objtool.h>
|
|
#include <asm/asm.h>
|
|
|
|
#define ALT_FLAGS_SHIFT 16
|
|
|
|
#define ALT_FLAG_NOT (1 << 0)
|
|
#define ALT_NOT(feature) ((ALT_FLAG_NOT << ALT_FLAGS_SHIFT) | (feature))
|
|
#define ALT_FLAG_DIRECT_CALL (1 << 1)
|
|
#define ALT_DIRECT_CALL(feature) ((ALT_FLAG_DIRECT_CALL << ALT_FLAGS_SHIFT) | (feature))
|
|
#define ALT_CALL_ALWAYS ALT_DIRECT_CALL(X86_FEATURE_ALWAYS)
|
|
|
|
#ifndef __ASSEMBLER__
|
|
|
|
#include <linux/stddef.h>
|
|
|
|
/*
|
|
* Alternative inline assembly for SMP.
|
|
*
|
|
* The LOCK_PREFIX macro defined here replaces the LOCK and
|
|
* LOCK_PREFIX macros used everywhere in the source tree.
|
|
*
|
|
* SMP alternatives use the same data structures as the other
|
|
* alternatives and the X86_FEATURE_UP flag to indicate the case of a
|
|
* UP system running a SMP kernel. The existing apply_alternatives()
|
|
* works fine for patching a SMP kernel for UP.
|
|
*
|
|
* The SMP alternative tables can be kept after boot and contain both
|
|
* UP and SMP versions of the instructions to allow switching back to
|
|
* SMP at runtime, when hotplugging in a new CPU, which is especially
|
|
* useful in virtualized environments.
|
|
*
|
|
* The very common lock prefix is handled as special case in a
|
|
* separate table which is a pure address list without replacement ptr
|
|
* and size information. That keeps the table sizes small.
|
|
*/
|
|
|
|
#ifdef CONFIG_SMP
|
|
#define LOCK_PREFIX_HERE \
|
|
".pushsection .smp_locks,\"a\"\n" \
|
|
".balign 4\n" \
|
|
".long 671f - .\n" /* offset */ \
|
|
".popsection\n" \
|
|
"671:"
|
|
|
|
#define LOCK_PREFIX LOCK_PREFIX_HERE "\n\tlock "
|
|
|
|
#else /* ! CONFIG_SMP */
|
|
#define LOCK_PREFIX_HERE ""
|
|
#define LOCK_PREFIX ""
|
|
#endif
|
|
|
|
/*
|
|
* The patching flags are part of the upper bits of the @ft_flags parameter when
|
|
* specifying them. The split is currently like this:
|
|
*
|
|
* [31... flags ...16][15... CPUID feature bit ...0]
|
|
*
|
|
* but since this is all hidden in the macros argument being split, those fields can be
|
|
* extended in the future to fit in a u64 or however the need arises.
|
|
*/
|
|
struct alt_instr {
|
|
s32 instr_offset; /* original instruction */
|
|
s32 repl_offset; /* offset to replacement instruction */
|
|
|
|
union {
|
|
struct {
|
|
u32 cpuid: 16; /* CPUID bit set for replacement */
|
|
u32 flags: 16; /* patching control flags */
|
|
};
|
|
u32 ft_flags;
|
|
};
|
|
|
|
u8 instrlen; /* length of original instruction */
|
|
u8 replacementlen; /* length of new instruction */
|
|
} __packed;
|
|
|
|
extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
|
|
|
|
/*
|
|
* Debug flag that can be tested to see whether alternative
|
|
* instructions were patched in already:
|
|
*/
|
|
extern int alternatives_patched;
|
|
|
|
extern void alternative_instructions(void);
|
|
extern void apply_alternatives(struct alt_instr *start, struct alt_instr *end);
|
|
extern void apply_retpolines(s32 *start, s32 *end);
|
|
extern void apply_returns(s32 *start, s32 *end);
|
|
extern void apply_seal_endbr(s32 *start, s32 *end);
|
|
extern void apply_fineibt(s32 *start_retpoline, s32 *end_retpoine,
|
|
s32 *start_cfi, s32 *end_cfi);
|
|
|
|
struct module;
|
|
|
|
struct callthunk_sites {
|
|
s32 *call_start, *call_end;
|
|
};
|
|
|
|
#ifdef CONFIG_CALL_THUNKS
|
|
extern void callthunks_patch_builtin_calls(void);
|
|
extern void callthunks_patch_module_calls(struct callthunk_sites *sites,
|
|
struct module *mod);
|
|
extern void *callthunks_translate_call_dest(void *dest);
|
|
extern int x86_call_depth_emit_accounting(u8 **pprog, void *func, void *ip);
|
|
#else
|
|
static __always_inline void callthunks_patch_builtin_calls(void) {}
|
|
static __always_inline void
|
|
callthunks_patch_module_calls(struct callthunk_sites *sites,
|
|
struct module *mod) {}
|
|
static __always_inline void *callthunks_translate_call_dest(void *dest)
|
|
{
|
|
return dest;
|
|
}
|
|
static __always_inline int x86_call_depth_emit_accounting(u8 **pprog,
|
|
void *func, void *ip)
|
|
{
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#ifdef CONFIG_SMP
|
|
extern void alternatives_smp_module_add(struct module *mod, char *name,
|
|
void *locks, void *locks_end,
|
|
void *text, void *text_end);
|
|
extern void alternatives_smp_module_del(struct module *mod);
|
|
extern void alternatives_enable_smp(void);
|
|
extern int alternatives_text_reserved(void *start, void *end);
|
|
extern bool skip_smp_alternatives;
|
|
#else
|
|
static inline void alternatives_smp_module_add(struct module *mod, char *name,
|
|
void *locks, void *locks_end,
|
|
void *text, void *text_end) {}
|
|
static inline void alternatives_smp_module_del(struct module *mod) {}
|
|
static inline void alternatives_enable_smp(void) {}
|
|
static inline int alternatives_text_reserved(void *start, void *end)
|
|
{
|
|
return 0;
|
|
}
|
|
#endif /* CONFIG_SMP */
|
|
|
|
#define ALT_CALL_INSTR "call BUG_func"
|
|
|
|
#define alt_slen "772b-771b"
|
|
#define alt_total_slen "773b-771b"
|
|
#define alt_rlen "775f-774f"
|
|
|
|
#define OLDINSTR(oldinstr) \
|
|
"# ALT: oldinstr\n" \
|
|
"771:\n\t" oldinstr "\n772:\n" \
|
|
"# ALT: padding\n" \
|
|
".skip -(((" alt_rlen ")-(" alt_slen ")) > 0) * " \
|
|
"((" alt_rlen ")-(" alt_slen ")),0x90\n" \
|
|
"773:\n"
|
|
|
|
#define ALTINSTR_ENTRY(ft_flags) \
|
|
".pushsection .altinstructions,\"a\"\n" \
|
|
" .long 771b - .\n" /* label */ \
|
|
" .long 774f - .\n" /* new instruction */ \
|
|
" .4byte " __stringify(ft_flags) "\n" /* feature + flags */ \
|
|
" .byte " alt_total_slen "\n" /* source len */ \
|
|
" .byte " alt_rlen "\n" /* replacement len */ \
|
|
".popsection\n"
|
|
|
|
#define ALTINSTR_REPLACEMENT(newinstr) /* replacement */ \
|
|
".pushsection .altinstr_replacement, \"ax\"\n" \
|
|
"# ALT: replacement\n" \
|
|
"774:\n\t" newinstr "\n775:\n" \
|
|
".popsection\n"
|
|
|
|
/* alternative assembly primitive: */
|
|
#define ALTERNATIVE(oldinstr, newinstr, ft_flags) \
|
|
OLDINSTR(oldinstr) \
|
|
ALTINSTR_ENTRY(ft_flags) \
|
|
ALTINSTR_REPLACEMENT(newinstr)
|
|
|
|
#define ALTERNATIVE_2(oldinstr, newinstr1, ft_flags1, newinstr2, ft_flags2) \
|
|
ALTERNATIVE(ALTERNATIVE(oldinstr, newinstr1, ft_flags1), newinstr2, ft_flags2)
|
|
|
|
/* If @feature is set, patch in @newinstr_yes, otherwise @newinstr_no. */
|
|
#define ALTERNATIVE_TERNARY(oldinstr, ft_flags, newinstr_yes, newinstr_no) \
|
|
ALTERNATIVE_2(oldinstr, newinstr_no, X86_FEATURE_ALWAYS, newinstr_yes, ft_flags)
|
|
|
|
#define ALTERNATIVE_3(oldinstr, newinstr1, ft_flags1, newinstr2, ft_flags2, \
|
|
newinstr3, ft_flags3) \
|
|
ALTERNATIVE(ALTERNATIVE_2(oldinstr, newinstr1, ft_flags1, newinstr2, ft_flags2), \
|
|
newinstr3, ft_flags3)
|
|
|
|
/*
|
|
* Alternative instructions for different CPU types or capabilities.
|
|
*
|
|
* This allows to use optimized instructions even on generic binary
|
|
* kernels.
|
|
*
|
|
* length of oldinstr must be longer or equal the length of newinstr
|
|
* It can be padded with nops as needed.
|
|
*
|
|
* For non barrier like inlines please define new variants
|
|
* without volatile and memory clobber.
|
|
*/
|
|
#define alternative(oldinstr, newinstr, ft_flags) \
|
|
asm_inline volatile(ALTERNATIVE(oldinstr, newinstr, ft_flags) : : : "memory")
|
|
|
|
#define alternative_2(oldinstr, newinstr1, ft_flags1, newinstr2, ft_flags2) \
|
|
asm_inline volatile(ALTERNATIVE_2(oldinstr, newinstr1, ft_flags1, newinstr2, ft_flags2) ::: "memory")
|
|
|
|
/*
|
|
* Alternative inline assembly with input.
|
|
*
|
|
* Peculiarities:
|
|
* No memory clobber here.
|
|
* Argument numbers start with 1.
|
|
* Leaving an unused argument 0 to keep API compatibility.
|
|
*/
|
|
#define alternative_input(oldinstr, newinstr, ft_flags, input...) \
|
|
asm_inline volatile(ALTERNATIVE(oldinstr, newinstr, ft_flags) \
|
|
: : "i" (0), ## input)
|
|
|
|
/* Like alternative_input, but with a single output argument */
|
|
#define alternative_io(oldinstr, newinstr, ft_flags, output, input...) \
|
|
asm_inline volatile(ALTERNATIVE(oldinstr, newinstr, ft_flags) \
|
|
: output : "i" (0), ## input)
|
|
|
|
/*
|
|
* Like alternative_io, but for replacing a direct call with another one.
|
|
*
|
|
* Use the %c operand modifier which is the generic way to print a bare
|
|
* constant expression with all syntax-specific punctuation omitted. %P
|
|
* is the x86-specific variant which can handle constants too, for
|
|
* historical reasons, but it should be used primarily for PIC
|
|
* references: i.e., if used for a function, it would add the PLT
|
|
* suffix.
|
|
*/
|
|
#define alternative_call(oldfunc, newfunc, ft_flags, output, input, clobbers...) \
|
|
asm_inline volatile(ALTERNATIVE("call %c[old]", "call %c[new]", ft_flags) \
|
|
: ALT_OUTPUT_SP(output) \
|
|
: [old] "i" (oldfunc), [new] "i" (newfunc) \
|
|
COMMA(input) \
|
|
: clobbers)
|
|
|
|
/*
|
|
* Like alternative_call, but there are two features and respective functions.
|
|
* If CPU has feature2, function2 is used.
|
|
* Otherwise, if CPU has feature1, function1 is used.
|
|
* Otherwise, old function is used.
|
|
*/
|
|
#define alternative_call_2(oldfunc, newfunc1, ft_flags1, newfunc2, ft_flags2, \
|
|
output, input, clobbers...) \
|
|
asm_inline volatile(ALTERNATIVE_2("call %c[old]", "call %c[new1]", ft_flags1, \
|
|
"call %c[new2]", ft_flags2) \
|
|
: ALT_OUTPUT_SP(output) \
|
|
: [old] "i" (oldfunc), [new1] "i" (newfunc1), \
|
|
[new2] "i" (newfunc2) \
|
|
COMMA(input) \
|
|
: clobbers)
|
|
|
|
#define ALT_OUTPUT_SP(...) ASM_CALL_CONSTRAINT, ## __VA_ARGS__
|
|
|
|
/* Macro for creating assembler functions avoiding any C magic. */
|
|
#define DEFINE_ASM_FUNC(func, instr, sec) \
|
|
asm (".pushsection " #sec ", \"ax\"\n" \
|
|
".global " #func "\n\t" \
|
|
".type " #func ", @function\n\t" \
|
|
ASM_FUNC_ALIGN "\n" \
|
|
#func ":\n\t" \
|
|
ASM_ENDBR \
|
|
instr "\n\t" \
|
|
ASM_RET \
|
|
".size " #func ", . - " #func "\n\t" \
|
|
".popsection")
|
|
|
|
void BUG_func(void);
|
|
void nop_func(void);
|
|
|
|
#else /* __ASSEMBLER__ */
|
|
|
|
#ifdef CONFIG_SMP
|
|
.macro LOCK_PREFIX
|
|
672: lock
|
|
.pushsection .smp_locks,"a"
|
|
.balign 4
|
|
.long 672b - .
|
|
.popsection
|
|
.endm
|
|
#else
|
|
.macro LOCK_PREFIX
|
|
.endm
|
|
#endif
|
|
|
|
/*
|
|
* Issue one struct alt_instr descriptor entry (need to put it into
|
|
* the section .altinstructions, see below). This entry contains
|
|
* enough information for the alternatives patching code to patch an
|
|
* instruction. See apply_alternatives().
|
|
*/
|
|
.macro altinstr_entry orig alt ft_flags orig_len alt_len
|
|
.long \orig - .
|
|
.long \alt - .
|
|
.4byte \ft_flags
|
|
.byte \orig_len
|
|
.byte \alt_len
|
|
.endm
|
|
|
|
.macro ALT_CALL_INSTR
|
|
call BUG_func
|
|
.endm
|
|
|
|
/*
|
|
* Define an alternative between two instructions. If @feature is
|
|
* present, early code in apply_alternatives() replaces @oldinstr with
|
|
* @newinstr. ".skip" directive takes care of proper instruction padding
|
|
* in case @newinstr is longer than @oldinstr.
|
|
*/
|
|
#define __ALTERNATIVE(oldinst, newinst, flag) \
|
|
740: \
|
|
oldinst ; \
|
|
741: \
|
|
.skip -(((744f-743f)-(741b-740b)) > 0) * ((744f-743f)-(741b-740b)),0x90 ;\
|
|
742: \
|
|
.pushsection .altinstructions,"a" ; \
|
|
altinstr_entry 740b,743f,flag,742b-740b,744f-743f ; \
|
|
.popsection ; \
|
|
.pushsection .altinstr_replacement,"ax" ; \
|
|
743: \
|
|
newinst ; \
|
|
744: \
|
|
.popsection ;
|
|
|
|
.macro ALTERNATIVE oldinstr, newinstr, ft_flags
|
|
__ALTERNATIVE(\oldinstr, \newinstr, \ft_flags)
|
|
.endm
|
|
|
|
#define old_len 141b-140b
|
|
#define new_len1 144f-143f
|
|
#define new_len2 145f-144f
|
|
#define new_len3 146f-145f
|
|
|
|
/*
|
|
* Same as ALTERNATIVE macro above but for two alternatives. If CPU
|
|
* has @feature1, it replaces @oldinstr with @newinstr1. If CPU has
|
|
* @feature2, it replaces @oldinstr with @feature2.
|
|
*/
|
|
.macro ALTERNATIVE_2 oldinstr, newinstr1, ft_flags1, newinstr2, ft_flags2
|
|
__ALTERNATIVE(__ALTERNATIVE(\oldinstr, \newinstr1, \ft_flags1),
|
|
\newinstr2, \ft_flags2)
|
|
.endm
|
|
|
|
.macro ALTERNATIVE_3 oldinstr, newinstr1, ft_flags1, newinstr2, ft_flags2, newinstr3, ft_flags3
|
|
__ALTERNATIVE(ALTERNATIVE_2(\oldinstr, \newinstr1, \ft_flags1, \newinstr2, \ft_flags2),
|
|
\newinstr3, \ft_flags3)
|
|
.endm
|
|
|
|
/* If @feature is set, patch in @newinstr_yes, otherwise @newinstr_no. */
|
|
#define ALTERNATIVE_TERNARY(oldinstr, ft_flags, newinstr_yes, newinstr_no) \
|
|
ALTERNATIVE_2 oldinstr, newinstr_no, X86_FEATURE_ALWAYS, \
|
|
newinstr_yes, ft_flags
|
|
|
|
#endif /* __ASSEMBLER__ */
|
|
|
|
#endif /* _ASM_X86_ALTERNATIVE_H */
|