summaryrefslogtreecommitdiff
path: root/linux/x86
diff options
context:
space:
mode:
authorJosh Wilsdon <jwilsdon@joyent.com>2011-04-06 16:00:25 -0700
committerJosh Wilsdon <jwilsdon@joyent.com>2011-04-06 16:00:25 -0700
commit8ddb3439b2f21ccfb06e6d0b4a8a1fb0f944cf07 (patch)
tree0f6315b0729487ed1aaf08d1fac3b1b247f4a41f /linux/x86
parent4cfee15efd14f6dec47e679a3c29fe1718178095 (diff)
downloadillumos-kvm-8ddb3439b2f21ccfb06e6d0b4a8a1fb0f944cf07.tar.gz
[HVM-29] Add in Linux source from http://sourceforge.net/projects/kvm/files/kvm-kmod/2.6.34/kvm-kmod-2.6.34.tar.bz2/download (minus ia64 bits, powerpc bits and some scripts we definitely don't need)
Diffstat (limited to 'linux/x86')
-rw-r--r--linux/x86/Kbuild14
-rw-r--r--linux/x86/Makefile.pre1
-rw-r--r--linux/x86/debug.h23
-rw-r--r--linux/x86/external-module-compat.h756
-rw-r--r--linux/x86/preempt.c247
-rw-r--r--linux/x86/vmx-debug.c1117
6 files changed, 2158 insertions, 0 deletions
diff --git a/linux/x86/Kbuild b/linux/x86/Kbuild
new file mode 100644
index 0000000..fad05d5
--- /dev/null
+++ b/linux/x86/Kbuild
@@ -0,0 +1,14 @@
+obj-m := kvm.o kvm-intel.o kvm-amd.o
+kvm-objs := kvm_main.o x86.o mmu.o emulate.o ../anon_inodes.o irq.o i8259.o \
+ lapic.o ioapic.o preempt.o i8254.o coalesced_mmio.o irq_comm.o \
+ timer.o eventfd.o assigned-dev.o \
+ ../external-module-compat.o ../request-irq-compat.o
+ifeq ($(CONFIG_IOMMU_API),y)
+kvm-objs += iommu.o
+endif
+kvm-intel-objs := vmx.o vmx-debug.o
+kvm-amd-objs := svm.o
+
+kvm-objs += ../srcu.o
+
+CFLAGS_kvm_main.o = -DKVM_MAIN
diff --git a/linux/x86/Makefile.pre b/linux/x86/Makefile.pre
new file mode 100644
index 0000000..e38baf1
--- /dev/null
+++ b/linux/x86/Makefile.pre
@@ -0,0 +1 @@
+prerequisite:
diff --git a/linux/x86/debug.h b/linux/x86/debug.h
new file mode 100644
index 0000000..3579365
--- /dev/null
+++ b/linux/x86/debug.h
@@ -0,0 +1,23 @@
+#ifndef __KVM_DEBUG_H
+#define __KVM_DEBUG_H
+
+#ifdef KVM_DEBUG
+
+void show_msrs(struct kvm_vcpu *vcpu);
+
+
+void show_irq(struct kvm_vcpu *vcpu, int irq);
+void show_page(struct kvm_vcpu *vcpu, gva_t addr);
+void show_u64(struct kvm_vcpu *vcpu, gva_t addr);
+void show_code(struct kvm_vcpu *vcpu);
+int vm_entry_test(struct kvm_vcpu *vcpu);
+
+void vmcs_dump(struct kvm_vcpu *vcpu);
+void regs_dump(struct kvm_vcpu *vcpu);
+void sregs_dump(struct kvm_vcpu *vcpu);
+void show_pending_interrupts(struct kvm_vcpu *vcpu);
+void vcpu_dump(struct kvm_vcpu *vcpu);
+
+#endif
+
+#endif
diff --git a/linux/x86/external-module-compat.h b/linux/x86/external-module-compat.h
new file mode 100644
index 0000000..5626954
--- /dev/null
+++ b/linux/x86/external-module-compat.h
@@ -0,0 +1,756 @@
+
+/*
+ * Compatibility header for building as an external module.
+ */
+
+#include <linux/compiler.h>
+#include <linux/version.h>
+
+#include <linux/types.h>
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
+
+typedef u64 phys_addr_t;
+
+#endif
+
+#include "../external-module-compat-comm.h"
+
+#include <asm/msr.h>
+#include <asm/asm.h>
+
+#ifndef CONFIG_HAVE_KVM_EVENTFD
+#define CONFIG_HAVE_KVM_EVENTFD 1
+#endif
+
+#ifndef CONFIG_KVM_APIC_ARCHITECTURE
+#define CONFIG_KVM_APIC_ARCHITECTURE
+#endif
+
+#ifndef CONFIG_KVM_MMIO
+#define CONFIG_KVM_MMIO
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
+
+#ifdef CONFIG_X86_64
+#define DECLARE_ARGS(val, low, high) unsigned low, high
+#define EAX_EDX_VAL(val, low, high) ((low) | ((u64)(high) << 32))
+#define EAX_EDX_ARGS(val, low, high) "a" (low), "d" (high)
+#define EAX_EDX_RET(val, low, high) "=a" (low), "=d" (high)
+#else
+#define DECLARE_ARGS(val, low, high) unsigned long long val
+#define EAX_EDX_VAL(val, low, high) (val)
+#define EAX_EDX_ARGS(val, low, high) "A" (val)
+#define EAX_EDX_RET(val, low, high) "=A" (val)
+#endif
+
+#ifndef __ASM_EX_SEC
+# define __ASM_EX_SEC " .section __ex_table,\"a\"\n"
+#endif
+
+#ifndef _ASM_EXTABLE
+# define _ASM_EXTABLE(from,to) \
+ __ASM_EX_SEC \
+ _ASM_ALIGN "\n" \
+ _ASM_PTR #from "," #to "\n" \
+ " .previous\n"
+#endif
+
+#ifndef __ASM_SEL
+#ifdef CONFIG_X86_32
+# define __ASM_SEL(a,b) __ASM_FORM(a)
+#else
+# define __ASM_SEL(a,b) __ASM_FORM(b)
+#endif
+#endif
+
+#ifndef __ASM_FORM
+# define __ASM_FORM(x) " " #x " "
+#endif
+
+#ifndef _ASM_PTR
+#define _ASM_PTR __ASM_SEL(.long, .quad)
+#endif
+
+#ifndef _ASM_ALIGN
+#define _ASM_ALIGN __ASM_SEL(.balign 4, .balign 8)
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) || defined(CONFIG_X86_64)
+
+static inline unsigned long long native_read_msr_safe(unsigned int msr,
+ int *err)
+{
+ DECLARE_ARGS(val, low, high);
+
+ asm volatile("2: rdmsr ; xor %[err],%[err]\n"
+ "1:\n\t"
+ ".section .fixup,\"ax\"\n\t"
+ "3: mov %[fault],%[err] ; jmp 1b\n\t"
+ ".previous\n\t"
+ _ASM_EXTABLE(2b, 3b)
+ : [err] "=r" (*err), EAX_EDX_RET(val, low, high)
+ : "c" (msr), [fault] "i" (-EFAULT));
+ return EAX_EDX_VAL(val, low, high);
+}
+
+#endif
+
+static inline unsigned long long kvm_native_read_tsc(void)
+{
+ DECLARE_ARGS(val, low, high);
+
+ asm volatile("rdtsc" : EAX_EDX_RET(val, low, high));
+ return EAX_EDX_VAL(val, low, high);
+}
+
+#else /* >= 2.6.25 */
+
+#define kvm_native_read_tsc native_read_tsc
+
+#endif /* >= 2.6.25 */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26)
+
+static inline int rdmsrl_safe(unsigned msr, unsigned long long *p)
+{
+ int err;
+
+ *p = native_read_msr_safe(msr, &err);
+ return err;
+}
+
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22)
+
+#ifndef _EFER_SCE
+#define _EFER_SCE 0 /* SYSCALL/SYSRET */
+#endif
+
+#ifndef EFER_SCE
+#define EFER_SCE (1<<_EFER_SCE)
+#endif
+
+#endif
+
+#ifndef MSR_KERNEL_GS_BASE
+#define MSR_KERNEL_GS_BASE 0xc0000102
+#endif
+
+#ifndef MSR_TSC_AUX
+#define MSR_TSC_AUX 0xc0000103
+#endif
+
+#ifndef MSR_VM_CR
+#define MSR_VM_CR 0xc0010114
+#endif
+
+#ifndef MSR_VM_HSAVE_PA
+#define MSR_VM_HSAVE_PA 0xc0010117
+#endif
+
+#ifndef _EFER_SVME
+#define _EFER_SVME 12
+#define EFER_SVME (1<<_EFER_SVME)
+#endif
+
+#ifndef _EFER_FFXSR
+#define _EFER_FFXSR 14 /* Enable Fast FXSAVE/FXRSTOR */
+#define EFER_FFXSR (1<<_EFER_FFXSR)
+#endif
+
+#ifndef MSR_STAR
+#define MSR_STAR 0xc0000081
+#endif
+
+#ifndef MSR_K8_INT_PENDING_MSG
+#define MSR_K8_INT_PENDING_MSG 0xc0010055
+#endif
+
+#include <asm/cpufeature.h>
+
+#ifndef X86_FEATURE_SVM
+#define X86_FEATURE_SVM (6*32+ 2) /* Secure virtual machine */
+#endif
+
+#ifndef X86_FEATURE_FXSR_OPT
+#define X86_FEATURE_FXSR_OPT (1*32+25)
+#endif
+
+#ifndef X86_FEATURE_GBPAGES
+#define X86_FEATURE_GBPAGES (1*32+26) /* GB pages */
+#endif
+
+#ifndef X86_FEATURE_SSSE3
+#define X86_FEATURE_SSSE3 (4*32+ 9) /* Supplemental SSE-3 */
+#endif
+
+#ifndef X86_FEATURE_XMM4_1
+#define X86_FEATURE_XMM4_1 (4*32+19) /* "sse4_1" SSE-4.1 */
+#endif
+
+#ifndef X86_FEATURE_XMM4_2
+#define X86_FEATURE_XMM4_2 (4*32+20) /* "sse4_2" SSE-4.2 */
+#endif
+
+#ifndef X86_FEATURE_MOVBE
+#define X86_FEATURE_MOVBE (4*32+22) /* MOVBE instruction */
+#endif
+
+#ifndef X86_FEATURE_POPCNT
+#define X86_FEATURE_POPCNT (4*32+23) /* POPCNT instruction */
+#endif
+
+#ifndef X86_FEATURE_CR8_LEGACY
+#define X86_FEATURE_CR8_LEGACY (6*32+ 4) /* CR8 in 32-bit mode */
+#endif
+
+#ifndef X86_FEATURE_ABM
+#define X86_FEATURE_ABM (6*32+ 5) /* Advanced bit manipulation */
+#endif
+
+#ifndef X86_FEATURE_SSE4A
+#define X86_FEATURE_SSE4A (6*32+ 6) /* SSE-4A */
+#endif
+
+#ifndef X86_FEATURE_MISALIGNSSE
+#define X86_FEATURE_MISALIGNSSE (6*32+ 7) /* Misaligned SSE mode */
+#endif
+
+#ifndef X86_FEATURE_3DNOWPREFETCH
+#define X86_FEATURE_3DNOWPREFETCH (6*32+ 8) /* 3DNow prefetch instructions */
+#endif
+
+#ifndef X86_FEATURE_SSE5
+#define X86_FEATURE_SSE5 (6*32+11) /* SSE-5 */
+#endif
+
+#ifndef X86_FEATURE_X2APIC
+#define X86_FEATURE_X2APIC (4*32+21) /* x2APIC */
+#endif
+
+#ifndef MSR_AMD64_PATCH_LOADER
+#define MSR_AMD64_PATCH_LOADER 0xc0010020
+#endif
+
+#include <linux/smp.h>
+
+#ifndef X86_CR0_PE
+#define X86_CR0_PE 0x00000001
+#endif
+
+#ifndef X86_CR0_MP
+#define X86_CR0_MP 0x00000002
+#endif
+
+#ifndef X86_CR0_EM
+#define X86_CR0_EM 0x00000004
+#endif
+
+#ifndef X86_CR0_TS
+#define X86_CR0_TS 0x00000008
+#endif
+
+#ifndef X86_CR0_ET
+#define X86_CR0_ET 0x00000010
+#endif
+
+#ifndef X86_CR0_NE
+#define X86_CR0_NE 0x00000020
+#endif
+
+#ifndef X86_CR0_WP
+#define X86_CR0_WP 0x00010000
+#endif
+
+#ifndef X86_CR0_AM
+#define X86_CR0_AM 0x00040000
+#endif
+
+#ifndef X86_CR0_NW
+#define X86_CR0_NW 0x20000000
+#endif
+
+#ifndef X86_CR0_CD
+#define X86_CR0_CD 0x40000000
+#endif
+
+#ifndef X86_CR0_PG
+#define X86_CR0_PG 0x80000000
+#endif
+
+#ifndef X86_CR3_PWT
+#define X86_CR3_PWT 0x00000008
+#endif
+
+#ifndef X86_CR3_PCD
+#define X86_CR3_PCD 0x00000010
+#endif
+
+#ifndef X86_CR4_VMXE
+#define X86_CR4_VMXE 0x00002000
+#endif
+
+#undef X86_CR8_TPR
+#define X86_CR8_TPR 0x0f
+
+/*
+ * 2.6.22 does not define set_64bit() under nonpae
+ */
+#ifdef CONFIG_X86_32
+
+#include <asm/cmpxchg.h>
+
+static inline void __kvm_set_64bit(u64 *ptr, u64 val)
+{
+ unsigned int low = val;
+ unsigned int high = val >> 32;
+
+ __asm__ __volatile__ (
+ "\n1:\t"
+ "movl (%0), %%eax\n\t"
+ "movl 4(%0), %%edx\n\t"
+ "lock cmpxchg8b (%0)\n\t"
+ "jnz 1b"
+ : /* no outputs */
+ : "D"(ptr),
+ "b"(low),
+ "c"(high)
+ : "ax","dx","memory");
+}
+
+#undef set_64bit
+#define set_64bit __kvm_set_64bit
+
+static inline unsigned long long __kvm_cmpxchg64(volatile void *ptr,
+ unsigned long long old,
+ unsigned long long new)
+{
+ unsigned long long prev;
+ __asm__ __volatile__("lock cmpxchg8b %3"
+ : "=A"(prev)
+ : "b"((unsigned long)new),
+ "c"((unsigned long)(new >> 32)),
+ "m"(*__xg(ptr)),
+ "0"(old)
+ : "memory");
+ return prev;
+}
+
+#define kvm_cmpxchg64(ptr,o,n)\
+ ((__typeof__(*(ptr)))__kvm_cmpxchg64((ptr),(unsigned long long)(o),\
+ (unsigned long long)(n)))
+
+#undef cmpxchg64
+#define cmpxchg64(ptr, o, n) kvm_cmpxchg64(ptr, o, n)
+
+#endif
+
+#ifndef CONFIG_PREEMPT_NOTIFIERS
+
+#ifdef CONFIG_HAVE_HW_BREAKPOINT
+#error Preemption notifier emulation does not work for this kernel.
+#endif
+
+/*
+ * Include sched|preempt.h before defining CONFIG_PREEMPT_NOTIFIERS to avoid
+ * a miscompile.
+ */
+#include <linux/sched.h>
+#include <linux/preempt.h>
+#define CONFIG_PREEMPT_NOTIFIERS
+#define CONFIG_PREEMPT_NOTIFIERS_COMPAT
+
+struct preempt_notifier;
+
+struct preempt_ops {
+ void (*sched_in)(struct preempt_notifier *notifier, int cpu);
+ void (*sched_out)(struct preempt_notifier *notifier,
+ struct task_struct *next);
+};
+
+struct preempt_notifier {
+ struct list_head link;
+ struct task_struct *tsk;
+ struct preempt_ops *ops;
+};
+
+void preempt_notifier_register(struct preempt_notifier *notifier);
+void preempt_notifier_unregister(struct preempt_notifier *notifier);
+
+static inline void preempt_notifier_init(struct preempt_notifier *notifier,
+ struct preempt_ops *ops)
+{
+ notifier->ops = ops;
+}
+
+void start_special_insn(void);
+void end_special_insn(void);
+void in_special_section(void);
+
+void preempt_notifier_sys_init(void);
+void preempt_notifier_sys_exit(void);
+
+#else
+
+static inline void start_special_insn(void) {}
+static inline void end_special_insn(void) {}
+static inline void in_special_section(void) {}
+
+static inline void preempt_notifier_sys_init(void) {}
+static inline void preempt_notifier_sys_exit(void) {}
+
+#endif
+
+/* CONFIG_HAS_IOMEM is apparently fairly new too (2.6.21 for x86_64). */
+#ifndef CONFIG_HAS_IOMEM
+#define CONFIG_HAS_IOMEM 1
+#endif
+
+/* X86_FEATURE_NX is missing in some x86_64 kernels */
+
+#include <asm/cpufeature.h>
+
+#ifndef X86_FEATURE_NX
+#define X86_FEATURE_NX (1*32+20)
+#endif
+
+/* EFER_LMA and EFER_LME are missing in pre 2.6.24 i386 kernels */
+#ifndef EFER_LME
+#define _EFER_LME 8 /* Long mode enable */
+#define _EFER_LMA 10 /* Long mode active (read-only) */
+#define EFER_LME (1<<_EFER_LME)
+#define EFER_LMA (1<<_EFER_LMA)
+#endif
+
+struct kvm_desc_struct {
+ union {
+ struct { unsigned int a, b; };
+ struct {
+ u16 limit0;
+ u16 base0;
+ unsigned base1: 8, type: 4, s: 1, dpl: 2, p: 1;
+ unsigned limit: 4, avl: 1, l: 1, d: 1, g: 1, base2: 8;
+ };
+
+ };
+} __attribute__((packed));
+
+struct kvm_ldttss_desc64 {
+ u16 limit0;
+ u16 base0;
+ unsigned base1 : 8, type : 5, dpl : 2, p : 1;
+ unsigned limit1 : 4, zero0 : 3, g : 1, base2 : 8;
+ u32 base3;
+ u32 zero1;
+} __attribute__((packed));
+
+struct kvm_desc_ptr {
+ unsigned short size;
+ unsigned long address;
+} __attribute__((packed));
+
+static inline unsigned long
+kvm_get_desc_base(const struct kvm_desc_struct *desc)
+{
+ return desc->base0 | ((desc->base1) << 16) | ((desc->base2) << 24);
+}
+
+static inline void
+kvm_set_desc_base(struct kvm_desc_struct *desc, unsigned long base)
+{
+ desc->base0 = base & 0xffff;
+ desc->base1 = (base >> 16) & 0xff;
+ desc->base2 = (base >> 24) & 0xff;
+}
+
+static inline unsigned long
+kvm_get_desc_limit(const struct kvm_desc_struct *desc)
+{
+ return desc->limit0 | (desc->limit << 16);
+}
+
+static inline void
+kvm_set_desc_limit(struct kvm_desc_struct *desc, unsigned long limit)
+{
+ desc->limit0 = limit & 0xffff;
+ desc->limit = (limit >> 16) & 0xf;
+}
+
+static inline void kvm_native_store_gdt(struct kvm_desc_ptr *dtr)
+{
+ asm volatile("sgdt %0":"=m" (*dtr));
+}
+
+static inline void kvm_native_store_idt(struct kvm_desc_ptr *dtr)
+{
+ asm volatile("sidt %0":"=m" (*dtr));
+}
+
+#include <asm/msr.h>
+#ifndef MSR_FS_BASE
+#define MSR_FS_BASE 0xc0000100
+#endif
+#ifndef MSR_GS_BASE
+#define MSR_GS_BASE 0xc0000101
+#endif
+
+/* undefine lapic */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18)
+
+#undef lapic
+
+#endif
+
+#include <asm/hw_irq.h>
+#ifndef NMI_VECTOR
+#define NMI_VECTOR 2
+#endif
+
+#ifndef MSR_MTRRcap
+#define MSR_MTRRcap 0x0fe
+#define MSR_MTRRfix64K_00000 0x250
+#define MSR_MTRRfix16K_80000 0x258
+#define MSR_MTRRfix16K_A0000 0x259
+#define MSR_MTRRfix4K_C0000 0x268
+#define MSR_MTRRfix4K_C8000 0x269
+#define MSR_MTRRfix4K_D0000 0x26a
+#define MSR_MTRRfix4K_D8000 0x26b
+#define MSR_MTRRfix4K_E0000 0x26c
+#define MSR_MTRRfix4K_E8000 0x26d
+#define MSR_MTRRfix4K_F0000 0x26e
+#define MSR_MTRRfix4K_F8000 0x26f
+#define MSR_MTRRdefType 0x2ff
+#endif
+
+#ifndef MSR_IA32_CR_PAT
+#define MSR_IA32_CR_PAT 0x00000277
+#endif
+
+#ifndef MSR_VM_IGNNE
+#define MSR_VM_IGNNE 0xc0010115
+#endif
+
+/* Define DEBUGCTLMSR bits */
+#ifndef DEBUGCTLMSR_LBR
+
+#define _DEBUGCTLMSR_LBR 0 /* last branch recording */
+#define _DEBUGCTLMSR_BTF 1 /* single-step on branches */
+
+#define DEBUGCTLMSR_LBR (1UL << _DEBUGCTLMSR_LBR)
+#define DEBUGCTLMSR_BTF (1UL << _DEBUGCTLMSR_BTF)
+
+#endif
+
+#ifndef MSR_FAM10H_MMIO_CONF_BASE
+#define MSR_FAM10H_MMIO_CONF_BASE 0xc0010058
+#endif
+
+#ifndef MSR_AMD64_NB_CFG
+#define MSR_AMD64_NB_CFG 0xc001001f
+#endif
+
+#include <asm/asm.h>
+
+#ifndef __ASM_SIZE
+# define ____ASM_FORM(x) " " #x " "
+# ifdef CONFIG_X86_64
+# define __ASM_SIZE(inst) ____ASM_FORM(inst##q)
+# else
+# define __ASM_SIZE(inst) ____ASM_FORM(inst##l)
+# endif
+#endif
+
+#ifndef _ASM_PTR
+# ifdef CONFIG_X86_64
+# define _ASM_PTR ".quad"
+# else
+# define _ASM_PTR ".long"
+# endif
+#endif
+
+/* Intel VT MSRs */
+#ifndef MSR_IA32_VMX_BASIC
+#define MSR_IA32_VMX_BASIC 0x00000480
+#define MSR_IA32_VMX_PINBASED_CTLS 0x00000481
+#define MSR_IA32_VMX_PROCBASED_CTLS 0x00000482
+#define MSR_IA32_VMX_EXIT_CTLS 0x00000483
+#define MSR_IA32_VMX_ENTRY_CTLS 0x00000484
+#define MSR_IA32_VMX_MISC 0x00000485
+#define MSR_IA32_VMX_CR0_FIXED0 0x00000486
+#define MSR_IA32_VMX_CR0_FIXED1 0x00000487
+#define MSR_IA32_VMX_CR4_FIXED0 0x00000488
+#define MSR_IA32_VMX_CR4_FIXED1 0x00000489
+#define MSR_IA32_VMX_VMCS_ENUM 0x0000048a
+#define MSR_IA32_VMX_PROCBASED_CTLS2 0x0000048b
+#define MSR_IA32_VMX_EPT_VPID_CAP 0x0000048c
+#endif
+
+#ifndef MSR_IA32_FEATURE_CONTROL
+#define MSR_IA32_FEATURE_CONTROL 0x0000003a
+
+#define FEATURE_CONTROL_LOCKED (1<<0)
+#define FEATURE_CONTROL_VMXON_ENABLED (1<<2)
+#endif
+
+#ifndef MSR_IA32_TSC
+#define MSR_IA32_TSC 0x00000010
+#endif
+
+#ifndef MSR_K7_HWCR
+#define MSR_K7_HWCR 0xc0010015
+#endif
+
+#ifndef MSR_K8_SYSCFG
+#define MSR_K8_SYSCFG 0xc0010010
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25) && defined(__x86_64__)
+
+#undef set_debugreg
+#define set_debugreg(value, register) \
+ __asm__("movq %0,%%db" #register \
+ : /* no output */ \
+ :"r" ((unsigned long)value))
+
+#endif
+
+#if !defined(CONFIG_X86_64) && LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
+#define kvm_compat_debugreg(x) debugreg[x]
+#else
+#define kvm_compat_debugreg(x) debugreg##x
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
+
+struct mtrr_var_range {
+ u32 base_lo;
+ u32 base_hi;
+ u32 mask_lo;
+ u32 mask_hi;
+};
+
+/* In the Intel processor's MTRR interface, the MTRR type is always held in
+ an 8 bit field: */
+typedef u8 mtrr_type;
+
+#define MTRR_NUM_FIXED_RANGES 88
+#define MTRR_MAX_VAR_RANGES 256
+
+struct mtrr_state_type {
+ struct mtrr_var_range var_ranges[MTRR_MAX_VAR_RANGES];
+ mtrr_type fixed_ranges[MTRR_NUM_FIXED_RANGES];
+ unsigned char enabled;
+ unsigned char have_fixed;
+ mtrr_type def_type;
+};
+
+#endif
+
+#ifndef CONFIG_HAVE_KVM_IRQCHIP
+#define CONFIG_HAVE_KVM_IRQCHIP 1
+#endif
+
+#include <asm/mce.h>
+
+#ifndef MCG_CTL_P
+#define MCG_CTL_P (1ULL<<8)
+#define MCG_STATUS_MCIP (1ULL<<2)
+#define MCI_STATUS_VAL (1ULL<<63)
+#define MCI_STATUS_OVER (1ULL<<62)
+#define MCI_STATUS_UC (1ULL<<61)
+#endif
+
+/* do_machine_check() exported in 2.6.31 */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,31)
+
+static inline void kvm_do_machine_check(struct pt_regs *regs, long error_code)
+{
+ panic("kvm machine check!\n");
+}
+
+#else
+
+#define kvm_do_machine_check do_machine_check
+
+#endif
+
+/* pt_regs.flags was once pt_regs.eflags */
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,25)
+
+#define kvm_pt_regs_flags eflags
+
+# ifdef CONFIG_X86_64
+# define kvm_pt_regs_cs cs
+# else
+# define kvm_pt_regs_cs xcs
+# endif
+
+#else
+
+#define kvm_pt_regs_flags flags
+#define kvm_pt_regs_cs cs
+
+#endif
+
+/* boot_cpu_data.x86_phys_bits only appeared for i386 in 2.6.30 */
+
+#if !defined(CONFIG_X86_64) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,30))
+
+#define kvm_x86_phys_bits 40
+
+#else
+
+#define kvm_x86_phys_bits (boot_cpu_data.x86_phys_bits)
+
+#endif
+
+#include <asm/apicdef.h>
+
+#ifndef APIC_BASE_MSR
+#define APIC_BASE_MSR 0x800
+#endif
+
+#ifndef APIC_SPIV_DIRECTED_EOI
+#define APIC_SPIV_DIRECTED_EOI (1 << 12)
+#endif
+
+#ifndef APIC_LVR_DIRECTED_EOI
+#define APIC_LVR_DIRECTED_EOI (1 << 24)
+#endif
+
+#ifndef APIC_SELF_IPI
+#define APIC_SELF_IPI 0x3F0
+#endif
+
+#ifndef X2APIC_ENABLE
+#define X2APIC_ENABLE (1UL << 10)
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
+
+static inline int hw_breakpoint_active(void)
+{
+ return test_thread_flag(TIF_DEBUG);
+}
+
+static inline void hw_breakpoint_restore(void)
+{
+ set_debugreg(current->thread.kvm_compat_debugreg(0), 0);
+ set_debugreg(current->thread.kvm_compat_debugreg(1), 1);
+ set_debugreg(current->thread.kvm_compat_debugreg(2), 2);
+ set_debugreg(current->thread.kvm_compat_debugreg(3), 3);
+ set_debugreg(current->thread.kvm_compat_debugreg(6), 6);
+ set_debugreg(current->thread.kvm_compat_debugreg(7), 7);
+}
+
+#endif
+
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,24) && defined(CONFIG_X86_64)
+#define kvm_check_tsc_unstable() 1
+#else
+#define kvm_check_tsc_unstable check_tsc_unstable
+#endif
diff --git a/linux/x86/preempt.c b/linux/x86/preempt.c
new file mode 100644
index 0000000..440060b
--- /dev/null
+++ b/linux/x86/preempt.c
@@ -0,0 +1,247 @@
+
+#ifdef CONFIG_PREEMPT_NOTIFIERS_COMPAT
+
+#include <linux/sched.h>
+#include <linux/percpu.h>
+
+static DEFINE_SPINLOCK(pn_lock);
+static LIST_HEAD(pn_list);
+
+#define dprintk(fmt) do { \
+ if (0) \
+ printk("%s (%d/%d): " fmt, __FUNCTION__, \
+ current->pid, raw_smp_processor_id()); \
+ } while (0)
+
+static void preempt_enable_sched_out_notifiers(void)
+{
+ asm volatile ("mov %0, %%db0" : : "r"(schedule));
+ asm volatile ("mov %0, %%db7" : : "r"(0x701ul));
+ current->thread.kvm_compat_debugreg(7) = 0ul;
+#ifdef TIF_DEBUG
+ clear_tsk_thread_flag(current, TIF_DEBUG);
+#endif
+}
+
+static void preempt_enable_sched_in_notifiers(void * addr)
+{
+ asm volatile ("mov %0, %%db0" : : "r"(addr));
+ asm volatile ("mov %0, %%db7" : : "r"(0x701ul));
+ current->thread.kvm_compat_debugreg(0) = (unsigned long) addr;
+ current->thread.kvm_compat_debugreg(7) = 0x701ul;
+#ifdef TIF_DEBUG
+ set_tsk_thread_flag(current, TIF_DEBUG);
+#endif
+}
+
+static void __preempt_disable_notifiers(void)
+{
+ asm volatile ("mov %0, %%db7" : : "r"(0ul));
+}
+
+static void preempt_disable_notifiers(void)
+{
+ __preempt_disable_notifiers();
+ current->thread.kvm_compat_debugreg(7) = 0ul;
+#ifdef TIF_DEBUG
+ clear_tsk_thread_flag(current, TIF_DEBUG);
+#endif
+}
+
+static void fastcall __attribute__((used)) preempt_notifier_trigger(void *** ip)
+{
+ struct preempt_notifier *pn;
+ int cpu = raw_smp_processor_id();
+ int found = 0;
+
+ dprintk(" - in\n");
+ //dump_stack();
+ spin_lock(&pn_lock);
+ list_for_each_entry(pn, &pn_list, link)
+ if (pn->tsk == current) {
+ found = 1;
+ break;
+ }
+ spin_unlock(&pn_lock);
+
+ if (found) {
+ if ((void *) *ip != schedule) {
+ dprintk("sched_in\n");
+ preempt_enable_sched_out_notifiers();
+
+ preempt_disable();
+ local_irq_enable();
+ pn->ops->sched_in(pn, cpu);
+ local_irq_disable();
+ preempt_enable_no_resched();
+ } else {
+ void * sched_in_addr;
+ dprintk("sched_out\n");
+#ifdef CONFIG_X86_64
+ sched_in_addr = **(ip+3);
+#else
+ /* no special debug stack switch on x86 */
+ sched_in_addr = (void *) *(ip+3);
+#endif
+ preempt_enable_sched_in_notifiers(sched_in_addr);
+
+ preempt_disable();
+ local_irq_enable();
+ pn->ops->sched_out(pn, NULL);
+ local_irq_disable();
+ preempt_enable_no_resched();
+ }
+ } else
+ __preempt_disable_notifiers();
+ dprintk(" - out\n");
+}
+
+unsigned long orig_int1_handler;
+
+#ifdef CONFIG_X86_64
+
+#define SAVE_REGS \
+ "push %rax; push %rbx; push %rcx; push %rdx; " \
+ "push %rsi; push %rdi; push %rbp; " \
+ "push %r8; push %r9; push %r10; push %r11; " \
+ "push %r12; push %r13; push %r14; push %r15"
+
+#define RESTORE_REGS \
+ "pop %r15; pop %r14; pop %r13; pop %r12; " \
+ "pop %r11; pop %r10; pop %r9; pop %r8; " \
+ "pop %rbp; pop %rdi; pop %rsi; " \
+ "pop %rdx; pop %rcx; pop %rbx; pop %rax "
+
+#define TMP "%rax"
+
+#else
+
+#define SAVE_REGS "pusha"
+#define RESTORE_REGS "popa"
+#define TMP "%eax"
+
+#endif
+
+asm ("pn_int1_handler: \n\t"
+ "push " TMP " \n\t"
+ "mov %db7, " TMP " \n\t"
+ "cmp $0x701, " TMP " \n\t"
+ "pop " TMP " \n\t"
+ "jnz .Lnotme \n\t"
+ "push " TMP " \n\t"
+ "mov %db6, " TMP " \n\t"
+ "test $0x1, " TMP " \n\t"
+ "pop " TMP " \n\t"
+ "jz .Lnotme \n\t"
+ SAVE_REGS "\n\t"
+#ifdef CONFIG_X86_64
+ "leaq 120(%rsp),%rdi\n\t"
+#else
+ "leal 32(%esp),%eax\n\t"
+#endif
+ "call preempt_notifier_trigger \n\t"
+ RESTORE_REGS "\n\t"
+#ifdef CONFIG_X86_64
+ "orq $0x10000, 16(%rsp) \n\t"
+ "iretq \n\t"
+#else
+ "orl $0x10000, 8(%esp) \n\t"
+ "iret \n\t"
+#endif
+ ".Lnotme: \n\t"
+#ifdef CONFIG_X86_64
+ "jmpq *orig_int1_handler\n\t"
+#else
+ "jmpl *orig_int1_handler\n\t"
+#endif
+ );
+
+void preempt_notifier_register(struct preempt_notifier *notifier)
+{
+ unsigned long flags;
+
+ dprintk(" - in\n");
+ spin_lock_irqsave(&pn_lock, flags);
+ preempt_enable_sched_out_notifiers();
+ notifier->tsk = current;
+ list_add(&notifier->link, &pn_list);
+ spin_unlock_irqrestore(&pn_lock, flags);
+ dprintk(" - out\n");
+}
+
+void preempt_notifier_unregister(struct preempt_notifier *notifier)
+{
+ unsigned long flags;
+
+ dprintk(" - in\n");
+ spin_lock_irqsave(&pn_lock, flags);
+ list_del(&notifier->link);
+ spin_unlock_irqrestore(&pn_lock, flags);
+ preempt_disable_notifiers();
+ dprintk(" - out\n");
+}
+
+struct intr_gate {
+ u16 offset0;
+ u16 segment;
+ u16 junk;
+ u16 offset1;
+#ifdef CONFIG_X86_64
+ u32 offset2;
+ u32 blah;
+#endif
+} __attribute__((packed));
+
+struct idt_desc {
+ u16 limit;
+ struct intr_gate *gates;
+} __attribute__((packed));
+
+static struct intr_gate orig_int1_gate;
+
+void pn_int1_handler(void);
+
+void preempt_notifier_sys_init(void)
+{
+ struct idt_desc idt_desc;
+ struct intr_gate *int1_gate;
+
+ printk("kvm: emulating preempt notifiers;"
+ " do not benchmark on this machine\n");
+ dprintk("\n");
+ asm ("sidt %0" : "=m"(idt_desc));
+ int1_gate = &idt_desc.gates[1];
+ orig_int1_gate = *int1_gate;
+ orig_int1_handler = int1_gate->offset0
+ | ((u32)int1_gate->offset1 << 16);
+#ifdef CONFIG_X86_64
+ orig_int1_handler |= (u64)int1_gate->offset2 << 32;
+#endif
+ int1_gate->offset0 = (unsigned long)pn_int1_handler;
+ int1_gate->offset1 = (unsigned long)pn_int1_handler >> 16;
+#ifdef CONFIG_X86_64
+ int1_gate->offset2 = (unsigned long)pn_int1_handler >> 32;
+#endif
+}
+
+static void do_disable(void *blah)
+{
+#ifdef TIF_DEBUG
+ if (!test_tsk_thread_flag(current, TIF_DEBUG))
+#else
+ if (!current->thread.kvm_compat_debugreg(7))
+#endif
+ __preempt_disable_notifiers();
+}
+
+void preempt_notifier_sys_exit(void)
+{
+ struct idt_desc idt_desc;
+
+ dprintk("\n");
+ kvm_on_each_cpu(do_disable, NULL, 1);
+ asm ("sidt %0" : "=m"(idt_desc));
+ idt_desc.gates[1] = orig_int1_gate;
+}
+
+#endif
diff --git a/linux/x86/vmx-debug.c b/linux/x86/vmx-debug.c
new file mode 100644
index 0000000..1549b39
--- /dev/null
+++ b/linux/x86/vmx-debug.c
@@ -0,0 +1,1117 @@
+/*
+ * Kernel-based Virtual Machine driver for Linux
+ *
+ * This module enables machines with Intel VT-x extensions to run virtual
+ * machines without emulation or binary translation.
+ *
+ * Debug support
+ *
+ * Copyright (C) 2006 Qumranet, Inc.
+ *
+ * Authors:
+ * Yaniv Kamay <yaniv@qumranet.com>
+ * Avi Kivity <avi@qumranet.com>
+ *
+ */
+
+#include <linux/highmem.h>
+
+#include <linux/kvm_host.h>
+#include <asm/vmx.h>
+#include <asm/kvm_host.h>
+#include "mmu.h"
+#include "lapic.h"
+#include "debug.h"
+
+#include "x86.h"
+
+#ifdef KVM_DEBUG
+
+static unsigned long vmcs_readl(unsigned long field)
+{
+ unsigned long value;
+
+ asm volatile (ASM_VMX_VMREAD_RDX_RAX
+ : "=a"(value) : "d"(field) : "cc");
+ return value;
+}
+
+static u16 vmcs_read16(unsigned long field)
+{
+ return vmcs_readl(field);
+}
+
+static u32 vmcs_read32(unsigned long field)
+{
+ return vmcs_readl(field);
+}
+
+static u64 vmcs_read64(unsigned long field)
+{
+#ifdef CONFIG_X86_64
+ return vmcs_readl(field);
+#else
+ return vmcs_readl(field) | ((u64)vmcs_readl(field+1) << 32);
+#endif
+}
+
+void show_code(struct kvm_vcpu *vcpu)
+{
+ gva_t rip = vmcs_readl(GUEST_RIP);
+ u8 code[50];
+ char buf[30 + 3 * sizeof code];
+ int i;
+ gpa_t gpa;
+
+ if (!is_long_mode(vcpu))
+ rip += vmcs_readl(GUEST_CS_BASE);
+
+ gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, rip, 0, NULL);
+ if (gpa == UNMAPPED_GVA)
+ return;
+ kvm_read_guest(vcpu->kvm, gpa, code, sizeof code);
+ for (i = 0; i < sizeof code; ++i)
+ sprintf(buf + i * 3, " %02x", code[i]);
+ vcpu_printf(vcpu, "code: %lx%s\n", rip, buf);
+}
+
+struct gate_struct {
+ u16 offset_low;
+ u16 segment;
+ unsigned ist : 3, zero0 : 5, type : 5, dpl : 2, p : 1;
+ u16 offset_middle;
+ u32 offset_high;
+ u32 zero1;
+} __attribute__((packed));
+
+void show_irq(struct kvm_vcpu *vcpu, int irq)
+{
+ unsigned long idt_base = vmcs_readl(GUEST_IDTR_BASE);
+ unsigned long idt_limit = vmcs_readl(GUEST_IDTR_LIMIT);
+ struct gate_struct gate;
+ gpa_t gpa;
+
+ if (!is_long_mode(vcpu))
+ vcpu_printf(vcpu, "%s: not in long mode\n", __FUNCTION__);
+
+ if (!is_long_mode(vcpu) || idt_limit < irq * sizeof(gate)) {
+ vcpu_printf(vcpu, "%s: 0x%x read_guest err\n",
+ __FUNCTION__,
+ irq);
+ return;
+ }
+
+ gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, idt_base + irq * sizeof(gate),
+ 0, NULL);
+ if (gpa == UNMAPPED_GVA)
+ return;
+
+ if (kvm_read_guest(vcpu->kvm, gpa, &gate, sizeof(gate)) != sizeof(gate)) {
+ vcpu_printf(vcpu, "%s: 0x%x read_guest err\n",
+ __FUNCTION__,
+ irq);
+ return;
+ }
+ vcpu_printf(vcpu, "%s: 0x%x handler 0x%llx\n",
+ __FUNCTION__,
+ irq,
+ ((u64)gate.offset_high << 32) |
+ ((u64)gate.offset_middle << 16) |
+ gate.offset_low);
+}
+
+void show_page(struct kvm_vcpu *vcpu,
+ gva_t addr)
+{
+ u64 *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ gpa_t gpa;
+
+ if (!buf)
+ return;
+
+ addr &= PAGE_MASK;
+ gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr, 0, NULL);
+ if (gpa == UNMAPPED_GVA)
+ return;
+ if (kvm_read_guest(vcpu->kvm, gpa, buf, PAGE_SIZE)) {
+ int i;
+ for (i = 0; i < PAGE_SIZE / sizeof(u64) ; i++) {
+ u8 *ptr = (u8*)&buf[i];
+ int j;
+ vcpu_printf(vcpu, " 0x%16.16lx:",
+ addr + i * sizeof(u64));
+ for (j = 0; j < sizeof(u64) ; j++)
+ vcpu_printf(vcpu, " 0x%2.2x", ptr[j]);
+ vcpu_printf(vcpu, "\n");
+ }
+ }
+ kfree(buf);
+}
+
+void show_u64(struct kvm_vcpu *vcpu, gva_t addr)
+{
+ u64 buf;
+ gpa_t gpa;
+
+ gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr, 0, NULL);
+ if (gpa == UNMAPPED_GVA)
+ return;
+ if (kvm_read_guest(vcpu->kvm, gpa, &buf, sizeof(u64)) == sizeof(u64)) {
+ u8 *ptr = (u8*)&buf;
+ int j;
+ vcpu_printf(vcpu, " 0x%16.16lx:", addr);
+ for (j = 0; j < sizeof(u64) ; j++)
+ vcpu_printf(vcpu, " 0x%2.2x", ptr[j]);
+ vcpu_printf(vcpu, "\n");
+ }
+}
+
+#define IA32_DEBUGCTL_RESERVED_BITS 0xfffffffffffffe3cULL
+
+static int is_canonical(unsigned long addr)
+{
+ return addr == ((long)addr << 16) >> 16;
+}
+
+int vm_entry_test_guest(struct kvm_vcpu *vcpu)
+{
+ unsigned long cr0;
+ unsigned long cr4;
+ unsigned long cr3;
+ unsigned long dr7;
+ u64 ia32_debugctl;
+ unsigned long sysenter_esp;
+ unsigned long sysenter_eip;
+ unsigned long rflags;
+ unsigned long cpu_exec_ctrl, cpu_secondary_exec_ctrl;
+ unsigned long tpr_threshold;
+
+ int long_mode;
+ int virtual8086;
+
+ #define RFLAGS_VM (1 << 17)
+ #define RFLAGS_RF (1 << 9)
+
+
+ #define VIR8086_SEG_BASE_TEST(seg)\
+ if (vmcs_readl(GUEST_##seg##_BASE) != \
+ (unsigned long)vmcs_read16(GUEST_##seg##_SELECTOR) << 4) {\
+ vcpu_printf(vcpu, "%s: "#seg" base 0x%lx in "\
+ "virtual8086 is not "#seg" selector 0x%x"\
+ " shifted right 4 bits\n",\
+ __FUNCTION__,\
+ vmcs_readl(GUEST_##seg##_BASE),\
+ vmcs_read16(GUEST_##seg##_SELECTOR));\
+ return 0;\
+ }
+
+ #define VIR8086_SEG_LIMIT_TEST(seg)\
+ if (vmcs_readl(GUEST_##seg##_LIMIT) != 0x0ffff) { \
+ vcpu_printf(vcpu, "%s: "#seg" limit 0x%lx in "\
+ "virtual8086 is not 0xffff\n",\
+ __FUNCTION__,\
+ vmcs_readl(GUEST_##seg##_LIMIT));\
+ return 0;\
+ }
+
+ #define VIR8086_SEG_AR_TEST(seg)\
+ if (vmcs_read32(GUEST_##seg##_AR_BYTES) != 0x0f3) { \
+ vcpu_printf(vcpu, "%s: "#seg" AR 0x%x in "\
+ "virtual8086 is not 0xf3\n",\
+ __FUNCTION__,\
+ vmcs_read32(GUEST_##seg##_AR_BYTES));\
+ return 0;\
+ }
+
+
+ cr0 = vmcs_readl(GUEST_CR0);
+
+ if (!(cr0 & X86_CR0_PG)) {
+ vcpu_printf(vcpu, "%s: cr0 0x%lx, PG is not set\n",
+ __FUNCTION__, cr0);
+ return 0;
+ }
+
+ if (!(cr0 & X86_CR0_PE)) {
+ vcpu_printf(vcpu, "%s: cr0 0x%lx, PE is not set\n",
+ __FUNCTION__, cr0);
+ return 0;
+ }
+
+ if (!(cr0 & X86_CR0_NE)) {
+ vcpu_printf(vcpu, "%s: cr0 0x%lx, NE is not set\n",
+ __FUNCTION__, cr0);
+ return 0;
+ }
+
+ if (!(cr0 & X86_CR0_WP)) {
+ vcpu_printf(vcpu, "%s: cr0 0x%lx, WP is not set\n",
+ __FUNCTION__, cr0);
+ }
+
+ cr4 = vmcs_readl(GUEST_CR4);
+
+ if (!(cr4 & X86_CR4_VMXE)) {
+ vcpu_printf(vcpu, "%s: cr4 0x%lx, VMXE is not set\n",
+ __FUNCTION__, cr4);
+ return 0;
+ }
+
+ if (!(cr4 & X86_CR4_PAE)) {
+ vcpu_printf(vcpu, "%s: cr4 0x%lx, PAE is not set\n",
+ __FUNCTION__, cr4);
+ }
+
+ ia32_debugctl = vmcs_read64(GUEST_IA32_DEBUGCTL);
+
+ if (ia32_debugctl & IA32_DEBUGCTL_RESERVED_BITS ) {
+ vcpu_printf(vcpu, "%s: ia32_debugctl 0x%llx, reserve bits\n",
+ __FUNCTION__, ia32_debugctl);
+ return 0;
+ }
+
+ long_mode = is_long_mode(vcpu);
+
+ if (long_mode) {
+ }
+
+ if ( long_mode && !(cr4 & X86_CR4_PAE)) {
+ vcpu_printf(vcpu, "%s: long mode and not PAE\n",
+ __FUNCTION__);
+ return 0;
+ }
+
+ cr3 = vmcs_readl(GUEST_CR3);
+
+ if (cr3 & CR3_L_MODE_RESERVED_BITS) {
+ vcpu_printf(vcpu, "%s: cr3 0x%lx, reserved bits\n",
+ __FUNCTION__, cr3);
+ return 0;
+ }
+
+ if ( !long_mode && (cr4 & X86_CR4_PAE)) {
+ /* check the 4 PDPTEs for reserved bits */
+ unsigned long pdpt_pfn = cr3 >> PAGE_SHIFT;
+ int i;
+ u64 pdpte;
+ unsigned offset = (cr3 & (PAGE_SIZE-1)) >> 5;
+ u64 *pdpt = kmap_atomic(pfn_to_page(pdpt_pfn), KM_USER0);
+
+ for (i = 0; i < 4; ++i) {
+ pdpte = pdpt[offset + i];
+ if ((pdpte & 1) && (pdpte & 0xfffffff0000001e6ull))
+ break;
+ }
+
+ kunmap_atomic(pdpt, KM_USER0);
+
+ if (i != 4) {
+ vcpu_printf(vcpu, "%s: pae cr3[%d] 0x%llx, reserved bits\n",
+ __FUNCTION__, i, pdpte);
+ return 0;
+ }
+ }
+
+ dr7 = vmcs_readl(GUEST_DR7);
+
+ if (dr7 & ~((1ULL << 32) - 1)) {
+ vcpu_printf(vcpu, "%s: dr7 0x%lx, reserved bits\n",
+ __FUNCTION__, dr7);
+ return 0;
+ }
+
+ sysenter_esp = vmcs_readl(GUEST_SYSENTER_ESP);
+
+ if (!is_canonical(sysenter_esp)) {
+ vcpu_printf(vcpu, "%s: sysenter_esp 0x%lx, not canonical\n",
+ __FUNCTION__, sysenter_esp);
+ return 0;
+ }
+
+ sysenter_eip = vmcs_readl(GUEST_SYSENTER_EIP);
+
+ if (!is_canonical(sysenter_eip)) {
+ vcpu_printf(vcpu, "%s: sysenter_eip 0x%lx, not canonical\n",
+ __FUNCTION__, sysenter_eip);
+ return 0;
+ }
+
+ rflags = vmcs_readl(GUEST_RFLAGS);
+ virtual8086 = rflags & RFLAGS_VM;
+
+
+ if (vmcs_read16(GUEST_TR_SELECTOR) & SELECTOR_TI_MASK) {
+ vcpu_printf(vcpu, "%s: tr selctor 0x%x, TI is set\n",
+ __FUNCTION__, vmcs_read16(GUEST_TR_SELECTOR));
+ return 0;
+ }
+
+ if (!(vmcs_read32(GUEST_LDTR_AR_BYTES) & AR_UNUSABLE_MASK) &&
+ vmcs_read16(GUEST_LDTR_SELECTOR) & SELECTOR_TI_MASK) {
+ vcpu_printf(vcpu, "%s: ldtr selctor 0x%x,"
+ " is usable and TI is set\n",
+ __FUNCTION__, vmcs_read16(GUEST_LDTR_SELECTOR));
+ return 0;
+ }
+
+ if (!virtual8086 &&
+ (vmcs_read16(GUEST_SS_SELECTOR) & SELECTOR_RPL_MASK) !=
+ (vmcs_read16(GUEST_CS_SELECTOR) & SELECTOR_RPL_MASK)) {
+ vcpu_printf(vcpu, "%s: ss selctor 0x%x cs selctor 0x%x,"
+ " not same RPL\n",
+ __FUNCTION__,
+ vmcs_read16(GUEST_SS_SELECTOR),
+ vmcs_read16(GUEST_CS_SELECTOR));
+ return 0;
+ }
+
+ if (virtual8086) {
+ VIR8086_SEG_BASE_TEST(CS);
+ VIR8086_SEG_BASE_TEST(SS);
+ VIR8086_SEG_BASE_TEST(DS);
+ VIR8086_SEG_BASE_TEST(ES);
+ VIR8086_SEG_BASE_TEST(FS);
+ VIR8086_SEG_BASE_TEST(GS);
+ }
+
+ if (!is_canonical(vmcs_readl(GUEST_TR_BASE)) ||
+ !is_canonical(vmcs_readl(GUEST_FS_BASE)) ||
+ !is_canonical(vmcs_readl(GUEST_GS_BASE)) ) {
+ vcpu_printf(vcpu, "%s: TR 0x%lx FS 0x%lx or GS 0x%lx base"
+ " is not canonical\n",
+ __FUNCTION__,
+ vmcs_readl(GUEST_TR_BASE),
+ vmcs_readl(GUEST_FS_BASE),
+ vmcs_readl(GUEST_GS_BASE));
+ return 0;
+
+ }
+
+ if (!(vmcs_read32(GUEST_LDTR_AR_BYTES) & AR_UNUSABLE_MASK) &&
+ !is_canonical(vmcs_readl(GUEST_LDTR_BASE))) {
+ vcpu_printf(vcpu, "%s: LDTR base 0x%lx, usable and is not"
+ " canonical\n",
+ __FUNCTION__,
+ vmcs_readl(GUEST_LDTR_BASE));
+ return 0;
+ }
+
+ if ((vmcs_readl(GUEST_CS_BASE) & ~((1ULL << 32) - 1))) {
+ vcpu_printf(vcpu, "%s: CS base 0x%lx, not all bits 63-32"
+ " are zero\n",
+ __FUNCTION__,
+ vmcs_readl(GUEST_CS_BASE));
+ return 0;
+ }
+
+ #define SEG_BASE_TEST(seg)\
+ if ( !(vmcs_read32(GUEST_##seg##_AR_BYTES) & AR_UNUSABLE_MASK) &&\
+ (vmcs_readl(GUEST_##seg##_BASE) & ~((1ULL << 32) - 1))) {\
+ vcpu_printf(vcpu, "%s: "#seg" base 0x%lx, is usable and not"\
+ " all bits 63-32 are zero\n",\
+ __FUNCTION__,\
+ vmcs_readl(GUEST_##seg##_BASE));\
+ return 0;\
+ }
+ SEG_BASE_TEST(SS);
+ SEG_BASE_TEST(DS);
+ SEG_BASE_TEST(ES);
+
+ if (virtual8086) {
+ VIR8086_SEG_LIMIT_TEST(CS);
+ VIR8086_SEG_LIMIT_TEST(SS);
+ VIR8086_SEG_LIMIT_TEST(DS);
+ VIR8086_SEG_LIMIT_TEST(ES);
+ VIR8086_SEG_LIMIT_TEST(FS);
+ VIR8086_SEG_LIMIT_TEST(GS);
+ }
+
+ if (virtual8086) {
+ VIR8086_SEG_AR_TEST(CS);
+ VIR8086_SEG_AR_TEST(SS);
+ VIR8086_SEG_AR_TEST(DS);
+ VIR8086_SEG_AR_TEST(ES);
+ VIR8086_SEG_AR_TEST(FS);
+ VIR8086_SEG_AR_TEST(GS);
+ } else {
+
+ u32 cs_ar = vmcs_read32(GUEST_CS_AR_BYTES);
+ u32 ss_ar = vmcs_read32(GUEST_SS_AR_BYTES);
+ u32 tr_ar = vmcs_read32(GUEST_TR_AR_BYTES);
+ u32 ldtr_ar = vmcs_read32(GUEST_LDTR_AR_BYTES);
+
+ #define SEG_G_TEST(seg) { \
+ u32 lim = vmcs_read32(GUEST_##seg##_LIMIT); \
+ u32 ar = vmcs_read32(GUEST_##seg##_AR_BYTES); \
+ int err = 0; \
+ if (((lim & ~PAGE_MASK) != ~PAGE_MASK) && (ar & AR_G_MASK)) \
+ err = 1; \
+ if ((lim & ~((1u << 20) - 1)) && !(ar & AR_G_MASK)) \
+ err = 1; \
+ if (err) { \
+ vcpu_printf(vcpu, "%s: "#seg" AR 0x%x, G err. lim" \
+ " is 0x%x\n", \
+ __FUNCTION__, \
+ ar, lim); \
+ return 0; \
+ } \
+ }
+
+
+ if (!(cs_ar & AR_TYPE_ACCESSES_MASK)) {
+ vcpu_printf(vcpu, "%s: cs AR 0x%x, accesses is clear\n",
+ __FUNCTION__,
+ cs_ar);
+ return 0;
+ }
+
+ if (!(cs_ar & AR_TYPE_CODE_MASK)) {
+ vcpu_printf(vcpu, "%s: cs AR 0x%x, code is clear\n",
+ __FUNCTION__,
+ cs_ar);
+ return 0;
+ }
+
+ if (!(cs_ar & AR_S_MASK)) {
+ vcpu_printf(vcpu, "%s: cs AR 0x%x, type is sys\n",
+ __FUNCTION__,
+ cs_ar);
+ return 0;
+ }
+
+ if ((cs_ar & AR_TYPE_MASK) >= 8 && (cs_ar & AR_TYPE_MASK) < 12 &&
+ AR_DPL(cs_ar) !=
+ (vmcs_read16(GUEST_CS_SELECTOR) & SELECTOR_RPL_MASK) ) {
+ vcpu_printf(vcpu, "%s: cs AR 0x%x, "
+ "DPL(0x%x) not as RPL(0x%x)\n",
+ __FUNCTION__,
+ cs_ar, AR_DPL(cs_ar), vmcs_read16(GUEST_CS_SELECTOR) & SELECTOR_RPL_MASK);
+ return 0;
+ }
+
+ if ((cs_ar & AR_TYPE_MASK) >= 13 && (cs_ar & AR_TYPE_MASK) < 16 &&
+ AR_DPL(cs_ar) >
+ (vmcs_read16(GUEST_CS_SELECTOR) & SELECTOR_RPL_MASK) ) {
+ vcpu_printf(vcpu, "%s: cs AR 0x%x, "
+ "DPL greater than RPL\n",
+ __FUNCTION__,
+ cs_ar);
+ return 0;
+ }
+
+ if (!(cs_ar & AR_P_MASK)) {
+ vcpu_printf(vcpu, "%s: CS AR 0x%x, not "
+ "present\n",
+ __FUNCTION__,
+ cs_ar);
+ return 0;
+ }
+
+ if ((cs_ar & AR_RESERVD_MASK)) {
+ vcpu_printf(vcpu, "%s: CS AR 0x%x, reseved"
+ " bits are set\n",
+ __FUNCTION__,
+ cs_ar);
+ return 0;
+ }
+
+ if (long_mode & (cs_ar & AR_L_MASK) && (cs_ar & AR_DB_MASK)) {
+ vcpu_printf(vcpu, "%s: CS AR 0x%x, DB and L are set"
+ " in long mode\n",
+ __FUNCTION__,
+ cs_ar);
+ return 0;
+
+ }
+
+ SEG_G_TEST(CS);
+
+ if (!(ss_ar & AR_UNUSABLE_MASK)) {
+ if ((ss_ar & AR_TYPE_MASK) != 3 &&
+ (ss_ar & AR_TYPE_MASK) != 7 ) {
+ vcpu_printf(vcpu, "%s: ss AR 0x%x, usable and type"
+ " is not 3 or 7\n",
+ __FUNCTION__,
+ ss_ar);
+ return 0;
+ }
+
+ if (!(ss_ar & AR_S_MASK)) {
+ vcpu_printf(vcpu, "%s: ss AR 0x%x, usable and"
+ " is sys\n",
+ __FUNCTION__,
+ ss_ar);
+ return 0;
+ }
+ if (!(ss_ar & AR_P_MASK)) {
+ vcpu_printf(vcpu, "%s: SS AR 0x%x, usable"
+ " and not present\n",
+ __FUNCTION__,
+ ss_ar);
+ return 0;
+ }
+
+ if ((ss_ar & AR_RESERVD_MASK)) {
+ vcpu_printf(vcpu, "%s: SS AR 0x%x, reseved"
+ " bits are set\n",
+ __FUNCTION__,
+ ss_ar);
+ return 0;
+ }
+
+ SEG_G_TEST(SS);
+
+ }
+
+ if (AR_DPL(ss_ar) !=
+ (vmcs_read16(GUEST_SS_SELECTOR) & SELECTOR_RPL_MASK) ) {
+ vcpu_printf(vcpu, "%s: SS AR 0x%x, "
+ "DPL not as RPL\n",
+ __FUNCTION__,
+ ss_ar);
+ return 0;
+ }
+
+ #define SEG_AR_TEST(seg) {\
+ u32 ar = vmcs_read32(GUEST_##seg##_AR_BYTES);\
+ if (!(ar & AR_UNUSABLE_MASK)) {\
+ if (!(ar & AR_TYPE_ACCESSES_MASK)) {\
+ vcpu_printf(vcpu, "%s: "#seg" AR 0x%x, "\
+ "usable and not accesses\n",\
+ __FUNCTION__,\
+ ar);\
+ return 0;\
+ }\
+ if ((ar & AR_TYPE_CODE_MASK) &&\
+ !(ar & AR_TYPE_READABLE_MASK)) {\
+ vcpu_printf(vcpu, "%s: "#seg" AR 0x%x, "\
+ "code and not readable\n",\
+ __FUNCTION__,\
+ ar);\
+ return 0;\
+ }\
+ if (!(ar & AR_S_MASK)) {\
+ vcpu_printf(vcpu, "%s: "#seg" AR 0x%x, usable and"\
+ " is sys\n",\
+ __FUNCTION__,\
+ ar);\
+ return 0;\
+ }\
+ if ((ar & AR_TYPE_MASK) >= 0 && \
+ (ar & AR_TYPE_MASK) < 12 && \
+ AR_DPL(ar) < (vmcs_read16(GUEST_##seg##_SELECTOR) & \
+ SELECTOR_RPL_MASK) ) {\
+ vcpu_printf(vcpu, "%s: "#seg" AR 0x%x, "\
+ "DPL less than RPL\n",\
+ __FUNCTION__,\
+ ar);\
+ return 0;\
+ }\
+ if (!(ar & AR_P_MASK)) {\
+ vcpu_printf(vcpu, "%s: "#seg" AR 0x%x, usable and"\
+ " not present\n",\
+ __FUNCTION__,\
+ ar);\
+ return 0;\
+ }\
+ if ((ar & AR_RESERVD_MASK)) {\
+ vcpu_printf(vcpu, "%s: "#seg" AR"\
+ " 0x%x, reseved"\
+ " bits are set\n",\
+ __FUNCTION__,\
+ ar);\
+ return 0;\
+ }\
+ SEG_G_TEST(seg)\
+ }\
+ }
+
+#undef DS
+#undef ES
+#undef FS
+#undef GS
+
+ SEG_AR_TEST(DS);
+ SEG_AR_TEST(ES);
+ SEG_AR_TEST(FS);
+ SEG_AR_TEST(GS);
+
+ // TR test
+ if (long_mode) {
+ if ((tr_ar & AR_TYPE_MASK) != AR_TYPE_BUSY_64_TSS) {
+ vcpu_printf(vcpu, "%s: TR AR 0x%x, long"
+ " mode and not 64bit busy"
+ " tss\n",
+ __FUNCTION__,
+ tr_ar);
+ return 0;
+ }
+ } else {
+ if ((tr_ar & AR_TYPE_MASK) != AR_TYPE_BUSY_32_TSS &&
+ (tr_ar & AR_TYPE_MASK) != AR_TYPE_BUSY_16_TSS) {
+ vcpu_printf(vcpu, "%s: TR AR 0x%x, legacy"
+ " mode and not 16/32bit "
+ "busy tss\n",
+ __FUNCTION__,
+ tr_ar);
+ return 0;
+ }
+
+ }
+ if ((tr_ar & AR_S_MASK)) {
+ vcpu_printf(vcpu, "%s: TR AR 0x%x, S is set\n",
+ __FUNCTION__,
+ tr_ar);
+ return 0;
+ }
+ if (!(tr_ar & AR_P_MASK)) {
+ vcpu_printf(vcpu, "%s: TR AR 0x%x, P is not set\n",
+ __FUNCTION__,
+ tr_ar);
+ return 0;
+ }
+
+ if ((tr_ar & (AR_RESERVD_MASK| AR_UNUSABLE_MASK))) {
+ vcpu_printf(vcpu, "%s: TR AR 0x%x, reserved bit are"
+ " set\n",
+ __FUNCTION__,
+ tr_ar);
+ return 0;
+ }
+ SEG_G_TEST(TR);
+
+ // TR test
+ if (!(ldtr_ar & AR_UNUSABLE_MASK)) {
+
+ if ((ldtr_ar & AR_TYPE_MASK) != AR_TYPE_LDT) {
+ vcpu_printf(vcpu, "%s: LDTR AR 0x%x,"
+ " bad type\n",
+ __FUNCTION__,
+ ldtr_ar);
+ return 0;
+ }
+
+ if ((ldtr_ar & AR_S_MASK)) {
+ vcpu_printf(vcpu, "%s: LDTR AR 0x%x,"
+ " S is set\n",
+ __FUNCTION__,
+ ldtr_ar);
+ return 0;
+ }
+
+ if (!(ldtr_ar & AR_P_MASK)) {
+ vcpu_printf(vcpu, "%s: LDTR AR 0x%x,"
+ " P is not set\n",
+ __FUNCTION__,
+ ldtr_ar);
+ return 0;
+ }
+ if ((ldtr_ar & AR_RESERVD_MASK)) {
+ vcpu_printf(vcpu, "%s: LDTR AR 0x%x,"
+ " reserved bit are set\n",
+ __FUNCTION__,
+ ldtr_ar);
+ return 0;
+ }
+ SEG_G_TEST(LDTR);
+ }
+ }
+
+ // GDTR and IDTR
+
+
+ #define IDT_GDT_TEST(reg)\
+ if (!is_canonical(vmcs_readl(GUEST_##reg##_BASE))) {\
+ vcpu_printf(vcpu, "%s: "#reg" BASE 0x%lx, not canonical\n",\
+ __FUNCTION__,\
+ vmcs_readl(GUEST_##reg##_BASE));\
+ return 0;\
+ }\
+ if (vmcs_read32(GUEST_##reg##_LIMIT) >> 16) {\
+ vcpu_printf(vcpu, "%s: "#reg" LIMIT 0x%x, size err\n",\
+ __FUNCTION__,\
+ vmcs_read32(GUEST_##reg##_LIMIT));\
+ return 0;\
+ }\
+
+ IDT_GDT_TEST(GDTR);
+ IDT_GDT_TEST(IDTR);
+
+
+ // RIP
+
+ if ((!long_mode || !(vmcs_read32(GUEST_CS_AR_BYTES) & AR_L_MASK)) &&
+ vmcs_readl(GUEST_RIP) & ~((1ULL << 32) - 1) ){
+ vcpu_printf(vcpu, "%s: RIP 0x%lx, size err\n",
+ __FUNCTION__,
+ vmcs_readl(GUEST_RIP));
+ return 0;
+ }
+
+ if (!is_canonical(vmcs_readl(GUEST_RIP))) {
+ vcpu_printf(vcpu, "%s: RIP 0x%lx, not canonical\n",
+ __FUNCTION__,
+ vmcs_readl(GUEST_RIP));
+ return 0;
+ }
+
+ // RFLAGS
+ #define RFLAGS_RESEVED_CLEAR_BITS\
+ (~((1ULL << 22) - 1) | (1ULL << 15) | (1ULL << 5) | (1ULL << 3))
+ #define RFLAGS_RESEVED_SET_BITS (1 << 1)
+
+ if ((rflags & RFLAGS_RESEVED_CLEAR_BITS) ||
+ !(rflags & RFLAGS_RESEVED_SET_BITS)) {
+ vcpu_printf(vcpu, "%s: RFLAGS 0x%lx, reserved bits 0x%llx 0x%x\n",
+ __FUNCTION__,
+ rflags,
+ RFLAGS_RESEVED_CLEAR_BITS,
+ RFLAGS_RESEVED_SET_BITS);
+ return 0;
+ }
+
+ if (long_mode && virtual8086) {
+ vcpu_printf(vcpu, "%s: RFLAGS 0x%lx, vm and long mode\n",
+ __FUNCTION__,
+ rflags);
+ return 0;
+ }
+
+
+ if (!(rflags & RFLAGS_RF)) {
+ u32 vm_entry_info = vmcs_read32(VM_ENTRY_INTR_INFO_FIELD);
+ if ((vm_entry_info & INTR_INFO_VALID_MASK) &&
+ (vm_entry_info & INTR_INFO_INTR_TYPE_MASK) ==
+ INTR_TYPE_EXT_INTR) {
+ vcpu_printf(vcpu, "%s: RFLAGS 0x%lx, external"
+ " interrupt and RF is clear\n",
+ __FUNCTION__,
+ rflags);
+ return 0;
+ }
+
+ }
+
+ cpu_exec_ctrl = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL);
+ cpu_secondary_exec_ctrl = vmcs_read32(SECONDARY_VM_EXEC_CONTROL);
+ tpr_threshold = vmcs_read32(TPR_THRESHOLD);
+
+ if ((cpu_exec_ctrl & CPU_BASED_TPR_SHADOW)) {
+ if (tpr_threshold & ~0xf) {
+ vcpu_printf(vcpu, "%s: if TPR shadow execution control"
+ " is 1 bits 31:4 of TPR threshold must"
+ " be 0", __FUNCTION__);
+ return 0;
+ }
+ if (!(cpu_secondary_exec_ctrl &
+ SECONDARY_EXEC_VIRTUALIZE_APIC_ACCESSES)) {
+ u32 apic_tpr = *((u32 *)(vcpu->arch.apic->regs + 0x80));
+ apic_tpr >>= 4;
+ if (tpr_threshold > apic_tpr) {
+ vcpu_printf(vcpu, "%s: if TPR shadow execution control"
+ " is 1 and virtual apic accesses is 0"
+ " the value of bits 3:0 of the TPR "
+ "threshold VM-execution control field"
+ " should not be greater than the value"
+ " of bits 7:4 in byte 80H on the "
+ "virtual-APIC page", __FUNCTION__);
+ return 0;
+ }
+
+ }
+ }
+
+ // to be continued from Checks on Guest Non-Register State (22.3.1.5)
+ return 1;
+}
+
+static int check_fixed_bits(struct kvm_vcpu *vcpu, const char *reg,
+ unsigned long cr,
+ u32 msr_fixed_0, u32 msr_fixed_1)
+{
+ u64 fixed_bits_0, fixed_bits_1;
+
+ rdmsrl(msr_fixed_0, fixed_bits_0);
+ rdmsrl(msr_fixed_1, fixed_bits_1);
+ if ((cr & fixed_bits_0) != fixed_bits_0) {
+ vcpu_printf(vcpu, "%s: %s (%lx) has one of %llx unset\n",
+ __FUNCTION__, reg, cr, fixed_bits_0);
+ return 0;
+ }
+ if ((~cr & ~fixed_bits_1) != ~fixed_bits_1) {
+ vcpu_printf(vcpu, "%s: %s (%lx) has one of %llx set\n",
+ __FUNCTION__, reg, cr, ~fixed_bits_1);
+ return 0;
+ }
+ return 1;
+}
+
+static int phys_addr_width(void)
+{
+ unsigned eax, ebx, ecx, edx;
+
+ cpuid(0x80000008, &eax, &ebx, &ecx, &edx);
+ return eax & 0xff;
+}
+
+static int check_canonical(struct kvm_vcpu *vcpu, const char *name,
+ unsigned long reg)
+{
+#ifdef CONFIG_X86_64
+ unsigned long x;
+
+ if (sizeof(reg) == 4)
+ return 1;
+ x = (long)reg >> 48;
+ if (!(x == 0 || x == ~0UL)) {
+ vcpu_printf(vcpu, "%s: %s (%lx) not canonical\n",
+ __FUNCTION__, name, reg);
+ return 0;
+ }
+#endif
+ return 1;
+}
+
+static int check_selector(struct kvm_vcpu *vcpu, const char *name,
+ int rpl_ti, int null,
+ u16 sel)
+{
+ if (rpl_ti && (sel & 7)) {
+ vcpu_printf(vcpu, "%s: %s (%x) nonzero rpl or ti\n",
+ __FUNCTION__, name, sel);
+ return 0;
+ }
+ if (null && !sel) {
+ vcpu_printf(vcpu, "%s: %s (%x) zero\n",
+ __FUNCTION__, name, sel);
+ return 0;
+ }
+ return 1;
+}
+
+//#define MSR_IA32_VMX_CR0_FIXED0 0x486
+//#define MSR_IA32_VMX_CR0_FIXED1 0x487
+
+//#define MSR_IA32_VMX_CR4_FIXED0 0x488
+//#define MSR_IA32_VMX_CR4_FIXED1 0x489
+#define VM_EXIT_HOST_ADD_SPACE_SIZE 0x00000200
+
+int vm_entry_test_host(struct kvm_vcpu *vcpu)
+{
+ int r = 1;
+ unsigned long cr0 = vmcs_readl(HOST_CR0);
+ unsigned long cr4 = vmcs_readl(HOST_CR4);
+ unsigned long cr3 = vmcs_readl(HOST_CR3);
+ int host_64;
+
+ host_64 = vmcs_read32(VM_EXIT_CONTROLS) & VM_EXIT_HOST_ADD_SPACE_SIZE;
+
+ /* 22.2.2 */
+ r &= check_fixed_bits(vcpu, "host cr0", cr0, MSR_IA32_VMX_CR0_FIXED0,
+ MSR_IA32_VMX_CR0_FIXED1);
+
+ r &= check_fixed_bits(vcpu, "host cr0", cr4, MSR_IA32_VMX_CR4_FIXED0,
+ MSR_IA32_VMX_CR4_FIXED1);
+ if ((u64)cr3 >> phys_addr_width()) {
+ vcpu_printf(vcpu, "%s: cr3 (%lx) vs phys addr width\n",
+ __FUNCTION__, cr3);
+ r = 0;
+ }
+
+ r &= check_canonical(vcpu, "host ia32_sysenter_eip",
+ vmcs_readl(HOST_IA32_SYSENTER_EIP));
+ r &= check_canonical(vcpu, "host ia32_sysenter_esp",
+ vmcs_readl(HOST_IA32_SYSENTER_ESP));
+
+ /* 22.2.3 */
+ r &= check_selector(vcpu, "host cs", 1, 1,
+ vmcs_read16(HOST_CS_SELECTOR));
+ r &= check_selector(vcpu, "host ss", 1, !host_64,
+ vmcs_read16(HOST_SS_SELECTOR));
+ r &= check_selector(vcpu, "host ds", 1, 0,
+ vmcs_read16(HOST_DS_SELECTOR));
+ r &= check_selector(vcpu, "host es", 1, 0,
+ vmcs_read16(HOST_ES_SELECTOR));
+ r &= check_selector(vcpu, "host fs", 1, 0,
+ vmcs_read16(HOST_FS_SELECTOR));
+ r &= check_selector(vcpu, "host gs", 1, 0,
+ vmcs_read16(HOST_GS_SELECTOR));
+ r &= check_selector(vcpu, "host tr", 1, 1,
+ vmcs_read16(HOST_TR_SELECTOR));
+
+#ifdef CONFIG_X86_64
+ r &= check_canonical(vcpu, "host fs base",
+ vmcs_readl(HOST_FS_BASE));
+ r &= check_canonical(vcpu, "host gs base",
+ vmcs_readl(HOST_GS_BASE));
+ r &= check_canonical(vcpu, "host gdtr base",
+ vmcs_readl(HOST_GDTR_BASE));
+ r &= check_canonical(vcpu, "host idtr base",
+ vmcs_readl(HOST_IDTR_BASE));
+#endif
+
+ /* 22.2.4 */
+#ifdef CONFIG_X86_64
+ if (!host_64) {
+ vcpu_printf(vcpu, "%s: vm exit controls: !64 bit host\n",
+ __FUNCTION__);
+ r = 0;
+ }
+ if (!(cr4 & X86_CR4_PAE)) {
+ vcpu_printf(vcpu, "%s: cr4 (%lx): !pae\n",
+ __FUNCTION__, cr4);
+ r = 0;
+ }
+ r &= check_canonical(vcpu, "host rip", vmcs_readl(HOST_RIP));
+#endif
+
+ return r;
+}
+
+int vm_entry_test(struct kvm_vcpu *vcpu)
+{
+ int rg, rh;
+
+ rg = vm_entry_test_guest(vcpu);
+ rh = vm_entry_test_host(vcpu);
+ return rg && rh;
+}
+
+void vmcs_dump(struct kvm_vcpu *vcpu)
+{
+ vcpu_printf(vcpu, "************************ vmcs_dump ************************\n");
+ vcpu_printf(vcpu, "VM_ENTRY_CONTROLS 0x%x\n", vmcs_read32(VM_ENTRY_CONTROLS));
+
+ vcpu_printf(vcpu, "GUEST_CR0 0x%lx\n", vmcs_readl(GUEST_CR0));
+ vcpu_printf(vcpu, "GUEST_CR3 0x%lx\n", vmcs_readl(GUEST_CR3));
+ vcpu_printf(vcpu, "GUEST_CR4 0x%lx\n", vmcs_readl(GUEST_CR4));
+
+ vcpu_printf(vcpu, "GUEST_SYSENTER_ESP 0x%lx\n", vmcs_readl(GUEST_SYSENTER_ESP));
+ vcpu_printf(vcpu, "GUEST_SYSENTER_EIP 0x%lx\n", vmcs_readl(GUEST_SYSENTER_EIP));
+
+
+ vcpu_printf(vcpu, "GUEST_IA32_DEBUGCTL 0x%llx\n", vmcs_read64(GUEST_IA32_DEBUGCTL));
+ vcpu_printf(vcpu, "GUEST_DR7 0x%lx\n", vmcs_readl(GUEST_DR7));
+
+ vcpu_printf(vcpu, "GUEST_RFLAGS 0x%lx\n", vmcs_readl(GUEST_RFLAGS));
+ vcpu_printf(vcpu, "GUEST_RIP 0x%lx\n", vmcs_readl(GUEST_RIP));
+
+ vcpu_printf(vcpu, "GUEST_CS_SELECTOR 0x%x\n", vmcs_read16(GUEST_CS_SELECTOR));
+ vcpu_printf(vcpu, "GUEST_DS_SELECTOR 0x%x\n", vmcs_read16(GUEST_DS_SELECTOR));
+ vcpu_printf(vcpu, "GUEST_ES_SELECTOR 0x%x\n", vmcs_read16(GUEST_ES_SELECTOR));
+ vcpu_printf(vcpu, "GUEST_FS_SELECTOR 0x%x\n", vmcs_read16(GUEST_FS_SELECTOR));
+ vcpu_printf(vcpu, "GUEST_GS_SELECTOR 0x%x\n", vmcs_read16(GUEST_GS_SELECTOR));
+ vcpu_printf(vcpu, "GUEST_SS_SELECTOR 0x%x\n", vmcs_read16(GUEST_SS_SELECTOR));
+
+ vcpu_printf(vcpu, "GUEST_TR_SELECTOR 0x%x\n", vmcs_read16(GUEST_TR_SELECTOR));
+ vcpu_printf(vcpu, "GUEST_LDTR_SELECTOR 0x%x\n", vmcs_read16(GUEST_LDTR_SELECTOR));
+
+ vcpu_printf(vcpu, "GUEST_CS_AR_BYTES 0x%x\n", vmcs_read32(GUEST_CS_AR_BYTES));
+ vcpu_printf(vcpu, "GUEST_DS_AR_BYTES 0x%x\n", vmcs_read32(GUEST_DS_AR_BYTES));
+ vcpu_printf(vcpu, "GUEST_ES_AR_BYTES 0x%x\n", vmcs_read32(GUEST_ES_AR_BYTES));
+ vcpu_printf(vcpu, "GUEST_FS_AR_BYTES 0x%x\n", vmcs_read32(GUEST_FS_AR_BYTES));
+ vcpu_printf(vcpu, "GUEST_GS_AR_BYTES 0x%x\n", vmcs_read32(GUEST_GS_AR_BYTES));
+ vcpu_printf(vcpu, "GUEST_SS_AR_BYTES 0x%x\n", vmcs_read32(GUEST_SS_AR_BYTES));
+
+ vcpu_printf(vcpu, "GUEST_LDTR_AR_BYTES 0x%x\n", vmcs_read32(GUEST_LDTR_AR_BYTES));
+ vcpu_printf(vcpu, "GUEST_TR_AR_BYTES 0x%x\n", vmcs_read32(GUEST_TR_AR_BYTES));
+
+ vcpu_printf(vcpu, "GUEST_CS_BASE 0x%lx\n", vmcs_readl(GUEST_CS_BASE));
+ vcpu_printf(vcpu, "GUEST_DS_BASE 0x%lx\n", vmcs_readl(GUEST_DS_BASE));
+ vcpu_printf(vcpu, "GUEST_ES_BASE 0x%lx\n", vmcs_readl(GUEST_ES_BASE));
+ vcpu_printf(vcpu, "GUEST_FS_BASE 0x%lx\n", vmcs_readl(GUEST_FS_BASE));
+ vcpu_printf(vcpu, "GUEST_GS_BASE 0x%lx\n", vmcs_readl(GUEST_GS_BASE));
+ vcpu_printf(vcpu, "GUEST_SS_BASE 0x%lx\n", vmcs_readl(GUEST_SS_BASE));
+
+
+ vcpu_printf(vcpu, "GUEST_LDTR_BASE 0x%lx\n", vmcs_readl(GUEST_LDTR_BASE));
+ vcpu_printf(vcpu, "GUEST_TR_BASE 0x%lx\n", vmcs_readl(GUEST_TR_BASE));
+
+ vcpu_printf(vcpu, "GUEST_CS_LIMIT 0x%x\n", vmcs_read32(GUEST_CS_LIMIT));
+ vcpu_printf(vcpu, "GUEST_DS_LIMIT 0x%x\n", vmcs_read32(GUEST_DS_LIMIT));
+ vcpu_printf(vcpu, "GUEST_ES_LIMIT 0x%x\n", vmcs_read32(GUEST_ES_LIMIT));
+ vcpu_printf(vcpu, "GUEST_FS_LIMIT 0x%x\n", vmcs_read32(GUEST_FS_LIMIT));
+ vcpu_printf(vcpu, "GUEST_GS_LIMIT 0x%x\n", vmcs_read32(GUEST_GS_LIMIT));
+ vcpu_printf(vcpu, "GUEST_SS_LIMIT 0x%x\n", vmcs_read32(GUEST_SS_LIMIT));
+
+ vcpu_printf(vcpu, "GUEST_LDTR_LIMIT 0x%x\n", vmcs_read32(GUEST_LDTR_LIMIT));
+ vcpu_printf(vcpu, "GUEST_TR_LIMIT 0x%x\n", vmcs_read32(GUEST_TR_LIMIT));
+
+ vcpu_printf(vcpu, "GUEST_GDTR_BASE 0x%lx\n", vmcs_readl(GUEST_GDTR_BASE));
+ vcpu_printf(vcpu, "GUEST_IDTR_BASE 0x%lx\n", vmcs_readl(GUEST_IDTR_BASE));
+
+ vcpu_printf(vcpu, "GUEST_GDTR_LIMIT 0x%x\n", vmcs_read32(GUEST_GDTR_LIMIT));
+ vcpu_printf(vcpu, "GUEST_IDTR_LIMIT 0x%x\n", vmcs_read32(GUEST_IDTR_LIMIT));
+
+ vcpu_printf(vcpu, "EXCEPTION_BITMAP 0x%x\n", vmcs_read32(EXCEPTION_BITMAP));
+ vcpu_printf(vcpu, "CPU_BASED_VM_EXEC_CONTROL 0x%x\n", vmcs_read32(CPU_BASED_VM_EXEC_CONTROL));
+ vcpu_printf(vcpu, "SECONDARY_VM_EXEC_CONTROL 0x%x\n", vmcs_read32(SECONDARY_VM_EXEC_CONTROL));
+ vcpu_printf(vcpu, "TPR_THREASHOLD 0x%x\n", vmcs_read32(TPR_THRESHOLD));
+ vcpu_printf(vcpu, "TPR 0x%x\n", *((u32 *) (vcpu->arch.apic->regs + 0x80)));
+ vcpu_printf(vcpu, "***********************************************************\n");
+}
+
+void regs_dump(struct kvm_vcpu *vcpu)
+{
+ #define REG_DUMP(reg) \
+ vcpu_printf(vcpu, #reg" = 0x%lx(VCPU)\n", vcpu->arch.regs[VCPU_REGS_##reg])
+ #define VMCS_REG_DUMP(reg) \
+ vcpu_printf(vcpu, #reg" = 0x%lx(VMCS)\n", vmcs_readl(GUEST_##reg))
+
+ vcpu_printf(vcpu, "************************ regs_dump ************************\n");
+ REG_DUMP(RAX);
+ REG_DUMP(RBX);
+ REG_DUMP(RCX);
+ REG_DUMP(RDX);
+ REG_DUMP(RSP);
+ REG_DUMP(RBP);
+ REG_DUMP(RSI);
+ REG_DUMP(RDI);
+#ifdef CONFIG_X86_64
+ REG_DUMP(R8);
+ REG_DUMP(R9);
+ REG_DUMP(R10);
+ REG_DUMP(R11);
+ REG_DUMP(R12);
+ REG_DUMP(R13);
+ REG_DUMP(R14);
+ REG_DUMP(R15);
+#endif
+
+ VMCS_REG_DUMP(RSP);
+ VMCS_REG_DUMP(RIP);
+ VMCS_REG_DUMP(RFLAGS);
+
+ vcpu_printf(vcpu, "***********************************************************\n");
+}
+
+void sregs_dump(struct kvm_vcpu *vcpu)
+{
+ vcpu_printf(vcpu, "************************ sregs_dump ************************\n");
+ vcpu_printf(vcpu, "cr0 = 0x%lx\n", vcpu->arch.cr0);
+ vcpu_printf(vcpu, "cr2 = 0x%lx\n", vcpu->arch.cr2);
+ vcpu_printf(vcpu, "cr3 = 0x%lx\n", vcpu->arch.cr3);
+ vcpu_printf(vcpu, "cr4 = 0x%lx\n", vcpu->arch.cr4);
+ vcpu_printf(vcpu, "cr8 = 0x%lx\n", vcpu->arch.cr8);
+ vcpu_printf(vcpu, "efer = 0x%llx\n", vcpu->arch.efer);
+ vcpu_printf(vcpu, "***********************************************************\n");
+}
+
+void show_pending_interrupts(struct kvm_vcpu *vcpu)
+{
+ vcpu_printf(vcpu, "************************ pending interrupts ****************\n");
+ if (vcpu->arch.interrupt.pending)
+ vcpu_printf(vcpu, "nr = %d%s\n", vcpu->arch.interrupt.nr, vcpu->arch.interrupt.soft?"(soft)":"");
+ vcpu_printf(vcpu, "************************************************************\n");
+}
+
+void vcpu_dump(struct kvm_vcpu *vcpu)
+{
+ regs_dump(vcpu);
+ sregs_dump(vcpu);
+ vmcs_dump(vcpu);
+ show_pending_interrupts(vcpu);
+ /* more ... */
+}
+#endif
+