--- /dev/null
+/*
+ * trap.S: Trap and world switch handlers
+ *
+ * Leendert van Doorn, leendert@watson.ibm.com
+ * Copyright (c) 2005, International Business Machines Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include "machine.h"
+#include "vm86.h"
+#include "offsets.h"
+
+/*
+ * All processor exception/faults/interrupts end up here.
+ *
+ * On an exception/fault, the processor pushes CS:EIP, SS, ESP and an
+ * optional error code onto the stack. The common_trap routine
+ * below saves the processor context and transfers control to trap()
+ * whose job it is to virtualize and pass on the trap.
+ */
+ .macro TRAP_HANDLER trapno error
+ .text
+ .align 16
+1: .if \error == 0
+ pushl $0 /* dummy error code */
+ .endif
+ pushl $\trapno
+ jmp common_trap
+ .section .rodata
+ .long 1b
+ .text
+ .endm
+
+ .section .rodata
+ .code32
+ .align 4
+ .global trap_handlers
+trap_handlers:
+ TRAP_HANDLER 0, 0 /* divide error */
+ TRAP_HANDLER 1, 0 /* debug */
+ TRAP_HANDLER 2, 0 /* NMI interrupt */
+ TRAP_HANDLER 3, 0 /* breakpoint */
+ TRAP_HANDLER 4, 0 /* overflow */
+ TRAP_HANDLER 5, 0 /* BOUND range exceeded */
+ TRAP_HANDLER 6, 0 /* invalid opcode */
+ TRAP_HANDLER 7, 0 /* device not available */
+ TRAP_HANDLER 8, 1 /* double fault */
+ TRAP_HANDLER 9, 0 /* coprocessor segment overrun */
+ TRAP_HANDLER 10, 1 /* invalid TSS */
+ TRAP_HANDLER 11, 1 /* segment not present */
+ TRAP_HANDLER 12, 1 /* stack-segment fault */
+ TRAP_HANDLER 13, 1 /* general protection */
+ TRAP_HANDLER 14, 1 /* page fault */
+ TRAP_HANDLER 15, 0 /* reserved */
+ TRAP_HANDLER 16, 0 /* FPU floating-point error */
+ TRAP_HANDLER 17, 1 /* alignment check */
+ TRAP_HANDLER 18, 0 /* machine check */
+ TRAP_HANDLER 19, 0 /* SIMD floating-point error */
+ TRAP_HANDLER 20, 0 /* reserved */
+ TRAP_HANDLER 21, 0 /* reserved */
+ TRAP_HANDLER 22, 0 /* reserved */
+ TRAP_HANDLER 23, 0 /* reserved */
+ TRAP_HANDLER 24, 0 /* reserved */
+ TRAP_HANDLER 25, 0 /* reserved */
+ TRAP_HANDLER 26, 0 /* reserved */
+ TRAP_HANDLER 27, 0 /* reserved */
+ TRAP_HANDLER 28, 0 /* reserved */
+ TRAP_HANDLER 29, 0 /* reserved */
+ TRAP_HANDLER 30, 0 /* reserved */
+ TRAP_HANDLER 31, 0 /* reserved */
+ TRAP_HANDLER 32, 0 /* irq 0 */
+ TRAP_HANDLER 33, 0 /* irq 1 */
+ TRAP_HANDLER 34, 0 /* irq 2 */
+ TRAP_HANDLER 35, 0 /* irq 3 */
+ TRAP_HANDLER 36, 0 /* irq 4 */
+ TRAP_HANDLER 37, 0 /* irq 5 */
+ TRAP_HANDLER 38, 0 /* irq 6 */
+ TRAP_HANDLER 39, 0 /* irq 7 */
+ TRAP_HANDLER 40, 0 /* irq 8 */
+ TRAP_HANDLER 41, 0 /* irq 9 */
+ TRAP_HANDLER 42, 0 /* irq 10 */
+ TRAP_HANDLER 43, 0 /* irq 11 */
+ TRAP_HANDLER 44, 0 /* irq 12 */
+ TRAP_HANDLER 45, 0 /* irq 13 */
+ TRAP_HANDLER 46, 0 /* irq 14 */
+ TRAP_HANDLER 47, 0 /* irq 15 */
+
+ .text
+ .code32
+ .align 16
+common_trap: /* common trap handler */
+ pushl %gs
+ pushl %fs
+ pushl %ds
+ pushl %es
+ pushal
+
+ movl $DATA_SELECTOR, %eax /* make sure these are sane */
+ movl %eax, %ds
+ movl %eax, %es
+ movl %eax, %fs
+ movl %eax, %gs
+ movl %esp, %ebp
+
+ pushl %ebp
+ pushl 52(%ebp)
+ pushl 48(%ebp)
+ call trap /* trap(trapno, errno, regs) */
+ addl $12, %esp
+
+trap_return:
+ popal
+ popl %es
+ popl %ds
+ popl %fs
+ popl %gs
+ addl $8, %esp /* skip trapno, errno */
+ iret
+ /* NOT REACHED */
+
+
+/*
+ * A world switch to real mode occured. The hypervisor saved the
+ * executing context into "oldctx" and instantiated "newctx", which
+ * gets us here. Here we push a stack frame that is compatible with
+ * a trap frame (see above) so that we can handle this event as a
+ * regular trap.
+ */
+ .text
+ .align 16
+ .globl switch_to_real_mode
+switch_to_real_mode:
+ pushl oldctx+VMX_ASSIST_CTX_GS_SEL /* 16 to 32-bit transition */
+ pushl oldctx+VMX_ASSIST_CTX_FS_SEL
+ pushl oldctx+VMX_ASSIST_CTX_DS_SEL
+ pushl oldctx+VMX_ASSIST_CTX_ES_SEL
+ pushl oldctx+VMX_ASSIST_CTX_SS_SEL
+ pushl oldctx+VMX_ASSIST_CTX_ESP
+ pushl oldctx+VMX_ASSIST_CTX_EFLAGS
+ pushl oldctx+VMX_ASSIST_CTX_CS_SEL
+ pushl oldctx+VMX_ASSIST_CTX_EIP
+ pushl $-1 /* trapno, errno */
+ pushl $-1
+ pushl %gs
+ pushl %fs
+ pushl %ds
+ pushl %es
+ pushal
+
+ movl %esp, %ebp
+ pushl %ebp
+ call enter_real_mode
+ addl $4, %esp
+
+ jmp trap_return
+ /* NOT REACHED */
+
+
+/*
+ * Switch to protected mode. At this point all the registers have
+ * been reloaded by trap_return and all we have to do is cause a
+ * world switch by turning on CR0.PE.
+ */
+ .text
+ .align 16
+ .globl switch_to_protected_mode
+switch_to_protected_mode:
+ movl oldctx+VMX_ASSIST_CTX_CR0, %esp
+ movl %esp, %cr0 /* actual world switch ! */
+
+ /* NOT REACHED */
+ pushl $switch_failed
+ call panic
+ jmp .
+
+ .data
+ .align 4
+switch_failed:
+ .asciz "World switch to protected mode failed\n"
+