s390/cpuinfo: show dynamic and static cpu mhz
authorHeiko Carstens <heiko.carstens@de.ibm.com>
Thu, 14 Apr 2016 10:35:22 +0000 (12:35 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Mon, 13 Jun 2016 13:58:17 +0000 (15:58 +0200)
Show the dynamic and static cpu mhz of each cpu. Since these values
are per cpu this requires a fundamental extension of the format of
/proc/cpuinfo.

Historically we had only a single line per cpu and a summary at the
top of the file. This format is hardly extendible if we want to add
more per cpu information.

Therefore this patch adds per cpu blocks at the end of /proc/cpuinfo:

cpu             : 0
cpu Mhz dynamic : 5504
cpu Mhz static  : 5504

cpu             : 1
cpu Mhz dynamic : 5504
cpu Mhz static  : 5504

cpu             : 2
cpu Mhz dynamic : 5504
cpu Mhz static  : 5504

cpu             : 3
cpu Mhz dynamic : 5504
cpu Mhz static  : 5504

Right now each block contains only the dynamic and static cpu mhz,
but it can be easily extended like on every other architecture.

This extension is supposed to be compatible with the old format.

Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Acked-by: Sascha Silbe <silbe@linux.vnet.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/include/asm/processor.h
arch/s390/kernel/cache.c
arch/s390/kernel/processor.c
arch/s390/kernel/setup.c
drivers/s390/char/sclp_config.c

index 9d4d311..0952920 100644 (file)
@@ -77,7 +77,10 @@ static inline void get_cpu_id(struct cpuid *ptr)
        asm volatile("stidp %0" : "=Q" (*ptr));
 }
 
-extern void s390_adjust_jiffies(void);
+void s390_adjust_jiffies(void);
+void s390_update_cpu_mhz(void);
+void cpu_detect_mhz_feature(void);
+
 extern const struct seq_operations cpuinfo_op;
 extern int sysctl_ieee_emulation_warnings;
 extern void execve_tail(void);
@@ -233,6 +236,18 @@ void cpu_relax(void);
 
 #define cpu_relax_lowlatency()  barrier()
 
