Merge branch 'x86-fpu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 4 Nov 2015 04:50:26 +0000 (20:50 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 4 Nov 2015 04:50:26 +0000 (20:50 -0800)
Pull x86 fpu changes from Ingo Molnar:
 "There are two main areas of changes:

   - Rework of the extended FPU state code to robustify the kernel's
     usage of cpuid provided xstate sizes - and related changes (Dave
     Hansen)"

   - math emulation enhancements: new modern FPU instructions support,
     with testcases, plus cleanups (Denys Vlasnko)"

* 'x86-fpu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (23 commits)
  x86/fpu: Fixup uninitialized feature_name warning
  x86/fpu/math-emu: Add support for FISTTP instructions
  x86/fpu/math-emu, selftests: Add test for FISTTP instructions
  x86/fpu/math-emu: Add support for FCMOVcc insns
  x86/fpu/math-emu: Add support for F[U]COMI[P] insns
  x86/fpu/math-emu: Remove define layer for undocumented opcodes
  x86/fpu/math-emu, selftests: Add tests for FCMOV and FCOMI insns
  x86/fpu/math-emu: Remove !NO_UNDOC_CODE
  x86/fpu: Check CPU-provided sizes against struct declarations
  x86/fpu: Check to ensure increasing-offset xstate offsets
  x86/fpu: Correct and check XSAVE xstate size calculations
  x86/fpu: Add C structures for AVX-512 state components
  x86/fpu: Rework YMM definition
  x86/fpu/mpx: Rework MPX 'xstate' types
  x86/fpu: Add xfeature_enabled() helper instead of test_bit()
  x86/fpu: Remove 'xfeature_nr'
  x86/fpu: Rework XSTATE_* macros to remove magic '2'
  x86/fpu: Rename XFEATURES_NR_MAX
  x86/fpu: Rename XSAVE macros
  x86/fpu: Remove partial LWP support definitions
  ...

1  2 
arch/x86/crypto/camellia_aesni_avx_glue.c
arch/x86/kvm/x86.c
tools/testing/selftests/x86/Makefile

