The branch main has been updated by andrew:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=1ecf7d5b38319d110d0f5bff26d6f8a9c1042cf4

commit 1ecf7d5b38319d110d0f5bff26d6f8a9c1042cf4
Author:     Andrew Turner <[email protected]>
AuthorDate: 2026-05-13 10:41:17 +0000
Commit:     Andrew Turner <[email protected]>
CommitDate: 2026-08-26 11:17:18 +0000

    arm64: vmm: Split out VGIC register handling to a common file
    
    Reviewed by:    Sarah Walker <[email protected]>
    Sponsored by:   Arm Ltd
---
 sys/arm64/vmm/io/vgic.c          |  79 +++++++++++++++++++++-
 sys/arm64/vmm/io/vgic_internal.h |  49 ++++++++++++++
 sys/arm64/vmm/io/vgic_v3.c       | 137 +++------------------------------------
 3 files changed, 136 insertions(+), 129 deletions(-)

diff --git a/sys/arm64/vmm/io/vgic.c b/sys/arm64/vmm/io/vgic.c
index ee841292ed33..582280823f1e 100644
--- a/sys/arm64/vmm/io/vgic.c
+++ b/sys/arm64/vmm/io/vgic.c
@@ -1,7 +1,7 @@
 /*-
  * SPDX-License-Identifier: BSD-2-Clause
  *
- * Copyright (c) 2023 Arm Ltd
+ * Copyright (c) 2023,2026 Arm Ltd
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -32,9 +32,86 @@
 
 #include "vgic.h"
 #include "vgic_if.h"
+#include "vgic_internal.h"
 
 device_t vgic_dev;
 
+/* Common register read-only/write-ignored helpers */
+void
+vgic_zero_read(struct hypctx *hypctx, u_int reg, uint64_t *rval,
+    void *arg)
+{
+       *rval = 0;
+}
+
+void
+vgic_ignore_write(struct hypctx *hypctx, u_int reg, u_int offset, u_int size,
+    uint64_t wval, void *arg)
+{
+       /* Nothing to do */
+}
+
+bool
+vgic_register_read(struct hypctx *hypctx, struct vgic_register *reg_list,
+    u_int reg_list_size, u_int reg, u_int size, uint64_t *rval, void *arg)
+{
+       u_int i, offset;
+
+       for (i = 0; i < reg_list_size; i++) {
+               if (reg_list[i].start <= reg && reg_list[i].end >= reg + size) {
+                       offset = reg & (reg_list[i].size - 1);
+                       reg -= offset;
+                       if ((reg_list[i].flags & size) != 0) {
+                               reg_list[i].read(hypctx, reg, rval, NULL);
+
+                               /* Move the bits into the correct place */
+                               *rval >>= (offset * 8);
+                               if (size < 8) {
+                                       *rval &= (1ul << (size * 8)) - 1;
+                               }
+                       } else {
+                               /*
+                                * The access is an invalid size. Section
+                                * 12.1.3 "GIC memory-mapped register access"
+                                * of the GICv3 and GICv4 spec issue H
+                                * (IHI0069) lists the options. For a read
+                                * the controller returns unknown data, in
+                                * this case it is zero.
+                                */
+                               *rval = 0;
+                       }
+                       return (true);
+               }
+       }
+       return (false);
+}
+
+bool
+vgic_register_write(struct hypctx *hypctx, struct vgic_register *reg_list,
+    u_int reg_list_size, u_int reg, u_int size, uint64_t wval, void *arg)
+{
+       u_int i, offset;
+
+       for (i = 0; i < reg_list_size; i++) {
+               if (reg_list[i].start <= reg && reg_list[i].end >= reg + size) {
+                       offset = reg & (reg_list[i].size - 1);
+                       reg -= offset;
+                       if ((reg_list[i].flags & size) != 0) {
+                               reg_list[i].write(hypctx, reg, offset,
+                                   size, wval, NULL);
+                       } else {
+                               /*
+                                * See the comment in vgic_register_read.
+                                * For writes the controller ignores the
+                                * operation.
+                                */
+                       }
+                       return (true);
+               }
+       }
+       return (false);
+}
+
 bool
 vgic_present(void)
 {
diff --git a/sys/arm64/vmm/io/vgic_internal.h b/sys/arm64/vmm/io/vgic_internal.h
index 2f5cfc7c0891..2f47aef50724 100644
--- a/sys/arm64/vmm/io/vgic_internal.h
+++ b/sys/arm64/vmm/io/vgic_internal.h
@@ -80,4 +80,53 @@ struct vgic_v3_cpu {
        u_int           ich_lr_used;
 };
 
+typedef void (register_read)(struct hypctx *, u_int, uint64_t *, void *);
+typedef void (register_write)(struct hypctx *, u_int, u_int, u_int,
+    uint64_t, void *);
+
+register_read vgic_zero_read;
+register_write vgic_ignore_write;
+
+#define        VGIC_8_BIT      (1 << 0)
+/* (1 << 1) is reserved for 16 bit accesses */
+#define        VGIC_32_BIT     (1 << 2)
+#define        VGIC_64_BIT     (1 << 3)
+
+struct vgic_register {
+       u_int start;    /* Start within a memory region */
+       u_int end;
+       u_int size;
+       u_int flags;
+       register_read *read;
+       register_write *write;
+};
+
+#define        VGIC_REGISTER_RANGE(reg_start, reg_end, reg_size, reg_flags, 
readf, \
+    writef)                                                            \
+{                                                                      \
+       .start = (reg_start),                                           \
+       .end = (reg_end),                                               \
+       .size = (reg_size),                                             \
+       .flags = (reg_flags),                                           \
+       .read = (readf),                                                \
+       .write = (writef),                                              \
+}
+
+#define        VGIC_REGISTER_RANGE_RAZ_WI(reg_start, reg_end, reg_size, 
reg_flags) \
+       VGIC_REGISTER_RANGE(reg_start, reg_end, reg_size, reg_flags,    \
+           vgic_zero_read, vgic_ignore_write)
+
+#define        VGIC_REGISTER(start_addr, reg_size, reg_flags, readf, writef)   
\
+       VGIC_REGISTER_RANGE(start_addr, (start_addr) + (reg_size),      \
+           reg_size, reg_flags, readf, writef)
+
+#define        VGIC_REGISTER_RAZ_WI(start_addr, reg_size, reg_flags)           
\
+       VGIC_REGISTER_RANGE_RAZ_WI(start_addr,                          \
+           (start_addr) + (reg_size), reg_size, reg_flags)
+
+bool vgic_register_read(struct hypctx *, struct vgic_register *, u_int, u_int,
+    u_int, uint64_t *, void *);
+bool vgic_register_write(struct hypctx *, struct vgic_register *, u_int, u_int,
+    u_int, uint64_t, void *);
+
 #endif /* _VGIC_INTERNAL_H_ */
