From: Andrea Arcangeli <andrea@qumranet.com>
To: kvm-devel@lists.sourceforge.net
Subject: [1/3] -reserved-ram for PCI passthrough without VT-d and without paravirt
Date: Mon, 31 Mar 2008 19:02:55 +0200 [thread overview]
Message-ID: <20080331170255.GC12427@duo.random> (raw)
In-Reply-To: <20080331165554.GB12427@duo.random>
This is the kvm.git patch to enable -reserved-ram (without this kvm
will simply gracefully fail to emulate the illegal instruction inside
the bad_page). This trick avoids altering the ioctl api with libkvm,
in short if get_user_pages fails on a host kernel with reserved ram
config option enabled, it tries to see if it's a remap_pfn_range
mapping backing the memslot. In such case it checks if the ram was
reserved with page_count 0 and if so it disables the reference
counting as those pages are invisibile to linux. As long as pfn_valid
returns, pfn_to_page should be safe, so shall the memmap array be
allocated with holes corresponding to the holes generated in the e820
map, simply bad_page will be returned gracefully without risk like if
this patch wasn't applied to kvm.git.
Signed-off-by: Andrea Arcangeli <andrea@qumranet.com>
diff --git a/arch/x86/kvm/paging_tmpl.h b/arch/x86/kvm/paging_tmpl.h
index e9ae5db..e7a9c82 100644
--- a/arch/x86/kvm/paging_tmpl.h
+++ b/arch/x86/kvm/paging_tmpl.h
@@ -263,7 +263,8 @@ static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *page,
npage = vcpu->arch.update_pte.page;
if (!npage)
return;
- get_page(npage);
+ if (!page_is_reserved(npage))
+ get_page(npage);
mmu_set_spte(vcpu, spte, page->role.access, pte_access, 0, 0,
gpte & PT_DIRTY_MASK, NULL, largepage, gpte_to_gfn(gpte),
npage, true);
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index f4e1436..7f087ac 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -281,6 +281,18 @@ static inline void kvm_migrate_apic_timer(struct kvm_vcpu *vcpu)
set_bit(KVM_REQ_MIGRATE_TIMER, &vcpu->requests);
}
+#ifdef CONFIG_RESERVE_PHYSICAL_START
+static inline int page_is_reserved(struct page * page)
+{
+ return !page_count(page);
+}
+#else /* CONFIG_RESERVE_PHYSICAL_START */
+static inline int page_is_reserved(struct page * page)
+{
+ return 0;
+}
+#endif /* CONFIG_RESERVE_PHYSICAL_START */
+
enum kvm_stat_kind {
KVM_STAT_VM,
KVM_STAT_VCPU,
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 30bf832..50a7b3e 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -498,6 +524,65 @@ unsigned long gfn_to_hva(struct kvm *kvm, gfn_t gfn)
return (slot->userspace_addr + (gfn - slot->base_gfn) * PAGE_SIZE);
}
+
+#ifdef CONFIG_RESERVE_PHYSICAL_START
+static struct page *direct_page(struct mm_struct *mm,
+ unsigned long address)
+{
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *ptep, pte;
+ spinlock_t *ptl;
+ struct page *page;
+ struct vm_area_struct *vma;
+ unsigned long pfn;
+
+ page = NULL;
+ if (!capable(CAP_SYS_ADMIN)) /* go safe */
+ goto out;
+
+ vma = find_vma(current->mm, address);
+ if (!vma || vma->vm_start > address ||
+ !(vma->vm_flags & VM_PFNMAP))
+ goto out;
+
+ pgd = pgd_offset(mm, address);
+ if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
+ goto out;
+
+ pud = pud_offset(pgd, address);
+ if (pud_none(*pud) || unlikely(pud_bad(*pud)))
+ goto out;
+
+ pmd = pmd_offset(pud, address);
+ if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
+ goto out;
+
+ ptep = pte_offset_map_lock(mm, pmd, address, &ptl);
+ if (!ptep)
+ goto out;
+
+ pte = *ptep;
+ if (!pte_present(pte))
+ goto unlock;
+
+ pfn = pte_pfn(pte);
+ if (!pfn_valid(pfn))
+ goto unlock;
+
+ page = pfn_to_page(pfn);
+ if (!page_is_reserved(page)) {
+ page = NULL;
+ goto unlock;
+ }
+unlock:
+ pte_unmap_unlock(ptep, ptl);
+out:
+ return page;
+}
+#endif /* CONFIG_RESERVE_PHYSICAL_START */
+
/*
* Requires current->mm->mmap_sem to be held
*/
@@ -519,6 +604,11 @@ struct page *gfn_to_page(struct kvm *kvm, gfn_t gfn)
NULL);
if (npages != 1) {
+#ifdef CONFIG_RESERVE_PHYSICAL_START
+ page[0] = direct_page(current->mm, addr);
+ if (page[0])
+ return page[0];
+#endif
get_page(bad_page);
return bad_page;
}
@@ -530,15 +620,18 @@ EXPORT_SYMBOL_GPL(gfn_to_page);
void kvm_release_page_clean(struct page *page)
{
- put_page(page);
+ if (!page_is_reserved(page))
+ put_page(page);
}
EXPORT_SYMBOL_GPL(kvm_release_page_clean);
void kvm_release_page_dirty(struct page *page)
{
- if (!PageReserved(page))
- SetPageDirty(page);
- put_page(page);
+ if (!page_is_reserved(page)) {
+ if (!PageReserved(page))
+ SetPageDirty(page);
+ put_page(page);
+ }
}
EXPORT_SYMBOL_GPL(kvm_release_page_dirty);
-------------------------------------------------------------------------
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://ad.doubleclick.net/clk;164216239;13503038;w?http://sf.net/marketplace
next prev parent reply other threads:[~2008-03-31 17:02 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-03-31 16:55 [0/3] -reserved-ram for PCI passthrough without VT-d and without paravirt Andrea Arcangeli
2008-03-31 17:02 ` Andrea Arcangeli [this message]
2008-03-31 17:07 ` [2/3] " Andrea Arcangeli
2008-03-31 17:20 ` [3/3] -reserved-ram for PCI passthrough without iommu " Andrea Arcangeli
2008-03-31 17:20 ` Andrea Arcangeli
2008-03-31 17:20 ` Andrea Arcangeli
2008-04-11 12:13 ` [0/3] -reserved-ram for PCI passthrough without VT-d " Amit Shah
2008-04-11 18:36 ` [0/3] -reserved-ram for PCI passthrough without VT-d and without?paravirt Andrea Arcangeli
2008-04-12 7:41 ` Amit Shah
2008-04-12 12:22 ` Andrea Arcangeli
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=20080331170255.GC12427@duo.random \
--to=andrea@qumranet.com \
--cc=kvm-devel@lists.sourceforge.net \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.