summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristiano F. Haesbaert <haesbaert@cvs.openbsd.org>2012-03-27 02:23:05 +0000
committerChristiano F. Haesbaert <haesbaert@cvs.openbsd.org>2012-03-27 02:23:05 +0000
commit0e32e73a6835575f1f36a6b27373b8a96a360215 (patch)
tree985f8856a489b2319f3022c02e226c3da4117874
parent919b507fdda291edc718813bd18ccbe28f5961b1 (diff)
Run identifycpu() on its own cpu.
Discussed with many on hackers. "Go ahead" kettenis@ "Get to it" deraadt@
-rw-r--r--sys/arch/amd64/amd64/cpu.c27
-rw-r--r--sys/arch/amd64/amd64/identcpu.c83
-rw-r--r--sys/arch/amd64/include/cpu.h5
3 files changed, 70 insertions, 45 deletions
diff --git a/sys/arch/amd64/amd64/cpu.c b/sys/arch/amd64/amd64/cpu.c
index f8b442bce7a..b81deb3ebf5 100644
--- a/sys/arch/amd64/amd64/cpu.c
+++ b/sys/arch/amd64/amd64/cpu.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.c,v 1.45 2012/02/25 00:12:07 haesbaert Exp $ */
+/* $OpenBSD: cpu.c,v 1.46 2012/03/27 02:23:04 haesbaert Exp $ */
/* $NetBSD: cpu.c,v 1.1 2003/04/26 18:39:26 fvdl Exp $ */
/*-
@@ -333,7 +333,6 @@ cpu_attach(struct device *parent, struct device *self, void *aux)
cpu_start_secondary(ci);
ncpus++;
if (ci->ci_flags & CPUF_PRESENT) {
- identifycpu(ci);
ci->ci_next = cpu_info_list->ci_next;
cpu_info_list->ci_next = ci;
}
@@ -446,6 +445,17 @@ cpu_start_secondary(struct cpu_info *ci)
#endif
}
+ atomic_setbits_int(&ci->ci_flags, CPUF_IDENTIFY);
+
+ /*
+ * wait for it to identify
+ */
+ for (i = 100000; (ci->ci_flags & CPUF_IDENTIFY) && i > 0; i--)
+ delay(10);
+
+ if (ci->ci_flags & CPUF_IDENTIFY)
+ printf("%s: failed to identify\n", ci->ci_dev->dv_xname);
+
CPU_START_CLEANUP(ci);
}
@@ -484,9 +494,6 @@ cpu_hatch(void *v)
cpu_init_msrs(ci);
- cpu_probe_features(ci);
- cpu_feature &= ci->ci_feature_flags;
-
#ifdef DEBUG
if (ci->ci_flags & CPUF_PRESENT)
panic("%s: already running!?", ci->ci_dev->dv_xname);
@@ -497,6 +504,16 @@ cpu_hatch(void *v)
lapic_enable();
lapic_startclock();
+ /* We need to wait until we can identify, otherwise dmesg output
+ * will be messy. */
+ while ((ci->ci_flags & CPUF_IDENTIFY) == 0)
+ delay(10);
+
+ identifycpu(ci);
+
+ /* Signal we're done */
+ atomic_clearbits_int(&ci->ci_flags, CPUF_IDENTIFY);
+
while ((ci->ci_flags & CPUF_GO) == 0)
delay(10);
#ifdef DEBUG
diff --git a/sys/arch/amd64/amd64/identcpu.c b/sys/arch/amd64/amd64/identcpu.c
index 8f99571c75b..77436353af2 100644
--- a/sys/arch/amd64/amd64/identcpu.c
+++ b/sys/arch/amd64/amd64/identcpu.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: identcpu.c,v 1.34 2012/01/08 14:39:26 haesbaert Exp $ */
+/* $OpenBSD: identcpu.c,v 1.35 2012/03/27 02:23:04 haesbaert Exp $ */
/* $NetBSD: identcpu.c,v 1.1 2003/04/26 18:39:28 fvdl Exp $ */
/*
@@ -303,26 +303,31 @@ identifycpu(struct cpu_info *ci)
u_int32_t dummy, val, pnfeatset;
u_int32_t brand[12];
u_int32_t vendor[4];
+ char mycpu_model[48];
int i, max;
char *brandstr_from, *brandstr_to;
int skipspace;
CPUID(1, ci->ci_signature, val, dummy, ci->ci_feature_flags);
CPUID(0x80000000, pnfeatset, dummy, dummy, dummy);
- if (pnfeatset >= 0x80000001)
+ if (pnfeatset >= 0x80000001) {
+ u_int32_t ecx;
+
CPUID(0x80000001, dummy, dummy,
- ecpu_ecxfeature, ci->ci_feature_eflags);
+ ecx, ci->ci_feature_eflags);
+ if (ci->ci_flags & CPUF_PRIMARY)
+ ecpu_ecxfeature = ecx;
+ /* Let cpu_fature be the common bits */
+ cpu_feature &= ci->ci_feature_flags;
+ }
- vendor[3] = 0;
- CPUID(0, dummy, vendor[0], vendor[2], vendor[1]); /* yup, 0 2 1 */
CPUID(0x80000002, brand[0], brand[1], brand[2], brand[3]);
CPUID(0x80000003, brand[4], brand[5], brand[6], brand[7]);
CPUID(0x80000004, brand[8], brand[9], brand[10], brand[11]);
+ strlcpy(mycpu_model, (char *)brand, sizeof(mycpu_model));
- strlcpy(cpu_model, (char *)brand, sizeof(cpu_model));
-
- /* Remove leading and duplicated spaces from cpu_model */
- brandstr_from = brandstr_to = cpu_model;
+ /* Remove leading and duplicated spaces from mycpu_model */
+ brandstr_from = brandstr_to = mycpu_model;
skipspace = 1;
while (*brandstr_from != '\0') {
if (!skipspace || *brandstr_from != ' ') {
@@ -335,8 +340,13 @@ identifycpu(struct cpu_info *ci)
}
*brandstr_to = '\0';
- if (cpu_model[0] == 0)
- strlcpy(cpu_model, "Opteron or Athlon 64", sizeof(cpu_model));
+ if (mycpu_model[0] == 0)
+ strlcpy(mycpu_model, "Opteron or Athlon 64",
+ sizeof(mycpu_model));
+
+ /* If primary cpu, fill in the global cpu_model used by sysctl */
+ if (ci->ci_flags & CPUF_PRIMARY)
+ strlcpy(cpu_model, mycpu_model, sizeof(cpu_model));
ci->ci_family = (ci->ci_signature >> 8) & 0x0f;
ci->ci_model = (ci->ci_signature >> 4) & 0x0f;
@@ -351,13 +361,16 @@ identifycpu(struct cpu_info *ci)
amd_cpu_cacheinfo(ci);
- printf("%s: %s", ci->ci_dev->dv_xname, cpu_model);
+ printf("%s: %s", ci->ci_dev->dv_xname, mycpu_model);
if (ci->ci_tsc_freq != 0)
printf(", %lu.%02lu MHz", (ci->ci_tsc_freq + 4999) / 1000000,
((ci->ci_tsc_freq + 4999) / 10000) % 100);
- cpuspeed = (ci->ci_tsc_freq + 4999) / 1000000;
- cpu_cpuspeed = cpu_amd64speed;
+
+ if (ci->ci_flags & CPUF_PRIMARY) {
+ cpuspeed = (ci->ci_tsc_freq + 4999) / 1000000;
+ cpu_cpuspeed = cpu_amd64speed;
+ }
printf("\n%s: ", ci->ci_dev->dv_xname);
@@ -383,25 +396,25 @@ identifycpu(struct cpu_info *ci)
x86_print_cacheinfo(ci);
#ifndef SMALL_KERNEL
- if (pnfeatset > 0x80000007) {
- CPUID(0x80000007, dummy, dummy, dummy, pnfeatset);
+ if (ci->ci_flags & CPUF_PRIMARY) {
+ if (pnfeatset > 0x80000007) {
+ CPUID(0x80000007, dummy, dummy, dummy, pnfeatset);
- if (pnfeatset & 0x06) {
- if ((ci->ci_signature & 0xF00) == 0xf00)
- setperf_setup = k8_powernow_init;
+ if (pnfeatset & 0x06) {
+ if ((ci->ci_signature & 0xF00) == 0xf00)
+ setperf_setup = k8_powernow_init;
+ }
+ if (ci->ci_family >= 0x10)
+ setperf_setup = k1x_init;
}
- if (ci->ci_family >= 0x10)
- setperf_setup = k1x_init;
- }
- if (cpu_ecxfeature & CPUIDECX_EST) {
- setperf_setup = est_init;
- }
-
- if (cpu_ecxfeature & CPUIDECX_AES)
- amd64_has_aesni = 1;
+ if (cpu_ecxfeature & CPUIDECX_EST)
+ setperf_setup = est_init;
- if (!strncmp(cpu_model, "Intel", 5)) {
+ if (cpu_ecxfeature & CPUIDECX_AES)
+ amd64_has_aesni = 1;
+ }
+ if (!strncmp(mycpu_model, "Intel", 5)) {
u_int32_t cflushsz;
CPUID(0x01, dummy, cflushsz, dummy, dummy);
@@ -420,13 +433,14 @@ identifycpu(struct cpu_info *ci)
#endif
-
+ vendor[3] = 0;
+ CPUID(0, dummy, vendor[0], vendor[2], vendor[1]); /* yup, 0 2 1 */
/* AuthenticAMD: h t u A i t n e */
if (vendor[0] == 0x68747541 && vendor[1] == 0x69746e65 &&
vendor[2] == 0x444d4163) /* DMAc */
amd64_errata(ci);
- if (strncmp(cpu_model, "VIA Nano processor", 18) == 0) {
+ if (strncmp(mycpu_model, "VIA Nano processor", 18) == 0) {
ci->cpu_setup = via_nano_setup;
#ifndef SMALL_KERNEL
strlcpy(ci->ci_sensordev.xname, ci->ci_dev->dv_xname,
@@ -438,10 +452,3 @@ identifycpu(struct cpu_info *ci)
#endif
}
}
-
-void
-cpu_probe_features(struct cpu_info *ci)
-{
- ci->ci_feature_flags = cpu_feature;
- ci->ci_signature = 0;
-}
diff --git a/sys/arch/amd64/include/cpu.h b/sys/arch/amd64/include/cpu.h
index d9c0f1a0190..e3f5ff0dead 100644
--- a/sys/arch/amd64/include/cpu.h
+++ b/sys/arch/amd64/include/cpu.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: cpu.h,v 1.70 2011/12/26 23:07:04 haesbaert Exp $ */
+/* $OpenBSD: cpu.h,v 1.71 2012/03/27 02:23:04 haesbaert Exp $ */
/* $NetBSD: cpu.h,v 1.1 2003/04/26 18:39:39 fvdl Exp $ */
/*-
@@ -135,6 +135,8 @@ struct cpu_info {
#define CPUF_SP 0x0004 /* CPU is only processor */
#define CPUF_PRIMARY 0x0008 /* CPU is active primary processor */
+#define CPUF_IDENTIFY 0x0010 /* CPU may now identify */
+
#define CPUF_PRESENT 0x1000 /* CPU is present */
#define CPUF_RUNNING 0x2000 /* CPU is running */
#define CPUF_PAUSE 0x4000 /* CPU is paused in DDB */
@@ -264,7 +266,6 @@ extern int cpuspeed;
/* identcpu.c */
void identifycpu(struct cpu_info *);
int cpu_amd64speed(int *);
-void cpu_probe_features(struct cpu_info *);
/* machdep.c */
void dumpconf(void);