diff options
Diffstat (limited to 'arch/x86/kvm/x86.c')
-rw-r--r-- | arch/x86/kvm/x86.c | 45 |
1 files changed, 33 insertions, 12 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 464da936c53d..02363e37d4a6 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -1763,6 +1763,7 @@ u64 get_kvmclock_ns(struct kvm *kvm) | |||
1763 | { | 1763 | { |
1764 | struct kvm_arch *ka = &kvm->arch; | 1764 | struct kvm_arch *ka = &kvm->arch; |
1765 | struct pvclock_vcpu_time_info hv_clock; | 1765 | struct pvclock_vcpu_time_info hv_clock; |
1766 | u64 ret; | ||
1766 | 1767 | ||
1767 | spin_lock(&ka->pvclock_gtod_sync_lock); | 1768 | spin_lock(&ka->pvclock_gtod_sync_lock); |
1768 | if (!ka->use_master_clock) { | 1769 | if (!ka->use_master_clock) { |
@@ -1774,10 +1775,17 @@ u64 get_kvmclock_ns(struct kvm *kvm) | |||
1774 | hv_clock.system_time = ka->master_kernel_ns + ka->kvmclock_offset; | 1775 | hv_clock.system_time = ka->master_kernel_ns + ka->kvmclock_offset; |
1775 | spin_unlock(&ka->pvclock_gtod_sync_lock); | 1776 | spin_unlock(&ka->pvclock_gtod_sync_lock); |
1776 | 1777 | ||
1778 | /* both __this_cpu_read() and rdtsc() should be on the same cpu */ | ||
1779 | get_cpu(); | ||
1780 | |||
1777 | kvm_get_time_scale(NSEC_PER_SEC, __this_cpu_read(cpu_tsc_khz) * 1000LL, | 1781 | kvm_get_time_scale(NSEC_PER_SEC, __this_cpu_read(cpu_tsc_khz) * 1000LL, |
1778 | &hv_clock.tsc_shift, | 1782 | &hv_clock.tsc_shift, |
1779 | &hv_clock.tsc_to_system_mul); | 1783 | &hv_clock.tsc_to_system_mul); |
1780 | return __pvclock_read_cycles(&hv_clock, rdtsc()); | 1784 | ret = __pvclock_read_cycles(&hv_clock, rdtsc()); |
1785 | |||
1786 | put_cpu(); | ||
1787 | |||
1788 | return ret; | ||
1781 | } | 1789 | } |
1782 | 1790 | ||
1783 | static void kvm_setup_pvclock_page(struct kvm_vcpu *v) | 1791 | static void kvm_setup_pvclock_page(struct kvm_vcpu *v) |
@@ -3288,11 +3296,14 @@ static void kvm_vcpu_ioctl_x86_get_xsave(struct kvm_vcpu *vcpu, | |||
3288 | } | 3296 | } |
3289 | } | 3297 | } |
3290 | 3298 | ||
3299 | #define XSAVE_MXCSR_OFFSET 24 | ||
3300 | |||
3291 | static int kvm_vcpu_ioctl_x86_set_xsave(struct kvm_vcpu *vcpu, | 3301 | static int kvm_vcpu_ioctl_x86_set_xsave(struct kvm_vcpu *vcpu, |
3292 | struct kvm_xsave *guest_xsave) | 3302 | struct kvm_xsave *guest_xsave) |
3293 | { | 3303 | { |
3294 | u64 xstate_bv = | 3304 | u64 xstate_bv = |
3295 | *(u64 *)&guest_xsave->region[XSAVE_HDR_OFFSET / sizeof(u32)]; | 3305 | *(u64 *)&guest_xsave->region[XSAVE_HDR_OFFSET / sizeof(u32)]; |
3306 | u32 mxcsr = *(u32 *)&guest_xsave->region[XSAVE_MXCSR_OFFSET / sizeof(u32)]; | ||
3296 | 3307 | ||
3297 | if (boot_cpu_has(X86_FEATURE_XSAVE)) { | 3308 | if (boot_cpu_has(X86_FEATURE_XSAVE)) { |
3298 | /* | 3309 | /* |
@@ -3300,11 +3311,13 @@ static int kvm_vcpu_ioctl_x86_set_xsave(struct kvm_vcpu *vcpu, | |||
3300 | * CPUID leaf 0xD, index 0, EDX:EAX. This is for compatibility | 3311 | * CPUID leaf 0xD, index 0, EDX:EAX. This is for compatibility |
3301 | * with old userspace. | 3312 | * with old userspace. |
3302 | */ | 3313 | */ |
3303 | if (xstate_bv & ~kvm_supported_xcr0()) | 3314 | if (xstate_bv & ~kvm_supported_xcr0() || |
3315 | mxcsr & ~mxcsr_feature_mask) | ||
3304 | return -EINVAL; | 3316 | return -EINVAL; |
3305 | load_xsave(vcpu, (u8 *)guest_xsave->region); | 3317 | load_xsave(vcpu, (u8 *)guest_xsave->region); |
3306 | } else { | 3318 | } else { |
3307 | if (xstate_bv & ~XFEATURE_MASK_FPSSE) | 3319 | if (xstate_bv & ~XFEATURE_MASK_FPSSE || |
3320 | mxcsr & ~mxcsr_feature_mask) | ||
3308 | return -EINVAL; | 3321 | return -EINVAL; |
3309 | memcpy(&vcpu->arch.guest_fpu.state.fxsave, | 3322 | memcpy(&vcpu->arch.guest_fpu.state.fxsave, |
3310 | guest_xsave->region, sizeof(struct fxregs_state)); | 3323 | guest_xsave->region, sizeof(struct fxregs_state)); |
@@ -4818,16 +4831,20 @@ emul_write: | |||
4818 | 4831 | ||
4819 | static int kernel_pio(struct kvm_vcpu *vcpu, void *pd) | 4832 | static int kernel_pio(struct kvm_vcpu *vcpu, void *pd) |
4820 | { | 4833 | { |
4821 | /* TODO: String I/O for in kernel device */ | 4834 | int r = 0, i; |
4822 | int r; | ||
4823 | 4835 | ||
4824 | if (vcpu->arch.pio.in) | 4836 | for (i = 0; i < vcpu->arch.pio.count; i++) { |
4825 | r = kvm_io_bus_read(vcpu, KVM_PIO_BUS, vcpu->arch.pio.port, | 4837 | if (vcpu->arch.pio.in) |
4826 | vcpu->arch.pio.size, pd); | 4838 | r = kvm_io_bus_read(vcpu, KVM_PIO_BUS, vcpu->arch.pio.port, |
4827 | else | 4839 | vcpu->arch.pio.size, pd); |
4828 | r = kvm_io_bus_write(vcpu, KVM_PIO_BUS, | 4840 | else |
4829 | vcpu->arch.pio.port, vcpu->arch.pio.size, | 4841 | r = kvm_io_bus_write(vcpu, KVM_PIO_BUS, |
4830 | pd); | 4842 | vcpu->arch.pio.port, vcpu->arch.pio.size, |
4843 | pd); | ||
4844 | if (r) | ||
4845 | break; | ||
4846 | pd += vcpu->arch.pio.size; | ||
4847 | } | ||
4831 | return r; | 4848 | return r; |
4832 | } | 4849 | } |
4833 | 4850 | ||
@@ -4865,6 +4882,8 @@ static int emulator_pio_in_emulated(struct x86_emulate_ctxt *ctxt, | |||
4865 | if (vcpu->arch.pio.count) | 4882 | if (vcpu->arch.pio.count) |
4866 | goto data_avail; | 4883 | goto data_avail; |
4867 | 4884 | ||
4885 | memset(vcpu->arch.pio_data, 0, size * count); | ||
4886 | |||
4868 | ret = emulator_pio_in_out(vcpu, size, port, val, count, true); | 4887 | ret = emulator_pio_in_out(vcpu, size, port, val, count, true); |
4869 | if (ret) { | 4888 | if (ret) { |
4870 | data_avail: | 4889 | data_avail: |
@@ -5048,6 +5067,8 @@ static bool emulator_get_segment(struct x86_emulate_ctxt *ctxt, u16 *selector, | |||
5048 | 5067 | ||
5049 | if (var.unusable) { | 5068 | if (var.unusable) { |
5050 | memset(desc, 0, sizeof(*desc)); | 5069 | memset(desc, 0, sizeof(*desc)); |
5070 | if (base3) | ||
5071 | *base3 = 0; | ||
5051 | return false; | 5072 | return false; |
5052 | } | 5073 | } |
5053 | 5074 | ||