diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | bitops.h | 2 | ||||
-rw-r--r-- | kvm.c | 33 | ||||
-rw-r--r-- | kvm.h | 2094 | ||||
-rw-r--r-- | kvm_cache_regs.c | 1 | ||||
-rw-r--r-- | kvm_coalesced_mmio.h | 13 | ||||
-rw-r--r-- | kvm_cpuid.h | 130 | ||||
-rw-r--r-- | kvm_host.h | 559 | ||||
-rw-r--r-- | kvm_i8254.c | 7 | ||||
-rw-r--r-- | kvm_i8254.h | 1 | ||||
-rw-r--r-- | kvm_impl.h | 155 | ||||
-rw-r--r-- | kvm_ioapic.c | 1 | ||||
-rw-r--r-- | kvm_irq_comm.c | 7 | ||||
-rw-r--r-- | kvm_lapic.c | 21 | ||||
-rw-r--r-- | kvm_mmu.c | 9 | ||||
-rw-r--r-- | kvm_msidef.h | 56 | ||||
-rw-r--r-- | kvm_paging_tmpl.h | 3 | ||||
-rw-r--r-- | kvm_subr.c | 48 | ||||
-rw-r--r-- | kvm_vmx.c | 33 | ||||
-rw-r--r-- | kvm_x86.c | 3 | ||||
-rw-r--r-- | kvm_x86.h | 259 | ||||
-rw-r--r-- | kvm_x86host.h | 440 |
22 files changed, 1642 insertions, 2235 deletions
@@ -9,7 +9,7 @@ LD=/usr/bin/ld CTFCONVERT=$(KERNEL_SOURCE)/usr/src/tools/ctf/cvt/i386/ctfconvert CTFMERGE=$(KERNEL_SOURCE)/usr/src/tools/ctf/cvt/i386/ctfmerge DESTDIR= -CFLAGS += -DCONFIG_HAVE_KVM_IRQCHIP -D__KVM_HAVE_IOAPIC -DCONFIG_X86_64 -DCONFIG_X86 -D_KERNEL -D_MACHDEP -Dx86 -DDEBUG -c -g -DCONFIG_SOLARIS -DCONFIG_KVM_MMIO -DCONFIG_KVM_APIC_ARCHITECTURE -O2 -fident -fno-inline -fno-inline-functions -fno-builtin -fno-asm -nodefaultlibs -D__sun -O -D_ASM_INLINES -ffreestanding -Wall -Wno-unknown-pragmas -Wpointer-arith -Wno-unused -gdwarf-2 -std=gnu99 -fno-dwarf2-indirect-strings -Werror -DDIS_MEM -D_KERNEL -ffreestanding -D_SYSCALL32 -D_DDI_STRICT -Di86pc -D_MACHDEP -DOPTERON_ERRATUM_88 -DOPTERON_ERRATUM_91 -DOPTERON_ERRATUM_93 -DOPTERON_ERRATUM_95 -DOPTERON_ERRATUM_99 -DOPTERON_ERRATUM_100 -DOPTERON_ERRATUM_101 -DOPTERON_ERRATUM_108 -DOPTERON_ERRATUM_109 -DOPTERON_ERRATUM_121 -DOPTERON_ERRATUM_122 -DOPTERON_ERRATUM_123 -DOPTERON_ERRATUM_131 -DOPTERON_WORKAROUND_6336786 -DOPTERON_WORKAROUND_6323525 -DOPTERON_ERRATUM_172 -DOPTERON_ERRATUM_298 -I$(KERNEL_SOURCE)/usr/src/uts/common -nostdinc -c -DUTS_RELEASE="5.11" -DUTS_VERSION="joyent.147" -DUTS_PLATFORM="i86pc" -mno-red-zone +CFLAGS += -DCONFIG_HAVE_KVM_IRQCHIP -D__KVM_HAVE_IOAPIC -DCONFIG_X86_64 -DCONFIG_X86 -D_KERNEL -D_MACHDEP -Dx86 -DDEBUG -c -g -DCONFIG_SOLARIS -DCONFIG_KVM_MMIO -DCONFIG_KVM_APIC_ARCHITECTURE -DCONFIG_HAVE_KVM_IRQCHIP -O2 -fident -fno-inline -fno-inline-functions -fno-builtin -fno-asm -nodefaultlibs -D__sun -O -D_ASM_INLINES -ffreestanding -Wall -Wno-unknown-pragmas -Wpointer-arith -Wno-unused -gdwarf-2 -std=gnu99 -fno-dwarf2-indirect-strings -Werror -DDIS_MEM -D_KERNEL -ffreestanding -D_SYSCALL32 -D_DDI_STRICT -Di86pc -D_MACHDEP -DOPTERON_ERRATUM_88 -DOPTERON_ERRATUM_91 -DOPTERON_ERRATUM_93 -DOPTERON_ERRATUM_95 -DOPTERON_ERRATUM_99 -DOPTERON_ERRATUM_100 -DOPTERON_ERRATUM_101 -DOPTERON_ERRATUM_108 -DOPTERON_ERRATUM_109 -DOPTERON_ERRATUM_121 -DOPTERON_ERRATUM_122 -DOPTERON_ERRATUM_123 -DOPTERON_ERRATUM_131 -DOPTERON_WORKAROUND_6336786 -DOPTERON_WORKAROUND_6323525 -DOPTERON_ERRATUM_172 -DOPTERON_ERRATUM_298 -I$(KERNEL_SOURCE)/usr/src/uts/common -nostdinc -c -DUTS_RELEASE="5.11" -DUTS_VERSION="joyent.147" -DUTS_PLATFORM="i86pc" -mno-red-zone INCLUDEDIR= -I $(KERNEL_SOURCE)/usr/src/uts/intel -I $(KERNEL_SOURCE)/usr/src/uts/i86pc -I $(KERNEL_SOURCE)/usr/src/uts/common CSTYLE=$(KERNEL_SOURCE)/usr/src/tools/scripts/cstyle @@ -17,6 +17,8 @@ #include <asm/alternative.h> #endif /*XXX*/ +#include "kvm_impl.h" + #define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) #define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, 8 * sizeof(long)) @@ -34,14 +34,15 @@ #include <sys/strsubr.h> #include <sys/stream.h> +#include "bitops.h" #include "vmx.h" #include "msr-index.h" #include "msr.h" #include "irqflags.h" #include "kvm_host.h" -#include "kvm_x86host.h" #include "kvm_lapic.h" #include "processor-flags.h" +#include "kvm_cpuid.h" #include "hyperv.h" #include "apicdef.h" #include "kvm_iodev.h" @@ -85,7 +86,6 @@ static volatile uint32_t hardware_enable_failed; static int kvm_usage_count; static list_t vm_list; kmutex_t kvm_lock; -kmem_cache_t *kvm_cache; /* * Driver forward declarations @@ -871,8 +871,6 @@ kvm_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) kvm_dip = dip; kvm_base_minor = instance; - kvm_cache = kmem_cache_create("kvm_cache", KVM_VM_DATA_SIZE, - ptob(1), NULL, NULL, NULL, NULL, NULL, 0); list_create(&vm_list, sizeof (struct kvm), offsetof(struct kvm, vm_list)); kvm_minor = vmem_create("kvm_minor", (void *)1, UINT32_MAX - 1, 1, @@ -896,7 +894,6 @@ kvm_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) VERIFY(instance == kvm_base_minor); ddi_prop_remove_all(dip); ddi_remove_minor_node(dip, NULL); - kmem_cache_destroy(kvm_cache); list_destroy(&vm_list); vmem_destroy(kvm_minor); kvm_dip = NULL; @@ -4973,6 +4970,12 @@ get_desc_limit(const struct desc_struct *desc) return (desc->c.b.limit0 | (desc->c.b.limit << 16)); } +unsigned long get_desc_base(const struct desc_struct *desc) +{ + return (unsigned)(desc->c.b.base0 | ((desc->c.b.base1) << 16) | ((desc->c.b.base2) << 24)); +} + + static void seg_desct_to_kvm_desct(struct desc_struct *seg_desc, uint16_t selector, struct kvm_segment *kvm_desct) @@ -5552,7 +5555,7 @@ out: -static inline void +void kvm_guest_exit(void) { #ifdef XXX @@ -5563,7 +5566,7 @@ kvm_guest_exit(void) #endif } -static inline void +void kvm_guest_enter(void) { #ifdef XXX @@ -7210,7 +7213,7 @@ kvm_ioctl(dev_t dev, int cmd, intptr_t arg, int md, cred_t *cr, int *rv) #endif #ifdef KVM_CAP_IRQ_ROUTING case KVM_SET_GSI_ROUTING: { - struct kvm_kirq_routing *route; + struct kvm_irq_routing *route; struct kvm *kvmp; struct kvm_irq_routing_entry *entries; uint32_t nroutes; @@ -7219,20 +7222,20 @@ kvm_ioctl(dev_t dev, int cmd, intptr_t arg, int md, cred_t *cr, int *rv) * Note the route must be allocated on the heap. The sizeof * (kvm_kirq_routing) is approximately 0xc038 currently. */ - route = kmem_zalloc(sizeof (kvm_kirq_routing_t), KM_SLEEP); + route = kmem_zalloc(sizeof (kvm_irq_routing_t), KM_SLEEP); /* * copyin the number of routes, then copyin the routes * themselves. */ if (copyin(argp, &nroutes, sizeof (nroutes)) != 0) { - kmem_free(route, sizeof (kvm_kirq_routing_t)); + kmem_free(route, sizeof (kvm_irq_routing_t)); rval = EFAULT; break; } if (nroutes <= 0) { - kmem_free(route, sizeof (kvm_kirq_routing_t)); + kmem_free(route, sizeof (kvm_irq_routing_t)); rval = EINVAL; break; } @@ -7240,26 +7243,26 @@ kvm_ioctl(dev_t dev, int cmd, intptr_t arg, int md, cred_t *cr, int *rv) if (copyin(argp, route, sizeof (struct kvm_irq_routing) + (nroutes - 1) * sizeof (struct kvm_irq_routing_entry)) != 0) { - kmem_free(route, sizeof (kvm_kirq_routing_t)); + kmem_free(route, sizeof (kvm_irq_routing_t)); rval = EFAULT; break; } if ((kvmp = ksp->kds_kvmp) == NULL) { - kmem_free(route, sizeof (kvm_kirq_routing_t)); + kmem_free(route, sizeof (kvm_irq_routing_t)); rval = EINVAL; break; } if (route->nr >= KVM_MAX_IRQ_ROUTES || route->flags) { - kmem_free(route, sizeof (kvm_kirq_routing_t)); + kmem_free(route, sizeof (kvm_irq_routing_t)); rval = EINVAL; break; } rval = kvm_set_irq_routing(kvmp, route->entries, route->nr, route->flags); - kmem_free(route, sizeof (kvm_kirq_routing_t)); + kmem_free(route, sizeof (kvm_irq_routing_t)); *rv = 0; break; } @@ -1,536 +1,46 @@ -#ifndef SOLARIS_KVM_H -#define SOLARIS_KVM_H +#ifndef __KVM_H +#define __KVM_H -#include <sys/list.h> #include <sys/types.h> -#include <sys/kstat.h> -#include <sys/ddi.h> -#include <sys/sunddi.h> -#include <sys/sdt.h> -#include <sys/avl.h> -#undef _ASM /* cyclic.h expects this not defined */ -#include <sys/cyclic.h> -#define _ASM -#include <sys/atomic.h> -#include "kvm_types.h" - -#define XXX_KVM_PROBE DTRACE_PROBE2(kvm__xxx, \ - char *, __FILE__, int, __LINE__) -#define XXX_KVM_SYNC_PROBE DTRACE_PROBE2(kvm__xxx__sync, \ - char *, __FILE__, int, __LINE__) - -#define KVM_CPUALL -1 -typedef void (*kvm_xcall_t)(void *); - -#ifdef _KERNEL -#include "bitops.h" -#ifdef CONFIG_MMU_NOTIFIER -#include "mmu_notifier.h" -#endif /*CONFIG_MMU_NOTIFIER*/ -#endif /*_KERNEL*/ +#include <sys/param.h> +#include "kvm_x86.h" #define KVM_API_VERSION 12 /* same as linux (for qemu compatability...) */ -#ifndef offsetof -#define offsetof(s, m) ((size_t)(&((s *)0)->m)) -#endif - -#define offset_in_page(p) ((unsigned long)(p) & ~PAGEMASK) - -/* borrowed liberally from linux... */ - -#define MAX_IO_MSRS 256 -#define CR0_RESERVED_BITS \ - (~(unsigned long)(X86_CR0_PE | X86_CR0_MP | X86_CR0_EM | X86_CR0_TS \ - | X86_CR0_ET | X86_CR0_NE | X86_CR0_WP | X86_CR0_AM \ - | X86_CR0_NW | X86_CR0_CD | X86_CR0_PG)) -#define CR4_RESERVED_BITS \ - (~(unsigned long)(X86_CR4_VME | X86_CR4_PVI | X86_CR4_TSD | X86_CR4_DE\ - | X86_CR4_PSE | X86_CR4_PAE | X86_CR4_MCE \ - | X86_CR4_PGE | X86_CR4_PCE | X86_CR4_OSFXSR \ - | X86_CR4_OSXMMEXCPT | X86_CR4_VMXE)) - -#define CR8_RESERVED_BITS (~(unsigned long)X86_CR8_TPR) - -#define KVM_MAX_VCPUS 64 - -#ifdef _KERNEL -#define MCG_CTL_P (1ULL<<8) /* MCG_CTL register available */ -#endif /*_KERNEL*/ - -#define KVM_MAX_MCE_BANKS 32 -#define KVM_MCE_CAP_SUPPORTED MCG_CTL_P - -#ifdef __ASSEMBLY__ -# define __IA64_UL(x) (x) -# define __IA64_UL_CONST(x) x - -#else -# define __IA64_UL(x) ((unsigned long)(x)) -# define __IA64_UL_CONST(x) x##UL -#endif - -/* - * This must match KVM_IA64_VCPU_STACK_{SHIFT,SIZE} arch/ia64/include/asm/kvm.h - */ -#define KVM_STK_SHIFT 16 -#define KVM_STK_OFFSET (__IA64_UL_CONST(1)<< KVM_STK_SHIFT) - -#define KVM_VM_STRUCT_SHIFT 19 -#define KVM_VM_STRUCT_SIZE (__IA64_UL_CONST(1) << KVM_VM_STRUCT_SHIFT) - -#define KVM_MEM_DIRY_LOG_SHIFT 19 -#define KVM_MEM_DIRTY_LOG_SIZE (__IA64_UL_CONST(1) << KVM_MEM_DIRY_LOG_SHIFT) - - -#define KVM_VM_BUFFER_BASE (KVM_VMM_BASE + VMM_SIZE) -#define KVM_VM_BUFFER_SIZE (__IA64_UL_CONST(8)<<20) - -/* - * kvm guest's data area looks as follow: - * - * +----------------------+ ------- KVM_VM_DATA_SIZE - * | vcpu[n]'s data | | ___________________KVM_STK_OFFSET - * | | | / | - * | .......... | | /vcpu's struct&stack | - * | .......... | | /---------------------|---- 0 - * | vcpu[5]'s data | | / vpd | - * | vcpu[4]'s data | |/-----------------------| - * | vcpu[3]'s data | / vtlb | - * | vcpu[2]'s data | /|------------------------| - * | vcpu[1]'s data |/ | vhpt | - * | vcpu[0]'s data |____________________________| - * +----------------------+ | - * | memory dirty log | | - * +----------------------+ | - * | vm's data struct | | - * +----------------------+ | - * | | | - * | | | - * | | | - * | | | - * | | | - * | | | - * | | | - * | vm's p2m table | | - * | | | - * | | | - * | | | | - * vm's data->| | | | - * +----------------------+ ------- 0 - * To support large memory, needs to increase the size of p2m. - * To support more vcpus, needs to ensure it has enough space to - * hold vcpus' data. - */ - -#define KVM_VM_DATA_SHIFT 26 -#define KVM_VM_DATA_SIZE (__IA64_UL_CONST(1) << KVM_VM_DATA_SHIFT) -#define KVM_VM_DATA_BASE (KVM_VMM_BASE + KVM_VM_DATA_SIZE) - -#define KVM_P2M_BASE KVM_VM_DATA_BASE -#define KVM_P2M_SIZE (__IA64_UL_CONST(24) << 20) - -/*Define the max vcpus and memory for Guests.*/ -#define KVM_MAX_MEM_SIZE (KVM_P2M_SIZE >> 3 << PAGESHIFT) - -#define VMM_LOG_LEN 256 - -#define VHPT_SHIFT 16 -#define VHPT_SIZE (__IA64_UL_CONST(1) << VHPT_SHIFT) -#define VHPT_NUM_ENTRIES (__IA64_UL_CONST(1) << (VHPT_SHIFT-5)) - -#define VTLB_SHIFT 16 -#define VTLB_SIZE (__IA64_UL_CONST(1) << VTLB_SHIFT) -#define VTLB_NUM_ENTRIES (1UL << (VHPT_SHIFT-5)) - -#define VPD_SHIFT 16 -#define VPD_SIZE (__IA64_UL_CONST(1) << VPD_SHIFT) - -#define VCPU_STRUCT_SHIFT 16 -#define VCPU_STRUCT_SIZE (__IA64_UL_CONST(1) << VCPU_STRUCT_SHIFT) - -#define KVM_NR_PAGE_SIZES 3 /* XXX assumes x86 */ - -#ifdef _KERNEL -typedef struct kvm_vcpu_data { - char vcpu_vhpt[VHPT_SIZE]; - char vcpu_vtlb[VTLB_SIZE]; - char vcpu_vpd[VPD_SIZE]; - char vcpu_struct[VCPU_STRUCT_SIZE]; -} kvm_vcpu_data_t; - -typedef struct kvm_vm_data { - char kvm_p2m[KVM_P2M_SIZE]; - char kvm_vm_struct[KVM_VM_STRUCT_SIZE]; - char kvm_mem_dirty_log[KVM_MEM_DIRTY_LOG_SIZE]; - struct kvm_vcpu_data vcpu_data[KVM_MAX_VCPUS]; -} kvm_vm_data_t; - -/* - * We don't want allocation failures within the mmu code, so we preallocate - * enough memory for a single page fault in a cache. - */ - - -#define KVM_NR_DB_REGS 4 - -/* - * fxsave fpu state. Taken from x86_64/processor.h. To be killed when - * we have asm/x86/processor.h - */ -typedef struct fxsave { - uint16_t cwd; - uint16_t swd; - uint16_t twd; - uint16_t fop; - uint64_t rip; - uint64_t rdp; - uint32_t mxcsr; - uint32_t mxcsr_mask; - uint32_t st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */ -#ifdef CONFIG_X86_64 - uint32_t xmm_space[64]; /* 16*16 bytes for each XMM-reg = 256 bytes */ -#else - uint32_t xmm_space[32]; /* 8*16 bytes for each XMM-reg = 128 bytes */ -#endif -} fxsave_t; - -#endif /*_KERNEL*/ - -#define KVM_MAX_CPUID_ENTRIES 40 - -#define KVM_POSSIBLE_CR0_GUEST_BITS X86_CR0_TS -#define KVM_POSSIBLE_CR4_GUEST_BITS \ - (X86_CR4_PVI | X86_CR4_DE | X86_CR4_PCE | X86_CR4_OSFXSR \ - | X86_CR4_OSXMMEXCPT | X86_CR4_PGE) - - -#ifndef CONFIG_X86_64 -#define mod_64(x, y) ((x) - (y) * div64_u64(x, y)) -#else -#define mod_64(x, y) ((x) % (y)) -#endif - -#ifdef _KERNEL -#include "kvm_emulate.h" - - -#endif /*_KERNEL*/ - -#define APIC_LDR 0xD0 - -#define APIC_LVT_NUM 6 -/* 14 is the version for Xeon and Pentium 8.4.8*/ -#define APIC_VERSION (0x14UL | ((APIC_LVT_NUM - 1) << 16)) -#define LAPIC_MMIO_LENGTH (1 << 12) -/* followed define is not in apicdef.h */ -#define APIC_SHORT_MASK 0xc0000 -#define APIC_DEST_NOSHORT 0x0 -#define APIC_DEST_MASK 0x800 -#define MAX_APIC_VECTOR 256 - -#define KVM_IOAPIC_NUM_PINS 24 - -#ifndef ARRAY_SIZE -#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) -#endif /*ARRAY_SIZE*/ - -#define LVT_MASK \ - (APIC_LVT_MASKED | APIC_SEND_PENDING | APIC_VECTOR_MASK) - -#define LINT_MASK \ - (LVT_MASK | APIC_MODE_MASK | APIC_INPUT_POLARITY | \ - APIC_LVT_REMOTE_IRR | APIC_LVT_LEVEL_TRIGGER) - -#ifdef _KERNEL - -/* XXX This shouldn't be necessary */ -#include "kvm_timer.h" - -struct vcpu_vmx; -struct kvm_user_return_notifier; - -typedef struct kvm_vcpu_stats { - kstat_named_t kvmvs_id; /* instance of associated kvm */ - kstat_named_t kvmvs_nmi_injections; /* number of NMI injections */ - kstat_named_t kvmvs_irq_injections; /* number of IRQ injections */ - kstat_named_t kvmvs_fpu_reload; /* number of FPU reloads */ - kstat_named_t kvmvs_host_state_reload; /* host state (re)loads */ - kstat_named_t kvmvs_insn_emulation; /* instruction emulation */ - kstat_named_t kvmvs_insn_emulation_fail; /* emulation failures */ - kstat_named_t kvmvs_exits; /* total VM exits */ - kstat_named_t kvmvs_halt_exits; /* exits due to HLT */ - kstat_named_t kvmvs_irq_exits; /* exits due to IRQ */ - kstat_named_t kvmvs_io_exits; /* exits due to I/O instrn */ - kstat_named_t kvmvs_mmio_exits; /* exits due to mem mppd I/O */ - kstat_named_t kvmvs_nmi_window_exits; /* exits due to NMI window */ - kstat_named_t kvmvs_irq_window_exits; /* exits due to IRQ window */ - kstat_named_t kvmvs_request_irq_exits; /* exits due to requested IRQ */ - kstat_named_t kvmvs_signal_exits; /* exits due to pending sig */ - kstat_named_t kvmvs_halt_wakeup; /* wakeups from HLT */ - kstat_named_t kvmvs_invlpg; /* INVLPG instructions */ - kstat_named_t kvmvs_pf_guest; /* injected guest pagefaults */ - kstat_named_t kvmvs_pf_fixed; /* fixed pagefaults */ - kstat_named_t kvmvs_hypercalls; /* hypercalls (VMCALL instrn) */ -} kvm_vcpu_stats_t; - -#define KVM_VCPU_KSTAT_INIT(vcpu, field, name) \ - kstat_named_init(&((vcpu)->kvcpu_stats.field), name, KSTAT_DATA_UINT64); - -#define KVM_VCPU_KSTAT_INC(vcpu, field) \ - (vcpu)->kvcpu_stats.field.value.ui64++; - -typedef struct kvm_vcpu { - struct kvm *kvm; -#ifdef CONFIG_PREEMPT_NOTIFIERS - struct preempt_notifier preempt_notifier; -#endif - int vcpu_id; - kmutex_t mutex; - int cpu; - struct kvm_run *run; - unsigned long requests; - unsigned long guest_debug; - int srcu_idx; - - int fpu_active; - int guest_fpu_loaded; - - kmutex_t kvcpu_kick_lock; - kcondvar_t kvcpu_kick_cv; - kvm_vcpu_stats_t kvcpu_stats; - kstat_t *kvcpu_kstat; - - int sigset_active; - sigset_t sigset; - - /*#ifdef CONFIG_HAS_IOMEM*/ - int mmio_needed; - int mmio_read_completed; - int mmio_is_write; - int mmio_size; - unsigned char mmio_data[8]; - gpa_t mmio_phys_addr; - /*#endif*/ - - struct kvm_vcpu_arch arch; - ddi_umem_cookie_t cookie; - struct kvm_user_return_notifier *urn; -} kvm_vcpu_t; - -#define KVM_NR_SHARED_MSRS 16 - -typedef struct kvm_shared_msrs_global { - int nr; - uint32_t msrs[KVM_NR_SHARED_MSRS]; -} kvm_shared_msrs_global_t; - -typedef struct kvm_user_return_notifier { - void (*on_user_return)(struct kvm_vcpu *, - struct kvm_user_return_notifier *); -} kvm_user_return_notifier_t; - -typedef struct kvm_shared_msrs { - struct kvm_user_return_notifier urn; - int registered; - struct kvm_shared_msr_values { - uint64_t host; - uint64_t curr; - } values[KVM_NR_SHARED_MSRS]; -} kvm_shared_msrs_t; - -typedef struct kvm_memory_slot { - gfn_t base_gfn; - unsigned long npages; - unsigned long flags; - unsigned long *rmap; - unsigned long *dirty_bitmap; - struct { - unsigned long rmap_pde; - int write_count; - } *lpage_info[KVM_NR_PAGE_SIZES]; - unsigned long userspace_addr; - int user_alloc; -} kvm_memory_slot_t; - - -typedef struct kvm_memslots { - int nmemslots; - struct kvm_memory_slot memslots[KVM_MEMORY_SLOTS + - KVM_PRIVATE_MEM_SLOTS]; -} kvm_memslots_t; - -#endif /*_KERNEL*/ - -#ifdef x86 - - -#define KVM_ALIAS_SLOTS 4 - -#define KVM_HPAGE_SHIFT(x) (PAGESHIFT + (((x) - 1) * 9)) -#define KVM_HPAGE_MASK(x) (~(KVM_HPAGE_SIZE(x) - 1)) -#define KVM_PAGES_PER_HPAGE(x) (KVM_HPAGE_SIZE(x) / PAGESIZE) - -#define DE_VECTOR 0 -#define DB_VECTOR 1 -#define BP_VECTOR 3 -#define OF_VECTOR 4 -#define BR_VECTOR 5 -#define UD_VECTOR 6 -#define NM_VECTOR 7 -#define DF_VECTOR 8 -#define TS_VECTOR 10 -#define NP_VECTOR 11 -#define SS_VECTOR 12 -#define GP_VECTOR 13 -#define PF_VECTOR 14 -#define MF_VECTOR 16 -#define MC_VECTOR 18 - -#define SELECTOR_TI_MASK (1 << 2) -#define SELECTOR_RPL_MASK 0x03 - -#define IOPL_SHIFT 12 - -#define KVM_ALIAS_SLOTS 4 - -#define KVM_PERMILLE_MMU_PAGES 20 -#define KVM_MIN_ALLOC_MMU_PAGES 64 -#define KVM_MMU_HASH_SHIFT 10 -#define KVM_NUM_MMU_PAGES (1 << KVM_MMU_HASH_SHIFT) -#define KVM_MIN_FREE_MMU_PAGES 5 -#define KVM_REFILL_PAGES 25 - -#define KVM_NR_FIXED_MTRR_REGION 88 -#define KVM_NR_VAR_MTRR 8 - -#ifdef _KERNEL -extern kmutex_t kvm_lock; -extern list_t vm_list; -#endif /*_KERNEL*/ - -#define KVM_USERSPACE_IRQ_SOURCE_ID 0 - -/* - * Extension capability list. - */ -#define KVM_CAP_IRQCHIP 0 -#define KVM_CAP_HLT 1 -#define KVM_CAP_MMU_SHADOW_CACHE_CONTROL 2 -#define KVM_CAP_USER_MEMORY 3 -#define KVM_CAP_SET_TSS_ADDR 4 -#define KVM_CAP_VAPIC 6 -#define KVM_CAP_EXT_CPUID 7 -#define KVM_CAP_CLOCKSOURCE 8 -#define KVM_CAP_NR_VCPUS 9 /* returns max vcpus per vm */ -#define KVM_CAP_NR_MEMSLOTS 10 /* returns max memory slots per vm */ -#define KVM_CAP_PIT 11 -#define KVM_CAP_NOP_IO_DELAY 12 -#define KVM_CAP_PV_MMU 13 -#define KVM_CAP_MP_STATE 14 -#define KVM_CAP_COALESCED_MMIO 15 -#define KVM_CAP_SYNC_MMU 16 /* Changes to host mmap are reflected in guest */ -#ifdef __KVM_HAVE_DEVICE_ASSIGNMENT -#define KVM_CAP_DEVICE_ASSIGNMENT 17 -#endif -#define KVM_CAP_IOMMU 18 - -/* For vcpu->arch.iommu_flags */ -#define KVM_IOMMU_CACHE_COHERENCY 0x1 - -#ifdef __KVM_HAVE_MSI -#define KVM_CAP_DEVICE_MSI 20 -#endif -/* Bug in KVM_SET_USER_MEMORY_REGION fixed: */ -#define KVM_CAP_DESTROY_MEMORY_REGION_WORKS 21 -#ifdef __KVM_HAVE_USER_NMI -#define KVM_CAP_USER_NMI 22 -#endif -#ifdef __KVM_HAVE_GUEST_DEBUG -#define KVM_CAP_SET_GUEST_DEBUG 23 -#endif -#define KVM_CAP_REINJECT_CONTROL 24 -#ifdef __KVM_HAVE_IOAPIC -#define KVM_CAP_IRQ_ROUTING 25 -#endif -#define KVM_CAP_IRQ_INJECT_STATUS 26 -#ifdef __KVM_HAVE_DEVICE_ASSIGNMENT -#define KVM_CAP_DEVICE_DEASSIGNMENT 27 -#endif -#ifdef __KVM_HAVE_MSIX -#define KVM_CAP_DEVICE_MSIX 28 -#endif -#define KVM_CAP_ASSIGN_DEV_IRQ 29 -/* Another bug in KVM_SET_USER_MEMORY_REGION fixed: */ -#define KVM_CAP_JOIN_MEMORY_REGIONS_WORKS 30 -#define KVM_CAP_MCE 31 -#define KVM_CAP_IRQFD 32 -#define KVM_CAP_PIT2 33 -#define KVM_CAP_SET_BOOT_CPU_ID 34 -#define KVM_CAP_PIT_STATE2 35 -#define KVM_CAP_IOEVENTFD 36 -#define KVM_CAP_SET_IDENTITY_MAP_ADDR 37 -#define KVM_CAP_XEN_HVM 38 -#define KVM_CAP_ADJUST_CLOCK 39 -#define KVM_CAP_INTERNAL_ERROR_DATA 40 -#define KVM_CAP_VCPU_EVENTS 41 -#define KVM_CAP_S390_PSW 42 -#define KVM_CAP_PPC_SEGSTATE 43 -#define KVM_CAP_HYPERV 44 -#define KVM_CAP_HYPERV_VAPIC 45 -#define KVM_CAP_HYPERV_SPIN 46 -#define KVM_CAP_PCI_SEGMENT 47 -#define KVM_CAP_X86_ROBUST_SINGLESTEP 51 +/* for KVM_CREATE_MEMORY_REGION */ +typedef struct kvm_memory_region { + uint32_t slot; + uint32_t flags; + uint64_t guest_phys_addr; + uint64_t memory_size; /* bytes */ +} kvm_memory_region_t; -#define KVM_IRQCHIP_PIC_MASTER 0 -#define KVM_IRQCHIP_PIC_SLAVE 1 -#define KVM_IRQCHIP_IOAPIC 2 -#define KVM_NR_IRQCHIPS 3 +/* for KVM_SET_USER_MEMORY_REGION */ +typedef struct kvm_userspace_memory_region { + uint32_t slot; + uint32_t flags; + uint64_t guest_phys_addr; + uint64_t memory_size; /* bytes */ + uint64_t userspace_addr; /* start of the userspace allocated memory */ +} kvm_userspace_memory_region_t; -/* for KVM_GET_IRQCHIP and KVM_SET_IRQCHIP */ -typedef struct kvm_pic_state { - uint8_t last_irr; /* edge detection */ - uint8_t irr; /* interrupt request register */ - uint8_t imr; /* interrupt mask register */ - uint8_t isr; /* interrupt service register */ - uint8_t priority_add; /* highest irq priority */ - uint8_t irq_base; - uint8_t read_reg_select; - uint8_t poll; - uint8_t special_mask; - uint8_t init_state; - uint8_t auto_eoi; - uint8_t rotate_on_auto_eoi; - uint8_t special_fully_nested_mode; - uint8_t init4; /* true if 4 byte init */ - uint8_t elcr; /* PIIX edge/trigger selection */ - uint8_t elcr_mask; -} kvm_pic_state_t; +/* for kvm_memory_region::flags */ +#define KVM_MEM_LOG_DIRTY_PAGES 1UL +#define KVM_MEMSLOT_INVALID (1UL << 1) -#define KVM_IOAPIC_NUM_PINS 24 -typedef struct kvm_ioapic_state { - uint64_t base_address; - uint32_t ioregsel; - uint32_t id; - uint32_t irr; - uint32_t pad; +/* for KVM_IRQ_LINE */ +typedef struct kvm_irq_level { + /* + * ACPI gsi notion of irq. + * For IA-64 (APIC model) IOAPIC0: irq 0-23; IOAPIC1: irq 24-47.. + * For X86 (standard AT mode) PIC0/1: irq 0-15. IOAPIC0: 0-23.. + */ union { - uint64_t bits; - struct { - uint8_t vector; - uint8_t delivery_mode:3; - uint8_t dest_mode:1; - uint8_t delivery_status:1; - uint8_t polarity:1; - uint8_t remote_irr:1; - uint8_t trig_mode:1; - uint8_t mask:1; - uint8_t reserve:7; - uint8_t reserved[4]; - uint8_t dest_id; - } fields; - } redirtbl[KVM_IOAPIC_NUM_PINS]; -} kvm_ioapic_state_t; + uint32_t irq; + int32_t status; + }; + uint32_t level; +} kvm_irq_level_t; typedef struct kvm_irqchip { uint32_t chip_id; @@ -548,526 +58,7 @@ typedef struct kvm_pit_config { uint32_t pad[15]; } kvm_pit_config_t; -/* for KVM_GET_REGS and KVM_SET_REGS */ -typedef struct kvm_regs { - /* out (KVM_GET_REGS) / in (KVM_SET_REGS) */ - uint64_t rax, rbx, rcx, rdx; - uint64_t rsi, rdi, rsp, rbp; - uint64_t r8, r9, r10, r11; - uint64_t r12, r13, r14, r15; - uint64_t rip, rflags; -} kvm_regs_t; - -typedef struct kvm_mp_state { - uint32_t mp_state; -} kvm_mp_state_t; - -/* for KVM_GET_LAPIC and KVM_SET_LAPIC */ -#define KVM_APIC_REG_SIZE 0x400 -typedef struct kvm_lapic_state { - char regs[KVM_APIC_REG_SIZE]; -} kvm_lapic_state_t; - -typedef struct kvm_dtable { - uint64_t base; - unsigned short limit; - unsigned short padding[3]; -} kvm_dtable_t; - -/* Architectural interrupt line count. */ -#define KVM_NR_INTERRUPTS 256 - - -typedef struct kvm_vmx_segment_field { - unsigned selector; - unsigned base; - unsigned limit; - unsigned ar_bytes; -} kvm_vmx_segment_field_t; - -/* for KVM_GET_SREGS and KVM_SET_SREGS */ -typedef struct kvm_sregs { - /* out (KVM_GET_SREGS) / in (KVM_SET_SREGS) */ - struct kvm_segment cs, ds, es, fs, gs, ss; - struct kvm_segment tr, ldt; - struct kvm_dtable gdt, idt; - uint64_t cr0, cr2, cr3, cr4, cr8; - uint64_t efer; - uint64_t apic_base; - unsigned long interrupt_bitmap[(KVM_NR_INTERRUPTS + (64-1)) / 64]; /*XXX 64 = bits in unsigned long*/ -} kvm_sregs_t; - -/* When set in flags, include corresponding fields on KVM_SET_VCPU_EVENTS */ -#define KVM_VCPUEVENT_VALID_NMI_PENDING 0x00000001 -#define KVM_VCPUEVENT_VALID_SIPI_VECTOR 0x00000002 - -/* for KVM_GET/SET_VCPU_EVENTS */ -typedef struct kvm_vcpu_events { - struct { - unsigned char injected; - unsigned char nr; - unsigned char has_error_code; - unsigned char pad; - uint32_t error_code; - } exception; - struct { - unsigned char injected; - unsigned char nr; - unsigned char soft; - unsigned char pad; - } interrupt; - struct { - unsigned char injected; - unsigned char pending; - unsigned char masked; - unsigned char pad; - } nmi; - uint32_t sipi_vector; - uint32_t flags; - uint32_t reserved[10]; -} kvm_vcpu_events_t; - -#define KVM_CAP_IRQ_ROUTING 25 - -#ifdef KVM_CAP_IRQ_ROUTING -typedef struct kvm_irq_routing_irqchip { - uint32_t irqchip; - uint32_t pin; -} kvm_irq_routing_irqchip_t; - -/* - * Shift/mask fields for msi address - */ - -#define MSI_ADDR_BASE_HI 0 -#define MSI_ADDR_BASE_LO 0xfee00000 - -#define MSI_ADDR_DEST_MODE_SHIFT 2 -#define MSI_ADDR_DEST_MODE_PHYSICAL (0 << MSI_ADDR_DEST_MODE_SHIFT) -#define MSI_ADDR_DEST_MODE_LOGICAL (1 << MSI_ADDR_DEST_MODE_SHIFT) - -#define MSI_ADDR_REDIRECTION_SHIFT 3 -#define MSI_ADDR_REDIRECTION_CPU (0 << MSI_ADDR_REDIRECTION_SHIFT) - /* dedicated cpu */ -#define MSI_ADDR_REDIRECTION_LOWPRI (1 << MSI_ADDR_REDIRECTION_SHIFT) - /* lowest priority */ - -#define MSI_ADDR_DEST_ID_SHIFT 12 -#define MSI_ADDR_DEST_ID_MASK 0x00ffff0 -#define MSI_ADDR_DEST_ID(dest) (((dest) << MSI_ADDR_DEST_ID_SHIFT) & \ - MSI_ADDR_DEST_ID_MASK) -#define MSI_ADDR_EXT_DEST_ID(dest) ((dest) & 0xffffff00) - -#define MSI_ADDR_IR_EXT_INT (1 << 4) -#define MSI_ADDR_IR_SHV (1 << 3) -#define MSI_ADDR_IR_INDEX1(index) ((index & 0x8000) >> 13) -#define MSI_ADDR_IR_INDEX2(index) ((index & 0x7fff) << 5) -#define MSI_DATA_VECTOR_SHIFT 0 -#define MSI_DATA_VECTOR_MASK 0x000000ff -#define MSI_DATA_VECTOR(v) (((v) << MSI_DATA_VECTOR_SHIFT) & \ - MSI_DATA_VECTOR_MASK) -#define MSI_DATA_TRIGGER_SHIFT 15 -#define MSI_DATA_TRIGGER_EDGE (0 << MSI_DATA_TRIGGER_SHIFT) -#define MSI_DATA_TRIGGER_LEVEL (1 << MSI_DATA_TRIGGER_SHIFT) - -typedef struct kvm_irq_routing_msi { - uint32_t address_lo; - uint32_t address_hi; - uint32_t data; - uint32_t pad; -} kvm_irq_routing_msi_t; - -/* gsi routing entry types */ -#define KVM_IRQ_ROUTING_IRQCHIP 1 -#define KVM_IRQ_ROUTING_MSI 2 - -typedef struct kvm_irq_routing_entry { - uint32_t gsi; - uint32_t type; - uint32_t flags; - uint32_t pad; - union { - struct kvm_irq_routing_irqchip irqchip; - struct kvm_irq_routing_msi msi; - uint32_t pad[8]; - } u; -} kvm_irq_routing_entry_t; - -typedef struct kvm_irq_routing { - uint32_t nr; - uint32_t flags; - struct kvm_irq_routing_entry entries[1]; -} kvm_irq_routing_t; - -#endif - -#define KVM_MAX_MCE_BANKS 32 -#define KVM_MCE_CAP_SUPPORTED MCG_CTL_P - - -struct kvm_vcpu; -struct kvm; - -typedef struct kvm_irq_ack_notifier { - list_t link; - unsigned gsi; - void (*irq_acked)(struct kvm_irq_ack_notifier *kian); -} kvm_irq_ack_notifier_t; - -#define KVM_ASSIGNED_MSIX_PENDING 0x1 -typedef struct kvm_guest_msix_entry { - uint32_t vector; - unsigned short entry; - unsigned short flags; -} kvm_guest_msix_entry_t; - -typedef struct kvm_assigned_dev_kernel { - struct kvm_irq_ack_notifier ack_notifier; - list_t interrupt_work; - list_t list; - int assigned_dev_id; - int host_segnr; - int host_busnr; - int host_devfn; - unsigned int entries_nr; - int host_irq; - unsigned char host_irq_disabled; - struct msix_entry *host_msix_entries; - int guest_irq; - struct kvm_guest_msix_entry *guest_msix_entries; - unsigned long irq_requested_type; - int irq_source_id; - int flags; - struct pci_dev *dev; - struct kvm *kvm; - kmutex_t assigned_dev_lock; -} kvm_assigned_dev_kernel_t; - -#ifndef container_of -/** - * container_of - cast a member of a structure out to the containing structure - * @ptr: the pointer to the member. - * @type: the type of the container struct this is embedded in. - * @member: the name of the member within the struct. - * - */ -#define container_of(ptr, type, member) ({ \ - const typeof( ((type *)0)->member ) *__mptr = (ptr); \ - (type *)( (char *)__mptr - offsetof(type,member) );}) -#endif /*container_of*/ - -/* Avoid include hell */ -#define NMI_VECTOR 0x02 - -/* - * Save the original ist values for checking stack pointers during debugging - */ -typedef struct orig_ist { - unsigned long ist[7]; -} orig_ist_t; - -#define MXCSR_DEFAULT 0x1f80 - -typedef struct i387_fsave_struct { - uint32_t cwd; /* FPU Control Word */ - uint32_t swd; /* FPU Status Word */ - uint32_t twd; /* FPU Tag Word */ - uint32_t fip; /* FPU IP Offset */ - uint32_t fcs; /* FPU IP Selector */ - uint32_t foo; /* FPU Operand Pointer Offset */ - uint32_t fos; /* FPU Operand Pointer Selector */ - - /* 8*10 bytes for each FP-reg = 80 bytes: */ - uint32_t st_space[20]; - - /* Software status information [not touched by FSAVE ]: */ - uint32_t status; -} i387_fsave_struct_t; - - -typedef struct i387_soft_struct { - uint32_t cwd; - uint32_t swd; - uint32_t twd; - uint32_t fip; - uint32_t fcs; - uint32_t foo; - uint32_t fos; - /* 8*10 bytes for each FP-reg = 80 bytes: */ - uint32_t st_space[20]; - unsigned char ftop; - unsigned char changed; - unsigned char lookahead; - unsigned char no_update; - unsigned char rm; - unsigned char alimit; - struct math_emu_info *info; - uint32_t entry_eip; -} i387_soft_struct_t; - -#define KVM_CPUID_FLAG_SIGNIFCANT_INDEX 1 -#define KVM_CPUID_FLAG_STATEFUL_FUNC 2 -#define KVM_CPUID_FLAG_STATE_READ_NEXT 4 - - -/* for KVM_GET_FPU and KVM_SET_FPU */ -typedef struct kvm_fpu { - unsigned char fpr[8][16]; - unsigned short fcw; - unsigned short fsw; - unsigned char ftwx; /* in fxsave format */ - unsigned char pad1; - unsigned short last_opcode; - uint64_t last_ip; - uint64_t last_dp; - unsigned char xmm[16][16]; - uint32_t mxcsr; - uint32_t pad2; -} kvm_fpu_t; - -typedef struct kvm_msr_entry { - uint32_t index; - uint32_t reserved; - uint64_t data; -} kvm_msr_entry_t; - -/* for KVM_GET_MSRS and KVM_SET_MSRS */ -typedef struct kvm_msrs { - uint32_t nmsrs; /* number of msrs in entries */ - uint32_t pad; - - struct kvm_msr_entry entries[100]; -} kvm_msrs_t; - -/* for KVM_GET_MSR_INDEX_LIST */ -typedef struct kvm_msr_list { - uint32_t nmsrs; /* number of msrs in entries */ - uint32_t indices[1]; -} kvm_msr_list_t; - -typedef struct kvm_cpuid_entry { - uint32_t function; - uint32_t eax; - uint32_t ebx; - uint32_t ecx; - uint32_t edx; - uint32_t padding; -} kvm_cpuid_entry_t; - -/* for KVM_SET_CPUID */ -typedef struct kvm_cpuid { - uint32_t nent; - uint32_t padding; - struct kvm_cpuid_entry entries[100]; -} kvm_cpuid_t; - -/* for KVM_GET_PIT and KVM_SET_PIT */ -typedef struct kvm_pit_channel_state { - uint32_t count; /* can be 65536 */ - uint16_t latched_count; - uint8_t count_latched; - uint8_t status_latched; - uint8_t status; - uint8_t read_state; - uint8_t write_state; - uint8_t write_latch; - uint8_t rw_mode; - uint8_t mode; - uint8_t bcd; - uint8_t gate; - int64_t count_load_time; -} kvm_pit_channel_state_t; - -typedef struct kvm_debug_exit_arch { - uint32_t exception; - uint32_t pad; - uint64_t pc; - uint64_t dr6; - uint64_t dr7; -} kvm_debug_exit_arch_t; - -#define KVM_GUESTDBG_USE_SW_BP 0x00010000 -#define KVM_GUESTDBG_USE_HW_BP 0x00020000 -#define KVM_GUESTDBG_INJECT_DB 0x00040000 -#define KVM_GUESTDBG_INJECT_BP 0x00080000 - -#ifdef XXX -/* for KVM_SET_GUEST_DEBUG */ -typedef struct kvm_guest_debug_arch { - uint64_t debugreg[8]; -} kvm_guest_debug_arch_t; -#endif /*XXX*/ - -typedef struct kvm_pit_state { - struct kvm_pit_channel_state channels[3]; -} kvm_pit_state_t; - -#define KVM_PIT_FLAGS_HPET_LEGACY 0x00000001 - -typedef struct kvm_pit_state2 { - struct kvm_pit_channel_state channels[3]; - uint32_t flags; - uint32_t reserved[9]; -} kvm_pit_state2_t; - -typedef struct kvm_reinject_control { - uint8_t pit_reinject; - uint8_t reserved[31]; -} kvm_reinject_control_t; - - -/* for KVM_SET_CPUID2 */ -typedef struct kvm_cpuid2 { - uint32_t nent; - uint32_t padding; - struct kvm_cpuid_entry2 entries[100]; -} kvm_cpuid2_t; - -#define X86_SHADOW_INT_MOV_SS 1 -#define X86_SHADOW_INT_STI 2 - - -struct pvclock_wall_clock { - uint32_t version; - uint32_t sec; - uint32_t nsec; -} __attribute__((__packed__)); - -typedef struct pvclock_wall_clock pvclock_wall_clock_t; - -typedef struct msi_msg { - uint32_t address_lo; /* low 32 bits of msi message address */ - uint32_t address_hi; /* high 32 bits of msi message address */ - uint32_t data; /* 16 bits of msi message data */ -} msi_msg_t; - - -typedef struct kvm_kernel_irq_routing_entry { - uint32_t gsi; - uint32_t type; - int (*set)(struct kvm_kernel_irq_routing_entry *e, - struct kvm *kvm, int irq_source_id, int level); - union { - struct { - unsigned irqchip; - unsigned pin; - } irqchip; - struct msi_msg msi; - }; - struct list_node link; -} kvm_kernel_irq_routing_entry_t; - -/*#ifdef __KVM_HAVE_IOAPIC*/ - -#define KVM_MAX_IRQ_ROUTES 1024 - -typedef struct kvm_irq_routing_table { - int chip[KVM_NR_IRQCHIPS][KVM_IOAPIC_NUM_PINS]; - struct kvm_kernel_irq_routing_entry *rt_entries; - uint32_t nr_rt_entries; - /* - * Array indexed by gsi. Each entry contains list of irq chips - * the gsi is connected to. - */ - list_t map[KVM_MAX_IRQ_ROUTES+1]; -} kvm_irq_routing_table_t; - -typedef struct kvm_kirq_routing { - uint32_t nr; - uint32_t flags; - struct kvm_irq_routing_entry entries[KVM_MAX_IRQ_ROUTES+1]; -} kvm_kirq_routing_t; - -/*#endif __KVM_HAVE_IOAPIC*/ - -#define MTRRphysBase_MSR(reg) (0x200 + 2 * (reg)) -#define MTRRphysMask_MSR(reg) (0x200 + 2 * (reg) + 1) - -#endif /*x86*/ - -#ifdef _KERNEL - -enum kvm_bus { - KVM_MMIO_BUS, - KVM_PIO_BUS, - KVM_NR_BUSES -}; - -typedef struct kvm_stats { - kstat_named_t kvmks_pid; /* PID of opening process */ - kstat_named_t kvmks_mmu_pte_write; /* page table entry writes */ - kstat_named_t kvmks_mmu_pte_zapped; /* zapped page table entries */ - kstat_named_t kvmks_mmu_pte_updated; /* page table entry updates */ - kstat_named_t kvmks_mmu_flooded; /* # of pages flooded */ - kstat_named_t kvmks_mmu_cache_miss; /* misses in page cache */ - kstat_named_t kvmks_mmu_recycled; /* recycles from free list */ - kstat_named_t kvmks_remote_tlb_flush; /* remote TLB flushes */ - kstat_named_t kvmks_lpages; /* large pages in use */ -} kvm_stats_t; - -#define KVM_KSTAT_INIT(kvmp, field, name) \ - kstat_named_init(&((kvmp)->kvm_stats.field), name, KSTAT_DATA_UINT64); - -#define KVM_KSTAT_INC(kvmp, field) \ - (kvmp)->kvm_stats.field.value.ui64++; - -#define KVM_KSTAT_DEC(kvmp, field) \ - (kvmp)->kvm_stats.field.value.ui64--; - -typedef struct kvm { - kmutex_t mmu_lock; - kmutex_t requests_lock; - kmutex_t slots_lock; - struct as *mm; /* userspace tied to this vm */ - struct kvm_memslots *memslots; - /* the following was a read-copy update mechanism */ - /* we'll use a reader-writer lock, for now */ - krwlock_t kvm_rwlock; -#ifdef CONFIG_KVM_APIC_ARCHITECTURE - uint32_t bsp_vcpu_id; - struct kvm_vcpu *bsp_vcpu; -#endif - struct kvm_vcpu *vcpus[KVM_MAX_VCPUS]; - volatile int online_vcpus; - struct list_node vm_list; - kmutex_t lock; - struct kvm_io_bus *buses[KVM_NR_BUSES]; -#ifdef CONFIG_HAVE_KVM_EVENTFD - struct { - kmutex_t lock; - struct list_head items; - } irqfds; - struct list_head ioeventfds; -#endif - struct kstat *kvm_kstat; - kvm_stats_t kvm_stats; - struct kvm_arch arch; - volatile int users_count; -#ifdef KVM_COALESCED_MMIO_PAGE_OFFSET - struct kvm_coalesced_mmio_dev *coalesced_mmio_dev; - struct kvm_coalesced_mmio_ring *coalesced_mmio_ring; - ddi_umem_cookie_t mmio_cookie; -#endif - - kmutex_t irq_lock; -#ifdef CONFIG_HAVE_KVM_IRQCHIP - struct kvm_irq_routing_table *irq_routing; - list_t mask_notifier_list; - list_t irq_ack_notifier_list; -#endif - -#if defined(KVM_ARCH_WANT_MMU_NOTIFIER) && defined(CONFIG_MMU_NOTIFIER) - struct mmu_notifier mmu_notifier; - unsigned long mmu_notifier_seq; - long mmu_notifier_count; -#endif - int kvmid; /* unique identifier for this kvm */ - int kvm_clones; - pid_t kvm_pid; /* pid associated with this kvm */ - kmutex_t kvm_avllock; - avl_tree_t kvm_avlmp; /* avl tree for mmu to page_t mapping */ -} kvm_t; -#endif /*_KERNEL*/ +#define KVM_PIT_SPEAKER_DUMMY 1 #define KVM_EXIT_UNKNOWN 0 #define KVM_EXIT_EXCEPTION 1 @@ -1201,126 +192,221 @@ typedef struct kvm_run { }; } kvm_run_t; -/* the following is directly copied from ioctl.h on linux */ -#ifndef _ASM_GENERIC_IOCTL_H -#define _ASM_GENERIC_IOCTL_H +typedef struct kvm_coalesced_mmio_zone { + uint64_t addr; + uint32_t size; + uint32_t pad; +} kvm_coalesced_mmio_zone_t; -/* ioctl command encoding: 32 bits total, command in lower 16 bits, - * size of the parameter structure in the lower 14 bits of the - * upper 16 bits. - * Encoding the size of the parameter structure in the ioctl request - * is useful for catching programs compiled with old versions - * and to avoid overwriting user space outside the user buffer area. - * The highest 2 bits are reserved for indicating the ``access mode''. - * NOTE: This limits the max parameter size to 16kB -1 ! - */ +typedef struct kvm_coalesced_mmio { + uint64_t phys_addr; + uint32_t len; + uint32_t pad; + unsigned char data[8]; +} kvm_coalesced_mmio_t; -/* - * The following is for compatibility across the various Linux - * platforms. The generic ioctl numbering scheme doesn't really enforce - * a type field. De facto, however, the top 8 bits of the lower 16 - * bits are indeed used as a type field, so we might just as well make - * this explicit here. Please be sure to use the decoding macros - * below from now on. - */ -#define _IOC_NRBITS 8 -#define _IOC_TYPEBITS 8 +typedef struct kvm_coalesced_mmio_ring { + uint32_t first, last; + struct kvm_coalesced_mmio coalesced_mmio[1]; +} kvm_coalesced_mmio_ring_t; -/* - * Let any architecture override either of the following before - * including this file. - */ +/* XXX NEEDS TO DIE! */ +typedef struct kvm_coalesced_mmio_zone_ioc { + struct kvm_coalesced_mmio_zone zone; + int kvmid; +} kvm_coalesced_mmio_zone_ioc_t; -#ifndef _IOC_SIZEBITS -# define _IOC_SIZEBITS 14 -#endif +#define KVM_COALESCED_MMIO_MAX \ + ((PAGESIZE - sizeof(struct kvm_coalesced_mmio_ring)) / \ + sizeof(struct kvm_coalesced_mmio)) -#ifndef _IOC_DIRBITS -# define _IOC_DIRBITS 2 -#endif +/* for KVM_INTERRUPT */ +typedef struct kvm_interrupt { + /* in */ + uint32_t irq; +} kvm_interrupt_t; -#define _IOC_NRMASK ((1 << _IOC_NRBITS)-1) -#define _IOC_TYPEMASK ((1 << _IOC_TYPEBITS)-1) -#define _IOC_SIZEMASK ((1 << _IOC_SIZEBITS)-1) -#define _IOC_DIRMASK ((1 << _IOC_DIRBITS)-1) +/* for KVM_GET_DIRTY_LOG */ +typedef struct kvm_dirty_log { + uint32_t slot; + uint32_t padding1; + union { + void *dirty_bitmap; /* one bit per page */ + uint64_t padding2; + }v; +} kvm_dirty_log_t; -#define _IOC_NRSHIFT 0 -#define _IOC_TYPESHIFT (_IOC_NRSHIFT+_IOC_NRBITS) -#define _IOC_SIZESHIFT (_IOC_TYPESHIFT+_IOC_TYPEBITS) -#define _IOC_DIRSHIFT (_IOC_SIZESHIFT+_IOC_SIZEBITS) +/* for KVM_SET_SIGNAL_MASK */ +typedef struct kvm_signal_mask { + uint32_t len; + uint8_t sigset[1]; +} kvm_signal_mask_t; -/* - * Direction bits, which any architecture can choose to override - * before including this file. - */ +/* for KVM_TPR_ACCESS_REPORTING */ +typedef struct kvm_tpr_access_ctl { + uint32_t enabled; + uint32_t flags; + uint32_t reserved[8]; +} kvm_tpr_access_ctl_t; -#ifndef _IOC_NONE -# define _IOC_NONE 0U -#endif +/* for KVM_SET_VAPIC_ADDR */ +typedef struct kvm_vapic_addr { + uint64_t vapic_addr; +} kvm_vapic_addr_t; -#ifndef _IOC_WRITE -# define _IOC_WRITE 1U -#endif +/* for KVM_SET_MP_STATE */ +#define KVM_MP_STATE_RUNNABLE 0 +#define KVM_MP_STATE_UNINITIALIZED 1 +#define KVM_MP_STATE_INIT_RECEIVED 2 +#define KVM_MP_STATE_HALTED 3 +#define KVM_MP_STATE_SIPI_RECEIVED 4 -#ifndef _IOC_READ -# define _IOC_READ 2U -#endif +typedef struct kvm_mp_state { + uint32_t mp_state; +} kvm_mp_state_t; -#define _IOC(dir,type,nr,size) \ - (((dir) << _IOC_DIRSHIFT) | \ - ((type) << _IOC_TYPESHIFT) | \ - ((nr) << _IOC_NRSHIFT) | \ - ((size) << _IOC_SIZESHIFT)) +/* for KVM_SET_GUEST_DEBUG */ -#ifdef XXX -#ifdef _KERNEL +#define KVM_GUESTDBG_ENABLE 0x00000001 +#define KVM_GUESTDBG_SINGLESTEP 0x00000002 -/* provoke compile error for invalid uses of size argument */ -extern unsigned int __invalid_size_argument_for_IOC; -#define _IOC_TYPECHECK(t) \ - ((sizeof(t) == sizeof(t[1]) && \ - sizeof(t) < (1 << _IOC_SIZEBITS)) ? \ - sizeof(t) : __invalid_size_argument_for_IOC) -#else -#define _IOC_TYPECHECK(t) (sizeof(t)) -#endif /*_KERNEL*/ -#else /*XXX*/ +typedef struct kvm_guest_debug { + uint32_t control; + uint32_t pad; + struct kvm_guest_debug_arch arch; +} kvm_guest_debug_t; -#define _IOC_TYPECHECK(t) (sizeof(t)) -static void native_load_tr_desc(void) -{ - __asm__ volatile("ltr %w0"::"q" (KTSS_SEL)); -} +/* ioctl commands */ + +#define KVMIO 0xAE + +/* + * ioctls for /dev/kvm fds: + */ +#define KVM_GET_API_VERSION _IO(KVMIO, 0x00) +#define KVM_CREATE_VM _IO(KVMIO, 0x01) /* returns a VM fd */ +#define KVM_GET_MSR_INDEX_LIST _IOWR(KVMIO, 0x02, struct kvm_msr_list) +#define KVM_CLONE _IO(KVMIO, 0x20) +#define KVM_NET_QUEUE _IO(KVMIO, 0x21) + +/* + * Check if a kvm extension is available. Argument is extension number, + * return is 1 (yes) or 0 (no, sorry). + */ +#define KVM_CHECK_EXTENSION _IO(KVMIO, 0x03) -#define load_TR_desc() native_load_tr_desc() +/* + * Get size for mmap(vcpu_fd) + */ +#define KVM_GET_VCPU_MMAP_SIZE _IO(KVMIO, 0x04) /* in bytes */ +#define KVM_GET_SUPPORTED_CPUID _IOWR(KVMIO, 0x05, struct kvm_cpuid2) -#endif /*XXX*/ +/* + * Extension capability list. + */ +#define KVM_CAP_IRQCHIP 0 +#define KVM_CAP_HLT 1 +#define KVM_CAP_MMU_SHADOW_CACHE_CONTROL 2 +#define KVM_CAP_USER_MEMORY 3 +#define KVM_CAP_SET_TSS_ADDR 4 +#define KVM_CAP_VAPIC 6 +#define KVM_CAP_EXT_CPUID 7 +#define KVM_CAP_CLOCKSOURCE 8 +#define KVM_CAP_NR_VCPUS 9 /* returns max vcpus per vm */ +#define KVM_CAP_NR_MEMSLOTS 10 /* returns max memory slots per vm */ +#define KVM_CAP_PIT 11 +#define KVM_CAP_NOP_IO_DELAY 12 +#define KVM_CAP_PV_MMU 13 +#define KVM_CAP_MP_STATE 14 +#define KVM_CAP_COALESCED_MMIO 15 +#define KVM_CAP_SYNC_MMU 16 /* Changes to host mmap are reflected in guest */ +#ifdef __KVM_HAVE_DEVICE_ASSIGNMENT +#define KVM_CAP_DEVICE_ASSIGNMENT 17 +#endif +#define KVM_CAP_IOMMU 18 +#ifdef __KVM_HAVE_MSI +#define KVM_CAP_DEVICE_MSI 20 +#endif +/* Bug in KVM_SET_USER_MEMORY_REGION fixed: */ +#define KVM_CAP_DESTROY_MEMORY_REGION_WORKS 21 +#ifdef __KVM_HAVE_USER_NMI +#define KVM_CAP_USER_NMI 22 +#endif +#ifdef __KVM_HAVE_GUEST_DEBUG +#define KVM_CAP_SET_GUEST_DEBUG 23 +#endif +#define KVM_CAP_REINJECT_CONTROL 24 +#ifdef __KVM_HAVE_IOAPIC +#define KVM_CAP_IRQ_ROUTING 25 +#endif +#define KVM_CAP_IRQ_INJECT_STATUS 26 +#ifdef __KVM_HAVE_DEVICE_ASSIGNMENT +#define KVM_CAP_DEVICE_DEASSIGNMENT 27 +#endif +#ifdef __KVM_HAVE_MSIX +#define KVM_CAP_DEVICE_MSIX 28 +#endif +#define KVM_CAP_ASSIGN_DEV_IRQ 29 +/* Another bug in KVM_SET_USER_MEMORY_REGION fixed: */ +#define KVM_CAP_JOIN_MEMORY_REGIONS_WORKS 30 +#define KVM_CAP_MCE 31 +#define KVM_CAP_IRQFD 32 +#define KVM_CAP_PIT2 33 +#define KVM_CAP_SET_BOOT_CPU_ID 34 +#define KVM_CAP_PIT_STATE2 35 +#define KVM_CAP_IOEVENTFD 36 +#define KVM_CAP_SET_IDENTITY_MAP_ADDR 37 +#define KVM_CAP_XEN_HVM 38 +#define KVM_CAP_ADJUST_CLOCK 39 +#define KVM_CAP_INTERNAL_ERROR_DATA 40 +#define KVM_CAP_VCPU_EVENTS 41 +#define KVM_CAP_S390_PSW 42 +#define KVM_CAP_PPC_SEGSTATE 43 +#define KVM_CAP_HYPERV 44 +#define KVM_CAP_HYPERV_VAPIC 45 +#define KVM_CAP_HYPERV_SPIN 46 +#define KVM_CAP_PCI_SEGMENT 47 +#define KVM_CAP_X86_ROBUST_SINGLESTEP 51 +#ifdef KVM_CAP_IRQ_ROUTING +typedef struct kvm_irq_routing_irqchip { + uint32_t irqchip; + uint32_t pin; +} kvm_irq_routing_irqchip_t; -#ifdef XXX -#define _IOR(type,nr,size) _IOC(_IOC_READ,(type),(nr),(_IOC_TYPECHECK(size))) -#define _IOW(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size))) -#define _IOWR(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),(_IOC_TYPECHECK(size))) -#define _IOR_BAD(type,nr,size) _IOC(_IOC_READ,(type),(nr),sizeof(size)) -#define _IOW_BAD(type,nr,size) _IOC(_IOC_WRITE,(type),(nr),sizeof(size)) -#define _IOWR_BAD(type,nr,size) _IOC(_IOC_READ|_IOC_WRITE,(type),(nr),sizeof(size)) -#endif /*XXX*/ -/* used to decode ioctl numbers.. */ -#define _IOC_DIR(nr) (((nr) >> _IOC_DIRSHIFT) & _IOC_DIRMASK) -#define _IOC_TYPE(nr) (((nr) >> _IOC_TYPESHIFT) & _IOC_TYPEMASK) -#define _IOC_NR(nr) (((nr) >> _IOC_NRSHIFT) & _IOC_NRMASK) -#define _IOC_SIZE(nr) (((nr) >> _IOC_SIZESHIFT) & _IOC_SIZEMASK) +typedef struct kvm_irq_routing_msi { + uint32_t address_lo; + uint32_t address_hi; + uint32_t data; + uint32_t pad; +} kvm_irq_routing_msi_t; -#define IOCSIZE_MASK (_IOC_SIZEMASK << _IOC_SIZESHIFT) -#define IOCSIZE_SHIFT (_IOC_SIZESHIFT) +/* gsi routing entry types */ +#define KVM_IRQ_ROUTING_IRQCHIP 1 +#define KVM_IRQ_ROUTING_MSI 2 -#endif /* _ASM_GENERIC_IOCTL_H */ +typedef struct kvm_irq_routing_entry { + uint32_t gsi; + uint32_t type; + uint32_t flags; + uint32_t pad; + union { + struct kvm_irq_routing_irqchip irqchip; + struct kvm_irq_routing_msi msi; + uint32_t pad[8]; + } u; +} kvm_irq_routing_entry_t; -/* ioctl commands */ +typedef struct kvm_irq_routing { + uint32_t nr; + uint32_t flags; + struct kvm_irq_routing_entry entries[1]; +} kvm_irq_routing_t; -#define KVMIO 0xAE +#endif /* KVM_CAP_IRQ_ROUTING */ +#ifdef KVM_CAP_MCE /* x86 MCE */ typedef struct kvm_x86_mce { uint64_t status; @@ -1331,6 +417,7 @@ typedef struct kvm_x86_mce { uint8_t pad1[7]; uint64_t pad2[3]; } kvm_x86_mce_t; +#endif /* KVM_CAP_MCE */ typedef struct kvm_clock_data { uint64_t clock; @@ -1338,101 +425,6 @@ typedef struct kvm_clock_data { uint32_t pad[9]; } kvm_clock_data_t; -/* for KVM_SET_SIGNAL_MASK */ -typedef struct kvm_signal_mask { - uint32_t len; - uint8_t sigset[1]; -} kvm_signal_mask_t; - -typedef struct kvm_set_boot_cpu_id_ioc { - int id; -} kvm_set_boot_cpu_id_ioc_t; - -/* - * ioctls for vcpu fds - */ -#define KVM_RUN _IO(KVMIO, 0x80) -#define KVM_GET_REGS _IOR(KVMIO, 0x81, struct kvm_regs) -#define KVM_SET_REGS _IOW(KVMIO, 0x82, struct kvm_regs) -#define KVM_GET_SREGS _IOR(KVMIO, 0x83, struct kvm_sregs) -#define KVM_SET_SREGS _IOW(KVMIO, 0x84, struct kvm_sregs) -#define KVM_INTERRUPT _IOW(KVMIO, 0x86, struct kvm_interrupt) -#define KVM_SET_CPUID _IOW(KVMIO, 0x8a, struct kvm_cpuid) -#define KVM_SET_SIGNAL_MASK _IOW(KVMIO, 0x8b, struct kvm_signal_mask) -#define KVM_GET_FPU _IOR(KVMIO, 0x8c, struct kvm_fpu) -#define KVM_SET_FPU _IOW(KVMIO, 0x8d, struct kvm_fpu) -#define KVM_GET_MSRS _IOWR(KVMIO, 0x88, struct kvm_msrs) -#define KVM_SET_MSRS _IOW(KVMIO, 0x89, struct kvm_msrs) -#define KVM_GET_LAPIC _IOR(KVMIO, 0x8e, struct kvm_lapic_state) -#define KVM_SET_LAPIC _IOW(KVMIO, 0x8f, struct kvm_lapic_state) -#define KVM_GET_MP_STATE _IOR(KVMIO, 0x98, struct kvm_mp_state) -#define KVM_SET_MP_STATE _IOW(KVMIO, 0x99, struct kvm_mp_state) -/* MCE for x86 */ -#define KVM_X86_SETUP_MCE _IOW(KVMIO, 0x9c, uint64_t) -#define KVM_X86_GET_MCE_CAP_SUPPORTED _IOR(KVMIO, 0x9d, uint64_t) -#define KVM_X86_SET_MCE _IOW(KVMIO, 0x9e, struct kvm_x86_mce) - -#define KVM_REINJECT_CONTROL _IO(KVMIO, 0x71) -#define KVM_SET_BOOT_CPU_ID _IO(KVMIO, 0x78) - -#define KVM_SET_CLOCK _IOW(KVMIO, 0x7b, struct kvm_clock_data) -#define KVM_GET_CLOCK _IOR(KVMIO, 0x7c, struct kvm_clock_data) - -/* Available with KVM_CAP_VCPU_EVENTS */ -#define KVM_GET_VCPU_EVENTS _IOR(KVMIO, 0x9f, struct kvm_vcpu_events) -#define KVM_SET_VCPU_EVENTS _IOW(KVMIO, 0xa0, struct kvm_vcpu_events) -/* Available with KVM_CAP_PIT_STATE2 */ -#define KVM_GET_PIT2 _IOR(KVMIO, 0x9f, struct kvm_pit_state2) -#define KVM_SET_PIT2 _IOW(KVMIO, 0xa0, struct kvm_pit_state2) - - - -/* - * ioctls for /dev/kvm fds: - */ -#define KVM_GET_API_VERSION _IO(KVMIO, 0x00) -#define KVM_CREATE_VM _IO(KVMIO, 0x01) /* returns a VM fd */ -#define KVM_DESTROY_VM _IO(KVMIO, 0x0a) -#define KVM_CLONE _IO(KVMIO, 0x20) -#define KVM_NET_QUEUE _IO(KVMIO, 0x21) - -#define KVM_GET_MSR_INDEX_LIST _IOWR(KVMIO, 0x02, struct kvm_msr_list) - -#define KVM_S390_ENABLE_SIE _IO(KVMIO, 0x06) - -#define KVM_GET_VCPU_MMAP_SIZE _IO(KVMIO, 0x04) /* in bytes */ - -#define KVM_GET_SUPPORTED_CPUID _IOWR(KVMIO, 0x05, struct kvm_cpuid2) - -/* for KVM_IRQ_LINE */ -typedef struct kvm_irq_level { - /* - * ACPI gsi notion of irq. - * For IA-64 (APIC model) IOAPIC0: irq 0-23; IOAPIC1: irq 24-47.. - * For X86 (standard AT mode) PIC0/1: irq 0-15. IOAPIC0: 0-23.. - */ - union { - uint32_t irq; - int32_t status; - }; - uint32_t level; -} kvm_irq_level_t; - -/* - * for KVM_SET_IDENTITY_MAP_ADDR - */ - -typedef struct kvm_id_map_addr { - int pad; - uint64_t addr; -} kvm_id_map_addr_t; - -/* for KVM_SET_IDENTITY_MAP_ADDR */ -typedef struct kvm_id_map_addr_ioc { - uint64_t ident_addr; -} kvm_id_map_addr_ioc_t; - - /* * ioctls for VM fds */ @@ -1445,612 +437,98 @@ typedef struct kvm_id_map_addr_ioc { #define KVM_GET_DIRTY_LOG _IOW(KVMIO, 0x42, struct kvm_dirty_log) #define KVM_SET_NR_MMU_PAGES _IO(KVMIO, 0x44) #define KVM_GET_NR_MMU_PAGES _IO(KVMIO, 0x45) +#define KVM_SET_USER_MEMORY_REGION _IOW(KVMIO, 0x46, \ + struct kvm_userspace_memory_region) + #define KVM_SET_TSS_ADDR _IO(KVMIO, 0x47) #define KVM_SET_IDENTITY_MAP_ADDR _IOW(KVMIO, 0x48, struct kvm_id_map_addr_ioc) + /* Device model IOC */ #define KVM_CREATE_IRQCHIP _IO(KVMIO, 0x60) #define KVM_IRQ_LINE _IOW(KVMIO, 0x61, struct kvm_irq_level) -#define KVM_IRQ_LINE_STATUS _IOWR(KVMIO, 0x67, struct kvm_irq_level) #define KVM_GET_IRQCHIP _IOWR(KVMIO, 0x62, struct kvm_irqchip) #define KVM_SET_IRQCHIP _IOR(KVMIO, 0x63, struct kvm_irqchip) - -#define KVM_PIT_SPEAKER_DUMMY 1 - #define KVM_CREATE_PIT _IO(KVMIO, 0x64) #define KVM_GET_PIT _IOWR(KVMIO, 0x65, struct kvm_pit_state) #define KVM_SET_PIT _IOR(KVMIO, 0x66, struct kvm_pit_state) -#define KVM_CREATE_PIT2 _IOW(KVMIO, 0x77, struct kvm_pit_config) - +#define KVM_IRQ_LINE_STATUS _IOWR(KVMIO, 0x67, struct kvm_irq_level) #define KVM_REGISTER_COALESCED_MMIO \ _IOW(KVMIO, 0x67, struct kvm_coalesced_mmio_zone_ioc) #define KVM_UNREGISTER_COALESCED_MMIO \ _IOW(KVMIO, 0x68, struct kvm_coalesced_mmio_zone_ioc) - -#define KVM_SET_GSI_ROUTING _IOW(KVMIO, 0x6a, struct kvm_kirq_routing) +#define KVM_SET_GSI_ROUTING _IOW(KVMIO, 0x6a, struct kvm_irq_routing) +#define KVM_REINJECT_CONTROL _IO(KVMIO, 0x71) +#define KVM_CREATE_PIT2 _IOW(KVMIO, 0x77, struct kvm_pit_config) +#define KVM_SET_BOOT_CPU_ID _IO(KVMIO, 0x78) +#define KVM_SET_CLOCK _IOW(KVMIO, 0x7b, struct kvm_clock_data) +#define KVM_GET_CLOCK _IOR(KVMIO, 0x7c, struct kvm_clock_data) +/* Available with KVM_CAP_PIT_STATE2 */ +#define KVM_GET_PIT2 _IOR(KVMIO, 0x9f, struct kvm_pit_state2) +#define KVM_SET_PIT2 _IOW(KVMIO, 0xa0, struct kvm_pit_state2) /* - * Check if a kvm extension is available. Argument is extension number, - * return is 1 (yes) or 0 (no, sorry). + * ioctls for vcpu fds */ -#define KVM_CHECK_EXTENSION _IO(KVMIO, 0x03) - -/* for KVM_INTERRUPT */ -typedef struct kvm_interrupt { - /* in */ - uint32_t irq; -} kvm_interrupt_t; - -/* for KVM_GET_DIRTY_LOG */ -typedef struct kvm_dirty_log { - uint32_t slot; - uint32_t padding1; - union { - void *dirty_bitmap; /* one bit per page */ - uint64_t padding2; - }v; -} kvm_dirty_log_t; - -typedef struct kvm_coalesced_mmio { - uint64_t phys_addr; - uint32_t len; - uint32_t pad; - unsigned char data[8]; -} kvm_coalesced_mmio_t; - -typedef struct kvm_coalesced_mmio_ring { - uint32_t first, last; - struct kvm_coalesced_mmio coalesced_mmio[1]; -} kvm_coalesced_mmio_ring_t; - -#define KVM_COALESCED_MMIO_MAX \ - ((PAGESIZE - sizeof(struct kvm_coalesced_mmio_ring)) / \ - sizeof(struct kvm_coalesced_mmio)) - -/* for KVM_SET_VAPIC_ADDR */ -typedef struct kvm_vapic_addr { - uint64_t vapic_addr; -} kvm_vapic_addr_t; - -/* for KVM_SET_MP_STATE */ -#define KVM_MP_STATE_RUNNABLE 0 -#define KVM_MP_STATE_UNINITIALIZED 1 -#define KVM_MP_STATE_INIT_RECEIVED 2 -#define KVM_MP_STATE_HALTED 3 -#define KVM_MP_STATE_SIPI_RECEIVED 4 - -/* for KVM_TPR_ACCESS_REPORTING */ -typedef struct kvm_tpr_access_ctl { - uint32_t enabled; - uint32_t flags; - uint32_t reserved[8]; -} kvm_tpr_access_ctl_t; - -typedef struct kvm_tpr_acl_ioc { - struct kvm_tpr_access_ctl tac; - int kvm_id; - int cpu_index; -} kvm_tpr_acl_ioc_t; - +#define KVM_RUN _IO(KVMIO, 0x80) +#define KVM_GET_REGS _IOR(KVMIO, 0x81, struct kvm_regs) +#define KVM_SET_REGS _IOW(KVMIO, 0x82, struct kvm_regs) +#define KVM_GET_SREGS _IOR(KVMIO, 0x83, struct kvm_sregs) +#define KVM_SET_SREGS _IOW(KVMIO, 0x84, struct kvm_sregs) +#define KVM_INTERRUPT _IOW(KVMIO, 0x86, struct kvm_interrupt) +#define KVM_GET_MSRS _IOWR(KVMIO, 0x88, struct kvm_msrs) +#define KVM_SET_MSRS _IOW(KVMIO, 0x89, struct kvm_msrs) +#define KVM_SET_CPUID _IOW(KVMIO, 0x8a, struct kvm_cpuid) +#define KVM_SET_SIGNAL_MASK _IOW(KVMIO, 0x8b, struct kvm_signal_mask) +#define KVM_GET_FPU _IOR(KVMIO, 0x8c, struct kvm_fpu) +#define KVM_SET_FPU _IOW(KVMIO, 0x8d, struct kvm_fpu) +#define KVM_GET_LAPIC _IOR(KVMIO, 0x8e, struct kvm_lapic_state) +#define KVM_SET_LAPIC _IOW(KVMIO, 0x8f, struct kvm_lapic_state) #define KVM_SET_CPUID2 _IOW(KVMIO, 0x90, struct kvm_cpuid2) #define KVM_GET_CPUID2 _IOWR(KVMIO, 0x91, struct kvm_cpuid2) /* Available with KVM_CAP_VAPIC */ #define KVM_TPR_ACCESS_REPORTING _IOWR(KVMIO, 0x92, struct kvm_tpr_acl_ioc) /* Available with KVM_CAP_VAPIC */ #define KVM_SET_VAPIC_ADDR _IOW(KVMIO, 0x93, struct kvm_vapic_addr) +#define KVM_GET_MP_STATE _IOR(KVMIO, 0x98, struct kvm_mp_state) +#define KVM_SET_MP_STATE _IOW(KVMIO, 0x99, struct kvm_mp_state) +/* MCE for x86 */ +#define KVM_X86_SETUP_MCE _IOW(KVMIO, 0x9c, uint64_t) +#define KVM_X86_GET_MCE_CAP_SUPPORTED _IOR(KVMIO, 0x9d, uint64_t) +#define KVM_X86_SET_MCE _IOW(KVMIO, 0x9e, struct kvm_x86_mce) +/* Available with KVM_CAP_VCPU_EVENTS */ +#define KVM_GET_VCPU_EVENTS _IOR(KVMIO, 0x9f, struct kvm_vcpu_events) +#define KVM_SET_VCPU_EVENTS _IOW(KVMIO, 0xa0, struct kvm_vcpu_events) -#define APIC_BUS_CYCLE_NS 1 -#define NSEC_PER_MSEC 1000000L -#define NSEC_PER_SEC 1000000000L - -/* for kvm_memory_region::flags */ -#define KVM_MEM_LOG_DIRTY_PAGES 1UL -#define KVM_MEMSLOT_INVALID (1UL << 1) - - -/* for KVM_CREATE_MEMORY_REGION */ -typedef struct kvm_memory_region { - uint32_t slot; - uint32_t flags; - uint64_t guest_phys_addr; - uint64_t memory_size; /* bytes */ -} kvm_memory_region_t; - -/* for KVM_SET_USER_MEMORY_REGION */ -typedef struct kvm_userspace_memory_region { - uint32_t slot; - uint32_t flags; - uint64_t guest_phys_addr; - uint64_t memory_size; /* bytes */ - uint64_t userspace_addr; /* start of the userspace allocated memory */ -} kvm_userspace_memory_region_t; - -#ifndef XXX -#define KVM_SET_USER_MEMORY_REGION _IOW(KVMIO, 0x46, \ - struct kvm_userspace_memory_region) -#else -#define KVM_SET_USER_MEMORY_REGION _IOW(KVMIO, 0x46, \ - struct kvm_set_user_memory_ioc) -#endif /*XXX*/ - +/* + * XXX Additions which probably are changes from qemu/kvm upstream + */ /* for KVM_SET_TSS_ADDR ioctl */ typedef struct kvm_tss { - uint64_t addr; /* in */ + uint64_t addr; /* in */ } kvm_tss_t; -/* for KVM_CREATE_VCPU */ -typedef struct kvm_vcpu_ioc { - uint32_t id; /*IN*/ - uint64_t kvm_run_addr; /*OUT*/ - uint64_t kvm_vcpu_addr; /* OUT, id is not unique across VMs */ -} kvm_vcpu_ioc_t; - - - -/* LDT or TSS descriptor in the GDT. 16 bytes. */ -struct ldttss_desc64 { - unsigned short limit0; - unsigned short base0; - unsigned base1 : 8, type : 5, dpl : 2, p : 1; - unsigned limit1 : 4, zero0 : 3, g : 1, base2 : 8; - uint32_t base3; - uint32_t zero1; -} __attribute__((packed)); - -typedef struct ldttss_desc64 ldttss_desc64_t; - -#ifdef _KERNEL - -#define kvm_for_each_vcpu(idx, vcpup, kvm) \ - for (idx = 0, vcpup = kvm_get_vcpu(kvm, idx); \ - idx < kvm->online_vcpus && vcpup; /* XXX - need protection */ \ - vcpup = kvm_get_vcpu(kvm, ++idx)) - -extern struct kvm_vcpu *kvm_get_vcpu(struct kvm *kvm, int i); - -typedef struct kvm_irq_mask_notifier { - void (*func)(struct kvm_irq_mask_notifier *kimn, int masked); - int irq; - struct list_node link; -} kvm_irq_mask_notifier_t; - -/* Intel-defined CPU features, CPUID level 0x00000001 (edx), word 0 */ -#define X86_FEATURE_FPU (0 * 32 + 0) /* Onboard FPU */ -#define X86_FEATURE_VME (0 * 32 + 1) /* Virtual Mode Extensions */ -#define X86_FEATURE_DE (0 * 32 + 2) /* Debugging Extensions */ -#define X86_FEATURE_PSE (0 * 32 + 3) /* Page Size Extensions */ -#define X86_FEATURE_TSC (0 * 32 + 4) /* Time Stamp Counter */ -#define X86_FEATURE_MSR (0 * 32 + 5) /* Model-Specific Registers */ -#define X86_FEATURE_PAE (0 * 32 + 6) /* Phys. Address Extensions */ -#define X86_FEATURE_MCE (0 * 32 + 7) /* Machine Check Exception */ -#define X86_FEATURE_CX8 (0 * 32 + 8) /* CMPXCHG8 instruction */ -#define X86_FEATURE_APIC (0 * 32 + 9) /* Onboard APIC */ -#define X86_FEATURE_SEP (0 * 32 + 11) /* SYSENTER/SYSEXIT */ -#define X86_FEATURE_MTRR (0 * 32 + 12) /* Memory Type Range Regs. */ -#define X86_FEATURE_PGE (0 * 32 + 13) /* Page Global Enable */ -#define X86_FEATURE_MCA (0 * 32 + 14) /* Machine Check Architecture */ -#define X86_FEATURE_CMOV (0 * 32 + 15) /* CMOV instructions */ - /* (+ FCMOVcc, FCOMI w/ FPU) */ -#define X86_FEATURE_PAT (0 * 32 + 16) /* Page Attribute Table */ -#define X86_FEATURE_PSE36 (0 * 32 + 17) /* 36-bit PSEs */ -#define X86_FEATURE_PN (0 * 32 + 18) /* Processor serial number */ -#define X86_FEATURE_CLFLSH (0 * 32 + 19) /* "clflush" instruction */ -#define X86_FEATURE_DS (0 * 32 + 21) /* "dts" Debug Store */ -#define X86_FEATURE_ACPI (0 * 32 + 22) /* ACPI via MSR */ -#define X86_FEATURE_MMX (0 * 32 + 23) /* Multimedia Extensions */ -#define X86_FEATURE_FXSR (0 * 32 + 24) /* FXSAVE/FXRSTOR, CR4.OSFXSR */ -#define X86_FEATURE_XMM (0 * 32 + 25) /* "sse" */ -#define X86_FEATURE_XMM2 (0 * 32 + 26) /* "sse2" */ -#define X86_FEATURE_SELFSNOOP (0 * 32 + 27) /* "ss" CPU self snoop */ -#define X86_FEATURE_HT (0 * 32 + 28) /* Hyper-Threading */ -#define X86_FEATURE_ACC (0 * 32 + 29) /* "tm" Auto. clock control */ -#define X86_FEATURE_IA64 (0 * 32 + 30) /* IA-64 processor */ -#define X86_FEATURE_PBE (0 * 32 + 31) /* Pending Break Enable */ - -/* AMD-defined CPU features, CPUID level 0x80000001, word 1 */ -/* Don't duplicate feature flags which are redundant with Intel! */ -#define X86_FEATURE_SYSCALL (1 * 32 + 11) /* SYSCALL/SYSRET */ -#define X86_FEATURE_MP (1 * 32 + 19) /* MP Capable. */ -#define X86_FEATURE_NX (1 * 32 + 20) /* Execute Disable */ -#define X86_FEATURE_MMXEXT (1 * 32 + 22) /* AMD MMX extensions */ -#define X86_FEATURE_FXSR_OPT (1 * 32 + 25) /* FXSAVE/FXRSTOR optimiztns */ -#define X86_FEATURE_GBPAGES (1 * 32 + 26) /* "pdpe1gb" GB pages */ -#define X86_FEATURE_RDTSCP (1 * 32 + 27) /* RDTSCP */ -#define X86_FEATURE_LM (1 * 32 + 29) /* Long Mode (x86-64) */ -#define X86_FEATURE_3DNOWEXT (1 * 32 + 30) /* AMD 3DNow! extensions */ -#define X86_FEATURE_3DNOW (1 * 32 + 31) /* 3DNow! */ - -/* cpu types for specific tunings: */ -#define X86_FEATURE_K8 (3 * 32 + 4) /* "" Opteron, Athlon64 */ -#define X86_FEATURE_K7 (3 * 32 + 5) /* "" Athlon */ -#define X86_FEATURE_P3 (3 * 32 + 6) /* "" P3 */ -#define X86_FEATURE_P4 (3 * 32 + 7) /* "" P4 */ -#define X86_FEATURE_CONSTANT_TSC (3 * 32 + 8) /* TSC ticks at constant rate */ -#define X86_FEATURE_UP (3 * 32 + 9) /* smp kernel running on up */ -#define X86_FEATURE_FXSAVE_LEAK (3 * 32 + 10) /* FXSAVE leaks FOP/FIP/FOP */ -#define X86_FEATURE_ARCH_PERFMON (3 * 32 + 11) /* Intel Arch. PerfMon */ -#define X86_FEATURE_PEBS (3 * 32 + 12) /* Precise-Event Based Smplng */ -#define X86_FEATURE_BTS (3 * 32 + 13) /* Branch Trace Store */ -#define X86_FEATURE_SYSCALL32 (3 * 32 + 14) /* syscall in ia32 userspace */ -#define X86_FEATURE_SYSENTER32 (3 * 32 + 15) /* sysenter in ia32 userspace */ -#define X86_FEATURE_REP_GOOD (3 * 32 + 16) /* rep microcode works well */ -#define X86_FEATURE_MFENCE_RDTSC (3 * 32 + 17) /* Mfence synchronizes RDTSC */ -#define X86_FEATURE_LFENCE_RDTSC (3 * 32 + 18) /* Lfence synchronizes RDTSC */ -#define X86_FEATURE_11AP (3 * 32 + 19) /* Bad local APIC aka 11AP */ -#define X86_FEATURE_NOPL (3 * 32 + 20) /* NOPL (0F 1F) instructions */ -#define X86_FEATURE_AMDC1E (3 * 32 + 21) /* AMD C1E detected */ -#define X86_FEATURE_XTOPOLOGY (3 * 32 + 22) /* topology enum extensions */ -#define X86_FEATURE_TSC_RELIABLE (3 * 32 + 23) /* TSC is reliable */ -#define X86_FEATURE_NONSTOP_TSC (3 * 32 + 24) /* TSC continues in C states */ -#define X86_FEATURE_CLFLUSH_MONITOR (3 * 32 + 25) /* clflush reqd w/ monitor */ -#define X86_FEATURE_EXTD_APICID (3 * 32 + 26) /* extended APICID (8 bits) */ -#define X86_FEATURE_AMD_DCM (3 * 32 + 27) /* multi-node processor */ -#define X86_FEATURE_APERFMPERF (3 * 32 + 28) /* APERFMPERF */ - -/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ -#define X86_FEATURE_XMM3 (4 * 32 + 0) /* "pni" SSE-3 */ -#define X86_FEATURE_PCLMULQDQ (4 * 32 + 1) /* PCLMULQDQ instruction */ -#define X86_FEATURE_DTES64 (4 * 32 + 2) /* 64-bit Debug Store */ -#define X86_FEATURE_MWAIT (4 * 32 + 3) /* "monitor" Monitor/Mwait */ -#define X86_FEATURE_DSCPL (4 * 32 + 4) /* ds_cpl CPL Qual Debug Str */ -#define X86_FEATURE_VMX (4 * 32 + 5) /* Hardware virtualization */ -#define X86_FEATURE_SMX (4 * 32 + 6) /* Safer mode */ -#define X86_FEATURE_EST (4 * 32 + 7) /* Enhanced SpeedStep */ -#define X86_FEATURE_TM2 (4 * 32 + 8) /* Thermal Monitor 2 */ -#define X86_FEATURE_SSSE3 (4 * 32 + 9) /* Supplemental SSE-3 */ -#define X86_FEATURE_CID (4 * 32 + 10) /* Context ID */ -#define X86_FEATURE_FMA (4 * 32 + 12) /* Fused multiply-add */ -#define X86_FEATURE_CX16 (4 * 32 + 13) /* CMPXCHG16B */ -#define X86_FEATURE_XTPR (4 * 32 + 14) /* Send Task Priority Msgs */ -#define X86_FEATURE_PDCM (4 * 32 + 15) /* Performance Capabilities */ -#define X86_FEATURE_DCA (4 * 32 + 18) /* Direct Cache Access */ -#define X86_FEATURE_XMM4_1 (4 * 32 + 19) /* "sse4_1" SSE-4.1 */ -#define X86_FEATURE_XMM4_2 (4 * 32 + 20) /* "sse4_2" SSE-4.2 */ -#define X86_FEATURE_X2APIC (4 * 32 + 21) /* x2APIC */ -#define X86_FEATURE_MOVBE (4 * 32 + 22) /* MOVBE instruction */ -#define X86_FEATURE_POPCNT (4 * 32 + 23) /* POPCNT instruction */ -#define X86_FEATURE_AES (4 * 32 + 25) /* AES instructions */ -#define X86_FEATURE_XSAVE (4 * 32 + 26) /* XSAVE/XRSTOR/XSETBV/XGETBV */ -#define X86_FEATURE_OSXSAVE (4 * 32 + 27) /* "" XSAVE enabled in the OS */ -#define X86_FEATURE_AVX (4 * 32 + 28) /* Advanced Vector Extensions */ -#define X86_FEATURE_HYPERVISOR (4 * 32 + 31) /* Running on a hypervisor */ - -/* More extended AMD flags: CPUID level 0x80000001, ecx, word 6 */ -#define X86_FEATURE_LAHF_LM (6 * 32 + 0) /* LAHF/SAHF in long mode */ -#define X86_FEATURE_CMP_LEGACY (6 * 32 + 1) /* HyperThreading invalid */ -#define X86_FEATURE_SVM (6 * 32 + 2) /* Secure virtual machine */ -#define X86_FEATURE_EXTAPIC (6 * 32 + 3) /* Extended APIC space */ -#define X86_FEATURE_CR8_LEGACY (6 * 32 + 4) /* CR8 in 32-bit mode */ -#define X86_FEATURE_ABM (6 * 32 + 5) /* Advanced bit manipulation */ -#define X86_FEATURE_SSE4A (6 * 32 + 6) /* SSE-4A */ -#define X86_FEATURE_MISALIGNSSE (6 * 32 + 7) /* Misaligned SSE mode */ -#define X86_FEATURE_3DNOWPREFETCH (6 * 32 + 8) /* 3DNow prefetch */ -#define X86_FEATURE_OSVW (6 * 32 + 9) /* OS Visible Workaround */ -#define X86_FEATURE_IBS (6 * 32 + 10) /* Instruction Based Sampling */ -#define X86_FEATURE_SSE5 (6 * 32 + 11) /* SSE-5 */ -#define X86_FEATURE_SKINIT (6 * 32 + 12) /* SKINIT/STGI instructions */ -#define X86_FEATURE_WDT (6 * 32 + 13) /* Watchdog timer */ -#define X86_FEATURE_NODEID_MSR (6 * 32 + 19) /* NodeId MSR */ - -/* Transmeta-defined CPU features, CPUID level 0x80860001, word 2 */ -#define X86_FEATURE_RECOVERY (2 * 32 + 0) /* CPU in recovery mode */ -#define X86_FEATURE_LONGRUN (2 * 32 + 1) /* Longrun power control */ -#define X86_FEATURE_LRTI (2 * 32 + 3) /* LongRun table interface */ - - -#ifdef __KVM_HAVE_IOAPIC -void kvm_get_intr_delivery_bitmask(struct kvm_ioapic *ioapic, - union kvm_ioapic_redirect_entry *entry, - unsigned long *deliver_bitmask); -#endif -int kvm_set_irq(struct kvm *kvm, int irq_source_id, uint32_t irq, int level); -void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin); -void kvm_register_irq_ack_notifier(struct kvm *kvm, - struct kvm_irq_ack_notifier *kian); -void kvm_unregister_irq_ack_notifier(struct kvm *kvm, - struct kvm_irq_ack_notifier *kian); -int kvm_request_irq_source_id(struct kvm *kvm); -void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id); - -#ifdef CONFIG_HAVE_KVM_IRQCHIP - -int kvm_setup_default_irq_routing(struct kvm *kvm); -int kvm_set_irq_routing(struct kvm *kvm, - const struct kvm_irq_routing_entry *entries, - unsigned nr, - unsigned flags); -void kvm_free_irq_routing(struct kvm *kvm); - -#else - -static void kvm_free_irq_routing(struct kvm *kvm) {} - -#endif /*CONFIG_HAVE_KVM_IRQCHIP*/ - /* - * vcpu->requests bit members - */ -#define KVM_REQ_TLB_FLUSH 0 -#define KVM_REQ_MIGRATE_TIMER 1 -#define KVM_REQ_REPORT_TPR_ACCESS 2 -#define KVM_REQ_MMU_RELOAD 3 -#define KVM_REQ_TRIPLE_FAULT 4 -#define KVM_REQ_PENDING_TIMER 5 -#define KVM_REQ_UNHALT 6 -#define KVM_REQ_MMU_SYNC 7 -#define KVM_REQ_KVMCLOCK_UPDATE 8 -#define KVM_REQ_KICK 9 -#define KVM_REQ_DEACTIVATE_FPU 10 - -#define KVM_USERSPACE_IRQ_SOURCE_ID 0 - -#define RW_STATE_LSB 1 -#define RW_STATE_MSB 2 -#define RW_STATE_WORD0 3 -#define RW_STATE_WORD1 4 - -#define page_to_pfn(page) (page->p_pagenum) - -#ifdef XXX -#define __ex(x) __kvm_handle_fault_on_reboot(x) -#endif /*XXX*/ - -#ifdef CONFIG_PREEMPT_NOTIFIERS -#ifdef XXX - -struct preempt_notifier; - -/** - * preempt_ops - notifiers called when a task is preempted and rescheduled - * @sched_in: we're about to be rescheduled: - * notifier: struct preempt_notifier for the task being scheduled - * cpu: cpu we're scheduled on - * @sched_out: we've just been preempted - * notifier: struct preempt_notifier for the task being preempted - * next: the task that's kicking us out - * - * Please note that sched_in and out are called under different - * contexts. sched_out is called with rq lock held and irq disabled - * while sched_in is called without rq lock and irq enabled. This - * difference is intentional and depended upon by its users. - */ -typedef struct preempt_ops { - void (*sched_in)(struct preempt_notifier *notifier, int cpu); - void (*sched_out)(struct preempt_notifier *notifier, - struct task_struct *next); -} preempt_ops_t; - -/** - * preempt_notifier - key for installing preemption notifiers - * @link: internal use - * @ops: defines the notifier functions to be called - * - * Usually used in conjunction with container_of(). - */ -typedef struct preempt_notifier { - struct hlist_node link; - struct preempt_ops *ops; -} preempt_notifier_t; - -void preempt_notifier_register(struct preempt_notifier *notifier); -void preempt_notifier_unregister(struct preempt_notifier *notifier); -void preempt_notifier_init(struct preempt_notifier *notifier, - struct preempt_ops *ops); - -#endif /*XXX*/ -#endif /*CONFIG_PREEMPT_NOTIFIERS*/ -typedef struct cpuid_data { - struct kvm_cpuid2 cpuid; - struct kvm_cpuid_entry2 entries[100]; -} __attribute__((packed)) cpuid_data; - -/* - * It would be nice to use something smarter than a linear search, TBD... - * Thankfully we dont expect many devices to register (famous last words :), - * so until then it will suffice. At least its abstracted so we can change - * in one place. + * for KVM_SET_IDENTITY_MAP_ADDR */ -typedef struct kvm_io_bus { - int dev_count; -#define NR_IOBUS_DEVS 200 - struct kvm_io_device *devs[NR_IOBUS_DEVS]; -} kvm_io_bus_t; - -int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr, - int len, const void *val); -int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr, int len, - void *val); -int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, - struct kvm_io_device *dev); -int kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx, - struct kvm_io_device *dev); - -unsigned long kvm_dirty_bitmap_bytes(struct kvm_memory_slot *memslot); - -int kvm_set_memory_region(struct kvm *kvm, - struct kvm_userspace_memory_region *mem, - int user_alloc); -int __kvm_set_memory_region(struct kvm *kvm, - struct kvm_userspace_memory_region *mem, - int user_alloc); -int kvm_arch_prepare_memory_region(struct kvm *kvm, - struct kvm_memory_slot *memslot, - struct kvm_memory_slot old, - struct kvm_userspace_memory_region *mem, - int user_alloc); -void kvm_arch_commit_memory_region(struct kvm *kvm, - struct kvm_userspace_memory_region *mem, - struct kvm_memory_slot old, - int user_alloc); - -int is_error_page(struct page *page); -int is_error_pfn(pfn_t pfn); -int kvm_is_error_hva(unsigned long addr); -void kvm_disable_largepages(void); -void kvm_arch_flush_shadow(struct kvm *kvm); -gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn); -gfn_t unalias_gfn_instantiation(struct kvm *kvm, gfn_t gfn); - -page_t *gfn_to_page(struct kvm *kvm, gfn_t gfn); -unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn); -void kvm_release_page_clean(struct page *page); -void kvm_release_page_dirty(struct page *page); -void kvm_set_page_dirty(struct page *page); -void kvm_set_page_accessed(struct page *page); - -pfn_t gfn_to_pfn(struct kvm *kvm, gfn_t gfn); -pfn_t gfn_to_pfn_memslot(struct kvm *kvm, - struct kvm_memory_slot *slot, gfn_t gfn); -int memslot_id(struct kvm *kvm, gfn_t gfn); -void kvm_get_pfn(struct kvm_vcpu *vcpu, pfn_t pfn); - -int kvm_read_guest_page(struct kvm *kvm, gfn_t gfn, void *data, int offset, - int len); -int kvm_read_guest_atomic(struct kvm *kvm, gpa_t gpa, void *data, - unsigned long len); -int kvm_read_guest(struct kvm *kvm, gpa_t gpa, void *data, unsigned long len); -int kvm_write_guest_page(struct kvm *kvm, gfn_t gfn, const void *data, - int offset, int len); -int kvm_write_guest(struct kvm *kvm, gpa_t gpa, const void *data, - unsigned long len); -int kvm_clear_guest_page(struct kvm *kvm, gfn_t gfn, int offset, int len); -int kvm_clear_guest(struct kvm *kvm, gpa_t gpa, unsigned long len); -struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn); -int kvm_is_visible_gfn(struct kvm *kvm, gfn_t gfn); -unsigned long kvm_host_page_size(struct kvm *kvm, gfn_t gfn); -void mark_page_dirty(struct kvm *kvm, gfn_t gfn); - -void kvm_vcpu_block(struct kvm_vcpu *vcpu); -void kvm_vcpu_on_spin(struct kvm_vcpu *vcpu); -void kvm_resched(struct kvm_vcpu *vcpu); -void kvm_load_guest_fpu(struct kvm_vcpu *vcpu); -void kvm_put_guest_fpu(struct kvm_vcpu *vcpu); -void kvm_flush_remote_tlbs(struct kvm *kvm); -void kvm_reload_remote_mmus(struct kvm *kvm); - -long kvm_arch_dev_ioctl(struct file *filp, - unsigned int ioctl, unsigned long arg); -long kvm_arch_vcpu_ioctl(struct file *filp, - unsigned int ioctl, unsigned long arg); - -int kvm_get_dirty_log(struct kvm *kvm, - struct kvm_dirty_log *log, int *is_dirty); -int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, - struct kvm_dirty_log *log); - -int kvm_vm_ioctl_set_memory_region(struct kvm *kvm, - struct - kvm_userspace_memory_region *mem, - int user_alloc); -long kvm_arch_vm_ioctl(struct file *filp, - unsigned int ioctl, unsigned long arg); - -int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu); -int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu); - -#ifdef XXX -int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu, - struct kvm_translation *tr); -#endif /*XXX*/ - -int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs); -int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs); -int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu, - struct kvm_sregs *sregs); -int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, - struct kvm_sregs *sregs); -int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu, - struct kvm_mp_state *mp_state); -int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu, - struct kvm_mp_state *mp_state); -int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, - struct kvm_guest_debug *dbg); -int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu); - -int kvm_arch_init(void *opaque); -void kvm_arch_exit(void); - -int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu); -void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu); - -void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu); -void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu); -void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu); -int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu); -void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu); -int kvm_arch_vcpu_reset(struct kvm_vcpu *vcpu); -int kvm_arch_hardware_enable(void *garbage); -void kvm_arch_hardware_disable(void *garbage); -int kvm_arch_hardware_setup(void); -void kvm_arch_hardware_unsetup(void); -void kvm_arch_check_processor_compat(void *rtn); -int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu); - -void kvm_free_physmem(struct kvm *kvm); - -void kvm_vcpu_uninit(struct kvm_vcpu *); - -struct kvm *kvm_arch_create_vm(void); -void kvm_arch_destroy_vm(struct kvm *kvm); -void kvm_arch_destroy_vm_comps(struct kvm *kvm); -void kvm_free_all_assigned_devices(struct kvm *kvm); -void kvm_arch_sync_events(struct kvm *kvm); - -int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu); -void kvm_vcpu_kick(struct kvm_vcpu *vcpu); - -void kvm_sigprocmask(int how, sigset_t *, sigset_t *); - -void kvm_register_irq_mask_notifier(struct kvm *kvm, int irq, - struct kvm_irq_mask_notifier *kimn); -void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq, - struct kvm_irq_mask_notifier *kimn); -void kvm_fire_mask_notifiers(struct kvm *kvm, int irq, int mask); - -extern int irqchip_in_kernel(struct kvm *kvm); -extern void kvm_inject_nmi(struct kvm_vcpu *); - -int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot); -int kvm_iommu_map_guest(struct kvm *kvm); -int kvm_iommu_unmap_guest(struct kvm *kvm); -int kvm_assign_device(struct kvm *kvm, - struct kvm_assigned_dev_kernel *assigned_dev); -int kvm_deassign_device(struct kvm *kvm, - struct kvm_assigned_dev_kernel *assigned_dev); - -extern unsigned long kvm_rip_read(struct kvm_vcpu *); -extern int kvm_vcpu_is_bsp(struct kvm_vcpu *); - -extern struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct kvm_vcpu *vcpu, - uint32_t function, uint32_t index); - -#define BITS_PER_LONG (sizeof (unsigned long) * 8) - -#define MSR_EFER 0xc0000080 /* extended feature register */ - -#define KVM_TRACE1(name, type1, arg1) \ - DTRACE_PROBE1(kvm__##name, type1, arg1); - -#define KVM_TRACE2(name, type1, arg1, type2, arg2) \ - DTRACE_PROBE2(kvm__##name, type1, arg1, type2, arg2); - -#define KVM_TRACE3(name, type1, arg1, type2, arg2, type3, arg3) \ - DTRACE_PROBE3(kvm__##name, type1, arg1, type2, arg2, type3, arg3); +typedef struct kvm_id_map_addr { + int pad; + uint64_t addr; +} kvm_id_map_addr_t; -#define KVM_TRACE4(name, type1, arg1, type2, arg2, type3, arg3, \ - type4, arg4) \ - DTRACE_PROBE4(kvm__##name, type1, arg1, type2, arg2, \ - type3, arg3, type4, arg4); +/* for KVM_SET_IDENTITY_MAP_ADDR */ +typedef struct kvm_id_map_addr_ioc { + uint64_t ident_addr; +} kvm_id_map_addr_ioc_t; -#define KVM_TRACE5(name, type1, arg1, type2, arg2, type3, arg3, \ - type4, arg4, type5, arg5) \ - DTRACE_PROBE5(kvm__##name, type1, arg1, type2, arg2, \ - type3, arg3, type4, arg4, type5, arg5); +typedef struct kvm_tpr_acl_ioc { + struct kvm_tpr_access_ctl tac; + int kvm_id; + int cpu_index; +} kvm_tpr_acl_ioc_t; -#define KVM_TRACE6(name, type1, arg1, type2, arg2, type3, arg3, \ - type4, arg4, type5, arg5, type6, arg6) \ - DTRACE_PROBE6(kvm__##name, type1, arg1, type2, arg2, \ - type3, arg3, type4, arg4, type5, arg5, type6, arg6); +typedef struct kvm_set_boot_cpu_id_ioc { + int id; +} kvm_set_boot_cpu_id_ioc_t; -#endif -#endif /*SOLARIS_KVM_H*/ +#endif /* __KVM_H */ diff --git a/kvm_cache_regs.c b/kvm_cache_regs.c index 33da1f2..599afd2 100644 --- a/kvm_cache_regs.c +++ b/kvm_cache_regs.c @@ -5,6 +5,7 @@ /* * XXX Need proper header files! */ +#include "bitops.h" #include "msr.h" #include "irqflags.h" #include "kvm_host.h" diff --git a/kvm_coalesced_mmio.h b/kvm_coalesced_mmio.h index f4b971e..a401ff5 100644 --- a/kvm_coalesced_mmio.h +++ b/kvm_coalesced_mmio.h @@ -10,19 +10,6 @@ * */ -/* XXX Linux doesn't define these structures here so why do we? */ - -typedef struct kvm_coalesced_mmio_zone { - uint64_t addr; - uint32_t size; - uint32_t pad; -} kvm_coalesced_mmio_zone_t; - -typedef struct kvm_coalesced_mmio_zone_ioc { - struct kvm_coalesced_mmio_zone zone; - int kvmid; -} kvm_coalesced_mmio_zone_ioc_t; - #ifdef CONFIG_KVM_MMIO #define KVM_COALESCED_MMIO_ZONE_MAX 100 diff --git a/kvm_cpuid.h b/kvm_cpuid.h new file mode 100644 index 0000000..2d3bd66 --- /dev/null +++ b/kvm_cpuid.h @@ -0,0 +1,130 @@ +/* + * Common CPUID definitions for KVM + */ + +#ifndef __KVM_CPUID_H +#define __KVM_CPUID_H + +/* Intel-defined CPU features, CPUID level 0x00000001 (edx), word 0 */ +#define X86_FEATURE_FPU (0 * 32 + 0) /* Onboard FPU */ +#define X86_FEATURE_VME (0 * 32 + 1) /* Virtual Mode Extensions */ +#define X86_FEATURE_DE (0 * 32 + 2) /* Debugging Extensions */ +#define X86_FEATURE_PSE (0 * 32 + 3) /* Page Size Extensions */ +#define X86_FEATURE_TSC (0 * 32 + 4) /* Time Stamp Counter */ +#define X86_FEATURE_MSR (0 * 32 + 5) /* Model-Specific Registers */ +#define X86_FEATURE_PAE (0 * 32 + 6) /* Phys. Address Extensions */ +#define X86_FEATURE_MCE (0 * 32 + 7) /* Machine Check Exception */ +#define X86_FEATURE_CX8 (0 * 32 + 8) /* CMPXCHG8 instruction */ +#define X86_FEATURE_APIC (0 * 32 + 9) /* Onboard APIC */ +#define X86_FEATURE_SEP (0 * 32 + 11) /* SYSENTER/SYSEXIT */ +#define X86_FEATURE_MTRR (0 * 32 + 12) /* Memory Type Range Regs. */ +#define X86_FEATURE_PGE (0 * 32 + 13) /* Page Global Enable */ +#define X86_FEATURE_MCA (0 * 32 + 14) /* Machine Check Architecture */ +#define X86_FEATURE_CMOV (0 * 32 + 15) /* CMOV instructions */ + /* (+ FCMOVcc, FCOMI w/ FPU) */ +#define X86_FEATURE_PAT (0 * 32 + 16) /* Page Attribute Table */ +#define X86_FEATURE_PSE36 (0 * 32 + 17) /* 36-bit PSEs */ +#define X86_FEATURE_PN (0 * 32 + 18) /* Processor serial number */ +#define X86_FEATURE_CLFLSH (0 * 32 + 19) /* "clflush" instruction */ +#define X86_FEATURE_DS (0 * 32 + 21) /* "dts" Debug Store */ +#define X86_FEATURE_ACPI (0 * 32 + 22) /* ACPI via MSR */ +#define X86_FEATURE_MMX (0 * 32 + 23) /* Multimedia Extensions */ +#define X86_FEATURE_FXSR (0 * 32 + 24) /* FXSAVE/FXRSTOR, CR4.OSFXSR */ +#define X86_FEATURE_XMM (0 * 32 + 25) /* "sse" */ +#define X86_FEATURE_XMM2 (0 * 32 + 26) /* "sse2" */ +#define X86_FEATURE_SELFSNOOP (0 * 32 + 27) /* "ss" CPU self snoop */ +#define X86_FEATURE_HT (0 * 32 + 28) /* Hyper-Threading */ +#define X86_FEATURE_ACC (0 * 32 + 29) /* "tm" Auto. clock control */ +#define X86_FEATURE_IA64 (0 * 32 + 30) /* IA-64 processor */ +#define X86_FEATURE_PBE (0 * 32 + 31) /* Pending Break Enable */ + +/* AMD-defined CPU features, CPUID level 0x80000001, word 1 */ +/* Don't duplicate feature flags which are redundant with Intel! */ +#define X86_FEATURE_SYSCALL (1 * 32 + 11) /* SYSCALL/SYSRET */ +#define X86_FEATURE_MP (1 * 32 + 19) /* MP Capable. */ +#define X86_FEATURE_NX (1 * 32 + 20) /* Execute Disable */ +#define X86_FEATURE_MMXEXT (1 * 32 + 22) /* AMD MMX extensions */ +#define X86_FEATURE_FXSR_OPT (1 * 32 + 25) /* FXSAVE/FXRSTOR optimiztns */ +#define X86_FEATURE_GBPAGES (1 * 32 + 26) /* "pdpe1gb" GB pages */ +#define X86_FEATURE_RDTSCP (1 * 32 + 27) /* RDTSCP */ +#define X86_FEATURE_LM (1 * 32 + 29) /* Long Mode (x86-64) */ +#define X86_FEATURE_3DNOWEXT (1 * 32 + 30) /* AMD 3DNow! extensions */ +#define X86_FEATURE_3DNOW (1 * 32 + 31) /* 3DNow! */ + +/* cpu types for specific tunings: */ +#define X86_FEATURE_K8 (3 * 32 + 4) /* "" Opteron, Athlon64 */ +#define X86_FEATURE_K7 (3 * 32 + 5) /* "" Athlon */ +#define X86_FEATURE_P3 (3 * 32 + 6) /* "" P3 */ +#define X86_FEATURE_P4 (3 * 32 + 7) /* "" P4 */ +#define X86_FEATURE_CONSTANT_TSC (3 * 32 + 8) /* TSC ticks at constant rate */ +#define X86_FEATURE_UP (3 * 32 + 9) /* smp kernel running on up */ +#define X86_FEATURE_FXSAVE_LEAK (3 * 32 + 10) /* FXSAVE leaks FOP/FIP/FOP */ +#define X86_FEATURE_ARCH_PERFMON (3 * 32 + 11) /* Intel Arch. PerfMon */ +#define X86_FEATURE_PEBS (3 * 32 + 12) /* Precise-Event Based Smplng */ +#define X86_FEATURE_BTS (3 * 32 + 13) /* Branch Trace Store */ +#define X86_FEATURE_SYSCALL32 (3 * 32 + 14) /* syscall in ia32 userspace */ +#define X86_FEATURE_SYSENTER32 (3 * 32 + 15) /* sysenter in ia32 userspace */ +#define X86_FEATURE_REP_GOOD (3 * 32 + 16) /* rep microcode works well */ +#define X86_FEATURE_MFENCE_RDTSC (3 * 32 + 17) /* Mfence synchronizes RDTSC */ +#define X86_FEATURE_LFENCE_RDTSC (3 * 32 + 18) /* Lfence synchronizes RDTSC */ +#define X86_FEATURE_11AP (3 * 32 + 19) /* Bad local APIC aka 11AP */ +#define X86_FEATURE_NOPL (3 * 32 + 20) /* NOPL (0F 1F) instructions */ +#define X86_FEATURE_AMDC1E (3 * 32 + 21) /* AMD C1E detected */ +#define X86_FEATURE_XTOPOLOGY (3 * 32 + 22) /* topology enum extensions */ +#define X86_FEATURE_TSC_RELIABLE (3 * 32 + 23) /* TSC is reliable */ +#define X86_FEATURE_NONSTOP_TSC (3 * 32 + 24) /* TSC continues in C states */ +#define X86_FEATURE_CLFLUSH_MONITOR (3 * 32 + 25) /* clflush reqd w/ monitor */ +#define X86_FEATURE_EXTD_APICID (3 * 32 + 26) /* extended APICID (8 bits) */ +#define X86_FEATURE_AMD_DCM (3 * 32 + 27) /* multi-node processor */ +#define X86_FEATURE_APERFMPERF (3 * 32 + 28) /* APERFMPERF */ + +/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ +#define X86_FEATURE_XMM3 (4 * 32 + 0) /* "pni" SSE-3 */ +#define X86_FEATURE_PCLMULQDQ (4 * 32 + 1) /* PCLMULQDQ instruction */ +#define X86_FEATURE_DTES64 (4 * 32 + 2) /* 64-bit Debug Store */ +#define X86_FEATURE_MWAIT (4 * 32 + 3) /* "monitor" Monitor/Mwait */ +#define X86_FEATURE_DSCPL (4 * 32 + 4) /* ds_cpl CPL Qual Debug Str */ +#define X86_FEATURE_VMX (4 * 32 + 5) /* Hardware virtualization */ +#define X86_FEATURE_SMX (4 * 32 + 6) /* Safer mode */ +#define X86_FEATURE_EST (4 * 32 + 7) /* Enhanced SpeedStep */ +#define X86_FEATURE_TM2 (4 * 32 + 8) /* Thermal Monitor 2 */ +#define X86_FEATURE_SSSE3 (4 * 32 + 9) /* Supplemental SSE-3 */ +#define X86_FEATURE_CID (4 * 32 + 10) /* Context ID */ +#define X86_FEATURE_FMA (4 * 32 + 12) /* Fused multiply-add */ +#define X86_FEATURE_CX16 (4 * 32 + 13) /* CMPXCHG16B */ +#define X86_FEATURE_XTPR (4 * 32 + 14) /* Send Task Priority Msgs */ +#define X86_FEATURE_PDCM (4 * 32 + 15) /* Performance Capabilities */ +#define X86_FEATURE_DCA (4 * 32 + 18) /* Direct Cache Access */ +#define X86_FEATURE_XMM4_1 (4 * 32 + 19) /* "sse4_1" SSE-4.1 */ +#define X86_FEATURE_XMM4_2 (4 * 32 + 20) /* "sse4_2" SSE-4.2 */ +#define X86_FEATURE_X2APIC (4 * 32 + 21) /* x2APIC */ +#define X86_FEATURE_MOVBE (4 * 32 + 22) /* MOVBE instruction */ +#define X86_FEATURE_POPCNT (4 * 32 + 23) /* POPCNT instruction */ +#define X86_FEATURE_AES (4 * 32 + 25) /* AES instructions */ +#define X86_FEATURE_XSAVE (4 * 32 + 26) /* XSAVE/XRSTOR/XSETBV/XGETBV */ +#define X86_FEATURE_OSXSAVE (4 * 32 + 27) /* "" XSAVE enabled in the OS */ +#define X86_FEATURE_AVX (4 * 32 + 28) /* Advanced Vector Extensions */ +#define X86_FEATURE_HYPERVISOR (4 * 32 + 31) /* Running on a hypervisor */ +/* More extended AMD flags: CPUID level 0x80000001, ecx, word 6 */ +#define X86_FEATURE_LAHF_LM (6 * 32 + 0) /* LAHF/SAHF in long mode */ +#define X86_FEATURE_CMP_LEGACY (6 * 32 + 1) /* HyperThreading invalid */ +#define X86_FEATURE_SVM (6 * 32 + 2) /* Secure virtual machine */ +#define X86_FEATURE_EXTAPIC (6 * 32 + 3) /* Extended APIC space */ +#define X86_FEATURE_CR8_LEGACY (6 * 32 + 4) /* CR8 in 32-bit mode */ +#define X86_FEATURE_ABM (6 * 32 + 5) /* Advanced bit manipulation */ +#define X86_FEATURE_SSE4A (6 * 32 + 6) /* SSE-4A */ +#define X86_FEATURE_MISALIGNSSE (6 * 32 + 7) /* Misaligned SSE mode */ +#define X86_FEATURE_3DNOWPREFETCH (6 * 32 + 8) /* 3DNow prefetch */ +#define X86_FEATURE_OSVW (6 * 32 + 9) /* OS Visible Workaround */ +#define X86_FEATURE_IBS (6 * 32 + 10) /* Instruction Based Sampling */ +#define X86_FEATURE_SSE5 (6 * 32 + 11) /* SSE-5 */ +#define X86_FEATURE_SKINIT (6 * 32 + 12) /* SKINIT/STGI instructions */ +#define X86_FEATURE_WDT (6 * 32 + 13) /* Watchdog timer */ +#define X86_FEATURE_NODEID_MSR (6 * 32 + 19) /* NodeId MSR */ + +/* Transmeta-defined CPU features, CPUID level 0x80860001, word 2 */ +#define X86_FEATURE_RECOVERY (2 * 32 + 0) /* CPU in recovery mode */ +#define X86_FEATURE_LONGRUN (2 * 32 + 1) /* Longrun power control */ +#define X86_FEATURE_LRTI (2 * 32 + 3) /* LongRun table interface */-/* More extended AMD flags: CPUID level 0x80000001, ecx, word 6 */ + +#endif @@ -1,38 +1,27 @@ -#ifndef __KVM_HOST_H -#define __KVM_HOST_H - /* - * This work is licensed under the terms of the GNU GPL, version 2. See - * the COPYING file in the top-level directory. + * This work is licensed under the terms of the GNU GPL, version 2. See the + * COPYING file in the top-level directory. */ -#ifdef XXX -#include <linux/types.h> -#include <linux/hardirq.h> -#include <linux/list.h> -#include <linux/mutex.h> -#include <linux/spinlock.h> -#include <linux/signal.h> -#include <linux/sched.h> -#include <linux/mm.h> -#include <linux/preempt.h> -#include <linux/msi.h> -#include <asm/signal.h> - -#include <linux/kvm.h> -#include <linux/kvm_para.h> +#ifndef __KVM_HOST_H +#define __KVM_HOST_H -#endif /*XXX*/ +#include <sys/types.h> +#include <sys/list.h> +#include <sys/mutex.h> +#include <sys/sunddi.h> #include "kvm_types.h" +#include "kvm_impl.h" +#include "kvm_x86host.h" -#define KVM_MEMORY_SLOTS 32 /* XXX assumes x86 */ -#define KVM_PRIVATE_MEM_SLOTS 4 /* XXX assumes x86 */ -#define TSS_PRIVATE_MEMSLOT (KVM_MEMORY_SLOTS + 0) -#define APIC_ACCESS_PAGE_PRIVATE_MEMSLOT (KVM_MEMORY_SLOTS + 1) -#define IDENTITY_PAGETABLE_PRIVATE_MEMSLOT (KVM_MEMORY_SLOTS + 2) +/* + * XXX Do these really belong here? + */ +#define NSEC_PER_MSEC 1000000L +#define NSEC_PER_SEC 1000000000L -#include "kvm_x86host.h" +#define BITS_PER_LONG (sizeof (unsigned long) * 8) /* * vcpu->requests bit members @@ -55,17 +44,192 @@ struct kvm; struct kvm_vcpu; extern struct kmem_cache *kvm_vcpu_cache; +/* + * It would be nice to use something smarter than a linear search, TBD... + * Thankfully we dont expect many devices to register (famous last words :), + * so until then it will suffice. At least its abstracted so we can change + * in one place. + */ +typedef struct kvm_io_bus { + int dev_count; +#define NR_IOBUS_DEVS 200 + struct kvm_io_device *devs[NR_IOBUS_DEVS]; +} kvm_io_bus_t; + +enum kvm_bus { + KVM_MMIO_BUS, + KVM_PIO_BUS, + KVM_NR_BUSES +}; + +int kvm_io_bus_write(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr, + int len, const void *val); +int kvm_io_bus_read(struct kvm *kvm, enum kvm_bus bus_idx, gpa_t addr, int len, + void *val); +int kvm_io_bus_register_dev(struct kvm *kvm, enum kvm_bus bus_idx, + struct kvm_io_device *dev); +int kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx, + struct kvm_io_device *dev); + +#define KVM_MAX_IRQ_ROUTES 1024 + +typedef struct kvm_vcpu { + struct kvm *kvm; +#ifdef CONFIG_PREEMPT_NOTIFIERS + struct preempt_notifier preempt_notifier; +#endif + int vcpu_id; + kmutex_t mutex; + int cpu; + struct kvm_run *run; + unsigned long requests; + unsigned long guest_debug; + int srcu_idx; + + int fpu_active; + int guest_fpu_loaded; + + kmutex_t kvcpu_kick_lock; + kcondvar_t kvcpu_kick_cv; + kvm_vcpu_stats_t kvcpu_stats; + kstat_t *kvcpu_kstat; + + int sigset_active; + sigset_t sigset; + + /*#ifdef CONFIG_HAS_IOMEM*/ + int mmio_needed; + int mmio_read_completed; + int mmio_is_write; + int mmio_size; + unsigned char mmio_data[8]; + gpa_t mmio_phys_addr; + /*#endif*/ + + struct kvm_vcpu_arch arch; + ddi_umem_cookie_t cookie; + struct kvm_user_return_notifier *urn; +} kvm_vcpu_t; + +typedef struct kvm_memory_slot { + gfn_t base_gfn; + unsigned long npages; + unsigned long flags; + unsigned long *rmap; + unsigned long *dirty_bitmap; + struct { + unsigned long rmap_pde; + int write_count; + } *lpage_info[KVM_NR_PAGE_SIZES]; + unsigned long userspace_addr; + int user_alloc; +} kvm_memory_slot_t; + +unsigned long kvm_dirty_bitmap_bytes(struct kvm_memory_slot *memslot); + +typedef struct kvm_kernel_irq_routing_entry { + uint32_t gsi; + uint32_t type; + int (*set)(struct kvm_kernel_irq_routing_entry *e, + struct kvm *kvm, int irq_source_id, int level); + union { + struct { + unsigned irqchip; + unsigned pin; + } irqchip; + struct msi_msg msi; + }; + struct list_node link; +} kvm_kernel_irq_routing_entry_t; + +typedef struct kvm_irq_routing_table { + int chip[KVM_NR_IRQCHIPS][KVM_IOAPIC_NUM_PINS]; + struct kvm_kernel_irq_routing_entry *rt_entries; + uint32_t nr_rt_entries; + /* + * Array indexed by gsi. Each entry contains list of irq chips + * the gsi is connected to. + */ + list_t map[KVM_MAX_IRQ_ROUTES+1]; +} kvm_irq_routing_table_t; + +typedef struct kvm_memslots { + int nmemslots; + struct kvm_memory_slot memslots[KVM_MEMORY_SLOTS + + KVM_PRIVATE_MEM_SLOTS]; +} kvm_memslots_t; + +typedef struct kvm { + kmutex_t mmu_lock; + kmutex_t requests_lock; + kmutex_t slots_lock; + struct as *mm; /* userspace tied to this vm */ + struct kvm_memslots *memslots; + /* the following was a read-copy update mechanism */ + /* we'll use a reader-writer lock, for now */ + krwlock_t kvm_rwlock; +#ifdef CONFIG_KVM_APIC_ARCHITECTURE + uint32_t bsp_vcpu_id; + struct kvm_vcpu *bsp_vcpu; +#endif + struct kvm_vcpu *vcpus[KVM_MAX_VCPUS]; + volatile int online_vcpus; + struct list_node vm_list; + kmutex_t lock; + struct kvm_io_bus *buses[KVM_NR_BUSES]; +#ifdef CONFIG_HAVE_KVM_EVENTFD + struct { + kmutex_t lock; + struct list_head items; + } irqfds; + struct list_head ioeventfds; +#endif + struct kstat *kvm_kstat; + kvm_stats_t kvm_stats; + struct kvm_arch arch; + volatile int users_count; +#ifdef KVM_COALESCED_MMIO_PAGE_OFFSET + struct kvm_coalesced_mmio_dev *coalesced_mmio_dev; + struct kvm_coalesced_mmio_ring *coalesced_mmio_ring; + ddi_umem_cookie_t mmio_cookie; +#endif + + kmutex_t irq_lock; +#ifdef CONFIG_HAVE_KVM_IRQCHIP + struct kvm_irq_routing_table *irq_routing; + list_t mask_notifier_list; + list_t irq_ack_notifier_list; +#endif + +#if defined(KVM_ARCH_WANT_MMU_NOTIFIER) && defined(CONFIG_MMU_NOTIFIER) + struct mmu_notifier mmu_notifier; + unsigned long mmu_notifier_seq; + long mmu_notifier_count; +#endif + int kvmid; /* unique identifier for this kvm */ + int kvm_clones; + pid_t kvm_pid; /* pid associated with this kvm */ + kmutex_t kvm_avllock; + avl_tree_t kvm_avlmp; /* avl tree for mmu to page_t mapping */ +} kvm_t; + +extern struct kvm_vcpu *kvm_get_vcpu(struct kvm *kvm, int i); + +#define kvm_for_each_vcpu(idx, vcpup, kvm) \ + for (idx = 0, vcpup = kvm_get_vcpu(kvm, idx); \ + idx < kvm->online_vcpus && vcpup; /* XXX - need protection */ \ + vcpup = kvm_get_vcpu(kvm, ++idx)) + +int kvm_vcpu_init(struct kvm_vcpu *, struct kvm *, unsigned); void kvm_vcpu_uninit(struct kvm_vcpu *vcpu); void vcpu_load(struct kvm_vcpu *vcpu); void vcpu_put(struct kvm_vcpu *vcpu); -#ifdef XXX -int kvm_init(void *opaque, unsigned int vcpu_size, - struct module *module); + +int kvm_init(void *opaque, unsigned int vcpu_size); void kvm_exit(void); -#endif /*XXX*/ void kvm_get_kvm(struct kvm *kvm); void kvm_put_kvm(struct kvm *kvm); @@ -77,39 +241,209 @@ static int is_error_hpa(hpa_t hpa) { return hpa >> HPA_MSB; } extern page_t *bad_page; extern pfn_t bad_pfn; +int is_error_page(struct page *page); +int is_error_pfn(pfn_t pfn); +int kvm_is_error_hva(unsigned long addr); + +int kvm_set_memory_region(struct kvm *kvm, + struct kvm_userspace_memory_region *mem, + int user_alloc); +int __kvm_set_memory_region(struct kvm *kvm, + struct kvm_userspace_memory_region *mem, + int user_alloc); +int kvm_arch_prepare_memory_region(struct kvm *kvm, + struct kvm_memory_slot *memslot, + struct kvm_memory_slot old, + struct kvm_userspace_memory_region *mem, + int user_alloc); +void kvm_arch_commit_memory_region(struct kvm *kvm, + struct kvm_userspace_memory_region *mem, + struct kvm_memory_slot old, + int user_alloc); + +void kvm_disable_largepages(void); +void kvm_arch_flush_shadow(struct kvm *kvm); +gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn); +gfn_t unalias_gfn_instantiation(struct kvm *kvm, gfn_t gfn); + +page_t *gfn_to_page(struct kvm *kvm, gfn_t gfn); +unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn); +void kvm_release_page_clean(struct page *page); +void kvm_release_page_dirty(struct page *page); +void kvm_set_page_dirty(struct page *page); +void kvm_set_page_accessed(struct page *page); + +pfn_t gfn_to_pfn(struct kvm *kvm, gfn_t gfn); +pfn_t gfn_to_pfn_memslot(struct kvm *kvm, + struct kvm_memory_slot *slot, gfn_t gfn); +int memslot_id(struct kvm *kvm, gfn_t gfn); +void kvm_release_pfn_dirty(pfn_t); +void kvm_release_pfn_clean(pfn_t); +void kvm_set_pfn_dirty(pfn_t); +void kvm_set_pfn_accessed(struct kvm *, pfn_t); +void kvm_get_pfn(struct kvm_vcpu *vcpu, pfn_t pfn); + +int kvm_read_guest_page(struct kvm *kvm, gfn_t gfn, void *data, int offset, + int len); +int kvm_read_guest_atomic(struct kvm *kvm, gpa_t gpa, void *data, + unsigned long len); +int kvm_read_guest(struct kvm *kvm, gpa_t gpa, void *data, unsigned long len); +int kvm_write_guest_page(struct kvm *kvm, gfn_t gfn, const void *data, + int offset, int len); +int kvm_write_guest(struct kvm *kvm, gpa_t gpa, const void *data, + unsigned long len); +int kvm_clear_guest_page(struct kvm *kvm, gfn_t gfn, int offset, int len); +int kvm_clear_guest(struct kvm *kvm, gpa_t gpa, unsigned long len); +struct kvm_memory_slot *gfn_to_memslot(struct kvm *kvm, gfn_t gfn); +int kvm_is_visible_gfn(struct kvm *kvm, gfn_t gfn); +unsigned long kvm_host_page_size(struct kvm *kvm, gfn_t gfn); +void mark_page_dirty(struct kvm *kvm, gfn_t gfn); + +void kvm_vcpu_block(struct kvm_vcpu *vcpu); +void kvm_vcpu_on_spin(struct kvm_vcpu *vcpu); +void kvm_resched(struct kvm_vcpu *vcpu); +void kvm_load_guest_fpu(struct kvm_vcpu *vcpu); +void kvm_put_guest_fpu(struct kvm_vcpu *vcpu); +void kvm_flush_remote_tlbs(struct kvm *kvm); +void kvm_reload_remote_mmus(struct kvm *kvm); + +long kvm_arch_dev_ioctl(struct file *filp, + unsigned int ioctl, unsigned long arg); +long kvm_arch_vcpu_ioctl(struct file *filp, + unsigned int ioctl, unsigned long arg); +extern int kvm_dev_ioctl_check_extension(long ext, int *rv); +int kvm_get_dirty_log(struct kvm *kvm, + struct kvm_dirty_log *log, int *is_dirty); +int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, + struct kvm_dirty_log *log); + +int kvm_vm_ioctl_set_memory_region(struct kvm *kvm, + struct + kvm_userspace_memory_region *mem, + int user_alloc); +long kvm_arch_vm_ioctl(struct file *filp, + unsigned int ioctl, unsigned long arg); + +int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu); +int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu); + +int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs); +int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs); +int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu, + struct kvm_sregs *sregs); +int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, + struct kvm_sregs *sregs); +int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu, + struct kvm_mp_state *mp_state); +int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu, + struct kvm_mp_state *mp_state); +int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, + struct kvm_guest_debug *dbg); +int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu); + +int kvm_arch_init(void *opaque); +void kvm_arch_exit(void); + +int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu); +void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu); + +void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu); +void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu); +void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu); +int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu); +void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu); + +int kvm_arch_vcpu_reset(struct kvm_vcpu *vcpu); +int kvm_arch_hardware_enable(void *garbage); +void kvm_arch_hardware_disable(void *garbage); +int kvm_arch_hardware_setup(void); +void kvm_arch_hardware_unsetup(void); +void kvm_arch_check_processor_compat(void *rtn); +int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu); + +void kvm_free_physmem(struct kvm *kvm); + +struct kvm *kvm_arch_create_vm(void); +void kvm_arch_destroy_vm(struct kvm *kvm); +void kvm_arch_destroy_vm_comps(struct kvm *kvm); +void kvm_free_all_assigned_devices(struct kvm *kvm); +void kvm_arch_sync_events(struct kvm *kvm); + +int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu); +void kvm_vcpu_kick(struct kvm_vcpu *vcpu); + +extern int kvm_is_mmio_pfn(pfn_t pfn); + +typedef struct kvm_irq_ack_notifier { + list_t link; + unsigned gsi; + void (*irq_acked)(struct kvm_irq_ack_notifier *kian); +} kvm_irq_ack_notifier_t; + +#define KVM_ASSIGNED_MSIX_PENDING 0x1 +typedef struct kvm_guest_msix_entry { + uint32_t vector; + unsigned short entry; + unsigned short flags; +} kvm_guest_msix_entry_t; + +typedef struct kvm_assigned_dev_kernel { + struct kvm_irq_ack_notifier ack_notifier; + list_t interrupt_work; + list_t list; + int assigned_dev_id; + int host_segnr; + int host_busnr; + int host_devfn; + unsigned int entries_nr; + int host_irq; + unsigned char host_irq_disabled; + struct msix_entry *host_msix_entries; + int guest_irq; + struct kvm_guest_msix_entry *guest_msix_entries; + unsigned long irq_requested_type; + int irq_source_id; + int flags; + struct pci_dev *dev; + struct kvm *kvm; + kmutex_t assigned_dev_lock; +} kvm_assigned_dev_kernel_t; + +typedef struct kvm_irq_mask_notifier { + void (*func)(struct kvm_irq_mask_notifier *kimn, int masked); + int irq; + struct list_node link; +} kvm_irq_mask_notifier_t; + +void kvm_register_irq_mask_notifier(struct kvm *kvm, int irq, + struct kvm_irq_mask_notifier *kimn); +void kvm_unregister_irq_mask_notifier(struct kvm *kvm, int irq, + struct kvm_irq_mask_notifier *kimn); +void kvm_fire_mask_notifiers(struct kvm *kvm, int irq, int mask); + +int kvm_set_irq(struct kvm *kvm, int irq_source_id, uint32_t irq, int level); +void kvm_notify_acked_irq(struct kvm *kvm, unsigned irqchip, unsigned pin); +void kvm_register_irq_ack_notifier(struct kvm *kvm, + struct kvm_irq_ack_notifier *kian); +void kvm_unregister_irq_ack_notifier(struct kvm *kvm, + struct kvm_irq_ack_notifier *kian); +int kvm_request_irq_source_id(struct kvm *kvm); +void kvm_free_irq_source_id(struct kvm *kvm, int irq_source_id); + /* For vcpu->arch.iommu_flags */ #define KVM_IOMMU_CACHE_COHERENCY 0x1 +int kvm_iommu_map_pages(struct kvm *kvm, struct kvm_memory_slot *slot); +int kvm_iommu_map_guest(struct kvm *kvm); +int kvm_iommu_unmap_guest(struct kvm *kvm); +int kvm_assign_device(struct kvm *kvm, + struct kvm_assigned_dev_kernel *assigned_dev); +int kvm_deassign_device(struct kvm *kvm, + struct kvm_assigned_dev_kernel *assigned_dev); -#ifdef XXX -static void kvm_guest_enter(void) -{ - account_system_vtime(current); - current->flags |= PF_VCPU; -} - -static void kvm_guest_exit(void) -{ - account_system_vtime(current); - current->flags &= ~PF_VCPU; -} - -gpa_t gfn_to_gpa(gfn_t gfn) -{ - return (gpa_t)gfn << PAGESHIFT; -} - -static hpa_t pfn_to_hpa(pfn_t pfn) -{ - return (hpa_t)pfn << PAGESHIFT; -} - -static void kvm_migrate_timers(struct kvm_vcpu *vcpu) -{ - set_bit(KVM_REQ_MIGRATE_TIMER, &vcpu->requests); -} - -#endif /*XXX*/ +void kvm_guest_enter(void); +void kvm_guest_exit(void); +void kvm_migrate_timers(struct kvm_vcpu *vcpu); enum kvm_stat_kind { KVM_STAT_VM, @@ -125,70 +459,67 @@ typedef struct kvm_stats_debugfs_item { extern struct kvm_stats_debugfs_item debugfs_entries[]; extern struct dentry *kvm_debugfs_dir; -#ifdef XXX -#ifdef KVM_ARCH_WANT_MMU_NOTIFIER -static int mmu_notifier_retry(struct kvm_vcpu *vcpu, unsigned long mmu_seq) -{ - if (unlikely(vcpu->kvm->mmu_notifier_count)) - return 1; - /* - * Both reads happen under the mmu_lock and both values are - * modified under mmu_lock, so there's no need of smb_rmb() - * here in between, otherwise mmu_notifier_count should be - * read before mmu_notifier_seq, see - * mmu_notifier_invalidate_range_end write side. - */ - if (vcpu->kvm->mmu_notifier_seq != mmu_seq) - return 1; - return 0; -} -#endif -#endif /*XXX*/ - #ifndef KVM_ARCH_HAS_UNALIAS_INSTANTIATION #define unalias_gfn_instantiation unalias_gfn #endif -#undef CONFIG_HAVE_KVM_EVENTFD - -#ifdef CONFIG_HAVE_KVM_EVENTFD +#ifdef CONFIG_HAVE_KVM_IRQCHIP -void kvm_eventfd_init(struct kvm *kvm); -int kvm_irqfd(struct kvm *kvm, int fd, int gsi, int flags); -void kvm_irqfd_release(struct kvm *kvm); -int kvm_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args); +int kvm_setup_default_irq_routing(struct kvm *kvm); +int kvm_set_irq_routing(struct kvm *kvm, + const struct kvm_irq_routing_entry *entries, + unsigned nr, + unsigned flags); +void kvm_free_irq_routing(struct kvm *kvm); #else -static void kvm_eventfd_init(struct kvm *kvm) {} -static int kvm_irqfd(struct kvm *kvm, int fd, int gsi, int flags) -{ - return -EINVAL; -} - -static void kvm_irqfd_release(struct kvm *kvm) {} -#ifdef XXX -static int kvm_ioeventfd(struct kvm *kvm, struct kvm_ioeventfd *args) -{ - return -ENOSYS; -} -#endif /*XXX*/ -#endif /* CONFIG_HAVE_KVM_EVENTFD */ - -#ifdef __KVM_HAVE_DEVICE_ASSIGNMENT +static void kvm_free_irq_routing(struct kvm *kvm) {} -long kvm_vm_ioctl_assigned_device(struct kvm *kvm, unsigned ioctl, - unsigned long arg); - -#else - -static long kvm_vm_ioctl_assigned_device(struct kvm *kvm, unsigned ioctl, - unsigned long arg) -{ - return -ENOTTY; -} +#endif /*CONFIG_HAVE_KVM_IRQCHIP*/ +#ifdef CONFIG_KVM_APIC_ARCHITECTURE +extern int kvm_vcpu_is_bsp(struct kvm_vcpu *); #endif -#endif +void kvm_sigprocmask(int how, sigset_t *, sigset_t *); +/* + * XXX Is this really necessary? There really isn't another way to do it? + */ +#define offset_in_page(p) ((unsigned long)(p) & ~PAGEMASK) + +/* borrowed liberally from linux... */ + +#define MAX_IO_MSRS 256 +#define CR0_RESERVED_BITS \ + (~(unsigned long)(X86_CR0_PE | X86_CR0_MP | X86_CR0_EM | X86_CR0_TS \ + | X86_CR0_ET | X86_CR0_NE | X86_CR0_WP | X86_CR0_AM \ + | X86_CR0_NW | X86_CR0_CD | X86_CR0_PG)) +#define CR4_RESERVED_BITS \ + (~(unsigned long)(X86_CR4_VME | X86_CR4_PVI | X86_CR4_TSD | X86_CR4_DE\ + | X86_CR4_PSE | X86_CR4_PAE | X86_CR4_MCE \ + | X86_CR4_PGE | X86_CR4_PCE | X86_CR4_OSFXSR \ + | X86_CR4_OSXMMEXCPT | X86_CR4_VMXE)) + +#define CR8_RESERVED_BITS (~(unsigned long)X86_CR8_TPR) + +#define MCG_CTL_P (1ULL<<8) /* MCG_CTL register available */ +#define KVM_MAX_MCE_BANKS 32 +#define KVM_MCE_CAP_SUPPORTED MCG_CTL_P +#define page_to_pfn(page) (page->p_pagenum) + + +/* LDT or TSS descriptor in the GDT. 16 bytes. */ +struct ldttss_desc64 { + unsigned short limit0; + unsigned short base0; + unsigned base1 : 8, type : 5, dpl : 2, p : 1; + unsigned limit1 : 4, zero0 : 3, g : 1, base2 : 8; + uint32_t base3; + uint32_t zero1; +} __attribute__((packed)); + +typedef struct ldttss_desc64 ldttss_desc64_t; + +#endif /* __KVM_HOST_H */ diff --git a/kvm_i8254.c b/kvm_i8254.c index b6d2991..99e6007 100644 --- a/kvm_i8254.c +++ b/kvm_i8254.c @@ -46,6 +46,13 @@ extern int kvm_vcpu_is_bsp(struct kvm_vcpu *vcpu); +#define mod_64(x, y) ((x) % (y)) + +#define RW_STATE_LSB 1 +#define RW_STATE_MSB 2 +#define RW_STATE_WORD0 3 +#define RW_STATE_WORD1 4 + static uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c) { diff --git a/kvm_i8254.h b/kvm_i8254.h index 92e842a..31da46b 100644 --- a/kvm_i8254.h +++ b/kvm_i8254.h @@ -2,6 +2,7 @@ #define __KVM_I8254_H #include "kvm_iodev.h" +#include "kvm_timer.h" typedef struct kvm_kpit_channel_state { uint32_t count; /* can be 65536 */ diff --git a/kvm_impl.h b/kvm_impl.h new file mode 100644 index 0000000..3b2142b --- /dev/null +++ b/kvm_impl.h @@ -0,0 +1,155 @@ +/* + * This header files contains pieces necessary for the illumos implementation of + * the kvm driver. These definitions should not be exported to userland. + */ +#ifndef __KVM_IMPL_H +#define __KVM_IMPL_H + +#include <sys/kstat.h> +#include <sys/sdt.h> + +#define XXX_KVM_PROBE DTRACE_PROBE2(kvm__xxx, \ + char *, __FILE__, int, __LINE__) +#define XXX_KVM_SYNC_PROBE DTRACE_PROBE2(kvm__xxx__sync, \ + char *, __FILE__, int, __LINE__) + +#define KVM_TRACE1(name, type1, arg1) \ + DTRACE_PROBE1(kvm__##name, type1, arg1); + +#define KVM_TRACE2(name, type1, arg1, type2, arg2) \ + DTRACE_PROBE2(kvm__##name, type1, arg1, type2, arg2); + +#define KVM_TRACE3(name, type1, arg1, type2, arg2, type3, arg3) \ + DTRACE_PROBE3(kvm__##name, type1, arg1, type2, arg2, type3, arg3); + +#define KVM_TRACE4(name, type1, arg1, type2, arg2, type3, arg3, \ + type4, arg4) \ + DTRACE_PROBE4(kvm__##name, type1, arg1, type2, arg2, \ + type3, arg3, type4, arg4); + +#define KVM_TRACE5(name, type1, arg1, type2, arg2, type3, arg3, \ + type4, arg4, type5, arg5) \ + DTRACE_PROBE5(kvm__##name, type1, arg1, type2, arg2, \ + type3, arg3, type4, arg4, type5, arg5); + +#define KVM_TRACE6(name, type1, arg1, type2, arg2, type3, arg3, \ + type4, arg4, type5, arg5, type6, arg6) \ + DTRACE_PROBE6(kvm__##name, type1, arg1, type2, arg2, \ + type3, arg3, type4, arg4, type5, arg5, type6, arg6); + +typedef struct kvm_vcpu_stats { + kstat_named_t kvmvs_id; /* instance of associated kvm */ + kstat_named_t kvmvs_nmi_injections; /* number of NMI injections */ + kstat_named_t kvmvs_irq_injections; /* number of IRQ injections */ + kstat_named_t kvmvs_fpu_reload; /* number of FPU reloads */ + kstat_named_t kvmvs_host_state_reload; /* host state (re)loads */ + kstat_named_t kvmvs_insn_emulation; /* instruction emulation */ + kstat_named_t kvmvs_insn_emulation_fail; /* emulation failures */ + kstat_named_t kvmvs_exits; /* total VM exits */ + kstat_named_t kvmvs_halt_exits; /* exits due to HLT */ + kstat_named_t kvmvs_irq_exits; /* exits due to IRQ */ + kstat_named_t kvmvs_io_exits; /* exits due to I/O instrn */ + kstat_named_t kvmvs_mmio_exits; /* exits due to mem mppd I/O */ + kstat_named_t kvmvs_nmi_window_exits; /* exits due to NMI window */ + kstat_named_t kvmvs_irq_window_exits; /* exits due to IRQ window */ + kstat_named_t kvmvs_request_irq_exits; /* exits due to requested IRQ */ + kstat_named_t kvmvs_signal_exits; /* exits due to pending sig */ + kstat_named_t kvmvs_halt_wakeup; /* wakeups from HLT */ + kstat_named_t kvmvs_invlpg; /* INVLPG instructions */ + kstat_named_t kvmvs_pf_guest; /* injected guest pagefaults */ + kstat_named_t kvmvs_pf_fixed; /* fixed pagefaults */ + kstat_named_t kvmvs_hypercalls; /* hypercalls (VMCALL instrn) */ +} kvm_vcpu_stats_t; + +#define KVM_VCPU_KSTAT_INIT(vcpu, field, name) \ + kstat_named_init(&((vcpu)->kvcpu_stats.field), name, KSTAT_DATA_UINT64); + +#define KVM_VCPU_KSTAT_INC(vcpu, field) \ + (vcpu)->kvcpu_stats.field.value.ui64++; + +typedef struct kvm_stats { + kstat_named_t kvmks_pid; /* PID of opening process */ + kstat_named_t kvmks_mmu_pte_write; /* page table entry writes */ + kstat_named_t kvmks_mmu_pte_zapped; /* zapped page table entries */ + kstat_named_t kvmks_mmu_pte_updated; /* page table entry updates */ + kstat_named_t kvmks_mmu_flooded; /* # of pages flooded */ + kstat_named_t kvmks_mmu_cache_miss; /* misses in page cache */ + kstat_named_t kvmks_mmu_recycled; /* recycles from free list */ + kstat_named_t kvmks_remote_tlb_flush; /* remote TLB flushes */ + kstat_named_t kvmks_lpages; /* large pages in use */ +} kvm_stats_t; + +#define KVM_KSTAT_INIT(kvmp, field, name) \ + kstat_named_init(&((kvmp)->kvm_stats.field), name, KSTAT_DATA_UINT64); + +#define KVM_KSTAT_INC(kvmp, field) \ + (kvmp)->kvm_stats.field.value.ui64++; + +#define KVM_KSTAT_DEC(kvmp, field) \ + (kvmp)->kvm_stats.field.value.ui64--; + + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) +#endif /*ARRAY_SIZE*/ + +#define KVM_CPUALL -1 + +typedef void (*kvm_xcall_t)(void *); + +/* + * XXX + * All the follwoing definitions are ones that are expected to just be in + * x86/x86.c by Linux. However we currently have the things that need them + * spread out across two files. For now we are putting them here, but this + * should not last very long. + */ +#define KVM_NR_SHARED_MSRS 16 + +typedef struct kvm_shared_msrs_global { + int nr; + uint32_t msrs[KVM_NR_SHARED_MSRS]; +} kvm_shared_msrs_global_t; + +struct kvm_vcpu; + +typedef struct kvm_user_return_notifier { + void (*on_user_return)(struct kvm_vcpu *, + struct kvm_user_return_notifier *); +} kvm_user_return_notifier_t; + +typedef struct kvm_shared_msrs { + struct kvm_user_return_notifier urn; + int registered; + struct kvm_shared_msr_values { + uint64_t host; + uint64_t curr; + } values[KVM_NR_SHARED_MSRS]; +} kvm_shared_msrs_t; + +/* + * fxsave fpu state. Taken from x86_64/processor.h. To be killed when + * we have asm/x86/processor.h + */ +typedef struct fxsave { + uint16_t cwd; + uint16_t swd; + uint16_t twd; + uint16_t fop; + uint64_t rip; + uint64_t rdp; + uint32_t mxcsr; + uint32_t mxcsr_mask; + uint32_t st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */ +#ifdef CONFIG_X86_64 + uint32_t xmm_space[64]; /* 16*16 bytes for each XMM-reg = 256 bytes */ +#else + uint32_t xmm_space[32]; /* 8*16 bytes for each XMM-reg = 128 bytes */ +#endif +} fxsave_t; + +#ifndef offsetof +#define offsetof(s, m) ((size_t)(&((s *)0)->m)) +#endif + +#endif diff --git a/kvm_ioapic.c b/kvm_ioapic.c index 3e53bcf..285cf72 100644 --- a/kvm_ioapic.c +++ b/kvm_ioapic.c @@ -31,6 +31,7 @@ /* * XXX Need proper header files! */ +#include "bitops.h" #include "msr.h" #include "irqflags.h" #include "kvm_host.h" diff --git a/kvm_irq_comm.c b/kvm_irq_comm.c index aa4cf14..f4df4e1 100644 --- a/kvm_irq_comm.c +++ b/kvm_irq_comm.c @@ -19,11 +19,15 @@ * */ +#include <sys/sysmacros.h> + /* * XXX Need proper header files! */ +#include "bitops.h" #include "msr.h" #include "irqflags.h" +#include "kvm_msidef.h" #include "kvm_host.h" #include "kvm_x86host.h" #include "kvm_iodev.h" @@ -35,6 +39,7 @@ extern long find_first_zero_bit(const unsigned long *, unsigned long); extern int kvm_pic_set_irq(void *, int, int); +extern int irqchip_in_kernel(struct kvm *kvm); static int kvm_irq_line_state(unsigned long *irq_state, int irq_source_id, int level) @@ -422,7 +427,7 @@ kvm_set_irq_routing(struct kvm *kvm, const struct kvm_irq_routing_entry *ue, for (i = 0; i < nr; ++i) { if (ue[i].gsi >= KVM_MAX_IRQ_ROUTES) return (-EINVAL); - nr_rt_entries = max(nr_rt_entries, ue[i].gsi); + nr_rt_entries = MAX(nr_rt_entries, ue[i].gsi); } nr_rt_entries += 1; diff --git a/kvm_lapic.c b/kvm_lapic.c index a2db3b3..3f9b3e9 100644 --- a/kvm_lapic.c +++ b/kvm_lapic.c @@ -24,6 +24,8 @@ /* * XXX Need proper header files! */ +#include "bitops.h" +#include "kvm_cpuid.h" #include "msr.h" #include "irqflags.h" #include "kvm_host.h" @@ -36,7 +38,26 @@ #include "irq.h" int __apic_accept_irq(struct kvm_lapic *, int, int, int, int); +/* XXX */ extern caddr_t page_address(page_t *); +extern int irqchip_in_kernel(struct kvm *kvm); +extern unsigned long kvm_rip_read(struct kvm_vcpu *); +extern struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct kvm_vcpu *vcpu, + uint32_t function, uint32_t index); + +#define APIC_BUS_CYCLE_NS 1 +#define APIC_LDR 0xD0 + +#define APIC_LVT_NUM 6 +/* 14 is the version for Xeon and Pentium 8.4.8*/ +#define APIC_VERSION (0x14UL | ((APIC_LVT_NUM - 1) << 16)) +#define LAPIC_MMIO_LENGTH (1 << 12) +/* followed define is not in apicdef.h */ +#define APIC_SHORT_MASK 0xc0000 +#define APIC_DEST_NOSHORT 0x0 +#define APIC_DEST_MASK 0x800 +#define MAX_APIC_VECTOR 256 + #define LVT_MASK \ (APIC_LVT_MASKED | APIC_SEND_PENDING | APIC_VECTOR_MASK) @@ -1,4 +1,7 @@ +#include <sys/sysmacros.h> + #include "processor-flags.h" +#include "bitops.h" #include "msr.h" #include "irqflags.h" #include "kvm_host.h" @@ -1464,7 +1467,7 @@ kvm_mmu_change_mmu_pages(struct kvm *kvm, unsigned int kvm_nr_mmu_pages) int used_pages; used_pages = kvm->arch.n_alloc_mmu_pages - kvm->arch.n_free_mmu_pages; - used_pages = max(0, used_pages); + used_pages = MAX(0, used_pages); /* for the time being, assume that address space will only grow */ /* larger. The following code will be added later. */ @@ -2734,7 +2737,7 @@ kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva) return (r); } -static void +void __kvm_mmu_free_some_pages(struct kvm_vcpu *vcpu) { while (vcpu->kvm->arch.n_free_mmu_pages < KVM_REFILL_PAGES && @@ -2990,7 +2993,7 @@ kvm_mmu_calculate_mmu_pages(struct kvm *kvm) nr_pages += slots->memslots[i].npages; nr_mmu_pages = nr_pages * KVM_PERMILLE_MMU_PAGES / 1000; - nr_mmu_pages = max(nr_mmu_pages, (unsigned int)KVM_MIN_ALLOC_MMU_PAGES); + nr_mmu_pages = MAX(nr_mmu_pages, (unsigned int)KVM_MIN_ALLOC_MMU_PAGES); return (nr_mmu_pages); } diff --git a/kvm_msidef.h b/kvm_msidef.h new file mode 100644 index 0000000..006b56d --- /dev/null +++ b/kvm_msidef.h @@ -0,0 +1,56 @@ +#ifndef __KVM_MDIDEF_H +#define __KVM_MSIDEF_H + +/* + * Constants for Intel APIC based MSI messages. + */ + +/* + * Shifts for MSI data + */ + +#define MSI_DATA_VECTOR_SHIFT 0 +#define MSI_DATA_VECTOR_MASK 0x000000ff +#define MSI_DATA_VECTOR(v) (((v) << MSI_DATA_VECTOR_SHIFT) & \ + MSI_DATA_VECTOR_MASK) + +#define MSI_DATA_DELIVERY_MODE_SHIFT 8 +#define MSI_DATA_DELIVERY_FIXED (0 << MSI_DATA_DELIVERY_MODE_SHIFT) +#define MSI_DATA_DELIVERY_LOWPRI (1 << MSI_DATA_DELIVERY_MODE_SHIFT) + +#define MSI_DATA_LEVEL_SHIFT 14 +#define MSI_DATA_LEVEL_DEASSERT (0 << MSI_DATA_LEVEL_SHIFT) +#define MSI_DATA_LEVEL_ASSERT (1 << MSI_DATA_LEVEL_SHIFT) + +#define MSI_DATA_TRIGGER_SHIFT 15 +#define MSI_DATA_TRIGGER_EDGE (0 << MSI_DATA_TRIGGER_SHIFT) +#define MSI_DATA_TRIGGER_LEVEL (1 << MSI_DATA_TRIGGER_SHIFT) + +/* + * Shift/mask fields for msi address + */ + +#define MSI_ADDR_BASE_HI 0 +#define MSI_ADDR_BASE_LO 0xfee00000 + +#define MSI_ADDR_DEST_MODE_SHIFT 2 +#define MSI_ADDR_DEST_MODE_PHYSICAL (0 << MSI_ADDR_DEST_MODE_SHIFT) +#define MSI_ADDR_DEST_MODE_LOGICAL (1 << MSI_ADDR_DEST_MODE_SHIFT) + +#define MSI_ADDR_REDIRECTION_SHIFT 3 +#define MSI_ADDR_REDIRECTION_CPU (0 << MSI_ADDR_REDIRECTION_SHIFT) + /* dedicated cpu */ +#define MSI_ADDR_REDIRECTION_LOWPRI (1 << MSI_ADDR_REDIRECTION_SHIFT) + /* lowest priority */ + +#define MSI_ADDR_DEST_ID_SHIFT 12 +#define MSI_ADDR_DEST_ID_MASK 0x00ffff0 +#define MSI_ADDR_DEST_ID(dest) (((dest) << MSI_ADDR_DEST_ID_SHIFT) & \ + MSI_ADDR_DEST_ID_MASK) + +#define MSI_ADDR_IR_EXT_INT (1 << 4) +#define MSI_ADDR_IR_SHV (1 << 3) +#define MSI_ADDR_IR_INDEX1(index) ((index & 0x8000) >> 13) +#define MSI_ADDR_IR_INDEX2(index) ((index & 0x7fff) << 5) + +#endif diff --git a/kvm_paging_tmpl.h b/kvm_paging_tmpl.h index 3c44040..982bd3d 100644 --- a/kvm_paging_tmpl.h +++ b/kvm_paging_tmpl.h @@ -16,6 +16,7 @@ * the COPYING file in the top-level directory. * */ +#include <sys/sysmacros.h> /* * We need the mmu code to access both 32-bit and 64-bit guest ptes, @@ -470,7 +471,7 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr, } if (walker.level >= PT_DIRECTORY_LEVEL) { - level = min(walker.level, mapping_level(vcpu, walker.gfn)); + level = MIN(walker.level, mapping_level(vcpu, walker.gfn)); walker.gfn = walker.gfn & ~(KVM_PAGES_PER_HPAGE(level) - 1); } #ifdef XXX @@ -222,3 +222,51 @@ is_long_mode(struct kvm_vcpu *vcpu) return (0); #endif } + +unsigned short kvm_read_fs(void) +{ + unsigned short seg; + __asm__("mov %%fs, %0" : "=g"(seg)); + return seg; +} + +unsigned short kvm_read_gs(void) +{ + unsigned short seg; + __asm__("mov %%gs, %0" : "=g"(seg)); + return seg; +} + +unsigned short kvm_read_ldt(void) +{ + unsigned short ldt; + __asm__("sldt %0" : "=g"(ldt)); + return ldt; +} + +void kvm_load_fs(unsigned short sel) +{ + __asm__("mov %0, %%fs" : : "rm"(sel)); +} + +void kvm_load_gs(unsigned short sel) +{ + __asm__("mov %0, %%gs" : : "rm"(sel)); +} + +void kvm_load_ldt(unsigned short sel) +{ + __asm__("lldt %0" : : "rm"(sel)); +} + + +void kvm_get_idt(struct descriptor_table *table) +{ + __asm__("sidt %0" : "=m"(*table)); +} + +void kvm_get_gdt(struct descriptor_table *table) +{ + __asm__("sgdt %0" : "=m"(*table)); +} + @@ -23,8 +23,10 @@ /* * XXX Need proper header files! */ +#include "bitops.h" #include "processor-flags.h" #include "msr.h" +#include "kvm_cpuid.h" #include "irqflags.h" #include "kvm_host.h" #include "kvm_x86host.h" @@ -100,6 +102,11 @@ extern int kvm_mmu_get_spte_hierarchy(struct kvm_vcpu *, uint64_t, uint64_t sptes[4]); extern void kvm_queue_interrupt(struct kvm_vcpu *, uint8_t, int); extern int kvm_vcpu_init(struct kvm_vcpu *, struct kvm *, unsigned); +extern int irqchip_in_kernel(struct kvm *kvm); +extern unsigned long kvm_rip_read(struct kvm_vcpu *); +extern struct kvm_cpuid_entry2 *kvm_find_cpuid_entry(struct kvm_vcpu *vcpu, + uint32_t function, uint32_t index); + /* These are the region types */ #define MTRR_TYPE_UNCACHABLE 0 @@ -160,16 +167,6 @@ uint64_t *vmxarea_pa; /* physical address of each vmxarea */ #define RMODE_GUEST_OWNED_EFLAGS_BITS (~(X86_EFLAGS_IOPL | X86_EFLAGS_VM)) -#define __kvm_handle_fault_on_reboot(insn) \ - "666: " insn "\n\t" \ - ".pushsection .fixup, \"ax\" \n" \ - "667: \n\t" \ - __ASM_SIZE(push) " $666b \n\t" \ - ".popsection \n\t" \ - ".pushsection __ex_table, \"a\" \n\t" \ - _ASM_PTR " 666b, 667b \n\t" \ - ".popsection \n\t" - #define __ex(x) __kvm_handle_fault_on_reboot(x) #define page_to_phys(page) (page->p_pagenum << PAGESHIFT) @@ -294,6 +291,14 @@ typedef struct vmx_capability { .ar_bytes = GUEST_##seg##_AR_BYTES, \ } +typedef struct kvm_vmx_segment_field { + unsigned selector; + unsigned base; + unsigned limit; + unsigned ar_bytes; +} kvm_vmx_segment_field_t; + + struct kvm_vmx_segment_field kvm_vmx_segment_fields[] = { VMX_SEGMENT_FIELD(CS), VMX_SEGMENT_FIELD(DS), @@ -324,6 +329,14 @@ static const uint32_t vmx_msr_index[] = { #define NR_VMX_MSR ARRAY_SIZE(vmx_msr_index) +static void native_load_tr_desc(void) +{ + __asm__ volatile("ltr %w0"::"q" (KTSS_SEL)); +} + +#define load_TR_desc() native_load_tr_desc() + + static int is_page_fault(uint32_t intr_info) { @@ -24,6 +24,7 @@ #include <sys/int_limits.h> #include <sys/x_call.h> +#include "bitops.h" #include "msr-index.h" #include "msr.h" #include "vmx.h" @@ -31,7 +32,6 @@ #include "apicdef.h" #include "kvm_types.h" #include "kvm_host.h" -#include "kvm_x86host.h" #include "kvm_iodev.h" #define PER_CPU_ATTRIBUTES @@ -63,6 +63,7 @@ extern int is_long_mode(struct kvm_vcpu *vcpu); extern void kvm_mmu_unload(struct kvm_vcpu *); extern void kvm_free_physmem_slot(struct kvm_memory_slot *, struct kvm_memory_slot *); +extern unsigned long get_desc_base(const struct desc_struct *desc); unsigned long segment_base(uint16_t selector) diff --git a/kvm_x86.h b/kvm_x86.h new file mode 100644 index 0000000..ff98454 --- /dev/null +++ b/kvm_x86.h @@ -0,0 +1,259 @@ +#ifndef __KVM_X86_H +#define __KVM_X86_H + +#include <sys/types.h> + +#define KVM_NR_INTERRUPTS 256 + +/* for KVM_GET_IRQCHIP and KVM_SET_IRQCHIP */ +typedef struct kvm_pic_state { + uint8_t last_irr; /* edge detection */ + uint8_t irr; /* interrupt request register */ + uint8_t imr; /* interrupt mask register */ + uint8_t isr; /* interrupt service register */ + uint8_t priority_add; /* highest irq priority */ + uint8_t irq_base; + uint8_t read_reg_select; + uint8_t poll; + uint8_t special_mask; + uint8_t init_state; + uint8_t auto_eoi; + uint8_t rotate_on_auto_eoi; + uint8_t special_fully_nested_mode; + uint8_t init4; /* true if 4 byte init */ + uint8_t elcr; /* PIIX edge/trigger selection */ + uint8_t elcr_mask; +} kvm_pic_state_t; + +#define KVM_IOAPIC_NUM_PINS 24 +typedef struct kvm_ioapic_state { + uint64_t base_address; + uint32_t ioregsel; + uint32_t id; + uint32_t irr; + uint32_t pad; + union { + uint64_t bits; + struct { + uint8_t vector; + uint8_t delivery_mode:3; + uint8_t dest_mode:1; + uint8_t delivery_status:1; + uint8_t polarity:1; + uint8_t remote_irr:1; + uint8_t trig_mode:1; + uint8_t mask:1; + uint8_t reserve:7; + uint8_t reserved[4]; + uint8_t dest_id; + } fields; + } redirtbl[KVM_IOAPIC_NUM_PINS]; +} kvm_ioapic_state_t; + +#define KVM_IRQCHIP_PIC_MASTER 0 +#define KVM_IRQCHIP_PIC_SLAVE 1 +#define KVM_IRQCHIP_IOAPIC 2 +#define KVM_NR_IRQCHIPS 3 + +/* for KVM_GET_REGS and KVM_SET_REGS */ +typedef struct kvm_regs { + /* out (KVM_GET_REGS) / in (KVM_SET_REGS) */ + uint64_t rax, rbx, rcx, rdx; + uint64_t rsi, rdi, rsp, rbp; + uint64_t r8, r9, r10, r11; + uint64_t r12, r13, r14, r15; + uint64_t rip, rflags; +} kvm_regs_t; + +/* for KVM_GET_LAPIC and KVM_SET_LAPIC */ +#define KVM_APIC_REG_SIZE 0x400 +typedef struct kvm_lapic_state { + char regs[KVM_APIC_REG_SIZE]; +} kvm_lapic_state_t; + +typedef struct kvm_segment { + uint64_t base; + uint32_t limit; + unsigned short selector; + unsigned char type; + unsigned char present, dpl, db, s, l, g, avl; + unsigned char unusable; + unsigned char padding; +} kvm_segment_t; + +typedef struct kvm_dtable { + uint64_t base; + unsigned short limit; + unsigned short padding[3]; +} kvm_dtable_t; + +/* for KVM_GET_SREGS and KVM_SET_SREGS */ +typedef struct kvm_sregs { + /* out (KVM_GET_SREGS) / in (KVM_SET_SREGS) */ + struct kvm_segment cs, ds, es, fs, gs, ss; + struct kvm_segment tr, ldt; + struct kvm_dtable gdt, idt; + uint64_t cr0, cr2, cr3, cr4, cr8; + uint64_t efer; + uint64_t apic_base; + unsigned long interrupt_bitmap[(KVM_NR_INTERRUPTS + (64-1)) / 64]; /*XXX 64 = bits in unsigned long*/ +} kvm_sregs_t; + +/* for KVM_GET_FPU and KVM_SET_FPU */ +typedef struct kvm_fpu { + unsigned char fpr[8][16]; + unsigned short fcw; + unsigned short fsw; + unsigned char ftwx; /* in fxsave format */ + unsigned char pad1; + unsigned short last_opcode; + uint64_t last_ip; + uint64_t last_dp; + unsigned char xmm[16][16]; + uint32_t mxcsr; + uint32_t pad2; +} kvm_fpu_t; + +typedef struct kvm_msr_entry { + uint32_t index; + uint32_t reserved; + uint64_t data; +} kvm_msr_entry_t; + +/* for KVM_GET_MSRS and KVM_SET_MSRS */ +typedef struct kvm_msrs { + uint32_t nmsrs; /* number of msrs in entries */ + uint32_t pad; + + struct kvm_msr_entry entries[100]; +} kvm_msrs_t; + +/* for KVM_GET_MSR_INDEX_LIST */ +typedef struct kvm_msr_list { + uint32_t nmsrs; /* number of msrs in entries */ + uint32_t indices[1]; +} kvm_msr_list_t; + +typedef struct kvm_cpuid_entry { + uint32_t function; + uint32_t eax; + uint32_t ebx; + uint32_t ecx; + uint32_t edx; + uint32_t padding; +} kvm_cpuid_entry_t; + +/* for KVM_SET_CPUID */ +typedef struct kvm_cpuid { + uint32_t nent; + uint32_t padding; + struct kvm_cpuid_entry entries[100]; +} kvm_cpuid_t; + +typedef struct kvm_cpuid_entry2 { + uint32_t function; + uint32_t index; + uint32_t flags; + uint32_t eax; + uint32_t ebx; + uint32_t ecx; + uint32_t edx; + uint32_t padding[3]; +} kvm_cpuid_entry2_t; + + +#define KVM_CPUID_FLAG_SIGNIFCANT_INDEX 1 +#define KVM_CPUID_FLAG_STATEFUL_FUNC 2 +#define KVM_CPUID_FLAG_STATE_READ_NEXT 4 + +/* for KVM_SET_CPUID2 */ +typedef struct kvm_cpuid2 { + uint32_t nent; + uint32_t padding; + struct kvm_cpuid_entry2 entries[100]; +} kvm_cpuid2_t; + +/* for KVM_GET_PIT and KVM_SET_PIT */ +typedef struct kvm_pit_channel_state { + uint32_t count; /* can be 65536 */ + uint16_t latched_count; + uint8_t count_latched; + uint8_t status_latched; + uint8_t status; + uint8_t read_state; + uint8_t write_state; + uint8_t write_latch; + uint8_t rw_mode; + uint8_t mode; + uint8_t bcd; + uint8_t gate; + int64_t count_load_time; +} kvm_pit_channel_state_t; + +typedef struct kvm_debug_exit_arch { + uint32_t exception; + uint32_t pad; + uint64_t pc; + uint64_t dr6; + uint64_t dr7; +} kvm_debug_exit_arch_t; + +#define KVM_GUESTDBG_USE_SW_BP 0x00010000 +#define KVM_GUESTDBG_USE_HW_BP 0x00020000 +#define KVM_GUESTDBG_INJECT_DB 0x00040000 +#define KVM_GUESTDBG_INJECT_BP 0x00080000 + +/* for KVM_SET_GUEST_DEBUG */ +typedef struct kvm_guest_debug_arch { + uint64_t debugreg[8]; +} kvm_guest_debug_arch_t; + + +typedef struct kvm_pit_state { + struct kvm_pit_channel_state channels[3]; +} kvm_pit_state_t; + +#define KVM_PIT_FLAGS_HPET_LEGACY 0x00000001 + +typedef struct kvm_pit_state2 { + struct kvm_pit_channel_state channels[3]; + uint32_t flags; + uint32_t reserved[9]; +} kvm_pit_state2_t; + +typedef struct kvm_reinject_control { + uint8_t pit_reinject; + uint8_t reserved[31]; +} kvm_reinject_control_t; + +/* When set in flags, include corresponding fields on KVM_SET_VCPU_EVENTS */ +#define KVM_VCPUEVENT_VALID_NMI_PENDING 0x00000001 +#define KVM_VCPUEVENT_VALID_SIPI_VECTOR 0x00000002 + +/* for KVM_GET/SET_VCPU_EVENTS */ +typedef struct kvm_vcpu_events { + struct { + unsigned char injected; + unsigned char nr; + unsigned char has_error_code; + unsigned char pad; + uint32_t error_code; + } exception; + struct { + unsigned char injected; + unsigned char nr; + unsigned char soft; + unsigned char pad; + } interrupt; + struct { + unsigned char injected; + unsigned char pending; + unsigned char masked; + unsigned char pad; + } nmi; + uint32_t sipi_vector; + uint32_t flags; + uint32_t reserved[10]; +} kvm_vcpu_events_t; + +#endif /* __KVM_X86_H */ diff --git a/kvm_x86host.h b/kvm_x86host.h index b42375f..bc8bb67 100644 --- a/kvm_x86host.h +++ b/kvm_x86host.h @@ -1,41 +1,21 @@ -/* - * Kernel-based Virtual Machine driver for Linux - * - * This header defines architecture specific interfaces, x86 version - * - * This work is licensed under the terms of the GNU GPL, version 2. See - * the COPYING file in the top-level directory. - * - */ - -#ifndef _ASM_X86_KVM_HOST_H -#define _ASM_X86_KVM_HOST_H - -#ifdef XXX -#include <linux/types.h> -#include <linux/mm.h> -#include <linux/mmu_notifier.h> -#include <linux/tracepoint.h> - -#include <linux/kvm.h> -#include <linux/kvm_para.h> -#include <linux/kvm_types.h> +#ifndef __KVM_X86_HOST_H +#define __KVM_X86_HOST_H -#include <asm/pvclock-abi.h> -#include <asm/desc.h> -#include <asm/mtrr.h> -#include <asm/msr-index.h> - -#endif - -#include <sys/avl.h> -#include <sys/ksynch.h> +#include <sys/types.h> #include <sys/list.h> +#include <sys/mutex.h> +#include <sys/avl.h> #include <sys/bitmap.h> #include <vm/page.h> #include <sys/pte.h> + +#include "kvm.h" #include "kvm_types.h" -#include "msr.h" + +#define KVM_MAX_VCPUS 64 +#define KVM_MEMORY_SLOTS 32 +/* memory slots that are not exposted to userspace */ +#define KVM_PRIVATE_MEM_SLOTS 4 /* XXX assumes x86 */ #define KVM_PIO_PAGE_OFFSET 1 #define KVM_COALESCED_MMIO_PAGE_OFFSET 2 @@ -89,24 +69,11 @@ #define KVM_NR_FIXED_MTRR_REGION 88 #define KVM_NR_VAR_MTRR 8 -#ifdef _KERNEL extern kmutex_t kvm_lock; extern list_t vm_list; struct kvm_vcpu; struct kvm; -#endif /*_KERNEL*/ - -enum { - VCPU_SREG_ES, - VCPU_SREG_CS, - VCPU_SREG_SS, - VCPU_SREG_DS, - VCPU_SREG_FS, - VCPU_SREG_GS, - VCPU_SREG_TR, - VCPU_SREG_LDTR, -}; enum kvm_reg { VCPU_REGS_RAX = 0, @@ -135,6 +102,17 @@ enum kvm_reg_ex { VCPU_EXREG_PDPTR = NR_VCPU_REGS, }; +enum { + VCPU_SREG_ES, + VCPU_SREG_CS, + VCPU_SREG_SS, + VCPU_SREG_DS, + VCPU_SREG_FS, + VCPU_SREG_GS, + VCPU_SREG_TR, + VCPU_SREG_LDTR, +}; + #include "kvm_emulate.h" #define KVM_NR_MEM_OBJS 40 @@ -163,7 +141,6 @@ typedef struct kvm_mmu_memory_cache { void *objects[KVM_NR_MEM_OBJS]; } kvm_mmu_memory_cache_t; -#ifdef _KERNEL #define NR_PTE_CHAIN_ENTRIES 5 typedef struct kvm_pte_chain { @@ -231,8 +208,6 @@ typedef struct kvm_mmu_page { unsigned long unsync_child_bitmap[BT_BITOUL(512)]; } kvm_mmu_page_t; -#endif /*_KERNEL*/ - typedef struct kvm_pv_mmu_op_buffer { void *ptr; unsigned len; @@ -253,7 +228,6 @@ typedef struct kvm_pio_request { int rep; } kvm_pio_request_t; -#ifdef _KERNEL /* * x86 supports 3 paging modes (4-level 64-bit, 3-level 64-bit, and 2-level * 32-bit). The kvm_mmu structure abstracts the details of the current mmu @@ -279,93 +253,41 @@ typedef struct kvm_mmu { uint64_t rsvd_bits_mask[2][4]; } kvm_mmu_t; -#endif /*_KERNEL*/ - -typedef struct kvm_cpuid_entry2 { - uint32_t function; - uint32_t index; - uint32_t flags; - uint32_t eax; - uint32_t ebx; - uint32_t ecx; - uint32_t edx; - uint32_t padding[3]; -} kvm_cpuid_entry2_t; - -typedef struct kvm_segment { - uint64_t base; - uint32_t limit; - unsigned short selector; - unsigned char type; - unsigned char present, dpl, db, s, l, g, avl; - unsigned char unusable; - unsigned char padding; -} kvm_segment_t; - - -#ifdef _KERNEL - -struct x86_emulate_ctxt; - -/* In the Intel processor's MTRR interface, the MTRR type is always held in - an 8 bit field: */ -typedef unsigned char mtrr_type; - -#define MTRR_NUM_FIXED_RANGES 88 -#define MTRR_MAX_VAR_RANGES 256 - -typedef struct mtrr_var_range { - uint32_t base_lo; - uint32_t base_hi; - uint32_t mask_lo; - uint32_t mask_hi; -} mtrr_var_range_t; - -typedef 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; -} mtrr_state_type_t; - struct i387_fxsave_struct { - unsigned short cwd; /* Control Word */ - unsigned short swd; /* Status Word */ - unsigned short twd; /* Tag Word */ - unsigned short fop; /* Last Instruction Opcode */ - union { - struct { - uint64_t rip; /* Instruction Pointer */ - uint64_t rdp; /* Data Pointer */ - }v1; - struct { - uint32_t fip; /* FPU IP Offset */ - uint32_t fcs; /* FPU IP Selector */ - uint32_t foo; /* FPU Operand Offset */ - uint32_t fos; /* FPU Operand Selector */ - }v2; - }v12; - uint32_t mxcsr; /* MXCSR Register State */ - uint32_t mxcsr_mask; /* MXCSR Mask */ - - /* 8*16 bytes for each FP-reg = 128 bytes: */ - uint32_t st_space[32]; - - /* 16*16 bytes for each XMM-reg = 256 bytes: */ - uint32_t xmm_space[64]; - - uint32_t padding[12]; - - union { - uint32_t padding1[12]; - uint32_t sw_reserved[12]; - }v3; + unsigned short cwd; /* Control Word */ + unsigned short swd; /* Status Word */ + unsigned short twd; /* Tag Word */ + unsigned short fop; /* Last Instruction Opcode */ + union { + struct { + uint64_t rip; /* Instruction Pointer */ + uint64_t rdp; /* Data Pointer */ + }v1; + struct { + uint32_t fip; /* FPU IP Offset */ + uint32_t fcs; /* FPU IP Selector */ + uint32_t foo; /* FPU Operand Offset */ + uint32_t fos; /* FPU Operand Selector */ + }v2; + }v12; + uint32_t mxcsr; /* MXCSR Register State */ + uint32_t mxcsr_mask; /* MXCSR Mask */ + + /* 8*16 bytes for each FP-reg = 128 bytes: */ + uint32_t st_space[32]; + + /* 16*16 bytes for each XMM-reg = 256 bytes: */ + uint32_t xmm_space[64]; + + uint32_t padding[12]; + + union { + uint32_t padding1[12]; + uint32_t sw_reserved[12]; + }v3; } __attribute__((aligned(16))); -typedef struct i387_fxsave_struct i387_fxsave_struct_t; - /* * These structs MUST NOT be changed. * They are the ABI between hypervisor and guest OS. @@ -386,18 +308,54 @@ typedef struct i387_fxsave_struct i387_fxsave_struct_t; * and after reading them. */ -struct pvclock_vcpu_time_info { +struct pvclock_wall_clock { uint32_t version; - uint32_t pad0; - uint64_t tsc_timestamp; - uint64_t system_time; - uint32_t tsc_to_system_mul; - char tsc_shift; - unsigned char pad[3]; + uint32_t sec; + uint32_t nsec; +} __attribute__((__packed__)); + +typedef struct pvclock_wall_clock pvclock_wall_clock_t; + +struct pvclock_vcpu_time_info { + uint32_t version; + uint32_t pad0; + uint64_t tsc_timestamp; + uint64_t system_time; + uint32_t tsc_to_system_mul; + char tsc_shift; + unsigned char pad[3]; } __attribute__((__packed__)); /* 32 bytes */ typedef struct pvclock_vcpu_time_info pvclock_vcpu_time_info_t; +typedef struct msi_msg { + uint32_t address_lo; /* low 32 bits of msi message address */ + uint32_t address_hi; /* high 32 bits of msi message address */ + uint32_t data; /* 16 bits of msi message data */ +} msi_msg_t; + +/* In the Intel processor's MTRR interface, the MTRR type is always held in + an 8 bit field: */ +typedef unsigned char mtrr_type; + +#define MTRR_NUM_FIXED_RANGES 88 +#define MTRR_MAX_VAR_RANGES 256 + +typedef struct mtrr_var_range { + uint32_t base_lo; + uint32_t base_hi; + uint32_t mask_lo; + uint32_t mask_hi; +} mtrr_var_range_t; + +typedef 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; +} mtrr_state_type_t; + typedef struct kvm_vcpu_arch { uint64_t host_tsc; /* @@ -529,17 +487,15 @@ typedef struct kvm_mem_aliases { } kvm_mem_aliases_t; typedef struct kvm_xen_hvm_config { - uint32_t flags; - uint32_t msr; - uint64_t blob_addr_32; - uint64_t blob_addr_64; - unsigned char blob_size_32; - unsigned char blob_size_64; - unsigned char pad2[30]; + uint32_t flags; + uint32_t msr; + uint64_t blob_addr_32; + uint64_t blob_addr_64; + unsigned char blob_size_32; + unsigned char blob_size_64; + unsigned char pad2[30]; } kvm_xen_hvm_config_t; - - typedef struct kvm_arch { struct kvm_mem_aliases *aliases; @@ -618,27 +574,6 @@ typedef struct kvm_vcpu_stat { uint32_t nmi_injections; } kvm_vcpu_stat_t; -#define KVM_GUESTDBG_USE_SW_BP 0x00010000 -#define KVM_GUESTDBG_USE_HW_BP 0x00020000 -#define KVM_GUESTDBG_INJECT_DB 0x00040000 -#define KVM_GUESTDBG_INJECT_BP 0x00080000 - -/* for KVM_SET_GUEST_DEBUG */ -typedef struct kvm_guest_debug_arch { - uint64_t debugreg[8]; -} kvm_guest_debug_arch_t; - -/* for KVM_SET_GUEST_DEBUG */ - -#define KVM_GUESTDBG_ENABLE 0x00000001 -#define KVM_GUESTDBG_SINGLESTEP 0x00000002 - -typedef struct kvm_guest_debug { - uint32_t control; - uint32_t pad; - struct kvm_guest_debug_arch arch; -} kvm_guest_debug_t; - struct descriptor_table { unsigned short limit; unsigned long base; @@ -646,8 +581,6 @@ struct descriptor_table { typedef struct descriptor_table descriptor_table_t; -struct kvm_vcpu_ioc; - typedef struct kvm_x86_ops { int (*cpu_has_kvm_support)(void); /* __init */ int (*disabled_by_bios)(void); /* __init */ @@ -743,8 +676,9 @@ void kvm_mmu_slot_remove_write_access(struct kvm *kvm, int slot); void kvm_mmu_zap_all(struct kvm *kvm); unsigned int kvm_mmu_calculate_mmu_pages(struct kvm *kvm); void kvm_mmu_change_mmu_pages(struct kvm *kvm, unsigned int kvm_nr_mmu_pages); + int load_pdptrs(struct kvm_vcpu *vcpu, unsigned long cr3); -#ifdef XXX + int emulator_write_phys(struct kvm_vcpu *vcpu, gpa_t gpa, const void *val, int bytes); int kvm_pv_mmu_op(struct kvm_vcpu *vcpu, unsigned long bytes, @@ -752,7 +686,6 @@ int kvm_pv_mmu_op(struct kvm_vcpu *vcpu, unsigned long bytes, uint8_t kvm_get_guest_memory_type(struct kvm_vcpu *vcpu, gfn_t gfn); extern int tdp_enabled; -#endif /*XXX*/ enum emulation_result { EMULATE_DONE, /* no further processing */ @@ -764,7 +697,6 @@ enum emulation_result { #define EMULTYPE_TRAP_UD (1 << 1) #define EMULTYPE_SKIP (1 << 2) -#ifdef XXX int emulate_instruction(struct kvm_vcpu *vcpu, unsigned long cr2, uint16_t error_code, int emulation_type); void kvm_report_emulation_failure(struct kvm_vcpu *cvpu, const char *context); @@ -780,7 +712,6 @@ void kvm_enable_efer_bits(uint64_t); int kvm_get_msr(struct kvm_vcpu *vcpu, uint32_t msr_index, uint64_t *data); int kvm_set_msr(struct kvm_vcpu *vcpu, uint32_t msr_index, uint64_t data); - int kvm_emulate_pio(struct kvm_vcpu *vcpu, int in, int size, unsigned port); int kvm_emulate_pio_string(struct kvm_vcpu *vcpu, int in, @@ -815,9 +746,7 @@ unsigned long kvm_get_rflags(struct kvm_vcpu *vcpu); void kvm_set_rflags(struct kvm_vcpu *vcpu, unsigned long rflags); void kvm_queue_exception(struct kvm_vcpu *vcpu, unsigned nr); -#endif /*XXX*/ extern void kvm_queue_exception_e(struct kvm_vcpu *vcpu, unsigned nr, uint32_t error_code); -#ifdef XXX void kvm_inject_page_fault(struct kvm_vcpu *vcpu, unsigned long cr2, uint32_t error_code); int kvm_require_cpl(struct kvm_vcpu *vcpu, int required_cpl); @@ -833,6 +762,30 @@ int emulator_write_emulated(unsigned long addr, unsigned int bytes, struct kvm_vcpu *vcpu); +/* + * FIXME: Accessing the desc_struct through its fields is more elegant, + * and should be the one valid thing to do. However, a lot of open code + * still touches the a and b accessors, and doing this allow us to do it + * incrementally. We keep the signature as a struct, rather than an union, + * so we can get rid of it transparently in the future -- glommer + */ +/* 8 byte segment descriptor */ +struct desc_struct { + union { + struct { + unsigned int a; + unsigned int b; + }a; + struct { + unsigned short limit0; + unsigned short 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; + }b; + }c; +} __attribute__((packed)); + +extern unsigned long segment_base(uint16_t selector); void kvm_mmu_flush_tlb(struct kvm_vcpu *vcpu); void kvm_mmu_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa, @@ -864,96 +817,43 @@ int kvm_check_iopl(struct kvm_vcpu *vcpu); struct kvm_memory_slot *gfn_to_memslot_unaliased(struct kvm *kvm, gfn_t gfn); +struct kvm_mmu_page *page_header(struct kvm *, hpa_t shadow_page); -#endif /*XXX*/ +/* XXX Fold into kvm_subr.c */ +unsigned short kvm_read_fs(void); +unsigned short kvm_read_gs(void); +unsigned short kvm_read_ldt(void); +void kvm_load_fs(unsigned short sel); +void kvm_load_gs(unsigned short sel); +void kvm_load_ldt(unsigned short sel); +void kvm_get_idt(struct descriptor_table *table); +void kvm_get_gdt(struct descriptor_table *table); -static unsigned short kvm_read_fs(void) -{ - unsigned short seg; - __asm__("mov %%fs, %0" : "=g"(seg)); - return seg; -} - -static unsigned short kvm_read_gs(void) -{ - unsigned short seg; - __asm__("mov %%gs, %0" : "=g"(seg)); - return seg; -} - -static unsigned short kvm_read_ldt(void) -{ - unsigned short ldt; - __asm__("sldt %0" : "=g"(ldt)); - return ldt; -} - -static void kvm_load_fs(unsigned short sel) -{ - __asm__("mov %0, %%fs" : : "rm"(sel)); -} - -static void kvm_load_gs(unsigned short sel) -{ - __asm__("mov %0, %%gs" : : "rm"(sel)); -} - -static void kvm_load_ldt(unsigned short sel) -{ - __asm__("lldt %0" : : "rm"(sel)); -} - - -static void kvm_get_idt(struct descriptor_table *table) -{ - __asm__("sidt %0" : "=m"(*table)); -} - -static void kvm_get_gdt(struct descriptor_table *table) -{ - __asm__("sgdt %0" : "=m"(*table)); -} +extern unsigned long kvm_read_tr_base(void); -/* - * FIXME: Accessing the desc_struct through its fields is more elegant, - * and should be the one valid thing to do. However, a lot of open code - * still touches the a and b accessors, and doing this allow us to do it - * incrementally. We keep the signature as a struct, rather than an union, - * so we can get rid of it transparently in the future -- glommer - */ -/* 8 byte segment descriptor */ -struct desc_struct { - union { - struct { - unsigned int a; - unsigned int b; - }a; - struct { - unsigned short limit0; - unsigned short 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; - }b; - }c; -} __attribute__((packed)); +extern unsigned long read_msr(unsigned long); -typedef struct desc_struct desc_struct_t; +void kvm_fx_save(struct i387_fxsave_struct *image); -static unsigned long get_desc_base(const struct desc_struct *desc) -{ - return (unsigned)(desc->c.b.base0 | ((desc->c.b.base1) << 16) | ((desc->c.b.base2) << 24)); -} +void kvm_fx_restore(struct i387_fxsave_struct *image); -extern unsigned long segment_base(uint16_t selector); -extern unsigned long kvm_read_tr_base(void); +void kvm_fx_finit(void); + +uint32_t get_rdx_init_val(void); + +void kvm_inject_gp(struct kvm_vcpu *vcpu, uint32_t error_code); + +#define __kvm_handle_fault_on_reboot(insn) \ + "666: " insn "\n\t" \ + ".pushsection .fixup, \"ax\" \n" \ + "667: \n\t" \ + __ASM_SIZE(push) " $666b \n\t" \ + ".popsection \n\t" \ + ".pushsection __ex_table, \"a\" \n\t" \ + _ASM_PTR " 666b, 667b \n\t" \ + ".popsection \n\t" -extern unsigned long read_msr(unsigned long msr); -extern void kvm_fx_save(struct i387_fxsave_struct *image); -extern void kvm_fx_restore(struct i387_fxsave_struct *image); -extern void kvm_fx_finit(void); -extern uint32_t get_rdx_init_val(void); -extern void kvm_inject_gp(struct kvm_vcpu *vcpu, uint32_t error_code); #define TSS_IOPB_BASE_OFFSET 0x66 #define TSS_BASE_SIZE 0x68 @@ -981,13 +881,15 @@ enum { * Trap the fault and ignore the instruction if that happens. */ -#include "linkage.h" - -#include <ia32/sys/asm_linkage.h> - -/*asmlinkage*/ void kvm_handle_fault_on_reboot(void); - - +#define __kvm_handle_fault_on_reboot(insn) \ + "666: " insn "\n\t" \ + ".pushsection .fixup, \"ax\" \n" \ + "667: \n\t" \ + __ASM_SIZE(push) " $666b \n\t" \ + ".popsection \n\t" \ + ".pushsection __ex_table, \"a\" \n\t" \ + _ASM_PTR " 666b, 667b \n\t" \ + ".popsection \n\t" #define KVM_ARCH_WANT_MMU_NOTIFIER @@ -1002,5 +904,7 @@ int kvm_cpu_get_interrupt(struct kvm_vcpu *v); void kvm_define_shared_msr(unsigned index, uint32_t msr); void kvm_set_shared_msr(struct kvm_vcpu *, unsigned index, uint64_t val, uint64_t mask); -#endif /*_KERNEL*/ -#endif /* _ASM_X86_KVM_HOST_H */ + +#define NMI_VECTOR 0x02 + +#endif |