From nobody Sat Nov 15 09:08:46 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=reject dis=none) header.from=unpredictable.fr ARC-Seal: i=1; a=rsa-sha256; t=1754122854; cv=none; d=zohomail.com; s=zohoarc; b=nV13HkrSyRRn6Jl/j8Ntr/GdDmdj77dZ9nQ2tH+ms4Y+39gaYixYhbIQwm7NTx/W0P28isle6DAfSyZfzrhJx2Cz8redrAkG5fz4MLGt4JcSHZms3BDd7b5SZJLTFvveC9bnPBrTEm9YzhxrBER7Z1tsiCb7zU3kyYXl19AYBWo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1754122854; h=Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=7+ALo17Td1jtv80LEsrsActnIwEcJLZoAvs9uOvM3YM=; b=bI+p5QUvEjp2jMwO5nSWK9lg22IKY9J7ZTrT7gzdAJNjAKZ0/nt5d+aDiZ6PvTYcEmRDccP0DZwtZ7iIhZYjyJsLjhUY9J+qKw8DPxAxBlf7GmcrXv81Mrrwm8qsDm6ZcYALx0vQzRv1acZ8V0r6pqB2Q7o/JYPjcfiUW5Figow= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1754122854520263.7382223095691; Sat, 2 Aug 2025 01:20:54 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1ui7Sc-0000Nu-AE; Sat, 02 Aug 2025 04:19:22 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ui7Ri-0007I6-U6 for qemu-devel@nongnu.org; Sat, 02 Aug 2025 04:18:27 -0400 Received: from p-east3-cluster6-host2-snip4-2.eps.apple.com ([57.103.85.143] helo=outbound.qs.icloud.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1ui7Re-000541-0W for qemu-devel@nongnu.org; Sat, 02 Aug 2025 04:18:26 -0400 Received: from outbound.qs.icloud.com (unknown [127.0.0.2]) by p00-icloudmta-asmtp-us-east-2d-60-percent-11 (Postfix) with ESMTPS id 8AFCC1800148; Sat, 2 Aug 2025 08:18:18 +0000 (UTC) Received: from localhost.localdomain (qs-asmtp-me-k8s.p00.prod.me.com [17.57.155.37]) by p00-icloudmta-asmtp-us-east-2d-60-percent-11 (Postfix) with ESMTPSA id E935518000A4; Sat, 2 Aug 2025 08:18:15 +0000 (UTC) Dkim-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=unpredictable.fr; s=sig1; bh=7+ALo17Td1jtv80LEsrsActnIwEcJLZoAvs9uOvM3YM=; h=From:To:Subject:Date:Message-Id:MIME-Version:x-icloud-hme; b=S/PGF6z9oKAzxFa8Kp4u8Xq01SSWfXD3q56P0qtlu70oMPM2brMZ8w9kGX9cSutWYRilbuu11lXxVU56Fao7siGw8ZfJoX7RZK9GwZI6HAczeyOxRk+DNFd2dZSAoZipcsTniaINrY4mwpof7U/vUrm7Fkojdpv1xNYEYjJdVDxLrRon3/giHML3rRrQn/uh75wHBfD3K4qDhhYuGPJyXqHW1adbuvEQRN7DRiPBB5uLgsuy8djHX4YYKoZwhwJ8qmOVQ8aVisb127nDWl49yABzl5h5Y62fz55TDtIaWGIFufUtHBvDYfyqQXhpm5fcx1L9144LKK5EvfJXAjxU2g== X-Client-IP: 46.189.47.18 From: Mohamed Mediouni To: qemu-devel@nongnu.org Cc: Richard Henderson , Zhao Liu , Yanan Wang , qemu-arm@nongnu.org, Sunil Muthuswamy , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , Igor Mammedov , Peter Maydell , Shannon Zhao , "Michael S. Tsirkin" , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Eduardo Habkost , Marcel Apfelbaum , Mohamed Mediouni , Paolo Bonzini , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Ani Sinha Subject: [PATCH v3 06/14] whpx: interrupt controller support Date: Sat, 2 Aug 2025 10:17:52 +0200 Message-Id: <20250802081800.76030-7-mohamed@unpredictable.fr> X-Mailer: git-send-email 2.39.5 (Apple Git-154) In-Reply-To: <20250802081800.76030-1-mohamed@unpredictable.fr> References: <20250802081800.76030-1-mohamed@unpredictable.fr> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-ORIG-GUID: MWca6tI1tZ3VyCmhXJ4wUF9rGBosqsT- X-Proofpoint-Spam-Details-Enc: AW1haW4tMjUwODAyMDA3MCBTYWx0ZWRfXwvThGuJdG5X9 9tiyuLzZmWuhiMWYkkyqNDi2c3FQmvz1PjBwu4iYBkJJxX44tdACCH95p/ZQ0L2wX+UBhN384At 2zC8ihShb+2v1Y8cQsPAOgT4MbwRZb2jOE5MXi2mk0ukUriQPbAcpGloKJtpVN37cIox5WVrxAE fj//M7/X9Rwa7VqJSSQoDd1BJud9A6cI4p9qbT7pTi4QXplvq+jG2v3NVX4zO2qu+DU/cK0e54S eC/jJ0d2gTV9lWjgFYTvE9MysP7koz7ozjodaFQ51I+2rHzSpOFF2v3P4de7v0hegcqA8L1kg= X-Proofpoint-GUID: MWca6tI1tZ3VyCmhXJ4wUF9rGBosqsT- X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1099,Hydra:6.1.9,FMLib:17.12.80.40 definitions=2025-08-01_08,2025-08-01_01,2025-03-28_01 X-Proofpoint-Spam-Details: rule=notspam policy=default score=0 malwarescore=0 bulkscore=0 suspectscore=0 spamscore=0 mlxscore=0 mlxlogscore=999 adultscore=0 clxscore=1030 phishscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.22.0-2506270000 definitions=main-2508020070 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=57.103.85.143; envelope-from=mohamed@unpredictable.fr; helo=outbound.qs.icloud.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, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED=0.001, RCVD_IN_VALIDITY_RPBL_BLOCKED=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @unpredictable.fr) X-ZM-MESSAGEID: 1754122858035116600 Content-Type: text/plain; charset="utf-8" Signed-off-by: Mohamed Mediouni --- hw/arm/virt.c | 3 + hw/intc/arm_gicv3_common.c | 3 + hw/intc/arm_gicv3_whpx.c | 261 +++++++++++++++++++++++++++++ hw/intc/meson.build | 1 + include/hw/intc/arm_gicv3_common.h | 3 + 5 files changed, 271 insertions(+) create mode 100644 hw/intc/arm_gicv3_whpx.c diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 5951b331f3..98a1c74c42 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -49,6 +49,7 @@ #include "system/tcg.h" #include "system/kvm.h" #include "system/hvf.h" +#include "system/whpx.h" #include "system/qtest.h" #include "hw/loader.h" #include "qapi/error.h" @@ -2060,6 +2061,8 @@ static void finalize_gic_version(VirtMachineState *vm= s) /* KVM w/o kernel irqchip can only deal with GICv2 */ gics_supported |=3D VIRT_GIC_VERSION_2_MASK; accel_name =3D "KVM with kernel-irqchip=3Doff"; + } else if (whpx_enabled()) { + gics_supported |=3D VIRT_GIC_VERSION_3_MASK; } else if (tcg_enabled() || hvf_enabled() || qtest_enabled()) { gics_supported |=3D VIRT_GIC_VERSION_2_MASK; if (module_object_class_by_name("arm-gicv3")) { diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c index e438d8c042..8b85b60c9b 100644 --- a/hw/intc/arm_gicv3_common.c +++ b/hw/intc/arm_gicv3_common.c @@ -32,6 +32,7 @@ #include "gicv3_internal.h" #include "hw/arm/linux-boot-if.h" #include "system/kvm.h" +#include "system/whpx.h" =20 =20 static void gicv3_gicd_no_migration_shift_bug_post_load(GICv3State *cs) @@ -662,6 +663,8 @@ const char *gicv3_class_name(void) { if (kvm_irqchip_in_kernel()) { return "kvm-arm-gicv3"; + } else if (whpx_enabled()) { + return TYPE_WHPX_GICV3; } else { if (kvm_enabled()) { error_report("Userspace GICv3 is not supported with KVM"); diff --git a/hw/intc/arm_gicv3_whpx.c b/hw/intc/arm_gicv3_whpx.c new file mode 100644 index 0000000000..ead4e167c5 --- /dev/null +++ b/hw/intc/arm_gicv3_whpx.c @@ -0,0 +1,261 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +/* + * ARM Generic Interrupt Controller using HVF platform support + * + * Copyright (c) 2025 Mohamed Mediouni + * Based on vGICv3 KVM code by Pavel Fedin + * + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "hw/intc/arm_gicv3_common.h" +#include "qemu/error-report.h" +#include "qemu/module.h" +#include "system/runstate.h" +#include "system/whpx.h" +#include "system/whpx-internal.h" +#include "gicv3_internal.h" +#include "vgic_common.h" +#include "qom/object.h" +#include "target/arm/cpregs.h" + +#include "hw/arm/bsa.h" +#include +#include +#include + +struct WHPXARMGICv3Class { + ARMGICv3CommonClass parent_class; + DeviceRealize parent_realize; + ResettablePhases parent_phases; +}; + +typedef struct WHPXARMGICv3Class WHPXARMGICv3Class; + +/* This is reusing the GICv3State typedef from ARM_GICV3_ITS_COMMON */ +DECLARE_OBJ_CHECKERS(GICv3State, WHPXARMGICv3Class, + WHPX_GICV3, TYPE_WHPX_GICV3); + +static void whpx_gicv3_check(GICv3State *s) +{ +} + +static void whpx_gicv3_put_cpu(CPUState *cpu_state, run_on_cpu_data arg) +{ +} + +static void whpx_gicv3_put(GICv3State *s) +{ + int ncpu; + + whpx_gicv3_check(s); + + for (ncpu =3D 0; ncpu < s->num_cpu; ncpu++) { + run_on_cpu_data data; + data.host_ptr =3D &s->cpu[ncpu]; + run_on_cpu(s->cpu[ncpu].cpu, whpx_gicv3_put_cpu, data); + } +} + +static void whpx_gicv3_get_cpu(CPUState *cpu_state, run_on_cpu_data arg) +{ +} + +static void whpx_gicv3_get(GICv3State *s) +{ + int ncpu; + + for (ncpu =3D 0; ncpu < s->num_cpu; ncpu++) { + run_on_cpu_data data; + data.host_ptr =3D &s->cpu[ncpu]; + run_on_cpu(s->cpu[ncpu].cpu, whpx_gicv3_get_cpu, data); + } +} + +static void whpx_gicv3_set_irq(void *opaque, int irq, int level) +{ + struct whpx_state *whpx =3D &whpx_global; + + GICv3State *s =3D (GICv3State *)opaque; + if (irq > s->num_irq) { + return; + } + WHV_INTERRUPT_TYPE interrupt_type =3D WHvArm64InterruptTypeFixed; + WHV_INTERRUPT_CONTROL interrupt_control =3D { + interrupt_type =3D WHvArm64InterruptTypeFixed, + .RequestedVector =3D GIC_INTERNAL + irq, .InterruptControl.Asserted = =3D level}; + + whp_dispatch.WHvRequestInterrupt(whpx->partition, &interrupt_control, + sizeof(interrupt_control)); +} + +static void whpx_gicv3_icc_reset(CPUARMState *env, const ARMCPRegInfo *ri) +{ + GICv3State *s; + GICv3CPUState *c; + + c =3D (GICv3CPUState *)env->gicv3state; + s =3D c->gic; + + c->icc_pmr_el1 =3D 0; + /* + * Architecturally the reset value of the ICC_BPR registers + * is UNKNOWN. We set them all to 0 here; when the kernel + * uses these values to program the ICH_VMCR_EL2 fields that + * determine the guest-visible ICC_BPR register values, the + * hardware's "writing a value less than the minimum sets + * the field to the minimum value" behaviour will result in + * them effectively resetting to the correct minimum value + * for the host GIC. + */ + c->icc_bpr[GICV3_G0] =3D 0; + c->icc_bpr[GICV3_G1] =3D 0; + c->icc_bpr[GICV3_G1NS] =3D 0; + + c->icc_sre_el1 =3D 0x7; + memset(c->icc_apr, 0, sizeof(c->icc_apr)); + memset(c->icc_igrpen, 0, sizeof(c->icc_igrpen)); + + if (s->migration_blocker) { + return; + } + + c->icc_ctlr_el1[GICV3_S] =3D c->icc_ctlr_el1[GICV3_NS]; +} + +static void whpx_gicv3_reset_hold(Object *obj, ResetType type) +{ + GICv3State *s =3D ARM_GICV3_COMMON(obj); + WHPXARMGICv3Class *kgc =3D WHPX_GICV3_GET_CLASS(s); + + if (kgc->parent_phases.hold) { + kgc->parent_phases.hold(obj, type); + } + + whpx_gicv3_put(s); +} + + +/* + * CPU interface registers of GIC needs to be reset on CPU reset. + * For the calling arm_gicv3_icc_reset() on CPU reset, we register + * below ARMCPRegInfo. As we reset the whole cpu interface under single + * register reset, we define only one register of CPU interface instead + * of defining all the registers. + */ +static const ARMCPRegInfo gicv3_cpuif_reginfo[] =3D { + { .name =3D "ICC_CTLR_EL1", .state =3D ARM_CP_STATE_BOTH, + .opc0 =3D 3, .opc1 =3D 0, .crn =3D 12, .crm =3D 12, .opc2 =3D 4, + /* + * If ARM_CP_NOP is used, resetfn is not called, + * So ARM_CP_NO_RAW is appropriate type. + */ + .type =3D ARM_CP_NO_RAW, + .access =3D PL1_RW, + .readfn =3D arm_cp_read_zero, + .writefn =3D arm_cp_write_ignore, + /* + * We hang the whole cpu interface reset routine off here + * rather than parcelling it out into one little function + * per register + */ + .resetfn =3D whpx_gicv3_icc_reset, + }, +}; + +static void whpx_set_reg(CPUState *cpu, WHV_REGISTER_NAME reg, WHV_REGISTE= R_VALUE val) +{ + struct whpx_state *whpx =3D &whpx_global; + HRESULT hr; + hr =3D whp_dispatch.WHvSetVirtualProcessorRegisters(whpx->partition, c= pu->cpu_index, + ®, 1, &val); + + if (FAILED(hr)) { + error_report("WHPX: Failed to set register %08x, hr=3D%08lx", reg,= hr); + } +} + +static void whpx_gicv3_realize(DeviceState *dev, Error **errp) +{ + GICv3State *s =3D WHPX_GICV3(dev); + WHPXARMGICv3Class *kgc =3D WHPX_GICV3_GET_CLASS(s); + Error *local_err =3D NULL; + int i; + + kgc->parent_realize(dev, &local_err); + if (local_err) { + error_propagate(errp, local_err); + return; + } + + if (s->revision !=3D 3) { + error_setg(errp, "unsupported GIC revision %d for platform GIC", + s->revision); + } + + if (s->security_extn) { + error_setg(errp, "the platform vGICv3 does not implement the " + "security extensions"); + return; + } + + if (s->nmi_support) { + error_setg(errp, "NMI is not supported with the platform GIC"); + return; + } + + if (s->nb_redist_regions > 1) { + error_setg(errp, "Multiple VGICv3 redistributor regions are not " + "supported by WHPX"); + error_append_hint(errp, "A maximum of %d VCPUs can be used", + s->redist_region_count[0]); + return; + } + + gicv3_init_irqs_and_mmio(s, whpx_gicv3_set_irq, NULL); + + for (i =3D 0; i < s->num_cpu; i++) { + CPUState *cpu_state =3D qemu_get_cpu(i); + ARMCPU *cpu =3D ARM_CPU(cpu_state); + WHV_REGISTER_VALUE val =3D {.Reg64 =3D 0x080A0000 + (GICV3_REDIST_= SIZE * i)}; + whpx_set_reg(cpu_state, WHvArm64RegisterGicrBaseGpa, val); + define_arm_cp_regs(cpu, gicv3_cpuif_reginfo); + } + + if (s->maint_irq) { + error_setg(errp, "Nested virtualisation not currently supported by= WHPX."); + return; + } +} + +static void whpx_gicv3_class_init(ObjectClass *klass, const void *data) +{ + DeviceClass *dc =3D DEVICE_CLASS(klass); + ResettableClass *rc =3D RESETTABLE_CLASS(klass); + ARMGICv3CommonClass *agcc =3D ARM_GICV3_COMMON_CLASS(klass); + WHPXARMGICv3Class *kgc =3D WHPX_GICV3_CLASS(klass); + + agcc->pre_save =3D whpx_gicv3_get; + agcc->post_load =3D whpx_gicv3_put; + + device_class_set_parent_realize(dc, whpx_gicv3_realize, + &kgc->parent_realize); + resettable_class_set_parent_phases(rc, NULL, whpx_gicv3_reset_hold, NU= LL, + &kgc->parent_phases); +} + +static const TypeInfo whpx_arm_gicv3_info =3D { + .name =3D TYPE_WHPX_GICV3, + .parent =3D TYPE_ARM_GICV3_COMMON, + .instance_size =3D sizeof(GICv3State), + .class_init =3D whpx_gicv3_class_init, + .class_size =3D sizeof(WHPXARMGICv3Class), +}; + +static void whpx_gicv3_register_types(void) +{ + type_register_static(&whpx_arm_gicv3_info); +} + +type_init(whpx_gicv3_register_types) diff --git a/hw/intc/meson.build b/hw/intc/meson.build index 3137521a4a..9342ff0e2c 100644 --- a/hw/intc/meson.build +++ b/hw/intc/meson.build @@ -41,6 +41,7 @@ specific_ss.add(when: 'CONFIG_APIC', if_true: files('apic= .c', 'apic_common.c')) specific_ss.add(when: 'CONFIG_ARM_GIC', if_true: files('arm_gicv3_cpuif_co= mmon.c')) specific_ss.add(when: 'CONFIG_ARM_GICV3', if_true: files('arm_gicv3_cpuif.= c')) specific_ss.add(when: 'CONFIG_ARM_GIC_KVM', if_true: files('arm_gic_kvm.c'= )) +specific_ss.add(when: 'CONFIG_WHPX', if_true: files('arm_gicv3_whpx.c')) specific_ss.add(when: ['CONFIG_ARM_GIC_KVM', 'TARGET_AARCH64'], if_true: f= iles('arm_gicv3_kvm.c', 'arm_gicv3_its_kvm.c')) specific_ss.add(when: 'CONFIG_ARM_V7M', if_true: files('armv7m_nvic.c')) specific_ss.add(when: 'CONFIG_GRLIB', if_true: files('grlib_irqmp.c')) diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3= _common.h index c18503869f..7776558a0e 100644 --- a/include/hw/intc/arm_gicv3_common.h +++ b/include/hw/intc/arm_gicv3_common.h @@ -306,6 +306,9 @@ typedef struct ARMGICv3CommonClass ARMGICv3CommonClass; DECLARE_OBJ_CHECKERS(GICv3State, ARMGICv3CommonClass, ARM_GICV3_COMMON, TYPE_ARM_GICV3_COMMON) =20 +/* Types for GICv3 kernel-irqchip */ +#define TYPE_WHPX_GICV3 "whpx-arm-gicv3" + struct ARMGICv3CommonClass { /*< private >*/ SysBusDeviceClass parent_class; --=20 2.39.5 (Apple Git-154)