+#define ECAG_CACHE_ATTRIBUTE   0
+#define ECAG_CPU_ATTRIBUTE     1
+
+static inline unsigned long __ecag(unsigned int asi, unsigned char parm)
+{
+       unsigned long val;
+
+       asm volatile(".insn     rsy,0xeb000000004c,%0,0,0(%1)" /* ecag */
+                    : "=d" (val) : "a" (asi << 8 | parm));
+       return val;
+}
+
 static inline void psw_set_key(unsigned int key)
 {
        asm volatile("spka 0(%0)" : : "d" (key));
index 77a84bd..c8a8327 100644 (file)
@@ -99,12 +99,7 @@ static inline enum cache_type get_cache_type(struct cache_info *ci, int level)
 
 static inline unsigned long ecag(int ai, int li, int ti)
 {
-       unsigned long cmd, val;
-
-       cmd = ai << 4 | li << 1 | ti;
-       asm volatile(".insn     rsy,0xeb000000004c,%0,0,0(%1)" /* ecag */
-                    : "=d" (val) : "a" (cmd));
-       return val;
+       return __ecag(ECAG_CACHE_ATTRIBUTE, ai << 4 | li << 1 | ti);
 }
 
 static void ci_leaf_init(struct cacheinfo *this_leaf, int private,
index 4f7a96d..06ca71b 100644 (file)
 #include <linux/delay.h>
 #include <linux/cpu.h>
 #include <asm/diag.h>
+#include <asm/facility.h>
 #include <asm/elf.h>
 #include <asm/lowcore.h>
 #include <asm/param.h>
 #include <asm/smp.h>
 
-static DEFINE_PER_CPU(struct cpuid, cpu_id);
+struct cpu_info {
+       unsigned int cpu_mhz_dynamic;
+       unsigned int cpu_mhz_static;
+       struct cpuid cpu_id;
+};
+
+static DEFINE_PER_CPU(struct cpu_info, cpu_info);
+
+static bool machine_has_cpu_mhz;
+
+void __init cpu_detect_mhz_feature(void)
+{
+       if (test_facility(34) && __ecag(ECAG_CPU_ATTRIBUTE, 0) != -1UL)
+               machine_has_cpu_mhz = 1;
+}
+
+static void update_cpu_mhz(void *arg)
+{
+       unsigned long mhz;
+       struct cpu_info *c;
+
+       mhz = __ecag(ECAG_CPU_ATTRIBUTE, 0);
+       c = this_cpu_ptr(&cpu_info);
+       c->cpu_mhz_dynamic = mhz >> 32;
+       c->cpu_mhz_static = mhz & 0xffffffff;
+}
+
+void s390_update_cpu_mhz(void)
+{
+       s390_adjust_jiffies();
+       if (machine_has_cpu_mhz)
+               on_each_cpu(update_cpu_mhz, NULL, 0);
+}
 
 void notrace cpu_relax(void)
 {
@@ -35,9 +68,11 @@ EXPORT_SYMBOL(cpu_relax);
  */
 void cpu_init(void)
 {
-       struct cpuid *id = this_cpu_ptr(&cpu_id);
+       struct cpuid *id = this_cpu_ptr(&cpu_info.cpu_id);
 
        get_cpu_id(id);
+       if (machine_has_cpu_mhz)
+               update_cpu_mhz(NULL);
        atomic_inc(&init_mm.mm_count);
        current->active_mm = &init_mm;
        BUG_ON(current->mm);
@@ -64,7 +99,6 @@ static void show_cpu_summary(struct seq_file *m, void *v)
        };
        int i, cpu;
 
-       s390_adjust_jiffies();
        seq_printf(m, "vendor_id       : IBM/S390\n"
                   "# processors    : %i\n"
                   "bogomips per cpu: %lu.%02lu\n",
@@ -80,7 +114,7 @@ static void show_cpu_summary(struct seq_file *m, void *v)
        seq_puts(m, "\n");
        show_cacheinfo(m);
        for_each_online_cpu(cpu) {
-               struct cpuid *id = &per_cpu(cpu_id, cpu);
+               struct cpuid *id = &per_cpu(cpu_info.cpu_id, cpu);
 
                seq_printf(m, "processor %d: "
                           "version = %02X,  "
@@ -90,6 +124,14 @@ static void show_cpu_summary(struct seq_file *m, void *v)
        }
 }
 
+static void show_cpu_mhz(struct seq_file *m, unsigned long n)
+{
+       struct cpu_info *c = per_cpu_ptr(&cpu_info, n);
+
+       seq_printf(m, "cpu MHz dynamic : %d\n", c->cpu_mhz_dynamic);
+       seq_printf(m, "cpu MHz static  : %d\n", c->cpu_mhz_static);
+}
+
 /*
  * show_cpuinfo - Get information on one CPU for use by procfs.
  */
@@ -99,6 +141,10 @@ static int show_cpuinfo(struct seq_file *m, void *v)
 
        if (!n)
                show_cpu_summary(m, v);
+       if (!machine_has_cpu_mhz)
+               return 0;
+       seq_printf(m, "\ncpu             : %ld\n", n);
+       show_cpu_mhz(m, n);
        return 0;
 }
 
@@ -132,4 +178,3 @@ const struct seq_operations cpuinfo_op = {
        .stop   = c_stop,
        .show   = show_cpuinfo,
 };
-
index f319391..d4e0742 100644 (file)
@@ -901,6 +901,7 @@ void __init setup_arch(char **cmdline_p)
        setup_vmcoreinfo();
        setup_lowcore();
        smp_fill_possible_mask();
+       cpu_detect_mhz_feature();
         cpu_init();
        numa_setup();
 
index 2ced50c..1406fb6 100644 (file)
@@ -47,7 +47,7 @@ static void sclp_cpu_capability_notify(struct work_struct *work)
        int cpu;
        struct device *dev;
 
-       s390_adjust_jiffies();
+       s390_update_cpu_mhz();
        pr_info("CPU capability may have changed\n");
        get_online_cpus();
        for_each_online_cpu(cpu) {