Commit 097a116c authored by Heiko Carstens's avatar Heiko Carstens Committed by Martin Schwidefsky

s390/cpuinfo: show dynamic and static cpu mhz

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: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Acked-by: default avatarSascha Silbe <silbe@linux.vnet.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent 219a21b3
...@@ -77,7 +77,10 @@ static inline void get_cpu_id(struct cpuid *ptr) ...@@ -77,7 +77,10 @@ static inline void get_cpu_id(struct cpuid *ptr)
asm volatile("stidp %0" : "=Q" (*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 const struct seq_operations cpuinfo_op;
extern int sysctl_ieee_emulation_warnings; extern int sysctl_ieee_emulation_warnings;
extern void execve_tail(void); extern void execve_tail(void);
...@@ -233,6 +236,18 @@ void cpu_relax(void); ...@@ -233,6 +236,18 @@ void cpu_relax(void);
#define cpu_relax_lowlatency() barrier() #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) static inline void psw_set_key(unsigned int key)
{ {
asm volatile("spka 0(%0)" : : "d" (key)); asm volatile("spka 0(%0)" : : "d" (key));
......
...@@ -99,12 +99,7 @@ static inline enum cache_type get_cache_type(struct cache_info *ci, int level) ...@@ -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) static inline unsigned long ecag(int ai, int li, int ti)
{ {
unsigned long cmd, val; return __ecag(ECAG_CACHE_ATTRIBUTE, ai << 4 | li << 1 | ti);
cmd = ai << 4 | li << 1 | ti;
asm volatile(".insn rsy,0xeb000000004c,%0,0,0(%1)" /* ecag */
: "=d" (val) : "a" (cmd));
return val;
} }
static void ci_leaf_init(struct cacheinfo *this_leaf, int private, static void ci_leaf_init(struct cacheinfo *this_leaf, int private,
......
...@@ -13,12 +13,45 @@ ...@@ -13,12 +13,45 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/cpu.h> #include <linux/cpu.h>
#include <asm/diag.h> #include <asm/diag.h>
#include <asm/facility.h>
#include <asm/elf.h> #include <asm/elf.h>
#include <asm/lowcore.h> #include <asm/lowcore.h>
#include <asm/param.h> #include <asm/param.h>
#include <asm/smp.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) void notrace cpu_relax(void)
{ {
...@@ -35,9 +68,11 @@ EXPORT_SYMBOL(cpu_relax); ...@@ -35,9 +68,11 @@ EXPORT_SYMBOL(cpu_relax);
*/ */
void cpu_init(void) 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); get_cpu_id(id);
if (machine_has_cpu_mhz)
update_cpu_mhz(NULL);
atomic_inc(&init_mm.mm_count); atomic_inc(&init_mm.mm_count);
current->active_mm = &init_mm; current->active_mm = &init_mm;
BUG_ON(current->mm); BUG_ON(current->mm);
...@@ -64,7 +99,6 @@ static void show_cpu_summary(struct seq_file *m, void *v) ...@@ -64,7 +99,6 @@ static void show_cpu_summary(struct seq_file *m, void *v)
}; };
int i, cpu; int i, cpu;
s390_adjust_jiffies();
seq_printf(m, "vendor_id : IBM/S390\n" seq_printf(m, "vendor_id : IBM/S390\n"
"# processors : %i\n" "# processors : %i\n"
"bogomips per cpu: %lu.%02lu\n", "bogomips per cpu: %lu.%02lu\n",
...@@ -80,7 +114,7 @@ static void show_cpu_summary(struct seq_file *m, void *v) ...@@ -80,7 +114,7 @@ static void show_cpu_summary(struct seq_file *m, void *v)
seq_puts(m, "\n"); seq_puts(m, "\n");
show_cacheinfo(m); show_cacheinfo(m);
for_each_online_cpu(cpu) { 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: " seq_printf(m, "processor %d: "
"version = %02X, " "version = %02X, "
...@@ -90,6 +124,14 @@ static void show_cpu_summary(struct seq_file *m, void *v) ...@@ -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. * 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) ...@@ -99,6 +141,10 @@ static int show_cpuinfo(struct seq_file *m, void *v)
if (!n) if (!n)
show_cpu_summary(m, v); 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; return 0;
} }
...@@ -132,4 +178,3 @@ const struct seq_operations cpuinfo_op = { ...@@ -132,4 +178,3 @@ const struct seq_operations cpuinfo_op = {
.stop = c_stop, .stop = c_stop,
.show = show_cpuinfo, .show = show_cpuinfo,
}; };
...@@ -901,6 +901,7 @@ void __init setup_arch(char **cmdline_p) ...@@ -901,6 +901,7 @@ void __init setup_arch(char **cmdline_p)
setup_vmcoreinfo(); setup_vmcoreinfo();
setup_lowcore(); setup_lowcore();
smp_fill_possible_mask(); smp_fill_possible_mask();
cpu_detect_mhz_feature();
cpu_init(); cpu_init();
numa_setup(); numa_setup();
......
...@@ -47,7 +47,7 @@ static void sclp_cpu_capability_notify(struct work_struct *work) ...@@ -47,7 +47,7 @@ static void sclp_cpu_capability_notify(struct work_struct *work)
int cpu; int cpu;
struct device *dev; struct device *dev;
s390_adjust_jiffies(); s390_update_cpu_mhz();
pr_info("CPU capability may have changed\n"); pr_info("CPU capability may have changed\n");
get_online_cpus(); get_online_cpus();
for_each_online_cpu(cpu) { for_each_online_cpu(cpu) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment