arm64: Discover GICv2 from ACPI.
Change-Id: I89f2968a756d767f3a88c002292696a725a00918 Reviewed-on: https://review.haiku-os.org/c/haiku/+/5275 Tested-by: Commit checker robot <[email protected]> Reviewed-by: Adrien Destugues <[email protected]>
This commit is contained in:
@@ -65,7 +65,12 @@ enum {
|
||||
ACPI_MADT_LOCAL_SAPIC = 7,
|
||||
ACPI_MADT_PLATFORM_INTERRUPT_SOURCE = 8,
|
||||
ACPI_MADT_PROCESSOR_LOCAL_X2_APIC_NMI = 9,
|
||||
ACPI_MADT_LOCAL_X2_APIC_NMI = 0XA
|
||||
ACPI_MADT_LOCAL_X2_APIC_NMI = 0xA,
|
||||
ACPI_MADT_GIC_INTERFACE = 0xB,
|
||||
ACPI_MADT_GIC_DISTRIBUTOR = 0xC,
|
||||
ACPI_MADT_GIC_MSI_FRAME = 0xD,
|
||||
ACPI_MADT_GIC_REDISTRIBUTOR = 0xE,
|
||||
ACPI_MADT_GIC_ITS = 0xF
|
||||
};
|
||||
|
||||
typedef struct acpi_apic {
|
||||
@@ -203,6 +208,38 @@ typedef struct acpi_local_x2_apic_nmi {
|
||||
uint8 reserved3; /* reserved (must be set to zero) */
|
||||
} _PACKED acpi_local_x2_apic_nmi;
|
||||
|
||||
typedef struct acpi_gic_interface {
|
||||
uint8 type;
|
||||
uint8 length;
|
||||
uint16 reserved1;
|
||||
uint32 cpu_interface_num;
|
||||
uint32 acpi_processor_uid;
|
||||
uint32 flags;
|
||||
uint32 parking_protocol_ver;
|
||||
uint32 performance_gsiv;
|
||||
uint64 parked_address;
|
||||
uint64 base_address;
|
||||
uint64 gicv_address;
|
||||
uint64 gich_address;
|
||||
uint32 vgic_maintenance_gsiv;
|
||||
uint64 gicr_address;
|
||||
uint64 mpidr;
|
||||
uint8 efficiency_class;
|
||||
uint8 reserved2;
|
||||
uint16 spe_overflow_gsiv;
|
||||
} _PACKED acpi_gic_interface;
|
||||
|
||||
typedef struct acpi_gic_distributor {
|
||||
uint8 type;
|
||||
uint8 length;
|
||||
uint16 reserved1;
|
||||
uint32 gic_id;
|
||||
uint64 base_address;
|
||||
uint32 reserved2;
|
||||
uint8 gic_version;
|
||||
uint8 reserved[3];
|
||||
} _PACKED acpi_gic_distributor;
|
||||
|
||||
typedef struct acpi_gas {
|
||||
uint8 address_space_id;
|
||||
uint8 bit_width;
|
||||
|
||||
@@ -49,4 +49,35 @@ arch_handle_acpi()
|
||||
dprintf("discovered uart from acpi: base=%lx, irq=%u, clock=%lu\n",
|
||||
uart.regs.start, uart.irq, uart.clock);
|
||||
}
|
||||
|
||||
acpi_madt *madt = (acpi_madt*)acpi_find_table(ACPI_MADT_SIGNATURE);
|
||||
if (madt != NULL) {
|
||||
uint64 gicc_base = 0;
|
||||
uint64 gicd_base = 0;
|
||||
uint8 version = 0;
|
||||
|
||||
acpi_apic *desc = (acpi_apic*)(madt + 1);
|
||||
while (desc != (acpi_apic*)((char*)madt + madt->header.length)) {
|
||||
if (desc->type == ACPI_MADT_GIC_INTERFACE) {
|
||||
acpi_gic_interface *acpi_gicc = (acpi_gic_interface*)desc;
|
||||
if (acpi_gicc->cpu_interface_num == 0)
|
||||
gicc_base = acpi_gicc->base_address;
|
||||
} else if (desc->type == ACPI_MADT_GIC_DISTRIBUTOR) {
|
||||
acpi_gic_distributor *acpi_gicd = (acpi_gic_distributor*)desc;
|
||||
gicd_base = acpi_gicd->base_address;
|
||||
version = acpi_gicd->gic_version;
|
||||
}
|
||||
desc = (acpi_apic*)((char*)desc + desc->length);
|
||||
}
|
||||
|
||||
if (version == 2 && gicc_base != 0 && gicd_base != 0) {
|
||||
intc_info &intc = gKernelArgs.arch_args.interrupt_controller;
|
||||
strcpy(intc.kind, INTC_KIND_GICV2);
|
||||
intc.regs1.start = gicd_base;
|
||||
intc.regs2.start = gicc_base;
|
||||
|
||||
dprintf("discovered gic from acpi: version=%d, gicd=%lx, gicc=%lx\n",
|
||||
version, gicd_base, gicc_base);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user