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