diff options
author | Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> | 2010-12-17 17:58:43 -0500 |
---|---|---|
committer | Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> | 2011-07-18 18:43:28 -0400 |
commit | bc7fe1d977734efe6059d6d537b439135ad4a34c (patch) | |
tree | 06a437e5cabe7355e0824935b0a8d24d801b6289 /arch | |
parent | dcf7435cfe617c9d9f3dd501d3f5ed4d0b30c218 (diff) |
xen/mmu: tune pgtable alloc/release
Make sure the fastpath code is inlined. Batch the page permission change
and the pin/unpin, and make sure that it can be batched with any
adjacent set_pte/pmd/etc operations.
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/xen/mmu.c | 53 |
1 files changed, 44 insertions, 9 deletions
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index eb9112687cee..f987bde77c49 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c | |||
@@ -1497,22 +1497,52 @@ static void __init xen_release_pmd_init(unsigned long pfn) | |||
1497 | make_lowmem_page_readwrite(__va(PFN_PHYS(pfn))); | 1497 | make_lowmem_page_readwrite(__va(PFN_PHYS(pfn))); |
1498 | } | 1498 | } |
1499 | 1499 | ||
1500 | static inline void __pin_pagetable_pfn(unsigned cmd, unsigned long pfn) | ||
1501 | { | ||
1502 | struct multicall_space mcs; | ||
1503 | struct mmuext_op *op; | ||
1504 | |||
1505 | mcs = __xen_mc_entry(sizeof(*op)); | ||
1506 | op = mcs.args; | ||
1507 | op->cmd = cmd; | ||
1508 | op->arg1.mfn = pfn_to_mfn(pfn); | ||
1509 | |||
1510 | MULTI_mmuext_op(mcs.mc, mcs.args, 1, NULL, DOMID_SELF); | ||
1511 | } | ||
1512 | |||
1513 | static inline void __set_pfn_prot(unsigned long pfn, pgprot_t prot) | ||
1514 | { | ||
1515 | struct multicall_space mcs; | ||
1516 | unsigned long addr = (unsigned long)__va(pfn << PAGE_SHIFT); | ||
1517 | |||
1518 | mcs = __xen_mc_entry(0); | ||
1519 | MULTI_update_va_mapping(mcs.mc, (unsigned long)addr, | ||
1520 | pfn_pte(pfn, prot), 0); | ||
1521 | } | ||
1522 | |||
1500 | /* This needs to make sure the new pte page is pinned iff its being | 1523 | /* This needs to make sure the new pte page is pinned iff its being |
1501 | attached to a pinned pagetable. */ | 1524 | attached to a pinned pagetable. */ |
1502 | static void xen_alloc_ptpage(struct mm_struct *mm, unsigned long pfn, unsigned level) | 1525 | static inline void xen_alloc_ptpage(struct mm_struct *mm, unsigned long pfn, |
1526 | unsigned level) | ||
1503 | { | 1527 | { |
1504 | struct page *page = pfn_to_page(pfn); | 1528 | bool pinned = PagePinned(virt_to_page(mm->pgd)); |
1505 | int pinned = PagePinned(virt_to_page(mm->pgd)); | 1529 | |
1506 | |||
1507 | trace_xen_mmu_alloc_ptpage(mm, pfn, level, pinned); | 1530 | trace_xen_mmu_alloc_ptpage(mm, pfn, level, pinned); |
1508 | 1531 | ||
1509 | if (pinned) { | 1532 | if (pinned) { |
1533 | struct page *page = pfn_to_page(pfn); | ||
1534 | |||
1510 | SetPagePinned(page); | 1535 | SetPagePinned(page); |
1511 | 1536 | ||
1512 | if (!PageHighMem(page)) { | 1537 | if (!PageHighMem(page)) { |
1513 | make_lowmem_page_readonly(__va(PFN_PHYS((unsigned long)pfn))); | 1538 | xen_mc_batch(); |
1539 | |||
1540 | __set_pfn_prot(pfn, PAGE_KERNEL_RO); | ||
1541 | |||
1514 | if (level == PT_PTE && USE_SPLIT_PTLOCKS) | 1542 | if (level == PT_PTE && USE_SPLIT_PTLOCKS) |
1515 | pin_pagetable_pfn(MMUEXT_PIN_L1_TABLE, pfn); | 1543 | __pin_pagetable_pfn(MMUEXT_PIN_L1_TABLE, pfn); |
1544 | |||
1545 | xen_mc_issue(PARAVIRT_LAZY_MMU); | ||
1516 | } else { | 1546 | } else { |
1517 | /* make sure there are no stray mappings of | 1547 | /* make sure there are no stray mappings of |
1518 | this page */ | 1548 | this page */ |
@@ -1532,7 +1562,7 @@ static void xen_alloc_pmd(struct mm_struct *mm, unsigned long pfn) | |||
1532 | } | 1562 | } |
1533 | 1563 | ||
1534 | /* This should never happen until we're OK to use struct page */ | 1564 | /* This should never happen until we're OK to use struct page */ |
1535 | static void xen_release_ptpage(unsigned long pfn, unsigned level) | 1565 | static inline void xen_release_ptpage(unsigned long pfn, unsigned level) |
1536 | { | 1566 | { |
1537 | struct page *page = pfn_to_page(pfn); | 1567 | struct page *page = pfn_to_page(pfn); |
1538 | bool pinned = PagePinned(page); | 1568 | bool pinned = PagePinned(page); |
@@ -1541,9 +1571,14 @@ static void xen_release_ptpage(unsigned long pfn, unsigned level) | |||
1541 | 1571 | ||
1542 | if (pinned) { | 1572 | if (pinned) { |
1543 | if (!PageHighMem(page)) { | 1573 | if (!PageHighMem(page)) { |
1574 | xen_mc_batch(); | ||
1575 | |||
1544 | if (level == PT_PTE && USE_SPLIT_PTLOCKS) | 1576 | if (level == PT_PTE && USE_SPLIT_PTLOCKS) |
1545 | pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, pfn); | 1577 | __pin_pagetable_pfn(MMUEXT_UNPIN_TABLE, pfn); |
1546 | make_lowmem_page_readwrite(__va(PFN_PHYS(pfn))); | 1578 | |
1579 | __set_pfn_prot(pfn, PAGE_KERNEL); | ||
1580 | |||
1581 | xen_mc_issue(PARAVIRT_LAZY_MMU); | ||
1547 | } | 1582 | } |
1548 | ClearPagePinned(page); | 1583 | ClearPagePinned(page); |
1549 | } | 1584 | } |