xref: /titanic_50/usr/src/uts/i86xpv/ml/hyperevent.s (revision 843e19887f64dde75055cf8842fc4db2171eff45)
1*843e1988Sjohnlev/*
2*843e1988Sjohnlev * CDDL HEADER START
3*843e1988Sjohnlev *
4*843e1988Sjohnlev * The contents of this file are subject to the terms of the
5*843e1988Sjohnlev * Common Development and Distribution License (the "License").
6*843e1988Sjohnlev * You may not use this file except in compliance with the License.
7*843e1988Sjohnlev *
8*843e1988Sjohnlev * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*843e1988Sjohnlev * or http://www.opensolaris.org/os/licensing.
10*843e1988Sjohnlev * See the License for the specific language governing permissions
11*843e1988Sjohnlev * and limitations under the License.
12*843e1988Sjohnlev *
13*843e1988Sjohnlev * When distributing Covered Code, include this CDDL HEADER in each
14*843e1988Sjohnlev * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*843e1988Sjohnlev * If applicable, add the following below this CDDL HEADER, with the
16*843e1988Sjohnlev * fields enclosed by brackets "[]" replaced with your own identifying
17*843e1988Sjohnlev * information: Portions Copyright [yyyy] [name of copyright owner]
18*843e1988Sjohnlev *
19*843e1988Sjohnlev * CDDL HEADER END
20*843e1988Sjohnlev */
21*843e1988Sjohnlev
22*843e1988Sjohnlev/*
23*843e1988Sjohnlev * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24*843e1988Sjohnlev * Use is subject to license terms.
25*843e1988Sjohnlev */
26*843e1988Sjohnlev
27*843e1988Sjohnlev#pragma	ident	"%Z%%M%	%I%	%E% SMI"
28*843e1988Sjohnlev
29*843e1988Sjohnlev#include <sys/asm_linkage.h>
30*843e1988Sjohnlev#include <sys/hypervisor.h>
31*843e1988Sjohnlev#include <sys/privregs.h>
32*843e1988Sjohnlev#include <sys/segments.h>
33*843e1988Sjohnlev#include <sys/traptrace.h>
34*843e1988Sjohnlev#include <sys/trap.h>
35*843e1988Sjohnlev#include <sys/psw.h>
36*843e1988Sjohnlev#include <sys/x86_archext.h>
37*843e1988Sjohnlev#include <sys/asm_misc.h>
38*843e1988Sjohnlev
39*843e1988Sjohnlev#if !defined(__lint)
40*843e1988Sjohnlev#include "assym.h"
41*843e1988Sjohnlev#endif
42*843e1988Sjohnlev
43*843e1988Sjohnlev#if defined(__lint)
44*843e1988Sjohnlev
45*843e1988Sjohnlevvoid
46*843e1988Sjohnlevxen_failsafe_callback(void)
47*843e1988Sjohnlev{}
48*843e1988Sjohnlev
49*843e1988Sjohnlevvoid
50*843e1988Sjohnlevxen_callback(void)
51*843e1988Sjohnlev{}
52*843e1988Sjohnlev
53*843e1988Sjohnlev#else	/* __lint */
54*843e1988Sjohnlev
55*843e1988Sjohnlev	/*
56*843e1988Sjohnlev	 * The stack frame for events is exactly that of an x86 hardware
57*843e1988Sjohnlev	 * interrupt.
58*843e1988Sjohnlev	 *
59*843e1988Sjohnlev	 * The stack frame for a failsafe callback is augmented with saved
60*843e1988Sjohnlev	 * values for segment registers:
61*843e1988Sjohnlev	 *
62*843e1988Sjohnlev	 * i386
63*843e1988Sjohnlev	 *	%ds, %es, %fs, %gs, %eip, %cs, %eflags [, %oldesp, %oldss ]
64*843e1988Sjohnlev	 *
65*843e1988Sjohnlev	 * On amd64 the stack frame for events is exactly that of an hardware
66*843e1988Sjohnlev	 * interrupt with the addition of rcx and r11.
67*843e1988Sjohnlev	 *
68*843e1988Sjohnlev	 * The stack frame for a failsafe callback is augmented with saved
69*843e1988Sjohnlev	 * values for segment registers:
70*843e1988Sjohnlev	 *
71*843e1988Sjohnlev	 * amd64
72*843e1988Sjohnlev	 *	%rcx, %r11, %ds, %es, %fs, %gs, %rip, %cs, %rflags,
73*843e1988Sjohnlev	 *      [, %oldrsp, %oldss ]
74*843e1988Sjohnlev	 *
75*843e1988Sjohnlev	 * The hypervisor  does this to allow the guest OS to handle returns
76*843e1988Sjohnlev	 * to processes which have bad segment registers.
77*843e1988Sjohnlev	 *
78*843e1988Sjohnlev	 * [See comments in xen/arch/x86/[x86_64,x86_32]/entry.S]
79*843e1988Sjohnlev	 *
80*843e1988Sjohnlev	 * We will construct a fully fledged 'struct regs' and call trap
81*843e1988Sjohnlev	 * with a #gp fault.
82*843e1988Sjohnlev	 */
83*843e1988Sjohnlev
84*843e1988Sjohnlev#if defined(__amd64)
85*843e1988Sjohnlev
86*843e1988Sjohnlev	ENTRY(xen_failsafe_callback)
87*843e1988Sjohnlev
88*843e1988Sjohnlev	/*
89*843e1988Sjohnlev	 * The saved values of rcx and r11 are on the top of the stack.
90*843e1988Sjohnlev	 * pop them and let INTR_PUSH save them. We drop ds, es, fs and
91*843e1988Sjohnlev	 * gs since the hypervisor will have already loaded these for us.
92*843e1988Sjohnlev	 * If any were bad and faulted the hypervisor would have loaded
93*843e1988Sjohnlev	 * them with the null selctor.
94*843e1988Sjohnlev	 */
95*843e1988Sjohnlev	XPV_TRAP_POP	/* rcx, r11 */
96*843e1988Sjohnlev
97*843e1988Sjohnlev	/*
98*843e1988Sjohnlev	 * XXPV
99*843e1988Sjohnlev	 * If the current segregs are provided for us on the stack by
100*843e1988Sjohnlev	 * the hypervisor then we should simply move them into their proper
101*843e1988Sjohnlev	 * location in the regs struct?
102*843e1988Sjohnlev	 */
103*843e1988Sjohnlev	addq    $_CONST(_MUL(4, CLONGSIZE)), %rsp
104*843e1988Sjohnlev
105*843e1988Sjohnlev	/*
106*843e1988Sjohnlev	 * XXPV
107*843e1988Sjohnlev	 * It would be nice to somehow figure out which selector caused
108*843e1988Sjohnlev	 * #gp fault.
109*843e1988Sjohnlev	 */
110*843e1988Sjohnlev
111*843e1988Sjohnlev	pushq	$0	/* dummy error */
112*843e1988Sjohnlev	pushq	$T_GPFLT
113*843e1988Sjohnlev
114*843e1988Sjohnlev	INTR_PUSH
115*843e1988Sjohnlev	INTGATE_INIT_KERNEL_FLAGS
116*843e1988Sjohnlev
117*843e1988Sjohnlev	/*
118*843e1988Sjohnlev	 * We're here because HYPERVISOR_IRET to userland failed due to a
119*843e1988Sjohnlev	 * bad %cs value. Rewrite %cs, %ss and %rip on the stack so trap
120*843e1988Sjohnlev	 * will know to handle this with kern_gpfault and kill the currently
121*843e1988Sjohnlev	 * running process.
122*843e1988Sjohnlev	 */
123*843e1988Sjohnlev	movq	$KCS_SEL, REGOFF_CS(%rsp)
124*843e1988Sjohnlev	movq	$KDS_SEL, REGOFF_SS(%rsp)
125*843e1988Sjohnlev	leaq	nopop_sys_rtt_syscall(%rip), %rdi
126*843e1988Sjohnlev	movq	%rdi, REGOFF_RIP(%rsp)
127*843e1988Sjohnlev
128*843e1988Sjohnlev	TRACE_PTR(%rdi, %rbx, %ebx, %rcx, $TT_EVENT) /* Uses labels 8 and 9 */
129*843e1988Sjohnlev	TRACE_REGS(%rdi, %rsp, %rbx, %rcx)	/* Uses label 9 */
130*843e1988Sjohnlev	TRACE_STAMP(%rdi)		/* Clobbers %eax, %edx, uses 9 */
131*843e1988Sjohnlev
132*843e1988Sjohnlev	movq	%rsp, %rbp
133*843e1988Sjohnlev
134*843e1988Sjohnlev	TRACE_STACK(%rdi)
135*843e1988Sjohnlev
136*843e1988Sjohnlev	movq	%rbp, %rdi
137*843e1988Sjohnlev
138*843e1988Sjohnlev	ENABLE_INTR_FLAGS
139*843e1988Sjohnlev
140*843e1988Sjohnlev	movq	%rbp, %rdi
141*843e1988Sjohnlev	xorl	%esi, %esi
142*843e1988Sjohnlev	movl	%gs:CPU_ID, %edx
143*843e1988Sjohnlev	call	trap		/* trap(rp, addr, cpuid) handles all trap */
144*843e1988Sjohnlev	jmp	_sys_rtt
145*843e1988Sjohnlev	SET_SIZE(xen_failsafe_callback)
146*843e1988Sjohnlev
147*843e1988Sjohnlev#elif defined(__i386)
148*843e1988Sjohnlev
149*843e1988Sjohnlev	ENTRY(xen_failsafe_callback)
150*843e1988Sjohnlev
151*843e1988Sjohnlev	/*
152*843e1988Sjohnlev	 * drop ds, es, fs and gs
153*843e1988Sjohnlev	 */
154*843e1988Sjohnlev	addl    $_CONST(_MUL(4, CLONGSIZE)), %esp /* see comment for 64-bit */
155*843e1988Sjohnlev
156*843e1988Sjohnlev	pushl	$0	/* dummy error (see comment for 64-bit) */
157*843e1988Sjohnlev	pushl	$T_GPFLT
158*843e1988Sjohnlev
159*843e1988Sjohnlev	INTR_PUSH
160*843e1988Sjohnlev	INTGATE_INIT_KERNEL_FLAGS	/* (set kernel flag values) */
161*843e1988Sjohnlev
162*843e1988Sjohnlev	/*
163*843e1988Sjohnlev	 * The fact were here is because HYPERVISOR_IRET to userland
164*843e1988Sjohnlev	 * failed due to a bad %cs value. Rewrite %cs, %ss and %eip
165*843e1988Sjohnlev	 * on the stack so trap will know to handle this with
166*843e1988Sjohnlev	 * kern_gpfault and kill the currently running process.
167*843e1988Sjohnlev	 */
168*843e1988Sjohnlev	movl	$KCS_SEL, REGOFF_CS(%esp)
169*843e1988Sjohnlev	movl	$KDS_SEL, REGOFF_SS(%esp)
170*843e1988Sjohnlev	leal	nopop_sys_rtt_syscall, %edi
171*843e1988Sjohnlev	movl	%edi, REGOFF_EIP(%esp)
172*843e1988Sjohnlev
173*843e1988Sjohnlev	TRACE_PTR(%edi, %ebx, %ebx, %ecx, $TT_EVENT) /* Uses labels 8 and 9 */
174*843e1988Sjohnlev	TRACE_REGS(%edi, %esp, %ebx, %ecx)	/* Uses label 9 */
175*843e1988Sjohnlev	TRACE_STAMP(%edi)		/* Clobbers %eax, %edx, uses 9 */
176*843e1988Sjohnlev
177*843e1988Sjohnlev	movl	%esp, %ebp
178*843e1988Sjohnlev
179*843e1988Sjohnlev	TRACE_STACK(%edi)
180*843e1988Sjohnlev
181*843e1988Sjohnlev	ENABLE_INTR_FLAGS
182*843e1988Sjohnlev
183*843e1988Sjohnlev	pushl	%gs:CPU_ID
184*843e1988Sjohnlev	pushl	$0
185*843e1988Sjohnlev	pushl	%ebp
186*843e1988Sjohnlev	call	trap		/* trap(rp, addr, cpuid) handles all traps */
187*843e1988Sjohnlev	addl	$12, %esp
188*843e1988Sjohnlev	jmp	_sys_rtt
189*843e1988Sjohnlev	SET_SIZE(xen_failsafe_callback)
190*843e1988Sjohnlev
191*843e1988Sjohnlev#endif	/* __i386 */
192*843e1988Sjohnlev
193*843e1988Sjohnlev#if defined(__amd64)
194*843e1988Sjohnlev
195*843e1988Sjohnlev	ENTRY(xen_callback)
196*843e1988Sjohnlev	XPV_TRAP_POP
197*843e1988Sjohnlev
198*843e1988Sjohnlev	pushq	$0			/* dummy error */
199*843e1988Sjohnlev	pushq	$T_AST
200*843e1988Sjohnlev
201*843e1988Sjohnlev	INTR_PUSH
202*843e1988Sjohnlev	INTGATE_INIT_KERNEL_FLAGS	/* (set kernel flag values) */
203*843e1988Sjohnlev
204*843e1988Sjohnlev	TRACE_PTR(%rdi, %rbx, %ebx, %rcx, $TT_EVENT) /* Uses labels 8 and 9 */
205*843e1988Sjohnlev	TRACE_REGS(%rdi, %rsp, %rbx, %rcx)	/* Uses label 9 */
206*843e1988Sjohnlev	TRACE_STAMP(%rdi)		/* Clobbers %eax, %edx, uses 9 */
207*843e1988Sjohnlev
208*843e1988Sjohnlev	movq	%rsp, %rbp
209*843e1988Sjohnlev
210*843e1988Sjohnlev	TRACE_STACK(%rdi)
211*843e1988Sjohnlev
212*843e1988Sjohnlev	movq	%rdi, %rsi		/* rsi = trap trace recode pointer */
213*843e1988Sjohnlev	movq	%rbp, %rdi		/* rdi = struct regs pointer */
214*843e1988Sjohnlev	call	xen_callback_handler
215*843e1988Sjohnlev
216*843e1988Sjohnlev	jmp	_sys_rtt_ints_disabled
217*843e1988Sjohnlev	/*NOTREACHED*/
218*843e1988Sjohnlev
219*843e1988Sjohnlev	SET_SIZE(xen_callback)
220*843e1988Sjohnlev
221*843e1988Sjohnlev#elif defined(__i386)
222*843e1988Sjohnlev
223*843e1988Sjohnlev	ENTRY(xen_callback)
224*843e1988Sjohnlev	pushl	$0			/* dummy error */
225*843e1988Sjohnlev	pushl	$T_AST
226*843e1988Sjohnlev
227*843e1988Sjohnlev	INTR_PUSH
228*843e1988Sjohnlev	INTGATE_INIT_KERNEL_FLAGS	/* (set kernel flag values) */
229*843e1988Sjohnlev
230*843e1988Sjohnlev	TRACE_PTR(%edi, %ebx, %ebx, %ecx, $TT_EVENT) /* Uses labels 8 and 9 */
231*843e1988Sjohnlev	TRACE_REGS(%edi, %esp, %ebx, %ecx)	/* Uses label 9 */
232*843e1988Sjohnlev	TRACE_STAMP(%edi)		/* Clobbers %eax, %edx, uses 9 */
233*843e1988Sjohnlev
234*843e1988Sjohnlev	movl	%esp, %ebp
235*843e1988Sjohnlev
236*843e1988Sjohnlev	TRACE_STACK(%edi)
237*843e1988Sjohnlev
238*843e1988Sjohnlev	pushl	%edi			/* pass trap trace record pointer */
239*843e1988Sjohnlev	pushl	%ebp			/* pass struct regs pointer */
240*843e1988Sjohnlev	call	xen_callback_handler
241*843e1988Sjohnlev	addl	$8, %esp
242*843e1988Sjohnlev
243*843e1988Sjohnlev	jmp	_sys_rtt_ints_disabled
244*843e1988Sjohnlev	/*NOTREACHED*/
245*843e1988Sjohnlev
246*843e1988Sjohnlev	SET_SIZE(xen_callback)
247*843e1988Sjohnlev
248*843e1988Sjohnlev#endif	/* __i386 */
249*843e1988Sjohnlev#endif	/* __lint */
250