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#include <sys/panic.h> 39*843e1988Sjohnlev 40*843e1988Sjohnlev#if !defined(__lint) 41*843e1988Sjohnlev#include "assym.h" 42*843e1988Sjohnlev#endif 43*843e1988Sjohnlev 44*843e1988Sjohnlev#if defined(__lint) 45*843e1988Sjohnlev 46*843e1988Sjohnlevvoid 47*843e1988Sjohnlevxpv_panic_callback(void) 48*843e1988Sjohnlev{} 49*843e1988Sjohnlev 50*843e1988Sjohnlev/* ARGSUSED */ 51*843e1988Sjohnlevvoid 52*843e1988Sjohnlevxpv_panic_setcr3(ulong_t cr3) 53*843e1988Sjohnlev{} 54*843e1988Sjohnlev 55*843e1988Sjohnlevvoid 56*843e1988Sjohnlevxpv_panic_reload_cr3(void) 57*843e1988Sjohnlev{} 58*843e1988Sjohnlev 59*843e1988Sjohnlevvoid 60*843e1988Sjohnlevxpv_resetgs(void) 61*843e1988Sjohnlev{} 62*843e1988Sjohnlev 63*843e1988Sjohnlev#else /* __lint */ 64*843e1988Sjohnlev 65*843e1988Sjohnlev#if defined(__amd64) 66*843e1988Sjohnlev ENTRY_NP(xpv_panic_getcr3) 67*843e1988Sjohnlev movq %cr3, %rax 68*843e1988Sjohnlev ret 69*843e1988Sjohnlev SET_SIZE(xpv_panic_getcr3) 70*843e1988Sjohnlev 71*843e1988Sjohnlev ENTRY_NP(xpv_panic_setcr3) 72*843e1988Sjohnlev movq %rdi, %cr3 73*843e1988Sjohnlev ret 74*843e1988Sjohnlev SET_SIZE(xpv_panic_setcr3) 75*843e1988Sjohnlev 76*843e1988Sjohnlev ENTRY(xpv_panic_reload_cr3) 77*843e1988Sjohnlev movq %cr3, %rdi 78*843e1988Sjohnlev movq %rdi, %cr3 79*843e1988Sjohnlev ret 80*843e1988Sjohnlev SET_SIZE(xpv_panic_reload_cr3) 81*843e1988Sjohnlev 82*843e1988Sjohnlev ENTRY_NP(xpv_panic_prep) 83*843e1988Sjohnlev pushq %rbp 84*843e1988Sjohnlev movq %rsp, %rbp 85*843e1988Sjohnlev 86*843e1988Sjohnlev subq $REGSIZE, %rsp 87*843e1988Sjohnlev movq %rax, REGOFF_RAX(%rsp) 88*843e1988Sjohnlev movq %rbx, REGOFF_RBX(%rsp) 89*843e1988Sjohnlev movq %rsp, %rax 90*843e1988Sjohnlev addq $REGSIZE, %rax 91*843e1988Sjohnlev movq (%rax), %rbx 92*843e1988Sjohnlev movq %rbx, REGOFF_RBP(%rsp) 93*843e1988Sjohnlev movq 8(%rax), %rbx 94*843e1988Sjohnlev movq %rbx, REGOFF_TRAPNO(%rsp) 95*843e1988Sjohnlev movq 16(%rax), %rbx 96*843e1988Sjohnlev movq %rbx, REGOFF_ERR(%rsp) 97*843e1988Sjohnlev movq 24(%rax), %rbx 98*843e1988Sjohnlev movq %rbx, REGOFF_RIP(%rsp) 99*843e1988Sjohnlev movq 32(%rax), %rbx 100*843e1988Sjohnlev movq %rbx, REGOFF_CS(%rsp) 101*843e1988Sjohnlev movq 40(%rax), %rbx 102*843e1988Sjohnlev movq %rbx, REGOFF_RFL(%rsp) 103*843e1988Sjohnlev addq $56, %rax 104*843e1988Sjohnlev movq %rax, REGOFF_RSP(%rsp) 105*843e1988Sjohnlev xorl %eax, %eax 106*843e1988Sjohnlev movw %gs, %ax 107*843e1988Sjohnlev mov %rax, REGOFF_GS(%rsp) 108*843e1988Sjohnlev movw %fs, %ax 109*843e1988Sjohnlev mov %rax, REGOFF_FS(%rsp) 110*843e1988Sjohnlev movw %es, %ax 111*843e1988Sjohnlev mov %rax, REGOFF_ES(%rsp) 112*843e1988Sjohnlev movw %ds, %ax 113*843e1988Sjohnlev mov %rax, REGOFF_DS(%rsp) 114*843e1988Sjohnlev movw %ss, %ax 115*843e1988Sjohnlev mov %rax, REGOFF_SS(%rsp) 116*843e1988Sjohnlev movq %rcx, REGOFF_RCX(%rsp) 117*843e1988Sjohnlev movq %rdx, REGOFF_RDX(%rsp) 118*843e1988Sjohnlev movq %rdi, REGOFF_RDI(%rsp) 119*843e1988Sjohnlev movq %rsi, REGOFF_RSI(%rsp) 120*843e1988Sjohnlev movq %r8, REGOFF_R8(%rsp) 121*843e1988Sjohnlev movq %r9, REGOFF_R9(%rsp) 122*843e1988Sjohnlev movq %r10, REGOFF_R10(%rsp) 123*843e1988Sjohnlev movq %r11, REGOFF_R11(%rsp) 124*843e1988Sjohnlev movq %r12, REGOFF_R12(%rsp) 125*843e1988Sjohnlev movq %r13, REGOFF_R13(%rsp) 126*843e1988Sjohnlev movq %r14, REGOFF_R14(%rsp) 127*843e1988Sjohnlev movq %r15, REGOFF_R15(%rsp) 128*843e1988Sjohnlev 129*843e1988Sjohnlev movq %rsp, %rdi 130*843e1988Sjohnlev call xpv_die 131*843e1988Sjohnlev SET_SIZE(xpv_panic_prep) 132*843e1988Sjohnlev 133*843e1988Sjohnlev /* 134*843e1988Sjohnlev * Switch to the Solaris panic stack and jump into the Xen panic 135*843e1988Sjohnlev * handling code. 136*843e1988Sjohnlev */ 137*843e1988Sjohnlev ENTRY_NP(xpv_panic_hdlr) 138*843e1988Sjohnlev leaq panic_stack(%rip), %rsp 139*843e1988Sjohnlev addq $PANICSTKSIZE, %rsp 140*843e1988Sjohnlev call xpv_do_panic 141*843e1988Sjohnlev SET_SIZE(xpv_panic_hdlr) 142*843e1988Sjohnlev 143*843e1988Sjohnlev ENTRY_NP(xpv_surprise_intr) 144*843e1988Sjohnlev pushq %rbp 145*843e1988Sjohnlev movq %rsp, %rbp 146*843e1988Sjohnlev subq $REGOFF_TRAPNO, %rsp 147*843e1988Sjohnlev __SAVE_REGS 148*843e1988Sjohnlev movq %rsp, %rdi 149*843e1988Sjohnlev addq $REGOFF_TRAPNO, %rdi 150*843e1988Sjohnlev call xpv_interrupt 151*843e1988Sjohnlev __RESTORE_REGS 152*843e1988Sjohnlev addq $REGOFF_TRAPNO, %rsp 153*843e1988Sjohnlev popq %rbp 154*843e1988Sjohnlev iretq 155*843e1988Sjohnlev SET_SIZE(xpv_surprise_intr) 156*843e1988Sjohnlev 157*843e1988Sjohnlev ENTRY_NP(xpv_timer_trap) 158*843e1988Sjohnlev pushq %rbp 159*843e1988Sjohnlev movq %rsp, %rbp 160*843e1988Sjohnlev subq $REGOFF_TRAPNO, %rsp 161*843e1988Sjohnlev __SAVE_REGS 162*843e1988Sjohnlev movq %rsp, %rdi 163*843e1988Sjohnlev addq $REGOFF_TRAPNO, %rdi 164*843e1988Sjohnlev call xpv_timer_tick 165*843e1988Sjohnlev __RESTORE_REGS 166*843e1988Sjohnlev addq $REGOFF_TRAPNO, %rsp 167*843e1988Sjohnlev popq %rbp 168*843e1988Sjohnlev iretq 169*843e1988Sjohnlev SET_SIZE(xpv_timer_trap) 170*843e1988Sjohnlev 171*843e1988Sjohnlev#elif defined(__i386) 172*843e1988Sjohnlev 173*843e1988Sjohnlev ENTRY_NP(xpv_panic_setcr3) 174*843e1988Sjohnlev movl 4(%esp), %eax 175*843e1988Sjohnlev movl %eax, %cr3 176*843e1988Sjohnlev ret 177*843e1988Sjohnlev SET_SIZE(xpv_panic_setcr3) 178*843e1988Sjohnlev 179*843e1988Sjohnlev ENTRY(xpv_panic_reload_cr3) 180*843e1988Sjohnlev movl %cr3, %eax 181*843e1988Sjohnlev movl %eax, %cr3 182*843e1988Sjohnlev ret 183*843e1988Sjohnlev SET_SIZE(xpv_panic_reload_cr3) 184*843e1988Sjohnlev 185*843e1988Sjohnlev /* 186*843e1988Sjohnlev * Stack on entry: 187*843e1988Sjohnlev * +------------+ 188*843e1988Sjohnlev * | EFLAGS | 189*843e1988Sjohnlev * | CS | 190*843e1988Sjohnlev * | EIP | 191*843e1988Sjohnlev * | Error | 192*843e1988Sjohnlev * | Trap | <---- %esp 193*843e1988Sjohnlev * +------------+ 194*843e1988Sjohnlev */ 195*843e1988Sjohnlev ENTRY_NP(xpv_panic_prep) 196*843e1988Sjohnlev pushl %ebp 197*843e1988Sjohnlev movl %esp, %ebp 198*843e1988Sjohnlev 199*843e1988Sjohnlev subl $REGSIZE, %esp 200*843e1988Sjohnlev movl %eax, REGOFF_EAX(%esp) 201*843e1988Sjohnlev movl %ebx, REGOFF_EBX(%esp) 202*843e1988Sjohnlev movl %esp, %eax 203*843e1988Sjohnlev addl $REGSIZE, %eax 204*843e1988Sjohnlev movl (%eax), %ebx 205*843e1988Sjohnlev movl %ebx, REGOFF_EBP(%esp) 206*843e1988Sjohnlev movl 4(%eax), %ebx 207*843e1988Sjohnlev movl %ebx, REGOFF_TRAPNO(%esp) 208*843e1988Sjohnlev movl 8(%eax), %ebx 209*843e1988Sjohnlev movl %ebx, REGOFF_ERR(%esp) 210*843e1988Sjohnlev movl 12(%eax), %ebx 211*843e1988Sjohnlev movl %ebx, REGOFF_EIP(%esp) 212*843e1988Sjohnlev movl 16(%eax), %ebx 213*843e1988Sjohnlev movl %ebx, REGOFF_CS(%esp) 214*843e1988Sjohnlev movl 20(%eax), %ebx 215*843e1988Sjohnlev movl %ebx, REGOFF_EFL(%esp) 216*843e1988Sjohnlev addl $28, %eax 217*843e1988Sjohnlev movl %eax, REGOFF_ESP(%esp) 218*843e1988Sjohnlev xorl %eax, %eax 219*843e1988Sjohnlev movw %gs, %ax 220*843e1988Sjohnlev mov %eax, REGOFF_GS(%esp) 221*843e1988Sjohnlev movw %fs, %ax 222*843e1988Sjohnlev mov %eax, REGOFF_FS(%esp) 223*843e1988Sjohnlev movw %es, %ax 224*843e1988Sjohnlev mov %eax, REGOFF_ES(%esp) 225*843e1988Sjohnlev movw %ds, %ax 226*843e1988Sjohnlev mov %eax, REGOFF_DS(%esp) 227*843e1988Sjohnlev movw %ss, %ax 228*843e1988Sjohnlev mov %eax, REGOFF_SS(%esp) 229*843e1988Sjohnlev movl %ecx, REGOFF_ECX(%esp) 230*843e1988Sjohnlev movl %edx, REGOFF_EDX(%esp) 231*843e1988Sjohnlev movl %edi, REGOFF_EDI(%esp) 232*843e1988Sjohnlev movl %esi, REGOFF_ESI(%esp) 233*843e1988Sjohnlev pushl %esp 234*843e1988Sjohnlev call xpv_die 235*843e1988Sjohnlev SET_SIZE(xpv_panic_prep) 236*843e1988Sjohnlev 237*843e1988Sjohnlev /* 238*843e1988Sjohnlev * Switch to the Solaris panic stack and jump into the Xen panic 239*843e1988Sjohnlev * handling code. 240*843e1988Sjohnlev */ 241*843e1988Sjohnlev ENTRY_NP(xpv_panic_hdlr) 242*843e1988Sjohnlev movl 4(%esp), %eax 243*843e1988Sjohnlev lea panic_stack, %esp 244*843e1988Sjohnlev add $PANICSTKSIZE, %esp 245*843e1988Sjohnlev pushl %eax 246*843e1988Sjohnlev call xpv_do_panic 247*843e1988Sjohnlev SET_SIZE(xpv_panic_hdlr) 248*843e1988Sjohnlev 249*843e1988Sjohnlev ENTRY_NP(xpv_surprise_intr) 250*843e1988Sjohnlev push %ebp 251*843e1988Sjohnlev movl %esp, %ebp 252*843e1988Sjohnlev pusha 253*843e1988Sjohnlev call xpv_interrupt 254*843e1988Sjohnlev popa 255*843e1988Sjohnlev pop %ebp 256*843e1988Sjohnlev iret 257*843e1988Sjohnlev SET_SIZE(xpv_surprise_intr) 258*843e1988Sjohnlev 259*843e1988Sjohnlev ENTRY_NP(xpv_timer_trap) 260*843e1988Sjohnlev push %ebp 261*843e1988Sjohnlev movl %esp, %ebp 262*843e1988Sjohnlev pusha 263*843e1988Sjohnlev call xpv_timer_tick 264*843e1988Sjohnlev popa 265*843e1988Sjohnlev pop %ebp 266*843e1988Sjohnlev iret 267*843e1988Sjohnlev SET_SIZE(xpv_timer_trap) 268*843e1988Sjohnlev 269*843e1988Sjohnlev#endif /* __i386 */ 270*843e1988Sjohnlev 271*843e1988Sjohnlev ENTRY_NP(xpv_panic_sti) 272*843e1988Sjohnlev sti 273*843e1988Sjohnlev ret 274*843e1988Sjohnlev SET_SIZE(xpv_panic_sti) 275*843e1988Sjohnlev 276*843e1988Sjohnlev ENTRY_NP(xpv_panic_halt) 277*843e1988Sjohnlev sti 278*843e1988Sjohnlev hlt 279*843e1988Sjohnlev ret 280*843e1988Sjohnlev SET_SIZE(xpv_panic_halt) 281*843e1988Sjohnlev 282*843e1988Sjohnlev ENTRY_NP(xpv_panic_resetgs) 283*843e1988Sjohnlev movl $KGS_SEL, %eax 284*843e1988Sjohnlev movw %ax, %gs 285*843e1988Sjohnlev ret 286*843e1988Sjohnlev SET_SIZE(xpv_panic_resetgs) 287*843e1988Sjohnlev 288*843e1988Sjohnlev ENTRY_NP(xpv_invaltrap) 289*843e1988Sjohnlev push $0xbad0 290*843e1988Sjohnlev push $0x0bad 291*843e1988Sjohnlev jmp xpv_panic_prep 292*843e1988Sjohnlev SET_SIZE(xpv_invaltrap) 293*843e1988Sjohnlev 294*843e1988Sjohnlev ENTRY_NP(xpv_div0trap) 295*843e1988Sjohnlev push $0 296*843e1988Sjohnlev push $T_ZERODIV 297*843e1988Sjohnlev jmp xpv_panic_prep 298*843e1988Sjohnlev SET_SIZE(xpv_div0trap) 299*843e1988Sjohnlev 300*843e1988Sjohnlev ENTRY_NP(xpv_dbgtrap) 301*843e1988Sjohnlev push $0 302*843e1988Sjohnlev push $T_SGLSTP 303*843e1988Sjohnlev jmp xpv_panic_prep 304*843e1988Sjohnlev SET_SIZE(xpv_dbgtrap) 305*843e1988Sjohnlev 306*843e1988Sjohnlev ENTRY_NP(xpv_nmiint) 307*843e1988Sjohnlev push $0 308*843e1988Sjohnlev push $T_NMIFLT 309*843e1988Sjohnlev jmp xpv_panic_prep 310*843e1988Sjohnlev SET_SIZE(xpv_nmiint) 311*843e1988Sjohnlev 312*843e1988Sjohnlev ENTRY_NP(xpv_brktrap) 313*843e1988Sjohnlev /* XXX: check for error */ 314*843e1988Sjohnlev push $T_BPTFLT 315*843e1988Sjohnlev jmp xpv_panic_prep 316*843e1988Sjohnlev SET_SIZE(xpv_brktrap) 317*843e1988Sjohnlev 318*843e1988Sjohnlev ENTRY_NP(xpv_ovflotrap) 319*843e1988Sjohnlev push $0 320*843e1988Sjohnlev push $T_OVFLW 321*843e1988Sjohnlev jmp xpv_panic_prep 322*843e1988Sjohnlev SET_SIZE(xpv_ovflotrap) 323*843e1988Sjohnlev 324*843e1988Sjohnlev ENTRY_NP(xpv_boundstrap) 325*843e1988Sjohnlev push $0 326*843e1988Sjohnlev push $T_BOUNDFLT 327*843e1988Sjohnlev jmp xpv_panic_prep 328*843e1988Sjohnlev SET_SIZE(xpv_boundstrap) 329*843e1988Sjohnlev 330*843e1988Sjohnlev ENTRY_NP(xpv_invoptrap) 331*843e1988Sjohnlev push $T_ILLINST 332*843e1988Sjohnlev jmp xpv_panic_prep 333*843e1988Sjohnlev SET_SIZE(xpv_invoptrap) 334*843e1988Sjohnlev 335*843e1988Sjohnlev ENTRY_NP(xpv_ndptrap) 336*843e1988Sjohnlev push $0 337*843e1988Sjohnlev push $T_NOEXTFLT 338*843e1988Sjohnlev jmp xpv_panic_prep 339*843e1988Sjohnlev SET_SIZE(xpv_ndptrap) 340*843e1988Sjohnlev 341*843e1988Sjohnlev ENTRY_NP(xpv_syserrtrap) 342*843e1988Sjohnlev /* XXX: check for error */ 343*843e1988Sjohnlev push $T_DBLFLT 344*843e1988Sjohnlev jmp xpv_panic_prep 345*843e1988Sjohnlev SET_SIZE(xpv_syserrtrap) 346*843e1988Sjohnlev 347*843e1988Sjohnlev ENTRY_NP(xpv_invtsstrap) 348*843e1988Sjohnlev push $T_TSSFLT 349*843e1988Sjohnlev jmp xpv_panic_prep 350*843e1988Sjohnlev SET_SIZE(xpv_invtsstrap) 351*843e1988Sjohnlev 352*843e1988Sjohnlev ENTRY_NP(xpv_segnptrap) 353*843e1988Sjohnlev push $T_SEGFLT 354*843e1988Sjohnlev jmp xpv_panic_prep 355*843e1988Sjohnlev SET_SIZE(xpv_segnptrap) 356*843e1988Sjohnlev 357*843e1988Sjohnlev ENTRY_NP(xpv_stktrap) 358*843e1988Sjohnlev push $T_STKFLT 359*843e1988Sjohnlev jmp xpv_panic_prep 360*843e1988Sjohnlev SET_SIZE(xpv_stktrap) 361*843e1988Sjohnlev 362*843e1988Sjohnlev ENTRY_NP(xpv_gptrap) 363*843e1988Sjohnlev push $T_GPFLT 364*843e1988Sjohnlev jmp xpv_panic_prep 365*843e1988Sjohnlev SET_SIZE(xpv_gptrap) 366*843e1988Sjohnlev 367*843e1988Sjohnlev ENTRY_NP(xpv_pftrap) 368*843e1988Sjohnlev push $T_PGFLT 369*843e1988Sjohnlev jmp xpv_panic_prep 370*843e1988Sjohnlev SET_SIZE(xpv_pftrap) 371*843e1988Sjohnlev 372*843e1988Sjohnlev ENTRY_NP(xpv_ndperr) 373*843e1988Sjohnlev push $0 374*843e1988Sjohnlev push $T_EXTERRFLT 375*843e1988Sjohnlev jmp xpv_panic_prep 376*843e1988Sjohnlev SET_SIZE(xpv_ndperr) 377*843e1988Sjohnlev 378*843e1988Sjohnlev ENTRY_NP(xpv_achktrap) 379*843e1988Sjohnlev push $T_ALIGNMENT 380*843e1988Sjohnlev jmp xpv_panic_prep 381*843e1988Sjohnlev SET_SIZE(xpv_achktrap) 382*843e1988Sjohnlev 383*843e1988Sjohnlev ENTRY_NP(xpv_mcetrap) 384*843e1988Sjohnlev push $0 385*843e1988Sjohnlev push $T_MCE 386*843e1988Sjohnlev jmp xpv_panic_prep 387*843e1988Sjohnlev SET_SIZE(xpv_mcetrap) 388*843e1988Sjohnlev 389*843e1988Sjohnlev ENTRY_NP(xpv_xmtrap) 390*843e1988Sjohnlev push $0 391*843e1988Sjohnlev push $T_SIMDFPE 392*843e1988Sjohnlev jmp xpv_panic_prep 393*843e1988Sjohnlev SET_SIZE(xpv_xmtrap) 394*843e1988Sjohnlev 395*843e1988Sjohnlev#endif /* __lint */ 396