Pull new-efi-memmap into release branch
[cascardo/linux.git] / arch / ia64 / kernel / setup.c
index 2693e15..f95fd27 100644 (file)
@@ -20,6 +20,7 @@
  * 02/01/00 R.Seth     fixed get_cpuinfo for SMP
  * 01/07/99 S.Eranian  added the support for command line argument
  * 06/24/99 W.Drummond added boot_cpu_data.
+ * 05/28/05 Z. Menyhart        Dynamic stride size for "flush_icache_range()"
  */
 #include <linux/config.h>
 #include <linux/module.h>
@@ -40,6 +41,8 @@
 #include <linux/serial_core.h>
 #include <linux/efi.h>
 #include <linux/initrd.h>
+#include <linux/platform.h>
+#include <linux/pm.h>
 
 #include <asm/ia32.h>
 #include <asm/machvec.h>
@@ -75,6 +78,19 @@ struct screen_info screen_info;
 unsigned long vga_console_iobase;
 unsigned long vga_console_membase;
 
+static struct resource data_resource = {
+       .name   = "Kernel data",
+       .flags  = IORESOURCE_BUSY | IORESOURCE_MEM
+};
+
+static struct resource code_resource = {
+       .name   = "Kernel code",
+       .flags  = IORESOURCE_BUSY | IORESOURCE_MEM
+};
+extern void efi_initialize_iomem_resources(struct resource *,
+               struct resource *);
+extern char _text[], _end[], _etext[];
+
 unsigned long ia64_max_cacheline_size;
 unsigned long ia64_iobase;     /* virtual address for I/O accesses */
 EXPORT_SYMBOL(ia64_iobase);
@@ -82,6 +98,13 @@ struct io_space io_space[MAX_IO_SPACES];
 EXPORT_SYMBOL(io_space);
 unsigned int num_io_spaces;
 
+/*
+ * "flush_icache_range()" needs to know what processor dependent stride size to use
+ * when it makes i-cache(s) coherent with d-caches.
+ */
+#define        I_CACHE_STRIDE_SHIFT    5       /* Safest way to go: 32 bytes by 32 bytes */
+unsigned long ia64_i_cache_stride_shift = ~0;
+
 /*
  * The merge_mask variable needs to be set to (max(iommu_page_size(iommu)) - 1).  This
  * mask specifies a mask of address bits that must be 0 in order for two buffers to be
@@ -161,6 +184,22 @@ sort_regions (struct rsvd_region *rsvd_region, int max)
        }
 }
 
+/*
+ * Request address space for all standard resources
+ */
+static int __init register_memory(void)
+{
+       code_resource.start = ia64_tpa(_text);
+       code_resource.end   = ia64_tpa(_etext) - 1;
+       data_resource.start = ia64_tpa(_etext);
+       data_resource.end   = ia64_tpa(_end) - 1;
+       efi_initialize_iomem_resources(&code_resource, &data_resource);
+
+       return 0;
+}
+
+__initcall(register_memory);
+
 /**
  * reserve_memory - setup reserved memory areas
  *
@@ -201,6 +240,9 @@ reserve_memory (void)
        }
 #endif
 
+       efi_memmap_init(&rsvd_region[n].start, &rsvd_region[n].end);
+       n++;
+
        /* end of memory marker */
        rsvd_region[n].start = ~0UL;
        rsvd_region[n].end   = ~0UL;
