Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/1.1/patches/2231730/?format=api
{ "id": 2231730, "url": "http://patchwork.ozlabs.org/api/1.1/patches/2231730/?format=api", "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260501101505.3485916-15-peter.maydell@linaro.org/", "project": { "id": 14, "url": "http://patchwork.ozlabs.org/api/1.1/projects/14/?format=api", "name": "QEMU Development", "link_name": "qemu-devel", "list_id": "qemu-devel.nongnu.org", "list_email": "qemu-devel@nongnu.org", "web_url": "", "scm_url": "", "webscm_url": "" }, "msgid": "<20260501101505.3485916-15-peter.maydell@linaro.org>", "date": "2026-05-01T10:14:51", "name": "[PULL,14/28] hw/intc: Add hvf vGIC interrupt controller support", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "923ee6b817cde366e2716bd1a93457fef75ff7c5", "submitter": { "id": 5111, "url": "http://patchwork.ozlabs.org/api/1.1/people/5111/?format=api", "name": "Peter Maydell", "email": "peter.maydell@linaro.org" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/qemu-devel/patch/20260501101505.3485916-15-peter.maydell@linaro.org/mbox/", "series": [ { "id": 502437, "url": "http://patchwork.ozlabs.org/api/1.1/series/502437/?format=api", "web_url": "http://patchwork.ozlabs.org/project/qemu-devel/list/?series=502437", "date": "2026-05-01T10:14:41", "name": "[PULL,01/28] hw/arm/fsl-imx8mp: Do not create redundant unimplemented devices", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/502437/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2231730/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2231730/checks/", "tags": {}, "headers": { "Return-Path": "<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>", "X-Original-To": "incoming@patchwork.ozlabs.org", "Delivered-To": "patchwork-incoming@legolas.ozlabs.org", "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=linaro.org header.i=@linaro.org header.a=rsa-sha256\n header.s=google header.b=kF5XHJtf;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org\n (client-ip=209.51.188.17; helo=lists1p.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=patchwork.ozlabs.org)" ], "Received": [ "from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17])\n\t(using TLSv1.2 with cipher ECDHE-ECDSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4g6RnR5q3Jz1yJv\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 01 May 2026 20:18:03 +1000 (AEST)", "from localhost ([::1] helo=lists1p.gnu.org)\n\tby lists1p.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces@nongnu.org>)\n\tid 1wIkuJ-00043O-Tg; Fri, 01 May 2026 06:15:39 -0400", "from eggs.gnu.org ([2001:470:142:3::10])\n by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <peter.maydell@linaro.org>)\n id 1wIkuD-00040n-93\n for qemu-devel@nongnu.org; Fri, 01 May 2026 06:15:34 -0400", "from mail-wm1-x32f.google.com ([2a00:1450:4864:20::32f])\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128)\n (Exim 4.90_1) (envelope-from <peter.maydell@linaro.org>)\n id 1wIku9-0000B9-LZ\n for qemu-devel@nongnu.org; Fri, 01 May 2026 06:15:33 -0400", "by mail-wm1-x32f.google.com with SMTP id\n 5b1f17b1804b1-48984d29fe3so26211845e9.0\n for <qemu-devel@nongnu.org>; Fri, 01 May 2026 03:15:28 -0700 (PDT)", "from lanath.. (wildly.archaic.org.uk. [81.2.115.145])\n by smtp.gmail.com with ESMTPSA id\n 5b1f17b1804b1-48a8fede418sm12863335e9.6.2026.05.01.03.15.26\n for <qemu-devel@nongnu.org>\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Fri, 01 May 2026 03:15:26 -0700 (PDT)" ], "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=linaro.org; s=google; t=1777630527; x=1778235327; darn=nongnu.org;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:to:from:from:to:cc:subject:date:message-id\n :reply-to; bh=VHYQ3sEbHhf9JiOzweo2r0DAPn1IB5i37+wIDFmfga4=;\n b=kF5XHJtf9eeCUKqRKp8wtqzBfgRkbk31Qmb/koTVCMF83YzNqK4jqvIlAyxt6rrpKE\n dC0znY7lYQ6n4x+repolLJ9r6Vwc3KxmYt+GqHnjB+jtM2tDqZVIpugmmwgojn+MbkQs\n XRu+PYukF55GRDnJ6ZxR2TmP9Np1VNqTD4RgtuR6OGrPJqxxkPmbFQvtORKNSc++hhpA\n 5z1DI6vDNe+Ykv7rqY7x5fIYVMUNFYJeuIeUMmUVknej5S5YAj2lHwW3nJwJhzx8IlXA\n W8NxLKbJ6g0l/3D6eniDxYoiMugfDc2Oi6+wQDmq/amjeK5Ofaub/9WLW9EcGeKn72JF\n 4nfA==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1777630527; x=1778235327;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:to:from:x-gm-gg:x-gm-message-state:from:to\n :cc:subject:date:message-id:reply-to;\n bh=VHYQ3sEbHhf9JiOzweo2r0DAPn1IB5i37+wIDFmfga4=;\n b=AplfQqd9D9ZKy/Tm3DWfUFVmIA9i9ahZkLfXrssCdg6bo4e7/hGHv6N3ET3hkyPOnn\n pxQQ/6QuUHZPlD/ja2md8P+8U2MwMcg6b+7vtPCQIpHGhYZvgmD52em1ffqAyd7f3i9g\n W9E6kp6fE0iimecxj1FedFdZ0qL9kb3ZG07QYuZLfG5MCbVX4JwbCw3WUb0Igz9E7Cxo\n j/RZup9HnZ0Sz1TkKlkiopdWM2FYnmPXDRGJyKyQ6IxQHMqICgjyI6kj2WNL6cj3oK6v\n RrjT287Ajo3dS87AyaabfgCyUi3J0Cf/mAEmQvZoog902VVnZfEEpzoa6BrFU7mAYY6O\n dT3Q==", "X-Gm-Message-State": "AOJu0Yzqx/yFDbgyTtExw5/SuBxU/F7sAVYT6/j2c+PMHSWZDSL/JZLo\n MUlb3KkJrqlTjDgtoyzeFs3Q7ZCP5tjaHsXWB0RHlC3QcxefLx3D1OH3YH0YsIox3XwU1DJBEOF\n xpX2X", "X-Gm-Gg": "AeBDiev49e0y/4sGetVhWx4iY20MudL7Ks6maKdKv9Hdoh9DkgPDIVhwRen6XyZbXXF\n UdeCo7KY8MZyvucczhxw0Kf945zNF6QHq9D1IUjn/ZcGrrkdArGX9TwpDzQIbTo3CHCL3XGXV3W\n xmYLTtsJR7D4BdhYASDlOAlBQJhALXy1NI9ldxbShdIJfK0KjelQxhzdEaQEW/jVK8N3Ob2o2Mb\n CSjloD+7g+g58TzjX9M5WgK2u4UGSbRaIel1rXj/M/o6ufvXWm14syg2dTWWq97eH9WJEtUSz5d\n A5jQazQa2DuwiESC4npKhBprQ3WNotl+aHH4lO5P5WaMGdyDA2tqt7lrLKqLKfjolpCCCtv8X5G\n 1pBnVk05sH9ojP97ALiTHH9SjjsjWb87WNE5UYN+rWNgwxcEPwcCOxeF3WI+s0n8oO6ZR5hYXFV\n G2v3yX/H6aSML9yO770mC/Ny1LXlw+tsi4rmCckr9YkcbkVWyamr56X+yLec080l6MH9qeCV81K\n s1jbtxrLfJLG2qKWDnbAd7qd2QqVh7quZWfX0+rL3XqMf7sO6Hq", "X-Received": "by 2002:a05:600c:4e16:b0:489:1f3e:5f6f with SMTP id\n 5b1f17b1804b1-48a83e73c23mr114823855e9.12.1777630527359;\n Fri, 01 May 2026 03:15:27 -0700 (PDT)", "From": "Peter Maydell <peter.maydell@linaro.org>", "To": "qemu-devel@nongnu.org", "Subject": "[PULL 14/28] hw/intc: Add hvf vGIC interrupt controller support", "Date": "Fri, 1 May 2026 11:14:51 +0100", "Message-ID": "<20260501101505.3485916-15-peter.maydell@linaro.org>", "X-Mailer": "git-send-email 2.43.0", "In-Reply-To": "<20260501101505.3485916-1-peter.maydell@linaro.org>", "References": "<20260501101505.3485916-1-peter.maydell@linaro.org>", "MIME-Version": "1.0", "Content-Type": "text/plain; charset=UTF-8", "Content-Transfer-Encoding": "8bit", "Received-SPF": "pass client-ip=2a00:1450:4864:20::32f;\n envelope-from=peter.maydell@linaro.org; helo=mail-wm1-x32f.google.com", "X-Spam_score_int": "-20", "X-Spam_score": "-2.1", "X-Spam_bar": "--", "X-Spam_report": "(-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1,\n DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1,\n RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001,\n SPF_PASS=-0.001 autolearn=ham autolearn_force=no", "X-Spam_action": "no action", "X-BeenThere": "qemu-devel@nongnu.org", "X-Mailman-Version": "2.1.29", "Precedence": "list", "List-Id": "qemu development <qemu-devel.nongnu.org>", "List-Unsubscribe": "<https://lists.nongnu.org/mailman/options/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>", "List-Archive": "<https://lists.nongnu.org/archive/html/qemu-devel>", "List-Post": "<mailto:qemu-devel@nongnu.org>", "List-Help": "<mailto:qemu-devel-request@nongnu.org?subject=help>", "List-Subscribe": "<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=subscribe>", "Errors-To": "qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org", "Sender": "qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org" }, "content": "From: Mohamed Mediouni <mohamed@unpredictable.fr>\n\nThis opens up the door to nested virtualisation support.\n\nSigned-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>\nReviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>\nReviewed-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org>\nMessage-id: 20260429190532.26538-2-mohamed@unpredictable.fr\nSigned-off-by: Peter Maydell <peter.maydell@linaro.org>\n---\n hw/intc/arm_gicv3_hvf.c | 749 +++++++++++++++++++++++++++++\n hw/intc/meson.build | 1 +\n include/hw/intc/arm_gicv3_common.h | 1 +\n 3 files changed, 751 insertions(+)\n create mode 100644 hw/intc/arm_gicv3_hvf.c", "diff": "diff --git a/hw/intc/arm_gicv3_hvf.c b/hw/intc/arm_gicv3_hvf.c\nnew file mode 100644\nindex 0000000000..22f19d274d\n--- /dev/null\n+++ b/hw/intc/arm_gicv3_hvf.c\n@@ -0,0 +1,749 @@\n+/* SPDX-License-Identifier: GPL-2.0-or-later */\n+/*\n+ * ARM Generic Interrupt Controller using HVF platform support\n+ *\n+ * Copyright (c) 2025 Mohamed Mediouni\n+ * Based on vGICv3 KVM code by Pavel Fedin\n+ *\n+ */\n+\n+#include \"qemu/osdep.h\"\n+#include \"qapi/error.h\"\n+#include \"hw/intc/arm_gicv3_common.h\"\n+#include \"qemu/error-report.h\"\n+#include \"qemu/module.h\"\n+#include \"system/runstate.h\"\n+#include \"system/hvf.h\"\n+#include \"system/hvf_int.h\"\n+#include \"hvf_arm.h\"\n+#include \"gicv3_internal.h\"\n+#include \"vgic_common.h\"\n+#include \"qom/object.h\"\n+#include \"target/arm/cpregs.h\"\n+#include <Hypervisor/Hypervisor.h>\n+\n+/*\n+ * For the GIC, override the check outright, as availability is checked\n+ * elsewhere\n+ */\n+#pragma clang diagnostic push\n+#pragma clang diagnostic ignored \"-Wunguarded-availability\"\n+\n+struct HVFARMGICv3Class {\n+ ARMGICv3CommonClass parent_class;\n+ DeviceRealize parent_realize;\n+ ResettablePhases parent_phases;\n+};\n+\n+typedef struct HVFARMGICv3Class HVFARMGICv3Class;\n+\n+/* This is reusing the GICv3State typedef from ARM_GICV3_ITS_COMMON */\n+DECLARE_OBJ_CHECKERS(GICv3State, HVFARMGICv3Class,\n+ HVF_GICV3, TYPE_HVF_GICV3);\n+\n+/*\n+ * Loop through each distributor IRQ related register; since bits\n+ * corresponding to SPIs and PPIs are RAZ/WI when affinity routing\n+ * is enabled, we skip those.\n+ */\n+#define for_each_dist_irq_reg(_irq, _max, _field_width) \\\n+ for (_irq = GIC_INTERNAL; _irq < _max; _irq += (32 / _field_width))\n+\n+/*\n+ * Wrap calls to the vGIC APIs to assert_hvf_ok()\n+ * as a macro to keep the code clean.\n+ */\n+#define hv_gic_get_distributor_reg(offset, reg) \\\n+ assert_hvf_ok(hv_gic_get_distributor_reg(offset, reg))\n+\n+#define hv_gic_set_distributor_reg(offset, reg) \\\n+ assert_hvf_ok(hv_gic_set_distributor_reg(offset, reg))\n+\n+#define hv_gic_get_redistributor_reg(vcpu, reg, value) \\\n+ assert_hvf_ok(hv_gic_get_redistributor_reg(vcpu, reg, value))\n+\n+#define hv_gic_set_redistributor_reg(vcpu, reg, value) \\\n+ assert_hvf_ok(hv_gic_set_redistributor_reg(vcpu, reg, value))\n+\n+#define hv_gic_get_icc_reg(vcpu, reg, value) \\\n+ assert_hvf_ok(hv_gic_get_icc_reg(vcpu, reg, value))\n+\n+#define hv_gic_set_icc_reg(vcpu, reg, value) \\\n+ assert_hvf_ok(hv_gic_set_icc_reg(vcpu, reg, value))\n+\n+#define hv_gic_get_ich_reg(vcpu, reg, value) \\\n+ assert_hvf_ok(hv_gic_get_ich_reg(vcpu, reg, value))\n+\n+#define hv_gic_set_ich_reg(vcpu, reg, value) \\\n+ assert_hvf_ok(hv_gic_set_ich_reg(vcpu, reg, value))\n+\n+static void hvf_dist_get_priority(GICv3State *s,\n+ hv_gic_distributor_reg_t offset,\n+ uint8_t *bmp)\n+{\n+ uint64_t reg;\n+ uint32_t *field;\n+ int irq;\n+ field = (uint32_t *)(bmp);\n+\n+ for_each_dist_irq_reg(irq, s->num_irq, 8) {\n+ hv_gic_get_distributor_reg(offset, ®);\n+ *field = reg;\n+ offset += 4;\n+ field++;\n+ }\n+}\n+\n+static void hvf_dist_put_priority(GICv3State *s,\n+ hv_gic_distributor_reg_t offset,\n+ uint8_t *bmp)\n+{\n+ uint32_t reg, *field;\n+ int irq;\n+ field = (uint32_t *)(bmp);\n+\n+ for_each_dist_irq_reg(irq, s->num_irq, 8) {\n+ reg = *field;\n+ hv_gic_set_distributor_reg(offset, reg);\n+ offset += 4;\n+ field++;\n+ }\n+}\n+\n+static void hvf_dist_get_edge_trigger(GICv3State *s,\n+ hv_gic_distributor_reg_t offset,\n+ uint32_t *bmp)\n+{\n+ uint64_t reg;\n+ int irq;\n+\n+ for_each_dist_irq_reg(irq, s->num_irq, 2) {\n+ hv_gic_get_distributor_reg(offset, ®);\n+ reg = half_unshuffle32(reg >> 1);\n+ if (irq % 32 != 0) {\n+ reg = (reg << 16);\n+ }\n+ *gic_bmp_ptr32(bmp, irq) |= reg;\n+ offset += 4;\n+ }\n+}\n+\n+static void hvf_dist_put_edge_trigger(GICv3State *s,\n+ hv_gic_distributor_reg_t offset,\n+ uint32_t *bmp)\n+{\n+ uint32_t reg;\n+ int irq;\n+\n+ for_each_dist_irq_reg(irq, s->num_irq, 2) {\n+ reg = *gic_bmp_ptr32(bmp, irq);\n+ if (irq % 32 != 0) {\n+ reg = (reg & 0xffff0000) >> 16;\n+ } else {\n+ reg = reg & 0xffff;\n+ }\n+ reg = half_shuffle32(reg) << 1;\n+ hv_gic_set_distributor_reg(offset, reg);\n+ offset += 4;\n+ }\n+}\n+\n+/* Read a bitmap register group from the kernel VGIC. */\n+static void hvf_dist_getbmp(GICv3State *s, hv_gic_distributor_reg_t offset,\n+ uint32_t *bmp)\n+{\n+ uint64_t reg;\n+ int irq;\n+\n+ for_each_dist_irq_reg(irq, s->num_irq, 1) {\n+ hv_gic_get_distributor_reg(offset, ®);\n+ *gic_bmp_ptr32(bmp, irq) = reg;\n+ offset += 4;\n+ }\n+}\n+\n+static void hvf_dist_putbmp(GICv3State *s, hv_gic_distributor_reg_t offset,\n+ hv_gic_distributor_reg_t clroffset, uint32_t *bmp)\n+{\n+ uint32_t reg;\n+ int irq;\n+\n+ for_each_dist_irq_reg(irq, s->num_irq, 1) {\n+ /*\n+ * If this bitmap is a set/clear register pair, first write to the\n+ * clear-reg to clear all bits before using the set-reg to write\n+ * the 1 bits.\n+ */\n+ if (clroffset != 0) {\n+ reg = 0;\n+ hv_gic_set_distributor_reg(clroffset, reg);\n+ clroffset += 4;\n+ }\n+ reg = *gic_bmp_ptr32(bmp, irq);\n+ hv_gic_set_distributor_reg(offset, reg);\n+ offset += 4;\n+ }\n+}\n+\n+static void hvf_gicv3_check(GICv3State *s)\n+{\n+ uint64_t reg;\n+ uint32_t num_irq;\n+\n+ /* Sanity checking s->num_irq */\n+ hv_gic_get_distributor_reg(HV_GIC_DISTRIBUTOR_REG_GICD_TYPER, ®);\n+ num_irq = ((reg & 0x1f) + 1) * 32;\n+\n+ if (num_irq < s->num_irq) {\n+ error_report(\"Model requests %u IRQs, but HVF supports max %u\",\n+ s->num_irq, num_irq);\n+ abort();\n+ }\n+}\n+\n+static void hvf_gicv3_put_cpu_el2(CPUState *cpu_state, run_on_cpu_data arg)\n+{\n+ int num_pri_bits;\n+\n+ /* Redistributor state */\n+ GICv3CPUState *c = arg.host_ptr;\n+ hv_vcpu_t vcpu = c->cpu->accel->fd;\n+\n+ hv_gic_set_ich_reg(vcpu, HV_GIC_ICH_REG_VMCR_EL2, c->ich_vmcr_el2);\n+ hv_gic_set_ich_reg(vcpu, HV_GIC_ICH_REG_HCR_EL2, c->ich_hcr_el2);\n+\n+ for (int i = 0; i < GICV3_LR_MAX; i++) {\n+ hv_gic_set_ich_reg(vcpu, HV_GIC_ICH_REG_LR0_EL2, c->ich_lr_el2[i]);\n+ }\n+\n+ num_pri_bits = c->vpribits;\n+\n+ switch (num_pri_bits) {\n+ case 7:\n+ hv_gic_set_ich_reg(vcpu, HV_GIC_ICH_REG_AP0R0_EL2 + 3,\n+ c->ich_apr[GICV3_G0][3]);\n+ hv_gic_set_ich_reg(vcpu, HV_GIC_ICH_REG_AP0R0_EL2 + 2,\n+ c->ich_apr[GICV3_G0][2]);\n+ /* fall through */\n+ case 6:\n+ hv_gic_set_ich_reg(vcpu, HV_GIC_ICH_REG_AP0R0_EL2 + 1,\n+ c->ich_apr[GICV3_G0][1]);\n+ /* fall through */\n+ default:\n+ hv_gic_set_ich_reg(vcpu, HV_GIC_ICH_REG_AP0R0_EL2,\n+ c->ich_apr[GICV3_G0][0]);\n+ }\n+\n+ switch (num_pri_bits) {\n+ case 7:\n+ hv_gic_set_ich_reg(vcpu, HV_GIC_ICH_REG_AP1R0_EL2 + 3,\n+ c->ich_apr[GICV3_G1NS][3]);\n+ hv_gic_set_ich_reg(vcpu, HV_GIC_ICH_REG_AP1R0_EL2 + 2,\n+ c->ich_apr[GICV3_G1NS][2]);\n+ /* fall through */\n+ case 6:\n+ hv_gic_set_ich_reg(vcpu, HV_GIC_ICH_REG_AP1R0_EL2 + 1,\n+ c->ich_apr[GICV3_G1NS][1]);\n+ /* fall through */\n+ default:\n+ hv_gic_set_ich_reg(vcpu, HV_GIC_ICH_REG_AP1R0_EL2,\n+ c->ich_apr[GICV3_G1NS][0]);\n+ }\n+}\n+\n+static void hvf_gicv3_put_cpu(CPUState *cpu_state, run_on_cpu_data arg)\n+{\n+ uint32_t reg;\n+ uint64_t reg64;\n+ int i, num_pri_bits;\n+\n+ /* Redistributor state */\n+ GICv3CPUState *c = arg.host_ptr;\n+ hv_vcpu_t vcpu = c->cpu->accel->fd;\n+\n+ reg = c->gicr_waker;\n+ hv_gic_set_redistributor_reg(vcpu, HV_GIC_REDISTRIBUTOR_REG_GICR_IGROUPR0, reg);\n+\n+ reg = c->gicr_igroupr0;\n+ hv_gic_set_redistributor_reg(vcpu, HV_GIC_REDISTRIBUTOR_REG_GICR_IGROUPR0, reg);\n+\n+ reg = ~0;\n+ hv_gic_set_redistributor_reg(vcpu, HV_GIC_REDISTRIBUTOR_REG_GICR_ICENABLER0, reg);\n+ reg = c->gicr_ienabler0;\n+ hv_gic_set_redistributor_reg(vcpu, HV_GIC_REDISTRIBUTOR_REG_GICR_ISENABLER0, reg);\n+\n+ /* Restore config before pending so we treat level/edge correctly */\n+ reg = half_shuffle32(c->edge_trigger >> 16) << 1;\n+ hv_gic_set_redistributor_reg(vcpu, HV_GIC_REDISTRIBUTOR_REG_GICR_ICFGR1, reg);\n+\n+ reg = ~0;\n+ hv_gic_set_redistributor_reg(vcpu, HV_GIC_REDISTRIBUTOR_REG_GICR_ICPENDR0, reg);\n+ reg = c->gicr_ipendr0;\n+ hv_gic_set_redistributor_reg(vcpu, HV_GIC_REDISTRIBUTOR_REG_GICR_ISPENDR0, reg);\n+\n+ reg = ~0;\n+ hv_gic_set_redistributor_reg(vcpu, HV_GIC_REDISTRIBUTOR_REG_GICR_ICACTIVER0, reg);\n+ reg = c->gicr_iactiver0;\n+ hv_gic_set_redistributor_reg(vcpu, HV_GIC_REDISTRIBUTOR_REG_GICR_ISACTIVER0, reg);\n+\n+ for (i = 0; i < GIC_INTERNAL; i += 4) {\n+ reg = c->gicr_ipriorityr[i] |\n+ (c->gicr_ipriorityr[i + 1] << 8) |\n+ (c->gicr_ipriorityr[i + 2] << 16) |\n+ (c->gicr_ipriorityr[i + 3] << 24);\n+ hv_gic_set_redistributor_reg(vcpu,\n+ HV_GIC_REDISTRIBUTOR_REG_GICR_IPRIORITYR0 + i, reg);\n+ }\n+\n+ /* CPU interface state */\n+ hv_gic_set_icc_reg(vcpu, HV_GIC_ICC_REG_SRE_EL1, c->icc_sre_el1);\n+\n+ hv_gic_set_icc_reg(vcpu, HV_GIC_ICC_REG_CTLR_EL1,\n+ c->icc_ctlr_el1[GICV3_NS]);\n+ hv_gic_set_icc_reg(vcpu, HV_GIC_ICC_REG_IGRPEN0_EL1,\n+ c->icc_igrpen[GICV3_G0]);\n+ hv_gic_set_icc_reg(vcpu, HV_GIC_ICC_REG_IGRPEN1_EL1,\n+ c->icc_igrpen[GICV3_G1NS]);\n+ hv_gic_set_icc_reg(vcpu, HV_GIC_ICC_REG_PMR_EL1, c->icc_pmr_el1);\n+ hv_gic_set_icc_reg(vcpu, HV_GIC_ICC_REG_BPR0_EL1, c->icc_bpr[GICV3_G0]);\n+ hv_gic_set_icc_reg(vcpu, HV_GIC_ICC_REG_BPR1_EL1, c->icc_bpr[GICV3_G1NS]);\n+\n+ num_pri_bits = ((c->icc_ctlr_el1[GICV3_NS] &\n+ ICC_CTLR_EL1_PRIBITS_MASK) >>\n+ ICC_CTLR_EL1_PRIBITS_SHIFT) + 1;\n+\n+ switch (num_pri_bits) {\n+ case 7:\n+ reg64 = c->icc_apr[GICV3_G0][3];\n+ hv_gic_set_icc_reg(vcpu, HV_GIC_ICC_REG_AP0R0_EL1 + 3, reg64);\n+ reg64 = c->icc_apr[GICV3_G0][2];\n+ hv_gic_set_icc_reg(vcpu, HV_GIC_ICC_REG_AP0R0_EL1 + 2, reg64);\n+ /* fall through */\n+ case 6:\n+ reg64 = c->icc_apr[GICV3_G0][1];\n+ hv_gic_set_icc_reg(vcpu, HV_GIC_ICC_REG_AP0R0_EL1 + 1, reg64);\n+ /* fall through */\n+ default:\n+ reg64 = c->icc_apr[GICV3_G0][0];\n+ hv_gic_set_icc_reg(vcpu, HV_GIC_ICC_REG_AP0R0_EL1, reg64);\n+ }\n+\n+ switch (num_pri_bits) {\n+ case 7:\n+ reg64 = c->icc_apr[GICV3_G1NS][3];\n+ hv_gic_set_icc_reg(vcpu, HV_GIC_ICC_REG_AP1R0_EL1 + 3, reg64);\n+ reg64 = c->icc_apr[GICV3_G1NS][2];\n+ hv_gic_set_icc_reg(vcpu, HV_GIC_ICC_REG_AP1R0_EL1 + 2, reg64);\n+ /* fall through */\n+ case 6:\n+ reg64 = c->icc_apr[GICV3_G1NS][1];\n+ hv_gic_set_icc_reg(vcpu, HV_GIC_ICC_REG_AP1R0_EL1 + 1, reg64);\n+ /* fall through */\n+ default:\n+ reg64 = c->icc_apr[GICV3_G1NS][0];\n+ hv_gic_set_icc_reg(vcpu, HV_GIC_ICC_REG_AP1R0_EL1, reg64);\n+ }\n+\n+ /* Registers beyond this point are with nested virt only */\n+ if (c->gic->maint_irq) {\n+ hvf_gicv3_put_cpu_el2(cpu_state, arg);\n+ }\n+}\n+\n+static void hvf_gicv3_put(GICv3State *s)\n+{\n+ uint32_t reg;\n+ int ncpu, i;\n+\n+ hvf_gicv3_check(s);\n+\n+ reg = s->gicd_ctlr;\n+ hv_gic_set_distributor_reg(HV_GIC_DISTRIBUTOR_REG_GICD_CTLR, reg);\n+\n+ /* per-CPU state */\n+\n+ for (ncpu = 0; ncpu < s->num_cpu; ncpu++) {\n+ run_on_cpu_data data;\n+ data.host_ptr = &s->cpu[ncpu];\n+ run_on_cpu(s->cpu[ncpu].cpu, hvf_gicv3_put_cpu, data);\n+ }\n+\n+ /* s->enable bitmap -> GICD_ISENABLERn */\n+ hvf_dist_putbmp(s, HV_GIC_DISTRIBUTOR_REG_GICD_ISENABLER0,\n+ HV_GIC_DISTRIBUTOR_REG_GICD_ICENABLER0, s->enabled);\n+\n+ /* s->group bitmap -> GICD_IGROUPRn */\n+ hvf_dist_putbmp(s, HV_GIC_DISTRIBUTOR_REG_GICD_IGROUPR0,\n+ 0, s->group);\n+\n+ /*\n+ * Restore targets before pending to ensure the pending state is set on\n+ * the appropriate CPU interfaces in the kernel\n+ */\n+\n+ /* s->gicd_irouter[irq] -> GICD_IROUTERn */\n+ for (i = GIC_INTERNAL; i < s->num_irq; i++) {\n+ uint32_t offset = HV_GIC_DISTRIBUTOR_REG_GICD_IROUTER32 + (8 * i)\n+ - (8 * GIC_INTERNAL);\n+ hv_gic_set_distributor_reg(offset, s->gicd_irouter[i]);\n+ }\n+\n+ /*\n+ * s->trigger bitmap -> GICD_ICFGRn\n+ * (restore configuration registers before pending IRQs so we treat\n+ * level/edge correctly)\n+ */\n+ hvf_dist_put_edge_trigger(s, HV_GIC_DISTRIBUTOR_REG_GICD_ICFGR0, s->edge_trigger);\n+\n+ /* s->pending bitmap -> GICD_ISPENDRn */\n+ hvf_dist_putbmp(s, HV_GIC_DISTRIBUTOR_REG_GICD_ISPENDR0,\n+ HV_GIC_DISTRIBUTOR_REG_GICD_ICPENDR0, s->pending);\n+\n+ /* s->active bitmap -> GICD_ISACTIVERn */\n+ hvf_dist_putbmp(s, HV_GIC_DISTRIBUTOR_REG_GICD_ISACTIVER0,\n+ HV_GIC_DISTRIBUTOR_REG_GICD_ICACTIVER0, s->active);\n+\n+ /* s->gicd_ipriority[] -> GICD_IPRIORITYRn */\n+ hvf_dist_put_priority(s, HV_GIC_DISTRIBUTOR_REG_GICD_IPRIORITYR0, s->gicd_ipriority);\n+}\n+\n+static void hvf_gicv3_get_cpu_el2(CPUState *cpu_state, run_on_cpu_data arg)\n+{\n+ int num_pri_bits;\n+\n+ /* Redistributor state */\n+ GICv3CPUState *c = arg.host_ptr;\n+ hv_vcpu_t vcpu = c->cpu->accel->fd;\n+\n+ hv_gic_get_ich_reg(vcpu, HV_GIC_ICH_REG_VMCR_EL2, &c->ich_vmcr_el2);\n+ hv_gic_get_ich_reg(vcpu, HV_GIC_ICH_REG_HCR_EL2, &c->ich_hcr_el2);\n+\n+ for (int i = 0; i < GICV3_LR_MAX; i++) {\n+ hv_gic_get_ich_reg(vcpu, HV_GIC_ICH_REG_LR0_EL2, &c->ich_lr_el2[i]);\n+ }\n+\n+ num_pri_bits = c->vpribits;\n+\n+ switch (num_pri_bits) {\n+ case 7:\n+ hv_gic_get_ich_reg(vcpu, HV_GIC_ICH_REG_AP0R0_EL2 + 3,\n+ &c->ich_apr[GICV3_G0][3]);\n+ hv_gic_get_ich_reg(vcpu, HV_GIC_ICH_REG_AP0R0_EL2 + 2,\n+ &c->ich_apr[GICV3_G0][2]);\n+ /* fall through */\n+ case 6:\n+ hv_gic_get_ich_reg(vcpu, HV_GIC_ICH_REG_AP0R0_EL2 + 1,\n+ &c->ich_apr[GICV3_G0][1]);\n+ /* fall through */\n+ default:\n+ hv_gic_get_ich_reg(vcpu, HV_GIC_ICH_REG_AP0R0_EL2,\n+ &c->ich_apr[GICV3_G0][0]);\n+ }\n+\n+ switch (num_pri_bits) {\n+ case 7:\n+ hv_gic_get_ich_reg(vcpu, HV_GIC_ICH_REG_AP1R0_EL2 + 3,\n+ &c->ich_apr[GICV3_G1NS][3]);\n+ hv_gic_get_ich_reg(vcpu, HV_GIC_ICH_REG_AP1R0_EL2 + 2,\n+ &c->ich_apr[GICV3_G1NS][2]);\n+ /* fall through */\n+ case 6:\n+ hv_gic_get_ich_reg(vcpu, HV_GIC_ICH_REG_AP1R0_EL2 + 1,\n+ &c->ich_apr[GICV3_G1NS][1]);\n+ /* fall through */\n+ default:\n+ hv_gic_get_ich_reg(vcpu, HV_GIC_ICH_REG_AP1R0_EL2,\n+ &c->ich_apr[GICV3_G1NS][0]);\n+ }\n+}\n+\n+static void hvf_gicv3_get_cpu(CPUState *cpu_state, run_on_cpu_data arg)\n+{\n+ uint64_t reg;\n+ int i, num_pri_bits;\n+\n+ /* Redistributor state */\n+ GICv3CPUState *c = arg.host_ptr;\n+ hv_vcpu_t vcpu = c->cpu->accel->fd;\n+\n+ hv_gic_get_redistributor_reg(vcpu, HV_GIC_REDISTRIBUTOR_REG_GICR_IGROUPR0,\n+ ®);\n+ c->gicr_igroupr0 = reg;\n+ hv_gic_get_redistributor_reg(vcpu, HV_GIC_REDISTRIBUTOR_REG_GICR_ISENABLER0,\n+ ®);\n+ c->gicr_ienabler0 = reg;\n+ hv_gic_get_redistributor_reg(vcpu, HV_GIC_REDISTRIBUTOR_REG_GICR_ICFGR1,\n+ ®);\n+ c->edge_trigger = half_unshuffle32(reg >> 1) << 16;\n+ hv_gic_get_redistributor_reg(vcpu, HV_GIC_REDISTRIBUTOR_REG_GICR_ISPENDR0,\n+ ®);\n+ c->gicr_ipendr0 = reg;\n+ hv_gic_get_redistributor_reg(vcpu, HV_GIC_REDISTRIBUTOR_REG_GICR_ISACTIVER0,\n+ ®);\n+ c->gicr_iactiver0 = reg;\n+\n+ for (i = 0; i < GIC_INTERNAL; i += 4) {\n+ hv_gic_get_redistributor_reg(\n+ vcpu, HV_GIC_REDISTRIBUTOR_REG_GICR_IPRIORITYR0 + i, ®);\n+ c->gicr_ipriorityr[i] = extract32(reg, 0, 8);\n+ c->gicr_ipriorityr[i + 1] = extract32(reg, 8, 8);\n+ c->gicr_ipriorityr[i + 2] = extract32(reg, 16, 8);\n+ c->gicr_ipriorityr[i + 3] = extract32(reg, 24, 8);\n+ }\n+\n+ /* CPU interface */\n+ hv_gic_get_icc_reg(vcpu, HV_GIC_ICC_REG_SRE_EL1, &c->icc_sre_el1);\n+\n+ hv_gic_get_icc_reg(vcpu, HV_GIC_ICC_REG_CTLR_EL1,\n+ &c->icc_ctlr_el1[GICV3_NS]);\n+ hv_gic_get_icc_reg(vcpu, HV_GIC_ICC_REG_IGRPEN0_EL1,\n+ &c->icc_igrpen[GICV3_G0]);\n+ hv_gic_get_icc_reg(vcpu, HV_GIC_ICC_REG_IGRPEN1_EL1,\n+ &c->icc_igrpen[GICV3_G1NS]);\n+ hv_gic_get_icc_reg(vcpu, HV_GIC_ICC_REG_PMR_EL1, &c->icc_pmr_el1);\n+ hv_gic_get_icc_reg(vcpu, HV_GIC_ICC_REG_BPR0_EL1, &c->icc_bpr[GICV3_G0]);\n+ hv_gic_get_icc_reg(vcpu, HV_GIC_ICC_REG_BPR1_EL1, &c->icc_bpr[GICV3_G1NS]);\n+ num_pri_bits = ((c->icc_ctlr_el1[GICV3_NS] & ICC_CTLR_EL1_PRIBITS_MASK) >>\n+ ICC_CTLR_EL1_PRIBITS_SHIFT) +\n+ 1;\n+\n+ switch (num_pri_bits) {\n+ case 7:\n+ hv_gic_get_icc_reg(vcpu, HV_GIC_ICC_REG_AP0R0_EL1 + 3,\n+ &c->icc_apr[GICV3_G0][3]);\n+ hv_gic_get_icc_reg(vcpu, HV_GIC_ICC_REG_AP0R0_EL1 + 2,\n+ &c->icc_apr[GICV3_G0][2]);\n+ /* fall through */\n+ case 6:\n+ hv_gic_get_icc_reg(vcpu, HV_GIC_ICC_REG_AP0R0_EL1 + 1,\n+ &c->icc_apr[GICV3_G0][1]);\n+ /* fall through */\n+ default:\n+ hv_gic_get_icc_reg(vcpu, HV_GIC_ICC_REG_AP0R0_EL1,\n+ &c->icc_apr[GICV3_G0][0]);\n+ }\n+\n+ switch (num_pri_bits) {\n+ case 7:\n+ hv_gic_get_icc_reg(vcpu, HV_GIC_ICC_REG_AP1R0_EL1 + 3,\n+ &c->icc_apr[GICV3_G1NS][3]);\n+ hv_gic_get_icc_reg(vcpu, HV_GIC_ICC_REG_AP1R0_EL1 + 2,\n+ &c->icc_apr[GICV3_G1NS][2]);\n+ /* fall through */\n+ case 6:\n+ hv_gic_get_icc_reg(vcpu, HV_GIC_ICC_REG_AP1R0_EL1 + 1,\n+ &c->icc_apr[GICV3_G1NS][1]);\n+ /* fall through */\n+ default:\n+ hv_gic_get_icc_reg(vcpu, HV_GIC_ICC_REG_AP1R0_EL1,\n+ &c->icc_apr[GICV3_G1NS][0]);\n+ }\n+\n+ /* Registers beyond this point are with nested virt only */\n+ if (c->gic->maint_irq) {\n+ hvf_gicv3_get_cpu_el2(cpu_state, arg);\n+ }\n+}\n+\n+static void hvf_gicv3_get(GICv3State *s)\n+{\n+ uint64_t reg;\n+ int ncpu, i;\n+\n+ hvf_gicv3_check(s);\n+\n+ hv_gic_get_distributor_reg(HV_GIC_DISTRIBUTOR_REG_GICD_CTLR, ®);\n+ s->gicd_ctlr = reg;\n+\n+ /* Redistributor state (one per CPU) */\n+\n+ for (ncpu = 0; ncpu < s->num_cpu; ncpu++) {\n+ run_on_cpu_data data;\n+ data.host_ptr = &s->cpu[ncpu];\n+ run_on_cpu(s->cpu[ncpu].cpu, hvf_gicv3_get_cpu, data);\n+ }\n+\n+ /* GICD_IGROUPRn -> s->group bitmap */\n+ hvf_dist_getbmp(s, HV_GIC_DISTRIBUTOR_REG_GICD_IGROUPR0, s->group);\n+\n+ /* GICD_ISENABLERn -> s->enabled bitmap */\n+ hvf_dist_getbmp(s, HV_GIC_DISTRIBUTOR_REG_GICD_ISENABLER0, s->enabled);\n+\n+ /* GICD_ISPENDRn -> s->pending bitmap */\n+ hvf_dist_getbmp(s, HV_GIC_DISTRIBUTOR_REG_GICD_ISPENDR0, s->pending);\n+\n+ /* GICD_ISACTIVERn -> s->active bitmap */\n+ hvf_dist_getbmp(s, HV_GIC_DISTRIBUTOR_REG_GICD_ISACTIVER0, s->active);\n+\n+ /* GICD_ICFGRn -> s->trigger bitmap */\n+ hvf_dist_get_edge_trigger(s, HV_GIC_DISTRIBUTOR_REG_GICD_ICFGR0,\n+ s->edge_trigger);\n+\n+ /* GICD_IPRIORITYRn -> s->gicd_ipriority[] */\n+ hvf_dist_get_priority(s, HV_GIC_DISTRIBUTOR_REG_GICD_IPRIORITYR0,\n+ s->gicd_ipriority);\n+\n+ /* GICD_IROUTERn -> s->gicd_irouter[irq] */\n+ for (i = GIC_INTERNAL; i < s->num_irq; i++) {\n+ uint32_t offset = HV_GIC_DISTRIBUTOR_REG_GICD_IROUTER32\n+ + (8 * i) - (8 * GIC_INTERNAL);\n+ hv_gic_get_distributor_reg(offset, &s->gicd_irouter[i]);\n+ }\n+}\n+\n+static void hvf_gicv3_set_irq(void *opaque, int irq, int level)\n+{\n+ GICv3State *s = opaque;\n+ if (irq > s->num_irq) {\n+ return;\n+ }\n+ hv_gic_set_spi(GIC_INTERNAL + irq, !!level);\n+}\n+\n+static void hvf_gicv3_icc_reset(CPUARMState *env, const ARMCPRegInfo *ri)\n+{\n+ GICv3CPUState *c;\n+\n+ c = env->gicv3state;\n+ c->icc_pmr_el1 = 0;\n+ /*\n+ * Architecturally the reset value of the ICC_BPR registers\n+ * is UNKNOWN. We set them all to 0 here; when the kernel\n+ * uses these values to program the ICH_VMCR_EL2 fields that\n+ * determine the guest-visible ICC_BPR register values, the\n+ * hardware's \"writing a value less than the minimum sets\n+ * the field to the minimum value\" behaviour will result in\n+ * them effectively resetting to the correct minimum value\n+ * for the host GIC.\n+ */\n+ c->icc_bpr[GICV3_G0] = 0;\n+ c->icc_bpr[GICV3_G1] = 0;\n+ c->icc_bpr[GICV3_G1NS] = 0;\n+\n+ c->icc_sre_el1 = 0x7;\n+ memset(c->icc_apr, 0, sizeof(c->icc_apr));\n+ memset(c->icc_igrpen, 0, sizeof(c->icc_igrpen));\n+}\n+\n+static void hvf_gicv3_reset_hold(Object *obj, ResetType type)\n+{\n+ GICv3State *s = ARM_GICV3_COMMON(obj);\n+ HVFARMGICv3Class *kgc = HVF_GICV3_GET_CLASS(s);\n+\n+ if (kgc->parent_phases.hold) {\n+ kgc->parent_phases.hold(obj, type);\n+ }\n+\n+ hvf_gicv3_put(s);\n+}\n+\n+\n+/*\n+ * CPU interface registers of GIC needs to be reset on CPU reset.\n+ * For the calling arm_gicv3_icc_reset() on CPU reset, we register\n+ * below ARMCPRegInfo. As we reset the whole cpu interface under single\n+ * register reset, we define only one register of CPU interface instead\n+ * of defining all the registers.\n+ */\n+static const ARMCPRegInfo gicv3_cpuif_reginfo[] = {\n+ { .name = \"ICC_CTLR_EL1\", .state = ARM_CP_STATE_BOTH,\n+ .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 12, .opc2 = 4,\n+ /*\n+ * If ARM_CP_NOP is used, resetfn is not called,\n+ * So ARM_CP_NO_RAW is appropriate type.\n+ */\n+ .type = ARM_CP_NO_RAW,\n+ .access = PL1_RW,\n+ .readfn = arm_cp_read_zero,\n+ .writefn = arm_cp_write_ignore,\n+ /*\n+ * We hang the whole cpu interface reset routine off here\n+ * rather than parcelling it out into one little function\n+ * per register\n+ */\n+ .resetfn = hvf_gicv3_icc_reset,\n+ },\n+};\n+\n+static void hvf_gicv3_realize(DeviceState *dev, Error **errp)\n+{\n+ ERRP_GUARD();\n+ GICv3State *s = HVF_GICV3(dev);\n+ HVFARMGICv3Class *kgc = HVF_GICV3_GET_CLASS(s);\n+ int i;\n+\n+ kgc->parent_realize(dev, errp);\n+ if (*errp) {\n+ return;\n+ }\n+\n+ if (s->revision != 3) {\n+ error_setg(errp, \"unsupported GIC revision %d for platform GIC\",\n+ s->revision);\n+ }\n+\n+ if (s->security_extn) {\n+ error_setg(errp, \"the platform vGICv3 does not implement the \"\n+ \"security extensions\");\n+ return;\n+ }\n+\n+ if (s->nmi_support) {\n+ error_setg(errp, \"NMI is not supported with the platform GIC\");\n+ return;\n+ }\n+\n+ if (s->nb_redist_regions > 1) {\n+ error_setg(errp, \"Multiple VGICv3 redistributor regions are not \"\n+ \"supported by HVF\");\n+ error_append_hint(errp, \"A maximum of %d VCPUs can be used\",\n+ s->redist_region_count[0]);\n+ return;\n+ }\n+\n+ gicv3_init_irqs_and_mmio(s, hvf_gicv3_set_irq, NULL);\n+\n+ for (i = 0; i < s->num_cpu; i++) {\n+ ARMCPU *cpu = ARM_CPU(qemu_get_cpu(i));\n+\n+ define_arm_cp_regs(cpu, gicv3_cpuif_reginfo);\n+ }\n+\n+ if (s->maint_irq && s->maint_irq != HV_GIC_INT_MAINTENANCE) {\n+ error_setg(errp, \"vGIC maintenance IRQ mismatch with the hardcoded one in HVF.\");\n+ return;\n+ }\n+}\n+\n+static void hvf_gicv3_class_init(ObjectClass *klass, const void *data)\n+{\n+ DeviceClass *dc = DEVICE_CLASS(klass);\n+ ResettableClass *rc = RESETTABLE_CLASS(klass);\n+ ARMGICv3CommonClass *agcc = ARM_GICV3_COMMON_CLASS(klass);\n+ HVFARMGICv3Class *kgc = HVF_GICV3_CLASS(klass);\n+\n+ agcc->pre_save = hvf_gicv3_get;\n+ agcc->post_load = hvf_gicv3_put;\n+\n+ device_class_set_parent_realize(dc, hvf_gicv3_realize,\n+ &kgc->parent_realize);\n+ resettable_class_set_parent_phases(rc, NULL, hvf_gicv3_reset_hold, NULL,\n+ &kgc->parent_phases);\n+}\n+\n+static const TypeInfo hvf_arm_gicv3_info = {\n+ .name = TYPE_HVF_GICV3,\n+ .parent = TYPE_ARM_GICV3_COMMON,\n+ .instance_size = sizeof(GICv3State),\n+ .class_init = hvf_gicv3_class_init,\n+ .class_size = sizeof(HVFARMGICv3Class),\n+};\n+\n+static void hvf_gicv3_register_types(void)\n+{\n+ type_register_static(&hvf_arm_gicv3_info);\n+}\n+\n+type_init(hvf_gicv3_register_types)\n+\n+#pragma clang diagnostic pop\ndiff --git a/hw/intc/meson.build b/hw/intc/meson.build\nindex 96742df090..b7baf8a0f6 100644\n--- a/hw/intc/meson.build\n+++ b/hw/intc/meson.build\n@@ -42,6 +42,7 @@ arm_common_ss.add(when: 'CONFIG_ARM_GIC', if_true: files('arm_gicv3_cpuif_common\n arm_common_ss.add(when: 'CONFIG_ARM_GICV3', if_true: files('arm_gicv3_cpuif.c'))\n specific_ss.add(when: 'CONFIG_ARM_GIC_KVM', if_true: files('arm_gic_kvm.c'))\n specific_ss.add(when: ['CONFIG_WHPX', 'TARGET_AARCH64'], if_true: files('arm_gicv3_whpx.c'))\n+specific_ss.add(when: ['CONFIG_HVF', 'CONFIG_ARM_GICV3'], if_true: files('arm_gicv3_hvf.c'))\n specific_ss.add(when: ['CONFIG_ARM_GIC_KVM', 'TARGET_AARCH64'], if_true: files('arm_gicv3_kvm.c', 'arm_gicv3_its_kvm.c'))\n arm_common_ss.add(when: 'CONFIG_ARM_V7M', if_true: files('armv7m_nvic.c'))\n specific_ss.add(when: 'CONFIG_GRLIB', if_true: files('grlib_irqmp.c'))\ndiff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h\nindex c55cf18120..9adcab0a0c 100644\n--- a/include/hw/intc/arm_gicv3_common.h\n+++ b/include/hw/intc/arm_gicv3_common.h\n@@ -315,6 +315,7 @@ DECLARE_OBJ_CHECKERS(GICv3State, ARMGICv3CommonClass,\n \n /* Types for GICv3 kernel-irqchip */\n #define TYPE_WHPX_GICV3 \"whpx-arm-gicv3\"\n+#define TYPE_HVF_GICV3 \"hvf-arm-gicv3\"\n \n struct ARMGICv3CommonClass {\n /*< private >*/\n", "prefixes": [ "PULL", "14/28" ] }