Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 84ff7a00 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'kvm-updates-2.6.27' of git://git.kernel.org/pub/scm/linux/kernel/git/avi/kvm

* 'kvm-updates-2.6.27' of git://git.kernel.org/pub/scm/linux/kernel/git/avi/kvm:
  KVM: s390: Fix kvm on IBM System z10
  KVM: Advertise synchronized mmu support to userspace
  KVM: Synchronize guest physical memory map to host virtual memory map
  KVM: Allow browsing memslots with mmu_lock
  KVM: Allow reading aliases with mmu_lock
parents 478735e4 1f4170e1
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -158,6 +158,7 @@ static int handle_stfl(struct kvm_vcpu *vcpu)

	vcpu->stat.instruction_stfl++;
	facility_list &= ~(1UL<<24); /* no stfle */
	facility_list &= ~(1UL<<23); /* no large pages */

	rc = copy_to_guest(vcpu, offsetof(struct _lowcore, stfl_fac_list),
			   &facility_list, sizeof(facility_list));
+100 −0
Original line number Diff line number Diff line
@@ -653,6 +653,84 @@ static void rmap_write_protect(struct kvm *kvm, u64 gfn)
	account_shadowed(kvm, gfn);
}

static int kvm_unmap_rmapp(struct kvm *kvm, unsigned long *rmapp)
{
	u64 *spte;
	int need_tlb_flush = 0;

	while ((spte = rmap_next(kvm, rmapp, NULL))) {
		BUG_ON(!(*spte & PT_PRESENT_MASK));
		rmap_printk("kvm_rmap_unmap_hva: spte %p %llx\n", spte, *spte);
		rmap_remove(kvm, spte);
		set_shadow_pte(spte, shadow_trap_nonpresent_pte);
		need_tlb_flush = 1;
	}
	return need_tlb_flush;
}

static int kvm_handle_hva(struct kvm *kvm, unsigned long hva,
			  int (*handler)(struct kvm *kvm, unsigned long *rmapp))
{
	int i;
	int retval = 0;

	/*
	 * If mmap_sem isn't taken, we can look the memslots with only
	 * the mmu_lock by skipping over the slots with userspace_addr == 0.
	 */
	for (i = 0; i < kvm->nmemslots; i++) {
		struct kvm_memory_slot *memslot = &kvm->memslots[i];
		unsigned long start = memslot->userspace_addr;
		unsigned long end;

		/* mmu_lock protects userspace_addr */
		if (!start)
			continue;

		end = start + (memslot->npages << PAGE_SHIFT);
		if (hva >= start && hva < end) {
			gfn_t gfn_offset = (hva - start) >> PAGE_SHIFT;
			retval |= handler(kvm, &memslot->rmap[gfn_offset]);
			retval |= handler(kvm,
					  &memslot->lpage_info[
						  gfn_offset /
						  KVM_PAGES_PER_HPAGE].rmap_pde);
		}
	}

	return retval;
}

int kvm_unmap_hva(struct kvm *kvm, unsigned long hva)
{
	return kvm_handle_hva(kvm, hva, kvm_unmap_rmapp);
}

static int kvm_age_rmapp(struct kvm *kvm, unsigned long *rmapp)
{
	u64 *spte;
	int young = 0;

	spte = rmap_next(kvm, rmapp, NULL);
	while (spte) {
		int _young;
		u64 _spte = *spte;
		BUG_ON(!(_spte & PT_PRESENT_MASK));
		_young = _spte & PT_ACCESSED_MASK;
		if (_young) {
			young = 1;
			clear_bit(PT_ACCESSED_SHIFT, (unsigned long *)spte);
		}
		spte = rmap_next(kvm, rmapp, spte);
	}
	return young;
}

int kvm_age_hva(struct kvm *kvm, unsigned long hva)
{
	return kvm_handle_hva(kvm, hva, kvm_age_rmapp);
}

#ifdef MMU_DEBUG
static int is_empty_shadow_page(u64 *spt)
{
@@ -1203,6 +1281,7 @@ static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, int write, gfn_t gfn)
	int r;
	int largepage = 0;
	pfn_t pfn;
	unsigned long mmu_seq;

	down_read(&current->mm->mmap_sem);
	if (is_largepage_backed(vcpu, gfn & ~(KVM_PAGES_PER_HPAGE-1))) {
@@ -1210,6 +1289,8 @@ static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, int write, gfn_t gfn)
		largepage = 1;
	}

	mmu_seq = vcpu->kvm->mmu_notifier_seq;
	/* implicit mb(), we'll read before PT lock is unlocked */
	pfn = gfn_to_pfn(vcpu->kvm, gfn);
	up_read(&current->mm->mmap_sem);

