summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2024-06-23 15:37:32 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2024-06-23 15:37:32 +0000
commit2b32552445a970cb4c7d1a30f48cf53142c00cde (patch)
tree07da3a37f1dcc28aa864ca250ef56d1a36c1aeea
parent0b318f608de39db5ec5389f2794b0fcb281666e3 (diff)
Add support for ACPI firmware that provides the base address of individual
GIC redistributors in the per-CPU GIC MADT table entries. ok patrick@
-rw-r--r--sys/arch/arm64/stand/efiboot/conf.c4
-rw-r--r--sys/arch/arm64/stand/efiboot/efiacpi.c36
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 <kettenis@openbsd.org>
@@ -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");
}