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