linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / arch / i386 / kernel / setup.c
index f168220..0fc23c0 100644 (file)
  * This file handles the architecture-dependent parts of initialization
  */
 
+#include <linux/config.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/mmzone.h>
-#include <linux/screen_info.h>
+#include <linux/tty.h>
 #include <linux/ioport.h>
 #include <linux/acpi.h>
 #include <linux/apm_bios.h>
 #include <linux/initrd.h>
 #include <linux/bootmem.h>
 #include <linux/seq_file.h>
-#include <linux/platform_device.h>
 #include <linux/console.h>
 #include <linux/mca.h>
 #include <linux/root_dev.h>
@@ -46,7 +46,6 @@
 #include <linux/kexec.h>
 #include <linux/crash_dump.h>
 #include <linux/dmi.h>
-#include <linux/pfn.h>
 
 #include <video/edid.h>
 
@@ -59,7 +58,7 @@
 #include <asm/io_apic.h>
 #include <asm/ist.h>
 #include <asm/io.h>
-#include <setup_arch.h>
+#include "setup_arch_pre.h"
 #include <bios_ebda.h>
 
 /* Forward Declaration. */
@@ -409,8 +408,8 @@ static void __init limit_regions(unsigned long long size)
        }
 }
 
-void __init add_memory_region(unsigned long long start,
-                             unsigned long long size, int type)
+static void __init add_memory_region(unsigned long long start,
+                                  unsigned long long size, int type)
 {
        int x;
 
@@ -473,7 +472,7 @@ static struct change_member *change_point[2*E820MAX] __initdata;
 static struct e820entry *overlap_list[E820MAX] __initdata;
 static struct e820entry new_bios[E820MAX] __initdata;
 
-int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map)
+static int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map)
 {
        struct change_member *change_tmp;
        unsigned long current_type, last_type;
@@ -642,7 +641,7 @@ int __init sanitize_e820_map(struct e820entry * biosmap, char * pnr_map)
  * thinkpad 560x, for example, does not cooperate with the memory
  * detection code.)
  */
-int __init copy_e820_map(struct e820entry * biosmap, int nr_map)
+static int __init copy_e820_map(struct e820entry * biosmap, int nr_map)
 {
        /* Only one memory region (or negative)? Ignore it */
        if (nr_map < 2)
@@ -700,6 +699,12 @@ static inline void copy_edd(void)
 }
 #endif
 
