ARM: Move creation of /proc/cpu out of alignment.c
[safe/jmp/linux-2.6] / arch / arm / kernel / setup.c
index e90422d..5357e48 100644 (file)
 #include <linux/interrupt.h>
 #include <linux/smp.h>
 #include <linux/fs.h>
+#include <linux/proc_fs.h>
 
+#include <asm/unified.h>
 #include <asm/cpu.h>
 #include <asm/cputype.h>
 #include <asm/elf.h>
 #include <asm/procinfo.h>
+#include <asm/sections.h>
 #include <asm/setup.h>
 #include <asm/mach-types.h>
 #include <asm/cacheflush.h>
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
 #include <asm/traps.h>
+#include <asm/unwind.h>
 
 #include "compat.h"
 #include "atags.h"
+#include "tcm.h"
 
 #ifndef MEM_SIZE
 #define MEM_SIZE       (16*1024*1024)
@@ -59,15 +64,15 @@ static int __init fpe_setup(char *line)
 __setup("fpe=", fpe_setup);
 #endif
 
-extern void paging_init(struct meminfo *, struct machine_desc *desc);
+extern void paging_init(struct machine_desc *desc);
 extern void reboot_setup(char *str);
-extern int root_mountflags;
-extern void _stext, _text, _etext, __data_start, _edata, _end;
 
 unsigned int processor_id;
 EXPORT_SYMBOL(processor_id);
 unsigned int __machine_arch_type;
 EXPORT_SYMBOL(__machine_arch_type);
+unsigned int cacheid;
+EXPORT_SYMBOL(cacheid);
 
 unsigned int __atags_pointer __initdata;
 
@@ -83,8 +88,6 @@ EXPORT_SYMBOL(system_serial_high);
 unsigned int elf_hwcap;
 EXPORT_SYMBOL(elf_hwcap);
 
-unsigned long __initdata vmalloc_reserve = 128 << 20;
-
 
 #ifdef MULTI_CPU
 struct processor processor;
@@ -113,10 +116,6 @@ static struct stack stacks[NR_CPUS];
 char elf_platform[ELF_PLATFORM_SIZE];
 EXPORT_SYMBOL(elf_platform);
 
-unsigned long phys_initrd_start __initdata = 0;
-unsigned long phys_initrd_size __initdata = 0;
-
-static struct meminfo meminfo __initdata = { 0, };
 static const char *cpu_name;
 static const char *machine_name;
 static char __initdata command_line[COMMAND_LINE_SIZE];
