On Mon, Mar 28, 2022 at 10:52:09PM -0500, Scott Cheloha wrote:
> I want to use the IA32_TSC_ADJUST MSR where available when testing TSC
> synchronization. We note if it's available during CPU identification.
>
> Can we do CPU identification earlier in cpu_hatch() and
> cpu_start_secondary(), before we do the TSC sync testing?
>
> This can wait until after release. I'm just trying to suss out
> whether there is an order dependency I'm not seeing. My laptop
> appears to boot and resume no differently with this patch.
>
> Thoughts?
The rest aside, moving the cpu_ucode_apply() call to after the
identifycpu() call is wrong as microcode can add cpuid bits.
I would keep cpu_tsx_disable() before it as well.
I'm sure I've had problems trying to change the sequencing
of lapic, tsc freq and identify in the past. It caused problems
only on certain machines.
>
> Index: cpu.c
> ===================================================================
> RCS file: /cvs/src/sys/arch/amd64/amd64/cpu.c,v
> retrieving revision 1.155
> diff -u -p -r1.155 cpu.c
> --- cpu.c 21 Feb 2022 11:03:39 -0000 1.155
> +++ cpu.c 29 Mar 2022 03:49:31 -0000
> @@ -842,20 +842,7 @@ cpu_start_secondary(struct cpu_info *ci)
> 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) {
> @@ -865,11 +852,28 @@ cpu_start_secondary(struct cpu_info *ci)
> 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);
> @@ -930,20 +934,7 @@ cpu_hatch(void *v)
> 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) {
> /*
> @@ -960,6 +951,19 @@ cpu_hatch(void *v)
> /* 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);
> +
> + lapic_enable();
> + lapic_startclock();
> + cpu_ucode_apply(ci);
> + cpu_tsx_disable(ci);
>
> while ((ci->ci_flags & CPUF_GO) == 0)
> delay(10);
>
>