x86 candidate patches for review VII: VDSO, CPUID, NMI watchdog, MCE, misc
Subsystems (3)
cover x86 candidate patches for review VII: VDSO, CPUID, NMI watchdog, MCE, misc
The last batch of x86 patches for .22 to review.
This one contains various patches that haven't hit l-k yet. Please review closely.
- Finally vDSO support for x86-64
* glibc support still missing unfortunately
- New early CPUID checking for i386
- Restructured NMI watchdog code
- Dynamic MCE polling interval adaption from Tim Hockin
- Some NUMA changes
- Use RDTSCP for synchronous get_cycles if possible
- Fix APIC timer calibration on x86-64 (stable candidate too)
- Drop CONFIG_REORDER as announced earlier
- Misc stuff
Happy reviewing!
-Andi
PATCH 1/30 x86_64: Dynamically adjust machine check interval
From: Tim Hockin <[email protected]>
Background:
We've found that MCEs (specifically DRAM SBEs) tend to come in bunches, especially when we are trying really hard to stress the system out. The current MCE poller uses a static interval which does not care whether it has or has not found MCEs recently.
Description:
This patch makes the MCE poller adjust the polling interval dynamically. If we find an MCE, poll 2x faster (down to 10 ms). When we stop finding MCEs, poll 2x slower (up to check_interval seconds). The check_interval tunable becomes the max polling interval. The "Machine check events logged" printk() is rate limited to the check_interval, which should be identical behavior to the old functionality.
Result:
If you start to take a lot of correctable errors (not exceptions), you log them faster and more accurately (less chance of overflowing the MCA registers). If you don't take a lot of errors, you will see no change.
Alternatives:
I considered simply reducing the polling interval to 10 ms immediately and keeping it there as long as we continue to find errors. This felt a bit heavy handed, but does perform significantly better for the default check_interval of 5 minutes (we're using a few seconds when testing for DRAM errors). I could be convinced to go with this, if anyone felt it was not too aggressive.
Testing:
I used an error-injecting DIMM to create lots of correctable DRAM errors and verified that the polling interval accelerates. The printk() only happens once per check_interval seconds.
Patch:
This patch is against 2.6.21-rc7.
--- Documentation/x86_64/machinecheck | 7 ++++++- arch/x86_64/kernel/mce.c | 32 ++++++++++++++++++++++++-------- 2 files changed, 30 insertions(+), 9 deletions(-)
Documentation/x86_64/machinecheck +6 -1
@@ -36,7 +36,12 @@ between all CPUs. check_interval How often to poll for corrected machine check errors, in seconds - (Note output is hexademical). Default 5 minutes. + (Note output is hexademical). Default 5 minutes. When the poller + finds MCEs it triggers an exponential speedup (poll more often) on + the polling interval. When the poller stops finding MCEs, it + triggers an exponential backoff (poll less often) on the polling + interval. The check_interval variable is both the initial and + maximum polling interval. tolerant Tolerance level. When a machine check exception occurs for a non
arch/x86_64/kernel/mce.c +24 -8
@@ -323,10 +323,13 @@ void mce_log_therm_throt_event(unsigned#endif /* CONFIG_X86_MCE_INTEL */ /* -* Periodic polling timer for "silent" machine check errors. +* Periodic polling timer for "silent" machine check errors. If the +* poller finds an MCE, poll 2x faster. When the poller finds no more +* errors, poll 2x slower (up to check_interval seconds). */ static int check_interval =5 *60 ;/* 5 minutes */ +static int next_interval;/* in jiffies */ static void mcheck_timer (struct work_struct *work); static DECLARE_DELAYED_WORK(mcheck_work, mcheck_timer);
@@ -339,7 +342,6 @@ static void mcheck_check_cpu(void *info)static void mcheck_timer (struct work_struct *work) {on_each_cpu (mcheck_check_cpu,NULL ,1 ,1 ); -schedule_delayed_work (&mcheck_work, check_interval *HZ );/* * It's ok to read stale data here for notify_user and
@@ -349,17 +351,30 @@ static void mcheck_timer(struct work_str* writes. */ if (notify_user && console_logged) { +static unsigned long last_print; +unsigned long now = jiffies; + +/* if we logged an MCE, reduce the polling interval */ + next_interval =max (next_interval/2 ,HZ /100 ); notify_user =0 ;clear_bit (0 , &console_logged); -printk (KERN_INFO "Machine check events logged\n" ); +if (time_after_eq (now, last_print + (check_interval*HZ ))) { + last_print = now; +printk (KERN_INFO "Machine check events logged\n" ); + } + }else { + next_interval =min (next_interval*2 , check_interval*HZ ); } + +schedule_delayed_work (&mcheck_work, next_interval); }static __init int periodic_mcheck_init (void ) { -if (check_interval) -schedule_delayed_work (&mcheck_work, check_interval*HZ ); + next_interval = check_interval *HZ ; +if (next_interval) +schedule_delayed_work (&mcheck_work, next_interval);return 0 ; }__initcall (periodic_mcheck_init);
@@ -597,12 +612,13 @@ static int mce_resume(struct sys_device/* Reinit MCEs after user configuration changes */ static void mce_restart (void ) { -if (check_interval) +if (next_interval)cancel_delayed_work (&mcheck_work);/* Timer race is harmless here */ on_each_cpu (mce_init,NULL ,1 ,1 ); -if (check_interval) -schedule_delayed_work (&mcheck_work, check_interval*HZ ); + next_interval = check_interval *HZ ; +if (next_interval) +schedule_delayed_work (&mcheck_work, next_interval); }static struct sysdev_class mce_sysclass = {
PATCH 2/30 x86_64: set node_possible_map at runtime - try 2
In reply to Andi KleenFrom: Suresh Siddha <[email protected]>
Set the node_possible_map at runtime on x86_64. On a non NUMA system, num_possible_nodes() will now say '1'.
---
--- arch/x86_64/mm/k8topology.c | 7 ++----- arch/x86_64/mm/numa.c | 10 ++++++++-- arch/x86_64/mm/srat.c | 8 +++++--- 3 files changed, 15 insertions(+), 10 deletions(-)
arch/x86_64/mm/k8topology.c +2 -5
@@ -49,11 +49,8 @@ int __init k8_scan_nodes(unsigned long sint found =0 ;u32 reg;unsigned numnodes; -nodemask_t nodes_parsed;unsigned dualcore =0 ; -nodes_clear (nodes_parsed); -if (!early_pci_allowed ())return -1 ;
@@ -102,7 +99,7 @@ int __init k8_scan_nodes(unsigned long s nodeid, (base>>8)&3, (limit>>8) & 3);return -1 ; } -if (node_isset (nodeid, nodes_parsed)) { +if (node_isset (nodeid, node_possible_map)) {printk (KERN_INFO "Node %d already present. Skipping\n" , nodeid);continue ;
@@ -155,7 +152,7 @@ int __init k8_scan_nodes(unsigned long s prevbase = base; -node_set (nodeid, nodes_parsed); +node_set (nodeid, node_possible_map); }if (!found)
arch/x86_64/mm/numa.c +8 -2
@@ -295,7 +295,7 @@ static int __init setup_node_range(int n ret =-1 ; } nodes[nid].end = *addr; -node_set_online (nid); +node_set (nid, node_possible_map);printk (KERN_INFO "Faking node %d at %016Lx-%016Lx (%LuMB)\n" , nid, nodes[nid].start, nodes[nid].end, (nodes[nid].end - nodes[nid].start) >>20 );
@@ -479,7 +479,7 @@ out:* SRAT. */ remove_all_active_ranges (); -for_each_online_node (i) { +for_each_node_mask (i, node_possible_map) {e820_register_active_regions (i, nodes[i].start >>PAGE_SHIFT , nodes[i].end >>PAGE_SHIFT );setup_node_bootmem (i, nodes[i].start, nodes[i].end);
@@ -494,20 +494,25 @@ void __init numa_initmem_init(unsigned l {int i; +nodes_clear (node_possible_map); +#ifdef CONFIG_NUMA_EMU if (cmdline && !numa_emulation (start_pfn, end_pfn))return ; +nodes_clear (node_possible_map);#endif #ifdef CONFIG_ACPI_NUMA if (!numa_off && !acpi_scan_nodes (start_pfn <<PAGE_SHIFT , end_pfn <<PAGE_SHIFT ))return ; +nodes_clear (node_possible_map);#endif #ifdef CONFIG_K8_NUMA if (!numa_off && !k8_scan_nodes (start_pfn<<PAGE_SHIFT , end_pfn<<PAGE_SHIFT ))return ; +nodes_clear (node_possible_map);#endif printk (KERN_INFO "%s\n" , numa_off ?"NUMA turned off" :"No NUMA configuration found" );
@@ -521,6 +526,7 @@ void __init numa_initmem_init(unsigned l memnodemap[0 ] =0 ;nodes_clear (node_online_map);node_set_online (0 ); +node_set (0 , node_possible_map);for (i =0 ; i <NR_CPUS ; i++)numa_set_node (i,0 ); node_to_cpumask[0 ] =cpumask_of_cpu (0 );
arch/x86_64/mm/srat.c +5 -3
@@ -419,19 +419,21 @@ int __init acpi_scan_nodes(unsigned longreturn -1 ; } + node_possible_map = nodes_parsed; +/* Finally register nodes */ -for_each_node_mask (i, nodes_parsed) +for_each_node_mask (i, node_possible_map)setup_node_bootmem (i, nodes[i].start, nodes[i].end);/* Try again in case setup_node_bootmem missed one due to missing bootmem */ -for_each_node_mask (i, nodes_parsed) +for_each_node_mask (i, node_possible_map)if (!node_online (i))setup_node_bootmem (i, nodes[i].start, nodes[i].end);for (i =0 ; i <NR_CPUS ; i++) {if (cpu_to_node[i] ==NUMA_NO_NODE )continue ; -if (!node_isset (cpu_to_node[i], nodes_parsed)) +if (!node_isset (cpu_to_node[i], node_possible_map))numa_set_node (i,NUMA_NO_NODE ); }numa_init_array ();
PATCH 3/30 i386: Clean up NMI watchdog code
In reply to Andi Kleen- Introduce a wd_ops structure
- Convert the various nmi watchdogs over to it
- This allows to split the perfctr reservation from the watchdog setup cleanly.
- Do perfctr reservation globally as it should have always been
- Remove dead code referenced only by unused EXPORT_SYMBOLs
--- arch/i386/kernel/cpu/Makefile | 2 arch/i386/kernel/cpu/perfctr-watchdog.c | 658 +++++++++++++++++++++++++ arch/i386/kernel/nmi.c | 829 ++------------------------------ include/asm-i386/nmi.h | 8 4 files changed, 721 insertions(+), 776 deletions(-)
arch/i386/kernel/nmi.c +53 -776
@@ -20,7 +20,6 @@#include <linux/sysdev.h> #include <linux/sysctl.h> #include <linux/percpu.h> -#include <linux/dmi.h> #include <linux/kprobes.h> #include <linux/cpumask.h> #include <linux/kernel_stat.h>
@@ -28,30 +27,14 @@#include <asm/smp.h> #include <asm/nmi.h> #include <asm/kdebug.h> -#include <asm/intel_arch_perfmon.h> #include "mach_traps.h" int unknown_nmi_panic;int nmi_watchdog_enabled; -/* perfctr_nmi_owner tracks the ownership of the perfctr registers: -* evtsel_nmi_owner tracks the ownership of the event selection -* - different performance counters/ event selection may be reserved for -* different subsystems this reservation system just tries to coordinate -* things a little -*/ - -/* this number is calculated from Intel's MSR_P4_CRU_ESCR5 register and it's -* offset from MSR_P4_BSU_ESCR0. It will be the max for all platforms (for now) -*/ -#define NMI_MAX_COUNTER_BITS 66 -#define NMI_MAX_COUNTER_LONGS BITS_TO_LONGS(NMI_MAX_COUNTER_BITS) - -static DEFINE_PER_CPU(unsigned long, perfctr_nmi_owner[NMI_MAX_COUNTER_LONGS]); -static DEFINE_PER_CPU(unsigned long, evntsel_nmi_owner[NMI_MAX_COUNTER_LONGS]); -static cpumask_t backtrace_mask =CPU_MASK_NONE ; +/* nmi_active: * >0: the lapic NMI watchdog is active, but can be disabled * <0: the lapic NMI watchdog has not been set up, and cannot
@@ -63,203 +46,11 @@ atomic_t nmi_active = ATOMIC_INIT(0); /unsigned int nmi_watchdog =NMI_DEFAULT ;static unsigned int nmi_hz =HZ ; -struct nmi_watchdog_ctlblk { -int enabled; -u64 check_bit; -unsigned int cccr_msr; -unsigned int perfctr_msr;/* the MSR to reset in NMI handler */ -unsigned int evntsel_msr;/* the MSR to select the events to handle */ -}; -static DEFINE_PER_CPU(struct nmi_watchdog_ctlblk, nmi_watchdog_ctlblk); +static DEFINE_PER_CPU(short, wd_enabled);/* local prototypes */ static int unknown_nmi_panic_callback (struct pt_regs *regs,int cpu); -/* converts an msr to an appropriate reservation bit */ -static inline unsigned int nmi_perfctr_msr_to_bit (unsigned int msr) -{ -/* returns the bit offset of the performance counter register */ -switch (boot_cpu_data.x86_vendor) { -case X86_VENDOR_AMD : -return (msr -MSR_K7_PERFCTR0 ); -case X86_VENDOR_INTEL : -if (cpu_has (&boot_cpu_data,X86_FEATURE_ARCH_PERFMON )) -return (msr -MSR_ARCH_PERFMON_PERFCTR0 ); - -switch (boot_cpu_data.x86) { -case 6 : -return (msr -MSR_P6_PERFCTR0 ); -case 15 : -return (msr -MSR_P4_BPU_PERFCTR0 ); - } - } -return 0 ; -} - -/* converts an msr to an appropriate reservation bit */ -static inline unsigned int nmi_evntsel_msr_to_bit (unsigned int msr) -{ -/* returns the bit offset of the event selection register */ -switch (boot_cpu_data.x86_vendor) { -case X86_VENDOR_AMD : -return (msr -MSR_K7_EVNTSEL0 ); -case X86_VENDOR_INTEL : -if (cpu_has (&boot_cpu_data,X86_FEATURE_ARCH_PERFMON )) -return (msr -MSR_ARCH_PERFMON_EVENTSEL0 ); - -switch (boot_cpu_data.x86) { -case 6 : -return (msr -MSR_P6_EVNTSEL0 ); -case 15 : -return (msr -MSR_P4_BSU_ESCR0 ); - } - } -return 0 ; -} - -/* checks for a bit availability (hack for oprofile) */ -int avail_to_resrv_perfctr_nmi_bit (unsigned int counter) -{ -int cpu; -BUG_ON (counter >NMI_MAX_COUNTER_BITS ); -for_each_possible_cpu (cpu) { -if (test_bit (counter, &per_cpu (perfctr_nmi_owner, cpu)[0 ])) -return 0 ; - } -return 1 ; -} - -/* checks the an msr for availability */ -int avail_to_resrv_perfctr_nmi (unsigned int msr) -{ -unsigned int counter; -int cpu; - - counter =nmi_perfctr_msr_to_bit (msr); -BUG_ON (counter >NMI_MAX_COUNTER_BITS ); - -for_each_possible_cpu (cpu) { -if (test_bit (counter, &per_cpu (perfctr_nmi_owner, cpu)[0 ])) -return 0 ; - } -return 1 ; -} - -static int __reserve_perfctr_nmi (int cpu,unsigned int msr) -{ -unsigned int counter; -if (cpu <0 ) - cpu =smp_processor_id (); - - counter =nmi_perfctr_msr_to_bit (msr); -BUG_ON (counter >NMI_MAX_COUNTER_BITS ); - -if (!test_and_set_bit (counter, &per_cpu (perfctr_nmi_owner, cpu)[0 ])) -return 1 ; -return 0 ; -} - -static void __release_perfctr_nmi (int cpu,unsigned int msr) -{ -unsigned int counter; -if (cpu <0 ) - cpu =smp_processor_id (); - - counter =nmi_perfctr_msr_to_bit (msr); -BUG_ON (counter >NMI_MAX_COUNTER_BITS ); - -clear_bit (counter, &per_cpu (perfctr_nmi_owner, cpu)[0 ]); -} - -int reserve_perfctr_nmi (unsigned int msr) -{ -int cpu, i; -for_each_possible_cpu (cpu) { -if (!__reserve_perfctr_nmi (cpu, msr)) { -for_each_possible_cpu (i) { -if (i >= cpu) -break ; -__release_perfctr_nmi (i, msr); - } -return 0 ; - } - } -return 1 ; -} - -void release_perfctr_nmi (unsigned int msr) -{ -int cpu; -for_each_possible_cpu (cpu) { -__release_perfctr_nmi (cpu, msr); - } -} - -int __reserve_evntsel_nmi (int cpu,unsigned int msr) -{ -unsigned int counter; -if (cpu <0 ) - cpu =smp_processor_id (); - - counter =nmi_evntsel_msr_to_bit (msr); -BUG_ON (counter >NMI_MAX_COUNTER_BITS ); - -if (!test_and_set_bit (counter, &per_cpu (evntsel_nmi_owner, cpu)[0 ])) -return 1 ; -return 0 ; -} - -static void __release_evntsel_nmi (int cpu,unsigned int msr) -{ -unsigned int counter; -if (cpu <0 ) - cpu =smp_processor_id (); - - counter =nmi_evntsel_msr_to_bit (msr); -BUG_ON (counter >NMI_MAX_COUNTER_BITS ); - -clear_bit (counter, &per_cpu (evntsel_nmi_owner, cpu)[0 ]); -} - -int reserve_evntsel_nmi (unsigned int msr) -{ -int cpu, i; -for_each_possible_cpu (cpu) { -if (!__reserve_evntsel_nmi (cpu, msr)) { -for_each_possible_cpu (i) { -if (i >= cpu) -break ; -__release_evntsel_nmi (i, msr); - } -return 0 ; - } - } -return 1 ; -} - -void release_evntsel_nmi (unsigned int msr) -{ -int cpu; -for_each_possible_cpu (cpu) { -__release_evntsel_nmi (cpu, msr); - } -} - -static __cpuinit inline int nmi_known_cpu (void ) -{ -switch (boot_cpu_data.x86_vendor) { -case X86_VENDOR_AMD : -return ((boot_cpu_data.x86 ==15 ) || (boot_cpu_data.x86 ==6 ) - || (boot_cpu_data.x86 ==16 )); -case X86_VENDOR_INTEL : -if (cpu_has (&boot_cpu_data,X86_FEATURE_ARCH_PERFMON )) -return 1 ; -else -return ((boot_cpu_data.x86 ==15 ) || (boot_cpu_data.x86 ==6 )); - } -return 0 ; -} -static int endflag__initdata =0 ;#ifdef CONFIG_SMP
@@ -281,28 +72,6 @@ static __init void nmi_cpu_busy(void *da }#endif -static unsigned int adjust_for_32bit_ctr (unsigned int hz) -{ -u64 counter_val; -unsigned int retval = hz; - -/* -* On Intel CPUs with P6/ARCH_PERFMON only 32 bits in the counter -* are writable, with higher bits sign extending from bit 31. -* So, we can only program the counter with 31 bit values and -* 32nd bit should be 1, for 33.. to be 1. -* Find the appropriate nmi_hz -*/ - counter_val = (u64 )cpu_khz *1000 ; -do_div (counter_val, retval); -if (counter_val >0x7fffffffULL ) { -u64 count = (u64 )cpu_khz *1000 ; -do_div (count,0x7fffffffUL ); - retval = count +1 ; - } -return retval; -} -static int __init check_nmi_watchdog (void ) {unsigned int *prev_nmi_count;
@@ -335,14 +104,14 @@ static int __init check_nmi_watchdog(voiif (!cpu_isset (cpu, cpu_callin_map))continue ;#endif -if (!per_cpu (nmi_watchdog_ctlblk, cpu).enabled) +if (!per_cpu (wd_enabled, cpu))continue ;if (nmi_count (cpu) - prev_nmi_count[cpu] <=5 ) {printk ("CPU#%d: NMI appears to be stuck (%d->%d)!\n" , cpu, prev_nmi_count[cpu],nmi_count (cpu)); -per_cpu (nmi_watchdog_ctlblk, cpu).enabled =0 ; +per_cpu (wd_enabled, cpu) =0 ;atomic_dec (&nmi_active); } }
@@ -356,16 +125,8 @@ static int __init check_nmi_watchdog(voi/* now that we know it works we can reduce NMI frequency to something more reasonable; makes a difference in some configs */ -if (nmi_watchdog ==NMI_LOCAL_APIC ) { -struct nmi_watchdog_ctlblk *wd = &__get_cpu_var (nmi_watchdog_ctlblk); - - nmi_hz =1 ; - -if (wd->perfctr_msr ==MSR_P6_PERFCTR0 || - wd->perfctr_msr ==MSR_ARCH_PERFMON_PERFCTR1 ) { - nmi_hz =adjust_for_32bit_ctr (nmi_hz); - } - } +if (nmi_watchdog ==NMI_LOCAL_APIC ) + nmi_hz =lapic_adjust_nmi_hz (1 );kfree (prev_nmi_count);return 0 ;
@@ -388,85 +149,8 @@ static int __init setup_nmi_watchdog(cha__setup ("nmi_watchdog=" , setup_nmi_watchdog); -static void disable_lapic_nmi_watchdog (void ) -{ -BUG_ON (nmi_watchdog !=NMI_LOCAL_APIC ); - -if (atomic_read (&nmi_active) <=0 ) -return ; - -on_each_cpu (stop_apic_nmi_watchdog,NULL ,0 ,1 ); - -BUG_ON (atomic_read (&nmi_active) !=0 ); -} - -static void enable_lapic_nmi_watchdog (void ) -{ -BUG_ON (nmi_watchdog !=NMI_LOCAL_APIC ); - -/* are we already enabled */ -if (atomic_read (&nmi_active) !=0 ) -return ; - -/* are we lapic aware */ -if (nmi_known_cpu () <=0 ) -return ; - -on_each_cpu (setup_apic_nmi_watchdog,NULL ,0 ,1 ); -touch_nmi_watchdog (); -} -void disable_timer_nmi_watchdog (void ) -{ -BUG_ON (nmi_watchdog !=NMI_IO_APIC ); - -if (atomic_read (&nmi_active) <=0 ) -return ; - -disable_irq (0 ); -on_each_cpu (stop_apic_nmi_watchdog,NULL ,0 ,1 ); - -BUG_ON (atomic_read (&nmi_active) !=0 ); -} - -void enable_timer_nmi_watchdog (void ) -{ -BUG_ON (nmi_watchdog !=NMI_IO_APIC ); - -if (atomic_read (&nmi_active) ==0 ) { -touch_nmi_watchdog (); -on_each_cpu (setup_apic_nmi_watchdog,NULL ,0 ,1 ); -enable_irq (0 ); - } -} - -static void __acpi_nmi_disable (void *__unused) -{ -apic_write_around (APIC_LVT0 ,APIC_DM_NMI |APIC_LVT_MASKED ); -} - -/* -* Disable timer based NMIs on all CPUs: -*/ -void acpi_nmi_disable (void ) -{ -if (atomic_read (&nmi_active) && nmi_watchdog ==NMI_IO_APIC ) -on_each_cpu (__acpi_nmi_disable,NULL ,0 ,1 ); -} - -static void __acpi_nmi_enable (void *__unused) -{ -apic_write_around (APIC_LVT0 ,APIC_DM_NMI ); -} - -/* -* Enable timer based NMIs on all CPUs: -*/ -void acpi_nmi_enable (void ) -{ -if (atomic_read (&nmi_active) && nmi_watchdog ==NMI_IO_APIC ) -on_each_cpu (__acpi_nmi_enable,NULL ,0 ,1 ); -} +/* Suspend/resume support */ #ifdef CONFIG_PM
@@ -513,7 +197,7 @@ static int __init init_lapic_nmi_sysfs(vif (nmi_watchdog !=NMI_LOCAL_APIC )return 0 ; -if (atomic_read (&nmi_active) <0 ) +if (atomic_read (&nmi_active) <0 )return 0 ; error =sysdev_class_register (&nmi_sysclass);
@@ -526,433 +210,69 @@ late_initcall(init_lapic_nmi_sysfs);#endif /* CONFIG_PM */ -/* -* Activate the NMI watchdog via the local APIC. -* Original code written by Keith Owens. -*/ - -static void write_watchdog_counter (unsigned int perfctr_msr,const char *descr) -{ -u64 count = (u64 )cpu_khz *1000 ; - -do_div (count, nmi_hz); -if (descr) -Dprintk ("setting %s to -0x%08Lx\n" , descr, count); -wrmsrl (perfctr_msr,0 - count); -} - -static void write_watchdog_counter32 (unsigned int perfctr_msr, -const char *descr) -{ -u64 count = (u64 )cpu_khz *1000 ; - -do_div (count, nmi_hz); -if (descr) -Dprintk ("setting %s to -0x%08Lx\n" , descr, count); -wrmsr (perfctr_msr, (u32)(-count),0 ); -} - -/* Note that these events don't tick when the CPU idles. This means -the frequency varies with CPU load. */ - -#define K7_EVNTSEL_ENABLE (1 << 22) -#define K7_EVNTSEL_INT (1 << 20) -#define K7_EVNTSEL_OS (1 << 17) -#define K7_EVNTSEL_USR (1 << 16) -#define K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING 0x76 -#define K7_NMI_EVENT K7_EVENT_CYCLES_PROCESSOR_IS_RUNNING - -static int setup_k7_watchdog (void ) -{ -unsigned int perfctr_msr, evntsel_msr; -unsigned int evntsel; -struct nmi_watchdog_ctlblk *wd = &__get_cpu_var (nmi_watchdog_ctlblk); - - perfctr_msr =MSR_K7_PERFCTR0 ; - evntsel_msr =MSR_K7_EVNTSEL0 ; -if (!__reserve_perfctr_nmi (-1 , perfctr_msr)) - goto fail; - -if (!__reserve_evntsel_nmi (-1 , evntsel_msr)) - goto fail1; - -wrmsrl (perfctr_msr,0UL ); - - evntsel =K7_EVNTSEL_INT - |K7_EVNTSEL_OS - |K7_EVNTSEL_USR - |K7_NMI_EVENT ; - -/* setup the timer */ -wrmsr (evntsel_msr, evntsel,0 ); -write_watchdog_counter (perfctr_msr,"K7_PERFCTR0" ); -apic_write (APIC_LVTPC ,APIC_DM_NMI ); - evntsel |=K7_EVNTSEL_ENABLE ; -wrmsr (evntsel_msr, evntsel,0 ); - - wd->perfctr_msr = perfctr_msr; - wd->evntsel_msr = evntsel_msr; - wd->cccr_msr =0 ;//unused - wd->check_bit =1ULL <<63 ; -return 1 ; -fail1: -__release_perfctr_nmi (-1 , perfctr_msr); -fail: -return 0 ; -} - -static void stop_k7_watchdog (void ) -{ -struct nmi_watchdog_ctlblk *wd = &__get_cpu_var (nmi_watchdog_ctlblk); - -wrmsr (wd->evntsel_msr,0 ,0 ); - -__release_evntsel_nmi (-1 , wd->evntsel_msr); -__release_perfctr_nmi (-1 , wd->perfctr_msr); -} - -#define P6_EVNTSEL0_ENABLE (1 << 22) -#define P6_EVNTSEL_INT (1 << 20) -#define P6_EVNTSEL_OS (1 << 17) -#define P6_EVNTSEL_USR (1 << 16) -#define P6_EVENT_CPU_CLOCKS_NOT_HALTED 0x79 -#define P6_NMI_EVENT P6_EVENT_CPU_CLOCKS_NOT_HALTED - -static int setup_p6_watchdog (void ) -{ -unsigned int perfctr_msr, evntsel_msr; -unsigned int evntsel; -struct nmi_watchdog_ctlblk *wd = &__get_cpu_var (nmi_watchdog_ctlblk); - - perfctr_msr =MSR_P6_PERFCTR0 ; - evntsel_msr =MSR_P6_EVNTSEL0 ; -if (!__reserve_perfctr_nmi (-1 , perfctr_msr)) - goto fail; - -if (!__reserve_evntsel_nmi (-1 , evntsel_msr)) - goto fail1; - -wrmsrl (perfctr_msr,0UL ); - - evntsel =P6_EVNTSEL_INT - |P6_EVNTSEL_OS - |P6_EVNTSEL_USR - |P6_NMI_EVENT ; - -/* setup the timer */ -wrmsr (evntsel_msr, evntsel,0 ); - nmi_hz =adjust_for_32bit_ctr (nmi_hz); -write_watchdog_counter32 (perfctr_msr,"P6_PERFCTR0" ); -apic_write (APIC_LVTPC ,APIC_DM_NMI ); - evntsel |=P6_EVNTSEL0_ENABLE ; -wrmsr (evntsel_msr, evntsel,0 ); - - wd->perfctr_msr = perfctr_msr; - wd->evntsel_msr = evntsel_msr; - wd->cccr_msr =0 ;//unused - wd->check_bit =1ULL <<39 ; -return 1 ; -fail1: -__release_perfctr_nmi (-1 , perfctr_msr); -fail: -return 0 ; -} - -static void stop_p6_watchdog (void ) -{ -struct nmi_watchdog_ctlblk *wd = &__get_cpu_var (nmi_watchdog_ctlblk); - -wrmsr (wd->evntsel_msr,0 ,0 ); - -__release_evntsel_nmi (-1 , wd->evntsel_msr); -__release_perfctr_nmi (-1 , wd->perfctr_msr); -} - -/* Note that these events don't tick when the CPU idles. This means -the frequency varies with CPU load. */ - -#define MSR_P4_MISC_ENABLE_PERF_AVAIL (1<<7) -#define P4_ESCR_EVENT_SELECT (N ) ((N)<<25) -#define P4_ESCR_OS (1<<3) -#define P4_ESCR_USR (1<<2) -#define P4_CCCR_OVF_PMI0 (1<<26) -#define P4_CCCR_OVF_PMI1 (1<<27) -#define P4_CCCR_THRESHOLD (N ) ((N)<<20) -#define P4_CCCR_COMPLEMENT (1<<19) -#define P4_CCCR_COMPARE (1<<18) -#define P4_CCCR_REQUIRED (3<<16) -#define P4_CCCR_ESCR_SELECT (N ) ((N)<<13) -#define P4_CCCR_ENABLE (1<<12) -#define P4_CCCR_OVF (1<<31) -/* Set up IQ_COUNTER0 to behave like a clock, by having IQ_CCCR0 filter -CRU_ESCR0 (with any non-null event selector) through a complemented -max threshold. [IA32-Vol3, Section 14.9.9] */ - -static int setup_p4_watchdog (void ) +static void __acpi_nmi_enable (void *__unused) { -unsigned int perfctr_msr, evntsel_msr, cccr_msr; -unsigned int evntsel, cccr_val; -unsigned int misc_enable, dummy; -unsigned int ht_num; -struct nmi_watchdog_ctlblk *wd = &__get_cpu_var (nmi_watchdog_ctlblk); - -rdmsr (MSR_IA32_MISC_ENABLE , misc_enable, dummy); -if (!(misc_enable &MSR_P4_MISC_ENABLE_PERF_AVAIL )) -return 0 ; - -#ifdef CONFIG_SMP -/* detect which hyperthread we are on */ -if (smp_num_siblings ==2 ) { -unsigned int ebx, apicid; - - ebx =cpuid_ebx (1 ); - apicid = (ebx >>24 ) &0xff ; - ht_num = apicid &1 ; - } else -#endif - ht_num =0 ; - -/* performance counters are shared resources -* assign each hyperthread its own set -* (re-use the ESCR0 register, seems safe -* and keeps the cccr_val the same) -*/ -if (!ht_num) { -/* logical cpu 0 */ - perfctr_msr =MSR_P4_IQ_PERFCTR0 ; - evntsel_msr =MSR_P4_CRU_ESCR0 ; - cccr_msr =MSR_P4_IQ_CCCR0 ; - cccr_val =P4_CCCR_OVF_PMI0 |P4_CCCR_ESCR_SELECT (4 ); - }else { -/* logical cpu 1 */ - perfctr_msr =MSR_P4_IQ_PERFCTR1 ; - evntsel_msr =MSR_P4_CRU_ESCR0 ; - cccr_msr =MSR_P4_IQ_CCCR1 ; - cccr_val =P4_CCCR_OVF_PMI1 |P4_CCCR_ESCR_SELECT (4 ); - } - -if (!__reserve_perfctr_nmi (-1 , perfctr_msr)) - goto fail; - -if (!__reserve_evntsel_nmi (-1 , evntsel_msr)) - goto fail1; - - evntsel =P4_ESCR_EVENT_SELECT (0x3F ) - |P4_ESCR_OS - |P4_ESCR_USR ; - - cccr_val |=P4_CCCR_THRESHOLD (15 ) - |P4_CCCR_COMPLEMENT - |P4_CCCR_COMPARE - |P4_CCCR_REQUIRED ; - -wrmsr (evntsel_msr, evntsel,0 ); -wrmsr (cccr_msr, cccr_val,0 ); -write_watchdog_counter (perfctr_msr,"P4_IQ_COUNTER0" ); -apic_write (APIC_LVTPC ,APIC_DM_NMI ); - cccr_val |=P4_CCCR_ENABLE ; -wrmsr (cccr_msr, cccr_val,0 ); - wd->perfctr_msr = perfctr_msr; - wd->evntsel_msr = evntsel_msr; - wd->cccr_msr = cccr_msr; - wd->check_bit =1ULL <<39 ; -return 1 ; -fail1: -__release_perfctr_nmi (-1 , perfctr_msr); -fail: -return 0 ; +apic_write_around (APIC_LVT0 ,APIC_DM_NMI ); } -static void stop_p4_watchdog (void ) +/* +* Enable timer based NMIs on all CPUs: +*/ +void acpi_nmi_enable (void ) { -struct nmi_watchdog_ctlblk *wd = &__get_cpu_var (nmi_watchdog_ctlblk); - -wrmsr (wd->cccr_msr,0 ,0 ); -wrmsr (wd->evntsel_msr,0 ,0 ); - -__release_evntsel_nmi (-1 , wd->evntsel_msr); -__release_perfctr_nmi (-1 , wd->perfctr_msr); +if (atomic_read (&nmi_active) && nmi_watchdog ==NMI_IO_APIC ) +on_each_cpu (__acpi_nmi_enable,NULL ,0 ,1 ); } -#define ARCH_PERFMON_NMI_EVENT_SEL ARCH_PERFMON_UNHALTED_CORE_CYCLES_SEL -#define ARCH_PERFMON_NMI_EVENT_UMASK ARCH_PERFMON_UNHALTED_CORE_CYCLES_UMASK - -static int setup_intel_arch_watchdog (void ) +static void __acpi_nmi_disable (void *__unused) { -unsigned int ebx; -union cpuid10_eax eax; -unsigned int unused; -unsigned int perfctr_msr, evntsel_msr; -unsigned int evntsel; -struct nmi_watchdog_ctlblk *wd = &__get_cpu_var (nmi_watchdog_ctlblk); - -/* -* Check whether the Architectural PerfMon supports -* Unhalted Core Cycles Event or not. -* NOTE: Corresponding bit = 0 in ebx indicates event present. -*/ -cpuid (10 , &(eax.full), &ebx, &unused, &unused); -if ((eax.split.mask_length < (ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX +1 )) || - (ebx &ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT )) - goto fail; - - perfctr_msr =MSR_ARCH_PERFMON_PERFCTR1 ; - evntsel_msr =MSR_ARCH_PERFMON_EVENTSEL1 ; - -if (!__reserve_perfctr_nmi (-1 , perfctr_msr)) - goto fail; - -if (!__reserve_evntsel_nmi (-1 , evntsel_msr)) - goto fail1; - -wrmsrl (perfctr_msr,0UL ); - - evntsel =ARCH_PERFMON_EVENTSEL_INT - |ARCH_PERFMON_EVENTSEL_OS - |ARCH_PERFMON_EVENTSEL_USR - |ARCH_PERFMON_NMI_EVENT_SEL - |ARCH_PERFMON_NMI_EVENT_UMASK ; - -/* setup the timer */ -wrmsr (evntsel_msr, evntsel,0 ); - nmi_hz =adjust_for_32bit_ctr (nmi_hz); -write_watchdog_counter32 (perfctr_msr,"INTEL_ARCH_PERFCTR0" ); -apic_write (APIC_LVTPC ,APIC_DM_NMI ); - evntsel |=ARCH_PERFMON_EVENTSEL0_ENABLE ; -wrmsr (evntsel_msr, evntsel,0 ); - - wd->perfctr_msr = perfctr_msr; - wd->evntsel_msr = evntsel_msr; - wd->cccr_msr =0 ;//unused - wd->check_bit =1ULL << (eax.split.bit_width -1 ); -return 1 ; -fail1: -__release_perfctr_nmi (-1 , perfctr_msr); -fail: -return 0 ; +apic_write (APIC_LVT0 ,APIC_DM_NMI |APIC_LVT_MASKED ); } -static void stop_intel_arch_watchdog (void ) +/* +* Disable timer based NMIs on all CPUs: +*/ +void acpi_nmi_disable (void ) { -unsigned int ebx; -union cpuid10_eax eax; -unsigned int unused; -struct nmi_watchdog_ctlblk *wd = &__get_cpu_var (nmi_watchdog_ctlblk); - -/* -* Check whether the Architectural PerfMon supports -* Unhalted Core Cycles Event or not. -* NOTE: Corresponding bit = 0 in ebx indicates event present. -*/ -cpuid (10 , &(eax.full), &ebx, &unused, &unused); -if ((eax.split.mask_length < (ARCH_PERFMON_UNHALTED_CORE_CYCLES_INDEX +1 )) || - (ebx &ARCH_PERFMON_UNHALTED_CORE_CYCLES_PRESENT )) -return ; - -wrmsr (wd->evntsel_msr,0 ,0 ); -__release_evntsel_nmi (-1 , wd->evntsel_msr); -__release_perfctr_nmi (-1 , wd->perfctr_msr); +if (atomic_read (&nmi_active) && nmi_watchdog ==NMI_IO_APIC ) +on_each_cpu (__acpi_nmi_disable,NULL ,0 ,1 ); }void setup_apic_nmi_watchdog (void *unused) { -struct nmi_watchdog_ctlblk *wd = &__get_cpu_var (nmi_watchdog_ctlblk); - -/* only support LOCAL and IO APICs for now */ -if ((nmi_watchdog !=NMI_LOCAL_APIC ) && - (nmi_watchdog !=NMI_IO_APIC )) -return ; - -if (wd->enabled ==1 ) -return ; +if (__get_cpu_var (wd_enabled)) +return ;/* cheap hack to support suspend/resume */ /* if cpu0 is not active neither should the other cpus */ if ((smp_processor_id () !=0 ) && (atomic_read (&nmi_active) <=0 ))return ; -if (nmi_watchdog ==NMI_LOCAL_APIC ) { -switch (boot_cpu_data.x86_vendor) { -case X86_VENDOR_AMD : -if (boot_cpu_data.x86 !=6 && boot_cpu_data.x86 !=15 && - boot_cpu_data.x86 !=16 ) -return ; -if (!setup_k7_watchdog ()) -return ; -break ; -case X86_VENDOR_INTEL : -if (cpu_has (&boot_cpu_data,X86_FEATURE_ARCH_PERFMON )) { -if (!setup_intel_arch_watchdog ()) -return ; -break ; - } -switch (boot_cpu_data.x86) { -case 6 : -if (boot_cpu_data.x86_model >0xd ) -return ; - -if (!setup_p6_watchdog ()) -return ; -break ; -case 15 : -if (boot_cpu_data.x86_model >0x4 ) -return ; - -if (!setup_p4_watchdog ()) -return ; -break ; -default : -return ; - } -break ; -default : +switch (nmi_watchdog) { +case NMI_LOCAL_APIC : +__get_cpu_var (wd_enabled) =1 ;/* enable it before to avoid race with handler */ +if (lapic_watchdog_init (nmi_hz) <0 ) { +__get_cpu_var (wd_enabled) =0 ;return ; } +/* FALL THROUGH */ +case NMI_IO_APIC : +__get_cpu_var (wd_enabled) =1 ; +atomic_inc (&nmi_active); } - wd->enabled =1 ; -atomic_inc (&nmi_active); }void stop_apic_nmi_watchdog (void *unused) { -struct nmi_watchdog_ctlblk *wd = &__get_cpu_var (nmi_watchdog_ctlblk); -/* only support LOCAL and IO APICs for now */ if ((nmi_watchdog !=NMI_LOCAL_APIC ) && (nmi_watchdog !=NMI_IO_APIC ))return ; - -if (wd->enabled ==0 ) +if (__get_cpu_var (wd_enabled) ==0 )return ; - -if (nmi_watchdog ==NMI_LOCAL_APIC ) { -switch (boot_cpu_data.x86_vendor) { -case X86_VENDOR_AMD : -stop_k7_watchdog (); -break ; -case X86_VENDOR_INTEL : -if (cpu_has (&boot_cpu_data,X86_FEATURE_ARCH_PERFMON )) { -stop_intel_arch_watchdog (); -break ; - } -switch (boot_cpu_data.x86) { -case 6 : -if (boot_cpu_data.x86_model >0xd ) -break ; -stop_p6_watchdog (); -break ; -case 15 : -if (boot_cpu_data.x86_model >0x4 ) -break ; -stop_p4_watchdog (); -break ; - } -break ; -default : -return ; - } - } - wd->enabled =0 ; +if (nmi_watchdog ==NMI_LOCAL_APIC ) +lapic_watchdog_stop (); +__get_cpu_var (wd_enabled) =0 ;atomic_dec (&nmi_active); }
@@ -1008,8 +328,6 @@ __kprobes int nmi_watchdog_tick(struct punsigned int sum;int touched =0 ;int cpu =smp_processor_id (); -struct nmi_watchdog_ctlblk *wd = &__get_cpu_var (nmi_watchdog_ctlblk); -u64 dummy;int rc=0 ;/* check for other users first */
@@ -1052,53 +370,20 @@ __kprobes int nmi_watchdog_tick(struct p alert_counter[cpu] =0 ; }/* see if the nmi watchdog went off */ -if (wd->enabled) { -if (nmi_watchdog ==NMI_LOCAL_APIC ) { -rdmsrl (wd->perfctr_msr, dummy); -if (dummy & wd->check_bit){ -/* this wasn't a watchdog timer interrupt */ - goto done; - } - -/* only Intel P4 uses the cccr msr */ -if (wd->cccr_msr !=0 ) { -/* -* P4 quirks: -* - An overflown perfctr will assert its interrupt -* until the OVF flag in its CCCR is cleared. -* - LVTPC is masked on interrupt and must be -* unmasked by the LVTPC handler. -*/ -rdmsrl (wd->cccr_msr, dummy); - dummy &= ~P4_CCCR_OVF ; -wrmsrl (wd->cccr_msr, dummy); -apic_write (APIC_LVTPC ,APIC_DM_NMI ); -/* start the cycle over again */ -write_watchdog_counter (wd->perfctr_msr,NULL ); - } -else if (wd->perfctr_msr ==MSR_P6_PERFCTR0 || - wd->perfctr_msr ==MSR_ARCH_PERFMON_PERFCTR1 ) { -/* P6 based Pentium M need to re-unmask -* the apic vector but it doesn't hurt -* other P6 variant. -* ArchPerfom/Core Duo also needs this */ -apic_write (APIC_LVTPC ,APIC_DM_NMI ); -/* P6/ARCH_PERFMON has 32 bit counter write */ -write_watchdog_counter32 (wd->perfctr_msr,NULL ); - }else { -/* start the cycle over again */ -write_watchdog_counter (wd->perfctr_msr,NULL ); - } - rc =1 ; - }else if (nmi_watchdog ==NMI_IO_APIC ) { -/* don't know how to accurately check for this. -* just assume it was a watchdog timer interrupt -* This matches the old behaviour. -*/ - rc =1 ; - } +if (!__get_cpu_var (wd_enabled)) +return rc; +switch (nmi_watchdog) { +case NMI_LOCAL_APIC : + rc |=lapic_wd_event (nmi_hz); +break ; +case NMI_IO_APIC : +/* don't know how to accurately check for this. +* just assume it was a watchdog timer interrupt +* This matches the old behaviour. +*/ + rc =1 ; +break ; } -done:return rc; }
@@ -1143,7 +428,7 @@ int proc_nmi_enabled(struct ctl_table *t }if (nmi_watchdog ==NMI_DEFAULT ) { -if (nmi_known_cpu () >0 ) +if (lapic_watchdog_ok ()) nmi_watchdog =NMI_LOCAL_APIC ;else nmi_watchdog =NMI_IO_APIC ;
@@ -1179,11 +464,3 @@ void __trigger_all_cpu_backtrace(void)EXPORT_SYMBOL (nmi_active);EXPORT_SYMBOL (nmi_watchdog); -EXPORT_SYMBOL (avail_to_resrv_perfctr_nmi); -EXPORT_SYMBOL (avail_to_resrv_perfctr_nmi_bit); -EXPORT_SYMBOL (reserve_perfctr_nmi); -EXPORT_SYMBOL (release_perfctr_nmi); -EXPORT_SYMBOL (reserve_evntsel_nmi); -EXPORT_SYMBOL (release_evntsel_nmi); -EXPORT_SYMBOL (disable_timer_nmi_watchdog); -EXPORT_SYMBOL (enable_timer_nmi_watchdog);
arch/i386/kernel/cpu/Makefile +2 -0
@@ -17,3 +17,5 @@ obj-$(CONFIG_X86_MCE) += mcheck/ obj-$(CONFIG_MTRR) += mtrr/ obj-$(CONFIG_CPU_FREQ) += cpufreq/ + +obj-$(CONFIG_X86_LOCAL_APIC) += perfctr-watchdog.o
arch/i386/kernel/cpu/perfctr-watchdog.c new file +658 -0
658 lines not on this page · raw message
include/asm-i386/nmi.h +8 -0
@@ -50,4 +50,12 @@ void __trigger_all_cpu_backtrace(void);#endif +void lapic_watchdog_stop (void ); +int lapic_watchdog_init (unsigned nmi_hz); +int lapic_wd_event (unsigned nmi_hz); +unsigned lapic_adjust_nmi_hz (unsigned hz); +int lapic_watchdog_ok (void ); +void disable_lapic_nmi_watchdog (void ); +void enable_lapic_nmi_watchdog (void ); +#endif /* ASM_NMI_H */
PATCH 4/30 x86_64: Use the 32bit wd_ops for 64bit too.
In reply to Andi KleenThis mainly removes a lot of code, replacing it with calls into the new 32bit perfctr-watchdog.c
--- arch/x86_64/kernel/Makefile | 3 arch/x86_64/kernel/nmi.c | 678 ++------------------------------------------ include/asm-x86_64/nmi.h | 9 3 files changed, 44 insertions(+), 646 deletions(-)
arch/x86_64/kernel/Makefile +2 -1
@@ -9,7 +9,7 @@ obj-y := process.o signal.o entry.o trap x8664_ksyms.o i387.o syscall.o vsyscall.o \ setup64.o bootflag.o e820.o reboot.o quirks.o i8237.o \ pci-dma.o pci-nommu.o alternative.o hpet.o tsc.o sched-clock.o \ - bugs.o + bugs.o perfctr-watchdog.o obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-$(CONFIG_X86_MCE) += mce.o therm_throt.o
@@ -59,3 +59,4 @@ msr-$(subst m,y,$(CONFIG_X86_MSR)) += . alternative-y += ../../i386/kernel/alternative.o pcspeaker-y += ../../i386/kernel/pcspeaker.o sched-clock-y += ../../i386/kernel/sched-clock.o +perfctr-watchdog-y += ../../i386/kernel/cpu/perfctr-watchdog.o
include/asm-x86_64/nmi.h +9 -0
@@ -80,4 +80,13 @@ extern int unknown_nmi_panic;void __trigger_all_cpu_backtrace (void );#define trigger_all_cpu_backtrace () __trigger_all_cpu_backtrace() + +void lapic_watchdog_stop (void ); +int lapic_watchdog_init (unsigned nmi_hz); +int lapic_wd_event (unsigned nmi_hz); +unsigned lapic_adjust_nmi_hz (unsigned hz); +int lapic_watchdog_ok (void ); +void disable_lapic_nmi_watchdog (void ); +void enable_lapic_nmi_watchdog (void ); +#endif /* ASM_NMI_H */
arch/x86_64/kernel/nmi.c +33 -645
772 lines not on this page · raw message
PATCH 5/30 x86_64: Define IGNORE_IOCTL() macro for compat_ioctls
In reply to Andi KleenDefine a new IGNORE_IOCTL() to let a compat ioctl not be warned about even when it is not implemented.
This is the same as COMPATIBLE_IOCTL internally, but better self documentng.
Valid reasons to use this:
- It is implemented with ->compat_ioctl on some device, but programs call it on others too.
- The ioctl is not implemented in the native kernel, but programs call it commonly anyways.
Most other reasons are not valid.
--- fs/compat_ioctl.c | 8 ++++++++ 1 file changed, 8 insertions(+)
fs/compat_ioctl.c +8 -0
@@ -2396,6 +2396,14 @@ lp_timeout_trans(unsigned int fd, unsign#define ULONG_IOCTL (cmd) \ { (cmd), (ioctl_trans_handler_t)sys_ioctl }, +/* ioctl should not be warned about even if it's not implemented. +Valid reasons to use this: +- It is implemented with ->compat_ioctl on some device, but programs +call it on others too. +- The ioctl is not implemented in the native kernel, but programs +call it commonly anyways. +Most other reasons are not valid. */ +#define IGNORE_IOCTL (cmd) COMPATIBLE_IOCTL(cmd) struct ioctl_trans ioctl_start[] = {#include <linux/compat_ioctl.h>
PATCH 6/30 x86_64: Shut up 32bit emulation for SIOCGIFCOUNT
In reply to Andi KleenThe kernel doesn't implement it, but some programs like java use it anyways. Shut the code up.
--- fs/compat_ioctl.c | 2 ++ 1 file changed, 2 insertions(+)
fs/compat_ioctl.c +2 -0
@@ -2602,6 +2602,8 @@ HANDLE_IOCTL(SIOCGIWENCODEEXT, do_wirele HANDLE_IOCTL(SIOCSIWPMKSA, do_wireless_ioctl) HANDLE_IOCTL(SIOCSIFBR, old_bridge_ioctl)HANDLE_IOCTL (SIOCGIFBR , old_bridge_ioctl) +/* Not implemented in the native kernel */ +IGNORE_IOCTL(SIOCGIFCOUNT) HANDLE_IOCTL(RTC_IRQP_READ32, rtc_ioctl) HANDLE_IOCTL(RTC_IRQP_SET32, rtc_ioctl) HANDLE_IOCTL(RTC_EPOCH_READ32, rtc_ioctl)
PATCH 7/30 x86_64: Avoid overflows during apic timer calibration
In reply to Andi KleenFrom: David P. Reed <[email protected]>
- Use 64bit TSC calculations to avoid handling overflow
- Use 32bit unsigned arithmetic for the APIC timer. This way overflows are handled correctly.
- Fix exit check of loop to account for apic timer counting down
--- arch/x86_64/kernel/apic.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
arch/x86_64/kernel/apic.c +6 -5
@@ -839,14 +839,15 @@ static void setup_APIC_timer(unsigned instatic int __init calibrate_APIC_clock (void ) { -int apic, apic_start, tsc, tsc_start; +unsigned apic, apic_start; +unsigned long tsc, tsc_start;int result;/* * Put whatever arbitrary (but long enough) timeout * value into the APIC clock, we just want to get the * counter running for calibration. */ -__setup_APIC_LVTT (1000000000 ); +__setup_APIC_LVTT (4000000000 ); apic_start =apic_read (APIC_TMCCT );#ifdef CONFIG_X86_PM_TIMER
@@ -857,13 +858,13 @@ static int __init calibrate_APIC_clock(v } else#endif { -rdtscl (tsc_start); +rdtscll (tsc_start);do { apic =apic_read (APIC_TMCCT ); -rdtscl (tsc); +rdtscll (tsc); }while ((tsc - tsc_start) <TICK_COUNT && - (apic - apic_start) <TICK_COUNT ); + (apic_start - apic) <TICK_COUNT ); result = (apic_start - apic) *1000L * tsc_khz / (tsc - tsc_start);
PATCH 8/30 x86_64: Add vDSO for x86-64 with gettimeofday/clock_gettime/getcpu
In reply to Andi KleenThis implements new vDSO for x86-64. The concept is similar to the existing vDSOs on i386 and PPC. x86-64 has had static vsyscalls before, but these are not flexible enough anymore.
A vDSO is a ELF shared library supplied by the kernel that is mapped into user address space. The vDSO mapping is randomized for each process for security reasons.
Doing this was needed for clock_gettime, because clock_gettime always needs a syscall fallback and having one at a fixed address would have made buffer overflow exploits too easy to write.
The vdso can be disabled with vdso=0
It currently includes a new gettimeofday implemention and optimized clock_gettime(). The gettimeofday implementation is slightly faster than the one in the old vsyscall. clock_gettime is significantly faster than the syscall for CLOCK_MONOTONIC and CLOCK_REALTIME.
The new calls are generally faster than the old vsyscall.
TBD: add new benchmarks
Advantages over the old x86-64 vsyscalls:
- Extensible
- Randomized
- Cleaner
- Easier to virtualize (the old static address range previously causes overhead e.g. for Xen because it has to create special page tables for it)
Weak points:
- glibc support still to be written
The VM interface is partly based on Ingo Molnar's i386 version.
--- Documentation/kernel-parameters.txt | 2 arch/x86_64/Makefile | 3 arch/x86_64/ia32/ia32_binfmt.c | 1 arch/x86_64/kernel/time.c | 1 arch/x86_64/kernel/vmlinux.lds.S | 12 +++ arch/x86_64/kernel/vsyscall.c | 22 +---- arch/x86_64/mm/init.c | 17 ++++ arch/x86_64/vdso/Makefile | 49 ++++++++++++ arch/x86_64/vdso/vclock_gettime.c | 120 +++++++++++++++++++++++++++++++ arch/x86_64/vdso/vdso-note.S | 25 ++++++ arch/x86_64/vdso/vdso-start.S | 2 arch/x86_64/vdso/vdso.S | 2 arch/x86_64/vdso/vdso.lds.S | 77 ++++++++++++++++++++ arch/x86_64/vdso/vextern.h | 16 ++++ arch/x86_64/vdso/vgetcpu.c | 50 +++++++++++++ arch/x86_64/vdso/vma.c | 137 ++++++++++++++++++++++++++++++++++++ arch/x86_64/vdso/voffset.h | 1 arch/x86_64/vdso/vvar.c | 12 +++ include/asm-x86_64/auxvec.h | 2 include/asm-x86_64/elf.h | 13 +++ include/asm-x86_64/mmu.h | 1 include/asm-x86_64/pgtable.h | 8 +- include/asm-x86_64/vgtod.h | 29 +++++++ include/asm-x86_64/vsyscall.h | 3 24 files changed, 583 insertions(+), 22 deletions(-)
arch/x86_64/ia32/ia32_binfmt.c +1 -0
@@ -38,6 +38,7 @@int sysctl_vsyscall32 =1 ; +#undef ARCH_DLINFO#define ARCH_DLINFO do { \ if (sysctl_vsyscall32) { \ NEW_AUX_ENT(AT_SYSINFO, (u32)(u64)VSYSCALL32_VSYSCALL); \
arch/x86_64/kernel/vmlinux.lds.S +12 -0
@@ -94,6 +94,9 @@ SECTIONS .vsyscall_gtod_data : AT(VLOAD(.vsyscall_gtod_data)) { *(.vsyscall_gtod_data) } vsyscall_gtod_data = VVIRT(.vsyscall_gtod_data); + .vsyscall_clock : AT(VLOAD(.vsyscall_clock)) + { *(.vsyscall_clock) } + vsyscall_clock = VVIRT(.vsyscall_clock); .vsyscall_1 ADDR(.vsyscall_0) + 1024: AT(VLOAD(.vsyscall_1))
@@ -153,6 +156,8 @@ SECTIONS . = ALIGN(4096); /* Init code and data */ __init_begin = .; + + .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) { _sinittext = .; *(.init.text)
@@ -190,6 +195,12 @@ SECTIONS .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) { *(.exit.text) } .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { *(.exit.data) } +/* vdso blob that is mapped into user space */ + vdso_start = . ; + .vdso : AT(ADDR(.vdso) - LOAD_OFFSET) { *(.vdso) } + . = ALIGN(4096); + vdso_end = .; + #ifdef CONFIG_BLK_DEV_INITRD . = ALIGN(4096); __initramfs_start = .;
@@ -202,6 +213,7 @@ SECTIONS .data.percpu : AT(ADDR(.data.percpu) - LOAD_OFFSET) { *(.data.percpu) } __per_cpu_end = .; . = ALIGN(4096); + __init_end = .; . = ALIGN(4096);
arch/x86_64/mm/init.c +17 -0
@@ -159,6 +159,14 @@ static __init void set_pte_phys(unsigned__flush_tlb_one (vaddr); } +void __init +set_kernel_map (void *vaddr,unsigned long len,unsigned long phys,pgprot_t prot) +{ +void *end = vaddr +ALIGN (len,PAGE_SIZE ); +for (; vaddr < end; vaddr +=PAGE_SIZE , phys +=PAGE_SIZE ) +set_pte_phys ((unsigned long )vaddr, phys, prot); +} +/* NOTE: this is meant to be run only at boot */ void __init __set_fixmap (enum fixed_addresses idx,unsigned long phys,pgprot_t prot)
@@ -756,3 +764,12 @@ int in_gate_area_no_task(unsigned long a {return (addr >=VSYSCALL_START ) && (addr <VSYSCALL_END ); } + +const char *arch_vma_name (struct vm_area_struct *vma) +{ +if (vma->vm_mm && vma->vm_start == (long )vma->vm_mm->context.vdso) +return "[vdso]" ; +if (vma == &gate_vma) +return "[vsyscall]" ; +return NULL ; +}
arch/x86_64/vdso/vdso-note.S new file +25 -0
@@ -0,0 +1,25 @@ +/* + * This supplies .note.* sections to go into the PT_NOTE inside the vDSO text. + * Here we can supply some information useful to userland. + */ + +#include <linux/uts.h> +#include <linux/version.h> + +#define ASM_ELF_NOTE_BEGIN(name, flags, vendor, type) \ + .section name, flags; \ + .balign 4; \ + .long 1f - 0f; /* name length */ \ + .long 3f - 2f; /* data length */ \ + .long type; /* note type */ \ +0: .asciz vendor; /* vendor name */ \ +1: .balign 4; \ +2: + +#define ASM_ELF_NOTE_END \ +3: .balign 4; /* pad out section */ \ + .previous + + ASM_ELF_NOTE_BEGIN(".note.kernel-version", "a", UTS_SYSNAME, 0) + .long LINUX_VERSION_CODE + ASM_ELF_NOTE_END
arch/x86_64/vdso/vdso.lds.S new file +77 -0
77 lines not on this page · raw message
arch/x86_64/vdso/Makefile new file +49 -0
49 lines not on this page · raw message
arch/x86_64/vdso/vclock_gettime.c new file +120 -0
120 lines not on this page · raw message
arch/x86_64/vdso/vma.c new file +137 -0
137 lines not on this page · raw message
arch/x86_64/vdso/vdso.S new file +2 -0
@@ -0,0 +1,2 @@ + .section ".vdso","a" + .incbin "arch/x86_64/vdso/vdso.so"
arch/x86_64/vdso/vdso-start.S new file +2 -0
@@ -0,0 +1,2 @@ + .globl vdso_kernel_start +vdso_kernel_start:
arch/x86_64/Makefile +2 -1
@@ -77,7 +77,8 @@ head-y := arch/x86_64/kernel/head.o arch libs-y += arch/x86_64/lib/ core-y += arch/x86_64/kernel/ \ arch/x86_64/mm/ \ - arch/x86_64/crypto/ + arch/x86_64/crypto/ \ + arch/x86_64/vdso/ core-$(CONFIG_IA32_EMULATION) += arch/x86_64/ia32/ drivers-$(CONFIG_PCI) += arch/x86_64/pci/ drivers-$(CONFIG_OPROFILE) += arch/x86_64/oprofile/
include/asm-x86_64/pgtable.h +7 -1
@@ -415,6 +415,9 @@ void vmalloc_sync_all(void);extern int kern_addr_valid (unsigned long addr); +extern void set_kernel_map (void *vaddr,unsigned long len, +unsigned long phys,pgprot_t prot); +#define io_remap_pfn_range (vma, vaddr, pfn, size, prot) \ remap_pfn_range(vma, vaddr, pfn, size, prot)
@@ -442,6 +445,9 @@ extern int kern_addr_valid(unsigned long#define __HAVE_ARCH_PTEP_SET_WRPROTECT#define __HAVE_ARCH_PTE_SAME#include <asm-generic/pgtable.h> -#endif /* !__ASSEMBLY__ */ +extern void +fix_set_pte_phys (unsigned long vaddr,unsigned long phys,pgprot_t prot); + +#endif /* !__ASSEMBLY__ */ #endif /* _X86_64_PGTABLE_H */
include/asm-x86_64/mmu.h +1 -0
@@ -15,6 +15,7 @@ typedef struct {rwlock_t ldtlock;int size;struct semaphore sem; + void *vdso; } mm_context_t;#endif
include/asm-x86_64/vsyscall.h +2 -1
@@ -22,6 +22,8 @@ enum vsyscall_num {/* Definitions for CONFIG_GENERIC_TIME definitions */ #define __section_vsyscall_gtod_data __attribute__ \ ((unused, __section__ (".vsyscall_gtod_data"),aligned(16))) +#define __section_vsyscall_clock __attribute__ \ + ((unused, __section__ (".vsyscall_clock"),aligned(16)))#define __vsyscall_fn __attribute__ ((unused,__section__(".vsyscall_fn")))#define VGETCPU_RDTSCP 1
@@ -36,7 +38,6 @@ extern volatile unsigned long __jiffies;/* kernel space (writeable) */ extern int vgetcpu_mode;extern struct timezone sys_tz; -extern struct vsyscall_gtod_data_t vsyscall_gtod_data;#endif /* __KERNEL__ */
include/asm-x86_64/auxvec.h +2 -0
@@ -1,4 +1,6 @@#ifndef __ASM_X86_64_AUXVEC_H#define __ASM_X86_64_AUXVEC_H +#define AT_SYSINFO_EHDR 33 +#endif
include/asm-x86_64/elf.h +13 -0
@@ -162,6 +162,19 @@ extern int dump_task_fpu (struct task_st/* 1GB for 64bit, 8MB for 32bit */ #define STACK_RND_MASK (test_thread_flag(TIF_IA32) ? 0x7ff : 0x3fffff) + +#define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1 +struct linux_binprm ; +extern int arch_setup_additional_pages (struct linux_binprm *bprm, +int executable_stack); + +extern int vdso_enabled; + +#define ARCH_DLINFO \ +do if (vdso_enabled) { \ + NEW_AUX_ENT(AT_SYSINFO_EHDR,(unsigned long)current->mm->context.vdso);\ +} while (0) +#endif #endif
arch/x86_64/vdso/vextern.h new file +16 -0
@@ -0,0 +1,16 @@ +#ifndef VEXTERN +#include <asm/vsyscall.h> +#define VEXTERN (x) \ + extern typeof(x) *vdso_ ## x __attribute__((visibility("hidden"))); +#endif + +#define VMAGIC 0xfeedbabeabcdefabUL + +/* Any kernel variables used in the vDSO must be exported in the main +kernel's vmlinux.lds.S/vsyscall.h/proper __section and +put into vextern.h and be referenced as a pointer with vdso prefix. +The main kernel later fills in the values. */ + +VEXTERN(jiffies) +VEXTERN(vgetcpu_mode) +VEXTERN(vsyscall_gtod_data)
arch/x86_64/vdso/vgetcpu.c new file +50 -0
50 lines not on this page · raw message
arch/x86_64/vdso/vvar.c new file +12 -0
@@ -0,0 +1,12 @@ +/* Define pointer to external vDSO variables. +These are part of the vDSO. The kernel fills in the real addresses +at boot time. This is done because when the vdso is linked the +kernel isn't yet and we don't know the final addresses. */ +#include <linux/kernel.h> +#include <linux/time.h> +#include <asm/vsyscall.h> +#include <asm/timex.h> +#include <asm/vgtod.h> + +#define VEXTERN (x) typeof (__ ## x) *vdso_ ## x = (void *)VMAGIC; +#include "vextern.h"
Documentation/kernel-parameters.txt +1 -1
@@ -1813,7 +1813,7 @@ and is between 256 and 4096 characters. usbhid.mousepoll= [USBHID] The interval which mice are to be polled at. - vdso= [IA-32,SH] + vdso= [IA-32,SH,x86-64] vdso=2: enable compat VDSO (default with COMPAT_VDSO) vdso=1: enable VDSO (default) vdso=0: disable VDSO mapping
arch/x86_64/kernel/vsyscall.c +4 -18
@@ -42,6 +42,7 @@#include <asm/segment.h> #include <asm/desc.h> #include <asm/topology.h> +#include <asm/vgtod.h> #define __vsyscall (nr) __attribute__ ((unused,__section__(".vsyscall_" #nr)))#define __syscall_clobber "r11","rcx","memory"
@@ -57,26 +58,9 @@* - writen by timer interrupt or systcl (/proc/sys/kernel/vsyscall64) * Try to keep this structure as small as possible to avoid cache line ping pongs */ -struct vsyscall_gtod_data_t { -seqlock_t lock; - -/* open coded 'struct timespec' */ -time_t wall_time_sec; -u32 wall_time_nsec; - -int sysctl_enabled; -struct timezone sys_tz; -struct {/* extract of a clocksource struct */ -cycle_t (*vread)(void ); -cycle_t cycle_last; -cycle_t mask; -u32 mult; -u32 shift; - } clock; -}; int __vgetcpu_mode __section_vgetcpu_mode; -struct vsyscall_gtod_data_t __vsyscall_gtod_data __section_vsyscall_gtod_data = +struct vsyscall_gtod_data __vsyscall_gtod_data __section_vsyscall_gtod_data = { .lock =SEQLOCK_UNLOCKED , .sysctl_enabled =1 ,
@@ -96,6 +80,8 @@ void update_vsyscall(struct timespec *wa vsyscall_gtod_data.wall_time_sec = wall_time->tv_sec; vsyscall_gtod_data.wall_time_nsec = wall_time->tv_nsec; vsyscall_gtod_data.sys_tz = sys_tz; + vsyscall_gtod_data.wall_time_nsec = wall_time->tv_nsec; + vsyscall_gtod_data.wall_to_monotonic = wall_to_monotonic;write_sequnlock_irqrestore (&vsyscall_gtod_data.lock, flags); }
arch/x86_64/kernel/time.c +1 -0
@@ -44,6 +44,7 @@#include <asm/hpet.h> #include <asm/mpspec.h> #include <asm/nmi.h> +#include <asm/vgtod.h> static char *timename =NULL ;
include/asm-x86_64/vgtod.h new file +29 -0
@@ -0,0 +1,29 @@ +#ifndef _ASM_VGTOD_H +#define _ASM_VGTOD_H 1 + +#include <asm/vsyscall.h> +#include <linux/clocksource.h> + +struct vsyscall_gtod_data { +seqlock_t lock; + +/* open coded 'struct timespec' */ +time_t wall_time_sec; +u32 wall_time_nsec; + +int sysctl_enabled; +struct timezone sys_tz; +struct {/* extract of a clocksource struct */ +cycle_t (*vread)(void ); +cycle_t cycle_last; +cycle_t mask; +u32 mult; +u32 shift; + } clock; +struct timespec wall_to_monotonic; +}; +extern struct vsyscall_gtod_data __vsyscall_gtod_data +__section_vsyscall_gtod_data; +extern struct vsyscall_gtod_data vsyscall_gtod_data; + +#endif
arch/x86_64/vdso/voffset.h new file +1 -0
@@ -0,0 +1 @@ +#define VDSO_TEXT_OFFSET 0x500
Re: [PATCH] [8/30] x86_64: Add vDSO for x86-64 with gettimeofday/clock_gettime/getcpu
Quoted 158 lines · Andi Kleen
This implements new vDSO for x86-64. The concept is similar to the existing vDSOs on i386 and PPC. x86-64 has had static vsyscalls before, but these are not flexible enough anymore.
A vDSO is a ELF shared library supplied by the kernel that is mapped into user address space. The vDSO mapping is randomized for each process for security reasons.
Doing this was needed for
clock_gettime, becauseclock_gettimealways needs a syscall fallback and having one at a fixed address would have made buffer overflow exploits too easy to write.The vdso can be disabled with vdso=0
It currently includes a new gettimeofday implemention and optimized
clock_gettime(). The gettimeofday implementation is slightly faster than the one in the old vsyscall.clock_gettimeis significantly faster than the syscall forCLOCK_MONOTONICandCLOCK_REALTIME.The new calls are generally faster than the old vsyscall.
TBD: add new benchmarks
Advantages over the old x86-64 vsyscalls:
- Extensible
- Randomized
- Cleaner
- Easier to virtualize (the old static address range previously causes overhead e.g. for Xen because it has to create special page tables for it)Weak points:
- glibc support still to be writtenThe VM interface is partly based on Ingo Molnar's i386 version.
Signed-off-by Andi Kleen <[email protected]>--- Documentation/kernel-parameters.txt | 2 arch/x86_64/Makefile | 3 arch/x86_64/ia32/ia32_binfmt.c | 1 arch/x86_64/kernel/time.c | 1 arch/x86_64/kernel/vmlinux.lds.S | 12 +++ arch/x86_64/kernel/vsyscall.c | 22 +---- arch/x86_64/mm/init.c | 17 ++++ arch/x86_64/vdso/Makefile | 49 ++++++++++++ arch/x86_64/vdso/vclock_gettime.c | 120 +++++++++++++++++++++++++++++++ arch/x86_64/vdso/vdso-note.S | 25 ++++++ arch/x86_64/vdso/vdso-start.S | 2 arch/x86_64/vdso/vdso.S | 2 arch/x86_64/vdso/vdso.lds.S | 77 ++++++++++++++++++++ arch/x86_64/vdso/vextern.h | 16 ++++ arch/x86_64/vdso/vgetcpu.c | 50 +++++++++++++ arch/x86_64/vdso/vma.c | 137 ++++++++++++++++++++++++++++++++++++ arch/x86_64/vdso/voffset.h | 1 arch/x86_64/vdso/vvar.c | 12 +++ include/asm-x86_64/auxvec.h | 2 include/asm-x86_64/elf.h | 13 +++ include/asm-x86_64/mmu.h | 1 include/asm-x86_64/pgtable.h | 8 +- include/asm-x86_64/vgtod.h | 29 +++++++ include/asm-x86_64/vsyscall.h | 3 24 files changed, 583 insertions(+), 22 deletions(-)Index:
linux/arch/x86_64/ia32/ia32_binfmt.c
===================================================================arch/x86_64/ia32/ia32_binfmt.c +1
-0@@ -38,6 +38,7 @@int sysctl_vsyscall32 =1 ; +#undef ARCH_DLINFO#define ARCH_DLINFO do { \ if (sysctl_vsyscall32) { \ NEW_AUX_ENT(AT_SYSINFO, (u32)(u64)VSYSCALL32_VSYSCALL); \Index:
linux/arch/x86_64/kernel/vmlinux.lds.S
===================================================================arch/x86_64/kernel/vmlinux.lds.S +12
-0@@ -94,6 +94,9 @@ SECTIONS .vsyscall_gtod_data : AT(VLOAD(.vsyscall_gtod_data)) { *(.vsyscall_gtod_data) } vsyscall_gtod_data = VVIRT(.vsyscall_gtod_data); + .vsyscall_clock : AT(VLOAD(.vsyscall_clock)) + { *(.vsyscall_clock) } + vsyscall_clock = VVIRT(.vsyscall_clock); .vsyscall_1 ADDR(.vsyscall_0) + 1024: AT(VLOAD(.vsyscall_1))@@ -153,6 +156,8 @@ SECTIONS . = ALIGN(4096); /* Init code and data */ __init_begin = .; + + .init.text : AT(ADDR(.init.text) - LOAD_OFFSET) { _sinittext = .; *(.init.text)@@ -190,6 +195,12 @@ SECTIONS .exit.text : AT(ADDR(.exit.text) - LOAD_OFFSET) { *(.exit.text) } .exit.data : AT(ADDR(.exit.data) - LOAD_OFFSET) { *(.exit.data) } +/* vdso blob that is mapped into user space */ + vdso_start = . ; + .vdso : AT(ADDR(.vdso) - LOAD_OFFSET) { *(.vdso) } + . = ALIGN(4096); + vdso_end = .; + #ifdef CONFIG_BLK_DEV_INITRD . = ALIGN(4096); __initramfs_start = .;@@ -202,6 +213,7 @@ SECTIONS .data.percpu : AT(ADDR(.data.percpu) - LOAD_OFFSET) { *(.data.percpu) } __per_cpu_end = .; . = ALIGN(4096); + __init_end = .; . = ALIGN(4096);Index:
linux/arch/x86_64/mm/init.c
===================================================================arch/x86_64/mm/init.c +17
-0@@ -159,6 +159,14 @@ static __init void set_pte_phys(unsigned__flush_tlb_one (vaddr); } +void __init +set_kernel_map (void *vaddr,unsigned long len,unsigned long phys,pgprot_t prot) +{ +void *end = vaddr +ALIGN (len,PAGE_SIZE ); +for (; vaddr < end; vaddr +=PAGE_SIZE , phys +=PAGE_SIZE ) +set_pte_phys ((unsigned long )vaddr, phys, prot); +} +/* NOTE: this is meant to be run only at boot */ void __init __set_fixmap (enum fixed_addresses idx,unsigned long phys,pgprot_t prot)@@ -756,3 +764,12 @@ int in_gate_area_no_task(unsigned long a {return (addr >=VSYSCALL_START ) && (addr <VSYSCALL_END ); } + +const char *arch_vma_name (struct vm_area_struct *vma) +{ +if (vma->vm_mm && vma->vm_start == (long )vma->vm_mm->context.vdso) +return "[vdso]" ; +if (vma == &gate_vma) +return "[vsyscall]" ; +return NULL ; +}Index:
linux/arch/x86_64/vdso/vdso-note.S
===================================================================
arch/x86_64/vdso/vdso-note.S line 9
Quoted 9 lines
arch/x86_64/vdso/vdso-note.S new file +9
-0@@ -0,0 +1,25 @@ +/* + * This supplies .note.* sections to go into the PT_NOTE inside the vDSO text. + * Here we can supply some information useful to userland. + */ + +#include <linux/uts.h> +#include <linux/version.h> + +#define ASM_ELF_NOTE_BEGIN(name, flags, vendor, type) \
Use linux/elfnote.h?
J
Re: [PATCH] [8/30] x86_64: Add vDSO for x86-64 with gettimeofday/clock_gettime/getcpu
Quoted 2 lines
Use
linux/elfnote.h?
Good point. Will fix. I just copied it from i386, but it probably should be there fixed too.
Actually they are not completely equivalent because the old macro generates the section name differently from the name in the payload (kernelversion, Linux). But I split that up into two notes now.
If that is done on i386 it might break gdb reading core files though?
BTW if anybody noticed the patch also contained a few dead hunks (two unused functions/ prototypes and some white space change). These are already gone now too.
-Andi
Re: [PATCH] [8/30] x86_64: Add vDSO for x86-64 with gettimeofday/clock_gettime/getcpu
Quoted 6 lines · Andi Kleen
Quoted 2 lines
Use
linux/elfnote.h?Good point. Will fix. I just copied it from i386, but it probably should be there fixed too.
Already has been. I posted a patch a day or so ago (reposted below).
Quoted 4 lines
Actually they are not completely equivalent because the old macro generates the section name differently from the name in the payload (kernelversion, Linux). But I split that up into two notes now.
Roland agreed that it doesn't matter.
Quoted 2 lines
If that is done on i386 it might break gdb reading core files though?
No. The notename in the final output is the same either way. The linker packs .note.* into a single .note section.
Subject: use elfnote.h to generate vsyscall notes.
Use existing elfnote.h to generate vsyscall notes, rather than doing it locally. Changes elfnote.h a bit to suite, since this is the first asm user, and it wasn't quite right.
--- arch/i386/kernel/vsyscall-note.S | 23 ++++++----------------- include/linux/elfnote.h | 18 +++++++++++++----- 2 files changed, 19 insertions(+), 22 deletions(-)
===================================================================
arch/i386/kernel/vsyscall-note.S +6 -17
@@ -3,23 +3,12 @@ * Here we can supply some information useful to userland. */ -#include <linux/uts.h> #include <linux/version.h> +#include <linux/elfnote.h> -#define ASM_ELF_NOTE_BEGIN(name, flags, vendor, type) \ - .section name, flags; \ - .balign 4; \ - .long 1f - 0f; /* name length */ \ - .long 3f - 2f; /* data length */ \ - .long type; /* note type */ \ -0: .asciz vendor; /* vendor name */ \ -1: .balign 4; \ -2: - -#define ASM_ELF_NOTE_END \ -3: .balign 4; /* pad out section */ \ - .previous - - ASM_ELF_NOTE_BEGIN(".note.kernel-version", "a", UTS_SYSNAME, 0) +/* Ideally this would use UTS_NAME, but using a quoted string here + doesn't work. Remember to change this when changing the + kernel's name. */ +ELFNOTE_START(Linux, 0, "a") .long LINUX_VERSION_CODE - ASM_ELF_NOTE_END +ELFNOTE_END
===================================================================
include/linux/elfnote.h +13 -5
@@ -38,17 +38,25 @@* e.g. ELFNOTE(XYZCo, 42, .asciz, "forty-two") * ELFNOTE(XYZCo, 12, .long, 0xdeadbeef) */ -#define ELFNOTE(name, type, desctype, descdata) \ -.pushsection .note.name, "",@note ; \ +#define ELFNOTE_START(name, type, flags) \ +.pushsection .note.name, flags,@note ; \ .align 4 ; \ .long 2f - 1f /* namesz */ ; \ - .long 4f - 3f /* descsz */ ; \ + .long 4484f - 3f /* descsz */ ; \ .long type ; \ 1:.asciz #name ; \ 2:.align 4 ; \ -3:desctype descdata ; \ -4:.align 4 ; \ +3: + +#define ELFNOTE_END \ +4484:.align 4 ; \ .popsection ; + +#define ELFNOTE (name, type, desc) \ + ELFNOTE_START(name, type, "") \ + desc ; \ + ELFNOTE_END +#else /* !__ASSEMBLER__ */ #include <linux/elf.h> /*
J
PATCH 9/30 x86_64: Use symbolic CPU features in early CPUID check
In reply to Andi KleenDead to magic numbers!
Generated code is the same.
--- arch/x86_64/kernel/verify_cpu.S | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-)
arch/x86_64/kernel/verify_cpu.S +16 -7
@@ -30,18 +30,27 @@ * appropriately. Either display a message or halt. */ -verify_cpu: +#include <asm/cpufeature.h> +verify_cpu: pushfl # Save caller passed flags pushl $0 # Kill any dangerous flags popfl - /* minimum CPUID flags for x86-64 */ - /* see http://www.x86-64.org/lists/discuss/msg02971.html */ -#define SSE_MASK ((1<<25)|(1<<26)) -#define REQUIRED_MASK1 ((1<<0)|(1<<3)|(1<<4)|(1<<5)|(1<<6)|(1<<8)|\ - (1<<13)|(1<<15)|(1<<24)) -#define REQUIRED_MASK2 (1<<29) + /* minimum CPUID flags for x86-64 as defined by AMD */ +#define M(x) (1<<(x)) +#define M2(a,b) M(a)|M(b) +#define M4(a,b,c,d) M(a)|M(b)|M(c)|M(d) + +#define SSE_MASK \ + (M2(X86_FEATURE_XMM,X86_FEATURE_XMM2)) +#define REQUIRED_MASK1 \ + (M4(X86_FEATURE_FPU,X86_FEATURE_PSE,X86_FEATURE_TSC,X86_FEATURE_MSR)|\ + M4(X86_FEATURE_PAE,X86_FEATURE_CX8,X86_FEATURE_PGE,X86_FEATURE_CMOV)|\ + M(X86_FEATURE_FXSR)) +#define REQUIRED_MASK2 \ + (M(X86_FEATURE_LM - 32)) + pushfl # standard way to check for cpuid popl %eax movl %eax,%ebx
PATCH 10/30 x86_64: Drop -traditional for arch/x86_64/boot
In reply to Andi KleenFollows i386 and useful cleanup.
--- arch/x86_64/boot/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86_64/boot/Makefile +1 -1
@@ -36,7 +36,7 @@ subdir- := compressed/ #Let make clean # --------------------------------------------------------------------------- $(obj)/bzImage: IMAGE_OFFSET := 0x100000 -$(obj)/bzImage: EXTRA_AFLAGS := -traditional $(SVGA_MODE) $(RAMDISK) -D__BIG_KERNEL__ +$(obj)/bzImage: EXTRA_AFLAGS := $(SVGA_MODE) $(RAMDISK) -D__BIG_KERNEL__ $(obj)/bzImage: BUILDFLAGS := -b quiet_cmd_image = BUILD $@
PATCH 11/30 i386: Drop -traditional in arch/i386/boot
In reply to Andi KleenNeeded for followon patch
--- arch/i386/boot/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/i386/boot/Makefile +2 -2
@@ -36,9 +36,9 @@ HOSTCFLAGS_build.o := $(LINUXINCLUDE) # --------------------------------------------------------------------------- $(obj)/zImage: IMAGE_OFFSET := 0x1000 -$(obj)/zImage: EXTRA_AFLAGS := -traditional $(SVGA_MODE) $(RAMDISK) +$(obj)/zImage: EXTRA_AFLAGS := $(SVGA_MODE) $(RAMDISK) $(obj)/bzImage: IMAGE_OFFSET := 0x100000 -$(obj)/bzImage: EXTRA_AFLAGS := -traditional $(SVGA_MODE) $(RAMDISK) -D__BIG_KERNEL__ +$(obj)/bzImage: EXTRA_AFLAGS := $(SVGA_MODE) $(RAMDISK) -D__BIG_KERNEL__ $(obj)/bzImage: BUILDFLAGS := -b quiet_cmd_image = BUILD $@
PATCH 12/30 i386: Verify important CPUID bits in real mode
In reply to Andi KleenCheck some CPUID bits that are needed for compiler generated early in boot. When the system is still in real mode before changing the VESA BIOS mode it is possible to still display an visible error message on the screen.
Similar to x86-64.
Includes cleanups from Eric Biederman
--- arch/i386/Kconfig.cpu | 22 ++++++++++- arch/i386/boot/setup.S | 17 ++++++++ arch/i386/kernel/verify_cpu.S | 68 +++++++++++++++++++++++++++++++++++ include/asm-i386/cpufeature.h | 3 + include/asm-i386/required-features.h | 34 +++++++++++++++++ 5 files changed, 142 insertions(+), 2 deletions(-)
arch/i386/kernel/verify_cpu.S new file +65 -0
@@ -0,0 +1,65 @@ +/* Check if CPU has some minimum CPUID bits + This runs in 16bit mode so that the caller can still use the BIOS + to output errors on the screen */ +#include <asm/cpufeature.h> + +verify_cpu: + pushfl # Save caller passed flags + pushl $0 # Kill any dangerous flags + popfl + +#if CONFIG_X86_MINIMUM_CPU_MODEL >= 4 + pushfl + orl $(1<<18),(%esp) # try setting AC + popfl + pushfl + popl %eax + testl $(1<<18),%eax + jz bad +#endif +#if REQUIRED_MASK1 != 0 + pushfl # standard way to check for cpuid + popl %eax + movl %eax,%ebx + xorl $0x200000,%eax + pushl %eax + popfl + pushfl + popl %eax + cmpl %eax,%ebx + pushfl # standard way to check for cpuid + popl %eax + movl %eax,%ebx + xorl $0x200000,%eax + pushl %eax + popfl + pushfl + popl %eax + cmpl %eax,%ebx + jz bad # REQUIRED_MASK1 != 0 requires CPUID + + movl $0x0,%eax # See if cpuid 1 is implemented + cpuid + cmpl $0x1,%eax + jb bad # no cpuid 1 + + movl $0x1,%eax # Does the cpu have what it takes + cpuid + +#if CONFIG_X86_MINIMUM_CPU_MODEL > 4 +#error add proper model checking here +#endif + + andl $REQUIRED_MASK1,%edx + xorl $REQUIRED_MASK1,%edx + jnz bad +#endif /* REQUIRED_MASK1 */ + + popfl + xor %eax,%eax + ret + +bad: + popfl + movl $1,%eax + ret
arch/i386/Kconfig.cpu +20 -2
@@ -240,14 +240,19 @@ config X86_L1_CACHE_SHIFT default "5" if MWINCHIP3D || MWINCHIP2 || MWINCHIPC6 || MCRUSOE || MEFFICEON || MCYRIXIII || MK6 || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || M586 || MVIAC3_2 || MGEODE_LX default "6" if MK7 || MK8 || MPENTIUMM || MCORE2 || MVIAC7 +config X86_XADD + bool + depends on !M386 + default y + config RWSEM_GENERIC_SPINLOCK bool - depends on M386 + depends on !X86_XADD default y config RWSEM_XCHGADD_ALGORITHM bool - depends on !M386 + depends on X86_XADD default y config ARCH_HAS_ILOG2_U32
@@ -331,3 +336,16 @@ config X86_TSC bool depends on (MWINCHIP3D || MWINCHIP2 || MCRUSOE || MEFFICEON || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || M586MMX || M586TSC || MK8 || MVIAC3_2 || MVIAC7 || MGEODEGX1 || MGEODE_LX || MCORE2) && !X86_NUMAQ default y + +# this should be set for all -march=.. options where the compiler +# generates cmov. +config X86_CMOV + bool + depends on (MK7 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MVIAC3_2 || MVIAC7) + default y + +config X86_MINIMUM_CPU_MODEL + int + default "4" if X86_XADD || X86_CMPXCHG || X86_BSWAP + default "0" +
arch/i386/boot/setup.S +17 -0
@@ -302,7 +302,24 @@ good_sig: loader_panic_mess: .string "Wrong loader, giving up..." +# check minimum cpuid +# we do this here because it is the last place we can actually +# show a user visible error message. Later the video modus +# might be already messed up. loader_ok: + call verify_cpu + testl %eax,%eax + jz cpu_ok + lea cpu_panic_mess,%si + call prtstr +1: jmp 1b + +cpu_panic_mess: + .asciz "PANIC: CPU too old for this kernel." + +#include "../kernel/verify_cpu.S" + +cpu_ok: # Get memory size (extended mem, kB) xorl %eax, %eax
include/asm-i386/cpufeature.h +3 -0
@@ -7,7 +7,10 @@#ifndef __ASM_I386_CPUFEATURE_H#define __ASM_I386_CPUFEATURE_H +#ifndef __ASSEMBLY__#include <linux/bitops.h> +#endif +#include <asm/required-features.h> #define NCAPINTS 7/* N 32-bit words worth of info */
include/asm-i386/required-features.h new file +34 -0
@@ -0,0 +1,34 @@ +#ifndef _ASM_REQUIRED_FEATURES_H +#define _ASM_REQUIRED_FEATURES_H 1 + +/* Define minimum CPUID feature set for kernel These bits are checked +really early to actually display a visible error message before the +kernel dies. Only add word 0 bits here + +Some requirements that are not in CPUID yet are also in the +CONFIG_X86_MINIMUM_CPU mode which is checked too. + +The real information is in arch/i386/Kconfig.cpu, this just converts +the CONFIGs into a bitmask */ + +#ifdef CONFIG_X86_PAE +#define NEED_PAE (1<<X86_FEATURE_PAE) +#else +#define NEED_PAE 0 +#endif + +#ifdef CONFIG_X86_CMOV +#define NEED_CMOV (1<<X86_FEATURE_CMOV) +#else +#define NEED_CMOV 0 +#endif + +#ifdef CONFIG_X86_CMPXCHG64 +#define NEED_CMPXCHG64 (1<<X86_FEATURE_CX8) +#else +#define NEED_CMPXCHG64 0 +#endif + +#define REQUIRED_MASK1 (NEED_PAE|NEED_CMOV|NEED_CMPXCHG64) + +#endif
PATCH 13/30 i386: Evaluate constant cpu features at runtime
In reply to Andi KleenRedefine cpu_has() to evaluate cpu features already checked in early boot at compile time. This way the compiler might eliminate some dead code.
--- include/asm-i386/cpufeature.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
include/asm-i386/cpufeature.h +6 -2
@@ -106,8 +106,12 @@#define X86_FEATURE_LAHF_LM (6*32+ 0)/* LAHF/SAHF in long mode */ #define X86_FEATURE_CMP_LEGACY (6*32+ 1)/* If yes HyperThreading not valid */ -#define cpu_has (c, bit) test_bit(bit, (c)->x86_capability) -#define boot_cpu_has (bit) test_bit(bit, boot_cpu_data.x86_capability) +#define cpu_has (c, bit) \ + ((__builtin_constant_p(bit) && (bit) < 32 && \ + (1UL << (bit)) & REQUIRED_MASK1) ? \ + 1 : \ + test_bit(bit, (c)->x86_capability)) +#define boot_cpu_has (bit) cpu_has(&boot_cpu_data, bit)#define cpu_has_fpu boot_cpu_has(X86_FEATURE_FPU)#define cpu_has_vme boot_cpu_has(X86_FEATURE_VME)
PATCH 14/30 i386: Implement alternative_io for i386
In reply to Andi KleenPorted from x86-64.
--- include/asm-i386/alternative.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
include/asm-i386/alternative.h +15 -0
@@ -82,6 +82,21 @@ static inline void alternatives_smp_swit "663:\n\t" newinstr "\n664:\n" /* replacement */\ ".previous" :: "i" (feature), ##input) +/* Like alternative_input, but with a single output argument */ +#define alternative_io(oldinstr, newinstr, feature, output, input...) \ + asm volatile ("661:\n\t" oldinstr "\n662:\n" \ + ".section .altinstructions,\"a\"\n" \ + " .align 4\n" \ + " .long 661b\n"/* label */ \ +" .long 663f\n" /* new instruction */ \ +" .byte %c[feat]\n" /* feature bit */ \ +" .byte 662b-661b\n" /* sourcelen */ \ +" .byte 664f-663f\n" /* replacementlen */ \ +".previous\n" \ +".section .altinstr_replacement,\"ax\"\n" \ +"663:\n\t" newinstr"\n664:\n" /* replacement */ \ + ".previous" : output : [feat] "i" (feature), ##input) +/* * Alternative inline assembly for SMP. *
PATCH 15/30 i386: Implement X86_FEATURE_SYNC_RDTSC on i386
In reply to Andi KleenSyncs up with x86-64.
--- arch/i386/kernel/cpu/intel.c | 4 +++- include/asm-i386/cpufeature.h | 1 + include/asm-i386/tsc.h | 4 ---- 3 files changed, 4 insertions(+), 5 deletions(-)
arch/i386/kernel/cpu/intel.c +3 -1
@@ -188,8 +188,10 @@ static void __cpuinit init_intel(struct }#endif -if (c->x86 ==15 ) +if (c->x86 ==15 ) {set_bit (X86_FEATURE_P4 , c->x86_capability); +set_bit (X86_FEATURE_SYNC_RDTSC , c->x86_capability); + }if (c->x86 ==6 )set_bit (X86_FEATURE_P3 , c->x86_capability); if ((c->x86 == 0xf && c->x86_model >= 0x03) ||
include/asm-i386/cpufeature.h +1 -0
@@ -79,6 +79,7 @@#define X86_FEATURE_PEBS (3*32+12)/* Precise-Event Based Sampling */ #define X86_FEATURE_BTS (3*32+13)/* Branch Trace Store */ #define X86_FEATURE_LAPIC_TIMER_BROKEN (3*32+ 14)/* lapic timer broken in C1 */ +#define X86_FEATURE_SYNC_RDTSC (3*32+15)/* RDTSC synchronizes the CPU */ /* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */ #define X86_FEATURE_XMM3 (4*32+ 0)/* Streaming SIMD Extensions-3 */
include/asm-i386/tsc.h +0 -4
@@ -35,7 +35,6 @@ static inline cycles_t get_cycles(void) static __always_inline cycles_t get_cycles_sync(void) {unsigned long long ret; -#ifdef X86_FEATURE_SYNC_RDTSC unsigned eax;/*
@@ -44,9 +43,6 @@ static __always_inline cycles_t get_cycl*/ alternative_io ("cpuid" ,ASM_NOP2 ,X86_FEATURE_SYNC_RDTSC , "=a" (eax), "0" (1) : "ebx","ecx","edx","memory"); -#else -sync_core (); -#endif rdtscll (ret);return ret;
PATCH 16/30 i386: Add X86_FEATURE_RDTSCP
In reply to Andi KleenFollowing x86-64
--- include/asm-i386/cpufeature.h | 1 + 1 file changed, 1 insertion(+)
include/asm-i386/cpufeature.h +1 -0
@@ -52,6 +52,7 @@#define X86_FEATURE_MP (1*32+19)/* MP Capable. */ #define X86_FEATURE_NX (1*32+20)/* Execute Disable */ #define X86_FEATURE_MMXEXT (1*32+22)/* AMD MMX extensions */ +#define X86_FEATURE_RDTSCP (1*32+27)/* RDTSCP */ #define X86_FEATURE_LM (1*32+29)/* Long Mode (x86-64) */ #define X86_FEATURE_3DNOWEXT (1*32+30)/* AMD 3DNow! extensions */ #define X86_FEATURE_3DNOW (1*32+31)/* 3DNow! */
PATCH 17/30 x86: Use RDTSCP for synchronous get_cycles if possible
In reply to Andi KleenRDTSCP is already synchronous and doesn't need an explicit CPUID. This is a little faster and more importantly avoids VMEXITs on Hypervisors.
Original patch from Joerg Roedel, but reworked by AK Also includes miscompilation fix by Eric Biederman
--- include/asm-i386/tsc.h | 9 +++++++++ 1 file changed, 9 insertions(+)
include/asm-i386/tsc.h +9 -0
@@ -38,6 +38,15 @@ static __always_inline cycles_t get_cyclunsigned eax;/* +* Use RDTSCP if possible; it is guaranteed to be synchronous +* and doesn't cause a VMEXIT on Hypervisors +*/ +alternative_io (ASM_NOP3 ,".byte 0x0f,0x01,0xf9" ,X86_FEATURE_RDTSCP , + "=A" (ret), "0" (0ULL) : "ecx", "memory"); +if (ret) +return ret; + +/* * Don't do an additional sync on CPUs where we know * RDTSC is already synchronous: */
PATCH 18/30 x86_64: Don't enable NUMA for a single node in K8 NUMA scanning
In reply to Andi KleenThis was supposed to see the full memory on a ASUS A8SX motherboard with 4GB RAM where the northbridge reports less memory, but it didn't help there. But it's a reasonable change so let's include it anyways.
--- arch/x86_64/mm/k8topology.c | 2 ++ 1 file changed, 2 insertions(+)
arch/x86_64/mm/k8topology.c +2 -0
@@ -62,6 +62,8 @@ int __init k8_scan_nodes(unsigned long s reg =read_pci_config (0 , nb,0 ,0x60 ); numnodes = ((reg >>4 ) &0xF ) +1 ; +if (numnodes <=1 ) +return -1 ;printk (KERN_INFO "Number of nodes %d\n" , numnodes);
PATCH 19/30 i386: Little cleanups in smpboot.c
In reply to Andi Kleen- Remove #if that is always set
- Fix warning
--- arch/i386/kernel/smpboot.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
arch/i386/kernel/smpboot.c +1 -3
@@ -516,7 +516,6 @@ static void unmap_cpu_to_logical_apicid(unmap_cpu_to_node (cpu); } -#if APIC_DEBUG static inline void __inquire_remote_apic (int apicid) {int i, regs[] = {APIC_ID >>4 ,APIC_LVR >>4 ,APIC_SPIV >>4 };
@@ -548,14 +547,13 @@ static inline void __inquire_remote_apicswitch (status) {case APIC_ICR_RR_VALID : status =apic_read (APIC_RRR ); -printk ("%08x\n" , status); +printk ("%lx\n" , status);break ;default :printk ("failed\n" ); } } } -#endif #ifdef WAKE_SECONDARY_VIA_NMI /*
PATCH 20/30 i386: Remove copy_*_user BUG_ONs for (size < 0)
In reply to Andi Kleenaccess_ok checks this case anyways, no need to check twice.
--- arch/i386/lib/usercopy.c | 7 ------- 1 file changed, 7 deletions(-)
arch/i386/lib/usercopy.c +0 -7
@@ -716,7 +716,6 @@ do { \unsigned long __copy_to_user_ll (void __user *to,const void *from,unsigned long n) { -BUG_ON ((long ) n <0 );#ifndef CONFIG_X86_WP_WORKS_OK if (unlikely (boot_cpu_data.wp_works_ok ==0 ) && ((unsigned long )to) <TASK_SIZE ) {
@@ -785,7 +784,6 @@ EXPORT_SYMBOL(__copy_to_user_ll);unsigned long __copy_from_user_ll (void *to,const void __user *from,unsigned long n) { -BUG_ON ((long )n <0 );if (movsl_is_ok (to, from, n))__copy_user_zeroing (to, from, n);else
@@ -797,7 +795,6 @@ EXPORT_SYMBOL(__copy_from_user_ll);unsigned long __copy_from_user_ll_nozero (void *to,const void __user *from,unsigned long n) { -BUG_ON ((long )n <0 );if (movsl_is_ok (to, from, n))__copy_user (to, from, n);else
@@ -810,7 +807,6 @@ EXPORT_SYMBOL(__copy_from_user_ll_nozerounsigned long __copy_from_user_ll_nocache (void *to,const void __user *from,unsigned long n) { -BUG_ON ((long )n <0 );#ifdef CONFIG_X86_INTEL_USERCOPY if ( n >64 && cpu_has_xmm2) n =__copy_user_zeroing_intel_nocache (to, from, n);
@@ -825,7 +821,6 @@ unsigned long __copy_from_user_ll_nocachunsigned long __copy_from_user_ll_nocache_nozero (void *to,const void __user *from,unsigned long n) { -BUG_ON ((long )n <0 );#ifdef CONFIG_X86_INTEL_USERCOPY if ( n >64 && cpu_has_xmm2) n =__copy_user_intel_nocache (to, from, n);
@@ -853,7 +848,6 @@ unsigned long __copy_from_user_ll_nocachunsigned long copy_to_user (void __user *to,const void *from,unsigned long n) { -BUG_ON ((long ) n <0 );if (access_ok (VERIFY_WRITE , to, n)) n =__copy_to_user (to, from, n);return n;
@@ -879,7 +873,6 @@ EXPORT_SYMBOL(copy_to_user);unsigned long copy_from_user (void *to,const void __user *from,unsigned long n) { -BUG_ON ((long ) n <0 );if (access_ok (VERIFY_READ , from, n)) n =__copy_from_user (to, from, n);else
PATCH 21/30 x86_64: Print type and size correctly for unknown compat ioctls
In reply to Andi Kleen--- fs/compat.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
fs/compat.c +3 -2
@@ -371,13 +371,14 @@ static void compat_ioctl_error(struct fi fn ="?" ; } -sprintf (buf,"'%c'" , (cmd>>24 ) &0x3f ); +sprintf (buf,"'%c'" , (cmd>>_IOC_TYPESHIFT) & _IOC_TYPEMASK);if (!isprint (buf[1 ]))sprintf (buf,"%02x" , buf[1 ]);compat_printk ("ioctl32(%s:%d): Unknown cmd fd(%d) " -"cmd(%08x){%s} arg(%08x) on %s\n" , +"cmd(%08x){t:%s;sz:%u} arg(%08x) on %s\n" , current->comm, current->pid, (int )fd, (unsigned int )cmd, buf, + (cmd >> _IOC_SIZESHIFT) & _IOC_SIZEMASK, (unsigned int )arg, fn);if (path)
PATCH 22/30 x86_64: Remove CONFIG_REORDER
In reply to Andi KleenThe option never worked well and functionlist wasn't well maintained. Also it made the build very slow on many binutils version.
So just remove it.
--- arch/x86_64/Kconfig | 8 arch/x86_64/Makefile | 1 arch/x86_64/kernel/functionlist | 1284 --------------------------------------- arch/x86_64/kernel/vmlinux.lds.S | 3 4 files changed, 1296 deletions(-)
arch/x86_64/Kconfig +0 -8
@@ -660,14 +660,6 @@ config CC_STACKPROTECTOR_ALL source kernel/Kconfig.hz -config REORDER - bool "Function reordering" - default n - help - This option enables the toolchain to reorder functions for a more - optimal TLB usage. If you have pretty much any version of binutils, - this can increase your kernel build time by roughly one minute. - config K8_NB def_bool y depends on AGP_AMD64 || IOMMU || (PCI && NUMA)
arch/x86_64/Makefile +0 -1
@@ -40,7 +40,6 @@ cflags-y += -m64 cflags-y += -mno-red-zone cflags-y += -mcmodel=kernel cflags-y += -pipe -cflags-kernel-$(CONFIG_REORDER) += -ffunction-sections cflags-y += -Wno-sign-compare cflags-y += -fno-asynchronous-unwind-tables ifneq ($(CONFIG_DEBUG_INFO),y)
arch/x86_64/kernel/functionlist deleted +0 -1284
1,284 lines not on this page · raw message
arch/x86_64/kernel/vmlinux.lds.S +0 -3
@@ -30,9 +30,6 @@ SECTIONS /* First the code that has to be first for bootstrapping */ *(.bootstrap.text) _stext = .; - /* Then all the functions that are "hot" in profiles, to group them - onto the same hugetlb entry */ - #include "functionlist" /* Then the rest */ *(.text) SCHED_TEXT
PATCH 23/30 x86_64: Share identical video.S between i386 and x86-64
In reply to Andi Kleen--- arch/x86_64/boot/setup.S | 2 arch/x86_64/boot/video.S | 2043 ----------------------------------------------- 2 files changed, 1 insertion(+), 2044 deletions(-)
arch/x86_64/boot/setup.S +1 -1
@@ -807,7 +807,7 @@ gdt_48: # Include video setup & detection code -#include "video.S" +#include "../../i386/boot/video.S" # Setup signature -- must be last setup_sig1: .word SIG1
arch/x86_64/boot/video.S deleted +0 -2043
2,043 lines not on this page · raw message
PATCH 24/30 x86_64: Shut up warnings for vfat compat ioctls on other file systems
In reply to Andi Kleenvfat implements compat handlers for these ioctls, but when they were executed on other file systems the kernel would still complain about an unknown compat ioctl. Just declare them as compatible and let them be rejected when not needed by the normal path.
This makes wine runs a lot quieter
--- fs/compat_ioctl.c | 9 +++++++++ 1 file changed, 9 insertions(+)
fs/compat_ioctl.c +9 -0
@@ -2627,6 +2627,15 @@ COMPATIBLE_IOCTL(LPRESET)/*LPGETSTATS not implemented, but no kernels seem to compile it in anyways*/ COMPATIBLE_IOCTL(LPGETFLAGS) HANDLE_IOCTL(LPSETTIMEOUT, lp_timeout_trans) + +/* fat 'r' ioctls. These are handled by fat with ->compat_ioctl, +but we don't want warnings on other file systems. So declare +them as compatible here. */ +#define VFAT_IOCTL_READDIR_BOTH32 _IOR('r', 1, struct compat_dirent[2]) +#define VFAT_IOCTL_READDIR_SHORT32 _IOR('r', 2, struct compat_dirent[2]) + +IGNORE_IOCTL(VFAT_IOCTL_READDIR_BOTH32) +IGNORE_IOCTL(VFAT_IOCTL_READDIR_SHORT32) };int ioctl_table_size =ARRAY_SIZE (ioctl_start);
Re: [PATCH] [24/30] x86_64: Shut up warnings for vfat compat ioctls on other file systems
Quoted 6 lines · Andi Kleen
vfat implements compat handlers for these ioctls, but when they were executed on other file systems the kernel would still complain about an unknown compat ioctl. Just declare them as compatible and let them be rejected when not needed by the normal path.
This makes wine runs a lot quieter
Does this also restore the original -ENOTTY return code?
The change that made it return -EINVAL broke a few Wine apps.
Re: [PATCH] [24/30] x86_64: Shut up warnings for vfat compat ioctls on other file systems
Quoted 11 lines · On Tuesday 01 May 2007 17:45:52 Chuck Ebbert wrote:
Quoted 6 lines · Andi Kleen
vfat implements compat handlers for these ioctls, but when they were executed on other file systems the kernel would still complain about an unknown compat ioctl. Just declare them as compatible and let them be rejected when not needed by the normal path.
This makes wine runs a lot quieter
Does this also restore the original
-ENOTTYreturn code?The change that made it return
-EINVALbroke a few Wine apps.
No it's still EINVAL as before. I just eliminated the printks.
I guess one could add a IGNORE_IOCTL_ENOTTY() or somesuch though if it's really a problem.
-Andi
PATCH 25/30 x86_64: Fix allnoconfig error in genapic_flat.c
In reply to Andi KleenFix:
In file included from include2/asm/apic.h:5,
from include2/asm/smp.h:15,
from linux/arch/x86_64/kernel/genapic_flat.c:18:linux/include/linux/pm.h: In function ‘call_platform_enable_wakeup’:linux/include/linux/pm.h:331: error: ‘EIO’ undeclared (first use in this function) linux/include/linux/pm.h:331: error: (Each undeclared identifier is reported only once linux/include/linux/pm.h:331: error: for each function it appears in.)
--- arch/x86_64/kernel/genapic_flat.c | 1 + 1 file changed, 1 insertion(+)
arch/x86_64/kernel/genapic_flat.c +1 -0
@@ -8,6 +8,7 @@* Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and * James Cleverdon. */ +#include <linux/errno.h> #include <linux/threads.h> #include <linux/cpumask.h> #include <linux/string.h>
PATCH 26/30 i386: Drop noisy e820 debugging printks
In reply to Andi Kleen--- arch/i386/kernel/e820.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-)
arch/i386/kernel/e820.c +2 -13
@@ -393,10 +393,8 @@ int __init sanitize_e820_map(struct e820____________________33__ ______________________4_ */ -printk ("sanitize start\n" );/* if there's only one memory region, don't bother */ if (*pnr_map <2 ) { -printk ("sanitize bail 0\n" );return -1 ; }
@@ -405,7 +403,6 @@ int __init sanitize_e820_map(struct e820/* bail out if we find any unreasonable addresses in bios map */ for (i=0 ; i<old_nr; i++)if (biosmap[i].addr + biosmap[i].size < biosmap[i].addr) { -printk ("sanitize bail 1\n" );return -1 ; }
@@ -501,7 +498,6 @@ int __init sanitize_e820_map(struct e820memcpy (biosmap, new_bios, new_nr*sizeof (struct e820entry )); *pnr_map = new_nr; -printk ("sanitize end\n" );return 0 ; }
@@ -532,7 +528,6 @@ int __init copy_e820_map(struct e820entrunsigned long long size = biosmap->size;unsigned long long end = start + size;unsigned long type = biosmap->type; -printk ("copy_e820_map() start: %016Lx size: %016Lx end: %016Lx type: %ld\n" , start, size, end, type);/* Overflow in 64 bits? Ignore the memory map. */ if (start > end)
@@ -543,17 +538,11 @@ int __init copy_e820_map(struct e820entr* Not right. Fix it up. */ if (type ==E820_RAM ) { -printk ("copy_e820_map() type is E820_RAM\n" );if (start <0x100000ULL && end >0xA0000ULL ) { -printk ("copy_e820_map() lies in range...\n" ); -if (start <0xA0000ULL ) { -printk ("copy_e820_map() start < 0xA0000ULL\n" ); +if (start <0xA0000ULL )add_memory_region (start,0xA0000ULL -start, type); - } -if (end <=0x100000ULL ) { -printk ("copy_e820_map() end <= 0x100000ULL\n" ); +if (end <=0x100000ULL )continue ; - } start =0x100000ULL ; size = end - start; }
PATCH 27/30 i386: white space fixes in i387.h
In reply to Andi KleenFrom: Jan Kiszka <[email protected]>
--- include/asm-i386/i387.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
include/asm-i386/i387.h +3 -3
@@ -83,8 +83,8 @@ static inline void __save_init_fpu( stru#define __clear_fpu ( tsk ) \ do { \ - if (task_thread_info(tsk)->status & TS_USEDFPU) { \ - asm volatile("fnclex ; fwait"); \ + if (task_thread_info(tsk)->status & TS_USEDFPU) { \ + asm volatile("fnclex ; fwait"); \ task_thread_info(tsk)->status &= ~TS_USEDFPU; \ stts(); \ } \
@@ -113,7 +113,7 @@ static inline void save_init_fpu( struct__clear_fpu ( tsk ); \preempt_enable (); \ }while (0 ) - \ +/* * FPU state interaction... */
PATCH 28/30 i386: avoid redundant preempt_disable in __unlazy_fpu
In reply to Andi KleenFrom: Jan Kiszka <[email protected]>
There are two callers of __unlazy_fpu, unlazy_fpu and __switch_to, and none of them appear to require additional preempt_disable/enable here. Let's open-code save_init_fpu in __unlazy_fpu to save a few ops.
--- include/asm-i386/i387.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
include/asm-i386/i387.h +6 -5
@@ -74,11 +74,12 @@ static inline void __save_init_fpu( strutask_thread_info (tsk)->status &= ~TS_USEDFPU ; } -#define __unlazy_fpu ( tsk ) do { \ - if (task_thread_info(tsk)->status & TS_USEDFPU) \ - save_init_fpu( tsk ); \ - else \ - tsk->fpu_counter = 0; \ +#define __unlazy_fpu ( tsk ) do { \ + if (task_thread_info(tsk)->status & TS_USEDFPU) { \ + __save_init_fpu(tsk); \ + stts(); \ + } else \ + tsk->fpu_counter = 0; \ } while (0)#define __clear_fpu ( tsk ) \
PATCH 29/30 x86_64: Don't exclude asm-offsets.c in Documentation/dontdiff
In reply to Andi Kleenasm-offsets.c is valid source code and needs to be diffed.
--- Documentation/dontdiff | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
Documentation/dontdiff +2 -2
@@ -55,8 +55,8 @@ aic7*seq.h* aicasm aicdb.h* asm -asm-offsets.* -asm_offsets.* +asm-offsets.h +asm_offsets.h autoconf.h* bbootsect bin2c
PATCH 30/30 x86_64: Add missing !X86_PAE dependincy to the 2G/2G split.
In reply to Andi KleenFrom: [email protected]
When in PAE mode we require that the user kernel divide to be on a 1G boundary. The 2G/2G split does not have that property so require !X86_PAE
--- arch/i386/Kconfig | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
arch/i386/Kconfig +1 -0
@@ -570,6 +570,7 @@ choice depends on !HIGHMEM bool "3G/1G user/kernel split (for full 1G low memory)" config VMSPLIT_2G + depends on !X86_PAE bool "2G/2G user/kernel split" config VMSPLIT_1G bool "1G/3G user/kernel split"
Signature · 1 line
1.5.1.1.181.g2de0
Re: [PATCH] [30/30] x86_64: Add missing !X86_PAE dependincy to the 2G/2G split.
Quoted 16 lines · Andi Kleen
From: [email protected]
When in PAE mode we require that the user kernel divide to be on a 1G boundary. The 2G/2G split does not have that property so require !X86_PAE
Signed-off-by Eric W. Biederman <[email protected]>--- arch/i386/Kconfig | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)arch/i386/Kconfig +0
-0
arch/i386/Kconfig choice · line 576
Quoted 7 lines
arch/i386/Kconfig +1
-0@@ -570,6 +570,7 @@ choice depends on !HIGHMEM bool "3G/1G user/kernel split (for full 1G low memory)" config VMSPLIT_2G + depends on !X86_PAE bool "2G/2G user/kernel split" config VMSPLIT_1G bool "1G/3G user/kernel split"
Hum... We lose a usefull 2G/2G split. Should'nt we use a patch to change PAGE_OFFSET to 0x8000000 instead of 0x78000000 and keep 2G/2G split ?
Maybe the following patch is better ?
[PATCH] i386 : Adjust CONFIG_PAGE_OFFSET in case of 2G/2G split and X86_PAE
When in PAE mode we require that the user kernel divide to be
on a 1G boundary. We must therefore make sure PAGE_OFFSET is correctlty defined in the 2G/2G split and PAE mode.
arch/i386/Kconfig +2 -1
@@ -578,7 +578,8 @@ endchoice config PAGE_OFFSET hex default 0xB0000000 if VMSPLIT_3G_OPT - default 0x78000000 if VMSPLIT_2G + default 0x78000000 if (VMSPLIT_2G && !X86_PAE) + default 0x80000000 if (VMSPLIT_2G && X86_PAE) default 0x40000000 if VMSPLIT_1G default 0xC0000000
Re: [PATCH] [30/30] x86_64: Add missing !X86_PAE dependincy to the 2G/2G split.
Quoted 12 lines · Eric Dumazet
Andi Kleen a ?crit :
Quoted 11 lines
From: [email protected]
When in PAE mode we require that the user kernel divide to be on a 1G boundary. The 2G/2G split does not have that property so require !X86_PAE
Signed-off-by Eric W. Biederman <[email protected]>---
arch/i386/Kconfig| 1 +1 files changed, 1 insertions(+), 0 deletions(-)
Quoted 15 lines
arch/i386/Kconfig choice · line 576
Quoted 12 lines
arch/i386/Kconfig +1
-0@@ -570,6 +570,7 @@ choice depends on !HIGHMEM bool "3G/1G user/kernel split (for full 1G low memory)" config VMSPLIT_2G + depends on !X86_PAE bool "2G/2G user/kernel split" config VMSPLIT_1G bool "1G/3G user/kernel split"Hum... We lose a usefull 2G/2G split. Should'nt we use a patch to change
PAGE_OFFSETto0x8000000instead of0x78000000and keep 2G/2G split ?
I dropped the patch for now.
Quoted 5 lines
[PATCH] i386 : Adjust
CONFIG_PAGE_OFFSETin case of 2G/2G split andX86_PAEWhen in PAE mode we require that the user kernel divide to be on a 1G boundary. We must therefore make sure
PAGE_OFFSETis correctlty defined in the 2G/2G split and PAE mode.
Looks reasonable. Did you test both cases? wli, ok for you too?
-Andi
Re: [PATCH] [30/30] x86_64: Add missing !X86_PAE dependincy to the 2G/2G split.
Quoted 2 lines · Eric Dumazet
Quoted 2 lines
Hum... We lose a usefull 2G/2G split. Should'nt we use a patch to change
PAGE_OFFSETto0x8000000instead of0x78000000and keep 2G/2G split ?
Quoted 1 line · Andi Kleen
I dropped the patch for now.
I'm more miffed about what it's cleaning up after than the patch itself.
Quoted 4 lines · Eric Dumazet
Quoted 4 lines
[PATCH] i386 : Adjust
CONFIG_PAGE_OFFSETin case of 2G/2G split andX86_PAEWhen in PAE mode we require that the user kernel divide to be on a 1G boundary. We must therefore make surePAGE_OFFSETis correctlty defined in the 2G/2G split and PAE mode.
Quoted 1 line · Andi Kleen
Looks reasonable. Did you test both cases? wli, ok for you too?
Sorry about the delay in replying.
I don't mind so long as we're not letting doorstop configs through. I'd probably do something more like
arch/i386/Kconfig +5 -1
@@ -571,6 +571,9 @@ bool "3G/1G user/kernel split (for full 1G low memory)" config VMSPLIT_2G bool "2G/2G user/kernel split" + config VMSPLIT_2G_OPT + depends on !HIGHMEM + bool "2G/2G user/kernel split (for full 2G low memory)" config VMSPLIT_1G bool "1G/3G user/kernel split" endchoice
@@ -578,7 +581,8 @@ config PAGE_OFFSET hex default 0xB0000000 if VMSPLIT_3G_OPT - default 0x78000000 if VMSPLIT_2G + default 0x80000000 if VMSPLIT_2G + default 0x78000000 if VMSPLIT_2G_OPT default 0x40000000 if VMSPLIT_1G default 0xC0000000
as a stopgap measure, but I'm not all that interested in grabbing patch credits where others could do it easily enough. Either of the config alterations is fine by me as they now stand; maybe Eric Dumazet might care to do something like my suggestion at some point.
My interest here is in approaches that aren't really centered around config options. Those are pmd handling for 1GB-unaligned PAGE_OFFSET in PAE and dynamic vmallocspace reservation, the latter of which is more complex than the first. I'd probably only do the pmd handling as it's much easier than dynamic vmallocspace, which does substantial violence to the core in order to reserve chunks of ZONE_NORMAL's virtualspace so that no boot-time virtualspace reservations need to be made for vmalloc(). Basically it would make vmalloc() proper use physically contiguous memory and vmap() fiddle with ZONE_NORMAL pagetables while reserving physical memory underlying the virtualspace reserved for vmap() so that it's no longer necessary to carve vmallocspace out of userspace to avoid highmem. That would occur at the cost of runtime memory footprint of the rarely-called vmap() and ZONE_NORMAL mapping updates. It would also alleviate pressure on vmallocspace in configurations where it would be severely limited.
I'm doing a bit of thinking about this laptop-avoiding-highmem problem. I've not come up with any better ideas than the dynamic vmallocspace approach to avoid ABI damage while avoiding both highmem and sacrificing memory for 1GB laptops, and slightly mitigating ABI damage for 2GB laptops' highmem avoidance efforts. I'm thinking the applicability isn't broad enough to merit the effort of dynamic vmallocspace. The pmd fixup for 1GB-unaligned splits is not such a big deal in comparison.
-- wli
Re: [PATCH] [30/30] x86_64: Add missing !X86_PAE dependincy to the 2G/2G split.
Quoted 28 lines · Bill Irwin
I don't mind so long as we're not letting doorstop configs through. I'd probably do something more like
Index: sched/arch/i386/Kconfig
===================================================================arch/i386/Kconfig +5
-1@@ -571,6 +571,9 @@ bool "3G/1G user/kernel split (for full 1G low memory)" config VMSPLIT_2G bool "2G/2G user/kernel split" + config VMSPLIT_2G_OPT + depends on !HIGHMEM + bool "2G/2G user/kernel split (for full 2G low memory)" config VMSPLIT_1G bool "1G/3G user/kernel split" endchoice@@ -578,7 +581,8 @@ config PAGE_OFFSET hex default 0xB0000000 if VMSPLIT_3G_OPT - default 0x78000000 if VMSPLIT_2G + default 0x80000000 if VMSPLIT_2G + default 0x78000000 if VMSPLIT_2G_OPT default 0x40000000 if VMSPLIT_1G default 0xC0000000
Quoted 1 line
as a stopgap measure, but I'm not all that interested in grabbing patch
..
Yup, I second that one. The idea of the original 2G split was to avoid the need for HIGHMEM entirely, reducing overhead on slower machines.
Having both kinds of splits is fine, but probably just the original one with the !PAE is okay too.
-ml
Re: [PATCH] [30/30] x86_64: Add missing !X86_PAE dependincy to the 2G/2G split.
In reply to Bill IrwinQuoted 46 lines · Bill Irwin
Quoted 1 line · Eric Dumazet
Quoted 1 line
Hum... We lose a usefull 2G/2G split. Should'nt we use a patch to change
PAGE_OFFSETto0x8000000instead of0x78000000and keep 2G/2G split ?Quoted 1 line · Andi Kleen
I dropped the patch for now.
I'm more miffed about what it's cleaning up after than the patch itself.
Quoted 3 lines · Eric Dumazet
Quoted 3 lines
[PATCH] i386 : Adjust
CONFIG_PAGE_OFFSETin case of 2G/2G split andX86_PAE
When in PAE mode we require that the user kernel divide to be
on a 1G boundary. We must therefore make surePAGE_OFFSETis correctlty defined in the 2G/2G split and PAE mode.Quoted 1 line · Andi Kleen
Looks reasonable. Did you test both cases? wli, ok for you too?
Sorry about the delay in replying.
I don't mind so long as we're not letting doorstop configs through. I'd probably do something more like
Index: sched/arch/i386/Kconfig
===================================================================arch/i386/Kconfig +5
-1@@ -571,6 +571,9 @@ bool "3G/1G user/kernel split (for full 1G low memory)" config VMSPLIT_2G bool "2G/2G user/kernel split" + config VMSPLIT_2G_OPT + depends on !HIGHMEM + bool "2G/2G user/kernel split (for full 2G low memory)" config VMSPLIT_1G bool "1G/3G user/kernel split" endchoice@@ -578,7 +581,8 @@ config PAGE_OFFSET hex default 0xB0000000 if VMSPLIT_3G_OPT - default 0x78000000 if VMSPLIT_2G + default 0x80000000 if VMSPLIT_2G + default 0x78000000 if VMSPLIT_2G_OPT default 0x40000000 if VMSPLIT_1G default 0xC0000000
Quoted 4 lines
as a stopgap measure, but I'm not all that interested in grabbing patch credits where others could do it easily enough. Either of the config alterations is fine by me as they now stand; maybe Eric Dumazet might care to do something like my suggestion at some point.
Your patch is very fine Bill, please resubmit it with proper Signed-off-by
My first patch was a trivial reaction to try to keep alive 2G/2G split, yours is better for fine tuning.
Thank you
Re: [PATCH] [30/30] x86_64: Add missing !X86_PAE dependincy to the 2G/2G split.
Quoted 4 lines · Bill Irwin
Quoted 4 lines
as a stopgap measure, but I'm not all that interested in grabbing patch credits where others could do it easily enough. Either of the config alterations is fine by me as they now stand; maybe Eric Dumazet might care to do something like my suggestion at some point.
Quoted 3 lines · Eric Dumazet
Your patch is very fine Bill, please resubmit it with proper Signed-off-by My first patch was a trivial reaction to try to keep alive 2G/2G split, yours is better for fine tuning.
I was hoping you would submit it as an update, but maybe adding your
Signed-off-by: to my own will do.
-- wli
Only 1GB-aligned kernel/user splits are now handled for PAE. The 2GB/2GB split attempts to avoid aliasing vmallocspace with the 1:1 mapping for physical memory by using an actual split of 1.875/2.125 to accommodate 128MB of vmallocspace out of what would otherwise be a full 2GB for userspace. That attempt disturbs the alignment required by PAE for 2GB/2GB splits, and furthermore does not provide a 2GB/2GB split as advertised.
This patch resolves the issues here in two manners. The first is by providing a true 2GB/2GB split in addition to the 1.875/2.125 split. The second is by renaming the 1.875/2.125 split to CONFIG_VMSPLIT_2G_OPT analogously to CONFIG_VMSPLIT_3G_OPT, which performs a similar manuever to avoid aliasing vmallocspace with the 1:1 mapping for physical memory around the 3GB boundary. With the 1.875/2.125 split properly-named, its config option is then tagged as depending on !HIGHMEM to express the PAE implementation's current inability to deal with such unaligned splits.
This patch is essentially a combination of two patches, one written by Eric Biederman and the other by Eric Dumazet. If they could add their Signed-off-by: to this, I'd be much obliged.
arch/i386/Kconfig +5 -1
@@ -571,6 +571,9 @@ bool "3G/1G user/kernel split (for full 1G low memory)" config VMSPLIT_2G bool "2G/2G user/kernel split" + config VMSPLIT_2G_OPT + depends on !HIGHMEM + bool "2G/2G user/kernel split (for full 2G low memory)" config VMSPLIT_1G bool "1G/3G user/kernel split" endchoice
@@ -578,7 +581,8 @@ config PAGE_OFFSET hex default 0xB0000000 if VMSPLIT_3G_OPT - default 0x78000000 if VMSPLIT_2G + default 0x80000000 if VMSPLIT_2G + default 0x78000000 if VMSPLIT_2G_OPT default 0x40000000 if VMSPLIT_1G default 0xC0000000
Eric W. Biederman
Acked-byRe: [PATCH] [30/30] x86_64: Add missing !X86_PAE dependincy to the 2G/2G split.
Quoted 23 lines · Bill Irwin
Only 1GB-aligned kernel/user splits are now handled for PAE. The 2GB/2GB split attempts to avoid aliasing vmallocspace with the 1:1 mapping for physical memory by using an actual split of 1.875/2.125 to accommodate 128MB of vmallocspace out of what would otherwise be a full 2GB for userspace. That attempt disturbs the alignment required by PAE for 2GB/2GB splits, and furthermore does not provide a 2GB/2GB split as advertised.
This patch resolves the issues here in two manners. The first is by providing a true 2GB/2GB split in addition to the 1.875/2.125 split. The second is by renaming the 1.875/2.125 split to
CONFIG_VMSPLIT_2G_OPTanalogously toCONFIG_VMSPLIT_3G_OPT, which performs a similar manuever to avoid aliasing vmallocspace with the 1:1 mapping for physical memory around the 3GB boundary. With the 1.875/2.125 split properly-named, its config option is then tagged as depending on !HIGHMEM to express the PAE implementation's current inability to deal with such unaligned splits.This patch is essentially a combination of two patches, one written by Eric Biederman and the other by Eric Dumazet. If they could add their Signed-off-by: to this, I'd be much obliged.
Quoted 5 lines
Signed-off-by William Irwin <[email protected]>Cc Eric Dumazet <[email protected]>Cc Mark Lord <[email protected]>Cc Eric W. Biederman <[email protected]>Cc Andi Kleen <[email protected]>
Quoted 26 lines
Index: sched/arch/i386/Kconfig
===================================================================arch/i386/Kconfig +5
-1@@ -571,6 +571,9 @@ bool "3G/1G user/kernel split (for full 1G low memory)" config VMSPLIT_2G bool "2G/2G user/kernel split" + config VMSPLIT_2G_OPT + depends on !HIGHMEM + bool "2G/2G user/kernel split (for full 2G low memory)" config VMSPLIT_1G bool "1G/3G user/kernel split" endchoice@@ -578,7 +581,8 @@ config PAGE_OFFSET hex default 0xB0000000 if VMSPLIT_3G_OPT - default 0x78000000 if VMSPLIT_2G + default 0x80000000 if VMSPLIT_2G + default 0x78000000 if VMSPLIT_2G_OPT default 0x40000000 if VMSPLIT_1G default 0xC0000000
Eric Dumazet
Acked-byRe: [PATCH] [30/30] x86_64: Add missing !X86_PAE dependincy to the 2G/2G split.
Quoted 24 lines · Eric W. Biederman
Quoted 22 lines · Bill Irwin
Only 1GB-aligned kernel/user splits are now handled for PAE. The 2GB/2GB split attempts to avoid aliasing vmallocspace with the 1:1 mapping for physical memory by using an actual split of 1.875/2.125 to accommodate 128MB of vmallocspace out of what would otherwise be a full 2GB for userspace. That attempt disturbs the alignment required by PAE for 2GB/2GB splits, and furthermore does not provide a 2GB/2GB split as advertised.
This patch resolves the issues here in two manners. The first is by providing a true 2GB/2GB split in addition to the 1.875/2.125 split. The second is by renaming the 1.875/2.125 split to
CONFIG_VMSPLIT_2G_OPTanalogously toCONFIG_VMSPLIT_3G_OPT, which performs a similar manuever to avoid aliasing vmallocspace with the 1:1 mapping for physical memory around the 3GB boundary. With the 1.875/2.125 split properly-named, its config option is then tagged as depending on !HIGHMEM to express the PAE implementation's current inability to deal with such unaligned splits.This patch is essentially a combination of two patches, one written by Eric Biederman and the other by Eric Dumazet. If they could add their Signed-off-by: to this, I'd be much obliged.
Quoted 7 lines
Quoted 5 lines
Signed-off-by William Irwin <[email protected]>Cc Eric Dumazet <[email protected]>Cc Mark Lord <[email protected]>Cc Eric W. Biederman <[email protected]>Cc Andi Kleen <[email protected]>
Re: [PATCH] [30/30] x86_64: Add missing !X86_PAE dependincy to the 2G/2G split.
In reply to Bill IrwinQuoted 6 lines · On Tuesday 01 May 2007 19:00:46 Bill Irwin wrote:
Quoted 4 lines · Bill Irwin
Quoted 4 lines
as a stopgap measure, but I'm not all that interested in grabbing patch credits where others could do it easily enough. Either of the config alterations is fine by me as they now stand; maybe Eric Dumazet might care to do something like my suggestion at some point.
Quoted 7 lines
Quoted 3 lines · Eric Dumazet
Your patch is very fine Bill, please resubmit it with proper Signed-off-by My first patch was a trivial reaction to try to keep alive 2G/2G split, yours is better for fine tuning.
I was hoping you would submit it as an update, but maybe adding your
Signed-off-by: to my own will do.
Added thanks
-Andi
Re: [PATCH] [30/30] x86_64: Add missing !X86_PAE dependincy to the 2G/2G split.
In reply to Andi KleenQuoted 8 lines · Andi Kleen
From: [email protected]
When in PAE mode we require that the user kernel divide to be on a 1G boundary. The 2G/2G split does not have that property so require !X86_PAESigned-off-by Eric W. Biederman <[email protected]>--- arch/i386/Kconfig | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
What on earth?
config PAGE_OFFSET
hex
default 0xB0000000 if VMSPLIT_3G_OPT
default 0x78000000 if VMSPLIT_2G
default 0x40000000 if VMSPLIT_1G
default 0xC0000000This appears to have been introduced by:
commit 975b3d3d5b983eb60706d35f0d24cd19f6badabf
Author: Mark Lord <[email protected]> Date: Wed Feb 1 03:06:11 2006 -0800
[PATCH] VMSPLIT config options
There's some sort of insanity going on here. Since when is 0x78000000 a 2GB/2GB split? Mark, dare I ask what you were thinking? That should be VMSPLIT_2G_OPT for 2GB laptops analogously to VMSPLIT_3G_OPT, if nothing else, as it's certainly not 2GB/2GB.
These VMSPLIT config options vs. PAE are foul as they're now done in any event. If they were done properly, they'd properly set up the pmd within which the division point between user and kernelspace falls.
This patch, I suppose, stops people from shooting themselves in the foot, but (IMHO) the VMSPLIT patches shouldn't have been merged without handling the partial pmd case. 2MB/4MB resolution is enough granularity for any reasonable purpose, so split ptes aren't worth the effort, but this nonsense with PAE vs. VMSPLIT is just preposterous. If you're going to play the VMSPLIT game at all, handle split pmd's.
I'll see what else is pending in the i386 pagetable arena and clear this up if there aren't other objections (this is where Andi gets to complain that things are too complex already and preemptively NAK to save me the effort, if it's not seen to be desirable). Eric, your patch is a reasonable stop-gap measure for the original deficiency.
-- wli
Re: [PATCH] [30/30] x86_64: Add missing !X86_PAE dependincy to the 2G/2G split.
Quoted 21 lines · William Lee Irwin III
Quoted 8 lines · Andi Kleen
From: [email protected]
When in PAE mode we require that the user kernel divide to be on a 1G boundary. The 2G/2G split does not have that property so require !X86_PAESigned-off-by Eric W. Biederman <[email protected]>--- arch/i386/Kconfig | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)What on earth?
config
PAGE_OFFSEThex default 0xB0000000 if VMSPLIT_3G_OPT default 0x78000000 if VMSPLIT_2G default 0x40000000 if VMSPLIT_1G default 0xC0000000This appears to have been introduced by:
commit975b3d3d5b983eb60706d35f0d24cd19f6badabf
Quoted 8 lines
Author: Mark Lord <[email protected]> Date: Wed Feb 1 03:06:11 2006 -0800[PATCH] VMSPLIT config options
There's some sort of insanity going on here. Since when is
0x78000000a 2GB/2GB split? Mark, dare I ask what you were thinking? That should beVMSPLIT_2G_OPTfor 2GB laptops analogously toVMSPLIT_3G_OPT, if nothing else, as it's certainly not 2GB/2GB.
Please could you stop saying others are insane ?
They are like you and can fail sometime. Apparently when the patch came, nobody (including you) commented.
It's not that difficult to think about VMALLOC space (I might be wrong about this, but I feel this explains 78000000 vs 80000000)
Quoted 17 lines
These VMSPLIT config options vs. PAE are foul as they're now done in any event. If they were done properly, they'd properly set up the pmd within which the division point between user and kernelspace falls.
This patch, I suppose, stops people from shooting themselves in the foot, but (IMHO) the VMSPLIT patches shouldn't have been merged without handling the partial pmd case. 2MB/4MB resolution is enough granularity for any reasonable purpose, so split ptes aren't worth the effort, but this nonsense with PAE vs. VMSPLIT is just preposterous. If you're going to play the VMSPLIT game at all, handle split pmd's.
I'll see what else is pending in the i386 pagetable arena and clear this up if there aren't other objections (this is where Andi gets to complain that things are too complex already and preemptively NAK to save me the effort, if it's not seen to be desirable). Eric, your patch is a reasonable stop-gap measure for the original deficiency.
Re: [PATCH] [30/30] x86_64: Add missing !X86_PAE dependincy to the 2G/2G split.
William Lee Irwin III a ?crit :
Quoted 4 lines
Quoted 4 lines
There's some sort of insanity going on here. Since when is
0x78000000a 2GB/2GB split? Mark, dare I ask what you were thinking? That should beVMSPLIT_2G_OPTfor 2GB laptops analogously toVMSPLIT_3G_OPT, if nothing else, as it's certainly not 2GB/2GB.
Quoted 5 lines · Eric Dumazet
Please could you stop saying others are insane ?
They are like you and can fail sometime. Apparently when the patch came, nobody (including you) commented.
It's not that difficult to think about VMALLOC space (I might be wrong about this, but I feel this explains 78000000 vs 80000000)
I'm obviously aware of vmallocspace. Read carefully:
Quoted 3 lines
Quoted 3 lines
a 2GB/2GB split? Mark, dare I ask what you were thinking? That should be
VMSPLIT_2G_OPTfor 2GB laptops analogously toVMSPLIT_3G_OPT, if nothing else, as it's certainly not 2GB/2GB.
The meaning of "for laptops" is that it's carving out a chunk of user virtualspace to use for vmallocspace in lieu of carving out a piece of the 1:1 mapping of physical memory for the same purpose.
-- wli
Re: [PATCH] [30/30] x86_64: Add missing !X86_PAE dependincy to the 2G/2G split.
In reply to William Lee Irwin IIIQuoted 21 lines · William Lee Irwin III
Quoted 8 lines · Andi Kleen
From: [email protected]
When in PAE mode we require that the user kernel divide to be on a 1G boundary. The 2G/2G split does not have that property so require !X86_PAESigned-off-by Eric W. Biederman <[email protected]>--- arch/i386/Kconfig | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)What on earth?
config
PAGE_OFFSEThex default 0xB0000000 if VMSPLIT_3G_OPT default 0x78000000 if VMSPLIT_2G default 0x40000000 if VMSPLIT_1G default 0xC0000000This appears to have been introduced by:
commit975b3d3d5b983eb60706d35f0d24cd19f6badabf
Quoted 8 lines
Author: Mark Lord <[email protected]> Date: Wed Feb 1 03:06:11 2006 -0800[PATCH] VMSPLIT config options
There's some sort of insanity going on here. Since when is
0x78000000a 2GB/2GB split? Mark, dare I ask what you were thinking? That should beVMSPLIT_2G_OPTfor 2GB laptops analogously toVMSPLIT_3G_OPT, if nothing else, as it's certainly not 2GB/2GB.
It makes a little more sense when you realize all of the options were originally !X86_PAE. So they were designed with highmem disabled.
Quoted 3 lines
These VMSPLIT config options vs. PAE are foul as they're now done in any event. If they were done properly, they'd properly set up the pmd within which the division point between user and kernelspace falls.
They were designed to avoid highmem a totally different design point.
Quoted 6 lines
This patch, I suppose, stops people from shooting themselves in the foot, but (IMHO) the VMSPLIT patches shouldn't have been merged without handling the partial pmd case. 2MB/4MB resolution is enough granularity for any reasonable purpose, so split ptes aren't worth the effort, but this nonsense with PAE vs. VMSPLIT is just preposterous. If you're going to play the VMSPLIT game at all, handle split pmd's.
What I find telling is that I fixed this based on code review not based on bug reports.
Quoted 5 lines
I'll see what else is pending in the i386 pagetable arena and clear this up if there aren't other objections (this is where Andi gets to complain that things are too complex already and preemptively NAK to save me the effort, if it's not seen to be desirable). Eric, your patch is a reasonable stop-gap measure for the original deficiency.
Frankly rather then putting much effort into this I suspect we should just delete these options entirely. We are long past the point where they matter.
Eric
Re: [PATCH] [30/30] x86_64: Add missing !X86_PAE dependincy to the 2G/2G split.
In reply to William Lee Irwin IIIQuoted 21 lines · William Lee Irwin III
Quoted 8 lines · Andi Kleen
From: [email protected]
When in PAE mode we require that the user kernel divide to be on a 1G boundary. The 2G/2G split does not have that property so require !X86_PAESigned-off-by Eric W. Biederman <[email protected]>--- arch/i386/Kconfig | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)What on earth?
config
PAGE_OFFSEThex default 0xB0000000 if VMSPLIT_3G_OPT default 0x78000000 if VMSPLIT_2G default 0x40000000 if VMSPLIT_1G default 0xC0000000This appears to have been introduced by:
commit975b3d3d5b983eb60706d35f0d24cd19f6badabf
Quoted 8 lines
Author: Mark Lord <[email protected]> Date: Wed Feb 1 03:06:11 2006 -0800[PATCH] VMSPLIT config options
There's some sort of insanity going on here. Since when is
0x78000000a 2GB/2GB split? Mark, dare I ask what you were thinking? That should beVMSPLIT_2G_OPTfor 2GB laptops analogously toVMSPLIT_3G_OPT, if nothing else, as it's certainly not 2GB/2GB.
You need to go search the archives and read the *extensive* thread on this from when it was introduced. Lots of high profile kernel developers were in on this one.
The idea is really simple: eliminate the need for HIGHMEM on common machines.
And yes, VMSPLIT_2G really means VMSPLIT_2G_OPT, in the same way as the (added last) VMSPLIT_3G_OPT flag.
Cheers
Re: [PATCH] [30/30] x86_64: Add missing !X86_PAE dependincy to the 2G/2G split.
Quoted 4 lines · William Lee Irwin III
Quoted 4 lines
There's some sort of insanity going on here. Since when is
0x78000000a 2GB/2GB split? Mark, dare I ask what you were thinking? That should beVMSPLIT_2G_OPTfor 2GB laptops analogously toVMSPLIT_3G_OPT, if nothing else, as it's certainly not 2GB/2GB.
Quoted 3 lines · Mark Lord
You need to go search the archives and read the *extensive* thread on this from when it was introduced. Lots of high profile kernel developers were in on this one.
Various good points were raised. The NX bit requiring 3-level pagetables suggests that 3-level pagetables without highmem would be valuable, at which point the unaligned splits to avoid highmem with 3-level pagetables gain additional relevance. I'll queue that up to be written along with split pmd affairs, and check for features dependent on 4-level pagetables, too.
Quoted 2 lines · Mark Lord
The idea is really simple: eliminate the need for HIGHMEM on common machines.
Of course. Everything is simple until it's done properly. It's why everyone forgets the "and no simpler" half of the quote, which turns the meaning of what everyone tries to quote on its head.
I guess looking over it I don't blame you so much. I should've been around to clean up these issues at the time it was happening. People seem to have been trying to use the RAM in their laptops without big slowdowns, and may not have had the VM "sophistication" to deal with the sorts of issues I'm raising.
Quoted 2 lines · Mark Lord
And yes,
VMSPLIT_2Greally meansVMSPLIT_2G_OPT, in the same way as the (added last)VMSPLIT_3G_OPTflag.
This was a large portion of the substance of my complaint.
-- wli
Re: [PATCH] [30/30] x86_64: Add missing !X86_PAE dependincy to the 2G/2G split.
Quoted 6 lines · William Lee Irwin III
..
Quoted 3 lines · Mark Lord
You need to go search the archives and read the *extensive* thread on this from when it was introduced. Lots of high profile kernel developers were in on this one.
Quoted 6 lines
Various good points were raised. The NX bit requiring 3-level pagetables suggests that 3-level pagetables without highmem would be valuable, at which point the unaligned splits to avoid highmem with 3-level pagetables gain additional relevance. I'll queue that up to be written along with split pmd affairs, and check for features dependent on 4-level pagetables, too.
Excellent! That would be super to have in there, William.
Cheers!