# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1202299675 0
# Node ID 9d0e86d8c1d1360be64921928ae98b3693adfc73
# Parent f8db1c6baad90b038e1cf4f91c3a829793344798
x86 vmx: Remove vmxassist.
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
tools/firmware/README | 83 -
tools/firmware/vmxassist/Makefile | 81 -
tools/firmware/vmxassist/gen.c | 52
tools/firmware/vmxassist/head.S | 94 -
tools/firmware/vmxassist/machine.h | 199 ---
tools/firmware/vmxassist/setup.c | 337 -----
tools/firmware/vmxassist/trap.S | 179 ---
tools/firmware/vmxassist/util.c | 430 -------
tools/firmware/vmxassist/util.h | 45
tools/firmware/vmxassist/vm86.c | 1992 ----------------------------------
tools/firmware/vmxassist/vm86.h | 64 -
tools/firmware/vmxassist/vmxassist.ld | 32
xen/include/public/hvm/vmx_assist.h | 122 --
tools/firmware/Makefile | 1
tools/firmware/hvmloader/Makefile | 3
tools/firmware/hvmloader/config.h | 1
tools/firmware/hvmloader/hvmloader.c | 28
xen/arch/x86/Rules.mk | 5
xen/arch/x86/hvm/hvm.c | 13
xen/arch/x86/hvm/vmx/Makefile | 2
xen/arch/x86/hvm/vmx/vmx.c | 298 -----
xen/arch/x86/hvm/vmx/x86_32/exits.S | 4
xen/arch/x86/hvm/vmx/x86_64/exits.S | 4
xen/arch/x86/hvm/vpic.c | 5
xen/include/asm-x86/hvm/vmx/vmcs.h | 13
25 files changed, 5 insertions(+), 4082 deletions(-)
diff -r f8db1c6baad9 -r 9d0e86d8c1d1 tools/firmware/Makefile
--- a/tools/firmware/Makefile Tue Feb 05 23:27:12 2008 +0000
+++ b/tools/firmware/Makefile Wed Feb 06 12:07:55 2008 +0000
@@ -9,7 +9,6 @@ SUBDIRS :=
SUBDIRS :=
SUBDIRS += rombios rombios/32bit
SUBDIRS += vgabios
-SUBDIRS += vmxassist
SUBDIRS += extboot
#SUBDIRS += etherboot
SUBDIRS += hvmloader
diff -r f8db1c6baad9 -r 9d0e86d8c1d1 tools/firmware/README
--- a/tools/firmware/README Tue Feb 05 23:27:12 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-Domain firmware support
------------------------
-
-One of the key advantages of full virtualization hardware support (such
-as Intel's VT or AMD's SVM extensions) is the ability to run unmodified
-guest operating systems. However, since most OSes rely on BIOS support
-during their early bringup, we need to provide a surrogate ROMBIOS and
-VGABIOS firmware layer.
-
-What's more, we need to support real-mode which is required by
-the firmware and bootstrap loaders. Real-mode support is especially
-challenging for Intel's VMX (VT) enabled CPUs where there is no real-mode
-support for VMX guest partitions. In this case you either have to do full
-emulation (full real-mode emulator; more complete but potentially slower)
-or partial emulation (use the VM8086 extensions, emulate only those
-instructions that are missing; faster, but potentially incomplete). The
-vmxassist code in this subdirectory uses the later approach because it
-is smaller and faster.
-
-The approach is relatively straight forward. Vmxloader contains three
-payloads (rombios, vgabios and vmxassist) and it is bootstrapped as any
-other 32-bit OS. Vmxloader copies its payloads to the addresses below
-and transfers control to vmxassist.
-
- vgabios VGABIOS (standard and Cirrus).
- Resides at C000:0000.
-
- vmxassist VMXAssist VM86 realmode emulator for VMX.
- Resides at D000:0000.
-
- rombios ROMBIOS code. Derived from Bochs.
- Resides at F000:0000
-
-Vmxassist first sets up it own world (GDT, IDT, TR, etc), enables
-VM8086 and then transfers control to F000:FFF0 and executes 16-bit
-code. Unsupported instructions cause a general protection failure at
-which point vmxassist kicks in and emulates the offending instruction.
-Whever the emulated code transitions to 32-bit protected mode, vmxassist
-will go away. Whenever 32-bit protected code transitions to real-mode,
-Xen/VMX will detect this and transfer control to vmxassist.
-
-Most of the vmxassist complexity comes from properly handling the
-real to protected mode and protected to real mode transitions and
-the proper emulation of the segment registers. Even though the Intel
-manual clearly states that you should immediately perform a jmp far
-after a mode transition, many operating systems execute additional
-instructions and some even refer to segment selectors and pop data
-from the stack. Vmxassist contains a number of work arounds for these
-OSes.
-
-
-Acknowledgements
-----------------
-
-The rombios was taken (largely unmodified) from Bochs, which was written
-by Kevin Lawton. The VGABIOS was written by Christophe Bothamy. Arun Sharma,
-Asit Mallick and Nitin Kamble (Intel) provided the E820 patches and lots
-of useful feedback.
-
-
-Contact
--------
-
-Leendert van Doorn
-IBM T.J. Watson Research Center
-19 Skyline Drive
-Hawthorne, NY 10532
-leendert@xxxxxxxxxxxxxx
-
-
-Tested Operating Systems
-------------------------
-
-Since vmxassist uses partial emulation, it may always miss opcodes
-that are required by a particular OS. The table below lists the OSes
-I have tried. The Install column indicates a full CD/DVD install into
-a VMX partition. The Disk column indicates booting from prefabricated
-disk image.
-
-Operating System Install Disk
-------------------------------------------------------------
-RedHat Enterprise Linux (RHEL3_U5) Yes Yes
-Fedora Code (FC3) (-) Yes
-FreeBSD 5.3 (-) Yes
-MS-DOS 5.0 (-) Yes
-
-(-) not tried yet
-
diff -r f8db1c6baad9 -r 9d0e86d8c1d1 tools/firmware/hvmloader/Makefile
--- a/tools/firmware/hvmloader/Makefile Tue Feb 05 23:27:12 2008 +0000
+++ b/tools/firmware/hvmloader/Makefile Wed Feb 06 12:07:55 2008 +0000
@@ -50,11 +50,10 @@ acpi/acpi.a:
acpi/acpi.a:
$(MAKE) -C acpi
-roms.h: ../rombios/BIOS-bochs-latest ../vgabios/VGABIOS-lgpl-latest.bin
../vgabios/VGABIOS-lgpl-latest.cirrus.bin ../vmxassist/vmxassist.bin
../etherboot/eb-roms.h ../extboot/extboot.bin
+roms.h: ../rombios/BIOS-bochs-latest ../vgabios/VGABIOS-lgpl-latest.bin
../vgabios/VGABIOS-lgpl-latest.cirrus.bin ../etherboot/eb-roms.h
../extboot/extboot.bin
sh ./mkhex rombios ../rombios/BIOS-bochs-latest > roms.h
sh ./mkhex vgabios_stdvga ../vgabios/VGABIOS-lgpl-latest.bin >> roms.h
sh ./mkhex vgabios_cirrusvga ../vgabios/VGABIOS-lgpl-latest.cirrus.bin
>> roms.h
- sh ./mkhex vmxassist ../vmxassist/vmxassist.bin >> roms.h
cat ../etherboot/eb-roms.h >> roms.h
sh ./mkhex extboot ../extboot/extboot.bin >> roms.h
diff -r f8db1c6baad9 -r 9d0e86d8c1d1 tools/firmware/hvmloader/config.h
--- a/tools/firmware/hvmloader/config.h Tue Feb 05 23:27:12 2008 +0000
+++ b/tools/firmware/hvmloader/config.h Wed Feb 06 12:07:55 2008 +0000
@@ -21,7 +21,6 @@
#define HYPERCALL_PHYSICAL_ADDRESS 0x00080000
#define VGABIOS_PHYSICAL_ADDRESS 0x000C0000
#define ETHERBOOT_PHYSICAL_ADDRESS 0x000C8000
-#define VMXASSIST_PHYSICAL_ADDRESS 0x000D0000
#define EXTBOOT_PHYSICAL_ADDRESS 0x000DF800
#define SMBIOS_PHYSICAL_ADDRESS 0x000E9000
#define SMBIOS_MAXIMUM_SIZE 0x00001000
diff -r f8db1c6baad9 -r 9d0e86d8c1d1 tools/firmware/hvmloader/hvmloader.c
--- a/tools/firmware/hvmloader/hvmloader.c Tue Feb 05 23:27:12 2008 +0000
+++ b/tools/firmware/hvmloader/hvmloader.c Wed Feb 06 12:07:55 2008 +0000
@@ -1,5 +1,5 @@
/*
- * hvmloader.c: HVM ROMBIOS/VGABIOS/ACPI/VMXAssist image loader.
+ * hvmloader.c: HVM bootloader.
*
* Leendert van Doorn, leendert@xxxxxxxxxxxxxx
* Copyright (c) 2005, International Business Machines Corporation.
@@ -40,7 +40,6 @@ asm(
" cli \n"
" movl $stack_top,%esp \n"
" movl %esp,%ebp \n"
- " movl %eax,initial_eax \n"
" call main \n"
/* Relocate real-mode trampoline to 0x0. */
" mov $trampoline_start,%esi \n"
@@ -98,8 +97,6 @@ asm(
"stack_top: \n"
);
-static unsigned int initial_eax;
-
void create_mp_tables(void);
int hvm_write_smbios_tables(void);
@@ -122,12 +119,6 @@ check_amd(void)
"=d" (*(int *)(&id[4]))
: "a" (0) );
return __builtin_memcmp(id, "AuthenticAMD", 12) == 0;
-}
-
-static int
-use_vmxassist(void)
-{
- return !check_amd() && !initial_eax;
}
static void
@@ -506,10 +497,6 @@ int main(void)
printf(" %05x-%05x: Extboot ROM\n",
EXTBOOT_PHYSICAL_ADDRESS,
EXTBOOT_PHYSICAL_ADDRESS + extboot_sz - 1);
- if ( use_vmxassist() )
- printf(" %05x-%05x: VMXAssist\n",
- VMXASSIST_PHYSICAL_ADDRESS,
- VMXASSIST_PHYSICAL_ADDRESS + sizeof(vmxassist) - 1);
if ( smbios_sz )
printf(" %05x-%05x: SMBIOS tables\n",
SMBIOS_PHYSICAL_ADDRESS,
@@ -523,19 +510,6 @@ int main(void)
ROMBIOS_PHYSICAL_ADDRESS,
ROMBIOS_PHYSICAL_ADDRESS + rombios_sz - 1);
- if ( use_vmxassist() )
- {
- printf("Loading VMXAssist ...\n");
- memcpy((void *)VMXASSIST_PHYSICAL_ADDRESS,
- vmxassist, sizeof(vmxassist));
-
- printf("VMX go ...\n");
- __asm__ __volatile__(
- "jmp *%%eax"
- : : "a" (VMXASSIST_PHYSICAL_ADDRESS), "d" (0)
- );
- }
-
printf("Invoking ROMBIOS ...\n");
return 0;
}
diff -r f8db1c6baad9 -r 9d0e86d8c1d1 tools/firmware/vmxassist/Makefile
--- a/tools/firmware/vmxassist/Makefile Tue Feb 05 23:27:12 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,81 +0,0 @@
-#
-# Makefile
-#
-# Leendert van Doorn, leendert@xxxxxxxxxxxxxx
-# 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.
-#
-
-# External CFLAGS can do more harm than good.
-CFLAGS :=
-
-override XEN_TARGET_ARCH = x86_32
-XEN_ROOT = ../../..
-include $(XEN_ROOT)/tools/Rules.mk
-
-# The emulator code lives in ROM space
-TEXTADDR=0x000D0000
-
-DEFINES=-DDEBUG -DTEXTADDR=$(TEXTADDR)
-XENINC=$(CFLAGS_include)
-
-# Disable PIE/SSP if GCC supports them. They can break us.
-CFLAGS += $(call cc-option,$(CC),-nopie,)
-CFLAGS += $(call cc-option,$(CC),-fno-stack-protector,)
-CFLAGS += $(call cc-option,$(CC),-fno-stack-protector-all,)
-
-CPP = cpp -P
-CFLAGS += $(DEFINES) -I. $(XENINC) -fno-builtin -O2 -msoft-float
-
-OBJECTS = head.o trap.o vm86.o setup.o util.o
-
-.PHONY: all
-all: vmxassist.bin
-
-vmxassist.bin: vmxassist.ld $(OBJECTS)
- $(CPP) $(DEFINES) vmxassist.ld > vmxassist.tmp
- $(LD) -o vmxassist $(LDFLAGS_DIRECT) --fatal-warnings -N -T
vmxassist.tmp $(OBJECTS)
- nm -n vmxassist > vmxassist.sym
- $(OBJCOPY) -p -O binary -R .note -R .comment -R .bss -S --gap-fill=0
vmxassist vmxassist.tmp
- dd if=vmxassist.tmp of=vmxassist.bin ibs=512 conv=sync
- rm -f vmxassist.tmp
-
-head.o: machine.h vm86.h head.S
- $(CC) $(CFLAGS) -D__ASSEMBLY__ $(DEFINES) -c head.S
-
-trap.o: machine.h vm86.h offsets.h trap.S
- $(CC) $(CFLAGS) -D__ASSEMBLY__ $(DEFINES) -c trap.S
-
-vm86.o: machine.h vm86.h vm86.c
- $(CC) $(CFLAGS) -c vm86.c
-
-setup.o: machine.h vm86.h setup.c
- $(CC) $(CFLAGS) -c setup.c
-
-util.o: machine.h vm86.h util.c
- $(CC) $(CFLAGS) -c util.c
-
-offsets.h: gen
- ./gen > offsets.h
-
-gen: vm86.h gen.c
- $(HOSTCC) $(HOSTCFLAGS) -I. $(XENINC) -o gen gen.c
-
-.PHONY: clean
-clean:
- rm -f vmxassist vmxassist.tmp vmxassist.bin vmxassist.run vmxassist.sym
head.s
- rm -f $(OBJECTS)
- rm -f gen gen.o offsets.h
-
diff -r f8db1c6baad9 -r 9d0e86d8c1d1 tools/firmware/vmxassist/gen.c
--- a/tools/firmware/vmxassist/gen.c Tue Feb 05 23:27:12 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,52 +0,0 @@
-/*
- * gen.c: Generate assembler symbols.
- *
- * Leendert van Doorn, leendert@xxxxxxxxxxxxxx
- * 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 <stdio.h>
-#include <stddef.h>
-#include <stdlib.h>
-#include <vm86.h>
-
-int
-main(void)
-{
- printf("/* MACHINE GENERATED; DO NOT EDIT */\n");
- printf("#define VMX_ASSIST_CTX_GS_SEL 0x%x\n",
- (unsigned int)offsetof(struct vmx_assist_context, gs_sel));
- printf("#define VMX_ASSIST_CTX_FS_SEL 0x%x\n",
- (unsigned int)offsetof(struct vmx_assist_context, fs_sel));
- printf("#define VMX_ASSIST_CTX_DS_SEL 0x%x\n",
- (unsigned int)offsetof(struct vmx_assist_context, ds_sel));
- printf("#define VMX_ASSIST_CTX_ES_SEL 0x%x\n",
- (unsigned int)offsetof(struct vmx_assist_context, es_sel));
- printf("#define VMX_ASSIST_CTX_SS_SEL 0x%x\n",
- (unsigned int)offsetof(struct vmx_assist_context, ss_sel));
- printf("#define VMX_ASSIST_CTX_ESP 0x%x\n",
- (unsigned int)offsetof(struct vmx_assist_context, esp));
- printf("#define VMX_ASSIST_CTX_EFLAGS 0x%x\n",
- (unsigned int)offsetof(struct vmx_assist_context, eflags));
- printf("#define VMX_ASSIST_CTX_CS_SEL 0x%x\n",
- (unsigned int)offsetof(struct vmx_assist_context, cs_sel));
- printf("#define VMX_ASSIST_CTX_EIP 0x%x\n",
- (unsigned int)offsetof(struct vmx_assist_context, eip));
-
- printf("#define VMX_ASSIST_CTX_CR0 0x%x\n",
- (unsigned int)offsetof(struct vmx_assist_context, cr0));
-
- return 0;
-}
diff -r f8db1c6baad9 -r 9d0e86d8c1d1 tools/firmware/vmxassist/head.S
--- a/tools/firmware/vmxassist/head.S Tue Feb 05 23:27:12 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,94 +0,0 @@
-/*
- * head.S: VMXAssist runtime start off.
- *
- * Leendert van Doorn, leendert@xxxxxxxxxxxxxx
- * 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 "vm86.h"
-#include "machine.h"
-
-/*
- * When a partition tries to mask off the CR0_PE bit a world
- * switch happens to the environment below. The magic indicates
- * that this is a valid context.
- */
- jmp _start
-
- .align 8
- .long VMXASSIST_MAGIC
- .long newctx /* new context */
- .long oldctx /* old context */
-
-/*
- * This is the real start. Control was transfered to this point
- * with CR0_PE set and executing in some 32-bit segment. We call
- * main and setup our own environment.
- */
- .globl _start
- .code32
-_start:
- cli
-
- /* save register parameters to C land */
-
- /* clear bss */
- cld
- xorb %al, %al
- movl $_bbss, %edi
- movl $_ebss, %ecx
- subl %edi, %ecx
- rep stosb
-
- movl %edx, booting_cpu
- movl %ebx, booting_vector
-
- /* make sure we are in a sane world */
- clts
-
- /* setup my own stack */
- movl $stack_top, %esp
- movl %esp, %ebp
-
- /* go ... */
- call main
- jmp halt
-
-/*
- * Something bad happened, print invoking %eip and loop forever
- */
- .align 4
- .globl halt
-halt:
- push $halt_msg
- call printf
- cli
- jmp .
-
- .data
-halt_msg:
- .asciz "Halt called from %%eip 0x%x\n"
-
-
-/*
- * Our stack
- */
- .bss
- .align 8
- .globl stack, stack_top
-stack:
- .skip STACK_SIZE
-stack_top:
-
diff -r f8db1c6baad9 -r 9d0e86d8c1d1 tools/firmware/vmxassist/machine.h
--- a/tools/firmware/vmxassist/machine.h Tue Feb 05 23:27:12 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,199 +0,0 @@
-/*
- * machine.h: Intel CPU specific definitions
- *
- * Leendert van Doorn, leendert@xxxxxxxxxxxxxx
- * 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.
- */
-#ifndef __MACHINE_H__
-#define __MACHINE_H__
-
-/* the size of our stack (4KB) */
-#define STACK_SIZE 8192
-
-#define TSS_SELECTOR 0x08
-#define CODE_SELECTOR 0x10
-#define DATA_SELECTOR 0x18
-
-#define CR0_PE (1 << 0)
-#define CR0_EM (1 << 2)
-#define CR0_TS (1 << 3)
-#define CR0_NE (1 << 5)
-#define CR0_PG (1 << 31)
-
-#define CR4_VME (1 << 0)
-#define CR4_PVI (1 << 1)
-#define CR4_PSE (1 << 4)
-#define CR4_PAE (1 << 5)
-
-#define EFLAGS_CF (1 << 0)
-#define EFLAGS_PF (1 << 2)
-#define EFLAGS_AF (1 << 4)
-#define EFLAGS_ZF (1 << 6)
-#define EFLAGS_SF (1 << 7)
-#define EFLAGS_TF (1 << 8)
-#define EFLAGS_IF (1 << 9)
-#define EFLAGS_DF (1 << 10)
-#define EFLAGS_OF (1 << 11)
-#define EFLAGS_IOPL (3 << 12)
-#define EFLAGS_VM ((1 << 17) | EFLAGS_IOPL)
-#define EFLAGS_VIF (1 << 19)
-#define EFLAGS_VIP (1 << 20)
-
-#define LOG_PGSIZE 12 /* log2(page size) */
-#define LOG_PDSIZE 22 /* log2(page directory size) */
-
-/* Derived constants */
-#define PGSIZE (1 << LOG_PGSIZE) /* page size */
-#define PGMASK (~(PGSIZE - 1)) /* page mask */
-#define LPGSIZE (1 << LOG_PDSIZE) /* large page size */
-#define LPGMASK (~(LPGSIZE - 1)) /* large page mask */
-
-/* Programmable Interrupt Contoller (PIC) defines */
-#define PIC_MASTER 0x20
-#define PIC_SLAVE 0xA0
-
-#define PIC_CMD 0 /* command */
-#define PIC_ISR 0 /* interrupt status */
-#define PIC_IMR 1 /* interrupt mask */
-
-
-#ifndef __ASSEMBLY__
-
-struct dtr {
- unsigned short size;
- unsigned long base __attribute__ ((packed));
-};
-
-struct tss {
- unsigned short prev_link;
- unsigned short _1;
- unsigned long esp0;
- unsigned short ss0;
- unsigned short _2;
- unsigned long esp1;
- unsigned short ss1;
- unsigned short _3;
- unsigned long esp2;
- unsigned short ss2;
- unsigned short _4;
- unsigned long cr3;
- unsigned long eip;
- unsigned long eflags;
- unsigned long eax;
- unsigned long ecx;
- unsigned long edx;
- unsigned long ebx;
- unsigned long esi;
- unsigned long edi;
- unsigned long esp;
- unsigned long ebp;
- unsigned long es;
- unsigned long cs;
- unsigned long ss;
- unsigned long ds;
- unsigned long fs;
- unsigned long gs;
- unsigned short ldt_segment;
- unsigned short _5;
- unsigned short _6;
- unsigned short iomap_base;
-#ifdef ENABLE_VME
- unsigned long int_redir[8];
-#endif
- unsigned char iomap[8193];
-};
-
-static inline void
-outw(unsigned short addr, unsigned short val)
-{
- __asm__ __volatile__ ("outw %%ax, %%dx" :: "d"(addr), "a"(val));
-}
-
-static inline void
-outb(unsigned short addr, unsigned char val)
-{
- __asm__ __volatile__ ("outb %%al, %%dx" :: "d"(addr), "a"(val));
-}
-
-static inline unsigned char
-inb(unsigned short addr)
-{
- unsigned char val;
-
- __asm__ __volatile__ ("inb %w1,%0" : "=a" (val) : "Nd" (addr));
- return val;
-}
-
-static inline unsigned
-get_cmos(int reg)
-{
- outb(0x70, reg);
- return inb(0x71);
-}
-
-static inline unsigned
-get_cr0(void)
-{
- unsigned rv;
- __asm__ __volatile__("movl %%cr0, %0" : "=r"(rv));
- return rv;
-}
-
-static inline void
-set_cr0(unsigned value)
-{
- __asm__ __volatile__(
- "movl %0, %%cr0\n"
- "jmp 1f\n"
- "1: nop\n"
- : /* no outputs */
- : "r"(value)
- );
-}
-
-static inline unsigned
-get_cr2(void)
-{
- unsigned rv;
-
- __asm__ __volatile__("movl %%cr2, %0" : "=r"(rv));
- return rv;
-}
-
-static inline unsigned
-get_cr4(void)
-{
- unsigned rv;
- __asm__ __volatile__("movl %%cr4, %0" : "=r"(rv));
- return rv;
-}
-
-static inline void
-set_cr3(unsigned addr)
-{
- __asm__ __volatile__("movl %0, %%cr3" : /* no outputs */ : "r"(addr));
-}
-
-static inline void
-set_cr4(unsigned value)
-{
- __asm__ __volatile__("movl %0, %%cr4" : /* no outputs */ : "r"(value));
-}
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* __MACHINE_H__ */
-
diff -r f8db1c6baad9 -r 9d0e86d8c1d1 tools/firmware/vmxassist/setup.c
--- a/tools/firmware/vmxassist/setup.c Tue Feb 05 23:27:12 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,337 +0,0 @@
-/*
- * setup.c: Setup the world for vmxassist.
- *
- * Leendert van Doorn, leendert@xxxxxxxxxxxxxx
- * 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 "vm86.h"
-#include "util.h"
-#include "machine.h"
-
-#if (VMXASSIST_BASE != TEXTADDR)
-#error VMXAssist base mismatch
-#endif
-
-#define NR_PGD (PGSIZE / sizeof(unsigned))
-
-#define min(a, b) ((a) > (b) ? (b) : (a))
-
-/* Which CPU are we booting, and what is the initial CS segment? */
-int booting_cpu, booting_vector;
-
-unsigned long long gdt[] __attribute__ ((aligned(32))) = {
- 0x0000000000000000ULL, /* 0x00: reserved */
- 0x0000890000000000ULL, /* 0x08: 32-bit TSS */
- 0x00CF9A000000FFFFULL, /* 0x10: CS 32-bit */
- 0x00CF92000000FFFFULL, /* 0x18: DS 32-bit */
-};
-
-struct dtr gdtr = { sizeof(gdt)-1, (unsigned long) &gdt };
-
-struct tss tss __attribute__ ((aligned(4)));
-
-unsigned long long idt[NR_TRAPS] __attribute__ ((aligned(32)));
-
-struct dtr idtr = { sizeof(idt)-1, (unsigned long) &idt };
-
-struct vmx_assist_context oldctx;
-struct vmx_assist_context newctx;
-
-unsigned long memory_size;
-int initialize_real_mode;
-
-extern char stack_top[];
-extern unsigned trap_handlers[];
-
-void
-banner(void)
-{
- printf("VMXAssist (%s)\n", __DATE__);
-
- /* Bochs its way to convey memory size */
- memory_size = ((get_cmos(0x35) << 8) | get_cmos(0x34)) << 6;
- if (memory_size > 0x3bc000)
- memory_size = 0x3bc000;
- memory_size = (memory_size << 10) + 0xF00000;
- if (memory_size <= 0xF00000)
- memory_size =
- (((get_cmos(0x31) << 8) | get_cmos(0x30)) + 0x400) << 10;
- memory_size += 0x400 << 10; /* + 1MB */
-
- printf("Memory size %ld MB\n", memory_size >> 20);
- printf("E820 map:\n");
- print_e820_map(HVM_E820, *HVM_E820_NR);
- printf("\n");
-}
-
-void
-setup_gdt(void)
-{
- unsigned long long addr = (unsigned long long) &tss;
-
- /* setup task state segment */
- memset(&tss, 0, sizeof(tss));
- tss.ss0 = DATA_SELECTOR;
- tss.esp0 = (unsigned) stack_top;
- tss.iomap_base = offsetof(struct tss, iomap);
- tss.iomap[sizeof(tss.iomap)-1] = 0xff;
-
- /* initialize gdt's tss selector */
- gdt[TSS_SELECTOR / sizeof(gdt[0])] |=
- ((addr & 0xFF000000) << (56-24)) |
- ((addr & 0x00FF0000) << (32-16)) |
- ((addr & 0x0000FFFF) << (16)) |
- (sizeof(tss) - 1);
-
- /* switch to our own gdt and set current tss */
- __asm__ __volatile__ ("lgdt %0" : : "m" (gdtr));
- __asm__ __volatile__ ("movl %%eax,%%ds;"
- "movl %%eax,%%es;"
- "movl %%eax,%%fs;"
- "movl %%eax,%%gs;"
- "movl %%eax,%%ss" : : "a" (DATA_SELECTOR));
-
- __asm__ __volatile__ ("ljmp %0,$1f; 1:" : : "i" (CODE_SELECTOR));
-
- __asm__ __volatile__ ("ltr %%ax" : : "a" (TSS_SELECTOR));
-}
-
-void
-set_intr_gate(int i, unsigned handler)
-{
- unsigned long long addr = handler;
-
- idt[i] = ((addr & 0xFFFF0000ULL) << 32) | (0x8E00ULL << 32) |
- (addr & 0xFFFFULL) | (CODE_SELECTOR << 16);
-}
-
-void
-setup_idt(void)
-{
- int i;
-
- for (i = 0; i < NR_TRAPS; i++)
- set_intr_gate(i, trap_handlers[i]);
- __asm__ __volatile__ ("lidt %0" : : "m" (idtr));
-}
-
-void
-setup_pic(void)
-{
- /* mask all interrupts */
- outb(PIC_MASTER + PIC_IMR, 0xFF);
- outb(PIC_SLAVE + PIC_IMR, 0xFF);
-
- /* setup master PIC */
- outb(PIC_MASTER + PIC_CMD, 0x11); /* edge triggered, cascade, ICW4 */
- outb(PIC_MASTER + PIC_IMR, NR_EXCEPTION_HANDLER);
- outb(PIC_MASTER + PIC_IMR, 1 << 2); /* slave on channel 2 */
- outb(PIC_MASTER + PIC_IMR, 0x01);
-
- /* setup slave PIC */
- outb(PIC_SLAVE + PIC_CMD, 0x11); /* edge triggered, cascade, ICW4 */
- outb(PIC_SLAVE + PIC_IMR, NR_EXCEPTION_HANDLER + 8);
- outb(PIC_SLAVE + PIC_IMR, 0x02); /* slave identity is 2 */
- outb(PIC_SLAVE + PIC_IMR, 0x01);
-
- /* enable all interrupts */
- outb(PIC_MASTER + PIC_IMR, 0);
- outb(PIC_SLAVE + PIC_IMR, 0);
-}
-
-void
-setiomap(int port)
-{
- tss.iomap[port >> 3] |= 1 << (port & 7);
-}
-
-void
-enter_real_mode(struct regs *regs)
-{
- /* mask off TSS busy bit */
- gdt[TSS_SELECTOR / sizeof(gdt[0])] &= ~0x0000020000000000ULL;
-
- /* start 8086 emulation of BIOS */
- if (initialize_real_mode) {
- initialize_real_mode = 0;
- regs->eflags |= EFLAGS_VM | 0x02;
- regs->ves = regs->vds = regs->vfs = regs->vgs = 0xF000;
- if (booting_cpu == 0) {
- regs->cs = 0xF000; /* ROM BIOS POST entry point */
- regs->eip = 0xFFF0;
- } else {
- regs->cs = booting_vector << 8; /* AP entry point */
- regs->eip = 0;
- }
-
- regs->uesp = regs->uss = 0;
- regs->eax = regs->ecx = regs->edx = regs->ebx = 0;
- regs->esp = regs->ebp = regs->esi = regs->edi = 0;
-
- /* intercept accesses to the PIC */
- setiomap(PIC_MASTER+PIC_CMD);
- setiomap(PIC_MASTER+PIC_IMR);
- setiomap(PIC_SLAVE+PIC_CMD);
- setiomap(PIC_SLAVE+PIC_IMR);
-
- printf("Starting emulated 16-bit real-mode: ip=%04x:%04x\n",
- regs->cs, regs->eip);
-
- mode = VM86_REAL; /* becomes previous mode */
- set_mode(regs, VM86_REAL);
-
- /* this should get us into 16-bit mode */
- return;
- }
-
- /* go from protected to real mode */
- set_mode(regs, VM86_PROTECTED_TO_REAL);
- emulate(regs);
- if (mode != VM86_REAL)
- panic("failed to emulate between clear PE and long jump.\n");
-}
-
-/*
- * Setup the environment for VMX assist.
- * This environment consists of flat segments (code and data),
- * its own gdt, idt, and tr.
- */
-void
-setup_ctx(void)
-{
- struct vmx_assist_context *c = &newctx;
-
- memset(c, 0, sizeof(*c));
- c->eip = (unsigned long) switch_to_real_mode;
- c->esp = (unsigned) stack_top;
- c->eflags = 0x2; /* no interrupts, please */
-
- /*
- * Obviously, vmx assist is not running with CR0_PE disabled.
- * The reason why the vmx assist cr0 has CR0.PE disabled is
- * that a transtion to CR0.PE causes a world switch. It seems
- * more natural to enable CR0.PE to cause a world switch to
- * protected mode rather than disabling it.
- */
- c->cr0 = (get_cr0() | CR0_NE) & ~CR0_PE;
- c->cr3 = 0;
- c->cr4 = get_cr4();
-
- c->idtr_limit = sizeof(idt)-1;
- c->idtr_base = (unsigned long) &idt;
-
- c->gdtr_limit = sizeof(gdt)-1;
- c->gdtr_base = (unsigned long) &gdt;
-
- c->cs_sel = CODE_SELECTOR;
- c->cs_limit = 0xFFFFFFFF;
- c->cs_base = 0;
- c->cs_arbytes.fields.seg_type = 0xb;
- c->cs_arbytes.fields.s = 1;
- c->cs_arbytes.fields.dpl = 0;
- c->cs_arbytes.fields.p = 1;
- c->cs_arbytes.fields.avl = 0;
- c->cs_arbytes.fields.default_ops_size = 1;
- c->cs_arbytes.fields.g = 1;
-
- c->ds_sel = DATA_SELECTOR;
- c->ds_limit = 0xFFFFFFFF;
- c->ds_base = 0;
- c->ds_arbytes = c->cs_arbytes;
- c->ds_arbytes.fields.seg_type = 0x3;
-
- c->es_sel = DATA_SELECTOR;
- c->es_limit = 0xFFFFFFFF;
- c->es_base = 0;
- c->es_arbytes = c->ds_arbytes;
-
- c->ss_sel = DATA_SELECTOR;
- c->ss_limit = 0xFFFFFFFF;
- c->ss_base = 0;
- c->ss_arbytes = c->ds_arbytes;
-
- c->fs_sel = DATA_SELECTOR;
- c->fs_limit = 0xFFFFFFFF;
- c->fs_base = 0;
- c->fs_arbytes = c->ds_arbytes;
-
- c->gs_sel = DATA_SELECTOR;
- c->gs_limit = 0xFFFFFFFF;
- c->gs_base = 0;
- c->gs_arbytes = c->ds_arbytes;
-
- c->tr_sel = TSS_SELECTOR;
- c->tr_limit = sizeof(tss) - 1;
- c->tr_base = (unsigned long) &tss;
- c->tr_arbytes.fields.seg_type = 0xb; /* 0x9 | 0x2 (busy) */
- c->tr_arbytes.fields.s = 0;
- c->tr_arbytes.fields.dpl = 0;
- c->tr_arbytes.fields.p = 1;
- c->tr_arbytes.fields.avl = 0;
- c->tr_arbytes.fields.default_ops_size = 0;
- c->tr_arbytes.fields.g = 0;
-
- c->ldtr_sel = 0;
- c->ldtr_limit = 0;
- c->ldtr_base = 0;
- c->ldtr_arbytes = c->ds_arbytes;
- c->ldtr_arbytes.fields.seg_type = 0x2;
- c->ldtr_arbytes.fields.s = 0;
- c->ldtr_arbytes.fields.dpl = 0;
- c->ldtr_arbytes.fields.p = 1;
- c->ldtr_arbytes.fields.avl = 0;
- c->ldtr_arbytes.fields.default_ops_size = 0;
- c->ldtr_arbytes.fields.g = 0;
-}
-
-/*
- * Start BIOS by causing a world switch to vmxassist, which causes
- * VM8086 to be enabled and control is transfered to F000:FFF0.
- */
-void
-start_bios(void)
-{
- if (booting_cpu == 0)
- printf("Start BIOS ...\n");
- else
- printf("Start AP %d from %08x ...\n",
- booting_cpu, booting_vector << 12);
-
- initialize_real_mode = 1;
- set_cr0(get_cr0() & ~CR0_PE);
- panic("vmxassist returned"); /* "cannot happen" */
-}
-
-int
-main(void)
-{
- if (booting_cpu == 0)
- banner();
-
- setup_gdt();
- setup_idt();
-
- set_cr4(get_cr4() | CR4_VME);
-
- setup_ctx();
-
- if (booting_cpu == 0)
- setup_pic();
-
- start_bios();
-
- return 0;
-}
diff -r f8db1c6baad9 -r 9d0e86d8c1d1 tools/firmware/vmxassist/trap.S
--- a/tools/firmware/vmxassist/trap.S Tue Feb 05 23:27:12 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,179 +0,0 @@
-/*
- * trap.S: Trap and world switch handlers
- *
- * Leendert van Doorn, leendert@xxxxxxxxxxxxxx
- * 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 */
- 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 36(%ebp)
- pushl 32(%ebp)
- call trap /* trap(trapno, errno, regs) */
- addl $12, %esp
-
-trap_return:
- popal
- 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
- 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"
-
diff -r f8db1c6baad9 -r 9d0e86d8c1d1 tools/firmware/vmxassist/util.c
--- a/tools/firmware/vmxassist/util.c Tue Feb 05 23:27:12 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,430 +0,0 @@
-/*
- * util.c: Commonly used utility functions.
- *
- * Leendert van Doorn, leendert@xxxxxxxxxxxxxx
- * 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 <stdarg.h>
-
-#include "util.h"
-#include "machine.h"
-
-#define isdigit(c) ((c) >= '0' && (c) <= '9')
-#define min(a, b) ((a) < (b) ? (a) : (b))
-
-static void putchar(int);
-static char *printnum(char *, unsigned long, int);
-static void _doprint(void (*)(int), const char *, va_list);
-
-void
-cpuid_addr_value(uint64_t addr, uint64_t *value)
-{
- uint32_t addr_low = (uint32_t)addr;
- uint32_t addr_high = (uint32_t)(addr >> 32);
- uint32_t value_low, value_high;
- static unsigned int addr_leaf;
-
- if (!addr_leaf) {
- unsigned int eax, ebx, ecx, edx;
- __asm__ __volatile__(
- "cpuid"
- : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
- : "0" (0x40000000));
- addr_leaf = eax + 1;
- }
-
- __asm__ __volatile__(
- "cpuid"
- : "=c" (value_low), "=d" (value_high)
- : "a" (addr_leaf), "0" (addr_low), "1" (addr_high)
- : "ebx");
-
- *value = (uint64_t)value_high << 32 | value_low;
-}
-
-void
-dump_regs(struct regs *regs)
-{
- printf("eax %8x ecx %8x edx %8x ebx %8x\n",
- regs->eax, regs->ecx, regs->edx, regs->ebx);
- printf("esp %8x ebp %8x esi %8x edi %8x\n",
- regs->esp, regs->ebp, regs->esi, regs->edi);
- printf("trapno %8x errno %8x\n", regs->trapno, regs->errno);
- printf("eip %8x cs %8x eflags %8x\n",
- regs->eip, regs->cs, regs->eflags);
- printf("uesp %8x uss %8x\n",
- regs->uesp, regs->uss);
- printf("ves %8x vds %8x vfs %8x vgs %8x\n",
- regs->ves, regs->vds, regs->vfs, regs->vgs);
-
- printf("cr0 %8lx cr2 %8x cr3 %8lx cr4 %8lx\n\n",
- (long)oldctx.cr0, get_cr2(),
- (long)oldctx.cr3, (long)oldctx.cr4);
-}
-
-#ifdef DEBUG
-void
-hexdump(unsigned char *data, int sz)
-{
- unsigned char *d;
- int i;
-
- for (d = data; sz > 0; d += 16, sz -= 16) {
- int n = sz > 16 ? 16 : sz;
-
- printf("%08x: ", (unsigned)d);
- for (i = 0; i < n; i++)
- printf("%02x%c", d[i], i == 7 ? '-' : ' ');
- for (; i < 16; i++)
- printf(" %c", i == 7 ? '-' : ' ');
- printf(" ");
- for (i = 0; i < n; i++)
- printf("%c", d[i] >= ' ' && d[i] <= '~' ? d[i] : '.');
- printf("\n");
- }
-}
-
-void
-print_e820_map(struct e820entry *map, int entries)
-{
- struct e820entry *m;
-
- if (entries > 32)
- entries = 32;
-
- for (m = map; m < &map[entries]; m++) {
- printf("%08lx%08lx - %08lx%08lx ",
- (unsigned long) (m->addr >> 32),
- (unsigned long) (m->addr),
- (unsigned long) ((m->addr+m->size) >> 32),
- (unsigned long) ((m->addr+m->size)));
-
- switch (m->type) {
- case E820_RAM:
- printf("(RAM)\n"); break;
- case E820_RESERVED:
- printf("(Reserved)\n"); break;
- case E820_ACPI:
- printf("(ACPI Data)\n"); break;
- case E820_NVS:
- printf("(ACPI NVS)\n"); break;
- default:
- printf("(Type %ld)\n", m->type); break;
- }
- }
-}
-
-void
-dump_dtr(unsigned long addr, unsigned long size)
-{
- unsigned long long entry;
- unsigned long base, limit;
- int i;
-
- for (i = 0; i < size; i += 8) {
- entry = ((unsigned long long *) addr)[i >> 3];
- base = (((entry >> (56-24)) & 0xFF000000) |
- ((entry >> (32-16)) & 0x00FF0000) |
- ((entry >> ( 16)) & 0x0000FFFF));
- limit = (((entry >> (48-16)) & 0x000F0000) |
- ((entry ) & 0x0000FFFF));
- if (entry & (1ULL << (23+32))) /* G */
- limit = (limit << 12) | 0xFFF;
-
- printf("[0x%x] = 0x%08x%08x, base 0x%lx, limit 0x%lx\n", i,
- (unsigned)(entry >> 32), (unsigned)(entry),
- base, limit);
- }
-}
-
-void
-dump_vmx_context(struct vmx_assist_context *c)
-{
- printf("eip 0x%lx, esp 0x%lx, eflags 0x%lx\n",
- (long) c->eip, (long) c->esp, (long) c->eflags);
-
- printf("cr0 0x%lx, cr3 0x%lx, cr4 0x%lx\n",
- (long)c->cr0, (long)c->cr3, (long)c->cr4);
-
- printf("idtr: limit 0x%lx, base 0x%lx\n",
- (long)c->idtr_limit, (long)c->idtr_base);
-
- printf("gdtr: limit 0x%lx, base 0x%lx\n",
- (long)c->gdtr_limit, (long)c->gdtr_base);
-
- printf("cs: sel 0x%lx, limit 0x%lx, base 0x%lx\n",
- (long)c->cs_sel, (long)c->cs_limit, (long)c->cs_base);
- printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n",
- c->cs_arbytes.fields.seg_type,
- c->cs_arbytes.fields.s,
- c->cs_arbytes.fields.dpl,
- c->cs_arbytes.fields.p,
- c->cs_arbytes.fields.avl,
- c->cs_arbytes.fields.default_ops_size,
- c->cs_arbytes.fields.g,
- c->cs_arbytes.fields.null_bit);
-
- printf("ds: sel 0x%lx, limit 0x%lx, base 0x%lx\n",
- (long)c->ds_sel, (long)c->ds_limit, (long)c->ds_base);
- printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n",
- c->ds_arbytes.fields.seg_type,
- c->ds_arbytes.fields.s,
- c->ds_arbytes.fields.dpl,
- c->ds_arbytes.fields.p,
- c->ds_arbytes.fields.avl,
- c->ds_arbytes.fields.default_ops_size,
- c->ds_arbytes.fields.g,
- c->ds_arbytes.fields.null_bit);
-
- printf("es: sel 0x%lx, limit 0x%lx, base 0x%lx\n",
- (long)c->es_sel, (long)c->es_limit, (long)c->es_base);
- printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n",
- c->es_arbytes.fields.seg_type,
- c->es_arbytes.fields.s,
- c->es_arbytes.fields.dpl,
- c->es_arbytes.fields.p,
- c->es_arbytes.fields.avl,
- c->es_arbytes.fields.default_ops_size,
- c->es_arbytes.fields.g,
- c->es_arbytes.fields.null_bit);
-
- printf("ss: sel 0x%lx, limit 0x%lx, base 0x%lx\n",
- (long)c->ss_sel, (long)c->ss_limit, (long)c->ss_base);
- printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n",
- c->ss_arbytes.fields.seg_type,
- c->ss_arbytes.fields.s,
- c->ss_arbytes.fields.dpl,
- c->ss_arbytes.fields.p,
- c->ss_arbytes.fields.avl,
- c->ss_arbytes.fields.default_ops_size,
- c->ss_arbytes.fields.g,
- c->ss_arbytes.fields.null_bit);
-
- printf("fs: sel 0x%lx, limit 0x%lx, base 0x%lx\n",
- (long)c->fs_sel, (long)c->fs_limit, (long)c->fs_base);
- printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n",
- c->fs_arbytes.fields.seg_type,
- c->fs_arbytes.fields.s,
- c->fs_arbytes.fields.dpl,
- c->fs_arbytes.fields.p,
- c->fs_arbytes.fields.avl,
- c->fs_arbytes.fields.default_ops_size,
- c->fs_arbytes.fields.g,
- c->fs_arbytes.fields.null_bit);
-
- printf("gs: sel 0x%lx, limit 0x%lx, base 0x%lx\n",
- (long)c->gs_sel, (long)c->gs_limit, (long)c->gs_base);
- printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n",
- c->gs_arbytes.fields.seg_type,
- c->gs_arbytes.fields.s,
- c->gs_arbytes.fields.dpl,
- c->gs_arbytes.fields.p,
- c->gs_arbytes.fields.avl,
- c->gs_arbytes.fields.default_ops_size,
- c->gs_arbytes.fields.g,
- c->gs_arbytes.fields.null_bit);
-
- printf("tr: sel 0x%lx, limit 0x%lx, base 0x%lx\n",
- (long)c->tr_sel, (long)c->tr_limit, (long)c->tr_base);
- printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n",
- c->tr_arbytes.fields.seg_type,
- c->tr_arbytes.fields.s,
- c->tr_arbytes.fields.dpl,
- c->tr_arbytes.fields.p,
- c->tr_arbytes.fields.avl,
- c->tr_arbytes.fields.default_ops_size,
- c->tr_arbytes.fields.g,
- c->tr_arbytes.fields.null_bit);
-
- printf("ldtr: sel 0x%lx, limit 0x%lx, base 0x%lx\n",
- (long)c->ldtr_sel, (long)c->ldtr_limit, (long)c->ldtr_base);
- printf("\ttype %d, s %d, dpl %d, p %d, avl %d, ops %d, g %d, nul %d\n",
- c->ldtr_arbytes.fields.seg_type,
- c->ldtr_arbytes.fields.s,
- c->ldtr_arbytes.fields.dpl,
- c->ldtr_arbytes.fields.p,
- c->ldtr_arbytes.fields.avl,
- c->ldtr_arbytes.fields.default_ops_size,
- c->ldtr_arbytes.fields.g,
- c->ldtr_arbytes.fields.null_bit);
-
- printf("GDTR <0x%lx,0x%lx>:\n",
- (long)c->gdtr_base, (long)c->gdtr_limit);
- dump_dtr(c->gdtr_base, c->gdtr_limit);
-}
-#endif /* DEBUG */
-
-/*
- * Lightweight printf that doesn't drag in everything under the sun.
- */
-int
-printf(const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- _doprint(putchar, fmt, ap);
- va_end(ap);
- return 0; /* for gcc compat */
-}
-
-int
-vprintf(const char *fmt, va_list ap)
-{
- _doprint(putchar, fmt, ap);
- return 0; /* for gcc compat */
-}
-
-void
-panic(const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- _doprint(putchar, fmt, ap);
- putchar('\n');
- va_end(ap);
- halt();
-}
-
-unsigned
-strlen(const char *s)
-{
- const char *q = s;
-
- while (*s++)
- /* void */;
- return s - q - 1;
-}
-
-static void
-putchar(int ch)
-{
- outb(0xE9, ch);
-}
-
-/*
- * A stripped down version of doprint,
- * but still powerful enough for most tasks.
- */
-static void
-_doprint(void (*put)(int), const char *fmt, va_list ap)
-{
- register char *str, c;
- int lflag, zflag, nflag;
- char buffer[17];
- unsigned value;
- int i, slen, pad;
-
- for ( ; *fmt != '\0'; fmt++) {
- pad = zflag = nflag = lflag = 0;
- if (*fmt == '%') {
- c = *++fmt;
- if (c == '-' || isdigit(c)) {
- if (c == '-') {
- nflag = 1;
- c = *++fmt;
- }
- zflag = c == '0';
- for (pad = 0; isdigit(c); c = *++fmt)
- pad = (pad * 10) + c - '0';
- }
- if (c == 'l') { /* long extension */
- lflag = 1;
- c = *++fmt;
- }
- if (c == 'd' || c == 'u' || c == 'o' || c == 'x') {
- if (lflag)
- value = va_arg(ap, unsigned);
- else
- value = (unsigned) va_arg(ap, unsigned
int);
- str = buffer;
- printnum(str, value,
- c == 'o' ? 8 : (c == 'x' ? 16 : 10));
- goto printn;
- } else if (c == 'O' || c == 'D' || c == 'X') {
- value = va_arg(ap, unsigned);
- str = buffer;
- printnum(str, value,
- c == 'O' ? 8 : (c == 'X' ? 16 : 10));
- printn:
- slen = strlen(str);
- for (i = pad - slen; i > 0; i--)
- put(zflag ? '0' : ' ');
- while (*str) put(*str++);
- } else if (c == 's') {
- str = va_arg(ap, char *);
- slen = strlen(str);
- if (nflag == 0)
- for (i = pad - slen; i > 0; i--) put('
');
- while (*str) put(*str++);
- if (nflag)
- for (i = pad - slen; i > 0; i--) put('
');
- } else if (c == 'c')
- put(va_arg(ap, int));
- else
- put(*fmt);
- } else
- put(*fmt);
- }
-}
-
-static char *
-printnum(char *p, unsigned long num, int base)
-{
- unsigned long n;
-
- if ((n = num/base) > 0)
- p = printnum(p, n, base);
- *p++ = "0123456789ABCDEF"[(int)(num % base)];
- *p = '\0';
- return p;
-}
-
-void *
-memset(void *s, int c, unsigned n)
-{
- int t0, t1;
-
- __asm__ __volatile__ ("cld; rep; stosb"
- : "=&c" (t0), "=&D" (t1)
- : "a" (c), "1" (s), "0" (n)
- : "memory");
- return s;
-}
-
-void *
-memcpy(void *dest, const void *src, unsigned n)
-{
- int t0, t1, t2;
-
- __asm__ __volatile__(
- "cld\n"
- "rep; movsl\n"
- "testb $2,%b4\n"
- "je 1f\n"
- "movsw\n"
- "1: testb $1,%b4\n"
- "je 2f\n"
- "movsb\n"
- "2:"
- : "=&c" (t0), "=&D" (t1), "=&S" (t2)
- : "0" (n/4), "q" (n), "1" ((long) dest), "2" ((long) src)
- : "memory"
- );
- return dest;
-}
-
diff -r f8db1c6baad9 -r 9d0e86d8c1d1 tools/firmware/vmxassist/util.h
--- a/tools/firmware/vmxassist/util.h Tue Feb 05 23:27:12 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,45 +0,0 @@
-/*
- * util.h: Useful utility functions.
- *
- * Leendert van Doorn, leendert@xxxxxxxxxxxxxx
- * 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.
- */
-#ifndef __UTIL_H__
-#define __UTIL_H__
-
-#include <stdarg.h>
-#include <vm86.h>
-
-#define offsetof(type, member) ((unsigned) &((type *)0)->member)
-
-struct vmx_assist_context;
-
-#include "../hvmloader/e820.h"
-
-extern void cpuid_addr_value(uint64_t addr, uint64_t *value);
-extern void hexdump(unsigned char *, int);
-extern void dump_regs(struct regs *);
-extern void dump_vmx_context(struct vmx_assist_context *);
-extern void print_e820_map(struct e820entry *, int);
-extern void dump_dtr(unsigned long, unsigned long);
-extern void *memcpy(void *, const void *, unsigned);
-extern void *memset(void *, int, unsigned);
-extern int printf(const char *fmt, ...);
-extern int vprintf(const char *fmt, va_list ap);
-extern void panic(const char *format, ...);
-extern void halt(void);
-
-#endif /* __UTIL_H__ */
diff -r f8db1c6baad9 -r 9d0e86d8c1d1 tools/firmware/vmxassist/vm86.c
--- a/tools/firmware/vmxassist/vm86.c Tue Feb 05 23:27:12 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,1992 +0,0 @@
-/*
- * vm86.c: A vm86 emulator. The main purpose of this emulator is to do as
- * little work as possible.
- *
- * Leendert van Doorn, leendert@xxxxxxxxxxxxxx
- * Copyright (c) 2005-2006, 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 "vm86.h"
-#include "util.h"
-#include "machine.h"
-
-#define HIGHMEM (1 << 20) /* 1MB */
-#define MASK16(v) ((v) & 0xFFFF)
-
-#define DATA32 0x0001
-#define ADDR32 0x0002
-#define SEG_CS 0x0004
-#define SEG_DS 0x0008
-#define SEG_ES 0x0010
-#define SEG_SS 0x0020
-#define SEG_FS 0x0040
-#define SEG_GS 0x0080
-#define REP 0x0100
-
-static unsigned prev_eip = 0;
-enum vm86_mode mode = 0;
-
-static struct regs saved_rm_regs;
-
-#ifdef DEBUG
-int traceset = 0;
-
-char *states[] = {
- "<VM86_REAL>",
- "<VM86_REAL_TO_PROTECTED>",
- "<VM86_PROTECTED_TO_REAL>",
- "<VM86_PROTECTED>"
-};
-
-static char *rnames[] = { "ax", "cx", "dx", "bx", "sp", "bp", "si", "di" };
-#endif /* DEBUG */
-
-#define PDE_PS (1 << 7)
-#define PT_ENTRY_PRESENT 0x1
-
-/* We only support access to <=4G physical memory due to 1:1 mapping */
-static uint64_t
-guest_linear_to_phys(uint32_t base)
-{
- uint32_t gcr3 = oldctx.cr3;
- uint64_t l2_mfn;
- uint64_t l1_mfn;
- uint64_t l0_mfn;
-
- if (!(oldctx.cr0 & CR0_PG))
- return base;
-
- if (!(oldctx.cr4 & CR4_PAE)) {
- l1_mfn = ((uint32_t *)(long)gcr3)[(base >> 22) & 0x3ff];
- if (!(l1_mfn & PT_ENTRY_PRESENT))
- panic("l2 entry not present\n");
-
- if ((oldctx.cr4 & CR4_PSE) && (l1_mfn & PDE_PS)) {
- l0_mfn = l1_mfn & 0xffc00000;
- return l0_mfn + (base & 0x3fffff);
- }
-
- l1_mfn &= 0xfffff000;
-
- l0_mfn = ((uint32_t *)(long)l1_mfn)[(base >> 12) & 0x3ff];
- if (!(l0_mfn & PT_ENTRY_PRESENT))
- panic("l1 entry not present\n");
- l0_mfn &= 0xfffff000;
-
- return l0_mfn + (base & 0xfff);
- } else {
- l2_mfn = ((uint64_t *)(long)gcr3)[(base >> 30) & 0x3];
- if (!(l2_mfn & PT_ENTRY_PRESENT))
- panic("l3 entry not present\n");
- l2_mfn &= 0xffffff000ULL;
-
- if (l2_mfn & 0xf00000000ULL) {
- printf("l2 page above 4G\n");
- cpuid_addr_value(l2_mfn + 8 * ((base >> 21) & 0x1ff),
&l1_mfn);
- } else
- l1_mfn = ((uint64_t *)(long)l2_mfn)[(base >> 21) &
0x1ff];
- if (!(l1_mfn & PT_ENTRY_PRESENT))
- panic("l2 entry not present\n");
-
- if (l1_mfn & PDE_PS) { /* CR4.PSE is ignored in PAE mode */
- l0_mfn = l1_mfn & 0xfffe00000ULL;
- return l0_mfn + (base & 0x1fffff);
- }
-
- l1_mfn &= 0xffffff000ULL;
-
- if (l1_mfn & 0xf00000000ULL) {
- printf("l1 page above 4G\n");
- cpuid_addr_value(l1_mfn + 8 * ((base >> 12) & 0x1ff),
&l0_mfn);
- } else
- l0_mfn = ((uint64_t *)(long)l1_mfn)[(base >> 12) &
0x1ff];
- if (!(l0_mfn & PT_ENTRY_PRESENT))
- panic("l1 entry not present\n");
-
- l0_mfn &= 0xffffff000ULL;
-
- return l0_mfn + (base & 0xfff);
- }
-}
-
-static unsigned
-address(struct regs *regs, unsigned seg, unsigned off)
-{
- uint64_t gdt_phys_base;
- unsigned long long entry;
- unsigned seg_base, seg_limit;
- unsigned entry_low, entry_high;
-
- if (seg == 0) {
- if (mode == VM86_REAL || mode == VM86_REAL_TO_PROTECTED)
- return off;
- else
- panic("segment is zero, but not in real mode!\n");
- }
-
- if (mode == VM86_REAL || seg > oldctx.gdtr_limit ||
- (mode == VM86_REAL_TO_PROTECTED && regs->cs == seg))
- return ((seg & 0xFFFF) << 4) + off;
-
- gdt_phys_base = guest_linear_to_phys(oldctx.gdtr_base);
- if (gdt_phys_base != (uint32_t)gdt_phys_base) {
- printf("gdt base address above 4G\n");
- cpuid_addr_value(gdt_phys_base + 8 * (seg >> 3), &entry);
- } else
- entry = ((unsigned long long *)(long)gdt_phys_base)[seg >> 3];
-
- entry_high = entry >> 32;
- entry_low = entry & 0xFFFFFFFF;
-
- seg_base = (entry_high & 0xFF000000) | ((entry >> 16) & 0xFFFFFF);
- seg_limit = (entry_high & 0xF0000) | (entry_low & 0xFFFF);
-
- if (entry_high & 0x8000 &&
- ((entry_high & 0x800000 && off >> 12 <= seg_limit) ||
- (!(entry_high & 0x800000) && off <= seg_limit)))
- return seg_base + off;
-
- panic("should never reach here in function address():\n\t"
- "entry=0x%08x%08x, mode=%d, seg=0x%08x, offset=0x%08x\n",
- entry_high, entry_low, mode, seg, off);
-
- return 0;
-}
-
-#ifdef DEBUG
-void
-trace(struct regs *regs, int adjust, char *fmt, ...)
-{
- unsigned off = regs->eip - adjust;
- va_list ap;
-
- if ((traceset & (1 << mode)) &&
- (mode == VM86_REAL_TO_PROTECTED || mode == VM86_REAL)) {
- /* 16-bit, seg:off addressing */
- unsigned addr = address(regs, regs->cs, off);
- printf("0x%08x: 0x%x:0x%04x ", addr, regs->cs, off);
- printf("(%d) ", mode);
- va_start(ap, fmt);
- vprintf(fmt, ap);
- va_end(ap);
- printf("\n");
- }
- if ((traceset & (1 << mode)) &&
- (mode == VM86_PROTECTED_TO_REAL || mode == VM86_PROTECTED)) {
- /* 16-bit, gdt addressing */
- unsigned addr = address(regs, regs->cs, off);
- printf("0x%08x: 0x%x:0x%08x ", addr, regs->cs, off);
- printf("(%d) ", mode);
- va_start(ap, fmt);
- vprintf(fmt, ap);
- va_end(ap);
- printf("\n");
- }
-}
-#endif /* DEBUG */
-
-static inline unsigned
-read32(unsigned addr)
-{
- return *(unsigned long *) addr;
-}
-
-static inline unsigned
-read16(unsigned addr)
-{
- return *(unsigned short *) addr;
-}
-
-static inline unsigned
-read8(unsigned addr)
-{
- return *(unsigned char *) addr;
-}
-
-static inline void
-write32(unsigned addr, unsigned value)
-{
- *(unsigned long *) addr = value;
-}
-
-static inline void
-write16(unsigned addr, unsigned value)
-{
- *(unsigned short *) addr = value;
-}
-
-static inline void
-write8(unsigned addr, unsigned value)
-{
- *(unsigned char *) addr = value;
-}
-
-static inline void
-push32(struct regs *regs, unsigned value)
-{
- regs->uesp -= 4;
- write32(address(regs, regs->uss, MASK16(regs->uesp)), value);
-}
-
-static inline void
-push16(struct regs *regs, unsigned value)
-{
- regs->uesp -= 2;
- write16(address(regs, regs->uss, MASK16(regs->uesp)), value);
-}
-
-static inline unsigned
-pop32(struct regs *regs)
-{
- unsigned value = read32(address(regs, regs->uss, MASK16(regs->uesp)));
- regs->uesp += 4;
- return value;
-}
-
-static inline unsigned
-pop16(struct regs *regs)
-{
- unsigned value = read16(address(regs, regs->uss, MASK16(regs->uesp)));
- regs->uesp += 2;
- return value;
-}
-
-static inline unsigned
-fetch32(struct regs *regs)
-{
- unsigned addr = address(regs, regs->cs, MASK16(regs->eip));
-
- regs->eip += 4;
- return read32(addr);
-}
-
-static inline unsigned
-fetch16(struct regs *regs)
-{
- unsigned addr = address(regs, regs->cs, MASK16(regs->eip));
-
- regs->eip += 2;
- return read16(addr);
-}
-
-static inline unsigned
-fetch8(struct regs *regs)
-{
- unsigned addr = address(regs, regs->cs, MASK16(regs->eip));
-
- regs->eip++;
- return read8(addr);
-}
-
-static unsigned
-getreg32(struct regs *regs, int r)
-{
- switch (r & 7) {
- case 0: return regs->eax;
- case 1: return regs->ecx;
- case 2: return regs->edx;
- case 3: return regs->ebx;
- case 4: return regs->uesp;
- case 5: return regs->ebp;
- case 6: return regs->esi;
- case 7: return regs->edi;
- }
- return ~0;
-}
-
-static unsigned
-getreg16(struct regs *regs, int r)
-{
- return MASK16(getreg32(regs, r));
-}
-
-static unsigned
-getreg8(struct regs *regs, int r)
-{
- switch (r & 7) {
- case 0: return regs->eax & 0xFF; /* al */
- case 1: return regs->ecx & 0xFF; /* cl */
- case 2: return regs->edx & 0xFF; /* dl */
- case 3: return regs->ebx & 0xFF; /* bl */
- case 4: return (regs->eax >> 8) & 0xFF; /* ah */
- case 5: return (regs->ecx >> 8) & 0xFF; /* ch */
- case 6: return (regs->edx >> 8) & 0xFF; /* dh */
- case 7: return (regs->ebx >> 8) & 0xFF; /* bh */
- }
- return ~0;
-}
-
-static void
-setreg32(struct regs *regs, int r, unsigned v)
-{
- switch (r & 7) {
- case 0: regs->eax = v; break;
- case 1: regs->ecx = v; break;
- case 2: regs->edx = v; break;
- case 3: regs->ebx = v; break;
- case 4: regs->uesp = v; break;
- case 5: regs->ebp = v; break;
- case 6: regs->esi = v; break;
- case 7: regs->edi = v; break;
- }
-}
-
-static void
-setreg16(struct regs *regs, int r, unsigned v)
-{
- setreg32(regs, r, (getreg32(regs, r) & ~0xFFFF) | MASK16(v));
-}
-
-static void
-setreg8(struct regs *regs, int r, unsigned v)
-{
- v &= 0xFF;
- switch (r & 7) {
- case 0: regs->eax = (regs->eax & ~0xFF) | v; break;
- case 1: regs->ecx = (regs->ecx & ~0xFF) | v; break;
- case 2: regs->edx = (regs->edx & ~0xFF) | v; break;
- case 3: regs->ebx = (regs->ebx & ~0xFF) | v; break;
- case 4: regs->eax = (regs->eax & ~0xFF00) | (v << 8); break;
- case 5: regs->ecx = (regs->ecx & ~0xFF00) | (v << 8); break;
- case 6: regs->edx = (regs->edx & ~0xFF00) | (v << 8); break;
- case 7: regs->ebx = (regs->ebx & ~0xFF00) | (v << 8); break;
- }
-}
-
-static unsigned
-segment(unsigned prefix, struct regs *regs, unsigned seg)
-{
- if (prefix & SEG_ES)
- seg = regs->ves;
- if (prefix & SEG_DS)
- seg = regs->vds;
- if (prefix & SEG_CS)
- seg = regs->cs;
- if (prefix & SEG_SS)
- seg = regs->uss;
- if (prefix & SEG_FS)
- seg = regs->vfs;
- if (prefix & SEG_GS)
- seg = regs->vgs;
- return seg;
-}
-
-static unsigned
-sib(struct regs *regs, int mod, unsigned byte)
-{
- unsigned scale = (byte >> 6) & 3;
- int index = (byte >> 3) & 7;
- int base = byte & 7;
- unsigned addr = 0;
-
- switch (mod) {
- case 0:
- if (base == 5)
- addr = fetch32(regs);
- else
- addr = getreg32(regs, base);
- break;
- case 1:
- addr = getreg32(regs, base) + (char) fetch8(regs);
- break;
- case 2:
- addr = getreg32(regs, base) + fetch32(regs);
- break;
- }
-
- if (index != 4)
- addr += getreg32(regs, index) << scale;
-
- return addr;
-}
-
-/*
- * Operand (modrm) decode
- */
-static unsigned
-operand(unsigned prefix, struct regs *regs, unsigned modrm)
-{
- int mod, disp = 0, seg;
-
- seg = segment(prefix, regs, regs->vds);
-
- if (prefix & ADDR32) { /* 32-bit addressing */
- switch ((mod = (modrm >> 6) & 3)) {
- case 0:
- switch (modrm & 7) {
- case 0: return address(regs, seg, regs->eax);
- case 1: return address(regs, seg, regs->ecx);
- case 2: return address(regs, seg, regs->edx);
- case 3: return address(regs, seg, regs->ebx);
- case 4: return address(regs, seg,
- sib(regs, mod,
fetch8(regs)));
- case 5: return address(regs, seg, fetch32(regs));
- case 6: return address(regs, seg, regs->esi);
- case 7: return address(regs, seg, regs->edi);
- }
- break;
- case 1:
- case 2:
- if ((modrm & 7) != 4) {
- if (mod == 1)
- disp = (char) fetch8(regs);
- else
- disp = (int) fetch32(regs);
- }
- switch (modrm & 7) {
- case 0: return address(regs, seg, regs->eax + disp);
- case 1: return address(regs, seg, regs->ecx + disp);
- case 2: return address(regs, seg, regs->edx + disp);
- case 3: return address(regs, seg, regs->ebx + disp);
- case 4: return address(regs, seg,
- sib(regs, mod,
fetch8(regs)));
- case 5: return address(regs, seg, regs->ebp + disp);
- case 6: return address(regs, seg, regs->esi + disp);
- case 7: return address(regs, seg, regs->edi + disp);
- }
- break;
- case 3:
- return getreg32(regs, modrm);
- }
- } else { /* 16-bit addressing */
- switch ((mod = (modrm >> 6) & 3)) {
- case 0:
- switch (modrm & 7) {
- case 0: return address(regs, seg, MASK16(regs->ebx) +
- MASK16(regs->esi));
- case 1: return address(regs, seg, MASK16(regs->ebx) +
- MASK16(regs->edi));
- case 2: return address(regs, seg, MASK16(regs->ebp) +
- MASK16(regs->esi));
- case 3: return address(regs, seg, MASK16(regs->ebp) +
- MASK16(regs->edi));
- case 4: return address(regs, seg, MASK16(regs->esi));
- case 5: return address(regs, seg, MASK16(regs->edi));
- case 6: return address(regs, seg, fetch16(regs));
- case 7: return address(regs, seg, MASK16(regs->ebx));
- }
- break;
- case 1:
- case 2:
- if (mod == 1)
- disp = (char) fetch8(regs);
- else
- disp = (int) fetch16(regs);
- switch (modrm & 7) {
- case 0: return address(regs, seg, MASK16(regs->ebx) +
- MASK16(regs->esi) + disp);
- case 1: return address(regs, seg, MASK16(regs->ebx) +
- MASK16(regs->edi) + disp);
- case 2: return address(regs, seg, MASK16(regs->ebp) +
- MASK16(regs->esi) + disp);
- case 3: return address(regs, seg, MASK16(regs->ebp) +
- MASK16(regs->edi) + disp);
- case 4: return address(regs, seg,
- MASK16(regs->esi) + disp);
- case 5: return address(regs, seg,
- MASK16(regs->edi) + disp);
- case 6: return address(regs, seg,
- MASK16(regs->ebp) + disp);
- case 7: return address(regs, seg,
- MASK16(regs->ebx) + disp);
- }
- break;
- case 3:
- return getreg16(regs, modrm);
- }
- }
-
- return 0;
-}
-
-/*
- * Load new IDT
- */
-static int
-lidt(struct regs *regs, unsigned prefix, unsigned modrm)
-{
- unsigned eip = regs->eip - 3;
- unsigned addr = operand(prefix, regs, modrm);
-
- oldctx.idtr_limit = ((struct dtr *) addr)->size;
- if ((prefix & DATA32) == 0)
- oldctx.idtr_base = ((struct dtr *) addr)->base & 0xFFFFFF;
- else
- oldctx.idtr_base = ((struct dtr *) addr)->base;
- TRACE((regs, regs->eip - eip, "lidt 0x%x <%d, 0x%x>",
- addr, oldctx.idtr_limit, oldctx.idtr_base));
-
- return 1;
-}
-
-/*
- * Load new GDT
- */
-static int
-lgdt(struct regs *regs, unsigned prefix, unsigned modrm)
-{
- unsigned eip = regs->eip - 3;
- unsigned addr = operand(prefix, regs, modrm);
-
- oldctx.gdtr_limit = ((struct dtr *) addr)->size;
- if ((prefix & DATA32) == 0)
- oldctx.gdtr_base = ((struct dtr *) addr)->base & 0xFFFFFF;
- else
- oldctx.gdtr_base = ((struct dtr *) addr)->base;
- TRACE((regs, regs->eip - eip, "lgdt 0x%x <%d, 0x%x>",
- addr, oldctx.gdtr_limit, oldctx.gdtr_base));
-
- return 1;
-}
-
-/*
- * Modify CR0 either through an lmsw instruction.
- */
-static int
-lmsw(struct regs *regs, unsigned prefix, unsigned modrm)
-{
- unsigned eip = regs->eip - 3;
- unsigned ax = operand(prefix, regs, modrm) & 0xF;
- unsigned cr0 = (oldctx.cr0 & 0xFFFFFFF0) | ax;
-
- TRACE((regs, regs->eip - eip, "lmsw 0x%x", ax));
- oldctx.cr0 = cr0 | CR0_PE | CR0_NE;
- if (cr0 & CR0_PE)
- set_mode(regs, VM86_REAL_TO_PROTECTED);
-
- return 1;
-}
-
-/*
- * We need to handle moves that address memory beyond the 64KB segment
- * limit that VM8086 mode enforces.
- */
-static int
-movr(struct regs *regs, unsigned prefix, unsigned opc)
-{
- unsigned eip = regs->eip - 1;
- unsigned modrm = fetch8(regs);
- unsigned addr = operand(prefix, regs, modrm);
- unsigned val, r = (modrm >> 3) & 7;
-
- if ((modrm & 0xC0) == 0xC0) {
- /*
- * Emulate all guest instructions in protected to real mode.
- */
- if (mode != VM86_PROTECTED_TO_REAL)
- return 0;
- }
-
- switch (opc) {
- case 0x88: /* addr32 mov r8, r/m8 */
- val = getreg8(regs, r);
- TRACE((regs, regs->eip - eip,
- "movb %%e%s, *0x%x", rnames[r], addr));
- write8(addr, val);
- return 1;
-
- case 0x8A: /* addr32 mov r/m8, r8 */
- TRACE((regs, regs->eip - eip,
- "movb *0x%x, %%%s", addr, rnames[r]));
- setreg8(regs, r, read8(addr));
- return 1;
-
- case 0x89: /* addr32 mov r16, r/m16 */
- val = getreg32(regs, r);
- if ((modrm & 0xC0) == 0xC0) {
- if (prefix & DATA32)
- setreg32(regs, modrm & 7, val);
- else
- setreg16(regs, modrm & 7, MASK16(val));
- return 1;
- }
-
- if (prefix & DATA32) {
- TRACE((regs, regs->eip - eip,
- "movl %%e%s, *0x%x", rnames[r], addr));
- write32(addr, val);
- } else {
- TRACE((regs, regs->eip - eip,
- "movw %%%s, *0x%x", rnames[r], addr));
- write16(addr, MASK16(val));
- }
- return 1;
-
- case 0x8B: /* mov r/m16, r16 */
- if ((modrm & 0xC0) == 0xC0) {
- if (prefix & DATA32)
- setreg32(regs, r, addr);
- else
- setreg16(regs, r, MASK16(addr));
- return 1;
- }
-
- if (prefix & DATA32) {
- TRACE((regs, regs->eip - eip,
- "movl *0x%x, %%e%s", addr, rnames[r]));
- setreg32(regs, r, read32(addr));
- } else {
- TRACE((regs, regs->eip - eip,
- "movw *0x%x, %%%s", addr, rnames[r]));
- setreg16(regs, r, read16(addr));
- }
- return 1;
-
- case 0xC6: /* addr32 movb $imm, r/m8 */
- if ((modrm >> 3) & 7)
- return 0;
- val = fetch8(regs);
- write8(addr, val);
- TRACE((regs, regs->eip - eip, "movb $0x%x, *0x%x",
- val, addr));
- return 1;
- }
- return 0;
-}
-
-/*
- * We need to handle string moves that address memory beyond the 64KB segment
- * limit that VM8086 mode enforces.
- */
-static inline int
-movs(struct regs *regs, unsigned prefix, unsigned opc)
-{
- unsigned eip = regs->eip - 1;
- unsigned sseg = segment(prefix, regs, regs->vds);
- unsigned dseg = regs->ves;
- unsigned saddr, daddr;
- unsigned count = 1;
- int incr = ((regs->eflags & EFLAGS_DF) == 0) ? 1 : -1;
-
- saddr = address(regs, sseg, regs->esi);
- daddr = address(regs, dseg, regs->edi);
-
- if ((prefix & REP) != 0) {
- count = regs->ecx;
- regs->ecx = 0;
- }
-
- switch (opc) {
- case 0xA4: /* movsb */
- regs->esi += (incr * count);
- regs->edi += (incr * count);
-
- while (count-- != 0) {
- write8(daddr, read8(saddr));
- daddr += incr;
- saddr += incr;
- }
- TRACE((regs, regs->eip - eip, "movsb (%%esi),%%es:(%%edi)"));
- break;
-
- case 0xA5: /* movsw */
- if ((prefix & DATA32) == 0) {
- incr = 2 * incr;
- regs->esi += (incr * count);
- regs->edi += (incr * count);
-
- while (count-- != 0) {
- write16(daddr, read16(saddr));
- daddr += incr;
- saddr += incr;
- }
- } else {
- incr = 4 * incr;
- regs->esi += (incr * count);
- regs->edi += (incr * count);
-
- while (count-- != 0) {
- write32(daddr, read32(saddr));
- daddr += incr;
- saddr += incr;
- }
- }
- TRACE((regs, regs->eip - eip, "movsw %s(%%esi),%%es:(%%edi)"));
- break;
- }
-
- return 1;
-}
-
-static inline int
-lods(struct regs *regs, unsigned prefix, unsigned opc)
-{
- unsigned eip = regs->eip - 1;
- unsigned seg = segment(prefix, regs, regs->vds);
- unsigned addr = address(regs, seg, regs->esi);
- unsigned count = 1;
- int incr = ((regs->eflags & EFLAGS_DF) == 0) ? 1 : -1;
-
- if ((prefix & REP) != 0) {
- count = regs->ecx;
- regs->ecx = 0;
- }
-
- switch (opc) {
- case 0xAD: /* lodsw */
- if ((prefix & DATA32) == 0) {
- incr = 2 * incr;
- regs->esi += (incr * count);
- while (count-- != 0) {
- setreg16(regs, 0, read16(addr));
- addr += incr;
- }
-
- TRACE((regs, regs->eip - eip, "lodsw (%%esi),%%ax"));
- } else {
- incr = 4 * incr;
- regs->esi += (incr * count);
- while (count-- != 0) {
- setreg32(regs, 0, read32(addr));
- addr += incr;
- }
- TRACE((regs, regs->eip - eip, "lodsw (%%esi),%%eax"));
- }
- break;
- }
- return 1;
-}
-/*
- * Move to and from a control register.
- */
-static int
-movcr(struct regs *regs, unsigned prefix, unsigned opc)
-{
- unsigned eip = regs->eip - 2;
- unsigned modrm = fetch8(regs);
- unsigned cr = (modrm >> 3) & 7;
-
- if ((modrm & 0xC0) != 0xC0) /* only registers */
- return 0;
-
- switch (opc) {
- case 0x20: /* mov Rd, Cd */
- TRACE((regs, regs->eip - eip, "movl %%cr%d, %%eax", cr));
- switch (cr) {
- case 0:
- setreg32(regs, modrm,
- oldctx.cr0 & ~(CR0_PE | CR0_NE));
- break;
- case 2:
- setreg32(regs, modrm, get_cr2());
- break;
- case 3:
- setreg32(regs, modrm, oldctx.cr3);
- break;
- case 4:
- setreg32(regs, modrm, oldctx.cr4);
- break;
- }
- break;
- case 0x22: /* mov Cd, Rd */
- TRACE((regs, regs->eip - eip, "movl %%eax, %%cr%d", cr));
- switch (cr) {
- case 0:
- oldctx.cr0 = getreg32(regs, modrm) | (CR0_PE | CR0_NE);
- if (getreg32(regs, modrm) & CR0_PE)
- set_mode(regs, VM86_REAL_TO_PROTECTED);
- else
- set_mode(regs, VM86_REAL);
- break;
- case 3:
- oldctx.cr3 = getreg32(regs, modrm);
- break;
- case 4:
- oldctx.cr4 = getreg32(regs, modrm);
- break;
- }
- break;
- }
-
- return 1;
-}
-
-static inline void set_eflags_ZF(unsigned mask, unsigned v1, struct regs *regs)
-{
- if ((v1 & mask) == 0)
- regs->eflags |= EFLAGS_ZF;
- else
- regs->eflags &= ~EFLAGS_ZF;
-}
-
-static void set_eflags_add(unsigned hi_bit_mask, unsigned v1, unsigned v2,
- unsigned result, struct regs *regs)
-{
- int bit_count;
- unsigned tmp;
- unsigned full_mask;
- unsigned nonsign_mask;
-
- /* Carry out of high order bit? */
- if ( v1 & v2 & hi_bit_mask )
- regs->eflags |= EFLAGS_CF;
- else
- regs->eflags &= ~EFLAGS_CF;
-
- /* Even parity in least significant byte? */
- tmp = result & 0xff;
- for (bit_count = 0; tmp != 0; bit_count++)
- tmp &= (tmp - 1);
-
- if (bit_count & 1)
- regs->eflags &= ~EFLAGS_PF;
- else
- regs->eflags |= EFLAGS_PF;
-
- /* Carry out of least significant BCD digit? */
- if ( v1 & v2 & (1<<3) )
- regs->eflags |= EFLAGS_AF;
- else
- regs->eflags &= ~EFLAGS_AF;
-
- /* Result is zero? */
- full_mask = (hi_bit_mask - 1) | hi_bit_mask;
- set_eflags_ZF(full_mask, result, regs);
-
- /* Sign of result? */
- if ( result & hi_bit_mask )
- regs->eflags |= EFLAGS_SF;
- else
- regs->eflags &= ~EFLAGS_SF;
-
- /* Carry out of highest non-sign bit? */
- nonsign_mask = (hi_bit_mask >> 1) & ~hi_bit_mask;
- if ( v1 & v2 & hi_bit_mask )
- regs->eflags |= EFLAGS_OF;
- else
- regs->eflags &= ~EFLAGS_OF;
-
-}
-
-/*
- * We need to handle cmp opcodes that address memory beyond the 64KB
- * segment limit that VM8086 mode enforces.
- */
-static int
-cmp(struct regs *regs, unsigned prefix, unsigned opc)
-{
- unsigned eip = regs->eip - 1;
- unsigned modrm = fetch8(regs);
- unsigned addr = operand(prefix, regs, modrm);
- unsigned diff, val, r = (modrm >> 3) & 7;
-
- if ((modrm & 0xC0) == 0xC0) /* no registers */
- return 0;
-
- switch (opc) {
- case 0x39: /* addr32 cmp r16, r/m16 */
- val = getreg32(regs, r);
- if (prefix & DATA32) {
- diff = read32(addr) - val;
- set_eflags_ZF(~0, diff, regs);
-
- TRACE((regs, regs->eip - eip,
- "cmp %%e%s, *0x%x (0x%x)",
- rnames[r], addr, diff));
- } else {
- diff = read16(addr) - val;
- set_eflags_ZF(0xFFFF, diff, regs);
-
- TRACE((regs, regs->eip - eip,
- "cmp %%%s, *0x%x (0x%x)",
- rnames[r], addr, diff));
- }
- break;
-
- /* other cmp opcodes ... */
- }
- return 1;
-}
-
-/*
- * We need to handle test opcodes that address memory beyond the 64KB
- * segment limit that VM8086 mode enforces.
- */
-static int
-test(struct regs *regs, unsigned prefix, unsigned opc)
-{
- unsigned eip = regs->eip - 1;
- unsigned modrm = fetch8(regs);
- unsigned addr = operand(prefix, regs, modrm);
- unsigned val, diff;
-
- if ((modrm & 0xC0) == 0xC0) /* no registers */
- return 0;
-
- switch (opc) {
- case 0xF6: /* testb $imm, r/m8 */
- if ((modrm >> 3) & 7)
- return 0;
- val = fetch8(regs);
- diff = read8(addr) & val;
- set_eflags_ZF(0xFF, diff, regs);
-
- TRACE((regs, regs->eip - eip, "testb $0x%x, *0x%x (0x%x)",
- val, addr, diff));
- break;
-
- /* other test opcodes ... */
- }
-
- return 1;
-}
-
-/*
- * We need to handle add opcodes that address memory beyond the 64KB
- * segment limit that VM8086 mode enforces.
- */
-static int
-add(struct regs *regs, unsigned prefix, unsigned opc)
-{
- unsigned eip = regs->eip - 1;
- unsigned modrm = fetch8(regs);
- unsigned addr = operand(prefix, regs, modrm);
- unsigned r = (modrm >> 3) & 7;
-
- unsigned val1 = 0;
- unsigned val2 = 0;
- unsigned result = 0;
- unsigned hi_bit;
-
- if ((modrm & 0xC0) == 0xC0) /* no registers */
- return 0;
-
- switch (opc) {
- case 0x00: /* addr32 add r8, r/m8 */
- val1 = getreg8(regs, r);
- val2 = read8(addr);
- result = val1 + val2;
- write8(addr, result);
- TRACE((regs, regs->eip - eip,
- "addb %%e%s, *0x%x", rnames[r], addr));
- break;
-
- case 0x01: /* addr32 add r16, r/m16 */
- if (prefix & DATA32) {
- val1 = getreg32(regs, r);
- val2 = read32(addr);
- result = val1 + val2;
- write32(addr, result);
- TRACE((regs, regs->eip - eip,
- "addl %%e%s, *0x%x", rnames[r], addr));
- } else {
- val1 = getreg16(regs, r);
- val2 = read16(addr);
- result = val1 + val2;
- write16(addr, result);
- TRACE((regs, regs->eip - eip,
- "addw %%e%s, *0x%x", rnames[r], addr));
- }
- break;
-
- case 0x03: /* addr32 add r/m16, r16 */
- if (prefix & DATA32) {
- val1 = getreg32(regs, r);
- val2 = read32(addr);
- result = val1 + val2;
- setreg32(regs, r, result);
- TRACE((regs, regs->eip - eip,
- "addl *0x%x, %%e%s", addr, rnames[r]));
- } else {
- val1 = getreg16(regs, r);
- val2 = read16(addr);
- result = val1 + val2;
- setreg16(regs, r, result);
- TRACE((regs, regs->eip - eip,
- "addw *0x%x, %%%s", addr, rnames[r]));
- }
- break;
- }
-
- if (opc == 0x00)
- hi_bit = (1<<7);
- else
- hi_bit = (prefix & DATA32) ? (1<<31) : (1<<15);
- set_eflags_add(hi_bit, val1, val2, result, regs);
-
- return 1;
-}
-
-/*
- * We need to handle pop opcodes that address memory beyond the 64KB
- * segment limit that VM8086 mode enforces.
- */
-static int
-pop(struct regs *regs, unsigned prefix, unsigned opc)
-{
- unsigned eip = regs->eip - 1;
- unsigned modrm = fetch8(regs);
- unsigned addr = operand(prefix, regs, modrm);
-
- if ((modrm & 0xC0) == 0xC0) /* no registers */
- return 0;
-
- switch (opc) {
- case 0x8F: /* pop r/m16 */
- if ((modrm >> 3) & 7)
- return 0;
- if (prefix & DATA32)
- write32(addr, pop32(regs));
- else
- write16(addr, pop16(regs));
- TRACE((regs, regs->eip - eip, "pop *0x%x", addr));
- break;
-
- /* other pop opcodes ... */
- }
-
- return 1;
-}
-
-static int
-mov_to_seg(struct regs *regs, unsigned prefix, unsigned opc)
-{
- unsigned modrm = fetch8(regs);
-
- /*
- * Emulate segment loads in:
- * 1) real->protected mode.
- * 2) protected->real mode.
- */
- if (mode != VM86_REAL_TO_PROTECTED &&
- mode != VM86_PROTECTED_TO_REAL)
- return 0;
-
- /* Register source only. */
- if ((modrm & 0xC0) != 0xC0)
- goto fail;
-
- switch ((modrm & 0x38) >> 3) {
- case 0: /* es */
- regs->ves = getreg16(regs, modrm);
- if (mode == VM86_PROTECTED_TO_REAL)
- return 1;
- saved_rm_regs.ves = 0;
- oldctx.es_sel = regs->ves;
- return 1;
-
- /* case 1: cs */
-
- case 2: /* ss */
- regs->uss = getreg16(regs, modrm);
- if (mode == VM86_PROTECTED_TO_REAL)
- return 1;
- saved_rm_regs.uss = 0;
- oldctx.ss_sel = regs->uss;
- return 1;
- case 3: /* ds */
- regs->vds = getreg16(regs, modrm);
- if (mode == VM86_PROTECTED_TO_REAL)
- return 1;
- saved_rm_regs.vds = 0;
- oldctx.ds_sel = regs->vds;
- return 1;
- case 4: /* fs */
- regs->vfs = getreg16(regs, modrm);
- if (mode == VM86_PROTECTED_TO_REAL)
- return 1;
- saved_rm_regs.vfs = 0;
- oldctx.fs_sel = regs->vfs;
- return 1;
- case 5: /* gs */
- regs->vgs = getreg16(regs, modrm);
- if (mode == VM86_PROTECTED_TO_REAL)
- return 1;
- saved_rm_regs.vgs = 0;
- oldctx.gs_sel = regs->vgs;
- return 1;
- }
-
- fail:
- printf("%s:%d: missed opcode %02x %02x\n",
- __FUNCTION__, __LINE__, opc, modrm);
- return 0;
-}
-
-/*
- * Emulate a segment load in protected mode
- */
-static int
-load_seg(unsigned long sel, uint32_t *base, uint32_t *limit, union
vmcs_arbytes *arbytes)
-{
- uint64_t gdt_phys_base;
- unsigned long long entry;
-
- /* protected mode: use seg as index into gdt */
- if (sel > oldctx.gdtr_limit)
- return 0;
-
- if (sel == 0) {
- arbytes->fields.null_bit = 1;
- return 1;
- }
-
- gdt_phys_base = guest_linear_to_phys(oldctx.gdtr_base);
- if (gdt_phys_base != (uint32_t)gdt_phys_base) {
- printf("gdt base address above 4G\n");
- cpuid_addr_value(gdt_phys_base + 8 * (sel >> 3), &entry);
- } else
- entry = ((unsigned long long *)(long)gdt_phys_base)[sel >> 3];
-
- /* Check the P bit first */
- if (!((entry >> (15+32)) & 0x1) && sel != 0)
- return 0;
-
- *base = (((entry >> (56-24)) & 0xFF000000) |
- ((entry >> (32-16)) & 0x00FF0000) |
- ((entry >> ( 16)) & 0x0000FFFF));
- *limit = (((entry >> (48-16)) & 0x000F0000) |
- (entry & 0x0000FFFF));
-
- arbytes->bytes = 0;
- arbytes->fields.seg_type = (entry >> (8+32)) & 0xF; /* TYPE */
- arbytes->fields.s = (entry >> (12+32)) & 0x1; /* S */
- if (arbytes->fields.s)
- arbytes->fields.seg_type |= 1; /* accessed */
- arbytes->fields.dpl = (entry >> (13+32)) & 0x3; /* DPL */
- arbytes->fields.p = (entry >> (15+32)) & 0x1; /* P */
- arbytes->fields.avl = (entry >> (20+32)) & 0x1; /* AVL */
- arbytes->fields.default_ops_size = (entry >> (22+32)) & 0x1; /* D */
-
- if (entry & (1ULL << (23+32))) { /* G */
- arbytes->fields.g = 1;
- *limit = (*limit << 12) | 0xFFF;
- }
-
- return 1;
-}
-
-/*
- * Emulate a protected mode segment load, falling back to clearing it if
- * the descriptor was invalid.
- */
-static void
-load_or_clear_seg(unsigned long sel, uint32_t *base, uint32_t *limit, union
vmcs_arbytes *arbytes)
-{
- if (!load_seg(sel, base, limit, arbytes))
- load_seg(0, base, limit, arbytes);
-}
-
-static unsigned char rm_irqbase[2];
-
-/*
- * Transition to protected mode
- */
-static void
-protected_mode(struct regs *regs)
-{
- extern char stack_top[];
-
- oldctx.rm_irqbase[0] = rm_irqbase[0];
- oldctx.rm_irqbase[1] = rm_irqbase[1];
-
- regs->eflags &= ~(EFLAGS_TF|EFLAGS_VM);
-
- oldctx.eip = regs->eip;
- oldctx.esp = regs->uesp;
- oldctx.eflags = regs->eflags;
-
- /* reload all segment registers */
- if (!load_seg(regs->cs, &oldctx.cs_base,
- &oldctx.cs_limit, &oldctx.cs_arbytes))
- panic("Invalid %%cs=0x%x for protected mode\n", regs->cs);
- oldctx.cs_sel = regs->cs;
-
- load_or_clear_seg(oldctx.es_sel, &oldctx.es_base,
- &oldctx.es_limit, &oldctx.es_arbytes);
- load_or_clear_seg(oldctx.ss_sel, &oldctx.ss_base,
- &oldctx.ss_limit, &oldctx.ss_arbytes);
- load_or_clear_seg(oldctx.ds_sel, &oldctx.ds_base,
- &oldctx.ds_limit, &oldctx.ds_arbytes);
- load_or_clear_seg(oldctx.fs_sel, &oldctx.fs_base,
- &oldctx.fs_limit, &oldctx.fs_arbytes);
- load_or_clear_seg(oldctx.gs_sel, &oldctx.gs_base,
- &oldctx.gs_limit, &oldctx.gs_arbytes);
-
- /* initialize jump environment to warp back to protected mode */
- regs->uss = DATA_SELECTOR;
- regs->uesp = (unsigned long)stack_top;
- regs->cs = CODE_SELECTOR;
- regs->eip = (unsigned long)switch_to_protected_mode;
-
- /* this should get us into 32-bit mode */
-}
-
-/*
- * Start real-mode emulation
- */
-static void
-real_mode(struct regs *regs)
-{
- regs->eflags |= EFLAGS_VM | 0x02;
-
- /*
- * When we transition from protected to real-mode and we
- * have not reloaded the segment descriptors yet, they are
- * interpreted as if they were in protect mode.
- * We emulate this behavior by assuming that these memory
- * reference are below 1MB and set %ss, %ds, %es accordingly.
- */
- if (regs->uss != 0) {
- if (regs->uss >= HIGHMEM)
- panic("%%ss 0x%lx higher than 1MB", regs->uss);
- regs->uss = address(regs, regs->uss, 0) >> 4;
- } else {
- regs->uss = saved_rm_regs.uss;
- }
- if (regs->vds != 0) {
- if (regs->vds >= HIGHMEM)
- panic("%%ds 0x%lx higher than 1MB", regs->vds);
- regs->vds = address(regs, regs->vds, 0) >> 4;
- } else {
- regs->vds = saved_rm_regs.vds;
- }
- if (regs->ves != 0) {
- if (regs->ves >= HIGHMEM)
- panic("%%es 0x%lx higher than 1MB", regs->ves);
- regs->ves = address(regs, regs->ves, 0) >> 4;
- } else {
- regs->ves = saved_rm_regs.ves;
- }
-
- /* this should get us into 16-bit mode */
-}
-
-/*
- * This is the smarts of the emulator and handles the mode transitions. The
- * emulator handles 4 different modes. 1) VM86_REAL: emulated real-mode,
- * Just handle those instructions that are not supported under VM8086.
- * 2) VM86_REAL_TO_PROTECTED: going from real-mode to protected mode. In
- * this we single step through the instructions until we reload the
- * new %cs (some OSes do a lot of computations before reloading %cs). 2)
- * VM86_PROTECTED_TO_REAL when we are going from protected to real mode. In
- * this case we emulate the instructions by hand. Finally, 4) VM86_PROTECTED
- * when we transitioned to protected mode and we should abandon the
- * emulator. No instructions are emulated when in VM86_PROTECTED mode.
- */
-void
-set_mode(struct regs *regs, enum vm86_mode newmode)
-{
- switch (newmode) {
- case VM86_REAL:
- if (mode == VM86_PROTECTED_TO_REAL ||
- mode == VM86_REAL_TO_PROTECTED) {
- regs->eflags &= ~EFLAGS_TF;
- real_mode(regs);
- } else if (mode != VM86_REAL)
- panic("unexpected real mode transition");
- break;
-
- case VM86_REAL_TO_PROTECTED:
- if (mode == VM86_REAL) {
- regs->eflags |= EFLAGS_TF;
- saved_rm_regs.vds = regs->vds;
- saved_rm_regs.ves = regs->ves;
- saved_rm_regs.vfs = regs->vfs;
- saved_rm_regs.vgs = regs->vgs;
- saved_rm_regs.uss = regs->uss;
- oldctx.ds_sel = 0;
- oldctx.es_sel = 0;
- oldctx.fs_sel = 0;
- oldctx.gs_sel = 0;
- oldctx.ss_sel = 0;
- } else if (mode != VM86_REAL_TO_PROTECTED)
- panic("unexpected real-to-protected mode transition");
- break;
-
- case VM86_PROTECTED_TO_REAL:
- if (mode != VM86_PROTECTED)
- panic("unexpected protected-to-real mode transition");
- break;
-
- case VM86_PROTECTED:
- if (mode != VM86_REAL_TO_PROTECTED)
- panic("unexpected protected mode transition");
- protected_mode(regs);
- break;
- }
-
- mode = newmode;
- if (mode != VM86_PROTECTED)
- TRACE((regs, 0, states[mode]));
-}
-
-static void
-jmpl(struct regs *regs, int prefix)
-{
- unsigned n = regs->eip;
- unsigned cs, eip;
-
- eip = (prefix & DATA32) ? fetch32(regs) : fetch16(regs);
- cs = fetch16(regs);
-
- TRACE((regs, (regs->eip - n) + 1, "jmpl 0x%x:0x%x", cs, eip));
-
- regs->cs = cs;
- regs->eip = eip;
-
- if (mode == VM86_REAL_TO_PROTECTED) /* jump to protected
mode */
- set_mode(regs, VM86_PROTECTED);
- else if (mode == VM86_PROTECTED_TO_REAL) /* jump to real mode */
- set_mode(regs, VM86_REAL);
- else
- panic("jmpl");
-}
-
-static void
-jmpl_indirect(struct regs *regs, int prefix, unsigned modrm)
-{
- unsigned n = regs->eip;
- unsigned cs, eip;
- unsigned addr;
-
- addr = operand(prefix, regs, modrm);
-
- eip = (prefix & DATA32) ? read32(addr) : read16(addr);
- addr += (prefix & DATA32) ? 4 : 2;
- cs = read16(addr);
-
- TRACE((regs, (regs->eip - n) + 1, "jmpl 0x%x:0x%x", cs, eip));
-
- regs->cs = cs;
- regs->eip = eip;
-
- if (mode == VM86_REAL_TO_PROTECTED) /* jump to protected
mode */
- set_mode(regs, VM86_PROTECTED);
- else if (mode == VM86_PROTECTED_TO_REAL) /* jump to real mode */
- set_mode(regs, VM86_REAL);
- else
- panic("jmpl");
-}
-
-static void
-retl(struct regs *regs, int prefix)
-{
- unsigned cs, eip;
-
- if (prefix & DATA32) {
- eip = pop32(regs);
- cs = MASK16(pop32(regs));
- } else {
- eip = pop16(regs);
- cs = pop16(regs);
- }
-
- TRACE((regs, 1, "retl (to 0x%x:0x%x)", cs, eip));
-
- regs->cs = cs;
- regs->eip = eip;
-
- if (mode == VM86_REAL_TO_PROTECTED) /* jump to protected
mode */
- set_mode(regs, VM86_PROTECTED);
- else if (mode == VM86_PROTECTED_TO_REAL) /* jump to real mode */
- set_mode(regs, VM86_REAL);
- else
- panic("retl");
-}
-
-static void
-interrupt(struct regs *regs, int n)
-{
- TRACE((regs, 0, "external interrupt %d", n));
- push16(regs, regs->eflags);
- push16(regs, regs->cs);
- push16(regs, regs->eip);
- regs->eflags &= ~EFLAGS_IF;
- regs->eip = read16(address(regs, 0, n * 4));
- regs->cs = read16(address(regs, 0, n * 4 + 2));
-}
-
-/*
- * Most port I/O operations are passed unmodified. We do have to be
- * careful and make sure the emulated program isn't remapping the
- * interrupt vectors. The following simple state machine catches
- * these attempts and rewrites them.
- */
-static int
-outbyte(struct regs *regs, unsigned prefix, unsigned opc)
-{
- static char icw2[2] = { 0 };
- int al, port;
-
- switch (opc) {
- case 0xE6: /* outb port, al */
- port = fetch8(regs);
- break;
- case 0xEE: /* outb (%dx), al */
- port = MASK16(regs->edx);
- break;
- default:
- return 0;
- }
-
- al = regs->eax & 0xFF;
-
- switch (port) {
- case PIC_MASTER + PIC_CMD:
- if (al & (1 << 4)) /* A0=0,D4=1 -> ICW1 */
- icw2[0] = 1;
- break;
- case PIC_MASTER + PIC_IMR:
- if (icw2[0]) {
- icw2[0] = 0;
- printf("Remapping master: ICW2 0x%x -> 0x%x\n",
- al, NR_EXCEPTION_HANDLER);
- rm_irqbase[0] = al;
- al = NR_EXCEPTION_HANDLER;
- }
- break;
-
- case PIC_SLAVE + PIC_CMD:
- if (al & (1 << 4)) /* A0=0,D4=1 -> ICW1 */
- icw2[1] = 1;
- break;
- case PIC_SLAVE + PIC_IMR:
- if (icw2[1]) {
- icw2[1] = 0;
- printf("Remapping slave: ICW2 0x%x -> 0x%x\n",
- al, NR_EXCEPTION_HANDLER+8);
- rm_irqbase[1] = al;
- al = NR_EXCEPTION_HANDLER+8;
- }
- break;
- }
-
- outb(port, al);
- return 1;
-}
-
-static int
-inbyte(struct regs *regs, unsigned prefix, unsigned opc)
-{
- int port;
-
- switch (opc) {
- case 0xE4: /* inb al, port */
- port = fetch8(regs);
- break;
- case 0xEC: /* inb al, (%dx) */
- port = MASK16(regs->edx);
- break;
- default:
- return 0;
- }
-
- regs->eax = (regs->eax & ~0xFF) | inb(port);
- return 1;
-}
-
-static void
-pushrm(struct regs *regs, int prefix, unsigned modrm)
-{
- unsigned n = regs->eip;
- unsigned addr;
- unsigned data;
-
- addr = operand(prefix, regs, modrm);
-
- if (prefix & DATA32) {
- data = read32(addr);
- push32(regs, data);
- } else {
- data = read16(addr);
- push16(regs, data);
- }
-
- TRACE((regs, (regs->eip - n) + 1, "push *0x%x", addr));
-}
-
-enum { OPC_INVALID, OPC_EMULATED };
-
-#define rdmsr(msr,val1,val2) \
- __asm__ __volatile__( \
- "rdmsr" \
- : "=a" (val1), "=d" (val2) \
- : "c" (msr))
-
-#define wrmsr(msr,val1,val2) \
- __asm__ __volatile__( \
- "wrmsr" \
- : /* no outputs */ \
- : "c" (msr), "a" (val1), "d" (val2))
-
-/*
- * Emulate a single instruction, including all its prefixes. We only implement
- * a small subset of the opcodes, and not all opcodes are implemented for each
- * of the four modes we can operate in.
- */
-static int
-opcode(struct regs *regs)
-{
- unsigned eip = regs->eip;
- unsigned opc, modrm, disp;
- unsigned prefix = 0;
-
- if (mode == VM86_PROTECTED_TO_REAL &&
- oldctx.cs_arbytes.fields.default_ops_size) {
- prefix |= DATA32;
- prefix |= ADDR32;
- }
-
- for (;;) {
- switch ((opc = fetch8(regs))) {
-
- case 0x00: /* addr32 add r8, r/m8 */
- case 0x01: /* addr32 add r16, r/m16 */
- case 0x03: /* addr32 add r/m16, r16 */
- if (mode != VM86_REAL && mode != VM86_REAL_TO_PROTECTED)
- goto invalid;
- if ((prefix & ADDR32) == 0)
- goto invalid;
- if (!add(regs, prefix, opc))
- goto invalid;
- return OPC_EMULATED;
-
- case 0x07: /* pop %es */
- regs->ves = (prefix & DATA32) ?
- pop32(regs) : pop16(regs);
- TRACE((regs, regs->eip - eip, "pop %%es"));
- if (mode == VM86_REAL_TO_PROTECTED) {
- saved_rm_regs.ves = 0;
- oldctx.es_sel = regs->ves;
- }
- return OPC_EMULATED;
-
- case 0x0F: /* two byte opcode */
- if (mode == VM86_PROTECTED)
- goto invalid;
- switch ((opc = fetch8(regs))) {
- case 0x01:
- switch (((modrm = fetch8(regs)) >> 3) & 7) {
- case 0: /* sgdt */
- case 1: /* sidt */
- goto invalid;
- case 2: /* lgdt */
- if (!lgdt(regs, prefix, modrm))
- goto invalid;
- return OPC_EMULATED;
- case 3: /* lidt */
- if (!lidt(regs, prefix, modrm))
- goto invalid;
- return OPC_EMULATED;
- case 4: /* smsw */
- goto invalid;
- case 5:
- goto invalid;
- case 6: /* lmsw */
- if (!lmsw(regs, prefix, modrm))
- goto invalid;
- return OPC_EMULATED;
- case 7: /* invlpg */
- goto invalid;
- }
- break;
- case 0x06: /* clts */
- oldctx.cr0 &= ~CR0_TS;
- return OPC_EMULATED;
- case 0x09: /* wbinvd */
- return OPC_EMULATED;
- case 0x20: /* mov Rd, Cd (1h) */
- case 0x22:
- if (!movcr(regs, prefix, opc))
- goto invalid;
- return OPC_EMULATED;
- case 0x30: /* WRMSR */
- wrmsr(regs->ecx, regs->eax, regs->edx);
- return OPC_EMULATED;
- case 0x32: /* RDMSR */
- rdmsr(regs->ecx, regs->eax, regs->edx);
- return OPC_EMULATED;
- default:
- goto invalid;
- }
- goto invalid;
-
- case 0x1F: /* pop %ds */
- regs->vds = (prefix & DATA32) ?
- pop32(regs) : pop16(regs);
- TRACE((regs, regs->eip - eip, "pop %%ds"));
- if (mode == VM86_REAL_TO_PROTECTED) {
- saved_rm_regs.vds = 0;
- oldctx.ds_sel = regs->vds;
- }
- return OPC_EMULATED;
-
- case 0x26:
- TRACE((regs, regs->eip - eip, "%%es:"));
- prefix |= SEG_ES;
- continue;
-
- case 0x2E:
- TRACE((regs, regs->eip - eip, "%%cs:"));
- prefix |= SEG_CS;
- continue;
-
- case 0x36:
- TRACE((regs, regs->eip - eip, "%%ss:"));
- prefix |= SEG_SS;
- continue;
-
- case 0x39: /* addr32 cmp r16, r/m16 */
- case 0x3B: /* addr32 cmp r/m16, r16 */
- if (mode == VM86_PROTECTED_TO_REAL || !(prefix &
ADDR32))
- goto invalid;
- if (!cmp(regs, prefix, opc))
- goto invalid;
- return OPC_EMULATED;
-
- case 0x3E:
- TRACE((regs, regs->eip - eip, "%%ds:"));
- prefix |= SEG_DS;
- continue;
-
- case 0x64:
- TRACE((regs, regs->eip - eip, "%%fs:"));
- prefix |= SEG_FS;
- continue;
-
- case 0x65:
- TRACE((regs, regs->eip - eip, "%%gs:"));
- prefix |= SEG_GS;
- continue;
-
- case 0x66:
- if (mode == VM86_PROTECTED_TO_REAL &&
- oldctx.cs_arbytes.fields.default_ops_size) {
- TRACE((regs, regs->eip - eip, "data16"));
- prefix &= ~DATA32;
- } else {
- TRACE((regs, regs->eip - eip, "data32"));
- prefix |= DATA32;
- }
- continue;
-
- case 0x67:
- if (mode == VM86_PROTECTED_TO_REAL &&
- oldctx.cs_arbytes.fields.default_ops_size) {
- TRACE((regs, regs->eip - eip, "addr16"));
- prefix &= ~ADDR32;
- } else {
- TRACE((regs, regs->eip - eip, "addr32"));
- prefix |= ADDR32;
- }
- continue;
-
- case 0x88: /* addr32 mov r8, r/m8 */
- case 0x8A: /* addr32 mov r/m8, r8 */
- if (mode == VM86_PROTECTED_TO_REAL || !(prefix &
ADDR32))
- goto invalid;
- if (!movr(regs, prefix, opc))
- goto invalid;
- return OPC_EMULATED;
-
- case 0x89: /* mov r16, r/m16 */
- case 0x8B: /* mov r/m16, r16 */
- if (mode != VM86_PROTECTED_TO_REAL && !(prefix &
ADDR32))
- goto invalid;
- if (!movr(regs, prefix, opc))
- goto invalid;
- return OPC_EMULATED;
-
- case 0x8E: /* mov r16, sreg */
- if (!mov_to_seg(regs, prefix, opc))
- goto invalid;
- return OPC_EMULATED;
-
- case 0x8F: /* addr32 pop r/m16 */
- if (!(prefix & ADDR32))
- goto invalid;
- if (!pop(regs, prefix, opc))
- goto invalid;
- return OPC_EMULATED;
-
- case 0x90: /* nop */
- TRACE((regs, regs->eip - eip, "nop"));
- return OPC_EMULATED;
-
- case 0x9C: /* pushf */
- TRACE((regs, regs->eip - eip, "pushf"));
- if (prefix & DATA32)
- push32(regs, regs->eflags & ~EFLAGS_VM);
- else
- push16(regs, regs->eflags & ~EFLAGS_VM);
- return OPC_EMULATED;
-
- case 0x9D: /* popf */
- TRACE((regs, regs->eip - eip, "popf"));
- if (prefix & DATA32)
- regs->eflags = pop32(regs);
- else
- regs->eflags = (regs->eflags & 0xFFFF0000L) |
- pop16(regs);
- regs->eflags |= EFLAGS_VM;
- return OPC_EMULATED;
-
- case 0xA1: /* mov ax, r/m16 */
- {
- int addr, data;
- int seg = segment(prefix, regs, regs->vds);
- int offset = prefix & ADDR32 ? fetch32(regs) :
fetch16(regs);
-
- if (prefix & DATA32) {
- addr = address(regs, seg, offset);
- data = read32(addr);
- setreg32(regs, 0, data);
- } else {
- addr = address(regs, seg, offset);
- data = read16(addr);
- setreg16(regs, 0, data);
- }
- TRACE((regs, regs->eip - eip, "mov *0x%x, %%ax", addr));
- return OPC_EMULATED;
- }
-
- case 0xA4: /* movsb */
- case 0xA5: /* movsw */
- if ((prefix & ADDR32) == 0)
- goto invalid;
- if (!movs(regs, prefix, opc))
- goto invalid;
- return OPC_EMULATED;
-
- case 0xAD: /* lodsw */
- if ((prefix & ADDR32) == 0)
- goto invalid;
- if (!lods(regs, prefix, opc))
- goto invalid;
- return OPC_EMULATED;
-
- case 0xBB: /* mov bx, imm16 */
- {
- int data;
- if (prefix & DATA32) {
- data = fetch32(regs);
- setreg32(regs, 3, data);
- } else {
- data = fetch16(regs);
- setreg16(regs, 3, data);
- }
- TRACE((regs, regs->eip - eip, "mov $0x%x, %%bx", data));
- return OPC_EMULATED;
- }
-
- case 0xC6: /* addr32 movb $imm, r/m8 */
- if (!(prefix & ADDR32))
- goto invalid;
- if (!movr(regs, prefix, opc))
- goto invalid;
- return OPC_EMULATED;
-
- case 0xCB: /* retl */
- if (mode == VM86_REAL_TO_PROTECTED ||
- mode == VM86_PROTECTED_TO_REAL) {
- retl(regs, prefix);
- return OPC_INVALID;
- }
- goto invalid;
-
- case 0xCD: /* int $n */
- TRACE((regs, regs->eip - eip, "int"));
- interrupt(regs, fetch8(regs));
- return OPC_EMULATED;
-
- case 0xCF: /* iret */
- if (prefix & DATA32) {
- TRACE((regs, regs->eip - eip, "data32 iretd"));
- regs->eip = pop32(regs);
- regs->cs = pop32(regs);
- regs->eflags = pop32(regs);
- } else {
- TRACE((regs, regs->eip - eip, "iret"));
- regs->eip = pop16(regs);
- regs->cs = pop16(regs);
- regs->eflags = (regs->eflags & 0xFFFF0000L) |
- pop16(regs);
- }
- return OPC_EMULATED;
-
- case 0xE4: /* inb al, port */
- if (!inbyte(regs, prefix, opc))
- goto invalid;
- return OPC_EMULATED;
-
- case 0xE6: /* outb port, al */
- if (!outbyte(regs, prefix, opc))
- goto invalid;
- return OPC_EMULATED;
-
- case 0xEA: /* jmpl */
- if (mode == VM86_REAL_TO_PROTECTED ||
- mode == VM86_PROTECTED_TO_REAL) {
- jmpl(regs, prefix);
- return OPC_INVALID;
- }
- goto invalid;
-
- case 0xFF:
- {
- unsigned modrm = fetch8(regs);
- switch((modrm >> 3) & 7) {
- case 5: /* jmpl (indirect) */
- if (mode == VM86_REAL_TO_PROTECTED ||
- mode == VM86_PROTECTED_TO_REAL) {
- jmpl_indirect(regs, prefix, modrm);
- return OPC_INVALID;
- }
- goto invalid;
-
- case 6: /* push r/m16 */
- pushrm(regs, prefix, modrm);
- return OPC_EMULATED;
-
- default:
- goto invalid;
- }
- }
-
- case 0xEB: /* short jump */
- if (mode == VM86_REAL_TO_PROTECTED ||
- mode == VM86_PROTECTED_TO_REAL) {
- disp = (char) fetch8(regs);
- TRACE((regs, 2, "jmp 0x%x", regs->eip + disp));
- regs->eip += disp;
- return OPC_EMULATED;
- }
- goto invalid;
-
- case 0xEC: /* inb al, (%dx) */
- if (!inbyte(regs, prefix, opc))
- goto invalid;
- return OPC_EMULATED;
-
- case 0xEE: /* outb (%dx), al */
- if (!outbyte(regs, prefix, opc))
- goto invalid;
- return OPC_EMULATED;
-
- case 0xF0: /* lock */
- TRACE((regs, regs->eip - eip, "lock"));
- continue;
-
- case 0xF4: /* hlt */
- TRACE((regs, regs->eip - eip, "hlt"));
- /* Do something power-saving here! */
- return OPC_EMULATED;
-
- case 0xF3: /* rep/repe/repz */
- TRACE((regs, regs->eip - eip, "rep"));
- prefix |= REP;
- continue;
-
- case 0xF6: /* addr32 testb $imm, r/m8 */
- if (!(prefix & ADDR32))
- goto invalid;
- if (!test(regs, prefix, opc))
- goto invalid;
- return OPC_EMULATED;
-
- case 0xFA: /* cli */
- TRACE((regs, regs->eip - eip, "cli"));
- regs->eflags &= ~EFLAGS_IF;
- return OPC_EMULATED;
-
- case 0xFB: /* sti */
- TRACE((regs, regs->eip - eip, "sti"));
- regs->eflags |= EFLAGS_IF;
- return OPC_EMULATED;
-
- default:
- goto invalid;
- }
- }
-
-invalid:
- regs->eip = eip;
- TRACE((regs, regs->eip - eip, "opc 0x%x", opc));
- return OPC_INVALID;
-}
-
-void
-emulate(struct regs *regs)
-{
- unsigned flteip;
- int nemul = 0;
- unsigned ip;
-
- /* emulate as many instructions as possible */
- while (opcode(regs) != OPC_INVALID)
- nemul++;
-
- /* detect the case where we are not making progress */
- if (nemul == 0 && prev_eip == regs->eip) {
- flteip = address(regs, MASK16(regs->cs), regs->eip);
-
- printf("Undecoded sequence: \n");
- for (ip=flteip; ip < flteip+16; ip++)
- printf("0x%02x ", read8(ip));
- printf("\n");
-
- panic("Unknown opcode at %04x:%04x=0x%x",
- MASK16(regs->cs), regs->eip, flteip);
- } else
- prev_eip = regs->eip;
-}
-
-void
-trap(int trapno, int errno, struct regs *regs)
-{
- /* emulate device interrupts */
- if (trapno >= NR_EXCEPTION_HANDLER) {
- int irq = trapno - NR_EXCEPTION_HANDLER;
- if (irq < 8)
- interrupt(regs, irq + 8);
- else
- interrupt(regs, 0x70 + (irq - 8));
- return;
- }
-
- switch (trapno) {
- case 1: /* Debug */
- if (regs->eflags & EFLAGS_VM) {
- /* emulate any 8086 instructions */
- if (mode == VM86_REAL)
- return;
- if (mode != VM86_REAL_TO_PROTECTED)
- panic("not in real-to-protected mode");
- emulate(regs);
- return;
- }
- goto invalid;
-
- case 13: /* GPF */
- if (regs->eflags & EFLAGS_VM) {
- /* emulate any 8086 instructions */
- if (mode == VM86_PROTECTED)
- panic("unexpected protected mode");
- emulate(regs);
- return;
- }
- goto invalid;
-
- default:
- invalid:
- printf("Trap (0x%x) while in %s mode\n",
- trapno, regs->eflags & EFLAGS_VM ? "real" :
"protected");
- if (trapno == 14)
- printf("Page fault address 0x%x\n", get_cr2());
- dump_regs(regs);
- halt();
- }
-}
diff -r f8db1c6baad9 -r 9d0e86d8c1d1 tools/firmware/vmxassist/vm86.h
--- a/tools/firmware/vmxassist/vm86.h Tue Feb 05 23:27:12 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,64 +0,0 @@
-/*
- * vm86.h: vm86 emulator definitions.
- *
- * Leendert van Doorn, leendert@xxxxxxxxxxxxxx
- * 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.
- */
-#ifndef __VM86_H__
-#define __VM86_H__
-
-#ifndef __ASSEMBLY__
-#include <stdint.h>
-#endif
-
-#include <xen/hvm/vmx_assist.h>
-
-#ifndef __ASSEMBLY__
-
-struct regs {
- unsigned edi, esi, ebp, esp, ebx, edx, ecx, eax;
- unsigned trapno, errno;
- unsigned eip, cs, eflags, uesp, uss;
- unsigned ves, vds, vfs, vgs;
-};
-
-enum vm86_mode {
- VM86_REAL = 0,
- VM86_REAL_TO_PROTECTED,
- VM86_PROTECTED_TO_REAL,
- VM86_PROTECTED
-};
-
-#ifdef DEBUG
-#define TRACE(a) trace a
-#else
-#define TRACE(a)
-#endif
-
-extern enum vm86_mode prevmode, mode;
-extern struct vmx_assist_context oldctx;
-
-extern void emulate(struct regs *);
-extern void dump_regs(struct regs *);
-extern void trace(struct regs *, int, char *, ...);
-
-extern void set_mode(struct regs *, enum vm86_mode);
-extern void switch_to_real_mode(void);
-extern void switch_to_protected_mode(void);
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* __VM86_H__ */
diff -r f8db1c6baad9 -r 9d0e86d8c1d1 tools/firmware/vmxassist/vmxassist.ld
--- a/tools/firmware/vmxassist/vmxassist.ld Tue Feb 05 23:27:12 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,32 +0,0 @@
-/*
- * vmxassist.ld
- */
-OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
-ENTRY(_start)
-
-SECTIONS
-{
- _btext = .;
- .text TEXTADDR :
- {
- *(.text)
- *(.rodata)
- *(.rodata.*)
- }
- _etext = .;
-
- _bdata = .;
- .data :
- {
- *(.data)
- }
- _edata = .;
-
- _bbss = .;
- .bss :
- {
- *(.bss)
- }
- _ebss = .;
-}
-
diff -r f8db1c6baad9 -r 9d0e86d8c1d1 xen/arch/x86/Rules.mk
--- a/xen/arch/x86/Rules.mk Tue Feb 05 23:27:12 2008 +0000
+++ b/xen/arch/x86/Rules.mk Wed Feb 06 12:07:55 2008 +0000
@@ -11,11 +11,6 @@ xenoprof := y
#
pae ?= n
supervisor_mode_kernel ?= n
-vmxassist ?= n
-
-ifeq ($(vmxassist),y)
-CFLAGS += -DVMXASSIST
-endif
# Solaris grabs stdarg.h and friends from the system include directory.
ifneq ($(XEN_OS),SunOS)
diff -r f8db1c6baad9 -r 9d0e86d8c1d1 xen/arch/x86/hvm/hvm.c
--- a/xen/arch/x86/hvm/hvm.c Tue Feb 05 23:27:12 2008 +0000
+++ b/xen/arch/x86/hvm/hvm.c Wed Feb 06 12:07:55 2008 +0000
@@ -1671,16 +1671,6 @@ int hvm_bringup_ap(int vcpuid, int tramp
ctxt->flags = VGCF_online;
ctxt->user_regs.eflags = 2;
-#ifdef VMXASSIST
- if ( boot_cpu_data.x86_vendor == X86_VENDOR_INTEL )
- {
- ctxt->user_regs.eip = VMXASSIST_BASE;
- ctxt->user_regs.edx = vcpuid;
- ctxt->user_regs.ebx = trampoline_vector;
- goto done;
- }
-#endif
-
v->arch.hvm_vcpu.guest_cr[0] = X86_CR0_ET;
hvm_update_guest_cr(v, 0);
@@ -1721,9 +1711,6 @@ int hvm_bringup_ap(int vcpuid, int tramp
hvm_set_segment_register(v, x86_seg_gdtr, ®);
hvm_set_segment_register(v, x86_seg_idtr, ®);
-#ifdef VMXASSIST
- done:
-#endif
/* Sync AP's TSC with BSP's. */
v->arch.hvm_vcpu.cache_tsc_offset =
v->domain->vcpu[0]->arch.hvm_vcpu.cache_tsc_offset;
diff -r f8db1c6baad9 -r 9d0e86d8c1d1 xen/arch/x86/hvm/vmx/Makefile
--- a/xen/arch/x86/hvm/vmx/Makefile Tue Feb 05 23:27:12 2008 +0000
+++ b/xen/arch/x86/hvm/vmx/Makefile Wed Feb 06 12:07:55 2008 +0000
@@ -4,9 +4,7 @@ subdir-$(x86_64) += x86_64
subdir-$(x86_64) += x86_64
obj-y += intr.o
-ifneq ($(vmxassist),y)
obj-y += realmode.o
-endif
obj-y += vmcs.o
obj-y += vmx.o
obj-y += vpmu.o
diff -r f8db1c6baad9 -r 9d0e86d8c1d1 xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c Tue Feb 05 23:27:12 2008 +0000
+++ b/xen/arch/x86/hvm/vmx/vmx.c Wed Feb 06 12:07:55 2008 +0000
@@ -94,11 +94,10 @@ static int vmx_vcpu_initialise(struct vc
vmx_install_vlapic_mapping(v);
-#ifndef VMXASSIST
+ /* %eax == 1 signals full real-mode support to the guest loader. */
if ( v->vcpu_id == 0 )
v->arch.guest_context.user_regs.eax = 1;
v->arch.hvm_vcpu.io_complete = vmx_realmode_io_complete;
-#endif
return 0;
}
@@ -708,10 +707,6 @@ static void vmx_load_cpu_state(struct vc
v->arch.hvm_vmx.cstar = data->msr_cstar;
v->arch.hvm_vmx.shadow_gs = data->shadow_gs;
-#endif
-
-#ifdef VMXASSIST
- v->arch.hvm_vmx.vmxassist_enabled = !(data->cr0 & X86_CR0_PE);
#endif
hvm_set_guest_time(v, data->tsc);
@@ -1266,43 +1261,6 @@ void vmx_cpuid_intercept(
{
unsigned int input = *eax;
unsigned int count = *ecx;
-
-#ifdef VMXASSIST
- if ( input == 0x40000003 )
- {
- /*
- * NB. Unsupported interface for private use of VMXASSIST only.
- * Note that this leaf lives at <max-hypervisor-leaf> + 1.
- */
- u64 value = ((u64)*edx << 32) | (u32)*ecx;
- p2m_type_t p2mt;
- unsigned long mfn;
- struct vcpu *v = current;
- char *p;
-
- mfn = mfn_x(gfn_to_mfn_current(value >> PAGE_SHIFT, &p2mt));
-
- gdprintk(XENLOG_INFO, "Input address is 0x%"PRIx64".\n", value);
-
- /* 8-byte aligned valid pseudophys address from vmxassist, please. */
- if ( (value & 7) || !p2m_is_ram(p2mt) ||
- !v->arch.hvm_vmx.vmxassist_enabled )
- {
- domain_crash(v->domain);
- return;
- }
- ASSERT(mfn_valid(mfn));
-
- p = map_domain_page(mfn);
- value = *((uint64_t *)(p + (value & (PAGE_SIZE - 1))));
- unmap_domain_page(p);
-
- gdprintk(XENLOG_INFO, "Output value is 0x%"PRIx64".\n", value);
- *ecx = (u32)value;
- *edx = (u32)(value >> 32);
- return;
- }
-#endif
hvm_cpuid(input, eax, ebx, ecx, edx);
@@ -1843,256 +1801,6 @@ static void vmx_io_instruction(unsigned
}
}
-#ifdef VMXASSIST
-
-static void vmx_world_save(struct vcpu *v, struct vmx_assist_context *c)
-{
- struct cpu_user_regs *regs = guest_cpu_user_regs();
-
- c->eip = regs->eip;
- c->eip += __get_instruction_length(); /* Safe: MOV Cn, LMSW, CLTS */
- c->esp = regs->esp;
- c->eflags = regs->eflags & ~X86_EFLAGS_RF;
-
- c->cr0 = v->arch.hvm_vcpu.guest_cr[0];
- c->cr3 = v->arch.hvm_vcpu.guest_cr[3];
- c->cr4 = v->arch.hvm_vcpu.guest_cr[4];
-
- c->idtr_limit = __vmread(GUEST_IDTR_LIMIT);
- c->idtr_base = __vmread(GUEST_IDTR_BASE);
-
- c->gdtr_limit = __vmread(GUEST_GDTR_LIMIT);
- c->gdtr_base = __vmread(GUEST_GDTR_BASE);
-
- c->cs_sel = __vmread(GUEST_CS_SELECTOR);
- c->cs_limit = __vmread(GUEST_CS_LIMIT);
- c->cs_base = __vmread(GUEST_CS_BASE);
- c->cs_arbytes.bytes = __vmread(GUEST_CS_AR_BYTES);
-
- c->ds_sel = __vmread(GUEST_DS_SELECTOR);
- c->ds_limit = __vmread(GUEST_DS_LIMIT);
- c->ds_base = __vmread(GUEST_DS_BASE);
- c->ds_arbytes.bytes = __vmread(GUEST_DS_AR_BYTES);
-
- c->es_sel = __vmread(GUEST_ES_SELECTOR);
- c->es_limit = __vmread(GUEST_ES_LIMIT);
- c->es_base = __vmread(GUEST_ES_BASE);
- c->es_arbytes.bytes = __vmread(GUEST_ES_AR_BYTES);
-
- c->ss_sel = __vmread(GUEST_SS_SELECTOR);
- c->ss_limit = __vmread(GUEST_SS_LIMIT);
- c->ss_base = __vmread(GUEST_SS_BASE);
- c->ss_arbytes.bytes = __vmread(GUEST_SS_AR_BYTES);
-
- c->fs_sel = __vmread(GUEST_FS_SELECTOR);
- c->fs_limit = __vmread(GUEST_FS_LIMIT);
- c->fs_base = __vmread(GUEST_FS_BASE);
- c->fs_arbytes.bytes = __vmread(GUEST_FS_AR_BYTES);
-
- c->gs_sel = __vmread(GUEST_GS_SELECTOR);
- c->gs_limit = __vmread(GUEST_GS_LIMIT);
- c->gs_base = __vmread(GUEST_GS_BASE);
- c->gs_arbytes.bytes = __vmread(GUEST_GS_AR_BYTES);
-
- c->tr_sel = __vmread(GUEST_TR_SELECTOR);
- c->tr_limit = __vmread(GUEST_TR_LIMIT);
- c->tr_base = __vmread(GUEST_TR_BASE);
- c->tr_arbytes.bytes = __vmread(GUEST_TR_AR_BYTES);
-
- c->ldtr_sel = __vmread(GUEST_LDTR_SELECTOR);
- c->ldtr_limit = __vmread(GUEST_LDTR_LIMIT);
- c->ldtr_base = __vmread(GUEST_LDTR_BASE);
- c->ldtr_arbytes.bytes = __vmread(GUEST_LDTR_AR_BYTES);
-}
-
-static int vmx_world_restore(struct vcpu *v, struct vmx_assist_context *c)
-{
- struct cpu_user_regs *regs = guest_cpu_user_regs();
- int rc;
-
- rc = vmx_restore_cr0_cr3(v, c->cr0, c->cr3);
- if ( rc )
- return rc;
-
- regs->eip = c->eip;
- regs->esp = c->esp;
- regs->eflags = c->eflags | 2;
-
- v->arch.hvm_vcpu.guest_cr[4] = c->cr4;
- vmx_update_guest_cr(v, 0);
- vmx_update_guest_cr(v, 4);
-
- __vmwrite(GUEST_IDTR_LIMIT, c->idtr_limit);
- __vmwrite(GUEST_IDTR_BASE, c->idtr_base);
-
- __vmwrite(GUEST_GDTR_LIMIT, c->gdtr_limit);
- __vmwrite(GUEST_GDTR_BASE, c->gdtr_base);
-
- __vmwrite(GUEST_CS_SELECTOR, c->cs_sel);
- __vmwrite(GUEST_CS_LIMIT, c->cs_limit);
- __vmwrite(GUEST_CS_BASE, c->cs_base);
- __vmwrite(GUEST_CS_AR_BYTES, c->cs_arbytes.bytes);
-
- __vmwrite(GUEST_DS_SELECTOR, c->ds_sel);
- __vmwrite(GUEST_DS_LIMIT, c->ds_limit);
- __vmwrite(GUEST_DS_BASE, c->ds_base);
- __vmwrite(GUEST_DS_AR_BYTES, c->ds_arbytes.bytes);
-
- __vmwrite(GUEST_ES_SELECTOR, c->es_sel);
- __vmwrite(GUEST_ES_LIMIT, c->es_limit);
- __vmwrite(GUEST_ES_BASE, c->es_base);
- __vmwrite(GUEST_ES_AR_BYTES, c->es_arbytes.bytes);
-
- __vmwrite(GUEST_SS_SELECTOR, c->ss_sel);
- __vmwrite(GUEST_SS_LIMIT, c->ss_limit);
- __vmwrite(GUEST_SS_BASE, c->ss_base);
- __vmwrite(GUEST_SS_AR_BYTES, c->ss_arbytes.bytes);
-
- __vmwrite(GUEST_FS_SELECTOR, c->fs_sel);
- __vmwrite(GUEST_FS_LIMIT, c->fs_limit);
- __vmwrite(GUEST_FS_BASE, c->fs_base);
- __vmwrite(GUEST_FS_AR_BYTES, c->fs_arbytes.bytes);
-
- __vmwrite(GUEST_GS_SELECTOR, c->gs_sel);
- __vmwrite(GUEST_GS_LIMIT, c->gs_limit);
- __vmwrite(GUEST_GS_BASE, c->gs_base);
- __vmwrite(GUEST_GS_AR_BYTES, c->gs_arbytes.bytes);
-
- __vmwrite(GUEST_TR_SELECTOR, c->tr_sel);
- __vmwrite(GUEST_TR_LIMIT, c->tr_limit);
- __vmwrite(GUEST_TR_BASE, c->tr_base);
- __vmwrite(GUEST_TR_AR_BYTES, c->tr_arbytes.bytes);
-
- __vmwrite(GUEST_LDTR_SELECTOR, c->ldtr_sel);
- __vmwrite(GUEST_LDTR_LIMIT, c->ldtr_limit);
- __vmwrite(GUEST_LDTR_BASE, c->ldtr_base);
- __vmwrite(GUEST_LDTR_AR_BYTES, c->ldtr_arbytes.bytes);
-
- paging_update_paging_modes(v);
- return 0;
-}
-
-enum { VMX_ASSIST_INVOKE = 0, VMX_ASSIST_RESTORE };
-
-static int vmx_assist(struct vcpu *v, int mode)
-{
- struct vmx_assist_context c;
- struct hvm_hw_vpic *vpic = v->domain->arch.hvm_domain.vpic;
- u32 magic, cp;
-
- if ( hvm_copy_from_guest_phys(&magic, VMXASSIST_MAGIC_OFFSET,
- sizeof(magic)) )
- {
- gdprintk(XENLOG_ERR, "No vmxassist: can't execute real mode code\n");
- domain_crash(v->domain);
- return 0;
- }
-
- if ( magic != VMXASSIST_MAGIC )
- {
- gdprintk(XENLOG_ERR, "vmxassist magic number not match\n");
- domain_crash(v->domain);
- return 0;
- }
-
- switch ( mode ) {
- /*
- * Transfer control to vmxassist.
- * Store the current context in VMXASSIST_OLD_CONTEXT and load
- * the new VMXASSIST_NEW_CONTEXT context. This context was created
- * by vmxassist and will transfer control to it.
- */
- case VMX_ASSIST_INVOKE:
- /* save the old context */
- if ( hvm_copy_from_guest_phys(&cp, VMXASSIST_OLD_CONTEXT, sizeof(cp)) )
- goto error;
- if ( cp != 0 ) {
- vmx_world_save(v, &c);
- if ( hvm_copy_to_guest_phys(cp, &c, sizeof(c)) )
- goto error;
- }
-
- /* restore the new context, this should activate vmxassist */
- if ( hvm_copy_from_guest_phys(&cp, VMXASSIST_NEW_CONTEXT, sizeof(cp)) )
- goto error;
- if ( cp != 0 ) {
- if ( hvm_copy_from_guest_phys(&c, cp, sizeof(c)) )
- goto error;
- if ( vmx_world_restore(v, &c) != 0 )
- goto error;
- v->arch.hvm_vmx.pm_irqbase[0] = vpic[0].irq_base;
- v->arch.hvm_vmx.pm_irqbase[1] = vpic[1].irq_base;
- vpic[0].irq_base = NR_EXCEPTION_HANDLER;
- vpic[1].irq_base = NR_EXCEPTION_HANDLER + 8;
- v->arch.hvm_vmx.vmxassist_enabled = 1;
- return 1;
- }
- break;
-
- /*
- * Restore the VMXASSIST_OLD_CONTEXT that was saved by
- * VMX_ASSIST_INVOKE above.
- */
- case VMX_ASSIST_RESTORE:
- /* save the old context */
- if ( hvm_copy_from_guest_phys(&cp, VMXASSIST_OLD_CONTEXT, sizeof(cp)) )
- goto error;
- if ( cp != 0 ) {
- if ( hvm_copy_from_guest_phys(&c, cp, sizeof(c)) )
- goto error;
- if ( vmx_world_restore(v, &c) != 0 )
- goto error;
- if ( v->arch.hvm_vmx.irqbase_mode ) {
- vpic[0].irq_base = c.rm_irqbase[0] & 0xf8;
- vpic[1].irq_base = c.rm_irqbase[1] & 0xf8;
- } else {
- vpic[0].irq_base = v->arch.hvm_vmx.pm_irqbase[0];
- vpic[1].irq_base = v->arch.hvm_vmx.pm_irqbase[1];
- }
- v->arch.hvm_vmx.vmxassist_enabled = 0;
- return 1;
- }
- break;
- }
-
- error:
- gdprintk(XENLOG_ERR, "Failed to transfer to vmxassist\n");
- domain_crash(v->domain);
- return 0;
-}
-
-static int vmx_set_cr0(unsigned long value)
-{
- struct vcpu *v = current;
-
- if ( hvm_set_cr0(value) == 0 )
- return 0;
-
- /*
- * VMX does not implement real-mode virtualization. We emulate
- * real-mode by performing a world switch to VMXAssist whenever
- * a partition disables the CR0.PE bit.
- */
- if ( !(value & X86_CR0_PE) )
- {
- if ( vmx_assist(v, VMX_ASSIST_INVOKE) )
- return 0; /* do not update eip! */
- }
- else if ( v->arch.hvm_vmx.vmxassist_enabled )
- {
- if ( vmx_assist(v, VMX_ASSIST_RESTORE) )
- return 0; /* do not update eip! */
- }
-
- return 1;
-}
-
-#else /* !defined(VMXASSIST) */
-
-#define vmx_set_cr0(v) hvm_set_cr0(v)
-
-#endif
-
#define CASE_SET_REG(REG, reg) \
case REG_ ## REG: regs->reg = value; break
#define CASE_GET_REG(REG, reg) \
@@ -2146,7 +1854,7 @@ static int mov_to_cr(int gp, int cr, str
switch ( cr )
{
case 0:
- return vmx_set_cr0(value);
+ return hvm_set_cr0(value);
case 3:
return hvm_set_cr3(value);
@@ -2243,7 +1951,7 @@ static int vmx_cr_access(unsigned long e
value = (value & ~0xF) |
(((exit_qualification & LMSW_SOURCE_DATA) >> 16) & 0xF);
HVMTRACE_1D(LMSW, current, value);
- return vmx_set_cr0(value);
+ return hvm_set_cr0(value);
default:
BUG();
}
diff -r f8db1c6baad9 -r 9d0e86d8c1d1 xen/arch/x86/hvm/vmx/x86_32/exits.S
--- a/xen/arch/x86/hvm/vmx/x86_32/exits.S Tue Feb 05 23:27:12 2008 +0000
+++ b/xen/arch/x86/hvm/vmx/x86_32/exits.S Wed Feb 06 12:07:55 2008 +0000
@@ -115,10 +115,8 @@ ENTRY(vmx_asm_do_vmentry)
movl $GUEST_RFLAGS,%eax
VMWRITE(UREGS_eflags)
-#ifndef VMXASSIST
testb $0xff,VCPU_vmx_emul(%ebx)
jnz vmx_goto_realmode
-#endif
cmpb $0,VCPU_vmx_launched(%ebx)
je vmx_launch
@@ -138,7 +136,6 @@ vmx_launch:
call vm_launch_fail
ud2
-#ifndef VMXASSIST
vmx_goto_realmode:
sti
movl %esp,%eax
@@ -146,4 +143,3 @@ vmx_goto_realmode:
call vmx_realmode
addl $4,%esp
jmp vmx_asm_do_vmentry
-#endif
diff -r f8db1c6baad9 -r 9d0e86d8c1d1 xen/arch/x86/hvm/vmx/x86_64/exits.S
--- a/xen/arch/x86/hvm/vmx/x86_64/exits.S Tue Feb 05 23:27:12 2008 +0000
+++ b/xen/arch/x86/hvm/vmx/x86_64/exits.S Wed Feb 06 12:07:55 2008 +0000
@@ -134,10 +134,8 @@ ENTRY(vmx_asm_do_vmentry)
movl $GUEST_RFLAGS,%eax
VMWRITE(UREGS_eflags)
-#ifndef VMXASSIST
testb $0xff,VCPU_vmx_emul(%rbx)
jnz vmx_goto_realmode
-#endif
cmpb $0,VCPU_vmx_launched(%rbx)
je vmx_launch
@@ -157,10 +155,8 @@ vmx_launch:
call vm_launch_fail
ud2
-#ifndef VMXASSIST
vmx_goto_realmode:
sti
movq %rsp,%rdi
call vmx_realmode
jmp vmx_asm_do_vmentry
-#endif
diff -r f8db1c6baad9 -r 9d0e86d8c1d1 xen/arch/x86/hvm/vpic.c
--- a/xen/arch/x86/hvm/vpic.c Tue Feb 05 23:27:12 2008 +0000
+++ b/xen/arch/x86/hvm/vpic.c Wed Feb 06 12:07:55 2008 +0000
@@ -271,11 +271,6 @@ static void vpic_ioport_write(
vpic->imr = val;
break;
case 1:
-#ifdef VMXASSIST
- /* Which mode is irqbase programmed in? */
- current->arch.hvm_vmx.irqbase_mode =
- current->arch.hvm_vmx.vmxassist_enabled;
-#endif
/* ICW2 */
vpic->irq_base = val & 0xf8;
vpic->init_state++;
diff -r f8db1c6baad9 -r 9d0e86d8c1d1 xen/include/asm-x86/hvm/vmx/vmcs.h
--- a/xen/include/asm-x86/hvm/vmx/vmcs.h Tue Feb 05 23:27:12 2008 +0000
+++ b/xen/include/asm-x86/hvm/vmx/vmcs.h Wed Feb 06 12:07:55 2008 +0000
@@ -23,10 +23,6 @@
#include <asm/hvm/io.h>
#include <asm/hvm/vmx/cpu.h>
#include <asm/hvm/vmx/vpmu.h>
-
-#ifdef VMXASSIST
-#include <public/hvm/vmx_assist.h>
-#endif
extern void start_vmx(void);
extern void vmcs_dump_vcpu(struct vcpu *v);
@@ -94,14 +90,6 @@ struct arch_vmx_struct {
unsigned long host_cr0;
-#ifdef VMXASSIST
-
- unsigned long vmxassist_enabled:1;
- unsigned long irqbase_mode:1;
- unsigned char pm_irqbase[2];
-
-#else
-
/* Are we emulating rather than VMENTERing? */
#define VMXEMUL_REALMODE 1 /* Yes, because CR0.PE == 0 */
#define VMXEMUL_BAD_CS 2 /* Yes, because CS.RPL != CPL */
@@ -112,7 +100,6 @@ struct arch_vmx_struct {
bool_t real_mode_io_in_progress;
bool_t real_mode_io_completed;
unsigned long real_mode_io_data;
-#endif
};
int vmx_create_vmcs(struct vcpu *v);
diff -r f8db1c6baad9 -r 9d0e86d8c1d1 xen/include/public/hvm/vmx_assist.h
--- a/xen/include/public/hvm/vmx_assist.h Tue Feb 05 23:27:12 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,122 +0,0 @@
-/*
- * vmx_assist.h: Context definitions for the VMXASSIST world switch.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- *
- * Leendert van Doorn, leendert@xxxxxxxxxxxxxx
- * Copyright (c) 2005, International Business Machines Corporation.
- */
-
-#ifndef _VMX_ASSIST_H_
-#define _VMX_ASSIST_H_
-
-#define VMXASSIST_BASE 0xD0000
-#define VMXASSIST_MAGIC 0x17101966
-#define VMXASSIST_MAGIC_OFFSET (VMXASSIST_BASE+8)
-
-#define VMXASSIST_NEW_CONTEXT (VMXASSIST_BASE + 12)
-#define VMXASSIST_OLD_CONTEXT (VMXASSIST_NEW_CONTEXT + 4)
-
-#ifndef __ASSEMBLY__
-
-#define NR_EXCEPTION_HANDLER 32
-#define NR_INTERRUPT_HANDLERS 16
-#define NR_TRAPS (NR_EXCEPTION_HANDLER+NR_INTERRUPT_HANDLERS)
-
-union vmcs_arbytes {
- struct arbyte_fields {
- unsigned int seg_type : 4,
- s : 1,
- dpl : 2,
- p : 1,
- reserved0 : 4,
- avl : 1,
- reserved1 : 1,
- default_ops_size: 1,
- g : 1,
- null_bit : 1,
- reserved2 : 15;
- } fields;
- unsigned int bytes;
-};
-
-/*
- * World switch state
- */
-struct vmx_assist_context {
- uint32_t eip; /* execution pointer */
- uint32_t esp; /* stack pointer */
- uint32_t eflags; /* flags register */
- uint32_t cr0;
- uint32_t cr3; /* page table directory */
- uint32_t cr4;
- uint32_t idtr_limit; /* idt */
- uint32_t idtr_base;
- uint32_t gdtr_limit; /* gdt */
- uint32_t gdtr_base;
- uint32_t cs_sel; /* cs selector */
- uint32_t cs_limit;
- uint32_t cs_base;
- union vmcs_arbytes cs_arbytes;
- uint32_t ds_sel; /* ds selector */
- uint32_t ds_limit;
- uint32_t ds_base;
- union vmcs_arbytes ds_arbytes;
- uint32_t es_sel; /* es selector */
- uint32_t es_limit;
- uint32_t es_base;
- union vmcs_arbytes es_arbytes;
- uint32_t ss_sel; /* ss selector */
- uint32_t ss_limit;
- uint32_t ss_base;
- union vmcs_arbytes ss_arbytes;
- uint32_t fs_sel; /* fs selector */
- uint32_t fs_limit;
- uint32_t fs_base;
- union vmcs_arbytes fs_arbytes;
- uint32_t gs_sel; /* gs selector */
- uint32_t gs_limit;
- uint32_t gs_base;
- union vmcs_arbytes gs_arbytes;
- uint32_t tr_sel; /* task selector */
- uint32_t tr_limit;
- uint32_t tr_base;
- union vmcs_arbytes tr_arbytes;
- uint32_t ldtr_sel; /* ldtr selector */
- uint32_t ldtr_limit;
- uint32_t ldtr_base;
- union vmcs_arbytes ldtr_arbytes;
-
- unsigned char rm_irqbase[2];
-};
-typedef struct vmx_assist_context vmx_assist_context_t;
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* _VMX_ASSIST_H_ */
-
-/*
- * Local variables:
- * mode: C
- * c-set-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|