index bacaa13acac544e037571bd292e91f5239256edc,12e729bfe71b7b1f744972e48295989f41932d70..93d8f295784e399c2fc363d8b5602fede9039529
@@@ -554,12 -554,8 +554,13 @@@ static int __init camellia_aesni_init(v
  {
        const char *feature_name;
  
-       if (!cpu_has_xfeatures(XSTATE_SSE | XSTATE_YMM, &feature_name)) {
 +      if (!cpu_has_avx || !cpu_has_aes || !cpu_has_osxsave) {
 +              pr_info("AVX or AES-NI instructions are not detected.\n");
 +              return -ENODEV;
 +      }
 +
+       if (!cpu_has_xfeatures(XFEATURE_MASK_SSE | XFEATURE_MASK_YMM,
+                               &feature_name)) {
                pr_info("CPU feature '%s' is not supported.\n", feature_name);
                return -ENODEV;
        }
diff --combined arch/x86/kvm/x86.c
index 9a9a198303219b6430159af03d4d1e1d898ec6f7,2d4e54db49afc2c9a05ae1df97793a26252d4c9b..bda65690788ebb5ec27bab1b934532cfd1034a25
@@@ -149,7 -149,6 +149,7 @@@ struct kvm_stats_debugfs_item debugfs_e
        { "nmi_window", VCPU_STAT(nmi_window_exits) },
        { "halt_exits", VCPU_STAT(halt_exits) },
        { "halt_successful_poll", VCPU_STAT(halt_successful_poll) },
 +      { "halt_attempted_poll", VCPU_STAT(halt_attempted_poll) },
        { "halt_wakeup", VCPU_STAT(halt_wakeup) },
        { "hypercalls", VCPU_STAT(hypercalls) },
        { "request_irq", VCPU_STAT(request_irq_exits) },
@@@ -663,9 -662,9 +663,9 @@@ static int __kvm_set_xcr(struct kvm_vcp
        /* Only support XCR_XFEATURE_ENABLED_MASK(xcr0) now  */
        if (index != XCR_XFEATURE_ENABLED_MASK)
                return 1;
-       if (!(xcr0 & XSTATE_FP))
+       if (!(xcr0 & XFEATURE_MASK_FP))
                return 1;
-       if ((xcr0 & XSTATE_YMM) && !(xcr0 & XSTATE_SSE))
+       if ((xcr0 & XFEATURE_MASK_YMM) && !(xcr0 & XFEATURE_MASK_SSE))
                return 1;
  
        /*
         * saving.  However, xcr0 bit 0 is always set, even if the
         * emulated CPU does not support XSAVE (see fx_init).
         */
-       valid_bits = vcpu->arch.guest_supported_xcr0 | XSTATE_FP;
+       valid_bits = vcpu->arch.guest_supported_xcr0 | XFEATURE_MASK_FP;
        if (xcr0 & ~valid_bits)
                return 1;
  
-       if ((!(xcr0 & XSTATE_BNDREGS)) != (!(xcr0 & XSTATE_BNDCSR)))
+       if ((!(xcr0 & XFEATURE_MASK_BNDREGS)) !=
+           (!(xcr0 & XFEATURE_MASK_BNDCSR)))
                return 1;
  
-       if (xcr0 & XSTATE_AVX512) {
-               if (!(xcr0 & XSTATE_YMM))
+       if (xcr0 & XFEATURE_MASK_AVX512) {
+               if (!(xcr0 & XFEATURE_MASK_YMM))
                        return 1;
-               if ((xcr0 & XSTATE_AVX512) != XSTATE_AVX512)
+               if ((xcr0 & XFEATURE_MASK_AVX512) != XFEATURE_MASK_AVX512)
                        return 1;
        }
        kvm_put_guest_xcr0(vcpu);
        vcpu->arch.xcr0 = xcr0;
  
-       if ((xcr0 ^ old_xcr0) & XSTATE_EXTEND_MASK)
+       if ((xcr0 ^ old_xcr0) & XFEATURE_MASK_EXTEND)
                kvm_update_cpuid(vcpu);
        return 0;
  }
@@@ -1708,6 -1708,8 +1709,6 @@@ static int kvm_guest_time_update(struc
                vcpu->pvclock_set_guest_stopped_request = false;
        }
  
 -      pvclock_flags |= PVCLOCK_COUNTS_FROM_ZERO;
 -
        /* If the host uses TSC clocksource, then it is stable */
        if (use_master_clock)
                pvclock_flags |= PVCLOCK_TSC_STABLE_BIT;
@@@ -2005,6 -2007,8 +2006,6 @@@ int kvm_set_msr_common(struct kvm_vcpu 
                                        &vcpu->requests);
  
                        ka->boot_vcpu_runs_old_kvmclock = tmp;
 -
 -                      ka->kvmclock_offset = -get_kernel_ns();
                }
  
                vcpu->arch.time = data;
@@@ -2186,8 -2190,6 +2187,8 @@@ int kvm_get_msr_common(struct kvm_vcpu 
        case MSR_IA32_LASTINTFROMIP:
        case MSR_IA32_LASTINTTOIP:
        case MSR_K8_SYSCFG:
 +      case MSR_K8_TSEG_ADDR:
 +      case MSR_K8_TSEG_MASK:
        case MSR_K7_HWCR:
        case MSR_VM_HSAVE_PA:
        case MSR_K8_INT_PENDING_MSG:
@@@ -2905,7 -2907,7 +2906,7 @@@ static void fill_xsave(u8 *dest, struc
         * Copy each region from the possibly compacted offset to the
         * non-compacted offset.
         */
-       valid = xstate_bv & ~XSTATE_FPSSE;
+       valid = xstate_bv & ~XFEATURE_MASK_FPSSE;
        while (valid) {
                u64 feature = valid & -valid;
                int index = fls64(feature) - 1;
@@@ -2943,7 -2945,7 +2944,7 @@@ static void load_xsave(struct kvm_vcpu 
         * Copy each region from the non-compacted offset to the
         * possibly compacted offset.
         */
-       valid = xstate_bv & ~XSTATE_FPSSE;
+       valid = xstate_bv & ~XFEATURE_MASK_FPSSE;
        while (valid) {
                u64 feature = valid & -valid;
                int index = fls64(feature) - 1;
@@@ -2971,7 -2973,7 +2972,7 @@@ static void kvm_vcpu_ioctl_x86_get_xsav
                        &vcpu->arch.guest_fpu.state.fxsave,
                        sizeof(struct fxregs_state));
                *(u64 *)&guest_xsave->region[XSAVE_HDR_OFFSET / sizeof(u32)] =
-                       XSTATE_FPSSE;
+                       XFEATURE_MASK_FPSSE;
        }
  }
  
@@@ -2991,7 -2993,7 +2992,7 @@@ static int kvm_vcpu_ioctl_x86_set_xsave
                        return -EINVAL;
                load_xsave(vcpu, (u8 *)guest_xsave->region);
        } else {
-               if (xstate_bv & ~XSTATE_FPSSE)
+               if (xstate_bv & ~XFEATURE_MASK_FPSSE)
                        return -EINVAL;
                memcpy(&vcpu->arch.guest_fpu.state.fxsave,
                        guest_xsave->region, sizeof(struct fxregs_state));
@@@ -6453,12 -6455,6 +6454,12 @@@ static inline int vcpu_block(struct kv
        return 1;
  }
  
 +static inline bool kvm_vcpu_running(struct kvm_vcpu *vcpu)
 +{
 +      return (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE &&
 +              !vcpu->arch.apf.halted);
 +}
 +
  static int vcpu_run(struct kvm_vcpu *vcpu)
  {
        int r;
        vcpu->srcu_idx = srcu_read_lock(&kvm->srcu);
  
        for (;;) {
 -              if (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE &&
 -                  !vcpu->arch.apf.halted)
 +              if (kvm_vcpu_running(vcpu))
                        r = vcpu_enter_guest(vcpu);
                else
                        r = vcpu_block(kvm, vcpu);
@@@ -7005,7 -7002,7 +7006,7 @@@ static void fx_init(struct kvm_vcpu *vc
        /*
         * Ensure guest xcr0 is valid for loading
         */
-       vcpu->arch.xcr0 = XSTATE_FP;
+       vcpu->arch.xcr0 = XFEATURE_MASK_FP;
  
        vcpu->arch.cr0 |= X86_CR0_ET;
  }
@@@ -7479,66 -7476,34 +7480,66 @@@ void kvm_arch_sync_events(struct kvm *k
        kvm_free_pit(kvm);
  }
  
 -int __x86_set_memory_region(struct kvm *kvm,
 -                          const struct kvm_userspace_memory_region *mem)
 +int __x86_set_memory_region(struct kvm *kvm, int id, gpa_t gpa, u32 size)
  {
        int i, r;
 +      unsigned long hva;
 +      struct kvm_memslots *slots = kvm_memslots(kvm);
 +      struct kvm_memory_slot *slot, old;
  
        /* Called with kvm->slots_lock held.  */
 -      BUG_ON(mem->slot >= KVM_MEM_SLOTS_NUM);
 +      if (WARN_ON(id >= KVM_MEM_SLOTS_NUM))
 +              return -EINVAL;
  
 +      slot = id_to_memslot(slots, id);
 +      if (size) {
 +              if (WARN_ON(slot->npages))
 +                      return -EEXIST;
 +
 +              /*
 +               * MAP_SHARED to prevent internal slot pages from being moved
 +               * by fork()/COW.
 +               */
 +              hva = vm_mmap(NULL, 0, size, PROT_READ | PROT_WRITE,
 +                            MAP_SHARED | MAP_ANONYMOUS, 0);
 +              if (IS_ERR((void *)hva))
 +                      return PTR_ERR((void *)hva);
 +      } else {
 +              if (!slot->npages)
 +                      return 0;
 +
 +              hva = 0;
 +      }
 +
 +      old = *slot;
        for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++) {
 -              struct kvm_userspace_memory_region m = *mem;
 +              struct kvm_userspace_memory_region m;
  
 -              m.slot |= i << 16;
 +              m.slot = id | (i << 16);
 +              m.flags = 0;
 +              m.guest_phys_addr = gpa;
 +              m.userspace_addr = hva;
 +              m.memory_size = size;
                r = __kvm_set_memory_region(kvm, &m);
                if (r < 0)
                        return r;
        }
  
 +      if (!size) {
 +              r = vm_munmap(old.userspace_addr, old.npages * PAGE_SIZE);
 +              WARN_ON(r < 0);
 +      }
 +
        return 0;
  }
  EXPORT_SYMBOL_GPL(__x86_set_memory_region);
  
 -int x86_set_memory_region(struct kvm *kvm,
 -                        const struct kvm_userspace_memory_region *mem)
 +int x86_set_memory_region(struct kvm *kvm, int id, gpa_t gpa, u32 size)
  {
        int r;
  
        mutex_lock(&kvm->slots_lock);
 -      r = __x86_set_memory_region(kvm, mem);
 +      r = __x86_set_memory_region(kvm, id, gpa, size);
        mutex_unlock(&kvm->slots_lock);
  
        return r;
@@@ -7553,9 -7518,16 +7554,9 @@@ void kvm_arch_destroy_vm(struct kvm *kv
                 * unless the the memory map has changed due to process exit
                 * or fd copying.
                 */
 -              struct kvm_userspace_memory_region mem;
 -              memset(&mem, 0, sizeof(mem));
 -              mem.slot = APIC_ACCESS_PAGE_PRIVATE_MEMSLOT;
 -              x86_set_memory_region(kvm, &mem);
 -
 -              mem.slot = IDENTITY_PAGETABLE_PRIVATE_MEMSLOT;
 -              x86_set_memory_region(kvm, &mem);
 -
 -              mem.slot = TSS_PRIVATE_MEMSLOT;
 -              x86_set_memory_region(kvm, &mem);
 +              x86_set_memory_region(kvm, APIC_ACCESS_PAGE_PRIVATE_MEMSLOT, 0, 0);
 +              x86_set_memory_region(kvm, IDENTITY_PAGETABLE_PRIVATE_MEMSLOT, 0, 0);
 +              x86_set_memory_region(kvm, TSS_PRIVATE_MEMSLOT, 0, 0);
        }
        kvm_iommu_unmap_guest(kvm);
        kfree(kvm->arch.vpic);
@@@ -7658,6 -7630,27 +7659,6 @@@ int kvm_arch_prepare_memory_region(stru
                                const struct kvm_userspace_memory_region *mem,
                                enum kvm_mr_change change)
  {
 -      /*
 -       * Only private memory slots need to be mapped here since
 -       * KVM_SET_MEMORY_REGION ioctl is no longer supported.
 -       */
 -      if ((memslot->id >= KVM_USER_MEM_SLOTS) && (change == KVM_MR_CREATE)) {
 -              unsigned long userspace_addr;
 -
 -              /*
 -               * MAP_SHARED to prevent internal slot pages from being moved
 -               * by fork()/COW.
 -               */
 -              userspace_addr = vm_mmap(NULL, 0, memslot->npages * PAGE_SIZE,
 -                                       PROT_READ | PROT_WRITE,
 -                                       MAP_SHARED | MAP_ANONYMOUS, 0);
 -
 -              if (IS_ERR((void *)userspace_addr))
 -                      return PTR_ERR((void *)userspace_addr);
 -
 -              memslot->userspace_addr = userspace_addr;
 -      }
 -
        return 0;
  }
  
@@@ -7719,6 -7712,17 +7720,6 @@@ void kvm_arch_commit_memory_region(stru
  {
        int nr_mmu_pages = 0;
  
 -      if (change == KVM_MR_DELETE && old->id >= KVM_USER_MEM_SLOTS) {
 -              int ret;
 -
 -              ret = vm_munmap(old->userspace_addr,
 -                              old->npages * PAGE_SIZE);
 -              if (ret < 0)
 -                      printk(KERN_WARNING
 -                             "kvm_vm_ioctl_set_memory_region: "
 -                             "failed to munmap memory\n");
 -      }
 -
        if (!kvm->arch.n_requested_mmu_pages)
                nr_mmu_pages = kvm_mmu_calculate_mmu_pages(kvm);
  
@@@ -7767,36 -7771,19 +7768,36 @@@ void kvm_arch_flush_shadow_memslot(stru
        kvm_mmu_invalidate_zap_all_pages(kvm);
  }
  
 +static inline bool kvm_vcpu_has_events(struct kvm_vcpu *vcpu)
 +{
 +      if (!list_empty_careful(&vcpu->async_pf.done))
 +              return true;
 +
 +      if (kvm_apic_has_events(vcpu))
 +              return true;
 +
 +      if (vcpu->arch.pv.pv_unhalted)
 +              return true;
 +
 +      if (atomic_read(&vcpu->arch.nmi_queued))
 +              return true;
 +
 +      if (test_bit(KVM_REQ_SMI, &vcpu->requests))
 +              return true;
 +
 +      if (kvm_arch_interrupt_allowed(vcpu) &&
 +          kvm_cpu_has_interrupt(vcpu))
 +              return true;
 +
 +      return false;
 +}
 +
  int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
  {
        if (is_guest_mode(vcpu) && kvm_x86_ops->check_nested_events)
                kvm_x86_ops->check_nested_events(vcpu, false);
  
 -      return (vcpu->arch.mp_state == KVM_MP_STATE_RUNNABLE &&
 -              !vcpu->arch.apf.halted)
 -              || !list_empty_careful(&vcpu->async_pf.done)
 -              || kvm_apic_has_events(vcpu)
 -              || vcpu->arch.pv.pv_unhalted
 -              || atomic_read(&vcpu->arch.nmi_queued) ||
 -              (kvm_arch_interrupt_allowed(vcpu) &&
 -               kvm_cpu_has_interrupt(vcpu));
 +      return kvm_vcpu_running(vcpu) || kvm_vcpu_has_events(vcpu);
  }
  
  int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
index 389701f599406bffa76980d98f27a0cb913ac1d5,7145b3d9030ca62422633c8023451bdc557f8c53..eabcff4119840aaf663da3bbd0a8c4154b072881
@@@ -4,8 -4,9 +4,9 @@@ include ../lib.m
  
  .PHONY: all all_32 all_64 warn_32bit_failure clean
  
 -TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs ldt_gdt syscall_nt
 -TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault sigreturn \
 +TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs ldt_gdt syscall_nt ptrace_syscall
- TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault sigreturn test_syscall_vdso unwind_vdso
++TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault sigreturn test_syscall_vdso unwind_vdso \
+                       test_FCMOV test_FCOMI test_FISTTP
  
  TARGETS_C_32BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_32BIT_ONLY)
  BINARIES_32 := $(TARGETS_C_32BIT_ALL:%=%_32)
@@@ -35,7 -36,7 +36,7 @@@ clean
        $(RM) $(BINARIES_32) $(BINARIES_64)
  
  $(TARGETS_C_32BIT_ALL:%=%_32): %_32: %.c
-       $(CC) -m32 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl
+       $(CC) -m32 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl -lm
  
  $(TARGETS_C_BOTHBITS:%=%_64): %_64: %.c
        $(CC) -m64 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl
@@@ -60,5 -61,3 +61,5 @@@ endi
  
  # Some tests have additional dependencies.
  sysret_ss_attrs_64: thunks.S
 +ptrace_syscall_32: raw_syscall_helper_32.S
 +test_syscall_vdso_32: thunks_32.S