From: Alexander Graf <agraf@suse.de>
To: KVM list <kvm@vger.kernel.org>
Cc: kvm-ppc@vger.kernel.org, Scott Wood <scottwood@freescale.com>
Subject: [PATCH 11/15] KVM: PPC: e500: Support large page mappings of PFNMAP vmas.
Date: Fri, 17 Jun 2011 14:49:48 +0000 [thread overview]
Message-ID: <1308322192-11918-12-git-send-email-agraf@suse.de> (raw)
In-Reply-To: <1308322192-11918-1-git-send-email-agraf@suse.de>
From: Scott Wood <scottwood@freescale.com>
This allows large pages to be used on guest mappings backed by things like
/dev/mem, resulting in a significant speedup when guest memory
is mapped this way (it's useful for directly-assigned MMIO, too).
This is not a substitute for hugetlbfs integration, but is useful for
configurations where devices are directly assigned on chips without an
IOMMU -- in these cases, we need guest physical and true physical to
match, and be contiguous, so static reservation and mapping via /dev/mem
is the most straightforward way to set things up.
Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
---
arch/powerpc/kvm/e500_tlb.c | 103 +++++++++++++++++++++++++++++++++++++++----
1 files changed, 94 insertions(+), 9 deletions(-)
diff --git a/arch/powerpc/kvm/e500_tlb.c b/arch/powerpc/kvm/e500_tlb.c
index 0291c3c..7f808c5 100644
--- a/arch/powerpc/kvm/e500_tlb.c
+++ b/arch/powerpc/kvm/e500_tlb.c
@@ -270,28 +270,113 @@ static inline void kvmppc_e500_deliver_tlb_miss(struct kvm_vcpu *vcpu,
static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
u64 gvaddr, gfn_t gfn, struct tlbe *gtlbe, int tlbsel, int esel)
{
+ struct kvm_memory_slot *slot;
struct tlbe *stlbe;
- unsigned long pfn;
+ unsigned long pfn, hva;
+ int pfnmap = 0;
+ int tsize = BOOK3E_PAGESZ_4K;
stlbe = &vcpu_e500->shadow_tlb[tlbsel][esel];
/*
* Translate guest physical to true physical, acquiring
* a page reference if it is normal, non-reserved memory.
+ *
+ * gfn_to_memslot() must succeed because otherwise we wouldn't
+ * have gotten this far. Eventually we should just pass the slot
+ * pointer through from the first lookup.
*/
- pfn = gfn_to_pfn(vcpu_e500->vcpu.kvm, gfn);
- if (is_error_pfn(pfn)) {
- printk(KERN_ERR "Couldn't get real page for gfn %lx!\n",
- (long)gfn);
- kvm_release_pfn_clean(pfn);
- return;
+ slot = gfn_to_memslot(vcpu_e500->vcpu.kvm, gfn);
+ hva = gfn_to_hva_memslot(slot, gfn);
+
+ if (tlbsel = 1) {
+ struct vm_area_struct *vma;
+ down_read(¤t->mm->mmap_sem);
+
+ vma = find_vma(current->mm, hva);
+ if (vma && hva >= vma->vm_start &&
+ (vma->vm_flags & VM_PFNMAP)) {
+ /*
+ * This VMA is a physically contiguous region (e.g.
+ * /dev/mem) that bypasses normal Linux page
+ * management. Find the overlap between the
+ * vma and the memslot.
+ */
+
+ unsigned long start, end;
+ unsigned long slot_start, slot_end;
+
+ pfnmap = 1;
+
+ start = vma->vm_pgoff;
+ end = start +
+ ((vma->vm_end - vma->vm_start) >> PAGE_SHIFT);
+
+ pfn = start + ((hva - vma->vm_start) >> PAGE_SHIFT);
+
+ slot_start = pfn - (gfn - slot->base_gfn);
+ slot_end = slot_start + slot->npages;
+
+ if (start < slot_start)
+ start = slot_start;
+ if (end > slot_end)
+ end = slot_end;
+
+ tsize = (gtlbe->mas1 & MAS1_TSIZE_MASK) >>
+ MAS1_TSIZE_SHIFT;
+
+ /*
+ * e500 doesn't implement the lowest tsize bit,
+ * or 1K pages.
+ */
+ tsize = max(BOOK3E_PAGESZ_4K, tsize & ~1);
+
+ /*
+ * Now find the largest tsize (up to what the guest
+ * requested) that will cover gfn, stay within the
+ * range, and for which gfn and pfn are mutually
+ * aligned.
+ */
+
+ for (; tsize > BOOK3E_PAGESZ_4K; tsize -= 2) {
+ unsigned long gfn_start, gfn_end, tsize_pages;
+ tsize_pages = 1 << (tsize - 2);
+
+ gfn_start = gfn & ~(tsize_pages - 1);
+ gfn_end = gfn_start + tsize_pages;
+
+ if (gfn_start + pfn - gfn < start)
+ continue;
+ if (gfn_end + pfn - gfn > end)
+ continue;
+ if ((gfn & (tsize_pages - 1)) !+ (pfn & (tsize_pages - 1)))
+ continue;
+
+ gvaddr &= ~((tsize_pages << PAGE_SHIFT) - 1);
+ pfn &= ~(tsize_pages - 1);
+ break;
+ }
+ }
+
+ up_read(¤t->mm->mmap_sem);
+ }
+
+ if (likely(!pfnmap)) {
+ pfn = gfn_to_pfn_memslot(vcpu_e500->vcpu.kvm, slot, gfn);
+ if (is_error_pfn(pfn)) {
+ printk(KERN_ERR "Couldn't get real page for gfn %lx!\n",
+ (long)gfn);
+ kvm_release_pfn_clean(pfn);
+ return;
+ }
}
/* Drop reference to old page. */
kvmppc_e500_shadow_release(vcpu_e500, tlbsel, esel);
- /* Force TS=1 IPROT=0 TSIZE=4KB for all guest mappings. */
- stlbe->mas1 = MAS1_TSIZE(BOOK3E_PAGESZ_4K)
+ /* Force TS=1 IPROT=0 for all guest mappings. */
+ stlbe->mas1 = MAS1_TSIZE(tsize)
| MAS1_TID(get_tlb_tid(gtlbe)) | MAS1_TS | MAS1_VALID;
stlbe->mas2 = (gvaddr & MAS2_EPN)
| e500_shadow_mas2_attrib(gtlbe->mas2,
--
1.6.0.2
next prev parent reply other threads:[~2011-06-17 14:49 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-06-17 14:49 [PULL 00/15] PPC KVM patch queue 2011-06-15 Alexander Graf
2011-06-17 14:49 ` [PATCH 01/15] KVM: PPC: fix partial application of "exit timing in ticks" Alexander Graf
2011-06-17 14:49 ` [PATCH 02/15] KVM: PPC: Resolve real-mode handlers through function exports Alexander Graf
2011-06-17 14:49 ` [PATCH 03/15] KVM: Add compat ioctl for KVM_SET_SIGNAL_MASK Alexander Graf
2011-06-19 9:04 ` Avi Kivity
2011-06-19 12:53 ` Alexander Graf
2011-06-19 13:01 ` Avi Kivity
2011-06-17 14:49 ` [PATCH 04/15] powerpc/e500: Save SPEFCSR in flush_spe_to_thread() Alexander Graf
2011-06-17 14:49 ` [PATCH 05/15] powerpc/e500: SPE register saving: take arbitrary struct offset Alexander Graf
2011-06-17 14:49 ` [PATCH 06/15] KVM: PPC: booke: use shadow_msr Alexander Graf
2011-06-17 14:49 ` [PATCH 07/15] KVM: PPC: e500: Save/restore SPE state Alexander Graf
2011-06-17 14:49 ` [PATCH 08/15] KVM: PPC: e500: Disable preloading TLB1 in tlb_load() Alexander Graf
2011-06-17 14:49 ` [PATCH 09/15] KVM: PPC: e500: don't use MAS0 as intermediate storage Alexander Graf
2011-06-17 14:49 ` [PATCH 10/15] KVM: PPC: e500: Eliminate shadow_pages[], and use pfns instead Alexander Graf
2011-06-17 14:49 ` Alexander Graf [this message]
2011-06-17 14:49 ` [PATCH 12/15] KVM: PPC: e500: enable magic page Alexander Graf
2011-06-17 14:49 ` [PATCH 13/15] KVM: PPC: e500: Stop keeping shadow TLB Alexander Graf
2011-06-17 14:49 ` [PATCH 14/15] KVM: PPC: e500: Add shadow PID support Alexander Graf
2011-06-17 14:49 ` [PATCH 15/15] KVM: PPC: e500: Don't search over the entire TLB0 Alexander Graf
2011-06-19 9:11 ` [PULL 00/15] PPC KVM patch queue 2011-06-15 Avi Kivity
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1308322192-11918-12-git-send-email-agraf@suse.de \
--to=agraf@suse.de \
--cc=kvm-ppc@vger.kernel.org \
--cc=kvm@vger.kernel.org \
--cc=scottwood@freescale.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox