xref: /openbsd/sys/arch/amd64/amd64/locore.S (revision cb5172cd)
1*cb5172cdSderaadt/*	$OpenBSD: locore.S,v 1.87 2017/07/06 06:17:04 deraadt Exp $	*/
2b5b9857bSart/*	$NetBSD: locore.S,v 1.13 2004/03/25 18:33:17 drochner Exp $	*/
3f5df1827Smickey
4f5df1827Smickey/*
5f5df1827Smickey * Copyright-o-rama!
6f5df1827Smickey */
7f5df1827Smickey
8f5df1827Smickey/*
9f5df1827Smickey * Copyright (c) 2001 Wasabi Systems, Inc.
10f5df1827Smickey * All rights reserved.
11f5df1827Smickey *
12f5df1827Smickey * Written by Frank van der Linden for Wasabi Systems, Inc.
13f5df1827Smickey *
14f5df1827Smickey * Redistribution and use in source and binary forms, with or without
15f5df1827Smickey * modification, are permitted provided that the following conditions
16f5df1827Smickey * are met:
17f5df1827Smickey * 1. Redistributions of source code must retain the above copyright
18f5df1827Smickey *    notice, this list of conditions and the following disclaimer.
19f5df1827Smickey * 2. Redistributions in binary form must reproduce the above copyright
20f5df1827Smickey *    notice, this list of conditions and the following disclaimer in the
21f5df1827Smickey *    documentation and/or other materials provided with the distribution.
22f5df1827Smickey * 3. All advertising materials mentioning features or use of this software
23f5df1827Smickey *    must display the following acknowledgement:
24f5df1827Smickey *      This product includes software developed for the NetBSD Project by
25f5df1827Smickey *      Wasabi Systems, Inc.
26f5df1827Smickey * 4. The name of Wasabi Systems, Inc. may not be used to endorse
27f5df1827Smickey *    or promote products derived from this software without specific prior
28f5df1827Smickey *    written permission.
29f5df1827Smickey *
30f5df1827Smickey * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
31f5df1827Smickey * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
32f5df1827Smickey * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
33f5df1827Smickey * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
34f5df1827Smickey * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
35f5df1827Smickey * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
36f5df1827Smickey * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
37f5df1827Smickey * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
38f5df1827Smickey * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
39f5df1827Smickey * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
40f5df1827Smickey * POSSIBILITY OF SUCH DAMAGE.
41f5df1827Smickey */
42f5df1827Smickey
43f5df1827Smickey
44f5df1827Smickey/*-
45f5df1827Smickey * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
46f5df1827Smickey * All rights reserved.
47f5df1827Smickey *
48f5df1827Smickey * This code is derived from software contributed to The NetBSD Foundation
49f5df1827Smickey * by Charles M. Hannum.
50f5df1827Smickey *
51f5df1827Smickey * Redistribution and use in source and binary forms, with or without
52f5df1827Smickey * modification, are permitted provided that the following conditions
53f5df1827Smickey * are met:
54f5df1827Smickey * 1. Redistributions of source code must retain the above copyright
55f5df1827Smickey *    notice, this list of conditions and the following disclaimer.
56f5df1827Smickey * 2. Redistributions in binary form must reproduce the above copyright
57f5df1827Smickey *    notice, this list of conditions and the following disclaimer in the
58f5df1827Smickey *    documentation and/or other materials provided with the distribution.
59f5df1827Smickey *
60f5df1827Smickey * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
61f5df1827Smickey * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
62f5df1827Smickey * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
63f5df1827Smickey * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
64f5df1827Smickey * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
65f5df1827Smickey * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
66f5df1827Smickey * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
67f5df1827Smickey * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
68f5df1827Smickey * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
69f5df1827Smickey * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
70f5df1827Smickey * POSSIBILITY OF SUCH DAMAGE.
71f5df1827Smickey */
72f5df1827Smickey
73f5df1827Smickey/*-
74f5df1827Smickey * Copyright (c) 1990 The Regents of the University of California.
75f5df1827Smickey * All rights reserved.
76f5df1827Smickey *
77f5df1827Smickey * This code is derived from software contributed to Berkeley by
78f5df1827Smickey * William Jolitz.
79f5df1827Smickey *
80f5df1827Smickey * Redistribution and use in source and binary forms, with or without
81f5df1827Smickey * modification, are permitted provided that the following conditions
82f5df1827Smickey * are met:
83f5df1827Smickey * 1. Redistributions of source code must retain the above copyright
84f5df1827Smickey *    notice, this list of conditions and the following disclaimer.
85f5df1827Smickey * 2. Redistributions in binary form must reproduce the above copyright
86f5df1827Smickey *    notice, this list of conditions and the following disclaimer in the
87f5df1827Smickey *    documentation and/or other materials provided with the distribution.
88b5b9857bSart * 3. Neither the name of the University nor the names of its contributors
89f5df1827Smickey *    may be used to endorse or promote products derived from this software
90f5df1827Smickey *    without specific prior written permission.
91f5df1827Smickey *
92f5df1827Smickey * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
93f5df1827Smickey * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
94f5df1827Smickey * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
95f5df1827Smickey * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
96f5df1827Smickey * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
97f5df1827Smickey * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
98f5df1827Smickey * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
99f5df1827Smickey * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
100f5df1827Smickey * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
101f5df1827Smickey * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
102f5df1827Smickey * SUCH DAMAGE.
103f5df1827Smickey *
104f5df1827Smickey *	@(#)locore.s	7.3 (Berkeley) 5/13/91
105f5df1827Smickey */
106f5df1827Smickey
107f5df1827Smickey#include "assym.h"
108f5df1827Smickey#include "lapic.h"
109f5df1827Smickey#include "ksyms.h"
110d8213a49Smikeb#include "xen.h"
111218ead0bSmikeb#include "hyperv.h"
112f5df1827Smickey
113f5df1827Smickey#include <sys/syscall.h>
114f5df1827Smickey
115f5df1827Smickey#include <machine/param.h>
116f5df1827Smickey#include <machine/segments.h>
117f5df1827Smickey#include <machine/specialreg.h>
118f5df1827Smickey#include <machine/trap.h>
119f5df1827Smickey#include <machine/frameasm.h>
120f5df1827Smickey
121f5df1827Smickey#if NLAPIC > 0
122f5df1827Smickey#include <machine/i82489reg.h>
123f5df1827Smickey#endif
124f5df1827Smickey
125f5df1827Smickey/*
126f5df1827Smickey * override user-land alignment before including asm.h
127f5df1827Smickey */
128*cb5172cdSderaadt#define	ALIGN_DATA	.align	8,0xcc
129f5df1827Smickey#define ALIGN_TEXT	.align 16,0x90
130f5df1827Smickey#define _ALIGN_TEXT	ALIGN_TEXT
131f5df1827Smickey
132f5df1827Smickey#include <machine/asm.h>
133f5df1827Smickey
134fbe53cacSkrw#define SET_CURPROC(proc,cpu)			\
135fbe53cacSkrw	movq	CPUVAR(SELF),cpu	;	\
136fbe53cacSkrw	movq	proc,CPUVAR(CURPROC)      ;	\
137fbe53cacSkrw	movq	cpu,P_CPU(proc)
138fbe53cacSkrw
139fbe53cacSkrw#define GET_CURPCB(reg)			movq	CPUVAR(CURPCB),reg
140fbe53cacSkrw#define SET_CURPCB(reg)			movq	reg,CPUVAR(CURPCB)
141fbe53cacSkrw
142fbe53cacSkrw
143f5df1827Smickey/*
144f5df1827Smickey * Initialization
145f5df1827Smickey */
146f5df1827Smickey	.data
147f5df1827Smickey
148f5df1827Smickey#if NLAPIC > 0
1490175496dSderaadt	.align  NBPG, 0xcc
150f5df1827Smickey	.globl _C_LABEL(local_apic), _C_LABEL(lapic_id), _C_LABEL(lapic_tpr)
151f5df1827Smickey_C_LABEL(local_apic):
152f5df1827Smickey	.space  LAPIC_ID
153f5df1827Smickey_C_LABEL(lapic_id):
154f5df1827Smickey	.long   0x00000000
155f5df1827Smickey	.space  LAPIC_TPRI-(LAPIC_ID+4)
156f5df1827Smickey_C_LABEL(lapic_tpr):
157f5df1827Smickey	.space  LAPIC_PPRI-LAPIC_TPRI
158f5df1827Smickey_C_LABEL(lapic_ppr):
159f5df1827Smickey	.space  LAPIC_ISR-LAPIC_PPRI
160f5df1827Smickey_C_LABEL(lapic_isr):
161f5df1827Smickey	.space  NBPG-LAPIC_ISR
162f5df1827Smickey#endif
163f5df1827Smickey
164576d2332Smlarkin	.globl	_C_LABEL(cpu_id),_C_LABEL(cpu_vendor)
165f5df1827Smickey	.globl	_C_LABEL(cpuid_level),_C_LABEL(cpu_feature)
1667196220cSmlarkin	.globl	_C_LABEL(cpu_ebxfeature)
1676995b18fShaesbaert	.globl	_C_LABEL(cpu_ecxfeature),_C_LABEL(ecpu_ecxfeature)
16807166672Smglocker	.globl	_C_LABEL(cpu_perf_eax)
16907166672Smglocker	.globl	_C_LABEL(cpu_perf_ebx)
17007166672Smglocker	.globl	_C_LABEL(cpu_perf_edx)
17107166672Smglocker	.globl	_C_LABEL(cpu_apmi_edx)
172886c356bSmlarkin	.globl	_C_LABEL(ssym),_C_LABEL(esym),_C_LABEL(boothowto)
173886c356bSmlarkin	.globl	_C_LABEL(bootdev)
1746483bf47Sderaadt	.globl	_C_LABEL(bootinfo), _C_LABEL(bootinfo_size), _C_LABEL(atdevbase)
175f5df1827Smickey	.globl	_C_LABEL(proc0paddr),_C_LABEL(PTDpaddr)
176f5df1827Smickey	.globl	_C_LABEL(biosbasemem),_C_LABEL(biosextmem)
1776483bf47Sderaadt	.globl	_C_LABEL(bootapiver)
17836414dbbSmlarkin	.globl	_C_LABEL(pg_nx)
179f5df1827Smickey_C_LABEL(cpu_id):	.long	0	# saved from `cpuid' instruction
180f5df1827Smickey_C_LABEL(cpu_feature):	.long	0	# feature flags from 'cpuid'
181f5df1827Smickey					#   instruction
1827196220cSmlarkin_C_LABEL(cpu_ebxfeature):.long	0	# ext. ebx feature flags from 'cpuid'
1837196220cSmlarkin_C_LABEL(cpu_ecxfeature):.long	0	# ext. ecx feature flags from 'cpuid'
1846995b18fShaesbaert_C_LABEL(ecpu_ecxfeature):.long	0	# extended ecx feature flags
18507166672Smglocker_C_LABEL(cpu_perf_eax):	.long	0	# arch. perf. mon. flags from 'cpuid'
18607166672Smglocker_C_LABEL(cpu_perf_ebx):	.long	0	# arch. perf. mon. flags from 'cpuid'
18707166672Smglocker_C_LABEL(cpu_perf_edx):	.long	0	# arch. perf. mon. flags from 'cpuid'
18807166672Smglocker_C_LABEL(cpu_apmi_edx):	.long	0	# adv. power mgmt. info. from 'cpuid'
189f5df1827Smickey_C_LABEL(cpuid_level):	.long	-1	# max. level accepted by 'cpuid'
190f5df1827Smickey					#   instruction
191f5df1827Smickey_C_LABEL(cpu_vendor):	.space	16	# vendor string returned by `cpuid'
192f5df1827Smickey					#   instruction
193c7636a68Smlarkin_C_LABEL(ssym):		.quad	0	# ptr to start of syms
194f5df1827Smickey_C_LABEL(esym):		.quad	0	# ptr to end of syms
195f5df1827Smickey_C_LABEL(atdevbase):	.quad	0	# location of start of iomem in virtual
196e9dacf7aStom_C_LABEL(bootapiver):	.long	0	# /boot API version
197f431e893Smillert_C_LABEL(bootdev):	.long	0	# device we booted from
198f5df1827Smickey_C_LABEL(proc0paddr):	.quad	0
199f5df1827Smickey_C_LABEL(PTDpaddr):	.quad	0	# paddr of PTD, for libkvm
200f5df1827Smickey#ifndef REALBASEMEM
201f5df1827Smickey_C_LABEL(biosbasemem):	.long	0	# base memory reported by BIOS
202f5df1827Smickey#else
203f5df1827Smickey_C_LABEL(biosbasemem):	.long	REALBASEMEM
204f5df1827Smickey#endif
205f5df1827Smickey#ifndef REALEXTMEM
206f5df1827Smickey_C_LABEL(biosextmem):	.long	0	# extended memory reported by BIOS
207f5df1827Smickey#else
208f5df1827Smickey_C_LABEL(biosextmem):	.long	REALEXTMEM
209f5df1827Smickey#endif
21036414dbbSmlarkin_C_LABEL(pg_nx):	.quad	0	# NX PTE bit (if CPU supports)
211f5df1827Smickey
212f5df1827Smickey#define	_RELOC(x)	((x) - KERNBASE)
213f5df1827Smickey#define	RELOC(x)	_RELOC(_C_LABEL(x))
214f5df1827Smickey
215f5df1827Smickey	.globl	gdt64
216f5df1827Smickey
217f5df1827Smickeygdt64:
218029cc5b9Smikeb	.word	gdt64_end-gdt64_start-1
219f5df1827Smickey	.quad	_RELOC(gdt64_start)
2200175496dSderaadt.align 64, 0xcc
221f5df1827Smickey
222f5df1827Smickeygdt64_start:
223f5df1827Smickey	.quad 0x0000000000000000	/* always empty */
224f5df1827Smickey	.quad 0x00af9a000000ffff	/* kernel CS */
225f5df1827Smickey	.quad 0x00cf92000000ffff	/* kernel DS */
226f5df1827Smickeygdt64_end:
227f5df1827Smickey
228f5df1827Smickey/*
229f5df1827Smickey * Some hackage to deal with 64bit symbols in 32 bit mode.
230e9dacf7aStom * This may not be needed if things are cleaned up a little.
231f5df1827Smickey */
232f5df1827Smickey
233f5df1827Smickey/*****************************************************************************/
234f5df1827Smickey
235f5df1827Smickey/*
236f5df1827Smickey * Signal trampoline; copied to top of user stack.
237aa7a0a27Sguenther * gdb's backtrace logic matches against the instructions in this.
238f5df1827Smickey */
239b983598cSderaadt	.section .rodata
240b983598cSderaadt	.globl	_C_LABEL(sigcode)
241b983598cSderaadt_C_LABEL(sigcode):
242f5df1827Smickey	call	*%rax
243f5df1827Smickey
244f5df1827Smickey	movq	%rsp,%rdi
245f5df1827Smickey	pushq	%rdi			/* fake return address */
246f5df1827Smickey	movq	$SYS_sigreturn,%rax
2471396572dSguenther	syscall
2487730d1d9Sderaadt	.globl	_C_LABEL(sigcoderet)
2497730d1d9Sderaadt_C_LABEL(sigcoderet):
250f5df1827Smickey	movq	$SYS_exit,%rax
251f5df1827Smickey	syscall
252f5df1827Smickey	.globl	_C_LABEL(esigcode)
253f5df1827Smickey_C_LABEL(esigcode):
254f5df1827Smickey
255b983598cSderaadt	.globl	_C_LABEL(sigfill)
256b983598cSderaadt_C_LABEL(sigfill):
257b983598cSderaadt	int3
258b983598cSderaadt_C_LABEL(esigfill):
259b983598cSderaadt	.globl	_C_LABEL(sigfillsiz)
260b983598cSderaadt_C_LABEL(sigfillsiz):
261b983598cSderaadt	.long	_C_LABEL(esigfill) - _C_LABEL(sigfill)
262b983598cSderaadt
263b983598cSderaadt	.text
264f5df1827Smickey/*
265f5df1827Smickey * void lgdt(struct region_descriptor *rdp);
266f5df1827Smickey * Change the global descriptor table.
267f5df1827Smickey */
268f5df1827SmickeyNENTRY(lgdt)
269f5df1827Smickey	/* Reload the descriptor table. */
270f5df1827Smickey	movq	%rdi,%rax
271f5df1827Smickey	lgdt	(%rax)
272f5df1827Smickey	/* Flush the prefetch q. */
273f5df1827Smickey	jmp	1f
274f5df1827Smickey	nop
275f5df1827Smickey1:	/* Reload "stale" selectors. */
276f5df1827Smickey	movl	$GSEL(GDATA_SEL, SEL_KPL),%eax
277f5df1827Smickey	movl	%eax,%ds
278f5df1827Smickey	movl	%eax,%es
279f5df1827Smickey	movl	%eax,%ss
280f5df1827Smickey	/* Reload code selector by doing intersegment return. */
281f5df1827Smickey	popq	%rax
282f5df1827Smickey	pushq	$GSEL(GCODE_SEL, SEL_KPL)
283f5df1827Smickey	pushq	%rax
284f5df1827Smickey	lretq
285f5df1827Smickey
286f5df1827SmickeyENTRY(setjmp)
287f5df1827Smickey	/*
288f5df1827Smickey	 * Only save registers that must be preserved across function
289f5df1827Smickey	 * calls according to the ABI (%rbx, %rsp, %rbp, %r12-%r15)
290f5df1827Smickey	 * and %rip.
291f5df1827Smickey	 */
292f5df1827Smickey	movq	%rdi,%rax
293f5df1827Smickey	movq	%rbx,(%rax)
294f5df1827Smickey	movq	%rsp,8(%rax)
295f5df1827Smickey	movq	%rbp,16(%rax)
296f5df1827Smickey	movq	%r12,24(%rax)
297f5df1827Smickey	movq	%r13,32(%rax)
298f5df1827Smickey	movq	%r14,40(%rax)
299f5df1827Smickey	movq	%r15,48(%rax)
300f5df1827Smickey	movq	(%rsp),%rdx
301f5df1827Smickey	movq	%rdx,56(%rax)
302f5df1827Smickey	xorl	%eax,%eax
303f5df1827Smickey	ret
304f5df1827Smickey
305f5df1827SmickeyENTRY(longjmp)
306f5df1827Smickey	movq	%rdi,%rax
307f5df1827Smickey	movq	(%rax),%rbx
308f5df1827Smickey	movq	8(%rax),%rsp
309f5df1827Smickey	movq	16(%rax),%rbp
310f5df1827Smickey	movq	24(%rax),%r12
311f5df1827Smickey	movq	32(%rax),%r13
312f5df1827Smickey	movq	40(%rax),%r14
313f5df1827Smickey	movq	48(%rax),%r15
314f5df1827Smickey	movq	56(%rax),%rdx
315f5df1827Smickey	movq	%rdx,(%rsp)
316f5df1827Smickey	xorl	%eax,%eax
317f5df1827Smickey	incl	%eax
318f5df1827Smickey	ret
319f5df1827Smickey
320f5df1827Smickey/*****************************************************************************/
321f5df1827Smickey
322f5df1827Smickey/*
32345053f4aSart * int cpu_switchto(struct proc *old, struct proc *new)
32445053f4aSart * Switch from "old" proc to "new".
325f5df1827Smickey */
32645053f4aSartENTRY(cpu_switchto)
327f5df1827Smickey	pushq	%rbx
328f5df1827Smickey	pushq	%rbp
329f5df1827Smickey	pushq	%r12
330f5df1827Smickey	pushq	%r13
331f5df1827Smickey	pushq	%r14
332f5df1827Smickey	pushq	%r15
333f5df1827Smickey
334fbe53cacSkrw	movq	%rdi, %r13
335fbe53cacSkrw	movq	%rsi, %r12
336fbe53cacSkrw
33760854cb9Sguenther	/* Record new proc. */
338fbe53cacSkrw	movb	$SONPROC,P_STAT(%r12)	# p->p_stat = SONPROC
339fbe53cacSkrw	SET_CURPROC(%r12,%rcx)
34060854cb9Sguenther
341fd94711fSguenther	movl	CPUVAR(CPUID),%edi
342fd94711fSguenther
343fbe53cacSkrw	/* If old proc exited, don't bother. */
344fbe53cacSkrw	testq	%r13,%r13
345f5df1827Smickey	jz	switch_exited
346f5df1827Smickey
347fbe53cacSkrw	/*
348fbe53cacSkrw	 * Save old context.
349fbe53cacSkrw	 *
350fbe53cacSkrw	 * Registers:
351fbe53cacSkrw	 *   %rax, %rcx - scratch
352fbe53cacSkrw	 *   %r13 - old proc, then old pcb
353fbe53cacSkrw	 *   %r12 - new proc
354fd94711fSguenther	 *   %edi - cpuid
355fbe53cacSkrw	 */
356fbe53cacSkrw
357fbe53cacSkrw	movq	P_ADDR(%r13),%r13
358fbe53cacSkrw
359fd94711fSguenther	/* clear the old pmap's bit for the cpu */
360fd94711fSguenther	movq	PCB_PMAP(%r13),%rcx
361fd94711fSguenther	lock
362f5e1db71Sguenther	btrq	%rdi,PM_CPUS(%rcx)
363fd94711fSguenther
364f5df1827Smickey	/* Save stack pointers. */
365f5df1827Smickey	movq	%rsp,PCB_RSP(%r13)
366f5df1827Smickey	movq	%rbp,PCB_RBP(%r13)
367fbe53cacSkrw
368f5df1827Smickeyswitch_exited:
369b13138f2Sguenther	/* did old proc run in userspace?  then reset the segment regs */
370b13138f2Sguenther	btrl	$CPUF_USERSEGS_BIT, CPUVAR(FLAGS)
371b13138f2Sguenther	jnc	restore_saved
372b13138f2Sguenther
373b13138f2Sguenther	/* set %ds, %es, and %fs to expected value to prevent info leak */
374b13138f2Sguenther	movw	$(GSEL(GUDATA_SEL, SEL_UPL)),%ax
375b13138f2Sguenther	movw	%ax,%ds
376b13138f2Sguenther	movw	%ax,%es
377b13138f2Sguenther	movw	%ax,%fs
378b13138f2Sguenther
379b13138f2Sguentherrestore_saved:
380f5df1827Smickey	/*
38145053f4aSart	 * Restore saved context.
382f5df1827Smickey	 *
383f5df1827Smickey	 * Registers:
384f5df1827Smickey	 *   %rax, %rcx, %rdx - scratch
385f5df1827Smickey	 *   %r13 - new pcb
386fbe53cacSkrw	 *   %r12 - new process
387f5df1827Smickey	 */
388f5df1827Smickey
389fbe53cacSkrw	/* No interrupts while loading new state. */
390fbe53cacSkrw	cli
391fbe53cacSkrw	movq	P_ADDR(%r12),%r13
392fbe53cacSkrw
393f5df1827Smickey	/* Restore stack pointers. */
394f5df1827Smickey	movq	PCB_RSP(%r13),%rsp
395f5df1827Smickey	movq	PCB_RBP(%r13),%rbp
396f5df1827Smickey
397fd94711fSguenther	movq	CPUVAR(TSS),%rcx
398fd94711fSguenther	movq	PCB_KSTACK(%r13),%rdx
399fd94711fSguenther	movq	%rdx,TSS_RSP0(%rcx)
400fd94711fSguenther
401fd94711fSguenther	movq	PCB_CR3(%r13),%rax
402fd94711fSguenther	movq	%rax,%cr3
403fd94711fSguenther
404fbe53cacSkrw	/* Don't bother with the rest if switching to a system process. */
405fbe53cacSkrw	testl	$P_SYSTEM,P_FLAG(%r12)
406fbe53cacSkrw	jnz	switch_restored
407fd94711fSguenther
408fd94711fSguenther	/* set the new pmap's bit for the cpu */
409fd94711fSguenther	movl	CPUVAR(CPUID),%edi
410fd94711fSguenther	movq	PCB_PMAP(%r13),%rcx
411fd94711fSguenther	lock
412f5e1db71Sguenther	btsq	%rdi,PM_CPUS(%rcx)
413fd94711fSguenther#ifdef DIAGNOSTIC
414fd94711fSguenther	jc	_C_LABEL(switch_pmcpu_set)
415fbe53cacSkrw#endif
416f5df1827Smickey
417fbe53cacSkrwswitch_restored:
418f5df1827Smickey	/* Restore cr0 (including FPU state). */
419f5df1827Smickey	movl	PCB_CR0(%r13),%ecx
420f5df1827Smickey#ifdef MULTIPROCESSOR
421f5df1827Smickey	movq	PCB_FPCPU(%r13),%r8
422f5df1827Smickey	cmpq	CPUVAR(SELF),%r8
423f5df1827Smickey	jz	1f
424f5df1827Smickey	orl	$CR0_TS,%ecx
425f5df1827Smickey1:
426f5df1827Smickey#endif
427f5df1827Smickey	movq	%rcx,%cr0
428f5df1827Smickey
429fbe53cacSkrw	SET_CURPCB(%r13)
430fbe53cacSkrw
431f5df1827Smickey	/* Interrupts are okay again. */
432f5df1827Smickey	sti
433f5df1827Smickey
434fbe53cacSkrwswitch_return:
435fbe53cacSkrw
436f5df1827Smickey	popq	%r15
437f5df1827Smickey	popq	%r14
438f5df1827Smickey	popq	%r13
439f5df1827Smickey	popq	%r12
440f5df1827Smickey	popq	%rbp
441f5df1827Smickey	popq	%rbx
442f5df1827Smickey	ret
443f5df1827Smickey
44445053f4aSartENTRY(cpu_idle_enter)
4452692ace4Sjordan	movq	_C_LABEL(cpu_idle_enter_fcn),%rax
4462692ace4Sjordan	cmpq	$0,%rax
4472692ace4Sjordan	je	1f
4482692ace4Sjordan	jmpq	*%rax
4492692ace4Sjordan1:
45045053f4aSart	ret
451f5df1827Smickey
45245053f4aSartENTRY(cpu_idle_cycle)
4532692ace4Sjordan	movq	_C_LABEL(cpu_idle_cycle_fcn),%rax
4542692ace4Sjordan	cmpq	$0,%rax
4552692ace4Sjordan	je	1f
4562692ace4Sjordan	call	*%rax
4572692ace4Sjordan	ret
4582692ace4Sjordan1:
4592692ace4Sjordan	sti
46045053f4aSart	hlt
46145053f4aSart	ret
462f5df1827Smickey
46345053f4aSartENTRY(cpu_idle_leave)
4642692ace4Sjordan	movq	_C_LABEL(cpu_idle_leave_fcn),%rax
4652692ace4Sjordan	cmpq	$0,%rax
4662692ace4Sjordan	je	1f
4672692ace4Sjordan	jmpq	*%rax
4682692ace4Sjordan1:
46945053f4aSart	ret
470f5df1827Smickey
471da4ea94cSart	.globl	_C_LABEL(panic)
472da4ea94cSart
473da4ea94cSart#ifdef DIAGNOSTIC
474fd94711fSguentherNENTRY(switch_pmcpu_set)
47532d5845fSderaadt	movabsq	$switch_active,%rdi
476fd94711fSguenther	call	_C_LABEL(panic)
477fd94711fSguenther	/* NOTREACHED */
478f5df1827Smickey
47932d5845fSderaadt	.section .rodata
48032d5845fSderaadtswitch_active:
48132d5845fSderaadt	.asciz	"activate already active pmap"
48232d5845fSderaadt	.text
48332d5845fSderaadt#endif /* DIAGNOSTIC */
484f5df1827Smickey/*
485f5df1827Smickey * savectx(struct pcb *pcb);
486f5df1827Smickey * Update pcb, saving current processor state.
487f5df1827Smickey */
488f5df1827SmickeyENTRY(savectx)
489f5df1827Smickey	/* Save stack pointers. */
490f5df1827Smickey	movq	%rsp,PCB_RSP(%rdi)
491f5df1827Smickey	movq	%rbp,PCB_RBP(%rdi)
492f5df1827Smickey
493f5df1827Smickey	ret
494f5df1827Smickey
495f5df1827SmickeyIDTVEC(syscall32)
496f5df1827Smickey	sysret		/* go away please */
497f5df1827Smickey
498f5df1827Smickey/*
499f5df1827Smickey * syscall insn entry. This currently isn't much faster, but
500f5df1827Smickey * it can be made faster in the future.
501f5df1827Smickey */
502f5df1827SmickeyIDTVEC(syscall)
50374ebaa6aSguenther	/*
50474ebaa6aSguenther	 * Enter here with interrupts blocked; %rcx contains the caller's
50574ebaa6aSguenther	 * %rip and the original rflags has been copied to %r11.  %cs and
50674ebaa6aSguenther	 * %ss have been updated to the kernel segments, but %rsp is still
50774ebaa6aSguenther	 * the user-space value.
50874ebaa6aSguenther	 * First order of business is to swap to the kernel gs.base so that
50974ebaa6aSguenther	 * we can access our struct cpu_info and use the scratch space there
51074ebaa6aSguenther	 * to switch to our kernel stack.  Once that's in place we can
51174ebaa6aSguenther	 * unblock interrupts and save the rest of the syscall frame.
51274ebaa6aSguenther	 */
513f5df1827Smickey	swapgs
514f5df1827Smickey	movq	%r15,CPUVAR(SCRATCH)
515f5df1827Smickey	movq	CPUVAR(CURPCB),%r15
516fd94711fSguenther	movq	PCB_KSTACK(%r15),%r15
517f5df1827Smickey	xchgq	%r15,%rsp
518f5df1827Smickey	sti
519f5df1827Smickey
520f5df1827Smickey	/*
521f5df1827Smickey	 * XXX don't need this whole frame, split of the
522f5df1827Smickey	 * syscall frame and trapframe is needed.
523f5df1827Smickey	 * First, leave some room for the trapno, error,
524f5df1827Smickey	 * ss:rsp, etc, so that all GP registers can be
525f5df1827Smickey	 * saved. Then, fill in the rest.
526f5df1827Smickey	 */
5271f7e6433Sguenther	pushq	$(GSEL(GUDATA_SEL, SEL_UPL))
528f5df1827Smickey	pushq	%r15
529f5df1827Smickey	subq	$(TF_RSP-TF_TRAPNO),%rsp
530f5df1827Smickey	movq	CPUVAR(SCRATCH),%r15
531f5df1827Smickey	subq	$32,%rsp
532f5df1827Smickey	INTR_SAVE_GPRS
533f5df1827Smickey	movq	%r11, TF_RFLAGS(%rsp)	/* old rflags from syscall insn */
5341f7e6433Sguenther	movq	$(GSEL(GUCODE_SEL, SEL_UPL)), TF_CS(%rsp)
535f5df1827Smickey	movq	%rcx,TF_RIP(%rsp)
5366620a6fbSguenther	movq	$2,TF_ERR(%rsp)		/* ignored */
537f5df1827Smickey
538f5df1827Smickey	movq	CPUVAR(CURPROC),%r14
539f5df1827Smickey	movq	%rsp,P_MD_REGS(%r14)	# save pointer to frame
540f5df1827Smickey	andl	$~MDP_IRET,P_MD_FLAGS(%r14)
541b5b9857bSart	movq	%rsp,%rdi
5424e1a77ceSsturm	call	_C_LABEL(syscall)
543c9ad316fSguenther
544c9ad316fSguenther.Lsyscall_check_asts:
545c9ad316fSguenther	/* Check for ASTs on exit to user mode. */
546f5df1827Smickey	cli
547f5df1827Smickey	CHECK_ASTPENDING(%r11)
548f5df1827Smickey	je	2f
549f5df1827Smickey	CLEAR_ASTPENDING(%r11)
550f5df1827Smickey	sti
551b5b9857bSart	movq	%rsp,%rdi
552c9ad316fSguenther	call	_C_LABEL(ast)
553c9ad316fSguenther	jmp	.Lsyscall_check_asts
554c9ad316fSguenther
555f5df1827Smickey2:
556f5df1827Smickey#ifdef DIAGNOSTIC
557b5b9857bSart	cmpl	$IPL_NONE,CPUVAR(ILEVEL)
558c9ad316fSguenther	jne	.Lsyscall_spl_not_lowered
5591396572dSguenther#endif /* DIAGNOSTIC */
5601396572dSguenther
561c9ad316fSguenther	/* Could registers have been changed that require an iretq? */
562c9ad316fSguenther	testl	$MDP_IRET, P_MD_FLAGS(%r14)
563c9ad316fSguenther	jne	intr_fast_exit
564c9ad316fSguenther
5651396572dSguenther	movq	TF_RDI(%rsp),%rdi
5661396572dSguenther	movq	TF_RSI(%rsp),%rsi
5671396572dSguenther	movq	TF_R8(%rsp),%r8
5681396572dSguenther	movq	TF_R9(%rsp),%r9
5691396572dSguenther	movq	TF_R10(%rsp),%r10
5701396572dSguenther	movq	TF_R12(%rsp),%r12
5711396572dSguenther	movq	TF_R13(%rsp),%r13
5721396572dSguenther	movq	TF_R14(%rsp),%r14
5731396572dSguenther	movq	TF_R15(%rsp),%r15
5741396572dSguenther	movq	TF_RBP(%rsp),%rbp
5751396572dSguenther	movq	TF_RBX(%rsp),%rbx
5761396572dSguenther
577f1665d79Sguenther	INTR_RESTORE_SELECTORS
5781396572dSguenther
5791396572dSguenther	movq	TF_RDX(%rsp),%rdx
5801396572dSguenther	movq	TF_RAX(%rsp),%rax
5811396572dSguenther
5821396572dSguenther	movq	TF_RIP(%rsp),%rcx
5831396572dSguenther	movq	TF_RFLAGS(%rsp),%r11
5841396572dSguenther	movq	TF_RSP(%rsp),%rsp
585f5df1827Smickey	sysretq
586f5df1827Smickey
587f5df1827Smickey#ifdef DIAGNOSTIC
588c9ad316fSguenther.Lsyscall_spl_not_lowered:
58932d5845fSderaadt	movabsq	$spl_lowered, %rdi
590f5df1827Smickey	movl	TF_RAX(%rsp),%esi
591f5df1827Smickey	movl	TF_RDI(%rsp),%edx
592f5df1827Smickey	movl	%ebx,%ecx
593b5b9857bSart	movl	CPUVAR(ILEVEL),%r8d
594f5df1827Smickey	xorq	%rax,%rax
595f5df1827Smickey	call	_C_LABEL(printf)
596f5df1827Smickey#ifdef DDB
597f5df1827Smickey	int	$3
598f5df1827Smickey#endif /* DDB */
599f5df1827Smickey	movl	$IPL_NONE,CPUVAR(ILEVEL)
600c9ad316fSguenther	jmp	.Lsyscall_check_asts
601f5df1827Smickey
60232d5845fSderaadt	.section .rodata
60332d5845fSderaadtspl_lowered:
60432d5845fSderaadt	.asciz	"WARNING: SPL NOT LOWERED ON SYSCALL %d %d EXIT %x %x\n"
60532d5845fSderaadt	.text
60632d5845fSderaadt#endif
607f5df1827Smickey
608f5df1827SmickeyNENTRY(proc_trampoline)
609f5df1827Smickey#ifdef MULTIPROCESSOR
610f5df1827Smickey	call	_C_LABEL(proc_trampoline_mp)
611f5df1827Smickey#endif
612f5df1827Smickey	movl	$IPL_NONE,CPUVAR(ILEVEL)
613f5df1827Smickey	movq	%r13,%rdi
614f5df1827Smickey	call	*%r12
615c9ad316fSguenther	movq	CPUVAR(CURPROC),%r14
616c9ad316fSguenther	jmp	.Lsyscall_check_asts
617f5df1827Smickey
618f5df1827Smickey
619f5df1827Smickey/*
6201396572dSguenther * Return via iretq, for real interrupts and signal returns
6211396572dSguenther */
622c9ad316fSguentherNENTRY(intr_fast_exit)
6231396572dSguenther	movq	TF_RDI(%rsp),%rdi
6241396572dSguenther	movq	TF_RSI(%rsp),%rsi
6251396572dSguenther	movq	TF_R8(%rsp),%r8
6261396572dSguenther	movq	TF_R9(%rsp),%r9
6271396572dSguenther	movq	TF_R10(%rsp),%r10
6281396572dSguenther	movq	TF_R12(%rsp),%r12
6291396572dSguenther	movq	TF_R13(%rsp),%r13
6301396572dSguenther	movq	TF_R14(%rsp),%r14
6311396572dSguenther	movq	TF_R15(%rsp),%r15
6321396572dSguenther	movq	TF_RBP(%rsp),%rbp
6331396572dSguenther	movq	TF_RBX(%rsp),%rbx
6341396572dSguenther
63592f33f2bSguenther	testq	$SEL_RPL,TF_CS(%rsp)
636c6853312Sguenther	je	5f
6371396572dSguenther
638f1665d79Sguenther	INTR_RESTORE_SELECTORS
6391396572dSguenther
6401396572dSguenther5:	movq	TF_RDX(%rsp),%rdx
6411396572dSguenther	movq	TF_RCX(%rsp),%rcx
6421396572dSguenther	movq	TF_R11(%rsp),%r11
6431396572dSguenther	movq	TF_RAX(%rsp),%rax
6446950c8e2Smpi
6456950c8e2Smpi#if !defined(GPROF) && defined(DDBPROF)
6466950c8e2Smpi	/*
6476950c8e2Smpi	 * If we are returning from a probe trap we need to fix the
6486950c8e2Smpi	 * stack layout and emulate the patched instruction.
6496950c8e2Smpi	 *
6506950c8e2Smpi	 * The code below does that by trashing %rax, so it MUST be
6516950c8e2Smpi	 * restored afterward.
6526950c8e2Smpi	 */
6536950c8e2Smpi	cmpl	$INTR_FAKE_TRAP, TF_ERR(%rsp)
6546950c8e2Smpi	je	.Lprobe_fixup
6556950c8e2Smpi#endif /* !defined(GPROF) && defined(DDBPROF) */
6566950c8e2Smpi
6571396572dSguenther	addq	$TF_RIP,%rsp
6581396572dSguenther
659c6853312Sguenther	.globl	_C_LABEL(doreti_iret)
660c6853312Sguenther_C_LABEL(doreti_iret):
661c6853312Sguenther	iretq
662c6853312Sguenther
6633a36161cSart
6646950c8e2Smpi#if !defined(GPROF) && defined(DDBPROF)
6656950c8e2Smpi.Lprobe_fixup:
6666950c8e2Smpi	/* Reserve enough room to emulate "pushq %rbp". */
6676950c8e2Smpi	subq	$16, %rsp
6686950c8e2Smpi
6696950c8e2Smpi	/* Shift hardware-saved registers. */
6706950c8e2Smpi	movq	(TF_RIP + 16)(%rsp), %rax
6716950c8e2Smpi	movq	%rax, TF_RIP(%rsp)
6726950c8e2Smpi	movq	(TF_CS + 16)(%rsp), %rax
6736950c8e2Smpi	movq	%rax, TF_CS(%rsp)
6746950c8e2Smpi	movq	(TF_RFLAGS + 16)(%rsp), %rax
6756950c8e2Smpi	movq	%rax, TF_RFLAGS(%rsp)
6766950c8e2Smpi	movq	(TF_RSP + 16)(%rsp), %rax
6776950c8e2Smpi	movq	%rax, TF_RSP(%rsp)
6786950c8e2Smpi	movq	(TF_SS + 16)(%rsp), %rax
6796950c8e2Smpi	movq	%rax, TF_SS(%rsp)
6806950c8e2Smpi
6812f2c18a3Smpi	/* Pull 8 bytes off the stack and store %rbp in the expected location.*/
6826950c8e2Smpi	movq	TF_RSP(%rsp), %rax
6836950c8e2Smpi	subq	$8, %rax
6846950c8e2Smpi	movq	%rax, TF_RSP(%rsp)
6856950c8e2Smpi	movq	%rbp, (%rax)
6866950c8e2Smpi
6876950c8e2Smpi	/* Write back overwritten %rax */
6886950c8e2Smpi	movq	(TF_RAX + 16)(%rsp),%rax
6896950c8e2Smpi
6906950c8e2Smpi	addq	$TF_RIP,%rsp
6916950c8e2Smpi	iretq
6926950c8e2Smpi#endif /* !defined(GPROF) && defined(DDBPROF) */
6936950c8e2Smpi
6943a36161cSartENTRY(pagezero)
6953a36161cSart	movq    $-PAGE_SIZE,%rdx
6963a36161cSart	subq    %rdx,%rdi
6973a36161cSart	xorq    %rax,%rax
6983a36161cSart1:
6993a36161cSart	movnti  %rax,(%rdi,%rdx)
7003a36161cSart	movnti  %rax,8(%rdi,%rdx)
7013a36161cSart	movnti  %rax,16(%rdi,%rdx)
7023a36161cSart	movnti  %rax,24(%rdi,%rdx)
7033a36161cSart	addq    $32,%rdx
7043a36161cSart	jne     1b
7053a36161cSart	sfence
7063a36161cSart	ret
7073c8478a6Sgwk
708d8213a49Smikeb#if NXEN > 0
709d8213a49Smikeb	/* Hypercall page needs to be page aligned */
710d8213a49Smikeb	.text
7110175496dSderaadt	.align	NBPG, 0xcc
712d8213a49Smikeb	.globl	_C_LABEL(xen_hypercall_page)
713d8213a49Smikeb_C_LABEL(xen_hypercall_page):
7140175496dSderaadt	.skip	0x1000, 0xcc
715d8213a49Smikeb#endif /* NXEN > 0 */
716218ead0bSmikeb
717218ead0bSmikeb#if NHYPERV > 0
718218ead0bSmikeb	/* Hypercall page needs to be page aligned */
719218ead0bSmikeb	.text
720218ead0bSmikeb	.align	NBPG, 0xcc
721218ead0bSmikeb	.globl	_C_LABEL(hv_hypercall_page)
722218ead0bSmikeb_C_LABEL(hv_hypercall_page):
723218ead0bSmikeb	.skip	0x1000, 0xcc
724218ead0bSmikeb#endif /* NXEN > 0 */
725