processor.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. /*
  2. * Copyright IBM Corp. 2008
  3. * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
  4. */
  5. #define KMSG_COMPONENT "cpu"
  6. #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
  7. #include <linux/kernel.h>
  8. #include <linux/init.h>
  9. #include <linux/seq_file.h>
  10. #include <linux/delay.h>
  11. #include <linux/cpu.h>
  12. #include <asm/diag.h>
  13. #include <asm/elf.h>
  14. #include <asm/lowcore.h>
  15. #include <asm/param.h>
  16. #include <asm/smp.h>
  17. static DEFINE_PER_CPU(struct cpuid, cpu_id);
  18. void notrace cpu_relax(void)
  19. {
  20. if (!smp_cpu_mtid && MACHINE_HAS_DIAG44) {
  21. diag_stat_inc(DIAG_STAT_X044);
  22. asm volatile("diag 0,0,0x44");
  23. }
  24. barrier();
  25. }
  26. EXPORT_SYMBOL(cpu_relax);
  27. /*
  28. * cpu_init - initializes state that is per-CPU.
  29. */
  30. void cpu_init(void)
  31. {
  32. struct cpuid *id = this_cpu_ptr(&cpu_id);
  33. get_cpu_id(id);
  34. atomic_inc(&init_mm.mm_count);
  35. current->active_mm = &init_mm;
  36. BUG_ON(current->mm);
  37. enter_lazy_tlb(&init_mm, current);
  38. }
  39. /*
  40. * cpu_have_feature - Test CPU features on module initialization
  41. */
  42. int cpu_have_feature(unsigned int num)
  43. {
  44. return elf_hwcap & (1UL << num);
  45. }
  46. EXPORT_SYMBOL(cpu_have_feature);
  47. /*
  48. * show_cpuinfo - Get information on one CPU for use by procfs.
  49. */
  50. static int show_cpuinfo(struct seq_file *m, void *v)
  51. {
  52. static const char *hwcap_str[] = {
  53. "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp",
  54. "edat", "etf3eh", "highgprs", "te", "vx"
  55. };
  56. static const char * const int_hwcap_str[] = {
  57. "sie"
  58. };
  59. unsigned long n = (unsigned long) v - 1;
  60. int i;
  61. if (!n) {
  62. s390_adjust_jiffies();
  63. seq_printf(m, "vendor_id : IBM/S390\n"
  64. "# processors : %i\n"
  65. "bogomips per cpu: %lu.%02lu\n",
  66. num_online_cpus(), loops_per_jiffy/(500000/HZ),
  67. (loops_per_jiffy/(5000/HZ))%100);
  68. seq_puts(m, "features\t: ");
  69. for (i = 0; i < ARRAY_SIZE(hwcap_str); i++)
  70. if (hwcap_str[i] && (elf_hwcap & (1UL << i)))
  71. seq_printf(m, "%s ", hwcap_str[i]);
  72. for (i = 0; i < ARRAY_SIZE(int_hwcap_str); i++)
  73. if (int_hwcap_str[i] && (int_hwcap & (1UL << i)))
  74. seq_printf(m, "%s ", int_hwcap_str[i]);
  75. seq_puts(m, "\n");
  76. show_cacheinfo(m);
  77. }
  78. if (cpu_online(n)) {
  79. struct cpuid *id = &per_cpu(cpu_id, n);
  80. seq_printf(m, "processor %li: "
  81. "version = %02X, "
  82. "identification = %06X, "
  83. "machine = %04X\n",
  84. n, id->version, id->ident, id->machine);
  85. }
  86. return 0;
  87. }
  88. static inline void *c_update(loff_t *pos)
  89. {
  90. if (*pos)
  91. *pos = cpumask_next(*pos - 1, cpu_online_mask);
  92. return *pos < nr_cpu_ids ? (void *)*pos + 1 : NULL;
  93. }
  94. static void *c_start(struct seq_file *m, loff_t *pos)
  95. {
  96. get_online_cpus();
  97. return c_update(pos);
  98. }
  99. static void *c_next(struct seq_file *m, void *v, loff_t *pos)
  100. {
  101. ++*pos;
  102. return c_update(pos);
  103. }
  104. static void c_stop(struct seq_file *m, void *v)
  105. {
  106. put_online_cpus();
  107. }
  108. const struct seq_operations cpuinfo_op = {
  109. .start = c_start,
  110. .next = c_next,
  111. .stop = c_stop,
  112. .show = show_cpuinfo,
  113. };