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 -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