@@ -180,63 +179,6 @@ static struct resource io_res[] = {
 #define lp1 io_res[1]
 #define lp2 io_res[2]
 
-static const char *cache_types[16] = {
-       "write-through",
-       "write-back",
-       "write-back",
-       "undefined 3",
-       "undefined 4",
-       "undefined 5",
-       "write-back",
-       "write-back",
-       "undefined 8",
-       "undefined 9",
-       "undefined 10",
-       "undefined 11",
-       "undefined 12",
-       "undefined 13",
-       "write-back",
-       "undefined 15",
-};
-
-static const char *cache_clean[16] = {
-       "not required",
-       "read-block",
-       "cp15 c7 ops",
-       "undefined 3",
-       "undefined 4",
-       "undefined 5",
-       "cp15 c7 ops",
-       "cp15 c7 ops",
-       "undefined 8",
-       "undefined 9",
-       "undefined 10",
-       "undefined 11",
-       "undefined 12",
-       "undefined 13",
-       "cp15 c7 ops",
-       "undefined 15",
-};
-
-static const char *cache_lockdown[16] = {
-       "not supported",
-       "not supported",
-       "not supported",
-       "undefined 3",
-       "undefined 4",
-       "undefined 5",
-       "format A",
-       "format B",
-       "undefined 8",
-       "undefined 9",
-       "undefined 10",
-       "undefined 11",
-       "undefined 12",
-       "undefined 13",
-       "format C",
-       "undefined 15",
-};
-
 static const char *proc_arch[] = {
        "undefined/unknown",
        "3",
@@ -257,48 +199,6 @@ static const char *proc_arch[] = {
        "?(17)",
 };
 
-#define CACHE_TYPE(x)  (((x) >> 25) & 15)
-#define CACHE_S(x)     ((x) & (1 << 24))
-#define CACHE_DSIZE(x) (((x) >> 12) & 4095)    /* only if S=1 */
-#define CACHE_ISIZE(x) ((x) & 4095)
-
-#define CACHE_SIZE(y)  (((y) >> 6) & 7)
-#define CACHE_ASSOC(y) (((y) >> 3) & 7)
-#define CACHE_M(y)     ((y) & (1 << 2))
-#define CACHE_LINE(y)  ((y) & 3)
-
-static inline void dump_cache(const char *prefix, int cpu, unsigned int cache)
-{
-       unsigned int mult = 2 + (CACHE_M(cache) ? 1 : 0);
-
-       printk("CPU%u: %s: %d bytes, associativity %d, %d byte lines, %d sets\n",
-               cpu, prefix,
-               mult << (8 + CACHE_SIZE(cache)),
-               (mult << CACHE_ASSOC(cache)) >> 1,
-               8 << CACHE_LINE(cache),
-               1 << (6 + CACHE_SIZE(cache) - CACHE_ASSOC(cache) -
-                       CACHE_LINE(cache)));
-}
-
-static void __init dump_cpu_info(int cpu)
-{
-       unsigned int info = read_cpuid_cachetype();
-
-       if (info != read_cpuid_id()) {
-               printk("CPU%u: D %s %s cache\n", cpu, cache_is_vivt() ? "VIVT" : "VIPT",
-                      cache_types[CACHE_TYPE(info)]);
-               if (CACHE_S(info)) {
-                       dump_cache("I cache", cpu, CACHE_ISIZE(info));
-                       dump_cache("D cache", cpu, CACHE_DSIZE(info));
-               } else {
-                       dump_cache("cache", cpu, CACHE_ISIZE(info));
-               }
-       }
-
-       if (arch_is_coherent())
-               printk("Cache coherency enabled\n");
-}
-
 int cpu_architecture(void)
 {
        int cpu_arch;
@@ -332,6 +232,35 @@ int cpu_architecture(void)
        return cpu_arch;
 }
 
+static void __init cacheid_init(void)
+{
+       unsigned int cachetype = read_cpuid_cachetype();
+       unsigned int arch = cpu_architecture();
+
+       if (arch >= CPU_ARCH_ARMv6) {
+               if ((cachetype & (7 << 29)) == 4 << 29) {
+                       /* ARMv7 register format */
+                       cacheid = CACHEID_VIPT_NONALIASING;
+                       if ((cachetype & (3 << 14)) == 1 << 14)
+                               cacheid |= CACHEID_ASID_TAGGED;
+               } else if (cachetype & (1 << 23))
+                       cacheid = CACHEID_VIPT_ALIASING;
+               else
+                       cacheid = CACHEID_VIPT_NONALIASING;
+       } else {
+               cacheid = CACHEID_VIVT;
+       }
+
+       printk("CPU: %s data cache, %s instruction cache\n",
+               cache_is_vivt() ? "VIVT" :
+               cache_is_vipt_aliasing() ? "VIPT aliasing" :
+               cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown",
+               cache_is_vivt() ? "VIVT" :
+               icache_is_vivt_asid_tagged() ? "VIVT ASID tagged" :
+               cache_is_vipt_aliasing() ? "VIPT aliasing" :
+               cache_is_vipt_nonaliasing() ? "VIPT nonaliasing" : "unknown");
+}
+
 /*
  * These functions re-use the assembly code in head.S, which
  * already provide the required functionality.
@@ -381,14 +310,14 @@ static void __init setup_processor(void)
        elf_hwcap &= ~HWCAP_THUMB;
 #endif
 
+       cacheid_init();
        cpu_proc_init();
 }
 
 /*
  * cpu_init - initialise one CPU.
  *
- * cpu_init dumps the cache information, initialises SMP specific
- * information, and sets up the per-CPU stacks.
+ * cpu_init sets up the per-CPU stacks.
  */
 void cpu_init(void)
 {
@@ -400,29 +329,39 @@ void cpu_init(void)
                BUG();
        }
 
-       if (system_state == SYSTEM_BOOTING)
-               dump_cpu_info(cpu);
+       /*
+        * Define the placement constraint for the inline asm directive below.
+        * In Thumb-2, msr with an immediate value is not allowed.
+        */
+#ifdef CONFIG_THUMB2_KERNEL
+#define PLC    "r"
+#else
+#define PLC    "I"
+#endif
 
        /*
         * setup stacks for re-entrant exception handlers
         */
        __asm__ (
        "msr    cpsr_c, %1\n\t"
-       "add    sp, %0, %2\n\t"
+       "add    r14, %0, %2\n\t"
+       "mov    sp, r14\n\t"
        "msr    cpsr_c, %3\n\t"
-       "add    sp, %0, %4\n\t"
+       "add    r14, %0, %4\n\t"
+       "mov    sp, r14\n\t"
        "msr    cpsr_c, %5\n\t"
-       "add    sp, %0, %6\n\t"
+       "add    r14, %0, %6\n\t"
+       "mov    sp, r14\n\t"
        "msr    cpsr_c, %7"
            :
            : "r" (stk),
-             "I" (PSR_F_BIT | PSR_I_BIT | IRQ_MODE),
+             PLC (PSR_F_BIT | PSR_I_BIT | IRQ_MODE),
              "I" (offsetof(struct stack, irq[0])),
-             "I" (PSR_F_BIT | PSR_I_BIT | ABT_MODE),
+             PLC (PSR_F_BIT | PSR_I_BIT | ABT_MODE),
              "I" (offsetof(struct stack, abt[0])),
-             "I" (PSR_F_BIT | PSR_I_BIT | UND_MODE),
+             PLC (PSR_F_BIT | PSR_I_BIT | UND_MODE),
              "I" (offsetof(struct stack, und[0])),
-             "I" (PSR_F_BIT | PSR_I_BIT | SVC_MODE)
+             PLC (PSR_F_BIT | PSR_I_BIT | SVC_MODE)
            : "r14");
 }
 
@@ -445,35 +384,34 @@ static struct machine_desc * __init setup_machine(unsigned int nr)
        return list;
 }
 