diff --git a/sys/arm64/vmm/io/vgic_v3.c b/sys/arm64/vmm/io/vgic_v3.c
index 763267a2a3c8..ff7a2a9a761f 100644
--- a/sys/arm64/vmm/io/vgic_v3.c
+++ b/sys/arm64/vmm/io/vgic_v3.c
@@ -107,50 +107,7 @@ static int vgic_v3_max_cpu_count(device_t dev, struct hyp 
*hyp);
 #define        INJECT_IRQ(hyp, vcpuid, irqid, level)                   \
     vgic_v3_inject_irq(NULL, (hyp), (vcpuid), (irqid), (level))
 
-typedef void (register_read)(struct hypctx *, u_int, uint64_t *, void *);
-typedef void (register_write)(struct hypctx *, u_int, u_int, u_int,
-    uint64_t, void *);
-
-#define        VGIC_8_BIT      (1 << 0)
-/* (1 << 1) is reserved for 16 bit accesses */
-#define        VGIC_32_BIT     (1 << 2)
-#define        VGIC_64_BIT     (1 << 3)
-
-struct vgic_register {
-       u_int start;    /* Start within a memory region */
-       u_int end;
-       u_int size;
-       u_int flags;
-       register_read *read;
-       register_write *write;
-};
-
-#define        VGIC_REGISTER_RANGE(reg_start, reg_end, reg_size, reg_flags, 
readf, \
-    writef)                                                            \
-{                                                                      \
-       .start = (reg_start),                                           \
-       .end = (reg_end),                                               \
-       .size = (reg_size),                                             \
-       .flags = (reg_flags),                                           \
-       .read = (readf),                                                \
-       .write = (writef),                                              \
-}
-
-#define        VGIC_REGISTER_RANGE_RAZ_WI(reg_start, reg_end, reg_size, 
reg_flags) \
-       VGIC_REGISTER_RANGE(reg_start, reg_end, reg_size, reg_flags,    \
-           gic_zero_read, gic_ignore_write)
-
-#define        VGIC_REGISTER(start_addr, reg_size, reg_flags, readf, writef)   
\
-       VGIC_REGISTER_RANGE(start_addr, (start_addr) + (reg_size),      \
-           reg_size, reg_flags, readf, writef)
-
-#define        VGIC_REGISTER_RAZ_WI(start_addr, reg_size, reg_flags)           
\
-       VGIC_REGISTER_RANGE_RAZ_WI(start_addr,                          \
-           (start_addr) + (reg_size), reg_size, reg_flags)
-
 static register_read gic_pidr2_read;
