On Tue, 26 May 2026 07:29:20 +0300
Leonid Bloch <[email protected]> wrote:

> This patch extends the GPE (General Purpose Event) handling to support
> the maximum number of interrupts available based on the machine's GPE
> register length, rather than being limited to the first 8 bits.
> 
> This change is needed to support additional ACPI devices that will be
> introduced in subsequent patches (Battery, AC adapter, and button devices).
> These new devices require GPE event bits beyond the first 8, which were
> previously not being properly handled by the event sending and SCI
> (System Control Interrupt) update mechanisms.
> 
> The actual number of available GPE interrupts varies by machine type:
> - PIIX4: GPE_LEN = 4 (32 bits total across status and enable registers)
> - ICH9: ICH9_PMIO_GPE0_LEN = 16 (128 bits total)
> 
> The patch modifies:
> - acpi_send_gpe_event(): Now properly propagates status bits across all
>   available GPE registers based on the machine's gpe.len value
> - acpi_update_sci(): Checks all GPE registers for pending interrupts,
>   not just the first byte
> 
> Note: A future enhancement could refactor the GPE handling to use the
> bitmap API from bitops.h instead of the current manual bit manipulation,
> which would provide a cleaner interface for these operations.
> 
> Signed-off-by: Leonid Bloch <[email protected]>
> ---
>  hw/acpi/core.c | 17 +++++++++++++++--
>  1 file changed, 15 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/acpi/core.c b/hw/acpi/core.c
> index a6a62a742d..ad7abe568d 100644
> --- a/hw/acpi/core.c
> +++ b/hw/acpi/core.c
> @@ -733,19 +733,32 @@ uint32_t acpi_gpe_ioport_readb(ACPIREGS *ar, uint32_t 
> addr)
>  void acpi_send_gpe_event(ACPIREGS *ar, qemu_irq irq,
>                           AcpiEventStatusBits status)
>  {
> -    ar->gpe.sts[0] |= status;
> +    int i;
> +    AcpiEventStatusBits st = status;
> +
> +    for (i = 0; i < ar->gpe.len / 2; i++) {
> +        ar->gpe.sts[i] |= st;
> +        st >>= TYPE_WIDTH(ar->gpe.sts[0]);
> +    }

Function is ever called with only one bit set at a time.
I'd suggest to add assert to guard for multiple bits and
use existing bitops instead of open-codding the loop.

>      acpi_update_sci(ar, irq);
>  }
>  
>  void acpi_update_sci(ACPIREGS *regs, qemu_irq irq)
>  {
>      int sci_level, pm1a_sts;
> +    bool gpe_sci = false;
> +    int i;
>  
>      pm1a_sts = acpi_pm1_evt_get_sts(regs);
>  
> +    for (i = 0; i < regs->gpe.len / 2; i++) {
> +        gpe_sci = gpe_sci || !!(regs->gpe.sts[i] & regs->gpe.en[i]);
> +    }
> +
>      sci_level = ((pm1a_sts &
>                    regs->pm1.evt.en & ACPI_BITMASK_PM1_COMMON_ENABLED) != 0) 
> ||
> -                ((regs->gpe.sts[0] & regs->gpe.en[0]) != 0);
> +                gpe_sci;
>  
>      qemu_set_irq(irq, sci_level);
>  


Reply via email to