KVM: x86: add module parameter to disable periodic kvmclock sync
[firefly-linux-kernel-4.4.55.git] / arch / x86 / kvm / x86.c
index cdccbe1749a53165ad1168fa1d4ec7e16d22d4c1..2211213a84e7a4184d297842ecc354b0760a6573 100644 (file)
@@ -99,6 +99,9 @@ module_param(ignore_msrs, bool, S_IRUGO | S_IWUSR);
 unsigned int min_timer_period_us = 500;
 module_param(min_timer_period_us, uint, S_IRUGO | S_IWUSR);
 
+static bool __read_mostly kvmclock_periodic_sync = true;
+module_param(kvmclock_periodic_sync, bool, S_IRUGO);
+
 bool kvm_has_tsc_control;
 EXPORT_SYMBOL_GPL(kvm_has_tsc_control);
 u32  kvm_max_guest_tsc_khz;
@@ -572,8 +575,7 @@ out:
 int kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
 {
        unsigned long old_cr0 = kvm_read_cr0(vcpu);
-       unsigned long update_bits = X86_CR0_PG | X86_CR0_WP |
-                                   X86_CR0_CD | X86_CR0_NW;
+       unsigned long update_bits = X86_CR0_PG | X86_CR0_WP;
 
        cr0 |= X86_CR0_ET;
 
@@ -702,8 +704,9 @@ EXPORT_SYMBOL_GPL(kvm_set_xcr);
 int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
 {
        unsigned long old_cr4 = kvm_read_cr4(vcpu);
-       unsigned long pdptr_bits = X86_CR4_PGE | X86_CR4_PSE |
-                                  X86_CR4_PAE | X86_CR4_SMEP;
+       unsigned long pdptr_bits = X86_CR4_PGE | X86_CR4_PSE | X86_CR4_PAE |
+                                  X86_CR4_SMEP | X86_CR4_SMAP;
+
        if (cr4 & CR4_RESERVED_BITS)
                return 1;
 
@@ -744,9 +747,6 @@ int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
            (!(cr4 & X86_CR4_PCIDE) && (old_cr4 & X86_CR4_PCIDE)))
                kvm_mmu_reset_context(vcpu);
 
-       if ((cr4 ^ old_cr4) & X86_CR4_SMAP)
-               update_permission_bitmask(vcpu, vcpu->arch.walk_mmu, false);
-
        if ((cr4 ^ old_cr4) & X86_CR4_OSXSAVE)
                kvm_update_cpuid(vcpu);
 
@@ -1770,6 +1770,9 @@ static void kvmclock_sync_fn(struct work_struct *work)
                                           kvmclock_sync_work);
        struct kvm *kvm = container_of(ka, struct kvm, arch);
 
+       if (!kvmclock_periodic_sync)
+               return;
+
        schedule_delayed_work(&kvm->arch.kvmclock_update_work, 0);
        schedule_delayed_work(&kvm->arch.kvmclock_sync_work,
                                        KVMCLOCK_SYNC_PERIOD);
@@ -1854,6 +1857,63 @@ bool kvm_mtrr_valid(struct kvm_vcpu *vcpu, u32 msr, u64 data)
 }
 EXPORT_SYMBOL_GPL(kvm_mtrr_valid);
 
+static void update_mtrr(struct kvm_vcpu *vcpu, u32 msr)
+{
+       struct mtrr_state_type *mtrr_state = &vcpu->arch.mtrr_state;
+       unsigned char mtrr_enabled = mtrr_state->enabled;
+       gfn_t start, end, mask;
+       int index;
+       bool is_fixed = true;
+
+       if (msr == MSR_IA32_CR_PAT || !tdp_enabled ||
+             !kvm_arch_has_noncoherent_dma(vcpu->kvm))
+               return;
+
+       if (!(mtrr_enabled & 0x2) && msr != MSR_MTRRdefType)
+               return;
+
+       switch (msr) {
+       case MSR_MTRRfix64K_00000:
+               start = 0x0;
+               end = 0x80000;
+               break;
+       case MSR_MTRRfix16K_80000:
+               start = 0x80000;
+               end = 0xa0000;
+               break;
+       case MSR_MTRRfix16K_A0000:
+               start = 0xa0000;
+               end = 0xc0000;
+               break;
+       case MSR_MTRRfix4K_C0000 ... MSR_MTRRfix4K_F8000:
+               index = msr - MSR_MTRRfix4K_C0000;
+               start = 0xc0000 + index * (32 << 10);
+               end = start + (32 << 10);
+               break;
+       case MSR_MTRRdefType:
+               is_fixed = false;
+               start = 0x0;
+               end = ~0ULL;
+               break;
+       default:
+               /* variable range MTRRs. */
+               is_fixed = false;
+               index = (msr - 0x200) / 2;
+               start = (((u64)mtrr_state->var_ranges[index].base_hi) << 32) +
+                      (mtrr_state->var_ranges[index].base_lo & PAGE_MASK);
+               mask = (((u64)mtrr_state->var_ranges[index].mask_hi) << 32) +
+                      (mtrr_state->var_ranges[index].mask_lo & PAGE_MASK);
+               mask |= ~0ULL << cpuid_maxphyaddr(vcpu);
+
+               end = ((start & mask) | ~mask) + 1;
+       }
+
+       if (is_fixed && !(mtrr_enabled & 0x1))
+               return;
+
+       kvm_zap_gfn_range(vcpu->kvm, gpa_to_gfn(start), gpa_to_gfn(end));
+}
+
 static int set_msr_mtrr(struct kvm_vcpu *vcpu, u32 msr, u64 data)
 {
        u64 *p = (u64 *)&vcpu->arch.mtrr_state.fixed_ranges;
@@ -1887,7 +1947,7 @@ static int set_msr_mtrr(struct kvm_vcpu *vcpu, u32 msr, u64 data)
                *pt = data;
        }
 
