proc.c 4.5 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5
#include <linux/smp.h>
#include <linux/timex.h>
#include <linux/string.h>
#include <asm/semaphore.h>
#include <linux/seq_file.h>
6
#include <linux/cpufreq.h>
L
Linus Torvalds 已提交
7 8 9 10

/*
 *	Get CPU information for use by the procfs.
 */
11
#ifdef CONFIG_X86_32
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
static void show_cpuinfo_core(struct seq_file *m, struct cpuinfo_x86 *c,
			      unsigned int cpu)
{
#ifdef CONFIG_X86_HT
	if (c->x86_max_cores * smp_num_siblings > 1) {
		seq_printf(m, "physical id\t: %d\n", c->phys_proc_id);
		seq_printf(m, "siblings\t: %d\n",
			   cpus_weight(per_cpu(cpu_core_map, cpu)));
		seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id);
		seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
	}
#endif
}

static void show_cpuinfo_misc(struct seq_file *m, struct cpuinfo_x86 *c)
{
	/*
	 * We use exception 16 if we have hardware math and we've either seen
	 * it or the CPU claims it is internal
	 */
	int fpu_exception = c->hard_math && (ignore_fpu_irq || cpu_has_fpu);
	seq_printf(m,
		   "fdiv_bug\t: %s\n"
		   "hlt_bug\t\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"
		   "wp\t\t: %s\n",
		   c->fdiv_bug ? "yes" : "no",
		   c->hlt_works_ok ? "no" : "yes",
		   c->f00f_bug ? "yes" : "no",
		   c->coma_bug ? "yes" : "no",
		   c->hard_math ? "yes" : "no",
		   fpu_exception ? "yes" : "no",
		   c->cpuid_level,
		   c->wp_works_ok ? "yes" : "no");
}
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
#else
static void show_cpuinfo_core(struct seq_file *m, struct cpuinfo_x86 *c,
			      unsigned int cpu)
{
#ifdef CONFIG_SMP
	if (c->x86_max_cores * smp_num_siblings > 1) {
		seq_printf(m, "physical id\t: %d\n", c->phys_proc_id);
		seq_printf(m, "siblings\t: %d\n",
			   cpus_weight(per_cpu(cpu_core_map, cpu)));
		seq_printf(m, "core id\t\t: %d\n", c->cpu_core_id);
		seq_printf(m, "cpu cores\t: %d\n", c->booted_cores);
	}
#endif
}

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
76

L
Linus Torvalds 已提交
77 78 79
static int show_cpuinfo(struct seq_file *m, void *v)
{
	struct cpuinfo_x86 *c = v;
80 81
	unsigned int cpu = 0;
	int i;
L
Linus Torvalds 已提交
82 83

#ifdef CONFIG_SMP
84
	cpu = c->cpu_index;
L
Linus Torvalds 已提交
85
#endif
86 87 88 89 90 91 92 93 94 95
	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");
L
Linus Torvalds 已提交
96 97 98 99 100 101

	if (c->x86_mask || c->cpuid_level >= 0)
		seq_printf(m, "stepping\t: %d\n", c->x86_mask);
	else
		seq_printf(m, "stepping\t: unknown\n");

102 103 104
	if (cpu_has(c, X86_FEATURE_TSC)) {
		unsigned int freq = cpufreq_quick_get(cpu);

105 106
		if (!freq)
			freq = cpu_khz;
A
Andrew Morton 已提交
107
		seq_printf(m, "cpu MHz\t\t: %u.%03u\n",
108
			   freq / 1000, (freq % 1000));
L
Linus Torvalds 已提交
109 110 111 112 113
	}

	/* Cache size */
	if (c->x86_cache_size >= 0)
		seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size);
114 115 116 117 118 119 120

	show_cpuinfo_core(m, c, cpu);
	show_cpuinfo_misc(m, c);

	seq_printf(m, "flags\t\t:");
	for (i = 0; i < 32*NCAPINTS; i++)
		if (cpu_has(c, i) && x86_cap_flags[i] != NULL)
L
Linus Torvalds 已提交
121 122
			seq_printf(m, " %s", x86_cap_flags[i]);

123 124 125
	seq_printf(m, "\nbogomips\t: %lu.%02lu\n",
		   c->loops_per_jiffy/(500000/HZ),
		   (c->loops_per_jiffy/(5000/HZ)) % 100);
126 127 128 129 130

#ifdef CONFIG_X86_64
	if (c->x86_tlbsize > 0)
		seq_printf(m, "TLB size\t: %d 4K pages\n", c->x86_tlbsize);
#endif
131
	seq_printf(m, "clflush size\t: %u\n", c->x86_clflush_size);
132 133 134 135 136
#ifdef CONFIG_X86_64
	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);
#endif
137 138 139

	seq_printf(m, "power management:");
	for (i = 0; i < 32; i++) {
140 141 142 143 144 145 146 147 148
		if (c->x86_power & (1 << i)) {
			if (i < ARRAY_SIZE(x86_power_flags) &&
			    x86_power_flags[i])
				seq_printf(m, "%s%s",
					   x86_power_flags[i][0]?" ":"",
					   x86_power_flags[i]);
			else
				seq_printf(m, " [%d]", i);
		}
149
	}
150

151
	seq_printf(m, "\n\n");
152

L
Linus Torvalds 已提交
153 154 155 156 157
	return 0;
}

static void *c_start(struct seq_file *m, loff_t *pos)
{
158
	if (*pos == 0)	/* just in case, cpu 0 is not the first */
159 160
		*pos = first_cpu(cpu_online_map);
	if ((*pos) < NR_CPUS && cpu_online(*pos))
161 162
		return &cpu_data(*pos);
	return NULL;
L
Linus Torvalds 已提交
163
}
164

L
Linus Torvalds 已提交
165 166
static void *c_next(struct seq_file *m, void *v, loff_t *pos)
{
167
	*pos = next_cpu(*pos, cpu_online_map);
L
Linus Torvalds 已提交
168 169
	return c_start(m, pos);
}
170

L
Linus Torvalds 已提交
171 172 173
static void c_stop(struct seq_file *m, void *v)
{
}
174

175
const struct seq_operations cpuinfo_op = {
L
Linus Torvalds 已提交
176 177 178 179 180
	.start	= c_start,
	.next	= c_next,
	.stop	= c_stop,
	.show	= show_cpuinfo,
};