-static register_read gic_zero_read;
-static register_write gic_ignore_write;
 
 /* GICD_CTLR */
 static register_read dist_ctlr_read;
@@ -203,13 +160,13 @@ static struct vgic_register dist_registers[] = {
        VGIC_REGISTER(GICD_CTLR, 4, VGIC_32_BIT, dist_ctlr_read,
            dist_ctlr_write),
        VGIC_REGISTER(GICD_TYPER, 4, VGIC_32_BIT, dist_typer_read,
-           gic_ignore_write),
+           vgic_ignore_write),
        VGIC_REGISTER(GICD_IIDR, 4, VGIC_32_BIT, dist_iidr_read,
-           gic_ignore_write),
+           vgic_ignore_write),
        VGIC_REGISTER_RAZ_WI(GICD_STATUSR, 4, VGIC_32_BIT),
-       VGIC_REGISTER(GICD_SETSPI_NSR, 4, VGIC_32_BIT, gic_zero_read,
+       VGIC_REGISTER(GICD_SETSPI_NSR, 4, VGIC_32_BIT, vgic_zero_read,
            dist_setclrspi_nsr_write),
-       VGIC_REGISTER(GICD_CLRSPI_NSR, 4, VGIC_32_BIT, gic_zero_read,
+       VGIC_REGISTER(GICD_CLRSPI_NSR, 4, VGIC_32_BIT, vgic_zero_read,
            dist_setclrspi_nsr_write),
        VGIC_REGISTER_RAZ_WI(GICD_SETSPI_SR, 4, VGIC_32_BIT),
        VGIC_REGISTER_RAZ_WI(GICD_CLRSPI_SR, 4, VGIC_32_BIT),
@@ -273,7 +230,7 @@ static struct vgic_register dist_registers[] = {
 
        VGIC_REGISTER_RANGE_RAZ_WI(GICD_PIDR4, GICD_PIDR2, 4, VGIC_32_BIT),
        VGIC_REGISTER(GICD_PIDR2, 4, VGIC_32_BIT, gic_pidr2_read,
-           gic_ignore_write),
+           vgic_ignore_write),
        VGIC_REGISTER_RANGE_RAZ_WI(GICD_PIDR2 + 4, GICD_SIZE, 4, VGIC_32_BIT),
 };
 
@@ -295,11 +252,11 @@ static register_read redist_typer_read;
 
 static struct vgic_register redist_rd_registers[] = {
        VGIC_REGISTER(GICR_CTLR, 4, VGIC_32_BIT, redist_ctlr_read,
-           gic_ignore_write),
+           vgic_ignore_write),
        VGIC_REGISTER(GICR_IIDR, 4, VGIC_32_BIT, redist_iidr_read,
-           gic_ignore_write),
+           vgic_ignore_write),
        VGIC_REGISTER(GICR_TYPER, 8, VGIC_64_BIT | VGIC_32_BIT,
-           redist_typer_read, gic_ignore_write),
+           redist_typer_read, vgic_ignore_write),
        VGIC_REGISTER_RAZ_WI(GICR_STATUSR, 4, VGIC_32_BIT),
        VGIC_REGISTER_RAZ_WI(GICR_WAKER, 4, VGIC_32_BIT),
        VGIC_REGISTER_RAZ_WI(GICR_SETLPIR, 8, VGIC_64_BIT | VGIC_32_BIT),
