From 3fe0bd1a994b92f835ed79b4c99bf1aab23ddbfb Mon Sep 17 00:00:00 2001 From: kettenis Date: Sun, 23 Jun 2024 15:37:31 +0000 Subject: [PATCH] Add support for ACPI firmware that provides the base address of individual GIC redistributors in the per-CPU GIC MADT table entries. ok patrick@ --- sys/arch/arm64/stand/efiboot/conf.c | 4 +-- sys/arch/arm64/stand/efiboot/efiacpi.c | 36 +++++++++++++++++++++++--- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/sys/arch/arm64/stand/efiboot/conf.c b/sys/arch/arm64/stand/efiboot/conf.c index a1174dc8b57..36090e2b77e 100644 --- a/sys/arch/arm64/stand/efiboot/conf.c +++ b/sys/arch/arm64/stand/efiboot/conf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: conf.c,v 1.48 2024/06/14 19:49:17 kettenis Exp $ */ +/* $OpenBSD: conf.c,v 1.49 2024/06/23 15:37:31 kettenis Exp $ */ /* * Copyright (c) 1996 Michael Shalayeff @@ -47,7 +47,7 @@ #include "efipxe.h" #include "softraid_arm64.h" -const char version[] = "1.19"; +const char version[] = "1.20"; int debug = 0; struct fs_ops file_system[] = { diff --git a/sys/arch/arm64/stand/efiboot/efiacpi.c b/sys/arch/arm64/stand/efiboot/efiacpi.c index 889b6f430d0..6f593cba8e8 100644 --- a/sys/arch/arm64/stand/efiboot/efiacpi.c +++ b/sys/arch/arm64/stand/efiboot/efiacpi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: efiacpi.c,v 1.16 2023/10/09 22:05:27 patrick Exp $ */ +/* $OpenBSD: efiacpi.c,v 1.17 2024/06/23 15:37:31 kettenis Exp $ */ /* * Copyright (c) 2018 Mark Kettenis @@ -402,7 +402,8 @@ static int gic_version; static uint64_t gicc_base; static uint64_t gicd_base; static uint64_t gicr_base; -static uint32_t gicr_size; +static uint64_t gicr_size; +static uint64_t gicr_stride; void efi_acpi_madt_gicc(struct acpi_madt_gicc *gicc) @@ -436,6 +437,30 @@ efi_acpi_madt_gicc(struct acpi_madt_gicc *gicc) /* Stash GIC information. */ gicc_base = gicc->base_address; + + /* + * The redistributor base address may be specified per-CPU. + * In that case we will need to reconstruct the base, size and + * stride to use for the redistributor registers. + */ + if (gicc->gicr_base_address > 0) { + if (gicr_base > 0) { + uint32_t size; + + if (gicc->gicr_base_address < gicr_base) + size = gicr_base - gicc->gicr_base_address; + else + size = gicc->gicr_base_address - gicr_base; + if (gicr_stride == 0 || size < gicr_stride) + gicr_stride = size; + if (gicr_size == 0 || size > gicr_size) + gicr_size = size; + gicr_base = MIN(gicr_base, gicc->gicr_base_address); + } else { + gicr_base = gicc->gicr_base_address; + gicr_size = 0x20000; + } + } } void @@ -579,7 +604,7 @@ efi_acpi_madt(struct acpi_table_header *hdr) reg[0] = htobe64(gicd_base); reg[1] = htobe64(0x10000); reg[2] = htobe64(gicr_base); - reg[3] = htobe64(gicr_size); + reg[3] = htobe64(gicr_size + gicr_stride); break; default: return; @@ -589,6 +614,11 @@ efi_acpi_madt(struct acpi_table_header *hdr) node = fdt_find_node("/interrupt-controller"); fdt_node_set_string_property(node, "compatible", compat); fdt_node_set_property(node, "reg", reg, sizeof(reg)); + if (gicr_stride > 0) { + uint64_t stride = htobe64(gicr_stride); + fdt_node_add_property(node, "redistributor-stride", + &stride, sizeof(stride)); + } fdt_node_set_string_property(node, "status", "okay"); } -- 2.20.1