diff --git a/sys/arch/x86/conf/files.x86 b/sys/arch/x86/conf/files.x86
index 17ccac2..1b14f08 100644
--- a/sys/arch/x86/conf/files.x86
+++ b/sys/arch/x86/conf/files.x86
@@ -25,7 +25,7 @@ define ipmibus {}
# CPU features
#
device cpu: cpufeaturebus
-attach cpu at cpubus
+attach cpu at cpubus with lapic
file arch/x86/x86/cpu.c cpu
file arch/x86/x86/cpu_rng.c cpu
diff --git a/sys/arch/x86/include/cpu.h b/sys/arch/x86/include/cpu.h
index bd6e7cf..778c547 100644
--- a/sys/arch/x86/include/cpu.h
+++ b/sys/arch/x86/include/cpu.h
@@ -335,6 +335,10 @@ void cpu_load_pmap(struct pmap *, struct pmap *);
void cpu_broadcast_halt(void);
void cpu_kick(struct cpu_info *);
+void cpu_attach_common(device_t, device_t, void *);
+int cpu_rescan(device_t, const char *, const int *);
+void cpu_childdetached(device_t, device_t);
+
#define curcpu() x86_curcpu()
#define curlwp x86_curlwp()
#define curpcb ((struct pcb *)lwp_getpcb(curlwp))
diff --git a/sys/arch/x86/include/cpuvar.h b/sys/arch/x86/include/cpuvar.h
index c0ea0c5..8dfdd64 100644
--- a/sys/arch/x86/include/cpuvar.h
+++ b/sys/arch/x86/include/cpuvar.h
@@ -95,6 +95,12 @@ struct cpufeature_attach_args {
const char *name;
};
+struct cpu_softc {
+ device_t sc_dev; /* device tree glue */
+ struct cpu_info *sc_info; /* pointer to CPU info */
+ bool sc_wasonline;
+};
+
#ifdef _KERNEL
#include <sys/kcpuset.h>
#if defined(_KERNEL_OPT)
diff --git a/sys/arch/x86/include/i82489var.h b/sys/arch/x86/include/i82489var.h
index fd2be1e..f34693a 100644
--- a/sys/arch/x86/include/i82489var.h
+++ b/sys/arch/x86/include/i82489var.h
@@ -88,7 +88,6 @@ struct cpu_info;
extern void lapic_boot_init(paddr_t);
extern void lapic_set_lvt(void);
extern void lapic_enable(void);
-extern void lapic_calibrate_timer(struct cpu_info *ci);
extern void lapic_initclocks(void);
extern uint32_t lapic_readreg(u_int);
diff --git a/sys/arch/x86/x86/cpu.c b/sys/arch/x86/x86/cpu.c
index 4f31ee4..66ce4aa 100644
--- a/sys/arch/x86/x86/cpu.c
+++ b/sys/arch/x86/x86/cpu.c
@@ -124,19 +124,11 @@ __KERNEL_RCSID(0, "$NetBSD: cpu.c,v 1.132 2017/07/28 14:12:26 riastradh Exp $");
static int cpu_match(device_t, cfdata_t, void *);
static void cpu_attach(device_t, device_t, void *);
static void cpu_defer(device_t);
-static int cpu_rescan(device_t, const char *, const int *);
-static void cpu_childdetached(device_t, device_t);
static bool cpu_stop(device_t);
static bool cpu_suspend(device_t, const pmf_qual_t *);
static bool cpu_resume(device_t, const pmf_qual_t *);
static bool cpu_shutdown(device_t, int);
-struct cpu_softc {
- device_t sc_dev; /* device tree glue */
- struct cpu_info *sc_info; /* pointer to CPU info */
- bool sc_wasonline;
-};
-
#ifdef MULTIPROCESSOR
int mp_cpu_start(struct cpu_info *, paddr_t);
void mp_cpu_start_cleanup(struct cpu_info *);
@@ -296,15 +288,20 @@ cpu_attach(device_t parent, device_t self, void *aux)
{
struct cpu_softc *sc = device_private(self);
struct cpu_attach_args *caa = aux;
+ sc->sc_dev = self;
+
+ cpu_attach_common(parent, self, caa);
+}
+void
+cpu_attach_common(device_t parent, device_t self, void *aux)
+{
+ struct cpu_softc *sc = device_private(self);
+ struct cpu_attach_args *caa = aux;
struct cpu_info *ci;
uintptr_t ptr;
-#if NLAPIC > 0
- int cpunum = caa->cpu_number;
-#endif
+
static bool again;
-
- sc->sc_dev = self;
-
+
if (ncpu == maxcpus) {
#ifndef _LP64
aprint_error(": too many CPUs, please use NetBSD/amd64\n");
@@ -338,22 +335,6 @@ cpu_attach(device_t parent, device_t self, void *aux)
aprint_naive(": %s Processor\n",
caa->cpu_role == CPU_ROLE_SP ? "Single" : "Boot");
ci = &cpu_info_primary;
-#if NLAPIC > 0
- if (cpunum != lapic_cpu_number()) {
- /* XXX should be done earlier. */
- uint32_t reg;
- aprint_verbose("\n");
- aprint_verbose_dev(self, "running CPU at apic %d"
- " instead of at expected %d", lapic_cpu_number(),
- cpunum);
- reg = lapic_readreg(LAPIC_ID);
- lapic_writereg(LAPIC_ID, (reg & ~LAPIC_ID_MASK) |
- (cpunum << LAPIC_ID_SHIFT));
- }
- if (cpunum != lapic_cpu_number()) {
- aprint_error_dev(self, "unable to reset apic id\n");
- }
-#endif
}
ci->ci_self = ci;
@@ -397,14 +378,6 @@ cpu_attach(device_t parent, device_t self, void *aux)
cpu_init(ci);
cpu_set_tss_gates(ci);
pmap_cpu_init_late(ci);
-#if NLAPIC > 0
- if (caa->cpu_role != CPU_ROLE_SP) {
- /* Enable lapic. */
- lapic_enable();
- lapic_set_lvt();
- lapic_calibrate_timer(ci);
- }
-#endif
/* Make sure DELAY() is initialized. */
DELAY(1);
again = true;
@@ -490,7 +463,7 @@ cpu_defer(device_t self)
cpu_rescan(self, NULL, NULL);
}
-static int
+int
cpu_rescan(device_t self, const char *ifattr, const int *locators)
{
struct cpu_softc *sc = device_private(self);
@@ -530,7 +503,7 @@ cpu_rescan(device_t self, const char *ifattr, const int *locators)
return 0;
}
-static void
+void
cpu_childdetached(device_t self, device_t child)
{
struct cpu_softc *sc = device_private(self);
diff --git a/sys/arch/x86/x86/lapic.c b/sys/arch/x86/x86/lapic.c
index 9c341bc..79d5416 100644
--- a/sys/arch/x86/x86/lapic.c
+++ b/sys/arch/x86/x86/lapic.c
@@ -92,6 +92,7 @@ extern int ddb_vec;
/* Referenced from vector.S */
void lapic_clockintr(void *, struct intrframe *);
+static void lapic_calibrate_timer(device_t);
static void lapic_delay(unsigned int);
static uint32_t lapic_gettick(void);
static void lapic_setup_bsp(paddr_t);
@@ -601,8 +602,8 @@ extern void (*initclock_func)(void); /* XXX put in header file */
*
* We're actually using the IRQ0 timer. Hmm.
*/
-void
-lapic_calibrate_timer(struct cpu_info *ci)
+static void
+lapic_calibrate_timer(device_t dev)
{
unsigned int seen, delta, initial_i8254, initial_lapic;
unsigned int cur_i8254, cur_lapic;
@@ -610,7 +611,7 @@ lapic_calibrate_timer(struct cpu_info *ci)
int i;
char tbuf[9];
- aprint_debug_dev(ci->ci_dev, "calibrating local timer\n");
+ aprint_debug_dev(dev, "calibrating local timer\n");
/*
* Configure timer to one-shot, interrupt masked,
@@ -642,7 +643,7 @@ lapic_calibrate_timer(struct cpu_info *ci)
humanize_number(tbuf, sizeof(tbuf), lapic_per_second, "Hz", 1000);
- aprint_debug_dev(ci->ci_dev, "apic clock running at %s\n", tbuf);
+ aprint_debug_dev(dev, "apic clock running at %s\n", tbuf);
if (lapic_per_second != 0) {
/*
@@ -935,3 +936,64 @@ lapic_dump(void)
apic_format_redir(device_xname(ci->ci_dev), "err", 0, 0,
lapic_readreg(LAPIC_LVERR));
}
+
+/*
+ * cpu attach helpers
+ * These are called via x86/mpacpi.c or x86/mpbios.c
+ */
+
+static int lapic_match(device_t, cfdata_t, void *);
+static void lapic_attach(device_t, device_t, void *);
+
+CFATTACH_DECL2_NEW(lapic, sizeof(struct cpu_softc),
+ lapic_match, lapic_attach, NULL, NULL, cpu_rescan, cpu_childdetached);
+
+static int
+lapic_match(device_t parent, cfdata_t match, void *aux)
+{
+ /* XXX: "detect" lapic ? */
+ return 1;
+}
+
+static void
+lapic_attach(device_t parent, device_t self, void *aux)
+{
+ struct cpu_softc *sc = device_private(self);
+ struct cpu_attach_args *caa = aux;
+
+ int cpunum = caa->cpu_number;
+
+ static bool again;
+
+ sc->sc_dev = self;
+
+ cpu_attach_common(parent, self, caa);
+
+ if (caa->cpu_role != CPU_ROLE_AP) {
+ if (cpunum != lapic_cpu_number()) {
+ /* XXX should be done earlier. */
+ uint32_t reg;
+ aprint_verbose("\n");
+ aprint_verbose_dev(self, "running CPU at apic %d"
+ " instead of at expected %d", lapic_cpu_number(),
+ cpunum);
+ reg = lapic_readreg(LAPIC_ID);
+ lapic_writereg(LAPIC_ID, (reg & ~LAPIC_ID_MASK) |
+ (cpunum << LAPIC_ID_SHIFT));
+ }
+ if (cpunum != lapic_cpu_number()) {
+ aprint_error_dev(self, "unable to reset apic id\n");
+ }
+ }
+
+ if (!again) {
+ if (caa->cpu_role != CPU_ROLE_SP) {
+ /* Enable lapic. */
+ lapic_enable();
+ lapic_set_lvt();
+ lapic_calibrate_timer(self);
+ }
+
+ again = true;
+ }
+}