diff options
author | Juergen Gross <jgross@suse.com> | 2014-11-28 05:53:59 -0500 |
---|---|---|
committer | David Vrabel <david.vrabel@citrix.com> | 2014-12-04 09:09:20 -0500 |
commit | 2e917175e1ef147a527a9158b9f09773ec94c0bd (patch) | |
tree | 0e2d5e5f1cdd88bc459e284eb9dc88c1c1b6e7bc | |
parent | 054954eb051f35e74b75a566a96fe756015352c8 (diff) |
xen: Speed up set_phys_to_machine() by using read-only mappings
Instead of checking at each call of set_phys_to_machine() whether a
new p2m page has to be allocated due to writing an entry in a large
invalid or identity area, just map those areas read only and react
to a page fault on write by allocating the new page.
This change will make the common path with no allocation much
faster as it only requires a single write of the new mfn instead
of walking the address translation tables and checking for the
special cases.
Suggested-by: David Vrabel <david.vrabel@citrix.com>
Signed-off-by: Juergen Gross <jgross@suse.com>
Reviewed-by: David Vrabel <david.vrabel@citrix.com>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Signed-off-by: David Vrabel <david.vrabel@citrix.com>
-rw-r--r-- | arch/x86/xen/p2m.c | 14 |
1 files changed, 8 insertions, 6 deletions
diff --git a/arch/x86/xen/p2m.c b/arch/x86/xen/p2m.c index 7d844739e513..8b5db51be4dd 100644 --- a/arch/x86/xen/p2m.c +++ b/arch/x86/xen/p2m.c | |||
@@ -70,6 +70,7 @@ | |||
70 | 70 | ||
71 | #include <asm/cache.h> | 71 | #include <asm/cache.h> |
72 | #include <asm/setup.h> | 72 | #include <asm/setup.h> |
73 | #include <asm/uaccess.h> | ||
73 | 74 | ||
74 | #include <asm/xen/page.h> | 75 | #include <asm/xen/page.h> |
75 | #include <asm/xen/hypercall.h> | 76 | #include <asm/xen/hypercall.h> |
@@ -316,9 +317,9 @@ static void __init xen_rebuild_p2m_list(unsigned long *p2m) | |||
316 | paravirt_alloc_pte(&init_mm, __pa(p2m_identity_pte) >> PAGE_SHIFT); | 317 | paravirt_alloc_pte(&init_mm, __pa(p2m_identity_pte) >> PAGE_SHIFT); |
317 | for (i = 0; i < PTRS_PER_PTE; i++) { | 318 | for (i = 0; i < PTRS_PER_PTE; i++) { |
318 | set_pte(p2m_missing_pte + i, | 319 | set_pte(p2m_missing_pte + i, |
319 | pfn_pte(PFN_DOWN(__pa(p2m_missing)), PAGE_KERNEL)); | 320 | pfn_pte(PFN_DOWN(__pa(p2m_missing)), PAGE_KERNEL_RO)); |
320 | set_pte(p2m_identity_pte + i, | 321 | set_pte(p2m_identity_pte + i, |
321 | pfn_pte(PFN_DOWN(__pa(p2m_identity)), PAGE_KERNEL)); | 322 | pfn_pte(PFN_DOWN(__pa(p2m_identity)), PAGE_KERNEL_RO)); |
322 | } | 323 | } |
323 | 324 | ||
324 | for (pfn = 0; pfn < xen_max_p2m_pfn; pfn += chunk) { | 325 | for (pfn = 0; pfn < xen_max_p2m_pfn; pfn += chunk) { |
@@ -365,7 +366,7 @@ static void __init xen_rebuild_p2m_list(unsigned long *p2m) | |||
365 | p2m_missing : p2m_identity; | 366 | p2m_missing : p2m_identity; |
366 | ptep = populate_extra_pte((unsigned long)(p2m + pfn)); | 367 | ptep = populate_extra_pte((unsigned long)(p2m + pfn)); |
367 | set_pte(ptep, | 368 | set_pte(ptep, |
368 | pfn_pte(PFN_DOWN(__pa(mfns)), PAGE_KERNEL)); | 369 | pfn_pte(PFN_DOWN(__pa(mfns)), PAGE_KERNEL_RO)); |
369 | continue; | 370 | continue; |
370 | } | 371 | } |
371 | 372 | ||
@@ -624,6 +625,9 @@ bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn) | |||
624 | return true; | 625 | return true; |
625 | } | 626 | } |
626 | 627 | ||
628 | if (likely(!__put_user(mfn, xen_p2m_addr + pfn))) | ||
629 | return true; | ||
630 | |||
627 | ptep = lookup_address((unsigned long)(xen_p2m_addr + pfn), &level); | 631 | ptep = lookup_address((unsigned long)(xen_p2m_addr + pfn), &level); |
628 | BUG_ON(!ptep || level != PG_LEVEL_4K); | 632 | BUG_ON(!ptep || level != PG_LEVEL_4K); |
629 | 633 | ||
@@ -633,9 +637,7 @@ bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn) | |||
633 | if (pte_pfn(*ptep) == PFN_DOWN(__pa(p2m_identity))) | 637 | if (pte_pfn(*ptep) == PFN_DOWN(__pa(p2m_identity))) |
634 | return mfn == IDENTITY_FRAME(pfn); | 638 | return mfn == IDENTITY_FRAME(pfn); |
635 | 639 | ||
636 | xen_p2m_addr[pfn] = mfn; | 640 | return false; |
637 | |||
638 | return true; | ||
639 | } | 641 | } |
640 | 642 | ||
641 | bool set_phys_to_machine(unsigned long pfn, unsigned long mfn) | 643 | bool set_phys_to_machine(unsigned long pfn, unsigned long mfn) |