-       kvm_mmu_reset_context(vcpu);
+       update_mtrr(vcpu, msr);
        return 0;
 }
 
@@ -6228,6 +6288,8 @@ void kvm_vcpu_reload_apic_access_page(struct kvm_vcpu *vcpu)
                return;
 
        page = gfn_to_page(vcpu->kvm, APIC_DEFAULT_PHYS_BASE >> PAGE_SHIFT);
+       if (is_error_page(page))
+               return;
        kvm_x86_ops->set_apic_access_page_addr(vcpu, page_to_phys(page));
 
        /*
@@ -7101,7 +7163,7 @@ void kvm_put_guest_fpu(struct kvm_vcpu *vcpu)
         * Every 255 times fpu_counter rolls over to 0; a guest that uses
         * the FPU in bursts will revert to loading it on demand.
         */
-       if (!use_eager_fpu()) {
+       if (!vcpu->arch.eager_fpu) {
                if (++vcpu->fpu_counter < 5)
                        kvm_make_request(KVM_REQ_DEACTIVATE_FPU, vcpu);
        }
@@ -7120,11 +7182,21 @@ void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu)
 struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
                                                unsigned int id)
 {
+       struct kvm_vcpu *vcpu;
+
        if (check_tsc_unstable() && atomic_read(&kvm->online_vcpus) != 0)
                printk_once(KERN_WARNING
                "kvm: SMP vm created on host with unstable TSC; "
                "guest TSC will not be reliable\n");
-       return kvm_x86_ops->vcpu_create(kvm, id);
+
+       vcpu = kvm_x86_ops->vcpu_create(kvm, id);
+
+       /*
+        * Activate fpu unconditionally in case the guest needs eager FPU.  It will be
+        * deactivated soon if it doesn't.
+        */
+       kvm_x86_ops->fpu_activate(vcpu);
+       return vcpu;
 }
 
 int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
@@ -7155,6 +7227,9 @@ void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
        kvm_write_tsc(vcpu, &msr);
        vcpu_put(vcpu);
 
+       if (!kvmclock_periodic_sync)
+               return;
+
        schedule_delayed_work(&kvm->arch.kvmclock_sync_work,
                                        KVMCLOCK_SYNC_PERIOD);
 }
@@ -7623,7 +7698,7 @@ out_free:
        return -ENOMEM;
 }
 
-void kvm_arch_memslots_updated(struct kvm *kvm)
+void kvm_arch_memslots_updated(struct kvm *kvm, struct kvm_memslots *slots)
 {
        /*
         * memslots->generation has been incremented.
@@ -7634,7 +7709,7 @@ void kvm_arch_memslots_updated(struct kvm *kvm)
 
 int kvm_arch_prepare_memory_region(struct kvm *kvm,
                                struct kvm_memory_slot *memslot,
-                               struct kvm_userspace_memory_region *mem,
+                               const struct kvm_userspace_memory_region *mem,
                                enum kvm_mr_change change)
 {
        /*
@@ -7712,14 +7787,14 @@ static void kvm_mmu_slot_apply_flags(struct kvm *kvm,
 }
 
 void kvm_arch_commit_memory_region(struct kvm *kvm,
-                               struct kvm_userspace_memory_region *mem,
+                               const struct kvm_userspace_memory_region *mem,
                                const struct kvm_memory_slot *old,
+                               const struct kvm_memory_slot *new,
                                enum kvm_mr_change change)
 {
-       struct kvm_memory_slot *new;
        int nr_mmu_pages = 0;
 
-       if ((mem->slot >= KVM_USER_MEM_SLOTS) && (change == KVM_MR_DELETE)) {
+       if (change == KVM_MR_DELETE && old->id >= KVM_USER_MEM_SLOTS) {
                int ret;
 
                ret = vm_munmap(old->userspace_addr,
@@ -7736,9 +7811,6 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
        if (nr_mmu_pages)
                kvm_mmu_change_mmu_pages(kvm, nr_mmu_pages);
 
-       /* It's OK to get 'new' slot here as it has already been installed */
-       new = id_to_memslot(kvm->memslots, mem->slot);
-
        /*
         * Dirty logging tracks sptes in 4k granularity, meaning that large
         * sptes have to be split.  If live migration is successful, the guest
@@ -7763,9 +7835,11 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
         * been zapped so no dirty logging staff is needed for old slot. For
         * KVM_MR_FLAGS_ONLY, the old slot is essentially the same one as the
         * new and it's also covered when dealing with the new slot.
+        *
+        * FIXME: const-ify all uses of struct kvm_memory_slot.
         */
        if (change != KVM_MR_DELETE)
-               kvm_mmu_slot_apply_flags(kvm, new);
+               kvm_mmu_slot_apply_flags(kvm, (struct kvm_memory_slot *) new);
 }
 
 void kvm_arch_flush_shadow_all(struct kvm *kvm)