Merge branch 'x86-asm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 asm updates from Ingo Molnar: "Misc updates: - Remove last remaining calls to exception_enter/exception_exit() and simplify the entry code some more. - Remove force_iret() - Add support for "Fast Short Rep Mov", which is available starting with Ice Lake Intel CPUs - and make the x86 assembly version of memmove() use REP MOV for all sizes when FSRM is available. - Micro-optimize/simplify the 32-bit boot code a bit. - Use a more future-proof SYSRET instruction mnemonic" * 'x86-asm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/boot: Simplify calculation of output address x86/entry/64: Add instruction suffix to SYSRET x86: Remove force_iret() x86/cpufeatures: Add support for fast short REP; MOVSB x86/context-tracking: Remove exception_enter/exit() from KVM_PV_REASON_PAGE_NOT_PRESENT async page fault x86/context-tracking: Remove exception_enter/exit() from do_page_fault()
This commit is contained in:
commit
bcc8aff6af
@ -189,11 +189,9 @@ SYM_FUNC_START_LOCAL_NOALIGN(.Lrelocated)
|
||||
/* push arguments for extract_kernel: */
|
||||
pushl $z_output_len /* decompressed length, end of relocs */
|
||||
|
||||
movl BP_init_size(%esi), %eax
|
||||
subl $_end, %eax
|
||||
movl %ebx, %ebp
|
||||
subl %eax, %ebp
|
||||
pushl %ebp /* output address */
|
||||
leal _end(%ebx), %eax
|
||||
subl BP_init_size(%esi), %eax
|
||||
pushl %eax /* output address */
|
||||
|
||||
pushl $z_input_len /* input_len */
|
||||
leal input_data(%ebx), %eax
|
||||
|
@ -1728,7 +1728,7 @@ SYM_CODE_END(nmi)
|
||||
SYM_CODE_START(ignore_sysret)
|
||||
UNWIND_HINT_EMPTY
|
||||
mov $-ENOSYS, %eax
|
||||
sysret
|
||||
sysretl
|
||||
SYM_CODE_END(ignore_sysret)
|
||||
#endif
|
||||
|
||||
|
@ -114,8 +114,6 @@ static int ia32_restore_sigcontext(struct pt_regs *regs,
|
||||
|
||||
err |= fpu__restore_sig(buf, 1);
|
||||
|
||||
force_iret();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -357,6 +357,7 @@
|
||||
/* Intel-defined CPU features, CPUID level 0x00000007:0 (EDX), word 18 */
|
||||
#define X86_FEATURE_AVX512_4VNNIW (18*32+ 2) /* AVX-512 Neural Network Instructions */
|
||||
#define X86_FEATURE_AVX512_4FMAPS (18*32+ 3) /* AVX-512 Multiply Accumulation Single precision */
|
||||
#define X86_FEATURE_FSRM (18*32+ 4) /* Fast Short Rep Mov */
|
||||
#define X86_FEATURE_AVX512_VP2INTERSECT (18*32+ 8) /* AVX-512 Intersect for D/Q */
|
||||
#define X86_FEATURE_MD_CLEAR (18*32+10) /* VERW clears CPU buffers */
|
||||
#define X86_FEATURE_TSX_FORCE_ABORT (18*32+13) /* "" TSX_FORCE_ABORT */
|
||||
|
@ -339,22 +339,6 @@ static inline unsigned long regs_get_kernel_argument(struct pt_regs *regs,
|
||||
|
||||
#define ARCH_HAS_USER_SINGLE_STEP_REPORT
|
||||
|
||||
/*
|
||||
* When hitting ptrace_stop(), we cannot return using SYSRET because
|
||||
* that does not restore the full CPU state, only a minimal set. The
|
||||
* ptracer can change arbitrary register values, which is usually okay
|
||||
* because the usual ptrace stops run off the signal delivery path which
|
||||
* forces IRET; however, ptrace_event() stops happen in arbitrary places
|
||||
* in the kernel and don't force IRET path.
|
||||
*
|
||||
* So force IRET path after a ptrace stop.
|
||||
*/
|
||||
#define arch_ptrace_stop_needed(code, info) \
|
||||
({ \
|
||||
force_iret(); \
|
||||
false; \
|
||||
})
|
||||
|
||||
struct user_desc;
|
||||
extern int do_get_thread_area(struct task_struct *p, int idx,
|
||||
struct user_desc __user *info);
|
||||
|
@ -239,15 +239,6 @@ static inline int arch_within_stack_frames(const void * const stack,
|
||||
current_thread_info()->status & TS_COMPAT)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Force syscall return via IRET by making it look as if there was
|
||||
* some work pending. IRET is our most capable (but slowest) syscall
|
||||
* return path, which is able to restore modified SS, CS and certain
|
||||
* EFLAGS values that other (fast) syscall return instructions
|
||||
* are not able to restore properly.
|
||||
*/
|
||||
#define force_iret() set_thread_flag(TIF_NOTIFY_RESUME)
|
||||
|
||||
extern void arch_task_cache_init(void);
|
||||
extern int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src);
|
||||
extern void arch_release_task_struct(struct task_struct *tsk);
|
||||
|
@ -245,17 +245,13 @@ NOKPROBE_SYMBOL(kvm_read_and_reset_pf_reason);
|
||||
dotraplinkage void
|
||||
do_async_page_fault(struct pt_regs *regs, unsigned long error_code, unsigned long address)
|
||||
{
|
||||
enum ctx_state prev_state;
|
||||
|
||||
switch (kvm_read_and_reset_pf_reason()) {
|
||||
default:
|
||||
do_page_fault(regs, error_code, address);
|
||||
break;
|
||||
case KVM_PV_REASON_PAGE_NOT_PRESENT:
|
||||
/* page is swapped out by the host. */
|
||||
prev_state = exception_enter();
|
||||
kvm_async_pf_task_wait((u32)address, !user_mode(regs));
|
||||
exception_exit(prev_state);
|
||||
break;
|
||||
case KVM_PV_REASON_PAGE_READY:
|
||||
rcu_irq_enter();
|
||||
|
@ -124,7 +124,6 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
|
||||
regs->ip = new_ip;
|
||||
regs->sp = new_sp;
|
||||
regs->flags = X86_EFLAGS_IF;
|
||||
force_iret();
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(start_thread);
|
||||
|
||||
|
@ -394,7 +394,6 @@ start_thread_common(struct pt_regs *regs, unsigned long new_ip,
|
||||
regs->cs = _cs;
|
||||
regs->ss = _ss;
|
||||
regs->flags = X86_EFLAGS_IF;
|
||||
force_iret();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -151,8 +151,6 @@ static int restore_sigcontext(struct pt_regs *regs,
|
||||
|
||||
err |= fpu__restore_sig(buf, IS_ENABLED(CONFIG_X86_32));
|
||||
|
||||
force_iret();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -381,7 +381,6 @@ static long do_sys_vm86(struct vm86plus_struct __user *user_vm86, bool plus)
|
||||
mark_screen_rdonly(tsk->mm);
|
||||
|
||||
memcpy((struct kernel_vm86_regs *)regs, &vm86regs, sizeof(vm86regs));
|
||||
force_iret();
|
||||
return regs->ax;
|
||||
}
|
||||
|
||||
|
@ -29,10 +29,7 @@
|
||||
SYM_FUNC_START_ALIAS(memmove)
|
||||
SYM_FUNC_START(__memmove)
|
||||
|
||||
/* Handle more 32 bytes in loop */
|
||||
mov %rdi, %rax
|
||||
cmp $0x20, %rdx
|
||||
jb 1f
|
||||
|
||||
/* Decide forward/backward copy mode */
|
||||
cmp %rdi, %rsi
|
||||
@ -42,7 +39,9 @@ SYM_FUNC_START(__memmove)
|
||||
cmp %rdi, %r8
|
||||
jg 2f
|
||||
|
||||
/* FSRM implies ERMS => no length checks, do the copy directly */
|
||||
.Lmemmove_begin_forward:
|
||||
ALTERNATIVE "cmp $0x20, %rdx; jb 1f", "", X86_FEATURE_FSRM
|
||||
ALTERNATIVE "", "movq %rdx, %rcx; rep movsb; retq", X86_FEATURE_ERMS
|
||||
|
||||
/*
|
||||
@ -114,6 +113,8 @@ SYM_FUNC_START(__memmove)
|
||||
*/
|
||||
.p2align 4
|
||||
2:
|
||||
cmp $0x20, %rdx
|
||||
jb 1f
|
||||
cmp $680, %rdx
|
||||
jb 6f
|
||||
cmp %dil, %sil
|
||||
|
@ -1487,27 +1487,6 @@ good_area:
|
||||
}
|
||||
NOKPROBE_SYMBOL(do_user_addr_fault);
|
||||
|
||||
/*
|
||||
* Explicitly marked noinline such that the function tracer sees this as the
|
||||
* page_fault entry point.
|
||||
*/
|
||||
static noinline void
|
||||
__do_page_fault(struct pt_regs *regs, unsigned long hw_error_code,
|
||||
unsigned long address)
|
||||
{
|
||||
prefetchw(¤t->mm->mmap_sem);
|
||||
|
||||
if (unlikely(kmmio_fault(regs, address)))
|
||||
return;
|
||||
|
||||
/* Was the fault on kernel-controlled part of the address space? */
|
||||
if (unlikely(fault_in_kernel_space(address)))
|
||||
do_kern_addr_fault(regs, hw_error_code, address);
|
||||
else
|
||||
do_user_addr_fault(regs, hw_error_code, address);
|
||||
}
|
||||
NOKPROBE_SYMBOL(__do_page_fault);
|
||||
|
||||
static __always_inline void
|
||||
trace_page_fault_entries(struct pt_regs *regs, unsigned long error_code,
|
||||
unsigned long address)
|
||||
@ -1522,13 +1501,19 @@ trace_page_fault_entries(struct pt_regs *regs, unsigned long error_code,
|
||||
}
|
||||
|
||||
dotraplinkage void
|
||||
do_page_fault(struct pt_regs *regs, unsigned long error_code, unsigned long address)
|
||||
do_page_fault(struct pt_regs *regs, unsigned long hw_error_code,
|
||||
unsigned long address)
|
||||
{
|
||||
enum ctx_state prev_state;
|
||||
prefetchw(¤t->mm->mmap_sem);
|
||||
trace_page_fault_entries(regs, hw_error_code, address);
|
||||
|
||||
prev_state = exception_enter();
|
||||
trace_page_fault_entries(regs, error_code, address);
|
||||
__do_page_fault(regs, error_code, address);
|
||||
exception_exit(prev_state);
|
||||
if (unlikely(kmmio_fault(regs, address)))
|
||||
return;
|
||||
|
||||
/* Was the fault on kernel-controlled part of the address space? */
|
||||
if (unlikely(fault_in_kernel_space(address)))
|
||||
do_kern_addr_fault(regs, hw_error_code, address);
|
||||
else
|
||||
do_user_addr_fault(regs, hw_error_code, address);
|
||||
}
|
||||
NOKPROBE_SYMBOL(do_page_fault);
|
||||
|
Loading…
Reference in New Issue
Block a user