aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/xen
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy@xensource.com>2007-07-17 21:37:06 -0400
committerJeremy Fitzhardinge <jeremy@goop.org>2007-07-18 11:47:44 -0400
commitd66bf8fcf3fce058a1cd164a7c8ee6093fdf039c (patch)
treed09a2a4a8d0e81b8f19a4844c18690fe521bf513 /arch/i386/xen
parentf120f13ea0dbb0b0d6675683d5f6faea71277e65 (diff)
xen: lazy-mmu operations
This patch uses the lazy-mmu hooks to batch mmu operations where possible. This is primarily useful for batching operations applied to active pagetables, which happens during mprotect, munmap, mremap and the like (mmap does not do bulk pagetable operations, so it isn't helped). Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com> Acked-by: Chris Wright <chrisw@sous-sol.org>
Diffstat (limited to 'arch/i386/xen')
-rw-r--r--arch/i386/xen/enlighten.c48
-rw-r--r--arch/i386/xen/mmu.c52
-rw-r--r--arch/i386/xen/multicalls.c4
3 files changed, 72 insertions, 32 deletions
diff --git a/arch/i386/xen/enlighten.c b/arch/i386/xen/enlighten.c
index a1124b7f1d14..031dc1dcf819 100644
--- a/arch/i386/xen/enlighten.c
+++ b/arch/i386/xen/enlighten.c
@@ -472,28 +472,38 @@ static void xen_apic_write(unsigned long reg, unsigned long val)
472 472
473static void xen_flush_tlb(void) 473static void xen_flush_tlb(void)
474{ 474{
475 struct mmuext_op op; 475 struct mmuext_op *op;
476 struct multicall_space mcs = xen_mc_entry(sizeof(*op));
476 477
477 op.cmd = MMUEXT_TLB_FLUSH_LOCAL; 478 op = mcs.args;
478 if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF)) 479 op->cmd = MMUEXT_TLB_FLUSH_LOCAL;
479 BUG(); 480 MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
481
482 xen_mc_issue(PARAVIRT_LAZY_MMU);
480} 483}
481 484
482static void xen_flush_tlb_single(unsigned long addr) 485static void xen_flush_tlb_single(unsigned long addr)
483{ 486{
484 struct mmuext_op op; 487 struct mmuext_op *op;
488 struct multicall_space mcs = xen_mc_entry(sizeof(*op));
485 489
486 op.cmd = MMUEXT_INVLPG_LOCAL; 490 op = mcs.args;
487 op.arg1.linear_addr = addr & PAGE_MASK; 491 op->cmd = MMUEXT_INVLPG_LOCAL;
488 if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF)) 492 op->arg1.linear_addr = addr & PAGE_MASK;
489 BUG(); 493 MULTI_mmuext_op(mcs.mc, op, 1, NULL, DOMID_SELF);
494
495 xen_mc_issue(PARAVIRT_LAZY_MMU);
490} 496}
491 497
492static void xen_flush_tlb_others(const cpumask_t *cpus, struct mm_struct *mm, 498static void xen_flush_tlb_others(const cpumask_t *cpus, struct mm_struct *mm,
493 unsigned long va) 499 unsigned long va)
494{ 500{
495 struct mmuext_op op; 501 struct {
502 struct mmuext_op op;
503 cpumask_t mask;
504 } *args;
496 cpumask_t cpumask = *cpus; 505 cpumask_t cpumask = *cpus;
506 struct multicall_space mcs;
497 507
498 /* 508 /*
499 * A couple of (to be removed) sanity checks: 509 * A couple of (to be removed) sanity checks:
@@ -510,17 +520,21 @@ static void xen_flush_tlb_others(const cpumask_t *cpus, struct mm_struct *mm,
510 if (cpus_empty(cpumask)) 520 if (cpus_empty(cpumask))
511 return; 521 return;
512 522
523 mcs = xen_mc_entry(sizeof(*args));
524 args = mcs.args;
525 args->mask = cpumask;
526 args->op.arg2.vcpumask = &args->mask;
527
513 if (va == TLB_FLUSH_ALL) { 528 if (va == TLB_FLUSH_ALL) {
514 op.cmd = MMUEXT_TLB_FLUSH_MULTI; 529 args->op.cmd = MMUEXT_TLB_FLUSH_MULTI;
515 op.arg2.vcpumask = (void *)cpus;
516 } else { 530 } else {
517 op.cmd = MMUEXT_INVLPG_MULTI; 531 args->op.cmd = MMUEXT_INVLPG_MULTI;
518 op.arg1.linear_addr = va; 532 args->op.arg1.linear_addr = va;
519 op.arg2.vcpumask = (void *)cpus;
520 } 533 }
521 534
522 if (HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF)) 535 MULTI_mmuext_op(mcs.mc, &args->op, 1, NULL, DOMID_SELF);
523 BUG(); 536
537 xen_mc_issue(PARAVIRT_LAZY_MMU);
524} 538}
525 539
526static unsigned long xen_read_cr2(void) 540static unsigned long xen_read_cr2(void)
diff --git a/arch/i386/xen/mmu.c b/arch/i386/xen/mmu.c
index f431cf14e644..4ae038aa6c24 100644
--- a/arch/i386/xen/mmu.c
+++ b/arch/i386/xen/mmu.c
@@ -98,12 +98,20 @@ void make_lowmem_page_readwrite(void *vaddr)
98 98
99void xen_set_pmd(pmd_t *ptr, pmd_t val) 99void xen_set_pmd(pmd_t *ptr, pmd_t val)
100{ 100{
101 struct mmu_update u; 101 struct multicall_space mcs;
102 struct mmu_update *u;
102 103
103 u.ptr = virt_to_machine(ptr).maddr; 104 preempt_disable();
104 u.val = pmd_val_ma(val); 105
105 if (HYPERVISOR_mmu_update(&u, 1, NULL, DOMID_SELF) < 0) 106 mcs = xen_mc_entry(sizeof(*u));
106 BUG(); 107 u = mcs.args;
108 u->ptr = virt_to_machine(ptr).maddr;
109 u->val = pmd_val_ma(val);
110 MULTI_mmu_update(mcs.mc, u, 1, NULL, DOMID_SELF);
111
112 xen_mc_issue(PARAVIRT_LAZY_MMU);
113
114 preempt_enable();
107} 115}
108 116
109/* 117/*
@@ -146,20 +154,38 @@ void set_pte_mfn(unsigned long vaddr, unsigned long mfn, pgprot_t flags)
146void xen_set_pte_at(struct mm_struct *mm, unsigned long addr, 154void xen_set_pte_at(struct mm_struct *mm, unsigned long addr,
147 pte_t *ptep, pte_t pteval) 155 pte_t *ptep, pte_t pteval)
148{ 156{
149 if ((mm != current->mm && mm != &init_mm) || 157 if (mm == current->mm || mm == &init_mm) {
150 HYPERVISOR_update_va_mapping(addr, pteval, 0) != 0) 158 if (xen_get_lazy_mode() == PARAVIRT_LAZY_MMU) {
151 xen_set_pte(ptep, pteval); 159 struct multicall_space mcs;
160 mcs = xen_mc_entry(0);
161
162 MULTI_update_va_mapping(mcs.mc, addr, pteval, 0);
163 xen_mc_issue(PARAVIRT_LAZY_MMU);
164 return;
165 } else
166 if (HYPERVISOR_update_va_mapping(addr, pteval, 0) == 0)
167 return;
168 }
169 xen_set_pte(ptep, pteval);
152} 170}
153 171
154#ifdef CONFIG_X86_PAE 172#ifdef CONFIG_X86_PAE
155void xen_set_pud(pud_t *ptr, pud_t val) 173void xen_set_pud(pud_t *ptr, pud_t val)
156{ 174{
157 struct mmu_update u; 175 struct multicall_space mcs;
176 struct mmu_update *u;
158 177
159 u.ptr = virt_to_machine(ptr).maddr; 178 preempt_disable();
160 u.val = pud_val_ma(val); 179
161 if (HYPERVISOR_mmu_update(&u, 1, NULL, DOMID_SELF) < 0) 180 mcs = xen_mc_entry(sizeof(*u));
162 BUG(); 181 u = mcs.args;
182 u->ptr = virt_to_machine(ptr).maddr;
183 u->val = pud_val_ma(val);
184 MULTI_mmu_update(mcs.mc, u, 1, NULL, DOMID_SELF);
185
186 xen_mc_issue(PARAVIRT_LAZY_MMU);
187
188 preempt_enable();
163} 189}
164 190
165void xen_set_pte(pte_t *ptep, pte_t pte) 191void xen_set_pte(pte_t *ptep, pte_t pte)
diff --git a/arch/i386/xen/multicalls.c b/arch/i386/xen/multicalls.c
index d4015a9ed46c..c837e8e463db 100644
--- a/arch/i386/xen/multicalls.c
+++ b/arch/i386/xen/multicalls.c
@@ -26,8 +26,8 @@
26 26
27#include "multicalls.h" 27#include "multicalls.h"
28 28
29#define MC_BATCH 8 29#define MC_BATCH 32
30#define MC_ARGS (MC_BATCH * 32 / sizeof(u64)) 30#define MC_ARGS (MC_BATCH * 16 / sizeof(u64))
31 31
32struct mc_buffer { 32struct mc_buffer {
33 struct multicall_entry entries[MC_BATCH]; 33 struct multicall_entry entries[MC_BATCH];