aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/xen
diff options
context:
space:
mode:
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];