diff options
| author | Andrea Arcangeli <aarcange@redhat.com> | 2013-07-24 21:04:38 -0400 |
|---|---|---|
| committer | Gleb Natapov <gleb@redhat.com> | 2013-08-27 04:01:10 -0400 |
| commit | 11feeb498086a3a5907b8148bdf1786a9b18fc55 (patch) | |
| tree | 9dcef9a577fd410f84f42b972e2fd4e1ff46f68c /virt | |
| parent | 0bd50dc971aad3c29043de4fb7bce45c351d1b67 (diff) | |
kvm: optimize away THP checks in kvm_is_mmio_pfn()
The checks on PG_reserved in the page structure on head and tail pages
aren't necessary because split_huge_page wouldn't transfer the
PG_reserved bit from head to tail anyway.
This was a forward-thinking check done in the case PageReserved was
set by a driver-owned page mapped in userland with something like
remap_pfn_range in a VM_PFNMAP region, but using hugepmds (not
possible right now). It was meant to be very safe, but it's overkill
as it's unlikely split_huge_page could ever run without the driver
noticing and tearing down the hugepage itself.
And if a driver in the future will really want to map a reserved
hugepage in userland using an huge pmd it should simply take care of
marking all subpages reserved too to keep KVM safe. This of course
would require such a hypothetical driver to tear down the huge pmd
itself and splitting the hugepage itself, instead of relaying on
split_huge_page, but that sounds very reasonable, especially
considering split_huge_page wouldn't currently transfer the reserved
bit anyway.
Signed-off-by: Andrea Arcangeli <aarcange@redhat.com>
Signed-off-by: Gleb Natapov <gleb@redhat.com>
Diffstat (limited to 'virt')
| -rw-r--r-- | virt/kvm/kvm_main.c | 24 |
1 files changed, 2 insertions, 22 deletions
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index d2836788561e..0fc25aed79a8 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
| @@ -102,28 +102,8 @@ static bool largepages_enabled = true; | |||
| 102 | 102 | ||
| 103 | bool kvm_is_mmio_pfn(pfn_t pfn) | 103 | bool kvm_is_mmio_pfn(pfn_t pfn) |
| 104 | { | 104 | { |
| 105 | if (pfn_valid(pfn)) { | 105 | if (pfn_valid(pfn)) |
| 106 | int reserved; | 106 | return PageReserved(pfn_to_page(pfn)); |
| 107 | struct page *tail = pfn_to_page(pfn); | ||
| 108 | struct page *head = compound_trans_head(tail); | ||
| 109 | reserved = PageReserved(head); | ||
| 110 | if (head != tail) { | ||
| 111 | /* | ||
| 112 | * "head" is not a dangling pointer | ||
| 113 | * (compound_trans_head takes care of that) | ||
| 114 | * but the hugepage may have been splitted | ||
| 115 | * from under us (and we may not hold a | ||
| 116 | * reference count on the head page so it can | ||
| 117 | * be reused before we run PageReferenced), so | ||
| 118 | * we've to check PageTail before returning | ||
| 119 | * what we just read. | ||
| 120 | */ | ||
| 121 | smp_rmb(); | ||
| 122 | if (PageTail(tail)) | ||
| 123 | return reserved; | ||
| 124 | } | ||
| 125 | return PageReserved(tail); | ||
| 126 | } | ||
| 127 | 107 | ||
| 128 | return true; | 108 | return true; |
| 129 | } | 109 | } |
