Hello,

Thanks for fixing this!

Damien Zammit via Bug reports for the GNU Hurd, le mar. 30 juin 2026 10:54:30 
+0000, a ecrit:
> The one-shot pit delay was not calibrated properly.
> This fixes the pit_udelay() function so it can be used for
> tiny delays within the kernel.  Removes dependence on HPET for smp.
> ---
>  i386/i386/pit.c | 16 ++++++++++------
>  i386/i386/pit.h |  3 +++
>  i386/i386/smp.c |  5 +++--
>  3 files changed, 16 insertions(+), 8 deletions(-)
> 
> diff --git a/i386/i386/pit.c b/i386/i386/pit.c
> index 6c006a98..1863e283 100644
> --- a/i386/i386/pit.c
> +++ b/i386/i386/pit.c
> @@ -66,10 +66,10 @@ int pit0_mode = PIT_C0|PIT_SQUAREMODE|PIT_READMODE ;
>  unsigned int clknumb = CLKNUM;               /* interrupt interval for timer 
> 0 */
>  
>  void
> -pit_prepare_sleep(int persec)
> +pit_prepare_sleep(int usec)
>  {
>      /* Prepare to sleep for 1/persec seconds */
> -    uint32_t val = 0;
> +    uint64_t val = 0;
>      uint8_t lsb, msb;
>  
>      val = inb(PITAUX_PORT);
> @@ -77,7 +77,7 @@ pit_prepare_sleep(int persec)
>      val |= PITAUX_GATE2;
>      outb (PITAUX_PORT, val);
>      outb (PITCTL_PORT, PIT_C2 | PIT_LOADMODE | PIT_ONESHOTMODE);
> -    val = CLKNUM / persec;
> +    val = CLKNUM * usec / 1000000;

Just changing the type of the eventual left-value will not change the
type of the expression. You want to cast CLKNUM into uint64_t before
multiplying it.

We'd also want to assert against too-long usec values, by checking that
val <= 0xffff.

>      lsb = val & 0xff;
>      msb = val >> 8;
>      outb (PITCTR2_PORT, lsb);
> @@ -104,15 +104,19 @@ pit_sleep(void)
>  void
>  pit_udelay(int usec)
>  {
> -    pit_prepare_sleep(1000000 / usec);
> +    while (usec > MAX_PIT_USEC) {

Ah, indeed!

> +        pit_prepare_sleep(MAX_PIT_USEC);
> +        pit_sleep();
> +        usec -= MAX_PIT_USEC;
> +    }
> +    pit_prepare_sleep(usec);
>      pit_sleep();
>  }
>  
>  void
>  pit_mdelay(int msec)
>  {
> -    pit_prepare_sleep(1000 / msec);
> -    pit_sleep();
> +    pit_udelay(1000 * msec);
>  }
>  
>  void
> diff --git a/i386/i386/pit.h b/i386/i386/pit.h
> index 49e1051b..350ddc21 100644
> --- a/i386/i386/pit.h
> +++ b/i386/i386/pit.h
> @@ -87,6 +87,9 @@ WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
>   */
>  #if  defined(AT386) || defined(ATX86_64)
>  #define CLKNUM               1193182
> +
> +/* CLKNUM ticks/s * (54924/1000000)s ~= 0xffff */
> +#define MAX_PIT_USEC 54924

Better explicitly write (0xffffll * 1000000/1193182) to explain the
computation.

>  #endif       /* AT386 */
>  
>  extern void clkstart(void);
> diff --git a/i386/i386/smp.c b/i386/i386/smp.c
> index dc3a8ba5..6b610020 100644
> --- a/i386/i386/smp.c
> +++ b/i386/i386/smp.c
> @@ -23,6 +23,7 @@
>  #include <i386/smp.h>
>  #include <i386/cpu.h>
>  #include <i386/pio.h>
> +#include <i386/pit.h>
>  #include <i386/vm_param.h>
>  #include <i386at/idt.h>
>  #include <i386at/cram.h>
> @@ -138,13 +139,13 @@ smp_send_ipi_startup_twice(int bsp_apic_id, int vector)
>           */
>          apic_send_ipi(ALL_EXCLUDING_SELF, STARTUP, PHYSICAL, DE_ASSERT, 
> EDGE, vector, bsp_apic_id);
>  
> -        hpet_udelay(10);
> +        pit_udelay(10);
>  
>          /* Wait for other cpu to accept IPI */
>          wait_for_ipi();
>          send_err = lapic->error_status.r;
>  
> -        hpet_udelay(10);
> +        pit_udelay(10);
>  
>          lapic->error_status.r = 0;
>          accept_err = lapic->error_status.r & 0xef;
> -- 
> 2.51.0

Reply via email to