On 5/11/22 14:34, Yuichiro NAITO wrote:
After applying your patch, cpu1 is not identified on my current kernel.
Dmesg shows as follows. I'll see it further more.
I found that LAPIC is necessary for `delay` function that is used in
`idendifycpu` and
waiting loop for CPUF_IDENTIFY flag is set.
I partly reverted calling `lapic_enable` and `lapic_startclock` and it works
for me.
Please see my following patch.
diff --git a/sys/arch/amd64/amd64/cpu.c b/sys/arch/amd64/amd64/cpu.c
index 4778347a12e..83c0297e7f1 100644
--- a/sys/arch/amd64/amd64/cpu.c
+++ b/sys/arch/amd64/amd64/cpu.c
@@ -844,50 +844,54 @@ cpu_start_secondary(struct cpu_info *ci)
* wait for it to become ready
*/
for (i = 100000; (!(ci->ci_flags & CPUF_PRESENT)) && i>0;i--) {
delay(10);
}
if (! (ci->ci_flags & CPUF_PRESENT)) {
printf("%s: failed to become ready\n", ci->ci_dev->dv_xname);
#if defined(MPDEBUG) && defined(DDB)
printf("dropping into debugger; continue from here to resume
boot\n");
db_enter();
#endif
- } else {
- /*
- * Synchronize time stamp counters. Invalidate cache and
- * synchronize twice (in tsc_sync_bp) to minimize possible
- * cache effects. Disable interrupts to try and rule out any
- * external interference.
- */
- s = intr_disable();
- wbinvd();
- tsc_sync_bp(ci);
- intr_restore(s);
-#ifdef TSC_DEBUG
- printf("TSC skew=%lld\n", (long long)ci->ci_tsc_skew);
-#endif
+ goto cleanup;
}
if ((ci->ci_flags & CPUF_IDENTIFIED) == 0) {
atomic_setbits_int(&ci->ci_flags, CPUF_IDENTIFY);
/* wait for it to identify */
for (i = 2000000; (ci->ci_flags & CPUF_IDENTIFY) && i > 0; i--)
delay(10);
- if (ci->ci_flags & CPUF_IDENTIFY)
+ if (ci->ci_flags & CPUF_IDENTIFY) {
printf("%s: failed to identify\n",
ci->ci_dev->dv_xname);
+ goto cleanup;
+ }
}
+ /*
+ * Synchronize time stamp counters. Invalidate cache and
+ * synchronize twice (in tsc_sync_bp) to minimize possible
+ * cache effects. Disable interrupts to try and rule out any
+ * external interference.
+ */
+ s = intr_disable();
+ wbinvd();
+ tsc_sync_bp(ci);
+ intr_restore(s);
+#ifdef TSC_DEBUG
+ printf("TSC skew=%lld\n", (long long)ci->ci_tsc_skew);
+#endif
+
+cleanup:
CPU_START_CLEANUP(ci);
pmap_kremove(MP_TRAMPOLINE, PAGE_SIZE);
pmap_kremove(MP_TRAMP_DATA, PAGE_SIZE);
}
void
cpu_boot_secondary(struct cpu_info *ci)
{
int i;
int64_t drift;
@@ -932,53 +936,53 @@ void
cpu_hatch(void *v)
{
struct cpu_info *ci = (struct cpu_info *)v;
int s;
cpu_init_msrs(ci);
#ifdef DEBUG
if (ci->ci_flags & CPUF_PRESENT)
panic("%s: already running!?", ci->ci_dev->dv_xname);
#endif
-
- /*
- * Synchronize the TSC for the first time. Note that interrupts are
- * off at this point.
- */
- wbinvd();
ci->ci_flags |= CPUF_PRESENT;
- ci->ci_tsc_skew = 0; /* reset on resume */
- tsc_sync_ap(ci);
lapic_enable();
lapic_startclock();
cpu_ucode_apply(ci);
cpu_tsx_disable(ci);
if ((ci->ci_flags & CPUF_IDENTIFIED) == 0) {
/*
* 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);
/* Prevent identifycpu() from running again */
atomic_setbits_int(&ci->ci_flags, CPUF_IDENTIFIED);
}
+ /*
+ * Synchronize the TSC for the first time. Note that interrupts are
+ * off at this point.
+ */
+ wbinvd();
+ ci->ci_tsc_skew = 0; /* reset on resume */
+ tsc_sync_ap(ci);
+
while ((ci->ci_flags & CPUF_GO) == 0)
delay(10);
#ifdef HIBERNATE
if ((ci->ci_flags & CPUF_PARK) != 0) {
atomic_clearbits_int(&ci->ci_flags, CPUF_PARK);
hibernate_drop_to_real_mode();
}
#endif /* HIBERNATE */
#ifdef DEBUG
if (ci->ci_flags & CPUF_RUNNING)
--
Yuichiro NAITO ([email protected])