#include <linux/cpu.h>
#include <linux/interrupt.h>
+#include <asm/cpu.h>
#include <asm/elf.h>
#include <asm/hardware.h>
#include <asm/io.h>
extern void squash_mem_tags(struct tag *tag);
extern void reboot_setup(char *str);
extern int root_mountflags;
-extern int _stext, _text, _etext, _edata, _end;
+extern void _stext, _text, _etext, __data_start, _edata, _end;
unsigned int processor_id;
unsigned int __machine_arch_type;
static union { char c[4]; unsigned long l; } endian_test __initdata = { { 'l', '?', '?', 'b' } };
#define ENDIANNESS ((char)endian_test.l)
+DEFINE_PER_CPU(struct cpuinfo_arm, cpu_data);
+
/*
* Standard memory resources
*/
static struct resource mem_res[] = {
{ "Video RAM", 0, 0, IORESOURCE_MEM },
- { "Kernel code", 0, 0, IORESOURCE_MEM },
+ { "Kernel text", 0, 0, IORESOURCE_MEM },
{ "Kernel data", 0, 0, IORESOURCE_MEM }
};
#define lp2 io_res[2]
static const char *cache_types[16] = {
- "VIVT write-through",
- "VIVT write-back",
- "VIVT write-back",
+ "write-through",
+ "write-back",
+ "write-back",
"undefined 3",
"undefined 4",
"undefined 5",
- "VIVT write-back",
- "VIVT write-back",
+ "write-back",
+ "write-back",
"undefined 8",
"undefined 9",
"undefined 10",
"undefined 11",
"undefined 12",
"undefined 13",
- "VIPT write-back",
+ "write-back",
"undefined 15",
};
#define CACHE_M(y) ((y) & (1 << 2))
#define CACHE_LINE(y) ((y) & 3)
-static inline void dump_cache(const char *prefix, unsigned int cache)
+static inline void dump_cache(const char *prefix, int cpu, unsigned int cache)
{
unsigned int mult = 2 + (CACHE_M(cache) ? 1 : 0);
- printk("%s: %d bytes, associativity %d, %d byte lines, %d sets\n",
- prefix,
+ 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),
CACHE_LINE(cache)));
}
-static void __init dump_cpu_info(void)
+static void __init dump_cpu_info(int cpu)
{
unsigned int info = read_cpuid(CPUID_CACHETYPE);
if (info != processor_id) {
- printk("CPU: D %s cache\n", cache_types[CACHE_TYPE(info)]);
+ 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("CPU: I cache", CACHE_ISIZE(info));
- dump_cache("CPU: D cache", CACHE_DSIZE(info));
+ dump_cache("I cache", cpu, CACHE_ISIZE(info));
+ dump_cache("D cache", cpu, CACHE_DSIZE(info));
} else {
- dump_cache("CPU: cache", CACHE_ISIZE(info));
+ dump_cache("cache", cpu, CACHE_ISIZE(info));
}
}
}
} else if ((processor_id & 0x0000f000) == 0x00007000) {
cpu_arch = (processor_id & (1 << 23)) ? CPU_ARCH_ARMv4T : CPU_ARCH_ARMv3;
} else {
- cpu_arch = (processor_id >> 16) & 15;
+ cpu_arch = (processor_id >> 16) & 7;
if (cpu_arch)
cpu_arch += CPU_ARCH_ARMv3;
}
return cpu_arch;
}
+/*
+ * These functions re-use the assembly code in head.S, which
+ * already provide the required functionality.
+ */
+extern struct proc_info_list *lookup_processor_type(void);
+extern struct machine_desc *lookup_machine_type(unsigned int);
+
static void __init setup_processor(void)
{
- extern struct proc_info_list __proc_info_begin, __proc_info_end;
struct proc_info_list *list;
/*
* types. The linker builds this table for us from the
* entries in arch/arm/mm/proc-*.S
*/
- for (list = &__proc_info_begin; list < &__proc_info_end ; list++)
- if ((processor_id & list->cpu_mask) == list->cpu_val)
- break;
-
- /*
- * If processor type is unrecognised, then we
- * can do nothing...
- */
- if (list >= &__proc_info_end) {
+ list = lookup_processor_type();
+ if (!list) {
printk("CPU configuration botched (ID %08x), unable "
"to continue.\n", processor_id);
while (1);
cpu_name, processor_id, (int)processor_id & 15,
proc_arch[cpu_architecture()]);
- dump_cpu_info();
+ dump_cpu_info(smp_processor_id());
sprintf(system_utsname.machine, "%s%c", list->arch_name, ENDIANNESS);
sprintf(elf_platform, "%s%c", list->elf_name, ENDIANNESS);
static struct machine_desc * __init setup_machine(unsigned int nr)
{
- extern struct machine_desc __arch_info_begin, __arch_info_end;
struct machine_desc *list;
/*
- * locate architecture in the list of supported architectures.
+ * locate machine in the list of supported machines.
*/
- for (list = &__arch_info_begin; list < &__arch_info_end; list++)
- if (list->nr == nr)
- break;
-
- /*
- * If the architecture type is not recognised, then we
- * can co nothing...
- */
- if (list >= &__arch_info_end) {
- printk("Architecture configuration botched (nr %d), unable "
+ list = lookup_machine_type(nr);
+ if (!list) {
+ printk("Machine configuration botched (nr %d), unable "
"to continue.\n", nr);
while (1);
}
struct resource *res;
int i;
- kernel_code.start = __virt_to_phys(init_mm.start_code);
- kernel_code.end = __virt_to_phys(init_mm.end_code - 1);
- kernel_data.start = __virt_to_phys(init_mm.end_code);
- kernel_data.end = __virt_to_phys(init_mm.brk - 1);
+ 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);
for (i = 0; i < mi->nr_banks; i++) {
unsigned long virt_start, virt_end;
* Set up various architecture-specific pointers
*/
init_arch_irq = mdesc->init_irq;
- init_arch_time = mdesc->init_time;
+ system_timer = mdesc->timer;
init_machine = mdesc->init_machine;
#ifdef CONFIG_VT
#endif
}
-static struct cpu cpu[1];
static int __init topology_init(void)
{
- return register_cpu(cpu, 0, NULL);
+ int cpu;
+
+ for_each_cpu(cpu)
+ register_cpu(&per_cpu(cpu_data, cpu).cpu, cpu, NULL);
+
+ return 0;
}
subsys_initcall(topology_init);
seq_printf(m, "Processor\t: %s rev %d (%s)\n",
cpu_name, (int)processor_id & 15, elf_platform);
+#if defined(CONFIG_SMP)
+ for_each_online_cpu(i) {
+ seq_printf(m, "Processor\t: %d\n", i);
+ seq_printf(m, "BogoMIPS\t: %lu.%02lu\n\n",
+ per_cpu(cpu_data, i).loops_per_jiffy / (500000UL/HZ),
+ (per_cpu(cpu_data, i).loops_per_jiffy / (5000UL/HZ)) % 100);
+ }
+#else /* CONFIG_SMP */
seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
loops_per_jiffy / (500000/HZ),
(loops_per_jiffy / (5000/HZ)) % 100);
+#endif
/* dump out the processor features */
seq_puts(m, "Features\t: ");