aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.hgignore2
-rw-r--r--docs/src/user.tex2
-rw-r--r--tools/debugger/libxendebug/xendebug.c4
-rw-r--r--tools/examples/Makefile2
-rw-r--r--tools/examples/README2
-rw-r--r--tools/examples/xmexample.hvm (renamed from tools/examples/xmexample.vmx)14
-rw-r--r--tools/firmware/Makefile5
-rw-r--r--tools/firmware/README10
-rw-r--r--tools/firmware/hvmloader/Makefile56
-rw-r--r--tools/firmware/hvmloader/acpi_madt.c (renamed from tools/firmware/vmxassist/acpi_madt.c)1
-rw-r--r--tools/firmware/hvmloader/hvmloader.c (renamed from tools/firmware/vmxassist/vmxloader.c)105
-rw-r--r--[-rwxr-xr-x]tools/firmware/hvmloader/mkhex (renamed from tools/firmware/vmxassist/mkhex)0
-rw-r--r--tools/firmware/rombios/rombios.c36
-rw-r--r--tools/firmware/rombios/rombios.diffs206
-rw-r--r--tools/firmware/vmxassist/Makefile21
-rw-r--r--tools/firmware/vmxassist/head.S3
-rw-r--r--tools/firmware/vmxassist/setup.c13
-rw-r--r--tools/firmware/vmxassist/vm86.c97
-rw-r--r--tools/firmware/vmxassist/vmxassist.ld1
-rw-r--r--tools/ioemu/exec-all.h2
-rw-r--r--tools/ioemu/hw/i8254.c32
-rw-r--r--tools/ioemu/hw/i8259.c4
-rw-r--r--tools/ioemu/monitor.c14
-rw-r--r--tools/ioemu/target-i386-dm/helper2.c10
-rw-r--r--tools/ioemu/vl.c8
-rw-r--r--tools/libxc/Makefile2
-rw-r--r--tools/libxc/xc_hvm_build.c (renamed from tools/libxc/xc_vmx_build.c)25
-rw-r--r--tools/libxc/xc_ia64_stubs.c2
-rw-r--r--tools/libxc/xc_linux_build.c2
-rw-r--r--tools/libxc/xc_ptrace.c4
-rw-r--r--tools/libxc/xc_ptrace_core.c4
-rw-r--r--tools/libxc/xenguest.h2
-rw-r--r--tools/python/xen/lowlevel/xc/xc.c21
-rw-r--r--tools/python/xen/xend/image.py32
-rw-r--r--tools/python/xen/xm/create.py12
-rw-r--r--tools/python/xen/xm/tests/test_create.py14
-rw-r--r--tools/xm-test/README24
-rw-r--r--tools/xm-test/configure.ac28
-rw-r--r--tools/xm-test/lib/XmTestLib/XenDomain.py14
-rw-r--r--tools/xm-test/lib/XmTestLib/config.py.in2
-rw-r--r--tools/xm-test/ramdisk/Makefile.am20
-rw-r--r--tools/xm-test/ramdisk/bin/create_disk_image2
-rw-r--r--tools/xm-test/tests/block-create/01_block_attach_device_pos.py4
-rw-r--r--tools/xm-test/tests/block-create/02_block_attach_file_device_pos.py4
-rw-r--r--tools/xm-test/tests/block-create/04_block_attach_device_repeatedly_pos.py4
-rw-r--r--tools/xm-test/tests/block-create/05_block_attach_and_dettach_device_repeatedly_pos.py4
-rw-r--r--tools/xm-test/tests/block-create/06_block_attach_baddomain_neg.py4
-rw-r--r--tools/xm-test/tests/block-create/07_block_attach_baddevice_neg.py4
-rw-r--r--tools/xm-test/tests/block-create/08_block_attach_bad_filedevice_neg.py4
-rw-r--r--tools/xm-test/tests/block-create/09_block_attach_and_dettach_device_check_data_pos.py4
-rw-r--r--tools/xm-test/tests/block-create/10_block_attach_dettach_multiple_devices.py4
-rw-r--r--tools/xm-test/tests/block-create/11_block_attach_shared_dom0.py4
-rw-r--r--tools/xm-test/tests/block-create/12_block_attach_shared_domU.py4
-rw-r--r--tools/xm-test/tests/block-destroy/01_block-destroy_btblock_pos.py4
-rw-r--r--tools/xm-test/tests/block-destroy/02_block-destroy_rtblock_pos.py4
-rw-r--r--tools/xm-test/tests/block-destroy/04_block-destroy_nonattached_neg.py4
-rw-r--r--tools/xm-test/tests/block-destroy/05_block-destroy_byname_pos.py4
-rw-r--r--tools/xm-test/tests/block-destroy/06_block-destroy_check_list_pos.py4
-rw-r--r--tools/xm-test/tests/block-list/01_block-list_pos.py4
-rw-r--r--tools/xm-test/tests/block-list/02_block-list_attachbd_pos.py4
-rw-r--r--tools/xm-test/tests/block-list/03_block-list_anotherbd_pos.py4
-rw-r--r--tools/xm-test/tests/block-list/04_block-list_nodb_pos.py4
-rw-r--r--tools/xm-test/tests/block-list/06_block-list_checkremove_pos.py4
-rw-r--r--tools/xm-test/tests/create/14_create_blockroot_pos.py2
-rw-r--r--tools/xm-test/tests/memmax/01_memmax_badparm_neg.py4
-rw-r--r--tools/xm-test/tests/memset/01_memset_basic_pos.py4
-rw-r--r--tools/xm-test/tests/memset/02_memset_badparm_neg.py4
-rw-r--r--tools/xm-test/tests/memset/03_memset_random_pos.py4
-rw-r--r--tools/xm-test/tests/memset/04_memset_smallmem_pos.py4
-rw-r--r--tools/xm-test/tests/migrate/01_migrate_localhost_pos.py4
-rw-r--r--tools/xm-test/tests/network-attach/01_network_attach_pos.py4
-rw-r--r--tools/xm-test/tests/network-attach/02_network_attach_detach_pos.py4
-rw-r--r--tools/xm-test/tests/network-attach/03_network_attach_detach_multiple_pos.py4
-rw-r--r--tools/xm-test/tests/restore/01_restore_basic_pos.py4
-rw-r--r--tools/xm-test/tests/restore/02_restore_badparm_neg.py4
-rw-r--r--tools/xm-test/tests/restore/03_restore_badfilename_neg.py4
-rw-r--r--tools/xm-test/tests/restore/04_restore_withdevices_pos.py4
-rw-r--r--tools/xm-test/tests/save/01_save_basic_pos.py4
-rw-r--r--tools/xm-test/tests/save/02_save_badparm_neg.py4
-rw-r--r--tools/xm-test/tests/save/03_save_bogusfile_neg.py4
-rw-r--r--tools/xm-test/tests/sysrq/01_sysrq_basic_neg.py4
-rw-r--r--tools/xm-test/tests/sysrq/02_sysrq_sync_pos.py4
-rw-r--r--tools/xm-test/tests/sysrq/03_sysrq_withreboot_pos.py4
-rw-r--r--xen/Rules.mk3
-rw-r--r--xen/arch/ia64/Makefile24
-rw-r--r--xen/arch/ia64/vmx/mmio.c2
-rw-r--r--xen/arch/ia64/vmx/vlsapic.c14
-rw-r--r--xen/arch/ia64/vmx/vmx_init.c4
-rw-r--r--xen/arch/ia64/vmx/vmx_vcpu.c2
-rw-r--r--xen/arch/x86/Makefile14
-rw-r--r--xen/arch/x86/cpu/amd.c113
-rw-r--r--xen/arch/x86/cpu/intel.c4
-rw-r--r--xen/arch/x86/dom0_ops.c15
-rw-r--r--xen/arch/x86/domain.c45
-rw-r--r--xen/arch/x86/hvm/hvm.c308
-rw-r--r--xen/arch/x86/hvm/i8259.c (renamed from xen/arch/x86/dm/i8259.c)60
-rw-r--r--xen/arch/x86/hvm/intercept.c (renamed from xen/arch/x86/vmx_intercept.c)106
-rw-r--r--xen/arch/x86/hvm/io.c (renamed from xen/arch/x86/vmx_io.c)355
-rw-r--r--xen/arch/x86/hvm/platform.c (renamed from xen/arch/x86/vmx_platform.c)146
-rw-r--r--xen/arch/x86/hvm/svm/emulate.c517
-rw-r--r--xen/arch/x86/hvm/svm/instrlen.c435
-rw-r--r--xen/arch/x86/hvm/svm/intr.c219
-rw-r--r--xen/arch/x86/hvm/svm/svm.c2707
-rw-r--r--xen/arch/x86/hvm/svm/vmcb.c605
-rw-r--r--xen/arch/x86/hvm/svm/x86_32/exits.S221
-rw-r--r--xen/arch/x86/hvm/svm/x86_64/exits.S179
-rw-r--r--xen/arch/x86/hvm/vioapic.c (renamed from xen/arch/x86/dm/vmx_vioapic.c)142
-rw-r--r--xen/arch/x86/hvm/vlapic.c (renamed from xen/arch/x86/vmx_vlapic.c)86
-rw-r--r--xen/arch/x86/hvm/vmx/io.c207
-rw-r--r--xen/arch/x86/hvm/vmx/vmcs.c (renamed from xen/arch/x86/vmx_vmcs.c)184
-rw-r--r--xen/arch/x86/hvm/vmx/vmx.c (renamed from xen/arch/x86/vmx.c)558
-rw-r--r--xen/arch/x86/hvm/vmx/x86_32/exits.S153
-rw-r--r--xen/arch/x86/hvm/vmx/x86_64/exits.S160
-rw-r--r--xen/arch/x86/i387.c3
-rw-r--r--xen/arch/x86/mpparse.c5
-rw-r--r--xen/arch/x86/shadow.c12
-rw-r--r--xen/arch/x86/x86_32/asm-offsets.c13
-rw-r--r--xen/arch/x86/x86_32/entry.S118
-rw-r--r--xen/arch/x86/x86_32/traps.c87
-rw-r--r--xen/arch/x86/x86_64/asm-offsets.c13
-rw-r--r--xen/arch/x86/x86_64/entry.S129
-rw-r--r--xen/arch/x86/x86_64/mm.c2
-rw-r--r--xen/arch/x86/x86_64/traps.c54
-rw-r--r--xen/include/asm-ia64/domain.h3
-rw-r--r--xen/include/asm-ia64/mm.h4
-rw-r--r--xen/include/asm-ia64/vmx_platform.h8
-rw-r--r--xen/include/asm-ia64/vmx_vcpu.h2
-rw-r--r--xen/include/asm-x86/config.h1
-rw-r--r--xen/include/asm-x86/cpufeature.h1
-rw-r--r--xen/include/asm-x86/domain.h12
-rw-r--r--xen/include/asm-x86/hvm/domain.h52
-rw-r--r--xen/include/asm-x86/hvm/hvm.h166
-rw-r--r--xen/include/asm-x86/hvm/io.h160
-rw-r--r--xen/include/asm-x86/hvm/support.h149
-rw-r--r--xen/include/asm-x86/hvm/svm/emulate.h161
-rw-r--r--xen/include/asm-x86/hvm/svm/intr.h34
-rw-r--r--xen/include/asm-x86/hvm/svm/svm.h91
-rw-r--r--xen/include/asm-x86/hvm/svm/vmcb.h503
-rw-r--r--xen/include/asm-x86/hvm/svm/vmmcall.h48
-rw-r--r--xen/include/asm-x86/hvm/vcpu.h51
-rw-r--r--xen/include/asm-x86/hvm/vioapic.h (renamed from xen/include/asm-x86/vmx_vioapic.h)22
-rw-r--r--xen/include/asm-x86/hvm/vlapic.h (renamed from xen/include/asm-x86/vmx_vlapic.h)20
-rw-r--r--xen/include/asm-x86/hvm/vmx/cpu.h (renamed from xen/include/asm-x86/vmx_cpu.h)12
-rw-r--r--xen/include/asm-x86/hvm/vmx/vmcs.h (renamed from xen/include/asm-x86/vmx_vmcs.h)80
-rw-r--r--xen/include/asm-x86/hvm/vmx/vmx.h (renamed from xen/include/asm-x86/vmx.h)99
-rw-r--r--xen/include/asm-x86/hvm/vpic.h (renamed from xen/include/asm-x86/vmx_vpic.h)27
-rw-r--r--xen/include/asm-x86/hvm/vpit.h74
-rw-r--r--xen/include/asm-x86/mpspec.h1
-rw-r--r--xen/include/asm-x86/msr.h10
-rw-r--r--xen/include/asm-x86/processor.h1
-rw-r--r--xen/include/asm-x86/regs.h6
-rw-r--r--xen/include/asm-x86/shadow.h17
-rw-r--r--xen/include/asm-x86/vmx_intercept.h65
-rw-r--r--xen/include/asm-x86/vmx_platform.h103
-rw-r--r--xen/include/asm-x86/vmx_vpit.h56
-rw-r--r--xen/include/public/arch-x86_32.h2
-rw-r--r--xen/include/public/arch-x86_64.h2
-rw-r--r--xen/include/xen/domain_page.h2
158 files changed, 8781 insertions, 2310 deletions
diff --git a/.hgignore b/.hgignore
index f867e970e1..9520d75d16 100644
--- a/.hgignore
+++ b/.hgignore
@@ -108,6 +108,8 @@
^tools/firmware/.*\.sym$
^tools/firmware/.*bios/.*bios.*\.txt$
^tools/firmware/acpi/acpigen$
+^tools/firmware/hvmloader/hvmloader$
+^tools/firmware/hvmloader/roms\.h$
^tools/firmware/rombios/BIOS-bochs-latest$
^tools/firmware/rombios/_rombios_\.c$
^tools/firmware/rombios/rombios\.s$
diff --git a/docs/src/user.tex b/docs/src/user.tex
index a27472ccce..7677bf6f85 100644
--- a/docs/src/user.tex
+++ b/docs/src/user.tex
@@ -137,7 +137,7 @@ support Xen, a key feature is that user space applications and
libraries \emph{do not} require modification.
With hardware CPU virtualization as provided by Intel VT and AMD
-Pacifica technology, the ability to run an unmodified guest OS kernel
+SVM technology, the ability to run an unmodified guest OS kernel
is available. No porting of the OS is required, although some
additional driver support is necessary within Xen itself. Unlike
traditional full virtualization hypervisors, which suffer a tremendous
diff --git a/tools/debugger/libxendebug/xendebug.c b/tools/debugger/libxendebug/xendebug.c
index 7a9deaa07f..8a4160637c 100644
--- a/tools/debugger/libxendebug/xendebug.c
+++ b/tools/debugger/libxendebug/xendebug.c
@@ -355,7 +355,7 @@ xendebug_memory_page (domain_context_p ctxt, int xc_handle, uint32_t vcpu,
if ( (pde = ctxt->cr3_virt[vcpu][vtopdi(va)]) == 0) /* logical address */
return 0;
- if (ctxt->context[vcpu].flags & VGCF_VMX_GUEST)
+ if (ctxt->context[vcpu].flags & VGCF_HVM_GUEST)
pde = ctxt->page_array[pde >> PAGE_SHIFT] << PAGE_SHIFT;
if (pde != ctxt->pde_phys[vcpu])
{
@@ -370,7 +370,7 @@ xendebug_memory_page (domain_context_p ctxt, int xc_handle, uint32_t vcpu,
if ((page = ctxt->pde_virt[vcpu][vtopti(va)]) == 0) /* logical address */
return 0;
- if (ctxt->context[vcpu].flags & VGCF_VMX_GUEST)
+ if (ctxt->context[vcpu].flags & VGCF_HVM_GUEST)
page = ctxt->page_array[page >> PAGE_SHIFT] << PAGE_SHIFT;
if (page != ctxt->page_phys[vcpu] || protection != ctxt->page_perm[vcpu])
{
diff --git a/tools/examples/Makefile b/tools/examples/Makefile
index 6c542aeae3..a94ea7aa0a 100644
--- a/tools/examples/Makefile
+++ b/tools/examples/Makefile
@@ -16,7 +16,7 @@ XEN_CONFIG_DIR = /etc/xen
XEN_CONFIGS = xend-config.sxp
XEN_CONFIGS += xmexample1
XEN_CONFIGS += xmexample2
-XEN_CONFIGS += xmexample.vmx
+XEN_CONFIGS += xmexample.hvm
XEN_CONFIGS += xmexample.vti
# Xen script dir and scripts to go there.
diff --git a/tools/examples/README b/tools/examples/README
index 889333ab63..a51ec758c4 100644
--- a/tools/examples/README
+++ b/tools/examples/README
@@ -32,6 +32,6 @@ xmexample2 - a more complex configuration script for 'xm create'
xmexample3 - an advanced configuration script for 'xm create'
that utilizes the vmid
xmexample.nbd - configuration script that uses NBD filesystems
-xmexample.vmx - a configuration script for creating a vmx domain with
+xmexample.hvm - a configuration script for creating a hvm domain with
'xm create'
xmexample.vti - a configuration script for creating a domain on vti
diff --git a/tools/examples/xmexample.vmx b/tools/examples/xmexample.hvm
index cdd7863912..a1b893b0d5 100644
--- a/tools/examples/xmexample.vmx
+++ b/tools/examples/xmexample.hvm
@@ -15,25 +15,25 @@ else:
#----------------------------------------------------------------------------
# Kernel image file.
-kernel = "/usr/lib/xen/boot/vmxloader"
+kernel = "/usr/lib/xen/boot/hvmloader"
-# The domain build function. VMX domain uses 'vmx'.
-builder='vmx'
+# The domain build function. HVM domain uses 'hvm'.
+builder='hvm'
# Initial memory allocation (in megabytes) for the new domain.
memory = 128
# A name for your domain. All domains must have different names.
-name = "ExampleVMXDomain"
+name = "ExampleHVMDomain"
#-----------------------------------------------------------------------------
# the number of cpus guest platform has, default=1
#vcpus=1
-# enable/disalbe vmx guest ACPI, default=0 (disabled)
+# enable/disable HVM guest ACPI, default=0 (disabled)
#acpi=0
-# enable/disalbe vmx guest APIC, default=0 (disabled)
+# enable/disable HVM guest APIC, default=0 (disabled)
#apic=0
# List of which CPUS this domain is allowed to use, default Xen picks
@@ -46,8 +46,6 @@ name = "ExampleVMXDomain"
#vif = [ 'type=ioemu, mac=00:16:3e:00:00:11, bridge=xenbr0' ]
# type=ioemu specify the NIC is an ioemu device not netfront
vif = [ 'type=ioemu, bridge=xenbr0' ]
-# for multiple NICs in device model, 3 in this example
-#vif = [ 'type=ioemu, bridge=xenbr0', 'type=ioemu', 'type=ioemu']
#----------------------------------------------------------------------------
# Define the disk devices you want the domain to have access to, and
diff --git a/tools/firmware/Makefile b/tools/firmware/Makefile
index 86918f5443..d0c738a41d 100644
--- a/tools/firmware/Makefile
+++ b/tools/firmware/Makefile
@@ -1,9 +1,9 @@
XEN_ROOT = ../..
include $(XEN_ROOT)/tools/Rules.mk
-# vmxloader is a 32-bit protected mode binary.
+# hvmloader is a 32-bit protected mode binary.
# It belongs in /usr/lib, not /usr/lib64.
-TARGET := vmxassist/vmxloader
+TARGET := hvmloader/hvmloader
INSTALL_DIR := $(DESTDIR)/usr/lib/xen/boot
SUBDIRS :=
@@ -11,6 +11,7 @@ SUBDIRS += rombios
SUBDIRS += vgabios
SUBDIRS += acpi
SUBDIRS += vmxassist
+SUBDIRS += hvmloader
.PHONY: all install clean
diff --git a/tools/firmware/README b/tools/firmware/README
index 0339fa679f..be796000f6 100644
--- a/tools/firmware/README
+++ b/tools/firmware/README
@@ -1,11 +1,11 @@
-Domain FirmWare support
+Domain firmware support
-----------------------
One of the key advantages of full virtualization hardware support (such
-as Intel's VT or AMD's Pacifica) 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.
+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
diff --git a/tools/firmware/hvmloader/Makefile b/tools/firmware/hvmloader/Makefile
new file mode 100644
index 0000000000..c23698e775
--- /dev/null
+++ b/tools/firmware/hvmloader/Makefile
@@ -0,0 +1,56 @@
+#
+# Makefile
+#
+# Leendert van Doorn, leendert@watson.ibm.com
+# Copyright (c) 2005, International Business Machines Corporation.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms and conditions of the GNU General Public License,
+# version 2, as published by the Free Software Foundation.
+#
+# This program is distributed in the hope it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+# Place - Suite 330, Boston, MA 02111-1307 USA.
+#
+
+XEN_ROOT = ../../..
+include $(XEN_ROOT)/tools/Rules.mk
+
+# The HVM loader is started in 32-bit mode at the address below:
+LOADADDR = 0x100000
+
+DEFINES =-DDEBUG
+XENINC =-I$(XEN_ROOT)/tools/libxc
+
+OBJECTS = hvmloader.o acpi_madt.o
+
+CC = gcc
+OBJCOPY = objcopy
+CFLAGS = $(DEFINES) -I. $(XENINC) -Wall -fno-builtin -O2 -msoft-float
+CFLAGS += -m32 -march=i686
+LDFLAGS = -m32 -nostdlib -Wl,-N -Wl,-Ttext -Wl,$(LOADADDR)
+
+all: hvmloader
+
+hvmloader: roms.h hvmloader.c acpi_madt.c
+ $(CC) $(CFLAGS) -c hvmloader.c acpi_madt.c
+ $(CC) $(LDFLAGS) -o hvmloader.tmp hvmloader.o acpi_madt.o
+ $(OBJCOPY) hvmloader.tmp hvmloader
+ rm -f hvmloader.tmp
+
+roms.h: ../rombios/BIOS-bochs-latest ../vgabios/VGABIOS-lgpl-latest.bin ../vgabios/VGABIOS-lgpl-latest.cirrus.bin ../vmxassist/vmxassist.bin
+ ./mkhex rombios ../rombios/BIOS-bochs-latest > roms.h
+ ./mkhex vgabios_stdvga ../vgabios/VGABIOS-lgpl-latest.bin >> roms.h
+ ./mkhex vgabios_cirrusvga ../vgabios/VGABIOS-lgpl-latest.cirrus.bin >> roms.h
+ ./mkhex vmxassist ../vmxassist/vmxassist.bin >> roms.h
+ ./mkhex acpi ../acpi/acpi.bin >> roms.h
+
+clean:
+ rm -f roms.h acpi.h
+ rm -f hvmloader hvmloader.tmp hvmloader.o $(OBJECTS)
+
diff --git a/tools/firmware/vmxassist/acpi_madt.c b/tools/firmware/hvmloader/acpi_madt.c
index 59e47b71c7..2e6d8d79e2 100644
--- a/tools/firmware/vmxassist/acpi_madt.c
+++ b/tools/firmware/hvmloader/acpi_madt.c
@@ -85,6 +85,7 @@ get_acpi_enabled(void)
return (t ? t->acpi_enabled : 0); /* default no acpi */
}
+
static void *
acpi_madt_get_madt(unsigned char *acpi_start)
{
diff --git a/tools/firmware/vmxassist/vmxloader.c b/tools/firmware/hvmloader/hvmloader.c
index 2a20715bfc..9700dfbb08 100644
--- a/tools/firmware/vmxassist/vmxloader.c
+++ b/tools/firmware/hvmloader/hvmloader.c
@@ -1,5 +1,5 @@
/*
- * vmxloader.c: ROM/VMXAssist image loader.
+ * hvmloader.c: HVM ROMBIOS/VGABIOS/ACPI/VMXAssist image loader.
*
* A quicky so that we can boot rom images as if they were a Linux kernel.
* This code will copy the rom images (ROMBIOS/VGABIOS/VM86) into their
@@ -21,13 +21,16 @@
* 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 "roms.h"
+#include "../acpi/acpi2_0.h" /* for ACPI_PHYSICAL_ADDRESS */
-#include "acpi.h"
-#include "../acpi/acpi2_0.h" // for ACPI_PHYSICAL_ADDRESS
-int acpi_madt_update(unsigned char* acpi_start);
-int get_acpi_enabled(void);
+/* memory map */
+#define VGABIOS_PHYSICAL_ADDRESS 0x000C0000
+#define VMXASSIST_PHYSICAL_ADDRESS 0x000D0000
+#define ROMBIOS_PHYSICAL_ADDRESS 0x000F0000
+
+/* invoke SVM's paged realmode support */
+#define SVM_VMMCALL_RESET_TO_REALMODE 0x00000001
/*
* C runtime start off
@@ -66,6 +69,30 @@ asm(
"stack_top: \n"
);
+extern int get_acpi_enabled(void);
+extern int acpi_madt_update(unsigned char* acpi_start);
+
+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;
+}
+
void *
memcpy(void *dest, const void *src, unsigned n)
{
@@ -103,38 +130,82 @@ cirrus_check(void)
return inb(0x3C5) == 0x12;
}
+int
+vmmcall(int edi, int esi, int edx, int ecx, int ebx)
+{
+ int eax;
+
+ __asm__ __volatile__(
+ ".byte 0x0F,0x01,0xD9"
+ : "=a" (eax)
+ : "a"(0x58454E00), /* XEN\0 key */
+ "b"(ebx), "c"(ecx), "d"(edx), "D"(edi), "S"(esi)
+ );
+ return eax;
+}
+
+int
+check_amd(void)
+{
+ char id[12];
+
+ __asm__ __volatile__(
+ "cpuid"
+ : "=b" (*(int *)(&id[0])),
+ "=c" (*(int *)(&id[8])),
+ "=d" (*(int *)(&id[4]))
+ : "a" (0)
+ );
+ return __builtin_memcmp(id, "AuthenticAMD", 12) == 0;
+}
+
int
main(void)
{
- puts("VMXAssist Loader\n");
+ puts("HVM Loader\n");
+
puts("Loading ROMBIOS ...\n");
- memcpy((void *)0xF0000, rombios, sizeof(rombios));
+ memcpy((void *)ROMBIOS_PHYSICAL_ADDRESS, rombios, sizeof(rombios));
if (cirrus_check()) {
puts("Loading Cirrus VGABIOS ...\n");
- memcpy((void *)0xC0000,
+ memcpy((void *)VGABIOS_PHYSICAL_ADDRESS,
vgabios_cirrusvga, sizeof(vgabios_cirrusvga));
} else {
puts("Loading Standard VGABIOS ...\n");
- memcpy((void *)0xC0000,
+ memcpy((void *)VGABIOS_PHYSICAL_ADDRESS,
vgabios_stdvga, sizeof(vgabios_stdvga));
}
if (get_acpi_enabled() != 0) {
puts("Loading ACPI ...\n");
- acpi_madt_update((unsigned char*)acpi);
+ acpi_madt_update((unsigned char *) acpi);
if (ACPI_PHYSICAL_ADDRESS+sizeof(acpi) <= 0xF0000) {
- /* make sure acpi table does not overlap rombios
+ /*
+ * Make sure acpi table does not overlap rombios
* currently acpi less than 8K will be OK.
*/
- memcpy((void *)ACPI_PHYSICAL_ADDRESS, acpi, sizeof(acpi));
+ memcpy((void *)ACPI_PHYSICAL_ADDRESS, acpi,
+ sizeof(acpi));
}
}
- puts("Loading VMXAssist ...\n");
- memcpy((void *)TEXTADDR, vmxassist, sizeof(vmxassist));
+ if (check_amd()) {
+ /* AMD implies this is SVM */
+ puts("SVM go ...\n");
+ vmmcall(SVM_VMMCALL_RESET_TO_REALMODE, 0, 0, 0, 0);
+ } else {
+ puts("Loading VMXAssist ...\n");
+ memcpy((void *)VMXASSIST_PHYSICAL_ADDRESS,
+ vmxassist, sizeof(vmxassist));
- puts("Go ...\n");
- asm volatile ( "jmp *%%eax" : : "a" (TEXTADDR), "d" (0) );
+ puts("VMX go ...\n");
+ __asm__ __volatile__(
+ "jmp *%%eax"
+ : : "a" (VMXASSIST_PHYSICAL_ADDRESS), "d" (0)
+ );
+ }
+ puts("Failed to invoke ROMBIOS\n");
return 0;
}
+
diff --git a/tools/firmware/vmxassist/mkhex b/tools/firmware/hvmloader/mkhex
index 7389d70483..7389d70483 100755..100644
--- a/tools/firmware/vmxassist/mkhex
+++ b/tools/firmware/hvmloader/mkhex
diff --git a/tools/firmware/rombios/rombios.c b/tools/firmware/rombios/rombios.c
index 857e94523a..397b9d8204 100644
--- a/tools/firmware/rombios/rombios.c
+++ b/tools/firmware/rombios/rombios.c
@@ -26,8 +26,8 @@
// ROM BIOS for use with Bochs/Plex x86 emulation environment
-#define VMXASSIST
-#undef VMXTEST
+#define HVMASSIST
+#undef HVMTEST
// Xen full virtualization does not handle unaligned IO with page crossing.
// Disable 32-bit PIO as a workaround.
@@ -177,8 +177,8 @@
#define BASE_MEM_IN_K (640 - EBDA_SIZE)
// Define the application NAME
-#ifdef VMXASSIST
-# define BX_APPNAME "VMXAssist"
+#ifdef HVMASSIST
+# define BX_APPNAME "HVMAssist"
#elif PLEX86
# define BX_APPNAME "Plex86"
#else
@@ -1430,7 +1430,7 @@ ASM_START
ASM_END
}
-#ifdef VMXASSIST
+#ifdef HVMASSIST
void
copy_e820_table()
{
@@ -1440,7 +1440,7 @@ copy_e820_table()
write_word(0xe000, 0x8, nr_entries);
memcpyb(0xe000, 0x10, 0x9000, 0x2d0, nr_entries * 0x14);
}
-#endif /* VMXASSIST */
+#endif /* HVMASSIST */
#if BX_DEBUG_SERIAL
/* serial debug port*/
@@ -1520,7 +1520,7 @@ send(action, c)
if (c == '\n') uart_tx_byte(BX_DEBUG_PORT, '\r');
uart_tx_byte(BX_DEBUG_PORT, c);
#endif
-#ifdef VMXASSIST
+#ifdef HVMASSIST
outb(0xE9, c);
#endif
#if BX_VIRTUAL_PORTS
@@ -4089,7 +4089,7 @@ ASM_END
case 0x20: // coded by osmaker aka K.J.
if(regs.u.r32.edx == 0x534D4150) /* SMAP */
{
-#ifdef VMXASSIST
+#ifdef HVMASSIST
if ((regs.u.r16.bx / 0x14) * 0x14 == regs.u.r16.bx) {
Bit16u e820_table_size = read_word(0xe000, 0x8) * 0x14;
@@ -9595,7 +9595,7 @@ post_default_ints:
;; int 1C already points at dummy_iret_handler (above)
mov al, #0x34 ; timer0: binary count, 16bit count, mode 2
out 0x43, al
-#ifdef VMXASSIST
+#ifdef HVMASSIST
mov al, #0x0b ; #0xe90b = 20 Hz (temporary, until we fix xen/vmx support)
out 0x40, al ; lsb
mov al, #0xe9
@@ -9702,22 +9702,10 @@ post_default_ints:
mov al, #0x11 ; send initialisation commands
out 0x20, al
out 0xa0, al
-#ifdef VMXASSIST
- ;; The vm86 emulator expects interrupts to be mapped beyond the reserved
- ;; vectors (0 through 31). Since rombios fully controls the hardware, we
- ;; map it the way the emulator needs it and expect that it will do the
- ;; proper 8086 interrupt translation (that is, master pic base is at 0x8
- ;; and slave pic base is at 0x70).
- mov al, #0x20
- out 0x21, al
- mov al, #0x28
- out 0xa1, al
-#else
mov al, #0x08
out 0x21, al
mov al, #0x70
out 0xa1, al
-#endif
mov al, #0x04
out 0x21, al
mov al, #0x02
@@ -9734,7 +9722,7 @@ post_default_ints:
#endif
out 0xa1, AL ;slave pic: unmask IRQ 12, 13, 14
-#ifdef VMXASSIST
+#ifdef HVMASSIST
call _copy_e820_table
#endif
@@ -10368,13 +10356,13 @@ dummy_iret_handler:
HALT(__LINE__)
iret
-#ifdef VMXTEST
+#ifdef HVMTEST
.org 0xffe0
jmp 0xf000:post;
#endif
.org 0xfff0 ; Power-up Entry Point
-#ifdef VMXTEST
+#ifdef HVMTEST
jmp 0xd000:0x0003;
#else
jmp 0xf000:post
diff --git a/tools/firmware/rombios/rombios.diffs b/tools/firmware/rombios/rombios.diffs
deleted file mode 100644
index 8ec23ef9de..0000000000
--- a/tools/firmware/rombios/rombios.diffs
+++ /dev/null
@@ -1,206 +0,0 @@
---- /home/leendert/cvs/bochs/bios/rombios.c 2005-05-23 12:18:11.000000000 -0400
-+++ rombios.c 2005-06-01 23:46:45.000000000 -0400
-@@ -26,6 +26,7 @@
-
- // ROM BIOS for use with Bochs/Plex x86 emulation environment
-
-+#define VMXASSIST
-
- // ROM BIOS compatability entry points:
- // ===================================
-@@ -170,7 +171,9 @@
- #define BASE_MEM_IN_K (640 - EBDA_SIZE)
-
- // Define the application NAME
--#ifdef PLEX86
-+#ifdef VMXASSIST
-+# define BX_APPNAME "VMXAssist"
-+#elif PLEX86
- # define BX_APPNAME "Plex86"
- #else
- # define BX_APPNAME "Bochs"
-@@ -314,7 +317,6 @@
- ASM_END
- }
-
--#if 0
- // memcpy of count bytes
- void
- memcpyb(dseg,doffset,sseg,soffset,count)
-@@ -362,6 +364,7 @@
- ASM_END
- }
-
-+#if 0
- // memcpy of count dword
- void
- memcpyd(dseg,doffset,sseg,soffset,count)
-@@ -858,6 +861,7 @@
- static void write_byte();
- static void write_word();
- static void bios_printf();
-+static void copy_e820_table();
-
- static Bit8u inhibit_mouse_int_and_events();
- static void enable_mouse_int_and_events();
-@@ -1420,6 +1424,16 @@
- ASM_END
- }
-
-+#ifdef VMXASSIST
-+void
-+copy_e820_table()
-+{
-+ Bit8u nr_entries = read_byte(0x9000, 0x1e8);
-+ write_word(0xe000, 0x8, nr_entries);
-+ memcpyb(0xe000, 0x10, 0x9000, 0x2d0, nr_entries * 0x14);
-+}
-+#endif /* VMXASSIST */
-+
- #if BX_DEBUG_SERIAL
- /* serial debug port*/
- #define BX_DEBUG_PORT 0x03f8
-@@ -1498,6 +1512,9 @@
- if (c == '\n') uart_tx_byte(BX_DEBUG_PORT, '\r');
- uart_tx_byte(BX_DEBUG_PORT, c);
- #endif
-+#ifdef VMXASSIST
-+ outb(0xE9, c);
-+#endif
- #if BX_VIRTUAL_PORTS
- if (action & BIOS_PRINTF_DEBUG) outb(DEBUG_PORT, c);
- if (action & BIOS_PRINTF_INFO) outb(INFO_PORT, c);
-@@ -4053,6 +4070,66 @@
- case 0x20: // coded by osmaker aka K.J.
- if(regs.u.r32.edx == 0x534D4150)
- {
-+#ifdef VMXASSIST
-+ if ((regs.u.r16.bx / 0x14)* 0x14 == regs.u.r16.bx) {
-+ Bit16u e820_table_size = read_word(0xe000, 0x8) * 0x14;
-+
-+ if (regs.u.r16.bx + 0x14 <= e820_table_size) {
-+ memcpyb(ES, regs.u.r16.di,
-+ 0xe000, 0x10 + regs.u.r16.bx, 0x14);
-+ }
-+ regs.u.r32.ebx += 0x14;
-+ if ((regs.u.r32.ebx + 0x14 - 1) > e820_table_size)
-+ regs.u.r32.ebx = 0;
-+ regs.u.r32.eax = 0x534D4150;
-+ regs.u.r32.ecx = 0x14;
-+ CLEAR_CF();
-+ return;
-+ } else if (regs.u.r16.bx == 1) {
-+ extended_memory_size = inb_cmos(0x35);
-+ extended_memory_size <<= 8;
-+ extended_memory_size |= inb_cmos(0x34);
-+ extended_memory_size *= 64;
-+ if (extended_memory_size > 0x3bc000) // greater than EFF00000???
-+ {
-+ extended_memory_size = 0x3bc000; // everything after this is reserved memory until we get to 0x100000000
-+ }
-+ extended_memory_size *= 1024;
-+ extended_memory_size += 15728640; // make up for the 16mb of memory that is chopped off
-+
-+ if (extended_memory_size <= 15728640)
-+ {
-+ extended_memory_size = inb_cmos(0x31);
-+ extended_memory_size <<= 8;
-+ extended_memory_size |= inb_cmos(0x30);
-+ extended_memory_size *= 1024;
-+ }
-+
-+ write_word(ES, regs.u.r16.di, 0x0000);
-+ write_word(ES, regs.u.r16.di+2, 0x0010);
-+ write_word(ES, regs.u.r16.di+4, 0x0000);
-+ write_word(ES, regs.u.r16.di+6, 0x0000);
-+
-+ write_word(ES, regs.u.r16.di+8, extended_memory_size);
-+ extended_memory_size >>= 16;
-+ write_word(ES, regs.u.r16.di+10, extended_memory_size);
-+ extended_memory_size >>= 16;
-+ write_word(ES, regs.u.r16.di+12, extended_memory_size);
-+ extended_memory_size >>= 16;
-+ write_word(ES, regs.u.r16.di+14, extended_memory_size);
-+
-+ write_word(ES, regs.u.r16.di+16, 0x1);
-+ write_word(ES, regs.u.r16.di+18, 0x0);
-+
-+ regs.u.r32.ebx = 0;
-+ regs.u.r32.eax = 0x534D4150;
-+ regs.u.r32.ecx = 0x14;
-+ CLEAR_CF();
-+ return;
-+ } else { /* AX=E820, DX=534D4150, BX unrecognized */
-+ goto int15_unimplemented;
-+ }
-+#else
- switch(regs.u.r16.bx)
- {
- case 0:
-@@ -4070,6 +4147,7 @@
- write_word(ES, regs.u.r16.di+18, 0x0);
-
- regs.u.r32.ebx = 1;
-+
- regs.u.r32.eax = 0x534D4150;
- regs.u.r32.ecx = 0x14;
- CLEAR_CF();
-@@ -4121,6 +4199,7 @@
- goto int15_unimplemented;
- break;
- }
-+#endif
- } else {
- // if DX != 0x534D4150)
- goto int15_unimplemented;
-@@ -9497,9 +9576,16 @@
- ;; int 1C already points at dummy_iret_handler (above)
- mov al, #0x34 ; timer0: binary count, 16bit count, mode 2
- out 0x43, al
-+#ifdef VMXASSIST
-+ mov al, #0x0b ; #0xe90b = 20 Hz (temporary, until we fix xen/vmx support)
-+ out 0x40, al ; lsb
-+ mov al, #0xe9
-+ out 0x40, al ; msb
-+#else
- mov al, #0x00 ; maximum count of 0000H = 18.2Hz
- out 0x40, al
- out 0x40, al
-+#endif
-
- ;; Keyboard
- SET_INT_VECTOR(0x09, #0xF000, #int09_handler)
-@@ -9597,10 +9683,22 @@
- mov al, #0x11 ; send initialisation commands
- out 0x20, al
- out 0xa0, al
-+#ifdef VMXASSIST
-+ ;; The vm86 emulator expects interrupts to be mapped beyond the reserved
-+ ;; vectors (0 through 31). Since rombios fully controls the hardware, we
-+ ;; map it the way the emulator needs it and expect that it will do the
-+ ;; proper 8086 interrupt translation (that is, master pic base is at 0x8
-+ ;; and slave pic base is at 0x70).
-+ mov al, #0x20
-+ out 0x21, al
-+ mov al, #0x28
-+ out 0xa1, al
-+#else
- mov al, #0x08
- out 0x21, al
- mov al, #0x70
- out 0xa1, al
-+#endif
- mov al, #0x04
- out 0x21, al
- mov al, #0x02
-@@ -9617,6 +9715,10 @@
- #endif
- out 0xa1, AL ;slave pic: unmask IRQ 12, 13, 14
-
-+#ifdef VMXASSIST
-+ call _copy_e820_table
-+#endif
-+
- call pcibios_init
-
- call rom_scan
diff --git a/tools/firmware/vmxassist/Makefile b/tools/firmware/vmxassist/Makefile
index e64473716b..4f84410132 100644
--- a/tools/firmware/vmxassist/Makefile
+++ b/tools/firmware/vmxassist/Makefile
@@ -37,13 +37,7 @@ LDFLAGS = -m elf_i386
OBJECTS = head.o trap.o vm86.o setup.o util.o
-all: vmxloader
-
-vmxloader: roms.h vmxloader.c acpi.h acpi_madt.c
- $(CC) $(CFLAGS) $(DEFINES) -c vmxloader.c -c acpi_madt.c
- $(CC) -o vmxloader.tmp -m32 -nostdlib -Wl,-N -Wl,-Ttext -Wl,0x100000 vmxloader.o acpi_madt.o
- objcopy vmxloader.tmp vmxloader
- rm -f vmxloader.tmp
+all: vmxassist.bin
vmxassist.bin: vmxassist.ld $(OBJECTS)
$(CPP) $(DEFINES) vmxassist.ld > vmxassist.tmp
@@ -68,15 +62,6 @@ setup.o: machine.h setup.c
util.o: machine.h util.c
$(CC) $(CFLAGS) -c util.c
-roms.h: ../rombios/BIOS-bochs-latest ../vgabios/VGABIOS-lgpl-latest.bin ../vgabios/VGABIOS-lgpl-latest.cirrus.bin vmxassist.bin
- ./mkhex rombios ../rombios/BIOS-bochs-latest > roms.h
- ./mkhex vgabios_stdvga ../vgabios/VGABIOS-lgpl-latest.bin >> roms.h
- ./mkhex vgabios_cirrusvga ../vgabios/VGABIOS-lgpl-latest.cirrus.bin >> roms.h
- ./mkhex vmxassist vmxassist.bin >> roms.h
-
-acpi.h: ../acpi/acpi.bin
- ./mkhex acpi ../acpi/acpi.bin > acpi.h
-
offsets.h: gen
./gen > offsets.h
@@ -84,7 +69,7 @@ gen: gen.c
$(HOSTCC) $(HOSTCFLAGS) -I. $(XENINC) -o gen gen.c
clean:
- rm -f vmxassist vmxassist.tmp vmxassist.bin vmxassist.run vmxassist.sym head.s roms.h acpi.h
- rm -f vmxloader vmxloader.tmp vmxloader.o $(OBJECTS)
+ rm -f vmxassist vmxassist.tmp vmxassist.bin vmxassist.run vmxassist.sym head.s
+ rm -f $(OBJECTS)
rm -f gen gen.o offsets.h
diff --git a/tools/firmware/vmxassist/head.S b/tools/firmware/vmxassist/head.S
index 1410a730f0..129f69274f 100644
--- a/tools/firmware/vmxassist/head.S
+++ b/tools/firmware/vmxassist/head.S
@@ -111,6 +111,9 @@ _start:
cli
/* save register parameters to C land */
+#ifdef TEST
+ xorl %edx, %edx
+#endif
movl %edx, booting_cpu
movl %ebx, booting_vector
diff --git a/tools/firmware/vmxassist/setup.c b/tools/firmware/vmxassist/setup.c
index dc253afec0..c4fcbb6846 100644
--- a/tools/firmware/vmxassist/setup.c
+++ b/tools/firmware/vmxassist/setup.c
@@ -194,6 +194,12 @@ setup_pic(void)
}
void
+setiomap(int port)
+{
+ tss.iomap[port >> 3] |= 1 << (port & 7);
+}
+
+void
enter_real_mode(struct regs *regs)
{
/* mask off TSS busy bit */
@@ -217,6 +223,13 @@ enter_real_mode(struct regs *regs)
}
regs->uesp = 0;
regs->uss = 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);
diff --git a/tools/firmware/vmxassist/vm86.c b/tools/firmware/vmxassist/vm86.c
index c9a5311405..eb3ee3992c 100644
--- a/tools/firmware/vmxassist/vm86.c
+++ b/tools/firmware/vmxassist/vm86.c
@@ -738,6 +738,83 @@ interrupt(struct regs *regs, int n)
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.
+ */
+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);
+ 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);
+ al = NR_EXCEPTION_HANDLER+8;
+ }
+ break;
+ }
+
+ outb(port, al);
+ return 1;
+}
+
+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;
+}
+
enum { OPC_INVALID, OPC_EMULATED };
/*
@@ -885,6 +962,16 @@ opcode(struct regs *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)) {
@@ -903,6 +990,16 @@ opcode(struct regs *regs)
}
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;
diff --git a/tools/firmware/vmxassist/vmxassist.ld b/tools/firmware/vmxassist/vmxassist.ld
index c9807c63f6..5bcc491075 100644
--- a/tools/firmware/vmxassist/vmxassist.ld
+++ b/tools/firmware/vmxassist/vmxassist.ld
@@ -2,7 +2,6 @@
* vmxassist.ld
*/
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
-/*OUTPUT_ARCH(i386)*/
ENTRY(_start)
SECTIONS
diff --git a/tools/ioemu/exec-all.h b/tools/ioemu/exec-all.h
index 0e5ab710d6..97d591bcf6 100644
--- a/tools/ioemu/exec-all.h
+++ b/tools/ioemu/exec-all.h
@@ -584,5 +584,5 @@ static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr)
//#define DEBUG_UNUSED_IOPORT
//#define DEBUG_IOPORT
-#define TARGET_VMX
+#define TARGET_HVM
diff --git a/tools/ioemu/hw/i8254.c b/tools/ioemu/hw/i8254.c
index 226db96962..1d98bd72a5 100644
--- a/tools/ioemu/hw/i8254.c
+++ b/tools/ioemu/hw/i8254.c
@@ -50,7 +50,7 @@ typedef struct PITChannelState {
int64_t next_transition_time;
QEMUTimer *irq_timer;
int irq;
- int vmx_channel; /* Is this accelerated by VMX ? */
+ int hvm_channel; /* Is this accelerated by HVM ? */
} PITChannelState;
struct PITState {
@@ -61,8 +61,8 @@ static PITState pit_state;
static void pit_irq_timer_update(PITChannelState *s, int64_t current_time);
-/* currently operate which channel for vmx use */
-int vmx_channel = -1;
+/* currently operate which channel for hvm use */
+int hvm_channel = -1;
extern FILE *logfile;
static int pit_get_count(PITChannelState *s)
{
@@ -215,7 +215,7 @@ int pit_get_gate(PITState *pit, int channel)
return s->gate;
}
-void pit_reset_vmx_vectors()
+void pit_reset_hvm_vectors()
{
extern shared_iopage_t *shared_page;
ioreq_t *req;
@@ -225,18 +225,18 @@ void pit_reset_vmx_vectors()
irq = 0;
for(i = 0; i < 3; i++) {
- if (pit_state.channels[i].vmx_channel)
+ if (pit_state.channels[i].hvm_channel)
break;
}
if (i == 3)
return;
- /* Assumes just one VMX accelerated channel */
- vmx_channel = i;
- s = &pit_state.channels[vmx_channel];
+ /* Assumes just one HVM accelerated channel */
+ hvm_channel = i;
+ s = &pit_state.channels[hvm_channel];
fprintf(logfile,
- "VMX_PIT:guest init pit channel %d!\n", vmx_channel);
+ "HVM_PIT:guest init pit channel %d!\n", hvm_channel);
req = &shared_page->vcpu_iodata[0].vp_ioreq;
req->state = STATE_IORESP_HOOK;
@@ -247,9 +247,9 @@ void pit_reset_vmx_vectors()
*/
req->u.data = s->count;
req->u.data |= (irq << 16);
- req->u.data |= (vmx_channel << 24);
+ req->u.data |= (hvm_channel << 24);
req->u.data |= ((s->rw_mode) << 26);
- fprintf(logfile, "VMX_PIT:pass info 0x%llx to HV!\n", req->u.data);
+ fprintf(logfile, "HVM_PIT:pass info 0x%llx to HV!\n", req->u.data);
}
static inline void pit_load_count(PITChannelState *s, int val)
@@ -261,9 +261,9 @@ static inline void pit_load_count(PITChannelState *s, int val)
/* guest init this pit channel for periodic mode. we do not update related
* timer so the channel never send intr from device model*/
- if (vmx_channel != -1 && s->mode == 2) {
- pit_reset_vmx_vectors();
- vmx_channel = -1;
+ if (hvm_channel != -1 && s->mode == 2) {
+ pit_reset_hvm_vectors();
+ hvm_channel = -1;
}
/* pit_irq_timer_update(s, s->count_load_time);*/
@@ -323,8 +323,8 @@ static void pit_ioport_write(void *opaque, uint32_t addr, uint32_t val)
}
} else {
s = &pit->channels[addr];
- s->vmx_channel = 1;
- vmx_channel = addr;
+ s->hvm_channel = 1;
+ hvm_channel = addr;
switch(s->write_state) {
default:
case RW_STATE_LSB:
diff --git a/tools/ioemu/hw/i8259.c b/tools/ioemu/hw/i8259.c
index 6385bca28f..4964076041 100644
--- a/tools/ioemu/hw/i8259.c
+++ b/tools/ioemu/hw/i8259.c
@@ -31,7 +31,7 @@
//#define DEBUG_IRQ_LATENCY
//#define DEBUG_IRQ_COUNT
-extern void pit_reset_vmx_vectors();
+extern void pit_reset_hvm_vectors();
typedef struct PicState {
uint8_t last_irr; /* edge detection */
@@ -368,7 +368,7 @@ static void pic_ioport_write(void *opaque, uint32_t addr, uint32_t val)
case 1:
s->irq_base = val & 0xf8;
s->init_state = 2;
- pit_reset_vmx_vectors();
+ pit_reset_hvm_vectors();
break;
case 2:
if (s->init4) {
diff --git a/tools/ioemu/monitor.c b/tools/ioemu/monitor.c
index 643313197d..3280dc0169 100644
--- a/tools/ioemu/monitor.c
+++ b/tools/ioemu/monitor.c
@@ -225,10 +225,10 @@ static void do_info_history (void)
}
}
-extern void destroy_vmx_domain(void);
+extern void destroy_hvm_domain(void);
static void do_quit(void)
{
- destroy_vmx_domain();
+ destroy_hvm_domain();
exit(0);
}
@@ -506,8 +506,8 @@ static term_cmd_t info_cmds[] = {
"", "show i8259 (PIC) state", },
{ "pci", "", pci_info,
"", "show PCI info", },
- { "vmxiopage", "", sp_info,
- "", "show VMX device model shared page info", },
+ { "hvmiopage", "", sp_info,
+ "", "show HVM device model shared page info", },
{ NULL, NULL, },
};
@@ -700,7 +700,7 @@ static void monitor_handle_command(const char *cmdline)
args[nb_args++] = (void *)has_option;
}
break;
- /* TODO: add more commands we need here to support vmx device model */
+ /* TODO: add more commands we need here to support hvm device model */
case '/':
case 'i':
default:
@@ -772,14 +772,14 @@ static void monitor_handle_command1(void *opaque, const char *cmdline)
static void monitor_start_input(void)
{
- readline_start("(VTXen) ", 0, monitor_handle_command1, NULL);
+ readline_start("(HVMXen) ", 0, monitor_handle_command1, NULL);
}
void monitor_init(CharDriverState *hd, int show_banner)
{
monitor_hd = hd;
if (show_banner) {
- term_printf("VMX device model. type 'q' to exit\n");
+ term_printf("HVM device model. type 'q' to exit\n");
}
qemu_chr_add_read_handler(hd, term_can_read, term_read, NULL);
monitor_start_input();
diff --git a/tools/ioemu/target-i386-dm/helper2.c b/tools/ioemu/target-i386-dm/helper2.c
index 4d3088ce3b..94f10df4a3 100644
--- a/tools/ioemu/target-i386-dm/helper2.c
+++ b/tools/ioemu/target-i386-dm/helper2.c
@@ -20,7 +20,9 @@
/*
* Main cpu loop for handling I/O requests coming from a virtual machine
+ *
* Copyright © 2004, Intel Corporation.
+ * Copyright © 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 Lesser General Public License,
@@ -394,7 +396,7 @@ void cpu_handle_ioreq(CPUState *env)
int xc_handle;
void
-destroy_vmx_domain(void)
+destroy_hvm_domain(void)
{
extern FILE* logfile;
char destroy_cmd[32];
@@ -467,11 +469,11 @@ int main_loop(void)
(void)ioctl(evtchn_fd, IOCTL_EVTCHN_NOTIFY, &notify);
}
}
- destroy_vmx_domain();
+ destroy_hvm_domain();
return 0;
}
-static void qemu_vmx_reset(void *unused)
+static void qemu_hvm_reset(void *unused)
{
char cmd[64];
@@ -489,7 +491,7 @@ CPUState * cpu_init()
int rc;
cpu_exec_init();
- qemu_register_reset(qemu_vmx_reset, NULL);
+ qemu_register_reset(qemu_hvm_reset, NULL);
env = malloc(sizeof(CPUX86State));
if (!env)
return NULL;
diff --git a/tools/ioemu/vl.c b/tools/ioemu/vl.c
index 736a762d19..aeed28e1e2 100644
--- a/tools/ioemu/vl.c
+++ b/tools/ioemu/vl.c
@@ -125,7 +125,7 @@ static char network_script[1024];
int pit_min_timer_count = 0;
int nb_nics;
char bridge[16];
-char domain_name[1024] = { 'V', 'T', 'X', 'E', 'N', '-'};
+char domain_name[1024] = { 'H','V', 'M', 'X', 'E', 'N', '-'};
NetDriverState nd_table[MAX_NICS];
QEMUTimer *gui_timer;
QEMUTimer *polling_timer;
@@ -826,8 +826,8 @@ static void init_timers(void)
{
/* get times() syscall frequency */
timer_freq = sysconf(_SC_CLK_TCK);
-
-#ifndef TARGET_VMX
+
+#ifndef TARGET_HVM
/* timer signal */
sigfillset(&act.sa_mask);
act.sa_flags = 0;
@@ -869,7 +869,7 @@ static void init_timers(void)
pit_min_timer_count = ((uint64_t)itv.it_interval.tv_usec *
PIT_FREQ) / 1000000;
}
-#endif /* TARGET_VMX */
+#endif /* TARGET_HVM */
}
#endif
}
diff --git a/tools/libxc/Makefile b/tools/libxc/Makefile
index 44fc9d8160..84d4829ecf 100644
--- a/tools/libxc/Makefile
+++ b/tools/libxc/Makefile
@@ -45,7 +45,7 @@ else
BUILD_SRCS += xc_load_aout9.c
BUILD_SRCS += xc_linux_restore.c
BUILD_SRCS += xc_linux_save.c
-BUILD_SRCS += xc_vmx_build.c
+BUILD_SRCS += xc_hvm_build.c
endif
CFLAGS += -Wall
diff --git a/tools/libxc/xc_vmx_build.c b/tools/libxc/xc_hvm_build.c
index 222ec17207..086adbb181 100644
--- a/tools/libxc/xc_vmx_build.c
+++ b/tools/libxc/xc_hvm_build.c
@@ -1,5 +1,5 @@
/******************************************************************************
- * xc_vmx_build.c
+ * xc_hvm_build.c
*/
#include <stddef.h>
@@ -12,7 +12,7 @@
#include <xen/hvm/hvm_info_table.h>
#include <xen/hvm/ioreq.h>
-#define VMX_LOADER_ENTR_ADDR 0x00100000
+#define HVM_LOADER_ENTR_ADDR 0x00100000
#define L1_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_USER)
#define L2_PROT (_PAGE_PRESENT|_PAGE_RW|_PAGE_ACCESSED|_PAGE_DIRTY|_PAGE_USER)
@@ -133,7 +133,7 @@ set_hvm_info_checksum(struct hvm_info_table *t)
/*
* Use E820 reserved memory 0x9F800 to pass HVM info to vmxloader
- * vmxloader will use this info to set BIOS accordingly
+ * hvmloader will use this info to set BIOS accordingly
*/
static int set_hvm_info(int xc_handle, uint32_t dom,
unsigned long *pfn_list, unsigned int vcpus,
@@ -142,6 +142,7 @@ static int set_hvm_info(int xc_handle, uint32_t dom,
char *va_map;
struct hvm_info_table *va_hvm;
+
va_map = xc_map_foreign_range(
xc_handle,
dom,
@@ -302,7 +303,7 @@ static int setup_guest(int xc_handle,
unsigned long shared_info_frame,
unsigned int control_evtchn,
unsigned int vcpus,
- unsigned int acpi,
+ unsigned int acpi,
unsigned int apic,
unsigned int store_evtchn,
unsigned long *store_mfn)
@@ -357,7 +358,7 @@ static int setup_guest(int xc_handle,
vpt_end = vpt_start + (nr_pt_pages * PAGE_SIZE);
printf("VIRTUAL MEMORY ARRANGEMENT:\n"
- " Loaded VMX loader: %08lx->%08lx\n"
+ " Loaded HVM loader: %08lx->%08lx\n"
" Page tables: %08lx->%08lx\n"
" TOTAL: %08lx->%08lx\n",
dsi.v_kernstart, dsi.v_kernend,
@@ -514,7 +515,7 @@ static int setup_guest(int xc_handle,
}
if ( set_hvm_info(xc_handle, dom, page_array, vcpus, acpi, apic) ) {
- fprintf(stderr, "Couldn't set hvm info for VMX guest.\n");
+ fprintf(stderr, "Couldn't set hvm info for HVM guest.\n");
goto error_out;
}
@@ -595,13 +596,13 @@ static int setup_guest(int xc_handle,
return -1;
}
-int xc_vmx_build(int xc_handle,
+int xc_hvm_build(int xc_handle,
uint32_t domid,
int memsize,
const char *image_name,
unsigned int control_evtchn,
unsigned int vcpus,
- unsigned int acpi,
+ unsigned int acpi,
unsigned int apic,
unsigned int store_evtchn,
unsigned long *store_mfn)
@@ -622,8 +623,8 @@ int xc_vmx_build(int xc_handle,
if ( !strstr(xen_caps, "hvm") )
{
- PERROR("CPU doesn't support VMX Extensions or "
- "CPU VMX Extensions are not turned on");
+ PERROR("CPU doesn't support HVM extensions or "
+ "the extensions are not enabled");
goto error_out;
}
@@ -653,6 +654,7 @@ int xc_vmx_build(int xc_handle,
memset(ctxt, 0, sizeof(*ctxt));
+ ctxt->flags = VGCF_HVM_GUEST;
if ( setup_guest(xc_handle, domid, memsize, image, image_size, nr_pages,
ctxt, op.u.getdomaininfo.shared_info_frame, control_evtchn,
vcpus, acpi, apic, store_evtchn, store_mfn) < 0)
@@ -663,7 +665,6 @@ int xc_vmx_build(int xc_handle,
free(image);
- ctxt->flags = VGCF_VMX_GUEST;
/* FPU is set up to default initial state. */
memset(&ctxt->fpu_ctxt, 0, sizeof(ctxt->fpu_ctxt));
@@ -779,7 +780,7 @@ static int parseelfimage(char *elfbase,
dsi->v_kernstart = kernstart;
dsi->v_kernend = kernend;
- dsi->v_kernentry = VMX_LOADER_ENTR_ADDR;
+ dsi->v_kernentry = HVM_LOADER_ENTR_ADDR;
dsi->v_end = dsi->v_kernend;
diff --git a/tools/libxc/xc_ia64_stubs.c b/tools/libxc/xc_ia64_stubs.c
index e742df3ba0..2a403cd3b6 100644
--- a/tools/libxc/xc_ia64_stubs.c
+++ b/tools/libxc/xc_ia64_stubs.c
@@ -621,7 +621,7 @@ static int setup_guest( int xc_handle,
return -1;
}
-int xc_vmx_build(int xc_handle,
+int xc_hvm_build(int xc_handle,
uint32_t domid,
int memsize,
const char *image_name,
diff --git a/tools/libxc/xc_linux_build.c b/tools/libxc/xc_linux_build.c
index eae62d20ce..f90f509f2c 100644
--- a/tools/libxc/xc_linux_build.c
+++ b/tools/libxc/xc_linux_build.c
@@ -815,7 +815,7 @@ static int setup_guest(int xc_handle,
start_info->mod_len = initrd_len;
}
if ( cmdline != NULL )
- {
+ {
strncpy((char *)start_info->cmd_line, cmdline, MAX_GUEST_CMDLINE);
start_info->cmd_line[MAX_GUEST_CMDLINE-1] = '\0';
}
diff --git a/tools/libxc/xc_ptrace.c b/tools/libxc/xc_ptrace.c
index ac30269cfb..5cea66db82 100644
--- a/tools/libxc/xc_ptrace.c
+++ b/tools/libxc/xc_ptrace.c
@@ -240,7 +240,7 @@ map_domain_va(
}
if ( (pde = cr3_virt[cpu][vtopdi(va)]) == 0 )
goto error_out;
- if ( (ctxt[cpu].flags & VGCF_VMX_GUEST) && paging_enabled(&ctxt[cpu]) )
+ if ( (ctxt[cpu].flags & VGCF_HVM_GUEST) && paging_enabled(&ctxt[cpu]) )
pde = page_array[pde >> PAGE_SHIFT] << PAGE_SHIFT;
if ( pde != pde_phys[cpu] )
{
@@ -255,7 +255,7 @@ map_domain_va(
}
if ( (page = pde_virt[cpu][vtopti(va)]) == 0 )
goto error_out;
- if ( (ctxt[cpu].flags & VGCF_VMX_GUEST) && paging_enabled(&ctxt[cpu]) )
+ if ( (ctxt[cpu].flags & VGCF_HVM_GUEST) && paging_enabled(&ctxt[cpu]) )
page = page_array[page >> PAGE_SHIFT] << PAGE_SHIFT;
if ( (page != page_phys[cpu]) || (perm != prev_perm[cpu]) )
{
diff --git a/tools/libxc/xc_ptrace_core.c b/tools/libxc/xc_ptrace_core.c
index 43463b65a3..3c55b0474b 100644
--- a/tools/libxc/xc_ptrace_core.c
+++ b/tools/libxc/xc_ptrace_core.c
@@ -126,7 +126,7 @@ map_domain_va(unsigned long domfd, int cpu, void * guest_va)
}
if ((pde = cr3_virt[cpu][vtopdi(va)]) == 0) /* logical address */
goto error_out;
- if (ctxt[cpu].flags & VGCF_VMX_GUEST)
+ if (ctxt[cpu].flags & VGCF_HVM_GUEST)
pde = p2m_array[pde >> PAGE_SHIFT] << PAGE_SHIFT;
if (pde != pde_phys[cpu])
{
@@ -142,7 +142,7 @@ map_domain_va(unsigned long domfd, int cpu, void * guest_va)
}
if ((page = pde_virt[cpu][vtopti(va)]) == 0) /* logical address */
goto error_out;
- if (ctxt[cpu].flags & VGCF_VMX_GUEST)
+ if (ctxt[cpu].flags & VGCF_HVM_GUEST)
page = p2m_array[page >> PAGE_SHIFT] << PAGE_SHIFT;
if (page != page_phys[cpu])
{
diff --git a/tools/libxc/xenguest.h b/tools/libxc/xenguest.h
index 5cad964f80..4a11b5ec1b 100644
--- a/tools/libxc/xenguest.h
+++ b/tools/libxc/xenguest.h
@@ -53,7 +53,7 @@ int xc_linux_build(int xc_handle,
unsigned int console_evtchn,
unsigned long *console_mfn);
-int xc_vmx_build(int xc_handle,
+int xc_hvm_build(int xc_handle,
uint32_t domid,
int memsize,
const char *image_name,
diff --git a/tools/python/xen/lowlevel/xc/xc.c b/tools/python/xen/lowlevel/xc/xc.c
index f935044b26..d7cc20a274 100644
--- a/tools/python/xen/lowlevel/xc/xc.c
+++ b/tools/python/xen/lowlevel/xc/xc.c
@@ -355,7 +355,7 @@ static PyObject *pyxc_linux_build(XcObject *self,
"console_mfn", console_mfn);
}
-static PyObject *pyxc_vmx_build(XcObject *self,
+static PyObject *pyxc_hvm_build(XcObject *self,
PyObject *args,
PyObject *kwds)
{
@@ -369,16 +369,15 @@ static PyObject *pyxc_vmx_build(XcObject *self,
unsigned long store_mfn = 0;
static char *kwd_list[] = { "dom", "control_evtchn", "store_evtchn",
- "memsize", "image", "vcpus", "acpi", "apic",
- NULL };
-
+ "memsize", "image", "vcpus", "acpi", "apic",
+ NULL };
if ( !PyArg_ParseTupleAndKeywords(args, kwds, "iiiisiii", kwd_list,
&dom, &control_evtchn, &store_evtchn,
- &memsize, &image, &vcpus, &acpi, &apic) )
+ &memsize, &image, &vcpus, &acpi, &apic) )
return NULL;
- if ( xc_vmx_build(self->xc_handle, dom, memsize, image, control_evtchn,
- vcpus, acpi, apic, store_evtchn, &store_mfn) != 0 )
+ if ( xc_hvm_build(self->xc_handle, dom, memsize, image, control_evtchn,
+ vcpus, acpi, apic, store_evtchn, &store_mfn) != 0 )
return PyErr_SetFromErrno(xc_error);
return Py_BuildValue("{s:i}", "store_mfn", store_mfn);
@@ -965,12 +964,12 @@ static PyMethodDef pyxc_methods[] = {
" vcpus [int, 1]: Number of Virtual CPUS in domain.\n\n"
"Returns: [int] 0 on success; -1 on error.\n" },
- { "vmx_build",
- (PyCFunction)pyxc_vmx_build,
+ { "hvm_build",
+ (PyCFunction)pyxc_hvm_build,
METH_VARARGS | METH_KEYWORDS, "\n"
- "Build a new VMX guest OS.\n"
+ "Build a new HVM guest OS.\n"
" dom [int]: Identifier of domain to build into.\n"
- " image [str]: Name of VMX loader image file.\n"
+ " image [str]: Name of HVM loader image file.\n"
" vcpus [int, 1]: Number of Virtual CPUS in domain.\n\n"
"Returns: [int] 0 on success; -1 on error.\n" },
diff --git a/tools/python/xen/xend/image.py b/tools/python/xen/xend/image.py
index 338a1006eb..8a73ed90b6 100644
--- a/tools/python/xen/xend/image.py
+++ b/tools/python/xen/xend/image.py
@@ -143,7 +143,7 @@ class ImageHandler:
def getDomainMemory(self, mem):
"""@return The memory required, in KiB, by the domain to store the
- given amount, also in KiB. This is normally just mem, but VMX domains
+ given amount, also in KiB. This is normally just mem, but HVM domains
have overheads to account for."""
return mem
@@ -183,21 +183,21 @@ class LinuxImageHandler(ImageHandler):
cmdline = self.cmdline,
ramdisk = self.ramdisk)
-class VmxImageHandler(ImageHandler):
+class HVMImageHandler(ImageHandler):
- ostype = "vmx"
+ ostype = "hvm"
def configure(self, imageConfig, deviceConfig):
ImageHandler.configure(self, imageConfig, deviceConfig)
info = xc.xeninfo()
- if not 'hvm' in info['xen_caps']:
- raise VmError("vmx: not an Intel VT platform, we stop creating!")
+ if not 'hvm' in info['xen_caps']:
+ raise VmError("Not an HVM capable platform, we stop creating!")
self.dmargs = self.parseDeviceModelArgs(imageConfig, deviceConfig)
self.device_model = sxp.child_value(imageConfig, 'device_model')
if not self.device_model:
- raise VmError("vmx: missing device model")
+ raise VmError("hvm: missing device model")
self.display = sxp.child_value(imageConfig, 'display')
self.xauthority = sxp.child_value(imageConfig, 'xauthority')
@@ -217,7 +217,7 @@ class VmxImageHandler(ImageHandler):
# Create an event channel
self.device_channel = xc.evtchn_alloc_unbound(dom=self.vm.getDomid(),
remote_dom=0)
- log.info("VMX device model port: %d", self.device_channel)
+ log.info("HVM device model port: %d", self.device_channel)
store_evtchn = self.vm.getStorePort()
@@ -232,7 +232,7 @@ class VmxImageHandler(ImageHandler):
self.register_shutdown_watch()
- return xc.vmx_build(dom = self.vm.getDomid(),
+ return xc.hvm_build(dom = self.vm.getDomid(),
image = self.kernel,
control_evtchn = self.device_channel,
store_evtchn = store_evtchn,
@@ -283,7 +283,7 @@ class VmxImageHandler(ImageHandler):
continue;
vbddev_list = ['hda', 'hdb', 'hdc', 'hdd']
if vbddev not in vbddev_list:
- raise VmError("vmx: for qemu vbd type=file&dev=hda~hdd")
+ raise VmError("hvm: for qemu vbd type=file&dev=hda~hdd")
ret.append("-%s" % vbddev)
ret.append("%s" % vbdparam)
if name == 'vif':
@@ -405,8 +405,8 @@ class VmxImageHandler(ImageHandler):
def register_shutdown_watch(self):
""" add xen store watch on control/shutdown """
self.shutdownWatch = xswatch(self.vm.dompath + "/control/shutdown", \
- self.vmx_shutdown)
- log.debug("vmx shutdown watch registered")
+ self.hvm_shutdown)
+ log.debug("hvm shutdown watch registered")
def unregister_shutdown_watch(self):
"""Remove the watch on the control/shutdown, if any. Nothrow
@@ -416,11 +416,11 @@ class VmxImageHandler(ImageHandler):
if self.shutdownWatch:
self.shutdownWatch.unwatch()
except:
- log.exception("Unwatching vmx shutdown watch failed.")
+ log.exception("Unwatching hvm shutdown watch failed.")
self.shutdownWatch = None
- log.debug("vmx shutdown watch unregistered")
+ log.debug("hvm shutdown watch unregistered")
- def vmx_shutdown(self, _):
+ def hvm_shutdown(self, _):
""" watch call back on node control/shutdown,
if node changed, this function will be called
"""
@@ -429,7 +429,7 @@ class VmxImageHandler(ImageHandler):
vm = xd.domain_lookup( self.vm.getDomid() )
reason = vm.readDom('control/shutdown')
- log.debug("vmx_shutdown fired, shutdown reason=%s", reason)
+ log.debug("hvm_shutdown fired, shutdown reason=%s", reason)
for x in shutdown_reasons.keys():
if shutdown_reasons[x] == reason:
vm.info['shutdown'] = 1
@@ -444,7 +444,7 @@ image type.
imageHandlerClasses = {}
-for h in LinuxImageHandler, VmxImageHandler:
+for h in LinuxImageHandler, HVMImageHandler:
imageHandlerClasses[h.ostype] = h
diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py
index a6408f82ba..4aeaf34945 100644
--- a/tools/python/xen/xm/create.py
+++ b/tools/python/xen/xm/create.py
@@ -162,11 +162,11 @@ gopts.var('cpus', val='CPUS',
gopts.var('acpi', val='ACPI',
fn=set_int, default=0,
- use="Disable or enable ACPI of VMX domain.")
+ use="Disable or enable ACPI of HVM domain.")
gopts.var('apic', val='APIC',
fn=set_int, default=0,
- use="Disable or enable APIC of VMX domain.")
+ use="Disable or enable APIC of HVM domain.")
gopts.var('vcpus', val='VCPUS',
fn=set_int, default=1,
@@ -441,8 +441,8 @@ def configure_image(vals):
if vals.extra:
config_image.append(['args', vals.extra])
- if vals.builder == 'vmx':
- configure_vmx(config_image, vals)
+ if vals.builder == 'hvm':
+ configure_hvm(config_image, vals)
return config_image
@@ -536,8 +536,8 @@ def configure_vifs(config_devs, vals):
config_devs.append(['device', config_vif])
-def configure_vmx(config_image, vals):
- """Create the config for VMX devices.
+def configure_hvm(config_image, vals):
+ """Create the config for HVM devices.
"""
args = [ 'device_model', 'vcpus', 'cdrom', 'boot', 'fda', 'fdb',
'localtime', 'serial', 'stdvga', 'isa', 'nographic', 'audio',
diff --git a/tools/python/xen/xm/tests/test_create.py b/tools/python/xen/xm/tests/test_create.py
index f04496288d..4cce721ea0 100644
--- a/tools/python/xen/xm/tests/test_create.py
+++ b/tools/python/xen/xm/tests/test_create.py
@@ -141,15 +141,15 @@ cpu_weight = 0.75
})
- def testVMXConfigFile(self):
+ def testHVMConfigFile(self):
(fd, fname) = tempfile.mkstemp()
try:
os.write(fd,
'''
-kernel = "/usr/lib/xen/boot/vmxloader"
-builder='vmx'
+kernel = "/usr/lib/xen/boot/hvmloader"
+builder='hvm'
memory = 128
-name = "ExampleVMXDomain"
+name = "ExampleHVMDomain"
vcpus=1
vif = [ 'type=ioemu, bridge=xenbr0' ]
disk = [ 'file:/var/images/min-el3-i386.img,ioemu:hda,w' ]
@@ -163,10 +163,10 @@ ne2000=0
os.close(fd)
self.t('-f %s display=fakedisplay' % fname,
- { 'kernel' : '/usr/lib/xen/boot/vmxloader',
- 'builder' : 'vmx',
+ { 'kernel' : '/usr/lib/xen/boot/hvmloader',
+ 'builder' : 'hvm',
'memory' : 128,
- 'name' : 'ExampleVMXDomain',
+ 'name' : 'ExampleHVMDomain',
'vcpus' : 1,
'nics' : -1,
'vif' : ['type=ioemu, bridge=xenbr0'],
diff --git a/tools/xm-test/README b/tools/xm-test/README
index 481baca211..f65e9a26b5 100644
--- a/tools/xm-test/README
+++ b/tools/xm-test/README
@@ -60,26 +60,26 @@ BUILDING with HVM Support
=========================
If you'd like to build and run this with hardware virtual machine assist
-(HVM) support to test fully virtualized disk images on VMX hardware,
-please add the --enable-vmx-support option to configure:
+(HVM) support to test fully virtualized disk images on VMX/SVM hardware,
+please add the --enable-hvm-support option to configure:
# ./autogen
- # ./configure --enable-vmx-support
+ # ./configure --enable-hvm-support
# make
The ramdisk/bin/create_disk_image script, which builds the full virt
disk.img, requires Lilo 22.7+ to be installed on the system. Lilo is
used to install the bootloader on the disk.img.
-If HVM / VMX support is enabled, the ramdisk/bin/create_disk_image script
+If HVM support is enabled, the ramdisk/bin/create_disk_image script
will be run to create a full virt disk.img in the ramdisk directory. The
script, by default, will look in /boot for the first non-Xen kernel it
runs across. If you'd like to set xm-test to use a specific kernel,
rather than the first one it finds in /boot, you can configure it in
-with the "--with-vmx-kernel=KERNEL" option:
-
+with the "--with-hvm-kernel=KERNEL" option:
+
# ./autogen
-# ./configure --enable-vmx-support --with-vmx-kernel=KERNEL
+# ./configure --enable-hvm-support --with-hvm-kernel=KERNEL
# make
Otherwise, you can always rerun the create script using the -k option
@@ -92,14 +92,14 @@ used. If you'd like to specify a different location for the driver or
want to tell the script that the driver is built into the kernel, please
use the "--with-driver-dir=DRVDIR" configure option. If built into
the kernel, please use the key word "builtin" with the option:
-
+
# ./autogen
-# ./configure --enable-vmx-support --with-driver-dir=builtin
+# ./configure --enable-hvm-support --with-driver-dir=builtin
- or -
-# ./configure --enable-vmx-support --with-driver-dir=/driver/directory
+# ./configure --enable-hvm-support --with-driver-dir=/driver/directory
# make
-
-Xm-test will look for disk.img in the ramdisk directory when run by
+
+Xm-test will look for disk.img in the ramdisk directory when run by
default.
diff --git a/tools/xm-test/configure.ac b/tools/xm-test/configure.ac
index 8f844c1148..22b2addc8f 100644
--- a/tools/xm-test/configure.ac
+++ b/tools/xm-test/configure.ac
@@ -15,18 +15,18 @@ TESTLIB=../../lib
RD_PATH=../../ramdisk
TENV="PYTHONPATH=$PYTHONPATH:$TESTLIB:/usr/lib/python RD_PATH=$RD_PATH"
-AC_ARG_ENABLE(vmx-support,
- [[ --enable-vmx-support enable hardware virtual machine assist]],
+AC_ARG_ENABLE(hvm-support,
+ [[ --enable-hvm-support enable hardware virtual machine assist]],
[
- ENABLE_VMX=True
+ ENABLE_HVM=True
],[
- ENABLE_VMX=False
+ ENABLE_HVM=False
])
-if test "x$ENABLE_VMX" = "xTrue"; then
+if test "x$ENABLE_HVM" = "xTrue"; then
if test "$LILO" = "no"; then
AC_MSG_ERROR([lilo not found
-lilo version 22.7 or greater must be installed for testing with vmx enabled.])
+lilo version 22.7 or greater must be installed for testing with hvm enabled.])
else
pass=`$LILO -V | sed -e "s/LILO version //" | awk -F "." '{if ($1 >=22 && $2 >= 7) print "true"; else print "false"}'`
if test "$pass" != "true"; then
@@ -35,16 +35,16 @@ lilo version 22.7 or greater must be installed for testing with vmx enabled.])
fi
fi
-AM_CONDITIONAL(VMX, test x$ENABLE_VMX = xTrue)
-AC_SUBST(ENABLE_VMX)
+AM_CONDITIONAL(HVM, test x$ENABLE_HVM = xTrue)
+AC_SUBST(ENABLE_HVM)
-AC_ARG_WITH(vmx-kernel,
- [[ --with-vmx-kernel=kernel Use this kernel for vmx disk.img testing]],
- VMXKERNEL=$withval,
- VMXKERNEL="no")
+AC_ARG_WITH(hvm-kernel,
+ [[ --with-hvm-kernel=kernel Use this kernel for hvm disk.img testing]],
+ HVMKERNEL=$withval,
+ HVMKERNEL="no")
-dnl substitute @VMXKERNEL@ in all Makefiles
-AC_SUBST(VMXKERNEL)
+dnl substitute @HVMKERNEL@ in all Makefiles
+AC_SUBST(HVMKERNEL)
AC_ARG_WITH(driver-dir,
[[ --with-driver-dir=drvdir Look in this directory for the pcnet32 driver for the vmx disk.img. drvdir can equal key word "builtin" if driver is built into the kernel]],
diff --git a/tools/xm-test/lib/XmTestLib/XenDomain.py b/tools/xm-test/lib/XmTestLib/XenDomain.py
index 49e111e68b..80825064a8 100644
--- a/tools/xm-test/lib/XmTestLib/XenDomain.py
+++ b/tools/xm-test/lib/XmTestLib/XenDomain.py
@@ -70,14 +70,14 @@ ParavirtDefaults = {"memory" : 64,
"root" : "/dev/ram0",
"ramdisk" : getRdPath() + "/initrd.img"
}
-VmxDefaults = {"memory" : 64,
+HVMDefaults = {"memory" : 64,
"vcpus" : 1,
"acpi" : 0,
"apic" : 0,
"disk" : ["file:%s/disk.img,ioemu:%s,w" %
(getRdPath(), BLOCK_ROOT_DEV)],
- "kernel" : "/usr/lib/xen/boot/vmxloader",
- "builder" : "vmx",
+ "kernel" : "/usr/lib/xen/boot/hvmloader",
+ "builder" : "hvm",
"sdl" : 0,
"vnc" : 0,
"vncviewer" : 0,
@@ -86,8 +86,8 @@ VmxDefaults = {"memory" : 64,
"device_model" : getDeviceModel()
}
-if ENABLE_VMX_SUPPORT:
- configDefaults = VmxDefaults
+if ENABLE_HVM_SUPPORT:
+ configDefaults = HVMDefaults
else:
configDefaults = ParavirtDefaults
@@ -247,7 +247,7 @@ class XmTestDomain(XenDomain):
def start(self):
XenDomain.start(self)
- if ENABLE_VMX_SUPPORT:
+ if ENABLE_HVM_SUPPORT:
waitForBoot()
def startNow(self):
@@ -271,7 +271,7 @@ if __name__ == "__main__":
print str(c)
-
+
# c.write("/tmp/foo.conf")
diff --git a/tools/xm-test/lib/XmTestLib/config.py.in b/tools/xm-test/lib/XmTestLib/config.py.in
index 86e7cf7a2c..dafbc1f909 100644
--- a/tools/xm-test/lib/XmTestLib/config.py.in
+++ b/tools/xm-test/lib/XmTestLib/config.py.in
@@ -1,4 +1,4 @@
#!/usr/bin/python
-ENABLE_VMX_SUPPORT = @ENABLE_VMX@
+ENABLE_HVM_SUPPORT = @ENABLE_HVM@
diff --git a/tools/xm-test/ramdisk/Makefile.am b/tools/xm-test/ramdisk/Makefile.am
index 21133f5c4e..ad71da4b14 100644
--- a/tools/xm-test/ramdisk/Makefile.am
+++ b/tools/xm-test/ramdisk/Makefile.am
@@ -9,12 +9,12 @@ BR_IMG = $(BR_SRC)/rootfs.i386.ext2
BR_ROOT = build_i386/root
-VMX_SCRIPT = bin/create_disk_image
+HVM_SCRIPT = bin/create_disk_image
XMTEST_MAJ_VER = $(shell echo @PACKAGE_VERSION@ | perl -pe 's/(\d+)\.(\d+)\.\d+/\1.\2/')
XMTEST_VER_IMG = initrd-$(XMTEST_MAJ_VER).img
-if VMX
+if HVM
all: initrd.img disk.img
else
all: initrd.img
@@ -44,16 +44,16 @@ initrd.img: $(XMTEST_VER_IMG)
ln -sf $(XMTEST_VER_IMG) initrd.img
disk.img: $(XMTEST_VER_IMG)
- chmod a+x $(VMX_SCRIPT)
- @if test ! "$(VMXKERNEL)" = "no" -a ! "$(DRVDIR)" = "no"; then \
- $(VMX_SCRIPT) -r $(XMTEST_VER_IMG) -k $(VMXKERNEL) \
+ chmod a+x $(HVM_SCRIPT)
+ @if test ! "$(HVMKERNEL)" = "no" -a ! "$(DRVDIR)" = "no"; then \
+ $(HVM_SCRIPT) -r $(XMTEST_VER_IMG) -k $(HVMKERNEL) \
-d $(DRVDIR); \
- elif test "$(VMXKERNEL)" = "no" -a ! "$(DRVDIR)" = "no"; then \
- $(VMX_SCRIPT) -r $(XMTEST_VER_IMG) -d $(DRVDIR); \
- elif test ! "$(VMXKERNEL)" = "no" -a "$(DRVDIR)" = "no"; then \
- $(VMX_SCRIPT) -r $(XMTEST_VER_IMG) -k $(VMXKERNEL); \
+ elif test "$(HVMKERNEL)" = "no" -a ! "$(DRVDIR)" = "no"; then \
+ $(HVM_SCRIPT) -r $(XMTEST_VER_IMG) -d $(DRVDIR); \
+ elif test ! "$(HVMKERNEL)" = "no" -a "$(DRVDIR)" = "no"; then \
+ $(HVM_SCRIPT) -r $(XMTEST_VER_IMG) -k $(HVMKERNEL); \
else \
- $(VMX_SCRIPT) -r $(XMTEST_VER_IMG); \
+ $(HVM_SCRIPT) -r $(XMTEST_VER_IMG); \
fi
existing:
diff --git a/tools/xm-test/ramdisk/bin/create_disk_image b/tools/xm-test/ramdisk/bin/create_disk_image
index 836e8a5c14..bde4b2dede 100644
--- a/tools/xm-test/ramdisk/bin/create_disk_image
+++ b/tools/xm-test/ramdisk/bin/create_disk_image
@@ -46,7 +46,7 @@ function die()
function usage()
{
cat << EOU
-Command creates a vmx guest disk image for xm-test.
+Command creates a hvm guest disk image for xm-test.
Usage: $0 [OPTIONS]
diff --git a/tools/xm-test/tests/block-create/01_block_attach_device_pos.py b/tools/xm-test/tests/block-create/01_block_attach_device_pos.py
index 5c2febdad4..564ffad0bf 100644
--- a/tools/xm-test/tests/block-create/01_block_attach_device_pos.py
+++ b/tools/xm-test/tests/block-create/01_block_attach_device_pos.py
@@ -9,8 +9,8 @@ import time
from XmTestLib import *
-if ENABLE_VMX_SUPPORT:
- SKIP("Block-attach not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Block-attach not supported for HVM domains")
# Create a domain (default XmTestDomain, with our ramdisk)
domain = XmTestDomain()
diff --git a/tools/xm-test/tests/block-create/02_block_attach_file_device_pos.py b/tools/xm-test/tests/block-create/02_block_attach_file_device_pos.py
index 36d64cc56e..0cfb6de109 100644
--- a/tools/xm-test/tests/block-create/02_block_attach_file_device_pos.py
+++ b/tools/xm-test/tests/block-create/02_block_attach_file_device_pos.py
@@ -9,8 +9,8 @@ import time
from XmTestLib import *
-if ENABLE_VMX_SUPPORT:
- SKIP("Block-attach not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Block-attach not supported for HVM domains")
# Create a domain (default XmTestDomain, with our ramdisk)
domain = XmTestDomain()
diff --git a/tools/xm-test/tests/block-create/04_block_attach_device_repeatedly_pos.py b/tools/xm-test/tests/block-create/04_block_attach_device_repeatedly_pos.py
index d392c60427..8a5680f10b 100644
--- a/tools/xm-test/tests/block-create/04_block_attach_device_repeatedly_pos.py
+++ b/tools/xm-test/tests/block-create/04_block_attach_device_repeatedly_pos.py
@@ -9,8 +9,8 @@ import time
from XmTestLib import *
-if ENABLE_VMX_SUPPORT:
- SKIP("Block-attach not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Block-attach not supported for HVM domains")
# Create a domain (default XmTestDomain, with our ramdisk)
domain = XmTestDomain()
diff --git a/tools/xm-test/tests/block-create/05_block_attach_and_dettach_device_repeatedly_pos.py b/tools/xm-test/tests/block-create/05_block_attach_and_dettach_device_repeatedly_pos.py
index 06cc116974..1434ad2176 100644
--- a/tools/xm-test/tests/block-create/05_block_attach_and_dettach_device_repeatedly_pos.py
+++ b/tools/xm-test/tests/block-create/05_block_attach_and_dettach_device_repeatedly_pos.py
@@ -9,8 +9,8 @@ import time
from XmTestLib import *
-if ENABLE_VMX_SUPPORT:
- SKIP("Block-attach not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Block-attach not supported for HVM domains")
# Create a domain (default XmTestDomain, with our ramdisk)
domain = XmTestDomain()
diff --git a/tools/xm-test/tests/block-create/06_block_attach_baddomain_neg.py b/tools/xm-test/tests/block-create/06_block_attach_baddomain_neg.py
index bd28bc18be..edfeba1643 100644
--- a/tools/xm-test/tests/block-create/06_block_attach_baddomain_neg.py
+++ b/tools/xm-test/tests/block-create/06_block_attach_baddomain_neg.py
@@ -5,8 +5,8 @@
from XmTestLib import *
-if ENABLE_VMX_SUPPORT:
- SKIP("Block-attach not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Block-attach not supported for HVM domains")
status, output = traceCommand("xm block-attach NOT-EXIST phy:ram1 sdb1 w")
diff --git a/tools/xm-test/tests/block-create/07_block_attach_baddevice_neg.py b/tools/xm-test/tests/block-create/07_block_attach_baddevice_neg.py
index 8c08658068..ac179d50a3 100644
--- a/tools/xm-test/tests/block-create/07_block_attach_baddevice_neg.py
+++ b/tools/xm-test/tests/block-create/07_block_attach_baddevice_neg.py
@@ -9,8 +9,8 @@ import time
from XmTestLib import *
-if ENABLE_VMX_SUPPORT:
- SKIP("Block-attach not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Block-attach not supported for HVM domains")
# Create a domain (default XmTestDomain, with our ramdisk)
domain = XmTestDomain()
diff --git a/tools/xm-test/tests/block-create/08_block_attach_bad_filedevice_neg.py b/tools/xm-test/tests/block-create/08_block_attach_bad_filedevice_neg.py
index e34f5c8ebd..2a908c3295 100644
--- a/tools/xm-test/tests/block-create/08_block_attach_bad_filedevice_neg.py
+++ b/tools/xm-test/tests/block-create/08_block_attach_bad_filedevice_neg.py
@@ -9,8 +9,8 @@ import time
from XmTestLib import *
-if ENABLE_VMX_SUPPORT:
- SKIP("Block-attach not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Block-attach not supported for HVM domains")
# Create a domain (default XmTestDomain, with our ramdisk)
domain = XmTestDomain()
diff --git a/tools/xm-test/tests/block-create/09_block_attach_and_dettach_device_check_data_pos.py b/tools/xm-test/tests/block-create/09_block_attach_and_dettach_device_check_data_pos.py
index 60b12da70e..4bcfd863f3 100644
--- a/tools/xm-test/tests/block-create/09_block_attach_and_dettach_device_check_data_pos.py
+++ b/tools/xm-test/tests/block-create/09_block_attach_and_dettach_device_check_data_pos.py
@@ -9,8 +9,8 @@ import time
from XmTestLib import *
-if ENABLE_VMX_SUPPORT:
- SKIP("Block-attach not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Block-attach not supported for HVM domains")
# Create a domain (default XmTestDomain, with our ramdisk)
domain = XmTestDomain()
diff --git a/tools/xm-test/tests/block-create/10_block_attach_dettach_multiple_devices.py b/tools/xm-test/tests/block-create/10_block_attach_dettach_multiple_devices.py
index 42fe9e5ebe..4c3b4d1851 100644
--- a/tools/xm-test/tests/block-create/10_block_attach_dettach_multiple_devices.py
+++ b/tools/xm-test/tests/block-create/10_block_attach_dettach_multiple_devices.py
@@ -46,8 +46,8 @@ def dettach(devname):
return 0, None
-if ENABLE_VMX_SUPPORT:
- SKIP("Block-attach not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Block-attach not supported for HVM domains")
# Create a domain (default XmTestDomain, with our ramdisk)
domain = XmTestDomain()
diff --git a/tools/xm-test/tests/block-create/11_block_attach_shared_dom0.py b/tools/xm-test/tests/block-create/11_block_attach_shared_dom0.py
index f2e5ca7d64..43f55e234c 100644
--- a/tools/xm-test/tests/block-create/11_block_attach_shared_dom0.py
+++ b/tools/xm-test/tests/block-create/11_block_attach_shared_dom0.py
@@ -5,8 +5,8 @@
from XmTestLib import *
-if ENABLE_VMX_SUPPORT:
- SKIP("Block-attach not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Block-attach not supported for HVM domains")
# Mount /dev/ram0
diff --git a/tools/xm-test/tests/block-create/12_block_attach_shared_domU.py b/tools/xm-test/tests/block-create/12_block_attach_shared_domU.py
index 07cf56c373..362e5039e8 100644
--- a/tools/xm-test/tests/block-create/12_block_attach_shared_domU.py
+++ b/tools/xm-test/tests/block-create/12_block_attach_shared_domU.py
@@ -5,8 +5,8 @@
from XmTestLib import *
-if ENABLE_VMX_SUPPORT:
- SKIP("Block-attach not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Block-attach not supported for HVM domains")
config = {"disk":"phy:/dev/ram0,hda1,w"}
diff --git a/tools/xm-test/tests/block-destroy/01_block-destroy_btblock_pos.py b/tools/xm-test/tests/block-destroy/01_block-destroy_btblock_pos.py
index 8f7086388c..e3f76c1985 100644
--- a/tools/xm-test/tests/block-destroy/01_block-destroy_btblock_pos.py
+++ b/tools/xm-test/tests/block-destroy/01_block-destroy_btblock_pos.py
@@ -5,8 +5,8 @@
from XmTestLib import *
-if ENABLE_VMX_SUPPORT:
- SKIP("Block-detach not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Block-detach not supported for HVM domains")
config = {"disk":"phy:/dev/ram0,hda1,w"}
domain = XmTestDomain(extraConfig=config)
diff --git a/tools/xm-test/tests/block-destroy/02_block-destroy_rtblock_pos.py b/tools/xm-test/tests/block-destroy/02_block-destroy_rtblock_pos.py
index 6c87db8198..db918b7634 100644
--- a/tools/xm-test/tests/block-destroy/02_block-destroy_rtblock_pos.py
+++ b/tools/xm-test/tests/block-destroy/02_block-destroy_rtblock_pos.py
@@ -5,8 +5,8 @@
from XmTestLib import *
-if ENABLE_VMX_SUPPORT:
- SKIP("Block-detach not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Block-detach not supported for HVM domains")
domain = XmTestDomain()
diff --git a/tools/xm-test/tests/block-destroy/04_block-destroy_nonattached_neg.py b/tools/xm-test/tests/block-destroy/04_block-destroy_nonattached_neg.py
index 4f1e485800..6fea02864f 100644
--- a/tools/xm-test/tests/block-destroy/04_block-destroy_nonattached_neg.py
+++ b/tools/xm-test/tests/block-destroy/04_block-destroy_nonattached_neg.py
@@ -7,8 +7,8 @@
from XmTestLib import *
-if ENABLE_VMX_SUPPORT:
- SKIP("Block-detach not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Block-detach not supported for HVM domains")
domain = XmTestDomain()
diff --git a/tools/xm-test/tests/block-destroy/05_block-destroy_byname_pos.py b/tools/xm-test/tests/block-destroy/05_block-destroy_byname_pos.py
index 2a0993f2a5..5e2587e35f 100644
--- a/tools/xm-test/tests/block-destroy/05_block-destroy_byname_pos.py
+++ b/tools/xm-test/tests/block-destroy/05_block-destroy_byname_pos.py
@@ -5,8 +5,8 @@
from XmTestLib import *
-if ENABLE_VMX_SUPPORT:
- SKIP("Block-detach not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Block-detach not supported for HVM domains")
config = {"disk":"phy:/dev/ram0,hda1,w"}
domain = XmTestDomain(extraConfig=config)
diff --git a/tools/xm-test/tests/block-destroy/06_block-destroy_check_list_pos.py b/tools/xm-test/tests/block-destroy/06_block-destroy_check_list_pos.py
index 7f1c7cd453..01e81122b2 100644
--- a/tools/xm-test/tests/block-destroy/06_block-destroy_check_list_pos.py
+++ b/tools/xm-test/tests/block-destroy/06_block-destroy_check_list_pos.py
@@ -26,8 +26,8 @@ def checkXmLongList(domain):
else:
return False
-if ENABLE_VMX_SUPPORT:
- SKIP("Block-detach not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Block-detach not supported for HVM domains")
domain = XmTestDomain()
diff --git a/tools/xm-test/tests/block-list/01_block-list_pos.py b/tools/xm-test/tests/block-list/01_block-list_pos.py
index 185eb66dc2..d176be82f7 100644
--- a/tools/xm-test/tests/block-list/01_block-list_pos.py
+++ b/tools/xm-test/tests/block-list/01_block-list_pos.py
@@ -8,8 +8,8 @@
from XmTestLib import *
-if ENABLE_VMX_SUPPORT:
- SKIP("Block-list not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Block-list not supported for HVM domains")
config = {"disk":"phy:/dev/ram0,hda1,w"}
domain = XmTestDomain(extraConfig=config)
diff --git a/tools/xm-test/tests/block-list/02_block-list_attachbd_pos.py b/tools/xm-test/tests/block-list/02_block-list_attachbd_pos.py
index 27e56e5083..8a8459938e 100644
--- a/tools/xm-test/tests/block-list/02_block-list_attachbd_pos.py
+++ b/tools/xm-test/tests/block-list/02_block-list_attachbd_pos.py
@@ -8,8 +8,8 @@
from XmTestLib import *
-if ENABLE_VMX_SUPPORT:
- SKIP("Block-list not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Block-list not supported for HVM domains")
domain = XmTestDomain()
diff --git a/tools/xm-test/tests/block-list/03_block-list_anotherbd_pos.py b/tools/xm-test/tests/block-list/03_block-list_anotherbd_pos.py
index f873d87025..26e42097a4 100644
--- a/tools/xm-test/tests/block-list/03_block-list_anotherbd_pos.py
+++ b/tools/xm-test/tests/block-list/03_block-list_anotherbd_pos.py
@@ -8,8 +8,8 @@
from XmTestLib import *
-if ENABLE_VMX_SUPPORT:
- SKIP("Block-list not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Block-list not supported for HVM domains")
config = {"disk":"phy:/dev/ram0,hda1,w"}
domain = XmTestDomain(extraConfig=config)
diff --git a/tools/xm-test/tests/block-list/04_block-list_nodb_pos.py b/tools/xm-test/tests/block-list/04_block-list_nodb_pos.py
index 7ff1a2ddf7..ae5e4f51ac 100644
--- a/tools/xm-test/tests/block-list/04_block-list_nodb_pos.py
+++ b/tools/xm-test/tests/block-list/04_block-list_nodb_pos.py
@@ -8,8 +8,8 @@
from XmTestLib import *
-if ENABLE_VMX_SUPPORT:
- SKIP("Block-list not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Block-list not supported for HVM domains")
domain = XmTestDomain()
diff --git a/tools/xm-test/tests/block-list/06_block-list_checkremove_pos.py b/tools/xm-test/tests/block-list/06_block-list_checkremove_pos.py
index e342262659..ccdbe5c816 100644
--- a/tools/xm-test/tests/block-list/06_block-list_checkremove_pos.py
+++ b/tools/xm-test/tests/block-list/06_block-list_checkremove_pos.py
@@ -5,8 +5,8 @@
from XmTestLib import *
-if ENABLE_VMX_SUPPORT:
- SKIP("Block-list not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Block-list not supported for HVM domains")
domain = XmTestDomain()
diff --git a/tools/xm-test/tests/create/14_create_blockroot_pos.py b/tools/xm-test/tests/create/14_create_blockroot_pos.py
index c80a92ca8c..ef52ffc48a 100644
--- a/tools/xm-test/tests/create/14_create_blockroot_pos.py
+++ b/tools/xm-test/tests/create/14_create_blockroot_pos.py
@@ -17,7 +17,7 @@ rdpath = getRdPath()
# if verbose:
# print "Using %s" % output
-if ENABLE_VMX_SUPPORT:
+if ENABLE_HVM_SUPPORT:
domain = XmTestDomain(name="14_create_blockroot")
else:
config = {"memory" : "64",
diff --git a/tools/xm-test/tests/memmax/01_memmax_badparm_neg.py b/tools/xm-test/tests/memmax/01_memmax_badparm_neg.py
index e13fca8415..a2d37ec79a 100644
--- a/tools/xm-test/tests/memmax/01_memmax_badparm_neg.py
+++ b/tools/xm-test/tests/memmax/01_memmax_badparm_neg.py
@@ -8,8 +8,8 @@ import re
from XmTestLib import *
-if ENABLE_VMX_SUPPORT:
- SKIP("Mem-max not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Mem-max not supported for HVM domains")
status, output = traceCommand("xm mem-max")
eyecatcher = "Error:"
diff --git a/tools/xm-test/tests/memset/01_memset_basic_pos.py b/tools/xm-test/tests/memset/01_memset_basic_pos.py
index 5ed6406e8d..58e65966ac 100644
--- a/tools/xm-test/tests/memset/01_memset_basic_pos.py
+++ b/tools/xm-test/tests/memset/01_memset_basic_pos.py
@@ -20,8 +20,8 @@ import re
import time
from XmTestLib import *
-if ENABLE_VMX_SUPPORT:
- SKIP("Mem-set not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Mem-set not supported for HVM domains")
# Create a domain (default XmTestDomain, with our ramdisk)
domain = XmTestDomain()
diff --git a/tools/xm-test/tests/memset/02_memset_badparm_neg.py b/tools/xm-test/tests/memset/02_memset_badparm_neg.py
index a2f60c86d2..9e8fbafbef 100644
--- a/tools/xm-test/tests/memset/02_memset_badparm_neg.py
+++ b/tools/xm-test/tests/memset/02_memset_badparm_neg.py
@@ -18,8 +18,8 @@ import re
from XmTestLib import *
-if ENABLE_VMX_SUPPORT:
- SKIP("Mem-set not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Mem-set not supported for HVM domains")
# destroy no parm input - negative test
status, output = traceCommand("xm mem-set")
diff --git a/tools/xm-test/tests/memset/03_memset_random_pos.py b/tools/xm-test/tests/memset/03_memset_random_pos.py
index c4f3c47370..3f382938ff 100644
--- a/tools/xm-test/tests/memset/03_memset_random_pos.py
+++ b/tools/xm-test/tests/memset/03_memset_random_pos.py
@@ -8,8 +8,8 @@ import re
from XmTestLib import *
-if ENABLE_VMX_SUPPORT:
- SKIP("Mem-set not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Mem-set not supported for HVM domains")
domain = XmTestDomain()
diff --git a/tools/xm-test/tests/memset/04_memset_smallmem_pos.py b/tools/xm-test/tests/memset/04_memset_smallmem_pos.py
index d06571bd05..fd4c027949 100644
--- a/tools/xm-test/tests/memset/04_memset_smallmem_pos.py
+++ b/tools/xm-test/tests/memset/04_memset_smallmem_pos.py
@@ -5,8 +5,8 @@
from XmTestLib import *
-if ENABLE_VMX_SUPPORT:
- SKIP("Mem-set not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Mem-set not supported for HVM domains")
domain = XmTestDomain()
diff --git a/tools/xm-test/tests/migrate/01_migrate_localhost_pos.py b/tools/xm-test/tests/migrate/01_migrate_localhost_pos.py
index 8f86bdd128..a172efef61 100644
--- a/tools/xm-test/tests/migrate/01_migrate_localhost_pos.py
+++ b/tools/xm-test/tests/migrate/01_migrate_localhost_pos.py
@@ -17,8 +17,8 @@ import commands
from XmTestLib import *
-if ENABLE_VMX_SUPPORT:
- SKIP("Migrate currently not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Migrate currently not supported for HVM domains")
# Create a domain (default XmTestDomain, with our ramdisk)
domain = XmTestDomain()
diff --git a/tools/xm-test/tests/network-attach/01_network_attach_pos.py b/tools/xm-test/tests/network-attach/01_network_attach_pos.py
index eb692ab876..8d4b635a54 100644
--- a/tools/xm-test/tests/network-attach/01_network_attach_pos.py
+++ b/tools/xm-test/tests/network-attach/01_network_attach_pos.py
@@ -8,8 +8,8 @@ import sys
from XmTestLib import *
from network_utils import *
-if ENABLE_VMX_SUPPORT:
- SKIP("Network-attach not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Network-attach not supported for HVM domains")
# Create a domain (default XmTestDomain, with our ramdisk)
domain = XmTestDomain()
diff --git a/tools/xm-test/tests/network-attach/02_network_attach_detach_pos.py b/tools/xm-test/tests/network-attach/02_network_attach_detach_pos.py
index 08563eb239..5b50714b9d 100644
--- a/tools/xm-test/tests/network-attach/02_network_attach_detach_pos.py
+++ b/tools/xm-test/tests/network-attach/02_network_attach_detach_pos.py
@@ -10,8 +10,8 @@ import time
from XmTestLib import *
from network_utils import *
-if ENABLE_VMX_SUPPORT:
- SKIP("Network-attach not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Network-attach not supported for HVM domains")
# Create a domain (default XmTestDomain, with our ramdisk)
domain = XmTestDomain()
diff --git a/tools/xm-test/tests/network-attach/03_network_attach_detach_multiple_pos.py b/tools/xm-test/tests/network-attach/03_network_attach_detach_multiple_pos.py
index d169119d2c..76da5891a3 100644
--- a/tools/xm-test/tests/network-attach/03_network_attach_detach_multiple_pos.py
+++ b/tools/xm-test/tests/network-attach/03_network_attach_detach_multiple_pos.py
@@ -10,8 +10,8 @@ import time
from XmTestLib import *
from network_utils import *
-if ENABLE_VMX_SUPPORT:
- SKIP("Network-attach not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Network-attach not supported for HVM domains")
# Create a domain (default XmTestDomain, with our ramdisk)
domain = XmTestDomain()
diff --git a/tools/xm-test/tests/restore/01_restore_basic_pos.py b/tools/xm-test/tests/restore/01_restore_basic_pos.py
index 34c93e8cf8..9ea1ca4c53 100644
--- a/tools/xm-test/tests/restore/01_restore_basic_pos.py
+++ b/tools/xm-test/tests/restore/01_restore_basic_pos.py
@@ -12,8 +12,8 @@ import time
from XmTestLib import *
-if ENABLE_VMX_SUPPORT:
- SKIP("Restore currently not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Restore currently not supported for HVM domains")
domain = XmTestDomain()
diff --git a/tools/xm-test/tests/restore/02_restore_badparm_neg.py b/tools/xm-test/tests/restore/02_restore_badparm_neg.py
index c66ed79113..e5f2c90df1 100644
--- a/tools/xm-test/tests/restore/02_restore_badparm_neg.py
+++ b/tools/xm-test/tests/restore/02_restore_badparm_neg.py
@@ -12,8 +12,8 @@ import re
from XmTestLib import *
-if ENABLE_VMX_SUPPORT:
- SKIP("Restore currently not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Restore currently not supported for HVM domains")
status, output = traceCommand("xm restore -x")
eyecatcher1 = "Error:"
diff --git a/tools/xm-test/tests/restore/03_restore_badfilename_neg.py b/tools/xm-test/tests/restore/03_restore_badfilename_neg.py
index ba6e7e2f30..d45c87b08f 100644
--- a/tools/xm-test/tests/restore/03_restore_badfilename_neg.py
+++ b/tools/xm-test/tests/restore/03_restore_badfilename_neg.py
@@ -12,8 +12,8 @@ import re
from XmTestLib import *
-if ENABLE_VMX_SUPPORT:
- SKIP("Restore currently not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Restore currently not supported for HVM domains")
status, output = traceCommand("xm restore /tmp/NON_EXIST")
eyecatcher1 = "Error:"
diff --git a/tools/xm-test/tests/restore/04_restore_withdevices_pos.py b/tools/xm-test/tests/restore/04_restore_withdevices_pos.py
index 74c6145c03..b3dfe73121 100644
--- a/tools/xm-test/tests/restore/04_restore_withdevices_pos.py
+++ b/tools/xm-test/tests/restore/04_restore_withdevices_pos.py
@@ -7,8 +7,8 @@ from XmTestLib import *
import re
-if ENABLE_VMX_SUPPORT:
- SKIP("Restore currently not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Restore currently not supported for HVM domains")
config = {"disk": ["phy:/dev/ram0,hda1,w", "phy:/dev/ram1,hdb2,w"],
"vif": ['', '']}
diff --git a/tools/xm-test/tests/save/01_save_basic_pos.py b/tools/xm-test/tests/save/01_save_basic_pos.py
index 27e68a5deb..b5a87ad91d 100644
--- a/tools/xm-test/tests/save/01_save_basic_pos.py
+++ b/tools/xm-test/tests/save/01_save_basic_pos.py
@@ -7,8 +7,8 @@ import time
from XmTestLib import *
-if ENABLE_VMX_SUPPORT:
- SKIP("Save currently not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Save currently not supported for HVM domains")
domain = XmTestDomain()
diff --git a/tools/xm-test/tests/save/02_save_badparm_neg.py b/tools/xm-test/tests/save/02_save_badparm_neg.py
index c50dbe9013..2393c46381 100644
--- a/tools/xm-test/tests/save/02_save_badparm_neg.py
+++ b/tools/xm-test/tests/save/02_save_badparm_neg.py
@@ -12,8 +12,8 @@ import re
from XmTestLib import *
-if ENABLE_VMX_SUPPORT:
- SKIP("Save currently not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Save currently not supported for HVM domains")
status, output = traceCommand("xm save -x")
eyecatcher1 = "Error:"
diff --git a/tools/xm-test/tests/save/03_save_bogusfile_neg.py b/tools/xm-test/tests/save/03_save_bogusfile_neg.py
index 0115ee5f3b..2612f74b1b 100644
--- a/tools/xm-test/tests/save/03_save_bogusfile_neg.py
+++ b/tools/xm-test/tests/save/03_save_bogusfile_neg.py
@@ -10,8 +10,8 @@ import time
from XmTestLib import *
-if ENABLE_VMX_SUPPORT:
- SKIP("Save currently not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Save currently not supported for HVM domains")
domain = XmTestDomain()
diff --git a/tools/xm-test/tests/sysrq/01_sysrq_basic_neg.py b/tools/xm-test/tests/sysrq/01_sysrq_basic_neg.py
index 9d213e944a..cc42d47265 100644
--- a/tools/xm-test/tests/sysrq/01_sysrq_basic_neg.py
+++ b/tools/xm-test/tests/sysrq/01_sysrq_basic_neg.py
@@ -9,8 +9,8 @@ import re
from XmTestLib import *
-if ENABLE_VMX_SUPPORT:
- SKIP("Sysrq not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Sysrq not supported for HVM domains")
status, output = traceCommand("xm sysrq does_not_exist s");
diff --git a/tools/xm-test/tests/sysrq/02_sysrq_sync_pos.py b/tools/xm-test/tests/sysrq/02_sysrq_sync_pos.py
index 0b805fd7b6..3aea592a0e 100644
--- a/tools/xm-test/tests/sysrq/02_sysrq_sync_pos.py
+++ b/tools/xm-test/tests/sysrq/02_sysrq_sync_pos.py
@@ -9,8 +9,8 @@ import time
from XmTestLib import *
-if ENABLE_VMX_SUPPORT:
- SKIP("Sysrq not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Sysrq not supported for HVM domains")
# Create a domain (default XmTestDomain, with our ramdisk)
domain = XmTestDomain()
diff --git a/tools/xm-test/tests/sysrq/03_sysrq_withreboot_pos.py b/tools/xm-test/tests/sysrq/03_sysrq_withreboot_pos.py
index b69e5617b0..71cc9f1fb4 100644
--- a/tools/xm-test/tests/sysrq/03_sysrq_withreboot_pos.py
+++ b/tools/xm-test/tests/sysrq/03_sysrq_withreboot_pos.py
@@ -7,8 +7,8 @@ from XmTestLib import *
import time
-if ENABLE_VMX_SUPPORT:
- SKIP("Sysrq not supported for VMX domains")
+if ENABLE_HVM_SUPPORT:
+ SKIP("Sysrq not supported for HVM domains")
domain = XmTestDomain()
diff --git a/xen/Rules.mk b/xen/Rules.mk
index 276659053a..a0daaaca8f 100644
--- a/xen/Rules.mk
+++ b/xen/Rules.mk
@@ -53,6 +53,9 @@ else
CFLAGS += -g -DVERBOSE
endif
+# There is no real reason to compile without it
+CFLAGS += -g
+
ifeq ($(crash_debug),y)
CFLAGS += -g -DCRASH_DEBUG
endif
diff --git a/xen/arch/ia64/Makefile b/xen/arch/ia64/Makefile
index ed134a2fb0..5e93de6520 100644
--- a/xen/arch/ia64/Makefile
+++ b/xen/arch/ia64/Makefile
@@ -15,7 +15,7 @@ OBJS = xensetup.o setup.o time.o irq.o process.o smp.o \
OBJS += vmx_init.o vmx_virt.o vmx_vcpu.o vmx_process.o vmx_vsa.o vmx_ivt.o\
vmx_phy_mode.o vmx_utility.o vmx_interrupt.o vmx_entry.o vmmu.o \
vtlb.o mmio.o vlsapic.o vmx_hypercall.o mm.o vmx_support.o \
- pal_emul.o vmx_irq_ia64.o vmx_vioapic.o
+ pal_emul.o vmx_irq_ia64.o hvm_vioapic.o
# lib files from xen/arch/ia64/linux/ (linux/arch/ia64/lib)
OBJS += bitop.o clear_page.o flush.o copy_page_mck.o \
@@ -94,13 +94,19 @@ $(BASEDIR)/include/asm-ia64/.offsets.h.stamp:
|| ln -s $(BASEDIR)/include/xen $(BASEDIR)/include/linux
[ -e $(BASEDIR)/include/asm-ia64/xen ] \
|| ln -s $(BASEDIR)/include/asm-ia64/linux $(BASEDIR)/include/asm-ia64/xen
-# Link to DM file in Xen for ia64/vti
- [ -e $(BASEDIR)/include/asm-ia64/vmx_vpic.h ] \
- || ln -s ../../include/asm-x86/vmx_vpic.h $(BASEDIR)/include/asm-ia64/vmx_vpic.h
- [ -e $(BASEDIR)/include/asm-ia64/vmx_vioapic.h ] \
- || ln -s ../../include/asm-x86/vmx_vioapic.h $(BASEDIR)/include/asm-ia64/vmx_vioapic.h
- [ -e $(BASEDIR)/arch/ia64/vmx/vmx_vioapic.c ] \
- || ln -s ../../../arch/x86/dm/vmx_vioapic.c $(BASEDIR)/arch/ia64/vmx/vmx_vioapic.c
+# Link to HVM files in Xen for ia64/vti
+ [ -e $(BASEDIR)/include/asm-ia64/hvm ] \
+ || mkdir $(BASEDIR)/include/asm-ia64/hvm
+ [ -e $(BASEDIR)/include/asm-ia64/hvm/support.h ] \
+ || ln -s ../../../include/asm-x86/hvm/support.h $(BASEDIR)/include/asm-ia64/hvm/support.h
+ [ -e $(BASEDIR)/include/asm-ia64/hvm/io.h ] \
+ || ln -s ../../../include/asm-x86/hvm/io.h $(BASEDIR)/include/asm-ia64/hvm/io.h
+ [ -e $(BASEDIR)/include/asm-ia64/hvm/vpic.h ] \
+ || ln -s ../../../include/asm-x86/hvm/vpic.h $(BASEDIR)/include/asm-ia64/hvm/vpic.h
+ [ -e $(BASEDIR)/include/asm-ia64/hvm/vioapic.h ] \
+ || ln -s ../../../include/asm-x86/hvm/vioapic.h $(BASEDIR)/include/asm-ia64/hvm/vioapic.h
+ [ -e $(BASEDIR)/arch/ia64/vmx/hvm_vioapic.c ] \
+ || ln -s ../../../arch/x86/hvm/vioapic.c $(BASEDIR)/arch/ia64/vmx/hvm_vioapic.c
# Solve circular reference on asm-offsets.h
[ -f $(BASEDIR)/include/asm-ia64/asm-offsets.h ] \
|| echo "#define IA64_TASK_SIZE 0" > $(BASEDIR)/include/asm-ia64/asm-offsets.h
@@ -136,6 +142,8 @@ __umodsi3.o: idiv32.S
clean:
rm -f *.o *~ core xen.lds.s $(BASEDIR)/include/asm-ia64/.offsets.h.stamp asm-offsets.s map.out
rm -f asm-xsi-offsets.s $(BASEDIR)/include/asm-ia64/asm-xsi-offsets.h
+ rm -f $(BASEDIR)/arch/ia64/vmx/hvm_*.c
+ rm -rf $(BASEDIR)/include/asm-ia64/hvm
rm -f linux/lib/*.o
.PHONY: default clean
diff --git a/xen/arch/ia64/vmx/mmio.c b/xen/arch/ia64/vmx/mmio.c
index 342fa87621..fd06bc14bb 100644
--- a/xen/arch/ia64/vmx/mmio.c
+++ b/xen/arch/ia64/vmx/mmio.c
@@ -207,7 +207,7 @@ static void legacy_io_access(VCPU *vcpu, u64 pa, u64 *val, size_t s, int dir)
extern struct vmx_mmio_handler vioapic_mmio_handler;
static void mmio_access(VCPU *vcpu, u64 src_pa, u64 *dest, size_t s, int ma, int dir)
{
- struct virutal_platform_def *v_plat;
+ struct virtual_platform_def *v_plat;
//mmio_type_t iot;
unsigned long iot;
struct vmx_mmio_handler *vioapic_handler = &vioapic_mmio_handler;
diff --git a/xen/arch/ia64/vmx/vlsapic.c b/xen/arch/ia64/vmx/vlsapic.c
index 93dabc168b..2eef0a5c5b 100644
--- a/xen/arch/ia64/vmx/vlsapic.c
+++ b/xen/arch/ia64/vmx/vlsapic.c
@@ -38,7 +38,7 @@
#include <asm/vmx_pal_vsa.h>
#include <asm/kregs.h>
#include <asm/vmx_platform.h>
-#include <asm/vmx_vioapic.h>
+#include <asm/hvm/vioapic.h>
//u64 fire_itc;
//u64 fire_itc2;
@@ -278,7 +278,7 @@ void vmx_virq_line_assist(struct vcpu *v)
do {
irqs = *(volatile uint16_t*)virq_line;
} while ((uint16_t)cmpxchg(virq_line, irqs, 0) != irqs);
- vmx_vioapic_do_irqs(v->domain, irqs);
+ hvm_vioapic_do_irqs(v->domain, irqs);
}
virq_line = &spg->pic_clear_irr;
@@ -286,7 +286,7 @@ void vmx_virq_line_assist(struct vcpu *v)
do {
irqs = *(volatile uint16_t*)virq_line;
} while ((uint16_t)cmpxchg(virq_line, irqs, 0) != irqs);
- vmx_vioapic_do_irqs_clear(v->domain, irqs);
+ hvm_vioapic_do_irqs_clear(v->domain, irqs);
}
}
@@ -300,7 +300,7 @@ void vmx_virq_line_init(struct domain *d)
spg->pic_clear_irr = 0;
}
-int ioapic_match_logical_addr(vmx_vioapic_t *s, int number, uint16_t dest)
+int ioapic_match_logical_addr(hvm_vioapic_t *s, int number, uint16_t dest)
{
return (VLAPIC_ID(s->lapic_info[number]) == dest);
}
@@ -311,14 +311,14 @@ struct vlapic* apic_round_robin(struct domain *d,
uint32_t bitmap)
{
uint8_t bit;
- vmx_vioapic_t *s;
+ hvm_vioapic_t *s;
if (!bitmap) {
printk("<apic_round_robin> no bit on bitmap\n");
return NULL;
}
- s = &d->arch.vmx_platform.vmx_vioapic;
+ s = &d->arch.vmx_platform.vioapic;
for (bit = 0; bit < s->lapic_count; bit++) {
if (bitmap & (1 << bit))
return s->lapic_info[bit];
@@ -351,7 +351,7 @@ void vlsapic_reset(VCPU *vcpu)
#ifdef V_IOSAPIC_READY
vcpu->arch.arch_vmx.vlapic.vcpu = vcpu;
- vmx_vioapic_add_lapic(&vcpu->arch.arch_vmx.vlapic, vcpu);
+ hvm_vioapic_add_lapic(&vcpu->arch.arch_vmx.vlapic, vcpu);
#endif
DPRINTK("VLSAPIC inservice base=%lp\n", &VLSAPIC_INSVC(vcpu,0) );
}
diff --git a/xen/arch/ia64/vmx/vmx_init.c b/xen/arch/ia64/vmx/vmx_init.c
index 788b7bc1a0..edc9f8b67a 100644
--- a/xen/arch/ia64/vmx/vmx_init.c
+++ b/xen/arch/ia64/vmx/vmx_init.c
@@ -48,7 +48,7 @@
#include <asm/vmx.h>
#include <xen/mm.h>
#include <public/arch-ia64.h>
-#include <asm/vmx_vioapic.h>
+#include <asm/hvm/vioapic.h>
/* Global flag to identify whether Intel vmx feature is on */
u32 vmx_enabled = 0;
@@ -394,7 +394,7 @@ void vmx_setup_platform(struct domain *d, struct vcpu_guest_context *c)
vmx_virq_line_init(d);
/* Initialize iosapic model within hypervisor */
- vmx_vioapic_init(d);
+ hvm_vioapic_init(d);
}
diff --git a/xen/arch/ia64/vmx/vmx_vcpu.c b/xen/arch/ia64/vmx/vmx_vcpu.c
index 25e077bd8f..be9f08682d 100644
--- a/xen/arch/ia64/vmx/vmx_vcpu.c
+++ b/xen/arch/ia64/vmx/vmx_vcpu.c
@@ -198,7 +198,7 @@ vmx_vcpu_get_vtlb(VCPU *vcpu)
}
-struct virutal_platform_def *
+struct virtual_platform_def *
vmx_vcpu_get_plat(VCPU *vcpu)
{
return &(vcpu->domain->arch.vmx_platform);
diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile
index 3779672aa3..2eec245cfd 100644
--- a/xen/arch/x86/Makefile
+++ b/xen/arch/x86/Makefile
@@ -4,10 +4,14 @@ include $(BASEDIR)/Rules.mk
OBJS += $(patsubst %.S,%.o,$(wildcard $(TARGET_SUBARCH)/*.S))
OBJS += $(patsubst %.c,%.o,$(wildcard $(TARGET_SUBARCH)/*.c))
OBJS += $(patsubst %.c,%.o,$(wildcard acpi/*.c))
-OBJS += $(patsubst %.c,%.o,$(wildcard dm/*.c))
OBJS += $(patsubst %.c,%.o,$(wildcard mtrr/*.c))
OBJS += $(patsubst %.c,%.o,$(wildcard genapic/*.c))
OBJS += $(patsubst %.c,%.o,$(wildcard cpu/*.c))
+OBJS += $(patsubst %.c,%.o,$(wildcard hvm/*.c))
+OBJS += $(patsubst %.c,%.o,$(wildcard hvm/vmx/*.c))
+OBJS += $(patsubst %.S,%.o,$(wildcard hvm/vmx/$(TARGET_SUBARCH)/*.S))
+OBJS += $(patsubst %.c,%.o,$(wildcard hvm/svm/*.c))
+OBJS += $(patsubst %.S,%.o,$(wildcard hvm/svm/$(TARGET_SUBARCH)/*.S))
ifeq ($(TARGET_SUBARCH),x86_64)
OBJS := $(subst cpu/centaur.o,,$(OBJS))
@@ -74,9 +78,15 @@ clean:
rm -f x86_64/*.o x86_64/*~ x86_64/core
rm -f mtrr/*.o mtrr/*~ mtrr/core
rm -f acpi/*.o acpi/*~ acpi/core
- rm -f dm/*.o dm/*~ dm/core
rm -f genapic/*.o genapic/*~ genapic/core
rm -f cpu/*.o cpu/*~ cpu/core
+ rm -f hvm/*.o hvm/*~ hvm/core
+ rm -f hvm/vmx/*.o hvm/vmx/*~ hvm/vmx/core
+ rm -f hvm/vmx/x86_32/*.o hvm/vmx/x86_32/*~ hvm/vmx/x86_32/core
+ rm -f hvm/vmx/x86_64/*.o hvm/vmx/x86_64/*~ hvm/vmx/x86_64/core
+ rm -f hvm/svm/*.o hvm/svm/*~ hvm/svm/core
+ rm -f hvm/svm/x86_32/*.o hvm/svm/x86_32/*~ hvm/svm/x86_32/core
+ rm -f hvm/svm/x86_64/*.o hvm/svm/x86_64/*~ hvm/svm/x86_64/core
rm -f xen.lds
.PHONY: default clean
diff --git a/xen/arch/x86/cpu/amd.c b/xen/arch/x86/cpu/amd.c
index 3852bea9bc..de1e9cbc2f 100644
--- a/xen/arch/x86/cpu/amd.c
+++ b/xen/arch/x86/cpu/amd.c
@@ -3,12 +3,20 @@
#include <xen/bitops.h>
#include <xen/mm.h>
#include <xen/smp.h>
+#include <xen/sched.h>
#include <asm/io.h>
#include <asm/msr.h>
#include <asm/processor.h>
+#include <asm/hvm/vcpu.h>
+#include <asm/hvm/support.h>
+
#include "cpu.h"
+
+#define AMD_C1_CLOCK_RAMP 0x80000084
+#define AMD_ADVPM_TSC_INVARIANT 0x80000007
+
/*
* amd_flush_filter={on,off}. Forcibly Enable or disable the TLB flush
* filter on AMD 64-bit processors.
@@ -41,6 +49,99 @@ custom_param("amd_flush_filter", flush_filter);
extern void vide(void);
__asm__(".text\n.align 4\nvide: ret");
+
+/*
+ * Check if C1-Clock ramping enabled in PMM7.CpuLowPwrEnh
+ * On 8th-Generation cores only. Assume BIOS has setup
+ * all Northbridges equivalently.
+ */
+
+static int c1_ramp_8gen(void)
+{
+ u32 l;
+
+ /* Read dev=0x18, function = 3, offset=0x87 */
+ l = AMD_C1_CLOCK_RAMP;
+ /* fill in dev (18) + function (3) */
+ /* direct cfc/cf8 should be safe here */
+ l += (((0x18) << 3) + 0x3) << 8;
+ outl(l, 0xcf8);
+ return (1 & (inl(0xcfc) >> 24));
+}
+
+/*
+ * returns TRUE if ok to use TSC
+ */
+
+static int use_amd_tsc(struct cpuinfo_x86 *c)
+{
+ if (c->x86 < 0xf) {
+ /*
+ * TSC drift doesn't exist on 7th Gen or less
+ * However, OS still needs to consider effects
+ * of P-state changes on TSC
+ */
+ return 1;
+ } else if ( cpuid_edx(AMD_ADVPM_TSC_INVARIANT) & 0x100 ) {
+ /*
+ * CPUID.AdvPowerMgmtInfo.TscInvariant
+ * EDX bit 8, 8000_0007
+ * Invariant TSC on 8th Gen or newer, use it
+ * (assume all cores have invariant TSC)
+ */
+ return 1;
+ } else if ((mp_get_num_processors() == 1) && (c->x86_num_cores == 1)) {
+ /*
+ * OK to use TSC on uni-processor-uni-core
+ * However, OS still needs to consider effects
+ * of P-state changes on TSC
+ */
+ return 1;
+ } else if ( (mp_get_num_processors() == 1) && (c->x86 == 0x0f)
+ && !c1_ramp_8gen()) {
+ /*
+ * Use TSC on 8th Gen uni-proc with C1_ramp off
+ * However, OS still needs to consider effects
+ * of P-state changes on TSC
+ */
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+/*
+ * Disable C1-Clock ramping if enabled in PMM7.CpuLowPwrEnh
+ * On 8th-Generation cores only. Assume BIOS has setup
+ * all Northbridges equivalently.
+ */
+
+static void amd_disable_c1_ramping(void)
+{
+ u32 l, h;
+ int i;
+
+ for (i=0; i < NR_CPUS;i++) {
+ /* Read from the Northbridge for Node x. until we get invalid data */
+ /* fill in dev (18 + cpu#) + function (3) */
+ l = AMD_C1_CLOCK_RAMP + ((((0x18 + i) << 3) + 0x3) << 8);
+ /* direct cfc/cf8 should be safe here */
+ outl(l, 0xcf8);
+ h = inl(0xcfc);
+ if (h != 0xFFFFFFFF) {
+ h &= 0xFCFFFFFF; /* clears pmm7[1:0] */
+ outl(l, 0xcf8);
+ outl(h, 0xcfc);
+ printk ("AMD: Disabling C1 Clock Ramping Node #%x\n",i);
+ }
+ else {
+ i = NR_CPUS;
+ }
+
+ }
+ return;
+}
+
static void __init init_amd(struct cpuinfo_x86 *c)
{
u32 l, h;
@@ -246,6 +347,18 @@ static void __init init_amd(struct cpuinfo_x86 *c)
cpu, c->x86_num_cores, cpu_core_id[cpu]);
}
#endif
+ /*
+ * Prevent TSC drift in non single-processor, single-core platforms
+ */
+ if ( !use_amd_tsc(c) && (c->x86 == 0x0f) && c1_ramp_8gen() &&
+ (smp_processor_id() == 0)) {
+ /* Disable c1 Clock Ramping on all cores */
+ amd_disable_c1_ramping();
+ }
+
+#ifdef CONFIG_SVM
+ start_svm();
+#endif
}
static unsigned int amd_size_cache(struct cpuinfo_x86 * c, unsigned int size)
diff --git a/xen/arch/x86/cpu/intel.c b/xen/arch/x86/cpu/intel.c
index ef713eb95e..b699f4af54 100644
--- a/xen/arch/x86/cpu/intel.c
+++ b/xen/arch/x86/cpu/intel.c
@@ -10,7 +10,9 @@
#include <asm/mpspec.h>
#include <asm/apic.h>
#include <mach_apic.h>
-#include <asm/vmx_vmcs.h>
+#include <asm/hvm/vpit.h>
+#include <asm/hvm/vcpu.h>
+#include <asm/hvm/support.h>
#include "cpu.h"
diff --git a/xen/arch/x86/dom0_ops.c b/xen/arch/x86/dom0_ops.c
index ab06691546..4ed7aa5592 100644
--- a/xen/arch/x86/dom0_ops.c
+++ b/xen/arch/x86/dom0_ops.c
@@ -20,6 +20,8 @@
#include <xen/iocap.h>
#include <asm/shadow.h>
#include <asm/irq.h>
+#include <asm/hvm/hvm.h>
+#include <asm/hvm/support.h>
#include <asm/processor.h>
#include <public/sched_ctl.h>
@@ -448,15 +450,12 @@ long arch_do_dom0_op(struct dom0_op *op, struct dom0_op *u_dom0_op)
void arch_getdomaininfo_ctxt(
struct vcpu *v, struct vcpu_guest_context *c)
{
- extern void save_vmx_cpu_user_regs(struct cpu_user_regs *);
-
memcpy(c, &v->arch.guest_context, sizeof(*c));
- if ( VMX_DOMAIN(v) )
+ if ( HVM_DOMAIN(v) )
{
- save_vmx_cpu_user_regs(&c->user_regs);
- __vmread(CR0_READ_SHADOW, &c->ctrlreg[0]);
- __vmread(CR4_READ_SHADOW, &c->ctrlreg[4]);
+ hvm_store_cpu_guest_regs(v, &c->user_regs);
+ hvm_store_cpu_guest_ctrl_regs(v, c->ctrlreg);
}
else
{
@@ -470,8 +469,8 @@ void arch_getdomaininfo_ctxt(
c->flags |= VGCF_I387_VALID;
if ( KERNEL_MODE(v, &v->arch.guest_context.user_regs) )
c->flags |= VGCF_IN_KERNEL;
- if (VMX_DOMAIN(v))
- c->flags |= VGCF_VMX_GUEST;
+ if ( HVM_DOMAIN(v) )
+ c->flags |= VGCF_HVM_GUEST;
c->ctrlreg[3] = pagetable_get_paddr(v->arch.guest_table);
diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c
index efdb3b4976..eb54846b68 100644
--- a/xen/arch/x86/domain.c
+++ b/xen/arch/x86/domain.c
@@ -35,7 +35,8 @@
#include <asm/shadow.h>
#include <xen/console.h>
#include <xen/elf.h>
-#include <asm/vmx.h>
+#include <asm/hvm/hvm.h>
+#include <asm/hvm/support.h>
#include <asm/msr.h>
#include <xen/kernel.h>
#include <xen/multicall.h>
@@ -153,8 +154,7 @@ void machine_restart(char * __unused)
*/
smp_send_stop();
disable_IO_APIC();
-
- stop_vmx();
+ hvm_disable();
/* Rebooting needs to touch the page at absolute address 0. */
*((unsigned short *)__va(0x472)) = reboot_mode;
@@ -354,26 +354,26 @@ int arch_set_info_guest(
* #GP. If DS, ES, FS, GS are DPL 0 then they'll be cleared automatically.
* If SS RPL or DPL differs from CS RPL then we'll #GP.
*/
- if ( !(c->flags & VGCF_VMX_GUEST) )
+ if ( !(c->flags & VGCF_HVM_GUEST) )
{
if ( ((c->user_regs.cs & 3) == 0) ||
((c->user_regs.ss & 3) == 0) )
return -EINVAL;
}
else if ( !hvm_enabled )
- return -EINVAL;
+ return -EINVAL;
clear_bit(_VCPUF_fpu_initialised, &v->vcpu_flags);
if ( c->flags & VGCF_I387_VALID )
set_bit(_VCPUF_fpu_initialised, &v->vcpu_flags);
v->arch.flags &= ~TF_kernel_mode;
- if ( (c->flags & VGCF_IN_KERNEL) || (c->flags & VGCF_VMX_GUEST) )
+ if ( (c->flags & VGCF_IN_KERNEL) || (c->flags & VGCF_HVM_GUEST) )
v->arch.flags |= TF_kernel_mode;
memcpy(&v->arch.guest_context, c, sizeof(*c));
- if ( !(c->flags & VGCF_VMX_GUEST) )
+ if ( !(c->flags & VGCF_HVM_GUEST) )
{
/* IOPL privileges are virtualised. */
v->arch.iopl = (v->arch.guest_context.user_regs.eflags >> 12) & 3;
@@ -384,9 +384,7 @@ int arch_set_info_guest(
}
else if ( test_bit(_VCPUF_initialised, &v->vcpu_flags) )
{
- return modify_vmcs(
- &v->arch.arch_vmx,
- &v->arch.guest_context.user_regs);
+ hvm_modify_guest_state(v);
}
if ( test_bit(_VCPUF_initialised, &v->vcpu_flags) )
@@ -418,7 +416,7 @@ int arch_set_info_guest(
return -EINVAL;
}
}
- else if ( !(c->flags & VGCF_VMX_GUEST) )
+ else if ( !(c->flags & VGCF_HVM_GUEST) )
{
if ( !get_page_and_type(pfn_to_page(phys_basetab>>PAGE_SHIFT), d,
PGT_base_page_table) )
@@ -428,14 +426,17 @@ int arch_set_info_guest(
}
}
- if ( c->flags & VGCF_VMX_GUEST )
+ if ( c->flags & VGCF_HVM_GUEST )
{
- /* VMX uses the initially provided page tables as the P2M map. */
+ /* HVM uses the initially provided page tables as the P2M map. */
if ( !pagetable_get_paddr(d->arch.phys_table) )
d->arch.phys_table = v->arch.guest_table;
v->arch.guest_table = mk_pagetable(0);
- vmx_final_setup_guest(v);
+ if (!hvm_initialize_guest_resources(v))
+ return -EINVAL;
+
+ hvm_switch_on = 1;
}
update_pagetables(v);
@@ -611,8 +612,8 @@ static void save_segments(struct vcpu *v)
struct cpu_user_regs *regs = &ctxt->user_regs;
unsigned int dirty_segment_mask = 0;
- if ( VMX_DOMAIN(v) )
- rdmsrl(MSR_SHADOW_GS_BASE, v->arch.arch_vmx.msr_content.shadow_gs);
+ if ( HVM_DOMAIN(v) )
+ hvm_save_segments(v);
__asm__ __volatile__ ( "mov %%ds,%0" : "=m" (regs->ds) );
__asm__ __volatile__ ( "mov %%es,%0" : "=m" (regs->es) );
@@ -704,7 +705,7 @@ static void __context_switch(void)
loaddebug(&n->arch.guest_context, 7);
}
- if ( !VMX_DOMAIN(n) )
+ if ( !HVM_DOMAIN(n) )
{
set_int80_direct_trap(n);
switch_kernel_stack(n, cpu);
@@ -764,15 +765,16 @@ void context_switch(struct vcpu *prev, struct vcpu *next)
/* Re-enable interrupts before restoring state which may fault. */
local_irq_enable();
- if ( VMX_DOMAIN(next) )
+ if ( HVM_DOMAIN(next) )
{
- vmx_restore_msrs(next);
+ hvm_restore_msrs(next);
}
else
{
load_LDT(next);
load_segments(next);
- vmx_load_msrs(next);
+ if ( HVM_DOMAIN(next) )
+ hvm_load_msrs(next);
}
}
@@ -962,7 +964,8 @@ void domain_relinquish_resources(struct domain *d)
v->arch.guest_table_user = mk_pagetable(0);
}
- vmx_relinquish_resources(v);
+ if ( HVM_DOMAIN(v) )
+ hvm_relinquish_guest_resources(v);
}
shadow_mode_disable(d);
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
new file mode 100644
index 0000000000..c838d5c407
--- /dev/null
+++ b/xen/arch/x86/hvm/hvm.c
@@ -0,0 +1,308 @@
+/*
+ * hvm.c: Common hardware virtual machine abstractions.
+ *
+ * Copyright (c) 2004, Intel Corporation.
+ * 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 <xen/config.h>
+#include <xen/init.h>
+#include <xen/lib.h>
+#include <xen/trace.h>
+#include <xen/sched.h>
+#include <xen/irq.h>
+#include <xen/softirq.h>
+#include <xen/domain_page.h>
+#include <asm/current.h>
+#include <asm/io.h>
+#include <asm/shadow.h>
+#include <asm/regs.h>
+#include <asm/cpufeature.h>
+#include <asm/processor.h>
+#include <asm/types.h>
+#include <asm/msr.h>
+#include <asm/spinlock.h>
+#include <asm/hvm/hvm.h>
+#include <asm/hvm/support.h>
+#include <asm/shadow.h>
+#if CONFIG_PAGING_LEVELS >= 3
+#include <asm/shadow_64.h>
+#endif
+#include <public/sched.h>
+#include <public/hvm/ioreq.h>
+#include <public/hvm/hvm_info_table.h>
+
+int hvm_enabled = 0;
+int hvm_switch_on = 0;
+
+unsigned int opt_hvm_debug_level = 0;
+integer_param("hvm_debug", opt_hvm_debug_level);
+
+struct hvm_function_table hvm_funcs;
+
+static void hvm_map_io_shared_page(struct domain *d)
+{
+ int i;
+ unsigned char e820_map_nr;
+ struct e820entry *e820entry;
+ unsigned char *p;
+ unsigned long mpfn;
+ unsigned long gpfn = 0;
+
+ local_flush_tlb_pge();
+
+ mpfn = get_mfn_from_pfn(E820_MAP_PAGE >> PAGE_SHIFT);
+ if (mpfn == INVALID_MFN) {
+ printk("Can not find E820 memory map page for HVM domain.\n");
+ domain_crash_synchronous();
+ }
+
+ p = map_domain_page(mpfn);
+ if (p == NULL) {
+ printk("Can not map E820 memory map page for HVM domain.\n");
+ domain_crash_synchronous();
+ }
+
+ e820_map_nr = *(p + E820_MAP_NR_OFFSET);
+ e820entry = (struct e820entry *)(p + E820_MAP_OFFSET);
+
+ for ( i = 0; i < e820_map_nr; i++ )
+ {
+ if (e820entry[i].type == E820_SHARED_PAGE)
+ {
+ gpfn = (e820entry[i].addr >> PAGE_SHIFT);
+ break;
+ }
+ }
+
+ if ( gpfn == 0 ) {
+ printk("Can not get io request shared page"
+ " from E820 memory map for HVM domain.\n");
+ unmap_domain_page(p);
+ domain_crash_synchronous();
+ }
+ unmap_domain_page(p);
+
+ /* Initialise shared page */
+ mpfn = get_mfn_from_pfn(gpfn);
+ if (mpfn == INVALID_MFN) {
+ printk("Can not find io request shared page for HVM domain.\n");
+ domain_crash_synchronous();
+ }
+
+ p = map_domain_page_global(mpfn);
+ if (p == NULL) {
+ printk("Can not map io request shared page for HVM domain.\n");
+ domain_crash_synchronous();
+ }
+ d->arch.hvm_domain.shared_page_va = (unsigned long)p;
+
+ HVM_DBG_LOG(DBG_LEVEL_1, "eport: %x\n", iopacket_port(d));
+
+ clear_bit(iopacket_port(d),
+ &d->shared_info->evtchn_mask[0]);
+}
+
+static int validate_hvm_info(struct hvm_info_table *t)
+{
+ char signature[] = "HVM INFO";
+ uint8_t *ptr = (uint8_t *)t;
+ uint8_t sum = 0;
+ int i;
+
+ /* strncmp(t->signature, "HVM INFO", 8) */
+ for ( i = 0; i < 8; i++ ) {
+ if ( signature[i] != t->signature[i] ) {
+ printk("Bad hvm info signature\n");
+ return 0;
+ }
+ }
+
+ for ( i = 0; i < t->length; i++ )
+ sum += ptr[i];
+
+ return (sum == 0);
+}
+
+static void hvm_get_info(struct domain *d)
+{
+ unsigned char *p;
+ unsigned long mpfn;
+ struct hvm_info_table *t;
+
+ mpfn = get_mfn_from_pfn(HVM_INFO_PFN);
+ if ( mpfn == INVALID_MFN ) {
+ printk("Can not get info page mfn for HVM domain.\n");
+ domain_crash_synchronous();
+ }
+
+ p = map_domain_page(mpfn);
+ if ( p == NULL ) {
+ printk("Can not map info page for HVM domain.\n");
+ domain_crash_synchronous();
+ }
+
+ t = (struct hvm_info_table *)(p + HVM_INFO_OFFSET);
+
+ if ( validate_hvm_info(t) ) {
+ d->arch.hvm_domain.nr_vcpus = t->nr_vcpus;
+ d->arch.hvm_domain.apic_enabled = t->apic_enabled;
+ } else {
+ printk("Bad hvm info table\n");
+ d->arch.hvm_domain.nr_vcpus = 1;
+ d->arch.hvm_domain.apic_enabled = 0;
+ }
+
+ unmap_domain_page(p);
+}
+
+void hvm_setup_platform(struct domain* d)
+{
+ struct hvm_domain *platform;
+
+ if (!(HVM_DOMAIN(current) && (current->vcpu_id == 0)))
+ return;
+
+ hvm_map_io_shared_page(d);
+ hvm_get_info(d);
+
+ platform = &d->arch.hvm_domain;
+ pic_init(&platform->vpic, pic_irq_request, &platform->interrupt_request);
+ register_pic_io_hook();
+
+ if ( hvm_apic_support(d) ) {
+ spin_lock_init(&d->arch.hvm_domain.round_robin_lock);
+ hvm_vioapic_init(d);
+ }
+}
+
+void pic_irq_request(int *interrupt_request, int level)
+{
+ if (level)
+ *interrupt_request = 1;
+ else
+ *interrupt_request = 0;
+}
+
+void hvm_pic_assist(struct vcpu *v)
+{
+ global_iodata_t *spg;
+ u16 *virq_line, irqs;
+ struct hvm_virpic *pic = &v->domain->arch.hvm_domain.vpic;
+
+ spg = &get_sp(v->domain)->sp_global;
+ virq_line = &spg->pic_clear_irr;
+ if ( *virq_line ) {
+ do {
+ irqs = *(volatile u16*)virq_line;
+ } while ( (u16)cmpxchg(virq_line,irqs, 0) != irqs );
+ do_pic_irqs_clear(pic, irqs);
+ }
+ virq_line = &spg->pic_irr;
+ if ( *virq_line ) {
+ do {
+ irqs = *(volatile u16*)virq_line;
+ } while ( (u16)cmpxchg(virq_line,irqs, 0) != irqs );
+ do_pic_irqs(pic, irqs);
+ }
+}
+
+int cpu_get_interrupt(struct vcpu *v, int *type)
+{
+ int intno;
+ struct hvm_virpic *s = &v->domain->arch.hvm_domain.vpic;
+
+ if ( (intno = cpu_get_apic_interrupt(v, type)) != -1 ) {
+ /* set irq request if a PIC irq is still pending */
+ /* XXX: improve that */
+ pic_update_irq(s);
+ return intno;
+ }
+ /* read the irq from the PIC */
+ if ( (intno = cpu_get_pic_interrupt(v, type)) != -1 )
+ return intno;
+
+ return -1;
+}
+
+/*
+ * Copy from/to guest virtual.
+ */
+int
+hvm_copy(void *buf, unsigned long vaddr, int size, int dir)
+{
+ unsigned long gpa, mfn;
+ char *addr;
+ int count;
+
+ while (size > 0) {
+ count = PAGE_SIZE - (vaddr & ~PAGE_MASK);
+ if (count > size)
+ count = size;
+
+ if (hvm_paging_enabled(current)) {
+ gpa = gva_to_gpa(vaddr);
+ mfn = get_mfn_from_pfn(gpa >> PAGE_SHIFT);
+ } else
+ mfn = get_mfn_from_pfn(vaddr >> PAGE_SHIFT);
+ if (mfn == INVALID_MFN)
+ return 0;
+
+ addr = (char *)map_domain_page(mfn) + (vaddr & ~PAGE_MASK);
+
+ if (dir == HVM_COPY_IN)
+ memcpy(buf, addr, count);
+ else
+ memcpy(addr, buf, count);
+
+ unmap_domain_page(addr);
+
+ vaddr += count;
+ buf += count;
+ size -= count;
+ }
+
+ return 1;
+}
+
+/*
+ * HVM specific printbuf. Mostly used for hvmloader chit-chat.
+ */
+void hvm_print_line(struct vcpu *v, const char c)
+{
+ int *index = &v->domain->arch.hvm_domain.pbuf_index;
+ char *pbuf = v->domain->arch.hvm_domain.pbuf;
+
+ if (*index == HVM_PBUF_SIZE-2 || c == '\n') {
+ if (*index == HVM_PBUF_SIZE-2)
+ pbuf[(*index)++] = c;
+ pbuf[*index] = '\0';
+ printk("(GUEST: %u) %s\n", v->domain->domain_id, pbuf);
+ *index = 0;
+ } else
+ pbuf[(*index)++] = c;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
+
diff --git a/xen/arch/x86/dm/i8259.c b/xen/arch/x86/hvm/i8259.c
index 8a27835e9f..7bfb007865 100644
--- a/xen/arch/x86/dm/i8259.c
+++ b/xen/arch/x86/hvm/i8259.c
@@ -29,12 +29,10 @@
#include <xen/lib.h>
#include <xen/errno.h>
#include <xen/sched.h>
-#include <public/hvm/ioreq.h>
-#include <asm/vmx.h>
-#include <asm/vmx_vpic.h>
+#include <asm/hvm/hvm.h>
+#include <asm/hvm/io.h>
+#include <asm/hvm/support.h>
#include <asm/current.h>
-#include <asm/vmx_vioapic.h>
-#include <asm/vmx_vlapic.h>
/* set irq level. If an edge is detected, then the IRR is set to 1 */
static inline void pic_set_irq1(PicState *s, int irq, int level)
@@ -103,7 +101,7 @@ static int pic_get_irq(PicState *s)
/* raise irq to CPU if necessary. must be called every time the active
irq may change */
/* XXX: should not export it, but it is needed for an APIC kludge */
-void pic_update_irq(struct vmx_virpic *s)
+void pic_update_irq(struct hvm_virpic *s)
{
int irq2, irq;
@@ -123,9 +121,9 @@ void pic_update_irq(struct vmx_virpic *s)
void pic_set_irq_new(void *opaque, int irq, int level)
{
- struct vmx_virpic *s = opaque;
+ struct hvm_virpic *s = opaque;
- vmx_vioapic_set_irq(current->domain, irq, level);
+ hvm_vioapic_set_irq(current->domain, irq, level);
pic_set_irq1(&s->pics[irq >> 3], irq & 7, level);
/* used for IOAPIC irqs */
if (s->alt_irq_func)
@@ -133,24 +131,24 @@ void pic_set_irq_new(void *opaque, int irq, int level)
pic_update_irq(s);
}
-void do_pic_irqs (struct vmx_virpic *s, uint16_t irqs)
+void do_pic_irqs (struct hvm_virpic *s, uint16_t irqs)
{
s->pics[1].irr |= (uint8_t)(irqs >> 8);
s->pics[0].irr |= (uint8_t) irqs;
- vmx_vioapic_do_irqs(current->domain, irqs);
+ hvm_vioapic_do_irqs(current->domain, irqs);
pic_update_irq(s);
}
-void do_pic_irqs_clear (struct vmx_virpic *s, uint16_t irqs)
+void do_pic_irqs_clear (struct hvm_virpic *s, uint16_t irqs)
{
s->pics[1].irr &= ~(uint8_t)(irqs >> 8);
s->pics[0].irr &= ~(uint8_t) irqs;
- vmx_vioapic_do_irqs_clear(current->domain, irqs);
+ hvm_vioapic_do_irqs_clear(current->domain, irqs);
pic_update_irq(s);
}
/* obsolete function */
-void pic_set_irq(struct vmx_virpic *isa_pic, int irq, int level)
+void pic_set_irq(struct hvm_virpic *isa_pic, int irq, int level)
{
pic_set_irq_new(isa_pic, irq, level);
}
@@ -169,7 +167,7 @@ static inline void pic_intack(PicState *s, int irq)
s->irr &= ~(1 << irq);
}
-int pic_read_irq(struct vmx_virpic *s)
+int pic_read_irq(struct hvm_virpic *s)
{
int irq, irq2, intno;
@@ -200,7 +198,7 @@ int pic_read_irq(struct vmx_virpic *s)
return intno;
}
-static void update_shared_irr(struct vmx_virpic *s, PicState *c)
+static void update_shared_irr(struct hvm_virpic *s, PicState *c)
{
uint8_t *pl, *pe;
@@ -378,7 +376,7 @@ static uint32_t pic_ioport_read(void *opaque, uint32_t addr1)
/* memory mapped interrupt status */
/* XXX: may be the same than pic_read_irq() */
-uint32_t pic_intack_read(struct vmx_virpic *s)
+uint32_t pic_intack_read(struct hvm_virpic *s)
{
int ret;
@@ -409,7 +407,7 @@ static void pic_init1(int io_addr, int elcr_addr, PicState *s)
pic_reset(s);
}
-void pic_init(struct vmx_virpic *s, void (*irq_request)(),
+void pic_init(struct hvm_virpic *s, void (*irq_request)(),
void *irq_request_opaque)
{
memset(s, 0, sizeof(*s));
@@ -424,7 +422,7 @@ void pic_init(struct vmx_virpic *s, void (*irq_request)(),
return;
}
-void pic_set_alt_irq_func(struct vmx_virpic *s, void (*alt_irq_func)(),
+void pic_set_alt_irq_func(struct hvm_virpic *s, void (*alt_irq_func)(),
void *alt_irq_opaque)
{
s->alt_irq_func = alt_irq_func;
@@ -433,7 +431,7 @@ void pic_set_alt_irq_func(struct vmx_virpic *s, void (*alt_irq_func)(),
static int intercept_pic_io(ioreq_t *p)
{
- struct vmx_virpic *pic;
+ struct hvm_virpic *pic;
struct vcpu *v = current;
uint32_t data;
@@ -441,10 +439,10 @@ static int intercept_pic_io(ioreq_t *p)
printk("PIC_IO wrong access size %d!\n", (int)p->size);
return 1;
}
- pic = &v->domain->arch.vmx_platform.vmx_pic;
+ pic = &v->domain->arch.hvm_domain.vpic;
if ( p->dir == 0 ) {
if(p->pdata_valid)
- vmx_copy(&data, (unsigned long)p->u.pdata, p->size, VMX_COPY_IN);
+ hvm_copy(&data, (unsigned long)p->u.pdata, p->size, HVM_COPY_IN);
else
data = p->u.data;
pic_ioport_write((void*)&pic->pics[p->addr>>7],
@@ -454,7 +452,7 @@ static int intercept_pic_io(ioreq_t *p)
data = pic_ioport_read(
(void*)&pic->pics[p->addr>>7], (uint32_t) p->addr);
if(p->pdata_valid)
- vmx_copy(&data, (unsigned long)p->u.pdata, p->size, VMX_COPY_OUT);
+ hvm_copy(&data, (unsigned long)p->u.pdata, p->size, HVM_COPY_OUT);
else
p->u.data = (u64)data;
}
@@ -463,7 +461,7 @@ static int intercept_pic_io(ioreq_t *p)
static int intercept_elcr_io(ioreq_t *p)
{
- struct vmx_virpic *s;
+ struct hvm_virpic *s;
struct vcpu *v = current;
uint32_t data;
@@ -472,10 +470,10 @@ static int intercept_elcr_io(ioreq_t *p)
return 1;
}
- s = &v->domain->arch.vmx_platform.vmx_pic;
+ s = &v->domain->arch.hvm_domain.vpic;
if ( p->dir == 0 ) {
if(p->pdata_valid)
- vmx_copy(&data, (unsigned long)p->u.pdata, p->size, VMX_COPY_IN);
+ hvm_copy(&data, (unsigned long)p->u.pdata, p->size, HVM_COPY_IN);
else
data = p->u.data;
elcr_ioport_write((void*)&s->pics[p->addr&1],
@@ -487,7 +485,7 @@ static int intercept_elcr_io(ioreq_t *p)
data = (u64) elcr_ioport_read(
(void*)&s->pics[p->addr&1], (uint32_t) p->addr);
if(p->pdata_valid)
- vmx_copy(&data, (unsigned long)p->u.pdata, p->size, VMX_COPY_OUT);
+ hvm_copy(&data, (unsigned long)p->u.pdata, p->size, HVM_COPY_OUT);
else
p->u.data = (u64)data;
@@ -507,8 +505,8 @@ void register_pic_io_hook (void)
int cpu_get_pic_interrupt(struct vcpu *v, int *type)
{
int intno;
- struct vmx_virpic *s = &v->domain->arch.vmx_platform.vmx_pic;
- struct vmx_platform *plat = &v->domain->arch.vmx_platform;
+ struct hvm_virpic *s = &v->domain->arch.hvm_domain.vpic;
+ struct hvm_domain *plat = &v->domain->arch.hvm_domain;
if ( !vlapic_accept_pic_intr(v) )
return -1;
@@ -528,17 +526,17 @@ int is_pit_irq(struct vcpu *v, int irq, int type)
int pit_vec;
if (type == VLAPIC_DELIV_MODE_EXT)
- pit_vec = v->domain->arch.vmx_platform.vmx_pic.pics[0].irq_base;
+ pit_vec = v->domain->arch.hvm_domain.vpic.pics[0].irq_base;
else
pit_vec =
- v->domain->arch.vmx_platform.vmx_vioapic.redirtbl[0].RedirForm.vector;
+ v->domain->arch.hvm_domain.vioapic.redirtbl[0].RedirForm.vector;
return (irq == pit_vec);
}
int is_irq_enabled(struct vcpu *v, int irq)
{
- struct vmx_virpic *vpic=&v->domain->arch.vmx_platform.vmx_pic;
+ struct hvm_virpic *vpic=&v->domain->arch.hvm_domain.vpic;
if ( irq & 8 ) {
return !( (1 << (irq&7)) & vpic->pics[1].imr);
diff --git a/xen/arch/x86/vmx_intercept.c b/xen/arch/x86/hvm/intercept.c
index 419960842c..bc3d91f093 100644
--- a/xen/arch/x86/vmx_intercept.c
+++ b/xen/arch/x86/hvm/intercept.c
@@ -1,5 +1,6 @@
/*
- * vmx_intercept.c: Handle performance critical I/O packets in hypervisor space
+ * intercept.c: Handle performance critical I/O packets in hypervisor space
+ *
* Copyright (c) 2004, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
@@ -14,40 +15,37 @@
* 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 <xen/config.h>
#include <xen/types.h>
-#include <asm/vmx.h>
-#include <asm/vmx_platform.h>
-#include <asm/vmx_vpit.h>
-#include <asm/vmx_intercept.h>
-#include <asm/vmx_vlapic.h>
-#include <public/hvm/ioreq.h>
+#include <xen/sched.h>
+#include <asm/regs.h>
+#include <asm/hvm/hvm.h>
+#include <asm/hvm/support.h>
+#include <asm/hvm/domain.h>
#include <xen/lib.h>
#include <xen/sched.h>
#include <asm/current.h>
#include <io_ports.h>
#include <xen/event.h>
-#ifdef CONFIG_VMX
-extern struct vmx_mmio_handler vlapic_mmio_handler;
-extern struct vmx_mmio_handler vioapic_mmio_handler;
+extern struct hvm_mmio_handler vlapic_mmio_handler;
+extern struct hvm_mmio_handler vioapic_mmio_handler;
-#define VMX_MMIO_HANDLER_NR 2
+#define HVM_MMIO_HANDLER_NR 2
-struct vmx_mmio_handler *vmx_mmio_handlers[VMX_MMIO_HANDLER_NR] =
+struct hvm_mmio_handler *hvm_mmio_handlers[HVM_MMIO_HANDLER_NR] =
{
&vlapic_mmio_handler,
&vioapic_mmio_handler
};
-static inline void vmx_mmio_access(struct vcpu *v,
+static inline void hvm_mmio_access(struct vcpu *v,
ioreq_t *p,
- vmx_mmio_read_t read_handler,
- vmx_mmio_write_t write_handler)
+ hvm_mmio_read_t read_handler,
+ hvm_mmio_write_t write_handler)
{
ioreq_t *req;
vcpu_iodata_t *vio = get_vio(v->domain, v->vcpu_id);
@@ -78,17 +76,17 @@ static inline void vmx_mmio_access(struct vcpu *v,
data = read_handler(v,
req->addr + (sign * i * req->size),
req->size);
- vmx_copy(&data,
+ hvm_copy(&data,
(unsigned long)p->u.pdata + (sign * i * req->size),
p->size,
- VMX_COPY_OUT);
+ HVM_COPY_OUT);
}
} else { /* !req->dir == IOREQ_READ */
for (i = 0; i < req->count; i++) {
- vmx_copy(&data,
+ hvm_copy(&data,
(unsigned long)p->u.pdata + (sign * i * req->size),
p->size,
- VMX_COPY_IN);
+ HVM_COPY_IN);
write_handler(v,
req->addr + (sign * i * req->size),
req->size, data);
@@ -132,20 +130,20 @@ static inline void vmx_mmio_access(struct vcpu *v,
}
}
-int vmx_mmio_intercept(ioreq_t *p)
+int hvm_mmio_intercept(ioreq_t *p)
{
struct vcpu *v = current;
int i;
/* XXX currently only APIC use intercept */
- if ( !vmx_apic_support(v->domain) )
+ if ( !hvm_apic_support(v->domain) )
return 0;
- for ( i = 0; i < VMX_MMIO_HANDLER_NR; i++ ) {
- if ( vmx_mmio_handlers[i]->check_handler(v, p->addr) ) {
- vmx_mmio_access(v, p,
- vmx_mmio_handlers[i]->read_handler,
- vmx_mmio_handlers[i]->write_handler);
+ for ( i = 0; i < HVM_MMIO_HANDLER_NR; i++ ) {
+ if ( hvm_mmio_handlers[i]->check_handler(v, p->addr) ) {
+ hvm_mmio_access(v, p,
+ hvm_mmio_handlers[i]->read_handler,
+ hvm_mmio_handlers[i]->write_handler);
return 1;
}
}
@@ -156,11 +154,11 @@ int vmx_mmio_intercept(ioreq_t *p)
* Check if the request is handled inside xen
* return value: 0 --not handled; 1 --handled
*/
-int vmx_io_intercept(ioreq_t *p, int type)
+int hvm_io_intercept(ioreq_t *p, int type)
{
struct vcpu *v = current;
- struct vmx_io_handler *handler =
- &(v->domain->arch.vmx_platform.vmx_io_handler);
+ struct hvm_io_handler *handler =
+ &(v->domain->arch.hvm_domain.io_handler);
int i;
unsigned long addr, size;
@@ -180,8 +178,8 @@ int register_io_handler(unsigned long addr, unsigned long size,
intercept_action_t action, int type)
{
struct vcpu *v = current;
- struct vmx_io_handler *handler =
- &(v->domain->arch.vmx_platform.vmx_io_handler);
+ struct hvm_io_handler *handler =
+ &(v->domain->arch.hvm_domain.io_handler);
int num = handler->num_slot;
if (num >= MAX_IO_HANDLER) {
@@ -198,21 +196,25 @@ int register_io_handler(unsigned long addr, unsigned long size,
return 1;
}
-static void pit_cal_count(struct vmx_virpit *vpit)
+static void pit_cal_count(struct hvm_virpit *vpit)
{
u64 nsec_delta = (unsigned int)((NOW() - vpit->inject_point));
+
if (nsec_delta > vpit->period)
- VMX_DBG_LOG(DBG_LEVEL_1, "VMX_PIT:long time has passed from last injection!");
+ HVM_DBG_LOG(DBG_LEVEL_1,
+ "HVM_PIT: long time has passed from last injection!");
+
if(vpit->init_val == 0)
{
printk("PIT init value == 0!\n");
domain_crash_synchronous();
}
- vpit->count = vpit->init_val - ((nsec_delta * PIT_FREQ / 1000000000ULL) % vpit->init_val );
+ vpit->count = vpit->init_val
+ - ((nsec_delta * PIT_FREQ / 1000000000ULL) % vpit->init_val);
}
-static void pit_latch_io(struct vmx_virpit *vpit)
+static void pit_latch_io(struct hvm_virpit *vpit)
{
pit_cal_count(vpit);
@@ -228,7 +230,8 @@ static void pit_latch_io(struct vmx_virpit *vpit)
vpit->count_MSB_latched=1;
break;
case MSByte_multiple:
- VMX_DBG_LOG(DBG_LEVEL_1, "VMX_PIT:latch PIT counter before MSB_multiple!");
+ HVM_DBG_LOG(DBG_LEVEL_1,
+ "HVM_PIT: latch PIT counter before MSB_multiple!");
vpit->read_state=LSByte_multiple;
vpit->count_LSB_latched=1;
vpit->count_MSB_latched=1;
@@ -238,7 +241,7 @@ static void pit_latch_io(struct vmx_virpit *vpit)
}
}
-static int pit_read_io(struct vmx_virpit *vpit)
+static int pit_read_io(struct hvm_virpit *vpit)
{
if(vpit->count_LSB_latched) {
/* Read Least Significant Byte */
@@ -256,7 +259,7 @@ static int pit_read_io(struct vmx_virpit *vpit)
return ((vpit->count>>8) & 0xFF);
} else {
/* Unlatched Count Read */
- VMX_DBG_LOG(DBG_LEVEL_1, "VMX_PIT: unlatched read");
+ HVM_DBG_LOG(DBG_LEVEL_1, "HVM_PIT: unlatched read");
pit_cal_count(vpit);
if(!(vpit->read_state & 0x1)) {
/* Read Least Significant Byte */
@@ -274,7 +277,7 @@ static int pit_read_io(struct vmx_virpit *vpit)
}
}
-/* vmx_io_assist light-weight version, specific to PIT DM */
+/* hvm_io_assist light-weight version, specific to PIT DM */
static void resume_pit_io(ioreq_t *p)
{
struct cpu_user_regs *regs = guest_cpu_user_regs();
@@ -300,7 +303,7 @@ static void resume_pit_io(ioreq_t *p)
int intercept_pit_io(ioreq_t *p)
{
struct vcpu *v = current;
- struct vmx_virpit *vpit = &(v->domain->arch.vmx_platform.vmx_pit);
+ struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit);
if (p->size != 1 ||
p->pdata_valid ||
@@ -333,7 +336,7 @@ void hlt_timer_fn(void *data)
evtchn_set_pending(v, iopacket_port(v->domain));
}
-static __inline__ void missed_ticks(struct vmx_virpit*vpit)
+static __inline__ void missed_ticks(struct hvm_virpit*vpit)
{
int missed_ticks;
@@ -348,7 +351,7 @@ static __inline__ void missed_ticks(struct vmx_virpit*vpit)
static void pit_timer_fn(void *data)
{
struct vcpu *v = data;
- struct vmx_virpit *vpit = &(v->domain->arch.vmx_platform.vmx_pit);
+ struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit);
/* pick up missed timer tick */
missed_ticks(vpit);
@@ -360,7 +363,7 @@ static void pit_timer_fn(void *data)
}
}
-void pickup_deactive_ticks(struct vmx_virpit *vpit)
+void pickup_deactive_ticks(struct hvm_virpit *vpit)
{
if ( !active_timer(&(vpit->pit_timer)) ) {
@@ -375,18 +378,18 @@ void pickup_deactive_ticks(struct vmx_virpit *vpit)
/* Only some PIT operations such as load init counter need a hypervisor hook.
* leave all other operations in user space DM
*/
-void vmx_hooks_assist(struct vcpu *v)
+void hvm_hooks_assist(struct vcpu *v)
{
vcpu_iodata_t *vio = get_vio(v->domain, v->vcpu_id);
ioreq_t *p = &vio->vp_ioreq;
- struct vmx_virpit *vpit = &(v->domain->arch.vmx_platform.vmx_pit);
+ struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit);
int rw_mode, reinit = 0;
/* load init count*/
if (p->state == STATE_IORESP_HOOK) {
/* set up actimer, handle re-init */
if ( active_timer(&(vpit->pit_timer)) ) {
- VMX_DBG_LOG(DBG_LEVEL_1, "VMX_PIT: guest reset PIT with channel %lx!\n", (unsigned long) ((p->u.data >> 24) & 0x3) );
+ HVM_DBG_LOG(DBG_LEVEL_1, "HVM_PIT: guest reset PIT with channel %lx!\n", (unsigned long) ((p->u.data >> 24) & 0x3) );
stop_timer(&(vpit->pit_timer));
reinit = 1;
@@ -399,14 +402,14 @@ void vmx_hooks_assist(struct vcpu *v)
vpit->init_val = (p->u.data & 0xFFFF) ;
/* frequency(ns) of pit */
vpit->period = DIV_ROUND(((vpit->init_val) * 1000000000ULL), PIT_FREQ);
- VMX_DBG_LOG(DBG_LEVEL_1,"VMX_PIT: guest set init pit freq:%u ns, initval:0x%x\n", vpit->period, vpit->init_val);
+ HVM_DBG_LOG(DBG_LEVEL_1,"HVM_PIT: guest set init pit freq:%u ns, initval:0x%x\n", vpit->period, vpit->init_val);
if (vpit->period < 900000) { /* < 0.9 ms */
- printk("VMX_PIT: guest programmed too small an init_val: %x\n",
+ printk("HVM_PIT: guest programmed too small an init_val: %x\n",
vpit->init_val);
vpit->period = 1000000;
}
vpit->period_cycles = (u64)vpit->period * cpu_khz / 1000000L;
- printk("VMX_PIT: guest freq in cycles=%lld\n",(long long)vpit->period_cycles);
+ printk("HVM_PIT: guest freq in cycles=%lld\n",(long long)vpit->period_cycles);
vpit->channel = ((p->u.data >> 24) & 0x3);
vpit->first_injected = 0;
@@ -426,7 +429,7 @@ void vmx_hooks_assist(struct vcpu *v)
vpit->read_state=LSByte_multiple;
break;
default:
- printk("VMX_PIT:wrong PIT rw_mode!\n");
+ printk("HVM_PIT:wrong PIT rw_mode!\n");
break;
}
@@ -442,7 +445,6 @@ void vmx_hooks_assist(struct vcpu *v)
}
}
}
-#endif /* CONFIG_VMX */
/*
* Local variables:
diff --git a/xen/arch/x86/vmx_io.c b/xen/arch/x86/hvm/io.c
index 1ab368ff77..8e725fcecc 100644
--- a/xen/arch/x86/vmx_io.c
+++ b/xen/arch/x86/hvm/io.c
@@ -1,6 +1,8 @@
/*
- * vmx_io.c: handling I/O, interrupts related VMX entry/exit
+ * io.c: Handling I/O and interrupts.
+ *
* Copyright (c) 2004, Intel Corporation.
+ * 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,
@@ -14,7 +16,6 @@
* 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 <xen/config.h>
@@ -24,42 +25,24 @@
#include <xen/errno.h>
#include <xen/trace.h>
#include <xen/event.h>
+
#include <xen/hypercall.h>
#include <asm/current.h>
#include <asm/cpufeature.h>
#include <asm/processor.h>
#include <asm/msr.h>
-#include <asm/vmx.h>
-#include <asm/vmx_vmcs.h>
-#include <asm/vmx_platform.h>
-#include <asm/vmx_vpit.h>
#include <asm/apic.h>
#include <asm/shadow.h>
-#include <asm/vmx_vpic.h>
-#include <asm/vmx_vlapic.h>
+#include <asm/hvm/hvm.h>
+#include <asm/hvm/support.h>
+#include <asm/hvm/vpit.h>
+#include <asm/hvm/vpic.h>
+#include <asm/hvm/vlapic.h>
+
#include <public/sched.h>
#include <public/hvm/ioreq.h>
-#ifdef CONFIG_VMX
#if defined (__i386__)
-void load_cpu_user_regs(struct cpu_user_regs *regs)
-{
- /*
- * Write the guest register value into VMCS
- */
- __vmwrite(GUEST_SS_SELECTOR, regs->ss);
- __vmwrite(GUEST_RSP, regs->esp);
-
- __vmwrite(GUEST_RFLAGS, regs->eflags);
- if (regs->eflags & EF_TF)
- __vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
- else
- __vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
-
- __vmwrite(GUEST_CS_SELECTOR, regs->cs);
- __vmwrite(GUEST_RIP, regs->eip);
-}
-
static void set_reg_value (int size, int index, int seg, struct cpu_user_regs *regs, long value)
{
switch (size) {
@@ -182,21 +165,6 @@ static void set_reg_value (int size, int index, int seg, struct cpu_user_regs *r
}
}
#else
-void load_cpu_user_regs(struct cpu_user_regs *regs)
-{
- __vmwrite(GUEST_SS_SELECTOR, regs->ss);
- __vmwrite(GUEST_RSP, regs->rsp);
-
- __vmwrite(GUEST_RFLAGS, regs->rflags);
- if (regs->rflags & EF_TF)
- __vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
- else
- __vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
-
- __vmwrite(GUEST_CS_SELECTOR, regs->cs);
- __vmwrite(GUEST_RIP, regs->rip);
-}
-
static inline void __set_reg_value(unsigned long *reg, int size, long value)
{
switch (size) {
@@ -391,7 +359,7 @@ static inline void set_eflags_PF(int size, unsigned long v1,
regs->eflags |= X86_EFLAGS_PF;
}
-static void vmx_pio_assist(struct cpu_user_regs *regs, ioreq_t *p,
+static void hvm_pio_assist(struct cpu_user_regs *regs, ioreq_t *p,
struct mmio_op *mmio_opp)
{
unsigned long old_eax;
@@ -414,7 +382,7 @@ static void vmx_pio_assist(struct cpu_user_regs *regs, ioreq_t *p,
addr = regs->edi;
if (sign > 0)
addr -= p->size;
- vmx_copy(&p->u.data, addr, p->size, VMX_COPY_OUT);
+ hvm_copy(&p->u.data, addr, p->size, HVM_COPY_OUT);
} else if (p->pdata_valid) {
regs->edi += sign * p->count * p->size;
if (mmio_opp->flags & REPZ)
@@ -439,8 +407,8 @@ static void vmx_pio_assist(struct cpu_user_regs *regs, ioreq_t *p,
}
}
-static void vmx_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p,
- struct mmio_op *mmio_opp)
+static void hvm_mmio_assist(struct vcpu *v, struct cpu_user_regs *regs,
+ ioreq_t *p, struct mmio_op *mmio_opp)
{
int sign = p->df ? -1 : 1;
int size = -1, index = -1;
@@ -523,7 +491,7 @@ static void vmx_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p,
if (sign > 0)
addr -= p->size;
- vmx_copy(&p->u.data, addr, p->size, VMX_COPY_OUT);
+ hvm_copy(&p->u.data, addr, p->size, HVM_COPY_OUT);
}
if (mmio_opp->flags & REPZ)
@@ -680,10 +648,10 @@ static void vmx_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p,
break;
}
- load_cpu_user_regs(regs);
+ hvm_load_cpu_guest_regs(v, regs);
}
-void vmx_io_assist(struct vcpu *v)
+void hvm_io_assist(struct vcpu *v)
{
vcpu_iodata_t *vio;
ioreq_t *p;
@@ -691,13 +659,13 @@ void vmx_io_assist(struct vcpu *v)
struct mmio_op *mmio_opp;
struct cpu_user_regs *inst_decoder_regs;
- mmio_opp = &v->arch.arch_vmx.mmio_op;
+ mmio_opp = &v->arch.hvm_vcpu.mmio_op;
inst_decoder_regs = mmio_opp->inst_decoder_regs;
vio = get_vio(v->domain, v->vcpu_id);
if (vio == 0) {
- VMX_DBG_LOG(DBG_LEVEL_1,
+ HVM_DBG_LOG(DBG_LEVEL_1,
"bad shared page: %lx", (unsigned long) vio);
printf("bad shared page: %lx\n", (unsigned long) vio);
domain_crash_synchronous();
@@ -705,24 +673,24 @@ void vmx_io_assist(struct vcpu *v)
p = &vio->vp_ioreq;
if (p->state == STATE_IORESP_HOOK)
- vmx_hooks_assist(v);
+ hvm_hooks_assist(v);
- /* clear IO wait VMX flag */
- if (test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags)) {
+ /* clear IO wait HVM flag */
+ if (test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags)) {
if (p->state == STATE_IORESP_READY) {
p->state = STATE_INVALID;
- clear_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags);
+ clear_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags);
if (p->type == IOREQ_TYPE_PIO)
- vmx_pio_assist(regs, p, mmio_opp);
+ hvm_pio_assist(regs, p, mmio_opp);
else
- vmx_mmio_assist(regs, p, mmio_opp);
+ hvm_mmio_assist(v, regs, p, mmio_opp);
}
/* else an interrupt send event raced us */
}
}
-int vmx_clear_pending_io_event(struct vcpu *v)
+int hvm_clear_pending_io_event(struct vcpu *v)
{
struct domain *d = v->domain;
int port = iopacket_port(d);
@@ -731,7 +699,7 @@ int vmx_clear_pending_io_event(struct vcpu *v)
if (!d->shared_info->evtchn_pending[port/BITS_PER_LONG])
clear_bit(port/BITS_PER_LONG, &v->vcpu_info->evtchn_pending_sel);
- /* Note: VMX domains may need upcalls as well. */
+ /* Note: HVM domains may need upcalls as well. */
if (!v->vcpu_info->evtchn_pending_sel)
clear_bit(0, &v->vcpu_info->evtchn_upcall_pending);
@@ -739,270 +707,47 @@ int vmx_clear_pending_io_event(struct vcpu *v)
return test_and_clear_bit(port, &d->shared_info->evtchn_pending[0]);
}
-/* Because we've cleared the pending events first, we need to guarantee that
- * all events to be handled by xen for VMX domains are taken care of here.
+/*
+ * Because we've cleared the pending events first, we need to guarantee that
+ * all events to be handled by xen for HVM domains are taken care of here.
*
* interrupts are guaranteed to be checked before resuming guest.
- * VMX upcalls have been already arranged for if necessary.
+ * HVM upcalls have been already arranged for if necessary.
*/
-void vmx_check_events(struct vcpu *v)
+void hvm_check_events(struct vcpu *v)
{
- /* clear the event *before* checking for work. This should avoid
- the set-and-check races */
- if (vmx_clear_pending_io_event(v))
- vmx_io_assist(v);
+ /*
+ * Clear the event *before* checking for work. This should
+ * avoid the set-and-check races
+ */
+ if (hvm_clear_pending_io_event(current))
+ hvm_io_assist(v);
}
-/* On exit from vmx_wait_io, we're guaranteed to have a I/O response from
- the device model */
-void vmx_wait_io()
+/*
+ * On exit from hvm_wait_io, we're guaranteed to have a I/O response
+ * from the device model.
+ */
+void hvm_wait_io(void)
{
int port = iopacket_port(current->domain);
do {
if (!test_bit(port, &current->domain->shared_info->evtchn_pending[0]))
- do_sched_op(SCHEDOP_block, 0);
+ do_sched_op(SCHEDOP_block, 0);
- vmx_check_events(current);
- if (!test_bit(ARCH_VMX_IO_WAIT, &current->arch.arch_vmx.flags))
+ hvm_check_events(current);
+ if (!test_bit(ARCH_HVM_IO_WAIT, &current->arch.hvm_vcpu.ioflags))
break;
- /* Events other than IOPACKET_PORT might have woken us up. In that
- case, safely go back to sleep. */
+ /*
+ * Events other than IOPACKET_PORT might have woken us up.
+ * In that case, safely go back to sleep.
+ */
clear_bit(port/BITS_PER_LONG, &current->vcpu_info->evtchn_pending_sel);
clear_bit(0, &current->vcpu_info->evtchn_upcall_pending);
} while(1);
}
-/* Simple minded Local APIC priority implementation. Fix later */
-static __inline__ int find_highest_irq(u32 *pintr)
-{
- if (pintr[7])
- return __fls(pintr[7]) + (256-32*1);
- if (pintr[6])
- return __fls(pintr[6]) + (256-32*2);
- if (pintr[5])
- return __fls(pintr[5]) + (256-32*3);
- if (pintr[4])
- return __fls(pintr[4]) + (256-32*4);
- if (pintr[3])
- return __fls(pintr[3]) + (256-32*5);
- if (pintr[2])
- return __fls(pintr[2]) + (256-32*6);
- if (pintr[1])
- return __fls(pintr[1]) + (256-32*7);
- return __fls(pintr[0]);
-}
-
-void set_tsc_shift(struct vcpu *v,struct vmx_virpit *vpit)
-{
- u64 drift;
-
- if ( vpit->first_injected )
- drift = vpit->period_cycles * vpit->pending_intr_nr;
- else
- drift = 0;
- vpit->shift = v->arch.arch_vmx.tsc_offset - drift;
- __vmwrite(TSC_OFFSET, vpit->shift);
-
-#if defined (__i386__)
- __vmwrite(TSC_OFFSET_HIGH, ((vpit->shift)>> 32));
-#endif
-}
-
-#define BSP_CPU(v) (!(v->vcpu_id))
-static inline void
-interrupt_post_injection(struct vcpu * v, int vector, int type)
-{
- struct vmx_virpit *vpit = &(v->domain->arch.vmx_platform.vmx_pit);
-
- if ( is_pit_irq(v, vector, type) ) {
- if ( !vpit->first_injected ) {
- vpit->pending_intr_nr = 0;
- vpit->scheduled = NOW() + vpit->period;
- set_timer(&vpit->pit_timer, vpit->scheduled);
- vpit->first_injected = 1;
- } else {
- vpit->pending_intr_nr--;
- }
- vpit->inject_point = NOW();
- set_tsc_shift (v, vpit);
- }
-
- switch(type)
- {
- case VLAPIC_DELIV_MODE_EXT:
- break;
-
- default:
- vlapic_post_injection(v, vector, type);
- break;
- }
-}
-
-static inline void
-enable_irq_window(unsigned long cpu_exec_control)
-{
- if (!(cpu_exec_control & CPU_BASED_VIRTUAL_INTR_PENDING)) {
- cpu_exec_control |= CPU_BASED_VIRTUAL_INTR_PENDING;
- __vmwrite(CPU_BASED_VM_EXEC_CONTROL, cpu_exec_control);
- }
-}
-
-static inline void
-disable_irq_window(unsigned long cpu_exec_control)
-{
- if ( cpu_exec_control & CPU_BASED_VIRTUAL_INTR_PENDING ) {
- cpu_exec_control &= ~CPU_BASED_VIRTUAL_INTR_PENDING;
- __vmwrite(CPU_BASED_VM_EXEC_CONTROL, cpu_exec_control);
- }
-}
-
-static inline int irq_masked(unsigned long eflags)
-{
- return ((eflags & X86_EFLAGS_IF) == 0);
-}
-
-void pic_irq_request(int *interrupt_request, int level)
-{
- if (level)
- *interrupt_request = 1;
- else
- *interrupt_request = 0;
-}
-
-void vmx_pic_assist(struct vcpu *v)
-{
- global_iodata_t *spg;
- u16 *virq_line, irqs;
- struct vmx_virpic *pic = &v->domain->arch.vmx_platform.vmx_pic;
-
- spg = &get_sp(v->domain)->sp_global;
- virq_line = &spg->pic_clear_irr;
- if ( *virq_line ) {
- do {
- irqs = *(volatile u16*)virq_line;
- } while ( (u16)cmpxchg(virq_line,irqs, 0) != irqs );
- do_pic_irqs_clear(pic, irqs);
- }
- virq_line = &spg->pic_irr;
- if ( *virq_line ) {
- do {
- irqs = *(volatile u16*)virq_line;
- } while ( (u16)cmpxchg(virq_line,irqs, 0) != irqs );
- do_pic_irqs(pic, irqs);
- }
-
-}
-
-int cpu_get_interrupt(struct vcpu *v, int *type)
-{
- int intno;
- struct vmx_virpic *s = &v->domain->arch.vmx_platform.vmx_pic;
-
- if ( (intno = cpu_get_apic_interrupt(v, type)) != -1 ) {
- /* set irq request if a PIC irq is still pending */
- /* XXX: improve that */
- pic_update_irq(s);
- return intno;
- }
- /* read the irq from the PIC */
- if ( (intno = cpu_get_pic_interrupt(v, type)) != -1 )
- return intno;
-
- return -1;
-}
-
-asmlinkage void vmx_intr_assist(void)
-{
- int intr_type = 0;
- int highest_vector;
- unsigned long intr_fields, eflags, interruptibility, cpu_exec_control;
- struct vcpu *v = current;
- struct vmx_platform *plat=&v->domain->arch.vmx_platform;
- struct vmx_virpit *vpit = &plat->vmx_pit;
- struct vmx_virpic *pic= &plat->vmx_pic;
-
- vmx_pic_assist(v);
- __vmread_vcpu(v, CPU_BASED_VM_EXEC_CONTROL, &cpu_exec_control);
- if ( vpit->pending_intr_nr ) {
- pic_set_irq(pic, 0, 0);
- pic_set_irq(pic, 0, 1);
- }
-
- __vmread(VM_ENTRY_INTR_INFO_FIELD, &intr_fields);
-
- if (intr_fields & INTR_INFO_VALID_MASK) {
- enable_irq_window(cpu_exec_control);
- VMX_DBG_LOG(DBG_LEVEL_1, "vmx_intr_assist: intr_fields: %lx",
- intr_fields);
- return;
- }
-
- __vmread(GUEST_INTERRUPTIBILITY_INFO, &interruptibility);
-
- if (interruptibility) {
- enable_irq_window(cpu_exec_control);
- VMX_DBG_LOG(DBG_LEVEL_1, "interruptibility: %lx",interruptibility);
- return;
- }
-
- __vmread(GUEST_RFLAGS, &eflags);
- if (irq_masked(eflags)) {
- enable_irq_window(cpu_exec_control);
- return;
- }
-
- highest_vector = cpu_get_interrupt(v, &intr_type);
-
- if (highest_vector == -1) {
- disable_irq_window(cpu_exec_control);
- return;
- }
-
- switch (intr_type) {
- case VLAPIC_DELIV_MODE_EXT:
- case VLAPIC_DELIV_MODE_FIXED:
- case VLAPIC_DELIV_MODE_LPRI:
- vmx_inject_extint(v, highest_vector, VMX_INVALID_ERROR_CODE);
- TRACE_3D(TRC_VMX_INT, v->domain->domain_id, highest_vector, 0);
- break;
- case VLAPIC_DELIV_MODE_SMI:
- case VLAPIC_DELIV_MODE_NMI:
- case VLAPIC_DELIV_MODE_INIT:
- case VLAPIC_DELIV_MODE_STARTUP:
- default:
- printk("Unsupported interrupt type\n");
- BUG();
- break;
- }
-
- interrupt_post_injection(v, highest_vector, intr_type);
- return;
-}
-
-void vmx_do_resume(struct vcpu *v)
-{
- struct vmx_virpit *vpit = &(v->domain->arch.vmx_platform.vmx_pit);
- vmx_stts();
-
- if (event_pending(v)) {
- vmx_check_events(v);
-
- if (test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags))
- vmx_wait_io();
- }
- /* pick up the elapsed PIT ticks and re-enable pit_timer */
- if ( vpit->first_injected ) {
- pickup_deactive_ticks(vpit);
- }
- set_tsc_shift(v,vpit);
-
- /* We can't resume the guest if we're waiting on I/O */
- ASSERT(!test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags));
-}
-
-#endif /* CONFIG_VMX */
-
/*
* Local variables:
* mode: C
diff --git a/xen/arch/x86/vmx_platform.c b/xen/arch/x86/hvm/platform.c
index 45d1e0052b..4a2e0c851c 100644
--- a/xen/arch/x86/vmx_platform.c
+++ b/xen/arch/x86/hvm/platform.c
@@ -1,6 +1,8 @@
/*
- * vmx_platform.c: handling x86 platform related MMIO instructions
+ * platform.c: handling x86 platform related MMIO instructions
+ *
* Copyright (c) 2004, Intel Corporation.
+ * 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,
@@ -14,7 +16,6 @@
* 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 <xen/config.h>
@@ -25,8 +26,10 @@
#include <asm/page.h>
#include <xen/event.h>
#include <xen/trace.h>
-#include <asm/vmx.h>
-#include <asm/vmx_platform.h>
+#include <xen/sched.h>
+#include <asm/regs.h>
+#include <asm/hvm/hvm.h>
+#include <asm/hvm/support.h>
#include <public/hvm/ioreq.h>
#include <xen/lib.h>
@@ -35,23 +38,13 @@
#if CONFIG_PAGING_LEVELS >= 3
#include <asm/shadow_64.h>
#endif
-#ifdef CONFIG_VMX
#define DECODE_success 1
#define DECODE_failure 0
-#if defined (__x86_64__)
-void store_cpu_user_regs(struct cpu_user_regs *regs)
-{
- __vmread(GUEST_SS_SELECTOR, &regs->ss);
- __vmread(GUEST_RSP, &regs->rsp);
- __vmread(GUEST_RFLAGS, &regs->rflags);
- __vmread(GUEST_CS_SELECTOR, &regs->cs);
- __vmread(GUEST_DS_SELECTOR, &regs->ds);
- __vmread(GUEST_ES_SELECTOR, &regs->es);
- __vmread(GUEST_RIP, &regs->rip);
-}
+extern long evtchn_send(int lport);
+#if defined (__x86_64__)
static inline long __get_reg_value(unsigned long reg, int size)
{
switch(size) {
@@ -119,17 +112,6 @@ long get_reg_value(int size, int index, int seg, struct cpu_user_regs *regs)
}
}
#elif defined (__i386__)
-void store_cpu_user_regs(struct cpu_user_regs *regs)
-{
- __vmread(GUEST_SS_SELECTOR, &regs->ss);
- __vmread(GUEST_RSP, &regs->esp);
- __vmread(GUEST_RFLAGS, &regs->eflags);
- __vmread(GUEST_CS_SELECTOR, &regs->cs);
- __vmread(GUEST_DS_SELECTOR, &regs->ds);
- __vmread(GUEST_ES_SELECTOR, &regs->es);
- __vmread(GUEST_RIP, &regs->eip);
-}
-
static inline long __get_reg_value(unsigned long reg, int size)
{
switch(size) {
@@ -214,8 +196,6 @@ static inline unsigned char *check_prefix(unsigned char *inst,
thread_inst->op_size = WORD;
break;
case 0x67:
- printf("Error: Not handling 0x67 (yet)\n");
- domain_crash_synchronous();
break;
default:
return inst;
@@ -366,7 +346,7 @@ static int reg_mem(unsigned char size, unsigned char *opcode,
return DECODE_success;
}
-static int vmx_decode(int vm86, unsigned char *opcode, struct instruction *instr)
+static int hvm_decode(int realmode, unsigned char *opcode, struct instruction *instr)
{
unsigned char size_reg = 0;
unsigned char rex = 0;
@@ -376,7 +356,7 @@ static int vmx_decode(int vm86, unsigned char *opcode, struct instruction *instr
opcode = check_prefix(opcode, instr, &rex);
- if (vm86) { /* meaning is reversed */
+ if (realmode) { /* meaning is reversed */
if (instr->op_size == WORD)
instr->op_size = LONG;
else if (instr->op_size == LONG)
@@ -437,7 +417,7 @@ static int vmx_decode(int vm86, unsigned char *opcode, struct instruction *instr
}
instr->operand[0] = mk_operand(size_reg, 0, 0, IMMEDIATE);
- instr->immediate = get_immediate(vm86, opcode+1, instr->op_size);
+ instr->immediate = get_immediate(realmode, opcode+1, instr->op_size);
instr->operand[1] = mk_operand(size_reg, 0, 0, MEMORY);
switch (ins_subtype) {
@@ -531,7 +511,7 @@ static int vmx_decode(int vm86, unsigned char *opcode, struct instruction *instr
instr->op_size = BYTE;
instr->operand[0] = mk_operand(instr->op_size, 0, 0, IMMEDIATE);
- instr->immediate = get_immediate(vm86, opcode+1, instr->op_size);
+ instr->immediate = get_immediate(realmode, opcode+1, instr->op_size);
instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY);
return DECODE_success;
@@ -544,7 +524,7 @@ static int vmx_decode(int vm86, unsigned char *opcode, struct instruction *instr
GET_OP_SIZE_FOR_NONEBYTE(instr->op_size);
instr->operand[0] = mk_operand(instr->op_size, 0, 0, IMMEDIATE);
- instr->immediate = get_immediate(vm86, opcode+1, instr->op_size);
+ instr->immediate = get_immediate(realmode, opcode+1, instr->op_size);
instr->operand[1] = mk_operand(instr->op_size, 0, 0, MEMORY);
return DECODE_success;
@@ -565,7 +545,7 @@ static int vmx_decode(int vm86, unsigned char *opcode, struct instruction *instr
}
instr->operand[0] = mk_operand(size_reg, 0, 0, IMMEDIATE);
- instr->immediate = get_immediate(vm86, opcode+1, instr->op_size);
+ instr->immediate = get_immediate(realmode, opcode+1, instr->op_size);
instr->operand[1] = mk_operand(size_reg, 0, 0, MEMORY);
return DECODE_success;
@@ -634,11 +614,60 @@ int inst_copy_from_guest(unsigned char *buf, unsigned long guest_eip, int inst_l
{
if (inst_len > MAX_INST_LEN || inst_len <= 0)
return 0;
- if (!vmx_copy(buf, guest_eip, inst_len, VMX_COPY_IN))
+ if (!hvm_copy(buf, guest_eip, inst_len, HVM_COPY_IN))
return 0;
return inst_len;
}
+void send_pio_req(struct cpu_user_regs *regs, unsigned long port,
+ unsigned long count, int size, long value, int dir, int pvalid)
+{
+ struct vcpu *v = current;
+ vcpu_iodata_t *vio;
+ ioreq_t *p;
+
+ vio = get_vio(v->domain, v->vcpu_id);
+ if (vio == NULL) {
+ printk("bad shared page: %lx\n", (unsigned long) vio);
+ domain_crash_synchronous();
+ }
+
+ if (test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags)) {
+ printf("HVM I/O has not yet completed\n");
+ domain_crash_synchronous();
+ }
+ set_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags);
+
+ p = &vio->vp_ioreq;
+ p->dir = dir;
+ p->pdata_valid = pvalid;
+
+ p->type = IOREQ_TYPE_PIO;
+ p->size = size;
+ p->addr = port;
+ p->count = count;
+ p->df = regs->eflags & EF_DF ? 1 : 0;
+
+ if (pvalid) {
+ if (hvm_paging_enabled(current))
+ p->u.pdata = (void *) gva_to_gpa(value);
+ else
+ p->u.pdata = (void *) value; /* guest VA == guest PA */
+ } else
+ p->u.data = value;
+
+ if (hvm_portio_intercept(p)) {
+ p->state = STATE_IORESP_READY;
+ hvm_io_assist(v);
+ return;
+ }
+
+ p->state = STATE_IOREQ_READY;
+
+ evtchn_send(iopacket_port(v->domain));
+ hvm_wait_io();
+}
+
void send_mmio_req(unsigned char type, unsigned long gpa,
unsigned long count, int size, long value, int dir, int pvalid)
{
@@ -648,7 +677,7 @@ void send_mmio_req(unsigned char type, unsigned long gpa,
struct cpu_user_regs *regs;
extern long evtchn_send(int lport);
- regs = current->arch.arch_vmx.mmio_op.inst_decoder_regs;
+ regs = current->arch.hvm_vcpu.mmio_op.inst_decoder_regs;
vio = get_vio(v->domain, v->vcpu_id);
if (vio == NULL) {
@@ -658,12 +687,12 @@ void send_mmio_req(unsigned char type, unsigned long gpa,
p = &vio->vp_ioreq;
- if (test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags)) {
- printf("VMX I/O has not yet completed\n");
+ if (test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags)) {
+ printf("HVM I/O has not yet completed\n");
domain_crash_synchronous();
}
- set_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags);
+ set_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags);
p->dir = dir;
p->pdata_valid = pvalid;
@@ -674,23 +703,23 @@ void send_mmio_req(unsigned char type, unsigned long gpa,
p->df = regs->eflags & EF_DF ? 1 : 0;
if (pvalid) {
- if (vmx_paging_enabled(current))
+ if (hvm_paging_enabled(v))
p->u.pdata = (void *) gva_to_gpa(value);
else
p->u.pdata = (void *) value; /* guest VA == guest PA */
} else
p->u.data = value;
- if (vmx_mmio_intercept(p)){
+ if (hvm_mmio_intercept(p)){
p->state = STATE_IORESP_READY;
- vmx_io_assist(v);
+ hvm_io_assist(v);
return;
}
p->state = STATE_IOREQ_READY;
evtchn_send(iopacket_port(v->domain));
- vmx_wait_io();
+ hvm_wait_io();
}
static void mmio_operands(int type, unsigned long gpa, struct instruction *inst,
@@ -727,7 +756,7 @@ static void mmio_operands(int type, unsigned long gpa, struct instruction *inst,
}
#define GET_REPEAT_COUNT() \
- (mmio_inst.flags & REPZ ? (vm86 ? regs->ecx & 0xFFFF : regs->ecx) : 1)
+ (mmio_inst.flags & REPZ ? (realmode ? regs->ecx & 0xFFFF : regs->ecx) : 1)
void handle_mmio(unsigned long va, unsigned long gpa)
{
@@ -736,17 +765,21 @@ void handle_mmio(unsigned long va, unsigned long gpa)
struct cpu_user_regs *regs;
struct instruction mmio_inst;
unsigned char inst[MAX_INST_LEN];
- int i, vm86, ret;
+ int i, realmode, ret;
+ struct vcpu *v = current;
- mmio_opp = &current->arch.arch_vmx.mmio_op;
+ mmio_opp = &v->arch.hvm_vcpu.mmio_op;
regs = mmio_opp->inst_decoder_regs;
- store_cpu_user_regs(regs);
+ hvm_store_cpu_guest_regs(v, regs);
- __vmread(VM_EXIT_INSTRUCTION_LEN, &inst_len);
+ if ((inst_len = hvm_instruction_length(v)) <= 0) {
+ printf("handle_mmio: failed to get instruction length\n");
+ domain_crash_synchronous();
+ }
- vm86 = regs->eflags & X86_EFLAGS_VM;
- if (vm86)
+ realmode = hvm_realmode(v);
+ if (realmode)
inst_addr = (regs->cs << 4) + regs->eip;
else
inst_addr = regs->eip;
@@ -754,13 +787,14 @@ void handle_mmio(unsigned long va, unsigned long gpa)
memset(inst, 0, MAX_INST_LEN);
ret = inst_copy_from_guest(inst, inst_addr, inst_len);
if (ret != inst_len) {
- printf("handle_mmio - EXIT: get guest instruction fault\n");
+ printf("handle_mmio: failed to copy instruction\n");
domain_crash_synchronous();
}
init_instruction(&mmio_inst);
- if (vmx_decode(vm86, inst, &mmio_inst) == DECODE_failure) {
+ if (hvm_decode(realmode, inst, &mmio_inst) == DECODE_failure) {
+ printf("handle_mmio: failed to decode instruction\n");
printf("mmio opcode: va 0x%lx, gpa 0x%lx, len %ld:",
va, gpa, inst_len);
for (i = 0; i < inst_len; i++)
@@ -785,7 +819,7 @@ void handle_mmio(unsigned long va, unsigned long gpa)
int dir;
/* determine non-MMIO address */
- if (vm86) {
+ if (realmode) {
if (((regs->es << 4) + (regs->edi & 0xFFFF)) == va) {
dir = IOREQ_WRITE;
addr = (regs->ds << 4) + (regs->esi & 0xFFFF);
@@ -824,7 +858,7 @@ void handle_mmio(unsigned long va, unsigned long gpa)
regs->eip -= inst_len; /* do not advance %eip */
if (dir == IOREQ_WRITE)
- vmx_copy(&value, addr, size, VMX_COPY_IN);
+ hvm_copy(&value, addr, size, HVM_COPY_IN);
send_mmio_req(IOREQ_TYPE_COPY, gpa, 1, size, value, dir, 0);
} else {
if ((addr & PAGE_MASK) != ((addr + count * size - 1) & PAGE_MASK)) {
@@ -906,8 +940,6 @@ void handle_mmio(unsigned long va, unsigned long gpa)
}
}
-#endif /* CONFIG_VMX */
-
/*
* Local variables:
* mode: C
diff --git a/xen/arch/x86/hvm/svm/emulate.c b/xen/arch/x86/hvm/svm/emulate.c
new file mode 100644
index 0000000000..32be10f28c
--- /dev/null
+++ b/xen/arch/x86/hvm/svm/emulate.c
@@ -0,0 +1,517 @@
+/*
+ * emulate.c: handling SVM emulate instructions help.
+ * Copyright (c) 2005 AMD 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 <xen/config.h>
+#include <xen/init.h>
+#include <xen/lib.h>
+#include <xen/trace.h>
+#include <asm/msr.h>
+#include <asm/hvm/hvm.h>
+#include <asm/hvm/support.h>
+#include <asm/hvm/svm/vmcb.h>
+#include <asm/hvm/svm/emulate.h>
+
+#ifdef CONFIG_SVM
+
+extern int inst_copy_from_guest(unsigned char *buf, unsigned long guest_eip,
+ int inst_len);
+
+#define REX_PREFIX_BASE 0x40
+#define REX_X 0x02
+#define REX_W 0x08
+#define REX_R 0x04
+#define REX_B 0x01
+
+#define IS_REX_PREFIX(prefix) ((prefix & 0xf0) == REX_PREFIX_BASE)
+
+#define DECODE_MODRM_MOD(modrm) ((modrm & 0xC0) >> 6)
+
+#define DECODE_MODRM_REG(prefix, modrm) \
+ ((prefix & REX_R) && IS_REX_PREFIX(prefix)) \
+ ? (0x08 | ((modrm >> 3) & 0x07)) : ((modrm >> 3) & 0x07)
+
+#define DECODE_MODRM_RM(prefix, modrm) \
+ ((prefix & REX_B) && IS_REX_PREFIX(prefix)) \
+ ? (0x08 | (modrm & 0x07)) : (modrm & 0x07)
+
+#define DECODE_SIB_SCALE(sib) DECODE_MODRM_MOD(sib)
+
+#define DECODE_SIB_INDEX(prefix, sib) \
+ ((prefix & REX_X) && IS_REX_PREFIX(prefix)) \
+ ? (0x08 | ((sib >> 3) & 0x07)) : ((sib >> 3) & 0x07)
+
+#define DECODE_SIB_BASE(prefix, sib) DECODE_MODRM_RM(prefix, sib)
+
+
+static inline unsigned long DECODE_GPR_VALUE(struct vmcb_struct *vmcb,
+ struct cpu_user_regs *regs, u8 gpr_rm)
+{
+ unsigned long value;
+ switch (gpr_rm)
+ {
+ case 0x0:
+ value = regs->eax;
+ break;
+ case 0x1:
+ value = regs->ecx;
+ break;
+ case 0x2:
+ value = regs->edx;
+ break;
+ case 0x3:
+ value = regs->ebx;
+ break;
+ case 0x4:
+ value = (unsigned long)vmcb->rsp;
+ case 0x5:
+ value = regs->ebp;
+ break;
+ case 0x6:
+ value = regs->esi;
+ break;
+ case 0x7:
+ value = regs->edi;
+ break;
+#if X86_64
+ case 0x8:
+ value = regs->r8;
+ break;
+ case 0x9:
+ value = regs->r9;
+ break;
+ case 0xA:
+ value = regs->r10;
+ break;
+ case 0xB:
+ value = regs->r11;
+ break;
+ case 0xC:
+ value = regs->r12;
+ break;
+ case 0xD:
+ value = regs->r13;
+ break;
+ case 0xE:
+ value = regs->r14;
+ break;
+ case 0xF:
+ value = regs->r15;
+ break;
+#endif
+ default:
+ printk("Invlaid gpr_rm = %d\n", gpr_rm);
+ ASSERT(0);
+ value = (unsigned long)-1; /* error retrun */
+ }
+ return value;
+}
+
+
+#define CHECK_LENGTH64(num) \
+ if (num > length) \
+ { \
+ *size = 0; \
+ return (unsigned long) -1; \
+ }
+
+#if 0
+/*
+ * hv_is_canonical - checks if the given address is canonical
+ */
+static inline u64 hv_is_canonical(u64 addr)
+{
+ u64 bits = addr & (u64)0xffff800000000000;
+ return (u64)((bits == (u64)0xffff800000000000) || (bits == (u64)0x0));
+}
+#endif
+
+#define modrm operand [0]
+
+#define sib operand [1]
+
+
+unsigned long get_effective_addr_modrm64(struct vmcb_struct *vmcb,
+ struct cpu_user_regs *regs, const u8 prefix, const u8 *operand,
+ u8 *size)
+{
+ unsigned long effective_addr = (unsigned long) -1;
+ u8 length, modrm_mod, modrm_rm;
+ u32 disp = 0;
+
+ HVM_DBG_LOG(DBG_LEVEL_1, "get_effective_addr_modrm64(): prefix = %x, "
+ "length = %d, operand[0,1] = %x %x.\n", prefix, *size, operand [0],
+ operand [1]);
+
+ if ((NULL == size) || (NULL == operand) || (1 > *size))
+ {
+ *size = 0;
+ return effective_addr;
+ }
+
+ modrm_mod = DECODE_MODRM_MOD(modrm);
+ modrm_rm = DECODE_MODRM_RM(prefix, modrm);
+
+ length = *size;
+ *size = 1;
+ switch (modrm_rm)
+ {
+ case 0x4:
+#if __x86_64__
+ case 0xC:
+#endif
+ if (modrm_mod < 3)
+ {
+ *size = length;
+ effective_addr = get_effective_addr_sib(vmcb, regs, prefix, operand, size);
+ }
+ else
+ {
+ effective_addr = DECODE_GPR_VALUE(vmcb, regs, modrm_rm);
+ }
+ break;
+
+ case 0x5:
+ if (0 < modrm_mod)
+ {
+ effective_addr = regs->ebp;
+ *size = 1;
+ break;
+ }
+
+ CHECK_LENGTH64(*size + (u8)sizeof(u32));
+
+ memcpy (&disp, operand + 1, sizeof (u32));
+ *size += sizeof (u32);
+ if (vmcb->cs.attributes.fields.l) // 64-bit mode
+ return vmcb->rip + disp;
+ else
+ return disp;
+
+#if __x86_64__
+ case 0xD:
+ if (0 < modrm_mod)
+ {
+ *size = 1;
+ effective_addr = regs->r13;
+ break;
+ }
+
+ CHECK_LENGTH64(*size + (u8)sizeof(u32));
+
+ memcpy (&disp, operand + 1, sizeof (u32));
+ *size += sizeof (u32);
+
+ /* 64-bit mode */
+ if (vmcb->cs.attributes.fields.l)
+ return vmcb->rip + disp;
+ else
+ return disp;
+
+#endif
+ default:
+ effective_addr = DECODE_GPR_VALUE(vmcb, regs, modrm_rm);
+
+ }
+
+ if (3 > modrm_mod)
+ {
+ if (1 == modrm_mod )
+ {
+ CHECK_LENGTH64(*size + (u8)sizeof(u8));
+ disp = sib;
+ *size += sizeof (u8);
+ }
+ else if (2 == modrm_mod )
+ {
+ CHECK_LENGTH64(*size + sizeof (u32));
+ memcpy (&disp, operand + 1, sizeof (u32));
+ *size += sizeof (u32);
+ }
+
+ effective_addr += disp;
+ }
+
+ return effective_addr;
+}
+
+
+unsigned long get_effective_addr_sib(struct vmcb_struct *vmcb,
+ struct cpu_user_regs *regs, const u8 prefix, const u8 *operand,
+ u8 *size)
+{
+ unsigned long base, effective_addr = (unsigned long)-1;
+ u8 sib_scale, sib_idx, sib_base, length;
+ u32 disp = 0;
+
+ if (NULL == size || NULL == operand || 2 > *size)
+ {
+ *size = 0;
+ return effective_addr;
+ }
+
+ sib_scale = DECODE_SIB_SCALE(sib);
+ sib_idx = DECODE_SIB_INDEX(prefix, sib);
+ sib_base = DECODE_SIB_BASE(prefix, sib);
+
+ base = DECODE_GPR_VALUE(vmcb, regs, sib_base);
+
+ if ((unsigned long)-1 == base)
+ {
+ /*
+ * Surely this is wrong. base should be allowed to be -1, even if
+ * it's not the usual case...
+ */
+ *size = 0;
+ return base;
+ }
+
+ length = *size;
+ *size = 2;
+ if (0x5 == (sib_base & 0x5))
+ {
+ switch (DECODE_MODRM_MOD(modrm))
+ {
+ case 0:
+ CHECK_LENGTH64(*size + (u8)sizeof(u32));
+ memcpy (&disp, operand + 2, sizeof(u32));
+ *size += sizeof(u32);
+ base = disp;
+ break;
+
+ case 1:
+ CHECK_LENGTH64(*size + (u8)sizeof (u8));
+ *size += sizeof(u8);
+ base += operand [2];
+ break;
+
+ case 2:
+ CHECK_LENGTH64(*size + (u8)sizeof (u32));
+ memcpy(&disp, operand + 2, sizeof(u32));
+ *size += sizeof(u32);
+ base += disp;
+ }
+ }
+
+ if (4 == sib_idx)
+ return base;
+
+ effective_addr = DECODE_GPR_VALUE(vmcb, regs, sib_idx);
+
+ effective_addr <<= sib_scale;
+
+ return (effective_addr + base);
+}
+
+
+/* Get the register/mode number of src register in ModRM register. */
+unsigned int decode_dest_reg(u8 m)
+{
+#if __x86_64__
+ ASSERT(0); /* Need to adjust for REX prefix if applicable */
+#endif
+ return (m >> 3) & 7;
+}
+
+unsigned int decode_src_reg(u8 m)
+{
+#if __x86_64__
+ ASSERT(0); /* Need to adjust for REX prefix if applicable */
+#endif
+ return m & 7;
+}
+
+
+unsigned long svm_rip2pointer(struct vmcb_struct *vmcb)
+{
+ /*
+ * The following is subtle. Intuitively this code would be something like:
+ *
+ * if (16bit) addr = (cs << 4) + rip; else addr = rip;
+ *
+ * However, this code doesn't work for code executing after CR0.PE=0,
+ * but before the %cs has been updated. We don't get signalled when
+ * %cs is update, but fortunately, base contain the valid base address
+ * no matter what kind of addressing is used.
+ */
+ return vmcb->cs.base + vmcb->rip;
+}
+
+
+#define MAKE_INSTR(nm, ...) static const u8 OPCODE_##nm[] = { __VA_ARGS__ }
+
+/*
+ * Here's how it works:
+ * First byte: Length.
+ * Following bytes: Opcode bytes.
+ * Special case: Last byte, if zero, doesn't need to match.
+ */
+MAKE_INSTR(INVD, 2, 0x0f, 0x08);
+MAKE_INSTR(CPUID, 2, 0x0f, 0xa2);
+MAKE_INSTR(RDMSR, 2, 0x0f, 0x32);
+MAKE_INSTR(WRMSR, 2, 0x0f, 0x30);
+MAKE_INSTR(RDTSC, 2, 0x0f, 0x31);
+MAKE_INSTR(RDTSCP, 3, 0x0f, 0x01, 0xf9);
+MAKE_INSTR(CLI, 1, 0xfa);
+MAKE_INSTR(STI, 1, 0xfb);
+MAKE_INSTR(RDPMC, 2, 0x0f, 0x33);
+MAKE_INSTR(CLGI, 3, 0x0f, 0x01, 0xdd);
+MAKE_INSTR(STGI, 3, 0x0f, 0x01, 0xdc);
+MAKE_INSTR(VMRUN, 3, 0x0f, 0x01, 0xd8);
+MAKE_INSTR(VMLOAD, 3, 0x0f, 0x01, 0xda);
+MAKE_INSTR(VMSAVE, 3, 0x0f, 0x01, 0xdb);
+MAKE_INSTR(VMCALL, 3, 0x0f, 0x01, 0xd9);
+MAKE_INSTR(PAUSE, 2, 0xf3, 0x90);
+MAKE_INSTR(SKINIT, 3, 0x0f, 0x01, 0xde);
+MAKE_INSTR(MOV2CR, 3, 0x0f, 0x22, 0x00);
+MAKE_INSTR(MOVCR2, 3, 0x0f, 0x20, 0x00);
+MAKE_INSTR(MOV2DR, 3, 0x0f, 0x23, 0x00);
+MAKE_INSTR(MOVDR2, 3, 0x0f, 0x21, 0x00);
+MAKE_INSTR(PUSHF, 1, 0x9c);
+MAKE_INSTR(POPF, 1, 0x9d);
+MAKE_INSTR(RSM, 2, 0x0f, 0xaa);
+MAKE_INSTR(INVLPG, 3, 0x0f, 0x01, 0x00);
+MAKE_INSTR(INVLPGA,3, 0x0f, 0x01, 0xdf);
+MAKE_INSTR(HLT, 1, 0xf4);
+MAKE_INSTR(CLTS, 2, 0x0f, 0x06);
+MAKE_INSTR(LMSW, 3, 0x0f, 0x01, 0x00);
+MAKE_INSTR(SMSW, 3, 0x0f, 0x01, 0x00);
+
+static const u8 *opc_bytes[INSTR_MAX_COUNT] =
+{
+ [INSTR_INVD] = OPCODE_INVD,
+ [INSTR_CPUID] = OPCODE_CPUID,
+ [INSTR_RDMSR] = OPCODE_RDMSR,
+ [INSTR_WRMSR] = OPCODE_WRMSR,
+ [INSTR_RDTSC] = OPCODE_RDTSC,
+ [INSTR_RDTSCP] = OPCODE_RDTSCP,
+ [INSTR_CLI] = OPCODE_CLI,
+ [INSTR_STI] = OPCODE_STI,
+ [INSTR_RDPMC] = OPCODE_RDPMC,
+ [INSTR_CLGI] = OPCODE_CLGI,
+ [INSTR_STGI] = OPCODE_STGI,
+ [INSTR_VMRUN] = OPCODE_VMRUN,
+ [INSTR_VMLOAD] = OPCODE_VMLOAD,
+ [INSTR_VMSAVE] = OPCODE_VMSAVE,
+ [INSTR_VMCALL] = OPCODE_VMCALL,
+ [INSTR_PAUSE] = OPCODE_PAUSE,
+ [INSTR_SKINIT] = OPCODE_SKINIT,
+ [INSTR_MOV2CR] = OPCODE_MOV2CR,
+ [INSTR_MOVCR2] = OPCODE_MOVCR2,
+ [INSTR_MOV2DR] = OPCODE_MOV2DR,
+ [INSTR_MOVDR2] = OPCODE_MOVDR2,
+ [INSTR_PUSHF] = OPCODE_PUSHF,
+ [INSTR_POPF] = OPCODE_POPF,
+ [INSTR_RSM] = OPCODE_RSM,
+ [INSTR_INVLPG] = OPCODE_INVLPG,
+ [INSTR_INVLPGA]= OPCODE_INVLPGA,
+ [INSTR_CLTS] = OPCODE_CLTS,
+ [INSTR_HLT] = OPCODE_HLT,
+ [INSTR_LMSW] = OPCODE_LMSW,
+ [INSTR_SMSW] = OPCODE_SMSW
+};
+
+/*
+ * Intel has a vmcs entry to give the instruction length. AMD doesn't. So we
+ * have to do a little bit of work to find out...
+ *
+ * The caller can either pass a NULL pointer to the guest_eip_buf, or a pointer
+ * to enough bytes to satisfy the instruction including prefix bytes.
+ */
+unsigned int __get_instruction_length_from_list(struct vmcb_struct *vmcb,
+ enum instruction_index *list, unsigned int list_count,
+ u8 *guest_eip_buf, enum instruction_index *match)
+{
+ unsigned int inst_len = 0;
+ unsigned int i;
+ unsigned int j;
+ int found = 0;
+ enum instruction_index instr = 0;
+ u8 buffer[MAX_INST_LEN];
+ u8 *buf;
+ const u8 *opcode = NULL;
+
+ if (guest_eip_buf)
+ {
+ buf = guest_eip_buf;
+ }
+ else
+ {
+ inst_copy_from_guest(buffer, svm_rip2pointer(vmcb), MAX_INST_LEN);
+ buf = buffer;
+ }
+
+ for (j = 0; j < list_count; j++)
+ {
+ instr = list[j];
+ opcode = opc_bytes[instr];
+ ASSERT(opcode);
+
+ while (inst_len < MAX_INST_LEN &&
+ is_prefix(buf[inst_len]) &&
+ !is_prefix(opcode[1]))
+ inst_len++;
+
+ ASSERT(opcode[0] <= 15); /* Make sure the table is correct. */
+ found = 1;
+
+ for (i = 0; i < opcode[0]; i++)
+ {
+ /* If the last byte is zero, we just accept it without checking */
+ if (i == opcode[0]-1 && opcode[i+1] == 0)
+ break;
+
+ if (buf[inst_len+i] != opcode[i+1])
+ {
+ found = 0;
+ break;
+ }
+ }
+
+ if (found)
+ break;
+ }
+
+ /* It's a match */
+ if (found)
+ {
+ inst_len += opcode[0];
+
+ ASSERT(inst_len <= MAX_INST_LEN);
+
+ if (match)
+ *match = instr;
+
+ return inst_len;
+ }
+
+ printk("%s: Mismatch between expected and actual instruction bytes: "
+ "eip = %lx\n", __func__, (unsigned long)vmcb->rip);
+ return 0;
+}
+#endif /* CONFIG_SVM */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/x86/hvm/svm/instrlen.c b/xen/arch/x86/hvm/svm/instrlen.c
new file mode 100644
index 0000000000..526ee7ac41
--- /dev/null
+++ b/xen/arch/x86/hvm/svm/instrlen.c
@@ -0,0 +1,435 @@
+/*
+ * instrlen.c - calculates the instruction length for all operating modes
+ *
+ * Travis Betak, travis.betak@amd.com
+ * Copyright (c) 2005 AMD
+ *
+ * Essentially a very, very stripped version of Keir Fraser's work in
+ * x86_emulate.c. Used primarily for MMIO.
+ */
+
+/*
+ * TODO: the way in which we use svm_instrlen is very inefficient as is now
+ * stands. it will be worth while to return the actual instruction buffer
+ * along with the instruction length since we are getting the instruction length
+ * so we know how much of the buffer we need to fetch.
+ */
+
+#include <xen/config.h>
+#include <xen/types.h>
+#include <xen/lib.h>
+#include <xen/mm.h>
+#include <asm/regs.h>
+#define DPRINTF DPRINTK
+#include <asm-x86/x86_emulate.h>
+
+#ifdef CONFIG_SVM
+/*
+ * Opcode effective-address decode tables.
+ * Note that we only emulate instructions that have at least one memory
+ * operand (excluding implicit stack references). We assume that stack
+ * references and instruction fetches will never occur in special memory
+ * areas that require emulation. So, for example, 'mov <imm>,<reg>' need
+ * not be handled.
+ */
+
+/* Operand sizes: 8-bit operands or specified/overridden size. */
+#define BYTE_OP (1<<0) /* 8-bit operands. */
+/* Destination operand type. */
+#define IMPLICIT_OPS (1<<1) /* Implicit in opcode. No generic decode. */
+#define DST_REG (2<<1) /* Register operand. */
+#define DST_MEM (3<<1) /* Memory operand. */
+#define DST_MASK (3<<1)
+/* Source operand type. */
+#define SRC_NONE (0<<3) /* No source operand. */
+#define SRC_IMPLICIT (0<<3) /* Source operand is implicit in the opcode. */
+#define SRC_REG (1<<3) /* Register operand. */
+#define SRC_MEM (2<<3) /* Memory operand. */
+#define SRC_IMM (3<<3) /* Immediate operand. */
+#define SRC_IMMBYTE (4<<3) /* 8-bit sign-extended immediate operand. */
+#define SRC_MASK (7<<3)
+/* Generic MODRM decode. */
+#define MODRM (1<<6)
+/* Destination is only written; never read. */
+#define Mov (1<<7)
+
+static u8 opcode_table[256] = {
+ /* 0x00 - 0x07 */
+ BYTE_OP | DST_MEM | SRC_REG | MODRM, DST_MEM | SRC_REG | MODRM,
+ BYTE_OP | DST_REG | SRC_MEM | MODRM, DST_REG | SRC_MEM | MODRM,
+ 0, 0, 0, 0,
+ /* 0x08 - 0x0F */
+ BYTE_OP | DST_MEM | SRC_REG | MODRM, DST_MEM | SRC_REG | MODRM,
+ BYTE_OP | DST_REG | SRC_MEM | MODRM, DST_REG | SRC_MEM | MODRM,
+ 0, 0, 0, 0,
+ /* 0x10 - 0x17 */
+ BYTE_OP | DST_MEM | SRC_REG | MODRM, DST_MEM | SRC_REG | MODRM,
+ BYTE_OP | DST_REG | SRC_MEM | MODRM, DST_REG | SRC_MEM | MODRM,
+ 0, 0, 0, 0,
+ /* 0x18 - 0x1F */
+ BYTE_OP | DST_MEM | SRC_REG | MODRM, DST_MEM | SRC_REG | MODRM,
+ BYTE_OP | DST_REG | SRC_MEM | MODRM, DST_REG | SRC_MEM | MODRM,
+ 0, 0, 0, 0,
+ /* 0x20 - 0x27 */
+ BYTE_OP | DST_MEM | SRC_REG | MODRM, DST_MEM | SRC_REG | MODRM,
+ BYTE_OP | DST_REG | SRC_MEM | MODRM, DST_REG | SRC_MEM | MODRM,
+ 0, 0, 0, 0,
+ /* 0x28 - 0x2F */
+ BYTE_OP | DST_MEM | SRC_REG | MODRM, DST_MEM | SRC_REG | MODRM,
+ BYTE_OP | DST_REG | SRC_MEM | MODRM, DST_REG | SRC_MEM | MODRM,
+ 0, 0, 0, 0,
+ /* 0x30 - 0x37 */
+ BYTE_OP | DST_MEM | SRC_REG | MODRM, DST_MEM | SRC_REG | MODRM,
+ BYTE_OP | DST_REG | SRC_MEM | MODRM, DST_REG | SRC_MEM | MODRM,
+ 0, 0, 0, 0,
+ /* 0x38 - 0x3F */
+ BYTE_OP | DST_MEM | SRC_REG | MODRM, DST_MEM | SRC_REG | MODRM,
+ BYTE_OP | DST_REG | SRC_MEM | MODRM, DST_REG | SRC_MEM | MODRM,
+ 0, 0, 0, 0,
+ /* 0x40 - 0x4F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0x50 - 0x5F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0x60 - 0x6F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0x70 - 0x7F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0x80 - 0x87 */
+ BYTE_OP | DST_MEM | SRC_IMM | MODRM, DST_MEM | SRC_IMM | MODRM,
+ BYTE_OP | DST_MEM | SRC_IMM | MODRM, DST_MEM | SRC_IMMBYTE | MODRM,
+ BYTE_OP | DST_MEM | SRC_REG | MODRM, DST_MEM | SRC_REG | MODRM,
+ BYTE_OP | DST_MEM | SRC_REG | MODRM, DST_MEM | SRC_REG | MODRM,
+ /* 0x88 - 0x8F */
+ BYTE_OP | DST_MEM | SRC_REG | MODRM, DST_MEM | SRC_REG | MODRM,
+ BYTE_OP | DST_REG | SRC_MEM | MODRM, DST_REG | SRC_MEM | MODRM,
+ 0, 0, 0, DST_MEM | SRC_NONE | MODRM | Mov,
+ /* 0x90 - 0x9F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0xA0 - 0xA7 */
+ BYTE_OP | DST_REG | SRC_MEM | Mov, DST_REG | SRC_MEM | Mov,
+ BYTE_OP | DST_MEM | SRC_REG | Mov, DST_MEM | SRC_REG | Mov,
+ BYTE_OP | IMPLICIT_OPS | Mov, IMPLICIT_OPS | Mov,
+ BYTE_OP | IMPLICIT_OPS, IMPLICIT_OPS,
+ /* 0xA8 - 0xAF */
+ 0, 0, BYTE_OP | IMPLICIT_OPS | Mov, IMPLICIT_OPS | Mov,
+ BYTE_OP | IMPLICIT_OPS | Mov, IMPLICIT_OPS | Mov,
+ BYTE_OP | IMPLICIT_OPS, IMPLICIT_OPS,
+ /* 0xB0 - 0xBF */
+ SRC_IMMBYTE, SRC_IMMBYTE, SRC_IMMBYTE, SRC_IMMBYTE,
+ SRC_IMMBYTE, SRC_IMMBYTE, SRC_IMMBYTE, SRC_IMMBYTE,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0xC0 - 0xC7 */
+ BYTE_OP | DST_MEM | SRC_IMM | MODRM, DST_MEM | SRC_IMMBYTE | MODRM, 0, 0,
+ 0, 0, BYTE_OP | DST_MEM | SRC_IMM | MODRM, DST_MEM | SRC_IMM | MODRM,
+ /* 0xC8 - 0xCF */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0xD0 - 0xD7 */
+ BYTE_OP | DST_MEM | SRC_IMPLICIT | MODRM, DST_MEM | SRC_IMPLICIT | MODRM,
+ BYTE_OP | DST_MEM | SRC_IMPLICIT | MODRM, DST_MEM | SRC_IMPLICIT | MODRM,
+ 0, 0, 0, 0,
+ /* 0xD8 - 0xDF */
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0xE0 - 0xEF */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0xF0 - 0xF7 */
+ 0, 0, 0, 0,
+ 0, 0, BYTE_OP | DST_MEM | SRC_NONE | MODRM, DST_MEM | SRC_NONE | MODRM,
+ /* 0xF8 - 0xFF */
+ 0, 0, 0, 0,
+ 0, 0, BYTE_OP | DST_MEM | SRC_NONE | MODRM, DST_MEM | SRC_NONE | MODRM
+};
+
+static u8 twobyte_table[256] = {
+ /* 0x00 - 0x0F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, IMPLICIT_OPS | MODRM, 0, 0,
+ /* 0x10 - 0x1F */
+ 0, 0, 0, 0, 0, 0, 0, 0, IMPLICIT_OPS | MODRM, 0, 0, 0, 0, 0, 0, 0,
+ /* 0x20 - 0x2F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0x30 - 0x3F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0x40 - 0x47 */
+ DST_REG | SRC_MEM | MODRM | Mov, DST_REG | SRC_MEM | MODRM | Mov,
+ DST_REG | SRC_MEM | MODRM | Mov, DST_REG | SRC_MEM | MODRM | Mov,
+ DST_REG | SRC_MEM | MODRM | Mov, DST_REG | SRC_MEM | MODRM | Mov,
+ DST_REG | SRC_MEM | MODRM | Mov, DST_REG | SRC_MEM | MODRM | Mov,
+ /* 0x48 - 0x4F */
+ DST_REG | SRC_MEM | MODRM | Mov, DST_REG | SRC_MEM | MODRM | Mov,
+ DST_REG | SRC_MEM | MODRM | Mov, DST_REG | SRC_MEM | MODRM | Mov,
+ DST_REG | SRC_MEM | MODRM | Mov, DST_REG | SRC_MEM | MODRM | Mov,
+ DST_REG | SRC_MEM | MODRM | Mov, DST_REG | SRC_MEM | MODRM | Mov,
+ /* 0x50 - 0x5F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0x60 - 0x6F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0x70 - 0x7F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0x80 - 0x8F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0x90 - 0x9F */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0xA0 - 0xA7 */
+ 0, 0, 0, DST_MEM | SRC_REG | MODRM, 0, 0, 0, 0,
+ /* 0xA8 - 0xAF */
+ 0, 0, 0, DST_MEM | SRC_REG | MODRM, 0, 0, 0, 0,
+ /* 0xB0 - 0xB7 */
+ BYTE_OP | DST_MEM | SRC_REG | MODRM, DST_MEM | SRC_REG | MODRM, 0,
+ DST_MEM | SRC_REG | MODRM,
+ 0, 0,
+ DST_REG | SRC_MEM | MODRM,
+ DST_REG | SRC_REG | MODRM,
+
+ /* 0xB8 - 0xBF */
+ 0, 0, DST_MEM | SRC_IMMBYTE | MODRM, DST_MEM | SRC_REG | MODRM, 0, 0, 0, 0,
+ /* 0xC0 - 0xCF */
+ 0, 0, 0, 0, 0, 0, 0, IMPLICIT_OPS | MODRM, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0xD0 - 0xDF */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0xE0 - 0xEF */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ /* 0xF0 - 0xFF */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+/* read from guest memory */
+extern int inst_copy_from_guest(unsigned char *buf, unsigned long eip,
+ int length);
+extern void svm_dump_inst(unsigned long eip);
+
+/*
+ * insn_fetch - fetch the next 1 to 4 bytes from instruction stream
+ *
+ * @_type: u8, u16, u32, s8, s16, or s32
+ * @_size: 1, 2, or 4 bytes
+ * @_eip: address to fetch from guest memory
+ * @_length: updated! increments the current instruction length counter by _size
+ *
+ * INTERNAL this is used internally by svm_instrlen to fetch the next byte,
+ * word, or dword from guest memory at location _eip. we currently use a local
+ * unsigned long as the storage buffer since the most bytes we're gonna get
+ * is limited to 4.
+ */
+#define insn_fetch(_type, _size, _eip, _length) \
+({ unsigned long _x; \
+ if ((rc = inst_copy_from_guest((unsigned char *)(&(_x)), \
+ (unsigned long)(_eip), _size)) \
+ != _size) \
+ goto done; \
+ (_eip) += (_size); \
+ (_length) += (_size); \
+ (_type)_x; \
+})
+
+/**
+ * get_instruction_length - returns the current instructions length
+ *
+ * @regs: guest register state
+ * @cr2: target address
+ * @ops: guest memory operations
+ * @mode: guest operating mode
+ *
+ * EXTERNAL this routine calculates the length of the current instruction
+ * pointed to by eip. The guest state is _not_ changed by this routine.
+ */
+unsigned long svm_instrlen(struct cpu_user_regs *regs, int mode)
+{
+ u8 b, d, twobyte = 0;
+ u8 modrm, modrm_mod = 0, modrm_reg = 0, modrm_rm = 0;
+ unsigned int op_bytes = (mode == 8) ? 4 : mode, ad_bytes = mode;
+ unsigned int i;
+ int rc = 0;
+ u32 length = 0;
+ u8 tmp;
+
+ /* Copy the registers so we don't alter the guest's present state */
+ volatile struct cpu_user_regs _regs = *regs;
+
+ /* Check for Real Mode */
+ if (mode == 2)
+ _regs.eip += (_regs.cs << 4);
+
+ /* Legacy prefix check */
+ for (i = 0; i < 8; i++) {
+ switch (b = insn_fetch(u8, 1, _regs.eip, length)) {
+ case 0x66: /* operand-size override */
+ op_bytes ^= 6; /* switch between 2/4 bytes */
+ break;
+ case 0x67: /* address-size override */
+ ad_bytes ^= (mode == 8) ? 12 : 6; /* 2/4/8 bytes */
+ break;
+ case 0x2e: /* CS override */
+ case 0x3e: /* DS override */
+ case 0x26: /* ES override */
+ case 0x64: /* FS override */
+ case 0x65: /* GS override */
+ case 0x36: /* SS override */
+ case 0xf0: /* LOCK */
+ case 0xf3: /* REP/REPE/REPZ */
+ case 0xf2: /* REPNE/REPNZ */
+ break;
+ default:
+ goto done_prefixes;
+ }
+ }
+
+done_prefixes:
+
+ /* REX prefix check */
+ if ((mode == 8) && ((b & 0xf0) == 0x40))
+ {
+ if (b & 8)
+ op_bytes = 8; /* REX.W */
+ modrm_reg = (b & 4) << 1; /* REX.R */
+ /* REX.B and REX.X do not need to be decoded. */
+ b = insn_fetch(u8, 1, _regs.eip, length);
+ }
+
+ /* Opcode byte(s). */
+ d = opcode_table[b];
+ if (d == 0)
+ {
+ /* Two-byte opcode? */
+ if (b == 0x0f) {
+ twobyte = 1;
+ b = insn_fetch(u8, 1, _regs.eip, length);
+ d = twobyte_table[b];
+ }
+
+ /* Unrecognised? */
+ if (d == 0)
+ goto cannot_emulate;
+ }
+
+ /* MODRM and SIB bytes. */
+ if (d & MODRM)
+ {
+ modrm = insn_fetch(u8, 1, _regs.eip, length);
+ modrm_mod |= (modrm & 0xc0) >> 6;
+ modrm_reg |= (modrm & 0x38) >> 3;
+ modrm_rm |= (modrm & 0x07);
+ switch (modrm_mod)
+ {
+ case 0:
+ if ((modrm_rm == 4) &&
+ (((insn_fetch(u8, 1, _regs.eip,
+ length)) & 7) == 5))
+ {
+ length += 4;
+ _regs.eip += 4; /* skip SIB.base disp32 */
+ }
+ else if (modrm_rm == 5)
+ {
+ length += 4;
+ _regs.eip += 4; /* skip disp32 */
+ }
+ break;
+ case 1:
+ if (modrm_rm == 4)
+ {
+ insn_fetch(u8, 1, _regs.eip, length);
+ }
+ length += 1;
+ _regs.eip += 1; /* skip disp8 */
+ break;
+ case 2:
+ if (modrm_rm == 4)
+ {
+ insn_fetch(u8, 1, _regs.eip, length);
+ }
+ length += 4;
+ _regs.eip += 4; /* skip disp32 */
+ break;
+ case 3:
+ DPRINTF("Cannot parse ModRM.mod == 3.\n");
+ goto cannot_emulate;
+ }
+ }
+
+ /* Decode and fetch the destination operand: register or memory. */
+ switch (d & DST_MASK)
+ {
+ case IMPLICIT_OPS:
+ /* Special instructions do their own operand decoding. */
+ goto done;
+ }
+
+ /* Decode and fetch the source operand: register, memory or immediate */
+ switch (d & SRC_MASK)
+ {
+ case SRC_IMM:
+ tmp = (d & BYTE_OP) ? 1 : op_bytes;
+ if (tmp == 8)
+ tmp = 4;
+ /* NB. Immediates are sign-extended as necessary. */
+ switch (tmp) {
+ case 1:
+ insn_fetch(s8, 1, _regs.eip, length);
+ break;
+ case 2:
+ insn_fetch(s16, 2, _regs.eip, length);
+ break;
+ case 4:
+ insn_fetch(s32, 4, _regs.eip, length);
+ break;
+ }
+ break;
+ case SRC_IMMBYTE:
+ insn_fetch(s8, 1, _regs.eip, length);
+ break;
+ }
+
+ if (twobyte)
+ goto done;
+
+ switch (b)
+ {
+ case 0xa0:
+ case 0xa1: /* mov */
+ length += ad_bytes;
+ _regs.eip += ad_bytes; /* skip src displacement */
+ break;
+ case 0xa2:
+ case 0xa3: /* mov */
+ length += ad_bytes;
+ _regs.eip += ad_bytes; /* skip dst displacement */
+ break;
+ case 0xf6:
+ case 0xf7: /* Grp3 */
+ switch (modrm_reg)
+ {
+ case 0:
+ case 1: /* test */
+ /*
+ * Special case in Grp3: test has an
+ * immediate source operand.
+ */
+ tmp = (d & BYTE_OP) ? 1 : op_bytes;
+ if (tmp == 8)
+ tmp = 4;
+ switch (tmp)
+ {
+ case 1:
+ insn_fetch(s8, 1, _regs.eip, length);
+ break;
+ case 2:
+ insn_fetch(s16, 2, _regs.eip, length);
+ break;
+ case 4:
+ insn_fetch(s32, 4, _regs.eip, length);
+ break;
+ }
+ goto done;
+ }
+ break;
+ }
+
+done:
+ return length;
+
+cannot_emulate:
+ DPRINTF("Cannot emulate %02x at address %x (eip %x, mode %d)\n",
+ b, _regs.eip, regs->eip, mode);
+ svm_dump_inst(_regs.eip);
+ return (unsigned long)-1;
+}
+#endif /* CONFIG_SVM */
diff --git a/xen/arch/x86/hvm/svm/intr.c b/xen/arch/x86/hvm/svm/intr.c
new file mode 100644
index 0000000000..e63ad8ce1a
--- /dev/null
+++ b/xen/arch/x86/hvm/svm/intr.c
@@ -0,0 +1,219 @@
+/*
+ * intr.c: Interrupt handling for SVM.
+ * Copyright (c) 2005, AMD Inc.
+ * Copyright (c) 2004, Intel 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 <xen/config.h>
+#include <xen/init.h>
+#include <xen/mm.h>
+#include <xen/lib.h>
+#include <xen/trace.h>
+#include <xen/errno.h>
+#include <xen/shadow.h>
+#include <asm/cpufeature.h>
+#include <asm/processor.h>
+#include <asm/msr.h>
+#include <asm/hvm/hvm.h>
+#include <asm/hvm/io.h>
+#include <asm/hvm/support.h>
+#include <asm/hvm/svm/svm.h>
+#include <asm/hvm/svm/intr.h>
+#include <xen/event.h>
+#include <xen/kernel.h>
+#include <public/hvm/ioreq.h>
+#include <xen/domain_page.h>
+
+#ifdef CONFIG_SVM
+
+/*
+ * Most of this code is copied from vmx_io.c and modified
+ * to be suitable for SVM.
+ */
+#define BSP_CPU(v) (!(v->vcpu_id))
+
+static inline int svm_inject_extint(struct vcpu *v, int trap, int error_code)
+{
+ struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+ vintr_t intr;
+
+ ASSERT(vmcb);
+
+ /* Save all fields */
+ intr = vmcb->vintr;
+ /* Update only relevant fields */
+ intr.fields.irq = 1;
+ intr.fields.intr_masking = 1;
+ intr.fields.vector = trap;
+ intr.fields.prio = 0xF;
+ vmcb->vintr = intr;
+// printf( "IRQ = %d\n", trap );
+ return 0;
+}
+
+void svm_set_tsc_shift(struct vcpu *v, struct hvm_virpit *vpit)
+{
+ struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+ u64 drift;
+
+ if ( vpit->first_injected )
+ drift = vpit->period_cycles * vpit->pending_intr_nr;
+ else
+ drift = 0;
+ vmcb->tsc_offset = ( 0 - drift );
+}
+
+static inline void
+interrupt_post_injection(struct vcpu * v, int vector, int type)
+{
+ struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit);
+
+ switch(type)
+ {
+ case VLAPIC_DELIV_MODE_EXT:
+ case VLAPIC_DELIV_MODE_FIXED:
+ case VLAPIC_DELIV_MODE_LPRI:
+ if ( is_pit_irq(v, vector, type) ) {
+ if ( !vpit->first_injected ) {
+ vpit->first_injected = 1;
+ vpit->pending_intr_nr = 0;
+ }
+ else if (vpit->pending_intr_nr) {
+ --vpit->pending_intr_nr;
+ }
+ vpit->inject_point = NOW();
+ svm_set_tsc_shift (v, vpit);
+ }
+ break;
+
+ default:
+ printk("Not support interrupt type: %d\n", type);
+ break;
+ }
+}
+
+asmlinkage void svm_intr_assist(void)
+{
+ struct vcpu *v = current;
+ struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+ struct hvm_domain *plat=&v->domain->arch.hvm_domain;
+ struct hvm_virpit *vpit = &plat->vpit;
+ struct hvm_virpic *pic= &plat->vpic;
+ int intr_type = VLAPIC_DELIV_MODE_EXT;
+ int intr_vector = -1;
+ int re_injecting = 0;
+ unsigned long rflags;
+
+ ASSERT(vmcb);
+
+ /* Check if an Injection is active */
+ if (v->arch.hvm_svm.injecting_event) {
+ /* Previous Interrupt delivery caused this Intercept? */
+ if (vmcb->exitintinfo.fields.v && (vmcb->exitintinfo.fields.type == 0)) {
+ v->arch.hvm_svm.saved_irq_vector = vmcb->exitintinfo.fields.vector;
+// printk("Injecting PF#: saving IRQ from ExitInfo\n");
+ vmcb->exitintinfo.bytes = 0;
+
+ /* bail out, we won't be injecting an interrupt this time */
+ return;
+ }
+ }
+
+ /* Guest's interrputs masked? */
+ rflags = vmcb->rflags;
+ if (irq_masked(rflags)) {
+ HVM_DBG_LOG(DBG_LEVEL_1, "Guest IRQs masked: rflags: %lx", rflags);
+ /* bail out, we won't be injecting an interrupt this time */
+ return;
+ }
+
+ /* Interrupt delivery caused an Intercept? */
+ if (vmcb->exitintinfo.fields.v && (vmcb->exitintinfo.fields.type == 0)) {
+// printk("Re-injecting IRQ from ExitInfo\n");
+ intr_vector = vmcb->exitintinfo.fields.vector;
+ vmcb->exitintinfo.bytes = 0;
+ re_injecting = 1;
+ }
+ /* Previous interrupt still pending? */
+ else if (vmcb->vintr.fields.irq) {
+// printk("Re-injecting IRQ from Vintr\n");
+ intr_vector = vmcb->vintr.fields.vector;
+ vmcb->vintr.bytes = 0;
+ re_injecting = 1;
+ }
+ /* Pending IRQ saved at last VMExit? */
+ else if ( v->arch.hvm_svm.saved_irq_vector >= 0) {
+// printk("Re-Injecting saved IRQ\n");
+ intr_vector = v->arch.hvm_svm.saved_irq_vector;
+ v->arch.hvm_svm.saved_irq_vector = -1;
+ re_injecting = 1;
+ }
+ /* Now let's check for newer interrrupts */
+ else {
+ /* Interrput pending at the PIC? */
+ hvm_pic_assist(v);
+
+ if (vpit->pending_intr_nr) {
+ pic_set_irq(pic, 0, 0);
+ pic_set_irq(pic, 0, 1);
+ }
+
+ if (plat->interrupt_request) {
+ intr_vector = cpu_get_interrupt(v, &intr_type);
+ plat->interrupt_request = 0;
+ }
+ }
+
+ /* have we got an interrupt to inject? */
+ if (intr_vector >= 0) {
+ switch (intr_type) {
+ case VLAPIC_DELIV_MODE_EXT:
+ case VLAPIC_DELIV_MODE_FIXED:
+ case VLAPIC_DELIV_MODE_LPRI:
+ /* Re-injecting a PIT interruptt? */
+ if (re_injecting &&
+ is_pit_irq(v, intr_vector, intr_type)) {
+ ++vpit->pending_intr_nr;
+ }
+ /* let's inject this interrupt */
+ TRACE_3D(TRC_VMX_INT, v->domain->domain_id, intr_vector, 0);
+ svm_inject_extint(v, intr_vector, VMX_INVALID_ERROR_CODE);
+ interrupt_post_injection(v, intr_vector, intr_type);
+ break;
+ case VLAPIC_DELIV_MODE_SMI:
+ case VLAPIC_DELIV_MODE_NMI:
+ case VLAPIC_DELIV_MODE_INIT:
+ case VLAPIC_DELIV_MODE_STARTUP:
+ default:
+ printk("Unsupported interrupt type: %d\n", intr_type);
+ BUG();
+ break;
+ }
+ }
+}
+
+#endif /* CONFIG_SVM */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
new file mode 100644
index 0000000000..78f187a960
--- /dev/null
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -0,0 +1,2707 @@
+/*
+ * svm.c: handling SVM architecture-related VM exits
+ * Copyright (c) 2004, Intel Corporation.
+ * Copyright (c) 2005, AMD 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 <xen/config.h>
+#include <xen/init.h>
+#include <xen/lib.h>
+#include <xen/trace.h>
+#include <xen/sched.h>
+#include <xen/irq.h>
+#include <xen/softirq.h>
+#include <xen/hypercall.h>
+#include <asm/current.h>
+#include <asm/io.h>
+#include <asm/shadow.h>
+#include <asm/regs.h>
+#include <asm/cpufeature.h>
+#include <asm/processor.h>
+#include <asm/types.h>
+#include <asm/msr.h>
+#include <asm/spinlock.h>
+#include <asm/hvm/hvm.h>
+#include <asm/hvm/support.h>
+#include <asm/hvm/io.h>
+#include <asm/hvm/svm/svm.h>
+#include <asm/hvm/svm/vmcb.h>
+#include <asm/hvm/svm/emulate.h>
+#include <asm/hvm/svm/vmmcall.h>
+#include <asm/hvm/svm/intr.h>
+#include <asm/shadow.h>
+#if CONFIG_PAGING_LEVELS >= 3
+#include <asm/shadow_64.h>
+#endif
+#include <public/sched.h>
+#include <public/hvm/ioreq.h>
+
+#ifdef CONFIG_SVM
+
+#define SVM_EXTRA_DEBUG
+
+#ifdef TRACE_BUFFER
+static unsigned long trace_values[NR_CPUS][4];
+#define TRACE_VMEXIT(index,value) trace_values[current->processor][index]=value
+#else
+#define TRACE_VMEXIT(index,value) ((void)0)
+#endif
+
+/* Useful define */
+#define MAX_INST_SIZE 15
+
+/*
+ * External functions, etc. We should move these to some suitable header file(s) */
+
+extern long evtchn_send(int lport);
+extern void do_nmi(struct cpu_user_regs *, unsigned long);
+extern int inst_copy_from_guest(unsigned char *buf, unsigned long guest_eip,
+ int inst_len);
+extern asmlinkage void do_IRQ(struct cpu_user_regs *);
+extern void smp_apic_timer_interrupt(struct cpu_user_regs *);
+extern void timer_interrupt(int, void *, struct cpu_user_regs *);
+extern void send_pio_req(struct cpu_user_regs *regs, unsigned long port,
+ unsigned long count, int size, long value, int dir, int pvalid);
+extern int svm_instrlen(struct cpu_user_regs *regs, int mode);
+extern void svm_dump_inst(unsigned long eip);
+extern int svm_dbg_on;
+void svm_manual_event_injection32(struct vcpu *v, struct cpu_user_regs *regs,
+ int vector, int has_code);
+void svm_dump_regs(const char *from, struct cpu_user_regs *regs);
+
+static struct asid_pool ASIDpool[NR_CPUS];
+
+/*
+ * Initializes the POOL of ASID used by the guests per core.
+ */
+void asidpool_init( int core )
+{
+ int i;
+ ASIDpool[core].asid_lock = SPIN_LOCK_UNLOCKED;
+ spin_lock(&ASIDpool[core].asid_lock);
+ /* Host ASID is always in use */
+ ASIDpool[core].asid[INITIAL_ASID] = ASID_INUSE;
+ for( i=1; i<ASID_MAX; i++ )
+ {
+ ASIDpool[core].asid[i] = ASID_AVAILABLE;
+ }
+ spin_unlock(&ASIDpool[core].asid_lock);
+}
+
+
+/* internal function to get the next available ASID */
+static int asidpool_fetch_next( struct vmcb_struct *vmcb, int core )
+{
+ int i;
+ for( i = 1; i < ASID_MAX; i++ )
+ {
+ if( ASIDpool[core].asid[i] == ASID_AVAILABLE )
+ {
+ vmcb->guest_asid = i;
+ ASIDpool[core].asid[i] = ASID_INUSE;
+ return i;
+ }
+ }
+ return -1;
+}
+
+
+/*
+ * This functions assigns on the passed VMCB, the next
+ * available ASID number. If none are available, the
+ * TLB flush flag is set, and all retireds ASID
+ * are made available.
+ *
+ * Returns: 1 -- sucess;
+ * 0 -- failure -- no more ASID numbers
+ * available.
+ */
+int asidpool_assign_next( struct vmcb_struct *vmcb, int retire_current,
+ int oldcore, int newcore )
+{
+ int i;
+ int res = 1;
+ static unsigned long cnt=0;
+
+ spin_lock(&ASIDpool[oldcore].asid_lock);
+ if( retire_current && vmcb->guest_asid ) {
+ ASIDpool[oldcore].asid[ vmcb->guest_asid & (ASID_MAX-1) ] = ASID_RETIRED;
+ }
+ spin_unlock(&ASIDpool[oldcore].asid_lock);
+ spin_lock(&ASIDpool[newcore].asid_lock);
+ if( asidpool_fetch_next( vmcb, newcore ) < 0 ) {
+ if (svm_dbg_on)
+ printk( "SVM: tlb(%ld)\n", cnt++ );
+ /* FLUSH the TLB and all retired slots are made available */
+ vmcb->tlb_control = 1;
+ for( i = 1; i < ASID_MAX; i++ ) {
+ if( ASIDpool[newcore].asid[i] == ASID_RETIRED ) {
+ ASIDpool[newcore].asid[i] = ASID_AVAILABLE;
+ }
+ }
+ /* Get the First slot available */
+ res = asidpool_fetch_next( vmcb, newcore ) > 0;
+ }
+ spin_unlock(&ASIDpool[newcore].asid_lock);
+ return res;
+}
+
+void asidpool_retire( struct vmcb_struct *vmcb, int core )
+{
+ spin_lock(&ASIDpool[core].asid_lock);
+ if( vmcb->guest_asid ) {
+ ASIDpool[core].asid[ vmcb->guest_asid & (ASID_MAX-1) ] = ASID_RETIRED;
+ }
+ spin_unlock(&ASIDpool[core].asid_lock);
+}
+
+static inline int svm_inject_exception(struct vcpu *v, int trap, int error_code)
+{
+ void save_svm_cpu_user_regs(struct vcpu *, struct cpu_user_regs *);
+ struct cpu_user_regs regs;
+
+ printf("svm_inject_exception(trap %d, error_code 0x%x)\n",
+ trap, error_code);
+ save_svm_cpu_user_regs(v, &regs);
+ __hvm_bug(&regs);
+}
+
+void stop_svm(void)
+{
+ u32 eax, edx;
+
+ /* We turn off the EFER_SVME bit. */
+ rdmsr(MSR_EFER, eax, edx);
+ eax &= ~EFER_SVME;
+ wrmsr(MSR_EFER, eax, edx);
+
+ printk("AMD SVM Extension is disabled.\n");
+}
+
+int svm_initialize_guest_resources(struct vcpu *v)
+{
+ svm_final_setup_guest(v);
+ return 1;
+}
+
+int svm_relinquish_guest_resources(struct vcpu *v)
+{
+ svm_relinquish_resources(v);
+ return 1;
+}
+
+void svm_store_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *regs)
+{
+ struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+
+#if defined (__x86_64__)
+ regs->rip = vmcb->rip;
+ regs->rsp = vmcb->rsp;
+ regs->rflags = vmcb->rflags;
+ regs->cs = vmcb->cs.sel;
+ regs->ds = vmcb->ds.sel;
+ regs->es = vmcb->es.sel;
+ regs->ss = vmcb->ss.sel;
+ regs->gs = vmcb->gs.sel;
+ regs->fs = vmcb->fs.sel;
+#elif defined (__i386__)
+ regs->eip = vmcb->rip;
+ regs->esp = vmcb->rsp;
+ regs->eflags = vmcb->rflags;
+ regs->cs = vmcb->cs.sel;
+ regs->ds = vmcb->ds.sel;
+ regs->es = vmcb->es.sel;
+ regs->ss = vmcb->ss.sel;
+ regs->gs = vmcb->gs.sel;
+ regs->fs = vmcb->fs.sel;
+#endif
+}
+
+void svm_load_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *regs)
+{
+ svm_load_cpu_user_regs(v, regs);
+}
+
+#ifdef __x86_64__
+static struct svm_msr_state percpu_msr[NR_CPUS];
+
+static u32 msr_data_index[VMX_MSR_COUNT] =
+{
+ MSR_LSTAR, MSR_STAR, MSR_CSTAR,
+ MSR_SYSCALL_MASK, MSR_EFER,
+};
+
+void svm_save_segments(struct vcpu *v)
+{
+ rdmsrl(MSR_SHADOW_GS_BASE, v->arch.hvm_svm.msr_content.shadow_gs);
+}
+
+/*
+ * To avoid MSR save/restore at every VM exit/entry time, we restore
+ * the x86_64 specific MSRs at domain switch time. Since those MSRs are
+ * are not modified once set for generic domains, we don't save them,
+ * but simply reset them to the values set at percpu_traps_init().
+ */
+void svm_load_msrs(struct vcpu *n)
+{
+ struct svm_msr_state *host_state = &percpu_msr[smp_processor_id()];
+ int i;
+
+ if ( !hvm_switch_on )
+ return;
+
+ while ( host_state->flags )
+ {
+ i = find_first_set_bit(host_state->flags);
+ wrmsrl(msr_data_index[i], host_state->msr_items[i]);
+ clear_bit(i, &host_state->flags);
+ }
+}
+
+static void svm_save_init_msrs(void)
+{
+ struct svm_msr_state *host_state = &percpu_msr[smp_processor_id()];
+ int i;
+
+ for ( i = 0; i < SVM_MSR_COUNT; i++ )
+ rdmsrl(msr_data_index[i], host_state->msr_items[i]);
+}
+
+#define CASE_READ_MSR(address) \
+ case MSR_ ## address: \
+ msr_content = msr->msr_items[SVM_INDEX_MSR_ ## address]; \
+ break
+
+#define CASE_WRITE_MSR(address) \
+ case MSR_ ## address: \
+ msr->msr_items[SVM_INDEX_MSR_ ## address] = msr_content; \
+ if (!test_bit(SVM_INDEX_MSR_ ## address, &msr->flags)) \
+ { \
+ set_bit(SVM_INDEX_MSR_ ## address, &msr->flags); \
+ } \
+ break
+
+
+#define IS_CANO_ADDRESS(add) 1
+
+static inline int long_mode_do_msr_read(struct cpu_user_regs *regs)
+{
+ u64 msr_content = 0;
+ struct vcpu *vc = current;
+ struct svm_msr_state *msr = &vc->arch.hvm_svm.msr_content;
+ struct vmcb_struct *vmcb = vc->arch.hvm_svm.vmcb;
+
+ switch (regs->ecx)
+ {
+ case MSR_EFER:
+ msr_content = msr->msr_items[SVM_INDEX_MSR_EFER];
+ HVM_DBG_LOG(DBG_LEVEL_2, "EFER msr_content %llx\n",
+ (unsigned long long)msr_content);
+
+ if (test_bit(SVM_CPU_STATE_LME_ENABLED, &vc->arch.hvm_svm.cpu_state))
+ msr_content |= 1 << _EFER_LME;
+
+ if (SVM_LONG_GUEST(vc))
+ msr_content |= 1 << _EFER_LMA;
+
+ break;
+
+ case MSR_FS_BASE:
+ if (!(SVM_LONG_GUEST(vc)))
+ /* XXX should it be GP fault */
+ domain_crash_synchronous();
+
+ msr_content = vmcb->fs.base;
+ break;
+
+ case MSR_GS_BASE:
+ if (!(SVM_LONG_GUEST(vc)))
+ domain_crash_synchronous();
+
+ msr_content = vmcb->gs.base;
+ break;
+
+ case MSR_SHADOW_GS_BASE:
+ msr_content = msr->shadow_gs;
+ break;
+
+ CASE_READ_MSR(STAR);
+ CASE_READ_MSR(LSTAR);
+ CASE_READ_MSR(CSTAR);
+ CASE_READ_MSR(SYSCALL_MASK);
+ default:
+ return 0;
+ }
+
+ HVM_DBG_LOG(DBG_LEVEL_2, "mode_do_msr_read: msr_content: %lx\n",
+ msr_content);
+
+ regs->eax = msr_content & 0xffffffff;
+ regs->edx = msr_content >> 32;
+ return 1;
+}
+
+static inline int long_mode_do_msr_write(struct cpu_user_regs *regs)
+{
+ u64 msr_content = regs->eax | ((u64)regs->edx << 32);
+ struct vcpu *vc = current;
+ struct svm_msr_state *msr = &vc->arch.hvm_svm.msr_content;
+ struct svm_msr_state *host_state = &percpu_msr[smp_processor_id()];
+ struct vmcb_struct *vmcb = vc->arch.hvm_svm.vmcb;
+
+ HVM_DBG_LOG(DBG_LEVEL_1, "mode_do_msr_write msr %lx msr_content %lx\n",
+ regs->ecx, msr_content);
+
+ switch (regs->ecx)
+ {
+ case MSR_EFER:
+ if ((msr_content & EFER_LME) ^ test_bit(SVM_CPU_STATE_LME_ENABLED,
+ &vc->arch.hvm_svm.cpu_state))
+ {
+ if (test_bit(SVM_CPU_STATE_PG_ENABLED, &vc->arch.hvm_svm.cpu_state)
+ || !test_bit(SVM_CPU_STATE_PAE_ENABLED,
+ &vc->arch.hvm_svm.cpu_state))
+ {
+ svm_inject_exception(vc, TRAP_gp_fault, 0);
+ }
+ }
+
+ if (msr_content & EFER_LME)
+ set_bit(SVM_CPU_STATE_LME_ENABLED, &vc->arch.hvm_svm.cpu_state);
+
+ /* No update for LME/LMA since it have no effect */
+ msr->msr_items[SVM_INDEX_MSR_EFER] = msr_content;
+ if (msr_content & ~(EFER_LME | EFER_LMA))
+ {
+ msr->msr_items[SVM_INDEX_MSR_EFER] = msr_content;
+ if (!test_bit(SVM_INDEX_MSR_EFER, &msr->flags))
+ {
+ rdmsrl(MSR_EFER, host_state->msr_items[SVM_INDEX_MSR_EFER]);
+ set_bit(SVM_INDEX_MSR_EFER, &host_state->flags);
+ set_bit(SVM_INDEX_MSR_EFER, &msr->flags);
+ wrmsrl(MSR_EFER, msr_content);
+ }
+ }
+ break;
+
+ case MSR_FS_BASE:
+ case MSR_GS_BASE:
+ if (!(SVM_LONG_GUEST(vc)))
+ domain_crash_synchronous();
+
+ if (!IS_CANO_ADDRESS(msr_content))
+ {
+ HVM_DBG_LOG(DBG_LEVEL_1, "Not cano address of msr write\n");
+ svm_inject_exception(vc, TRAP_gp_fault, 0);
+ }
+
+ if (regs->ecx == MSR_FS_BASE)
+ vmcb->fs.base = msr_content;
+ else
+ vmcb->gs.base = msr_content;
+ break;
+
+ case MSR_SHADOW_GS_BASE:
+ if (!(SVM_LONG_GUEST(vc)))
+ domain_crash_synchronous();
+
+ vc->arch.hvm_svm.msr_content.shadow_gs = msr_content;
+ wrmsrl(MSR_SHADOW_GS_BASE, msr_content);
+ break;
+
+ CASE_WRITE_MSR(STAR);
+ CASE_WRITE_MSR(LSTAR);
+ CASE_WRITE_MSR(CSTAR);
+ CASE_WRITE_MSR(SYSCALL_MASK);
+ default:
+ return 0;
+ }
+ return 1;
+}
+
+void
+svm_restore_msrs(struct vcpu *v)
+{
+ int i = 0;
+ struct svm_msr_state *guest_state;
+ struct svm_msr_state *host_state;
+ unsigned long guest_flags;
+
+ guest_state = &v->arch.hvm_svm.msr_content;;
+ host_state = &percpu_msr[smp_processor_id()];
+
+ wrmsrl(MSR_SHADOW_GS_BASE, guest_state->shadow_gs);
+ guest_flags = guest_state->flags;
+ if (!guest_flags)
+ return;
+
+ while (guest_flags){
+ i = find_first_set_bit(guest_flags);
+
+ HVM_DBG_LOG(DBG_LEVEL_2,
+ "restore guest's index %d msr %lx with %lx\n",
+ i, (unsigned long) msr_data_index[i], (unsigned long) guest_state->msr_items[i]);
+ set_bit(i, &host_state->flags);
+ wrmsrl(msr_data_index[i], guest_state->msr_items[i]);
+ clear_bit(i, &guest_flags);
+ }
+}
+#else
+#define svm_save_init_msrs() ((void)0)
+
+static inline int long_mode_do_msr_read(struct cpu_user_regs *regs)
+{
+ return 0;
+}
+
+static inline int long_mode_do_msr_write(struct cpu_user_regs *regs)
+{
+ return 0;
+}
+#endif
+
+void svm_store_cpu_guest_ctrl_regs(struct vcpu *v, unsigned long crs[8])
+{
+ struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+
+ crs[0] = vmcb->cr0;
+ crs[3] = vmcb->cr3;
+ crs[4] = vmcb->cr4;
+}
+
+void svm_modify_guest_state(struct vcpu *v)
+{
+ svm_modify_vmcb(v, &v->arch.guest_context.user_regs);
+}
+
+int svm_realmode(struct vcpu *v)
+{
+ unsigned long cr0 = v->arch.hvm_svm.cpu_shadow_cr0;
+ unsigned long eflags = v->arch.hvm_svm.vmcb->rflags;
+
+ return (eflags & X86_EFLAGS_VM) || !(cr0 & X86_CR0_PE);
+}
+
+int svm_instruction_length(struct vcpu *v)
+{
+ struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+ unsigned long cr0 = vmcb->cr0, eflags = vmcb->rflags, mode;
+
+ mode = (eflags & X86_EFLAGS_VM) || !(cr0 & X86_CR0_PE) ? 2 : 4;
+ return svm_instrlen(guest_cpu_user_regs(), mode);
+}
+
+int start_svm(void)
+{
+ u32 eax, ecx, edx;
+
+ /* Xen does not fill x86_capability words except 0. */
+ ecx = cpuid_ecx(0x80000001);
+ boot_cpu_data.x86_capability[5] = ecx;
+
+ if (!(test_bit(X86_FEATURE_SVME, &boot_cpu_data.x86_capability)))
+ return 0;
+
+ rdmsr(MSR_EFER, eax, edx);
+ eax |= EFER_SVME;
+ wrmsr(MSR_EFER, eax, edx);
+ asidpool_init(smp_processor_id());
+ printk("AMD SVM Extension is enabled for cpu %d.\n", smp_processor_id());
+
+ svm_save_init_msrs();
+
+ /* Setup HVM interfaces */
+ hvm_funcs.disable = stop_svm;
+
+ hvm_funcs.initialize_guest_resources = svm_initialize_guest_resources;
+ hvm_funcs.relinquish_guest_resources = svm_relinquish_guest_resources;
+
+ hvm_funcs.store_cpu_guest_regs = svm_store_cpu_guest_regs;
+ hvm_funcs.load_cpu_guest_regs = svm_load_cpu_guest_regs;
+
+#ifdef __x86_64__
+ hvm_funcs.save_segments = svm_save_segments;
+ hvm_funcs.load_msrs = svm_load_msrs;
+ hvm_funcs.restore_msrs = svm_restore_msrs;
+#endif
+
+ hvm_funcs.store_cpu_guest_ctrl_regs = svm_store_cpu_guest_ctrl_regs;
+ hvm_funcs.modify_guest_state = svm_modify_guest_state;
+
+ hvm_funcs.realmode = svm_realmode;
+ hvm_funcs.paging_enabled = svm_paging_enabled;
+ hvm_funcs.instruction_length = svm_instruction_length;
+
+ hvm_enabled = 1;
+
+ return 1;
+}
+
+int svm_dbg_on = 0;
+
+static inline int svm_do_debugout(unsigned long exit_code)
+{
+ int i;
+
+ static unsigned long counter = 0;
+ static unsigned long works[] =
+ {
+ VMEXIT_IOIO,
+ VMEXIT_HLT,
+ VMEXIT_CPUID,
+ VMEXIT_DR0_READ,
+ VMEXIT_DR1_READ,
+ VMEXIT_DR2_READ,
+ VMEXIT_DR3_READ,
+ VMEXIT_DR6_READ,
+ VMEXIT_DR7_READ,
+ VMEXIT_DR0_WRITE,
+ VMEXIT_DR1_WRITE,
+ VMEXIT_DR2_WRITE,
+ VMEXIT_DR3_WRITE,
+ VMEXIT_CR0_READ,
+ VMEXIT_CR0_WRITE,
+ VMEXIT_CR3_READ,
+ VMEXIT_CR4_READ,
+ VMEXIT_MSR,
+ VMEXIT_CR0_WRITE,
+ VMEXIT_CR3_WRITE,
+ VMEXIT_CR4_WRITE,
+ VMEXIT_EXCEPTION_PF,
+ VMEXIT_INTR,
+ VMEXIT_INVLPG,
+ VMEXIT_EXCEPTION_NM
+ };
+
+
+#if 0
+ if (svm_dbg_on && exit_code != 0x7B)
+ return 1;
+#endif
+
+ counter++;
+
+#if 0
+ if ((exit_code == 0x4E
+ || exit_code == VMEXIT_CR0_READ
+ || exit_code == VMEXIT_CR0_WRITE)
+ && counter < 200000)
+ return 0;
+
+ if ((exit_code == 0x4E) && counter < 500000)
+ return 0;
+#endif
+
+ for (i = 0; i < sizeof(works) / sizeof(works[0]); i++)
+ if (exit_code == works[i])
+ return 0;
+
+ return 1;
+}
+
+
+void save_svm_cpu_user_regs(struct vcpu *v, struct cpu_user_regs *ctxt)
+{
+ struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+
+ ASSERT(vmcb);
+
+ ctxt->eax = vmcb->rax;
+ ctxt->ss = vmcb->ss.sel;
+ ctxt->esp = vmcb->rsp;
+ ctxt->eflags = vmcb->rflags;
+ ctxt->cs = vmcb->cs.sel;
+ ctxt->eip = vmcb->rip;
+
+ ctxt->gs = vmcb->gs.sel;
+ ctxt->fs = vmcb->fs.sel;
+ ctxt->es = vmcb->es.sel;
+ ctxt->ds = vmcb->ds.sel;
+}
+
+#if defined (__x86_64__)
+void svm_store_cpu_user_regs(struct cpu_user_regs *regs, struct vcpu *c )
+{
+}
+#elif defined (__i386__)
+void svm_store_cpu_user_regs(struct cpu_user_regs *regs, struct vcpu *v)
+{
+ struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+
+ regs->eip = vmcb->rip;
+ regs->esp = vmcb->rsp;
+ regs->eflags = vmcb->rflags;
+ regs->cs = vmcb->cs.sel;
+ regs->ds = vmcb->ds.sel;
+ regs->es = vmcb->es.sel;
+ regs->ss = vmcb->ss.sel;
+}
+#endif
+
+/* XXX Use svm_load_cpu_guest_regs instead */
+#if defined (__i386__)
+void svm_load_cpu_user_regs(struct vcpu *v, struct cpu_user_regs *regs)
+{
+ struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+ u32 *intercepts = &v->arch.hvm_svm.vmcb->exception_intercepts;
+
+ /* Write the guest register value into VMCB */
+ vmcb->rax = regs->eax;
+ vmcb->ss.sel = regs->ss;
+ vmcb->rsp = regs->esp;
+ vmcb->rflags = regs->eflags;
+ vmcb->cs.sel = regs->cs;
+ vmcb->rip = regs->eip;
+ if (regs->eflags & EF_TF)
+ *intercepts |= EXCEPTION_BITMAP_DB;
+ else
+ *intercepts &= ~EXCEPTION_BITMAP_DB;
+}
+#else /* (__i386__) */
+void svm_load_cpu_user_regs(struct vcpu *v, struct cpu_user_regs *regs)
+{
+ struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+ u32 *intercepts = &v->arch.hvm_svm.vmcb->exception_intercepts;
+
+ /* Write the guest register value into VMCB */
+ vmcb->rax = regs->rax;
+ vmcb->ss.sel = regs->ss;
+ vmcb->rsp = regs->rsp;
+ vmcb->rflags = regs->rflags;
+ vmcb->cs.sel = regs->cs;
+ vmcb->rip = regs->rip;
+ if (regs->rflags & EF_TF)
+ *intercepts |= EXCEPTION_BITMAP_DB;
+ else
+ *intercepts &= ~EXCEPTION_BITMAP_DB;
+}
+#endif /* !(__i386__) */
+
+int svm_paging_enabled(struct vcpu *v)
+{
+ unsigned long cr0;
+
+ cr0 = v->arch.hvm_svm.cpu_shadow_cr0;
+
+ return (cr0 & X86_CR0_PE) && (cr0 & X86_CR0_PG);
+}
+
+
+/* Make sure that xen intercepts any FP accesses from current */
+void svm_stts(struct vcpu *v)
+{
+ struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+
+ ASSERT(vmcb);
+
+ vmcb->cr0 |= X86_CR0_TS;
+
+ if (!(v->arch.hvm_svm.cpu_shadow_cr0 & X86_CR0_TS))
+ v->arch.hvm_svm.vmcb->exception_intercepts |= EXCEPTION_BITMAP_NM;
+}
+
+static void arch_svm_do_launch(struct vcpu *v)
+{
+ cpu_user_regs_t *regs = &current->arch.guest_context.user_regs;
+ int error;
+
+#if 0
+ if (svm_dbg_on)
+ printk("Do launch\n");
+#endif
+ error = construct_vmcb(&v->arch.hvm_svm, regs);
+ if ( error < 0 )
+ {
+ if (v->vcpu_id == 0) {
+ printk("Failed to construct a new VMCB for BSP.\n");
+ } else {
+ printk("Failed to construct a new VMCB for AP %d\n", v->vcpu_id);
+ }
+ domain_crash_synchronous();
+ }
+
+ svm_do_launch(v);
+#if 0
+ if (svm_dbg_on)
+ svm_dump_host_regs(__func__);
+#endif
+ reset_stack_and_jump(svm_asm_do_launch);
+}
+
+void svm_final_setup_guest(struct vcpu *v)
+{
+ v->arch.schedule_tail = arch_svm_do_launch;
+
+ if (v == v->domain->vcpu[0])
+ {
+ struct domain *d = v->domain;
+ struct vcpu *vc;
+
+ /* Initialize monitor page table */
+ for_each_vcpu(d, vc)
+ vc->arch.monitor_table = mk_pagetable(0);
+
+ /*
+ * Required to do this once per domain
+ * TODO: add a seperate function to do these.
+ */
+ memset(&d->shared_info->evtchn_mask[0], 0xff,
+ sizeof(d->shared_info->evtchn_mask));
+
+ /*
+ * Put the domain in shadow mode even though we're going to be using
+ * the shared 1:1 page table initially. It shouldn't hurt
+ */
+ shadow_mode_enable(d,
+ SHM_enable|SHM_refcounts|
+ SHM_translate|SHM_external|SHM_wr_pt_pte);
+ }
+}
+
+
+void svm_relinquish_resources(struct vcpu *v)
+{
+ struct hvm_virpit *vpit;
+ extern void destroy_vmcb(struct arch_svm_struct *); /* XXX */
+
+#if 0
+ /*
+ * This is not stored at the moment. We need to keep it somewhere and free
+ * it Or maybe not, as it's a per-cpu-core item, and I guess we don't
+ * normally remove CPU's other than for hot-plug capable systems, where I
+ * guess we have to allocate and free host-save area in this case. Let's
+ * not worry about it at the moment, as loosing one page per CPU hot-plug
+ * event doesn't seem that excessive. But I may be wrong.
+ */
+ free_host_save_area(v->arch.hvm_svm.host_save_area);
+#endif
+
+ if (v->vcpu_id == 0) {
+ /* unmap IO shared page */
+ struct domain *d = v->domain;
+ if (d->arch.hvm_domain.shared_page_va)
+ unmap_domain_page((void *)d->arch.hvm_domain.shared_page_va);
+ }
+
+ destroy_vmcb(&v->arch.hvm_svm);
+ free_monitor_pagetable(v);
+ vpit = &v->domain->arch.hvm_domain.vpit;
+ kill_timer(&vpit->pit_timer);
+ kill_timer(&v->arch.hvm_svm.hlt_timer);
+ if ( hvm_apic_support(v->domain) ) {
+ kill_timer( &(VLAPIC(v)->vlapic_timer) );
+ xfree( VLAPIC(v) );
+ }
+}
+
+
+void arch_svm_do_resume(struct vcpu *v)
+{
+ svm_do_resume(v);
+ reset_stack_and_jump(svm_asm_do_resume);
+}
+
+
+static int svm_do_page_fault(unsigned long va, struct cpu_user_regs *regs)
+{
+ struct vcpu *v = current;
+ unsigned long eip;
+ unsigned long gpa; /* FIXME: PAE */
+ int result;
+ struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+
+ ASSERT(vmcb);
+
+//#if HVM_DEBUG
+ eip = vmcb->rip;
+ HVM_DBG_LOG(DBG_LEVEL_VMMU,
+ "svm_do_page_fault = 0x%lx, eip = %lx, error_code = %lx",
+ va, eip, (unsigned long)regs->error_code);
+//#endif
+
+ if (!svm_paging_enabled(v))
+ {
+ handle_mmio(va, va);
+ TRACE_VMEXIT(2,2);
+ return 1;
+ }
+
+ update_pagetables(v);
+
+ gpa = gva_to_gpa(va);
+
+ /* Use 1:1 page table to identify MMIO address space */
+ if (mmio_space(gpa))
+ {
+ /* No support for APIC */
+ if (!hvm_apic_support(v->domain) && gpa >= 0xFEC00000)
+ {
+ unsigned long inst_len;
+ inst_len = svm_instruction_length(v);
+ if (inst_len == (unsigned long)-1)
+ {
+ printf("%s: INST_LEN - Unable to decode properly.\n", __func__);
+ domain_crash_synchronous();
+ }
+
+ __update_guest_eip(vmcb, inst_len);
+
+ return 1;
+ }
+
+ TRACE_VMEXIT (2,2);
+ handle_mmio(va, gpa);
+
+ return 1;
+ }
+
+ result = shadow_fault(va, regs);
+
+ if( result ) {
+ /* Let's make sure that the Guest TLB is flushed */
+ set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
+ }
+
+ TRACE_VMEXIT (2,result);
+
+ return result;
+}
+
+
+static void svm_do_no_device_fault(struct vmcb_struct *vmcb)
+{
+ struct vcpu *v = current;
+
+ clts();
+
+ setup_fpu(v);
+
+ if (!(v->arch.hvm_svm.cpu_shadow_cr0 & X86_CR0_TS))
+ vmcb->cr0 &= ~X86_CR0_TS;
+
+ vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_NM;
+}
+
+
+static void svm_do_general_protection_fault(struct vcpu *v,
+ struct cpu_user_regs *regs)
+{
+ struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+ unsigned long eip, error_code;
+ eventinj_t event;
+
+ ASSERT(vmcb);
+
+ eip = vmcb->rip;
+ error_code = vmcb->exitinfo1;
+
+ HVM_DBG_LOG(DBG_LEVEL_1,
+ "svm_general_protection_fault: eip = %lx, erro_code = %lx",
+ eip, error_code);
+
+ HVM_DBG_LOG(DBG_LEVEL_1,
+ "eax=%lx, ebx=%lx, ecx=%lx, edx=%lx, esi=%lx, edi=%lx",
+ (unsigned long)regs->eax, (unsigned long)regs->ebx,
+ (unsigned long)regs->ecx, (unsigned long)regs->edx,
+ (unsigned long)regs->esi, (unsigned long)regs->edi);
+
+
+ /* Reflect it back into the guest */
+ event.bytes = 0;
+ event.fields.v = 1;
+ event.fields.type = EVENTTYPE_EXCEPTION;
+ event.fields.vector = 13;
+ event.fields.ev = 1;
+ event.fields.errorcode = error_code;
+
+ vmcb->eventinj = event;
+}
+
+/* Reserved bits: [31:14], [12:1] */
+#define SVM_VCPU_CPUID_L1_RESERVED 0xffffdffe
+
+static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, unsigned long input,
+ struct cpu_user_regs *regs)
+{
+ unsigned int eax, ebx, ecx, edx;
+ unsigned long eip;
+ struct vcpu *v = current;
+ unsigned int inst_len;
+
+ ASSERT(vmcb);
+
+ eip = vmcb->rip;
+
+ HVM_DBG_LOG(DBG_LEVEL_1,
+ "do_cpuid: (eax) %lx, (ebx) %lx, (ecx) %lx, (edx) %lx,"
+ " (esi) %lx, (edi) %lx",
+ (unsigned long)regs->eax, (unsigned long)regs->ebx,
+ (unsigned long)regs->ecx, (unsigned long)regs->edx,
+ (unsigned long)regs->esi, (unsigned long)regs->edi);
+
+ cpuid(input, &eax, &ebx, &ecx, &edx);
+
+ if (input == 1)
+ {
+ if ( hvm_apic_support(v->domain) &&
+ !vlapic_global_enabled((VLAPIC(v))) )
+ clear_bit(X86_FEATURE_APIC, &edx);
+
+#ifdef __x86_64__
+ if ( v->domain->arch.ops->guest_paging_levels == PAGING_L2 )
+#endif
+ {
+ clear_bit(X86_FEATURE_PSE, &edx);
+ clear_bit(X86_FEATURE_PAE, &edx);
+ clear_bit(X86_FEATURE_PSE36, &edx);
+ }
+
+ /* Clear out reserved bits. */
+ ecx &= ~SVM_VCPU_CPUID_L1_RESERVED; /* mask off reserved bits */
+ }
+#ifdef __i386__
+ else if ( input == 0x80000001 )
+ {
+ /* Mask feature for Intel ia32e or AMD long mode. */
+ clear_bit(X86_FEATURE_LM & 31, &edx);
+ }
+#endif
+
+ regs->eax = (unsigned long)eax;
+ regs->ebx = (unsigned long)ebx;
+ regs->ecx = (unsigned long)ecx;
+ regs->edx = (unsigned long)edx;
+
+ HVM_DBG_LOG(DBG_LEVEL_1,
+ "svm_vmexit_do_cpuid: eip: %lx, input: %lx, out:eax=%x, "
+ "ebx=%x, ecx=%x, edx=%x",
+ eip, input, eax, ebx, ecx, edx);
+
+ inst_len = __get_instruction_length(vmcb, INSTR_CPUID, NULL);
+ __update_guest_eip(vmcb, inst_len);
+}
+
+
+static inline unsigned long *get_reg_p(unsigned int gpreg,
+ struct cpu_user_regs *regs, struct vmcb_struct *vmcb)
+{
+ unsigned long *reg_p = NULL;
+ switch (gpreg)
+ {
+ case SVM_REG_EAX:
+ reg_p = (unsigned long *)&regs->eax;
+ break;
+ case SVM_REG_EBX:
+ reg_p = (unsigned long *)&regs->ebx;
+ break;
+ case SVM_REG_ECX:
+ reg_p = (unsigned long *)&regs->ecx;
+ break;
+ case SVM_REG_EDX:
+ reg_p = (unsigned long *)&regs->edx;
+ break;
+ case SVM_REG_EDI:
+ reg_p = (unsigned long *)&regs->edi;
+ break;
+ case SVM_REG_ESI:
+ reg_p = (unsigned long *)&regs->esi;
+ break;
+ case SVM_REG_EBP:
+ reg_p = (unsigned long *)&regs->ebp;
+ break;
+ case SVM_REG_ESP:
+ reg_p = (unsigned long *)&vmcb->rsp;
+ break;
+#if __x86_64__
+ case SVM_REG_R8:
+ reg_p = (unsigned long *)&regs->r8;
+ break;
+ case SVM_REG_R9:
+ reg_p = (unsigned long *)&regs->r9;
+ break;
+ case SVM_REG_R10:
+ reg_p = (unsigned long *)&regs->r10;
+ break;
+ case SVM_REG_R11:
+ reg_p = (unsigned long *)&regs->r11;
+ break;
+ case SVM_REG_R12:
+ reg_p = (unsigned long *)&regs->r12;
+ break;
+ case SVM_REG_R13:
+ reg_p = (unsigned long *)&regs->r13;
+ break;
+ case SVM_REG_R14:
+ reg_p = (unsigned long *)&regs->r14;
+ break;
+ case SVM_REG_R15:
+ reg_p = (unsigned long *)&regs->r15;
+ break;
+#endif
+ default:
+ BUG();
+ }
+
+ return reg_p;
+}
+
+
+static inline unsigned long get_reg(unsigned int gpreg,
+ struct cpu_user_regs *regs, struct vmcb_struct *vmcb)
+{
+ unsigned long *gp;
+ gp = get_reg_p(gpreg, regs, vmcb);
+ return *gp;
+}
+
+
+static inline void set_reg(unsigned int gpreg, unsigned long value,
+ struct cpu_user_regs *regs, struct vmcb_struct *vmcb)
+{
+ unsigned long *gp;
+ gp = get_reg_p(gpreg, regs, vmcb);
+ *gp = value;
+}
+
+
+static void svm_dr_access (struct vcpu *v, unsigned int reg, unsigned int type,
+ struct cpu_user_regs *regs)
+{
+ unsigned long *reg_p = 0;
+ unsigned int gpreg = 0;
+ unsigned long eip;
+ unsigned int inst_len;
+ struct vmcb_struct *vmcb;
+ u8 buffer[MAX_INST_LEN];
+
+ vmcb = v->arch.hvm_svm.vmcb;
+
+ ASSERT(vmcb);
+
+ eip = vmcb->rip;
+ inst_copy_from_guest(buffer, svm_rip2pointer(vmcb), sizeof(buffer));
+
+ ASSERT(buffer[0] == 0x0f && (buffer[1] & 0xFD) == 0x21);
+
+ gpreg = decode_src_reg(buffer[2]);
+#if DEBUG
+ ASSERT(reg == decode_dest_reg(buffer[2]));
+#endif
+
+ HVM_DBG_LOG(DBG_LEVEL_1, "svm_dr_access : eip=%lx, reg=%d, gpreg = %x",
+ eip, reg, gpreg);
+
+ reg_p = get_reg_p(gpreg, regs, vmcb);
+
+ switch (type)
+ {
+ case TYPE_MOV_TO_DR:
+ inst_len = __get_instruction_length(vmcb, INSTR_MOV2DR, buffer);
+ v->arch.guest_context.debugreg[reg] = *reg_p;
+ break;
+ case TYPE_MOV_FROM_DR:
+ inst_len = __get_instruction_length(vmcb, INSTR_MOVDR2, buffer);
+ *reg_p = v->arch.guest_context.debugreg[reg];
+ break;
+ default:
+ __hvm_bug(regs);
+ break;
+ }
+ __update_guest_eip(vmcb, inst_len);
+}
+
+
+static unsigned int check_for_null_selector(struct vmcb_struct *vmcb,
+ unsigned int dir, unsigned long *base, unsigned int real)
+
+{
+ unsigned char inst[MAX_INST_LEN];
+ segment_selector_t seg;
+ int i;
+
+ memset(inst, 0, MAX_INST_LEN);
+ if (inst_copy_from_guest(inst, svm_rip2pointer(vmcb), sizeof(inst))
+ != MAX_INST_LEN)
+ {
+ printk("check_for_null_selector: get guest instruction failed\n");
+ domain_crash_synchronous();
+ }
+
+ for (i = 0; i < MAX_INST_LEN; i++)
+ {
+ switch (inst[i])
+ {
+ case 0xf3: /* REPZ */
+ case 0xf2: /* REPNZ */
+ case 0xf0: /* LOCK */
+ case 0x66: /* data32 */
+ case 0x67: /* addr32 */
+#if __x86_64__
+ /* REX prefixes */
+ case 0x40:
+ case 0x41:
+ case 0x42:
+ case 0x43:
+ case 0x44:
+ case 0x45:
+ case 0x46:
+ case 0x47:
+
+ case 0x48:
+ case 0x49:
+ case 0x4a:
+ case 0x4b:
+ case 0x4c:
+ case 0x4d:
+ case 0x4e:
+ case 0x4f:
+#endif
+ continue;
+ case 0x2e: /* CS */
+ seg = vmcb->cs;
+ break;
+ case 0x36: /* SS */
+ seg = vmcb->ss;
+ break;
+ case 0x26: /* ES */
+ seg = vmcb->es;
+ break;
+ case 0x64: /* FS */
+ seg = vmcb->fs;
+ break;
+ case 0x65: /* GS */
+ seg = vmcb->gs;
+ break;
+ case 0x3e: /* DS */
+ /* FALLTHROUGH */
+ seg = vmcb->ds;
+ break;
+ default:
+ if (dir == IOREQ_READ)
+ seg = vmcb->es;
+ else
+ seg = vmcb->ds;
+ }
+
+ /* In real Mode */
+ if (real)
+ seg.base = seg.sel << 4;
+
+ if (base)
+ *base = seg.base;
+
+ return seg.attributes.fields.p;
+ }
+
+ ASSERT(0);
+ return 0;
+}
+
+
+/* Get the address of INS/OUTS instruction */
+static inline unsigned long svm_get_io_address(struct vmcb_struct *vmcb,
+ struct cpu_user_regs *regs, unsigned int dir, unsigned int real)
+{
+ unsigned long addr = 0;
+ unsigned long base = 0;
+
+ check_for_null_selector(vmcb, dir, &base, real);
+
+ if (dir == IOREQ_WRITE)
+ {
+ if (real)
+ addr = (regs->esi & 0xFFFF) + base;
+ else
+ addr = regs->esi + base;
+ }
+ else
+ {
+ if (real)
+ addr = (regs->edi & 0xFFFF) + base;
+ else
+ addr = regs->edi + base;
+ }
+
+ return addr;
+}
+
+
+static void svm_io_instruction(struct vcpu *v, struct cpu_user_regs *regs)
+{
+ struct mmio_op *mmio_opp;
+ unsigned long eip, cs, eflags, cr0;
+ unsigned long port;
+ unsigned int real, size, dir;
+ ioio_info_t info;
+
+ struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+
+ ASSERT(vmcb);
+ mmio_opp = &current->arch.hvm_vcpu.mmio_op;
+ mmio_opp->instr = INSTR_PIO;
+ mmio_opp->flags = 0;
+
+ eip = vmcb->rip;
+ cs = vmcb->cs.sel;
+ eflags = vmcb->rflags;
+
+ info.bytes = vmcb->exitinfo1;
+
+ port = info.fields.port; /* port used to be addr */
+ dir = info.fields.type; /* direction */
+ if (info.fields.sz32)
+ size = 4;
+ else if (info.fields.sz16)
+ size = 2;
+ else
+ size = 1;
+
+ cr0 = vmcb->cr0;
+ real = (eflags & X86_EFLAGS_VM) || !(cr0 & X86_CR0_PE);
+
+ HVM_DBG_LOG(DBG_LEVEL_IO,
+ "svm_io_instruction: port 0x%lx real %d, eip=%lx:%lx, "
+ "exit_qualification = %lx",
+ (unsigned long) port, real, cs, eip, (unsigned long)info.bytes);
+
+ /*
+ * On SVM, the RIP of the intruction following the IN/OUT is saved in
+ * ExitInfo2
+ */
+ vmcb->rip = vmcb->exitinfo2;
+
+ /* string instruction */
+ if (info.fields.str)
+ {
+ unsigned long addr, count = 1;
+ int sign = regs->eflags & EF_DF ? -1 : 1;
+
+ addr = svm_get_io_address(vmcb, regs, dir, real);
+
+ /* "rep" prefix */
+ if (info.fields.rep)
+ {
+ mmio_opp->flags |= REPZ;
+ count = real ? regs->ecx & 0xFFFF : regs->ecx;
+ }
+
+ /*
+ * Handle string pio instructions that cross pages or that
+ * are unaligned. See the comments in hvm_platform.c/handle_mmio()
+ */
+ if ((addr & PAGE_MASK) != ((addr + size - 1) & PAGE_MASK))
+ {
+ unsigned long value = 0;
+
+ mmio_opp->flags |= OVERLAP;
+
+ if (dir == IOREQ_WRITE)
+ hvm_copy(&value, addr, size, HVM_COPY_IN);
+
+ send_pio_req(regs, port, 1, size, value, dir, 0);
+ }
+ else
+ {
+ if ((addr & PAGE_MASK) != ((addr + count * size - 1) & PAGE_MASK))
+ {
+ if (sign > 0)
+ count = (PAGE_SIZE - (addr & ~PAGE_MASK)) / size;
+ else
+ count = (addr & ~PAGE_MASK) / size;
+ }
+
+ send_pio_req(regs, port, count, size, addr, dir, 1);
+ }
+ }
+ else
+ {
+ if (port == 0xe9 && dir == IOREQ_WRITE && size == 1)
+ hvm_print_line(v, regs->eax); /* guest debug output */
+
+ send_pio_req(regs, port, 1, size, regs->eax, dir, 0);
+ }
+}
+
+
+static int svm_set_cr0(unsigned long value)
+{
+ struct vcpu *v = current;
+ unsigned long mfn;
+ int paging_enabled;
+ struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+
+ ASSERT(vmcb);
+
+ /* We don't want to lose PG. ET is reserved and should be always be 1*/
+ paging_enabled = svm_paging_enabled(v);
+ value |= X86_CR0_ET;
+ vmcb->cr0 = value | X86_CR0_PG;
+ v->arch.hvm_svm.cpu_shadow_cr0 = value;
+
+ /* Check if FP Unit Trap need to be on */
+ if (value & X86_CR0_TS)
+ {
+ vmcb->exception_intercepts |= EXCEPTION_BITMAP_NM;
+ }
+
+ HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR0 value = %lx\n", value);
+
+ if ((value & X86_CR0_PE) && (value & X86_CR0_PG) && !paging_enabled)
+ {
+ /* The guest CR3 must be pointing to the guest physical. */
+ if (!VALID_MFN(mfn =
+ get_mfn_from_pfn(v->arch.hvm_svm.cpu_cr3 >> PAGE_SHIFT))
+ || !get_page(pfn_to_page(mfn), v->domain))
+ {
+ printk("Invalid CR3 value = %lx\n", v->arch.hvm_svm.cpu_cr3);
+ domain_crash_synchronous(); /* need to take a clean path */
+ }
+
+#if defined(__x86_64__)
+ if (test_bit(SVM_CPU_STATE_LME_ENABLED, &v->arch.hvm_svm.cpu_state)
+ && !test_bit(SVM_CPU_STATE_PAE_ENABLED,
+ &v->arch.hvm_svm.cpu_state))
+ {
+ HVM_DBG_LOG(DBG_LEVEL_1, "Enable paging before PAE enable\n");
+ svm_inject_exception(v, TRAP_gp_fault, 0);
+ }
+
+ if (test_bit(SVM_CPU_STATE_LME_ENABLED, &v->arch.hvm_svm.cpu_state))
+ {
+ /* Here the PAE is should to be opened */
+ HVM_DBG_LOG(DBG_LEVEL_1, "Enable the Long mode\n");
+ set_bit(SVM_CPU_STATE_LMA_ENABLED,
+ &v->arch.hvm_svm.cpu_state);
+#if 0
+ __vmread(VM_ENTRY_CONTROLS, &vm_entry_value);
+ vm_entry_value |= VM_ENTRY_CONTROLS_IA32E_MODE;
+ __vmwrite(VM_ENTRY_CONTROLS, vm_entry_value);
+#else
+ printk("Cannot yet set SVM_CPU_STATE_LMA_ENABLED\n");
+ domain_crash_synchronous();
+#endif
+
+#if CONFIG_PAGING_LEVELS >= 4
+ if (!shadow_set_guest_paging_levels(v->domain, 4))
+ {
+ printk("Unsupported guest paging levels\n");
+ domain_crash_synchronous(); /* need to take a clean path */
+ }
+#endif
+ }
+ else
+ {
+#if CONFIG_PAGING_LEVELS >= 4
+ if (!shadow_set_guest_paging_levels(v->domain, 2))
+ {
+ printk("Unsupported guest paging levels\n");
+ domain_crash_synchronous(); /* need to take a clean path */
+ }
+#endif
+ }
+
+#if 0
+ unsigned long crn;
+
+ /* update CR4's PAE if needed */
+ __vmread(GUEST_CR4, &crn);
+ if ((!(crn & X86_CR4_PAE))
+ && test_bit(SVM_CPU_STATE_PAE_ENABLED,
+ &v->arch.hvm_svm.cpu_state))
+ {
+ HVM_DBG_LOG(DBG_LEVEL_1, "enable PAE on cr4\n");
+ __vmwrite(GUEST_CR4, crn | X86_CR4_PAE);
+ }
+#else
+ printk("Cannot yet set SVM_CPU_STATE_PAE_ENABLED\n");
+ domain_crash_synchronous();
+#endif
+#elif defined(__i386__)
+ {
+ unsigned long old_base_mfn;
+ old_base_mfn = pagetable_get_pfn(v->arch.guest_table);
+ if (old_base_mfn)
+ put_page(pfn_to_page(old_base_mfn));
+ }
+#endif
+ /* Now arch.guest_table points to machine physical. */
+ v->arch.guest_table = mk_pagetable(mfn << PAGE_SHIFT);
+ update_pagetables(v);
+
+ HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx",
+ (unsigned long) (mfn << PAGE_SHIFT));
+
+ set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
+ vmcb->cr3 = pagetable_get_paddr(v->arch.shadow_table);
+
+ /* arch->shadow_table should hold the next CR3 for shadow */
+ HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx, mfn = %lx\n",
+ v->arch.hvm_svm.cpu_cr3, mfn);
+ }
+
+ /*
+ * SVM implements paged real-mode and when we return to real-mode
+ * we revert back to the physical mappings that the domain builder
+ * created.
+ */
+ if ((value & X86_CR0_PE) == 0) {
+ if (value & X86_CR0_PG) {
+ svm_inject_exception(v, TRAP_gp_fault, 0);
+ return 0;
+ }
+
+ set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
+ vmcb->cr3 = pagetable_get_paddr(v->domain->arch.phys_table);
+ }
+
+ return 1;
+}
+
+
+/*
+ * Read from control registers. CR0 and CR4 are read from the shadow.
+ */
+static void mov_from_cr(int cr, int gp, struct cpu_user_regs *regs)
+{
+ unsigned long value = 0;
+ struct vcpu *v = current;
+ struct vmcb_struct *vmcb;
+
+ vmcb = v->arch.hvm_svm.vmcb;
+ ASSERT(vmcb);
+
+ switch (cr)
+ {
+ case 0:
+ value = v->arch.hvm_svm.cpu_shadow_cr0;
+ break;
+ case 2:
+ value = vmcb->cr2;
+ break;
+ case 3:
+ value = (unsigned long) v->arch.hvm_svm.cpu_cr3;
+ break;
+ case 4:
+ value = vmcb->cr4;
+ break;
+ case 8:
+#if 0
+ value = vmcb->m_cr8;
+#else
+ ASSERT(0);
+#endif
+ break;
+
+ default:
+ __hvm_bug(regs);
+ }
+
+ set_reg(gp, value, regs, vmcb);
+
+ HVM_DBG_LOG(DBG_LEVEL_VMMU, "mov_from_cr: CR%d, value = %lx,", cr, value);
+}
+
+
+/*
+ * Write to control registers
+ */
+static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
+{
+ unsigned long value;
+ unsigned long old_cr;
+ struct vcpu *v = current;
+ struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+
+ ASSERT(vmcb);
+
+ value = get_reg(gpreg, regs, vmcb);
+
+ HVM_DBG_LOG(DBG_LEVEL_1, "mov_to_cr: CR%d, value = %lx,", cr, value);
+ HVM_DBG_LOG(DBG_LEVEL_1, "current = %lx,", (unsigned long) current);
+
+ switch (cr)
+ {
+ case 0:
+ return svm_set_cr0(value);
+
+ case 3:
+ {
+ unsigned long old_base_mfn, mfn;
+
+ /* If paging is not enabled yet, simply copy the value to CR3. */
+ if (!svm_paging_enabled(v)) {
+ v->arch.hvm_svm.cpu_cr3 = value;
+ break;
+ }
+ set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
+
+ /* We make a new one if the shadow does not exist. */
+ if (value == v->arch.hvm_svm.cpu_cr3)
+ {
+ /*
+ * This is simple TLB flush, implying the guest has
+ * removed some translation or changed page attributes.
+ * We simply invalidate the shadow.
+ */
+ mfn = get_mfn_from_pfn(value >> PAGE_SHIFT);
+ if (mfn != pagetable_get_pfn(v->arch.guest_table))
+ __hvm_bug(regs);
+ shadow_sync_all(v->domain);
+ }
+ else
+ {
+ /*
+ * If different, make a shadow. Check if the PDBR is valid
+ * first.
+ */
+ HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 value = %lx", value);
+ if (((value >> PAGE_SHIFT) > v->domain->max_pages)
+ || !VALID_MFN(mfn = get_mfn_from_pfn(value >> PAGE_SHIFT))
+ || !get_page(pfn_to_page(mfn), v->domain))
+ {
+ printk("Invalid CR3 value=%lx\n", value);
+ domain_crash_synchronous(); /* need to take a clean path */
+ }
+
+ old_base_mfn = pagetable_get_pfn(v->arch.guest_table);
+ v->arch.guest_table = mk_pagetable(mfn << PAGE_SHIFT);
+
+ if (old_base_mfn)
+ put_page(pfn_to_page(old_base_mfn));
+
+ update_pagetables(v);
+
+ /* arch.shadow_table should now hold the next CR3 for shadow*/
+ v->arch.hvm_svm.cpu_cr3 = value;
+ HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx", value);
+ vmcb->cr3 = pagetable_get_paddr(v->arch.shadow_table);
+ }
+ break;
+ }
+
+ case 4:
+ /* CR4 */
+ if (value & X86_CR4_PAE)
+ __hvm_bug(regs); /* not implemented */
+
+ old_cr = vmcb->cr4;
+
+ vmcb->cr4 = value;
+
+ /*
+ * Writing to CR4 to modify the PSE, PGE, or PAE flag invalidates
+ * all TLB entries except global entries.
+ */
+ if ((old_cr ^ value) & (X86_CR4_PSE | X86_CR4_PGE | X86_CR4_PAE))
+ {
+ set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
+ shadow_sync_all(v->domain);
+ }
+ break;
+
+ default:
+ printk("invalid cr: %d\n", cr);
+ __hvm_bug(regs);
+ }
+
+ return 1;
+}
+
+
+#define ARR_SIZE(x) (sizeof(x) / sizeof(x[0]))
+
+
+static int svm_cr_access(struct vcpu *v, unsigned int cr, unsigned int type,
+ struct cpu_user_regs *regs)
+{
+ struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+ unsigned int inst_len = 0;
+ unsigned int gpreg;
+ unsigned long value;
+ u8 buffer[6];
+ int result = 1;
+ enum instruction_index list_a[] = {INSTR_MOV2CR, INSTR_CLTS, INSTR_LMSW};
+ enum instruction_index list_b[] = {INSTR_MOVCR2, INSTR_SMSW};
+ enum instruction_index match;
+
+ ASSERT(vmcb);
+
+ inst_copy_from_guest(buffer, svm_rip2pointer(vmcb), sizeof(buffer));
+
+ if (type == TYPE_MOV_TO_CR)
+ {
+ inst_len = __get_instruction_length_from_list(vmcb, list_a,
+ ARR_SIZE(list_a), buffer, &match);
+ }
+ else
+ {
+ inst_len = __get_instruction_length_from_list(vmcb, list_b,
+ ARR_SIZE(list_b), buffer, &match);
+ }
+
+ HVM_DBG_LOG(DBG_LEVEL_1, "eip = %lx", (unsigned long) vmcb->rip);
+
+ switch (match)
+ {
+ case INSTR_MOV2CR:
+ gpreg = decode_src_reg(buffer[2]);
+ result = mov_to_cr(gpreg, cr, regs);
+ break;
+
+ case INSTR_MOVCR2:
+ gpreg = decode_src_reg(buffer[2]);
+ mov_from_cr(cr, gpreg, regs);
+ break;
+
+ case INSTR_CLTS:
+ clts();
+ setup_fpu(current);
+ vmcb->cr0 &= ~X86_CR0_TS; /* clear TS */
+ v->arch.hvm_svm.cpu_shadow_cr0 &= ~X86_CR0_TS; /* clear TS */
+ vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_NM;
+ break;
+
+ case INSTR_LMSW:
+ if (svm_dbg_on)
+ svm_dump_inst(svm_rip2pointer(vmcb));
+
+ gpreg = decode_src_reg(buffer[2]);
+ value = get_reg(gpreg, regs, vmcb) & 0xF;
+
+ if (svm_dbg_on)
+ printk("CR0-LMSW value=%lx, reg=%d, inst_len=%d\n", value, gpreg,
+ inst_len);
+
+ value = (v->arch.hvm_svm.cpu_shadow_cr0 & ~0xF) | value;
+
+ if (svm_dbg_on)
+ printk("CR0-LMSW CR0 - New value=%lx\n", value);
+
+ result = svm_set_cr0(value);
+ break;
+
+ case INSTR_SMSW:
+ svm_dump_inst(svm_rip2pointer(vmcb));
+ value = v->arch.hvm_svm.cpu_shadow_cr0;
+ gpreg = decode_src_reg(buffer[2]);
+ set_reg(gpreg, value, regs, vmcb);
+
+ if (svm_dbg_on)
+ printk("CR0-SMSW value=%lx, reg=%d, inst_len=%d\n", value, gpreg,
+ inst_len);
+ break;
+
+ default:
+ __hvm_bug(regs);
+ break;
+ }
+
+ ASSERT(inst_len);
+
+ __update_guest_eip(vmcb, inst_len);
+
+ return result;
+}
+
+static inline void svm_do_msr_access(struct vcpu *v, struct cpu_user_regs *regs)
+{
+ struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+ unsigned int inst_len;
+ int64_t tsc_sum;
+
+ ASSERT(vmcb);
+
+ HVM_DBG_LOG(DBG_LEVEL_1, "svm_do_msr_access: ecx=%lx, eax=%lx, edx=%lx, "
+ "exitinfo = %lx", (unsigned long)regs->ecx,
+ (unsigned long)regs->eax, (unsigned long)regs->edx,
+ (unsigned long)vmcb->exitinfo1);
+
+ /* is it a read? */
+ if (vmcb->exitinfo1 == 0)
+ {
+ inst_len = __get_instruction_length(vmcb, INSTR_RDMSR, NULL);
+
+ regs->edx = 0;
+ switch (regs->ecx)
+ {
+ case MSR_IA32_SYSENTER_CS:
+ regs->eax = vmcb->sysenter_cs;
+ break;
+ case MSR_IA32_SYSENTER_ESP:
+ regs->eax = vmcb->sysenter_esp;
+ break;
+ case MSR_IA32_SYSENTER_EIP:
+ regs->eax = vmcb->sysenter_eip;
+ break;
+ case MSR_IA32_TIME_STAMP_COUNTER:
+ __asm__ __volatile__("rdtsc" : "=a" (regs->eax), "=d" (regs->edx));
+ tsc_sum = regs->edx;
+ tsc_sum = (tsc_sum << 32) + regs->eax;
+ tsc_sum += (int64_t) vmcb->tsc_offset;
+ regs->eax = tsc_sum & 0xFFFFFFFF;
+ regs->edx = (tsc_sum >> 32) & 0xFFFFFFFF;
+ break;
+ default:
+ if (long_mode_do_msr_read(regs))
+ goto done;
+ rdmsr_user(regs->ecx, regs->eax, regs->edx);
+ break;
+ }
+ }
+ else
+ {
+ inst_len = __get_instruction_length(vmcb, INSTR_WRMSR, NULL);
+
+ switch (regs->ecx)
+ {
+ case MSR_IA32_SYSENTER_CS:
+ vmcb->sysenter_cs = regs->eax;
+ break;
+ case MSR_IA32_SYSENTER_ESP:
+ vmcb->sysenter_esp = regs->eax;
+ break;
+ case MSR_IA32_SYSENTER_EIP:
+ vmcb->sysenter_eip = regs->eax;
+ break;
+ default:
+ long_mode_do_msr_write(regs);
+ break;
+ }
+ }
+
+done:
+
+ HVM_DBG_LOG(DBG_LEVEL_1, "svm_do_msr_access returns: "
+ "ecx=%lx, eax=%lx, edx=%lx",
+ (unsigned long)regs->ecx, (unsigned long)regs->eax,
+ (unsigned long)regs->edx);
+
+ __update_guest_eip(vmcb, inst_len);
+}
+
+
+/*
+ * Need to use this exit to reschedule
+ */
+static inline void svm_vmexit_do_hlt(struct vmcb_struct *vmcb)
+{
+ struct vcpu *v = current;
+ struct hvm_virpit *vpit = &v->domain->arch.hvm_domain.vpit;
+ s_time_t next_pit = -1, next_wakeup;
+ unsigned int inst_len;
+
+ svm_stts(v);
+ inst_len = __get_instruction_length(vmcb, INSTR_HLT, NULL);
+ __update_guest_eip(vmcb, inst_len);
+
+ if ( !v->vcpu_id ) {
+ next_pit = get_pit_scheduled(v, vpit);
+ }
+ next_wakeup = get_apictime_scheduled(v);
+ if ( (next_pit != -1 && next_pit < next_wakeup) || next_wakeup == -1 ) {
+ next_wakeup = next_pit;
+ }
+ if ( next_wakeup != - 1 )
+ set_timer(&current->arch.hvm_svm.hlt_timer, next_wakeup);
+ do_sched_op(SCHEDOP_block, 0);
+}
+
+
+static inline void svm_vmexit_do_mwait(void)
+{
+ return;
+}
+
+
+#ifdef XEN_DEBUGGER
+static void svm_debug_save_cpu_user_regs(struct vmcb_struct *vmcb,
+ struct cpu_user_regs *regs)
+{
+ regs->eip = vmcb->rip;
+ regs->esp = vmcb->rsp;
+ regs->eflags = vmcb->rflags;
+
+ regs->xcs = vmcb->cs.sel;
+ regs->xds = vmcb->ds.sel;
+ regs->xes = vmcb->es.sel;
+ regs->xfs = vmcb->fs.sel;
+ regs->xgs = vmcb->gs.sel;
+ regs->xss = vmcb->ss.sel;
+}
+
+
+static void svm_debug_restore_cpu_user_regs(struct cpu_user_regs *regs)
+{
+ vmcb->ss.sel = regs->xss;
+ vmcb->rsp = regs->esp;
+ vmcb->rflags = regs->eflags;
+ vmcb->cs.sel = regs->xcs;
+ vmcb->rip = regs->eip;
+
+ vmcb->gs.sel = regs->xgs;
+ vmcb->fs.sel = regs->xfs;
+ vmcb->es.sel = regs->xes;
+ vmcb->ds.sel = regs->xds;
+}
+#endif
+
+
+void svm_handle_invlpg(const short invlpga, struct cpu_user_regs *regs)
+{
+ struct vcpu *v = current;
+ u8 opcode[MAX_INST_SIZE], prefix, length = MAX_INST_SIZE;
+ unsigned long g_vaddr;
+ unsigned int inst_len;
+ struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+
+ ASSERT(vmcb);
+ /*
+ * Unknown how many bytes the invlpg instruction will take. Use the
+ * maximum instruction length here
+ */
+ if (inst_copy_from_guest(opcode, svm_rip2pointer(vmcb), length) < length)
+ {
+ printk("svm_handle_invlpg (): Error reading memory %d bytes\n", length);
+ __hvm_bug(regs);
+ }
+
+ if (invlpga)
+ {
+ inst_len = __get_instruction_length(vmcb, INSTR_INVLPGA, opcode);
+ __update_guest_eip(vmcb, inst_len);
+
+ /*
+ * The address is implicit on this instruction At the moment, we don't
+ * use ecx (ASID) to identify individual guests pages
+ */
+ g_vaddr = regs->eax;
+ }
+ else
+ {
+ /* What about multiple prefix codes? */
+ prefix = (is_prefix(opcode[0])?opcode[0]:0);
+ inst_len = __get_instruction_length(vmcb, INSTR_INVLPG, opcode);
+
+ inst_len--;
+ length -= inst_len;
+
+ /*
+ * Decode memory operand of the instruction including ModRM, SIB, and
+ * displacement to get effecticve address and length in bytes. Assume
+ * the system in either 32- or 64-bit mode.
+ */
+ g_vaddr = get_effective_addr_modrm64(vmcb, regs, prefix,
+ &opcode[inst_len], &length);
+
+ inst_len += length;
+ __update_guest_eip (vmcb, inst_len);
+ }
+
+ /* Overkill, we may not this */
+ set_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
+ shadow_invlpg(v, g_vaddr);
+}
+
+
+/*
+ * Reset to realmode causes execution to start at 0xF000:0xFFF0 in
+ * 16-bit realmode. Basically, this mimics a processor reset.
+ *
+ * returns 0 on success, non-zero otherwise
+ */
+static int svm_do_vmmcall_reset_to_realmode(struct vcpu *v,
+ struct cpu_user_regs *regs)
+{
+ struct vmcb_struct *vmcb;
+
+ ASSERT(v);
+ ASSERT(regs);
+
+ vmcb = v->arch.hvm_svm.vmcb;
+
+ ASSERT(vmcb);
+
+ /* clear the vmcb and user regs */
+ memset(regs, 0, sizeof(struct cpu_user_regs));
+
+ /* VMCB Control */
+ vmcb->tsc_offset = 0;
+
+ /* VMCB State */
+ vmcb->cr0 = X86_CR0_ET | X86_CR0_PG;
+ v->arch.hvm_svm.cpu_shadow_cr0 = X86_CR0_ET;
+
+ vmcb->cr2 = 0;
+ vmcb->cr4 = 0;
+
+ /* This will jump to ROMBIOS */
+ vmcb->rip = 0xFFF0;
+
+ /* setup the segment registers and all their hidden states */
+ vmcb->cs.sel = 0xF000;
+ vmcb->cs.attributes.bytes = 0x089b;
+ vmcb->cs.limit = 0xffff;
+ vmcb->cs.base = 0x000F0000;
+
+ vmcb->ss.sel = 0x00;
+ vmcb->ss.attributes.bytes = 0x0893;
+ vmcb->ss.limit = 0xffff;
+ vmcb->ss.base = 0x00;
+
+ vmcb->ds.sel = 0x00;
+ vmcb->ds.attributes.bytes = 0x0893;
+ vmcb->ds.limit = 0xffff;
+ vmcb->ds.base = 0x00;
+
+ vmcb->es.sel = 0x00;
+ vmcb->es.attributes.bytes = 0x0893;
+ vmcb->es.limit = 0xffff;
+ vmcb->es.base = 0x00;
+
+ vmcb->fs.sel = 0x00;
+ vmcb->fs.attributes.bytes = 0x0893;
+ vmcb->fs.limit = 0xffff;
+ vmcb->fs.base = 0x00;
+
+ vmcb->gs.sel = 0x00;
+ vmcb->gs.attributes.bytes = 0x0893;
+ vmcb->gs.limit = 0xffff;
+ vmcb->gs.base = 0x00;
+
+ vmcb->ldtr.sel = 0x00;
+ vmcb->ldtr.attributes.bytes = 0x0000;
+ vmcb->ldtr.limit = 0x0;
+ vmcb->ldtr.base = 0x00;
+
+ vmcb->gdtr.sel = 0x00;
+ vmcb->gdtr.attributes.bytes = 0x0000;
+ vmcb->gdtr.limit = 0x0;
+ vmcb->gdtr.base = 0x00;
+
+ vmcb->tr.sel = 0;
+ vmcb->tr.attributes.bytes = 0;
+ vmcb->tr.limit = 0x0;
+ vmcb->tr.base = 0;
+
+ vmcb->idtr.sel = 0x00;
+ vmcb->idtr.attributes.bytes = 0x0000;
+ vmcb->idtr.limit = 0x3ff;
+ vmcb->idtr.base = 0x00;
+
+ vmcb->rax = 0;
+
+ return 0;
+}
+
+
+/*
+ * svm_do_vmmcall - SVM VMMCALL handler
+ *
+ * returns 0 on success, non-zero otherwise
+ */
+static int svm_do_vmmcall(struct vcpu *v, struct cpu_user_regs *regs)
+{
+ struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+ unsigned int inst_len;
+
+ ASSERT(vmcb);
+ ASSERT(regs);
+
+ inst_len = __get_instruction_length(vmcb, INSTR_VMCALL, NULL);
+
+ /* VMMCALL sanity check */
+ if (vmcb->cpl > get_vmmcall_cpl(regs->edi))
+ {
+ printf("VMMCALL CPL check failed\n");
+ return -1;
+ }
+
+ /* handle the request */
+ switch (regs->edi)
+ {
+ case VMMCALL_RESET_TO_REALMODE:
+ if (svm_do_vmmcall_reset_to_realmode(v, regs))
+ {
+ printf("svm_do_vmmcall_reset_to_realmode() failed\n");
+ return -1;
+ }
+
+ /* since we just reset the VMCB, return without adjusting the eip */
+ return 0;
+ case VMMCALL_DEBUG:
+ printf("DEBUG features not implemented yet\n");
+ break;
+ default:
+ break;
+ }
+
+ hvm_print_line(v, regs->eax); /* provides the current domain */
+
+ __update_guest_eip(vmcb, inst_len);
+ return 0;
+}
+
+
+void svm_dump_inst(unsigned long eip)
+{
+ u8 opcode[256];
+ unsigned long ptr;
+ int len;
+ int i;
+
+ ptr = eip & ~0xff;
+ len = 0;
+
+ if (hvm_copy(opcode, ptr, sizeof(opcode), HVM_COPY_IN))
+ len = sizeof(opcode);
+
+ printf("Code bytes around(len=%d) %lx:", len, eip);
+ for (i = 0; i < len; i++)
+ {
+ if ((i & 0x0f) == 0)
+ printf("\n%08lx:", ptr+i);
+
+ printf("%02x ", opcode[i]);
+ }
+
+ printf("\n");
+}
+
+
+void svm_dump_regs(const char *from, struct cpu_user_regs *regs)
+{
+ struct vcpu *v = current;
+ struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+ unsigned long pt = pagetable_get_paddr(v->arch.shadow_table);
+
+ printf("%s: guest registers from %s:\n", __func__, from);
+#if defined (__x86_64__)
+ printk("rax: %016lx rbx: %016lx rcx: %016lx\n",
+ regs->rax, regs->rbx, regs->rcx);
+ printk("rdx: %016lx rsi: %016lx rdi: %016lx\n",
+ regs->rdx, regs->rsi, regs->rdi);
+ printk("rbp: %016lx rsp: %016lx r8: %016lx\n",
+ regs->rbp, regs->rsp, regs->r8);
+ printk("r9: %016lx r10: %016lx r11: %016lx\n",
+ regs->r9, regs->r10, regs->r11);
+ printk("r12: %016lx r13: %016lx r14: %016lx\n",
+ regs->r12, regs->r13, regs->r14);
+ printk("r15: %016lx cr0: %016lx cr3: %016lx\n",
+ regs->r15, v->arch.hvm_svm.cpu_shadow_cr0, vmcb->cr3);
+#else
+ printf("eax: %08x, ebx: %08x, ecx: %08x, edx: %08x\n",
+ regs->eax, regs->ebx, regs->ecx, regs->edx);
+ printf("edi: %08x, esi: %08x, ebp: %08x, esp: %08x\n",
+ regs->edi, regs->esi, regs->ebp, regs->esp);
+ printf("%s: guest cr0: %lx\n", __func__,
+ v->arch.hvm_svm.cpu_shadow_cr0);
+ printf("guest CR3 = %llx\n", vmcb->cr3);
+#endif
+ printf("%s: pt = %lx\n", __func__, pt);
+}
+
+
+void svm_dump_host_regs(const char *from)
+{
+ struct vcpu *v = current;
+ unsigned long pt = pt = pagetable_get_paddr(v->arch.monitor_table);
+ unsigned long cr3, cr0;
+ printf("Host registers at %s\n", from);
+
+ __asm__ __volatile__ ("\tmov %%cr0,%0\n"
+ "\tmov %%cr3,%1\n"
+ : "=r" (cr0), "=r"(cr3));
+ printf("%s: pt = %lx, cr3 = %lx, cr0 = %lx\n", __func__, pt, cr3, cr0);
+}
+
+#ifdef SVM_EXTRA_DEBUG
+static char *exit_reasons[] = {
+ [VMEXIT_CR0_READ] = "CR0_READ",
+ [VMEXIT_CR1_READ] = "CR1_READ",
+ [VMEXIT_CR2_READ] = "CR2_READ",
+ [VMEXIT_CR3_READ] = "CR3_READ",
+ [VMEXIT_CR4_READ] = "CR4_READ",
+ [VMEXIT_CR5_READ] = "CR5_READ",
+ [VMEXIT_CR6_READ] = "CR6_READ",
+ [VMEXIT_CR7_READ] = "CR7_READ",
+ [VMEXIT_CR8_READ] = "CR8_READ",
+ [VMEXIT_CR9_READ] = "CR9_READ",
+ [VMEXIT_CR10_READ] = "CR10_READ",
+ [VMEXIT_CR11_READ] = "CR11_READ",
+ [VMEXIT_CR12_READ] = "CR12_READ",
+ [VMEXIT_CR13_READ] = "CR13_READ",
+ [VMEXIT_CR14_READ] = "CR14_READ",
+ [VMEXIT_CR15_READ] = "CR15_READ",
+ [VMEXIT_CR0_WRITE] = "CR0_WRITE",
+ [VMEXIT_CR1_WRITE] = "CR1_WRITE",
+ [VMEXIT_CR2_WRITE] = "CR2_WRITE",
+ [VMEXIT_CR3_WRITE] = "CR3_WRITE",
+ [VMEXIT_CR4_WRITE] = "CR4_WRITE",
+ [VMEXIT_CR5_WRITE] = "CR5_WRITE",
+ [VMEXIT_CR6_WRITE] = "CR6_WRITE",
+ [VMEXIT_CR7_WRITE] = "CR7_WRITE",
+ [VMEXIT_CR8_WRITE] = "CR8_WRITE",
+ [VMEXIT_CR9_WRITE] = "CR9_WRITE",
+ [VMEXIT_CR10_WRITE] = "CR10_WRITE",
+ [VMEXIT_CR11_WRITE] = "CR11_WRITE",
+ [VMEXIT_CR12_WRITE] = "CR12_WRITE",
+ [VMEXIT_CR13_WRITE] = "CR13_WRITE",
+ [VMEXIT_CR14_WRITE] = "CR14_WRITE",
+ [VMEXIT_CR15_WRITE] = "CR15_WRITE",
+ [VMEXIT_DR0_READ] = "DR0_READ",
+ [VMEXIT_DR1_READ] = "DR1_READ",
+ [VMEXIT_DR2_READ] = "DR2_READ",
+ [VMEXIT_DR3_READ] = "DR3_READ",
+ [VMEXIT_DR4_READ] = "DR4_READ",
+ [VMEXIT_DR5_READ] = "DR5_READ",
+ [VMEXIT_DR6_READ] = "DR6_READ",
+ [VMEXIT_DR7_READ] = "DR7_READ",
+ [VMEXIT_DR8_READ] = "DR8_READ",
+ [VMEXIT_DR9_READ] = "DR9_READ",
+ [VMEXIT_DR10_READ] = "DR10_READ",
+ [VMEXIT_DR11_READ] = "DR11_READ",
+ [VMEXIT_DR12_READ] = "DR12_READ",
+ [VMEXIT_DR13_READ] = "DR13_READ",
+ [VMEXIT_DR14_READ] = "DR14_READ",
+ [VMEXIT_DR15_READ] = "DR15_READ",
+ [VMEXIT_DR0_WRITE] = "DR0_WRITE",
+ [VMEXIT_DR1_WRITE] = "DR1_WRITE",
+ [VMEXIT_DR2_WRITE] = "DR2_WRITE",
+ [VMEXIT_DR3_WRITE] = "DR3_WRITE",
+ [VMEXIT_DR4_WRITE] = "DR4_WRITE",
+ [VMEXIT_DR5_WRITE] = "DR5_WRITE",
+ [VMEXIT_DR6_WRITE] = "DR6_WRITE",
+ [VMEXIT_DR7_WRITE] = "DR7_WRITE",
+ [VMEXIT_DR8_WRITE] = "DR8_WRITE",
+ [VMEXIT_DR9_WRITE] = "DR9_WRITE",
+ [VMEXIT_DR10_WRITE] = "DR10_WRITE",
+ [VMEXIT_DR11_WRITE] = "DR11_WRITE",
+ [VMEXIT_DR12_WRITE] = "DR12_WRITE",
+ [VMEXIT_DR13_WRITE] = "DR13_WRITE",
+ [VMEXIT_DR14_WRITE] = "DR14_WRITE",
+ [VMEXIT_DR15_WRITE] = "DR15_WRITE",
+ [VMEXIT_EXCEPTION_DE] = "EXCEPTION_DE",
+ [VMEXIT_EXCEPTION_DB] = "EXCEPTION_DB",
+ [VMEXIT_EXCEPTION_NMI] = "EXCEPTION_NMI",
+ [VMEXIT_EXCEPTION_BP] = "EXCEPTION_BP",
+ [VMEXIT_EXCEPTION_OF] = "EXCEPTION_OF",
+ [VMEXIT_EXCEPTION_BR] = "EXCEPTION_BR",
+ [VMEXIT_EXCEPTION_UD] = "EXCEPTION_UD",
+ [VMEXIT_EXCEPTION_NM] = "EXCEPTION_NM",
+ [VMEXIT_EXCEPTION_DF] = "EXCEPTION_DF",
+ [VMEXIT_EXCEPTION_09] = "EXCEPTION_09",
+ [VMEXIT_EXCEPTION_TS] = "EXCEPTION_TS",
+ [VMEXIT_EXCEPTION_NP] = "EXCEPTION_NP",
+ [VMEXIT_EXCEPTION_SS] = "EXCEPTION_SS",
+ [VMEXIT_EXCEPTION_GP] = "EXCEPTION_GP",
+ [VMEXIT_EXCEPTION_PF] = "EXCEPTION_PF",
+ [VMEXIT_EXCEPTION_15] = "EXCEPTION_15",
+ [VMEXIT_EXCEPTION_MF] = "EXCEPTION_MF",
+ [VMEXIT_EXCEPTION_AC] = "EXCEPTION_AC",
+ [VMEXIT_EXCEPTION_MC] = "EXCEPTION_MC",
+ [VMEXIT_EXCEPTION_XF] = "EXCEPTION_XF",
+ [VMEXIT_INTR] = "INTR",
+ [VMEXIT_NMI] = "NMI",
+ [VMEXIT_SMI] = "SMI",
+ [VMEXIT_INIT] = "INIT",
+ [VMEXIT_VINTR] = "VINTR",
+ [VMEXIT_CR0_SEL_WRITE] = "CR0_SEL_WRITE",
+ [VMEXIT_IDTR_READ] = "IDTR_READ",
+ [VMEXIT_GDTR_READ] = "GDTR_READ",
+ [VMEXIT_LDTR_READ] = "LDTR_READ",
+ [VMEXIT_TR_READ] = "TR_READ",
+ [VMEXIT_IDTR_WRITE] = "IDTR_WRITE",
+ [VMEXIT_GDTR_WRITE] = "GDTR_WRITE",
+ [VMEXIT_LDTR_WRITE] = "LDTR_WRITE",
+ [VMEXIT_TR_WRITE] = "TR_WRITE",
+ [VMEXIT_RDTSC] = "RDTSC",
+ [VMEXIT_RDPMC] = "RDPMC",
+ [VMEXIT_PUSHF] = "PUSHF",
+ [VMEXIT_POPF] = "POPF",
+ [VMEXIT_CPUID] = "CPUID",
+ [VMEXIT_RSM] = "RSM",
+ [VMEXIT_IRET] = "IRET",
+ [VMEXIT_SWINT] = "SWINT",
+ [VMEXIT_INVD] = "INVD",
+ [VMEXIT_PAUSE] = "PAUSE",
+ [VMEXIT_HLT] = "HLT",
+ [VMEXIT_INVLPG] = "INVLPG",
+ [VMEXIT_INVLPGA] = "INVLPGA",
+ [VMEXIT_IOIO] = "IOIO",
+ [VMEXIT_MSR] = "MSR",
+ [VMEXIT_TASK_SWITCH] = "TASK_SWITCH",
+ [VMEXIT_FERR_FREEZE] = "FERR_FREEZE",
+ [VMEXIT_SHUTDOWN] = "SHUTDOWN",
+ [VMEXIT_VMRUN] = "VMRUN",
+ [VMEXIT_VMMCALL] = "VMMCALL",
+ [VMEXIT_VMLOAD] = "VMLOAD",
+ [VMEXIT_VMSAVE] = "VMSAVE",
+ [VMEXIT_STGI] = "STGI",
+ [VMEXIT_CLGI] = "CLGI",
+ [VMEXIT_SKINIT] = "SKINIT",
+ [VMEXIT_RDTSCP] = "RDTSCP",
+ [VMEXIT_ICEBP] = "ICEBP",
+ [VMEXIT_NPF] = "NPF"
+};
+#endif /* SVM_EXTRA_DEBUG */
+
+#ifdef SVM_WALK_GUEST_PAGES
+void walk_shadow_and_guest_pt(unsigned long gva)
+{
+ l2_pgentry_t gpde;
+ l2_pgentry_t spde;
+ l1_pgentry_t gpte;
+ l1_pgentry_t spte;
+ struct vcpu *v = current;
+ struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+ unsigned long gpa;
+
+ gpa = gva_to_gpa( gva );
+ printk( "gva = %lx, gpa=%lx, gCR3=%x\n", gva, gpa, (u32)vmcb->cr3 );
+ if( !svm_paging_enabled(v) || mmio_space( gpa ) )
+ {
+ return;
+ }
+
+ /* let's dump the guest and shadow page info */
+
+ __guest_get_l2e(v, gva, &gpde);
+ printk( "G-PDE = %x, flags=%x\n", gpde.l2, l2e_get_flags(gpde) );
+ __shadow_get_l2e( v, gva, &spde );
+ printk( "S-PDE = %x, flags=%x\n", spde.l2, l2e_get_flags(spde) );
+
+ if ( unlikely(!(l2e_get_flags(gpde) & _PAGE_PRESENT)) )
+ return;
+
+ spte = l1e_empty();
+
+ // This is actually overkill - we only need to make sure the hl2 is in-sync.
+ shadow_sync_va(v, gva);
+
+ gpte.l1 = 0;
+ __copy_from_user(&gpte, &linear_pg_table[ l1_linear_offset(gva) ], sizeof(gpte) );
+ printk( "G-PTE = %x, flags=%x\n", gpte.l1, l1e_get_flags(gpte) );
+ __copy_from_user( &spte, &phys_to_machine_mapping[ l1e_get_pfn( gpte ) ], sizeof(spte) );
+ printk( "S-PTE = %x, flags=%x\n", spte.l1, l1e_get_flags(spte));
+}
+#endif /* SVM_WALK_GUEST_PAGES */
+
+asmlinkage void svm_vmexit_handler(struct cpu_user_regs regs)
+{
+ unsigned int exit_reason;
+ unsigned long eip;
+ struct vcpu *v = current;
+ int error;
+ int do_debug = 0;
+ struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+
+ ASSERT(vmcb);
+
+ exit_reason = vmcb->exitcode;
+ save_svm_cpu_user_regs(v, &regs);
+ v->arch.hvm_svm.injecting_event = 0;
+
+ vmcb->tlb_control = 0;
+
+#ifdef SVM_EXTRA_DEBUG
+{
+#if defined(__i386__)
+#define rip eip
+#endif
+
+ static unsigned long intercepts_counter = 0;
+
+ if (svm_dbg_on && exit_reason == VMEXIT_EXCEPTION_PF)
+ {
+ if (svm_paging_enabled(v) && !mmio_space(gva_to_gpa(vmcb->exitinfo2)))
+ {
+ printk("I%08ld,ExC=%s(%d),IP=%x:%llx,I1=%llx,I2=%llx,INT=%llx\n",
+ intercepts_counter,
+ exit_reasons[exit_reason], exit_reason, regs.cs,
+ (unsigned long long) regs.rip,
+ (unsigned long long) vmcb->exitinfo1,
+ (unsigned long long) vmcb->exitinfo2,
+ (unsigned long long) vmcb->exitintinfo.bytes);
+ }
+ }
+ else if (svm_dbg_on
+ && exit_reason != VMEXIT_IOIO
+ && exit_reason != VMEXIT_INTR)
+ {
+
+ if (exit_reasons[exit_reason])
+ {
+ printk("I%08ld,ExC=%s(%d),IP=%x:%llx,I1=%llx,I2=%llx,INT=%llx\n",
+ intercepts_counter,
+ exit_reasons[exit_reason], exit_reason, regs.cs,
+ (unsigned long long) regs.rip,
+ (unsigned long long) vmcb->exitinfo1,
+ (unsigned long long) vmcb->exitinfo2,
+ (unsigned long long) vmcb->exitintinfo.bytes);
+ }
+ else
+ {
+ printk("I%08ld,ExC=%d(0x%x),IP=%x:%llx,I1=%llx,I2=%llx,INT=%llx\n",
+ intercepts_counter, exit_reason, exit_reason, regs.cs,
+ (unsigned long long) regs.rip,
+ (unsigned long long) vmcb->exitinfo1,
+ (unsigned long long) vmcb->exitinfo2,
+ (unsigned long long) vmcb->exitintinfo.bytes);
+ }
+ }
+
+#ifdef SVM_WALK_GUEST_PAGES
+ if( exit_reason == VMEXIT_EXCEPTION_PF && ( ( vmcb->exitinfo2 == vmcb->rip )|| vmcb->exitintinfo.bytes) )
+ {
+ if (svm_paging_enabled(v) && !mmio_space(gva_to_gpa(vmcb->exitinfo2)))
+ walk_shadow_and_guest_pt( vmcb->exitinfo2 );
+ }
+#endif
+
+ intercepts_counter++;
+
+#if 0
+ if (svm_dbg_on)
+ do_debug = svm_do_debugout(exit_reason);
+#endif
+
+ if (do_debug)
+ {
+ printk("%s:+ guest_table = 0x%08x, monitor_table = 0x%08x, "
+ "shadow_table = 0x%08x\n",
+ __func__,
+ (int) v->arch.guest_table.pfn,
+ (int) v->arch.monitor_table.pfn,
+ (int) v->arch.shadow_table.pfn);
+
+ svm_dump_vmcb(__func__, vmcb);
+ svm_dump_regs(__func__, &regs);
+ svm_dump_inst(svm_rip2pointer(vmcb));
+ }
+
+#if defined(__i386__)
+#undef rip
+#endif
+
+}
+#endif /* SVM_EXTRA_DEBUG */
+
+ if (exit_reason == -1)
+ {
+ printk("%s: exit_reason == -1 - Did someone clobber the VMCB\n",
+ __func__);
+ BUG();
+ domain_crash_synchronous();
+ }
+
+ perfc_incra(vmexits, exit_reason);
+ eip = vmcb->rip;
+
+#ifdef SVM_EXTRA_DEBUG
+ if (do_debug)
+ {
+ printk("eip = %lx, exit_reason = %d (0x%x)\n",
+ eip, exit_reason, exit_reason);
+ }
+#endif /* SVM_EXTRA_DEBUG */
+
+ TRACE_3D(TRC_VMX_VMEXIT, v->domain->domain_id, eip, exit_reason);
+
+ switch (exit_reason)
+ {
+ case VMEXIT_EXCEPTION_DB:
+ {
+#ifdef XEN_DEBUGGER
+ svm_debug_save_cpu_user_regs(&regs);
+ pdb_handle_exception(1, &regs, 1);
+ svm_debug_restore_cpu_user_regs(&regs);
+#else
+ svm_store_cpu_user_regs(&regs, v);
+ domain_pause_for_debugger();
+ do_sched_op(SCHEDOP_yield, 0);
+#endif
+ }
+ break;
+
+ case VMEXIT_NMI:
+ do_nmi(&regs, 0);
+ break;
+
+#ifdef XEN_DEBUGGER
+ case VMEXIT_EXCEPTION_BP:
+ svm_debug_save_cpu_user_regs(&regs);
+ pdb_handle_exception(3, &regs, 1);
+ svm_debug_restore_cpu_user_regs(&regs);
+ break;
+#endif
+
+ case VMEXIT_EXCEPTION_NM:
+ svm_do_no_device_fault(vmcb);
+ break;
+
+ case VMEXIT_EXCEPTION_GP:
+ /* This should probably not be trapped in the future */
+ regs.error_code = vmcb->exitinfo1;
+ v->arch.hvm_svm.injecting_event = 1;
+ svm_do_general_protection_fault(v, &regs);
+ break;
+
+ case VMEXIT_EXCEPTION_PF:
+ {
+ unsigned long va;
+ va = vmcb->exitinfo2;
+ regs.error_code = vmcb->exitinfo1;
+ HVM_DBG_LOG(DBG_LEVEL_VMMU,
+ "eax=%lx, ebx=%lx, ecx=%lx, edx=%lx, esi=%lx, edi=%lx",
+ (unsigned long)regs.eax, (unsigned long)regs.ebx,
+ (unsigned long)regs.ecx, (unsigned long)regs.edx,
+ (unsigned long)regs.esi, (unsigned long)regs.edi);
+
+ v->arch.hvm_vcpu.mmio_op.inst_decoder_regs = &regs;
+
+//printk("PF1\n");
+ if (!(error = svm_do_page_fault(va, &regs)))
+ {
+ v->arch.hvm_svm.injecting_event = 1;
+ /* Inject #PG using Interruption-Information Fields */
+ vmcb->eventinj.bytes = 0;
+ vmcb->eventinj.fields.v = 1;
+ vmcb->eventinj.fields.ev = 1;
+ vmcb->eventinj.fields.errorcode = regs.error_code;
+ vmcb->eventinj.fields.type = EVENTTYPE_EXCEPTION;
+ vmcb->eventinj.fields.vector = TRAP_page_fault;
+ v->arch.hvm_svm.cpu_cr2 = va;
+ vmcb->cr2 = va;
+ TRACE_3D(TRC_VMX_INT, v->domain->domain_id,
+ VMEXIT_EXCEPTION_PF, va);
+ }
+ break;
+ }
+
+ case VMEXIT_EXCEPTION_DF:
+ printk("Guest double fault");
+ BUG();
+ break;
+
+ case VMEXIT_INTR:
+ svm_stts(v);
+ raise_softirq(SCHEDULE_SOFTIRQ);
+ break;
+
+ case VMEXIT_GDTR_WRITE:
+ printk("WRITE to GDTR\n");
+ break;
+
+ case VMEXIT_TASK_SWITCH:
+ __hvm_bug(&regs);
+ break;
+
+ case VMEXIT_CPUID:
+ svm_vmexit_do_cpuid(vmcb, regs.eax, &regs);
+ break;
+
+ case VMEXIT_HLT:
+ svm_vmexit_do_hlt(vmcb);
+ break;
+
+ case VMEXIT_INVLPG:
+ svm_handle_invlpg(0, &regs);
+ break;
+
+ case VMEXIT_INVLPGA:
+ svm_handle_invlpg(1, &regs);
+ break;
+
+ case VMEXIT_VMMCALL:
+ svm_do_vmmcall(v, &regs);
+ break;
+
+ case VMEXIT_CR0_READ:
+ svm_cr_access(v, 0, TYPE_MOV_FROM_CR, &regs);
+ break;
+
+ case VMEXIT_CR2_READ:
+ svm_cr_access(v, 2, TYPE_MOV_FROM_CR, &regs);
+ break;
+
+ case VMEXIT_CR3_READ:
+ svm_cr_access(v, 3, TYPE_MOV_FROM_CR, &regs);
+ break;
+
+ case VMEXIT_CR4_READ:
+ svm_cr_access(v, 4, TYPE_MOV_FROM_CR, &regs);
+ break;
+
+ case VMEXIT_CR8_READ:
+ svm_cr_access(v, 8, TYPE_MOV_FROM_CR, &regs);
+ break;
+
+ case VMEXIT_CR0_WRITE:
+ svm_cr_access(v, 0, TYPE_MOV_TO_CR, &regs);
+ break;
+
+ case VMEXIT_CR2_WRITE:
+ svm_cr_access(v, 2, TYPE_MOV_TO_CR, &regs);
+ break;
+
+ case VMEXIT_CR3_WRITE:
+ svm_cr_access(v, 3, TYPE_MOV_TO_CR, &regs);
+ break;
+
+ case VMEXIT_CR4_WRITE:
+ svm_cr_access(v, 4, TYPE_MOV_TO_CR, &regs);
+ break;
+
+ case VMEXIT_CR8_WRITE:
+ svm_cr_access(v, 8, TYPE_MOV_TO_CR, &regs);
+ break;
+
+ case VMEXIT_DR0_READ:
+ svm_dr_access(v, 0, TYPE_MOV_FROM_DR, &regs);
+ break;
+
+ case VMEXIT_DR1_READ:
+ svm_dr_access(v, 1, TYPE_MOV_FROM_DR, &regs);
+ break;
+
+ case VMEXIT_DR2_READ:
+ svm_dr_access(v, 2, TYPE_MOV_FROM_DR, &regs);
+ break;
+
+ case VMEXIT_DR3_READ:
+ svm_dr_access(v, 3, TYPE_MOV_FROM_DR, &regs);
+ break;
+
+ case VMEXIT_DR6_READ:
+ svm_dr_access(v, 6, TYPE_MOV_FROM_DR, &regs);
+ break;
+
+ case VMEXIT_DR7_READ:
+ svm_dr_access(v, 7, TYPE_MOV_FROM_DR, &regs);
+ break;
+
+ case VMEXIT_DR0_WRITE:
+ svm_dr_access(v, 0, TYPE_MOV_TO_DR, &regs);
+ break;
+
+ case VMEXIT_DR1_WRITE:
+ svm_dr_access(v, 1, TYPE_MOV_TO_DR, &regs);
+ break;
+
+ case VMEXIT_DR2_WRITE:
+ svm_dr_access(v, 2, TYPE_MOV_TO_DR, &regs);
+ break;
+
+ case VMEXIT_DR3_WRITE:
+ svm_dr_access(v, 3, TYPE_MOV_TO_DR, &regs);
+ break;
+
+ case VMEXIT_DR6_WRITE:
+ svm_dr_access(v, 6, TYPE_MOV_TO_DR, &regs);
+ break;
+
+ case VMEXIT_DR7_WRITE:
+ svm_dr_access(v, 7, TYPE_MOV_TO_DR, &regs);
+ break;
+
+ case VMEXIT_IOIO:
+ svm_io_instruction(v, &regs);
+ break;
+
+ case VMEXIT_MSR:
+ svm_do_msr_access(v, &regs);
+ break;
+
+ case VMEXIT_SHUTDOWN:
+ printk("Guest shutdown exit\n");
+ domain_crash_synchronous();
+ break;
+
+ default:
+ printk("unexpected VMEXIT: exit reason = 0x%x, exitinfo1 = %llx, "
+ "exitinfo2 = %llx\n", exit_reason,
+ (unsigned long long)vmcb->exitinfo1,
+ (unsigned long long)vmcb->exitinfo2);
+ __hvm_bug(&regs); /* should not happen */
+ break;
+ }
+
+#ifdef SVM_EXTRA_DEBUG
+ if (do_debug)
+ {
+ printk("%s: Done switch on vmexit_code\n", __func__);
+ svm_dump_regs(__func__, &regs);
+ }
+
+ if (do_debug)
+ {
+ printk("vmexit_handler():- guest_table = 0x%08x, "
+ "monitor_table = 0x%08x, shadow_table = 0x%08x\n",
+ (int)v->arch.guest_table.pfn,
+ (int)v->arch.monitor_table.pfn,
+ (int)v->arch.shadow_table.pfn);
+ printk("svm_vmexit_handler: Returning\n");
+ }
+#endif
+
+ return;
+}
+
+asmlinkage void svm_load_cr2(void)
+{
+ struct vcpu *v = current;
+
+ local_irq_disable();
+#ifdef __i386__
+ asm volatile("movl %0,%%cr2": :"r" (v->arch.hvm_svm.cpu_cr2));
+#else
+ asm volatile("movq %0,%%cr2": :"r" (v->arch.hvm_svm.cpu_cr2));
+#endif
+}
+
+asmlinkage void svm_asid(void)
+{
+ struct vcpu *v = current;
+ struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+ int core = smp_processor_id();
+ /*
+ * if need to assign new asid or if switching cores,
+ * then retire asid for old core, and assign new for new core.
+ */
+ if( svm_dbg_on)
+ printk("old core %d new core %d\n",(int)v->arch.hvm_svm.core,(int)core);
+
+ if( test_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags) ||
+ (v->arch.hvm_svm.core != core)) {
+ if(!asidpool_assign_next(vmcb, 1,
+ v->arch.hvm_svm.core, core)) {
+ BUG();
+ }
+ }
+ clear_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
+}
+#endif /* CONFIG_SVM */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/x86/hvm/svm/vmcb.c b/xen/arch/x86/hvm/svm/vmcb.c
new file mode 100644
index 0000000000..c528ed1805
--- /dev/null
+++ b/xen/arch/x86/hvm/svm/vmcb.c
@@ -0,0 +1,605 @@
+/*
+ * vmcb.c: VMCB management
+ * Copyright (c) 2005, AMD Corporation.
+ * Copyright (c) 2004, Intel 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 <xen/config.h>
+#include <xen/init.h>
+#include <xen/mm.h>
+#include <xen/lib.h>
+#include <xen/errno.h>
+#include <xen/shadow.h>
+#include <asm/cpufeature.h>
+#include <asm/processor.h>
+#include <asm/msr.h>
+#include <asm/hvm/hvm.h>
+#include <asm/hvm/io.h>
+#include <asm/hvm/support.h>
+#include <asm/hvm/svm/svm.h>
+#include <asm/hvm/svm/intr.h>
+#include <xen/event.h>
+#include <xen/kernel.h>
+#include <xen/domain_page.h>
+
+#ifdef CONFIG_SVM
+
+extern int svm_dbg_on;
+extern int asidpool_assign_next( struct vmcb_struct *vmcb, int retire_current,
+ int oldcore, int newcore);
+
+#define round_pgdown(_p) ((_p)&PAGE_MASK) /* coped from domain.c */
+
+#define GUEST_SEGMENT_LIMIT 0xffffffff
+
+#define IOPM_SIZE (12 * 1024)
+#define MSRPM_SIZE (8 * 1024)
+
+struct vmcb_struct *alloc_vmcb(void)
+{
+ struct vmcb_struct *vmcb = NULL;
+ unsigned int order;
+ order = get_order_from_bytes(sizeof(struct vmcb_struct));
+ ASSERT(order >= 0);
+ vmcb = alloc_xenheap_pages(order);
+ ASSERT(vmcb);
+
+ if (vmcb)
+ memset(vmcb, 0, sizeof(struct vmcb_struct));
+
+ return vmcb;
+}
+
+
+void free_vmcb(struct vmcb_struct *vmcb)
+{
+ unsigned int order;
+
+ order = get_order_from_bytes(sizeof(struct vmcb_struct));
+ ASSERT(vmcb);
+
+ if (vmcb)
+ free_xenheap_pages(vmcb, order);
+}
+
+
+struct host_save_area *alloc_host_save_area(void)
+{
+ unsigned int order = 0;
+ struct host_save_area *hsa = NULL;
+
+ hsa = alloc_xenheap_pages(order);
+ ASSERT(hsa);
+
+ if (hsa)
+ memset(hsa, 0, PAGE_SIZE);
+
+ return hsa;
+}
+
+
+void free_host_save_area(struct host_save_area *hsa)
+{
+ unsigned int order;
+
+ order = get_order_from_bytes(PAGE_SIZE);
+ ASSERT(hsa);
+
+ if (hsa)
+ free_xenheap_pages(hsa, order);
+}
+
+
+/* Set up intercepts to exit the guest into the hypervisor when we want it. */
+static int construct_vmcb_controls(struct arch_svm_struct *arch_svm)
+{
+ struct vmcb_struct *vmcb;
+ u32 *iopm;
+ u32 *msrpm;
+
+ vmcb = arch_svm->vmcb;
+
+ ASSERT(vmcb);
+
+ /* mask off all general 1 intercepts except those listed here */
+ vmcb->general1_intercepts =
+ ~(GENERAL1_INTERCEPT_CR0_SEL_WRITE | GENERAL1_INTERCEPT_VINTR |
+ GENERAL1_INTERCEPT_IDTR_READ | GENERAL1_INTERCEPT_IDTR_WRITE |
+ GENERAL1_INTERCEPT_GDTR_READ | GENERAL1_INTERCEPT_GDTR_WRITE |
+ GENERAL1_INTERCEPT_LDTR_READ | GENERAL1_INTERCEPT_LDTR_WRITE |
+ GENERAL1_INTERCEPT_TR_READ | GENERAL1_INTERCEPT_TR_WRITE |
+ GENERAL1_INTERCEPT_RDTSC | GENERAL1_INTERCEPT_PUSHF |
+ GENERAL1_INTERCEPT_SWINT | GENERAL1_INTERCEPT_POPF |
+ GENERAL1_INTERCEPT_IRET | GENERAL1_INTERCEPT_PAUSE |
+ GENERAL1_INTERCEPT_TASK_SWITCH
+ );
+
+ /* turn on the general 2 intercepts */
+ vmcb->general2_intercepts =
+ GENERAL2_INTERCEPT_VMRUN | GENERAL2_INTERCEPT_VMMCALL |
+ GENERAL2_INTERCEPT_VMLOAD | GENERAL2_INTERCEPT_VMSAVE |
+ GENERAL2_INTERCEPT_STGI | GENERAL2_INTERCEPT_CLGI |
+ GENERAL2_INTERCEPT_SKINIT | GENERAL2_INTERCEPT_RDTSCP;
+
+ /* read or write all debug registers 0 - 15 */
+ vmcb->dr_intercepts = 0;
+
+ /* RD/WR all control registers 0 - 15, but not read CR2 */
+ vmcb->cr_intercepts = ~(CR_INTERCEPT_CR2_READ | CR_INTERCEPT_CR2_WRITE);
+
+ /* The following is for I/O and MSR permision map */
+ iopm = alloc_xenheap_pages(get_order_from_bytes(IOPM_SIZE));
+
+ ASSERT(iopm);
+ memset(iopm, 0xff, IOPM_SIZE);
+ clear_bit(PC_DEBUG_PORT, iopm);
+ msrpm = alloc_xenheap_pages(get_order_from_bytes(MSRPM_SIZE));
+
+ ASSERT(msrpm);
+ memset(msrpm, 0xff, MSRPM_SIZE);
+
+ arch_svm->iopm = iopm;
+ arch_svm->msrpm = msrpm;
+
+ vmcb->iopm_base_pa = (u64) virt_to_phys(iopm);
+ vmcb->msrpm_base_pa = (u64) virt_to_phys(msrpm);
+
+ return 0;
+}
+
+
+/*
+ * modify guest eflags and execption bitmap for gdb
+ */
+int svm_modify_vmcb(struct vcpu *v, struct cpu_user_regs *regs)
+{
+ int error;
+ if ((error = load_vmcb(&v->arch.hvm_svm, v->arch.hvm_svm.host_save_pa)))
+ {
+ printk("svm_modify_vmcb: load_vmcb failed: VMCB = %lx\n",
+ (unsigned long) v->arch.hvm_svm.host_save_pa);
+ return -EINVAL;
+ }
+ svm_load_cpu_user_regs(v,regs);
+ return 0;
+}
+
+
+/*
+ * Initially set the same environement as host.
+ */
+static int construct_init_vmcb_guest(struct arch_svm_struct *arch_svm,
+ struct cpu_user_regs *regs )
+{
+ int error = 0;
+ unsigned long crn;
+ segment_attributes_t attrib;
+ unsigned long dr7;
+ unsigned long eflags;
+ unsigned long shadow_cr;
+ struct vmcb_struct *vmcb = arch_svm->vmcb;
+ struct Xgt_desc_struct desc;
+
+ /* Allows IRQs to be shares */
+ vmcb->vintr.fields.intr_masking = 1;
+
+ /* Set up event injection entry in VMCB. Just clear it. */
+ vmcb->eventinj.bytes = 0;
+
+ /* TSC */
+ vmcb->tsc_offset = 0;
+
+ vmcb->cs.sel = regs->cs;
+ vmcb->es.sel = regs->es;
+ vmcb->ss.sel = regs->ss;
+ vmcb->ds.sel = regs->ds;
+ vmcb->fs.sel = regs->fs;
+ vmcb->gs.sel = regs->gs;
+
+ /* Guest segment Limits. 64K for real mode*/
+ vmcb->cs.limit = GUEST_SEGMENT_LIMIT;
+ vmcb->es.limit = GUEST_SEGMENT_LIMIT;
+ vmcb->ss.limit = GUEST_SEGMENT_LIMIT;
+ vmcb->ds.limit = GUEST_SEGMENT_LIMIT;
+ vmcb->fs.limit = GUEST_SEGMENT_LIMIT;
+ vmcb->gs.limit = GUEST_SEGMENT_LIMIT;
+
+ /* Base address for segments */
+ vmcb->cs.base = 0;
+ vmcb->es.base = 0;
+ vmcb->ss.base = 0;
+ vmcb->ds.base = 0;
+ vmcb->fs.base = 0;
+ vmcb->gs.base = 0;
+
+ __asm__ __volatile__ ("sidt (%0) \n" :: "a"(&desc) : "memory");
+ vmcb->idtr.base = desc.address;
+ vmcb->idtr.limit = desc.size;
+
+ /* Set up segment attributes */
+ attrib.bytes = 0;
+ attrib.fields.type = 0x3; /* type = 3 */
+ attrib.fields.s = 1; /* code or data, i.e. not system */
+ attrib.fields.dpl = 0; /* DPL = 0 */
+ attrib.fields.p = 1; /* segment present */
+ attrib.fields.db = 1; /* 32-bit */
+ attrib.fields.g = 1; /* 4K pages in limit */
+
+ /* Data selectors */
+ vmcb->es.attributes = attrib;
+ vmcb->ss.attributes = attrib;
+ vmcb->ds.attributes = attrib;
+ vmcb->fs.attributes = attrib;
+ vmcb->gs.attributes = attrib;
+
+ /* Code selector */
+ attrib.fields.type = 0xb; /* type=0xb -> executable/readable, accessed */
+ vmcb->cs.attributes = attrib;
+
+ /* Global descriptor table */
+ //NMERGE7500 - can probably remove access to gdtr
+ vmcb->gdtr.base = regs->edx;
+ regs->edx = 0;
+ ASSERT(regs->eax <= 0xFFFF); /* Make sure we're in the limit */
+ vmcb->gdtr.limit = regs->eax;
+ regs->eax = 0;
+
+ /* Local Descriptor Table */
+ attrib.fields.s = 0; /* not code or data segement */
+ attrib.fields.type = 0x2; /* LDT */
+ attrib.fields.db = 0; /* 16-bit */
+ attrib.fields.g = 0;
+ vmcb->ldtr.attributes = attrib;
+
+ attrib.fields.type = 0xb; /* 32-bit TSS (busy) */
+ vmcb->tr.attributes = attrib;
+ vmcb->tr.base = 0;
+ vmcb->tr.limit = 0xff;
+
+ __asm__ __volatile__ ("mov %%cr0,%0" : "=r" (crn) :);
+ vmcb->cr0 = crn;
+
+ /* Initally PG, PE are not set*/
+ shadow_cr = vmcb->cr0;
+ shadow_cr &= ~X86_CR0_PG;
+ arch_svm->cpu_shadow_cr0 = shadow_cr;
+
+ /* CR3 is set in svm_final_setup_guest */
+
+ __asm__ __volatile__ ("mov %%cr4,%0" : "=r" (crn) :);
+ shadow_cr = crn;
+ vmcb->cr4 = shadow_cr;
+
+//MERGE7500 - should write a 0 instead to rsp?
+ vmcb->rsp = regs->esp;
+ vmcb->rip = regs->eip;
+
+ eflags = regs->eflags & ~HVM_EFLAGS_RESERVED_0; /* clear 0s */
+ eflags |= HVM_EFLAGS_RESERVED_1; /* set 1s */
+
+ vmcb->rflags = eflags;
+
+ __asm__ __volatile__ ("mov %%dr7, %0\n" : "=r" (dr7));
+ vmcb->dr7 = dr7;
+
+ return error;
+}
+
+
+/*
+ * destroy the vmcb.
+ */
+
+void destroy_vmcb(struct arch_svm_struct *arch_svm)
+{
+ if(arch_svm->vmcb != NULL)
+ {
+ asidpool_retire(arch_svm->vmcb, arch_svm->core);
+ free_vmcb(arch_svm->vmcb);
+ }
+ if(arch_svm->iopm != NULL) {
+ free_xenheap_pages(
+ arch_svm->iopm, get_order_from_bytes(IOPM_SIZE));
+ arch_svm->iopm = NULL;
+ }
+ if(arch_svm->msrpm != NULL) {
+ free_xenheap_pages(
+ arch_svm->msrpm, get_order_from_bytes(MSRPM_SIZE));
+ arch_svm->msrpm = NULL;
+ }
+ arch_svm->vmcb = NULL;
+}
+
+
+/*
+ * construct the vmcb.
+ */
+
+int construct_vmcb(struct arch_svm_struct *arch_svm, struct cpu_user_regs *regs)
+{
+ int error;
+ long rc=0;
+ struct host_save_area *hsa = NULL;
+ u64 phys_hsa;
+
+ memset(arch_svm, 0, sizeof(struct arch_svm_struct));
+
+ if (!(arch_svm->vmcb = alloc_vmcb())) {
+ printk("Failed to create a new VMCB\n");
+ rc = -ENOMEM;
+ goto err_out;
+ }
+
+ /*
+ * The following code is for allocating host_save_area.
+ * Note: We either allocate a Host Save Area per core or per VCPU.
+ * However, we do not want a global data structure
+ * for HSA per core, we decided to implement a HSA for each VCPU.
+ * It will waste space since VCPU number is larger than core number.
+ * But before we find a better place for HSA for each core, we will
+ * stay will this solution.
+ */
+
+ if (!(hsa = alloc_host_save_area()))
+ {
+ printk("Failed to allocate Host Save Area\n");
+ rc = -ENOMEM;
+ goto err_out;
+ }
+
+ phys_hsa = (u64) virt_to_phys(hsa);
+ arch_svm->host_save_area = hsa;
+ arch_svm->host_save_pa = phys_hsa;
+
+ arch_svm->vmcb_pa = (u64) virt_to_phys(arch_svm->vmcb);
+
+ if ((error = load_vmcb(arch_svm, arch_svm->host_save_pa)))
+ {
+ printk("construct_vmcb: load_vmcb failed: VMCB = %lx\n",
+ (unsigned long) arch_svm->host_save_pa);
+ rc = -EINVAL;
+ goto err_out;
+ }
+
+ if ((error = construct_vmcb_controls(arch_svm)))
+ {
+ printk("construct_vmcb: construct_vmcb_controls failed\n");
+ rc = -EINVAL;
+ goto err_out;
+ }
+
+ /* guest selectors */
+ if ((error = construct_init_vmcb_guest(arch_svm, regs)))
+ {
+ printk("construct_vmcb: construct_vmcb_guest failed\n");
+ rc = -EINVAL;
+ goto err_out;
+ }
+
+ arch_svm->vmcb->exception_intercepts = MONITOR_DEFAULT_EXCEPTION_BITMAP;
+ if (regs->eflags & EF_TF)
+ arch_svm->vmcb->exception_intercepts |= EXCEPTION_BITMAP_DB;
+ else
+ arch_svm->vmcb->exception_intercepts &= ~EXCEPTION_BITMAP_DB;
+
+ return 0;
+
+err_out:
+ destroy_vmcb(arch_svm);
+ return rc;
+}
+
+
+void svm_do_launch(struct vcpu *v)
+{
+ /* Update CR3, GDT, LDT, TR */
+ struct vmcb_struct *vmcb;
+ int core = smp_processor_id();
+ vmcb = v->arch.hvm_svm.vmcb;
+ ASSERT(vmcb);
+
+ svm_stts(v);
+
+ /* current core is the one we will perform the vmrun on */
+ v->arch.hvm_svm.core = core;
+ clear_bit(ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags);
+ if(!asidpool_assign_next(vmcb, 0, core, core)) {
+ BUG();
+ }
+
+ if (v->vcpu_id == 0)
+ hvm_setup_platform(v->domain);
+
+ if (hvm_apic_support(v->domain))
+ vlapic_init(v);
+ init_timer(&v->arch.hvm_svm.hlt_timer,
+ hlt_timer_fn, v, v->processor);
+
+ vmcb->ldtr.sel = 0;
+ vmcb->ldtr.base = 0;
+ vmcb->ldtr.limit = 0;
+ vmcb->ldtr.attributes.bytes = 0;
+
+ vmcb->efer = EFER_SVME; /* Make sure VMRUN won't return with -1 */
+
+ if (svm_dbg_on)
+ {
+ unsigned long pt;
+ pt = pagetable_get_paddr(v->arch.shadow_table);
+ printk("%s: shadow_table = %lx\n", __func__, pt);
+ pt = pagetable_get_paddr(v->arch.guest_table);
+ printk("%s: guest_table = %lx\n", __func__, pt);
+ pt = pagetable_get_paddr(v->domain->arch.phys_table);
+ printk("%s: phys_table = %lx\n", __func__, pt);
+ }
+
+ if (svm_paging_enabled(v))
+ {
+ vmcb->cr3 = pagetable_get_paddr(v->arch.guest_table);
+ }
+ else
+ {
+ vmcb->cr3 = pagetable_get_paddr(v->domain->arch.phys_table);
+ }
+
+ if (svm_dbg_on)
+ {
+ printk("%s: cr3 = %lx ", __func__, (unsigned long)vmcb->cr3);
+ printk("init_guest_table: guest_table = 0x%08x, monitor_table = 0x%08x,"
+ " shadow_table = 0x%08x\n", (int)v->arch.guest_table.pfn,
+ (int)v->arch.monitor_table.pfn, (int)v->arch.shadow_table.pfn);
+ }
+
+ v->arch.schedule_tail = arch_svm_do_resume;
+
+ v->arch.hvm_svm.injecting_event = 0;
+ v->arch.hvm_svm.saved_irq_vector = -1;
+
+ if (svm_dbg_on)
+ svm_dump_vmcb(__func__, vmcb);
+}
+
+
+int load_vmcb(struct arch_svm_struct *arch_svm, u64 phys_hsa)
+{
+ u32 phys_hsa_lo, phys_hsa_hi;
+
+ phys_hsa_lo = (u32) phys_hsa;
+ phys_hsa_hi = (u32) (phys_hsa >> 32);
+
+ wrmsr(MSR_K8_VM_HSAVE_PA, phys_hsa_lo, phys_hsa_hi);
+ set_bit(ARCH_SVM_VMCB_LOADED, &arch_svm->flags);
+ return 0;
+}
+
+
+/*
+ * Resume the guest.
+ */
+void svm_do_resume(struct vcpu *v)
+{
+ struct hvm_virpit *vpit = &v->domain->arch.hvm_domain.vpit;
+
+ if (event_pending(v))
+ {
+ hvm_check_events(v);
+
+ if (test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags))
+ hvm_wait_io();
+ }
+
+ /* pick up the elapsed PIT ticks and re-enable pit_timer */
+ if ( vpit->first_injected ) {
+ pickup_deactive_ticks(vpit);
+ }
+ svm_set_tsc_shift(v, vpit);
+
+ /* We can't resume the guest if we're waiting on I/O */
+ ASSERT(!test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags));
+}
+
+
+void svm_launch_fail(unsigned long eflags)
+{
+ BUG();
+}
+
+
+void svm_resume_fail(unsigned long eflags)
+{
+ BUG();
+}
+
+
+void svm_dump_sel(char *name, segment_selector_t *s)
+{
+ printf("%s: sel=0x%04x, attr=0x%04x, limit=0x%08x, base=0x%016llx\n",
+ name, s->sel, s->attributes.bytes, s->limit,
+ (unsigned long long)s->base);
+}
+
+
+void svm_dump_vmcb(const char *from, struct vmcb_struct *vmcb)
+{
+ printf("Dumping guest's current state at %s...\n", from);
+ printf("Size of VMCB = %d, address = %p\n",
+ (int) sizeof(struct vmcb_struct), vmcb);
+
+ printf("cr_intercepts = 0x%08x dr_intercepts = 0x%08x exception_intercepts "
+ "= 0x%08x\n", vmcb->cr_intercepts, vmcb->dr_intercepts,
+ vmcb->exception_intercepts);
+ printf("general1_intercepts = 0x%08x general2_intercepts = 0x%08x\n",
+ vmcb->general1_intercepts, vmcb->general2_intercepts);
+ printf("iopm_base_pa = %016llx msrpm_base_pa = 0x%016llx tsc_offset = "
+ "0x%016llx\n",
+ (unsigned long long) vmcb->iopm_base_pa,
+ (unsigned long long) vmcb->msrpm_base_pa,
+ (unsigned long long) vmcb->tsc_offset);
+ printf("tlb_control = 0x%08x vintr = 0x%016llx interrupt_shadow = "
+ "0x%016llx\n", vmcb->tlb_control,
+ (unsigned long long) vmcb->vintr.bytes,
+ (unsigned long long) vmcb->interrupt_shadow);
+ printf("exitcode = 0x%016llx exitintinfo = 0x%016llx\n",
+ (unsigned long long) vmcb->exitcode,
+ (unsigned long long) vmcb->exitintinfo.bytes);
+ printf("exitinfo1 = 0x%016llx exitinfo2 = 0x%016llx \n",
+ (unsigned long long) vmcb->exitinfo1,
+ (unsigned long long) vmcb->exitinfo2);
+ printf("np_enable = 0x%016llx guest_asid = 0x%03x\n",
+ (unsigned long long) vmcb->np_enable, vmcb->guest_asid);
+ printf("cpl = %d efer = 0x%016llx star = 0x%016llx lstar = 0x%016llx\n",
+ vmcb->cpl, (unsigned long long) vmcb->efer,
+ (unsigned long long) vmcb->star, (unsigned long long) vmcb->lstar);
+ printf("CR0 = 0x%016llx CR2 = 0x%016llx\n",
+ (unsigned long long) vmcb->cr0, (unsigned long long) vmcb->cr2);
+ printf("CR3 = 0x%016llx CR4 = 0x%016llx\n",
+ (unsigned long long) vmcb->cr3, (unsigned long long) vmcb->cr4);
+ printf("RSP = 0x%016llx RIP = 0x%016llx\n",
+ (unsigned long long) vmcb->rsp, (unsigned long long) vmcb->rip);
+ printf("RAX = 0x%016llx RFLAGS=0x%016llx\n",
+ (unsigned long long) vmcb->rax, (unsigned long long) vmcb->rflags);
+ printf("DR6 = 0x%016llx, DR7 = 0x%016llx\n",
+ (unsigned long long) vmcb->dr6, (unsigned long long) vmcb->dr7);
+ printf("CSTAR = 0x%016llx SFMask = 0x%016llx\n",
+ (unsigned long long) vmcb->cstar, (unsigned long long) vmcb->sfmask);
+ printf("KernGSBase = 0x%016llx PAT = 0x%016llx \n",
+ (unsigned long long) vmcb->kerngsbase,
+ (unsigned long long) vmcb->g_pat);
+
+ /* print out all the selectors */
+ svm_dump_sel("CS", &vmcb->cs);
+ svm_dump_sel("DS", &vmcb->ds);
+ svm_dump_sel("SS", &vmcb->ss);
+ svm_dump_sel("ES", &vmcb->es);
+ svm_dump_sel("FS", &vmcb->fs);
+ svm_dump_sel("GS", &vmcb->gs);
+ svm_dump_sel("GDTR", &vmcb->gdtr);
+ svm_dump_sel("LDTR", &vmcb->ldtr);
+ svm_dump_sel("IDTR", &vmcb->idtr);
+ svm_dump_sel("TR", &vmcb->tr);
+}
+#endif /* CONFIG_SVM */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/x86/hvm/svm/x86_32/exits.S b/xen/arch/x86/hvm/svm/x86_32/exits.S
new file mode 100644
index 0000000000..c5d3e7d8f9
--- /dev/null
+++ b/xen/arch/x86/hvm/svm/x86_32/exits.S
@@ -0,0 +1,221 @@
+/*
+ * exits.S: SVM architecture-specific exit handling.
+ * Copyright (c) 2004, Intel Corporation.
+ * Copyright (c) 2005, AMD 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 <xen/config.h>
+#include <xen/errno.h>
+#include <xen/softirq.h>
+#include <asm/asm_defns.h>
+#include <asm/apicdef.h>
+#include <asm/page.h>
+#include <public/xen.h>
+
+#define GET_CURRENT(reg) \
+ movl $STACK_SIZE-4, reg; \
+ orl %esp, reg; \
+ andl $~3,reg; \
+ movl (reg),reg;
+
+/*
+ * At VMExit time the processor saves the guest selectors, esp, eip,
+ * and eflags. Therefore we don't save them, but simply decrement
+ * the kernel stack pointer to make it consistent with the stack frame
+ * at usual interruption time. The eflags of the host is not saved by VMX,
+ * and we set it to the fixed value.
+ *
+ * We also need the room, especially because orig_eax field is used
+ * by do_IRQ(). Compared the cpu_user_regs, we skip pushing for the following:
+ * (10) u32 gs;
+ * (9) u32 fs;
+ * (8) u32 ds;
+ * (7) u32 es;
+ * <- get_stack_bottom() (= HOST_ESP)
+ * (6) u32 ss;
+ * (5) u32 esp;
+ * (4) u32 eflags;
+ * (3) u32 cs;
+ * (2) u32 eip;
+ * (2/1) u16 entry_vector;
+ * (1/1) u16 error_code;
+ * However, get_stack_bottom() actually returns 20 bytes before the real
+ * bottom of the stack to allow space for:
+ * domain pointer, DS, ES, FS, GS. Therefore, we effectively skip 6 registers.
+ */
+
+#define HVM_MONITOR_EFLAGS 0x202 /* IF on */
+#define NR_SKIPPED_REGS 6 /* See the above explanation */
+#define HVM_SAVE_ALL_NOSEGREGS \
+ pushl $HVM_MONITOR_EFLAGS; \
+ popf; \
+ subl $(NR_SKIPPED_REGS*4), %esp; \
+ movl $0, 0xc(%esp); /* eflags==0 identifies cpu_user_regs as HVM guest */ \
+ pushl %eax; \
+ pushl %ebp; \
+ pushl %edi; \
+ pushl %esi; \
+ pushl %edx; \
+ pushl %ecx; \
+ pushl %ebx;
+
+#define HVM_RESTORE_ALL_NOSEGREGS \
+ popl %ebx; \
+ popl %ecx; \
+ popl %edx; \
+ popl %esi; \
+ popl %edi; \
+ popl %ebp; \
+ popl %eax; \
+ addl $(NR_SKIPPED_REGS*4), %esp
+
+#ifdef CONFIG_SVM
+
+ ALIGN
+
+#define VMRUN .byte 0x0F,0x01,0xD8
+#define VMLOAD .byte 0x0F,0x01,0xDA
+#define VMSAVE .byte 0x0F,0x01,0xDB
+#define STGI .byte 0x0F,0x01,0xDC
+#define CLGI .byte 0x0F,0x01,0xDD
+
+#define DO_TSC_OFFSET 0
+#define DO_FPUSAVE 1
+
+ENTRY(svm_asm_do_launch)
+ sti
+ CLGI
+ GET_CURRENT(%ebx)
+ movl VCPU_svm_vmcb(%ebx), %ecx
+ movl 24(%esp), %eax
+ movl %eax, VMCB_rax(%ecx)
+ movl VCPU_svm_hsa_pa(%ebx), %eax
+ VMSAVE
+
+#if DO_FPUSAVE
+ mov %cr0, %eax
+ push %eax
+ clts
+ lea VCPU_arch_guest_fpu_ctxt(%ebx), %eax
+ fxrstor (%eax)
+ pop %eax
+ mov %eax, %cr0
+#endif
+
+#if (DO_TSC_OFFSET)
+ pushl %edx /* eax and edx get trashed by rdtsc */
+ pushl %eax
+ rdtsc
+ subl VCPU_svm_vmexit_tsc(%ebx),%eax /* tsc's from */
+ sbbl VCPU_svm_vmexit_tsc+4(%ebx),%edx /* last #VMEXIT? */
+ subl %eax,VMCB_tsc_offset(%ecx) /* subtract from running TSC_OFFSET */
+ sbbl %edx,VMCB_tsc_offset+4(%ecx)
+ subl $20000,VMCB_tsc_offset(%ecx) /* fudge factor for VMXXX calls */
+ sbbl $0,VMCB_tsc_offset+4(%ecx)
+
+ /*
+ * TODO: may need to add a kludge factor to account for all the cycles
+ * burned in VMLOAD, VMSAVE, VMRUN...
+ */
+
+ popl %eax
+ popl %edx
+ #endif
+
+ movl VCPU_svm_vmcb_pa(%ebx), %eax
+ popl %ebx
+ popl %ecx
+ popl %edx
+ popl %esi
+ popl %edi
+ popl %ebp
+
+ /*
+ * Skip %eax, we need to have vmcb address in there.
+ * Don't worry, EAX is restored through the VMRUN instruction.
+ */
+ addl $4, %esp
+ addl $(NR_SKIPPED_REGS*4), %esp
+ VMLOAD
+ VMRUN
+ VMSAVE
+ /* eax is the only register we're allowed to touch here... */
+
+#if DO_FPUSAVE
+ mov %cr0, %eax
+ push %eax
+ clts
+ GET_CURRENT(%eax)
+ lea VCPU_arch_guest_fpu_ctxt(%eax), %eax
+ fxsave (%eax)
+ fnclex
+ pop %eax
+ mov %eax, %cr0
+#endif
+
+ GET_CURRENT(%eax)
+
+#if (DO_TSC_OFFSET)
+ pushl %edx
+ pushl %ebx
+ movl %eax,%ebx
+ rdtsc
+ movl %eax,VCPU_svm_vmexit_tsc(%ebx)
+ movl %edx,VCPU_svm_vmexit_tsc+4(%ebx)
+ movl %ebx,%eax
+ popl %ebx
+ popl %edx
+#endif
+
+ movl VCPU_svm_hsa_pa(%eax), %eax
+ VMLOAD
+
+ HVM_SAVE_ALL_NOSEGREGS
+ STGI
+ call svm_vmexit_handler
+ jmp svm_asm_do_resume
+
+ ALIGN
+
+ENTRY(svm_asm_do_resume)
+svm_test_all_events:
+ GET_CURRENT(%ebx)
+/*test_all_events:*/
+ xorl %ecx,%ecx
+ notl %ecx
+ cli # tests must not race interrupts
+/*test_softirqs:*/
+ movl VCPU_processor(%ebx),%eax
+ shl $IRQSTAT_shift,%eax
+ test %ecx,irq_stat(%eax,1)
+ jnz svm_process_softirqs
+svm_restore_all_guest:
+ call svm_intr_assist
+ call svm_asid
+ call svm_load_cr2
+ sti
+ /*
+ * Check if we are going back to SVM-based VM
+ * By this time, all the setups in the VMCB must be complete.
+ */
+ jmp svm_asm_do_launch
+
+ ALIGN
+svm_process_softirqs:
+ sti
+ call do_softirq
+ jmp svm_test_all_events
+#endif /* CONFIG_SVM */
+
diff --git a/xen/arch/x86/hvm/svm/x86_64/exits.S b/xen/arch/x86/hvm/svm/x86_64/exits.S
new file mode 100644
index 0000000000..3e8eadbe02
--- /dev/null
+++ b/xen/arch/x86/hvm/svm/x86_64/exits.S
@@ -0,0 +1,179 @@
+/*
+ * exits.S: SVM architecture-specific exit handling.
+ * Copyright (c) 2004, Intel Corporation.
+ * Copyright (c) 2005, AMD 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 <xen/config.h>
+#include <xen/errno.h>
+#include <xen/softirq.h>
+#include <asm/asm_defns.h>
+#include <asm/apicdef.h>
+#include <asm/page.h>
+#include <public/xen.h>
+
+#define GET_CURRENT(reg) \
+ movq $STACK_SIZE-8, reg; \
+ orq %rsp, reg; \
+ andq $~7,reg; \
+ movq (reg),reg;
+
+/*
+ * At VMExit time the processor saves the guest selectors, rsp, rip,
+ * and rflags. Therefore we don't save them, but simply decrement
+ * the kernel stack pointer to make it consistent with the stack frame
+ * at usual interruption time. The rflags of the host is not saved by VMX,
+ * and we set it to the fixed value.
+ *
+ * We also need the room, especially because orig_eax field is used
+ * by do_IRQ(). Compared the cpu_user_regs, we skip pushing for the following:
+ * (10) u64 gs;
+ * (9) u64 fs;
+ * (8) u64 ds;
+ * (7) u64 es;
+ * <- get_stack_bottom() (= HOST_ESP)
+ * (6) u64 ss;
+ * (5) u64 rsp;
+ * (4) u64 rflags;
+ * (3) u64 cs;
+ * (2) u64 rip;
+ * (2/1) u32 entry_vector;
+ * (1/1) u32 error_code;
+ */
+#define HVM_MONITOR_RFLAGS 0x202 /* IF on */
+#define NR_SKIPPED_REGS 6 /* See the above explanation */
+#define HVM_SAVE_ALL_NOSEGREGS \
+ pushq $HVM_MONITOR_RFLAGS; \
+ popfq; \
+ subq $(NR_SKIPPED_REGS*8), %rsp; \
+ pushq %rdi; \
+ pushq %rsi; \
+ pushq %rdx; \
+ pushq %rcx; \
+ pushq %rax; \
+ pushq %r8; \
+ pushq %r9; \
+ pushq %r10; \
+ pushq %r11; \
+ pushq %rbx; \
+ pushq %rbp; \
+ pushq %r12; \
+ pushq %r13; \
+ pushq %r14; \
+ pushq %r15; \
+
+#define HVM_RESTORE_ALL_NOSEGREGS \
+ popq %r15; \
+ popq %r14; \
+ popq %r13; \
+ popq %r12; \
+ popq %rbp; \
+ popq %rbx; \
+ popq %r11; \
+ popq %r10; \
+ popq %r9; \
+ popq %r8; \
+ popq %rax; \
+ popq %rcx; \
+ popq %rdx; \
+ popq %rsi; \
+ popq %rdi; \
+ addq $(NR_SKIPPED_REGS*8), %rsp; \
+
+#ifdef CONFIG_SVM
+#define VMRUN .byte 0x0F,0x01,0xD8
+#define VMLOAD .byte 0x0F,0x01,0xDA
+#define VMSAVE .byte 0x0F,0x01,0xDB
+#define STGI .byte 0x0F,0x01,0xDC
+#define CLGI .byte 0x0F,0x01,0xDD
+
+ENTRY(svm_asm_do_launch)
+ sti
+ CLGI
+ GET_CURRENT(%rbx)
+ movq VCPU_svm_vmcb(%rbx), %rcx
+ movq UREGS_rax(%rsp), %rax
+ movq %rax, VMCB_rax(%rcx)
+ movq VCPU_svm_hsa_pa(%rbx), %rax
+ VMSAVE
+ /* XXX FPU SAVE */
+ /* XXX DO TSC OFFSET */
+
+ movq VCPU_svm_vmcb_pa(%rbx), %rax
+ popq %r15
+ popq %r14
+ popq %r13
+ popq %r12
+ popq %rbp
+ popq %rbx
+ popq %r11
+ popq %r10
+ popq %r9
+ popq %r8
+ /*
+ * Skip %rax, we need to have vmcb address in there.
+ * Don't worry, RAX is restored through the VMRUN instruction.
+ */
+ addq $8, %rsp
+ popq %rcx
+ popq %rdx
+ popq %rsi
+ popq %rdi
+ addq $(NR_SKIPPED_REGS*8), %rsp
+
+ VMLOAD
+ VMRUN
+ VMSAVE
+ /* rax is the only register we're allowed to touch here... */
+
+ /* XXX FPU SAVE */
+ GET_CURRENT(%rax)
+ /* XXX DO TSC OFFSET */
+ movq VCPU_svm_hsa_pa(%rax), %rax
+ VMLOAD
+
+ HVM_SAVE_ALL_NOSEGREGS
+ STGI
+ call svm_vmexit_handler
+ jmp svm_asm_do_resume
+
+ENTRY(svm_asm_do_resume)
+svm_test_all_events:
+ GET_CURRENT(%rbx)
+/*test_all_events:*/
+ cli # tests must not race interrupts
+/*test_softirqs:*/
+ movl VCPU_processor(%rbx),%eax
+ shl $IRQSTAT_shift, %rax
+ leaq irq_stat(%rip), %rdx
+ testl $~0, (%rdx, %rax, 1)
+ jnz svm_process_softirqs
+svm_restore_all_guest:
+ call svm_intr_assist
+ call svm_load_cr2
+ sti
+ /*
+ * Check if we are going back to VMX-based VM
+ * By this time, all the setups in the VMCS must be complete.
+ */
+ jmp svm_asm_do_launch
+
+ ALIGN
+svm_process_softirqs:
+ sti
+ call do_softirq
+ jmp svm_test_all_events
+#endif /* CONFIG_SVM */
+
diff --git a/xen/arch/x86/dm/vmx_vioapic.c b/xen/arch/x86/hvm/vioapic.c
index 201788e858..7bf2728f0d 100644
--- a/xen/arch/x86/dm/vmx_vioapic.c
+++ b/xen/arch/x86/hvm/vioapic.c
@@ -27,9 +27,6 @@
* Ported to xen by using virtual IRQ line.
*/
-#include <asm/vmx_vioapic.h>
-#include <asm/vmx_platform.h>
-
#include <xen/config.h>
#include <xen/types.h>
#include <xen/mm.h>
@@ -38,11 +35,16 @@
#include <xen/errno.h>
#include <xen/sched.h>
#include <public/hvm/ioreq.h>
-#include <asm/vmx.h>
-#include <asm/vmx_vpic.h>
+#include <asm/hvm/io.h>
+#include <asm/hvm/vpic.h>
+#include <asm/hvm/support.h>
#include <asm/current.h>
-static void ioapic_enable(vmx_vioapic_t *s, uint8_t enable)
+#if defined(__ia64__)
+#define opt_hvm_debug_level opt_vmx_debug_level
+#endif
+
+static void ioapic_enable(hvm_vioapic_t *s, uint8_t enable)
{
if (enable)
s->flags |= IOAPIC_ENABLE_FLAG;
@@ -50,11 +52,11 @@ static void ioapic_enable(vmx_vioapic_t *s, uint8_t enable)
s->flags &= ~IOAPIC_ENABLE_FLAG;
}
-static void ioapic_dump_redir(vmx_vioapic_t *s, uint8_t entry)
+static void ioapic_dump_redir(hvm_vioapic_t *s, uint8_t entry)
{
RedirStatus redir = s->redirtbl[entry];
- VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_dump_redir "
+ HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_dump_redir "
"entry %x vector %x deliver_mod %x destmode %x delivestatus %x "
"polarity %x remote_irr %x trigmod %x mask %x dest_id %x\n",
entry, redir.RedirForm.vector, redir.RedirForm.deliver_mode,
@@ -64,7 +66,7 @@ static void ioapic_dump_redir(vmx_vioapic_t *s, uint8_t entry)
redir.RedirForm.dest_id);
}
-#ifdef VMX_DOMAIN_SAVE_RESTORE
+#ifdef HVM_DOMAIN_SAVE_RESTORE
void ioapic_save(QEMUFile* f, void* opaque)
{
printk("no implementation for ioapic_save\n");
@@ -77,7 +79,7 @@ int ioapic_load(QEMUFile* f, void* opaque, int version_id)
}
#endif
-static unsigned long vmx_vioapic_read_indirect(struct vmx_vioapic *s,
+static unsigned long hvm_vioapic_read_indirect(struct hvm_vioapic *s,
unsigned long addr,
unsigned long length)
{
@@ -127,14 +129,14 @@ static unsigned long vmx_vioapic_read_indirect(struct vmx_vioapic *s,
return result;
}
-static unsigned long vmx_vioapic_read(struct vcpu *v,
+static unsigned long hvm_vioapic_read(struct vcpu *v,
unsigned long addr,
unsigned long length)
{
- struct vmx_vioapic *s = &(v->domain->arch.vmx_platform.vmx_vioapic);
+ struct hvm_vioapic *s = &(v->domain->arch.hvm_domain.vioapic);
uint32_t result = 0;
- VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "vmx_vioapic_read addr %lx\n", addr);
+ HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "hvm_vioapic_read addr %lx\n", addr);
ASSERT(s);
@@ -146,7 +148,7 @@ static unsigned long vmx_vioapic_read(struct vcpu *v,
break;
case IOAPIC_REG_WINDOW:
- result = vmx_vioapic_read_indirect(s, addr, length);
+ result = hvm_vioapic_read_indirect(s, addr, length);
break;
default:
@@ -156,7 +158,7 @@ static unsigned long vmx_vioapic_read(struct vcpu *v,
return result;
}
-static void vmx_vioapic_update_imr(struct vmx_vioapic *s, int index)
+static void hvm_vioapic_update_imr(struct hvm_vioapic *s, int index)
{
if (s->redirtbl[index].RedirForm.mask)
set_bit(index, &s->imr);
@@ -164,14 +166,14 @@ static void vmx_vioapic_update_imr(struct vmx_vioapic *s, int index)
clear_bit(index, &s->imr);
}
-static void vmx_vioapic_write_indirect(struct vmx_vioapic *s,
+static void hvm_vioapic_write_indirect(struct hvm_vioapic *s,
unsigned long addr,
unsigned long length,
unsigned long val)
{
switch (s->ioregsel) {
case IOAPIC_REG_VERSION:
- printk("vmx_vioapic_write_indirect: version register read only\n");
+ printk("hvm_vioapic_write_indirect: version register read only\n");
break;
#ifndef __ia64__
@@ -188,7 +190,7 @@ static void vmx_vioapic_write_indirect(struct vmx_vioapic *s,
{
uint32_t redir_index = 0;
- VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "vmx_vioapic_write_indirect "
+ HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "hvm_vioapic_write_indirect "
"change redir index %x val %lx\n",
redir_index, val);
@@ -206,9 +208,9 @@ static void vmx_vioapic_write_indirect(struct vmx_vioapic *s,
redir_content = ((redir_content >> 32) << 32) |
(val & 0xffffffff);
s->redirtbl[redir_index].value = redir_content;
- vmx_vioapic_update_imr(s, redir_index);
+ hvm_vioapic_update_imr(s, redir_index);
} else {
- printk("vmx_vioapic_write_indirect "
+ printk("hvm_vioapic_write_indirect "
"error register %x\n", s->ioregsel);
}
break;
@@ -216,12 +218,12 @@ static void vmx_vioapic_write_indirect(struct vmx_vioapic *s,
} /* switch */
}
-static void vmx_vioapic_write(struct vcpu *v,
+static void hvm_vioapic_write(struct vcpu *v,
unsigned long addr,
unsigned long length,
unsigned long val)
{
- vmx_vioapic_t *s = &(v->domain->arch.vmx_platform.vmx_vioapic);
+ hvm_vioapic_t *s = &(v->domain->arch.hvm_domain.vioapic);
ASSERT(s);
@@ -233,7 +235,7 @@ static void vmx_vioapic_write(struct vcpu *v,
break;
case IOAPIC_REG_WINDOW:
- vmx_vioapic_write_indirect(s, addr, length, val);
+ hvm_vioapic_write_indirect(s, addr, length, val);
break;
#ifdef __ia64__
@@ -247,9 +249,9 @@ static void vmx_vioapic_write(struct vcpu *v,
}
}
-static int vmx_vioapic_range(struct vcpu *v, unsigned long addr)
+static int hvm_vioapic_range(struct vcpu *v, unsigned long addr)
{
- vmx_vioapic_t *s = &(v->domain->arch.vmx_platform.vmx_vioapic);
+ hvm_vioapic_t *s = &(v->domain->arch.hvm_domain.vioapic);
if ((s->flags & IOAPIC_ENABLE_FLAG) &&
(addr >= s->base_address &&
@@ -259,25 +261,25 @@ static int vmx_vioapic_range(struct vcpu *v, unsigned long addr)
return 0;
}
-struct vmx_mmio_handler vioapic_mmio_handler = {
- .check_handler = vmx_vioapic_range,
- .read_handler = vmx_vioapic_read,
- .write_handler = vmx_vioapic_write
+struct hvm_mmio_handler vioapic_mmio_handler = {
+ .check_handler = hvm_vioapic_range,
+ .read_handler = hvm_vioapic_read,
+ .write_handler = hvm_vioapic_write
};
-static void vmx_vioapic_reset(vmx_vioapic_t *s)
+static void hvm_vioapic_reset(hvm_vioapic_t *s)
{
int i;
- memset(s, 0, sizeof(vmx_vioapic_t));
+ memset(s, 0, sizeof(hvm_vioapic_t));
for (i = 0; i < IOAPIC_NUM_PINS; i++) {
s->redirtbl[i].RedirForm.mask = 0x1;
- vmx_vioapic_update_imr(s, i);
+ hvm_vioapic_update_imr(s, i);
}
}
-static void ioapic_update_config(vmx_vioapic_t *s,
+static void ioapic_update_config(hvm_vioapic_t *s,
unsigned long address,
uint8_t enable)
{
@@ -289,7 +291,7 @@ static void ioapic_update_config(vmx_vioapic_t *s,
s->base_address = address;
}
-static int ioapic_inj_irq(vmx_vioapic_t *s,
+static int ioapic_inj_irq(hvm_vioapic_t *s,
struct vlapic * target,
uint8_t vector,
uint8_t trig_mode,
@@ -299,7 +301,7 @@ static int ioapic_inj_irq(vmx_vioapic_t *s,
ASSERT(s && target);
- VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_inj_irq "
+ HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_inj_irq "
"irq %d trig %d delive mode %d\n",
vector, trig_mode, delivery_mode);
@@ -307,7 +309,7 @@ static int ioapic_inj_irq(vmx_vioapic_t *s,
case VLAPIC_DELIV_MODE_FIXED:
case VLAPIC_DELIV_MODE_LPRI:
if (vlapic_set_irq(target, vector, trig_mode) && (trig_mode == 1))
- printk("<ioapic_inj_irq> level interrupt happen before cleard\n");
+ printk("<ioapic_inj_irq> level interrupt happen before cleared\n");
result = 1;
break;
default:
@@ -320,13 +322,13 @@ static int ioapic_inj_irq(vmx_vioapic_t *s,
}
#ifndef __ia64__
-static int ioapic_match_logical_addr(vmx_vioapic_t *s, int number, uint8_t dest)
+static int ioapic_match_logical_addr(hvm_vioapic_t *s, int number, uint8_t dest)
{
int result = 0;
ASSERT(s && s->lapic_info[number]);
- VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_match_logical_addr "
+ HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_match_logical_addr "
"number %i dest %x\n",
number, dest);
@@ -351,10 +353,10 @@ static int ioapic_match_logical_addr(vmx_vioapic_t *s, int number, uint8_t dest)
return result;
}
#else
-extern int ioapic_match_logical_addr(vmx_vioapic_t *s, int number, uint8_t dest);
+extern int ioapic_match_logical_addr(hvm_vioapic_t *s, int number, uint8_t dest);
#endif
-static uint32_t ioapic_get_delivery_bitmask(vmx_vioapic_t *s,
+static uint32_t ioapic_get_delivery_bitmask(hvm_vioapic_t *s,
uint16_t dest,
uint8_t dest_mode,
uint8_t vector,
@@ -363,7 +365,7 @@ static uint32_t ioapic_get_delivery_bitmask(vmx_vioapic_t *s,
uint32_t mask = 0;
int i;
- VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_get_delivery_bitmask "
+ HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_get_delivery_bitmask "
"dest %d dest_mode %d "
"vector %d del_mode %d, lapic_count %d\n",
dest, dest_mode, vector, delivery_mode, s->lapic_count);
@@ -372,7 +374,7 @@ static uint32_t ioapic_get_delivery_bitmask(vmx_vioapic_t *s,
if (dest_mode == 0) { /* Physical mode */
for (i = 0; i < s->lapic_count; i++) {
- if (VLAPIC_ID(s->lapic_info[i]) == dest) {
+ if (VLAPIC_ID(s->lapic_info[i]) == dest) {
mask = 1 << i;
break;
}
@@ -389,13 +391,13 @@ static uint32_t ioapic_get_delivery_bitmask(vmx_vioapic_t *s,
}
}
- VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_get_delivery_bitmask "
+ HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_get_delivery_bitmask "
"mask %x\n", mask);
return mask;
}
-static void ioapic_deliver(vmx_vioapic_t *s, int irqno)
+static void ioapic_deliver(hvm_vioapic_t *s, int irqno)
{
uint16_t dest = s->redirtbl[irqno].RedirForm.dest_id;
uint8_t dest_mode = s->redirtbl[irqno].RedirForm.destmode;
@@ -404,7 +406,7 @@ static void ioapic_deliver(vmx_vioapic_t *s, int irqno)
uint8_t trig_mode = s->redirtbl[irqno].RedirForm.trigmod;
uint32_t deliver_bitmask;
- VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "IOAPIC deliver: "
+ HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "IOAPIC deliver: "
"dest %x dest_mode %x delivery_mode %x vector %x trig_mode %x\n",
dest, dest_mode, delivery_mode, vector, trig_mode);
@@ -412,7 +414,7 @@ static void ioapic_deliver(vmx_vioapic_t *s, int irqno)
ioapic_get_delivery_bitmask(s, dest, dest_mode, vector, delivery_mode);
if (!deliver_bitmask) {
- VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic deliver "
+ HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic deliver "
"no target on destination\n");
return;
@@ -427,8 +429,8 @@ static void ioapic_deliver(vmx_vioapic_t *s, int irqno)
s->domain, dest_mode, vector, deliver_bitmask);
if (target)
ioapic_inj_irq(s, target, vector, trig_mode, delivery_mode);
- else{
- VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic deliver "
+ else{
+ HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic deliver "
"null round robin mask %x vector %x delivery_mode %x\n",
deliver_bitmask, vector, deliver_bitmask);
}
@@ -460,7 +462,7 @@ static void ioapic_deliver(vmx_vioapic_t *s, int irqno)
}
}
-static int ioapic_get_highest_irq(vmx_vioapic_t *s)
+static int ioapic_get_highest_irq(hvm_vioapic_t *s)
{
uint32_t irqs;
@@ -471,13 +473,13 @@ static int ioapic_get_highest_irq(vmx_vioapic_t *s)
}
-static void service_ioapic(vmx_vioapic_t *s)
+static void service_ioapic(hvm_vioapic_t *s)
{
int irqno;
while ((irqno = ioapic_get_highest_irq(s)) != -1) {
- VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "service_ioapic "
+ HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "service_ioapic "
"highest irqno %x\n", irqno);
if (!test_bit(irqno, &s->imr)) {
@@ -492,36 +494,36 @@ static void service_ioapic(vmx_vioapic_t *s)
}
}
-void vmx_vioapic_do_irqs(struct domain *d, uint16_t irqs)
+void hvm_vioapic_do_irqs(struct domain *d, uint16_t irqs)
{
- vmx_vioapic_t *s = &(d->arch.vmx_platform.vmx_vioapic);
+ hvm_vioapic_t *s = &(d->arch.hvm_domain.vioapic);
- if (!vmx_apic_support(d))
+ if (!hvm_apic_support(d))
return;
s->irr |= irqs & ~s->imr;
service_ioapic(s);
}
-void vmx_vioapic_do_irqs_clear(struct domain *d, uint16_t irqs)
+void hvm_vioapic_do_irqs_clear(struct domain *d, uint16_t irqs)
{
- vmx_vioapic_t *s = &(d->arch.vmx_platform.vmx_vioapic);
+ hvm_vioapic_t *s = &(d->arch.hvm_domain.vioapic);
- if (!vmx_apic_support(d))
+ if (!hvm_apic_support(d))
return;
s->irr &= ~irqs;
service_ioapic(s);
}
-void vmx_vioapic_set_irq(struct domain *d, int irq, int level)
+void hvm_vioapic_set_irq(struct domain *d, int irq, int level)
{
- vmx_vioapic_t *s = &(d->arch.vmx_platform.vmx_vioapic);
+ hvm_vioapic_t *s = &(d->arch.hvm_domain.vioapic);
- if (!vmx_apic_support(d))
+ if (!hvm_apic_support(d))
return ;
- VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_set_irq "
+ HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "ioapic_set_irq "
"irq %x level %x\n", irq, level);
if (irq < 0 || irq >= IOAPIC_NUM_PINS) {
@@ -552,7 +554,7 @@ void vmx_vioapic_set_irq(struct domain *d, int irq, int level)
}
/* XXX If level interrupt, use vector->irq table for performance */
-static int get_redir_num(vmx_vioapic_t *s, int vector)
+static int get_redir_num(hvm_vioapic_t *s, int vector)
{
int i = 0;
@@ -568,7 +570,7 @@ static int get_redir_num(vmx_vioapic_t *s, int vector)
void ioapic_update_EOI(struct domain *d, int vector)
{
- vmx_vioapic_t *s = &(d->arch.vmx_platform.vmx_vioapic);
+ hvm_vioapic_t *s = &(d->arch.hvm_domain.vioapic);
int redir_num;
if ((redir_num = get_redir_num(s, vector)) == -1) {
@@ -582,12 +584,12 @@ void ioapic_update_EOI(struct domain *d, int vector)
}
}
-int vmx_vioapic_add_lapic(struct vlapic *vlapic, struct vcpu *v)
+int hvm_vioapic_add_lapic(struct vlapic *vlapic, struct vcpu *v)
{
- vmx_vioapic_t *s = &(v->domain->arch.vmx_platform.vmx_vioapic);
+ hvm_vioapic_t *s = &(v->domain->arch.hvm_domain.vioapic);
if (v->vcpu_id != s->lapic_count) {
- printk("vmx_vioapic_add_lapic "
+ printk("hvm_vioapic_add_lapic "
"cpu_id not match vcpu_id %x lapic_count %x\n",
v->vcpu_id, s->lapic_count);
domain_crash_synchronous();
@@ -600,14 +602,14 @@ int vmx_vioapic_add_lapic(struct vlapic *vlapic, struct vcpu *v)
return s->lapic_count;
}
-vmx_vioapic_t * vmx_vioapic_init(struct domain *d)
+hvm_vioapic_t * hvm_vioapic_init(struct domain *d)
{
int i = 0;
- vmx_vioapic_t *s = &(d->arch.vmx_platform.vmx_vioapic);
+ hvm_vioapic_t *s = &(d->arch.hvm_domain.vioapic);
- VMX_DBG_LOG(DBG_LEVEL_IOAPIC, "vmx_vioapic_init\n");
+ HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "hvm_vioapic_init\n");
- vmx_vioapic_reset(s);
+ hvm_vioapic_reset(s);
s->domain = d;
diff --git a/xen/arch/x86/vmx_vlapic.c b/xen/arch/x86/hvm/vlapic.c
index d487f9739e..0c4e2e35af 100644
--- a/xen/arch/x86/vmx_vlapic.c
+++ b/xen/arch/x86/hvm/vlapic.c
@@ -1,5 +1,6 @@
/*
- * vmx_vlapic.c: virtualize LAPIC for VMX vcpus.
+ * vlapic.c: virtualize LAPIC for HVM vcpus.
+ *
* Copyright (c) 2004, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
@@ -14,7 +15,6 @@
* 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 <xen/config.h>
@@ -25,17 +25,15 @@
#include <asm/page.h>
#include <xen/event.h>
#include <xen/trace.h>
-#include <asm/vmx.h>
-#include <asm/vmx_platform.h>
-#include <asm/vmx_vlapic.h>
-#include <asm/vmx_vioapic.h>
+#include <asm/hvm/hvm.h>
+#include <asm/hvm/io.h>
+#include <asm/hvm/support.h>
+
#include <xen/lib.h>
#include <xen/sched.h>
#include <asm/current.h>
#include <public/hvm/ioreq.h>
-#ifdef CONFIG_VMX
-
/* XXX remove this definition after GFW enabled */
#define VLAPIC_NO_BIOS
@@ -60,16 +58,16 @@ int vlapic_find_highest_irr(struct vlapic *vlapic)
return result;
}
-int vmx_apic_support(struct domain *d)
+int hvm_apic_support(struct domain *d)
{
- return d->arch.vmx_platform.apic_enabled;
+ return d->arch.hvm_domain.apic_enabled;
}
s_time_t get_apictime_scheduled(struct vcpu *v)
{
struct vlapic *vlapic = VLAPIC(v);
- if ( !vmx_apic_support(v->domain) || !vlapic_lvt_timer_enabled(vlapic) )
+ if ( !hvm_apic_support(v->domain) || !vlapic_lvt_timer_enabled(vlapic) )
return -1;
return vlapic->vlapic_timer.expires;
}
@@ -111,7 +109,7 @@ uint32_t vlapic_update_ppr(struct vlapic *vlapic)
vlapic->processor_priority = ppr;
- VMX_DBG_LOG(DBG_LEVEL_VLAPIC_INTERRUPT,
+ HVM_DBG_LOG(DBG_LEVEL_VLAPIC_INTERRUPT,
"vlapic_update_ppr: vlapic %p ppr %x isr %x isrv %x",
vlapic, ppr, isr, isrv);
@@ -126,7 +124,7 @@ static int vlapic_match_dest(struct vcpu *v, struct vlapic *source,
int result = 0;
struct vlapic *target = VLAPIC(v);
- VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_match_dest: "
+ HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_match_dest: "
"target %p source %p dest %x dest_mode %x short_hand %x "
"delivery_mode %x",
target, source, dest, dest_mode, short_hand, delivery_mode);
@@ -135,10 +133,10 @@ static int vlapic_match_dest(struct vcpu *v, struct vlapic *source,
( (delivery_mode != VLAPIC_DELIV_MODE_INIT) &&
(delivery_mode != VLAPIC_DELIV_MODE_STARTUP) &&
(delivery_mode != VLAPIC_DELIV_MODE_NMI) )) {
- VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_match_dest "
+ HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_match_dest "
"uninitialized target v %p delivery_mode %x dest %x\n",
- v, delivery_mode, dest);
- return result;
+ v, delivery_mode, dest);
+ return result;
}
switch (short_hand) {
@@ -146,7 +144,7 @@ static int vlapic_match_dest(struct vcpu *v, struct vlapic *source,
if (!dest_mode) { /* Physical */
result = ((target ? target->id : v->vcpu_id ) == dest);
} else { /* Logical */
- if (!target)
+ if (!target)
break;
if (((target->dest_format >> 28) & 0xf) == 0xf) { /* Flat mode */
result = (target->logical_dest >> 24) & dest;
@@ -228,7 +226,7 @@ static int vlapic_accept_irq(struct vcpu *v, int delivery_mode,
case VLAPIC_DELIV_MODE_INIT:
if (!level && trig_mode == 1) { //Deassert
- printk("This vmx_vlapic is for P4, no work for De-assert init\n");
+ printk("This hvm_vlapic is for P4, no work for De-assert init\n");
} else {
/* FIXME How to check the situation after vcpu reset? */
vlapic->init_sipi_sipi_state = VLAPIC_INIT_SIPI_SIPI_STATE_WAIT_SIPI;
@@ -243,10 +241,10 @@ static int vlapic_accept_irq(struct vcpu *v, int delivery_mode,
break;
vlapic->init_sipi_sipi_state = VLAPIC_INIT_SIPI_SIPI_STATE_NORM;
if (!vlapic->vcpu) {
- /* XXX Call vmx_bringup_ap here */
+ /* XXX Call hvm_bringup_ap here */
result = 0;
}else{
- //vmx_vcpu_reset(vlapic->vcpu);
+ //hvm_vcpu_reset(vlapic->vcpu);
}
break;
@@ -280,14 +278,14 @@ struct vlapic* apic_round_robin(struct domain *d,
return NULL;
}
- spin_lock(&d->arch.vmx_platform.round_robin_lock);
+ spin_lock(&d->arch.hvm_domain.round_robin_lock);
- old = next = d->arch.vmx_platform.round_info[vector];
+ old = next = d->arch.hvm_domain.round_info[vector];
do {
/* the vcpu array is arranged according to vcpu_id */
if (test_bit(next, &bitmap)) {
- target = d->vcpu[next]->arch.arch_vmx.vlapic;
+ target = d->vcpu[next]->arch.hvm_vcpu.vlapic;
if (!target || !vlapic_enabled(target)) {
printk("warning: targe round robin local apic disabled\n");
@@ -303,8 +301,8 @@ struct vlapic* apic_round_robin(struct domain *d,
next = 0;
}while(next != old);
- d->arch.vmx_platform.round_info[vector] = next;
- spin_unlock(&d->arch.vmx_platform.round_robin_lock);
+ d->arch.hvm_domain.round_info[vector] = next;
+ spin_unlock(&d->arch.hvm_domain.round_robin_lock);
return target;
}
@@ -354,7 +352,7 @@ void vlapic_ipi(struct vlapic *vlapic)
struct vcpu *v = NULL;
uint32_t lpr_map;
- VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_ipi: "
+ HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_ipi: "
"icr_high %x icr_low %x "
"short_hand %x dest %x trig_mode %x level %x "
"dest_mode %x delivery_mode %x vector %x",
@@ -393,7 +391,7 @@ static void vlapic_begin_timer(struct vlapic *vlapic)
set_timer(&(vlapic->vlapic_timer), vlapic->vlapic_timer.expires );
- VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_begin_timer: "
+ HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_begin_timer: "
"bus_scale %x now %08x%08x expire %08x%08x "
"offset %08x%08x current %x",
get_apic_bus_scale(), (uint32_t)(cur >> 32), (uint32_t)cur,
@@ -407,7 +405,7 @@ void vlapic_read_aligned(struct vlapic *vlapic, unsigned int offset,
unsigned int len, unsigned int *result)
{
if (len != 4) {
- VMX_DBG_LOG(DBG_LEVEL_VLAPIC,
+ HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
"local apic read with len=%d (should be 4)", len);
}
@@ -515,7 +513,7 @@ void vlapic_read_aligned(struct vlapic *vlapic, unsigned int offset,
if (cur <= vlapic->timer_current_update) {
passed = ~0x0LL - vlapic->timer_current_update + cur;
- VMX_DBG_LOG(DBG_LEVEL_VLAPIC,"time elapsed");
+ HVM_DBG_LOG(DBG_LEVEL_VLAPIC,"time elapsed");
}else
passed = cur - vlapic->timer_current_update;
@@ -533,7 +531,7 @@ void vlapic_read_aligned(struct vlapic *vlapic, unsigned int offset,
vlapic->timer_current = *result;
vlapic->timer_current_update = NOW();
- VMX_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER,
+ HVM_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER,
"initial %x timer current %x "
"update %08x%08x cur %08x%08x offset %d",
vlapic->timer_initial, vlapic->timer_current,
@@ -565,7 +563,7 @@ static unsigned long vlapic_read(struct vcpu *v, unsigned long address,
if ( len != 4) {
/* some bugs on kernel cause read this with byte*/
- VMX_DBG_LOG(DBG_LEVEL_VLAPIC,
+ HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
"Local APIC read with len = %lx, should be 4 instead\n",
len);
}
@@ -592,7 +590,7 @@ static unsigned long vlapic_read(struct vcpu *v, unsigned long address,
break;
}
- VMX_DBG_LOG(DBG_LEVEL_VLAPIC,
+ HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
"vlapic_read offset %x with length %lx and the result is %lx",
offset, len, result);
return result;
@@ -605,7 +603,7 @@ static void vlapic_write(struct vcpu *v, unsigned long address,
unsigned int offset = address - vlapic->base_address;
if (offset != 0xb0)
- VMX_DBG_LOG(DBG_LEVEL_VLAPIC,
+ HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
"vlapic_write offset %x with length %lx source %lx",
offset, len, val);
@@ -747,7 +745,7 @@ static void vlapic_write(struct vcpu *v, unsigned long address,
vlapic_begin_timer(vlapic);
- VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "timer_init %x timer_current %x"
+ HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "timer_init %x timer_current %x"
"timer_current_update %08x%08x",
vlapic->timer_initial, vlapic->timer_current,
(uint32_t)(vlapic->timer_current_update >> 32),
@@ -762,7 +760,7 @@ static void vlapic_write(struct vcpu *v, unsigned long address,
tmp2 = ((tmp1 & 0x3 )|((tmp1 & 0x8) >>1)) + 1;
vlapic->timer_divide_counter = 0x1<<tmp2;
- VMX_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER,
+ HVM_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER,
"timer divider is 0x%x",
vlapic->timer_divide_counter);
}
@@ -786,7 +784,7 @@ static int vlapic_range(struct vcpu *v, unsigned long addr)
return 0;
}
-struct vmx_mmio_handler vlapic_mmio_handler = {
+struct hvm_mmio_handler vlapic_mmio_handler = {
.check_handler = vlapic_range,
.read_handler = vlapic_read,
.write_handler = vlapic_write
@@ -807,7 +805,7 @@ void vlapic_msr_set(struct vlapic *vlapic, uint64_t value)
if (!(value & 0x800))
set_bit(_VLAPIC_GLOB_DISABLE, &vlapic->status );
- VMX_DBG_LOG(DBG_LEVEL_VLAPIC,
+ HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
"apic base msr = 0x%08x%08x,\nbase address = 0x%lx",
(uint32_t)(vlapic->apic_base_msr >> 32),
(uint32_t)vlapic->apic_base_msr,
@@ -851,7 +849,7 @@ void vlapic_timer_fn(void *data)
vlapic->timer_current = 0;
}
- VMX_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER,
+ HVM_DBG_LOG(DBG_LEVEL_VLAPIC_TIMER,
"vlapic_timer_fn: now: %08x%08x expire %08x%08x init %x current %x",
(uint32_t)(NOW() >> 32),(uint32_t)NOW(),
(uint32_t)(vlapic->vlapic_timer.expires >> 32),
@@ -894,8 +892,8 @@ int cpu_get_apic_interrupt(struct vcpu* v, int *mode)
if (highest_irr < 0x10) {
vlapic->err_status |= 0x20;
/* XXX What will happen if this vector illegal stil */
- VMX_DBG_LOG(DBG_LEVEL_VLAPIC,
- "vmx_intr_assist: illegal vector number %x err_status %x",
+ HVM_DBG_LOG(DBG_LEVEL_VLAPIC,
+ "hvm_intr_assist: illegal vector number %x err_status %x",
highest_irr, vlapic_lvt_vector(vlapic, VLAPIC_LVT_ERROR));
set_bit(vlapic_lvt_vector(vlapic, VLAPIC_LVT_ERROR), &vlapic->irr[0]);
@@ -984,7 +982,7 @@ static int vlapic_reset(struct vlapic *vlapic)
vlapic->spurious_vec = 0xff;
- vmx_vioapic_add_lapic(vlapic, v);
+ hvm_vioapic_add_lapic(vlapic, v);
init_timer(&vlapic->vlapic_timer,
vlapic_timer_fn, vlapic, v->processor);
@@ -1001,7 +999,7 @@ static int vlapic_reset(struct vlapic *vlapic)
}
#endif
- VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_reset: "
+ HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_reset: "
"vcpu=%p id=%d vlapic_apic_base_msr=%08x%08x "
"vlapic_base_address=%0lx",
v, vlapic->id, (uint32_t)(vlapic->apic_base_msr >> 32),
@@ -1016,7 +1014,7 @@ int vlapic_init(struct vcpu *v)
ASSERT( v != NULL );
- VMX_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_init %d", v->vcpu_id);
+ HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "vlapic_init %d", v->vcpu_id);
vlapic = xmalloc_bytes(sizeof(struct vlapic));
if (!vlapic) {
@@ -1034,5 +1032,3 @@ int vlapic_init(struct vcpu *v)
return 0;
}
-
-#endif /* CONFIG_VMX */
diff --git a/xen/arch/x86/hvm/vmx/io.c b/xen/arch/x86/hvm/vmx/io.c
new file mode 100644
index 0000000000..7b3975194c
--- /dev/null
+++ b/xen/arch/x86/hvm/vmx/io.c
@@ -0,0 +1,207 @@
+/*
+ * io.c: handling I/O, interrupts related VMX entry/exit
+ * Copyright (c) 2004, Intel 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 <xen/config.h>
+#include <xen/init.h>
+#include <xen/mm.h>
+#include <xen/lib.h>
+#include <xen/errno.h>
+#include <xen/trace.h>
+#include <xen/event.h>
+
+#include <asm/current.h>
+#include <asm/cpufeature.h>
+#include <asm/processor.h>
+#include <asm/msr.h>
+#include <asm/hvm/hvm.h>
+#include <asm/hvm/io.h>
+#include <asm/hvm/support.h>
+#include <asm/hvm/vmx/vmx.h>
+#include <asm/hvm/vmx/vmcs.h>
+#include <asm/hvm/vpic.h>
+#include <asm/hvm/vlapic.h>
+#include <public/hvm/ioreq.h>
+
+#ifdef CONFIG_VMX
+
+#define BSP_CPU(v) (!(v->vcpu_id))
+
+void vmx_set_tsc_shift(struct vcpu *v, struct hvm_virpit *vpit)
+{
+ u64 drift;
+
+ if ( vpit->first_injected )
+ drift = vpit->period_cycles * vpit->pending_intr_nr;
+ else
+ drift = 0;
+ vpit->shift = v->arch.hvm_vmx.tsc_offset - drift;
+ __vmwrite(TSC_OFFSET, vpit->shift);
+
+#if defined (__i386__)
+ __vmwrite(TSC_OFFSET_HIGH, ((vpit->shift)>> 32));
+#endif
+}
+
+static inline void
+interrupt_post_injection(struct vcpu * v, int vector, int type)
+{
+ struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit);
+
+ if ( is_pit_irq(v, vector, type) ) {
+ if ( !vpit->first_injected ) {
+ vpit->pending_intr_nr = 0;
+ vpit->scheduled = NOW() + vpit->period;
+ set_timer(&vpit->pit_timer, vpit->scheduled);
+ vpit->first_injected = 1;
+ } else {
+ vpit->pending_intr_nr--;
+ }
+ vpit->inject_point = NOW();
+ vmx_set_tsc_shift (v, vpit);
+ }
+
+ switch(type)
+ {
+ case VLAPIC_DELIV_MODE_EXT:
+ break;
+
+ default:
+ vlapic_post_injection(v, vector, type);
+ break;
+ }
+}
+
+static inline void
+enable_irq_window(unsigned long cpu_exec_control)
+{
+ if (!(cpu_exec_control & CPU_BASED_VIRTUAL_INTR_PENDING)) {
+ cpu_exec_control |= CPU_BASED_VIRTUAL_INTR_PENDING;
+ __vmwrite(CPU_BASED_VM_EXEC_CONTROL, cpu_exec_control);
+ }
+}
+
+static inline void
+disable_irq_window(unsigned long cpu_exec_control)
+{
+ if ( cpu_exec_control & CPU_BASED_VIRTUAL_INTR_PENDING ) {
+ cpu_exec_control &= ~CPU_BASED_VIRTUAL_INTR_PENDING;
+ __vmwrite(CPU_BASED_VM_EXEC_CONTROL, cpu_exec_control);
+ }
+}
+
+asmlinkage void vmx_intr_assist(void)
+{
+ int intr_type = 0;
+ int highest_vector;
+ unsigned long intr_fields, eflags, interruptibility, cpu_exec_control;
+ struct vcpu *v = current;
+ struct hvm_domain *plat=&v->domain->arch.hvm_domain;
+ struct hvm_virpit *vpit = &plat->vpit;
+ struct hvm_virpic *pic= &plat->vpic;
+
+ hvm_pic_assist(v);
+ __vmread_vcpu(v, CPU_BASED_VM_EXEC_CONTROL, &cpu_exec_control);
+ if ( vpit->pending_intr_nr ) {
+ pic_set_irq(pic, 0, 0);
+ pic_set_irq(pic, 0, 1);
+ }
+
+ __vmread(VM_ENTRY_INTR_INFO_FIELD, &intr_fields);
+
+ if (intr_fields & INTR_INFO_VALID_MASK) {
+ enable_irq_window(cpu_exec_control);
+ HVM_DBG_LOG(DBG_LEVEL_1, "vmx_intr_assist: intr_fields: %lx",
+ intr_fields);
+ return;
+ }
+
+ __vmread(GUEST_INTERRUPTIBILITY_INFO, &interruptibility);
+
+ if (interruptibility) {
+ enable_irq_window(cpu_exec_control);
+ HVM_DBG_LOG(DBG_LEVEL_1, "interruptibility: %lx",interruptibility);
+ return;
+ }
+
+ __vmread(GUEST_RFLAGS, &eflags);
+ if (irq_masked(eflags)) {
+ enable_irq_window(cpu_exec_control);
+ return;
+ }
+
+ highest_vector = cpu_get_interrupt(v, &intr_type);
+
+ if (highest_vector == -1) {
+ disable_irq_window(cpu_exec_control);
+ return;
+ }
+
+ switch (intr_type) {
+ case VLAPIC_DELIV_MODE_EXT:
+ case VLAPIC_DELIV_MODE_FIXED:
+ case VLAPIC_DELIV_MODE_LPRI:
+ vmx_inject_extint(v, highest_vector, VMX_INVALID_ERROR_CODE);
+ TRACE_3D(TRC_VMX_INT, v->domain->domain_id, highest_vector, 0);
+ break;
+ case VLAPIC_DELIV_MODE_SMI:
+ case VLAPIC_DELIV_MODE_NMI:
+ case VLAPIC_DELIV_MODE_INIT:
+ case VLAPIC_DELIV_MODE_STARTUP:
+ default:
+ printk("Unsupported interrupt type\n");
+ BUG();
+ break;
+ }
+
+ interrupt_post_injection(v, highest_vector, intr_type);
+ return;
+}
+
+void vmx_do_resume(struct vcpu *v)
+{
+ struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit);
+
+ vmx_stts();
+
+ if (event_pending(v)) {
+ hvm_check_events(v);
+
+ if (test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags))
+ hvm_wait_io();
+ }
+ /* pick up the elapsed PIT ticks and re-enable pit_timer */
+ if ( vpit->first_injected ) {
+ pickup_deactive_ticks(vpit);
+ }
+ vmx_set_tsc_shift(v,vpit);
+
+ /* We can't resume the guest if we're waiting on I/O */
+ ASSERT(!test_bit(ARCH_HVM_IO_WAIT, &v->arch.hvm_vcpu.ioflags));
+}
+#endif /* CONFIG_VMX */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/x86/vmx_vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c
index 9b7c9d41d2..569f389fc8 100644
--- a/xen/arch/x86/vmx_vmcs.c
+++ b/xen/arch/x86/hvm/vmx/vmcs.c
@@ -1,5 +1,5 @@
/*
- * vmx_vmcs.c: VMCS management
+ * vmcs.c: VMCS management
* Copyright (c) 2004, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
@@ -14,7 +14,6 @@
* 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 <xen/config.h>
@@ -27,15 +26,18 @@
#include <asm/cpufeature.h>
#include <asm/processor.h>
#include <asm/msr.h>
-#include <asm/vmx.h>
-#include <asm/vmx_vioapic.h>
+#include <asm/hvm/hvm.h>
+#include <asm/hvm/io.h>
+#include <asm/hvm/support.h>
+#include <asm/hvm/vmx/vmx.h>
+#include <asm/hvm/vmx/vmcs.h>
#include <asm/flushtlb.h>
#include <xen/event.h>
#include <xen/kernel.h>
-#include <public/hvm/hvm_info_table.h>
#if CONFIG_PAGING_LEVELS >= 4
#include <asm/shadow_64.h>
#endif
+
#ifdef CONFIG_VMX
int vmcs_size;
@@ -143,140 +145,6 @@ struct host_execution_env {
#endif
};
-static void vmx_map_io_shared_page(struct domain *d)
-{
- int i;
- unsigned char e820_map_nr;
- struct e820entry *e820entry;
- unsigned char *p;
- unsigned long mpfn;
- unsigned long gpfn = 0;
-
- local_flush_tlb_pge();
-
- mpfn = get_mfn_from_pfn(E820_MAP_PAGE >> PAGE_SHIFT);
- if (mpfn == INVALID_MFN) {
- printk("Can not find E820 memory map page for VMX domain.\n");
- domain_crash_synchronous();
- }
-
- p = map_domain_page(mpfn);
- if (p == NULL) {
- printk("Can not map E820 memory map page for VMX domain.\n");
- domain_crash_synchronous();
- }
-
- e820_map_nr = *(p + E820_MAP_NR_OFFSET);
- e820entry = (struct e820entry *)(p + E820_MAP_OFFSET);
-
- for ( i = 0; i < e820_map_nr; i++ )
- {
- if (e820entry[i].type == E820_SHARED_PAGE)
- {
- gpfn = (e820entry[i].addr >> PAGE_SHIFT);
- break;
- }
- }
-
- if ( gpfn == 0 ) {
- printk("Can not get io request shared page"
- " from E820 memory map for VMX domain.\n");
- unmap_domain_page(p);
- domain_crash_synchronous();
- }
- unmap_domain_page(p);
-
- /* Initialise shared page */
- mpfn = get_mfn_from_pfn(gpfn);
- if (mpfn == INVALID_MFN) {
- printk("Can not find io request shared page for VMX domain.\n");
- domain_crash_synchronous();
- }
-
- p = map_domain_page_global(mpfn);
- if (p == NULL) {
- printk("Can not map io request shared page for VMX domain.\n");
- domain_crash_synchronous();
- }
- d->arch.vmx_platform.shared_page_va = (unsigned long)p;
-
- VMX_DBG_LOG(DBG_LEVEL_1, "eport: %x\n", iopacket_port(d));
-
- clear_bit(iopacket_port(d),
- &d->shared_info->evtchn_mask[0]);
-}
-
-static int validate_hvm_info(struct hvm_info_table *t)
-{
- char signature[] = "HVM INFO";
- uint8_t *ptr = (uint8_t *)t;
- uint8_t sum = 0;
- int i;
-
- /* strncmp(t->signature, "HVM INFO", 8) */
- for ( i = 0; i < 8; i++ ) {
- if ( signature[i] != t->signature[i] ) {
- printk("Bad hvm info signature\n");
- return 0;
- }
- }
-
- for ( i = 0; i < t->length; i++ )
- sum += ptr[i];
-
- return (sum == 0);
-}
-
-static void vmx_get_hvm_info(struct domain *d)
-{
- unsigned char *p;
- unsigned long mpfn;
- struct hvm_info_table *t;
-
- mpfn = get_mfn_from_pfn(HVM_INFO_PFN);
- if ( mpfn == INVALID_MFN ) {
- printk("Can not get hvm info page mfn for VMX domain.\n");
- domain_crash_synchronous();
- }
-
- p = map_domain_page(mpfn);
- if ( p == NULL ) {
- printk("Can not map hvm info page for VMX domain.\n");
- domain_crash_synchronous();
- }
-
- t = (struct hvm_info_table *)(p + HVM_INFO_OFFSET);
-
- if ( validate_hvm_info(t) ) {
- d->arch.vmx_platform.nr_vcpus = t->nr_vcpus;
- d->arch.vmx_platform.apic_enabled = t->apic_enabled;
- } else {
- printk("Bad hvm info table\n");
- d->arch.vmx_platform.nr_vcpus = 1;
- d->arch.vmx_platform.apic_enabled = 0;
- }
-
- unmap_domain_page(p);
-}
-
-static void vmx_setup_platform(struct domain* d)
-{
- struct vmx_platform *platform;
-
- vmx_map_io_shared_page(d);
- vmx_get_hvm_info(d);
-
- platform = &d->arch.vmx_platform;
- pic_init(&platform->vmx_pic, pic_irq_request,
- &platform->interrupt_request);
- register_pic_io_hook();
-
- if ( vmx_apic_support(d) ) {
- spin_lock_init(&d->arch.vmx_platform.round_robin_lock);
- vmx_vioapic_init(d);
- }
-}
-
static void vmx_set_host_env(struct vcpu *v)
{
unsigned int tr, cpu, error = 0;
@@ -310,7 +178,7 @@ static void vmx_do_launch(struct vcpu *v)
u64 host_tsc;
if (v->vcpu_id == 0)
- vmx_setup_platform(v->domain);
+ hvm_setup_platform(v->domain);
__asm__ __volatile__ ("mov %%cr0,%0" : "=r" (cr0) : );
@@ -337,11 +205,11 @@ static void vmx_do_launch(struct vcpu *v)
vmx_stts();
- if(vmx_apic_support(v->domain))
+ if(hvm_apic_support(v->domain))
vlapic_init(v);
vmx_set_host_env(v);
- init_timer(&v->arch.arch_vmx.hlt_timer, hlt_timer_fn, v, v->processor);
+ init_timer(&v->arch.hvm_vmx.hlt_timer, hlt_timer_fn, v, v->processor);
error |= __vmwrite(GUEST_LDTR_SELECTOR, 0);
error |= __vmwrite(GUEST_LDTR_BASE, 0);
@@ -355,12 +223,12 @@ static void vmx_do_launch(struct vcpu *v)
__vmwrite(HOST_RSP, (unsigned long)get_stack_bottom());
v->arch.schedule_tail = arch_vmx_do_resume;
- v->arch.arch_vmx.launch_cpu = smp_processor_id();
+ v->arch.hvm_vmx.launch_cpu = smp_processor_id();
/* init guest tsc to start from 0 */
rdtscll(host_tsc);
- v->arch.arch_vmx.tsc_offset = 0 - host_tsc;
- set_tsc_shift (v, &v->domain->arch.vmx_platform.vmx_pit);
+ v->arch.hvm_vmx.tsc_offset = 0 - host_tsc;
+ vmx_set_tsc_shift(v, &v->domain->arch.hvm_domain.vpit);
}
/*
@@ -458,8 +326,8 @@ static inline int construct_init_vmcs_guest(cpu_user_regs_t *regs)
error |= __vmwrite(GUEST_RIP, regs->eip);
/* Guest EFLAGS */
- eflags = regs->eflags & ~VMCS_EFLAGS_RESERVED_0; /* clear 0s */
- eflags |= VMCS_EFLAGS_RESERVED_1; /* set 1s */
+ eflags = regs->eflags & ~HVM_EFLAGS_RESERVED_0; /* clear 0s */
+ eflags |= HVM_EFLAGS_RESERVED_1; /* set 1s */
error |= __vmwrite(GUEST_RFLAGS, eflags);
error |= __vmwrite(GUEST_INTERRUPTIBILITY_INFO, 0);
@@ -528,6 +396,7 @@ static int construct_vmcs(struct arch_vmx_struct *arch_vmx,
u64 vmcs_phys_ptr;
memset(arch_vmx, 0, sizeof(struct arch_vmx_struct));
+
/*
* Create a new VMCS
*/
@@ -614,7 +483,9 @@ int modify_vmcs(struct arch_vmx_struct *arch_vmx,
(unsigned long) vmcs_phys_ptr);
return -EINVAL;
}
- load_cpu_user_regs(regs);
+
+/* XXX VMX change modify_vmcs arg to v */
+ hvm_load_cpu_guest_regs(current, regs);
__vmptrld(old_phys_ptr);
@@ -626,7 +497,7 @@ void vm_launch_fail(unsigned long eflags)
unsigned long error;
__vmread(VM_INSTRUCTION_ERROR, &error);
printk("<vm_launch_fail> error code %lx\n", error);
- __vmx_bug(guest_cpu_user_regs());
+ __hvm_bug(guest_cpu_user_regs());
}
void vm_resume_fail(unsigned long eflags)
@@ -634,24 +505,24 @@ void vm_resume_fail(unsigned long eflags)
unsigned long error;
__vmread(VM_INSTRUCTION_ERROR, &error);
printk("<vm_resume_fail> error code %lx\n", error);
- __vmx_bug(guest_cpu_user_regs());
+ __hvm_bug(guest_cpu_user_regs());
}
void arch_vmx_do_resume(struct vcpu *v)
{
- if ( v->arch.arch_vmx.launch_cpu == smp_processor_id() )
+ if ( v->arch.hvm_vmx.launch_cpu == smp_processor_id() )
{
- load_vmcs(&v->arch.arch_vmx, virt_to_phys(v->arch.arch_vmx.vmcs));
+ load_vmcs(&v->arch.hvm_vmx, virt_to_phys(v->arch.hvm_vmx.vmcs));
vmx_do_resume(v);
reset_stack_and_jump(vmx_asm_do_resume);
}
else
{
- __vmpclear(virt_to_phys(v->arch.arch_vmx.vmcs));
- load_vmcs(&v->arch.arch_vmx, virt_to_phys(v->arch.arch_vmx.vmcs));
+ __vmpclear(virt_to_phys(v->arch.hvm_vmx.vmcs));
+ load_vmcs(&v->arch.hvm_vmx, virt_to_phys(v->arch.hvm_vmx.vmcs));
vmx_do_resume(v);
vmx_set_host_env(v);
- v->arch.arch_vmx.launch_cpu = smp_processor_id();
+ v->arch.hvm_vmx.launch_cpu = smp_processor_id();
reset_stack_and_jump(vmx_asm_do_relaunch);
}
}
@@ -661,7 +532,7 @@ void arch_vmx_do_launch(struct vcpu *v)
int error;
cpu_user_regs_t *regs = &current->arch.guest_context.user_regs;
- error = construct_vmcs(&v->arch.arch_vmx, regs);
+ error = construct_vmcs(&v->arch.hvm_vmx, regs);
if ( error < 0 )
{
if (v->vcpu_id == 0) {
@@ -674,7 +545,6 @@ void arch_vmx_do_launch(struct vcpu *v)
vmx_do_launch(v);
reset_stack_and_jump(vmx_asm_do_launch);
}
-
#endif /* CONFIG_VMX */
/*
diff --git a/xen/arch/x86/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index c0d3875073..fe4c839029 100644
--- a/xen/arch/x86/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -35,29 +35,25 @@
#include <asm/types.h>
#include <asm/msr.h>
#include <asm/spinlock.h>
-#include <asm/vmx.h>
-#include <asm/vmx_vmcs.h>
-#include <asm/vmx_intercept.h>
+#include <asm/hvm/hvm.h>
+#include <asm/hvm/support.h>
+#include <asm/hvm/vmx/vmx.h>
+#include <asm/hvm/vmx/vmcs.h>
#include <asm/shadow.h>
#if CONFIG_PAGING_LEVELS >= 3
#include <asm/shadow_64.h>
#endif
#include <public/sched.h>
#include <public/hvm/ioreq.h>
-#include <asm/vmx_vpic.h>
-#include <asm/vmx_vlapic.h>
+#include <asm/hvm/vpic.h>
+#include <asm/hvm/vlapic.h>
-int hvm_enabled;
#ifdef CONFIG_VMX
-unsigned int opt_vmx_debug_level = 0;
-integer_param("vmx_debug", opt_vmx_debug_level);
static unsigned long trace_values[NR_CPUS][4];
#define TRACE_VMEXIT(index,value) trace_values[smp_processor_id()][index]=value
-static int vmx_switch_on;
-
void vmx_final_setup_guest(struct vcpu *v)
{
v->arch.schedule_tail = arch_vmx_do_launch;
@@ -84,31 +80,26 @@ void vmx_final_setup_guest(struct vcpu *v)
SHM_enable|SHM_refcounts|
SHM_translate|SHM_external|SHM_wr_pt_pte);
}
-
- vmx_switch_on = 1;
}
void vmx_relinquish_resources(struct vcpu *v)
{
- struct vmx_virpit *vpit;
-
- if ( !VMX_DOMAIN(v) )
- return;
-
+ struct hvm_virpit *vpit;
+
if (v->vcpu_id == 0) {
/* unmap IO shared page */
struct domain *d = v->domain;
- if ( d->arch.vmx_platform.shared_page_va )
+ if ( d->arch.hvm_domain.shared_page_va )
unmap_domain_page_global(
- (void *)d->arch.vmx_platform.shared_page_va);
+ (void *)d->arch.hvm_domain.shared_page_va);
}
- destroy_vmcs(&v->arch.arch_vmx);
+ destroy_vmcs(&v->arch.hvm_vmx);
free_monitor_pagetable(v);
- vpit = &v->domain->arch.vmx_platform.vmx_pit;
+ vpit = &v->domain->arch.hvm_domain.vpit;
kill_timer(&vpit->pit_timer);
- kill_timer(&v->arch.arch_vmx.hlt_timer);
- if ( vmx_apic_support(v->domain) && (VLAPIC(v) != NULL) )
+ kill_timer(&v->arch.hvm_vmx.hlt_timer);
+ if ( hvm_apic_support(v->domain) && (VLAPIC(v) != NULL) )
{
kill_timer(&VLAPIC(v)->vlapic_timer);
xfree(VLAPIC(v));
@@ -116,7 +107,7 @@ void vmx_relinquish_resources(struct vcpu *v)
}
#ifdef __x86_64__
-static struct msr_state percpu_msr[NR_CPUS];
+static struct vmx_msr_state percpu_msr[NR_CPUS];
static u32 msr_data_index[VMX_MSR_COUNT] =
{
@@ -124,6 +115,11 @@ static u32 msr_data_index[VMX_MSR_COUNT] =
MSR_SYSCALL_MASK, MSR_EFER,
};
+void vmx_save_segments(struct vcpu *v)
+{
+ rdmsrl(MSR_SHADOW_GS_BASE, v->arch.hvm_vmx.msr_content.shadow_gs);
+}
+
/*
* To avoid MSR save/restore at every VM exit/entry time, we restore
* the x86_64 specific MSRs at domain switch time. Since those MSRs are
@@ -132,10 +128,10 @@ static u32 msr_data_index[VMX_MSR_COUNT] =
*/
void vmx_load_msrs(struct vcpu *n)
{
- struct msr_state *host_state = &percpu_msr[smp_processor_id()];
+ struct vmx_msr_state *host_state = &percpu_msr[smp_processor_id()];
int i;
- if ( !vmx_switch_on )
+ if ( !hvm_switch_on )
return;
while ( host_state->flags )
@@ -148,7 +144,7 @@ void vmx_load_msrs(struct vcpu *n)
static void vmx_save_init_msrs(void)
{
- struct msr_state *host_state = &percpu_msr[smp_processor_id()];
+ struct vmx_msr_state *host_state = &percpu_msr[smp_processor_id()];
int i;
for ( i = 0; i < VMX_MSR_COUNT; i++ )
@@ -177,13 +173,13 @@ static inline int long_mode_do_msr_read(struct cpu_user_regs *regs)
{
u64 msr_content = 0;
struct vcpu *vc = current;
- struct msr_state * msr = &vc->arch.arch_vmx.msr_content;
+ struct vmx_msr_state * msr = &vc->arch.hvm_vmx.msr_content;
switch(regs->ecx){
case MSR_EFER:
msr_content = msr->msr_items[VMX_INDEX_MSR_EFER];
- VMX_DBG_LOG(DBG_LEVEL_2, "EFER msr_content %llx\n", (unsigned long long)msr_content);
+ HVM_DBG_LOG(DBG_LEVEL_2, "EFER msr_content %llx\n", (unsigned long long)msr_content);
if (test_bit(VMX_CPU_STATE_LME_ENABLED,
- &vc->arch.arch_vmx.cpu_state))
+ &vc->arch.hvm_vmx.cpu_state))
msr_content |= 1 << _EFER_LME;
if (VMX_LONG_GUEST(vc))
@@ -211,7 +207,7 @@ static inline int long_mode_do_msr_read(struct cpu_user_regs *regs)
default:
return 0;
}
- VMX_DBG_LOG(DBG_LEVEL_2, "mode_do_msr_read: msr_content: %lx\n", msr_content);
+ HVM_DBG_LOG(DBG_LEVEL_2, "mode_do_msr_read: msr_content: %lx\n", msr_content);
regs->eax = msr_content & 0xffffffff;
regs->edx = msr_content >> 32;
return 1;
@@ -221,28 +217,28 @@ static inline int long_mode_do_msr_write(struct cpu_user_regs *regs)
{
u64 msr_content = regs->eax | ((u64)regs->edx << 32);
struct vcpu *vc = current;
- struct msr_state * msr = &vc->arch.arch_vmx.msr_content;
- struct msr_state * host_state =
+ struct vmx_msr_state * msr = &vc->arch.hvm_vmx.msr_content;
+ struct vmx_msr_state * host_state =
&percpu_msr[smp_processor_id()];
- VMX_DBG_LOG(DBG_LEVEL_1, " mode_do_msr_write msr %lx msr_content %lx\n",
+ HVM_DBG_LOG(DBG_LEVEL_1, " mode_do_msr_write msr %lx msr_content %lx\n",
regs->ecx, msr_content);
switch (regs->ecx){
case MSR_EFER:
if ((msr_content & EFER_LME) ^
test_bit(VMX_CPU_STATE_LME_ENABLED,
- &vc->arch.arch_vmx.cpu_state)){
+ &vc->arch.hvm_vmx.cpu_state)){
if (test_bit(VMX_CPU_STATE_PG_ENABLED,
- &vc->arch.arch_vmx.cpu_state) ||
+ &vc->arch.hvm_vmx.cpu_state) ||
!test_bit(VMX_CPU_STATE_PAE_ENABLED,
- &vc->arch.arch_vmx.cpu_state)){
+ &vc->arch.hvm_vmx.cpu_state)){
vmx_inject_exception(vc, TRAP_gp_fault, 0);
}
}
if (msr_content & EFER_LME)
set_bit(VMX_CPU_STATE_LME_ENABLED,
- &vc->arch.arch_vmx.cpu_state);
+ &vc->arch.hvm_vmx.cpu_state);
/* No update for LME/LMA since it have no effect */
msr->msr_items[VMX_INDEX_MSR_EFER] =
msr_content;
@@ -263,7 +259,7 @@ static inline int long_mode_do_msr_write(struct cpu_user_regs *regs)
if (!(VMX_LONG_GUEST(vc)))
domain_crash_synchronous();
if (!IS_CANO_ADDRESS(msr_content)){
- VMX_DBG_LOG(DBG_LEVEL_1, "Not cano address of msr write\n");
+ HVM_DBG_LOG(DBG_LEVEL_1, "Not cano address of msr write\n");
vmx_inject_exception(vc, TRAP_gp_fault, 0);
}
if (regs->ecx == MSR_FS_BASE)
@@ -275,7 +271,7 @@ static inline int long_mode_do_msr_write(struct cpu_user_regs *regs)
case MSR_SHADOW_GS_BASE:
if (!(VMX_LONG_GUEST(vc)))
domain_crash_synchronous();
- vc->arch.arch_vmx.msr_content.shadow_gs = msr_content;
+ vc->arch.hvm_vmx.msr_content.shadow_gs = msr_content;
wrmsrl(MSR_SHADOW_GS_BASE, msr_content);
break;
@@ -293,11 +289,11 @@ void
vmx_restore_msrs(struct vcpu *v)
{
int i = 0;
- struct msr_state *guest_state;
- struct msr_state *host_state;
+ struct vmx_msr_state *guest_state;
+ struct vmx_msr_state *host_state;
unsigned long guest_flags ;
- guest_state = &v->arch.arch_vmx.msr_content;;
+ guest_state = &v->arch.hvm_vmx.msr_content;;
host_state = &percpu_msr[smp_processor_id()];
wrmsrl(MSR_SHADOW_GS_BASE, guest_state->shadow_gs);
@@ -308,7 +304,7 @@ vmx_restore_msrs(struct vcpu *v)
while (guest_flags){
i = find_first_set_bit(guest_flags);
- VMX_DBG_LOG(DBG_LEVEL_2,
+ HVM_DBG_LOG(DBG_LEVEL_2,
"restore guest's index %d msr %lx with %lx\n",
i, (unsigned long) msr_data_index[i], (unsigned long) guest_state->msr_items[i]);
set_bit(i, &host_state->flags);
@@ -316,7 +312,6 @@ vmx_restore_msrs(struct vcpu *v)
clear_bit(i, &guest_flags);
}
}
-
#else /* __i386__ */
#define vmx_save_init_msrs() ((void)0)
@@ -328,6 +323,111 @@ static inline int long_mode_do_msr_write(struct cpu_user_regs *regs){
}
#endif
+void stop_vmx(void)
+{
+ if (read_cr4() & X86_CR4_VMXE)
+ __vmxoff();
+}
+
+int vmx_initialize_guest_resources(struct vcpu *v)
+{
+ vmx_final_setup_guest(v);
+ return 1;
+}
+
+int vmx_relinquish_guest_resources(struct vcpu *v)
+{
+ vmx_relinquish_resources(v);
+ return 1;
+}
+
+void vmx_store_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *regs)
+{
+#if defined (__x86_64__)
+ __vmread(GUEST_RFLAGS, &regs->rflags);
+ __vmread(GUEST_SS_SELECTOR, &regs->ss);
+ __vmread(GUEST_CS_SELECTOR, &regs->cs);
+ __vmread(GUEST_DS_SELECTOR, &regs->ds);
+ __vmread(GUEST_ES_SELECTOR, &regs->es);
+ __vmread(GUEST_GS_SELECTOR, &regs->gs);
+ __vmread(GUEST_FS_SELECTOR, &regs->fs);
+ __vmread(GUEST_RIP, &regs->rip);
+ __vmread(GUEST_RSP, &regs->rsp);
+#elif defined (__i386__)
+ __vmread(GUEST_RFLAGS, &regs->eflags);
+ __vmread(GUEST_SS_SELECTOR, &regs->ss);
+ __vmread(GUEST_CS_SELECTOR, &regs->cs);
+ __vmread(GUEST_DS_SELECTOR, &regs->ds);
+ __vmread(GUEST_ES_SELECTOR, &regs->es);
+ __vmread(GUEST_GS_SELECTOR, &regs->gs);
+ __vmread(GUEST_FS_SELECTOR, &regs->fs);
+ __vmread(GUEST_RIP, &regs->eip);
+ __vmread(GUEST_RSP, &regs->esp);
+#else
+#error Unsupported architecture
+#endif
+}
+
+void vmx_load_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *regs)
+{
+#if defined (__x86_64__)
+ __vmwrite(GUEST_SS_SELECTOR, regs->ss);
+ __vmwrite(GUEST_RSP, regs->rsp);
+
+ __vmwrite(GUEST_RFLAGS, regs->rflags);
+ if (regs->rflags & EF_TF)
+ __vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
+ else
+ __vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
+
+ __vmwrite(GUEST_CS_SELECTOR, regs->cs);
+ __vmwrite(GUEST_RIP, regs->rip);
+#elif defined (__i386__)
+ __vmwrite(GUEST_SS_SELECTOR, regs->ss);
+ __vmwrite(GUEST_RSP, regs->esp);
+
+ __vmwrite(GUEST_RFLAGS, regs->eflags);
+ if (regs->eflags & EF_TF)
+ __vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
+ else
+ __vm_clear_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_DB);
+
+ __vmwrite(GUEST_CS_SELECTOR, regs->cs);
+ __vmwrite(GUEST_RIP, regs->eip);
+#else
+#error Unsupported architecture
+#endif
+}
+
+void vmx_store_cpu_guest_ctrl_regs(struct vcpu *v, unsigned long crs[8])
+{
+ __vmread(CR0_READ_SHADOW, &crs[0]);
+ __vmread(GUEST_CR3, &crs[3]);
+ __vmread(CR4_READ_SHADOW, &crs[4]);
+}
+
+void vmx_modify_guest_state(struct vcpu *v)
+{
+ modify_vmcs(&v->arch.hvm_vmx, &v->arch.guest_context.user_regs);
+}
+
+int vmx_realmode(struct vcpu *v)
+{
+ unsigned long rflags;
+
+ __vmread(GUEST_RFLAGS, &rflags);
+ return rflags & X86_EFLAGS_VM;
+}
+
+int vmx_instruction_length(struct vcpu *v)
+{
+ unsigned long inst_len;
+
+ if (__vmread(VM_EXIT_INSTRUCTION_LEN, &inst_len))
+ return 0;
+ return inst_len;
+}
+
extern long evtchn_send(int lport);
void do_nmi(struct cpu_user_regs *);
@@ -403,24 +503,40 @@ int start_vmx(void)
vmx_save_init_msrs();
+ /* Setup HVM interfaces */
+ hvm_funcs.disable = stop_vmx;
+
+ hvm_funcs.initialize_guest_resources = vmx_initialize_guest_resources;
+ hvm_funcs.relinquish_guest_resources = vmx_relinquish_guest_resources;
+
+ hvm_funcs.store_cpu_guest_regs = vmx_store_cpu_guest_regs;
+ hvm_funcs.load_cpu_guest_regs = vmx_load_cpu_guest_regs;
+
+#ifdef __x86_64__
+ hvm_funcs.save_segments = vmx_save_segments;
+ hvm_funcs.load_msrs = vmx_load_msrs;
+ hvm_funcs.restore_msrs = vmx_restore_msrs;
+#endif
+
+ hvm_funcs.store_cpu_guest_ctrl_regs = vmx_store_cpu_guest_ctrl_regs;
+ hvm_funcs.modify_guest_state = vmx_modify_guest_state;
+
+ hvm_funcs.realmode = vmx_realmode;
+ hvm_funcs.paging_enabled = vmx_paging_enabled;
+ hvm_funcs.instruction_length = vmx_instruction_length;
+
hvm_enabled = 1;
return 1;
}
-void stop_vmx(void)
-{
- if (read_cr4() & X86_CR4_VMXE)
- __vmxoff();
-}
-
/*
* Not all cases receive valid value in the VM-exit instruction length field.
*/
#define __get_instruction_length(len) \
__vmread(VM_EXIT_INSTRUCTION_LEN, &(len)); \
if ((len) < 1 || (len) > 15) \
- __vmx_bug(&regs);
+ __hvm_bug(&regs);
static void inline __update_guest_eip(unsigned long inst_len)
{
@@ -441,7 +557,7 @@ static int vmx_do_page_fault(unsigned long va, struct cpu_user_regs *regs)
unsigned long eip;
__vmread(GUEST_RIP, &eip);
- VMX_DBG_LOG(DBG_LEVEL_VMMU,
+ HVM_DBG_LOG(DBG_LEVEL_VMMU,
"vmx_do_page_fault = 0x%lx, eip = %lx, error_code = %lx",
va, eip, (unsigned long)regs->error_code);
}
@@ -458,7 +574,7 @@ static int vmx_do_page_fault(unsigned long va, struct cpu_user_regs *regs)
if ( mmio_space(gpa) ){
struct vcpu *v = current;
/* No support for APIC */
- if (!vmx_apic_support(v->domain) && gpa >= 0xFEC00000) {
+ if (!hvm_apic_support(v->domain) && gpa >= 0xFEC00000) {
u32 inst_len;
__vmread(VM_EXIT_INSTRUCTION_LEN, &(inst_len));
__update_guest_eip(inst_len);
@@ -509,7 +625,7 @@ static void vmx_vmexit_do_cpuid(unsigned long input, struct cpu_user_regs *regs)
__vmread(GUEST_RIP, &eip);
- VMX_DBG_LOG(DBG_LEVEL_1,
+ HVM_DBG_LOG(DBG_LEVEL_1,
"do_cpuid: (eax) %lx, (ebx) %lx, (ecx) %lx, (edx) %lx,"
" (esi) %lx, (edi) %lx",
(unsigned long)regs->eax, (unsigned long)regs->ebx,
@@ -518,10 +634,10 @@ static void vmx_vmexit_do_cpuid(unsigned long input, struct cpu_user_regs *regs)
cpuid(input, &eax, &ebx, &ecx, &edx);
- if ( input == 1 )
+ if (input == 1)
{
- if ( vmx_apic_support(v->domain) &&
- !vlapic_global_enabled((VLAPIC(v))) )
+ if ( hvm_apic_support(v->domain) &&
+ !vlapic_global_enabled((VLAPIC(v))) )
clear_bit(X86_FEATURE_APIC, &edx);
#ifdef __x86_64__
@@ -551,7 +667,7 @@ static void vmx_vmexit_do_cpuid(unsigned long input, struct cpu_user_regs *regs)
regs->ecx = (unsigned long) ecx;
regs->edx = (unsigned long) edx;
- VMX_DBG_LOG(DBG_LEVEL_1,
+ HVM_DBG_LOG(DBG_LEVEL_1,
"vmx_vmexit_do_cpuid: eip: %lx, input: %lx, out:eax=%x, ebx=%x, ecx=%x, edx=%x",
eip, input, eax, ebx, ecx, edx);
@@ -571,7 +687,7 @@ static void vmx_dr_access (unsigned long exit_qualification, struct cpu_user_reg
reg = exit_qualification & DEBUG_REG_ACCESS_NUM;
- VMX_DBG_LOG(DBG_LEVEL_1,
+ HVM_DBG_LOG(DBG_LEVEL_1,
"vmx_dr_access : eip=%lx, reg=%d, exit_qualification = %lx",
eip, reg, exit_qualification);
@@ -586,7 +702,7 @@ static void vmx_dr_access (unsigned long exit_qualification, struct cpu_user_reg
case REG_ESP:
break;
default:
- __vmx_bug(regs);
+ __hvm_bug(regs);
}
switch (exit_qualification & DEBUG_REG_ACCESS_TYPE) {
@@ -621,7 +737,7 @@ static void vmx_vmexit_do_invlpg(unsigned long va)
__vmread(GUEST_RIP, &eip);
- VMX_DBG_LOG(DBG_LEVEL_VMMU, "vmx_vmexit_do_invlpg: eip=%lx, va=%lx",
+ HVM_DBG_LOG(DBG_LEVEL_VMMU, "vmx_vmexit_do_invlpg: eip=%lx, va=%lx",
eip, va);
/*
@@ -680,54 +796,9 @@ static int check_for_null_selector(unsigned long eip)
return 0;
}
-void send_pio_req(struct cpu_user_regs *regs, unsigned long port,
- unsigned long count, int size, long value, int dir, int pvalid)
-{
- struct vcpu *v = current;
- vcpu_iodata_t *vio;
- ioreq_t *p;
-
- vio = get_vio(v->domain, v->vcpu_id);
- if (vio == NULL) {
- printk("bad shared page: %lx\n", (unsigned long) vio);
- domain_crash_synchronous();
- }
-
- if (test_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags)) {
- printf("VMX I/O has not yet completed\n");
- domain_crash_synchronous();
- }
- set_bit(ARCH_VMX_IO_WAIT, &v->arch.arch_vmx.flags);
-
- p = &vio->vp_ioreq;
- p->dir = dir;
- p->pdata_valid = pvalid;
-
- p->type = IOREQ_TYPE_PIO;
- p->size = size;
- p->addr = port;
- p->count = count;
- p->df = regs->eflags & EF_DF ? 1 : 0;
-
- if (pvalid) {
- if (vmx_paging_enabled(current))
- p->u.pdata = (void *) gva_to_gpa(value);
- else
- p->u.pdata = (void *) value; /* guest VA == guest PA */
- } else
- p->u.data = value;
-
- if (vmx_portio_intercept(p)) {
- p->state = STATE_IORESP_READY;
- vmx_io_assist(v);
- return;
- }
-
- p->state = STATE_IOREQ_READY;
-
- evtchn_send(iopacket_port(v->domain));
- vmx_wait_io();
-}
+extern void send_pio_req(struct cpu_user_regs *regs, unsigned long port,
+ unsigned long count, int size, long value,
+ int dir, int pvalid);
static void vmx_io_instruction(struct cpu_user_regs *regs,
unsigned long exit_qualification, unsigned long inst_len)
@@ -737,7 +808,7 @@ static void vmx_io_instruction(struct cpu_user_regs *regs,
unsigned long port, size, dir;
int vm86;
- mmio_opp = &current->arch.arch_vmx.mmio_op;
+ mmio_opp = &current->arch.hvm_vcpu.mmio_op;
mmio_opp->instr = INSTR_PIO;
mmio_opp->flags = 0;
@@ -746,7 +817,7 @@ static void vmx_io_instruction(struct cpu_user_regs *regs,
__vmread(GUEST_RFLAGS, &eflags);
vm86 = eflags & X86_EFLAGS_VM ? 1 : 0;
- VMX_DBG_LOG(DBG_LEVEL_1,
+ HVM_DBG_LOG(DBG_LEVEL_1,
"vmx_io_instruction: vm86 %d, eip=%lx:%lx, "
"exit_qualification = %lx",
vm86, cs, eip, exit_qualification);
@@ -779,14 +850,14 @@ static void vmx_io_instruction(struct cpu_user_regs *regs,
/*
* Handle string pio instructions that cross pages or that
- * are unaligned. See the comments in vmx_platform.c/handle_mmio()
+ * are unaligned. See the comments in hvm_domain.c/handle_mmio()
*/
if ((addr & PAGE_MASK) != ((addr + size - 1) & PAGE_MASK)) {
unsigned long value = 0;
mmio_opp->flags |= OVERLAP;
if (dir == IOREQ_WRITE)
- vmx_copy(&value, addr, size, VMX_COPY_IN);
+ hvm_copy(&value, addr, size, HVM_COPY_IN);
send_pio_req(regs, port, 1, size, value, dir, 0);
} else {
if ((addr & PAGE_MASK) != ((addr + count * size - 1) & PAGE_MASK)) {
@@ -800,49 +871,15 @@ static void vmx_io_instruction(struct cpu_user_regs *regs,
send_pio_req(regs, port, count, size, addr, dir, 1);
}
} else {
+ if (port == 0xe9 && dir == IOREQ_WRITE && size == 1)
+ hvm_print_line(current, regs->eax); /* guest debug output */
+
__update_guest_eip(inst_len);
send_pio_req(regs, port, 1, size, regs->eax, dir, 0);
}
}
int
-vmx_copy(void *buf, unsigned long laddr, int size, int dir)
-{
- unsigned long gpa, mfn;
- char *addr;
- int count;
-
- while (size > 0) {
- count = PAGE_SIZE - (laddr & ~PAGE_MASK);
- if (count > size)
- count = size;
-
- if (vmx_paging_enabled(current)) {
- gpa = gva_to_gpa(laddr);
- mfn = get_mfn_from_pfn(gpa >> PAGE_SHIFT);
- } else
- mfn = get_mfn_from_pfn(laddr >> PAGE_SHIFT);
- if (mfn == INVALID_MFN)
- return 0;
-
- addr = (char *)map_domain_page(mfn) + (laddr & ~PAGE_MASK);
-
- if (dir == VMX_COPY_IN)
- memcpy(buf, addr, count);
- else
- memcpy(addr, buf, count);
-
- unmap_domain_page(addr);
-
- laddr += count;
- buf += count;
- size -= count;
- }
-
- return 1;
-}
-
-int
vmx_world_save(struct vcpu *v, struct vmx_assist_context *c)
{
unsigned long inst_len;
@@ -855,7 +892,7 @@ vmx_world_save(struct vcpu *v, struct vmx_assist_context *c)
error |= __vmread(GUEST_RFLAGS, &c->eflags);
error |= __vmread(CR0_READ_SHADOW, &c->cr0);
- c->cr3 = v->arch.arch_vmx.cpu_cr3;
+ c->cr3 = v->arch.hvm_vmx.cpu_cr3;
error |= __vmread(CR4_READ_SHADOW, &c->cr4);
error |= __vmread(GUEST_IDTR_LIMIT, &c->idtr_limit);
@@ -920,12 +957,12 @@ vmx_world_restore(struct vcpu *v, struct vmx_assist_context *c)
error |= __vmwrite(CR0_READ_SHADOW, c->cr0);
if (!vmx_paging_enabled(v)) {
- VMX_DBG_LOG(DBG_LEVEL_VMMU, "switching to vmxassist. use phys table");
+ HVM_DBG_LOG(DBG_LEVEL_VMMU, "switching to vmxassist. use phys table");
__vmwrite(GUEST_CR3, pagetable_get_paddr(v->domain->arch.phys_table));
goto skip_cr3;
}
- if (c->cr3 == v->arch.arch_vmx.cpu_cr3) {
+ if (c->cr3 == v->arch.hvm_vmx.cpu_cr3) {
/*
* This is simple TLB flush, implying the guest has
* removed some translation or changed page attributes.
@@ -943,7 +980,7 @@ vmx_world_restore(struct vcpu *v, struct vmx_assist_context *c)
* If different, make a shadow. Check if the PDBR is valid
* first.
*/
- VMX_DBG_LOG(DBG_LEVEL_VMMU, "CR3 c->cr3 = %x", c->cr3);
+ HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 c->cr3 = %x", c->cr3);
if ((c->cr3 >> PAGE_SHIFT) > v->domain->max_pages) {
printk("Invalid CR3 value=%x", c->cr3);
domain_crash_synchronous();
@@ -960,8 +997,8 @@ vmx_world_restore(struct vcpu *v, struct vmx_assist_context *c)
/*
* arch.shadow_table should now hold the next CR3 for shadow
*/
- v->arch.arch_vmx.cpu_cr3 = c->cr3;
- VMX_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %x", c->cr3);
+ v->arch.hvm_vmx.cpu_cr3 = c->cr3;
+ HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %x", c->cr3);
__vmwrite(GUEST_CR3, pagetable_get_paddr(v->arch.shadow_table));
}
@@ -1030,7 +1067,7 @@ vmx_assist(struct vcpu *v, int mode)
u32 cp;
/* make sure vmxassist exists (this is not an error) */
- if (!vmx_copy(&magic, VMXASSIST_MAGIC_OFFSET, sizeof(magic), VMX_COPY_IN))
+ if (!hvm_copy(&magic, VMXASSIST_MAGIC_OFFSET, sizeof(magic), HVM_COPY_IN))
return 0;
if (magic != VMXASSIST_MAGIC)
return 0;
@@ -1044,20 +1081,20 @@ vmx_assist(struct vcpu *v, int mode)
*/
case VMX_ASSIST_INVOKE:
/* save the old context */
- if (!vmx_copy(&cp, VMXASSIST_OLD_CONTEXT, sizeof(cp), VMX_COPY_IN))
+ if (!hvm_copy(&cp, VMXASSIST_OLD_CONTEXT, sizeof(cp), HVM_COPY_IN))
goto error;
if (cp != 0) {
if (!vmx_world_save(v, &c))
goto error;
- if (!vmx_copy(&c, cp, sizeof(c), VMX_COPY_OUT))
+ if (!hvm_copy(&c, cp, sizeof(c), HVM_COPY_OUT))
goto error;
}
/* restore the new context, this should activate vmxassist */
- if (!vmx_copy(&cp, VMXASSIST_NEW_CONTEXT, sizeof(cp), VMX_COPY_IN))
+ if (!hvm_copy(&cp, VMXASSIST_NEW_CONTEXT, sizeof(cp), HVM_COPY_IN))
goto error;
if (cp != 0) {
- if (!vmx_copy(&c, cp, sizeof(c), VMX_COPY_IN))
+ if (!hvm_copy(&c, cp, sizeof(c), HVM_COPY_IN))
goto error;
if (!vmx_world_restore(v, &c))
goto error;
@@ -1071,10 +1108,10 @@ vmx_assist(struct vcpu *v, int mode)
*/
case VMX_ASSIST_RESTORE:
/* save the old context */
- if (!vmx_copy(&cp, VMXASSIST_OLD_CONTEXT, sizeof(cp), VMX_COPY_IN))
+ if (!hvm_copy(&cp, VMXASSIST_OLD_CONTEXT, sizeof(cp), HVM_COPY_IN))
goto error;
if (cp != 0) {
- if (!vmx_copy(&c, cp, sizeof(c), VMX_COPY_IN))
+ if (!hvm_copy(&c, cp, sizeof(c), HVM_COPY_IN))
goto error;
if (!vmx_world_restore(v, &c))
goto error;
@@ -1114,34 +1151,34 @@ static int vmx_set_cr0(unsigned long value)
__vmwrite(GUEST_CR0, value | X86_CR0_PE | X86_CR0_PG | X86_CR0_NE);
__vmwrite(CR0_READ_SHADOW, value);
- VMX_DBG_LOG(DBG_LEVEL_VMMU, "Update CR0 value = %lx\n", value);
+ HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR0 value = %lx\n", value);
if ((value & X86_CR0_PE) && (value & X86_CR0_PG) && !paging_enabled) {
/*
* The guest CR3 must be pointing to the guest physical.
*/
if ( !VALID_MFN(mfn = get_mfn_from_pfn(
- v->arch.arch_vmx.cpu_cr3 >> PAGE_SHIFT)) ||
+ v->arch.hvm_vmx.cpu_cr3 >> PAGE_SHIFT)) ||
!get_page(pfn_to_page(mfn), v->domain) )
{
- printk("Invalid CR3 value = %lx", v->arch.arch_vmx.cpu_cr3);
+ printk("Invalid CR3 value = %lx", v->arch.hvm_vmx.cpu_cr3);
domain_crash_synchronous(); /* need to take a clean path */
}
#if defined(__x86_64__)
if (test_bit(VMX_CPU_STATE_LME_ENABLED,
- &v->arch.arch_vmx.cpu_state) &&
+ &v->arch.hvm_vmx.cpu_state) &&
!test_bit(VMX_CPU_STATE_PAE_ENABLED,
- &v->arch.arch_vmx.cpu_state)){
- VMX_DBG_LOG(DBG_LEVEL_1, "Enable paging before PAE enable\n");
+ &v->arch.hvm_vmx.cpu_state)){
+ HVM_DBG_LOG(DBG_LEVEL_1, "Enable paging before PAE enable\n");
vmx_inject_exception(v, TRAP_gp_fault, 0);
}
if (test_bit(VMX_CPU_STATE_LME_ENABLED,
- &v->arch.arch_vmx.cpu_state)){
+ &v->arch.hvm_vmx.cpu_state)){
/* Here the PAE is should to be opened */
- VMX_DBG_LOG(DBG_LEVEL_1, "Enable the Long mode\n");
+ HVM_DBG_LOG(DBG_LEVEL_1, "Enable the Long mode\n");
set_bit(VMX_CPU_STATE_LMA_ENABLED,
- &v->arch.arch_vmx.cpu_state);
+ &v->arch.hvm_vmx.cpu_state);
__vmread(VM_ENTRY_CONTROLS, &vm_entry_value);
vm_entry_value |= VM_ENTRY_CONTROLS_IA32E_MODE;
__vmwrite(VM_ENTRY_CONTROLS, vm_entry_value);
@@ -1169,9 +1206,9 @@ static int vmx_set_cr0(unsigned long value)
__vmread(GUEST_CR4, &crn);
if ( (!(crn & X86_CR4_PAE)) &&
test_bit(VMX_CPU_STATE_PAE_ENABLED,
- &v->arch.arch_vmx.cpu_state) )
+ &v->arch.hvm_vmx.cpu_state) )
{
- VMX_DBG_LOG(DBG_LEVEL_1, "enable PAE on cr4\n");
+ HVM_DBG_LOG(DBG_LEVEL_1, "enable PAE on cr4\n");
__vmwrite(GUEST_CR4, crn | X86_CR4_PAE);
}
}
@@ -1182,21 +1219,21 @@ static int vmx_set_cr0(unsigned long value)
v->arch.guest_table = mk_pagetable(mfn << PAGE_SHIFT);
update_pagetables(v);
- VMX_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx",
+ HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx",
(unsigned long) (mfn << PAGE_SHIFT));
__vmwrite(GUEST_CR3, pagetable_get_paddr(v->arch.shadow_table));
/*
* arch->shadow_table should hold the next CR3 for shadow
*/
- VMX_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx, mfn = %lx",
- v->arch.arch_vmx.cpu_cr3, mfn);
+ HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx, mfn = %lx",
+ v->arch.hvm_vmx.cpu_cr3, mfn);
}
if(!((value & X86_CR0_PE) && (value & X86_CR0_PG)) && paging_enabled)
- if(v->arch.arch_vmx.cpu_cr3){
+ if(v->arch.hvm_vmx.cpu_cr3) {
put_page(pfn_to_page(get_mfn_from_pfn(
- v->arch.arch_vmx.cpu_cr3 >> PAGE_SHIFT)));
+ v->arch.hvm_vmx.cpu_cr3 >> PAGE_SHIFT)));
v->arch.guest_table = mk_pagetable(0);
}
@@ -1216,9 +1253,9 @@ static int vmx_set_cr0(unsigned long value)
* Same to PE == 1 && PG == 0
*/
if (test_bit(VMX_CPU_STATE_LMA_ENABLED,
- &v->arch.arch_vmx.cpu_state)){
+ &v->arch.hvm_vmx.cpu_state)){
clear_bit(VMX_CPU_STATE_LMA_ENABLED,
- &v->arch.arch_vmx.cpu_state);
+ &v->arch.hvm_vmx.cpu_state);
__vmread(VM_ENTRY_CONTROLS, &vm_entry_value);
vm_entry_value &= ~VM_ENTRY_CONTROLS_IA32E_MODE;
__vmwrite(VM_ENTRY_CONTROLS, vm_entry_value);
@@ -1227,22 +1264,22 @@ static int vmx_set_cr0(unsigned long value)
clear_all_shadow_status(v->domain);
if (vmx_assist(v, VMX_ASSIST_INVOKE)) {
- set_bit(VMX_CPU_STATE_ASSIST_ENABLED, &v->arch.arch_vmx.cpu_state);
+ set_bit(VMX_CPU_STATE_ASSIST_ENABLED, &v->arch.hvm_vmx.cpu_state);
__vmread(GUEST_RIP, &eip);
- VMX_DBG_LOG(DBG_LEVEL_1,
+ HVM_DBG_LOG(DBG_LEVEL_1,
"Transfering control to vmxassist %%eip 0x%lx\n", eip);
return 0; /* do not update eip! */
}
} else if (test_bit(VMX_CPU_STATE_ASSIST_ENABLED,
- &v->arch.arch_vmx.cpu_state)) {
+ &v->arch.hvm_vmx.cpu_state)) {
__vmread(GUEST_RIP, &eip);
- VMX_DBG_LOG(DBG_LEVEL_1,
+ HVM_DBG_LOG(DBG_LEVEL_1,
"Enabling CR0.PE at %%eip 0x%lx\n", eip);
if (vmx_assist(v, VMX_ASSIST_RESTORE)) {
clear_bit(VMX_CPU_STATE_ASSIST_ENABLED,
- &v->arch.arch_vmx.cpu_state);
+ &v->arch.hvm_vmx.cpu_state);
__vmread(GUEST_RIP, &eip);
- VMX_DBG_LOG(DBG_LEVEL_1,
+ HVM_DBG_LOG(DBG_LEVEL_1,
"Restoring to %%eip 0x%lx\n", eip);
return 0; /* do not update eip! */
}
@@ -1297,11 +1334,11 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs)
break;
default:
printk("invalid gp: %d\n", gp);
- __vmx_bug(regs);
+ __hvm_bug(regs);
}
- VMX_DBG_LOG(DBG_LEVEL_1, "mov_to_cr: CR%d, value = %lx,", cr, value);
- VMX_DBG_LOG(DBG_LEVEL_1, "current = %lx,", (unsigned long) current);
+ HVM_DBG_LOG(DBG_LEVEL_1, "mov_to_cr: CR%d, value = %lx,", cr, value);
+ HVM_DBG_LOG(DBG_LEVEL_1, "current = %lx,", (unsigned long) current);
switch(cr) {
case 0:
@@ -1316,14 +1353,14 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs)
* If paging is not enabled yet, simply copy the value to CR3.
*/
if (!vmx_paging_enabled(v)) {
- v->arch.arch_vmx.cpu_cr3 = value;
+ v->arch.hvm_vmx.cpu_cr3 = value;
break;
}
/*
* We make a new one if the shadow does not exist.
*/
- if (value == v->arch.arch_vmx.cpu_cr3) {
+ if (value == v->arch.hvm_vmx.cpu_cr3) {
/*
* This is simple TLB flush, implying the guest has
* removed some translation or changed page attributes.
@@ -1331,14 +1368,14 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs)
*/
mfn = get_mfn_from_pfn(value >> PAGE_SHIFT);
if (mfn != pagetable_get_pfn(v->arch.guest_table))
- __vmx_bug(regs);
+ __hvm_bug(regs);
shadow_sync_all(v->domain);
} else {
/*
* If different, make a shadow. Check if the PDBR is valid
* first.
*/
- VMX_DBG_LOG(DBG_LEVEL_VMMU, "CR3 value = %lx", value);
+ HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 value = %lx", value);
if ( ((value >> PAGE_SHIFT) > v->domain->max_pages ) ||
!VALID_MFN(mfn = get_mfn_from_pfn(value >> PAGE_SHIFT)) ||
!get_page(pfn_to_page(mfn), v->domain) )
@@ -1354,8 +1391,8 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs)
/*
* arch.shadow_table should now hold the next CR3 for shadow
*/
- v->arch.arch_vmx.cpu_cr3 = value;
- VMX_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx",
+ v->arch.hvm_vmx.cpu_cr3 = value;
+ HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx",
value);
__vmwrite(GUEST_CR3, pagetable_get_paddr(v->arch.shadow_table));
}
@@ -1364,13 +1401,13 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs)
case 4: /* CR4 */
{
if (value & X86_CR4_PAE){
- set_bit(VMX_CPU_STATE_PAE_ENABLED, &v->arch.arch_vmx.cpu_state);
+ set_bit(VMX_CPU_STATE_PAE_ENABLED, &v->arch.hvm_vmx.cpu_state);
} else {
if (test_bit(VMX_CPU_STATE_LMA_ENABLED,
- &v->arch.arch_vmx.cpu_state)){
+ &v->arch.hvm_vmx.cpu_state)){
vmx_inject_exception(v, TRAP_gp_fault, 0);
}
- clear_bit(VMX_CPU_STATE_PAE_ENABLED, &v->arch.arch_vmx.cpu_state);
+ clear_bit(VMX_CPU_STATE_PAE_ENABLED, &v->arch.hvm_vmx.cpu_state);
}
__vmread(CR4_READ_SHADOW, &old_cr);
@@ -1389,7 +1426,7 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs)
}
default:
printk("invalid cr: %d\n", gp);
- __vmx_bug(regs);
+ __hvm_bug(regs);
}
return 1;
@@ -1409,9 +1446,9 @@ static void mov_from_cr(int cr, int gp, struct cpu_user_regs *regs)
struct vcpu *v = current;
if (cr != 3)
- __vmx_bug(regs);
+ __hvm_bug(regs);
- value = (unsigned long) v->arch.arch_vmx.cpu_cr3;
+ value = (unsigned long) v->arch.hvm_vmx.cpu_cr3;
switch (gp) {
CASE_SET_REG(EAX, eax);
@@ -1428,10 +1465,10 @@ static void mov_from_cr(int cr, int gp, struct cpu_user_regs *regs)
break;
default:
printk("invalid gp: %d\n", gp);
- __vmx_bug(regs);
+ __hvm_bug(regs);
}
- VMX_DBG_LOG(DBG_LEVEL_VMMU, "mov_from_cr: CR%d, value = %lx,", cr, value);
+ HVM_DBG_LOG(DBG_LEVEL_VMMU, "mov_from_cr: CR%d, value = %lx,", cr, value);
}
static int vmx_cr_access(unsigned long exit_qualification, struct cpu_user_regs *regs)
@@ -1477,7 +1514,7 @@ static int vmx_cr_access(unsigned long exit_qualification, struct cpu_user_regs
return vmx_set_cr0(value);
break;
default:
- __vmx_bug(regs);
+ __hvm_bug(regs);
break;
}
return 1;
@@ -1488,16 +1525,16 @@ static inline void vmx_do_msr_read(struct cpu_user_regs *regs)
u64 msr_content = 0;
struct vcpu *v = current;
- VMX_DBG_LOG(DBG_LEVEL_1, "vmx_do_msr_read: ecx=%lx, eax=%lx, edx=%lx",
+ HVM_DBG_LOG(DBG_LEVEL_1, "vmx_do_msr_read: ecx=%lx, eax=%lx, edx=%lx",
(unsigned long)regs->ecx, (unsigned long)regs->eax,
(unsigned long)regs->edx);
switch (regs->ecx) {
case MSR_IA32_TIME_STAMP_COUNTER:
{
- struct vmx_virpit *vpit;
+ struct hvm_virpit *vpit;
rdtscll(msr_content);
- vpit = &(v->domain->arch.vmx_platform.vmx_pit);
+ vpit = &(v->domain->arch.hvm_domain.vpit);
msr_content += vpit->shift;
break;
}
@@ -1523,7 +1560,7 @@ static inline void vmx_do_msr_read(struct cpu_user_regs *regs)
regs->eax = msr_content & 0xFFFFFFFF;
regs->edx = msr_content >> 32;
- VMX_DBG_LOG(DBG_LEVEL_1, "vmx_do_msr_read returns: "
+ HVM_DBG_LOG(DBG_LEVEL_1, "vmx_do_msr_read returns: "
"ecx=%lx, eax=%lx, edx=%lx",
(unsigned long)regs->ecx, (unsigned long)regs->eax,
(unsigned long)regs->edx);
@@ -1534,7 +1571,7 @@ static inline void vmx_do_msr_write(struct cpu_user_regs *regs)
u64 msr_content;
struct vcpu *v = current;
- VMX_DBG_LOG(DBG_LEVEL_1, "vmx_do_msr_write: ecx=%lx, eax=%lx, edx=%lx",
+ HVM_DBG_LOG(DBG_LEVEL_1, "vmx_do_msr_write: ecx=%lx, eax=%lx, edx=%lx",
(unsigned long)regs->ecx, (unsigned long)regs->eax,
(unsigned long)regs->edx);
@@ -1543,14 +1580,14 @@ static inline void vmx_do_msr_write(struct cpu_user_regs *regs)
switch (regs->ecx) {
case MSR_IA32_TIME_STAMP_COUNTER:
{
- struct vmx_virpit *vpit;
+ struct hvm_virpit *vpit;
u64 host_tsc, drift;
rdtscll(host_tsc);
- vpit = &(v->domain->arch.vmx_platform.vmx_pit);
- drift = v->arch.arch_vmx.tsc_offset - vpit->shift;
+ vpit = &(v->domain->arch.hvm_domain.vpit);
+ drift = v->arch.hvm_vmx.tsc_offset - vpit->shift;
vpit->shift = msr_content - host_tsc;
- v->arch.arch_vmx.tsc_offset = vpit->shift + drift;
+ v->arch.hvm_vmx.tsc_offset = vpit->shift + drift;
__vmwrite(TSC_OFFSET, vpit->shift);
#if defined (__i386__)
@@ -1575,7 +1612,7 @@ static inline void vmx_do_msr_write(struct cpu_user_regs *regs)
break;
}
- VMX_DBG_LOG(DBG_LEVEL_1, "vmx_do_msr_write returns: "
+ HVM_DBG_LOG(DBG_LEVEL_1, "vmx_do_msr_write returns: "
"ecx=%lx, eax=%lx, edx=%lx",
(unsigned long)regs->ecx, (unsigned long)regs->eax,
(unsigned long)regs->edx);
@@ -1587,7 +1624,7 @@ static inline void vmx_do_msr_write(struct cpu_user_regs *regs)
void vmx_vmexit_do_hlt(void)
{
struct vcpu *v=current;
- struct vmx_virpit *vpit = &(v->domain->arch.vmx_platform.vmx_pit);
+ struct hvm_virpit *vpit = &(v->domain->arch.hvm_domain.vpit);
s_time_t next_pit=-1,next_wakeup;
if ( !v->vcpu_id ) {
@@ -1598,7 +1635,7 @@ void vmx_vmexit_do_hlt(void)
next_wakeup = next_pit;
}
if ( next_wakeup != - 1 )
- set_timer(&current->arch.arch_vmx.hlt_timer, next_wakeup);
+ set_timer(&current->arch.hvm_vmx.hlt_timer, next_wakeup);
do_sched_op(SCHEDOP_block, 0);
}
@@ -1618,7 +1655,7 @@ static inline void vmx_vmexit_do_extint(struct cpu_user_regs *regs)
if ((error = __vmread(VM_EXIT_INTR_INFO, &vector))
&& !(vector & INTR_INFO_VALID_MASK))
- __vmx_bug(regs);
+ __hvm_bug(regs);
vector &= 0xff;
local_irq_disable();
@@ -1649,39 +1686,29 @@ static inline void vmx_vmexit_do_extint(struct cpu_user_regs *regs)
}
}
-#define BUF_SIZ 256
-#define MAX_LINE 80
-char print_buf[BUF_SIZ];
-static int index;
-
-static void vmx_print_line(const char c, struct vcpu *v)
+#if defined (__x86_64__)
+void store_cpu_user_regs(struct cpu_user_regs *regs)
{
-
- if (index == MAX_LINE || c == '\n') {
- if (index == MAX_LINE) {
- print_buf[index++] = c;
- }
- print_buf[index] = '\0';
- printk("(GUEST: %u) %s\n", v->domain->domain_id, (char *) &print_buf);
- index = 0;
- }
- else
- print_buf[index++] = c;
+ __vmread(GUEST_SS_SELECTOR, &regs->ss);
+ __vmread(GUEST_RSP, &regs->rsp);
+ __vmread(GUEST_RFLAGS, &regs->rflags);
+ __vmread(GUEST_CS_SELECTOR, &regs->cs);
+ __vmread(GUEST_DS_SELECTOR, &regs->ds);
+ __vmread(GUEST_ES_SELECTOR, &regs->es);
+ __vmread(GUEST_RIP, &regs->rip);
}
-
-void save_vmx_cpu_user_regs(struct cpu_user_regs *ctxt)
+#elif defined (__i386__)
+void store_cpu_user_regs(struct cpu_user_regs *regs)
{
- __vmread(GUEST_SS_SELECTOR, &ctxt->ss);
- __vmread(GUEST_RSP, &ctxt->esp);
- __vmread(GUEST_RFLAGS, &ctxt->eflags);
- __vmread(GUEST_CS_SELECTOR, &ctxt->cs);
- __vmread(GUEST_RIP, &ctxt->eip);
-
- __vmread(GUEST_GS_SELECTOR, &ctxt->gs);
- __vmread(GUEST_FS_SELECTOR, &ctxt->fs);
- __vmread(GUEST_ES_SELECTOR, &ctxt->es);
- __vmread(GUEST_DS_SELECTOR, &ctxt->ds);
+ __vmread(GUEST_SS_SELECTOR, &regs->ss);
+ __vmread(GUEST_RSP, &regs->esp);
+ __vmread(GUEST_RFLAGS, &regs->eflags);
+ __vmread(GUEST_CS_SELECTOR, &regs->cs);
+ __vmread(GUEST_DS_SELECTOR, &regs->ds);
+ __vmread(GUEST_ES_SELECTOR, &regs->es);
+ __vmread(GUEST_RIP, &regs->eip);
}
+#endif
#ifdef XEN_DEBUGGER
void save_cpu_user_regs(struct cpu_user_regs *regs)
@@ -1721,7 +1748,7 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs regs)
int error;
if ((error = __vmread(VM_EXIT_REASON, &exit_reason)))
- __vmx_bug(&regs);
+ __hvm_bug(&regs);
perfc_incra(vmexits, exit_reason);
@@ -1739,14 +1766,14 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs regs)
__vmwrite(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code);
}
- VMX_DBG_LOG(DBG_LEVEL_1, "idtv_info_field=%x", idtv_info_field);
+ HVM_DBG_LOG(DBG_LEVEL_1, "idtv_info_field=%x", idtv_info_field);
}
/* don't bother H/W interrutps */
if (exit_reason != EXIT_REASON_EXTERNAL_INTERRUPT &&
exit_reason != EXIT_REASON_VMCALL &&
exit_reason != EXIT_REASON_IO_INSTRUCTION)
- VMX_DBG_LOG(DBG_LEVEL_0, "exit reason = %x", exit_reason);
+ HVM_DBG_LOG(DBG_LEVEL_0, "exit reason = %x", exit_reason);
if (exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY) {
printk("Failed vm entry\n");
@@ -1774,7 +1801,7 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs regs)
if ((error = __vmread(VM_EXIT_INTR_INFO, &vector))
|| !(vector & INTR_INFO_VALID_MASK))
- __vmx_bug(&regs);
+ __hvm_bug(&regs);
vector &= 0xff;
TRACE_VMEXIT(1,vector);
@@ -1824,19 +1851,19 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs regs)
TRACE_VMEXIT(3,regs.error_code);
TRACE_VMEXIT(4,va);
- VMX_DBG_LOG(DBG_LEVEL_VMMU,
+ HVM_DBG_LOG(DBG_LEVEL_VMMU,
"eax=%lx, ebx=%lx, ecx=%lx, edx=%lx, esi=%lx, edi=%lx",
(unsigned long)regs.eax, (unsigned long)regs.ebx,
(unsigned long)regs.ecx, (unsigned long)regs.edx,
(unsigned long)regs.esi, (unsigned long)regs.edi);
- v->arch.arch_vmx.mmio_op.inst_decoder_regs = &regs;
+ v->arch.hvm_vcpu.mmio_op.inst_decoder_regs = &regs;
if (!(error = vmx_do_page_fault(va, &regs))) {
/*
* Inject #PG using Interruption-Information Fields
*/
vmx_inject_exception(v, TRAP_page_fault, regs.error_code);
- v->arch.arch_vmx.cpu_cr2 = va;
+ v->arch.hvm_vmx.cpu_cr2 = va;
TRACE_3D(TRC_VMX_INT, v->domain->domain_id, TRAP_page_fault, va);
}
break;
@@ -1858,7 +1885,7 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs regs)
MONITOR_CPU_BASED_EXEC_CONTROLS);
break;
case EXIT_REASON_TASK_SWITCH:
- __vmx_bug(&regs);
+ __hvm_bug(&regs);
break;
case EXIT_REASON_CPUID:
__get_instruction_length(inst_len);
@@ -1885,7 +1912,7 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs regs)
__vmread(GUEST_RIP, &eip);
__vmread(EXIT_QUALIFICATION, &exit_qualification);
- vmx_print_line(regs.eax, v); /* provides the current domain */
+ hvm_print_line(v, regs.eax); /* provides the current domain */
__update_guest_eip(inst_len);
break;
case EXIT_REASON_CR_ACCESS:
@@ -1894,7 +1921,7 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs regs)
__get_instruction_length(inst_len);
__vmread(EXIT_QUALIFICATION, &exit_qualification);
- VMX_DBG_LOG(DBG_LEVEL_1, "eip = %lx, inst_len =%lx, exit_qualification = %lx",
+ HVM_DBG_LOG(DBG_LEVEL_1, "eip = %lx, inst_len =%lx, exit_qualification = %lx",
eip, inst_len, exit_qualification);
if (vmx_cr_access(exit_qualification, &regs))
__update_guest_eip(inst_len);
@@ -1926,26 +1953,26 @@ asmlinkage void vmx_vmexit_handler(struct cpu_user_regs regs)
__update_guest_eip(inst_len);
break;
case EXIT_REASON_MWAIT_INSTRUCTION:
- __vmx_bug(&regs);
+ __hvm_bug(&regs);
break;
default:
- __vmx_bug(&regs); /* should not happen */
+ __hvm_bug(&regs); /* should not happen */
}
}
-asmlinkage void load_cr2(void)
+asmlinkage void vmx_load_cr2(void)
{
struct vcpu *v = current;
local_irq_disable();
#ifdef __i386__
- asm volatile("movl %0,%%cr2": :"r" (v->arch.arch_vmx.cpu_cr2));
+ asm volatile("movl %0,%%cr2": :"r" (v->arch.hvm_vmx.cpu_cr2));
#else
- asm volatile("movq %0,%%cr2": :"r" (v->arch.arch_vmx.cpu_cr2));
+ asm volatile("movq %0,%%cr2": :"r" (v->arch.hvm_vmx.cpu_cr2));
#endif
}
-asmlinkage void trace_vmentry (void)
+asmlinkage void vmx_trace_vmentry (void)
{
TRACE_5D(TRC_VMENTRY,
trace_values[smp_processor_id()][0],
@@ -1960,7 +1987,8 @@ asmlinkage void trace_vmentry (void)
TRACE_VMEXIT(4,9);
return;
}
-asmlinkage void trace_vmexit (void)
+
+asmlinkage void vmx_trace_vmexit (void)
{
TRACE_3D(TRC_VMEXIT,0,0,0);
return;
diff --git a/xen/arch/x86/hvm/vmx/x86_32/exits.S b/xen/arch/x86/hvm/vmx/x86_32/exits.S
new file mode 100644
index 0000000000..abf212617b
--- /dev/null
+++ b/xen/arch/x86/hvm/vmx/x86_32/exits.S
@@ -0,0 +1,153 @@
+/*
+ * exits.S: VMX architecture-specific exit handling.
+ * Copyright (c) 2004, Intel 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 <xen/config.h>
+#include <xen/errno.h>
+#include <xen/softirq.h>
+#include <asm/asm_defns.h>
+#include <asm/apicdef.h>
+#include <asm/page.h>
+#include <public/xen.h>
+
+#define GET_CURRENT(reg) \
+ movl $STACK_SIZE-4, reg; \
+ orl %esp, reg; \
+ andl $~3,reg; \
+ movl (reg),reg;
+
+/*
+ * At VMExit time the processor saves the guest selectors, esp, eip,
+ * and eflags. Therefore we don't save them, but simply decrement
+ * the kernel stack pointer to make it consistent with the stack frame
+ * at usual interruption time. The eflags of the host is not saved by VMX,
+ * and we set it to the fixed value.
+ *
+ * We also need the room, especially because orig_eax field is used
+ * by do_IRQ(). Compared the cpu_user_regs, we skip pushing for the following:
+ * (10) u32 gs;
+ * (9) u32 fs;
+ * (8) u32 ds;
+ * (7) u32 es;
+ * <- get_stack_bottom() (= HOST_ESP)
+ * (6) u32 ss;
+ * (5) u32 esp;
+ * (4) u32 eflags;
+ * (3) u32 cs;
+ * (2) u32 eip;
+ * (2/1) u16 entry_vector;
+ * (1/1) u16 error_code;
+ * However, get_stack_bottom() actually returns 20 bytes before the real
+ * bottom of the stack to allow space for:
+ * domain pointer, DS, ES, FS, GS. Therefore, we effectively skip 6 registers.
+ */
+
+#define HVM_MONITOR_EFLAGS 0x202 /* IF on */
+#define NR_SKIPPED_REGS 6 /* See the above explanation */
+#define HVM_SAVE_ALL_NOSEGREGS \
+ pushl $HVM_MONITOR_EFLAGS; \
+ popf; \
+ subl $(NR_SKIPPED_REGS*4), %esp; \
+ movl $0, 0xc(%esp); /* eflags==0 identifies cpu_user_regs as HVM guest */ \
+ pushl %eax; \
+ pushl %ebp; \
+ pushl %edi; \
+ pushl %esi; \
+ pushl %edx; \
+ pushl %ecx; \
+ pushl %ebx;
+
+#define HVM_RESTORE_ALL_NOSEGREGS \
+ popl %ebx; \
+ popl %ecx; \
+ popl %edx; \
+ popl %esi; \
+ popl %edi; \
+ popl %ebp; \
+ popl %eax; \
+ addl $(NR_SKIPPED_REGS*4), %esp
+
+ ALIGN
+
+#ifdef CONFIG_VMX
+
+ENTRY(vmx_asm_vmexit_handler)
+ /* selectors are restored/saved by VMX */
+ HVM_SAVE_ALL_NOSEGREGS
+ call vmx_trace_vmexit
+ call vmx_vmexit_handler
+ jmp vmx_asm_do_resume
+
+.macro vmx_asm_common launch initialized
+1:
+/* vmx_test_all_events */
+ .if \initialized
+ GET_CURRENT(%ebx)
+/*test_all_events:*/
+ xorl %ecx,%ecx
+ notl %ecx
+ cli # tests must not race interrupts
+/*test_softirqs:*/
+ movl VCPU_processor(%ebx),%eax
+ shl $IRQSTAT_shift,%eax
+ test %ecx,irq_stat(%eax,1)
+ jnz 2f
+
+/* vmx_restore_all_guest */
+ call vmx_intr_assist
+ call vmx_load_cr2
+ call vmx_trace_vmentry
+ .endif
+ HVM_RESTORE_ALL_NOSEGREGS
+ /*
+ * Check if we are going back to VMX-based VM
+ * By this time, all the setups in the VMCS must be complete.
+ */
+ .if \launch
+ /* VMLAUNCH */
+ .byte 0x0f,0x01,0xc2
+ pushf
+ call vm_launch_fail
+ .else
+ /* VMRESUME */
+ .byte 0x0f,0x01,0xc3
+ pushf
+ call vm_resume_fail
+ .endif
+ /* Should never reach here */
+ hlt
+
+ ALIGN
+ .if \initialized
+2:
+/* vmx_process_softirqs */
+ sti
+ call do_softirq
+ jmp 1b
+ ALIGN
+ .endif
+.endm
+
+ENTRY(vmx_asm_do_launch)
+ vmx_asm_common 1 0
+
+ENTRY(vmx_asm_do_resume)
+ vmx_asm_common 0 1
+
+ENTRY(vmx_asm_do_relaunch)
+ vmx_asm_common 1 1
+
+#endif /* CONFIG_VMX */
diff --git a/xen/arch/x86/hvm/vmx/x86_64/exits.S b/xen/arch/x86/hvm/vmx/x86_64/exits.S
new file mode 100644
index 0000000000..bfc581e461
--- /dev/null
+++ b/xen/arch/x86/hvm/vmx/x86_64/exits.S
@@ -0,0 +1,160 @@
+/*
+ * exits.S: VMX architecture-specific exit handling.
+ * Copyright (c) 2004, Intel 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 <xen/config.h>
+#include <xen/errno.h>
+#include <xen/softirq.h>
+#include <asm/asm_defns.h>
+#include <asm/apicdef.h>
+#include <asm/page.h>
+#include <public/xen.h>
+
+#define GET_CURRENT(reg) \
+ movq $STACK_SIZE-8, reg; \
+ orq %rsp, reg; \
+ andq $~7,reg; \
+ movq (reg),reg;
+
+/*
+ * At VMExit time the processor saves the guest selectors, rsp, rip,
+ * and rflags. Therefore we don't save them, but simply decrement
+ * the kernel stack pointer to make it consistent with the stack frame
+ * at usual interruption time. The rflags of the host is not saved by VMX,
+ * and we set it to the fixed value.
+ *
+ * We also need the room, especially because orig_eax field is used
+ * by do_IRQ(). Compared the cpu_user_regs, we skip pushing for the following:
+ * (10) u64 gs;
+ * (9) u64 fs;
+ * (8) u64 ds;
+ * (7) u64 es;
+ * <- get_stack_bottom() (= HOST_ESP)
+ * (6) u64 ss;
+ * (5) u64 rsp;
+ * (4) u64 rflags;
+ * (3) u64 cs;
+ * (2) u64 rip;
+ * (2/1) u32 entry_vector;
+ * (1/1) u32 error_code;
+ */
+#define HVM_MONITOR_RFLAGS 0x202 /* IF on */
+#define NR_SKIPPED_REGS 6 /* See the above explanation */
+#define HVM_SAVE_ALL_NOSEGREGS \
+ pushq $HVM_MONITOR_RFLAGS; \
+ popfq; \
+ subq $(NR_SKIPPED_REGS*8), %rsp; \
+ pushq %rdi; \
+ pushq %rsi; \
+ pushq %rdx; \
+ pushq %rcx; \
+ pushq %rax; \
+ pushq %r8; \
+ pushq %r9; \
+ pushq %r10; \
+ pushq %r11; \
+ pushq %rbx; \
+ pushq %rbp; \
+ pushq %r12; \
+ pushq %r13; \
+ pushq %r14; \
+ pushq %r15; \
+
+#define HVM_RESTORE_ALL_NOSEGREGS \
+ popq %r15; \
+ popq %r14; \
+ popq %r13; \
+ popq %r12; \
+ popq %rbp; \
+ popq %rbx; \
+ popq %r11; \
+ popq %r10; \
+ popq %r9; \
+ popq %r8; \
+ popq %rax; \
+ popq %rcx; \
+ popq %rdx; \
+ popq %rsi; \
+ popq %rdi; \
+ addq $(NR_SKIPPED_REGS*8), %rsp; \
+
+#ifdef CONFIG_VMX
+ENTRY(vmx_asm_vmexit_handler)
+ /* selectors are restored/saved by VMX */
+ HVM_SAVE_ALL_NOSEGREGS
+ call vmx_vmexit_handler
+ jmp vmx_asm_do_resume
+
+.macro vmx_asm_common launch initialized
+1:
+ .if \initialized
+/* vmx_test_all_events */
+ GET_CURRENT(%rbx)
+/* test_all_events: */
+ cli # tests must not race interrupts
+/*test_softirqs:*/
+ movl VCPU_processor(%rbx),%eax
+ shl $IRQSTAT_shift,%rax
+ leaq irq_stat(%rip), %rdx
+ testl $~0,(%rdx,%rax,1)
+ jnz 2f
+
+/* vmx_restore_all_guest */
+ call vmx_intr_assist
+ call vmx_load_cr2
+ .endif
+ /*
+ * Check if we are going back to VMX-based VM
+ * By this time, all the setups in the VMCS must be complete.
+ */
+ HVM_RESTORE_ALL_NOSEGREGS
+ .if \launch
+ /* VMLAUNCH */
+ .byte 0x0f,0x01,0xc2
+ pushfq
+ call vm_launch_fail
+ .else
+ /* VMRESUME */
+ .byte 0x0f,0x01,0xc3
+ pushfq
+ call vm_resume_fail
+ .endif
+ /* Should never reach here */
+ hlt
+
+ ALIGN
+
+ .if \initialized
+2:
+/* vmx_process_softirqs */
+ sti
+ call do_softirq
+ jmp 1b
+ ALIGN
+ .endif
+.endm
+
+ENTRY(vmx_asm_do_launch)
+ vmx_asm_common 1 0
+
+ENTRY(vmx_asm_do_resume)
+ vmx_asm_common 0 1
+
+ENTRY(vmx_asm_do_relaunch)
+ vmx_asm_common 1 1
+
+#endif /* CONFIG_VMX */
+
diff --git a/xen/arch/x86/i387.c b/xen/arch/x86/i387.c
index 9740be454d..4b1a2280bf 100644
--- a/xen/arch/x86/i387.c
+++ b/xen/arch/x86/i387.c
@@ -12,6 +12,7 @@
#include <xen/sched.h>
#include <asm/current.h>
#include <asm/processor.h>
+#include <asm/hvm/support.h>
#include <asm/i387.h>
void init_fpu(void)
@@ -29,7 +30,7 @@ void save_init_fpu(struct vcpu *tsk)
* This causes us to set the real flag, so we'll need
* to temporarily clear it while saving f-p state.
*/
- if ( VMX_DOMAIN(tsk) || (tsk->arch.guest_context.ctrlreg[0] & X86_CR0_TS) )
+ if ( HVM_DOMAIN(tsk) || (tsk->arch.guest_context.ctrlreg[0] & X86_CR0_TS) )
clts();
if ( cpu_has_fxsr )
diff --git a/xen/arch/x86/mpparse.c b/xen/arch/x86/mpparse.c
index 91355de55e..af667dad2d 100644
--- a/xen/arch/x86/mpparse.c
+++ b/xen/arch/x86/mpparse.c
@@ -730,6 +730,11 @@ void __init get_smp_config (void)
*/
}
+int __init mp_get_num_processors(void)
+{
+ return num_processors;
+}
+
static int __init smp_scan_config (unsigned long base, unsigned long length)
{
unsigned int *bp = phys_to_virt(base);
diff --git a/xen/arch/x86/shadow.c b/xen/arch/x86/shadow.c
index 6ae54e208a..42e2c7deed 100644
--- a/xen/arch/x86/shadow.c
+++ b/xen/arch/x86/shadow.c
@@ -226,7 +226,7 @@ alloc_shadow_page(struct domain *d,
if (d->arch.ops->guest_paging_levels == PAGING_L2)
{
#if CONFIG_PAGING_LEVELS >= 3
- /* For 32-bit VMX guest, 2 shadow L1s to simulate 1 guest L1
+ /* For 32-bit HVM guest, 2 shadow L1s to simulate 1 guest L1
* So need allocate 2 continues shadow L1 each time.
*/
page = alloc_domheap_pages(NULL, SL1_ORDER, 0);
@@ -602,7 +602,7 @@ static void shadow_map_l1_into_current_l2(unsigned long va)
#if CONFIG_PAGING_LEVELS >=3
if (d->arch.ops->guest_paging_levels == PAGING_L2)
{
- /* for 32-bit VMX guest on 64-bit or PAE host,
+ /* for 32-bit HVM guest on 64-bit or PAE host,
* need update two L2 entries each time
*/
if ( !get_shadow_ref(sl1mfn))
@@ -2838,7 +2838,7 @@ static unsigned long gva_to_gpa_pae(unsigned long gva)
/* 64-bit shadow-mode code testing */
/****************************************************************************/
/*
- * init_bl2() is for 32-bit VMX guest on 64-bit host
+ * init_bl2() is for 32-bit HVM guest on 64-bit host
* Using 1 shadow L4(l3) and 4 shadow L2s to simulate guest L2
*/
static inline unsigned long init_bl2(l4_pgentry_t *spl4e, unsigned long smfn)
@@ -2938,7 +2938,7 @@ static unsigned long shadow_l4_table(
#if CONFIG_PAGING_LEVELS >= 3
/*
* validate_bl2e_change()
- * The code is for 32-bit VMX gues on 64-bit host.
+ * The code is for 32-bit HVM guest on 64-bit host.
* To sync guest L2.
*/
@@ -3078,7 +3078,7 @@ static void shadow_set_l2e_64(unsigned long va, l2_pgentry_t sl2e,
shadow_map_into_current(v, va, PAGING_L3, PAGING_L4);
__shadow_get_l4e(v, va, &sl4e);
} else {
- printk("For non VMX shadow, create_l1_shadow:%d\n", create_l2_shadow);
+ printk("For non HVM shadow, create_l1_shadow:%d\n", create_l2_shadow);
}
}
@@ -3089,7 +3089,7 @@ static void shadow_set_l2e_64(unsigned long va, l2_pgentry_t sl2e,
shadow_map_into_current(v, va, PAGING_L2, PAGING_L3);
__shadow_get_l3e(v, va, &sl3e);
} else {
- printk("For non VMX shadow, create_l1_shadow:%d\n", create_l2_shadow);
+ printk("For non HVM shadow, create_l1_shadow:%d\n", create_l2_shadow);
}
shadow_update_min_max(l4e_get_pfn(sl4e), l3_table_offset(va));
diff --git a/xen/arch/x86/x86_32/asm-offsets.c b/xen/arch/x86/x86_32/asm-offsets.c
index ac00d9ca0e..cda414b5a5 100644
--- a/xen/arch/x86/x86_32/asm-offsets.c
+++ b/xen/arch/x86/x86_32/asm-offsets.c
@@ -65,12 +65,25 @@ void __dummy__(void)
arch.guest_context.kernel_ss);
OFFSET(VCPU_kernel_sp, struct vcpu,
arch.guest_context.kernel_sp);
+ OFFSET(VCPU_arch_guest_fpu_ctxt, struct vcpu, arch.guest_context.fpu_ctxt);
OFFSET(VCPU_flags, struct vcpu, vcpu_flags);
OFFSET(VCPU_nmi_addr, struct vcpu, nmi_addr);
DEFINE(_VCPUF_nmi_pending, _VCPUF_nmi_pending);
DEFINE(_VCPUF_nmi_masked, _VCPUF_nmi_masked);
BLANK();
+#ifdef CONFIG_SVM
+ OFFSET(VCPU_svm_vmcb_pa, struct vcpu, arch.hvm_svm.vmcb_pa);
+ OFFSET(VCPU_svm_hsa_pa, struct vcpu, arch.hvm_svm.host_save_pa);
+ OFFSET(VCPU_svm_vmcb, struct vcpu, arch.hvm_svm.vmcb);
+ OFFSET(VCPU_svm_vmexit_tsc, struct vcpu, arch.hvm_svm.vmexit_tsc);
+ BLANK();
+
+ OFFSET(VMCB_rax, struct vmcb_struct, rax);
+ OFFSET(VMCB_tsc_offset, struct vmcb_struct, tsc_offset);
+ BLANK();
+#endif
+
OFFSET(VCPUINFO_upcall_pending, vcpu_info_t, evtchn_upcall_pending);
OFFSET(VCPUINFO_upcall_mask, vcpu_info_t, evtchn_upcall_mask);
BLANK();
diff --git a/xen/arch/x86/x86_32/entry.S b/xen/arch/x86/x86_32/entry.S
index 4f491a60e1..db194c6c41 100644
--- a/xen/arch/x86/x86_32/entry.S
+++ b/xen/arch/x86/x86_32/entry.S
@@ -72,124 +72,6 @@
andl $~3,reg; \
movl (reg),reg;
-#ifdef CONFIG_VMX
-/*
- * At VMExit time the processor saves the guest selectors, esp, eip,
- * and eflags. Therefore we don't save them, but simply decrement
- * the kernel stack pointer to make it consistent with the stack frame
- * at usual interruption time. The eflags of the host is not saved by VMX,
- * and we set it to the fixed value.
- *
- * We also need the room, especially because orig_eax field is used
- * by do_IRQ(). Compared the cpu_user_regs, we skip pushing for the following:
- * (10) u32 gs;
- * (9) u32 fs;
- * (8) u32 ds;
- * (7) u32 es;
- * <- get_stack_bottom() (= HOST_ESP)
- * (6) u32 ss;
- * (5) u32 esp;
- * (4) u32 eflags;
- * (3) u32 cs;
- * (2) u32 eip;
- * (2/1) u16 entry_vector;
- * (1/1) u16 error_code;
- * However, get_stack_bottom() actually returns 20 bytes before the real
- * bottom of the stack to allow space for:
- * domain pointer, DS, ES, FS, GS. Therefore, we effectively skip 6 registers.
- */
-#define VMX_MONITOR_EFLAGS 0x202 /* IF on */
-#define NR_SKIPPED_REGS 6 /* See the above explanation */
-#define VMX_SAVE_ALL_NOSEGREGS \
- pushl $VMX_MONITOR_EFLAGS; \
- popf; \
- subl $(NR_SKIPPED_REGS*4), %esp; \
- movl $0, 0xc(%esp); /* eflags==0 identifies cpu_user_regs as VMX guest */ \
- pushl %eax; \
- pushl %ebp; \
- pushl %edi; \
- pushl %esi; \
- pushl %edx; \
- pushl %ecx; \
- pushl %ebx;
-
-#define VMX_RESTORE_ALL_NOSEGREGS \
- popl %ebx; \
- popl %ecx; \
- popl %edx; \
- popl %esi; \
- popl %edi; \
- popl %ebp; \
- popl %eax; \
- addl $(NR_SKIPPED_REGS*4), %esp
-
-ENTRY(vmx_asm_vmexit_handler)
- /* selectors are restored/saved by VMX */
- VMX_SAVE_ALL_NOSEGREGS
- call trace_vmexit
- call vmx_vmexit_handler
- jmp vmx_asm_do_resume
-
-.macro vmx_asm_common launch initialized
-1:
-/* vmx_test_all_events */
- .if \initialized
- GET_CURRENT(%ebx)
-/*test_all_events:*/
- xorl %ecx,%ecx
- notl %ecx
- cli # tests must not race interrupts
-/*test_softirqs:*/
- movl VCPU_processor(%ebx),%eax
- shl $IRQSTAT_shift,%eax
- test %ecx,irq_stat(%eax,1)
- jnz 2f
-
-/* vmx_restore_all_guest */
- call vmx_intr_assist
- call load_cr2
- call trace_vmentry
- .endif
- VMX_RESTORE_ALL_NOSEGREGS
- /*
- * Check if we are going back to VMX-based VM
- * By this time, all the setups in the VMCS must be complete.
- */
- .if \launch
- /* VMLAUNCH */
- .byte 0x0f,0x01,0xc2
- pushf
- call vm_launch_fail
- .else
- /* VMRESUME */
- .byte 0x0f,0x01,0xc3
- pushf
- call vm_resume_fail
- .endif
- /* Should never reach here */
- hlt
-
- ALIGN
- .if \initialized
-2:
-/* vmx_process_softirqs */
- sti
- call do_softirq
- jmp 1b
- ALIGN
- .endif
-.endm
-
-ENTRY(vmx_asm_do_launch)
- vmx_asm_common 1 0
-
-ENTRY(vmx_asm_do_resume)
- vmx_asm_common 0 1
-
-ENTRY(vmx_asm_do_relaunch)
- vmx_asm_common 1 1
-
-#endif
ALIGN
restore_all_guest:
diff --git a/xen/arch/x86/x86_32/traps.c b/xen/arch/x86/x86_32/traps.c
index 636a3d4627..e3f4527d25 100644
--- a/xen/arch/x86/x86_32/traps.c
+++ b/xen/arch/x86/x86_32/traps.c
@@ -10,74 +10,65 @@
#include <xen/symbols.h>
#include <asm/current.h>
#include <asm/flushtlb.h>
-#include <asm/vmx.h>
+#include <asm/hvm/hvm.h>
+#include <asm/hvm/support.h>
/* All CPUs have their own IDT to allow int80 direct trap. */
idt_entry_t *idt_tables[NR_CPUS] = { 0 };
void show_registers(struct cpu_user_regs *regs)
{
- unsigned long ss, ds, es, fs, gs, cs;
- unsigned long eip, esp, eflags, cr0, cr3;
+ struct cpu_user_regs faultregs;
+ unsigned long faultcrs[8];
const char *context;
- if ( VMX_DOMAIN(current) && (regs->eflags == 0) )
+ if ( HVM_DOMAIN(current) && regs->eflags == 0 )
{
- __vmread(GUEST_RIP, &eip);
- __vmread(GUEST_RSP, &esp);
- __vmread(GUEST_RFLAGS, &eflags);
- __vmread(GUEST_SS_SELECTOR, &ss);
- __vmread(GUEST_DS_SELECTOR, &ds);
- __vmread(GUEST_ES_SELECTOR, &es);
- __vmread(GUEST_FS_SELECTOR, &fs);
- __vmread(GUEST_GS_SELECTOR, &gs);
- __vmread(GUEST_CS_SELECTOR, &cs);
- __vmread(CR0_READ_SHADOW, &cr0);
- __vmread(GUEST_CR3, &cr3);
- context = "vmx guest";
+ context = "hvm";
+ hvm_load_cpu_guest_regs(current, &faultregs);
+ hvm_store_cpu_guest_ctrl_regs(current, faultcrs);
}
else
{
- eip = regs->eip;
- eflags = regs->eflags;
- cr0 = read_cr0();
- cr3 = read_cr3();
-
- __asm__ ( "movl %%fs,%0 ; movl %%gs,%1" : "=r" (fs), "=r" (gs) );
-
+ faultregs = *regs;
if ( GUEST_MODE(regs) )
{
- esp = regs->esp;
- ss = regs->ss & 0xffff;
- ds = regs->ds & 0xffff;
- es = regs->es & 0xffff;
- cs = regs->cs & 0xffff;
context = "guest";
- }
- else
- {
- esp = (unsigned long)&regs->esp;
- ss = __HYPERVISOR_DS;
- ds = __HYPERVISOR_DS;
- es = __HYPERVISOR_DS;
- cs = __HYPERVISOR_CS;
+ faultregs.ss &= 0xFFFF;
+ faultregs.ds &= 0xFFFF;
+ faultregs.es &= 0xFFFF;
+ faultregs.cs &= 0xFFFF;
+ }
+ else
+ {
context = "hypervisor";
- }
+ faultregs.esp = (unsigned long)&regs->esp;
+ faultregs.ss = __HYPERVISOR_DS;
+ faultregs.ds = __HYPERVISOR_DS;
+ faultregs.es = __HYPERVISOR_DS;
+ faultregs.cs = __HYPERVISOR_CS;
+ }
+ __asm__ ("movw %%fs,%0 ; movw %%gs,%1"
+ : "=r" (faultregs.fs), "=r" (faultregs.gs) );
+
+ faultcrs[0] = read_cr0();
+ faultcrs[3] = read_cr3();
}
- printk("CPU: %d\nEIP: %04lx:[<%08lx>]",
- smp_processor_id(), (unsigned long)0xffff & regs->cs, eip);
- if ( !GUEST_MODE(regs) )
- print_symbol(" %s", eip);
- printk("\nEFLAGS: %08lx CONTEXT: %s\n", eflags, context);
+ printk("CPU: %d\nEIP: %04x:[<%08x>]",
+ smp_processor_id(), faultregs.cs, faultregs.eip);
+ if ( !HVM_DOMAIN(current) && !GUEST_MODE(regs) )
+ print_symbol(" %s", faultregs.eip);
+ printk("\nEFLAGS: %08x CONTEXT: %s\n", faultregs.eflags, context);
printk("eax: %08x ebx: %08x ecx: %08x edx: %08x\n",
regs->eax, regs->ebx, regs->ecx, regs->edx);
- printk("esi: %08x edi: %08x ebp: %08x esp: %08lx\n",
- regs->esi, regs->edi, regs->ebp, esp);
- printk("cr0: %08lx cr3: %08lx\n", cr0, cr3);
- printk("ds: %04lx es: %04lx fs: %04lx gs: %04lx "
- "ss: %04lx cs: %04lx\n",
- ds, es, fs, gs, ss, cs);
+ printk("esi: %08x edi: %08x ebp: %08x esp: %08x\n",
+ regs->esi, regs->edi, regs->ebp, faultregs.esp);
+ printk("cr0: %08lx cr3: %08lx\n", faultcrs[0], faultcrs[3]);
+ printk("ds: %04x es: %04x fs: %04x gs: %04x "
+ "ss: %04x cs: %04x\n",
+ faultregs.ds, faultregs.es, faultregs.fs,
+ faultregs.gs, faultregs.ss, faultregs.cs);
show_stack(regs);
}
diff --git a/xen/arch/x86/x86_64/asm-offsets.c b/xen/arch/x86/x86_64/asm-offsets.c
index 27b8ed70c1..499ca07057 100644
--- a/xen/arch/x86/x86_64/asm-offsets.c
+++ b/xen/arch/x86/x86_64/asm-offsets.c
@@ -65,12 +65,25 @@ void __dummy__(void)
arch.guest_context.syscall_callback_eip);
OFFSET(VCPU_kernel_sp, struct vcpu,
arch.guest_context.kernel_sp);
+ OFFSET(VCPU_arch_guest_fpu_ctxt, struct vcpu, arch.guest_context.fpu_ctxt);
OFFSET(VCPU_flags, struct vcpu, vcpu_flags);
OFFSET(VCPU_nmi_addr, struct vcpu, nmi_addr);
DEFINE(_VCPUF_nmi_pending, _VCPUF_nmi_pending);
DEFINE(_VCPUF_nmi_masked, _VCPUF_nmi_masked);
BLANK();
+#ifdef CONFIG_SVM
+ OFFSET(VCPU_svm_vmcb_pa, struct vcpu, arch.hvm_svm.vmcb_pa);
+ OFFSET(VCPU_svm_hsa_pa, struct vcpu, arch.hvm_svm.host_save_pa);
+ OFFSET(VCPU_svm_vmcb, struct vcpu, arch.hvm_svm.vmcb);
+ OFFSET(VCPU_svm_vmexit_tsc, struct vcpu, arch.hvm_svm.vmexit_tsc);
+ BLANK();
+
+ OFFSET(VMCB_rax, struct vmcb_struct, rax);
+ OFFSET(VMCB_tsc_offset, struct vmcb_struct, tsc_offset);
+ BLANK();
+#endif
+
OFFSET(VCPUINFO_upcall_pending, vcpu_info_t, evtchn_upcall_pending);
OFFSET(VCPUINFO_upcall_mask, vcpu_info_t, evtchn_upcall_mask);
BLANK();
diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S
index 5c39f574be..e878fe4b6a 100644
--- a/xen/arch/x86/x86_64/entry.S
+++ b/xen/arch/x86/x86_64/entry.S
@@ -188,135 +188,6 @@ test_guest_events:
call create_bounce_frame
jmp test_all_events
-#ifdef CONFIG_VMX
-/*
- * At VMExit time the processor saves the guest selectors, rsp, rip,
- * and rflags. Therefore we don't save them, but simply decrement
- * the kernel stack pointer to make it consistent with the stack frame
- * at usual interruption time. The rflags of the host is not saved by VMX,
- * and we set it to the fixed value.
- *
- * We also need the room, especially because orig_eax field is used
- * by do_IRQ(). Compared the cpu_user_regs, we skip pushing for the following:
- * (10) u64 gs;
- * (9) u64 fs;
- * (8) u64 ds;
- * (7) u64 es;
- * <- get_stack_bottom() (= HOST_ESP)
- * (6) u64 ss;
- * (5) u64 rsp;
- * (4) u64 rflags;
- * (3) u64 cs;
- * (2) u64 rip;
- * (2/1) u32 entry_vector;
- * (1/1) u32 error_code;
- */
-#define VMX_MONITOR_RFLAGS 0x202 /* IF on */
-#define NR_SKIPPED_REGS 6 /* See the above explanation */
-#define VMX_SAVE_ALL_NOSEGREGS \
- pushq $VMX_MONITOR_RFLAGS; \
- popfq; \
- subq $(NR_SKIPPED_REGS*8), %rsp; \
- pushq %rdi; \
- pushq %rsi; \
- pushq %rdx; \
- pushq %rcx; \
- pushq %rax; \
- pushq %r8; \
- pushq %r9; \
- pushq %r10; \
- pushq %r11; \
- pushq %rbx; \
- pushq %rbp; \
- pushq %r12; \
- pushq %r13; \
- pushq %r14; \
- pushq %r15; \
-
-#define VMX_RESTORE_ALL_NOSEGREGS \
- popq %r15; \
- popq %r14; \
- popq %r13; \
- popq %r12; \
- popq %rbp; \
- popq %rbx; \
- popq %r11; \
- popq %r10; \
- popq %r9; \
- popq %r8; \
- popq %rax; \
- popq %rcx; \
- popq %rdx; \
- popq %rsi; \
- popq %rdi; \
- addq $(NR_SKIPPED_REGS*8), %rsp; \
-
-ENTRY(vmx_asm_vmexit_handler)
- /* selectors are restored/saved by VMX */
- VMX_SAVE_ALL_NOSEGREGS
- call vmx_vmexit_handler
- jmp vmx_asm_do_resume
-
-.macro vmx_asm_common launch initialized
-1:
- .if \initialized
-/* vmx_test_all_events */
- GET_CURRENT(%rbx)
-/* test_all_events: */
- cli # tests must not race interrupts
-/*test_softirqs:*/
- movl VCPU_processor(%rbx),%eax
- shl $IRQSTAT_shift,%rax
- leaq irq_stat(%rip), %rdx
- testl $~0,(%rdx,%rax,1)
- jnz 2f
-
-/* vmx_restore_all_guest */
- call vmx_intr_assist
- call load_cr2
- .endif
- /*
- * Check if we are going back to VMX-based VM
- * By this time, all the setups in the VMCS must be complete.
- */
- VMX_RESTORE_ALL_NOSEGREGS
- .if \launch
- /* VMLUANCH */
- .byte 0x0f,0x01,0xc2
- pushfq
- call vm_launch_fail
- .else
- /* VMRESUME */
- .byte 0x0f,0x01,0xc3
- pushfq
- call vm_resume_fail
- .endif
- /* Should never reach here */
- hlt
-
- ALIGN
-
- .if \initialized
-2:
-/* vmx_process_softirqs */
- sti
- call do_softirq
- jmp 1b
- ALIGN
- .endif
-.endm
-
-ENTRY(vmx_asm_do_launch)
- vmx_asm_common 1 0
-
-ENTRY(vmx_asm_do_resume)
- vmx_asm_common 0 1
-
-ENTRY(vmx_asm_do_relaunch)
- vmx_asm_common 1 1
-
-#endif
-
ALIGN
/* %rbx: struct vcpu */
process_softirqs:
diff --git a/xen/arch/x86/x86_64/mm.c b/xen/arch/x86/x86_64/mm.c
index 008da7d2ff..c101a0738e 100644
--- a/xen/arch/x86/x86_64/mm.c
+++ b/xen/arch/x86/x86_64/mm.c
@@ -188,7 +188,7 @@ long subarch_memory_op(int op, void *arg)
l3_pgentry_t l3e;
l2_pgentry_t l2e;
unsigned long mfn, v;
- unsigned int i;
+ unsigned int i = 0;
long rc = 0;
switch ( op )
diff --git a/xen/arch/x86/x86_64/traps.c b/xen/arch/x86/x86_64/traps.c
index 2f4b71b9ac..297cba2242 100644
--- a/xen/arch/x86/x86_64/traps.c
+++ b/xen/arch/x86/x86_64/traps.c
@@ -13,51 +13,57 @@
#include <asm/flushtlb.h>
#include <asm/msr.h>
#include <asm/shadow.h>
-#include <asm/vmx.h>
+#include <asm/hvm/hvm.h>
+#include <asm/hvm/support.h>
void show_registers(struct cpu_user_regs *regs)
{
- unsigned long rip, rsp, rflags, cs, cr0, cr3;
+ struct cpu_user_regs faultregs;
+ unsigned long faultcrs[8];
const char *context;
- if ( VMX_DOMAIN(current) && (regs->eflags == 0) )
+ if ( HVM_DOMAIN(current) && regs->eflags == 0 )
{
- __vmread(GUEST_RIP, &rip);
- __vmread(GUEST_RSP, &rsp);
- __vmread(GUEST_RFLAGS, &rflags);
- __vmread(GUEST_CS_SELECTOR, &cs);
- __vmread(CR0_READ_SHADOW, &cr0);
- __vmread(GUEST_CR3, &cr3);
- context = "vmx guest";
+ context = "hvm";
+ hvm_load_cpu_guest_regs(current, &faultregs);
+ hvm_store_cpu_guest_ctrl_regs(current, faultcrs);
}
else
{
- rip = regs->rip;
- rflags = regs->rflags;
- cr0 = read_cr0();
- cr3 = read_cr3();
- rsp = regs->rsp;
- cs = regs->cs & 0xffff;
- context = GUEST_MODE(regs) ? "guest" : "hypervisor";
+ faultregs = *regs;
+
+ if ( GUEST_MODE(regs) )
+ {
+ context = "guest";
+ }
+ else
+ {
+ context = "hypervisor";
+ faultregs.esp = (unsigned long)&regs->esp;
+ }
+
+ faultcrs[0] = read_cr0();
+ faultcrs[3] = read_cr3();
}
- printk("CPU: %d\nRIP: %04lx:[<%016lx>]",
- smp_processor_id(), cs, rip);
- if ( !GUEST_MODE(regs) )
- print_symbol(" %s", rip);
- printk("\nRFLAGS: %016lx CONTEXT: %s\n", rflags, context);
+ printk("CPU: %d\nRIP: %04x:[<%016lx>]",
+ smp_processor_id(), faultregs.cs, faultregs.rip);
+ if ( !HVM_DOMAIN(current) && !GUEST_MODE(regs) )
+ print_symbol(" %s", faultregs.rip);
+
+ printk("\nRFLAGS: %016lx CONTEXT: %s\n", faultregs.rflags, context);
printk("rax: %016lx rbx: %016lx rcx: %016lx\n",
regs->rax, regs->rbx, regs->rcx);
printk("rdx: %016lx rsi: %016lx rdi: %016lx\n",
regs->rdx, regs->rsi, regs->rdi);
printk("rbp: %016lx rsp: %016lx r8: %016lx\n",
- regs->rbp, rsp, regs->r8);
+ regs->rbp, faultregs.rsp, regs->r8);
printk("r9: %016lx r10: %016lx r11: %016lx\n",
regs->r9, regs->r10, regs->r11);
printk("r12: %016lx r13: %016lx r14: %016lx\n",
regs->r12, regs->r13, regs->r14);
printk("r15: %016lx cr0: %016lx cr3: %016lx\n",
- regs->r15, cr0, cr3);
+ regs->r15, faultcrs[0], faultcrs[3]);
show_stack(regs);
}
diff --git a/xen/include/asm-ia64/domain.h b/xen/include/asm-ia64/domain.h
index 3aac190963..4d4c17c8e7 100644
--- a/xen/include/asm-ia64/domain.h
+++ b/xen/include/asm-ia64/domain.h
@@ -26,7 +26,8 @@ struct arch_domain {
/* System pages out of guest memory, like for xenstore/console */
unsigned long sys_pgnr;
unsigned long max_pfn; /* Max pfn including I/O holes */
- struct virutal_platform_def vmx_platform;
+ struct virtual_platform_def vmx_platform;
+#define hvm_domain vmx_platform /* platform defs are not vmx specific */
u64 xen_vastart;
u64 xen_vaend;
diff --git a/xen/include/asm-ia64/mm.h b/xen/include/asm-ia64/mm.h
index d24ad0702a..07e1ccd6ed 100644
--- a/xen/include/asm-ia64/mm.h
+++ b/xen/include/asm-ia64/mm.h
@@ -414,6 +414,10 @@ extern unsigned long lookup_domain_mpa(struct domain *d, unsigned long mpaddr);
#define INVALID_M2P_ENTRY (~0U)
#define VALID_M2P(_e) (!((_e) & (1U<<63)))
#define IS_INVALID_M2P_ENTRY(_e) (!VALID_M2P(_e))
+
+#define set_pfn_from_mfn(mfn, pfn) (machine_to_phys_mapping[(mfn)] = (pfn))
+#define get_pfn_from_mfn(mfn) (machine_to_phys_mapping[(mfn)])
+
/* If pmt table is provided by control pannel later, we need __get_user
* here. However if it's allocated by HV, we should access it directly
*/
diff --git a/xen/include/asm-ia64/vmx_platform.h b/xen/include/asm-ia64/vmx_platform.h
index f72dfb9068..09b3db5a83 100644
--- a/xen/include/asm-ia64/vmx_platform.h
+++ b/xen/include/asm-ia64/vmx_platform.h
@@ -21,16 +21,16 @@
#include <public/xen.h>
#include <public/arch-ia64.h>
-#include <asm/vmx_vioapic.h>
+#include <asm/hvm/vioapic.h>
struct mmio_list;
-typedef struct virutal_platform_def {
+typedef struct virtual_platform_def {
unsigned long shared_page_va;
unsigned long pib_base;
unsigned char xtp;
struct mmio_list *mmio;
/* One IOSAPIC now... */
- struct vmx_vioapic vmx_vioapic;
+ struct hvm_vioapic vioapic;
} vir_plat_t;
static inline int __fls(uint32_t word)
@@ -63,7 +63,7 @@ static inline int vlapic_set_irq(struct vlapic *t, uint8_t vec, uint8_t trig)
/* As long as we register vlsapic to ioapic controller, it's said enabled */
#define vlapic_enabled(l) 1
-#define vmx_apic_support(d) 1
+#define hvm_apic_support(d) 1
#define VLAPIC_DELIV_MODE_FIXED 0x0
#define VLAPIC_DELIV_MODE_REDIR 0x1
diff --git a/xen/include/asm-ia64/vmx_vcpu.h b/xen/include/asm-ia64/vmx_vcpu.h
index 2367d00590..c3fae7efad 100644
--- a/xen/include/asm-ia64/vmx_vcpu.h
+++ b/xen/include/asm-ia64/vmx_vcpu.h
@@ -113,7 +113,7 @@ extern void guest_write_eoi(VCPU *vcpu);
extern uint64_t guest_read_vivr(VCPU *vcpu);
extern void vmx_inject_vhpi(VCPU *vcpu, u8 vec);
extern int vmx_vcpu_pend_interrupt(VCPU *vcpu, uint8_t vector);
-extern struct virutal_platform_def *vmx_vcpu_get_plat(VCPU *vcpu);
+extern struct virtual_platform_def *vmx_vcpu_get_plat(VCPU *vcpu);
extern void memread_p(VCPU *vcpu, u64 *src, u64 *dest, size_t s);
extern void memread_v(VCPU *vcpu, thash_data_t *vtlb, u64 *src, u64 *dest, size_t s);
extern void memwrite_v(VCPU *vcpu, thash_data_t *vtlb, u64 *src, u64 *dest, size_t s);
diff --git a/xen/include/asm-x86/config.h b/xen/include/asm-x86/config.h
index e463b8c29c..bc65b72507 100644
--- a/xen/include/asm-x86/config.h
+++ b/xen/include/asm-x86/config.h
@@ -19,6 +19,7 @@
#define CONFIG_X86_HT 1
#define CONFIG_SHADOW 1
#define CONFIG_VMX 1
+#define CONFIG_SVM 1
#define CONFIG_SMP 1
#define CONFIG_X86_LOCAL_APIC 1
#define CONFIG_X86_GOOD_APIC 1
diff --git a/xen/include/asm-x86/cpufeature.h b/xen/include/asm-x86/cpufeature.h
index 67b6a854f5..938b765808 100644
--- a/xen/include/asm-x86/cpufeature.h
+++ b/xen/include/asm-x86/cpufeature.h
@@ -90,6 +90,7 @@
/* More extended AMD flags: CPUID level 0x80000001, ecx, word 6 */
#define X86_FEATURE_LAHF_LM (5*32+ 0) /* LAHF/SAHF in long mode */
#define X86_FEATURE_CMP_LEGACY (5*32+ 1) /* If yes HyperThreading not valid */
+#define X86_FEATURE_SVME (5*32+ 2) /* Secure Virtual Machine */
#define cpu_has(c, bit) test_bit(bit, (c)->x86_capability)
#define boot_cpu_has(bit) test_bit(bit, boot_cpu_data.x86_capability)
diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h
index e4d3f6c03a..b6bd54aee4 100644
--- a/xen/include/asm-x86/domain.h
+++ b/xen/include/asm-x86/domain.h
@@ -1,10 +1,10 @@
-
#ifndef __ASM_DOMAIN_H__
#define __ASM_DOMAIN_H__
#include <xen/config.h>
#include <xen/mm.h>
-#include <asm/vmx_vmcs.h>
+#include <asm/hvm/vcpu.h>
+#include <asm/hvm/domain.h>
struct trap_bounce {
unsigned long error_code;
@@ -108,7 +108,7 @@ struct arch_domain
struct list_head free_shadow_frames;
pagetable_t phys_table; /* guest 1:1 pagetable */
- struct vmx_platform vmx_platform;
+ struct hvm_domain hvm_domain;
/* Shadow-translated guest: Pseudophys base address of reserved area. */
unsigned long first_reserved_pfn;
@@ -137,7 +137,7 @@ struct arch_vcpu
#endif
/* Virtual Machine Extensions */
- struct arch_vmx_struct arch_vmx;
+ struct hvm_vcpu hvm_vcpu;
/*
* Every domain has a L1 pagetable of its own. Per-domain mappings
@@ -166,6 +166,10 @@ struct arch_vcpu
unsigned long shadow_ldt_mapcnt;
} __cacheline_aligned;
+/* shorthands to improve code legibility */
+#define hvm_vmx hvm_vcpu.u.vmx
+#define hvm_svm hvm_vcpu.u.svm
+
#endif /* __ASM_DOMAIN_H__ */
/*
diff --git a/xen/include/asm-x86/hvm/domain.h b/xen/include/asm-x86/hvm/domain.h
new file mode 100644
index 0000000000..5edca8a078
--- /dev/null
+++ b/xen/include/asm-x86/hvm/domain.h
@@ -0,0 +1,52 @@
+/*
+ * domain.h: HVM per domain definitions
+ *
+ * Copyright (c) 2004, Intel Corporation.
+ * 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 __ASM_X86_HVM_DOMAIN_H__
+#define __ASM_X86_HVM_DOMAIN_H__
+
+#include <asm/e820.h>
+#include <asm/hvm/vpic.h>
+#include <asm/hvm/vpit.h>
+#include <asm/hvm/vlapic.h>
+#include <asm/hvm/vioapic.h>
+
+#define HVM_PBUF_SIZE 80
+
+struct hvm_domain {
+ unsigned long shared_page_va;
+ unsigned int nr_vcpus;
+ unsigned int apic_enabled;
+
+ struct hvm_virpit vpit;
+ struct hvm_virpic vpic;
+ struct hvm_vioapic vioapic;
+ struct hvm_io_handler io_handler;
+
+ unsigned char round_info[256];
+ spinlock_t round_robin_lock;
+ int interrupt_request;
+
+ int pbuf_index;
+ char pbuf[HVM_PBUF_SIZE];
+};
+
+#endif /* __ASM_X86_HVM_DOMAIN_H__ */
+
diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h
new file mode 100644
index 0000000000..9288e465d3
--- /dev/null
+++ b/xen/include/asm-x86/hvm/hvm.h
@@ -0,0 +1,166 @@
+/*
+ * hvm.h: Hardware virtual machine assist interface definitions.
+ *
+ * Leendert van Doorn, leendert@watson.ibm.com
+ * Copyright (c) 2005, International Business Machines Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ */
+#ifndef __ASM_X86_HVM_HVM_H__
+#define __ASM_X86_HVM_HVM_H__
+
+/*
+ * The hardware virtual machine (HVM) interface abstracts away from the
+ * x86/x86_64 CPU virtualization assist specifics. Currently this interface
+ * supports Intel's VT-x and AMD's SVM extensions.
+ */
+
+struct hvm_function_table {
+ /*
+ * Disable HVM functionality
+ */
+ void (*disable)(void);
+
+ /*
+ * Initialize/relinguish HVM guest resources
+ */
+ int (*initialize_guest_resources)(struct vcpu *v);
+ int (*relinquish_guest_resources)(struct vcpu *v);
+
+ /*
+ * Store and load guest state:
+ * 1) load/store guest register state,
+ * 2) load/store segment state (x86_64 only),
+ * 3) load/store msr register state (x86_64 only),
+ * 4) store guest control register state (used for panic dumps),
+ * 5) modify guest state (e.g., set debug flags).
+ */
+ void (*store_cpu_guest_regs)(struct vcpu *v, struct cpu_user_regs *r);
+ void (*load_cpu_guest_regs)(struct vcpu *v, struct cpu_user_regs *r);
+#ifdef __x86_64__
+ void (*save_segments)(struct vcpu *v);
+ void (*load_msrs)(struct vcpu *v);
+ void (*restore_msrs)(struct vcpu *v);
+#endif
+ void (*store_cpu_guest_ctrl_regs)(struct vcpu *v, unsigned long crs[8]);
+ void (*modify_guest_state)(struct vcpu *v);
+
+ /*
+ * Examine specifics of the guest state:
+ * 1) determine whether the guest is in real or vm8086 mode,
+ * 2) determine whether paging is enabled,
+ * 3) return the length of the instruction that caused an exit.
+ */
+ int (*realmode)(struct vcpu *v);
+ int (*paging_enabled)(struct vcpu *v);
+ int (*instruction_length)(struct vcpu *v);
+};
+
+extern struct hvm_function_table hvm_funcs;
+
+/*
+ * For convenience, we use short hands.
+ */
+static inline void
+hvm_disable(void)
+{
+ if (hvm_funcs.disable)
+ hvm_funcs.disable();
+}
+
+static inline int
+hvm_initialize_guest_resources(struct vcpu *v)
+{
+ if (hvm_funcs.initialize_guest_resources)
+ return hvm_funcs.initialize_guest_resources(v);
+ return 0;
+}
+
+static inline int
+hvm_relinquish_guest_resources(struct vcpu *v)
+{
+ if (hvm_funcs.relinquish_guest_resources)
+ return hvm_funcs.relinquish_guest_resources(v);
+ return 0;
+}
+
+static inline void
+hvm_store_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *r)
+{
+ hvm_funcs.store_cpu_guest_regs(v, r);
+}
+
+static inline void
+hvm_load_cpu_guest_regs(struct vcpu *v, struct cpu_user_regs *r)
+{
+ hvm_funcs.load_cpu_guest_regs(v, r);
+}
+
+#ifdef __x86_64__
+static inline void
+hvm_save_segments(struct vcpu *v)
+{
+ if (hvm_funcs.save_segments)
+ hvm_funcs.save_segments(v);
+}
+
+static inline void
+hvm_load_msrs(struct vcpu *v)
+{
+ if (hvm_funcs.load_msrs)
+ hvm_funcs.load_msrs(v);
+}
+
+static inline void
+hvm_restore_msrs(struct vcpu *v)
+{
+ if (hvm_funcs.restore_msrs)
+ hvm_funcs.restore_msrs(v);
+}
+#else
+#define hvm_save_segments(v) ((void)0)
+#define hvm_load_msrs(v) ((void)0)
+#define hvm_restore_msrs(v) ((void)0)
+#endif /* __x86_64__ */
+
+static inline void
+hvm_store_cpu_guest_ctrl_regs(struct vcpu *v, unsigned long crs[8])
+{
+ hvm_funcs.store_cpu_guest_ctrl_regs(v, crs);
+}
+
+static inline void
+hvm_modify_guest_state(struct vcpu *v)
+{
+ hvm_funcs.modify_guest_state(v);
+}
+
+static inline int
+hvm_realmode(struct vcpu *v)
+{
+ return hvm_funcs.realmode(v);
+}
+
+static inline int
+hvm_paging_enabled(struct vcpu *v)
+{
+ return hvm_funcs.paging_enabled(v);
+}
+
+static inline int
+hvm_instruction_length(struct vcpu *v)
+{
+ return hvm_funcs.instruction_length(v);
+}
+#endif /* __ASM_X86_HVM_HVM_H__ */
diff --git a/xen/include/asm-x86/hvm/io.h b/xen/include/asm-x86/hvm/io.h
new file mode 100644
index 0000000000..2639ccce2f
--- /dev/null
+++ b/xen/include/asm-x86/hvm/io.h
@@ -0,0 +1,160 @@
+/*
+ * io.h: HVM IO support
+ *
+ * Copyright (c) 2004, Intel 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 __ASM_X86_HVM_IO_H__
+#define __ASM_X86_HVM_IO_H__
+
+#include <asm/hvm/vpic.h>
+#include <asm/hvm/vioapic.h>
+#include <public/hvm/ioreq.h>
+
+#define MAX_OPERAND_NUM 2
+
+#define mk_operand(size_reg, index, seg, flag) \
+ (((size_reg) << 24) | ((index) << 16) | ((seg) << 8) | (flag))
+
+#define operand_size(operand) \
+ ((operand >> 24) & 0xFF)
+
+#define operand_index(operand) \
+ ((operand >> 16) & 0xFF)
+
+/* for instruction.operand[].size */
+#define BYTE 1
+#define WORD 2
+#define LONG 4
+#define QUAD 8
+#define BYTE_64 16
+
+/* for instruction.operand[].flag */
+#define REGISTER 0x1
+#define MEMORY 0x2
+#define IMMEDIATE 0x4
+
+/* for instruction.flags */
+#define REPZ 0x1
+#define REPNZ 0x2
+#define OVERLAP 0x4
+
+/* instruction type */
+#define INSTR_PIO 1
+#define INSTR_OR 2
+#define INSTR_AND 3
+#define INSTR_XOR 4
+#define INSTR_CMP 5
+#define INSTR_MOV 6
+#define INSTR_MOVS 7
+#define INSTR_MOVZX 8
+#define INSTR_MOVSX 9
+#define INSTR_STOS 10
+#define INSTR_TEST 11
+#define INSTR_BT 12
+
+struct instruction {
+ __s8 instr; /* instruction type */
+ __s16 op_size; /* the operand's bit size, e.g. 16-bit or 32-bit */
+ __u64 immediate;
+ __u16 seg_sel; /* segmentation selector */
+ __u32 operand[MAX_OPERAND_NUM]; /* order is AT&T assembly */
+ __u32 flags;
+};
+
+#define MAX_INST_LEN 32
+
+struct mmio_op {
+ int flags;
+ int instr; /* instruction */
+ unsigned long operand[2]; /* operands */
+ unsigned long immediate; /* immediate portion */
+ struct cpu_user_regs *inst_decoder_regs; /* current context */
+};
+
+#define MAX_IO_HANDLER 8
+
+#define VMX_PORTIO 0
+#define VMX_MMIO 1
+
+typedef int (*intercept_action_t)(ioreq_t *);
+typedef unsigned long (*hvm_mmio_read_t)(struct vcpu *v,
+ unsigned long addr,
+ unsigned long length);
+
+typedef void (*hvm_mmio_write_t)(struct vcpu *v,
+ unsigned long addr,
+ unsigned long length,
+ unsigned long val);
+
+typedef int (*hvm_mmio_check_t)(struct vcpu *v, unsigned long addr);
+
+struct io_handler {
+ int type;
+ unsigned long addr;
+ unsigned long size;
+ intercept_action_t action;
+};
+
+struct hvm_io_handler {
+ int num_slot;
+ struct io_handler hdl_list[MAX_IO_HANDLER];
+};
+
+struct hvm_mmio_handler {
+ hvm_mmio_check_t check_handler;
+ hvm_mmio_read_t read_handler;
+ hvm_mmio_write_t write_handler;
+};
+
+/* global io interception point in HV */
+extern int hvm_io_intercept(ioreq_t *p, int type);
+extern int register_io_handler(unsigned long addr, unsigned long size,
+ intercept_action_t action, int type);
+
+static inline int hvm_portio_intercept(ioreq_t *p)
+{
+ return hvm_io_intercept(p, VMX_PORTIO);
+}
+
+int hvm_mmio_intercept(ioreq_t *p);
+
+static inline int register_portio_handler(unsigned long addr,
+ unsigned long size,
+ intercept_action_t action)
+{
+ return register_io_handler(addr, size, action, VMX_PORTIO);
+}
+
+#if defined(__i386__) || defined(__x86_64__)
+static inline int irq_masked(unsigned long eflags)
+{
+ return ((eflags & X86_EFLAGS_IF) == 0);
+}
+#endif
+
+extern void handle_mmio(unsigned long, unsigned long);
+extern void hvm_wait_io(void);
+extern void hvm_io_assist(struct vcpu *v);
+extern void pic_irq_request(int *interrupt_request, int level);
+extern void hvm_pic_assist(struct vcpu *v);
+extern int cpu_get_interrupt(struct vcpu *v, int *type);
+
+// XXX - think about this, maybe use bit 30 of the mfn to signify an MMIO frame.
+#define mmio_space(gpa) (!VALID_MFN(get_mfn_from_pfn((gpa) >> PAGE_SHIFT)))
+
+#endif /* __ASM_X86_HVM_IO_H__ */
+
diff --git a/xen/include/asm-x86/hvm/support.h b/xen/include/asm-x86/hvm/support.h
new file mode 100644
index 0000000000..193de6f886
--- /dev/null
+++ b/xen/include/asm-x86/hvm/support.h
@@ -0,0 +1,149 @@
+/*
+ * support.h: HVM support routines used by VT-x and SVM.
+ *
+ * Leendert van Doorn, leendert@watson.ibm.com
+ * Copyright (c) 2005, International Business Machines Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef __ASM_X86_HVM_SUPPORT_H__
+#define __ASM_X86_HVM_SUPPORT_H__
+
+#include <xen/sched.h>
+#include <asm/types.h>
+#include <asm/regs.h>
+#include <asm/processor.h>
+
+#define HVM_DEBUG 1
+
+#define HVM_DOMAIN(v) ((v)->arch.guest_context.flags & VGCF_HVM_GUEST)
+
+static inline shared_iopage_t *get_sp(struct domain *d)
+{
+ return (shared_iopage_t *) d->arch.hvm_domain.shared_page_va;
+}
+
+static inline vcpu_iodata_t *get_vio(struct domain *d, unsigned long cpu)
+{
+ return &get_sp(d)->vcpu_iodata[cpu];
+}
+
+static inline int iopacket_port(struct domain *d)
+{
+ return get_sp(d)->sp_global.eport;
+}
+
+/* XXX these are really VMX specific */
+#define TYPE_MOV_TO_DR (0 << 4)
+#define TYPE_MOV_FROM_DR (1 << 4)
+#define TYPE_MOV_TO_CR (0 << 4)
+#define TYPE_MOV_FROM_CR (1 << 4)
+#define TYPE_CLTS (2 << 4)
+#define TYPE_LMSW (3 << 4)
+
+enum hval_bitmaps {
+ EXCEPTION_BITMAP_TABLE=0,
+};
+
+#define EXCEPTION_BITMAP_DE (1 << 0) /* Divide Error */
+#define EXCEPTION_BITMAP_DB (1 << 1) /* Debug */
+#define EXCEPTION_BITMAP_NMI (1 << 2) /* NMI */
+#define EXCEPTION_BITMAP_BP (1 << 3) /* Breakpoint */
+#define EXCEPTION_BITMAP_OF (1 << 4) /* Overflow */
+#define EXCEPTION_BITMAP_BR (1 << 5) /* BOUND Range Exceeded */
+#define EXCEPTION_BITMAP_UD (1 << 6) /* Invalid Opcode */
+#define EXCEPTION_BITMAP_NM (1 << 7) /* Device Not Available */
+#define EXCEPTION_BITMAP_DF (1 << 8) /* Double Fault */
+/* reserved */
+#define EXCEPTION_BITMAP_TS (1 << 10) /* Invalid TSS */
+#define EXCEPTION_BITMAP_NP (1 << 11) /* Segment Not Present */
+#define EXCEPTION_BITMAP_SS (1 << 12) /* Stack-Segment Fault */
+#define EXCEPTION_BITMAP_GP (1 << 13) /* General Protection */
+#define EXCEPTION_BITMAP_PG (1 << 14) /* Page Fault */
+#define EXCEPTION_BITMAP_MF (1 << 16) /* x87 FPU Floating-Point Error (Math Fault) */
+#define EXCEPTION_BITMAP_AC (1 << 17) /* Alignment Check */
+#define EXCEPTION_BITMAP_MC (1 << 18) /* Machine Check */
+#define EXCEPTION_BITMAP_XF (1 << 19) /* SIMD Floating-Point Exception */
+
+/* Pending Debug exceptions */
+#define PENDING_DEBUG_EXC_BP (1 << 12) /* break point */
+#define PENDING_DEBUG_EXC_BS (1 << 14) /* Single step */
+
+#ifdef XEN_DEBUGGER
+#define MONITOR_DEFAULT_EXCEPTION_BITMAP \
+ ( EXCEPTION_BITMAP_PG | \
+ EXCEPTION_BITMAP_DB | \
+ EXCEPTION_BITMAP_BP | \
+ EXCEPTION_BITMAP_GP )
+#else
+#define MONITOR_DEFAULT_EXCEPTION_BITMAP \
+ ( EXCEPTION_BITMAP_PG | \
+ EXCEPTION_BITMAP_GP )
+#endif
+
+#define PC_DEBUG_PORT 0x80
+
+#define VMX_INVALID_ERROR_CODE -1
+
+/*
+ * This works for both 32bit & 64bit eflags filteration
+ * done in construct_init_vmc[sb]_guest()
+ */
+#define HVM_EFLAGS_RESERVED_0 0xffc08028 /* bitmap for 0 */
+#define HVM_EFLAGS_RESERVED_1 0x00000002 /* bitmap for 1 */
+
+#if HVM_DEBUG
+#define DBG_LEVEL_0 (1 << 0)
+#define DBG_LEVEL_1 (1 << 1)
+#define DBG_LEVEL_2 (1 << 2)
+#define DBG_LEVEL_3 (1 << 3)
+#define DBG_LEVEL_IO (1 << 4)
+#define DBG_LEVEL_VMMU (1 << 5)
+#define DBG_LEVEL_VLAPIC (1 << 6)
+#define DBG_LEVEL_VLAPIC_TIMER (1 << 7)
+#define DBG_LEVEL_VLAPIC_INTERRUPT (1 << 7)
+#define DBG_LEVEL_IOAPIC (1 << 9)
+
+extern unsigned int opt_hvm_debug_level;
+#define HVM_DBG_LOG(level, _f, _a...) \
+ if ((level) & opt_hvm_debug_level) \
+ printk("[HVM:%d.%d] " _f "\n", \
+ current->domain->domain_id, current->vcpu_id, ## _a)
+#else
+#define HVM_DBG_LOG(level, _f, _a...)
+#endif
+
+#define __hvm_bug(regs) \
+ do { \
+ printk("__hvm_bug at %s:%d\n", __FILE__, __LINE__); \
+ show_registers(regs); \
+ domain_crash_synchronous(); \
+ } while (0)
+
+extern int hvm_enabled;
+extern int hvm_switch_on;
+
+enum { HVM_COPY_IN = 0, HVM_COPY_OUT };
+extern int hvm_copy(void *buf, unsigned long vaddr, int size, int dir);
+
+extern void hvm_setup_platform(struct domain* d);
+extern int hvm_mmio_intercept(ioreq_t *p);
+extern int hvm_io_intercept(ioreq_t *p, int type);
+extern void hvm_check_events(struct vcpu *v);
+extern void hvm_hooks_assist(struct vcpu *v);
+extern void hvm_print_line(struct vcpu *v, const char c);
+extern void hlt_timer_fn(void *data);
+
+#endif /* __ASM_X86_HVM_SUPPORT_H__ */
diff --git a/xen/include/asm-x86/hvm/svm/emulate.h b/xen/include/asm-x86/hvm/svm/emulate.h
new file mode 100644
index 0000000000..1dba011969
--- /dev/null
+++ b/xen/include/asm-x86/hvm/svm/emulate.h
@@ -0,0 +1,161 @@
+/*
+ * emulate.h: SVM instruction emulation bits.
+ * Copyright (c) 2005, AMD Corporation.
+ * Copyright (c) 2004, Intel 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 __ASM_X86_HVM_SVM_EMULATE_H__
+#define __ASM_X86_HVM_SVM_EMULATE_H__
+
+#ifdef CONFIG_SVM
+
+typedef enum OPERATING_MODE_ {
+ INVALID_OPERATING_MODE = -1,
+ LEGACY_MODE,
+ LEGACY_16BIT,
+ LONG_MODE,
+ COMP_MODE,
+ COMP_16BIT,
+ OPMODE_16BIT,
+
+ LEGACY_32BIT,
+ COMP_32BIT,
+ OPMODE_32BIT,
+
+ LONG_64BIT,
+ UNKNOWN_OP_MODE,
+ NUM_OPERATING_MODES
+} OPERATING_MODE;
+
+
+/* Enumerate some standard instructions that we support */
+enum instruction_index {
+ INSTR_INVD,
+ INSTR_CPUID,
+ INSTR_RDMSR,
+ INSTR_WRMSR,
+ INSTR_RDTSC,
+ INSTR_RDTSCP,
+ INSTR_CLI,
+ INSTR_STI,
+ INSTR_RDPMC,
+ INSTR_CLGI,
+ INSTR_STGI,
+ INSTR_VMRUN,
+ INSTR_VMLOAD,
+ INSTR_VMSAVE,
+ INSTR_VMCALL,
+ INSTR_PAUSE,
+ INSTR_SKINIT,
+ INSTR_MOV2CR, /* Mov register to CR */
+ INSTR_MOVCR2, /* Not MOV CR2, but MOV CRn to register */
+ INSTR_MOV2DR,
+ INSTR_MOVDR2,
+ INSTR_PUSHF,
+ INSTR_POPF,
+ INSTR_RSM,
+ INSTR_INVLPG,
+ INSTR_INVLPGA,
+ INSTR_HLT,
+ INSTR_CLTS,
+ INSTR_LMSW,
+ INSTR_SMSW,
+ INSTR_MAX_COUNT /* Must be last - Number of instructions supported */
+};
+
+
+extern unsigned long get_effective_addr_modrm64(struct vmcb_struct *vmcb,
+ struct cpu_user_regs *regs, const u8 prefix, const u8 *operand,
+ u8 *size);
+extern unsigned long get_effective_addr_sib(struct vmcb_struct *vmcb,
+ struct cpu_user_regs *regs, const u8 prefix, const u8 *operand,
+ u8 *size);
+extern OPERATING_MODE get_operating_mode (struct vmcb_struct *vmcb);
+extern unsigned int decode_dest_reg(u8 modrm);
+extern unsigned int decode_src_reg(u8 modrm);
+extern unsigned long svm_rip2pointer(struct vmcb_struct *vmcb);
+extern unsigned int __get_instruction_length_from_list(struct vmcb_struct *vmcb,
+ enum instruction_index *list, unsigned int list_count,
+ u8 *guest_eip_buf, enum instruction_index *match);
+
+
+static inline unsigned int __get_instruction_length(struct vmcb_struct *vmcb,
+ enum instruction_index instr, u8 *guest_eip_buf)
+{
+ return __get_instruction_length_from_list(vmcb, &instr, 1, guest_eip_buf,
+ NULL);
+}
+
+
+static inline unsigned int is_prefix(u8 opc)
+{
+ switch(opc)
+ {
+ case 0x66:
+ case 0x67:
+ case 0x2E:
+ case 0x3E:
+ case 0x26:
+ case 0x64:
+ case 0x65:
+ case 0x36:
+ case 0xF0:
+ case 0xF3:
+ case 0xF2:
+#if __x86_64__
+ case 0x40:
+ case 0x41:
+ case 0x42:
+ case 0x43:
+ case 0x44:
+ case 0x45:
+ case 0x46:
+ case 0x47:
+ case 0x48:
+ case 0x49:
+ case 0x4a:
+ case 0x4b:
+ case 0x4c:
+ case 0x4d:
+ case 0x4e:
+ case 0x4f:
+#endif /* __x86_64__ */
+ return 1;
+ }
+ return 0;
+}
+
+
+static void inline __update_guest_eip(struct vmcb_struct *vmcb,
+ unsigned long inst_len)
+{
+ vmcb->rip += inst_len;
+}
+
+#endif /* CONFIG_SVM */
+
+#endif /* __ASM_X86_HVM_SVM_EMULATE_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-x86/hvm/svm/intr.h b/xen/include/asm-x86/hvm/svm/intr.h
new file mode 100644
index 0000000000..763545ec00
--- /dev/null
+++ b/xen/include/asm-x86/hvm/svm/intr.h
@@ -0,0 +1,34 @@
+/*
+ * intr.h: SVM Architecture related definitions
+ * Copyright (c) 2005, AMD Corporation.
+ * Copyright (c) 2004, Intel 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 __ASM_X86_HVM_SVM_INTR_H__
+#define __ASM_X86_HVM_SVM_INTR_H__
+
+#ifdef CONFIG_SVM
+
+extern void svm_set_tsc_shift(struct vcpu *v, struct hvm_virpit *vpit);
+extern void svm_intr_assist(void);
+extern void svm_intr_assist_update(struct vcpu *v, int highest_vector);
+extern void svm_intr_assist_test_valid(struct vcpu *v,
+ unsigned long *intr_result);
+
+#endif /* CONFIG_SVM */
+
+#endif /* __ASM_X86_HVM_SVM_INTR_H__ */
diff --git a/xen/include/asm-x86/hvm/svm/svm.h b/xen/include/asm-x86/hvm/svm/svm.h
new file mode 100644
index 0000000000..3fc54c638c
--- /dev/null
+++ b/xen/include/asm-x86/hvm/svm/svm.h
@@ -0,0 +1,91 @@
+/*
+ * svm.h: SVM Architecture related definitions
+ * Copyright (c) 2005, AMD Corporation.
+ * Copyright (c) 2004, Intel 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 __ASM_X86_HVM_SVM_H__
+#define __ASM_X86_HVM_SVM_H__
+
+#include <xen/sched.h>
+#include <asm/types.h>
+#include <asm/regs.h>
+#include <asm/processor.h>
+#include <asm/hvm/svm/vmcb.h>
+#include <asm/i387.h>
+
+#ifdef CONFIG_SVM
+extern void asidpool_retire( struct vmcb_struct *vmcb, int core );
+
+extern void svm_asm_vmexit_handler(struct cpu_user_regs);
+extern void svm_setup_function_table(struct vcpu *v);
+
+extern int vmcb_size;
+extern unsigned int cpu_rev;
+
+extern void svm_stop(void);
+extern void svm_save_cpu_user_regs(struct vcpu *v, struct cpu_user_regs *regs);
+extern void svm_load_cpu_user_regs(struct vcpu *v, struct cpu_user_regs *regs);
+extern int svm_modify_vmcb(struct vcpu *v, struct cpu_user_regs *regs);
+extern void svm_vmread(struct vcpu *v, int index, unsigned long *value);
+extern void svm_vmwrite(struct vcpu *v, int index, unsigned long value);
+extern void svm_final_setup_guest(struct vcpu *v);
+extern int svm_paging_enabled(struct vcpu *v);
+extern void svm_relinquish_resources(struct vcpu *v);
+extern void svm_dump_vmcb(const char *from, struct vmcb_struct *vmcb);
+extern void svm_stts(struct vcpu *v);
+extern void svm_do_launch(struct vcpu *v);
+extern void svm_do_resume(struct vcpu *v);
+extern void arch_svm_do_resume(struct vcpu *v);
+extern int load_vmcb(struct arch_svm_struct *arch_svm, u64 phys_hsa);
+/* For debugging. Remove when no longer needed. */
+extern void svm_dump_host_regs(const char *from);
+
+/* ASID API */
+enum {
+ ASID_AVAILABLE = 0,
+ ASID_INUSE,
+ ASID_RETIRED
+};
+#define INITIAL_ASID 0
+#define ASID_MAX 64
+
+struct asid_pool {
+ spinlock_t asid_lock;
+ u32 asid[ASID_MAX];
+};
+
+#define SVM_REG_EAX (0)
+#define SVM_REG_ECX (1)
+#define SVM_REG_EDX (2)
+#define SVM_REG_EBX (3)
+#define SVM_REG_ESP (4)
+#define SVM_REG_EBP (5)
+#define SVM_REG_ESI (6)
+#define SVM_REG_EDI (7)
+#define SVM_REG_R8 (8)
+#define SVM_REG_R9 (9)
+#define SVM_REG_R10 (10)
+#define SVM_REG_R11 (11)
+#define SVM_REG_R12 (12)
+#define SVM_REG_R13 (13)
+#define SVM_REG_R14 (14)
+#define SVM_REG_R15 (15)
+
+#endif /* CONFIG_SVM */
+
+#endif /* __ASM_X86_HVM_SVM_H__ */
diff --git a/xen/include/asm-x86/hvm/svm/vmcb.h b/xen/include/asm-x86/hvm/svm/vmcb.h
new file mode 100644
index 0000000000..14d8e9194a
--- /dev/null
+++ b/xen/include/asm-x86/hvm/svm/vmcb.h
@@ -0,0 +1,503 @@
+/*
+ * vmcb.h: VMCB related definitions
+ * Copyright (c) 2005, AMD Corporation.
+ * Copyright (c) 2004, Intel 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 __ASM_X86_HVM_SVM_VMCB_H__
+#define __ASM_X86_HVM_SVM_VMCB_H__
+
+#include <asm/config.h>
+#include <asm/hvm/hvm.h>
+
+#ifdef CONFIG_SVM
+
+extern int start_svm(void);
+
+/* general 1 intercepts */
+enum GenericIntercept1bits
+{
+ GENERAL1_INTERCEPT_INTR = 1 << 0,
+ GENERAL1_INTERCEPT_NMI = 1 << 1,
+ GENERAL1_INTERCEPT_SMI = 1 << 2,
+ GENERAL1_INTERCEPT_INIT = 1 << 3,
+ GENERAL1_INTERCEPT_VINTR = 1 << 4,
+ GENERAL1_INTERCEPT_CR0_SEL_WRITE = 1 << 5,
+ GENERAL1_INTERCEPT_IDTR_READ = 1 << 6,
+ GENERAL1_INTERCEPT_GDTR_READ = 1 << 7,
+ GENERAL1_INTERCEPT_LDTR_READ = 1 << 8,
+ GENERAL1_INTERCEPT_TR_READ = 1 << 9,
+ GENERAL1_INTERCEPT_IDTR_WRITE = 1 << 10,
+ GENERAL1_INTERCEPT_GDTR_WRITE = 1 << 11,
+ GENERAL1_INTERCEPT_LDTR_WRITE = 1 << 12,
+ GENERAL1_INTERCEPT_TR_WRITE = 1 << 13,
+ GENERAL1_INTERCEPT_RDTSC = 1 << 14,
+ GENERAL1_INTERCEPT_RDPMC = 1 << 15,
+ GENERAL1_INTERCEPT_PUSHF = 1 << 16,
+ GENERAL1_INTERCEPT_POPF = 1 << 17,
+ GENERAL1_INTERCEPT_CPUID = 1 << 18,
+ GENERAL1_INTERCEPT_RSM = 1 << 19,
+ GENERAL1_INTERCEPT_IRET = 1 << 20,
+ GENERAL1_INTERCEPT_SWINT = 1 << 21,
+ GENERAL1_INTERCEPT_INVD = 1 << 22,
+ GENERAL1_INTERCEPT_PAUSE = 1 << 23,
+ GENERAL1_INTERCEPT_HLT = 1 << 24,
+ GENERAL1_INTERCEPT_INVLPG = 1 << 25,
+ GENERAL1_INTERCEPT_INVLPGA = 1 << 26,
+ GENERAL1_INTERCEPT_IOIO_PROT = 1 << 27,
+ GENERAL1_INTERCEPT_MSR_PROT = 1 << 28,
+ GENERAL1_INTERCEPT_TASK_SWITCH = 1 << 29,
+ GENERAL1_INTERCEPT_FERR_FREEZE = 1 << 30,
+ GENERAL1_INTERCEPT_SHUTDOWN_EVT = 1 << 31
+};
+
+/* general 2 intercepts */
+enum GenericIntercept2bits
+{
+ GENERAL2_INTERCEPT_VMRUN = 1 << 0,
+ GENERAL2_INTERCEPT_VMMCALL = 1 << 1,
+ GENERAL2_INTERCEPT_VMLOAD = 1 << 2,
+ GENERAL2_INTERCEPT_VMSAVE = 1 << 3,
+ GENERAL2_INTERCEPT_STGI = 1 << 4,
+ GENERAL2_INTERCEPT_CLGI = 1 << 5,
+ GENERAL2_INTERCEPT_SKINIT = 1 << 6,
+ GENERAL2_INTERCEPT_RDTSCP = 1 << 7,
+ GENERAL2_INTERCEPT_ICEBP = 1 << 8
+};
+
+
+/* control register intercepts */
+enum CRInterceptBits
+{
+ CR_INTERCEPT_CR0_READ = 1 << 0,
+ CR_INTERCEPT_CR1_READ = 1 << 1,
+ CR_INTERCEPT_CR2_READ = 1 << 2,
+ CR_INTERCEPT_CR3_READ = 1 << 3,
+ CR_INTERCEPT_CR4_READ = 1 << 4,
+ CR_INTERCEPT_CR5_READ = 1 << 5,
+ CR_INTERCEPT_CR6_READ = 1 << 6,
+ CR_INTERCEPT_CR7_READ = 1 << 7,
+ CR_INTERCEPT_CR8_READ = 1 << 8,
+ CR_INTERCEPT_CR9_READ = 1 << 9,
+ CR_INTERCEPT_CR10_READ = 1 << 10,
+ CR_INTERCEPT_CR11_READ = 1 << 11,
+ CR_INTERCEPT_CR12_READ = 1 << 12,
+ CR_INTERCEPT_CR13_READ = 1 << 13,
+ CR_INTERCEPT_CR14_READ = 1 << 14,
+ CR_INTERCEPT_CR15_READ = 1 << 15,
+ CR_INTERCEPT_CR0_WRITE = 1 << 16,
+ CR_INTERCEPT_CR1_WRITE = 1 << 17,
+ CR_INTERCEPT_CR2_WRITE = 1 << 18,
+ CR_INTERCEPT_CR3_WRITE = 1 << 19,
+ CR_INTERCEPT_CR4_WRITE = 1 << 20,
+ CR_INTERCEPT_CR5_WRITE = 1 << 21,
+ CR_INTERCEPT_CR6_WRITE = 1 << 22,
+ CR_INTERCEPT_CR7_WRITE = 1 << 23,
+ CR_INTERCEPT_CR8_WRITE = 1 << 24,
+ CR_INTERCEPT_CR9_WRITE = 1 << 25,
+ CR_INTERCEPT_CR10_WRITE = 1 << 26,
+ CR_INTERCEPT_CR11_WRITE = 1 << 27,
+ CR_INTERCEPT_CR12_WRITE = 1 << 28,
+ CR_INTERCEPT_CR13_WRITE = 1 << 29,
+ CR_INTERCEPT_CR14_WRITE = 1 << 30,
+ CR_INTERCEPT_CR15_WRITE = 1 << 31,
+};
+
+enum VMEXIT_EXITCODE
+{
+ /* control register read exitcodes */
+ VMEXIT_CR0_READ = 0,
+ VMEXIT_CR1_READ = 1,
+ VMEXIT_CR2_READ = 2,
+ VMEXIT_CR3_READ = 3,
+ VMEXIT_CR4_READ = 4,
+ VMEXIT_CR5_READ = 5,
+ VMEXIT_CR6_READ = 6,
+ VMEXIT_CR7_READ = 7,
+ VMEXIT_CR8_READ = 8,
+ VMEXIT_CR9_READ = 9,
+ VMEXIT_CR10_READ = 10,
+ VMEXIT_CR11_READ = 11,
+ VMEXIT_CR12_READ = 12,
+ VMEXIT_CR13_READ = 13,
+ VMEXIT_CR14_READ = 14,
+ VMEXIT_CR15_READ = 15,
+
+ /* control register write exitcodes */
+ VMEXIT_CR0_WRITE = 16,
+ VMEXIT_CR1_WRITE = 17,
+ VMEXIT_CR2_WRITE = 18,
+ VMEXIT_CR3_WRITE = 19,
+ VMEXIT_CR4_WRITE = 20,
+ VMEXIT_CR5_WRITE = 21,
+ VMEXIT_CR6_WRITE = 22,
+ VMEXIT_CR7_WRITE = 23,
+ VMEXIT_CR8_WRITE = 24,
+ VMEXIT_CR9_WRITE = 25,
+ VMEXIT_CR10_WRITE = 26,
+ VMEXIT_CR11_WRITE = 27,
+ VMEXIT_CR12_WRITE = 28,
+ VMEXIT_CR13_WRITE = 29,
+ VMEXIT_CR14_WRITE = 30,
+ VMEXIT_CR15_WRITE = 31,
+
+ /* debug register read exitcodes */
+ VMEXIT_DR0_READ = 32,
+ VMEXIT_DR1_READ = 33,
+ VMEXIT_DR2_READ = 34,
+ VMEXIT_DR3_READ = 35,
+ VMEXIT_DR4_READ = 36,
+ VMEXIT_DR5_READ = 37,
+ VMEXIT_DR6_READ = 38,
+ VMEXIT_DR7_READ = 39,
+ VMEXIT_DR8_READ = 40,
+ VMEXIT_DR9_READ = 41,
+ VMEXIT_DR10_READ = 42,
+ VMEXIT_DR11_READ = 43,
+ VMEXIT_DR12_READ = 44,
+ VMEXIT_DR13_READ = 45,
+ VMEXIT_DR14_READ = 46,
+ VMEXIT_DR15_READ = 47,
+
+ /* debug register write exitcodes */
+ VMEXIT_DR0_WRITE = 48,
+ VMEXIT_DR1_WRITE = 49,
+ VMEXIT_DR2_WRITE = 50,
+ VMEXIT_DR3_WRITE = 51,
+ VMEXIT_DR4_WRITE = 52,
+ VMEXIT_DR5_WRITE = 53,
+ VMEXIT_DR6_WRITE = 54,
+ VMEXIT_DR7_WRITE = 55,
+ VMEXIT_DR8_WRITE = 56,
+ VMEXIT_DR9_WRITE = 57,
+ VMEXIT_DR10_WRITE = 58,
+ VMEXIT_DR11_WRITE = 59,
+ VMEXIT_DR12_WRITE = 60,
+ VMEXIT_DR13_WRITE = 61,
+ VMEXIT_DR14_WRITE = 62,
+ VMEXIT_DR15_WRITE = 63,
+
+ /* processor exception exitcodes (VMEXIT_EXCP[0-31]) */
+ VMEXIT_EXCEPTION_DE = 64, /* divide-by-zero-error */
+ VMEXIT_EXCEPTION_DB = 65, /* debug */
+ VMEXIT_EXCEPTION_NMI = 66, /* non-maskable-interrupt */
+ VMEXIT_EXCEPTION_BP = 67, /* breakpoint */
+ VMEXIT_EXCEPTION_OF = 68, /* overflow */
+ VMEXIT_EXCEPTION_BR = 69, /* bound-range */
+ VMEXIT_EXCEPTION_UD = 70, /* invalid-opcode*/
+ VMEXIT_EXCEPTION_NM = 71, /* device-not-available */
+ VMEXIT_EXCEPTION_DF = 72, /* double-fault */
+ VMEXIT_EXCEPTION_09 = 73, /* unsupported (reserved) */
+ VMEXIT_EXCEPTION_TS = 74, /* invalid-tss */
+ VMEXIT_EXCEPTION_NP = 75, /* segment-not-present */
+ VMEXIT_EXCEPTION_SS = 76, /* stack */
+ VMEXIT_EXCEPTION_GP = 77, /* general-protection */
+ VMEXIT_EXCEPTION_PF = 78, /* page-fault */
+ VMEXIT_EXCEPTION_15 = 79, /* reserved */
+ VMEXIT_EXCEPTION_MF = 80, /* x87 floating-point exception-pending */
+ VMEXIT_EXCEPTION_AC = 81, /* alignment-check */
+ VMEXIT_EXCEPTION_MC = 82, /* machine-check */
+ VMEXIT_EXCEPTION_XF = 83, /* simd floating-point */
+
+ /* exceptions 20-31 (exitcodes 84-95) are reserved */
+
+ /* ...and the rest of the #VMEXITs */
+ VMEXIT_INTR = 96,
+ VMEXIT_NMI = 97,
+ VMEXIT_SMI = 98,
+ VMEXIT_INIT = 99,
+ VMEXIT_VINTR = 100,
+ VMEXIT_CR0_SEL_WRITE = 101,
+ VMEXIT_IDTR_READ = 102,
+ VMEXIT_GDTR_READ = 103,
+ VMEXIT_LDTR_READ = 104,
+ VMEXIT_TR_READ = 105,
+ VMEXIT_IDTR_WRITE = 106,
+ VMEXIT_GDTR_WRITE = 107,
+ VMEXIT_LDTR_WRITE = 108,
+ VMEXIT_TR_WRITE = 109,
+ VMEXIT_RDTSC = 110,
+ VMEXIT_RDPMC = 111,
+ VMEXIT_PUSHF = 112,
+ VMEXIT_POPF = 113,
+ VMEXIT_CPUID = 114,
+ VMEXIT_RSM = 115,
+ VMEXIT_IRET = 116,
+ VMEXIT_SWINT = 117,
+ VMEXIT_INVD = 118,
+ VMEXIT_PAUSE = 119,
+ VMEXIT_HLT = 120,
+ VMEXIT_INVLPG = 121,
+ VMEXIT_INVLPGA = 122,
+ VMEXIT_IOIO = 123,
+ VMEXIT_MSR = 124,
+ VMEXIT_TASK_SWITCH = 125,
+ VMEXIT_FERR_FREEZE = 126,
+ VMEXIT_SHUTDOWN = 127,
+ VMEXIT_VMRUN = 128,
+ VMEXIT_VMMCALL = 129,
+ VMEXIT_VMLOAD = 130,
+ VMEXIT_VMSAVE = 131,
+ VMEXIT_STGI = 132,
+ VMEXIT_CLGI = 133,
+ VMEXIT_SKINIT = 134,
+ VMEXIT_RDTSCP = 135,
+ VMEXIT_ICEBP = 136,
+ VMEXIT_NPF = 1024, /* nested paging fault */
+ VMEXIT_INVALID = -1
+};
+
+enum {
+ SVM_CPU_STATE_PG_ENABLED=0,
+ SVM_CPU_STATE_PAE_ENABLED,
+ SVM_CPU_STATE_LME_ENABLED,
+ SVM_CPU_STATE_LMA_ENABLED,
+ SVM_CPU_STATE_ASSIST_ENABLED,
+};
+
+#define SVM_LONG_GUEST(ed) \
+ (test_bit(SVM_CPU_STATE_LMA_ENABLED, &ed->arch.hvm_svm.cpu_state))
+
+enum {
+ SVM_INDEX_MSR_LSTAR = 0,
+ SVM_INDEX_MSR_STAR,
+ SVM_INDEX_MSR_CSTAR,
+ SVM_INDEX_MSR_SYSCALL_MASK,
+ SVM_INDEX_MSR_EFER,
+
+ SVM_MSR_COUNT,
+};
+
+struct svm_msr_state {
+ unsigned long flags;
+ unsigned long msr_items[SVM_MSR_COUNT];
+ unsigned long shadow_gs;
+};
+
+/*
+ * Attribute for segment selector. This is a copy of bit 40:47 & 52:55 of the
+ * segment descriptor.
+ */
+typedef union
+{
+ u16 bytes;
+ struct
+ {
+ u16 type:4; /* 0; Bit 40-43 */
+ u16 s: 1; /* 4; Bit 44 */
+ u16 dpl: 2; /* 5; Bit 45-46 */
+ u16 p: 1; /* 7; Bit 47 */
+ u16 avl: 1; /* 8; Bit 52 */
+ u16 l: 1; /* 9; Bit 53 */
+ u16 db: 1; /* 10; Bit 54 */
+ u16 g: 1; /* 11; Bit 55 */
+ } fields;
+} __attribute__ ((packed)) segment_attributes_t;
+
+typedef struct
+{
+ u16 sel;
+ segment_attributes_t attributes;
+ u32 limit;
+ u64 base;
+} __attribute__ ((packed)) segment_selector_t;
+
+typedef union
+{
+ u64 bytes;
+ struct
+ {
+ u64 vector: 8;
+ u64 type: 3;
+ u64 ev: 1;
+ u64 resvd1: 19;
+ u64 v: 1;
+ u64 errorcode:32;
+ } fields;
+} __attribute__ ((packed)) eventinj_t;
+
+enum EVENTTYPES
+{
+ EVENTTYPE_INTR = 0,
+ EVENTTYPE_NMI = 2,
+ EVENTTYPE_EXCEPTION = 3,
+ EVENTTYPE_SWINT = 4,
+};
+
+typedef union
+{
+ u64 bytes;
+ struct
+ {
+ u64 tpr: 8;
+ u64 irq: 1;
+ u64 rsvd0: 7;
+ u64 prio: 4;
+ u64 ign_tpr: 1;
+ u64 rsvd1: 3;
+ u64 intr_masking: 1;
+ u64 rsvd2: 7;
+ u64 vector: 8;
+ u64 rsvd3: 24;
+ } fields;
+} __attribute__ ((packed)) vintr_t;
+
+typedef union
+{
+ u64 bytes;
+ struct
+ {
+ u64 type: 1;
+ u64 rsv0: 1;
+ u64 str: 1;
+ u64 rep: 1;
+ u64 sz8: 1;
+ u64 sz16: 1;
+ u64 sz32: 1;
+ u64 rsv1: 9;
+ u64 port: 16;
+ } fields;
+} __attribute__ ((packed)) ioio_info_t;
+
+struct vmcb_struct {
+ u32 cr_intercepts; /* offset 0x00 */
+ u32 dr_intercepts; /* offset 0x04 */
+ u32 exception_intercepts; /* offset 0x08 */
+ u32 general1_intercepts; /* offset 0x0C */
+ u32 general2_intercepts; /* offset 0x10 */
+ u32 res01; /* offset 0x14 */
+ u64 res02; /* offset 0x18 */
+ u64 res03; /* offset 0x20 */
+ u64 res04; /* offset 0x28 */
+ u64 res05; /* offset 0x30 */
+ u64 res06; /* offset 0x38 */
+ u64 iopm_base_pa; /* offset 0x40 */
+ u64 msrpm_base_pa; /* offset 0x48 */
+ u64 tsc_offset; /* offset 0x50 */
+ u32 guest_asid; /* offset 0x58 */
+ u8 tlb_control; /* offset 0x5C */
+ u8 res07[3];
+ vintr_t vintr; /* offset 0x60 */
+ u64 interrupt_shadow; /* offset 0x68 */
+ u64 exitcode; /* offset 0x70 */
+ u64 exitinfo1; /* offset 0x78 */
+ u64 exitinfo2; /* offset 0x80 */
+ eventinj_t exitintinfo; /* offset 0x88 */
+ u64 np_enable; /* offset 0x90 */
+ u64 res08[2];
+ eventinj_t eventinj; /* offset 0xA8 */
+ u64 h_cr3; /* offset 0xB0 */
+ u64 res09[105]; /* offset 0xB8 pad to save area */
+
+ segment_selector_t es; /* offset 1024 */
+ segment_selector_t cs;
+ segment_selector_t ss;
+ segment_selector_t ds;
+ segment_selector_t fs;
+ segment_selector_t gs;
+ segment_selector_t gdtr;
+ segment_selector_t ldtr;
+ segment_selector_t idtr;
+ segment_selector_t tr;
+ u64 res10[5];
+ u8 res11[3];
+ u8 cpl;
+ u32 res12;
+ u64 efer; /* offset 1024 + 0xD0 */
+ u64 res13[14];
+ u64 cr4; /* loffset 1024 + 0x148 */
+ u64 cr3;
+ u64 cr0;
+ u64 dr7;
+ u64 dr6;
+ u64 rflags;
+ u64 rip;
+ u64 res14[11];
+ u64 rsp;
+ u64 res15[3];
+ u64 rax;
+ u64 star;
+ u64 lstar;
+ u64 cstar;
+ u64 sfmask;
+ u64 kerngsbase;
+ u64 sysenter_cs;
+ u64 sysenter_esp;
+ u64 sysenter_eip;
+ u64 cr2;
+ u64 pdpe0;
+ u64 pdpe1;
+ u64 pdpe2;
+ u64 pdpe3;
+ u64 g_pat;
+ u64 res16[50];
+ u64 res17[128];
+ u64 res18[128];
+} __attribute__ ((packed));
+
+
+struct arch_svm_struct {
+ struct vmcb_struct *vmcb;
+ void *host_save_area;
+ u64 host_save_pa;
+ u64 vmcb_pa;
+ u32 *iopm;
+ u32 *msrpm;
+ u64 vmexit_tsc; /* tsc read at #VMEXIT. for TSC_OFFSET */
+ int injecting_event;
+ int saved_irq_vector;
+ u32 core; /* cpu of last vmexit */
+
+ unsigned long flags; /* VMCB flags */
+ unsigned long cpu_shadow_cr0; /* copy of guest read shadow CR0 */
+ unsigned long cpu_cr2;
+ unsigned long cpu_cr3;
+ unsigned long cpu_state;
+ struct svm_msr_state msr_content;
+ struct timer hlt_timer; /* hlt ins emulation wakeup timer */
+};
+
+struct vmcb_struct *alloc_vmcb(void);
+struct host_save_area *alloc_host_save_area(void);
+void free_vmcb(struct vmcb_struct *vmcb);
+void free_host_save_area(struct host_save_area *hsa);
+void dump_vmcb(void);
+int construct_vmcb(struct arch_svm_struct *, struct cpu_user_regs *);
+
+#define VMCB_USE_HOST_ENV 1
+#define VMCB_USE_SEPARATE_ENV 0
+
+enum {
+ ARCH_SVM_VMCB_LOADED = 0,
+ ARCH_SVM_VMCB_ASSIGN_ASID
+};
+
+#define VMCB_EFLAGS_RESERVED_0 0xffc08028 /* bitmap for 0 */
+#define VMCB_EFLAGS_RESERVED_1 0x00000002 /* bitmap for 1 */
+
+#endif /* CONFIG_SVM */
+
+#endif /* ASM_X86_HVM_SVM_VMCS_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-x86/hvm/svm/vmmcall.h b/xen/include/asm-x86/hvm/svm/vmmcall.h
new file mode 100644
index 0000000000..b138aea90a
--- /dev/null
+++ b/xen/include/asm-x86/hvm/svm/vmmcall.h
@@ -0,0 +1,48 @@
+/*
+ * vmmcall.h: VMMCALL instruction support
+ *
+ * Travis Betak, travis.betak@amd.com
+ * Copyright (c) 2005, AMD 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 __ASM_X86_HVM_SVM_VMMCALL_H__
+#define __ASM_X86_HVM_SVM_VMMCALL_H__
+
+#ifdef CONFIG_SVM
+
+/* VMMCALL command fields */
+#define VMMCALL_CODE_CPL_MASK 0xC0000000
+#define VMMCALL_CODE_MBZ_MASK 0x3FFF0000
+#define VMMCALL_CODE_COMMAND_MASK 0x0000FFFF
+
+#define MAKE_VMMCALL_CODE(cpl,func) ((cpl << 30) | (func))
+
+/* CPL=0 VMMCALL Requests */
+#define VMMCALL_RESET_TO_REALMODE MAKE_VMMCALL_CODE(0,1)
+
+/* CPL=3 VMMCALL Requests */
+#define VMMCALL_DEBUG MAKE_VMMCALL_CODE(3,1)
+
+/* return the cpl required for the vmmcall cmd */
+static inline int get_vmmcall_cpl(int cmd)
+{
+ return (cmd & VMMCALL_CODE_CPL_MASK) >> 30;
+}
+
+#endif /* CONFIG_SVM */
+
+#endif /* __ASM_X86_HVM_SVM_VMMCALL_H__ */
diff --git a/xen/include/asm-x86/hvm/vcpu.h b/xen/include/asm-x86/hvm/vcpu.h
new file mode 100644
index 0000000000..c5f4b8c613
--- /dev/null
+++ b/xen/include/asm-x86/hvm/vcpu.h
@@ -0,0 +1,51 @@
+/*
+ * vcpu.h: HVM per vcpu definitions
+ *
+ * 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 __ASM_X86_HVM_VCPU_H__
+#define __ASM_X86_HVM_VCPU_H__
+
+#include <asm/hvm/io.h>
+#include <asm/hvm/vlapic.h>
+
+#ifdef CONFIG_VMX
+#include <asm/hvm/vmx/vmcs.h>
+#endif
+#ifdef CONFIG_SVM
+#include <asm/hvm/svm/vmcb.h>
+#endif
+
+struct hvm_vcpu {
+ unsigned long ioflags;
+ struct mmio_op mmio_op;
+ struct vlapic *vlapic;
+
+ union {
+#ifdef CONFIG_VMX
+ struct arch_vmx_struct vmx;
+#endif
+#ifdef CONFIG_SVM
+ struct arch_svm_struct svm;
+#endif
+ } u;
+};
+
+#define ARCH_HVM_IO_WAIT 1 /* Waiting for I/O completion */
+
+#endif /* __ASM_X86_HVM_VCPU_H__ */
+
diff --git a/xen/include/asm-x86/vmx_vioapic.h b/xen/include/asm-x86/hvm/vioapic.h
index 925bcef68b..6b72f95e5d 100644
--- a/xen/include/asm-x86/vmx_vioapic.h
+++ b/xen/include/asm-x86/hvm/vioapic.h
@@ -23,8 +23,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#ifndef _IOAPIC_H_
-#define _IOAPIC_H_
+#ifndef __ASM_X86_HVM_IOAPIC_H__
+#define __ASM_X86_HVM_IOAPIC_H__
#include <xen/config.h>
#include <xen/types.h>
@@ -91,7 +91,7 @@ typedef union RedirStatus
#define IOAPIC_ENABLE_FLAG (1 << IOAPIC_ENABLE_MASK)
#define MAX_LAPIC_NUM 32
-typedef struct vmx_vioapic {
+typedef struct hvm_vioapic {
uint32_t irr;
uint32_t isr; /* This is used for level trigger */
uint32_t imr;
@@ -104,21 +104,21 @@ typedef struct vmx_vioapic {
RedirStatus redirtbl[IOAPIC_NUM_PINS];
struct vlapic *lapic_info[MAX_LAPIC_NUM];
struct domain *domain;
-} vmx_vioapic_t;
+} hvm_vioapic_t;
-vmx_vioapic_t *vmx_vioapic_init(struct domain *d);
+hvm_vioapic_t *hvm_vioapic_init(struct domain *d);
-void vmx_vioapic_do_irqs_clear(struct domain *d, uint16_t irqs);
-void vmx_vioapic_do_irqs(struct domain *d, uint16_t irqs);
-void vmx_vioapic_set_irq(struct domain *d, int irq, int level);
+void hvm_vioapic_do_irqs_clear(struct domain *d, uint16_t irqs);
+void hvm_vioapic_do_irqs(struct domain *d, uint16_t irqs);
+void hvm_vioapic_set_irq(struct domain *d, int irq, int level);
-int vmx_vioapic_add_lapic(struct vlapic *vlapic, struct vcpu *v);
+int hvm_vioapic_add_lapic(struct vlapic *vlapic, struct vcpu *v);
void ioapic_update_EOI(struct domain *d, int vector);
-#ifdef VMX_DOMAIN_SAVE_RESTORE
+#ifdef HVM_DOMAIN_SAVE_RESTORE
void ioapic_save(QEMUFile* f, void* opaque);
int ioapic_load(QEMUFile* f, void* opaque, int version_id);
#endif
-#endif
+#endif /* __ASM_X86_HVM_IOAPIC_H__ */
diff --git a/xen/include/asm-x86/vmx_vlapic.h b/xen/include/asm-x86/hvm/vlapic.h
index 2527800b60..86fdcbca21 100644
--- a/xen/include/asm-x86/vmx_vlapic.h
+++ b/xen/include/asm-x86/hvm/vlapic.h
@@ -1,5 +1,6 @@
/*
- * vmx_vlapic.h: virtualize LAPIC definitions.
+ * hvm_vlapic.h: virtualize LAPIC definitions.
+ *
* Copyright (c) 2004, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
@@ -14,11 +15,10 @@
* 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 VMX_VLAPIC_H
-#define VMX_VLAPIC_H
+#ifndef __ASM_X86_HVM_VLAPIC_H__
+#define __ASM_X86_HVM_VLAPIC_H__
#include <asm/msr.h>
#include <public/hvm/ioreq.h>
@@ -71,7 +71,7 @@ static __inline__ int find_highest_bit(uint32_t *data, int length)
return __fls(data[length]) + 32 * length;
}
-#define VLAPIC(v) (v->arch.arch_vmx.vlapic)
+#define VLAPIC(v) (v->arch.hvm_vcpu.vlapic)
#define VAPIC_ID_MASK 0xff
#define VAPIC_LDR_MASK (VAPIC_ID_MASK << 24)
@@ -187,7 +187,7 @@ struct vlapic
uint32_t timer_current;
uint32_t timer_divconf;
uint32_t timer_divide_counter;
- struct timer vlapic_timer;
+ struct timer vlapic_timer;
int intr_pending_count[MAX_VECTOR];
s_time_t timer_current_update;
uint32_t icr_high;
@@ -208,7 +208,7 @@ static inline int vlapic_set_irq(struct vlapic *t, uint8_t vec, uint8_t trig)
ret = test_and_set_bit(vec, &t->irr[0]);
if (trig)
- test_and_set_bit(vec, &t->tmr[0]);
+ test_and_set_bit(vec, &t->tmr[0]);
/* We may need to wake up target vcpu, besides set pending bit here */
return ret;
@@ -246,8 +246,8 @@ struct vlapic* apic_round_robin(struct domain *d,
uint8_t dest_mode,
uint8_t vector,
uint32_t bitmap);
-s_time_t get_apictime_scheduled(struct vcpu *v);
-int vmx_apic_support(struct domain *d);
-#endif /* VMX_VLAPIC_H */
+s_time_t get_apictime_scheduled(struct vcpu *v);
+int hvm_apic_support(struct domain *d);
+#endif /* __ASM_X86_HVM_VLAPIC_H__ */
diff --git a/xen/include/asm-x86/vmx_cpu.h b/xen/include/asm-x86/hvm/vmx/cpu.h
index 2cccc151dd..606cf40ef6 100644
--- a/xen/include/asm-x86/vmx_cpu.h
+++ b/xen/include/asm-x86/hvm/vmx/cpu.h
@@ -1,5 +1,5 @@
/*
- * vmx_cpu.h: Virtual CPU state
+ * cpu.h: Virtual CPU state
* Copyright (c) 2004, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
@@ -16,8 +16,10 @@
* Place - Suite 330, Boston, MA 02111-1307 USA.
*
*/
-#ifndef __ASM_X86_VMX_VMCS_H__
-#define __ASM_X86_VMX_VMCS_H__
+#ifndef __ASM_X86_HVM_VMX_CPU_H__
+#define __ASM_X86_HVM_VMX_CPU_H__
+
+#ifdef CONFIG_VMX
/*
* Virtual CPU
@@ -32,4 +34,6 @@ struct arch_state_struct {
#define VMX_MF_32 1
#define VMX_MF_64 2
-#endif
+#endif /* CONFIG_VMX */
+
+#endif /* __ASM_X86_HVM_VMX_CPU_H__ */
diff --git a/xen/include/asm-x86/vmx_vmcs.h b/xen/include/asm-x86/hvm/vmx/vmcs.h
index 81b9fb6009..8092969e49 100644
--- a/xen/include/asm-x86/vmx_vmcs.h
+++ b/xen/include/asm-x86/hvm/vmx/vmcs.h
@@ -1,5 +1,5 @@
/*
- * vmx_vmcs.h: VMCS related definitions
+ * vmcs.h: VMCS related definitions
* Copyright (c) 2004, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
@@ -16,26 +16,19 @@
* Place - Suite 330, Boston, MA 02111-1307 USA.
*
*/
-#ifndef __ASM_X86_VMX_VMCS_H__
-#define __ASM_X86_VMX_VMCS_H__
+#ifndef __ASM_X86_HVM_VMX_VMCS_H__
+#define __ASM_X86_HVM_VMX_VMCS_H__
#include <asm/config.h>
-#include <asm/vmx_cpu.h>
-#include <asm/vmx_platform.h>
-#include <asm/vmx_vlapic.h>
+#include <asm/hvm/io.h>
+#include <asm/hvm/vmx/cpu.h>
#include <public/hvm/vmx_assist.h>
+#ifdef CONFIG_VMX
+
extern int start_vmx(void);
extern void stop_vmx(void);
-#if defined (__x86_64__)
-extern void vmx_load_msrs(struct vcpu *n);
-void vmx_restore_msrs(struct vcpu *v);
-#else
-#define vmx_load_msrs(_n) ((void)0)
-#define vmx_restore_msrs(_v) ((void)0)
-#endif
-
void vmx_final_setup_guest(struct vcpu *v);
void vmx_relinquish_resources(struct vcpu *v);
@@ -50,7 +43,7 @@ enum {
};
#define VMX_LONG_GUEST(ed) \
- (test_bit(VMX_CPU_STATE_LMA_ENABLED, &ed->arch.arch_vmx.cpu_state))
+ (test_bit(VMX_CPU_STATE_LMA_ENABLED, &ed->arch.hvm_vmx.cpu_state))
struct vmcs_struct {
u32 vmcs_revision_id;
@@ -69,22 +62,12 @@ enum {
VMX_MSR_COUNT,
};
-struct msr_state{
+struct vmx_msr_state {
unsigned long flags;
unsigned long msr_items[VMX_MSR_COUNT];
unsigned long shadow_gs;
};
-struct mmio_op {
- int flags;
- int instr; /* instruction */
- unsigned long operand[2]; /* operands */
- unsigned long immediate; /* immediate portion */
- struct cpu_user_regs *inst_decoder_regs; /* current context */
-};
-
-#define PC_DEBUG_PORT 0x80
-
struct arch_vmx_struct {
struct vmcs_struct *vmcs; /* VMCS pointer in virtual. */
unsigned int launch_cpu; /* VMCS is valid on this CPU. */
@@ -95,38 +78,28 @@ struct arch_vmx_struct {
unsigned long cpu_cr3;
unsigned long cpu_state;
unsigned long cpu_based_exec_control;
- struct msr_state msr_content;
- struct mmio_op mmio_op; /* MMIO */
+ struct vmx_msr_state msr_content;
void *io_bitmap_a, *io_bitmap_b;
- struct vlapic *vlapic;
u64 tsc_offset;
- struct timer hlt_timer; /* hlt ins emulation wakeup timer */
+ struct timer hlt_timer; /* hlt ins emulation wakeup timer */
};
#define vmx_schedule_tail(next) \
(next)->thread.arch_vmx.arch_vmx_schedule_tail((next))
-#define VMX_DOMAIN(v) ((v)->arch.arch_vmx.flags)
-
#define ARCH_VMX_VMCS_LOADED 0 /* VMCS has been loaded and active */
#define ARCH_VMX_VMCS_LAUNCH 1 /* Needs VMCS launch */
#define ARCH_VMX_VMCS_RESUME 2 /* Needs VMCS resume */
-#define ARCH_VMX_IO_WAIT 3 /* Waiting for I/O completion */
void vmx_do_resume(struct vcpu *);
struct vmcs_struct *alloc_vmcs(void);
int modify_vmcs(struct arch_vmx_struct *arch_vmx,
struct cpu_user_regs *regs);
void destroy_vmcs(struct arch_vmx_struct *arch_vmx);
-void hlt_timer_fn(void *data);
#define VMCS_USE_HOST_ENV 1
#define VMCS_USE_SEPARATE_ENV 0
-/* this works for both 32bit & 64bit eflags filteration done in construct_init_vmcs_guest() */
-#define VMCS_EFLAGS_RESERVED_0 0xffc08028 /* bitmap for 0 */
-#define VMCS_EFLAGS_RESERVED_1 0x00000002 /* bitmap for 1 */
-
extern int vmcs_version;
#define CPU_BASED_VIRTUAL_INTR_PENDING 0x00000004
@@ -275,36 +248,9 @@ enum vmcs_field {
HOST_RIP = 0x00006c16,
};
-#define VMX_DEBUG 1
-#if VMX_DEBUG
-#define DBG_LEVEL_0 (1 << 0)
-#define DBG_LEVEL_1 (1 << 1)
-#define DBG_LEVEL_2 (1 << 2)
-#define DBG_LEVEL_3 (1 << 3)
-#define DBG_LEVEL_IO (1 << 4)
-#define DBG_LEVEL_VMMU (1 << 5)
-#define DBG_LEVEL_VLAPIC (1 << 6)
-#define DBG_LEVEL_VLAPIC_TIMER (1 << 7)
-#define DBG_LEVEL_VLAPIC_INTERRUPT (1 << 8)
-#define DBG_LEVEL_IOAPIC (1 << 9)
-
-extern unsigned int opt_vmx_debug_level;
-#define VMX_DBG_LOG(level, _f, _a...) \
- if ((level) & opt_vmx_debug_level) \
- printk("[VMX:%d.%d] " _f "\n", \
- current->domain->domain_id, current->vcpu_id, ## _a)
-#else
-#define VMX_DBG_LOG(level, _f, _a...)
-#endif
-
-#define __vmx_bug(regs) \
- do { \
- printk("__vmx_bug at %s:%d\n", __FILE__, __LINE__); \
- show_registers(regs); \
- domain_crash_synchronous(); \
- } while (0)
+#endif /* CONFIG_VMX */
-#endif /* ASM_X86_VMX_VMCS_H__ */
+#endif /* ASM_X86_HVM_VMX_VMCS_H__ */
/*
* Local variables:
diff --git a/xen/include/asm-x86/vmx.h b/xen/include/asm-x86/hvm/vmx/vmx.h
index 05852a88be..4d485b0c15 100644
--- a/xen/include/asm-x86/vmx.h
+++ b/xen/include/asm-x86/hvm/vmx/vmx.h
@@ -16,25 +16,23 @@
* Place - Suite 330, Boston, MA 02111-1307 USA.
*
*/
-#ifndef __ASM_X86_VMX_H__
-#define __ASM_X86_VMX_H__
+#ifndef __ASM_X86_HVM_VMX_VMX_H__
+#define __ASM_X86_HVM_VMX_VMX_H__
#include <xen/sched.h>
#include <asm/types.h>
#include <asm/regs.h>
#include <asm/processor.h>
-#include <asm/vmx_vmcs.h>
+#include <asm/hvm/vmx/vmcs.h>
#include <asm/i387.h>
-#include <public/hvm/ioreq.h>
-
-extern int hvm_enabled;
+#ifdef CONFIG_VMX
extern void vmx_asm_vmexit_handler(struct cpu_user_regs);
extern void vmx_asm_do_resume(void);
extern void vmx_asm_do_launch(void);
extern void vmx_intr_assist(void);
-extern void pic_irq_request(int *interrupt_request, int level);
+extern void vmx_set_tsc_shift(struct vcpu *, struct hvm_virpit *);
extern void arch_vmx_do_launch(struct vcpu *);
extern void arch_vmx_do_resume(struct vcpu *);
@@ -147,10 +145,6 @@ extern unsigned int cpu_rev;
*/
#define CONTROL_REG_ACCESS_NUM 0x7 /* 2:0, number of control register */
#define CONTROL_REG_ACCESS_TYPE 0x30 /* 5:4, access type */
-#define TYPE_MOV_TO_CR (0 << 4)
-#define TYPE_MOV_FROM_CR (1 << 4)
-#define TYPE_CLTS (2 << 4)
-#define TYPE_LMSW (3 << 4)
#define CONTROL_REG_ACCESS_REG 0xf00 /* 10:8, general purpose register */
#define LMSW_SOURCE_DATA (0xFFFF << 16) /* 16:31 lmsw source */
#define REG_EAX (0 << 8)
@@ -179,43 +173,6 @@ extern unsigned int cpu_rev;
#define TYPE_MOV_FROM_DR (1 << 4)
#define DEBUG_REG_ACCESS_REG 0xf00 /* 11:8, general purpose register */
-#define EXCEPTION_BITMAP_DE (1 << 0) /* Divide Error */
-#define EXCEPTION_BITMAP_DB (1 << 1) /* Debug */
-#define EXCEPTION_BITMAP_NMI (1 << 2) /* NMI */
-#define EXCEPTION_BITMAP_BP (1 << 3) /* Breakpoint */
-#define EXCEPTION_BITMAP_OF (1 << 4) /* Overflow */
-#define EXCEPTION_BITMAP_BR (1 << 5) /* BOUND Range Exceeded */
-#define EXCEPTION_BITMAP_UD (1 << 6) /* Invalid Opcode */
-#define EXCEPTION_BITMAP_NM (1 << 7) /* Device Not Available */
-#define EXCEPTION_BITMAP_DF (1 << 8) /* Double Fault */
-/* reserved */
-#define EXCEPTION_BITMAP_TS (1 << 10) /* Invalid TSS */
-#define EXCEPTION_BITMAP_NP (1 << 11) /* Segment Not Present */
-#define EXCEPTION_BITMAP_SS (1 << 12) /* Stack-Segment Fault */
-#define EXCEPTION_BITMAP_GP (1 << 13) /* General Protection */
-#define EXCEPTION_BITMAP_PG (1 << 14) /* Page Fault */
-#define EXCEPTION_BITMAP_MF (1 << 16) /* x87 FPU Floating-Point Error (Math Fault) */
-#define EXCEPTION_BITMAP_AC (1 << 17) /* Alignment Check */
-#define EXCEPTION_BITMAP_MC (1 << 18) /* Machine Check */
-#define EXCEPTION_BITMAP_XF (1 << 19) /* SIMD Floating-Point Exception */
-
-/* Pending Debug exceptions */
-
-#define PENDING_DEBUG_EXC_BP (1 << 12) /* break point */
-#define PENDING_DEBUG_EXC_BS (1 << 14) /* Single step */
-
-#ifdef XEN_DEBUGGER
-#define MONITOR_DEFAULT_EXCEPTION_BITMAP \
- ( EXCEPTION_BITMAP_PG | \
- EXCEPTION_BITMAP_DB | \
- EXCEPTION_BITMAP_BP | \
- EXCEPTION_BITMAP_GP )
-#else
-#define MONITOR_DEFAULT_EXCEPTION_BITMAP \
- ( EXCEPTION_BITMAP_PG | \
- EXCEPTION_BITMAP_GP )
-#endif
-
/* These bits in the CR4 are owned by the host */
#ifdef __i386__
#define VMX_CR4_HOST_MASK (X86_CR4_VMXE)
@@ -319,13 +276,13 @@ static always_inline void __vmwrite_vcpu(struct vcpu *v, unsigned long field, un
{
switch(field) {
case CR0_READ_SHADOW:
- v->arch.arch_vmx.cpu_shadow_cr0 = value;
+ v->arch.hvm_vmx.cpu_shadow_cr0 = value;
break;
case GUEST_CR0:
- v->arch.arch_vmx.cpu_cr0 = value;
+ v->arch.hvm_vmx.cpu_cr0 = value;
break;
case CPU_BASED_VM_EXEC_CONTROL:
- v->arch.arch_vmx.cpu_based_exec_control = value;
+ v->arch.hvm_vmx.cpu_based_exec_control = value;
break;
default:
printk("__vmwrite_cpu: invalid field %lx\n", field);
@@ -337,13 +294,13 @@ static always_inline void __vmread_vcpu(struct vcpu *v, unsigned long field, uns
{
switch(field) {
case CR0_READ_SHADOW:
- *value = v->arch.arch_vmx.cpu_shadow_cr0;
+ *value = v->arch.hvm_vmx.cpu_shadow_cr0;
break;
case GUEST_CR0:
- *value = v->arch.arch_vmx.cpu_cr0;
+ *value = v->arch.hvm_vmx.cpu_cr0;
break;
case CPU_BASED_VM_EXEC_CONTROL:
- *value = v->arch.arch_vmx.cpu_based_exec_control;
+ *value = v->arch.hvm_vmx.cpu_based_exec_control;
break;
default:
printk("__vmread_cpu: invalid field %lx\n", field);
@@ -446,8 +403,6 @@ static inline int vmx_paging_enabled(struct vcpu *v)
return (cr0 & X86_CR0_PE) && (cr0 & X86_CR0_PG);
}
-#define VMX_INVALID_ERROR_CODE -1
-
static inline int __vmx_inject_exception(struct vcpu *v, int trap, int type,
int error_code)
{
@@ -493,7 +448,7 @@ static inline int vmx_reflect_exception(struct vcpu *v)
unsigned long eip;
__vmread(GUEST_RIP, &eip);
- VMX_DBG_LOG(DBG_LEVEL_1,
+ HVM_DBG_LOG(DBG_LEVEL_1,
"vmx_reflect_exception: eip = %lx, error_code = %x",
eip, error_code);
}
@@ -503,32 +458,6 @@ static inline int vmx_reflect_exception(struct vcpu *v)
return 0;
}
-static inline unsigned int vmx_get_vcpu_nr(struct domain *d)
-{
- return d->arch.vmx_platform.nr_vcpus;
-}
-
-static inline shared_iopage_t *get_sp(struct domain *d)
-{
- return (shared_iopage_t *) d->arch.vmx_platform.shared_page_va;
-}
-
-static inline vcpu_iodata_t *get_vio(struct domain *d, unsigned long cpu)
-{
- return &get_sp(d)->vcpu_iodata[cpu];
-}
-
-static inline int iopacket_port(struct domain *d)
-{
- return get_sp(d)->sp_global.eport;
-}
-
-/* Prototypes */
-void load_cpu_user_regs(struct cpu_user_regs *regs);
-void store_cpu_user_regs(struct cpu_user_regs *regs);
-
-enum { VMX_COPY_IN = 0, VMX_COPY_OUT };
-int vmx_copy(void *buf, unsigned long laddr, int size, int dir);
-void pickup_deactive_ticks(struct vmx_virpit *vpit);
+#endif /* CONFIG_VMX */
-#endif /* __ASM_X86_VMX_H__ */
+#endif /* __ASM_X86_HVM_VMX_VMX_H__ */
diff --git a/xen/include/asm-x86/vmx_vpic.h b/xen/include/asm-x86/hvm/vpic.h
index 256ac87ec5..57388119af 100644
--- a/xen/include/asm-x86/vmx_vpic.h
+++ b/xen/include/asm-x86/hvm/vpic.h
@@ -23,8 +23,8 @@
* THE SOFTWARE.
*/
-#ifndef _VMX_VPIC_H
-#define _VMX_VPIC_H
+#ifndef __ASM_X86_HVM_VPIC_H__
+#define __ASM_X86_HVM_VPIC_H__
#define hw_error(x) do {} while (0);
@@ -48,10 +48,10 @@ typedef struct PicState {
uint8_t init4; /* true if 4 byte init */
uint8_t elcr; /* PIIX edge/trigger selection*/
uint8_t elcr_mask;
- struct vmx_virpic *pics_state;
+ struct hvm_virpic *pics_state;
} PicState;
-struct vmx_virpic {
+struct hvm_virpic {
/* 0 is master pic, 1 is slave pic */
/* XXX: better separation between the two pics */
PicState pics[2];
@@ -63,23 +63,22 @@ struct vmx_virpic {
};
-void pic_set_irq(struct vmx_virpic *s, int irq, int level);
+void pic_set_irq(struct hvm_virpic *s, int irq, int level);
void pic_set_irq_new(void *opaque, int irq, int level);
-void pic_init(struct vmx_virpic *s,
+void pic_init(struct hvm_virpic *s,
void (*irq_request)(),
void *irq_request_opaque);
-void pic_set_alt_irq_func(struct vmx_virpic *s,
+void pic_set_alt_irq_func(struct hvm_virpic *s,
void(*alt_irq_func)(),
void *alt_irq_opaque);
-int pic_read_irq(struct vmx_virpic *s);
-void pic_update_irq(struct vmx_virpic *s);
-uint32_t pic_intack_read(struct vmx_virpic *s);
+int pic_read_irq(struct hvm_virpic *s);
+void pic_update_irq(struct hvm_virpic *s);
+uint32_t pic_intack_read(struct hvm_virpic *s);
void register_pic_io_hook (void);
int cpu_get_pic_interrupt(struct vcpu *v, int *type);
int is_pit_irq(struct vcpu *v, int irq, int type);
int is_irq_enabled(struct vcpu *v, int irq);
-void do_pic_irqs (struct vmx_virpic *s, uint16_t irqs);
-void do_pic_irqs_clear (struct vmx_virpic *s, uint16_t irqs);
+void do_pic_irqs (struct hvm_virpic *s, uint16_t irqs);
+void do_pic_irqs_clear (struct hvm_virpic *s, uint16_t irqs);
-/* APIC */
-#endif /* _VMX_VPIC_H */
+#endif /* __ASM_X86_HVM_VPIC_H__ */
diff --git a/xen/include/asm-x86/hvm/vpit.h b/xen/include/asm-x86/hvm/vpit.h
new file mode 100644
index 0000000000..716af8c334
--- /dev/null
+++ b/xen/include/asm-x86/hvm/vpit.h
@@ -0,0 +1,74 @@
+/*
+ * vpit.h: Virtual PIT definitions
+ *
+ * Copyright (c) 2004, Intel 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 __ASM_X86_HVM_VPIT_H__
+#define __ASM_X86_HVM_VPIT_H__
+
+#include <xen/config.h>
+#include <xen/init.h>
+#include <xen/lib.h>
+#include <xen/time.h>
+#include <xen/errno.h>
+#include <xen/timer.h>
+#include <asm/hvm/vpic.h>
+
+#define PIT_FREQ 1193181
+
+#define LSByte 0
+#define MSByte 1
+#define LSByte_multiple 2
+#define MSByte_multiple 3
+
+struct hvm_virpit {
+ /* for simulation of counter 0 in mode 2 */
+ u64 period_cycles; /* pit frequency in cpu cycles */
+ u64 inject_point; /* the time inject virt intr */
+ u64 shift; /* save the value of offset - drift */
+ s_time_t scheduled; /* scheduled timer interrupt */
+ struct timer pit_timer; /* periodic timer for mode 2*/
+ unsigned int channel; /* the pit channel, counter 0~2 */
+ unsigned int pending_intr_nr; /* the couner for pending timer interrupts */
+ u32 period; /* pit frequency in ns */
+ int first_injected; /* flag to prevent shadow window */
+
+ /* virtual PIT state for handle related I/O */
+ int read_state;
+ int count_LSB_latched;
+ int count_MSB_latched;
+
+ unsigned int count; /* the 16 bit channel count */
+ unsigned int init_val; /* the init value for the counter */
+};
+
+static __inline__ s_time_t get_pit_scheduled(
+ struct vcpu *v,
+ struct hvm_virpit *vpit)
+{
+ if ( is_irq_enabled(v, 0) ) {
+ return vpit->scheduled;
+ }
+ else
+ return -1;
+}
+
+/* to hook the ioreq packet to get the PIT initialization info */
+extern void hvm_hooks_assist(struct vcpu *v);
+void pickup_deactive_ticks(struct hvm_virpit *vpit);
+
+#endif /* __ASM_X86_HVM_VPIT_H__ */
diff --git a/xen/include/asm-x86/mpspec.h b/xen/include/asm-x86/mpspec.h
index 1e3d48a470..8cb7a1fa85 100644
--- a/xen/include/asm-x86/mpspec.h
+++ b/xen/include/asm-x86/mpspec.h
@@ -35,6 +35,7 @@ extern void mp_register_ioapic (u8 id, u32 address, u32 gsi_base);
extern void mp_override_legacy_irq (u8 bus_irq, u8 polarity, u8 trigger, u32 gsi);
extern void mp_config_acpi_legacy_irqs (void);
extern int mp_register_gsi (u32 gsi, int edge_level, int active_high_low);
+extern int mp_get_num_processors(void);
#endif /*CONFIG_ACPI_BOOT*/
#define PHYSID_ARRAY_SIZE BITS_TO_LONGS(MAX_APICS)
diff --git a/xen/include/asm-x86/msr.h b/xen/include/asm-x86/msr.h
index 3c1e8fb6ba..8b5ea950e1 100644
--- a/xen/include/asm-x86/msr.h
+++ b/xen/include/asm-x86/msr.h
@@ -88,7 +88,7 @@ static inline void wrmsrl(unsigned int msr, __u64 val)
/* Intel defined MSRs. */
#define MSR_IA32_P5_MC_ADDR 0
#define MSR_IA32_P5_MC_TYPE 1
-#define MSR_IA32_TIME_STAMP_COUNTER 0x10
+#define MSR_IA32_TIME_STAMP_COUNTER 0x10
#define MSR_IA32_PLATFORM_ID 0x17
#define MSR_IA32_EBL_CR_POWERON 0x2a
@@ -128,11 +128,13 @@ static inline void wrmsrl(unsigned int msr, __u64 val)
#define _EFER_LME 8 /* Long mode enable */
#define _EFER_LMA 10 /* Long mode active (read-only) */
#define _EFER_NX 11 /* No execute enable */
+#define _EFER_SVME 12
#define EFER_SCE (1<<_EFER_SCE)
#define EFER_LME (1<<_EFER_LME)
#define EFER_LMA (1<<_EFER_LMA)
#define EFER_NX (1<<_EFER_NX)
+#define EFER_SVME (1<<_EFER_SVME)
/* Intel MSRs. Some also available on other CPUs */
#define MSR_IA32_PLATFORM_ID 0x17
@@ -271,7 +273,6 @@ static inline void wrmsrl(unsigned int msr, __u64 val)
#define MSR_P4_U2L_ESCR0 0x3b0
#define MSR_P4_U2L_ESCR1 0x3b1
-/* AMD Defined MSRs */
#define MSR_K6_EFER 0xC0000080
#define MSR_K6_STAR 0xC0000081
#define MSR_K6_WHCR 0xC0000082
@@ -293,6 +294,11 @@ static inline void wrmsrl(unsigned int msr, __u64 val)
#define MSR_K7_FID_VID_CTL 0xC0010041
#define MSR_K7_FID_VID_STATUS 0xC0010042
+#define MSR_K8_TOP_MEM1 0xC001001A
+#define MSR_K8_TOP_MEM2 0xC001001D
+#define MSR_K8_VM_HSAVE_PA 0xC0010117
+#define MSR_K8_SYSCFG 0xC0000010
+
/* Centaur-Hauls/IDT defined MSRs. */
#define MSR_IDT_FCR1 0x107
#define MSR_IDT_FCR2 0x108
diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h
index 18748e3367..5ad42cd765 100644
--- a/xen/include/asm-x86/processor.h
+++ b/xen/include/asm-x86/processor.h
@@ -57,6 +57,7 @@
#define X86_CR0_MP 0x00000002 /* Monitor Coprocessor (RW) */
#define X86_CR0_EM 0x00000004 /* Require FPU Emulation (RO) */
#define X86_CR0_TS 0x00000008 /* Task Switched (RW) */
+#define X86_CR0_ET 0x00000010 /* Extension type (RO) */
#define X86_CR0_NE 0x00000020 /* Numeric Error Reporting (RW) */
#define X86_CR0_WP 0x00010000 /* Supervisor Write Protect (RW) */
#define X86_CR0_AM 0x00040000 /* Alignment Checking (RW) */
diff --git a/xen/include/asm-x86/regs.h b/xen/include/asm-x86/regs.h
index 5d99125d6c..dfa0868e44 100644
--- a/xen/include/asm-x86/regs.h
+++ b/xen/include/asm-x86/regs.h
@@ -33,10 +33,6 @@ enum EFLAGS {
#define GUEST_MODE(_r) (likely(VM86_MODE(_r) || !RING_0(_r)))
-#ifdef CONFIG_VMX
-#define GUEST_CONTEXT(_ed, _r) ( (VMX_DOMAIN(_ed) && ((_r)->eflags == 0)) || GUEST_MODE(_r) )
-#else
-#define GUEST_CONTEXT(_ed, _r) GUEST_MODE(_r)
-#endif
+#define GUEST_CONTEXT(_ed, _r) ((HVM_DOMAIN(_ed) && ((_r)->eflags == 0)) || GUEST_MODE(_r))
#endif /* __X86_REGS_H__ */
diff --git a/xen/include/asm-x86/shadow.h b/xen/include/asm-x86/shadow.h
index 2cab9fc69e..c7c9ce9b3b 100644
--- a/xen/include/asm-x86/shadow.h
+++ b/xen/include/asm-x86/shadow.h
@@ -31,7 +31,9 @@
#include <asm/current.h>
#include <asm/flushtlb.h>
#include <asm/processor.h>
-#include <asm/vmx.h>
+#include <asm/hvm/hvm.h>
+#include <asm/hvm/support.h>
+#include <asm/regs.h>
#include <public/dom0_ops.h>
#include <asm/shadow_public.h>
#include <asm/page-guest32.h>
@@ -168,8 +170,6 @@ static inline unsigned long __shadow_status(
static inline void update_hl2e(struct vcpu *v, unsigned long va);
#endif
-extern void vmx_shadow_clear_state(struct domain *);
-
static inline int page_is_page_table(struct pfn_info *page)
{
struct domain *owner = page_get_owner(page);
@@ -1707,21 +1707,18 @@ static inline void update_pagetables(struct vcpu *v)
struct domain *d = v->domain;
int paging_enabled;
-#ifdef CONFIG_VMX
- if ( VMX_DOMAIN(v) )
- paging_enabled = vmx_paging_enabled(v);
-
+ if ( HVM_DOMAIN(v) )
+ paging_enabled = hvm_paging_enabled(v);
else
-#endif
// HACK ALERT: there's currently no easy way to figure out if a domU
// has set its arch.guest_table to zero, vs not yet initialized it.
//
paging_enabled = !!pagetable_get_paddr(v->arch.guest_table);
/*
- * We don't call __update_pagetables() when vmx guest paging is
+ * We don't call __update_pagetables() when hvm guest paging is
* disabled as we want the linear_pg_table to be inaccessible so that
- * we bail out early of shadow_fault() if the vmx guest tries illegal
+ * we bail out early of shadow_fault() if the hvm guest tries illegal
* accesses while it thinks paging is turned off.
*/
if ( unlikely(shadow_mode_enabled(d)) && paging_enabled )
diff --git a/xen/include/asm-x86/vmx_intercept.h b/xen/include/asm-x86/vmx_intercept.h
deleted file mode 100644
index 11487ebe1b..0000000000
--- a/xen/include/asm-x86/vmx_intercept.h
+++ /dev/null
@@ -1,65 +0,0 @@
-#ifndef _VMX_INTERCEPT_H
-#define _VMX_INTERCEPT_H
-
-#include <xen/config.h>
-#include <xen/init.h>
-#include <xen/lib.h>
-#include <xen/time.h>
-#include <xen/errno.h>
-#include <public/hvm/ioreq.h>
-
-#define MAX_IO_HANDLER 8
-
-#define VMX_PORTIO 0
-#define VMX_MMIO 1
-
-typedef int (*intercept_action_t)(ioreq_t *);
-typedef unsigned long (*vmx_mmio_read_t)(struct vcpu *v,
- unsigned long addr,
- unsigned long length);
-
-typedef void (*vmx_mmio_write_t)(struct vcpu *v,
- unsigned long addr,
- unsigned long length,
- unsigned long val);
-
-typedef int (*vmx_mmio_check_t)(struct vcpu *v, unsigned long addr);
-
-struct io_handler {
- int type;
- unsigned long addr;
- unsigned long size;
- intercept_action_t action;
-};
-
-struct vmx_io_handler {
- int num_slot;
- struct io_handler hdl_list[MAX_IO_HANDLER];
-};
-
-struct vmx_mmio_handler {
- vmx_mmio_check_t check_handler;
- vmx_mmio_read_t read_handler;
- vmx_mmio_write_t write_handler;
-};
-
-/* global io interception point in HV */
-extern int vmx_io_intercept(ioreq_t *p, int type);
-extern int register_io_handler(unsigned long addr, unsigned long size,
- intercept_action_t action, int type);
-
-static inline int vmx_portio_intercept(ioreq_t *p)
-{
- return vmx_io_intercept(p, VMX_PORTIO);
-}
-
-int vmx_mmio_intercept(ioreq_t *p);
-
-static inline int register_portio_handler(unsigned long addr,
- unsigned long size,
- intercept_action_t action)
-{
- return register_io_handler(addr, size, action, VMX_PORTIO);
-}
-
-#endif /* _VMX_INTERCEPT_H */
diff --git a/xen/include/asm-x86/vmx_platform.h b/xen/include/asm-x86/vmx_platform.h
deleted file mode 100644
index 385f35d0c2..0000000000
--- a/xen/include/asm-x86/vmx_platform.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * vmx_platform.h: VMX platform support
- * Copyright (c) 2004, Intel 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 __ASM_X86_VMX_PLATFORM_H__
-#define __ASM_X86_VMX_PLATFORM_H__
-
-#include <public/xen.h>
-#include <asm/e820.h>
-#include <asm/vmx_vpit.h>
-#include <asm/vmx_intercept.h>
-#include <asm/vmx_vioapic.h>
-#include <asm/vmx_vpic.h>
-
-#define MAX_OPERAND_NUM 2
-
-#define mk_operand(size_reg, index, seg, flag) \
- (((size_reg) << 24) | ((index) << 16) | ((seg) << 8) | (flag))
-
-#define operand_size(operand) \
- ((operand >> 24) & 0xFF)
-
-#define operand_index(operand) \
- ((operand >> 16) & 0xFF)
-
-/* for instruction.operand[].size */
-#define BYTE 1
-#define WORD 2
-#define LONG 4
-#define QUAD 8
-#define BYTE_64 16
-
-/* for instruction.operand[].flag */
-#define REGISTER 0x1
-#define MEMORY 0x2
-#define IMMEDIATE 0x4
-
-/* for instruction.flags */
-#define REPZ 0x1
-#define REPNZ 0x2
-#define OVERLAP 0x4
-
-#define INSTR_PIO 1
-#define INSTR_OR 2
-#define INSTR_AND 3
-#define INSTR_XOR 4
-#define INSTR_CMP 5
-#define INSTR_MOV 6
-#define INSTR_MOVS 7
-#define INSTR_MOVZX 8
-#define INSTR_MOVSX 9
-#define INSTR_STOS 10
-#define INSTR_TEST 11
-#define INSTR_BT 12
-
-struct instruction {
- __s8 instr; /* instruction type */
- __s16 op_size; /* the operand's bit size, e.g. 16-bit or 32-bit */
- __u64 immediate;
- __u16 seg_sel; /* segmentation selector */
- __u32 operand[MAX_OPERAND_NUM]; /* order is AT&T assembly */
- __u32 flags;
-};
-
-#define MAX_INST_LEN 32
-
-struct vmx_platform {
- unsigned long shared_page_va;
- unsigned int nr_vcpus;
- unsigned int apic_enabled;
-
- struct vmx_virpit vmx_pit;
- struct vmx_io_handler vmx_io_handler;
- struct vmx_virpic vmx_pic;
- struct vmx_vioapic vmx_vioapic;
- unsigned char round_info[256];
- spinlock_t round_robin_lock;
- int interrupt_request;
-};
-
-extern void handle_mmio(unsigned long, unsigned long);
-extern void vmx_wait_io(void);
-extern void vmx_io_assist(struct vcpu *v);
-
-// XXX - think about this -- maybe use bit 30 of the mfn to signify an MMIO frame.
-#define mmio_space(gpa) (!VALID_MFN(get_mfn_from_pfn((gpa) >> PAGE_SHIFT)))
-
-#endif
diff --git a/xen/include/asm-x86/vmx_vpit.h b/xen/include/asm-x86/vmx_vpit.h
deleted file mode 100644
index b47e6d6512..0000000000
--- a/xen/include/asm-x86/vmx_vpit.h
+++ /dev/null
@@ -1,56 +0,0 @@
-#ifndef _VMX_VIRPIT_H
-#define _VMX_VIRPIT_H
-
-#include <xen/config.h>
-#include <xen/init.h>
-#include <xen/lib.h>
-#include <xen/time.h>
-#include <xen/errno.h>
-#include <xen/timer.h>
-#include <asm/vmx_vmcs.h>
-#include <asm/vmx_vpic.h>
-
-#define PIT_FREQ 1193181
-
-#define LSByte 0
-#define MSByte 1
-#define LSByte_multiple 2
-#define MSByte_multiple 3
-
-struct vmx_virpit {
- /* for simulation of counter 0 in mode 2*/
- u64 period_cycles; /* pit frequency in cpu cycles */
- u64 inject_point; /* the time inject virt intr */
- u64 shift; /* save the value of offset - drift */
- s_time_t scheduled; /* scheduled timer interrupt */
- struct timer pit_timer; /* periodic timer for mode 2*/
- unsigned int channel; /* the pit channel, counter 0~2 */
- unsigned int pending_intr_nr; /* the couner for pending timer interrupts */
- u32 period; /* pit frequency in ns */
- int first_injected; /* flag to prevent shadow window */
-
- /* virtual PIT state for handle related I/O */
- int read_state;
- int count_LSB_latched;
- int count_MSB_latched;
-
- unsigned int count; /* the 16 bit channel count */
- unsigned int init_val; /* the init value for the counter */
-};
-
-/* to hook the ioreq packet to get the PIT initializaiton info */
-extern void vmx_hooks_assist(struct vcpu *v);
-
-static __inline__ s_time_t get_pit_scheduled(
- struct vcpu *v,
- struct vmx_virpit *vpit)
-{
- if ( is_irq_enabled(v, 0) ) {
- return vpit->scheduled;
- }
- else
- return -1;
-}
-extern void set_tsc_shift(struct vcpu *v,struct vmx_virpit *vpit);
-
-#endif /* _VMX_VIRPIT_H_ */
diff --git a/xen/include/public/arch-x86_32.h b/xen/include/public/arch-x86_32.h
index c91dd10de8..baa175a5a0 100644
--- a/xen/include/public/arch-x86_32.h
+++ b/xen/include/public/arch-x86_32.h
@@ -114,7 +114,7 @@ typedef struct vcpu_guest_context {
/* FPU registers come first so they can be aligned for FXSAVE/FXRSTOR. */
struct { char x[512]; } fpu_ctxt; /* User-level FPU registers */
#define VGCF_I387_VALID (1<<0)
-#define VGCF_VMX_GUEST (1<<1)
+#define VGCF_HVM_GUEST (1<<1)
#define VGCF_IN_KERNEL (1<<2)
unsigned long flags; /* VGCF_* flags */
cpu_user_regs_t user_regs; /* User-level CPU registers */
diff --git a/xen/include/public/arch-x86_64.h b/xen/include/public/arch-x86_64.h
index 5036979e6a..d81a669cb4 100644
--- a/xen/include/public/arch-x86_64.h
+++ b/xen/include/public/arch-x86_64.h
@@ -196,7 +196,7 @@ typedef struct vcpu_guest_context {
/* FPU registers come first so they can be aligned for FXSAVE/FXRSTOR. */
struct { char x[512]; } fpu_ctxt; /* User-level FPU registers */
#define VGCF_I387_VALID (1<<0)
-#define VGCF_VMX_GUEST (1<<1)
+#define VGCF_HVM_GUEST (1<<1)
#define VGCF_IN_KERNEL (1<<2)
unsigned long flags; /* VGCF_* flags */
cpu_user_regs_t user_regs; /* User-level CPU registers */
diff --git a/xen/include/xen/domain_page.h b/xen/include/xen/domain_page.h
index b73011216b..b69547929e 100644
--- a/xen/include/xen/domain_page.h
+++ b/xen/include/xen/domain_page.h
@@ -48,6 +48,8 @@ domain_mmap_cache_init(struct domain_mmap_cache *cache)
{
ASSERT(cache != NULL);
cache->flags = 0;
+ cache->pfn = 0;
+ cache->va = NULL;
}
static inline void *