+/*
+ * Do NOT EVER look at the BIOS memory size location.
+ * It does not work on many machines.
+ */
+#define LOWMEMSIZE()   (0x9f000)
+
 static void __init parse_cmdline_early (char ** cmdline_p)
 {
        char c = ' ', *to = command_line, *from = saved_command_line;
@@ -956,38 +961,6 @@ 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 s, unsigned long e, unsigned type)
-{
-       u64 start = s;
-       u64 end = e;
-       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
  */
@@ -1085,10 +1058,10 @@ static int __init
 free_available_memory(unsigned long start, unsigned long end, void *arg)
 {
        /* check max_low_pfn */
-       if (start >= (max_low_pfn << PAGE_SHIFT))
+       if (start >= ((max_low_pfn + 1) << PAGE_SHIFT))
                return 0;
-       if (end >= (max_low_pfn << PAGE_SHIFT))
-               end = max_low_pfn << PAGE_SHIFT;
+       if (end >= ((max_low_pfn + 1) << PAGE_SHIFT))
+               end = (max_low_pfn + 1) << PAGE_SHIFT;
        if (start < end)
                free_bootmem(start, end - start);
 
@@ -1219,8 +1192,8 @@ void __init setup_bootmem_allocator(void)
         * the (very unlikely) case of us accidentally initializing the
         * bootmem allocator with an invalid RAM area.
         */
-       reserve_bootmem(__PHYSICAL_START, (PFN_PHYS(min_low_pfn) +
-                        bootmap_size + PAGE_SIZE-1) - (__PHYSICAL_START));
+       reserve_bootmem(PHYSICAL_START, (PFN_PHYS(min_low_pfn) +
+                        bootmap_size + PAGE_SIZE-1) - (PHYSICAL_START));
 
        /*
         * reserve physical page 0 - it's a special BIOS page on many boxes,
@@ -1313,11 +1286,9 @@ legacy_init_iomem_resources(struct resource *code_resource, struct resource *dat
        probe_roms();
        for (i = 0; i < e820.nr_map; i++) {
                struct resource *res;
-#ifndef CONFIG_RESOURCES_64BIT
                if (e820.map[i].addr + e820.map[i].size > 0x100000000ULL)
                        continue;
-#endif
-               res = kzalloc(sizeof(struct resource), GFP_ATOMIC);
+               res = alloc_bootmem_low(sizeof(struct resource));
                switch (e820.map[i].type) {
                case E820_RAM:  res->name = "System RAM"; break;
                case E820_ACPI: res->name = "ACPI Tables"; break;
@@ -1327,10 +1298,7 @@ legacy_init_iomem_resources(struct resource *code_resource, struct resource *dat
                res->start = e820.map[i].addr;
                res->end = res->start + e820.map[i].size - 1;
                res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
-               if (request_resource(&iomem_resource, res)) {
-                       kfree(res);
-                       continue;
-               }
+               request_resource(&iomem_resource, res);
                if (e820.map[i].type == E820_RAM) {
                        /*
                         *  We don't know which RAM region contains kernel data,
@@ -1348,15 +1316,13 @@ legacy_init_iomem_resources(struct resource *code_resource, struct resource *dat
 
 /*
  * Request address space for all standard resources
- *
- * 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)
+static void __init register_memory(void)
 {
-       int i;
+       unsigned long gapstart, gapsize, round;
+       unsigned long long last;
+       int           i;
 
-       printk("Setting up standard PCI resources\n");
        if (efi_enabled)
                efi_initialize_iomem_resources(&code_resource, &data_resource);
        else
@@ -1368,16 +1334,6 @@ static int __init request_standard_resources(void)
        /* request I/O space for devices used on all i[345]86 PCs */
        for (i = 0; i < STANDARD_IO_RESOURCES; i++)
                request_resource(&ioport_resource, &standard_io_resources[i]);
-       return 0;
-}
-
-subsys_initcall(request_standard_resources);
-
-static void __init register_memory(void)
-{
-       unsigned long gapstart, gapsize, round;
-       unsigned long long last;
-       int i;
 
        /*
         * Search for the bigest gap in the low 32 bits of the e820
@@ -1421,6 +1377,103 @@ static void __init register_memory(void)
                pci_mem_start, gapstart, gapsize);
 }
 
+/* Use inline assembly to define this because the nops are defined 
+   as inline assembly strings in the include files and we cannot 
+   get them easily into strings. */
+asm("\t.data\nintelnops: " 
+    GENERIC_NOP1 GENERIC_NOP2 GENERIC_NOP3 GENERIC_NOP4 GENERIC_NOP5 GENERIC_NOP6
+    GENERIC_NOP7 GENERIC_NOP8); 
+asm("\t.data\nk8nops: " 
+    K8_NOP1 K8_NOP2 K8_NOP3 K8_NOP4 K8_NOP5 K8_NOP6
+    K8_NOP7 K8_NOP8); 
+asm("\t.data\nk7nops: " 
+    K7_NOP1 K7_NOP2 K7_NOP3 K7_NOP4 K7_NOP5 K7_NOP6
+    K7_NOP7 K7_NOP8); 
+    
+extern unsigned char intelnops[], k8nops[], k7nops[];
+static unsigned char *intel_nops[ASM_NOP_MAX+1] = { 
+     NULL,
+     intelnops,
+     intelnops + 1,
+     intelnops + 1 + 2,
+     intelnops + 1 + 2 + 3,
+     intelnops + 1 + 2 + 3 + 4,
+     intelnops + 1 + 2 + 3 + 4 + 5,
+     intelnops + 1 + 2 + 3 + 4 + 5 + 6,
+     intelnops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
+}; 
+static unsigned char *k8_nops[ASM_NOP_MAX+1] = { 
+     NULL,
+     k8nops,
+     k8nops + 1,
+     k8nops + 1 + 2,
+     k8nops + 1 + 2 + 3,
+     k8nops + 1 + 2 + 3 + 4,
+     k8nops + 1 + 2 + 3 + 4 + 5,
+     k8nops + 1 + 2 + 3 + 4 + 5 + 6,
+     k8nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
+}; 
+static unsigned char *k7_nops[ASM_NOP_MAX+1] = { 
+     NULL,
+     k7nops,
+     k7nops + 1,
+     k7nops + 1 + 2,
+     k7nops + 1 + 2 + 3,
+     k7nops + 1 + 2 + 3 + 4,
+     k7nops + 1 + 2 + 3 + 4 + 5,
+     k7nops + 1 + 2 + 3 + 4 + 5 + 6,
+     k7nops + 1 + 2 + 3 + 4 + 5 + 6 + 7,
+}; 
+static struct nop { 
+     int cpuid; 
+     unsigned char **noptable; 
+} noptypes[] = { 
+     { X86_FEATURE_K8, k8_nops }, 
+     { X86_FEATURE_K7, k7_nops }, 
+     { -1, NULL }
+}; 
+
+/* Replace instructions with better alternatives for this CPU type.
+
+   This runs before SMP is initialized to avoid SMP problems with
+   self modifying code. This implies that assymetric systems where
+   APs have less capabilities than the boot processor are not handled. 
+   Tough. Make sure you disable such features by hand. */ 
+void apply_alternatives(void *start, void *end) 
+{ 
+       struct alt_instr *a; 
+       int diff, i, k;
+        unsigned char **noptable = intel_nops; 
+       for (i = 0; noptypes[i].cpuid >= 0; i++) { 
+               if (boot_cpu_has(noptypes[i].cpuid)) { 
+                       noptable = noptypes[i].noptable;
+                       break;
+               }
+       } 
+       for (a = start; (void *)a < end; a++) { 
+               if (!boot_cpu_has(a->cpuid))
+                       continue;
+               BUG_ON(a->replacementlen > a->instrlen); 
+               memcpy(a->instr, a->replacement, a->replacementlen); 
+               diff = a->instrlen - a->replacementlen; 
+               /* Pad the rest with nops */
+               for (i = a->replacementlen; diff > 0; diff -= k, i += k) {
+                       k = diff;
+                       if (k > ASM_NOP_MAX)
+                               k = ASM_NOP_MAX;
+                       memcpy(a->instr + i, noptable[k], k); 
+               } 
+       }
+} 
+
+void __init alternative_instructions(void)
+{
+       extern struct alt_instr __alt_instructions[], __alt_instructions_end[];
+       apply_alternatives(__alt_instructions, __alt_instructions_end);
+}
+
+static char * __init machine_specific_memory_setup(void);
+
 #ifdef CONFIG_MCA
 static void set_mca_bus(int x)
 {
@@ -1501,16 +1554,6 @@ void __init setup_arch(char **cmdline_p)
 
        parse_cmdline_early(cmdline_p);
 
-#ifdef CONFIG_EARLY_PRINTK
-       {
-               char *s = strstr(*cmdline_p, "earlyprintk=");
-               if (s) {
-                       setup_early_printk(strchr(s, '=') + 1);
-                       printk("early console enabled\n");
-               }
-       }
-#endif
-
        max_low_pfn = setup_memory();
 
        /*
@@ -1535,6 +1578,19 @@ void __init setup_arch(char **cmdline_p)
         * NOTE: at this point the bootmem allocator is fully available.
         */
 
+#ifdef CONFIG_EARLY_PRINTK
+       {
+               char *s = strstr(*cmdline_p, "earlyprintk=");
+               if (s) {
+                       extern void setup_early_printk(char *);
+
+                       setup_early_printk(strchr(s, '=') + 1);
+                       printk("early console enabled\n");
+               }
+       }
+#endif
+
+
        dmi_scan_machine();
 
 #ifdef CONFIG_X86_GENERICARCH
@@ -1543,18 +1599,15 @@ void __init setup_arch(char **cmdline_p)
        if (efi_enabled)
                efi_map_memmap();
 
-#ifdef CONFIG_ACPI
-       /*
-        * Parse the ACPI tables for possible boot-time SMP configuration.
-        */
-       acpi_boot_table_init();
-#endif
-
 #ifdef CONFIG_X86_IO_APIC
        check_acpi_pci();       /* Checks more than just ACPI actually */
 #endif
 
 #ifdef CONFIG_ACPI
+       /*
+        * Parse the ACPI tables for possible boot-time SMP configuration.
+        */
+       acpi_boot_table_init();
        acpi_boot_init();
 
 #if defined(CONFIG_SMP) && defined(CONFIG_X86_PC)
@@ -1579,26 +1632,9 @@ void __init setup_arch(char **cmdline_p)
        conswitchp = &dummy_con;
 #endif
 #endif
-       tsc_init();
-}
-
-static __init int add_pcspkr(void)
-{
-       struct platform_device *pd;
-       int ret;
-
-       pd = platform_device_alloc("pcspkr", -1);
-       if (!pd)
-               return -ENOMEM;
-
-       ret = platform_device_add(pd);
-       if (ret)
-               platform_device_put(pd);
-
-       return ret;
 }
-device_initcall(add_pcspkr);
 
+#include "setup_arch_post.h"
 /*
  * Local Variables:
  * mode:c