xref: /dragonfly/sys/cpu/x86_64/include/asmacros.h (revision cd9c4877)
1b2b3ffcdSSimon Schubert /*
2b2b3ffcdSSimon Schubert  * Copyright (c) 1993 The Regents of the University of California.
3b2b3ffcdSSimon Schubert  * Copyright (c) 2008 The DragonFly Project.
4b2b3ffcdSSimon Schubert  * All rights reserved.
5b2b3ffcdSSimon Schubert  *
6b2b3ffcdSSimon Schubert  * Redistribution and use in source and binary forms, with or without
7b2b3ffcdSSimon Schubert  * modification, are permitted provided that the following conditions
8b2b3ffcdSSimon Schubert  * are met:
9b2b3ffcdSSimon Schubert  * 1. Redistributions of source code must retain the above copyright
10b2b3ffcdSSimon Schubert  *    notice, this list of conditions and the following disclaimer.
11b2b3ffcdSSimon Schubert  * 2. Redistributions in binary form must reproduce the above copyright
12b2b3ffcdSSimon Schubert  *    notice, this list of conditions and the following disclaimer in the
13b2b3ffcdSSimon Schubert  *    documentation and/or other materials provided with the distribution.
14c66c7e2fSzrj  * 3. Neither the name of the University nor the names of its contributors
15b2b3ffcdSSimon Schubert  *    may be used to endorse or promote products derived from this software
16b2b3ffcdSSimon Schubert  *    without specific prior written permission.
17b2b3ffcdSSimon Schubert  *
18b2b3ffcdSSimon Schubert  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19b2b3ffcdSSimon Schubert  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20b2b3ffcdSSimon Schubert  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21b2b3ffcdSSimon Schubert  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22b2b3ffcdSSimon Schubert  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23b2b3ffcdSSimon Schubert  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24b2b3ffcdSSimon Schubert  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25b2b3ffcdSSimon Schubert  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26b2b3ffcdSSimon Schubert  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27b2b3ffcdSSimon Schubert  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28b2b3ffcdSSimon Schubert  * SUCH DAMAGE.
29b2b3ffcdSSimon Schubert  *
30b2b3ffcdSSimon Schubert  * $FreeBSD: src/sys/amd64/include/asmacros.h,v 1.32 2006/10/28 06:04:29 bde Exp $
31b2b3ffcdSSimon Schubert  */
32b2b3ffcdSSimon Schubert 
33b2b3ffcdSSimon Schubert #ifndef _CPU_ASMACROS_H_
34b2b3ffcdSSimon Schubert #define _CPU_ASMACROS_H_
35b2b3ffcdSSimon Schubert 
36b2b3ffcdSSimon Schubert #include <sys/cdefs.h>
379283c84bSMatthew Dillon #include <machine/specialreg.h>
38b2b3ffcdSSimon Schubert 
39b2b3ffcdSSimon Schubert /* XXX too much duplication in various asm*.h's. */
40b2b3ffcdSSimon Schubert 
41b2b3ffcdSSimon Schubert /*
42b2b3ffcdSSimon Schubert  * CNAME is used to manage the relationship between symbol names in C
43b2b3ffcdSSimon Schubert  * and the equivalent assembly language names.  CNAME is given a name as
44b2b3ffcdSSimon Schubert  * it would be used in a C program.  It expands to the equivalent assembly
45b2b3ffcdSSimon Schubert  * language name.
46b2b3ffcdSSimon Schubert  */
47b2b3ffcdSSimon Schubert #define CNAME(csym)		csym
48b2b3ffcdSSimon Schubert 
49b2b3ffcdSSimon Schubert #define ALIGN_DATA	.p2align 3	/* 8 byte alignment, zero filled */
50b2b3ffcdSSimon Schubert #define ALIGN_TEXT	.p2align 4,0x90	/* 16-byte alignment, nop filled */
51b2b3ffcdSSimon Schubert #define SUPERALIGN_TEXT	.p2align 4,0x90	/* 16-byte alignment, nop filled */
52b2b3ffcdSSimon Schubert 
53b2b3ffcdSSimon Schubert #define GEN_ENTRY(name)		ALIGN_TEXT; .globl CNAME(name); \
54b2b3ffcdSSimon Schubert 				.type CNAME(name),@function; CNAME(name):
55b2b3ffcdSSimon Schubert #define NON_GPROF_ENTRY(name)	GEN_ENTRY(name)
56b2b3ffcdSSimon Schubert #define NON_GPROF_RET		.byte 0xc3	/* opcode for `ret' */
57b2b3ffcdSSimon Schubert 
58b2b3ffcdSSimon Schubert #define	END(name)		.size name, . - name
59b2b3ffcdSSimon Schubert 
60b2b3ffcdSSimon Schubert /*
61b2b3ffcdSSimon Schubert  * ALTENTRY() has to align because it is before a corresponding ENTRY().
62b2b3ffcdSSimon Schubert  * ENTRY() has to align to because there may be no ALTENTRY() before it.
63b2b3ffcdSSimon Schubert  * If there is a previous ALTENTRY() then the alignment code for ENTRY()
64b2b3ffcdSSimon Schubert  * is empty.
65b2b3ffcdSSimon Schubert  */
66b2b3ffcdSSimon Schubert #define ALTENTRY(name)		GEN_ENTRY(name)
67b2b3ffcdSSimon Schubert #define	CROSSJUMP(jtrue, label, jfalse)	jtrue label
68b2b3ffcdSSimon Schubert #define	CROSSJUMPTARGET(label)
69b2b3ffcdSSimon Schubert #define ENTRY(name)		GEN_ENTRY(name)
70b2b3ffcdSSimon Schubert #define FAKE_MCOUNT(caller)
71b2b3ffcdSSimon Schubert #define MCOUNT
72b2b3ffcdSSimon Schubert #define MCOUNT_LABEL(name)
73b2b3ffcdSSimon Schubert #define MEXITCOUNT
74b2b3ffcdSSimon Schubert 
75b2b3ffcdSSimon Schubert #ifdef LOCORE
76b2b3ffcdSSimon Schubert /*
77b2b3ffcdSSimon Schubert  * Convenience macro for declaring interrupt entry points.
78b2b3ffcdSSimon Schubert  */
79b2b3ffcdSSimon Schubert #define	IDTVEC(name)	ALIGN_TEXT; .globl __CONCAT(X,name); \
80b2b3ffcdSSimon Schubert 			.type __CONCAT(X,name),@function; __CONCAT(X,name):
81b2b3ffcdSSimon Schubert 
82b2b3ffcdSSimon Schubert /*
834611d87fSMatthew Dillon  * stack frame macro support - supports mmu isolation, swapgs, and
844611d87fSMatthew Dillon  * stack frame pushing and popping.
854611d87fSMatthew Dillon  */
864611d87fSMatthew Dillon 
874611d87fSMatthew Dillon /*
884611d87fSMatthew Dillon  * Kernel pmap isolation to work-around the massive Intel mmu bug
894611d87fSMatthew Dillon  * that allows kernel memory to be sussed out due to speculative memory
904611d87fSMatthew Dillon  * reads and instruction execution creating timing differences that can
914611d87fSMatthew Dillon  * be detected by userland.  e.g. force speculative read, speculatively
924611d87fSMatthew Dillon  * execute a cmp/branch sequence, detect timing.  Iterate cmp $values
934611d87fSMatthew Dillon  * to suss-out content of speculatively read kernel memory.
944611d87fSMatthew Dillon  *
95fc921477SMatthew Dillon  * We do this by creating a trampoline area for all user->kernel and
96fc921477SMatthew Dillon  * kernel->user transitions.  The trampoline area allows us to limit
97fc921477SMatthew Dillon  * the reach the kernel map in the isolated version of the user pmap
98fc921477SMatthew Dillon  * to JUST the trampoline area (for all cpus), tss, and vector area.
99fc921477SMatthew Dillon  *
100fc921477SMatthew Dillon  * It is very important that these transitions not access any memory
101fc921477SMatthew Dillon  * outside of the trampoline page while the isolated user process pmap
102fc921477SMatthew Dillon  * is active in %cr3.
103fc921477SMatthew Dillon  *
104fc921477SMatthew Dillon  * The trampoline does not add much overhead when pmap isolation is
105fc921477SMatthew Dillon  * disabled, so we just run with it regardless.  Of course, when pmap
106fc921477SMatthew Dillon  * isolation is enabled, the %cr3 loads add 150-250ns to every system
107fc921477SMatthew Dillon  * call as well as (without PCID) smash the TLB.
108fc921477SMatthew Dillon  *
1094611d87fSMatthew Dillon  * KMMUENTER -	Executed by the trampoline when a user->kernel transition
1104611d87fSMatthew Dillon  *		is detected.  The stack pointer points into the pcpu
1114611d87fSMatthew Dillon  *		trampoline space and is available for register save/restore.
1124611d87fSMatthew Dillon  *		Other registers have not yet been saved.  %gs points at
1134611d87fSMatthew Dillon  *		the kernel pcpu structure.
1144611d87fSMatthew Dillon  *
1154611d87fSMatthew Dillon  *		Caller has already determined that a transition is in
1164611d87fSMatthew Dillon  *		progress and has already issued the swapgs.  hwtf indicates
1174611d87fSMatthew Dillon  *		how much hardware has already pushed.
1184611d87fSMatthew Dillon  *
1194611d87fSMatthew Dillon  * KMMUEXIT  -	Executed when a kernel->user transition is made.  The stack
1204611d87fSMatthew Dillon  *		pointer points into the pcpu trampoline space and we are
1214611d87fSMatthew Dillon  *		almost ready to iretq.  %gs still points at the kernel pcpu
1224611d87fSMatthew Dillon  *		structure.
1234611d87fSMatthew Dillon  *
1244611d87fSMatthew Dillon  *		Caller has already determined that a transition is in
1254611d87fSMatthew Dillon  *		progress.  hwtf indicates how much hardware has already
1264611d87fSMatthew Dillon  *		pushed.
1274611d87fSMatthew Dillon  */
1289283c84bSMatthew Dillon 
1299283c84bSMatthew Dillon /*
1309283c84bSMatthew Dillon  * KMMUENTER_CORE - Handles ISOMMU, IBRS, and IBPB.  Caller has already
1319283c84bSMatthew Dillon  *		    saved %rcx and %rdx.  We have to deal with %rax.
1329283c84bSMatthew Dillon  *
1339283c84bSMatthew Dillon  *		    XXX If IBPB is not supported, try to clear the
1349283c84bSMatthew Dillon  *		    call return hw cache w/ many x chained call sequence?
1359283c84bSMatthew Dillon  *
13685b33048SMatthew Dillon  * NOTE - IBRS2 - We are leaving IBRS on full-time.  However, Intel
13785b33048SMatthew Dillon  *		  believes it is not safe unless the MSR is poked on each
13885b33048SMatthew Dillon  *		  user->kernel transition, so poke the MSR for both IBRS1
13985b33048SMatthew Dillon  *		  and IBRS2.
1409283c84bSMatthew Dillon  */
1419283c84bSMatthew Dillon #define KMMUENTER_CORE							\
142fc921477SMatthew Dillon 	testq	$PCB_ISOMMU,PCPU(trampoline)+TR_PCB_FLAGS ; 		\
1434611d87fSMatthew Dillon 	je	40f ;							\
1448ed06571SMatthew Dillon 	movq	PCPU(trampoline)+TR_PCB_CR3,%rcx ;			\
1458ed06571SMatthew Dillon 	movq	%rcx,%cr3 ;						\
146375bb03eSMatthew Dillon 40:	movl	PCPU(trampoline)+TR_PCB_SPEC_CTRL,%edx ;		\
147375bb03eSMatthew Dillon 	testq	%rdx, %rdx ;						\
1489283c84bSMatthew Dillon 	je	43f ;							\
14926c7e964SMatthew Dillon 	movq	%rax, PCPU(trampoline)+TR_RAX ;				\
150375bb03eSMatthew Dillon 	testq	$SPEC_CTRL_DUMMY_ENABLE,%rdx ;				\
1519283c84bSMatthew Dillon 	je	41f ;							\
152375bb03eSMatthew Dillon 	movq	%rdx, %rax ;						\
153375bb03eSMatthew Dillon 	andq	$SPEC_CTRL_IBRS|SPEC_CTRL_STIBP, %rax ;			\
154375bb03eSMatthew Dillon 	movq	$MSR_SPEC_CTRL,%rcx ;					\
1558ed06571SMatthew Dillon 	xorl	%edx,%edx ;						\
1568ed06571SMatthew Dillon 	wrmsr ;								\
157375bb03eSMatthew Dillon 	movl	PCPU(trampoline)+TR_PCB_SPEC_CTRL,%edx ;		\
158375bb03eSMatthew Dillon 41:	testq	$SPEC_CTRL_DUMMY_IBPB,%rdx ;				\
1599283c84bSMatthew Dillon 	je	42f ;							\
1609283c84bSMatthew Dillon 	movl	$MSR_PRED_CMD,%ecx ;					\
161375bb03eSMatthew Dillon 	movl	$1,%eax ;						\
1629283c84bSMatthew Dillon 	xorl	%edx,%edx ;						\
1639283c84bSMatthew Dillon 	wrmsr ;								\
16426c7e964SMatthew Dillon 42:	movq	PCPU(trampoline)+TR_RAX, %rax ;				\
1659283c84bSMatthew Dillon 43:									\
1669283c84bSMatthew Dillon 
1679283c84bSMatthew Dillon /*
1689283c84bSMatthew Dillon  * Enter with trampoline, hardware pushed up to %rip
1699283c84bSMatthew Dillon  */
1709283c84bSMatthew Dillon #define KMMUENTER_TFRIP							\
1719283c84bSMatthew Dillon 	subq	$TR_RIP, %rsp ;						\
1729283c84bSMatthew Dillon 	movq	%rcx, TR_RCX(%rsp) ;					\
1739283c84bSMatthew Dillon 	movq	%rdx, TR_RDX(%rsp) ;					\
1749283c84bSMatthew Dillon 	KMMUENTER_CORE ;						\
1758ed06571SMatthew Dillon 	movq	%rsp, %rcx ;		/* trampoline rsp */		\
176fc921477SMatthew Dillon 	movq	PCPU(trampoline)+TR_PCB_RSP,%rsp ; /* kstack rsp */	\
1778ed06571SMatthew Dillon 	movq	TR_SS(%rcx), %rdx ;					\
1788ed06571SMatthew Dillon 	pushq	%rdx ;							\
1798ed06571SMatthew Dillon 	movq	TR_RSP(%rcx), %rdx ;					\
1808ed06571SMatthew Dillon 	pushq	%rdx ;							\
1818ed06571SMatthew Dillon 	movq	TR_RFLAGS(%rcx), %rdx ;					\
1828ed06571SMatthew Dillon 	pushq	%rdx ;							\
1838ed06571SMatthew Dillon 	movq	TR_CS(%rcx), %rdx ;					\
1848ed06571SMatthew Dillon 	pushq	%rdx ;							\
1858ed06571SMatthew Dillon 	movq	TR_RIP(%rcx), %rdx ;					\
1868ed06571SMatthew Dillon 	pushq	%rdx ;							\
1878ed06571SMatthew Dillon 	movq	TR_RDX(%rcx), %rdx ;					\
1888ed06571SMatthew Dillon 	movq	TR_RCX(%rcx), %rcx					\
1894611d87fSMatthew Dillon 
1909283c84bSMatthew Dillon /*
1919283c84bSMatthew Dillon  * Enter with trampoline, hardware pushed up to ERR
1929283c84bSMatthew Dillon  */
1934611d87fSMatthew Dillon #define KMMUENTER_TFERR							\
1944611d87fSMatthew Dillon 	subq	$TR_ERR, %rsp ;						\
1958ed06571SMatthew Dillon 	movq	%rcx, TR_RCX(%rsp) ;					\
1968ed06571SMatthew Dillon 	movq	%rdx, TR_RDX(%rsp) ;					\
1979283c84bSMatthew Dillon 	KMMUENTER_CORE ;						\
1988ed06571SMatthew Dillon 	movq	%rsp, %rcx ;		/* trampoline rsp */		\
199fc921477SMatthew Dillon 	movq	PCPU(trampoline)+TR_PCB_RSP,%rsp ; /* kstack rsp */	\
2008ed06571SMatthew Dillon 	movq	TR_SS(%rcx), %rdx ;					\
2018ed06571SMatthew Dillon 	pushq	%rdx ;							\
2028ed06571SMatthew Dillon 	movq	TR_RSP(%rcx), %rdx ;					\
2038ed06571SMatthew Dillon 	pushq	%rdx ;							\
2048ed06571SMatthew Dillon 	movq	TR_RFLAGS(%rcx), %rdx ;					\
2058ed06571SMatthew Dillon 	pushq	%rdx ;							\
2068ed06571SMatthew Dillon 	movq	TR_CS(%rcx), %rdx ;					\
2078ed06571SMatthew Dillon 	pushq	%rdx ;							\
2088ed06571SMatthew Dillon 	movq	TR_RIP(%rcx), %rdx ;					\
2098ed06571SMatthew Dillon 	pushq	%rdx ;							\
2108ed06571SMatthew Dillon 	movq	TR_ERR(%rcx), %rdx ;					\
2118ed06571SMatthew Dillon 	pushq	%rdx ;							\
2128ed06571SMatthew Dillon 	movq	TR_RDX(%rcx), %rdx ;					\
2138ed06571SMatthew Dillon 	movq	TR_RCX(%rcx), %rcx					\
2144611d87fSMatthew Dillon 
2159283c84bSMatthew Dillon /*
2169283c84bSMatthew Dillon  * Enter with trampoline, hardware pushed up to ERR and
2179283c84bSMatthew Dillon  * we need to save %cr2 early (before potentially reloading %cr3).
2189283c84bSMatthew Dillon  */
2194611d87fSMatthew Dillon #define KMMUENTER_TFERR_SAVECR2						\
2204611d87fSMatthew Dillon 	subq	$TR_ERR, %rsp ;						\
2218ed06571SMatthew Dillon 	movq	%rcx, TR_RCX(%rsp) ;					\
2228ed06571SMatthew Dillon 	movq	%rdx, TR_RDX(%rsp) ;					\
2238ed06571SMatthew Dillon 	movq	%cr2, %rcx ;						\
2248ed06571SMatthew Dillon 	movq	%rcx, PCPU(trampoline)+TR_CR2 ;				\
2259283c84bSMatthew Dillon 	KMMUENTER_CORE ;						\
2268ed06571SMatthew Dillon 	movq	%rsp, %rcx ;		/* trampoline rsp */		\
227fc921477SMatthew Dillon 	movq	PCPU(trampoline)+TR_PCB_RSP,%rsp ; /* kstack rsp */	\
2288ed06571SMatthew Dillon 	movq	TR_SS(%rcx), %rdx ;					\
2298ed06571SMatthew Dillon 	pushq	%rdx ;							\
2308ed06571SMatthew Dillon 	movq	TR_RSP(%rcx), %rdx ;					\
2318ed06571SMatthew Dillon 	pushq	%rdx ;							\
2328ed06571SMatthew Dillon 	movq	TR_RFLAGS(%rcx), %rdx ;					\
2338ed06571SMatthew Dillon 	pushq	%rdx ;							\
2348ed06571SMatthew Dillon 	movq	TR_CS(%rcx), %rdx ;					\
2358ed06571SMatthew Dillon 	pushq	%rdx ;							\
2368ed06571SMatthew Dillon 	movq	TR_RIP(%rcx), %rdx ;					\
2378ed06571SMatthew Dillon 	pushq	%rdx ;							\
2388ed06571SMatthew Dillon 	movq	TR_ERR(%rcx), %rdx ;					\
2398ed06571SMatthew Dillon 	pushq	%rdx ;							\
2408ed06571SMatthew Dillon 	movq	TR_RDX(%rcx), %rdx ;					\
2418ed06571SMatthew Dillon 	movq	TR_RCX(%rcx), %rcx					\
2424611d87fSMatthew Dillon 
2434611d87fSMatthew Dillon /*
2444611d87fSMatthew Dillon  * Set %cr3 if necessary on syscall entry.  No registers may be
2454611d87fSMatthew Dillon  * disturbed.
2468ed06571SMatthew Dillon  *
2479283c84bSMatthew Dillon  * NOTE: TR_CR2 is used by the caller to save %rsp, we cannot use it here.
2484611d87fSMatthew Dillon  */
2494611d87fSMatthew Dillon #define KMMUENTER_SYSCALL						\
2509283c84bSMatthew Dillon 	movq	%rcx, PCPU(trampoline)+TR_RCX ;				\
2519283c84bSMatthew Dillon 	movq	%rdx, PCPU(trampoline)+TR_RDX ;				\
2529283c84bSMatthew Dillon 	KMMUENTER_CORE ;						\
2539283c84bSMatthew Dillon 	movq	PCPU(trampoline)+TR_RDX, %rdx ;				\
2549283c84bSMatthew Dillon 	movq	PCPU(trampoline)+TR_RCX, %rcx 				\
2559283c84bSMatthew Dillon 
2569283c84bSMatthew Dillon /*
257cd89a7ceSMatthew Dillon  * KMMUEXIT_CORE handles IBRS, STIBP, and MDS, but not ISOMMU
2589283c84bSMatthew Dillon  *
2599283c84bSMatthew Dillon  * We don't re-execute the IBPB barrier on exit atm.
260cd89a7ceSMatthew Dillon  *
261cd89a7ceSMatthew Dillon  * The MDS barrier (Microarchitectural Data Sampling) should be executed
262cd89a7ceSMatthew Dillon  * prior to any return to user-mode, if supported and enabled.  This is
263cd89a7ceSMatthew Dillon  * Intel-only.
264cd89a7ceSMatthew Dillon  *
265cd89a7ceSMatthew Dillon  * WARNING! %rsp may not be usable (it could be pointing to the user
266cd89a7ceSMatthew Dillon  *	    stack at this point).  And we must save/restore any registers
267cd89a7ceSMatthew Dillon  *	    we use.
2689283c84bSMatthew Dillon  */
2699283c84bSMatthew Dillon #define KMMUEXIT_CORE							\
270cd89a7ceSMatthew Dillon 	testl	$SPEC_CTRL_DUMMY_ENABLE|SPEC_CTRL_MDS_ENABLE, PCPU(trampoline)+TR_PCB_SPEC_CTRL+4 ; \
271cd89a7ceSMatthew Dillon 	je	43f ;							\
2729283c84bSMatthew Dillon 	movq	%rax, PCPU(trampoline)+TR_RAX ;				\
273cd89a7ceSMatthew Dillon 	movl	PCPU(trampoline)+TR_PCB_SPEC_CTRL+4, %eax ;		\
274cd89a7ceSMatthew Dillon 	testq	$SPEC_CTRL_MDS_ENABLE, %rax ;				\
275cd89a7ceSMatthew Dillon 	je	41f ;							\
276cd89a7ceSMatthew Dillon 	movq	$GSEL(GDATA_SEL, SEL_KPL), PCPU(trampoline)+TR_RCX ;	\
277cd89a7ceSMatthew Dillon 	verw	PCPU(trampoline)+TR_RCX ;				\
278cd89a7ceSMatthew Dillon 41:	testq	$SPEC_CTRL_DUMMY_ENABLE, %rax ;				\
279cd89a7ceSMatthew Dillon 	je	42f ;							\
2809283c84bSMatthew Dillon 	movq	%rcx, PCPU(trampoline)+TR_RCX ;				\
2819283c84bSMatthew Dillon 	movq	%rdx, PCPU(trampoline)+TR_RDX ;				\
282375bb03eSMatthew Dillon 	andq	$SPEC_CTRL_IBRS|SPEC_CTRL_STIBP, %rax ;			\
283375bb03eSMatthew Dillon 	movq	$MSR_SPEC_CTRL,%rcx ;					\
2848ed06571SMatthew Dillon 	xorl	%edx,%edx ;						\
2858ed06571SMatthew Dillon 	wrmsr ;								\
2869283c84bSMatthew Dillon 	movq	PCPU(trampoline)+TR_RDX, %rdx ;				\
2879283c84bSMatthew Dillon 	movq	PCPU(trampoline)+TR_RCX, %rcx ;				\
288cd89a7ceSMatthew Dillon 42:	movq	PCPU(trampoline)+TR_RAX, %rax ;				\
289cd89a7ceSMatthew Dillon 43:
2904611d87fSMatthew Dillon 
2914611d87fSMatthew Dillon /*
2924611d87fSMatthew Dillon  * We are positioned at the base of the trapframe.  Advance the trapframe
2934611d87fSMatthew Dillon  * and handle MMU isolation.  MMU isolation requires us to copy the
2944611d87fSMatthew Dillon  * hardware frame to the trampoline area before setting %cr3 to the
2954611d87fSMatthew Dillon  * isolated map.  We then set the %rsp for iretq to TR_RIP in the
2964611d87fSMatthew Dillon  * trampoline area (after restoring the register we saved in TR_ERR).
2974611d87fSMatthew Dillon  */
2984611d87fSMatthew Dillon #define KMMUEXIT							\
2994611d87fSMatthew Dillon 	addq	$TF_RIP,%rsp ;						\
3009283c84bSMatthew Dillon 	KMMUEXIT_CORE ;							\
3019283c84bSMatthew Dillon 	testq	$PCB_ISOMMU,PCPU(trampoline)+TR_PCB_FLAGS ; 		\
302cd89a7ceSMatthew Dillon 	je	50f ;							\
3038ed06571SMatthew Dillon 	movq	%rcx, PCPU(trampoline)+TR_ERR ;	/* save in TR_ERR */	\
3048ed06571SMatthew Dillon 	popq	%rcx ;				/* copy %rip */		\
3058ed06571SMatthew Dillon 	movq	%rcx, PCPU(trampoline)+TR_RIP ;				\
3068ed06571SMatthew Dillon 	popq	%rcx ;				/* copy %cs */		\
3078ed06571SMatthew Dillon 	movq	%rcx, PCPU(trampoline)+TR_CS ;				\
3088ed06571SMatthew Dillon 	popq	%rcx ;				/* copy %rflags */	\
3098ed06571SMatthew Dillon 	movq	%rcx, PCPU(trampoline)+TR_RFLAGS ;			\
3108ed06571SMatthew Dillon 	popq	%rcx ;				/* copy %rsp */		\
3118ed06571SMatthew Dillon 	movq	%rcx, PCPU(trampoline)+TR_RSP ;				\
3128ed06571SMatthew Dillon 	popq	%rcx ;				/* copy %ss */		\
3138ed06571SMatthew Dillon 	movq	%rcx, PCPU(trampoline)+TR_SS ;				\
3148ed06571SMatthew Dillon 	movq	%gs:0,%rcx ;						\
3158ed06571SMatthew Dillon 	addq	$GD_TRAMPOLINE+TR_ERR,%rcx ;				\
3168ed06571SMatthew Dillon 	movq	%rcx,%rsp ;						\
3178ed06571SMatthew Dillon 	movq	PCPU(trampoline)+TR_PCB_CR3_ISO,%rcx ;			\
3188ed06571SMatthew Dillon 	movq	%rcx,%cr3 ;						\
3198ed06571SMatthew Dillon 	popq	%rcx ;		/* positioned at TR_RIP after this */	\
320cd89a7ceSMatthew Dillon 50:									\
3214611d87fSMatthew Dillon 
3224611d87fSMatthew Dillon /*
3234611d87fSMatthew Dillon  * Warning: user stack pointer already loaded into %rsp at this
3244611d87fSMatthew Dillon  * point.  We still have the kernel %gs.
3259283c84bSMatthew Dillon  *
3269283c84bSMatthew Dillon  * Caller will sysexit, we do not have to copy anything to the
3279283c84bSMatthew Dillon  * trampoline area.
3284611d87fSMatthew Dillon  */
3294611d87fSMatthew Dillon #define KMMUEXIT_SYSCALL						\
3309283c84bSMatthew Dillon 	KMMUEXIT_CORE ;							\
3319283c84bSMatthew Dillon 	testq	$PCB_ISOMMU,PCPU(trampoline)+TR_PCB_FLAGS ; 		\
332cd89a7ceSMatthew Dillon 	je	50f ;							\
3338ed06571SMatthew Dillon 	movq	%rcx, PCPU(trampoline)+TR_RCX ;				\
3348ed06571SMatthew Dillon 	movq	PCPU(trampoline)+TR_PCB_CR3_ISO,%rcx ;			\
3358ed06571SMatthew Dillon 	movq	%rcx,%cr3 ;						\
3368ed06571SMatthew Dillon 	movq	PCPU(trampoline)+TR_RCX, %rcx ;				\
337cd89a7ceSMatthew Dillon 50:									\
3384611d87fSMatthew Dillon 
3394611d87fSMatthew Dillon /*
3404611d87fSMatthew Dillon  * Macros to create and destroy a trap frame.  rsp has already been shifted
3414611d87fSMatthew Dillon  * to the base of the trapframe in the thread structure.
342b2b3ffcdSSimon Schubert  */
343b2b3ffcdSSimon Schubert #define PUSH_FRAME_REGS							\
344b2b3ffcdSSimon Schubert 	movq	%rdi,TF_RDI(%rsp) ;					\
345b2b3ffcdSSimon Schubert 	movq	%rsi,TF_RSI(%rsp) ;					\
346b2b3ffcdSSimon Schubert 	movq	%rdx,TF_RDX(%rsp) ;					\
347b2b3ffcdSSimon Schubert 	movq	%rcx,TF_RCX(%rsp) ;					\
348b2b3ffcdSSimon Schubert 	movq	%r8,TF_R8(%rsp) ;					\
349b2b3ffcdSSimon Schubert 	movq	%r9,TF_R9(%rsp) ;					\
350b2b3ffcdSSimon Schubert 	movq	%rax,TF_RAX(%rsp) ;					\
351b2b3ffcdSSimon Schubert 	movq	%rbx,TF_RBX(%rsp) ;					\
352b2b3ffcdSSimon Schubert 	movq	%rbp,TF_RBP(%rsp) ;					\
353b2b3ffcdSSimon Schubert 	movq	%r10,TF_R10(%rsp) ;					\
354b2b3ffcdSSimon Schubert 	movq	%r11,TF_R11(%rsp) ;					\
355b2b3ffcdSSimon Schubert 	movq	%r12,TF_R12(%rsp) ;					\
356b2b3ffcdSSimon Schubert 	movq	%r13,TF_R13(%rsp) ;					\
357b2b3ffcdSSimon Schubert 	movq	%r14,TF_R14(%rsp) ;					\
3589474cbefSMatthew Dillon 	movq	%r15,TF_R15(%rsp) ;					\
3599474cbefSMatthew Dillon 					/* SECURITY CLEAR REGS */	\
3609474cbefSMatthew Dillon 	xorq	%rax,%rax ;						\
3619474cbefSMatthew Dillon 	movq	%rax,%rbx ;						\
3629474cbefSMatthew Dillon 	movq	%rax,%rcx ;						\
3639474cbefSMatthew Dillon 	movq	%rax,%rdx ;						\
3649474cbefSMatthew Dillon 	movq	%rax,%rdi ;						\
3659474cbefSMatthew Dillon 	movq	%rax,%rsi ;						\
3669474cbefSMatthew Dillon 	movq	%rax,%rbp ;						\
3679474cbefSMatthew Dillon 	movq	%rax,%r8 ;						\
3689474cbefSMatthew Dillon 	movq	%rax,%r9 ;						\
3699474cbefSMatthew Dillon 	movq	%rax,%r10 ;						\
3709474cbefSMatthew Dillon 	movq	%rax,%r11 ;						\
3719474cbefSMatthew Dillon 	movq	%rax,%r12 ;						\
3729474cbefSMatthew Dillon 	movq	%rax,%r13 ;						\
3739474cbefSMatthew Dillon 	movq	%rax,%r14 ;						\
3749474cbefSMatthew Dillon 	movq	%rax,%r15 						\
3759474cbefSMatthew Dillon 
376b2b3ffcdSSimon Schubert 
3774611d87fSMatthew Dillon /*
3784611d87fSMatthew Dillon  * PUSH_FRAME is the first thing executed upon interrupt entry.  We are
3794611d87fSMatthew Dillon  * responsible for swapgs execution and the KMMUENTER dispatch.
38085b33048SMatthew Dillon  *
38185b33048SMatthew Dillon  * NOTE - PUSH_FRAME code doesn't mess with %gs or the stack, or assume it can
38285b33048SMatthew Dillon  *	  use PCPU(trampoline), if the trap/exception is from supevisor mode.
38385b33048SMatthew Dillon  *	  It only messes with that stuff when the trap/exception is from user
38485b33048SMatthew Dillon  *	  mode.  Our DBG and NMI code depend on this behavior.
3854611d87fSMatthew Dillon  */
3864611d87fSMatthew Dillon #define PUSH_FRAME_TFRIP						\
3874611d87fSMatthew Dillon 	testb	$SEL_RPL_MASK,TF_CS-TF_RIP(%rsp) ; /* from userland? */	\
3884611d87fSMatthew Dillon 	jz	1f ;							\
3894611d87fSMatthew Dillon 	swapgs ;		/* from userland */			\
3904611d87fSMatthew Dillon 	KMMUENTER_TFRIP ;	/* from userland */			\
391b2b3ffcdSSimon Schubert 1:									\
3924611d87fSMatthew Dillon 	subq	$TF_RIP,%rsp ;						\
393*cd9c4877SMatthew Dillon 	PUSH_FRAME_REGS ; 						\
394*cd9c4877SMatthew Dillon 	SMAP_CLOSE							\
395b2b3ffcdSSimon Schubert 
3964611d87fSMatthew Dillon #define PUSH_FRAME_TFERR						\
3974611d87fSMatthew Dillon 	testb	$SEL_RPL_MASK,TF_CS-TF_ERR(%rsp) ; /* from userland? */	\
3984611d87fSMatthew Dillon 	jz	1f ;							\
3994611d87fSMatthew Dillon 	swapgs ;		/* from userland */			\
4004611d87fSMatthew Dillon 	KMMUENTER_TFERR ;	/* from userland */			\
4014611d87fSMatthew Dillon 1:									\
4024611d87fSMatthew Dillon 	subq	$TF_ERR,%rsp ;						\
403*cd9c4877SMatthew Dillon 	PUSH_FRAME_REGS ;						\
404*cd9c4877SMatthew Dillon 	SMAP_CLOSE							\
4054611d87fSMatthew Dillon 
4064611d87fSMatthew Dillon #define PUSH_FRAME_TFERR_SAVECR2					\
4074611d87fSMatthew Dillon 	testb	$SEL_RPL_MASK,TF_CS-TF_ERR(%rsp) ;			\
4084611d87fSMatthew Dillon 	jz	1f ;							\
4094611d87fSMatthew Dillon 	swapgs ;		/* from userland */			\
4104611d87fSMatthew Dillon 	KMMUENTER_TFERR_SAVECR2 ;/* from userland */			\
4114611d87fSMatthew Dillon 	subq	$TF_ERR,%rsp ;						\
4124611d87fSMatthew Dillon 	PUSH_FRAME_REGS ;						\
4134611d87fSMatthew Dillon 	movq	PCPU(trampoline)+TR_CR2, %r10 ;				\
4144611d87fSMatthew Dillon 	jmp 2f ;							\
4154611d87fSMatthew Dillon 1:									\
4164611d87fSMatthew Dillon 	subq	$TF_ERR,%rsp ;						\
4174611d87fSMatthew Dillon 	PUSH_FRAME_REGS ;						\
4184611d87fSMatthew Dillon 	movq	%cr2, %r10 ;						\
4194611d87fSMatthew Dillon 2:									\
420*cd9c4877SMatthew Dillon 	movq	%r10, TF_ADDR(%rsp) ;					\
421*cd9c4877SMatthew Dillon 	SMAP_CLOSE							\
4224611d87fSMatthew Dillon 
4234611d87fSMatthew Dillon /*
4244611d87fSMatthew Dillon  * POP_FRAME is issued just prior to the iretq, or just prior to a
4254611d87fSMatthew Dillon  * jmp doreti_iret.  These must be passed in to the macro.
4264611d87fSMatthew Dillon  */
4274611d87fSMatthew Dillon #define POP_FRAME(lastinsn)						\
428b2b3ffcdSSimon Schubert 	movq	TF_RDI(%rsp),%rdi ;					\
429b2b3ffcdSSimon Schubert 	movq	TF_RSI(%rsp),%rsi ;					\
430b2b3ffcdSSimon Schubert 	movq	TF_RDX(%rsp),%rdx ;					\
431b2b3ffcdSSimon Schubert 	movq	TF_RCX(%rsp),%rcx ;					\
432b2b3ffcdSSimon Schubert 	movq	TF_R8(%rsp),%r8 ;					\
433b2b3ffcdSSimon Schubert 	movq	TF_R9(%rsp),%r9 ;					\
434b2b3ffcdSSimon Schubert 	movq	TF_RAX(%rsp),%rax ;					\
435b2b3ffcdSSimon Schubert 	movq	TF_RBX(%rsp),%rbx ;					\
436b2b3ffcdSSimon Schubert 	movq	TF_RBP(%rsp),%rbp ;					\
437b2b3ffcdSSimon Schubert 	movq	TF_R10(%rsp),%r10 ;					\
438b2b3ffcdSSimon Schubert 	movq	TF_R11(%rsp),%r11 ;					\
439b2b3ffcdSSimon Schubert 	movq	TF_R12(%rsp),%r12 ;					\
440b2b3ffcdSSimon Schubert 	movq	TF_R13(%rsp),%r13 ;					\
441b2b3ffcdSSimon Schubert 	movq	TF_R14(%rsp),%r14 ;					\
442b2b3ffcdSSimon Schubert 	movq	TF_R15(%rsp),%r15 ;					\
4439e24b495SMatthew Dillon 	cli ;								\
4444611d87fSMatthew Dillon 	testb	$SEL_RPL_MASK,TF_CS(%rsp) ; /* return to user? */	\
4454611d87fSMatthew Dillon 	jz	1f ;							\
4464611d87fSMatthew Dillon 	KMMUEXIT ;		/* return to user */			\
4474611d87fSMatthew Dillon 	swapgs ;		/* return to user */			\
4484611d87fSMatthew Dillon 	jmp	2f ;							\
4494611d87fSMatthew Dillon 1:									\
4504611d87fSMatthew Dillon 	addq	$TF_RIP,%rsp ;	/* setup for iretq */			\
4514611d87fSMatthew Dillon 2:									\
4524611d87fSMatthew Dillon 	lastinsn
453b2b3ffcdSSimon Schubert 
454b2b3ffcdSSimon Schubert /*
455b2b3ffcdSSimon Schubert  * Access per-CPU data.
456b2b3ffcdSSimon Schubert  */
457b2b3ffcdSSimon Schubert #define	PCPU(member)		%gs:gd_ ## member
4589611ff20SSepherosa Ziehau #define PCPU_E8(member,idx)	%gs:gd_ ## member(,idx,8)
459b2b3ffcdSSimon Schubert #define	PCPU_ADDR(member, reg)					\
460b2b3ffcdSSimon Schubert 	movq %gs:PC_PRVSPACE, reg ;				\
461b2b3ffcdSSimon Schubert 	addq $PC_ ## member, reg
462b2b3ffcdSSimon Schubert 
46348c77f2bSMatthew Dillon /*
46448c77f2bSMatthew Dillon  * This adds a code placemarker (the 3-byte NOP) and references
46548c77f2bSMatthew Dillon  * it from a section, allowing it to be replaced with a STAC or CLAC
46648c77f2bSMatthew Dillon  * instruction (also 3-byte instructions) when the system supports
46748c77f2bSMatthew Dillon  * SMAP.
46848c77f2bSMatthew Dillon  */
46948c77f2bSMatthew Dillon #define SMAP_OPEN						\
47048c77f2bSMatthew Dillon 	.globl	__start_set_smap_open ;				\
47148c77f2bSMatthew Dillon 	.globl	__stop_set_smap_open ;				\
47248c77f2bSMatthew Dillon 60:	nop	%eax ;						\
47348c77f2bSMatthew Dillon 	.section set_smap_open,"aw" ;				\
47448c77f2bSMatthew Dillon 	.quad	60b ;						\
47548c77f2bSMatthew Dillon 	.previous						\
47648c77f2bSMatthew Dillon 
47748c77f2bSMatthew Dillon #define SMAP_CLOSE						\
47848c77f2bSMatthew Dillon 	.globl	__start_set_smap_close ;			\
47948c77f2bSMatthew Dillon 	.globl	__stop_set_smap_close ;				\
48048c77f2bSMatthew Dillon 60:	nop	%eax ;						\
48148c77f2bSMatthew Dillon 	.section set_smap_close,"aw" ;				\
48248c77f2bSMatthew Dillon 	.quad	60b ;						\
48348c77f2bSMatthew Dillon 	.previous						\
48448c77f2bSMatthew Dillon 
485b2b3ffcdSSimon Schubert #endif /* LOCORE */
486b2b3ffcdSSimon Schubert 
487b2b3ffcdSSimon Schubert #endif /* !_CPU_ASMACROS_H_ */
488