diff options
Diffstat (limited to 'arch/i386/xen')
-rw-r--r-- | arch/i386/xen/enlighten.c | 48 | ||||
-rw-r--r-- | arch/i386/xen/mmu.c | 52 | ||||
-rw-r--r-- | arch/i386/xen/multicalls.c | 4 |
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 | ||
473 | static void xen_flush_tlb(void) | 473 | static 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 | ||
482 | static void xen_flush_tlb_single(unsigned long addr) | 485 | static 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 | ||
492 | static void xen_flush_tlb_others(const cpumask_t *cpus, struct mm_struct *mm, | 498 | static 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 | ||
526 | static unsigned long xen_read_cr2(void) | 540 | static 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 | ||
99 | void xen_set_pmd(pmd_t *ptr, pmd_t val) | 99 | void 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) | |||
146 | void xen_set_pte_at(struct mm_struct *mm, unsigned long addr, | 154 | void 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 |
155 | void xen_set_pud(pud_t *ptr, pud_t val) | 173 | void 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 | ||
165 | void xen_set_pte(pte_t *ptep, pte_t pte) | 191 | void 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 | ||
32 | struct mc_buffer { | 32 | struct mc_buffer { |
33 | struct multicall_entry entries[MC_BATCH]; | 33 | struct multicall_entry entries[MC_BATCH]; |