-static void __init early_initrd(char **p)
+static int __init arm_add_memory(unsigned long start, unsigned long size)
 {
-       unsigned long start, size;
+       struct membank *bank = &meminfo.bank[meminfo.nr_banks];
 
-       start = memparse(*p, p);
-       if (**p == ',') {
-               size = memparse((*p) + 1, p);
-
-               phys_initrd_start = start;
-               phys_initrd_size = size;
+       if (meminfo.nr_banks >= NR_BANKS) {
+               printk(KERN_CRIT "NR_BANKS too low, "
+                       "ignoring memory at %#lx\n", start);
+               return -EINVAL;
        }
-}
-__early_param("initrd=", early_initrd);
-
-static void __init arm_add_memory(unsigned long start, unsigned long size)
-{
-       struct membank *bank;
 
        /*
         * Ensure that start/size are aligned to a page boundary.
         * Size is appropriately rounded down, start is rounded up.
         */
        size -= start & ~PAGE_MASK;
-
-       bank = &meminfo.bank[meminfo.nr_banks++];
-
        bank->start = PAGE_ALIGN(start);
        bank->size  = size & PAGE_MASK;
        bank->node  = PHYS_TO_NID(start);
+
+       /*
+        * Check whether this memory region has non-zero size or
+        * invalid node number.
+        */
+       if (bank->size == 0 || bank->node >= MAX_NUMNODES)
+               return -EINVAL;
+
+       meminfo.nr_banks++;
+       return 0;
 }
 
 /*
@@ -505,17 +443,6 @@ static void __init early_mem(char **p)
 __early_param("mem=", early_mem);
 
 /*
- * vmalloc=size forces the vmalloc area to be exactly 'size'
- * bytes. This can be used to increase (or decrease) the vmalloc
- * area - the default is 128m.
- */
-static void __init early_vmalloc(char **arg)
-{
-       vmalloc_reserve = memparse(*arg, arg);
-}
-__early_param("vmalloc=", early_vmalloc);
-
-/*
  * Initial parsing of the command line.
  */
 static void __init parse_cmdline(char **cmdline_p, char *from)
@@ -529,12 +456,12 @@ static void __init parse_cmdline(char **cmdline_p, char *from)
                        struct early_params *p;
 
                        for (p = &__early_begin; p < &__early_end; p++) {
-                               int len = strlen(p->arg);
+                               int arglen = strlen(p->arg);
 
-                               if (memcmp(from, p->arg, len) == 0) {
+                               if (memcmp(from, p->arg, arglen) == 0) {
                                        if (to != command_line)
                                                to -= 1;
-                                       from += len;
+                                       from += arglen;
                                        p->fn(&from);
 
                                        while (*from != ' ' && *from != '\0')
@@ -575,24 +502,19 @@ request_standard_resources(struct meminfo *mi, struct machine_desc *mdesc)
        struct resource *res;
        int i;
 
-       kernel_code.start   = virt_to_phys(&_text);
-       kernel_code.end     = virt_to_phys(&_etext - 1);
-       kernel_data.start   = virt_to_phys(&__data_start);
-       kernel_data.end     = virt_to_phys(&_end - 1);
+       kernel_code.start   = virt_to_phys(_text);
+       kernel_code.end     = virt_to_phys(_etext - 1);
+       kernel_data.start   = virt_to_phys(_data);
+       kernel_data.end     = virt_to_phys(_end - 1);
 
        for (i = 0; i < mi->nr_banks; i++) {
-               unsigned long virt_start, virt_end;
-
                if (mi->bank[i].size == 0)
                        continue;
 
-               virt_start = __phys_to_virt(mi->bank[i].start);
-               virt_end   = virt_start + mi->bank[i].size - 1;
-
                res = alloc_bootmem_low(sizeof(*res));
                res->name  = "System RAM";
-               res->start = __virt_to_phys(virt_start);
-               res->end   = __virt_to_phys(virt_end);
+               res->start = mi->bank[i].start;
+               res->end   = mi->bank[i].start + mi->bank[i].size - 1;
                res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
 
                request_resource(&iomem_resource, res);
@@ -647,14 +569,7 @@ __tagtable(ATAG_CORE, parse_tag_core);
 
 static int __init parse_tag_mem32(const struct tag *tag)
 {
-       if (meminfo.nr_banks >= NR_BANKS) {
-               printk(KERN_WARNING
-                      "Ignoring memory bank 0x%08x size %dKB\n",
-                       tag->u.mem.start, tag->u.mem.size / 1024);
-               return -EINVAL;
-       }
-       arm_add_memory(tag->u.mem.start, tag->u.mem.size);
-       return 0;
+       return arm_add_memory(tag->u.mem.start, tag->u.mem.size);
 }
 
 __tagtable(ATAG_MEM, parse_tag_mem32);
@@ -696,26 +611,6 @@ static int __init parse_tag_ramdisk(const struct tag *tag)
 
 __tagtable(ATAG_RAMDISK, parse_tag_ramdisk);
 
-static int __init parse_tag_initrd(const struct tag *tag)
-{
-       printk(KERN_WARNING "ATAG_INITRD is deprecated; "
-               "please update your bootloader.\n");
-       phys_initrd_start = __virt_to_phys(tag->u.initrd.start);
-       phys_initrd_size = tag->u.initrd.size;
-       return 0;
-}
-
-__tagtable(ATAG_INITRD, parse_tag_initrd);
-
-static int __init parse_tag_initrd2(const struct tag *tag)
-{
-       phys_initrd_start = tag->u.initrd.start;
-       phys_initrd_size = tag->u.initrd.size;
-       return 0;
-}
-
-__tagtable(ATAG_INITRD2, parse_tag_initrd2);
-
 static int __init parse_tag_serialnr(const struct tag *tag)
 {
        system_serial_low = tag->u.serialnr.low;
@@ -807,6 +702,8 @@ void __init setup_arch(char **cmdline_p)
        struct machine_desc *mdesc;
        char *from = default_command_line;
 
+       unwind_init();
+
        setup_processor();
        mdesc = setup_machine(machine_arch_type);
        machine_name = mdesc->name;
@@ -838,15 +735,15 @@ void __init setup_arch(char **cmdline_p)
                parse_tags(tags);
        }
 
-       init_mm.start_code = (unsigned long) &_text;
-       init_mm.end_code   = (unsigned long) &_etext;
-       init_mm.end_data   = (unsigned long) &_edata;
-       init_mm.brk        = (unsigned long) &_end;
+       init_mm.start_code = (unsigned long) _text;
+       init_mm.end_code   = (unsigned long) _etext;
+       init_mm.end_data   = (unsigned long) _edata;
+       init_mm.brk        = (unsigned long) _end;
 
        memcpy(boot_command_line, from, COMMAND_LINE_SIZE);
        boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
        parse_cmdline(cmdline_p, from);
-       paging_init(&meminfo, mdesc);
+       paging_init(mdesc);
        request_standard_resources(&meminfo, mdesc);
 
 #ifdef CONFIG_SMP
@@ -854,6 +751,7 @@ void __init setup_arch(char **cmdline_p)
 #endif
 
        cpu_init();
+       tcm_init();
 
        /*
         * Set up various architecture-specific pointers
@@ -885,9 +783,21 @@ static int __init topology_init(void)
 
        return 0;
 }
-
 subsys_initcall(topology_init);
 
+#ifdef CONFIG_HAVE_PROC_CPU
+static int __init proc_cpu_init(void)
+{
+       struct proc_dir_entry *res;
+
+       res = proc_mkdir("cpu", NULL);
+       if (!res)
+               return -ENOMEM;
+       return 0;
+}
+fs_initcall(proc_cpu_init);
+#endif
+
 static const char *hwcap_str[] = {
        "swp",
        "half",
@@ -900,25 +810,13 @@ static const char *hwcap_str[] = {
        "java",
        "iwmmxt",
        "crunch",
+       "thumbee",
+       "neon",
+       "vfpv3",
+       "vfpv3d16",
        NULL
 };
 
-static void
-c_show_cache(struct seq_file *m, const char *type, unsigned int cache)
-{
-       unsigned int mult = 2 + (CACHE_M(cache) ? 1 : 0);
-
-       seq_printf(m, "%s size\t\t: %d\n"
-                     "%s assoc\t\t: %d\n"
-                     "%s line length\t: %d\n"
-                     "%s sets\t\t: %d\n",
-               type, mult << (8 + CACHE_SIZE(cache)),
-               type, (mult << CACHE_ASSOC(cache)) >> 1,
-               type, 8 << CACHE_LINE(cache),
-               type, 1 << (6 + CACHE_SIZE(cache) - CACHE_ASSOC(cache) -
-                           CACHE_LINE(cache)));
-}
-
 static int c_show(struct seq_file *m, void *v)
 {
        int i;
@@ -972,27 +870,6 @@ static int c_show(struct seq_file *m, void *v)
        }
        seq_printf(m, "CPU revision\t: %d\n", read_cpuid_id() & 15);
 
-       {
-               unsigned int cache_info = read_cpuid_cachetype();
-               if (cache_info != read_cpuid_id()) {
-                       seq_printf(m, "Cache type\t: %s\n"
-                                     "Cache clean\t: %s\n"
-                                     "Cache lockdown\t: %s\n"
-                                     "Cache format\t: %s\n",
-                                  cache_types[CACHE_TYPE(cache_info)],
-                                  cache_clean[CACHE_TYPE(cache_info)],
-                                  cache_lockdown[CACHE_TYPE(cache_info)],
-                                  CACHE_S(cache_info) ? "Harvard" : "Unified");
-
-                       if (CACHE_S(cache_info)) {
-                               c_show_cache(m, "I", CACHE_ISIZE(cache_info));
-                               c_show_cache(m, "D", CACHE_DSIZE(cache_info));
-                       } else {
-                               c_show_cache(m, "Cache", CACHE_ISIZE(cache_info));
-                       }
-               }
-       }
-
        seq_puts(m, "\n");
 
        seq_printf(m, "Hardware\t: %s\n", machine_name);