On Sun, Aug 28, 2022 at 03:26:49PM -0500, Scott Cheloha wrote:
> As promised off-list: in anticipation of merging the clock interrupt
> code, let's sync up the lapic timer parts of i386/lapic.c with the
> corresponding parts in amd64/lapic.c. They will need identical
> changes to use the new code, so the more alike they are the better.
>
> Notable differences remaining in the timer code:
>
> - We use i82489_readreg() and i82489_writereg() on i386 instead of
> lapic_readreg() and lapic_writereg().
>
> - lapic_clockintr() is just plain different on i386, I'm not
> touching it yet.
>
> - No way to skip_calibration on i386.
>
> We can do synchronized cleanup in a later patch.
>
> Does this compile and boot on i386? If so, ok?
Yes and yes (at least in an ESXi VM).
If others test on real hardware and it works, ok mlarkin; diff reads ok
to me.
-ml
>
> Index: i386/i386/lapic.c
> ===
> RCS file: /cvs/src/sys/arch/i386/i386/lapic.c,v
> retrieving revision 1.50
> diff -u -p -r1.50 lapic.c
> --- i386/i386/lapic.c 25 Aug 2022 17:38:16 - 1.50
> +++ i386/i386/lapic.c 28 Aug 2022 20:24:55 -
> @@ -244,11 +244,41 @@ u_int32_t lapic_tval;
> /*
> * this gets us up to a 4GHz busclock
> */
> -u_int32_t lapic_per_second;
> +u_int32_t lapic_per_second = 0;
> u_int32_t lapic_frac_usec_per_cycle;
> u_int64_t lapic_frac_cycle_per_usec;
> u_int32_t lapic_delaytab[26];
>
> +void lapic_timer_oneshot(uint32_t, uint32_t);
> +void lapic_timer_periodic(uint32_t, uint32_t);
> +
> +/*
> + * Start the local apic countdown timer.
> + *
> + * First set the mode, mask, and vector. Then set the
> + * divisor. Last, set the cycle count: this restarts
> + * the countdown.
> + */
> +static inline void
> +lapic_timer_start(uint32_t mode, uint32_t mask, uint32_t cycles)
> +{
> + i82489_writereg(LAPIC_LVTT, mode | mask | LAPIC_TIMER_VECTOR);
> + i82489_writereg(LAPIC_DCR_TIMER, LAPIC_DCRT_DIV1);
> + i82489_writereg(LAPIC_ICR_TIMER, cycles);
> +}
> +
> +void
> +lapic_timer_oneshot(uint32_t mask, uint32_t cycles)
> +{
> + lapic_timer_start(LAPIC_LVTT_TM_ONESHOT, mask, cycles);
> +}
> +
> +void
> +lapic_timer_periodic(uint32_t mask, uint32_t cycles)
> +{
> + lapic_timer_start(LAPIC_LVTT_TM_PERIODIC, mask, cycles);
> +}
> +
> void
> lapic_clockintr(void *arg)
> {
> @@ -262,17 +292,7 @@ lapic_clockintr(void *arg)
> void
> lapic_startclock(void)
> {
> - /*
> - * Start local apic countdown timer running, in repeated mode.
> - *
> - * Mask the clock interrupt and set mode,
> - * then set divisor,
> - * then unmask and set the vector.
> - */
> - i82489_writereg(LAPIC_LVTT, LAPIC_LVTT_TM|LAPIC_LVTT_M);
> - i82489_writereg(LAPIC_DCR_TIMER, LAPIC_DCRT_DIV1);
> - i82489_writereg(LAPIC_ICR_TIMER, lapic_tval);
> - i82489_writereg(LAPIC_LVTT, LAPIC_LVTT_TM|LAPIC_TIMER_VECTOR);
> + lapic_timer_periodic(0, lapic_tval);
> }
>
> void
> @@ -284,6 +304,7 @@ lapic_initclocks(void)
> }
>
> extern int gettick(void);/* XXX put in header file */
> +extern u_long rtclock_tval; /* XXX put in header file */
>
> static __inline void
> wait_next_cycle(void)
> @@ -325,38 +346,45 @@ lapic_calibrate_timer(struct cpu_info *c
>* Configure timer to one-shot, interrupt masked,
>* large positive number.
>*/
> - i82489_writereg(LAPIC_LVTT, LAPIC_LVTT_M);
> - i82489_writereg(LAPIC_DCR_TIMER, LAPIC_DCRT_DIV1);
> - i82489_writereg(LAPIC_ICR_TIMER, 0x8000);
> + lapic_timer_oneshot(LAPIC_LVTT_M, 0x8000);
>
> - s = intr_disable();
> + if (delay_func == i8254_delay) {
> + s = intr_disable();
>
> - /* wait for current cycle to finish */
> - wait_next_cycle();
> + /* wait for current cycle to finish */
> + wait_next_cycle();
>
> - startapic = lapic_gettick();
> + startapic = lapic_gettick();
>
> - /* wait the next hz cycles */
> - for (i = 0; i < hz; i++)
> - wait_next_cycle();
> + /* wait the next hz cycles */
> + for (i = 0; i < hz; i++)
> + wait_next_cycle();
>
> - endapic = lapic_gettick();
> + endapic = lapic_gettick();
>
> - intr_restore(s);
> + intr_restore(s);
>
> - dtick = hz * TIMER_DIV(hz);
> - dapic = startapic-endapic;
> + dtick = hz * rtclock_tval;
> + dapic = startapic-endapic;
>
> - /*
> - * there are TIMER_FREQ ticks per second.
> - * in dtick ticks, there are dapic bus clocks.
> - */
> - tmp = (TIMER_FREQ * dapic) / dtick;
> + /*
> + * there are TIMER_FREQ ticks per second.
> + * in dtick ticks, there are dapic bus clocks.
> + */
> + tmp = (TIMER_FREQ * dapic) / dtick;
>
> - lapic_per_second = tmp;
> + lapic_per_second = tmp;
> + } else {
> +