@@ -1220,6 +1301,8 @@ static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, int write, gfn_t gfn)
	}

	spin_lock(&vcpu->kvm->mmu_lock);
	if (mmu_notifier_retry(vcpu, mmu_seq))
		goto out_unlock;
	kvm_mmu_free_some_pages(vcpu);
	r = __direct_map(vcpu, v, write, largepage, gfn, pfn,
			 PT32E_ROOT_LEVEL);
@@ -1227,6 +1310,11 @@ static int nonpaging_map(struct kvm_vcpu *vcpu, gva_t v, int write, gfn_t gfn)


	return r;

out_unlock:
	spin_unlock(&vcpu->kvm->mmu_lock);
	kvm_release_pfn_clean(pfn);
	return 0;
}


@@ -1345,6 +1433,7 @@ static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t gpa,
	int r;
	int largepage = 0;
	gfn_t gfn = gpa >> PAGE_SHIFT;
	unsigned long mmu_seq;

	ASSERT(vcpu);
	ASSERT(VALID_PAGE(vcpu->arch.mmu.root_hpa));
@@ -1358,6 +1447,8 @@ static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t gpa,
		gfn &= ~(KVM_PAGES_PER_HPAGE-1);
		largepage = 1;
	}
	mmu_seq = vcpu->kvm->mmu_notifier_seq;
	/* implicit mb(), we'll read before PT lock is unlocked */
	pfn = gfn_to_pfn(vcpu->kvm, gfn);
	up_read(&current->mm->mmap_sem);
	if (is_error_pfn(pfn)) {
@@ -1365,12 +1456,19 @@ static int tdp_page_fault(struct kvm_vcpu *vcpu, gva_t gpa,
		return 1;
	}
	spin_lock(&vcpu->kvm->mmu_lock);
	if (mmu_notifier_retry(vcpu, mmu_seq))
		goto out_unlock;
	kvm_mmu_free_some_pages(vcpu);
	r = __direct_map(vcpu, gpa, error_code & PFERR_WRITE_MASK,
			 largepage, gfn, pfn, kvm_x86_ops->get_tdp_level());
	spin_unlock(&vcpu->kvm->mmu_lock);

	return r;

out_unlock:
	spin_unlock(&vcpu->kvm->mmu_lock);
	kvm_release_pfn_clean(pfn);
	return 0;
}

static void nonpaging_free(struct kvm_vcpu *vcpu)
@@ -1670,6 +1768,8 @@ static void mmu_guess_page_from_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
		gfn &= ~(KVM_PAGES_PER_HPAGE-1);
		vcpu->arch.update_pte.largepage = 1;
	}
	vcpu->arch.update_pte.mmu_seq = vcpu->kvm->mmu_notifier_seq;
	/* implicit mb(), we'll read before PT lock is unlocked */
	pfn = gfn_to_pfn(vcpu->kvm, gfn);
	up_read(&current->mm->mmap_sem);

+12 −0
Original line number Diff line number Diff line
@@ -263,6 +263,8 @@ static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *page,
	pfn = vcpu->arch.update_pte.pfn;
	if (is_error_pfn(pfn))
		return;
	if (mmu_notifier_retry(vcpu, vcpu->arch.update_pte.mmu_seq))
		return;
	kvm_get_pfn(pfn);
	mmu_set_spte(vcpu, spte, page->role.access, pte_access, 0, 0,
		     gpte & PT_DIRTY_MASK, NULL, largepage, gpte_to_gfn(gpte),
@@ -380,6 +382,7 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr,
	int r;
	pfn_t pfn;
	int largepage = 0;
	unsigned long mmu_seq;

	pgprintk("%s: addr %lx err %x\n", __func__, addr, error_code);
	kvm_mmu_audit(vcpu, "pre page fault");
@@ -413,6 +416,8 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr,
			largepage = 1;
		}
	}
	mmu_seq = vcpu->kvm->mmu_notifier_seq;
	/* implicit mb(), we'll read before PT lock is unlocked */
	pfn = gfn_to_pfn(vcpu->kvm, walker.gfn);
	up_read(&current->mm->mmap_sem);

