aboutsummaryrefslogtreecommitdiff
path: root/arch/i386/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel')
-rw-r--r--arch/i386/kernel/acpi/boot.c10
-rw-r--r--arch/i386/kernel/apic.c23
-rw-r--r--arch/i386/kernel/cpu/amd.c2
-rw-r--r--arch/i386/kernel/cpu/cpufreq/powernow-k8.c18
-rw-r--r--arch/i386/kernel/i386_ksyms.c1
-rw-r--r--arch/i386/kernel/mpparse.c43
-rw-r--r--arch/i386/kernel/reboot_fixups.c2
-rw-r--r--arch/i386/kernel/setup.c36
-rw-r--r--arch/i386/kernel/traps.c16
9 files changed, 100 insertions, 51 deletions
diff --git a/arch/i386/kernel/acpi/boot.c b/arch/i386/kernel/acpi/boot.c
index 033066176b3..030a0007a4e 100644
--- a/arch/i386/kernel/acpi/boot.c
+++ b/arch/i386/kernel/acpi/boot.c
@@ -168,7 +168,7 @@ int __init acpi_parse_mcfg(unsigned long phys_addr, unsigned long size)
unsigned long i;
int config_size;
- if (!phys_addr || !size)
+ if (!phys_addr || !size || !cpu_has_apic)
return -EINVAL;
mcfg = (struct acpi_table_mcfg *)__acpi_map_table(phys_addr, size);
@@ -215,7 +215,7 @@ static int __init acpi_parse_madt(unsigned long phys_addr, unsigned long size)
{
struct acpi_table_madt *madt = NULL;
- if (!phys_addr || !size)
+ if (!phys_addr || !size || !cpu_has_apic)
return -EINVAL;
madt = (struct acpi_table_madt *)__acpi_map_table(phys_addr, size);
@@ -693,6 +693,9 @@ static int __init acpi_parse_madt_lapic_entries(void)
{
int count;
+ if (!cpu_has_apic)
+ return -ENODEV;
+
/*
* Note that the LAPIC address is obtained from the MADT (32-bit value)
* and (optionally) overriden by a LAPIC_ADDR_OVR entry (64-bit value).
@@ -751,6 +754,9 @@ static int __init acpi_parse_madt_ioapic_entries(void)
return -ENODEV;
}
+ if (!cpu_has_apic)
+ return -ENODEV;
+
/*
* if "noapic" boot option, don't look for IO-APICs
*/
diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c
index 6273bf74c20..254cee9f0b7 100644
--- a/arch/i386/kernel/apic.c
+++ b/arch/i386/kernel/apic.c
@@ -62,6 +62,18 @@ int apic_verbosity;
static void apic_pm_activate(void);
+int modern_apic(void)
+{
+ unsigned int lvr, version;
+ /* AMD systems use old APIC versions, so check the CPU */
+ if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
+ boot_cpu_data.x86 >= 0xf)
+ return 1;
+ lvr = apic_read(APIC_LVR);
+ version = GET_APIC_VERSION(lvr);
+ return version >= 0x14;
+}
+
/*
* 'what should we do if we get a hw irq event on an illegal vector'.
* each architecture has to answer this themselves.
@@ -119,10 +131,7 @@ void enable_NMI_through_LVT0 (void * dummy)
int get_physical_broadcast(void)
{
- unsigned int lvr, version;
- lvr = apic_read(APIC_LVR);
- version = GET_APIC_VERSION(lvr);
- if (!APIC_INTEGRATED(version) || version >= 0x14)
+ if (modern_apic())
return 0xff;
else
return 0xf;
@@ -349,9 +358,9 @@ int __init verify_local_APIC(void)
void __init sync_Arb_IDs(void)
{
- /* Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1 */
- unsigned int ver = GET_APIC_VERSION(apic_read(APIC_LVR));
- if (ver >= 0x14) /* P4 or higher */
+ /* Unsupported on P4 - see Intel Dev. Manual Vol. 3, Ch. 8.6.1
+ And not needed on AMD */
+ if (modern_apic())
return;
/*
* Wait for idle.
diff --git a/arch/i386/kernel/cpu/amd.c b/arch/i386/kernel/cpu/amd.c
index 0810f81f2a0..ff2b2154ac1 100644
--- a/arch/i386/kernel/cpu/amd.c
+++ b/arch/i386/kernel/cpu/amd.c
@@ -212,8 +212,6 @@ static void __init init_amd(struct cpuinfo_x86 *c)
if (cpuid_eax(0x80000000) >= 0x80000008) {
c->x86_max_cores = (cpuid_ecx(0x80000008) & 0xff) + 1;
- if (c->x86_max_cores & (c->x86_max_cores - 1))
- c->x86_max_cores = 1;
}
if (cpuid_eax(0x80000000) >= 0x80000007) {
diff --git a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
index 712a26bd445..7c0e160a214 100644
--- a/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
+++ b/arch/i386/kernel/cpu/cpufreq/powernow-k8.c
@@ -46,7 +46,7 @@
#define PFX "powernow-k8: "
#define BFX PFX "BIOS error: "
-#define VERSION "version 1.60.1"
+#define VERSION "version 1.60.2"
#include "powernow-k8.h"
/* serialize freq changes */
@@ -55,7 +55,7 @@ static DEFINE_MUTEX(fidvid_mutex);
static struct powernow_k8_data *powernow_data[NR_CPUS];
#ifndef CONFIG_SMP
-static cpumask_t cpu_core_map[1] = { CPU_MASK_ALL };
+static cpumask_t cpu_core_map[1];
#endif
/* Return a frequency in MHz, given an input fid */
@@ -910,6 +910,9 @@ static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, unsi
unsigned int newstate;
int ret = -EIO;
+ if (!data)
+ return -EINVAL;
+
/* only run on specific CPU from here on */
oldmask = current->cpus_allowed;
set_cpus_allowed(current, cpumask_of_cpu(pol->cpu));
@@ -969,6 +972,9 @@ static int powernowk8_verify(struct cpufreq_policy *pol)
{
struct powernow_k8_data *data = powernow_data[pol->cpu];
+ if (!data)
+ return -EINVAL;
+
return cpufreq_frequency_table_verify(pol, data->powernow_table);
}
@@ -977,7 +983,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
{
struct powernow_k8_data *data;
cpumask_t oldmask = CPU_MASK_ALL;
- int rc, i;
+ int rc;
if (!cpu_online(pol->cpu))
return -ENODEV;
@@ -1063,8 +1069,7 @@ static int __cpuinit powernowk8_cpu_init(struct cpufreq_policy *pol)
printk("cpu_init done, current fid 0x%x, vid 0x%x\n",
data->currfid, data->currvid);
- for_each_cpu_mask(i, cpu_core_map[pol->cpu])
- powernow_data[i] = data;
+ powernow_data[pol->cpu] = data;
return 0;
@@ -1104,6 +1109,9 @@ static unsigned int powernowk8_get (unsigned int cpu)
if (!data)
return -EINVAL;
+ if (!data)
+ return -EINVAL;
+
set_cpus_allowed(current, cpumask_of_cpu(cpu));
if (smp_processor_id() != cpu) {
printk(KERN_ERR PFX "limiting to CPU %d failed in powernowk8_get\n", cpu);
diff --git a/arch/i386/kernel/i386_ksyms.c b/arch/i386/kernel/i386_ksyms.c
index 055325056a7..036a9857936 100644
--- a/arch/i386/kernel/i386_ksyms.c
+++ b/arch/i386/kernel/i386_ksyms.c
@@ -19,7 +19,6 @@ EXPORT_SYMBOL(__put_user_2);
EXPORT_SYMBOL(__put_user_4);
EXPORT_SYMBOL(__put_user_8);
-EXPORT_SYMBOL(strpbrk);
EXPORT_SYMBOL(strstr);
#ifdef CONFIG_SMP
diff --git a/arch/i386/kernel/mpparse.c b/arch/i386/kernel/mpparse.c
index 8d8aa9d1796..34d21e21e01 100644
--- a/arch/i386/kernel/mpparse.c
+++ b/arch/i386/kernel/mpparse.c
@@ -38,12 +38,6 @@
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.
@@ -110,21 +104,6 @@ static int __init mpf_checksum(unsigned char *mp, int len)
static int mpc_record;
static struct mpc_config_translation *translation_table[MAX_MPC_ENTRY] __initdata;
-#ifdef CONFIG_X86_NUMAQ
-static int MP_valid_apicid(int apicid, int version)
-{
- return hweight_long(apicid & 0xf) == 1 && (apicid >> 4) != 0xf;
-}
-#else
-static int MP_valid_apicid(int apicid, int version)
-{
- if (version >= 0x14)
- return apicid < 0xff;
- else
- return apicid < 0xf;
-}
-#endif
-
static void __devinit MP_processor_info (struct mpc_config_processor *m)
{
int ver, apicid;
@@ -190,12 +169,6 @@ static void __devinit MP_processor_info (struct mpc_config_processor *m)
ver = m->mpc_apicver;
- if (!MP_valid_apicid(apicid, ver)) {
- printk(KERN_WARNING "Processor #%d INVALID. (Max ID: %d).\n",
- m->mpc_apicid, MAX_APICS);
- return;
- }
-
/*
* Validate version
*/
@@ -225,7 +198,14 @@ static void __devinit MP_processor_info (struct mpc_config_processor *m)
cpu_set(num_processors, cpu_possible_map);
num_processors++;
- if (CPU_HOTPLUG_ENABLED || (num_processors > 8)) {
+ /*
+ * Would be preferable to switch to bigsmp when CONFIG_HOTPLUG_CPU=y
+ * but we need to work other dependencies like SMP_SUSPEND etc
+ * before this can be done without some confusion.
+ * if (CPU_HOTPLUG_ENABLED || num_processors > 8)
+ * - Ashok Raj <ashok.raj@intel.com>
+ */
+ if (num_processors > 8) {
switch (boot_cpu_data.x86_vendor) {
case X86_VENDOR_INTEL:
if (!APIC_XAPIC(ver)) {
@@ -249,6 +229,13 @@ static void __init MP_bus_info (struct mpc_config_bus *m)
mpc_oem_bus_info(m, str, translation_table[mpc_record]);
+ if (m->mpc_busid >= MAX_MP_BUSSES) {
+ printk(KERN_WARNING "MP table busid value (%d) for bustype %s "
+ " is too large, max. supported is %d\n",
+ m->mpc_busid, str, MAX_MP_BUSSES - 1);
+ return;
+ }
+
if (strncmp(str, BUSTYPE_ISA, sizeof(BUSTYPE_ISA)-1) == 0) {
mp_bus_id_to_type[m->mpc_busid] = MP_BUS_ISA;
} else if (strncmp(str, BUSTYPE_EISA, sizeof(BUSTYPE_EISA)-1) == 0) {
diff --git a/arch/i386/kernel/reboot_fixups.c b/arch/i386/kernel/reboot_fixups.c
index 10e21a4773d..99aab41a05b 100644
--- a/arch/i386/kernel/reboot_fixups.c
+++ b/arch/i386/kernel/reboot_fixups.c
@@ -51,7 +51,5 @@ void mach_reboot_fixups(void)
cur->reboot_fixup(dev);
}
-
- printk(KERN_WARNING "No reboot fixup found for your hardware\n");
}
diff --git a/arch/i386/kernel/setup.c b/arch/i386/kernel/setup.c
index eacc3f0a2ea..80cb3b2d099 100644
--- a/arch/i386/kernel/setup.c
+++ b/arch/i386/kernel/setup.c
@@ -963,6 +963,36 @@ efi_memory_present_wrapper(unsigned long start, unsigned long end, void *arg)
return 0;
}
+ /*
+ * This function checks if the entire range <start,end> is mapped with type.
+ *
+ * Note: this function only works correct if the e820 table is sorted and
+ * not-overlapping, which is the case
+ */
+int __init
+e820_all_mapped(unsigned long start, unsigned long end, unsigned type)
+{
+ int i;
+ for (i = 0; i < e820.nr_map; i++) {
+ struct e820entry *ei = &e820.map[i];
+ if (type && ei->type != type)
+ continue;
+ /* is the region (part) in overlap with the current region ?*/
+ if (ei->addr >= end || ei->addr + ei->size <= start)
+ continue;
+ /* if the region is at the beginning of <start,end> we move
+ * start to the end of the region since it's ok until there
+ */
+ if (ei->addr <= start)
+ start = ei->addr + ei->size;
+ /* if start is now at or beyond end, we're done, full
+ * coverage */
+ if (start >= end)
+ return 1; /* we're done */
+ }
+ return 0;
+}
+
/*
* Find the highest page frame number we have available
*/
@@ -1317,8 +1347,8 @@ legacy_init_iomem_resources(struct resource *code_resource, struct resource *dat
/*
* Request address space for all standard resources
*
- * This is called just before pcibios_assign_resources(), which is also
- * an fs_initcall, but is linked in later (in arch/i386/pci/i386.c).
+ * This is called just before pcibios_init(), which is also a
+ * subsys_initcall, but is linked in later (in arch/i386/pci/common.c).
*/
static int __init request_standard_resources(void)
{
@@ -1339,7 +1369,7 @@ static int __init request_standard_resources(void)
return 0;
}
-fs_initcall(request_standard_resources);
+subsys_initcall(request_standard_resources);
static void __init register_memory(void)
{
diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c
index e3852799459..2d22f5761b1 100644
--- a/arch/i386/kernel/traps.c
+++ b/arch/i386/kernel/traps.c
@@ -365,6 +365,9 @@ void die(const char * str, struct pt_regs * regs, long err)
if (++die.lock_owner_depth < 3) {
int nl = 0;
+ unsigned long esp;
+ unsigned short ss;
+
handle_BUG(regs);
printk(KERN_EMERG "%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
#ifdef CONFIG_PREEMPT
@@ -387,8 +390,19 @@ void die(const char * str, struct pt_regs * regs, long err)
printk("\n");
if (notify_die(DIE_OOPS, str, regs, err,
current->thread.trap_no, SIGSEGV) !=
- NOTIFY_STOP)
+ NOTIFY_STOP) {
show_registers(regs);
+ /* Executive summary in case the oops scrolled away */
+ esp = (unsigned long) (&regs->esp);
+ savesegment(ss, ss);
+ if (user_mode(regs)) {
+ esp = regs->esp;
+ ss = regs->xss & 0xffff;
+ }
+ printk(KERN_EMERG "EIP: [<%08lx>] ", regs->eip);
+ print_symbol("%s", regs->eip);
+ printk(" SS:ESP %04x:%08lx\n", ss, esp);
+ }
else
regs = NULL;
} else