root/arch/s390/kernel/processor.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. cpu_detect_mhz_feature
  2. update_cpu_mhz
  3. s390_update_cpu_mhz
  4. stop_machine_yield
  5. cpu_init
  6. cpu_have_feature
  7. show_facilities
  8. show_cpu_summary
  9. show_cpu_mhz
  10. show_cpuinfo
  11. c_update
  12. c_start
  13. c_next
  14. c_stop
  15. s390_isolate_bp
  16. s390_isolate_bp_guest

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  *  Copyright IBM Corp. 2008
   4  *  Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com)
   5  */
   6 
   7 #define KMSG_COMPONENT "cpu"
   8 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
   9 
  10 #include <linux/stop_machine.h>
  11 #include <linux/cpufeature.h>
  12 #include <linux/bitops.h>
  13 #include <linux/kernel.h>
  14 #include <linux/sched/mm.h>
  15 #include <linux/init.h>
  16 #include <linux/seq_file.h>
  17 #include <linux/mm_types.h>
  18 #include <linux/delay.h>
  19 #include <linux/cpu.h>
  20 
  21 #include <asm/diag.h>
  22 #include <asm/facility.h>
  23 #include <asm/elf.h>
  24 #include <asm/lowcore.h>
  25 #include <asm/param.h>
  26 #include <asm/smp.h>
  27 
  28 struct cpu_info {
  29         unsigned int cpu_mhz_dynamic;
  30         unsigned int cpu_mhz_static;
  31         struct cpuid cpu_id;
  32 };
  33 
  34 static DEFINE_PER_CPU(struct cpu_info, cpu_info);
  35 static DEFINE_PER_CPU(int, cpu_relax_retry);
  36 
  37 static bool machine_has_cpu_mhz;
  38 
  39 void __init cpu_detect_mhz_feature(void)
  40 {
  41         if (test_facility(34) && __ecag(ECAG_CPU_ATTRIBUTE, 0) != -1UL)
  42                 machine_has_cpu_mhz = true;
  43 }
  44 
  45 static void update_cpu_mhz(void *arg)
  46 {
  47         unsigned long mhz;
  48         struct cpu_info *c;
  49 
  50         mhz = __ecag(ECAG_CPU_ATTRIBUTE, 0);
  51         c = this_cpu_ptr(&cpu_info);
  52         c->cpu_mhz_dynamic = mhz >> 32;
  53         c->cpu_mhz_static = mhz & 0xffffffff;
  54 }
  55 
  56 void s390_update_cpu_mhz(void)
  57 {
  58         s390_adjust_jiffies();
  59         if (machine_has_cpu_mhz)
  60                 on_each_cpu(update_cpu_mhz, NULL, 0);
  61 }
  62 
  63 void notrace stop_machine_yield(const struct cpumask *cpumask)
  64 {
  65         int cpu, this_cpu;
  66 
  67         this_cpu = smp_processor_id();
  68         if (__this_cpu_inc_return(cpu_relax_retry) >= spin_retry) {
  69                 __this_cpu_write(cpu_relax_retry, 0);
  70                 cpu = cpumask_next_wrap(this_cpu, cpumask, this_cpu, false);
  71                 if (cpu >= nr_cpu_ids)
  72                         return;
  73                 if (arch_vcpu_is_preempted(cpu))
  74                         smp_yield_cpu(cpu);
  75         }
  76 }
  77 
  78 /*
  79  * cpu_init - initializes state that is per-CPU.
  80  */
  81 void cpu_init(void)
  82 {
  83         struct cpuid *id = this_cpu_ptr(&cpu_info.cpu_id);
  84 
  85         get_cpu_id(id);
  86         if (machine_has_cpu_mhz)
  87                 update_cpu_mhz(NULL);
  88         mmgrab(&init_mm);
  89         current->active_mm = &init_mm;
  90         BUG_ON(current->mm);
  91         enter_lazy_tlb(&init_mm, current);
  92 }
  93 
  94 /*
  95  * cpu_have_feature - Test CPU features on module initialization
  96  */
  97 int cpu_have_feature(unsigned int num)
  98 {
  99         return elf_hwcap & (1UL << num);
 100 }
 101 EXPORT_SYMBOL(cpu_have_feature);
 102 
 103 static void show_facilities(struct seq_file *m)
 104 {
 105         unsigned int bit;
 106         long *facilities;
 107 
 108         facilities = (long *)&S390_lowcore.stfle_fac_list;
 109         seq_puts(m, "facilities      :");
 110         for_each_set_bit_inv(bit, facilities, MAX_FACILITY_BIT)
 111                 seq_printf(m, " %d", bit);
 112         seq_putc(m, '\n');
 113 }
 114 
 115 static void show_cpu_summary(struct seq_file *m, void *v)
 116 {
 117         static const char *hwcap_str[] = {
 118                 "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp",
 119                 "edat", "etf3eh", "highgprs", "te", "vx", "vxd", "vxe", "gs",
 120                 "vxe2", "vxp", "sort", "dflt"
 121         };
 122         static const char * const int_hwcap_str[] = {
 123                 "sie"
 124         };
 125         int i, cpu;
 126 
 127         seq_printf(m, "vendor_id       : IBM/S390\n"
 128                    "# processors    : %i\n"
 129                    "bogomips per cpu: %lu.%02lu\n",
 130                    num_online_cpus(), loops_per_jiffy/(500000/HZ),
 131                    (loops_per_jiffy/(5000/HZ))%100);
 132         seq_printf(m, "max thread id   : %d\n", smp_cpu_mtid);
 133         seq_puts(m, "features\t: ");
 134         for (i = 0; i < ARRAY_SIZE(hwcap_str); i++)
 135                 if (hwcap_str[i] && (elf_hwcap & (1UL << i)))
 136                         seq_printf(m, "%s ", hwcap_str[i]);
 137         for (i = 0; i < ARRAY_SIZE(int_hwcap_str); i++)
 138                 if (int_hwcap_str[i] && (int_hwcap & (1UL << i)))
 139                         seq_printf(m, "%s ", int_hwcap_str[i]);
 140         seq_puts(m, "\n");
 141         show_facilities(m);
 142         show_cacheinfo(m);
 143         for_each_online_cpu(cpu) {
 144                 struct cpuid *id = &per_cpu(cpu_info.cpu_id, cpu);
 145 
 146                 seq_printf(m, "processor %d: "
 147                            "version = %02X,  "
 148                            "identification = %06X,  "
 149                            "machine = %04X\n",
 150                            cpu, id->version, id->ident, id->machine);
 151         }
 152 }
 153 
 154 static void show_cpu_mhz(struct seq_file *m, unsigned long n)
 155 {
 156         struct cpu_info *c = per_cpu_ptr(&cpu_info, n);
 157 
 158         seq_printf(m, "cpu MHz dynamic : %d\n", c->cpu_mhz_dynamic);
 159         seq_printf(m, "cpu MHz static  : %d\n", c->cpu_mhz_static);
 160 }
 161 
 162 /*
 163  * show_cpuinfo - Get information on one CPU for use by procfs.
 164  */
 165 static int show_cpuinfo(struct seq_file *m, void *v)
 166 {
 167         unsigned long n = (unsigned long) v - 1;
 168         unsigned long first = cpumask_first(cpu_online_mask);
 169 
 170         if (n == first)
 171                 show_cpu_summary(m, v);
 172         if (!machine_has_cpu_mhz)
 173                 return 0;
 174         seq_printf(m, "\ncpu number      : %ld\n", n);
 175         show_cpu_mhz(m, n);
 176         return 0;
 177 }
 178 
 179 static inline void *c_update(loff_t *pos)
 180 {
 181         if (*pos)
 182                 *pos = cpumask_next(*pos - 1, cpu_online_mask);
 183         else
 184                 *pos = cpumask_first(cpu_online_mask);
 185         return *pos < nr_cpu_ids ? (void *)*pos + 1 : NULL;
 186 }
 187 
 188 static void *c_start(struct seq_file *m, loff_t *pos)
 189 {
 190         get_online_cpus();
 191         return c_update(pos);
 192 }
 193 
 194 static void *c_next(struct seq_file *m, void *v, loff_t *pos)
 195 {
 196         ++*pos;
 197         return c_update(pos);
 198 }
 199 
 200 static void c_stop(struct seq_file *m, void *v)
 201 {
 202         put_online_cpus();
 203 }
 204 
 205 const struct seq_operations cpuinfo_op = {
 206         .start  = c_start,
 207         .next   = c_next,
 208         .stop   = c_stop,
 209         .show   = show_cpuinfo,
 210 };
 211 
 212 int s390_isolate_bp(void)
 213 {
 214         if (!test_facility(82))
 215                 return -EOPNOTSUPP;
 216         set_thread_flag(TIF_ISOLATE_BP);
 217         return 0;
 218 }
 219 EXPORT_SYMBOL(s390_isolate_bp);
 220 
 221 int s390_isolate_bp_guest(void)
 222 {
 223         if (!test_facility(82))
 224                 return -EOPNOTSUPP;
 225         set_thread_flag(TIF_ISOLATE_BP_GUEST);
 226         return 0;
 227 }
 228 EXPORT_SYMBOL(s390_isolate_bp_guest);

/* [<][>][^][v][top][bottom][index][help] */