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 #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; + } +}