diff options
author | Alex Shi <alex.shi@intel.com> | 2012-06-27 21:02:20 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2012-06-27 22:29:10 -0400 |
commit | 3df3212f9722c7e45c723b9ea231a04ba4dbc47c (patch) | |
tree | cb93a81efb12b91813ed69e86bc5be24ca31de9d /arch/x86/mm | |
parent | c4211f42d3e66875298a5e26a75109878c80f15b (diff) |
x86/tlb: add tlb_flushall_shift knob into debugfs
kernel will replace cr3 rewrite with invlpg when
tlb_flush_entries <= active_tlb_entries / 2^tlb_flushall_factor
if tlb_flushall_factor is -1, kernel won't do this replacement.
User can modify its value according to specific CPU/applications.
Thanks for Borislav providing the help message of
CONFIG_DEBUG_TLBFLUSH.
Signed-off-by: Alex Shi <alex.shi@intel.com>
Link: http://lkml.kernel.org/r/1340845344-27557-6-git-send-email-alex.shi@intel.com
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'arch/x86/mm')
-rw-r--r-- | arch/x86/mm/tlb.c | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c index 2939f2f9edbb..5911f61e300e 100644 --- a/arch/x86/mm/tlb.c +++ b/arch/x86/mm/tlb.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <asm/cache.h> | 12 | #include <asm/cache.h> |
13 | #include <asm/apic.h> | 13 | #include <asm/apic.h> |
14 | #include <asm/uv/uv.h> | 14 | #include <asm/uv/uv.h> |
15 | #include <linux/debugfs.h> | ||
15 | 16 | ||
16 | DEFINE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate) | 17 | DEFINE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate) |
17 | = { &init_mm, 0, }; | 18 | = { &init_mm, 0, }; |
@@ -430,3 +431,53 @@ void flush_tlb_all(void) | |||
430 | { | 431 | { |
431 | on_each_cpu(do_flush_tlb_all, NULL, 1); | 432 | on_each_cpu(do_flush_tlb_all, NULL, 1); |
432 | } | 433 | } |
434 | |||
435 | #ifdef CONFIG_DEBUG_TLBFLUSH | ||
436 | static ssize_t tlbflush_read_file(struct file *file, char __user *user_buf, | ||
437 | size_t count, loff_t *ppos) | ||
438 | { | ||
439 | char buf[32]; | ||
440 | unsigned int len; | ||
441 | |||
442 | len = sprintf(buf, "%hd\n", tlb_flushall_shift); | ||
443 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
444 | } | ||
445 | |||
446 | static ssize_t tlbflush_write_file(struct file *file, | ||
447 | const char __user *user_buf, size_t count, loff_t *ppos) | ||
448 | { | ||
449 | char buf[32]; | ||
450 | ssize_t len; | ||
451 | s8 shift; | ||
452 | |||
453 | len = min(count, sizeof(buf) - 1); | ||
454 | if (copy_from_user(buf, user_buf, len)) | ||
455 | return -EFAULT; | ||
456 | |||
457 | buf[len] = '\0'; | ||
458 | if (kstrtos8(buf, 0, &shift)) | ||
459 | return -EINVAL; | ||
460 | |||
461 | if (shift > 64) | ||
462 | return -EINVAL; | ||
463 | |||
464 | tlb_flushall_shift = shift; | ||
465 | return count; | ||
466 | } | ||
467 | |||
468 | static const struct file_operations fops_tlbflush = { | ||
469 | .read = tlbflush_read_file, | ||
470 | .write = tlbflush_write_file, | ||
471 | .llseek = default_llseek, | ||
472 | }; | ||
473 | |||
474 | static int __cpuinit create_tlb_flushall_shift(void) | ||
475 | { | ||
476 | if (cpu_has_invlpg) { | ||
477 | debugfs_create_file("tlb_flushall_shift", S_IRUSR | S_IWUSR, | ||
478 | arch_debugfs_dir, NULL, &fops_tlbflush); | ||
479 | } | ||
480 | return 0; | ||
481 | } | ||
482 | late_initcall(create_tlb_flushall_shift); | ||
483 | #endif | ||