@@ -234,28 +276,31 @@ find_initrd (void)
 static void __init
 io_port_init (void)
 {
-       extern unsigned long ia64_iobase;
        unsigned long phys_iobase;
 
        /*
-        *  Set `iobase' to the appropriate address in region 6 (uncached access range).
+        * Set `iobase' based on the EFI memory map or, failing that, the
+        * value firmware left in ar.k0.
+        *
+        * Note that in ia32 mode, IN/OUT instructions use ar.k0 to compute
+        * the port's virtual address, so ia32_load_state() loads it with a
+        * user virtual address.  But in ia64 mode, glibc uses the
+        * *physical* address in ar.k0 to mmap the appropriate area from
+        * /dev/mem, and the inX()/outX() interfaces use MMIO.  In both
+        * cases, user-mode can only use the legacy 0-64K I/O port space.
         *
-        *  The EFI memory map is the "preferred" location to get the I/O port space base,
-        *  rather the relying on AR.KR0. This should become more clear in future SAL
-        *  specs. We'll fall back to getting it out of AR.KR0 if no appropriate entry is
-        *  found in the memory map.
+        * ar.k0 is not involved in kernel I/O port accesses, which can use
+        * any of the I/O port spaces and are done via MMIO using the
+        * virtual mmio_base from the appropriate io_space[].
         */
        phys_iobase = efi_get_iobase();
-       if (phys_iobase)
-               /* set AR.KR0 since this is all we use it for anyway */
-               ia64_set_kr(IA64_KR_IO_BASE, phys_iobase);
-       else {
+       if (!phys_iobase) {
                phys_iobase = ia64_get_kr(IA64_KR_IO_BASE);
-               printk(KERN_INFO "No I/O port range found in EFI memory map, falling back "
-                      "to AR.KR0\n");
-               printk(KERN_INFO "I/O port base = 0x%lx\n", phys_iobase);
+               printk(KERN_INFO "No I/O port range found in EFI memory map, "
+                       "falling back to AR.KR0 (0x%lx)\n", phys_iobase);
        }
        ia64_iobase = (unsigned long) ioremap(phys_iobase, 0);
+       ia64_set_kr(IA64_KR_IO_BASE, __pa(ia64_iobase));
 
        /* setup legacy IO port space */
        io_space[0].mmio_base = ia64_iobase;
@@ -374,7 +419,7 @@ setup_arch (char **cmdline_p)
        if (early_console_setup(*cmdline_p) == 0)
                mark_bsp_online();
 
-#ifdef CONFIG_ACPI_BOOT
+#ifdef CONFIG_ACPI
        /* Initialize the ACPI boot-time table parser */
        acpi_table_init();
 # ifdef CONFIG_ACPI_NUMA
@@ -410,7 +455,7 @@ setup_arch (char **cmdline_p)
 
        cpu_init();     /* initialize the bootstrap CPU */
 
-#ifdef CONFIG_ACPI_BOOT
+#ifdef CONFIG_ACPI
        acpi_boot_init();
 #endif
 
@@ -626,6 +671,12 @@ setup_per_cpu_areas (void)
        /* start_kernel() requires this... */
 }
 
+/*
+ * Calculate the max. cache line size.
+ *
+ * In addition, the minimum of the i-cache stride sizes is calculated for
+ * "flush_icache_range()".
+ */
 static void
 get_max_cacheline_size (void)
 {
@@ -639,6 +690,8 @@ get_max_cacheline_size (void)
                 printk(KERN_ERR "%s: ia64_pal_cache_summary() failed (status=%ld)\n",
                        __FUNCTION__, status);
                 max = SMP_CACHE_BYTES;
+               /* Safest setup for "flush_icache_range()" */
+               ia64_i_cache_stride_shift = I_CACHE_STRIDE_SHIFT;
                goto out;
         }
 
@@ -647,14 +700,31 @@ get_max_cacheline_size (void)
                                                    &cci);
                if (status != 0) {
                        printk(KERN_ERR
-                              "%s: ia64_pal_cache_config_info(l=%lu) failed (status=%ld)\n",
+                              "%s: ia64_pal_cache_config_info(l=%lu, 2) failed (status=%ld)\n",
                               __FUNCTION__, l, status);
                        max = SMP_CACHE_BYTES;
+                       /* The safest setup for "flush_icache_range()" */
+                       cci.pcci_stride = I_CACHE_STRIDE_SHIFT;
+                       cci.pcci_unified = 1;
                }
                line_size = 1 << cci.pcci_line_size;
                if (line_size > max)
                        max = line_size;
-        }
+               if (!cci.pcci_unified) {
+                       status = ia64_pal_cache_config_info(l,
+                                                   /* cache_type (instruction)= */ 1,
+                                                   &cci);
+                       if (status != 0) {
+                               printk(KERN_ERR
+                               "%s: ia64_pal_cache_config_info(l=%lu, 1) failed (status=%ld)\n",
+                                       __FUNCTION__, l, status);
+                               /* The safest setup for "flush_icache_range()" */
+                               cci.pcci_stride = I_CACHE_STRIDE_SHIFT;
+                       }
+               }
+               if (cci.pcci_stride < ia64_i_cache_stride_shift)
+                       ia64_i_cache_stride_shift = cci.pcci_stride;
+       }
   out:
        if (max > ia64_max_cacheline_size)
                ia64_max_cacheline_size = max;
@@ -783,6 +853,7 @@ cpu_init (void)
        /* size of physical stacked register partition plus 8 bytes: */
        __get_cpu_var(ia64_phys_stacked_size_p8) = num_phys_stacked*8 + 8;
        platform_cpu_init();
+       pm_idle = default_idle;
 }
 
 void