@@ -313,7 +270,7 @@ static struct vgic_register redist_rd_registers[] = {
        /* These are identical to the dist registers */
        VGIC_REGISTER_RANGE_RAZ_WI(GICD_PIDR4, GICD_PIDR2, 4, VGIC_32_BIT),
        VGIC_REGISTER(GICD_PIDR2, 4, VGIC_32_BIT, gic_pidr2_read,
-           gic_ignore_write),
+           vgic_ignore_write),
        VGIC_REGISTER_RANGE_RAZ_WI(GICD_PIDR2 + 4, GICD_SIZE, 4,
            VGIC_32_BIT),
 };
@@ -597,21 +554,6 @@ gic_pidr2_read(struct hypctx *hypctx, u_int reg, uint64_t 
*rval,
        *rval = GICR_PIDR2_ARCH_GICv3 << GICR_PIDR2_ARCH_SHIFT;
 }
 
-/* Common read-only/write-ignored helpers */
-static void
-gic_zero_read(struct hypctx *hypctx, u_int reg, uint64_t *rval,
-    void *arg)
-{
-       *rval = 0;
-}
-
-static void
-gic_ignore_write(struct hypctx *hypctx, u_int reg, u_int offset, u_int size,
-    uint64_t wval, void *arg)
-{
-       /* Nothing to do */
-}
-
 static uint64_t
 read_enabler(struct hypctx *hypctx, int n)
 {
@@ -1262,67 +1204,6 @@ dist_irouter_write(struct hypctx *hypctx, u_int reg, 
u_int offset, u_int size,
        write_route(hypctx, n, wval, offset, size);
 }
 
-static bool
-vgic_register_read(struct hypctx *hypctx, struct vgic_register *reg_list,
-    u_int reg_list_size, u_int reg, u_int size, uint64_t *rval, void *arg)
-{
-       u_int i, offset;
-
-       for (i = 0; i < reg_list_size; i++) {
-               if (reg_list[i].start <= reg && reg_list[i].end >= reg + size) {
-                       offset = reg & (reg_list[i].size - 1);
-                       reg -= offset;
-                       if ((reg_list[i].flags & size) != 0) {
-                               reg_list[i].read(hypctx, reg, rval, NULL);
-
-                               /* Move the bits into the correct place */
-                               *rval >>= (offset * 8);
-                               if (size < 8) {
-                                       *rval &= (1ul << (size * 8)) - 1;
-                               }
-                       } else {
-                               /*
-                                * The access is an invalid size. Section
-                                * 12.1.3 "GIC memory-mapped register access"
-                                * of the GICv3 and GICv4 spec issue H
-                                * (IHI0069) lists the options. For a read
-                                * the controller returns unknown data, in
-                                * this case it is zero.
-                                */
-                               *rval = 0;
-                       }
-                       return (true);
-               }
-       }
-       return (false);
-}
-
-static bool
-vgic_register_write(struct hypctx *hypctx, struct vgic_register *reg_list,
-    u_int reg_list_size, u_int reg, u_int size, uint64_t wval, void *arg)
-{
-       u_int i, offset;
-
-       for (i = 0; i < reg_list_size; i++) {
-               if (reg_list[i].start <= reg && reg_list[i].end >= reg + size) {
-                       offset = reg & (reg_list[i].size - 1);
-                       reg -= offset;
-                       if ((reg_list[i].flags & size) != 0) {
-                               reg_list[i].write(hypctx, reg, offset,
-                                   size, wval, NULL);
-                       } else {
-                               /*
-                                * See the comment in vgic_register_read.
-                                * For writes the controller ignores the
-                                * operation.
-                                */
-                       }
-                       return (true);
-               }
-       }
-       return (false);
-}
-
 static int
 dist_read(struct vcpu *vcpu, uint64_t fault_ipa, uint64_t *rval,
     int size, void *arg)

Reply via email to