mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00

For historic reasons there are some TSC-related functions in the <asm/msr.h> header, even though there's an <asm/tsc.h> header. To facilitate the relocation of rdtsc{,_ordered}() from <asm/msr.h> to <asm/tsc.h> and to eventually eliminate the inclusion of <asm/msr.h> in <asm/tsc.h>, add an explicit <asm/msr.h> dependency to the source files that reference definitions from <asm/msr.h>. [ mingo: Clarified the changelog. ] Signed-off-by: Xin Li (Intel) <xin@zytor.com> Signed-off-by: Ingo Molnar <mingo@kernel.org> Acked-by: Dave Hansen <dave.hansen@linux.intel.com> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Acked-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com> Cc: Andy Lutomirski <luto@kernel.org> Cc: Brian Gerst <brgerst@gmail.com> Cc: Juergen Gross <jgross@suse.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Kees Cook <keescook@chromium.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Uros Bizjak <ubizjak@gmail.com> Link: https://lore.kernel.org/r/20250501054241.1245648-1-xin@zytor.com
119 lines
3.2 KiB
C
119 lines
3.2 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
/*
|
|
* Macros for Flexible Return and Event Delivery (FRED)
|
|
*/
|
|
|
|
#ifndef ASM_X86_FRED_H
|
|
#define ASM_X86_FRED_H
|
|
|
|
#include <linux/const.h>
|
|
|
|
#include <asm/asm.h>
|
|
#include <asm/msr.h>
|
|
#include <asm/trapnr.h>
|
|
|
|
/*
|
|
* FRED event return instruction opcodes for ERET{S,U}; supported in
|
|
* binutils >= 2.41.
|
|
*/
|
|
#define ERETS _ASM_BYTES(0xf2,0x0f,0x01,0xca)
|
|
#define ERETU _ASM_BYTES(0xf3,0x0f,0x01,0xca)
|
|
|
|
/*
|
|
* RSP is aligned to a 64-byte boundary before used to push a new stack frame
|
|
*/
|
|
#define FRED_STACK_FRAME_RSP_MASK _AT(unsigned long, (~0x3f))
|
|
|
|
/*
|
|
* Used for the return address for call emulation during code patching,
|
|
* and measured in 64-byte cache lines.
|
|
*/
|
|
#define FRED_CONFIG_REDZONE_AMOUNT 1
|
|
#define FRED_CONFIG_REDZONE (_AT(unsigned long, FRED_CONFIG_REDZONE_AMOUNT) << 6)
|
|
#define FRED_CONFIG_INT_STKLVL(l) (_AT(unsigned long, l) << 9)
|
|
#define FRED_CONFIG_ENTRYPOINT(p) _AT(unsigned long, (p))
|
|
|
|
#ifndef __ASSEMBLER__
|
|
|
|
#ifdef CONFIG_X86_FRED
|
|
#include <linux/kernel.h>
|
|
#include <linux/sched/task_stack.h>
|
|
|
|
#include <asm/ptrace.h>
|
|
|
|
struct fred_info {
|
|
/* Event data: CR2, DR6, ... */
|
|
unsigned long edata;
|
|
unsigned long resv;
|
|
};
|
|
|
|
/* Full format of the FRED stack frame */
|
|
struct fred_frame {
|
|
struct pt_regs regs;
|
|
struct fred_info info;
|
|
};
|
|
|
|
static __always_inline struct fred_info *fred_info(struct pt_regs *regs)
|
|
{
|
|
return &container_of(regs, struct fred_frame, regs)->info;
|
|
}
|
|
|
|
static __always_inline unsigned long fred_event_data(struct pt_regs *regs)
|
|
{
|
|
return fred_info(regs)->edata;
|
|
}
|
|
|
|
void asm_fred_entrypoint_user(void);
|
|
void asm_fred_entrypoint_kernel(void);
|
|
void asm_fred_entry_from_kvm(struct fred_ss);
|
|
|
|
__visible void fred_entry_from_user(struct pt_regs *regs);
|
|
__visible void fred_entry_from_kernel(struct pt_regs *regs);
|
|
__visible void __fred_entry_from_kvm(struct pt_regs *regs);
|
|
|
|
/* Can be called from noinstr code, thus __always_inline */
|
|
static __always_inline void fred_entry_from_kvm(unsigned int type, unsigned int vector)
|
|
{
|
|
struct fred_ss ss = {
|
|
.ss =__KERNEL_DS,
|
|
.type = type,
|
|
.vector = vector,
|
|
.nmi = type == EVENT_TYPE_NMI,
|
|
.lm = 1,
|
|
};
|
|
|
|
asm_fred_entry_from_kvm(ss);
|
|
}
|
|
|
|
void cpu_init_fred_exceptions(void);
|
|
void cpu_init_fred_rsps(void);
|
|
void fred_complete_exception_setup(void);
|
|
|
|
DECLARE_PER_CPU(unsigned long, fred_rsp0);
|
|
|
|
static __always_inline void fred_sync_rsp0(unsigned long rsp0)
|
|
{
|
|
__this_cpu_write(fred_rsp0, rsp0);
|
|
}
|
|
|
|
static __always_inline void fred_update_rsp0(void)
|
|
{
|
|
unsigned long rsp0 = (unsigned long) task_stack_page(current) + THREAD_SIZE;
|
|
|
|
if (cpu_feature_enabled(X86_FEATURE_FRED) && (__this_cpu_read(fred_rsp0) != rsp0)) {
|
|
wrmsrns(MSR_IA32_FRED_RSP0, rsp0);
|
|
__this_cpu_write(fred_rsp0, rsp0);
|
|
}
|
|
}
|
|
#else /* CONFIG_X86_FRED */
|
|
static __always_inline unsigned long fred_event_data(struct pt_regs *regs) { return 0; }
|
|
static inline void cpu_init_fred_exceptions(void) { }
|
|
static inline void cpu_init_fred_rsps(void) { }
|
|
static inline void fred_complete_exception_setup(void) { }
|
|
static inline void fred_entry_from_kvm(unsigned int type, unsigned int vector) { }
|
|
static inline void fred_sync_rsp0(unsigned long rsp0) { }
|
|
static inline void fred_update_rsp0(void) { }
|
|
#endif /* CONFIG_X86_FRED */
|
|
#endif /* !__ASSEMBLER__ */
|
|
|
|
#endif /* ASM_X86_FRED_H */
|