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(); > } > } > >