bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v3 2/4 gnumach] Add HPET timer for small accurate delays


From: Damien Zammit
Subject: Re: [PATCH v3 2/4 gnumach] Add HPET timer for small accurate delays
Date: Thu, 08 Feb 2024 04:33:41 +0000

Sorry I didn't realise.

I am using proton mail bridge to mail patches.
I don't know how to change the encoding...
Do you know if this would be a git send-email configuration setting?

Damien

Sent from Proton Mail mobile

-------- Original Message --------
On 8 Feb 2024, 10:28 am, Samuel Thibault wrote:

> Applied, thanks! Could you check with your mailer how to prevent it from 
> using the quoted-printable encoding? git am often has troubles applying your 
> patches, and I have to fix the patch by hand, it's really unconvenient. 
> Samuel Damien Zammit, le mer. 07 févr. 2024 05:02:15 +0000, a ecrit: > 
> TESTED: This works in qemu correctly > TESTED: This works on an AMD board 
> with ACPI v2.0 correctly > > --- > i386/i386/apic.c | 89 
> +++++++++++++++++++++++++++++++++++ > i386/i386/apic.h | 5 ++ > 
> i386/i386at/acpi_parse_apic.c | 35 ++++++++++---- > 
> i386/i386at/acpi_parse_apic.h | 23 +++++++++ > i386/i386at/model_dep.c | 5 ++ 
> > 5 files changed, 149 insertions(+), 8 deletions(-) > > diff --git 
> a/i386/i386/apic.c b/i386/i386/apic.c > index feb49c85..0b5be50f 100644 > --- 
> a/i386/i386/apic.c > +++ b/i386/i386/apic.c > @@ -26,6 +26,10 @@ > #include  
> > #include  > > +/* > + * Period of HPET timer in nanoseconds > + */ > 
> +uint32_t hpet_period_nsec; > > /* > * This dummy structure is needed so that 
> CPU_NUMBER can be called > @@ -362,3 +366,88 @@ lapic_eoi(void) > { > 
> lapic->eoi.r = 0; > } > + > +#define HPET32(x) *((volatile uint32_t 
> *)((uint8_t *)hpet_addr + x)) > +#define HPET_CAP_PERIOD 0x04 > +#define 
> HPET_CFG 0x10 > +# define HPET_CFG_ENABLE (1 +# define HPET_LEGACY_ROUTE (1 
> +#define HPET_COUNTER 0xf0 > +#define HPET_T0_CFG 0x100 > +# define 
> HPET_T0_32BIT_MODE (1 +# define HPET_T0_VAL_SET (1 +# define 
> HPET_T0_TYPE_PERIODIC (1 +# define HPET_T0_INT_ENABLE (1 +#define 
> HPET_T0_COMPARATOR 0x108 > + > +#define FSEC_PER_NSEC 1000000 > +#define 
> NSEC_PER_USEC 1000 > + > +/* This function sets up the HPET timer to be in > 
> + * 32 bit periodic mode and not generating any interrupts. > + * The timer 
> counts upwards and when it reaches 0xffffffff it > + * wraps to zero. The 
> timer ticks at a constant rate in nanoseconds which > + * is stored in 
> hpet_period_nsec variable. > + */ > +void > +hpet_init(void) > +{ > + 
> uint32_t period; > + uint32_t val; > + > + assert(hpet_addr != 0); > + > + /* 
> Find out how often the HPET ticks in nanoseconds */ > + period = 
> HPET32(HPET_CAP_PERIOD); > + hpet_period_nsec = period / FSEC_PER_NSEC; > + 
> printf("HPET ticks every %d nanoseconds\n", hpet_period_nsec); > + > + /* 
> Disable HPET and legacy interrupt routing mode */ > + val = HPET32(HPET_CFG); 
> > + val = val & ~(HPET_LEGACY_ROUTE | HPET_CFG_ENABLE); > + HPET32(HPET_CFG) 
> = val; > + > + /* Clear the counter */ > + HPET32(HPET_COUNTER) = 0; > + > + 
> /* Set up 32 bit periodic timer with no interrupts */ > + val = 
> HPET32(HPET_T0_CFG); > + val = (val & ~HPET_T0_INT_ENABLE) | 
> HPET_T0_32BIT_MODE | HPET_T0_TYPE_PERIODIC | HPET_T0_VAL_SET; > + 
> HPET32(HPET_T0_CFG) = val; > + > + /* Set comparator to max */ > + 
> HPET32(HPET_T0_COMPARATOR) = 0xffffffff; > + > + /* Enable the HPET */ > + 
> HPET32(HPET_CFG) |= HPET_CFG_ENABLE; > + > + printf("HPET enabled\n"); > +} > 
> + > +void > +hpet_udelay(uint32_t us) > +{ > + uint32_t start, now; > + 
> uint32_t max_delay_us = 0xffffffff / NSEC_PER_USEC; > + > + if (us > 
> max_delay_us) { > + printf("HPET ERROR: Delay too long, %d usec, truncating 
> to %d usec\n", > + us, max_delay_us); > + us = max_delay_us; > + } > + > + /* 
> Convert us to HPET ticks */ > + us = (us * NSEC_PER_USEC) / hpet_period_nsec; 
> > + > + start = HPET32(HPET_COUNTER); > + do { > + now = 
> HPET32(HPET_COUNTER); > + } while (now - start +} > + > +void > 
> +hpet_mdelay(uint32_t ms) > +{ > + hpet_udelay(ms * 1000); > +} > + > diff 
> --git a/i386/i386/apic.h b/i386/i386/apic.h > index 29387d9d..9eef0d8b 100644 
> > --- a/i386/i386/apic.h > +++ b/i386/i386/apic.h > @@ -252,10 +252,15 @@ 
> void calibrate_lapic_timer(void); > void ioapic_toggle(int pin, int mask); > 
> void ioapic_configure(void); > > +void hpet_init(void); > +void 
> hpet_udelay(uint32_t us); > +void hpet_mdelay(uint32_t ms); > + > extern int 
> timer_pin; > extern void intnull(int unit); > extern volatile ApicLocalUnit* 
> lapic; > extern int cpu_id_lut[]; > +extern uint32_t *hpet_addr; > > #endif > 
> > diff --git a/i386/i386at/acpi_parse_apic.c b/i386/i386at/acpi_parse_apic.c 
> > index dcd5da89..1cfc1791 100644 > --- a/i386/i386at/acpi_parse_apic.c > +++ 
> b/i386/i386at/acpi_parse_apic.c > @@ -34,6 +34,7 @@ > > static struct 
> acpi_apic *apic_madt = NULL; > unsigned lapic_addr; > +uint32_t *hpet_addr; > 
> > /* > * acpi_print_info: shows by screen the ACPI's rsdp and rsdt virtual 
> address > @@ -292,28 +293,37 @@ acpi_get_xsdt(phys_addr_t rsdp_phys, int* 
> acpi_xsdt_n) > * and the number of entries of RSDT table. > * > * Returns a 
> reference to APIC/MADT table if success, NULL if failure. > + * Also sets 
> hpet_addr to base address of HPET. > */ > static struct acpi_apic* > 
> acpi_get_apic(struct acpi_rsdt *rsdt, int acpi_rsdt_n) > { > struct acpi_dhdr 
> *descr_header; > + struct acpi_apic *madt = NULL; > int check_signature; > + 
> uint64_t map_addr; > > /* Search APIC entries in rsdt table. */ > for (int i 
> = 0; i descr_header = (struct acpi_dhdr*) 
> kmem_map_aligned_table(rsdt->entry[i], sizeof(struct acpi_dhdr), > 
> VM_PROT_READ); > > - /* Check if the entry contains an APIC. */ > + /* Check 
> if the entry is a MADT */ > check_signature = 
> acpi_check_signature(descr_header->signature, ACPI_APIC_SIG, 
> 4*sizeof(uint8_t)); > + if (check_signature == ACPI_SUCCESS) > + madt = 
> (struct acpi_apic*) descr_header; > > + /* Check if the entry is a HPET */ > 
> + check_signature = acpi_check_signature(descr_header->signature, 
> ACPI_HPET_SIG, 4*sizeof(uint8_t)); > if (check_signature == ACPI_SUCCESS) { > 
> - /* If yes, return the APIC. */ > - return (struct acpi_apic*) descr_header; 
> > + map_addr = ((struct acpi_hpet *)descr_header)->address.addr64; > + assert 
> (map_addr != 0); > + hpet_addr = (uint32_t *)kmem_map_aligned_table(map_addr, 
> 1024, VM_PROT_READ | VM_PROT_WRITE); > + printf("HPET at physical address 
> 0x%llx\n", map_addr); > } > } > > - return NULL; > + return madt; > } > > /* 
> > @@ -323,28 +333,37 @@ acpi_get_apic(struct acpi_rsdt *rsdt, int 
> acpi_rsdt_n) > * and the number of entries of XSDT table. > * > * Returns a 
> reference to APIC/MADT table if success, NULL if failure. > + * Also sets 
> hpet_addr to base address of HPET. > */ > static struct acpi_apic* > 
> acpi_get_apic2(struct acpi_xsdt *xsdt, int acpi_xsdt_n) > { > struct 
> acpi_dhdr *descr_header; > + struct acpi_apic *madt = NULL; > int 
> check_signature; > + uint64_t map_addr; > > /* Search APIC entries in rsdt 
> table. */ > for (int i = 0; i descr_header = (struct acpi_dhdr*) 
> kmem_map_aligned_table(xsdt->entry[i], sizeof(struct acpi_dhdr), > 
> VM_PROT_READ); > > - /* Check if the entry contains an APIC. */ > + /* Check 
> if the entry is an APIC. */ > check_signature = 
> acpi_check_signature(descr_header->signature, ACPI_APIC_SIG, 
> 4*sizeof(uint8_t)); > + if (check_signature == ACPI_SUCCESS) > + madt = 
> (struct acpi_apic *)descr_header; > > + /* Check if the entry is a HPET. */ > 
> + check_signature = acpi_check_signature(descr_header->signature, 
> ACPI_HPET_SIG, 4*sizeof(uint8_t)); > if (check_signature == ACPI_SUCCESS) { > 
> - /* If yes, return the APIC. */ > - return (struct acpi_apic*) descr_header; 
> > + map_addr = ((struct acpi_hpet *)descr_header)->address.addr64; > + assert 
> (map_addr != 0); > + hpet_addr = (uint32_t *)kmem_map_aligned_table(map_addr, 
> 1024, VM_PROT_READ | VM_PROT_WRITE); > + printf("HPET at physical address 
> 0x%llx\n", map_addr); > } > } > > - return NULL; > + return madt; > } > > /* 
> > diff --git a/i386/i386at/acpi_parse_apic.h b/i386/i386at/acpi_parse_apic.h 
> > index df36bb31..85e01170 100644 > --- a/i386/i386at/acpi_parse_apic.h > +++ 
> b/i386/i386at/acpi_parse_apic.h > @@ -91,6 +91,14 @@ struct acpi_xsdt { > 
> uint64_t entry[0]; > } __attribute__((__packed__)); > > +struct acpi_address 
> { > + uint8_t is_io; > + uint8_t reg_width; > + uint8_t reg_offset; > + 
> uint8_t reserved; > + uint64_t addr64; > +} __attribute__((__packed__)); > + 
> > /* APIC table signature. */ > #define ACPI_APIC_SIG "APIC" > > @@ -170,6 
> +178,21 @@ struct acpi_apic_irq_override { > uint16_t flags; > } 
> __attribute__((__packed__)); > > + > +#define ACPI_HPET_SIG "HPET" > + > +/* 
> > + * HPET High Precision Event Timer structure > + */ > +struct acpi_hpet { 
> > + struct acpi_dhdr header; > + uint32_t id; > + struct acpi_address 
> address; > + uint8_t sequence; > + uint16_t minimum_tick; > + uint8_t flags; 
> > +} __attribute__((__packed__)); > + > int acpi_apic_init(void); > void 
> acpi_print_info(phys_addr_t rsdp, void *rsdt, int acpi_rsdt_n); > > diff 
> --git a/i386/i386at/model_dep.c b/i386/i386at/model_dep.c > index 
> 173b99f5..b5f56c7d 100644 > --- a/i386/i386at/model_dep.c > +++ 
> b/i386/i386at/model_dep.c > @@ -229,6 +229,11 @@ void machine_init(void) > */ 
> > gdt_descr_tmp.linear_base += apboot_addr; > apboot_jmp_offset += 
> apboot_addr; > + > + /* > + * Initialize the HPET > + */ > + hpet_init(); > 
> #endif > } > > -- > 2.43.0 > > > -- Samuel --- Pour une évaluation 
> indépendante, transparente et rigoureuse ! Je soutiens la Commission 
> d'Évaluation de l'Inria.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]