Files
vystem-b/docs/shelter/irq/gsi.md
2026-05-27 19:34:54 +02:00

3.4 KiB

GSI subsystem

Introduction

This subsystem is responsible for registering all the interrupts sources overrides (ISO) and providing an abstraction to manipulate all the GSI lines and legacy IRQs.

ISOs registering

The subsystem can be initialized using sh_gsi_iso_array_init(). This allocate an array of 256 sh_gsi_ISO in which all the ISOs will be stored.

The ISO struct is the following:

typedef struct {
  sh_uint32 gsi;
  sh_bool valid;
  sh_uint8 source_irq;
  enum sh_gsi_POLARITY polarity;
  enum sh_gsi_TRIGGER_MODE trigger_mode;
  sh_uint8 bus;
} sh_gsi_ISO;

Any sh_gsi_ISO without the valid boolean to SH_TRUE should be considered as not occupied in the array.

The sh_gsi_POLARITY enum can take the following values:

enum sh_gsi_POLARITY {
  SH_GSI_POLARITY_NOT_SET=0,
  SH_GSI_POLARITY_BUS_DEFAULT,
  SH_GSI_POLARITY_ACTIVE_HIGH,
  SH_GSI_POLARITY_ACTIVE_LOW
};

The sh_gsi_TRIGGER_MODE enum can take the following values:

enum sh_gsi_TRIGGER_MODE {
  SH_GSI_TRIGGER_MODE_NOT_SET=0,
  SH_GSI_TRIGGER_MODE_BUS_DEFAULT,
  SH_GSI_TRIGGER_MODE_EDGE,
  SH_GSI_TRIGGER_MODE_LEVEL
};

Bus defaults are resolved when configuring the IOREDTBL of each IOAPIC.

During the MADT table parsing, ISOs are registered using the sh_gsi_iso_register(sh_uint8 bus,sh_uint8 source,sh_uint32 gsi,sh_uint16 flags) function, which expects the arguments as they are parsed in the MADT table.

Two functions can be used to search for ISOs:

  • sh_gsi_get_iso_by_irq(sh_uint8 irq): return a *sh_gsi_ISO with the provided legacy IRQ number. Return SH_NULLPTR if not found or error
  • sh_gsi_get_iso_by_gsi(sh_uint32 gsi): return a *sh_gsi_ISO with the provided GSI number. Return SH_NULLPTR if not found or error

IOAPIC abstraction

The GSI subsystem provides an abstraction to manipulate IOREDTBL entries based on the GSI or legacy IRQ number without interacting directly with the IOAPIC subsystem. The following functions are provided:

  • sh_gsi_get(sh_uint32 gsi,sh_ioapic_IOREDTBL_ENTRY *entry): return the IOREDTBL entry corresponding to the provided GSI
  • sh_gsi_set(sh_uint32 gsi,sh_ioapic_IOREDTBL_ENTRY *entry): set the IOREDTBL entry corresponding to the provided GSI with the provided entry. Automatically mask the IOREDTBL entry before writing the entry
  • sh_gsi_irq_set(sh_uint8 irq,sh_ioapic_IOREDTBL_ENTRY *entry): do the same as sh_gsi_set() but retrieves the original GSI before hand, taking into account registered ISOs
  • sh_gsi_mask(sh_uint32 gsi): mask the IOREDTBL entry corresponding to the provided GSI
  • sh_gsi_unmask(sh_uint32 gsi): unmask the IOREDTBL entry corresponding to the provided GSI
  • sh_gsi_irq_mask(sh_uint8 irq): do the same as sh_gsi_mask() but retrieves the original GSI before hand, taking into account registered ISOs
  • sh_gsi_irq_unmask(sh_uint8 irq): do the same as sh_gsi_unmask() but retrieves the original GSI before hand, taking into account registered ISOs

Legacy IRQs switch

What we call the legacy IRQs switch is the mapping of all the legacy IRQs to interrupt vectors 32 to 47, exactly like the PIT, and the transfer of legacy IRQs management from the PIT to the IOAPIC.

It's operated by sh_gsi_irq_switch(). This is the only function that is allowed to call sh_irq_switch_irq_management(). By default, all the IOREDTBL entries corresponding to the GSI lines used by all legacy IRQs will be mask.