xref: /illumos-gate/usr/src/uts/i86xpv/ml/hyperevent.S (revision 4283d10e18fc3904736c7c067fb29de9bb67d25d)
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#include <sys/asm_linkage.h>
28#include <sys/hypervisor.h>
29#include <sys/privregs.h>
30#include <sys/segments.h>
31#include <sys/traptrace.h>
32#include <sys/trap.h>
33#include <sys/psw.h>
34#include <sys/x86_archext.h>
35#include <sys/asm_misc.h>
36
37#include "assym.h"
38
39	/*
40	 * The stack frame for events is exactly that of an x86 hardware
41	 * interrupt.
42	 *
43	 * The stack frame for a failsafe callback is augmented with saved
44	 * values for segment registers:
45	 *
46	 * i386
47	 *	%ds, %es, %fs, %gs, %eip, %cs, %eflags [, %oldesp, %oldss ]
48	 *
49	 * On amd64 the stack frame for events is exactly that of an hardware
50	 * interrupt with the addition of rcx and r11.
51	 *
52	 * The stack frame for a failsafe callback is augmented with saved
53	 * values for segment registers:
54	 *
55	 * amd64
56	 *	%rcx, %r11, %ds, %es, %fs, %gs, %rip, %cs, %rflags,
57	 *      [, %oldrsp, %oldss ]
58	 *
59	 * The hypervisor  does this to allow the guest OS to handle returns
60	 * to processes which have bad segment registers.
61	 *
62	 * [See comments in xen/arch/x86/[x86_64,x86_32]/entry.S]
63	 *
64	 * We will construct a fully fledged 'struct regs' and call trap
65	 * with a #gp fault.
66	 */
67
68	ENTRY(xen_failsafe_callback)
69
70	/*
71	 * The saved values of rcx and r11 are on the top of the stack.
72	 * pop them and let INTR_PUSH save them. We drop ds, es, fs and
73	 * gs since the hypervisor will have already loaded these for us.
74	 * If any were bad and faulted the hypervisor would have loaded
75	 * them with the null selctor.
76	 */
77	XPV_TRAP_POP	/* rcx, r11 */
78
79	/*
80	 * XXPV
81	 * If the current segregs are provided for us on the stack by
82	 * the hypervisor then we should simply move them into their proper
83	 * location in the regs struct?
84	 */
85	addq    $_CONST(_MUL(4, CLONGSIZE)), %rsp
86
87	/*
88	 * XXPV
89	 * It would be nice to somehow figure out which selector caused
90	 * #gp fault.
91	 */
92
93	pushq	$0	/* dummy error */
94	pushq	$T_GPFLT
95
96	INTR_PUSH
97	INTGATE_INIT_KERNEL_FLAGS
98
99	/*
100	 * We're here because HYPERVISOR_IRET to userland failed due to a
101	 * bad %cs value. Rewrite %cs, %ss and %rip on the stack so trap
102	 * will know to handle this with kern_gpfault and kill the currently
103	 * running process.
104	 */
105	movq	$KCS_SEL, REGOFF_CS(%rsp)
106	movq	$KDS_SEL, REGOFF_SS(%rsp)
107	leaq	nopop_sys_rtt_syscall(%rip), %rdi
108	movq	%rdi, REGOFF_RIP(%rsp)
109
110	TRACE_PTR(%rdi, %rbx, %ebx, %rcx, $TT_EVENT) /* Uses labels 8 and 9 */
111	TRACE_REGS(%rdi, %rsp, %rbx, %rcx)	/* Uses label 9 */
112	TRACE_STAMP(%rdi)		/* Clobbers %eax, %edx, uses 9 */
113
114	movq	%rsp, %rbp
115
116	TRACE_STACK(%rdi)
117
118	movq	%rbp, %rdi
119
120	ENABLE_INTR_FLAGS
121
122	movq	%rbp, %rdi
123	xorl	%esi, %esi
124	movl	%gs:CPU_ID, %edx
125	call	trap		/* trap(rp, addr, cpuid) handles all trap */
126	jmp	_sys_rtt
127	SET_SIZE(xen_failsafe_callback)
128
129	ENTRY(xen_callback)
130	XPV_TRAP_POP
131
132	pushq	$0			/* dummy error */
133	pushq	$T_AST
134
135	INTR_PUSH
136	INTGATE_INIT_KERNEL_FLAGS	/* (set kernel flag values) */
137
138	TRACE_PTR(%rdi, %rbx, %ebx, %rcx, $TT_EVENT) /* Uses labels 8 and 9 */
139	TRACE_REGS(%rdi, %rsp, %rbx, %rcx)	/* Uses label 9 */
140	TRACE_STAMP(%rdi)		/* Clobbers %eax, %edx, uses 9 */
141
142	movq	%rsp, %rbp
143
144	TRACE_STACK(%rdi)
145
146	movq	%rdi, %rsi		/* rsi = trap trace recode pointer */
147	movq	%rbp, %rdi		/* rdi = struct regs pointer */
148	call	xen_callback_handler
149
150	jmp	_sys_rtt_ints_disabled
151	/*NOTREACHED*/
152
153	SET_SIZE(xen_callback)
154