/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _ASM_X86_SYNC_CORE_H
#define _ASM_X86_SYNC_CORE_H
#include <linux/preempt.h>
#include <asm /processor.h>
#include <asm /cpufeature.h>
#include <asm /special_insns.h>
#ifdef CONFIG_X86_32
static __always_inline void iret_to_self(void )
{
asm volatile (
"pushfl\n\t"
"pushl %%cs\n\t"
"pushl $1f\n\t"
"iret\n\t"
"1:"
: ASM_CALL_CONSTRAINT : : "memory" );
}
#else
static __always_inline void iret_to_self(void )
{
unsigned int tmp;
asm volatile (
"mov %%ss, %0\n\t"
"pushq %q0\n\t"
"pushq %%rsp\n\t"
"addq $8, (%%rsp)\n\t"
"pushfq\n\t"
"mov %%cs, %0\n\t"
"pushq %q0\n\t"
"pushq $1f\n\t"
"iretq\n\t"
"1:"
: "=&r" (tmp), ASM_CALL_CONSTRAINT : : "cc" , "memory" );
}
#endif /* CONFIG_X86_32 */
/*
* This function forces the icache and prefetched instruction stream to
* catch up with reality in two very specific cases :
*
* a ) Text was modified using one virtual address and is about to be executed
* from the same physical page at a different virtual address .
*
* b ) Text was modified on a different CPU , may subsequently be
* executed on this CPU , and you want to make sure the new version
* gets executed . This generally means you ' re calling this in an IPI .
*
* If you ' re calling this for a different reason , you ' re probably doing
* it wrong .
*
* Like all of Linux ' s memory ordering operations , this is a
* compiler barrier as well .
*/
static __always_inline void sync_core(void )
{
/*
* The SERIALIZE instruction is the most straightforward way to
* do this , but it is not universally available .
*/
if (static_cpu_has(X86_FEATURE_SERIALIZE)) {
serialize();
return ;
}
/*
* For all other processors , there are quite a few ways to do this .
* IRET - to - self is nice because it works on every CPU , at any CPL
* ( so it ' s compatible with paravirtualization ) , and it never exits
* to a hypervisor . The only downsides are that it ' s a bit slow
* ( it seems to be a bit more than 2 x slower than the fastest
* options ) and that it unmasks NMIs . The " push % cs " is needed ,
* because in paravirtual environments _ _ KERNEL_CS may not be a
* valid CS value when we do IRET directly .
*
* In case NMI unmasking or performance ever becomes a problem ,
* the next best option appears to be MOV - to - CR2 and an
* unconditional jump . That sequence also works on all CPUs ,
* but it will fault at CPL3 ( i . e . Xen PV ) .
*
* CPUID is the conventional way , but it ' s nasty : it doesn ' t
* exist on some 486 - like CPUs , and it usually exits to a
* hypervisor .
*/
iret_to_self();
}
/*
* Ensure that a core serializing instruction is issued before returning
* to user - mode . x86 implements return to user - space through sysexit ,
* sysrel , and sysretq , which are not core serializing .
*/
static inline void sync_core_before_usermode(void )
{
/* With PTI, we unconditionally serialize before running user code. */
if (static_cpu_has(X86_FEATURE_PTI))
return ;
/*
* Even if we ' re in an interrupt , we might reschedule before returning ,
* in which case we could switch to a different thread in the same mm
* and return using SYSRET or SYSEXIT . Instead of trying to keep
* track of our need to sync the core , just sync right away .
*/
sync_core();
}
#endif /* _ASM_X86_SYNC_CORE_H */
Messung V0.5 in Prozent C=93 H=62 G=78
¤ Dauer der Verarbeitung: 0.9 Sekunden
(vorverarbeitet am 2026-09-28)
¤
*© Formatika GbR, Deutschland