Re: i386/lapic.c: sync with amd64/lapic.c

2022-08-30 Thread Mike Larkin
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 {
> +   

i386/lapic.c: sync with amd64/lapic.c

2022-08-28 Thread Scott Cheloha
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?

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 {
+   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",
-