diff options
author | max <max@maxpad.(none)> | 2010-12-21 16:40:44 +0100 |
---|---|---|
committer | max <max@maxpad.(none)> | 2010-12-21 16:40:44 +0100 |
commit | c8e2e3d1ec0e7b7fc3dcf4e23aa320c8b628e79a (patch) | |
tree | 409179b4e6b47632935744c7cae6a450a8e134ef | |
parent | 20f1d9adf1addcc1497e84d3c8413eebaed6ba72 (diff) | |
download | illumos-kvm-c8e2e3d1ec0e7b7fc3dcf4e23aa320c8b628e79a.tar.gz |
bug fixes. fixup_rmode_irq unresolved.
l--------- | .#kvm.i | 1 | ||||
-rw-r--r-- | .gitignore | 2 | ||||
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | kvm | bin | 325208 -> 266840 bytes | |||
-rw-r--r-- | kvm.c | 123 | ||||
-rw-r--r-- | kvm.h | 39 | ||||
-rw-r--r-- | kvm_x86.c | 37 | ||||
-rw-r--r-- | kvm_x86host.h | 40 |
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 @@ -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 @@ -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 @@ -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; @@ -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" @@ -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 */ |