@@ -424,6 +429,8 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr,
	}

	spin_lock(&vcpu->kvm->mmu_lock);
	if (mmu_notifier_retry(vcpu, mmu_seq))
		goto out_unlock;
	kvm_mmu_free_some_pages(vcpu);
	shadow_pte = FNAME(fetch)(vcpu, addr, &walker, user_fault, write_fault,
				  largepage, &write_pt, pfn);
@@ -439,6 +446,11 @@ static int FNAME(page_fault)(struct kvm_vcpu *vcpu, gva_t addr,
	spin_unlock(&vcpu->kvm->mmu_lock);

	return write_pt;

out_unlock:
	spin_unlock(&vcpu->kvm->mmu_lock);
	kvm_release_pfn_clean(pfn);
	return 0;
}

static gpa_t FNAME(gva_to_gpa)(struct kvm_vcpu *vcpu, gva_t vaddr)
+17 −7
Original line number Diff line number Diff line
@@ -883,6 +883,7 @@ int kvm_dev_ioctl_check_extension(long ext)
	case KVM_CAP_PIT:
	case KVM_CAP_NOP_IO_DELAY:
	case KVM_CAP_MP_STATE:
	case KVM_CAP_SYNC_MMU:
		r = 1;
		break;
	case KVM_CAP_COALESCED_MMIO:
@@ -1495,6 +1496,7 @@ static int kvm_vm_ioctl_set_memory_alias(struct kvm *kvm,
		goto out;

	down_write(&kvm->slots_lock);
	spin_lock(&kvm->mmu_lock);

	p = &kvm->arch.aliases[alias->slot];
	p->base_gfn = alias->guest_phys_addr >> PAGE_SHIFT;
@@ -1506,6 +1508,7 @@ static int kvm_vm_ioctl_set_memory_alias(struct kvm *kvm,
			break;
	kvm->arch.naliases = n;

	spin_unlock(&kvm->mmu_lock);
	kvm_mmu_zap_all(kvm);

	up_write(&kvm->slots_lock);
@@ -3972,16 +3975,23 @@ int kvm_arch_set_memory_region(struct kvm *kvm,
	 */
	if (!user_alloc) {
		if (npages && !old.rmap) {
			unsigned long userspace_addr;

			down_write(&current->mm->mmap_sem);
			memslot->userspace_addr = do_mmap(NULL, 0,
			userspace_addr = do_mmap(NULL, 0,
						 npages * PAGE_SIZE,
						 PROT_READ | PROT_WRITE,
						 MAP_SHARED | MAP_ANONYMOUS,
						 0);
			up_write(&current->mm->mmap_sem);

			if (IS_ERR((void *)memslot->userspace_addr))
				return PTR_ERR((void *)memslot->userspace_addr);
			if (IS_ERR((void *)userspace_addr))
				return PTR_ERR((void *)userspace_addr);

			/* set userspace_addr atomically for kvm_hva_to_rmapp */
			spin_lock(&kvm->mmu_lock);
			memslot->userspace_addr = userspace_addr;
			spin_unlock(&kvm->mmu_lock);
		} else {
			if (!old.user_alloc && old.rmap) {
				int ret;
+6 −0
Original line number Diff line number Diff line
@@ -13,6 +13,7 @@

#include <linux/types.h>
#include <linux/mm.h>
#include <linux/mmu_notifier.h>

#include <linux/kvm.h>
#include <linux/kvm_para.h>
@@ -251,6 +252,7 @@ struct kvm_vcpu_arch {
		gfn_t gfn;	/* presumed gfn during guest pte update */
		pfn_t pfn;	/* pfn corresponding to that gfn */
		int largepage;
		unsigned long mmu_seq;
	} update_pte;

	struct i387_fxsave_struct host_fx_image;
@@ -729,4 +731,8 @@ asmlinkage void kvm_handle_fault_on_reboot(void);
	KVM_EX_ENTRY " 666b, 667b \n\t" \
	".popsection"

#define KVM_ARCH_WANT_MMU_NOTIFIER
int kvm_unmap_hva(struct kvm *kvm, unsigned long hva);
int kvm_age_hva(struct kvm *kvm, unsigned long hva);

#endif
Loading