2005-04-16 15:20:36 -07:00
|
|
|
#include <linux/smp.h>
|
|
|
|
#include <linux/timex.h>
|
|
|
|
#include <linux/string.h>
|
|
|
|
#include <linux/seq_file.h>
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get CPU information for use by the procfs.
|
|
|
|
*/
|
2008-02-20 11:45:29 -07:00
|
|
|
static void show_cpuinfo_core(struct seq_file *m, struct cpuinfo_x86 *c,
|
|
|
|
unsigned int cpu)
|
|
|
|
{
|
2009-02-28 06:20:21 -07:00
|
|
|
#ifdef CONFIG_SMP
|
x86/cpu: Always print SMP information in /proc/cpuinfo
Currently show_cpuinfo_core() displays cpu core information only if
the number of threads per a whole cores is 2 or larger.
However, this condition doesn't care about the number of
sockets. For example, this condition doesn't hold on systems
with two logical cpus consisting of two sockets and a single
core on each socket - yet the topology information would be
interesting to see in that case as well.
I don't know whether or not there are processors in real world
by which such configurations are possible, but at least on
vitual machine environments, such configuration can occur,
typically when no explicit SMP information is provided in
advance.
For example, on qemu/KVM, SMP information is specified via -smp
command-line option, more specifically, its syntax is:
-smp n[,cores=cores][,threads=threads][,sockets=sockets][,maxcpus=maxcpus]
If this is not specified, qemu tells configuration with
n-sockets, 1-core and 1-thread to the guest machine, on which
guest, MP information is not displayed in /proc/cpuinfo.
I saw this situation on VMWare guest environment, too.
To fix this issue, this patch simply removes the condition
because this information is useful even if there's only 1
thread.
Signed-off-by: HATAYAMA Daisuke <d.hatayama@jp.fujitsu.com>
Cc: Vivek Goyal <vgoyal@redhat.com>
Cc: H. Peter Anvin <hpa@linux.intel.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/5277D644.4090707@jp.fujitsu.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2013-11-04 10:15:48 -07:00
|
|
|
seq_printf(m, "physical id\t: %d\n", c->phys_proc_id);
|
2015-05-26 06:11:35 -07:00
|
|
|
seq_printf(m, "siblings\t: %d\n",
|
|
|
|
cpumask_weight(topology_core_cpumask(cpu)));
|
x86/cpu: Always print SMP information in /proc/cpuinfo
Currently show_cpuinfo_core() displays cpu core information only if
the number of threads per a whole cores is 2 or larger.
However, this condition doesn't care about the number of
sockets. For example, this condition doesn't hold on systems
with two logical cpus consisting of two sockets and a single
core on each socket - yet the topology information would be
interesting to see in that case as well.
I don't know whether or not there are processors in real world
by which such configurations are possible, but at least on
vitual machine environments, such configuration can occur,
typically when no explicit SMP information is provided in
advance.
For example, on qemu/KVM, SMP information is specified via -smp
command-line option, more specifically, its syntax is:
-smp n[,cores=cores][,threads=threads][,sockets=sockets][,maxcpus=maxcpus]
If this is not specified, qemu tells configuration with
n-sockets, 1-core and 1-thread to the guest machine, on which
guest, MP information is not displayed in /proc/cpuinfo.
I saw this situation on VMWare guest environment, too.
To fix this issue, this patch simply removes the condition
because this information is useful even if there's only 1
thread.
Signed-off-by: HATAYAMA Daisuke <d.hatayama@jp.fujitsu.com>
Cc: Vivek Goyal <vgoyal@redhat.com>
Cc: H. Peter Anvin <hpa@linux.intel.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/5277D644.4090707@jp.fujitsu.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
2013-11-04 10:15:48 -07:00
|
|
|
seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id);
|
|
|
|
seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
|
|
|
|
seq_printf(m, "apicid\t\t: %d\n", c->apicid);
|
|
|
|
seq_printf(m, "initial apicid\t: %d\n", c->initial_apicid);
|
2008-02-20 11:45:29 -07:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2009-02-28 06:20:21 -07:00
|
|
|
#ifdef CONFIG_X86_32
|
2008-02-20 11:45:29 -07:00
|
|
|
static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c)
|
|
|
|
{
|
|
|
|
seq_printf(m,
|
|
|
|
"fdiv_bug\t: %s\n"
|
|
|
|
"f00f_bug\t: %s\n"
|
|
|
|
"coma_bug\t: %s\n"
|
|
|
|
"fpu\t\t: %s\n"
|
|
|
|
"fpu_exception\t: %s\n"
|
|
|
|
"cpuid level\t: %d\n"
|
2017-02-12 14:12:08 -07:00
|
|
|
"wp\t\t: yes\n",
|
2013-03-20 07:07:25 -07:00
|
|
|
static_cpu_has_bug(X86_BUG_FDIV) ? "yes" : "no",
|
2013-03-20 07:07:24 -07:00
|
|
|
static_cpu_has_bug(X86_BUG_F00F) ? "yes" : "no",
|
2013-03-20 07:07:26 -07:00
|
|
|
static_cpu_has_bug(X86_BUG_COMA) ? "yes" : "no",
|
2013-04-29 07:04:20 -07:00
|
|
|
static_cpu_has(X86_FEATURE_FPU) ? "yes" : "no",
|
|
|
|
static_cpu_has(X86_FEATURE_FPU) ? "yes" : "no",
|
2017-02-12 14:12:08 -07:00
|
|
|
c->cpuid_level);
|
2008-02-20 11:45:29 -07:00
|
|
|
}
|
2008-02-20 11:48:02 -07:00
|
|
|
#else
|
|
|
|
static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c)
|
|
|
|
{
|
|
|
|
seq_printf(m,
|
|
|
|
"fpu\t\t: yes\n"
|
|
|
|
"fpu_exception\t: yes\n"
|
|
|
|
"cpuid level\t: %d\n"
|
|
|
|
"wp\t\t: yes\n",
|
|
|
|
c->cpuid_level);
|
|
|
|
}
|
|
|
|
#endif
|
2008-02-20 11:45:29 -07:00
|
|
|
|
2005-04-16 15:20:36 -07:00
|
|
|
static int show_cpuinfo(struct seq_file *m, void *v)
|
|
|
|
{
|
|
|
|
struct cpuinfo_x86 *c = v;
|
2011-12-20 17:52:22 -07:00
|
|
|
unsigned int cpu;
|
2008-02-20 11:45:29 -07:00
|
|
|
int i;
|
2005-04-16 15:20:36 -07:00
|
|
|
|
2008-02-20 11:45:29 -07:00
|
|
|
cpu = c->cpu_index;
|
|
|
|
seq_printf(m, "processor\t: %u\n"
|
|
|
|
"vendor_id\t: %s\n"
|
|
|
|
"cpu family\t: %d\n"
|
|
|
|
"model\t\t: %u\n"
|
|
|
|
"model name\t: %s\n",
|
|
|
|
cpu,
|
|
|
|
c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown",
|
|
|
|
c->x86,
|
|
|
|
c->x86_model,
|
|
|
|
c->x86_model_id[0] ? c->x86_model_id : "unknown");
|
2005-04-16 15:20:36 -07:00
|
|
|
|
|
|
|
if (c->x86_mask || c->cpuid_level >= 0)
|
|
|
|
seq_printf(m, "stepping\t: %d\n", c->x86_mask);
|
|
|
|
else
|
2014-11-28 14:03:41 -07:00
|
|
|
seq_puts(m, "stepping\t: unknown\n");
|
2011-10-12 17:46:33 -07:00
|
|
|
if (c->microcode)
|
2011-10-17 07:45:10 -07:00
|
|
|
seq_printf(m, "microcode\t: 0x%x\n", c->microcode);
|
2005-04-16 15:20:36 -07:00
|
|
|
|
x86: do not use cpufreq_quick_get() for /proc/cpuinfo "cpu MHz"
cpufreq_quick_get() allows cpufreq drivers to over-ride cpu_khz
that is otherwise reported in x86 /proc/cpuinfo "cpu MHz".
There are four problems with this scheme,
any of them is sufficient justification to delete it.
1. Depending on which cpufreq driver is loaded, the behavior
of this field is different.
2. Distros complain that they have to explain to users
why and how this field changes. Distros have requested a constant.
3. The two major providers of this information, acpi_cpufreq
and intel_pstate, both "get it wrong" in different ways.
acpi_cpufreq lies to the user by telling them that
they are running at whatever frequency was last
requested by software.
intel_pstate lies to the user by telling them that
they are running at the average frequency computed
over an undefined measurement. But an average computed
over an undefined interval, is itself, undefined...
4. On modern processors, user space utilities, such as
turbostat(1), are more accurate and more precise, while
supporing concurrent measurement over arbitrary intervals.
Users who have been consulting /proc/cpuinfo to
track changing CPU frequency will be dissapointed that
it no longer wiggles -- perhaps being unaware of the
limitations of the information they have been consuming.
Yes, they can change their scripts to look in sysfs
cpufreq/scaling_cur_frequency. Here they will find the same
data of dubious quality here removed from /proc/cpuinfo.
The value in sysfs will be addressed in a subsequent patch
to address issues 1-3, above.
Issue 4 will remain -- users that really care about
accurate frequency information should not be using either
proc or sysfs kernel interfaces.
They should be using using turbostat(8), or a similar
purpose-built analysis tool.
Signed-off-by: Len Brown <len.brown@intel.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2017-06-16 20:03:11 -07:00
|
|
|
if (cpu_has(c, X86_FEATURE_TSC))
|
2005-06-23 00:08:34 -07:00
|
|
|
seq_printf(m, "cpu MHz\t\t: %u.%03u\n",
|
x86: do not use cpufreq_quick_get() for /proc/cpuinfo "cpu MHz"
cpufreq_quick_get() allows cpufreq drivers to over-ride cpu_khz
that is otherwise reported in x86 /proc/cpuinfo "cpu MHz".
There are four problems with this scheme,
any of them is sufficient justification to delete it.
1. Depending on which cpufreq driver is loaded, the behavior
of this field is different.
2. Distros complain that they have to explain to users
why and how this field changes. Distros have requested a constant.
3. The two major providers of this information, acpi_cpufreq
and intel_pstate, both "get it wrong" in different ways.
acpi_cpufreq lies to the user by telling them that
they are running at whatever frequency was last
requested by software.
intel_pstate lies to the user by telling them that
they are running at the average frequency computed
over an undefined measurement. But an average computed
over an undefined interval, is itself, undefined...
4. On modern processors, user space utilities, such as
turbostat(1), are more accurate and more precise, while
supporing concurrent measurement over arbitrary intervals.
Users who have been consulting /proc/cpuinfo to
track changing CPU frequency will be dissapointed that
it no longer wiggles -- perhaps being unaware of the
limitations of the information they have been consuming.
Yes, they can change their scripts to look in sysfs
cpufreq/scaling_cur_frequency. Here they will find the same
data of dubious quality here removed from /proc/cpuinfo.
The value in sysfs will be addressed in a subsequent patch
to address issues 1-3, above.
Issue 4 will remain -- users that really care about
accurate frequency information should not be using either
proc or sysfs kernel interfaces.
They should be using using turbostat(8), or a similar
purpose-built analysis tool.
Signed-off-by: Len Brown <len.brown@intel.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2017-06-16 20:03:11 -07:00
|
|
|
cpu_khz / 1000, (cpu_khz % 1000));
|
2005-04-16 15:20:36 -07:00
|
|
|
|
|
|
|
/* Cache size */
|
|
|
|
if (c->x86_cache_size >= 0)
|
|
|
|
seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size);
|
2008-02-20 11:45:29 -07:00
|
|
|
|
|
|
|
show_cpuinfo_core(m, c, cpu);
|
|
|
|
show_cpuinfo_misc(m, c);
|
|
|
|
|
2014-11-28 14:03:41 -07:00
|
|
|
seq_puts(m, "flags\t\t:");
|
2008-02-20 11:45:29 -07:00
|
|
|
for (i = 0; i < 32*NCAPINTS; i++)
|
|
|
|
if (cpu_has(c, i) && x86_cap_flags[i] != NULL)
|
2005-04-16 15:20:36 -07:00
|
|
|
seq_printf(m, " %s", x86_cap_flags[i]);
|
|
|
|
|
2014-11-28 14:03:41 -07:00
|
|
|
seq_puts(m, "\nbugs\t\t:");
|
2014-06-24 04:25:03 -07:00
|
|
|
for (i = 0; i < 32*NBUGINTS; i++) {
|
|
|
|
unsigned int bug_bit = 32*NCAPINTS + i;
|
|
|
|
|
|
|
|
if (cpu_has_bug(c, bug_bit) && x86_bug_flags[i])
|
|
|
|
seq_printf(m, " %s", x86_bug_flags[i]);
|
|
|
|
}
|
|
|
|
|
2008-02-20 11:47:12 -07:00
|
|
|
seq_printf(m, "\nbogomips\t: %lu.%02lu\n",
|
|
|
|
c->loops_per_jiffy/(500000/HZ),
|
|
|
|
(c->loops_per_jiffy/(5000/HZ)) % 100);
|
2008-02-20 11:48:02 -07:00
|
|
|
|
|
|
|
#ifdef CONFIG_X86_64
|
|
|
|
if (c->x86_tlbsize > 0)
|
|
|
|
seq_printf(m, "TLB size\t: %d 4K pages\n", c->x86_tlbsize);
|
|
|
|
#endif
|
2008-02-20 11:47:12 -07:00
|
|
|
seq_printf(m, "clflush size\t: %u\n", c->x86_clflush_size);
|
2008-02-20 11:48:02 -07:00
|
|
|
seq_printf(m, "cache_alignment\t: %d\n", c->x86_cache_alignment);
|
|
|
|
seq_printf(m, "address sizes\t: %u bits physical, %u bits virtual\n",
|
|
|
|
c->x86_phys_bits, c->x86_virt_bits);
|
2008-02-20 11:47:12 -07:00
|
|
|
|
2014-11-28 14:03:41 -07:00
|
|
|
seq_puts(m, "power management:");
|
2008-02-20 11:47:12 -07:00
|
|
|
for (i = 0; i < 32; i++) {
|
2006-01-11 14:42:51 -07:00
|
|
|
if (c->x86_power & (1 << i)) {
|
|
|
|
if (i < ARRAY_SIZE(x86_power_flags) &&
|
|
|
|
x86_power_flags[i])
|
|
|
|
seq_printf(m, "%s%s",
|
2009-07-03 16:35:45 -07:00
|
|
|
x86_power_flags[i][0] ? " " : "",
|
2006-01-11 14:42:51 -07:00
|
|
|
x86_power_flags[i]);
|
|
|
|
else
|
|
|
|
seq_printf(m, " [%d]", i);
|
|
|
|
}
|
2008-02-20 11:47:12 -07:00
|
|
|
}
|
2006-01-11 14:42:51 -07:00
|
|
|
|
2014-11-28 14:03:41 -07:00
|
|
|
seq_puts(m, "\n\n");
|
2005-04-16 15:25:15 -07:00
|
|
|
|
2005-04-16 15:20:36 -07:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void *c_start(struct seq_file *m, loff_t *pos)
|
|
|
|
{
|
2012-09-18 22:42:23 -07:00
|
|
|
*pos = cpumask_next(*pos - 1, cpu_online_mask);
|
2008-10-21 21:42:30 -07:00
|
|
|
if ((*pos) < nr_cpu_ids)
|
2007-10-19 11:35:04 -07:00
|
|
|
return &cpu_data(*pos);
|
|
|
|
return NULL;
|
2005-04-16 15:20:36 -07:00
|
|
|
}
|
2008-02-20 11:45:29 -07:00
|
|
|
|
2005-04-16 15:20:36 -07:00
|
|
|
static void *c_next(struct seq_file *m, void *v, loff_t *pos)
|
|
|
|
{
|
2008-10-21 21:42:30 -07:00
|
|
|
(*pos)++;
|
2005-04-16 15:20:36 -07:00
|
|
|
return c_start(m, pos);
|
|
|
|
}
|
2008-02-20 11:45:29 -07:00
|
|
|
|
2005-04-16 15:20:36 -07:00
|
|
|
static void c_stop(struct seq_file *m, void *v)
|
|
|
|
{
|
|
|
|
}
|
2008-02-20 11:45:29 -07:00
|
|
|
|
2008-01-30 05:33:32 -07:00
|
|
|
const struct seq_operations cpuinfo_op = {
|
2005-04-16 15:20:36 -07:00
|
|
|
.start = c_start,
|
|
|
|
.next = c_next,
|
|
|
|
.stop = c_stop,
|
|
|
|
.show = show_cpuinfo,
|
|
|
|
};
|