summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormax <max@maxpad.(none)>2010-12-21 16:40:44 +0100
committermax <max@maxpad.(none)>2010-12-21 16:40:44 +0100
commitc8e2e3d1ec0e7b7fc3dcf4e23aa320c8b628e79a (patch)
tree409179b4e6b47632935744c7cae6a450a8e134ef
parent20f1d9adf1addcc1497e84d3c8413eebaed6ba72 (diff)
downloadillumos-kvm-c8e2e3d1ec0e7b7fc3dcf4e23aa320c8b628e79a.tar.gz
bug fixes. fixup_rmode_irq unresolved.
l---------.#kvm.i1
-rw-r--r--.gitignore2
-rw-r--r--Makefile2
-rw-r--r--kvmbin325208 -> 266840 bytes
-rw-r--r--kvm.c123
-rw-r--r--kvm.h39
-rw-r--r--kvm_x86.c37
-rw-r--r--kvm_x86host.h40
8 files changed, 161 insertions, 83 deletions
diff --git a/.#kvm.i b/.#kvm.i
deleted file mode 120000
index d3b8abd..0000000
--- a/.#kvm.i
+++ /dev/null
@@ -1 +0,0 @@
-max@maxpad.1918:1292836846 \ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 1fdb4d8..7d2541c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,7 @@ config-all-devices.*
config-host.*
config-target.*
i386
+kvm
*-softmmu
*-darwin-user
*-linux-user
@@ -44,6 +45,7 @@ qemu-monitor.texi
*.vr
*.d
*.o
+*.i
.pc
patches
pc-bios/bios-pq/status
diff --git a/Makefile b/Makefile
index b74e15d..b181a26 100644
--- a/Makefile
+++ b/Makefile
@@ -9,7 +9,7 @@ LD=/usr/bin/ld
CTFCONVERT=$(KERNEL_SOURCE)/usr/src/tools/proto/opt/onbld/bin/i386/ctfconvert
CTFMERGE=$(KERNEL_SOURCE)/usr/src/tools/proto/opt/onbld/bin/i386/ctfmerge
-CFLAGS += -D_KERNEL -D_MACHDEP -Dx86 -DCONFIG_X86_64 -DDEBUG -c -g -DCONFIG_SOLARIS -DCONFIG_KVM_MMIO
+CFLAGS += -D_KERNEL -D_MACHDEP -Dx86 -DCONFIG_X86_64 -DDEBUG -c -g -DCONFIG_SOLARIS -DCONFIG_KVM_MMIO -O2
INCLUDEDIR= -I $(KERNEL_SOURCE)/usr/src/uts/intel -I $(KERNEL_SOURCE)/usr/src/uts/i86pc -I $(KERNEL_SOURCE)/usr/src/uts/common
diff --git a/kvm b/kvm
index ea27a70..9b78c69 100644
--- a/kvm
+++ b/kvm
Binary files differ
diff --git a/kvm.c b/kvm.c
index 4ce9958..af12b37 100644
--- a/kvm.c
+++ b/kvm.c
@@ -177,6 +177,10 @@ static void vmx_set_nmi_mask(struct kvm_vcpu *vcpu, int masked);
static void enable_nmi_window(struct kvm_vcpu *vcpu);
static void enable_irq_window(struct kvm_vcpu *vcpu);
static void vmx_cpuid_update(struct kvm_vcpu *vcpu);
+static void vmx_fpu_activate(struct kvm_vcpu *vcpu);
+static void vmx_fpu_deactivate(struct kvm_vcpu *vcpu);
+static void vmx_decache_cr0_guest_bits(struct kvm_vcpu *vcpu);
+static void vmx_decache_cr4_guest_bits(struct kvm_vcpu *vcpu);
int get_ept_level(void);
static void vmx_cache_reg(struct kvm_vcpu *vcpu, enum kvm_reg reg);
@@ -239,8 +243,8 @@ static struct kvm_x86_ops vmx_x86_ops = {
.set_segment = vmx_set_segment /*vmx_set_segment*/,
.get_cpl = vmx_get_cpl /*vmx_get_cpl*/,
.get_cs_db_l_bits = nulldev /*vmx_get_cs_db_l_bits*/,
- .decache_cr0_guest_bits = nulldev /*vmx_decache_cr0_guest_bits*/,
- .decache_cr4_guest_bits = nulldev /*vmx_decache_cr4_guest_bits*/,
+ .decache_cr0_guest_bits = vmx_decache_cr0_guest_bits /*vmx_decache_cr0_guest_bits*/,
+ .decache_cr4_guest_bits = vmx_decache_cr4_guest_bits /*vmx_decache_cr4_guest_bits*/,
.set_cr0 = vmx_set_cr0,
.set_cr3 = vmx_set_cr3 /*vmx_set_cr3*/,
.set_cr4 = vmx_set_cr4,
@@ -252,8 +256,8 @@ static struct kvm_x86_ops vmx_x86_ops = {
.cache_reg = vmx_cache_reg /*vmx_cache_reg*/,
.get_rflags = vmx_get_rflags /*vmx_get_rflags*/,
.set_rflags = vmx_set_rflags /*vmx_set_rflags*/,
- .fpu_activate = nulldev /*vmx_fpu_activate*/,
- .fpu_deactivate = nulldev /*vmx_fpu_deactivate*/,
+ .fpu_activate = vmx_fpu_activate /*vmx_fpu_activate*/,
+ .fpu_deactivate = vmx_fpu_deactivate /*vmx_fpu_deactivate*/,
.tlb_flush = nulldev /*vmx_flush_tlb*/,
@@ -298,6 +302,70 @@ void vmcs_write32(unsigned long field, uint32_t value)
vmcs_writel(field, value);
}
+static void vmx_decache_cr0_guest_bits(struct kvm_vcpu *vcpu)
+{
+ ulong cr0_guest_owned_bits = vcpu->arch.cr0_guest_owned_bits;
+
+ vcpu->arch.cr0 &= ~cr0_guest_owned_bits;
+ vcpu->arch.cr0 |= vmcs_readl(GUEST_CR0) & cr0_guest_owned_bits;
+}
+
+static void vmx_decache_cr4_guest_bits(struct kvm_vcpu *vcpu)
+{
+ ulong cr4_guest_owned_bits = vcpu->arch.cr4_guest_owned_bits;
+
+ vcpu->arch.cr4 &= ~cr4_guest_owned_bits;
+ vcpu->arch.cr4 |= vmcs_readl(GUEST_CR4) & cr4_guest_owned_bits;
+}
+
+inline ulong kvm_read_cr0_bits(struct kvm_vcpu *vcpu, ulong mask)
+{
+ ulong tmask = mask & KVM_POSSIBLE_CR0_GUEST_BITS;
+
+ if (tmask & vcpu->arch.cr0_guest_owned_bits)
+ kvm_x86_ops->decache_cr0_guest_bits(vcpu);
+
+ return vcpu->arch.cr0 & mask;
+}
+
+static void vmcs_clear_bits(unsigned long field, uint32_t mask)
+{
+ vmcs_writel(field, vmcs_readl(field) & ~mask);
+}
+
+static void vmcs_set_bits(unsigned long field, uint32_t mask)
+{
+ vmcs_writel(field, vmcs_readl(field) | mask);
+}
+
+extern void update_exception_bitmap(struct kvm_vcpu *vcpu);
+
+static void vmx_fpu_activate(struct kvm_vcpu *vcpu)
+{
+ ulong cr0;
+
+ if (vcpu->fpu_active)
+ return;
+ vcpu->fpu_active = 1;
+ cr0 = vmcs_readl(GUEST_CR0);
+ cr0 &= ~(X86_CR0_TS | X86_CR0_MP);
+ cr0 |= kvm_read_cr0_bits(vcpu, X86_CR0_TS | X86_CR0_MP);
+ vmcs_writel(GUEST_CR0, cr0);
+ update_exception_bitmap(vcpu);
+ vcpu->arch.cr0_guest_owned_bits = X86_CR0_TS;
+ vmcs_writel(CR0_GUEST_HOST_MASK, ~vcpu->arch.cr0_guest_owned_bits);
+}
+
+static void vmx_fpu_deactivate(struct kvm_vcpu *vcpu)
+{
+ vmx_decache_cr0_guest_bits(vcpu);
+ vmcs_set_bits(GUEST_CR0, X86_CR0_TS | X86_CR0_MP);
+ update_exception_bitmap(vcpu);
+ vcpu->arch.cr0_guest_owned_bits = 0;
+ vmcs_writel(CR0_GUEST_HOST_MASK, ~vcpu->arch.cr0_guest_owned_bits);
+ vmcs_writel(CR0_READ_SHADOW, vcpu->arch.cr0);
+}
+
static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
{
struct kvm_cpuid_entry2 *best;
@@ -352,16 +420,6 @@ static void enable_nmi_window(struct kvm_vcpu *vcpu)
vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control);
}
-static void vmcs_clear_bits(unsigned long field, uint32_t mask)
-{
- vmcs_writel(field, vmcs_readl(field) & ~mask);
-}
-
-static void vmcs_set_bits(unsigned long field, uint32_t mask)
-{
- vmcs_writel(field, vmcs_readl(field) | mask);
-}
-
static void vmx_set_nmi_mask(struct kvm_vcpu *vcpu, int masked)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
@@ -1829,6 +1887,7 @@ int
zero_constructor(void *buf, void *arg, int tags)
{
bzero(buf, (size_t)arg);
+ return 0;
}
int kvm_mmu_module_init(void)
@@ -2112,8 +2171,12 @@ int kvm_init(void *opaque, unsigned int vcpu_size)
goto out_free_4;
#endif /*XXX*/
/* A kmem cache lets us meet the alignment requirements of fx_save. */
- kvm_vcpu_cache = kmem_cache_create("kvm_vcpu", vcpu_size,
- __alignof__(struct kvm_vcpu),
+ kvm_vcpu_cache = kmem_cache_create("kvm_vcpu", (size_t)vcpu_size,
+#ifdef XXX
+ (size_t)__alignof__(struct kvm_vcpu),
+#else
+ (size_t)PAGESIZE,
+#endif /*XXX*/
zero_constructor, NULL, NULL,
(void *)vcpu_size, NULL, 0);
if (!kvm_vcpu_cache) {
@@ -4112,12 +4175,14 @@ void kvm_put_guest_fpu(struct kvm_vcpu *vcpu)
if (!vcpu->guest_fpu_loaded)
return;
-#ifdef XXX
vcpu->guest_fpu_loaded = 0;
kvm_fx_save(&vcpu->arch.guest_fx_image);
kvm_fx_restore(&vcpu->arch.host_fx_image);
+#ifdef XXX
++vcpu->stat.fpu_reload;
- BT_BIT(&vcpu->requests, KVM_REQ_DEACTIVATE_FPU);
+#endif /*XXX*/
+ BT_SET(&vcpu->requests, KVM_REQ_DEACTIVATE_FPU);
+#ifdef XXX
trace_kvm_fpu(0);
#endif /*XXX*/
}
@@ -4154,18 +4219,13 @@ int is_long_mode(struct kvm_vcpu *vcpu)
#endif
}
-#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)
-
ulong kvm_read_cr4_bits(struct kvm_vcpu *vcpu, ulong mask)
{
uint64_t tmask = mask & KVM_POSSIBLE_CR4_GUEST_BITS;
-#ifdef XXX
+
if (tmask & vcpu->arch.cr4_guest_owned_bits)
kvm_x86_ops->decache_cr4_guest_bits(vcpu);
-#endif /*XXX*/
+
return vcpu->arch.cr4 & mask;
}
@@ -4681,17 +4741,6 @@ ulong kvm_read_cr4(struct kvm_vcpu *vcpu)
return kvm_read_cr4_bits(vcpu, ~0UL);
}
-inline ulong kvm_read_cr0_bits(struct kvm_vcpu *vcpu, ulong mask)
-{
- ulong tmask = mask & KVM_POSSIBLE_CR0_GUEST_BITS;
-#ifdef XXX
- if (tmask & vcpu->arch.cr0_guest_owned_bits)
- kvm_x86_ops->decache_cr0_guest_bits(vcpu);
-#endif /*XXX*/
- return vcpu->arch.cr0 & mask;
-}
-
-
ulong kvm_read_cr0(struct kvm_vcpu *vcpu)
{
return kvm_read_cr0_bits(vcpu, ~0UL);
@@ -6603,10 +6652,8 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu)
vmx->idt_vectoring_info = vmcs_read32(IDT_VECTORING_INFO_FIELD);
-#ifdef XXX
if (vmx->rmode.irq.pending)
fixup_rmode_irq(vmx);
-#endif /*XXX*/
asm("mov %0, %%ds; mov %0, %%es" : : "r"SEL_GDT(GDT_UDATA, SEL_UPL));
vmx->launched = 1;
diff --git a/kvm.h b/kvm.h
index e15d573..f1e3021 100644
--- a/kvm.h
+++ b/kvm.h
@@ -261,42 +261,13 @@ struct fxsave {
#endif
};
-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;
+#define KVM_MAX_CPUID_ENTRIES 40
-} __attribute__((aligned(16)));
+#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)
-#define KVM_MAX_CPUID_ENTRIES 40
#ifdef _KERNEL
#include "kvm_emulate.h"
diff --git a/kvm_x86.c b/kvm_x86.c
index 479e253..aafedc8 100644
--- a/kvm_x86.c
+++ b/kvm_x86.c
@@ -1528,7 +1528,7 @@ kvm_arch_vcpu_create(struct kvm *kvm, struct kvm_vcpu_ioc *arg, unsigned int id)
extern int enable_ept;
-static void update_exception_bitmap(struct kvm_vcpu *vcpu)
+void update_exception_bitmap(struct kvm_vcpu *vcpu)
{
uint32_t eb;
@@ -2013,6 +2013,35 @@ extern void kvm_register_write(struct kvm_vcpu *vcpu,
extern ulong kvm_read_cr0(struct kvm_vcpu *vcpu);
extern void setup_msrs(struct vcpu_vmx *vmx);
+void fx_init(struct kvm_vcpu *vcpu)
+{
+ unsigned after_mxcsr_mask;
+#ifdef XXX
+ /*
+ * Touch the fpu the first time in non atomic context as if
+ * this is the first fpu instruction the exception handler
+ * will fire before the instruction returns and it'll have to
+ * allocate ram with GFP_KERNEL.
+ */
+ if (!used_math())
+ kvm_fx_save(&vcpu->arch.host_fx_image);
+#endif /*XXX*/
+
+ /* Initialize guest FPU by resetting ours and saving into guest's */
+ kpreempt_disable();
+ kvm_fx_save(&vcpu->arch.host_fx_image);
+ kvm_fx_finit();
+ kvm_fx_save(&vcpu->arch.guest_fx_image);
+ kvm_fx_restore(&vcpu->arch.host_fx_image);
+ kpreempt_enable();
+
+ vcpu->arch.cr0 |= X86_CR0_ET;
+ after_mxcsr_mask = offsetof(struct i387_fxsave_struct, st_space);
+ vcpu->arch.guest_fx_image.mxcsr = 0x1f80;
+ memset((void *)&vcpu->arch.guest_fx_image + after_mxcsr_mask,
+ 0, sizeof(struct i387_fxsave_struct) - after_mxcsr_mask);
+}
+
int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
@@ -2035,15 +2064,13 @@ int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
vmx->vcpu.arch.regs[VCPU_REGS_RDX] = get_rdx_init_val();
kvm_set_cr8(&vmx->vcpu, 0);
msr = 0xfee00000 | MSR_IA32_APICBASE_ENABLE;
-#ifdef XXX
+
if (kvm_vcpu_is_bsp(&vmx->vcpu))
msr |= MSR_IA32_APICBASE_BSP;
-#endif /*XXX*/
+
kvm_set_apic_base(&vmx->vcpu, msr);
-#ifdef XXX
fx_init(&vmx->vcpu);
-#endif
seg_setup(VCPU_SREG_CS);
/*
diff --git a/kvm_x86host.h b/kvm_x86host.h
index b303d68..fe4d719 100644
--- a/kvm_x86host.h
+++ b/kvm_x86host.h
@@ -322,6 +322,41 @@ struct mtrr_state_type {
mtrr_type def_type;
};
+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;
+
+} __attribute__((aligned(16)));
+
struct kvm_vcpu_arch {
uint64_t host_tsc;
/*
@@ -371,10 +406,8 @@ struct kvm_vcpu_arch {
unsigned long mmu_seq;
} update_pte;
-#ifdef XXX
struct i387_fxsave_struct host_fx_image;
struct i387_fxsave_struct guest_fx_image;
-#endif /*XXX*/
gva_t mmio_fault_cr2;
struct kvm_pio_request pio;
@@ -886,7 +919,6 @@ static inline unsigned long read_msr(unsigned long msr)
}
#endif
-#ifdef XXX
static inline void kvm_fx_save(struct i387_fxsave_struct *image)
{
asm("fxsave (%0)":: "r" (image));
@@ -901,7 +933,7 @@ static inline void kvm_fx_finit(void)
{
asm("finit");
}
-#endif /*XXX*/
+
static inline uint32_t get_rdx_init_val(void)
{
return 0x600; /* P6 family */