diff options
Diffstat (limited to 'arch/x86/xen/mmu.c')
-rw-r--r-- | arch/x86/xen/mmu.c | 29 |
1 files changed, 26 insertions, 3 deletions
diff --git a/arch/x86/xen/mmu.c b/arch/x86/xen/mmu.c index c4a391f88980..72f08ab43a4d 100644 --- a/arch/x86/xen/mmu.c +++ b/arch/x86/xen/mmu.c | |||
@@ -514,20 +514,43 @@ static void drop_other_mm_ref(void *info) | |||
514 | 514 | ||
515 | if (__get_cpu_var(cpu_tlbstate).active_mm == mm) | 515 | if (__get_cpu_var(cpu_tlbstate).active_mm == mm) |
516 | leave_mm(smp_processor_id()); | 516 | leave_mm(smp_processor_id()); |
517 | |||
518 | /* If this cpu still has a stale cr3 reference, then make sure | ||
519 | it has been flushed. */ | ||
520 | if (x86_read_percpu(xen_current_cr3) == __pa(mm->pgd)) { | ||
521 | load_cr3(swapper_pg_dir); | ||
522 | arch_flush_lazy_cpu_mode(); | ||
523 | } | ||
517 | } | 524 | } |
518 | 525 | ||
519 | static void drop_mm_ref(struct mm_struct *mm) | 526 | static void drop_mm_ref(struct mm_struct *mm) |
520 | { | 527 | { |
528 | cpumask_t mask; | ||
529 | unsigned cpu; | ||
530 | |||
521 | if (current->active_mm == mm) { | 531 | if (current->active_mm == mm) { |
522 | if (current->mm == mm) | 532 | if (current->mm == mm) |
523 | load_cr3(swapper_pg_dir); | 533 | load_cr3(swapper_pg_dir); |
524 | else | 534 | else |
525 | leave_mm(smp_processor_id()); | 535 | leave_mm(smp_processor_id()); |
536 | arch_flush_lazy_cpu_mode(); | ||
537 | } | ||
538 | |||
539 | /* Get the "official" set of cpus referring to our pagetable. */ | ||
540 | mask = mm->cpu_vm_mask; | ||
541 | |||
542 | /* It's possible that a vcpu may have a stale reference to our | ||
543 | cr3, because its in lazy mode, and it hasn't yet flushed | ||
544 | its set of pending hypercalls yet. In this case, we can | ||
545 | look at its actual current cr3 value, and force it to flush | ||
546 | if needed. */ | ||
547 | for_each_online_cpu(cpu) { | ||
548 | if (per_cpu(xen_current_cr3, cpu) == __pa(mm->pgd)) | ||
549 | cpu_set(cpu, mask); | ||
526 | } | 550 | } |
527 | 551 | ||
528 | if (!cpus_empty(mm->cpu_vm_mask)) | 552 | if (!cpus_empty(mask)) |
529 | xen_smp_call_function_mask(mm->cpu_vm_mask, drop_other_mm_ref, | 553 | xen_smp_call_function_mask(mask, drop_other_mm_ref, mm, 1); |
530 | mm, 1); | ||
531 | } | 554 | } |
532 | #else | 555 | #else |
533 | static void drop_mm_ref(struct mm_struct *mm) | 556 | static void drop_mm_ref(struct mm_struct *mm) |