diff options
Diffstat (limited to 'arch/i386/kernel')
-rw-r--r-- | arch/i386/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/i386/kernel/cpu/amd.c | 4 | ||||
-rw-r--r-- | arch/i386/kernel/cpu/cpufreq/powernow-k7.c | 36 | ||||
-rw-r--r-- | arch/i386/kernel/cpu/cpufreq/powernow-k8.c | 2 | ||||
-rw-r--r-- | arch/i386/kernel/cpu/cpufreq/powernow-k8.h | 4 | ||||
-rw-r--r-- | arch/i386/kernel/cpu/cpufreq/speedstep-ich.c | 1 | ||||
-rw-r--r-- | arch/i386/kernel/cpu/cyrix.c | 1 | ||||
-rw-r--r-- | arch/i386/kernel/cpu/mcheck/k7.c | 6 | ||||
-rw-r--r-- | arch/i386/kernel/cpu/mtrr/cyrix.c | 2 | ||||
-rw-r--r-- | arch/i386/kernel/cpu/mtrr/generic.c | 2 | ||||
-rw-r--r-- | arch/i386/kernel/cpu/mtrr/main.c | 2 | ||||
-rw-r--r-- | arch/i386/kernel/cpu/mtrr/state.c | 2 | ||||
-rw-r--r-- | arch/i386/kernel/smp.c | 67 | ||||
-rw-r--r-- | arch/i386/kernel/smpboot.c | 22 | ||||
-rw-r--r-- | arch/i386/kernel/smpcommon.c | 79 | ||||
-rw-r--r-- | arch/i386/kernel/traps.c | 5 | ||||
-rw-r--r-- | arch/i386/kernel/verify_cpu.S | 27 | ||||
-rw-r--r-- | arch/i386/kernel/vmlinux.lds.S | 4 |
18 files changed, 160 insertions, 107 deletions
diff --git a/arch/i386/kernel/Makefile b/arch/i386/kernel/Makefile index 91cff8dc9e1a..06da59f6f837 100644 --- a/arch/i386/kernel/Makefile +++ b/arch/i386/kernel/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_X86_CPUID) += cpuid.o obj-$(CONFIG_MICROCODE) += microcode.o obj-$(CONFIG_APM) += apm.o obj-$(CONFIG_X86_SMP) += smp.o smpboot.o tsc_sync.o +obj-$(CONFIG_SMP) += smpcommon.o obj-$(CONFIG_X86_TRAMPOLINE) += trampoline.o obj-$(CONFIG_X86_MPPARSE) += mpparse.o obj-$(CONFIG_X86_LOCAL_APIC) += apic.o nmi.o diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c index 4fec702afd7e..6f47eeeb93ea 100644 --- a/arch/i386/kernel/cpu/amd.c +++ b/arch/i386/kernel/cpu/amd.c @@ -280,6 +280,10 @@ static void __cpuinit init_amd(struct cpuinfo_x86 *c) if (c->x86 == 0x10 && !force_mwait) clear_bit(X86_FEATURE_MWAIT, c->x86_capability); + + /* K6s reports MCEs but don't actually have all the MSRs */ + if (c->x86 < 6) + clear_bit(X86_FEATURE_MCE, c->x86_capability); } static unsigned int __cpuinit amd_size_cache(struct cpuinfo_x86 * c, unsigned int size) diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c index 837b04166a47..ca3e1d341889 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k7.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k7.c @@ -341,15 +341,17 @@ static int powernow_acpi_init(void) pc.val = (unsigned long) acpi_processor_perf->states[0].control; for (i = 0; i < number_scales; i++) { u8 fid, vid; - unsigned int speed; + struct acpi_processor_px *state = + &acpi_processor_perf->states[i]; + unsigned int speed, speed_mhz; - pc.val = (unsigned long) acpi_processor_perf->states[i].control; + pc.val = (unsigned long) state->control; dprintk ("acpi: P%d: %d MHz %d mW %d uS control %08x SGTC %d\n", i, - (u32) acpi_processor_perf->states[i].core_frequency, - (u32) acpi_processor_perf->states[i].power, - (u32) acpi_processor_perf->states[i].transition_latency, - (u32) acpi_processor_perf->states[i].control, + (u32) state->core_frequency, + (u32) state->power, + (u32) state->transition_latency, + (u32) state->control, pc.bits.sgtc); vid = pc.bits.vid; @@ -360,6 +362,18 @@ static int powernow_acpi_init(void) powernow_table[i].index |= (vid << 8); /* upper 8 bits */ speed = powernow_table[i].frequency; + speed_mhz = speed / 1000; + + /* processor_perflib will multiply the MHz value by 1000 to + * get a KHz value (e.g. 1266000). However, powernow-k7 works + * with true KHz values (e.g. 1266768). To ensure that all + * powernow frequencies are available, we must ensure that + * ACPI doesn't restrict them, so we round up the MHz value + * to ensure that perflib's computed KHz value is greater than + * or equal to powernow's KHz value. + */ + if (speed % 1000 > 0) + speed_mhz++; if ((fid_codes[fid] % 10)==5) { if (have_a0 == 1) @@ -368,10 +382,16 @@ static int powernow_acpi_init(void) dprintk (" FID: 0x%x (%d.%dx [%dMHz]) " "VID: 0x%x (%d.%03dV)\n", fid, fid_codes[fid] / 10, - fid_codes[fid] % 10, speed/1000, vid, + fid_codes[fid] % 10, speed_mhz, vid, mobile_vid_table[vid]/1000, mobile_vid_table[vid]%1000); + if (state->core_frequency != speed_mhz) { + state->core_frequency = speed_mhz; + dprintk(" Corrected ACPI frequency to %d\n", + speed_mhz); + } + if (latency < pc.bits.sgtc) latency = pc.bits.sgtc; @@ -602,7 +622,7 @@ static int __init powernow_cpu_init (struct cpufreq_policy *policy) result = powernow_acpi_init(); if (result) { printk (KERN_INFO PFX "ACPI and legacy methods failed\n"); - printk (KERN_INFO PFX "See http://www.codemonkey.org.uk/projects/cpufreq/powernow-k7.shtml\n"); + printk (KERN_INFO PFX "See http://www.codemonkey.org.uk/projects/cpufreq/powernow-k7.html\n"); } } else { /* SGTC use the bus clock as timer */ diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c index 7cf3d207b6b3..4ade55c5f333 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c @@ -521,7 +521,7 @@ static int check_supported_cpu(unsigned int cpu) if ((eax & CPUID_XFAM) == CPUID_XFAM_K8) { if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) || - ((eax & CPUID_XMOD) > CPUID_XMOD_REV_G)) { + ((eax & CPUID_XMOD) > CPUID_XMOD_REV_MASK)) { printk(KERN_INFO PFX "Processor cpuid %x not supported\n", eax); goto out; } diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h index 95be5013c984..b06c812208ca 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h @@ -46,8 +46,8 @@ struct powernow_k8_data { #define CPUID_XFAM 0x0ff00000 /* extended family */ #define CPUID_XFAM_K8 0 #define CPUID_XMOD 0x000f0000 /* extended model */ -#define CPUID_XMOD_REV_G 0x00060000 -#define CPUID_XFAM_10H 0x00100000 /* family 0x10 */ +#define CPUID_XMOD_REV_MASK 0x00080000 +#define CPUID_XFAM_10H 0x00100000 /* family 0x10 */ #define CPUID_USE_XFAM_XMOD 0x00000f00 #define CPUID_GET_MAX_CAPABILITIES 0x80000000 #define CPUID_FREQ_VOLT_CAPABILITIES 0x80000007 diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c index b425cd3d1838..698f980eb443 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c @@ -24,6 +24,7 @@ #include <linux/cpufreq.h> #include <linux/pci.h> #include <linux/slab.h> +#include <linux/sched.h> #include "speedstep-lib.h" diff --git a/arch/i386/kernel/cpu/cyrix.c b/arch/i386/kernel/cpu/cyrix.c index 0b8411a864fb..e88d2fba156b 100644 --- a/arch/i386/kernel/cpu/cyrix.c +++ b/arch/i386/kernel/cpu/cyrix.c @@ -7,6 +7,7 @@ #include <asm/processor.h> #include <asm/timer.h> #include <asm/pci-direct.h> +#include <asm/tsc.h> #include "cpu.h" diff --git a/arch/i386/kernel/cpu/mcheck/k7.c b/arch/i386/kernel/cpu/mcheck/k7.c index f9fa4142551e..eef63e3630c2 100644 --- a/arch/i386/kernel/cpu/mcheck/k7.c +++ b/arch/i386/kernel/cpu/mcheck/k7.c @@ -72,12 +72,12 @@ void amd_mcheck_init(struct cpuinfo_x86 *c) u32 l, h; int i; - machine_check_vector = k7_machine_check; - wmb(); - if (!cpu_has(c, X86_FEATURE_MCE)) return; + machine_check_vector = k7_machine_check; + wmb(); + printk (KERN_INFO "Intel machine check architecture supported.\n"); rdmsr (MSR_IA32_MCG_CAP, l, h); if (l & (1<<8)) /* Control register present ? */ diff --git a/arch/i386/kernel/cpu/mtrr/cyrix.c b/arch/i386/kernel/cpu/mtrr/cyrix.c index 0737a596db43..9edf5625584f 100644 --- a/arch/i386/kernel/cpu/mtrr/cyrix.c +++ b/arch/i386/kernel/cpu/mtrr/cyrix.c @@ -136,7 +136,7 @@ static void prepare_set(void) /* Save value of CR4 and clear Page Global Enable (bit 7) */ if ( cpu_has_pge ) { cr4 = read_cr4(); - write_cr4(cr4 & (unsigned char) ~(1 << 7)); + write_cr4(cr4 & ~X86_CR4_PGE); } /* Disable and flush caches. Note that wbinvd flushes the TLBs as diff --git a/arch/i386/kernel/cpu/mtrr/generic.c b/arch/i386/kernel/cpu/mtrr/generic.c index 5367e32e0403..c4ebb5126ef7 100644 --- a/arch/i386/kernel/cpu/mtrr/generic.c +++ b/arch/i386/kernel/cpu/mtrr/generic.c @@ -78,7 +78,7 @@ static void __cpuinit print_fixed(unsigned base, unsigned step, const mtrr_type* } /* Grab all of the MTRR state for this CPU into *state */ -void __init get_mtrr_state(void) +void get_mtrr_state(void) { unsigned int i; struct mtrr_var_range *vrs; diff --git a/arch/i386/kernel/cpu/mtrr/main.c b/arch/i386/kernel/cpu/mtrr/main.c index 02a2f39e5e0a..1cf466df330a 100644 --- a/arch/i386/kernel/cpu/mtrr/main.c +++ b/arch/i386/kernel/cpu/mtrr/main.c @@ -639,7 +639,7 @@ static struct sysdev_driver mtrr_sysdev_driver = { * initialized (i.e. before smp_init()). * */ -void __init mtrr_bp_init(void) +void mtrr_bp_init(void) { init_ifs(); diff --git a/arch/i386/kernel/cpu/mtrr/state.c b/arch/i386/kernel/cpu/mtrr/state.c index f62ecd15811a..7b39a2f954d9 100644 --- a/arch/i386/kernel/cpu/mtrr/state.c +++ b/arch/i386/kernel/cpu/mtrr/state.c @@ -19,7 +19,7 @@ void set_mtrr_prepare_save(struct set_mtrr_context *ctxt) /* Save value of CR4 and clear Page Global Enable (bit 7) */ if ( cpu_has_pge ) { ctxt->cr4val = read_cr4(); - write_cr4(ctxt->cr4val & (unsigned char) ~(1 << 7)); + write_cr4(ctxt->cr4val & ~X86_CR4_PGE); } /* Disable and flush caches. Note that wbinvd flushes the TLBs as diff --git a/arch/i386/kernel/smp.c b/arch/i386/kernel/smp.c index 706bda72dc60..6299c080f6e2 100644 --- a/arch/i386/kernel/smp.c +++ b/arch/i386/kernel/smp.c @@ -421,7 +421,7 @@ void flush_tlb_mm (struct mm_struct * mm) } if (!cpus_empty(cpu_mask)) flush_tlb_others(cpu_mask, mm, TLB_FLUSH_ALL); - check_pgt_cache(); + preempt_enable(); } @@ -467,7 +467,7 @@ void flush_tlb_all(void) * it goes straight through and wastes no time serializing * anything. Worst case is that we lose a reschedule ... */ -void native_smp_send_reschedule(int cpu) +static void native_smp_send_reschedule(int cpu) { WARN_ON(cpu_is_offline(cpu)); send_IPI_mask(cpumask_of_cpu(cpu), RESCHEDULE_VECTOR); @@ -546,9 +546,10 @@ static void __smp_call_function(void (*func) (void *info), void *info, * You must not call this function with disabled interrupts or from a * hardware interrupt handler or from a bottom half handler. */ -int native_smp_call_function_mask(cpumask_t mask, - void (*func)(void *), void *info, - int wait) +static int +native_smp_call_function_mask(cpumask_t mask, + void (*func)(void *), void *info, + int wait) { struct call_data_struct data; cpumask_t allbutself; @@ -599,60 +600,6 @@ int native_smp_call_function_mask(cpumask_t mask, return 0; } -/** - * smp_call_function(): Run a function on all other CPUs. - * @func: The function to run. This must be fast and non-blocking. - * @info: An arbitrary pointer to pass to the function. - * @nonatomic: Unused. - * @wait: If true, wait (atomically) until function has completed on other CPUs. - * - * Returns 0 on success, else a negative status code. - * - * If @wait is true, then returns once @func has returned; otherwise - * it returns just before the target cpu calls @func. - * - * You must not call this function with disabled interrupts or from a - * hardware interrupt handler or from a bottom half handler. - */ -int smp_call_function(void (*func) (void *info), void *info, int nonatomic, - int wait) -{ - return smp_call_function_mask(cpu_online_map, func, info, wait); -} -EXPORT_SYMBOL(smp_call_function); - -/** - * smp_call_function_single - Run a function on another CPU - * @cpu: The target CPU. Cannot be the calling CPU. - * @func: The function to run. This must be fast and non-blocking. - * @info: An arbitrary pointer to pass to the function. - * @nonatomic: Unused. - * @wait: If true, wait until function has completed on other CPUs. - * - * Returns 0 on success, else a negative status code. - * - * If @wait is true, then returns once @func has returned; otherwise - * it returns just before the target cpu calls @func. - */ -int smp_call_function_single(int cpu, void (*func) (void *info), void *info, - int nonatomic, int wait) -{ - /* prevent preemption and reschedule on another processor */ - int ret; - int me = get_cpu(); - if (cpu == me) { - WARN_ON(1); - put_cpu(); - return -EBUSY; - } - - ret = smp_call_function_mask(cpumask_of_cpu(cpu), func, info, wait); - - put_cpu(); - return ret; -} -EXPORT_SYMBOL(smp_call_function_single); - static void stop_this_cpu (void * dummy) { local_irq_disable(); @@ -670,7 +617,7 @@ static void stop_this_cpu (void * dummy) * this function calls the 'stop' function on all other CPUs in the system. */ -void native_smp_send_stop(void) +static void native_smp_send_stop(void) { /* Don't deadlock on the call lock in panic */ int nolock = !spin_trylock(&call_lock); diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index b92cc4e8b3bb..08f07a74a9d3 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -98,9 +98,6 @@ EXPORT_SYMBOL(x86_cpu_to_apicid); u8 apicid_2_node[MAX_APICID]; -DEFINE_PER_CPU(unsigned long, this_cpu_off); -EXPORT_PER_CPU_SYMBOL(this_cpu_off); - /* * Trampoline 80x86 program as an array. */ @@ -763,25 +760,6 @@ static inline struct task_struct * alloc_idle_task(int cpu) #define alloc_idle_task(cpu) fork_idle(cpu) #endif -/* Initialize the CPU's GDT. This is either the boot CPU doing itself - (still using the master per-cpu area), or a CPU doing it for a - secondary which will soon come up. */ -static __cpuinit void init_gdt(int cpu) -{ - struct desc_struct *gdt = get_cpu_gdt_table(cpu); - - pack_descriptor((u32 *)&gdt[GDT_ENTRY_PERCPU].a, - (u32 *)&gdt[GDT_ENTRY_PERCPU].b, - __per_cpu_offset[cpu], 0xFFFFF, - 0x80 | DESCTYPE_S | 0x2, 0x8); - - per_cpu(this_cpu_off, cpu) = __per_cpu_offset[cpu]; - per_cpu(cpu_number, cpu) = cpu; -} - -/* Defined in head.S */ -extern struct Xgt_desc_struct early_gdt_descr; - static int __cpuinit do_boot_cpu(int apicid, int cpu) /* * NOTE - on most systems this is a PHYSICAL apic ID, but on multiquad diff --git a/arch/i386/kernel/smpcommon.c b/arch/i386/kernel/smpcommon.c new file mode 100644 index 000000000000..1868ae18eb4d --- /dev/null +++ b/arch/i386/kernel/smpcommon.c @@ -0,0 +1,79 @@ +/* + * SMP stuff which is common to all sub-architectures. + */ +#include <linux/module.h> +#include <asm/smp.h> + +DEFINE_PER_CPU(unsigned long, this_cpu_off); +EXPORT_PER_CPU_SYMBOL(this_cpu_off); + +/* Initialize the CPU's GDT. This is either the boot CPU doing itself + (still using the master per-cpu area), or a CPU doing it for a + secondary which will soon come up. */ +__cpuinit void init_gdt(int cpu) +{ + struct desc_struct *gdt = get_cpu_gdt_table(cpu); + + pack_descriptor((u32 *)&gdt[GDT_ENTRY_PERCPU].a, + (u32 *)&gdt[GDT_ENTRY_PERCPU].b, + __per_cpu_offset[cpu], 0xFFFFF, + 0x80 | DESCTYPE_S | 0x2, 0x8); + + per_cpu(this_cpu_off, cpu) = __per_cpu_offset[cpu]; + per_cpu(cpu_number, cpu) = cpu; +} + + +/** + * smp_call_function(): Run a function on all other CPUs. + * @func: The function to run. This must be fast and non-blocking. + * @info: An arbitrary pointer to pass to the function. + * @nonatomic: Unused. + * @wait: If true, wait (atomically) until function has completed on other CPUs. + * + * Returns 0 on success, else a negative status code. + * + * If @wait is true, then returns once @func has returned; otherwise + * it returns just before the target cpu calls @func. + * + * You must not call this function with disabled interrupts or from a + * hardware interrupt handler or from a bottom half handler. + */ +int smp_call_function(void (*func) (void *info), void *info, int nonatomic, + int wait) +{ + return smp_call_function_mask(cpu_online_map, func, info, wait); +} +EXPORT_SYMBOL(smp_call_function); + +/** + * smp_call_function_single - Run a function on another CPU + * @cpu: The target CPU. Cannot be the calling CPU. + * @func: The function to run. This must be fast and non-blocking. + * @info: An arbitrary pointer to pass to the function. + * @nonatomic: Unused. + * @wait: If true, wait until function has completed on other CPUs. + * + * Returns 0 on success, else a negative status code. + * + * If @wait is true, then returns once @func has returned; otherwise + * it returns just before the target cpu calls @func. + */ +int smp_call_function_single(int cpu, void (*func) (void *info), void *info, + int nonatomic, int wait) +{ + /* prevent preemption and reschedule on another processor */ + int ret; + int me = get_cpu(); + if (cpu == me) { + WARN_ON(1); + put_cpu(); + return -EBUSY; + } + + ret = smp_call_function_mask(cpumask_of_cpu(cpu), func, info, wait); + + put_cpu(); + return ret; +} +EXPORT_SYMBOL(smp_call_function_single); diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index c05e7e861b29..90da0575fcff 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -733,11 +733,6 @@ static __kprobes void default_do_nmi(struct pt_regs * regs) */ if (nmi_watchdog_tick(regs, reason)) return; -#endif - if (notify_die(DIE_NMI_POST, "nmi_post", regs, reason, 2, 0) - == NOTIFY_STOP) - return; -#ifdef CONFIG_X86_LOCAL_APIC if (!do_nmi_callback(regs, smp_processor_id())) #endif unknown_nmi_error(reason, regs); diff --git a/arch/i386/kernel/verify_cpu.S b/arch/i386/kernel/verify_cpu.S index b2a9d80b6421..f1d1eacf4ab0 100644 --- a/arch/i386/kernel/verify_cpu.S +++ b/arch/i386/kernel/verify_cpu.S @@ -2,6 +2,7 @@ This runs in 16bit mode so that the caller can still use the BIOS to output errors on the screen */ #include <asm/cpufeature.h> +#include <asm/msr.h> verify_cpu: pushfl # Save caller passed flags @@ -45,6 +46,32 @@ verify_cpu: cmpl $0x1,%eax jb bad # no cpuid 1 +#if REQUIRED_MASK1 & NEED_CMPXCHG64 + /* Some VIA C3s need magic MSRs to enable CX64. Do this here */ + cmpl $0x746e6543,%ebx # Cent + jne 1f + cmpl $0x48727561,%edx # aurH + jne 1f + cmpl $0x736c7561,%ecx # auls + jne 1f + movl $1,%eax # check model + cpuid + movl %eax,%ebx + shr $8,%ebx + andl $0xf,%ebx + cmp $6,%ebx # check family == 6 + jne 1f + shr $4,%eax + andl $0xf,%eax + cmpl $6,%eax # check model >= 6 + jb 1f + # assume models >= 6 all support this MSR + movl $MSR_VIA_FCR,%ecx + rdmsr + orl $((1<<1)|(1<<7)),%eax # enable CMPXCHG64 and PGE + wrmsr +1: +#endif movl $0x1,%eax # Does the cpu have what it takes cpuid diff --git a/arch/i386/kernel/vmlinux.lds.S b/arch/i386/kernel/vmlinux.lds.S index 80bec6640230..aa87b06c7c82 100644 --- a/arch/i386/kernel/vmlinux.lds.S +++ b/arch/i386/kernel/vmlinux.lds.S @@ -44,7 +44,7 @@ SECTIONS /* read-only */ .text : AT(ADDR(.text) - LOAD_OFFSET) { - *(.text) + TEXT_TEXT SCHED_TEXT LOCK_TEXT KPROBES_TEXT @@ -74,7 +74,7 @@ SECTIONS /* writeable */ . = ALIGN(4096); .data : AT(ADDR(.data) - LOAD_OFFSET) { /* Data */ - *(.data) + DATA_DATA CONSTRUCTORS } :data |