diff options
Diffstat (limited to 'arch/x86/mm/tlb.c')
-rw-r--r-- | arch/x86/mm/tlb.c | 64 |
1 files changed, 6 insertions, 58 deletions
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c index 658bf0090565..0f3d0cea4d00 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c | |||
@@ -30,7 +30,6 @@ | |||
30 | 30 | ||
31 | atomic64_t last_mm_ctx_id = ATOMIC64_INIT(1); | 31 | atomic64_t last_mm_ctx_id = ATOMIC64_INIT(1); |
32 | 32 | ||
33 | DEFINE_STATIC_KEY_TRUE(tlb_use_lazy_mode); | ||
34 | 33 | ||
35 | static void choose_new_asid(struct mm_struct *next, u64 next_tlb_gen, | 34 | static void choose_new_asid(struct mm_struct *next, u64 next_tlb_gen, |
36 | u16 *new_asid, bool *need_flush) | 35 | u16 *new_asid, bool *need_flush) |
@@ -147,8 +146,8 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next, | |||
147 | this_cpu_write(cpu_tlbstate.is_lazy, false); | 146 | this_cpu_write(cpu_tlbstate.is_lazy, false); |
148 | 147 | ||
149 | if (real_prev == next) { | 148 | if (real_prev == next) { |
150 | VM_BUG_ON(this_cpu_read(cpu_tlbstate.ctxs[prev_asid].ctx_id) != | 149 | VM_WARN_ON(this_cpu_read(cpu_tlbstate.ctxs[prev_asid].ctx_id) != |
151 | next->context.ctx_id); | 150 | next->context.ctx_id); |
152 | 151 | ||
153 | /* | 152 | /* |
154 | * We don't currently support having a real mm loaded without | 153 | * We don't currently support having a real mm loaded without |
@@ -213,6 +212,9 @@ void switch_mm_irqs_off(struct mm_struct *prev, struct mm_struct *next, | |||
213 | } | 212 | } |
214 | 213 | ||
215 | /* | 214 | /* |
215 | * Please ignore the name of this function. It should be called | ||
216 | * switch_to_kernel_thread(). | ||
217 | * | ||
216 | * enter_lazy_tlb() is a hint from the scheduler that we are entering a | 218 | * enter_lazy_tlb() is a hint from the scheduler that we are entering a |
217 | * kernel thread or other context without an mm. Acceptable implementations | 219 | * kernel thread or other context without an mm. Acceptable implementations |
218 | * include doing nothing whatsoever, switching to init_mm, or various clever | 220 | * include doing nothing whatsoever, switching to init_mm, or various clever |
@@ -227,7 +229,7 @@ void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk) | |||
227 | if (this_cpu_read(cpu_tlbstate.loaded_mm) == &init_mm) | 229 | if (this_cpu_read(cpu_tlbstate.loaded_mm) == &init_mm) |
228 | return; | 230 | return; |
229 | 231 | ||
230 | if (static_branch_unlikely(&tlb_use_lazy_mode)) { | 232 | if (tlb_defer_switch_to_init_mm()) { |
231 | /* | 233 | /* |
232 | * There's a significant optimization that may be possible | 234 | * There's a significant optimization that may be possible |
233 | * here. We have accurate enough TLB flush tracking that we | 235 | * here. We have accurate enough TLB flush tracking that we |
@@ -626,57 +628,3 @@ static int __init create_tlb_single_page_flush_ceiling(void) | |||
626 | return 0; | 628 | return 0; |
627 | } | 629 | } |
628 | late_initcall(create_tlb_single_page_flush_ceiling); | 630 | late_initcall(create_tlb_single_page_flush_ceiling); |
629 | |||
630 | static ssize_t tlblazy_read_file(struct file *file, char __user *user_buf, | ||
631 | size_t count, loff_t *ppos) | ||
632 | { | ||
633 | char buf[2]; | ||
634 | |||
635 | buf[0] = static_branch_likely(&tlb_use_lazy_mode) ? '1' : '0'; | ||
636 | buf[1] = '\n'; | ||
637 | |||
638 | return simple_read_from_buffer(user_buf, count, ppos, buf, 2); | ||
639 | } | ||
640 | |||
641 | static ssize_t tlblazy_write_file(struct file *file, | ||
642 | const char __user *user_buf, size_t count, loff_t *ppos) | ||
643 | { | ||
644 | bool val; | ||
645 | |||
646 | if (kstrtobool_from_user(user_buf, count, &val)) | ||
647 | return -EINVAL; | ||
648 | |||
649 | if (val) | ||
650 | static_branch_enable(&tlb_use_lazy_mode); | ||
651 | else | ||
652 | static_branch_disable(&tlb_use_lazy_mode); | ||
653 | |||
654 | return count; | ||
655 | } | ||
656 | |||
657 | static const struct file_operations fops_tlblazy = { | ||
658 | .read = tlblazy_read_file, | ||
659 | .write = tlblazy_write_file, | ||
660 | .llseek = default_llseek, | ||
661 | }; | ||
662 | |||
663 | static int __init init_tlb_use_lazy_mode(void) | ||
664 | { | ||
665 | if (boot_cpu_has(X86_FEATURE_PCID)) { | ||
666 | /* | ||
667 | * Heuristic: with PCID on, switching to and from | ||
668 | * init_mm is reasonably fast, but remote flush IPIs | ||
669 | * as expensive as ever, so turn off lazy TLB mode. | ||
670 | * | ||
671 | * We can't do this in setup_pcid() because static keys | ||
672 | * haven't been initialized yet, and it would blow up | ||
673 | * badly. | ||
674 | */ | ||
675 | static_branch_disable(&tlb_use_lazy_mode); | ||
676 | } | ||
677 | |||
678 | debugfs_create_file("tlb_use_lazy_mode", S_IRUSR | S_IWUSR, | ||
679 | arch_debugfs_dir, NULL, &fops_tlblazy); | ||
680 | return 0; | ||
681 | } | ||
682 | late_initcall(init_tlb_use_lazy_mode); | ||