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 -0000      1.50
> +++ i386/i386/lapic.c 28 Aug 2022 20:24:55 -0000
> @@ -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, 0x80000000);
> +     lapic_timer_oneshot(LAPIC_LVTT_M, 0x80000000);
>
> -     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 {
> +             s = intr_disable();
> +             startapic = lapic_gettick();
> +             delay(1 * 1000 * 1000);
> +             endapic = lapic_gettick();
> +             intr_restore(s);
> +             lapic_per_second = startapic - endapic;
> +     }
>
> -     printf("%s: apic clock running at %lldMHz\n",
> -         ci->ci_dev->dv_xname, tmp / (1000 * 1000));
> +     printf("%s: apic clock running at %dMHz\n",
> +         ci->ci_dev->dv_xname, lapic_per_second / (1000 * 1000));
>
>       if (lapic_per_second != 0) {
>               /*
> @@ -366,10 +394,7 @@ lapic_calibrate_timer(struct cpu_info *c
>               lapic_tval = (lapic_per_second * 2) / hz;
>               lapic_tval = (lapic_tval / 2) + (lapic_tval & 0x1);
>
> -             i82489_writereg(LAPIC_LVTT, LAPIC_LVTT_TM | LAPIC_LVTT_M |
> -                 LAPIC_TIMER_VECTOR);
> -             i82489_writereg(LAPIC_DCR_TIMER, LAPIC_DCRT_DIV1);
> -             i82489_writereg(LAPIC_ICR_TIMER, lapic_tval);
> +             lapic_timer_periodic(LAPIC_LVTT_M, lapic_tval);
>
>               /*
>                * Compute fixed-point ratios between cycles and
> @@ -426,6 +451,8 @@ lapic_delay(int usec)
>               else
>                       deltat -= otick - tick;
>               otick = tick;
> +
> +             CPU_BUSY_CYCLE();
>       }
>  }
>
>

Reply via email to