#include <sys/errno.h>
#include <machine/asm.h>
#include <machine/frameasm.h>
__KERNEL_RCSID(0, "$NetBSD: cpufunc.S,v 1.54 2025/09/06 02:53:22 riastradh Exp $");
#include "opt_dtrace.h"
#include "opt_xen.h"
#include <machine/specialreg.h>
#include <machine/segments.h>
#include "assym.h"
ENTRY(x86_lfence)
lock
addl $0, -4(%esp)
ret
END(x86_lfence)
ENTRY(x86_sfence)
lock
addl $0, -4(%esp)
ret
END(x86_sfence)
ENTRY(x86_mfence)
lock
addl $0, -4(%esp)
ret
END(x86_mfence)
ENTRY(paravirt_membar_sync)
lock
addl $0,-4(%esp)
ret
END(paravirt_membar_sync)
#ifdef XEN
STRONG_ALIAS(xen_mb,paravirt_membar_sync)
#endif
#ifdef KDTRACE_HOOKS
ENTRY(dtrace_smap_enable)
# ifndef XENPV
SMAP_ENABLE
# endif
ret
END(dtrace_smap_enable)
ENTRY(dtrace_smap_disable)
# ifndef XENPV
SMAP_DISABLE
# endif
ret
END(dtrace_smap_disable)
#endif
#ifndef XENPV
ENTRY(lidt)
movl 4(%esp), %eax
lidt (%eax)
ret
END(lidt)
ENTRY(x86_hotpatch)
pushfl
cli
movl %cr0,%ecx
pushl %ecx
andl $~CR0_WP,%ecx
movl %ecx,%cr0
pushl 4*4(%esp)
pushl 4*4(%esp)
call _C_LABEL(x86_hotpatch_apply)
addl $2*4,%esp
wbinvd
popl %ecx
movl %ecx,%cr0
pushl %eax
call x86_flush
popl %eax
pushl %eax
call _C_LABEL(x86_hotpatch_cleanup)
addl $4,%esp
popfl
ret
END(x86_hotpatch)
#endif
ENTRY(x86_read_flags)
pushfl
popl %eax
ret
END(x86_read_flags)
ENTRY(x86_write_flags)
movl 4(%esp), %eax
pushl %eax
popfl
ret
END(x86_write_flags)
#ifndef XENPV
STRONG_ALIAS(x86_write_psl,x86_write_flags)
STRONG_ALIAS(x86_read_psl,x86_read_flags)
#endif
ENTRY(rdmsr_safe)
movl CPUVAR(CURLWP), %ecx
movl L_PCB(%ecx), %ecx
movl $_C_LABEL(msr_onfault), PCB_ONFAULT(%ecx)
movl 4(%esp), %ecx
rdmsr
movl 8(%esp), %ecx
movl %eax, (%ecx)
movl %edx, 4(%ecx)
xorl %eax, %eax
movl CPUVAR(CURLWP), %ecx
movl L_PCB(%ecx), %ecx
movl %eax, PCB_ONFAULT(%ecx)
ret
END(rdmsr_safe)
ENTRY(msr_onfault)
movl CPUVAR(CURLWP), %ecx
movl L_PCB(%ecx), %ecx
movl $0, PCB_ONFAULT(%ecx)
movl $EFAULT, %eax
ret
END(msr_onfault)
#define ADD_counter32 addl CPUVAR(CC_SKEW), %eax
#define ADD_counter ADD_counter32 ;\
adcl CPUVAR(CC_SKEW+4), %edx
#define SERIALIZE_lfence lfence
#define SERIALIZE_mfence mfence
#define CPU_COUNTER_FENCE(counter, fence) \
ENTRY(cpu_ ## counter ## _ ## fence) ;\
pushl %ebx ;\
movl CPUVAR(CURLWP), %ecx ;\
leal L_RU+RU_NIVCSW(%ecx), %ecx ;\
1: ;\
movl (%ecx), %ebx ;\
SERIALIZE_ ## fence ;\
rdtsc ;\
ADD_ ## counter ;\
cmpl %ebx, (%ecx) ;\
jne 2f ;\
popl %ebx ;\
ret ;\
2: ;\
jmp 1b ;\
END(cpu_ ## counter ## _ ## fence)
CPU_COUNTER_FENCE(counter, lfence)
CPU_COUNTER_FENCE(counter, mfence)
CPU_COUNTER_FENCE(counter32, lfence)
CPU_COUNTER_FENCE(counter32, mfence)
#define CPU_COUNTER_CPUID(counter) \
ENTRY(cpu_ ## counter ## _cpuid) ;\
pushl %ebx ;\
pushl %esi ;\
movl CPUVAR(CURLWP), %ecx ;\
leal L_RU+RU_NIVCSW(%ecx), %ecx ;\
1: ;\
movl (%ecx), %esi ;\
pushl %ecx ;\
xor %eax, %eax ;\
cpuid ;\
rdtsc ;\
ADD_ ## counter ;\
popl %ecx ;\
cmpl %esi, (%ecx) ;\
jne 2f ;\
popl %esi ;\
popl %ebx ;\
ret ;\
2: ;\
jmp 1b ;\
END(cpu_ ## counter ##_cpuid)
CPU_COUNTER_CPUID(counter)
CPU_COUNTER_CPUID(counter32)
ENTRY(breakpoint)
pushl %ebp
movl %esp, %ebp
int $0x03
popl %ebp
ret
END(breakpoint)
ENTRY(x86_curcpu)
movl %fs:(CPU_INFO_SELF), %eax
ret
END(x86_curcpu)
ENTRY(x86_curlwp)
movl %fs:(CPU_INFO_CURLWP), %eax
ret
END(x86_curlwp)
ENTRY(__byte_swap_u32_variable)
movl 4(%esp), %eax
bswapl %eax
ret
END(__byte_swap_u32_variable)
ENTRY(__byte_swap_u16_variable)
movl 4(%esp), %eax
xchgb %al, %ah
ret
END(__byte_swap_u16_variable)
ENTRY(x86_flush)
popl %eax
pushl $GSEL(GCODE_SEL, SEL_KPL)
pushl %eax
lret
END(x86_flush)
ENTRY(x86_hlt)
pushl %ebp
movl %esp, %ebp
hlt
leave
ret
END(x86_hlt)
ENTRY(x86_stihlt)
pushl %ebp
movl %esp, %ebp
sti
hlt
leave
ret
END(x86_stihlt)
ENTRY(x86_monitor)
movl 4(%esp), %eax
movl 8(%esp), %ecx
movl 12(%esp), %edx
monitor %eax, %ecx, %edx
ret
END(x86_monitor)
ENTRY(x86_mwait)
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
movl 12(%ebp), %ecx
mwait %eax, %ecx
leave
ret
END(x86_mwait)
ENTRY(stts)
movl %cr0, %eax
testl $CR0_TS, %eax
jnz 1f
orl $CR0_TS, %eax
movl %eax, %cr0
1:
ret
END(stts)
ENTRY(fldummy)
ffree %st(7)
fldz
ret
END(fldummy)
ENTRY(inb)
movl 4(%esp), %edx
xorl %eax, %eax
inb %dx, %al
ret
END(inb)
ENTRY(inw)
movl 4(%esp), %edx
xorl %eax, %eax
inw %dx, %ax
ret
END(inw)
ENTRY(inl)
movl 4(%esp), %edx
inl %dx, %eax
ret
END(inl)
ENTRY(outb)
movl 4(%esp), %edx
movl 8(%esp), %eax
outb %al, %dx
ret
END(outb)
ENTRY(outw)
movl 4(%esp), %edx
movl 8(%esp), %eax
outw %ax, %dx
ret
END(outw)
ENTRY(outl)
movl 4(%esp), %edx
movl 8(%esp), %eax
outl %eax, %dx
ret
END(outl)