1395d31d4SMartin Schwidefsky /* 2395d31d4SMartin Schwidefsky * Copyright IBM Corp. 2008 3395d31d4SMartin Schwidefsky * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) 4395d31d4SMartin Schwidefsky */ 5395d31d4SMartin Schwidefsky 6395d31d4SMartin Schwidefsky #define KMSG_COMPONENT "cpu" 7395d31d4SMartin Schwidefsky #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 8395d31d4SMartin Schwidefsky 9395d31d4SMartin Schwidefsky #include <linux/kernel.h> 10395d31d4SMartin Schwidefsky #include <linux/init.h> 11395d31d4SMartin Schwidefsky #include <linux/seq_file.h> 12395d31d4SMartin Schwidefsky #include <linux/delay.h> 1319726cecSHeiko Carstens #include <linux/cpu.h> 14395d31d4SMartin Schwidefsky #include <asm/elf.h> 15395d31d4SMartin Schwidefsky #include <asm/lowcore.h> 16395d31d4SMartin Schwidefsky #include <asm/param.h> 174d92f502SHeiko Carstens #include <asm/smp.h> 18395d31d4SMartin Schwidefsky 1994038a99SMartin Schwidefsky static DEFINE_PER_CPU(struct cpuid, cpu_id); 2094038a99SMartin Schwidefsky 21a9ca8eb7SHeiko Carstens void notrace cpu_relax(void) 224d92f502SHeiko Carstens { 234d92f502SHeiko Carstens if (!smp_cpu_mtid && MACHINE_HAS_DIAG44) 244d92f502SHeiko Carstens asm volatile("diag 0,0,0x44"); 254d92f502SHeiko Carstens barrier(); 264d92f502SHeiko Carstens } 274d92f502SHeiko Carstens EXPORT_SYMBOL(cpu_relax); 284d92f502SHeiko Carstens 2994038a99SMartin Schwidefsky /* 3094038a99SMartin Schwidefsky * cpu_init - initializes state that is per-CPU. 3194038a99SMartin Schwidefsky */ 32e2741f17SPaul Gortmaker void cpu_init(void) 3394038a99SMartin Schwidefsky { 34eb7e7d76SChristoph Lameter struct cpuid *id = this_cpu_ptr(&cpu_id); 3594038a99SMartin Schwidefsky 3694038a99SMartin Schwidefsky get_cpu_id(id); 3794038a99SMartin Schwidefsky atomic_inc(&init_mm.mm_count); 3894038a99SMartin Schwidefsky current->active_mm = &init_mm; 3994038a99SMartin Schwidefsky BUG_ON(current->mm); 4094038a99SMartin Schwidefsky enter_lazy_tlb(&init_mm, current); 4194038a99SMartin Schwidefsky } 4294038a99SMartin Schwidefsky 4394038a99SMartin Schwidefsky /* 448f00b3e2SHendrik Brueckner * cpu_have_feature - Test CPU features on module initialization 458f00b3e2SHendrik Brueckner */ 468f00b3e2SHendrik Brueckner int cpu_have_feature(unsigned int num) 478f00b3e2SHendrik Brueckner { 488f00b3e2SHendrik Brueckner return elf_hwcap & (1UL << num); 498f00b3e2SHendrik Brueckner } 508f00b3e2SHendrik Brueckner EXPORT_SYMBOL(cpu_have_feature); 518f00b3e2SHendrik Brueckner 528f00b3e2SHendrik Brueckner /* 53395d31d4SMartin Schwidefsky * show_cpuinfo - Get information on one CPU for use by procfs. 54395d31d4SMartin Schwidefsky */ 55395d31d4SMartin Schwidefsky static int show_cpuinfo(struct seq_file *m, void *v) 56395d31d4SMartin Schwidefsky { 57fbf3c542SHeiko Carstens static const char *hwcap_str[] = { 58395d31d4SMartin Schwidefsky "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp", 5980703617SMartin Schwidefsky "edat", "etf3eh", "highgprs", "te", "vx" 60395d31d4SMartin Schwidefsky }; 61395d31d4SMartin Schwidefsky unsigned long n = (unsigned long) v - 1; 62395d31d4SMartin Schwidefsky int i; 63395d31d4SMartin Schwidefsky 64395d31d4SMartin Schwidefsky if (!n) { 658e102301SHeiko Carstens s390_adjust_jiffies(); 66395d31d4SMartin Schwidefsky seq_printf(m, "vendor_id : IBM/S390\n" 67395d31d4SMartin Schwidefsky "# processors : %i\n" 68395d31d4SMartin Schwidefsky "bogomips per cpu: %lu.%02lu\n", 69395d31d4SMartin Schwidefsky num_online_cpus(), loops_per_jiffy/(500000/HZ), 70395d31d4SMartin Schwidefsky (loops_per_jiffy/(5000/HZ))%100); 71395d31d4SMartin Schwidefsky seq_puts(m, "features\t: "); 72fbf3c542SHeiko Carstens for (i = 0; i < ARRAY_SIZE(hwcap_str); i++) 73395d31d4SMartin Schwidefsky if (hwcap_str[i] && (elf_hwcap & (1UL << i))) 74395d31d4SMartin Schwidefsky seq_printf(m, "%s ", hwcap_str[i]); 75395d31d4SMartin Schwidefsky seq_puts(m, "\n"); 766668022cSHeiko Carstens show_cacheinfo(m); 77395d31d4SMartin Schwidefsky } 7819726cecSHeiko Carstens get_online_cpus(); 79395d31d4SMartin Schwidefsky if (cpu_online(n)) { 8094038a99SMartin Schwidefsky struct cpuid *id = &per_cpu(cpu_id, n); 81395d31d4SMartin Schwidefsky seq_printf(m, "processor %li: " 82395d31d4SMartin Schwidefsky "version = %02X, " 83395d31d4SMartin Schwidefsky "identification = %06X, " 84395d31d4SMartin Schwidefsky "machine = %04X\n", 8594038a99SMartin Schwidefsky n, id->version, id->ident, id->machine); 86395d31d4SMartin Schwidefsky } 8719726cecSHeiko Carstens put_online_cpus(); 88395d31d4SMartin Schwidefsky return 0; 89395d31d4SMartin Schwidefsky } 90395d31d4SMartin Schwidefsky 91395d31d4SMartin Schwidefsky static void *c_start(struct seq_file *m, loff_t *pos) 92395d31d4SMartin Schwidefsky { 93dd4a5a31SMartin Schwidefsky return *pos < nr_cpu_ids ? (void *)((unsigned long) *pos + 1) : NULL; 94395d31d4SMartin Schwidefsky } 95395d31d4SMartin Schwidefsky 96395d31d4SMartin Schwidefsky static void *c_next(struct seq_file *m, void *v, loff_t *pos) 97395d31d4SMartin Schwidefsky { 98395d31d4SMartin Schwidefsky ++*pos; 99395d31d4SMartin Schwidefsky return c_start(m, pos); 100395d31d4SMartin Schwidefsky } 101395d31d4SMartin Schwidefsky 102395d31d4SMartin Schwidefsky static void c_stop(struct seq_file *m, void *v) 103395d31d4SMartin Schwidefsky { 104395d31d4SMartin Schwidefsky } 105395d31d4SMartin Schwidefsky 106395d31d4SMartin Schwidefsky const struct seq_operations cpuinfo_op = { 107395d31d4SMartin Schwidefsky .start = c_start, 108395d31d4SMartin Schwidefsky .next = c_next, 109395d31d4SMartin Schwidefsky .stop = c_stop, 110395d31d4SMartin Schwidefsky .show = show_cpuinfo, 111395d31d4SMartin Schwidefsky }; 112395d31d4SMartin Schwidefsky 113