aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorAlex Shi <alex.shi@intel.com>2012-06-27 21:02:20 -0400
committerH. Peter Anvin <hpa@zytor.com>2012-06-27 22:29:10 -0400
commit3df3212f9722c7e45c723b9ea231a04ba4dbc47c (patch)
treecb93a81efb12b91813ed69e86bc5be24ca31de9d /arch/x86
parentc4211f42d3e66875298a5e26a75109878c80f15b (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')
-rw-r--r--arch/x86/Kconfig.debug19
-rw-r--r--arch/x86/mm/tlb.c51
2 files changed, 70 insertions, 0 deletions
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index e46c2147397f..b322f124ee3c 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -129,6 +129,25 @@ config DOUBLEFAULT
129 option saves about 4k and might cause you much additional grey 129 option saves about 4k and might cause you much additional grey
130 hair. 130 hair.
131 131
132config DEBUG_TLBFLUSH
133 bool "Set upper limit of TLB entries to flush one-by-one"
134 depends on DEBUG_KERNEL && (X86_64 || X86_INVLPG)
135 ---help---
136
137 X86-only for now.
138
139 This option allows the user to tune the amount of TLB entries the
140 kernel flushes one-by-one instead of doing a full TLB flush. In
141 certain situations, the former is cheaper. This is controlled by the
142 tlb_flushall_shift knob under /sys/kernel/debug/x86. If you set it
143 to -1, the code flushes the whole TLB unconditionally. Otherwise,
144 for positive values of it, the kernel will use single TLB entry
145 invalidating instructions according to the following formula:
146
147 flush_entries <= active_tlb_entries / 2^tlb_flushall_shift
148
149 If in doubt, say "N".
150
132config IOMMU_DEBUG 151config IOMMU_DEBUG
133 bool "Enable IOMMU debugging" 152 bool "Enable IOMMU debugging"
134 depends on GART_IOMMU && DEBUG_KERNEL 153 depends on GART_IOMMU && DEBUG_KERNEL
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
16DEFINE_PER_CPU_SHARED_ALIGNED(struct tlb_state, cpu_tlbstate) 17DEFINE_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
436static 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
446static 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
468static const struct file_operations fops_tlbflush = {
469 .read = tlbflush_read_file,
470 .write = tlbflush_write_file,
471 .llseek = default_llseek,
472};
473
474static 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}
482late_initcall(create_tlb_flushall_shift);
483#endif