From 8aae8284fece2b8fc404ccd40b7a30aa96f317b5 Mon Sep 17 00:00:00 2001 From: Jacob Shin Date: Mon, 21 Nov 2005 07:23:08 -0800 Subject: [CPUFREQ] Improve Error reporting in powernow-k8 This patch cleans up some error messages in the powernow-k8 driver and makes them more understandable. Signed-off-by: Jacob Shin Signed-off-by: Mark Langsdorf Signed-off-by: Dave Jones --- arch/i386/kernel/cpu/cpufreq/powernow-k8.c | 31 +++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c index 68a1fc87f4ca..349782736808 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c @@ -45,7 +45,7 @@ #define PFX "powernow-k8: " #define BFX PFX "BIOS error: " -#define VERSION "version 1.50.4" +#define VERSION "version 1.50.5" #include "powernow-k8.h" /* serialize freq changes */ @@ -464,7 +464,7 @@ static int check_supported_cpu(unsigned int cpu) set_cpus_allowed(current, cpumask_of_cpu(cpu)); if (smp_processor_id() != cpu) { - printk(KERN_ERR "limiting to cpu %u failed\n", cpu); + printk(KERN_ERR PFX "limiting to cpu %u failed\n", cpu); goto out; } @@ -517,22 +517,28 @@ static int check_pst_table(struct powernow_k8_data *data, struct pst_s *pst, u8 printk(KERN_ERR BFX "maxvid exceeded with pstate %d\n", j); return -ENODEV; } - if ((pst[j].fid > MAX_FID) - || (pst[j].fid & 1) - || (j && (pst[j].fid < HI_FID_TABLE_BOTTOM))) { + if (pst[j].fid > MAX_FID) { + printk(KERN_ERR BFX "maxfid exceeded with pstate %d\n", j); + return -ENODEV; + } + if (pst[j].fid & 1) { + printk(KERN_ERR BFX "fid invalid - %d : 0x%x\n", j, pst[j].fid); + return -EINVAL; + } + if (j && (pst[j].fid < HI_FID_TABLE_BOTTOM)) { /* Only first fid is allowed to be in "low" range */ - printk(KERN_ERR PFX "two low fids - %d : 0x%x\n", j, pst[j].fid); + printk(KERN_ERR BFX "two low fids - %d : 0x%x\n", j, pst[j].fid); return -EINVAL; } if (pst[j].fid < lastfid) lastfid = pst[j].fid; } if (lastfid & 1) { - printk(KERN_ERR PFX "lastfid invalid\n"); + printk(KERN_ERR BFX "lastfid invalid\n"); return -EINVAL; } if (lastfid > LO_FID_TABLE_TOP) - printk(KERN_INFO PFX "first fid not from lo freq table\n"); + printk(KERN_INFO BFX "first fid not from lo freq table\n"); return 0; } @@ -912,7 +918,7 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi set_cpus_allowed(current, cpumask_of_cpu(pol->cpu)); if (smp_processor_id() != pol->cpu) { - printk(KERN_ERR "limiting to cpu %u failed\n", pol->cpu); + printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu); goto err_out; } @@ -982,6 +988,9 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol) cpumask_t oldmask = CPU_MASK_ALL; int rc, i; + if (!cpu_online(pol->cpu)) + return -ENODEV; + if (!check_supported_cpu(pol->cpu)) return -ENODEV; @@ -1021,7 +1030,7 @@ static int __init powernowk8_cpu_init(struct cpufreq_policy *pol) set_cpus_allowed(current, cpumask_of_cpu(pol->cpu)); if (smp_processor_id() != pol->cpu) { - printk(KERN_ERR "limiting to cpu %u failed\n", pol->cpu); + printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu); goto err_out; } @@ -1162,7 +1171,7 @@ static void __exit powernowk8_exit(void) cpufreq_unregister_driver(&cpufreq_amd64_driver); } -MODULE_AUTHOR("Paul Devriendt and Mark Langsdorf and Mark Langsdorf "); MODULE_DESCRIPTION("AMD Athlon 64 and Opteron processor frequency driver."); MODULE_LICENSE("GPL"); -- cgit v1.2.2 From 019a61b99338d0ac05de25317b85da88e7ec4b35 Mon Sep 17 00:00:00 2001 From: "Langsdorf, Mark" Date: Tue, 29 Nov 2005 14:18:03 -0600 Subject: [PATCH] Support 100 MHz frequency transitions Future versions of the Opteron processor may support frequency transitions of 100 MHz, instead of the=20 current 200 MHz. This patch enables the powernow-k8 driver to transition to an odd FID code, indicating a multiple of 100 MHz frequency. Signed-off-by: Jacob Shin Signed-off-by: Mark Langsdorf Signed-off-by: Dave Jones --- arch/i386/kernel/cpu/cpufreq/powernow-k8.c | 17 +++++++---------- arch/i386/kernel/cpu/cpufreq/powernow-k8.h | 9 +++++---- 2 files changed, 12 insertions(+), 14 deletions(-) (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c index 349782736808..a342b32c0843 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c @@ -45,7 +45,7 @@ #define PFX "powernow-k8: " #define BFX PFX "BIOS error: " -#define VERSION "version 1.50.5" +#define VERSION "version 1.60.0" #include "powernow-k8.h" /* serialize freq changes */ @@ -336,7 +336,7 @@ static int core_voltage_pre_transition(struct powernow_k8_data *data, u32 reqvid /* Phase 2 - core frequency transition */ static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid) { - u32 vcoreqfid, vcocurrfid, vcofiddiff, savevid = data->currvid; + u32 vcoreqfid, vcocurrfid, vcofiddiff, fid_interval, savevid = data->currvid; if ((reqfid < HI_FID_TABLE_BOTTOM) && (data->currfid < HI_FID_TABLE_BOTTOM)) { printk(KERN_ERR PFX "ph2: illegal lo-lo transition 0x%x 0x%x\n", @@ -359,9 +359,11 @@ static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid) : vcoreqfid - vcocurrfid; while (vcofiddiff > 2) { + (data->currfid & 1) ? (fid_interval = 1) : (fid_interval = 2); + if (reqfid > data->currfid) { if (data->currfid > LO_FID_TABLE_TOP) { - if (write_new_fid(data, data->currfid + 2)) { + if (write_new_fid(data, data->currfid + fid_interval)) { return 1; } } else { @@ -371,7 +373,7 @@ static int core_frequency_transition(struct powernow_k8_data *data, u32 reqfid) } } } else { - if (write_new_fid(data, data->currfid - 2)) + if (write_new_fid(data, data->currfid - fid_interval)) return 1; } @@ -474,7 +476,7 @@ static int check_supported_cpu(unsigned int cpu) eax = cpuid_eax(CPUID_PROCESSOR_SIGNATURE); if (((eax & CPUID_USE_XFAM_XMOD) != CPUID_USE_XFAM_XMOD) || ((eax & CPUID_XFAM) != CPUID_XFAM_K8) || - ((eax & CPUID_XMOD) > CPUID_XMOD_REV_F)) { + ((eax & CPUID_XMOD) > CPUID_XMOD_REV_G)) { printk(KERN_INFO PFX "Processor cpuid %x not supported\n", eax); goto out; } @@ -521,10 +523,6 @@ static int check_pst_table(struct powernow_k8_data *data, struct pst_s *pst, u8 printk(KERN_ERR BFX "maxfid exceeded with pstate %d\n", j); return -ENODEV; } - if (pst[j].fid & 1) { - printk(KERN_ERR BFX "fid invalid - %d : 0x%x\n", j, pst[j].fid); - return -EINVAL; - } if (j && (pst[j].fid < HI_FID_TABLE_BOTTOM)) { /* Only first fid is allowed to be in "low" range */ printk(KERN_ERR BFX "two low fids - %d : 0x%x\n", j, pst[j].fid); @@ -1177,4 +1175,3 @@ MODULE_LICENSE("GPL"); late_initcall(powernowk8_init); module_exit(powernowk8_exit); - diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h index b1e85bb36396..d0de37d58e9a 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.h +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.h @@ -42,7 +42,7 @@ 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_F 0x00040000 +#define CPUID_XMOD_REV_G 0x00060000 #define CPUID_USE_XFAM_XMOD 0x00000f00 #define CPUID_GET_MAX_CAPABILITIES 0x80000000 #define CPUID_FREQ_VOLT_CAPABILITIES 0x80000007 @@ -86,13 +86,14 @@ struct powernow_k8_data { * low fid table * - lowest entry in the high fid table must be a <= 200MHz + 2 * the entry * in the low fid table - * - the parts can only step at 200 MHz intervals, so 1.9 GHz is never valid + * - the parts can only step at <= 200 MHz intervals, odd fid values are + * supported in revision G and later revisions. * - lowest frequency must be >= interprocessor hypertransport link speed * (only applies to MP systems obviously) */ /* fids (frequency identifiers) are arranged in 2 tables - lo and hi */ -#define LO_FID_TABLE_TOP 6 /* fid values marking the boundary */ +#define LO_FID_TABLE_TOP 7 /* fid values marking the boundary */ #define HI_FID_TABLE_BOTTOM 8 /* between the low and high tables */ #define LO_VCOFREQ_TABLE_TOP 1400 /* corresponding vco frequency values */ @@ -106,7 +107,7 @@ struct powernow_k8_data { #define MIN_FREQ 800 /* Min and max freqs, per spec */ #define MAX_FREQ 5000 -#define INVALID_FID_MASK 0xffffffc1 /* not a valid fid if these bits are set */ +#define INVALID_FID_MASK 0xffffffc0 /* not a valid fid if these bits are set */ #define INVALID_VID_MASK 0xffffffc0 /* not a valid vid if these bits are set */ #define VID_OFF 0x3f -- cgit v1.2.2 From 6df8900676c3f5c133328332fb8ad889fd0cc9e3 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Wed, 30 Nov 2005 13:33:30 -0800 Subject: [CPUFREQ] Fix indentation in powernow-k8 Signed-off-by: Dave Jones --- arch/i386/kernel/cpu/cpufreq/powernow-k8.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c index a342b32c0843..f44c1b1b04e9 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c @@ -216,10 +216,10 @@ static int write_new_vid(struct powernow_k8_data *data, u32 vid) do { wrmsr(MSR_FIDVID_CTL, lo, STOP_GRANT_5NS); - if (i++ > 100) { - printk(KERN_ERR PFX "internal error - pending bit very stuck - no further pstate changes possible\n"); - return 1; - } + if (i++ > 100) { + printk(KERN_ERR PFX "internal error - pending bit very stuck - no further pstate changes possible\n"); + return 1; + } } while (query_current_values_with_pending_wait(data)); if (savefid != data->currfid) { -- cgit v1.2.2 From d4921914de19339d7cd987d2ed6d48754821f41a Mon Sep 17 00:00:00 2001 From: "Gabriel A. Devenyi" Date: Thu, 1 Dec 2005 01:09:22 -0800 Subject: [PATCH] cpufreq-nforce2.c fix u32<0 test Thanks to LinuxICC (http://linuxicc.sf.net), a comparison of a u32 less than 0 was found, this patch changes the variable to a signed int so that comparison is meaningful. Signed-off-by: Gabriel A. Devenyi Signed-off-by: Andrew Morton Signed-off-by: Dave Jones --- arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c b/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c index 04a405345203..2b62dee35c6c 100644 --- a/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c +++ b/arch/i386/kernel/cpu/cpufreq/cpufreq-nforce2.c @@ -177,9 +177,10 @@ static unsigned int nforce2_fsb_read(int bootfsb) */ static int nforce2_set_fsb(unsigned int fsb) { - u32 pll, temp = 0; + u32 temp = 0; unsigned int tfsb; int diff; + int pll = 0; if ((fsb > max_fsb) || (fsb < NFORCE2_MIN_FSB)) { printk(KERN_ERR "cpufreq: FSB %d is out of range!\n", fsb); -- cgit v1.2.2 From cc6e8de8f0fab61760bb7091fb19eef1406e17be Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Tue, 6 Dec 2005 15:03:55 -0800 Subject: [CPUFREQ] Change loglevels on powernow-k8 bios error printk's. If a user has booted with 'quiet', some important messages don't get displayed which really should. We've seen at least one case where powernow-k8 stopped working, and the user needed a BIOS update that they didn't know about. Signed-off-by: Dave Jones --- arch/i386/kernel/cpu/cpufreq/powernow-k8.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c index f44c1b1b04e9..0fbbd4c1072e 100644 --- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c +++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c @@ -635,7 +635,7 @@ static int find_psb_table(struct powernow_k8_data *data) dprintk("table vers: 0x%x\n", psb->tableversion); if (psb->tableversion != PSB_VERSION_1_4) { - printk(KERN_INFO BFX "PSB table is not v1.4\n"); + printk(KERN_ERR BFX "PSB table is not v1.4\n"); return -ENODEV; } @@ -693,7 +693,7 @@ static int find_psb_table(struct powernow_k8_data *data) * BIOS and Kernel Developer's Guide, which is available on * www.amd.com */ - printk(KERN_INFO PFX "BIOS error - no PSB or ACPI _PSS objects\n"); + printk(KERN_ERR PFX "BIOS error - no PSB or ACPI _PSS objects\n"); return -ENODEV; } -- cgit v1.2.2 From 1a10760c91c394dfe4adfefeeaf85cd8098c4894 Mon Sep 17 00:00:00 2001 From: Mattia Dongili Date: Fri, 2 Dec 2005 21:59:41 +0100 Subject: [CPUFREQ] Measure transition latency at driver initialization The attached patch introduces runtime latency measurement for ICH[234] based chipsets instead of using CPUFREQ_ETERNAL. It includes some sanity checks in case the measured value is out of range and assigns a safe value of 500uSec that should still be enough on problematics chipsets (current testing report values ~200uSec). The measurement is currently done in speedstep_get_freqs in order to avoid further unnecessary transitions and in the hope it'll come handy for SMI also. Signed-off-by: Mattia Dongili Acked-by: Dominik Brodowski Signed-off-by: Dave Jones speedstep-ich.c | 4 ++-- speedstep-lib.c | 32 +++++++++++++++++++++++++++++++- speedstep-lib.h | 1 + speedstep-smi.c | 1 + 4 files changed, 35 insertions(+), 3 deletions(-) --- arch/i386/kernel/cpu/cpufreq/speedstep-ich.c | 4 ++-- arch/i386/kernel/cpu/cpufreq/speedstep-lib.c | 32 +++++++++++++++++++++++++++- arch/i386/kernel/cpu/cpufreq/speedstep-lib.h | 1 + arch/i386/kernel/cpu/cpufreq/speedstep-smi.c | 1 + 4 files changed, 35 insertions(+), 3 deletions(-) (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c index 5b7d18a06afa..862e0b5656b9 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c @@ -315,10 +315,11 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) cpus_allowed = current->cpus_allowed; set_cpus_allowed(current, policy->cpus); - /* detect low and high frequency */ + /* detect low and high frequency and transition latency */ result = speedstep_get_freqs(speedstep_processor, &speedstep_freqs[SPEEDSTEP_LOW].frequency, &speedstep_freqs[SPEEDSTEP_HIGH].frequency, + &policy->cpuinfo.transition_latency, &speedstep_set_state); set_cpus_allowed(current, cpus_allowed); if (result) @@ -335,7 +336,6 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) /* cpuinfo and default policy values */ policy->governor = CPUFREQ_DEFAULT_GOVERNOR; - policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL; policy->cur = speed; result = cpufreq_frequency_table_cpuinfo(policy, speedstep_freqs); diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c index d368b3f5fce8..7c47005a1805 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c @@ -320,11 +320,13 @@ EXPORT_SYMBOL_GPL(speedstep_detect_processor); unsigned int speedstep_get_freqs(unsigned int processor, unsigned int *low_speed, unsigned int *high_speed, + unsigned int *transition_latency, void (*set_state) (unsigned int state)) { unsigned int prev_speed; unsigned int ret = 0; unsigned long flags; + struct timeval tv1, tv2; if ((!processor) || (!low_speed) || (!high_speed) || (!set_state)) return -EINVAL; @@ -337,7 +339,7 @@ unsigned int speedstep_get_freqs(unsigned int processor, return -EIO; dprintk("previous speed is %u\n", prev_speed); - + local_irq_save(flags); /* switch to low state */ @@ -350,8 +352,17 @@ unsigned int speedstep_get_freqs(unsigned int processor, dprintk("low speed is %u\n", *low_speed); + /* start latency measurement */ + if (transition_latency) + do_gettimeofday(&tv1); + /* switch to high state */ set_state(SPEEDSTEP_HIGH); + + /* end latency measurement */ + if (transition_latency) + do_gettimeofday(&tv2); + *high_speed = speedstep_get_processor_frequency(processor); if (!*high_speed) { ret = -EIO; @@ -369,6 +380,25 @@ unsigned int speedstep_get_freqs(unsigned int processor, if (*high_speed != prev_speed) set_state(SPEEDSTEP_LOW); + if (transition_latency) { + *transition_latency = (tv2.tv_sec - tv1.tv_sec) * USEC_PER_SEC + + tv2.tv_usec - tv1.tv_usec; + dprintk("transition latency is %u uSec\n", *transition_latency); + + /* convert uSec to nSec and add 20% for safety reasons */ + *transition_latency *= 1200; + + /* check if the latency measurement is too high or too low + * and set it to a safe value (500uSec) in that case + */ + if (*transition_latency > 10000000 || *transition_latency < 50000) { + printk (KERN_WARNING "speedstep: frequency transition measured seems out of " + "range (%u nSec), falling back to a safe one of %u nSec.\n", + *transition_latency, 500000); + *transition_latency = 500000; + } + } + out: local_irq_restore(flags); return (ret); diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h index 261a2c9b7f6b..6a727fd3a77e 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-lib.h @@ -44,4 +44,5 @@ extern unsigned int speedstep_get_processor_frequency(unsigned int processor); extern unsigned int speedstep_get_freqs(unsigned int processor, unsigned int *low_speed, unsigned int *high_speed, + unsigned int *transition_latency, void (*set_state) (unsigned int state)); diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c index 2718fb6f6aba..28cc5d524afc 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-smi.c @@ -269,6 +269,7 @@ static int speedstep_cpu_init(struct cpufreq_policy *policy) result = speedstep_get_freqs(speedstep_processor, &speedstep_freqs[SPEEDSTEP_LOW].frequency, &speedstep_freqs[SPEEDSTEP_HIGH].frequency, + NULL, &speedstep_set_state); if (result) { -- cgit v1.2.2 From 9a7d82a89a8bf55b112f2a5c3b3f405eb95a4303 Mon Sep 17 00:00:00 2001 From: Mattia Dongili Date: Wed, 30 Nov 2005 22:00:59 +0100 Subject: [CPUFREQ] Move PMBASE reading away and do it only once at initialization time This patch moves away PMBASE reading and only performs it at cpufreq_register_driver time by exiting with -ENODEV if unable to read the value. Signed-off-by: Mattia Dongili Acked-by: Dominik Brodowski Signed-off-by: Dave Jones --- arch/i386/kernel/cpu/cpufreq/speedstep-ich.c | 43 +++++++++++++++++++--------- 1 file changed, 30 insertions(+), 13 deletions(-) (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c index 862e0b5656b9..b425cd3d1838 100644 --- a/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c +++ b/arch/i386/kernel/cpu/cpufreq/speedstep-ich.c @@ -40,6 +40,7 @@ static struct pci_dev *speedstep_chipset_dev; */ static unsigned int speedstep_processor = 0; +static u32 pmbase; /* * There are only two frequency states for each processor. Values @@ -56,34 +57,47 @@ static struct cpufreq_frequency_table speedstep_freqs[] = { /** - * speedstep_set_state - set the SpeedStep state - * @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH) + * speedstep_find_register - read the PMBASE address * - * Tries to change the SpeedStep state. + * Returns: -ENODEV if no register could be found */ -static void speedstep_set_state (unsigned int state) +static int speedstep_find_register (void) { - u32 pmbase; - u8 pm2_blk; - u8 value; - unsigned long flags; - - if (!speedstep_chipset_dev || (state > 0x1)) - return; + if (!speedstep_chipset_dev) + return -ENODEV; /* get PMBASE */ pci_read_config_dword(speedstep_chipset_dev, 0x40, &pmbase); if (!(pmbase & 0x01)) { printk(KERN_ERR "speedstep-ich: could not find speedstep register\n"); - return; + return -ENODEV; } pmbase &= 0xFFFFFFFE; if (!pmbase) { printk(KERN_ERR "speedstep-ich: could not find speedstep register\n"); - return; + return -ENODEV; } + dprintk("pmbase is 0x%x\n", pmbase); + return 0; +} + +/** + * speedstep_set_state - set the SpeedStep state + * @state: new processor frequency state (SPEEDSTEP_LOW or SPEEDSTEP_HIGH) + * + * Tries to change the SpeedStep state. + */ +static void speedstep_set_state (unsigned int state) +{ + u8 pm2_blk; + u8 value; + unsigned long flags; + + if (state > 0x1) + return; + /* Disable IRQs */ local_irq_save(flags); @@ -400,6 +414,9 @@ static int __init speedstep_init(void) return -EINVAL; } + if (speedstep_find_register()) + return -ENODEV; + return cpufreq_register_driver(&speedstep_driver); } -- cgit v1.2.2 From 95235ca2c20ac0b31a8eb39e2d599bcc3e9c9a10 Mon Sep 17 00:00:00 2001 From: Venkatesh Pallipadi Date: Fri, 2 Dec 2005 10:43:20 -0800 Subject: [CPUFREQ] CPU frequency display in /proc/cpuinfo What is the value shown in "cpu MHz" of /proc/cpuinfo when CPUs are capable of changing frequency? Today the answer is: It depends. On i386: SMP kernel - It is always the boot frequency UP kernel - Scales with the frequency change and shows that was last set. On x86_64: There is one single variable cpu_khz that gets written by all the CPUs. So, the frequency set by last CPU will be seen on /proc/cpuinfo of all the CPUs in the system. What you see also depends on whether you have constant_tsc capable CPU or not. On ia64: It is always boot time frequency of a particular CPU that gets displayed. The patch below changes this to: Show the last known frequency of the particular CPU, when cpufreq is present. If cpu doesnot support changing of frequency through cpufreq, then boot frequency will be shown. The patch affects i386, x86_64 and ia64 architectures. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Dave Jones --- arch/i386/kernel/cpu/proc.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/cpu/proc.c b/arch/i386/kernel/cpu/proc.c index e7921315ae9d..6d91b274589c 100644 --- a/arch/i386/kernel/cpu/proc.c +++ b/arch/i386/kernel/cpu/proc.c @@ -3,6 +3,7 @@ #include #include #include +#include /* * Get CPU information for use by the procfs. @@ -86,8 +87,11 @@ static int show_cpuinfo(struct seq_file *m, void *v) seq_printf(m, "stepping\t: unknown\n"); if ( cpu_has(c, X86_FEATURE_TSC) ) { + unsigned int freq = cpufreq_quick_get(n); + if (!freq) + freq = cpu_khz; seq_printf(m, "cpu MHz\t\t: %u.%03u\n", - cpu_khz / 1000, (cpu_khz % 1000)); + freq / 1000, (freq % 1000)); } /* Cache size */ -- cgit v1.2.2 From 82584ef75b7c14f22028595b0e8aa904464c5240 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Mon, 12 Dec 2005 00:37:02 -0800 Subject: [PATCH] x86: fix NMI with CPU hotplug With CPU hotplug enabled, NMI watchdog stoped working. It appears the violation is the cpu_online check in nmi handler. local ACPI based NMI watchdog is initialized before we set CPU online for APs. It's quite possible a NMI is fired before we set CPU online, and that's what happens here. Signed-off-by: Shaohua Li Acked-by: Zwane Mwaikambo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/traps.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index c34d1bfc5161..f0dffa03fbba 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -650,13 +650,6 @@ fastcall void do_nmi(struct pt_regs * regs, long error_code) cpu = smp_processor_id(); -#ifdef CONFIG_HOTPLUG_CPU - if (!cpu_online(cpu)) { - nmi_exit(); - return; - } -#endif - ++nmi_count(cpu); if (!rcu_dereference(nmi_callback)(regs, cpu)) -- cgit v1.2.2 From bf8d5c52c3b6b27061e3b7d779057fd9a6cac164 Mon Sep 17 00:00:00 2001 From: Keshavamurthy Anil S Date: Mon, 12 Dec 2005 00:37:34 -0800 Subject: [PATCH] kprobes: increment kprobe missed count for multiprobes When multiple probes are registered at the same address and if due to some recursion (probe getting triggered within a probe handler), we skip calling pre_handlers and just increment nmissed field. The below patch make sure it walks the list for multiple probes case. Without the below patch we get incorrect results of nmissed count for multiple probe case. Signed-off-by: Anil S Keshavamurthy Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/kprobes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c index 32b0c24ab9a6..19edcd526ba4 100644 --- a/arch/i386/kernel/kprobes.c +++ b/arch/i386/kernel/kprobes.c @@ -191,7 +191,7 @@ static int __kprobes kprobe_handler(struct pt_regs *regs) */ save_previous_kprobe(kcb); set_current_kprobe(p, regs, kcb); - p->nmissed++; + kprobes_inc_nmissed_count(p); prepare_singlestep(p, regs); kcb->kprobe_status = KPROBE_REENTER; return 1; -- cgit v1.2.2 From 5e9ef02ec00c70840661d174dc2f4862db471bb6 Mon Sep 17 00:00:00 2001 From: Shaohua Li Date: Mon, 12 Dec 2005 22:17:08 -0800 Subject: [PATCH] i386/x86-64 disable LAPIC completely for offline CPU Disabling LAPIC timer isn't sufficient. In some situations, such as we enabled NMI watchdog, there is still unexpected interrupt (such as NMI) invoked in offline CPU. This also avoids offline CPU receives spurious interrupt and anything similar. Signed-off-by: Shaohua Li Signed-off-by: Andi Kleen Acked-by: "Seth, Rohit" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/smpboot.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index d16520da4550..9ed449af8e9f 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -1338,8 +1338,7 @@ int __cpu_disable(void) if (cpu == 0) return -EBUSY; - /* We enable the timer again on the exit path of the death loop */ - disable_APIC_timer(); + clear_local_APIC(); /* Allow any queued timer interrupts to get serviced */ local_irq_enable(); mdelay(1); -- cgit v1.2.2 From 557962a926c62a9c4bd79d6b36df873d4f8c51ef Mon Sep 17 00:00:00 2001 From: Stas Sergeev Date: Sun, 1 Jan 2006 04:18:52 +0300 Subject: [PATCH] x86: teach dump_task_regs() about the -8 offset. This should fix multi-threaded core-files Signed-off-by: stsp@aknet.ru Signed-off-by: Linus Torvalds --- arch/i386/kernel/process.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index df6c2bcde067..2333aead0563 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -554,7 +554,9 @@ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs) struct pt_regs ptregs; ptregs = *(struct pt_regs *) - ((unsigned long)tsk->thread_info+THREAD_SIZE - sizeof(ptregs)); + ((unsigned long)tsk->thread_info + + /* see comments in copy_thread() about -8 */ + THREAD_SIZE - sizeof(ptregs) - 8); ptregs.xcs &= 0xffff; ptregs.xds &= 0xffff; ptregs.xes &= 0xffff; -- cgit v1.2.2 From 631b034724364b413e8a52e7c2e03a9d77e4c2b4 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert <76306.1226@compuserve.com> Date: Tue, 3 Jan 2006 22:36:14 -0500 Subject: [PATCH] i386: "invalid operand" -> "invalid opcode" According to the manual, INT 6 is "invalid opcode", not "invalid operand". Signed-off-by: Chuck Ebbert <76306.1226@compuserve.com> Signed-off-by: Linus Torvalds --- arch/i386/kernel/traps.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index f0dffa03fbba..ab0e9430f775 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -452,7 +452,7 @@ DO_VM86_ERROR( 3, SIGTRAP, "int3", int3) #endif DO_VM86_ERROR( 4, SIGSEGV, "overflow", overflow) DO_VM86_ERROR( 5, SIGSEGV, "bounds", bounds) -DO_ERROR_INFO( 6, SIGILL, "invalid operand", invalid_op, ILL_ILLOPN, regs->eip) +DO_ERROR_INFO( 6, SIGILL, "invalid opcode", invalid_op, ILL_ILLOPN, regs->eip) DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun) DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS) DO_ERROR(11, SIGBUS, "segment not present", segment_not_present) -- cgit v1.2.2 From 9f155b9802bb7049cd0f216c3fe903b58620df11 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert <76306.1226@compuserve.com> Date: Thu, 5 Jan 2006 23:11:29 -0500 Subject: [PATCH] i386: PTRACE_POKEUSR: allow changing RF bit in EFLAGS register. Setting RF (resume flag) allows a debugger to resume execution after a code breakpoint without tripping the breakpoint again. It is reset by the CPU after execution of one instruction. Requested by Stephane Eranian: "I am trying to the user HW debug registers on i386 and I am running into a problem with ptrace() not allowing access to EFLAGS_RF for POKEUSER (see FLAG_MASK). [ ... ] It avoids the need to remove the breakpoint, single step, and reinstall. The equivalent functionality exists on IA-64 and is allowed by ptrace()" Cc: Stephane Eranian Signed-off-by: Chuck Ebbert <76306.1226@compuserve.com> Signed-off-by: Linus Torvalds --- arch/i386/kernel/ptrace.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c index 5ffbb4b7ad05..5c1fb6aada5b 100644 --- a/arch/i386/kernel/ptrace.c +++ b/arch/i386/kernel/ptrace.c @@ -32,9 +32,12 @@ * in exit.c or in signal.c. */ -/* determines which flags the user has access to. */ -/* 1 = access 0 = no access */ -#define FLAG_MASK 0x00044dd5 +/* + * Determines which flags the user has access to [1 = access, 0 = no access]. + * Prohibits changing ID(21), VIP(20), VIF(19), VM(17), IOPL(12-13), IF(9). + * Also masks reserved bits (31-22, 15, 5, 3, 1). + */ +#define FLAG_MASK 0x00054dd5 /* set's the trap flag. */ #define TRAP_FLAG 0x100 -- cgit v1.2.2 From 7c4cb60e5b97677424e95baee9c29df54b26e6ba Mon Sep 17 00:00:00 2001 From: Zachary Amsden Date: Fri, 6 Jan 2006 00:11:47 -0800 Subject: [PATCH] x86: GDT alignment fix Make GDT page aligned and page padded to support running inside of a hypervisor. This prevents false sharing of the GDT page with other hot data, which is not allowed in Xen, and causes performance problems in VMware. Rather than go back to the old method of statically allocating the GDT (which wastes unneded space for non-present CPUs), the GDT for APs is allocated dynamically. Signed-off-by: Zachary Amsden Cc: "Seth, Rohit" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/apm.c | 2 ++ arch/i386/kernel/cpu/common.c | 3 --- arch/i386/kernel/head.S | 2 ++ arch/i386/kernel/i386_ksyms.c | 3 +-- arch/i386/kernel/smpboot.c | 6 ++++++ 5 files changed, 11 insertions(+), 5 deletions(-) (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c index 1e60acbed3c1..6c8e483ce9e4 100644 --- a/arch/i386/kernel/apm.c +++ b/arch/i386/kernel/apm.c @@ -2317,6 +2317,8 @@ static int __init apm_init(void) for (i = 0; i < NR_CPUS; i++) { struct desc_struct *gdt = get_cpu_gdt_table(i); + if (!gdt) + continue; set_base(gdt[APM_CS >> 3], __va((unsigned long)apm_info.bios.cseg << 4)); set_base(gdt[APM_CS_16 >> 3], diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c index 31e344b26bae..cbc32069683f 100644 --- a/arch/i386/kernel/cpu/common.c +++ b/arch/i386/kernel/cpu/common.c @@ -18,9 +18,6 @@ #include "cpu.h" -DEFINE_PER_CPU(struct desc_struct, cpu_gdt_table[GDT_ENTRIES]); -EXPORT_PER_CPU_SYMBOL(cpu_gdt_table); - DEFINE_PER_CPU(unsigned char, cpu_16bit_stack[CPU_16BIT_STACK_SIZE]); EXPORT_PER_CPU_SYMBOL(cpu_16bit_stack); diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S index e437fb367498..870f20bf33c8 100644 --- a/arch/i386/kernel/head.S +++ b/arch/i386/kernel/head.S @@ -525,3 +525,5 @@ ENTRY(cpu_gdt_table) .quad 0x0000000000000000 /* 0xf0 - unused */ .quad 0x0000000000000000 /* 0xf8 - GDT entry 31: double-fault TSS */ + /* Be sure this is zeroed to avoid false validations in Xen */ + .fill PAGE_SIZE_asm / 8 - GDT_ENTRIES,8,0 diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c index 180f070d03cb..3999bec50c33 100644 --- a/arch/i386/kernel/i386_ksyms.c +++ b/arch/i386/kernel/i386_ksyms.c @@ -3,8 +3,7 @@ #include #include -/* This is definitely a GPL-only symbol */ -EXPORT_SYMBOL_GPL(cpu_gdt_table); +EXPORT_SYMBOL_GPL(cpu_gdt_descr); EXPORT_SYMBOL(__down_failed); EXPORT_SYMBOL(__down_failed_interruptible); diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c index 9ed449af8e9f..b3c2e2c26743 100644 --- a/arch/i386/kernel/smpboot.c +++ b/arch/i386/kernel/smpboot.c @@ -903,6 +903,12 @@ static int __devinit do_boot_cpu(int apicid, int cpu) unsigned long start_eip; unsigned short nmi_high = 0, nmi_low = 0; + if (!cpu_gdt_descr[cpu].address && + !(cpu_gdt_descr[cpu].address = get_zeroed_page(GFP_KERNEL))) { + printk("Failed to allocate GDT for CPU %d\n", cpu); + return 1; + } + ++cpucount; /* -- cgit v1.2.2 From e43d674f44dc885a2476cab3537e639d9eaa31a9 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Fri, 6 Jan 2006 00:11:48 -0800 Subject: [PATCH] i386: don't blindly enable interrupts in die() Rather than blindly re-enabling interrupts in die(), save their state upon entry and then restore that state. If the kernel is in really bad condition and faults with interrupts disabled, re-enabling them in die() may cause even more trouble, implying more chances of data corruption. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/traps.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index ab0e9430f775..bb36a989db77 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -306,14 +306,17 @@ void die(const char * str, struct pt_regs * regs, long err) .lock_owner_depth = 0 }; static int die_counter; + unsigned long flags; if (die.lock_owner != raw_smp_processor_id()) { console_verbose(); - spin_lock_irq(&die.lock); + spin_lock_irqsave(&die.lock, flags); die.lock_owner = smp_processor_id(); die.lock_owner_depth = 0; bust_spinlocks(1); } + else + local_save_flags(flags); if (++die.lock_owner_depth < 3) { int nl = 0; @@ -340,7 +343,7 @@ void die(const char * str, struct pt_regs * regs, long err) bust_spinlocks(0); die.lock_owner = -1; - spin_unlock_irq(&die.lock); + spin_unlock_irqrestore(&die.lock, flags); if (kexec_should_crash(current)) crash_kexec(regs); -- cgit v1.2.2 From d43c6e8083ac8baeb1a167510aea34fcef396e33 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Fri, 6 Jan 2006 00:11:49 -0800 Subject: [PATCH] i386: move SIMD initialization Move some code unrelated to any dealing with hardware bugs from i386's bugs.h to a more logical place. Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/traps.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index bb36a989db77..f0c4060bd4d5 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -1098,6 +1098,28 @@ void __init trap_init(void) #endif set_trap_gate(19,&simd_coprocessor_error); + if (cpu_has_fxsr) { + /* + * Verify that the FXSAVE/FXRSTOR data will be 16-byte aligned. + * Generates a compile-time "error: zero width for bit-field" if + * the alignment is wrong. + */ + struct fxsrAlignAssert { + int _:!(offsetof(struct task_struct, + thread.i387.fxsave) & 15); + }; + + printk(KERN_INFO "Enabling fast FPU save and restore... "); + set_in_cr4(X86_CR4_OSFXSR); + printk("done.\n"); + } + if (cpu_has_xmm) { + printk(KERN_INFO "Enabling unmasked SIMD FPU exception " + "support... "); + set_in_cr4(X86_CR4_OSXMMEXCPT); + printk("done.\n"); + } + set_system_gate(SYSCALL_VECTOR,&system_call); /* -- cgit v1.2.2 From eb05c3249a8e8a675e79d221f4a0874dc10ec903 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Fri, 6 Jan 2006 00:11:49 -0800 Subject: [PATCH] i386: fix bound check IDT gate Other than apparently commonly assumed, the bound instruction does not require the corresponding IDT entry to have DPL 3. Acked-by: "Seth, Rohit" Acked-by: Zachary Amsden Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/traps.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index f0c4060bd4d5..53ad954e3ba4 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -1078,9 +1078,9 @@ void __init trap_init(void) set_trap_gate(0,÷_error); set_intr_gate(1,&debug); set_intr_gate(2,&nmi); - set_system_intr_gate(3, &int3); /* int3-5 can be called from all */ + set_system_intr_gate(3, &int3); /* int3/4 can be called from all */ set_system_gate(4,&overflow); - set_system_gate(5,&bounds); + set_trap_gate(5,&bounds); set_trap_gate(6,&invalid_op); set_trap_gate(7,&device_not_available); set_task_gate(8,GDT_ENTRY_DOUBLEFAULT_TSS); -- cgit v1.2.2 From ff6e8c0d5e47f0ceeebde86ec2f5919dbd5beb67 Mon Sep 17 00:00:00 2001 From: Zachary Amsden Date: Fri, 6 Jan 2006 00:11:50 -0800 Subject: [PATCH] x86: Cr4 is valid on some 486s So some 486 processors do have CR4 register. Allow them to present it in register dumps by using the old fault technique rather than testing processor family. Thanks to Maciej for noticing this. Signed-off-by: Zachary Amsden Cc: "Seth, Rohit" Cc: Stephen Rothwell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/process.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index 2333aead0563..6081a10d3416 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -308,9 +308,7 @@ void show_regs(struct pt_regs * regs) cr0 = read_cr0(); cr2 = read_cr2(); cr3 = read_cr3(); - if (current_cpu_data.x86 > 4) { - cr4 = read_cr4(); - } + cr4 = read_cr4_safe(); printk("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", cr0, cr2, cr3, cr4); show_trace(NULL, ®s->esp); } -- cgit v1.2.2 From 3012d2d209580c78b5927d55c60a10891be8befd Mon Sep 17 00:00:00 2001 From: Zachary Amsden Date: Fri, 6 Jan 2006 00:11:53 -0800 Subject: [PATCH] x86: Always relax segments APM BIOSes have many bugs regarding proper representation of the appropriate segment limits for calling the BIOS. By default, APM_RELAX_SEGMENTS is always turned on to support running the APM BIOS on these buggy machines. Keeping 64k limits poses very little danger to the kernel, because the pages where the APM BIOS is located will always be in low physical memory BIOS areas, which should already be marked reserved, and only buggy BIOSes would possibly overstep the segment bounds with writes to data anyway. Since forcing stricter limits breaks many machines and is not default behavior, it seems reasonable to deprecate the older code which may cause APM BIOS to fault. If you really have a badly enough broken APM BIOS that you have to turn off APM_RELAX_SEGMENTS, seems like the best recourse here would be to disable the APM BIOS and / or not compile it into your kernel to begin with, and / or add your system to the known bad list. The reason I want to deprecate this code is there is underlying brokenness with the set_limit macros, and getting rid of many of the call sites rather than rewriting them seems to be the simplest and most correct course of action. Signed-off-by: Zachary Amsden Acked-by: "Seth, Rohit" Cc: Stephen Rothwell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/apm.c | 55 ++++++++++++++++---------------------------------- 1 file changed, 17 insertions(+), 38 deletions(-) (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c index 6c8e483ce9e4..0d2981120cd6 100644 --- a/arch/i386/kernel/apm.c +++ b/arch/i386/kernel/apm.c @@ -302,17 +302,6 @@ extern int (*console_blank_hook)(int); #include "apm.h" -/* - * Define to make all _set_limit calls use 64k limits. The APM 1.1 BIOS is - * supposed to provide limit information that it recognizes. Many machines - * do this correctly, but many others do not restrict themselves to their - * claimed limit. When this happens, they will cause a segmentation - * violation in the kernel at boot time. Most BIOS's, however, will - * respect a 64k limit, so we use that. If you want to be pedantic and - * hold your BIOS to its claims, then undefine this. - */ -#define APM_RELAX_SEGMENTS - /* * Define to re-initialize the interrupt 0 timer to 100 Hz after a suspend. * This patched by Chad Miller , original code by @@ -2312,9 +2301,20 @@ static int __init apm_init(void) set_base(bad_bios_desc, __va((unsigned long)0x40 << 4)); _set_limit((char *)&bad_bios_desc, 4095 - (0x40 << 4)); + /* + * Set up the long jump entry point to the APM BIOS, which is called + * from inline assembly. + */ apm_bios_entry.offset = apm_info.bios.offset; apm_bios_entry.segment = APM_CS; + /* + * The APM 1.1 BIOS is supposed to provide limit information that it + * recognizes. Many machines do this correctly, but many others do + * not restrict themselves to their claimed limit. When this happens, + * they will cause a segmentation violation in the kernel at boot time. + * Most BIOS's, however, will respect a 64k limit, so we use that. + */ for (i = 0; i < NR_CPUS; i++) { struct desc_struct *gdt = get_cpu_gdt_table(i); if (!gdt) @@ -2325,33 +2325,12 @@ static int __init apm_init(void) __va((unsigned long)apm_info.bios.cseg_16 << 4)); set_base(gdt[APM_DS >> 3], __va((unsigned long)apm_info.bios.dseg << 4)); -#ifndef APM_RELAX_SEGMENTS - if (apm_info.bios.version == 0x100) { -#endif - /* For ASUS motherboard, Award BIOS rev 110 (and others?) */ - _set_limit((char *)&gdt[APM_CS >> 3], 64 * 1024 - 1); - /* For some unknown machine. */ - _set_limit((char *)&gdt[APM_CS_16 >> 3], 64 * 1024 - 1); - /* For the DEC Hinote Ultra CT475 (and others?) */ - _set_limit((char *)&gdt[APM_DS >> 3], 64 * 1024 - 1); -#ifndef APM_RELAX_SEGMENTS - } else { - _set_limit((char *)&gdt[APM_CS >> 3], - (apm_info.bios.cseg_len - 1) & 0xffff); - _set_limit((char *)&gdt[APM_CS_16 >> 3], - (apm_info.bios.cseg_16_len - 1) & 0xffff); - _set_limit((char *)&gdt[APM_DS >> 3], - (apm_info.bios.dseg_len - 1) & 0xffff); - /* workaround for broken BIOSes */ - if (apm_info.bios.cseg_len <= apm_info.bios.offset) - _set_limit((char *)&gdt[APM_CS >> 3], 64 * 1024 -1); - if (apm_info.bios.dseg_len <= 0x40) { /* 0x40 * 4kB == 64kB */ - /* for the BIOS that assumes granularity = 1 */ - gdt[APM_DS >> 3].b |= 0x800000; - printk(KERN_NOTICE "apm: we set the granularity of dseg.\n"); - } - } -#endif + /* For ASUS motherboard, Award BIOS rev 110 (and others?) */ + _set_limit((char *)&gdt[APM_CS >> 3], 64 * 1024 - 1); + /* For some unknown machine. */ + _set_limit((char *)&gdt[APM_CS_16 >> 3], 64 * 1024 - 1); + /* For the DEC Hinote Ultra CT475 (and others?) */ + _set_limit((char *)&gdt[APM_DS >> 3], 64 * 1024 - 1); } apm_proc = create_proc_info_entry("apm", 0, NULL, apm_get_info); -- cgit v1.2.2 From 99022c4695d3f45fcf7f3827aa46dd2d9e53e365 Mon Sep 17 00:00:00 2001 From: Zachary Amsden Date: Fri, 6 Jan 2006 00:11:53 -0800 Subject: [PATCH] x86: Apm seg in gdt Since APM BIOS segment limits are now fixed, set them in head.S GDT and don't use the complicated _set_limit() macro expansion. Signed-off-by: Zachary Amsden Acked-by: "Seth, Rohit" Cc: Stephen Rothwell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/apm.c | 6 ------ arch/i386/kernel/head.S | 9 +++++---- 2 files changed, 5 insertions(+), 10 deletions(-) (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c index 0d2981120cd6..45199bb6455b 100644 --- a/arch/i386/kernel/apm.c +++ b/arch/i386/kernel/apm.c @@ -2325,12 +2325,6 @@ static int __init apm_init(void) __va((unsigned long)apm_info.bios.cseg_16 << 4)); set_base(gdt[APM_DS >> 3], __va((unsigned long)apm_info.bios.dseg << 4)); - /* For ASUS motherboard, Award BIOS rev 110 (and others?) */ - _set_limit((char *)&gdt[APM_CS >> 3], 64 * 1024 - 1); - /* For some unknown machine. */ - _set_limit((char *)&gdt[APM_CS_16 >> 3], 64 * 1024 - 1); - /* For the DEC Hinote Ultra CT475 (and others?) */ - _set_limit((char *)&gdt[APM_DS >> 3], 64 * 1024 - 1); } apm_proc = create_proc_info_entry("apm", 0, NULL, apm_get_info); diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S index 870f20bf33c8..37b599fa4d18 100644 --- a/arch/i386/kernel/head.S +++ b/arch/i386/kernel/head.S @@ -510,13 +510,14 @@ ENTRY(cpu_gdt_table) .quad 0x0080920000000000 /* 0xa0 16-bit data */ .quad 0x0080920000000000 /* 0xa8 16-bit data */ .quad 0x0080920000000000 /* 0xb0 16-bit data */ + /* * The APM segments have byte granularity and their bases - * and limits are set at run time. + * are set at run time. All have 64k limits. */ - .quad 0x00409a0000000000 /* 0xb8 APM CS code */ - .quad 0x00009a0000000000 /* 0xc0 APM CS 16 code (16 bit) */ - .quad 0x0040920000000000 /* 0xc8 APM DS data */ + .quad 0x00409a000000ffff /* 0xb8 APM CS code */ + .quad 0x00009a000000ffff /* 0xc0 APM CS 16 code (16 bit) */ + .quad 0x004092000000ffff /* 0xc8 APM DS data */ .quad 0x0000920000000000 /* 0xd0 - ESPFIX 16-bit SS */ .quad 0x0000000000000000 /* 0xd8 - unused */ -- cgit v1.2.2 From 5fe9fe3c6f9a1ae7aa224bb7a66eb9aad9e4abef Mon Sep 17 00:00:00 2001 From: Zachary Amsden Date: Fri, 6 Jan 2006 00:11:55 -0800 Subject: [PATCH] x86: Pnp byte granularity The one remaining caller of set_limit, the PnP BIOS code, calls into the PnP BIOS, passing kernel parameters in and out. These parameteres may be passed from arbitrary kernel virtual memory, so they deserve strict protection to stop a bad BIOS from smashing beyond the object size. Unfortunately, the use of set_limit was badly botching this by setting the limit in terms of pages, when it really should have byte granularity. When doing this, I discovered my BIOS had the buggy code during the "get system device node" call: mov ax, es:[bx] Which is harmless, but has a trivial workaround. Signed-off-by: Zachary Amsden Cc: "Seth, Rohit" Cc: Stephen Rothwell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/head.S | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S index 37b599fa4d18..58d2746670b7 100644 --- a/arch/i386/kernel/head.S +++ b/arch/i386/kernel/head.S @@ -504,12 +504,12 @@ ENTRY(cpu_gdt_table) .quad 0x0000000000000000 /* 0x80 TSS descriptor */ .quad 0x0000000000000000 /* 0x88 LDT descriptor */ - /* Segments used for calling PnP BIOS */ - .quad 0x00c09a0000000000 /* 0x90 32-bit code */ - .quad 0x00809a0000000000 /* 0x98 16-bit code */ - .quad 0x0080920000000000 /* 0xa0 16-bit data */ - .quad 0x0080920000000000 /* 0xa8 16-bit data */ - .quad 0x0080920000000000 /* 0xb0 16-bit data */ + /* Segments used for calling PnP BIOS have byte granularity */ + .quad 0x00409a0000000000 /* 0x90 32-bit code */ + .quad 0x00009a0000000000 /* 0x98 16-bit code */ + .quad 0x0000920000000000 /* 0xa0 16-bit data */ + .quad 0x0000920000000000 /* 0xa8 16-bit data */ + .quad 0x0000920000000000 /* 0xb0 16-bit data */ /* * The APM segments have byte granularity and their bases -- cgit v1.2.2 From e6a9918c9617ed21f71f2f20b45efe06822c8f00 Mon Sep 17 00:00:00 2001 From: Zachary Amsden Date: Fri, 6 Jan 2006 00:11:56 -0800 Subject: [PATCH] x86: Fixed pnp bios limits PnP BIOS data, code, and 32-bit entry segments all have fixed limits as well; set them in the GDT rather than adding more code. It would be nice to add these fixups to the boot GDT rather than setting the GDT for each CPU; perhaps I can wiggle this in later, but getting it in before the subsys init looks tricky. Also, make some progress on deprecating the ugly Q_SET_SEL macros. Signed-off-by: Zachary Amsden Cc: "Seth, Rohit" Cc: Stephen Rothwell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/head.S | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/head.S b/arch/i386/kernel/head.S index 58d2746670b7..5884469f6bfe 100644 --- a/arch/i386/kernel/head.S +++ b/arch/i386/kernel/head.S @@ -504,10 +504,14 @@ ENTRY(cpu_gdt_table) .quad 0x0000000000000000 /* 0x80 TSS descriptor */ .quad 0x0000000000000000 /* 0x88 LDT descriptor */ - /* Segments used for calling PnP BIOS have byte granularity */ - .quad 0x00409a0000000000 /* 0x90 32-bit code */ - .quad 0x00009a0000000000 /* 0x98 16-bit code */ - .quad 0x0000920000000000 /* 0xa0 16-bit data */ + /* + * Segments used for calling PnP BIOS have byte granularity. + * They code segments and data segments have fixed 64k limits, + * the transfer segment sizes are set at run time. + */ + .quad 0x00409a000000ffff /* 0x90 32-bit code */ + .quad 0x00009a000000ffff /* 0x98 16-bit code */ + .quad 0x000092000000ffff /* 0xa0 16-bit data */ .quad 0x0000920000000000 /* 0xa8 16-bit data */ .quad 0x0000920000000000 /* 0xb0 16-bit data */ -- cgit v1.2.2 From 2891dcdc4538e8f4ce50c9d1eea457cf2d81fb5b Mon Sep 17 00:00:00 2001 From: Zachary Amsden Date: Fri, 6 Jan 2006 00:11:57 -0800 Subject: [PATCH] x86: Stop deleting nt Stop deleting NT bit from EFLAGS. See arch/i386/kernel/head.S line 223, which does something even better. Signed-off-by: Zachary Amsden Cc: "Seth, Rohit" Cc: Stephen Rothwell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/cpu/common.c | 5 ----- 1 file changed, 5 deletions(-) (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/cpu/common.c b/arch/i386/kernel/cpu/common.c index cbc32069683f..cca655688ffc 100644 --- a/arch/i386/kernel/cpu/common.c +++ b/arch/i386/kernel/cpu/common.c @@ -595,11 +595,6 @@ void __devinit cpu_init(void) load_gdt(&cpu_gdt_descr[cpu]); load_idt(&idt_descr); - /* - * Delete NT - */ - __asm__("pushfl ; andl $0xffffbfff,(%esp) ; popfl"); - /* * Set up and load the per-CPU TSS and LDT */ -- cgit v1.2.2 From 92f17f0171e864a2cbe448c5b7b473e72a7d27b8 Mon Sep 17 00:00:00 2001 From: Zachary Amsden Date: Fri, 6 Jan 2006 00:11:58 -0800 Subject: [PATCH] x86: Apm is on cpu zero only APM BIOS code has a protective wrapper that runs it only on CPU zero. Thus, no need to set APM BIOS segments in the GDT for other CPUs. Signed-off-by: Zachary Amsden Acked-by: "Seth, Rohit" Cc: Stephen Rothwell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/apm.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c index 45199bb6455b..d0b488056cc4 100644 --- a/arch/i386/kernel/apm.c +++ b/arch/i386/kernel/apm.c @@ -2222,8 +2222,8 @@ static struct dmi_system_id __initdata apm_dmi_table[] = { static int __init apm_init(void) { struct proc_dir_entry *apm_proc; + struct desc_struct *gdt; int ret; - int i; dmi_check_system(apm_dmi_table); @@ -2314,18 +2314,17 @@ static int __init apm_init(void) * not restrict themselves to their claimed limit. When this happens, * they will cause a segmentation violation in the kernel at boot time. * Most BIOS's, however, will respect a 64k limit, so we use that. + * + * Note we only set APM segments on CPU zero, since we pin the APM + * code to that CPU. */ - for (i = 0; i < NR_CPUS; i++) { - struct desc_struct *gdt = get_cpu_gdt_table(i); - if (!gdt) - continue; - set_base(gdt[APM_CS >> 3], - __va((unsigned long)apm_info.bios.cseg << 4)); - set_base(gdt[APM_CS_16 >> 3], - __va((unsigned long)apm_info.bios.cseg_16 << 4)); - set_base(gdt[APM_DS >> 3], - __va((unsigned long)apm_info.bios.dseg << 4)); - } + gdt = get_cpu_gdt_table(0); + set_base(gdt[APM_CS >> 3], + __va((unsigned long)apm_info.bios.cseg << 4)); + set_base(gdt[APM_CS_16 >> 3], + __va((unsigned long)apm_info.bios.cseg_16 << 4)); + set_base(gdt[APM_DS >> 3], + __va((unsigned long)apm_info.bios.dseg << 4)); apm_proc = create_proc_info_entry("apm", 0, NULL, apm_get_info); if (apm_proc) -- cgit v1.2.2 From 2684927c6b938ec7a679891e0ec1fa0709c521bd Mon Sep 17 00:00:00 2001 From: Zachary Amsden Date: Fri, 6 Jan 2006 00:11:59 -0800 Subject: [PATCH] x86: Deprecate useless bug Remove the "temporary debugging check" which has managed to live for quite some time, and is clearly unneeded. The mm can never be live at this point, so clearly checking the LDT in the mm->context is redundant as well. Signed-off-by: Zachary Amsden Cc: "Seth, Rohit" Cc: Stephen Rothwell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/process.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index 6081a10d3416..45e7f0ac4b04 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c @@ -402,17 +402,7 @@ void flush_thread(void) void release_thread(struct task_struct *dead_task) { - if (dead_task->mm) { - // temporary debugging check - if (dead_task->mm->context.size) { - printk("WARNING: dead process %8s still has LDT? <%p/%d>\n", - dead_task->comm, - dead_task->mm->context.ldt, - dead_task->mm->context.size); - BUG(); - } - } - + BUG_ON(dead_task->mm); release_vm86_irqs(dead_task); } -- cgit v1.2.2 From bb152f53120d66c98c1f16518407df6a84f23714 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Fri, 6 Jan 2006 00:12:05 -0800 Subject: [PATCH] x86/x86_64: mark rodata section read-only: make some datastructures const Mark some key kernel datastructures readonly. This patch was previously posted on Jun 28th but was back then not merged because nothing was enforcing rodata anyway.. well that changed now :) Patch by Christoph Lameter and Dave Jones Signed-off-by: Arjan van de Ven Signed-off-by: Ingo Molnar Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/entry.S | 1 + arch/i386/kernel/syscall_table.S | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S index e50b93155249..607c06007508 100644 --- a/arch/i386/kernel/entry.S +++ b/arch/i386/kernel/entry.S @@ -657,6 +657,7 @@ ENTRY(spurious_interrupt_bug) pushl $do_spurious_interrupt_bug jmp error_code +.section .rodata,"a" #include "syscall_table.S" syscall_table_size=(.-sys_call_table) diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S index 9b21a31d4f4e..f7ba4acc20ec 100644 --- a/arch/i386/kernel/syscall_table.S +++ b/arch/i386/kernel/syscall_table.S @@ -1,4 +1,3 @@ -.data ENTRY(sys_call_table) .long sys_restart_syscall /* 0 - old "setup()" system call, used for restarting */ .long sys_exit -- cgit v1.2.2 From 215c3409eed16c89b6d11ea1126bd9d4f36b9afd Mon Sep 17 00:00:00 2001 From: Andy Whitcroft Date: Fri, 6 Jan 2006 00:12:06 -0800 Subject: [PATCH] i386 sparsemem for single node systems Allow SPARSEMEM to be enabled on non-numa x86 systems. This is made dependant on EXPERIMENTAL also being set. When an in-tree user (such as simulated numa) exists it should be made dependant on that. The plan is to have no options and no selector as normal when !EXPERIMENTAL. When EXPERIMENTAL we enable the FLATMEM and SPARSEMEM options for X86_PC whilst maintaining DISCONTIGMEM and SPARSEMEM for NUMA. Signed-off-by: Andy Whitcroft Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/setup.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c index fdfcb0cba9b4..27c956db0461 100644 --- a/arch/i386/kernel/setup.c +++ b/arch/i386/kernel/setup.c @@ -954,6 +954,12 @@ efi_find_max_pfn(unsigned long start, unsigned long end, void *arg) return 0; } +static int __init +efi_memory_present_wrapper(unsigned long start, unsigned long end, void *arg) +{ + memory_present(0, start, end); + return 0; +} /* * Find the highest page frame number we have available @@ -965,6 +971,7 @@ void __init find_max_pfn(void) max_pfn = 0; if (efi_enabled) { efi_memmap_walk(efi_find_max_pfn, &max_pfn); + efi_memmap_walk(efi_memory_present_wrapper, NULL); return; } @@ -979,6 +986,7 @@ void __init find_max_pfn(void) continue; if (end > max_pfn) max_pfn = end; + memory_present(0, start, end); } } -- cgit v1.2.2 From e72c8585e09f127a69a1608bb5ccd1e3fc0dd41e Mon Sep 17 00:00:00 2001 From: Ashok Raj Date: Fri, 6 Jan 2006 00:12:09 -0800 Subject: [PATCH] make bigsmp the default mode if CONFIG_HOTPLUG_CPU If we are using hotplug enabled kernel, then make bigsmp the default mode. Signed-off-by: Ashok Raj Signed-off-by: Venkatesh Pallipadi Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/mpparse.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c index 1ca5269b1e86..91a64016956e 100644 --- a/arch/i386/kernel/mpparse.c +++ b/arch/i386/kernel/mpparse.c @@ -38,6 +38,12 @@ int smp_found_config; unsigned int __initdata maxcpus = NR_CPUS; +#ifdef CONFIG_HOTPLUG_CPU +#define CPU_HOTPLUG_ENABLED (1) +#else +#define CPU_HOTPLUG_ENABLED (0) +#endif + /* * Various Linux-internal data structures created from the * MP-table. @@ -219,14 +225,18 @@ static void __devinit MP_processor_info (struct mpc_config_processor *m) cpu_set(num_processors, cpu_possible_map); num_processors++; - if ((num_processors > 8) && - ((APIC_XAPIC(ver) && - (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL)) || - (boot_cpu_data.x86_vendor == X86_VENDOR_AMD))) - def_to_bigsmp = 1; - else - def_to_bigsmp = 0; - + if (CPU_HOTPLUG_ENABLED || (num_processors > 8)) { + switch (boot_cpu_data.x86_vendor) { + case X86_VENDOR_INTEL: + if (!APIC_XAPIC(ver)) { + def_to_bigsmp = 0; + break; + } + /* If P4 and above fall through */ + case X86_VENDOR_AMD: + def_to_bigsmp = 1; + } + } bios_cpu_apicid[num_processors - 1] = m->mpc_apicid; } -- cgit v1.2.2 From e31b88ba49460653bab87423287bb68743f5de5c Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Fri, 6 Jan 2006 00:12:11 -0800 Subject: [PATCH] x86: missing printk newline in apic boot option parser Missing newline in printk. Signed-off-by: Dave Jones Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/apic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c index 496a2c9909fe..d8f94e78de8a 100644 --- a/arch/i386/kernel/apic.c +++ b/arch/i386/kernel/apic.c @@ -721,7 +721,7 @@ static int __init apic_set_verbosity(char *str) apic_verbosity = APIC_VERBOSE; else printk(KERN_WARNING "APIC Verbosity level %s not recognised" - " use apic=verbose or apic=debug", str); + " use apic=verbose or apic=debug\n", str); return 0; } -- cgit v1.2.2 From 6926d570b6159c6a7f65921ca119a675b12fef86 Mon Sep 17 00:00:00 2001 From: Daniel Marjamaki Date: Fri, 6 Jan 2006 00:12:12 -0800 Subject: [PATCH] arch/i386/kernel/msr.c: removed unused variable Removed the unused variable "rv". Signed-off-by: Daniel Marjamaki Signed-off-by: H. Peter Anvin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/msr.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/msr.c b/arch/i386/kernel/msr.c index 44470fea4309..1d0a55e68760 100644 --- a/arch/i386/kernel/msr.c +++ b/arch/i386/kernel/msr.c @@ -172,7 +172,6 @@ static ssize_t msr_read(struct file *file, char __user * buf, { u32 __user *tmp = (u32 __user *) buf; u32 data[2]; - size_t rv; u32 reg = *ppos; int cpu = iminor(file->f_dentry->d_inode); int err; @@ -180,7 +179,7 @@ static ssize_t msr_read(struct file *file, char __user * buf, if (count % 8) return -EINVAL; /* Invalid chunk size */ - for (rv = 0; count; count -= 8) { + for (; count; count -= 8) { err = do_rdmsr(cpu, reg, &data[0], &data[1]); if (err) return err; -- cgit v1.2.2 From 6b7f430ee0a269464aa29159eb464e647ca313d3 Mon Sep 17 00:00:00 2001 From: Daniel Marjamaki Date: Fri, 6 Jan 2006 00:12:13 -0800 Subject: [PATCH] arch/i386/kernel/cpuid.c: unused variable Removed the unused variable "rv". Signed-off-by: Daniel Marjamaki Signed-off-by: H. Peter Anvin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/cpuid.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/cpuid.c b/arch/i386/kernel/cpuid.c index 13bae799e626..006141d1c12a 100644 --- a/arch/i386/kernel/cpuid.c +++ b/arch/i386/kernel/cpuid.c @@ -117,14 +117,13 @@ static ssize_t cpuid_read(struct file *file, char __user *buf, { char __user *tmp = buf; u32 data[4]; - size_t rv; u32 reg = *ppos; int cpu = iminor(file->f_dentry->d_inode); if (count % 16) return -EINVAL; /* Invalid chunk size */ - for (rv = 0; count; count -= 16) { + for (; count; count -= 16) { do_cpuid(cpu, reg, data); if (copy_to_user(tmp, &data, 16)) return -EFAULT; -- cgit v1.2.2 From f90b8116032f4216d260e31f966a3585319387ac Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Fri, 6 Jan 2006 00:12:14 -0800 Subject: [PATCH] Base support for AMD Geode GX/LX processors Provide basic support for the AMD Geode GX and LX processors. Signed-off-by: Jordan Crouse Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/cpu/amd.c | 7 ++++++- arch/i386/kernel/cpu/cyrix.c | 27 ++++++++++++++++++++++++++- 2 files changed, 32 insertions(+), 2 deletions(-) (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c index e344ef88cfcd..e7697e077f6b 100644 --- a/arch/i386/kernel/cpu/amd.c +++ b/arch/i386/kernel/cpu/amd.c @@ -161,8 +161,13 @@ static void __init init_amd(struct cpuinfo_x86 *c) set_bit(X86_FEATURE_K6_MTRR, c->x86_capability); break; } - break; + if (c->x86_model == 10) { + /* AMD Geode LX is model 10 */ + /* placeholder for any needed mods */ + break; + } + break; case 6: /* An Athlon/Duron */ /* Bit 15 of Athlon specific MSR 15, needs to be 0 diff --git a/arch/i386/kernel/cpu/cyrix.c b/arch/i386/kernel/cpu/cyrix.c index ff87cc22b323..75015975d038 100644 --- a/arch/i386/kernel/cpu/cyrix.c +++ b/arch/i386/kernel/cpu/cyrix.c @@ -342,6 +342,31 @@ static void __init init_cyrix(struct cpuinfo_x86 *c) return; } +/* + * Handle National Semiconductor branded processors + */ +static void __devinit init_nsc(struct cpuinfo_x86 *c) +{ + /* There may be GX1 processors in the wild that are branded + * NSC and not Cyrix. + * + * This function only handles the GX processor, and kicks every + * thing else to the Cyrix init function above - that should + * cover any processors that might have been branded differently + * after NSC aquired Cyrix. + * + * If this breaks your GX1 horribly, please e-mail + * info-linux@ldcmail.amd.com to tell us. + */ + + /* Handle the GX (Formally known as the GX2) */ + + if (c->x86 == 5 && c->x86_model == 5) + display_cacheinfo(c); + else + init_cyrix(c); +} + /* * Cyrix CPUs without cpuid or with cpuid not yet enabled can be detected * by the fact that they preserve the flags across the division of 5/2. @@ -422,7 +447,7 @@ int __init cyrix_init_cpu(void) static struct cpu_dev nsc_cpu_dev __initdata = { .c_vendor = "NSC", .c_ident = { "Geode by NSC" }, - .c_init = init_cyrix, + .c_init = init_nsc, .c_identify = generic_identify, }; -- cgit v1.2.2 From 3841b0a173cb6fc52163e67c03280543f2412db3 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Fri, 6 Jan 2006 00:12:16 -0800 Subject: [PATCH] APM Screen Blanking fix - Fix screen blanking on BIOSes that return APM_NOT_ENGAGED when APM enabled screen blanking is not turned on. The original code only tried to set the state on device 0x100, and then 0x1FF, and I added 0x101 to the mix too. - Clean up logic in apm_console_blank(). - Prevent the error message from printing out twice. Cc: Jordan Crouse Cc: Stephen Rothwell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/apm.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/apm.c b/arch/i386/kernel/apm.c index d0b488056cc4..2d793d4aef1a 100644 --- a/arch/i386/kernel/apm.c +++ b/arch/i386/kernel/apm.c @@ -1064,22 +1064,23 @@ static int apm_engage_power_management(u_short device, int enable) static int apm_console_blank(int blank) { - int error; - u_short state; + int error, i; + u_short state; + static const u_short dev[3] = { 0x100, 0x1FF, 0x101 }; state = blank ? APM_STATE_STANDBY : APM_STATE_READY; - /* Blank the first display device */ - error = set_power_state(0x100, state); - if ((error != APM_SUCCESS) && (error != APM_NO_ERROR)) { - /* try to blank them all instead */ - error = set_power_state(0x1ff, state); - if ((error != APM_SUCCESS) && (error != APM_NO_ERROR)) - /* try to blank device one instead */ - error = set_power_state(0x101, state); + + for (i = 0; i < ARRAY_SIZE(dev); i++) { + error = set_power_state(dev[i], state); + + if ((error == APM_SUCCESS) || (error == APM_NO_ERROR)) + return 1; + + if (error == APM_NOT_ENGAGED) + break; } - if ((error == APM_SUCCESS) || (error == APM_NO_ERROR)) - return 1; - if (error == APM_NOT_ENGAGED) { + + if (error == APM_NOT_ENGAGED && state != APM_STATE_READY) { static int tried; int eng_error; if (tried++ == 0) { -- cgit v1.2.2 From bcf0f0d233fc76e7c59c7f731caad555428d0e8d Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Fri, 6 Jan 2006 00:12:17 -0800 Subject: [PATCH] fix cpu frequency detection in arch/i386/kernel/timers/timer_tsc.c::recalibrate_cpu_khz() When we re-calibrate the frequency, it is likely that an interrupt (as for example the main system clock) will be triggered by the system. Therefore the calibration may not be accurate. This will also provide a fix to bug #5266. Many thanks to Larry Finger for helping resolving this issue. Signed-off-by: Bruno Ducrot Cc: john stultz Cc: Dave Jones Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/timers/timer_tsc.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/timers/timer_tsc.c b/arch/i386/kernel/timers/timer_tsc.c index d395e3b42485..47675bbbb316 100644 --- a/arch/i386/kernel/timers/timer_tsc.c +++ b/arch/i386/kernel/timers/timer_tsc.c @@ -330,7 +330,9 @@ int recalibrate_cpu_khz(void) unsigned int cpu_khz_old = cpu_khz; if (cpu_has_tsc) { + local_irq_disable(); init_cpu_khz(); + local_irq_enable(); cpu_data[0].loops_per_jiffy = cpufreq_scale(cpu_data[0].loops_per_jiffy, cpu_khz_old, -- cgit v1.2.2 From 76865c3f87e825dda0c458b02f30dd8ae64b7bdc Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Fri, 6 Jan 2006 00:12:19 -0800 Subject: [PATCH] i386: ioapic virtual wire mode fix o Currently, during kexec reboot, IOAPIC is re-programmed back to virtual wire mode if there was an i8259 connected to it. This enables getting timer interrupts in second kernel in legacy mode. o After putting into virtual wire mode, IOAPIC delivers the i8259 interrupts to CPU0. This works well for kexec but not for kdump as we might crash on a different CPU and second kernel will not see timer interrupts. o This patch modifies the redirection table entry to deliver the timer interrupts to the cpu we are rebooting (instead of hardcoding to zero). This ensures that second kernel receives timer interrupts even on a non-boot cpu. Signed-off-by: Vivek Goyal Cc: Andi Kleen Cc: "Seth, Rohit" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/io_apic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/io_apic.c b/arch/i386/kernel/io_apic.c index 22c8675c79f4..7554f8fd874a 100644 --- a/arch/i386/kernel/io_apic.c +++ b/arch/i386/kernel/io_apic.c @@ -1722,8 +1722,8 @@ void disable_IO_APIC(void) entry.dest_mode = 0; /* Physical */ entry.delivery_mode = dest_ExtINT; /* ExtInt */ entry.vector = 0; - entry.dest.physical.physical_dest = 0; - + entry.dest.physical.physical_dest = + GET_APIC_ID(apic_read(APIC_ID)); /* * Add it to the IO-APIC irq-routing table: -- cgit v1.2.2 From 766c3f94d4492ee4ec60b65693e71ee4b1d6fd68 Mon Sep 17 00:00:00 2001 From: Ben Collins Date: Fri, 6 Jan 2006 00:12:20 -0800 Subject: [PATCH] i386: Handle HP laptop rebooting properly. Signed-off-by: Ben Collins Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/reboot.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/i386/kernel') diff --git a/arch/i386/kernel/reboot.c b/arch/i386/kernel/reboot.c index 2afe0f8d555a..2fa5803a759d 100644 --- a/arch/i386/kernel/reboot.c +++ b/arch/i386/kernel/reboot.c @@ -111,12 +111,12 @@ static struct dmi_system_id __initdata reboot_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "PowerEdge 2400"), }, }, - { /* Handle problems with rebooting on HP nc6120 */ + { /* Handle problems with rebooting on HP laptops */ .callback = set_bios_reboot, - .ident = "HP Compaq nc6120", + .ident = "HP Compaq Laptop", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nc6120"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq"), }, }, { } -- cgit v1.2.2