xref: /netbsd-src/sys/arch/i386/include/frameasm.h (revision e6c7e151de239c49d2e38720a061ed9d1fa99309)
1 /*	$NetBSD: frameasm.h,v 1.29 2019/10/12 06:31:03 maxv Exp $	*/
2 
3 #ifndef _I386_FRAMEASM_H_
4 #define _I386_FRAMEASM_H_
5 
6 #ifdef _KERNEL_OPT
7 #include "opt_multiprocessor.h"
8 #include "opt_xen.h"
9 #endif
10 
11 
12 #ifdef XEN
13 /* XXX assym.h */
14 #define TRAP_INSTR	int	$0x82
15 #define XEN_BLOCK_EVENTS(reg)	movb	$1,EVTCHN_UPCALL_MASK(reg)
16 #define XEN_UNBLOCK_EVENTS(reg)	movb	$0,EVTCHN_UPCALL_MASK(reg)
17 #define XEN_TEST_PENDING(reg)	testb	$0xFF,EVTCHN_UPCALL_PENDING(reg)
18 #endif /* XEN */
19 
20 #if defined(XENPV)
21 #define CLI(reg)	movl	CPUVAR(VCPU),reg ;  \
22 			XEN_BLOCK_EVENTS(reg)
23 #define STI(reg)	movl	CPUVAR(VCPU),reg ;  \
24 			XEN_UNBLOCK_EVENTS(reg)
25 #define STIC(reg)	movl	CPUVAR(VCPU),reg ;  \
26 			XEN_UNBLOCK_EVENTS(reg)  ; \
27 			testb	$0xff,EVTCHN_UPCALL_PENDING(reg)
28 #else
29 #define CLI(reg)	cli
30 #define STI(reg)	sti
31 #ifdef XENPVHVM
32 #define STIC(reg)	sti ; \
33 			movl	CPUVAR(VCPU),reg ; \
34 			XEN_UNBLOCK_EVENTS(reg)  ; \
35 			testb	$0xff,EVTCHN_UPCALL_PENDING(reg)
36 #endif /* XENPVHVM */
37 
38 #endif /* XENPV */
39 
40 #define HP_NAME_CLAC		1
41 #define HP_NAME_STAC		2
42 #define HP_NAME_NOLOCK		3
43 #define HP_NAME_RETFENCE	4
44 
45 #define HOTPATCH(name, size) \
46 123:						; \
47 	.pushsection	.rodata.hotpatch, "a"	; \
48 	.byte		name			; \
49 	.byte		size			; \
50 	.long		123b			; \
51 	.popsection
52 
53 #define SMAP_ENABLE \
54 	HOTPATCH(HP_NAME_CLAC, 3)		; \
55 	.byte 0x90, 0x90, 0x90
56 
57 #define SMAP_DISABLE \
58 	HOTPATCH(HP_NAME_STAC, 3)		; \
59 	.byte 0x90, 0x90, 0x90
60 
61 /*
62  * These are used on interrupt or trap entry or exit.
63  */
64 #define	INTRENTRY \
65 	SMAP_ENABLE			; \
66 	subl	$TF_PUSHSIZE,%esp	; \
67 	movw	%gs,TF_GS(%esp)		; \
68 	movw	%fs,TF_FS(%esp) 	; \
69 	movl	%eax,TF_EAX(%esp)	; \
70 	movw	%es,TF_ES(%esp) 	; \
71 	movw	%ds,TF_DS(%esp) 	; \
72 	movl	$GSEL(GDATA_SEL, SEL_KPL),%eax	; \
73 	movl	%edi,TF_EDI(%esp)	; \
74 	movl	%esi,TF_ESI(%esp)	; \
75 	movw	%ax,%ds			; \
76 	movl	%ebp,TF_EBP(%esp)	; \
77 	movw	%ax,%es			; \
78 	movl	%ebx,TF_EBX(%esp)	; \
79 	movw	%ax,%gs			; \
80 	movl	%edx,TF_EDX(%esp)	; \
81 	movl	$GSEL(GCPU_SEL, SEL_KPL),%eax	; \
82 	movl	%ecx,TF_ECX(%esp)	; \
83 	movl	%eax,%fs		; \
84 	cld
85 
86 #define	INTRFASTEXIT \
87 	jmp	intrfastexit
88 
89 #define INTR_RECURSE_HWFRAME \
90 	pushfl				; \
91 	pushl	%cs			; \
92 	pushl	%esi			;
93 
94 #define	CHECK_DEFERRED_SWITCH \
95 	cmpl	$0, CPUVAR(WANT_PMAPLOAD)
96 
97 #define	CHECK_ASTPENDING(reg)	movl	CPUVAR(CURLWP),reg	; \
98 				cmpl	$0, L_MD_ASTPENDING(reg)
99 #define	CLEAR_ASTPENDING(reg)	movl	$0, L_MD_ASTPENDING(reg)
100 
101 /*
102  * If the FPU state is not in the CPU, restore it. Executed with interrupts
103  * disabled.
104  *
105  *     %ebx must not be modified
106  */
107 #define HANDLE_DEFERRED_FPU	\
108 	movl	CPUVAR(CURLWP),%eax			; \
109 	testl	$MDL_FPU_IN_CPU,L_MD_FLAGS(%eax)	; \
110 	jnz	1f					; \
111 	pushl	%eax					; \
112 	call	_C_LABEL(fpu_handle_deferred)		; \
113 	popl	%eax					; \
114 	orl	$MDL_FPU_IN_CPU,L_MD_FLAGS(%eax)	; \
115 1:
116 
117 /*
118  * IDEPTH_INCR:
119  * increase ci_idepth and switch to the interrupt stack if necessary.
120  * note that the initial value of ci_idepth is -1.
121  *
122  * => should be called with interrupt disabled.
123  * => save the old value of %esp in %eax.
124  */
125 
126 #define	IDEPTH_INCR \
127 	incl	CPUVAR(IDEPTH); \
128 	movl	%esp, %eax; \
129 	jne	999f; \
130 	movl	CPUVAR(INTRSTACK), %esp; \
131 999:	pushl	%eax; /* eax == pointer to intrframe */ \
132 
133 /*
134  * IDEPTH_DECR:
135  * decrement ci_idepth and switch back to
136  * the original stack saved by IDEPTH_INCR.
137  *
138  * => should be called with interrupt disabled.
139  */
140 
141 #define	IDEPTH_DECR \
142 	popl	%esp; \
143 	decl	CPUVAR(IDEPTH)
144 
145 #endif /* _I386_FRAMEASM_H_ */
146