From nobody Sat Sep 26 21:36:42 2026 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=quarantine dis=none) header.from=huawei.com ARC-Seal: i=1; a=rsa-sha256; t=1789733072; cv=none; d=zohomail.com; s=zohoarc; b=eFsloyYT6JhoJJwvw+frbh2mSNy/Zkbju193ihTn720Q/38Td9s+qlYOLvppv4yXRbxrW/tHIezX36WSoBlNB6VQNqJwSpSQo37SIs7ELCtp59wC1DrPvVIcqSb8ylVIPXjfh803Q9owXOunCyiGV8TXrw+q4RVV8JAIekiKQhQ= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1789733072; h=Content-Type: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:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=qzZOCur4BGqUx5xfENpBZYTSs+U/Bs6R7I9nIxljxEU=; b=bMZ+nOdOhJcjEtb4CVc56bf9Ozvvf/ho+lIV3dNMlj9jocurQyRfAGn4IpF5T0X9Lzo814stEgrtNqCJiW1Bn2UvEM6KpwmuOfFEqa6/dqU78HKRX+40ZVycnZ3XggwAkgw/8lHGBIQUL7BdzwCIawLmukCDalE6GmmfEqgQXdY= 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=quarantine dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1789733072359543.1429566076375; Fri, 18 Sep 2026 05:04:32 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x7XJw-0000M5-OJ; Fri, 18 Sep 2026 08:04:02 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x7UqI-0006qX-SC; Fri, 18 Sep 2026 05:25:14 -0400 Received: from canpmsgout03.his.huawei.com ([113.46.200.218]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x7UqE-0002I8-JA; Fri, 18 Sep 2026 05:25:14 -0400 Received: from mail.maildlp.com (unknown [172.19.162.140]) by canpmsgout03.his.huawei.com (SkyGuard) with ESMTPS id 4hmRjw0Y6NzpSyG; Fri, 18 Sep 2026 17:13:08 +0800 (CST) Received: from dggpemr200003.china.huawei.com (unknown [7.185.36.25]) by mail.maildlp.com (Postfix) with ESMTPS id 3087620333; Fri, 18 Sep 2026 17:24:57 +0800 (CST) Received: from huawei.com (10.50.159.234) by dggpemr200003.china.huawei.com (7.185.36.25) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.46; Fri, 18 Sep 2026 17:24:56 +0800 dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=qzZOCur4BGqUx5xfENpBZYTSs+U/Bs6R7I9nIxljxEU=; b=W58LaI3+G7xlTJOxfyISX2GCMCnQxIzZ9DNwfo9F3rUSelobFsfEHB0G+N/4fFJ2P9YJgXPHm PuL8QijMGF34206ePa1OchhXjjTwLyUvGsKBGPzsXn15squDDT6IwE/W6KuFJ0JhjJVy5qlHs3Y tUgNunHPPUlKKxTlHoW5QFE= From: Yize Wang To: , CC: , , , , , , , Subject: [PATCH 1/4] Sync KVM ARM VGIC batch register UAPI to QEMU headers Date: Fri, 18 Sep 2026 17:18:53 +0800 Message-ID: <20260918092120.370805-2-wangyize7@huawei.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260918092120.370805-1-wangyize7@huawei.com> References: <20260918092120.370805-1-wangyize7@huawei.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Originating-IP: [10.50.159.234] X-ClientProxiedBy: kwepems200001.china.huawei.com (7.221.188.67) To dggpemr200003.china.huawei.com (7.185.36.25) 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=lists1p.gnu.org; Received-SPF: pass client-ip=113.46.200.218; envelope-from=wangyize7@huawei.com; helo=canpmsgout03.his.huawei.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_MSPIKE_H2=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Fri, 18 Sep 2026 08:02:22 -0400 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development 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 @huawei.com) X-ZM-MESSAGEID: 1789733075003158500 Content-Type: text/plain; charset="utf-8" Add KVM_DEV_ARM_VGIC_GRP_BATCH_REGS, KVM_DEV_ARM_VGIC_BATCH_MAX, and kvm_dev_arm_vgic_batch_entry struct to arm64 QEMU vendored kernel headers. Signed-off-by: Chuan Zheng Signed-off-by: Yize Wang --- linux-headers/asm-arm64/kvm.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/linux-headers/asm-arm64/kvm.h b/linux-headers/asm-arm64/kvm.h index 6aefe79738..26ba4fb9cb 100644 --- a/linux-headers/asm-arm64/kvm.h +++ b/linux-headers/asm-arm64/kvm.h @@ -405,11 +405,20 @@ enum { #define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO 7 #define KVM_DEV_ARM_VGIC_GRP_ITS_REGS 8 #define KVM_DEV_ARM_VGIC_GRP_MAINT_IRQ 9 +#define KVM_DEV_ARM_VGIC_GRP_BATCH_REGS 10 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT 10 #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \ (0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT) #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK 0x3ff #define VGIC_LEVEL_INFO_LINE_LEVEL 0 +#define KVM_DEV_ARM_VGIC_BATCH_MAX 4096 + +struct kvm_dev_arm_vgic_batch_entry { + __u32 group; + __u64 attr; + __u32 val; + __s32 error; +}; =20 #define KVM_DEV_ARM_VGIC_CTRL_INIT 0 #define KVM_DEV_ARM_ITS_SAVE_TABLES 1 --=20 2.43.0 From nobody Sat Sep 26 21:36:42 2026 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=quarantine dis=none) header.from=huawei.com ARC-Seal: i=1; a=rsa-sha256; t=1789733072; cv=none; d=zohomail.com; s=zohoarc; b=OF8Byc5pNyWs1O+UZQiUWk+ses30M/j/gQcpuIACu5gDdUN8j/W9XuMhnb3davxdruw/gIdHnftvkXzK4AK/j/ZQZTgtT0C+dVMvpRASw5ez3r9PAlfsui/0yEXDlCvQbA9Zamk88Gf/xLELezqbsU+xRgKGvid87kJDPwp34U0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1789733072; h=Content-Type: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:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=dtMd+wjWdeZCTRTx7A2HQTJCsoRVybQIeSHKRP1uVA4=; b=fBIqA/wDaf5SK0Y4LXO1LTd0Ihro+Yo9OtlTlQbiEHeK4Ejz0UG/oIdRVdqv974LVkJ+Ijyw+v5I0AJYuHjbw6jw4UvE+MOj0DX0wbyd6FyFwb0d+3XVnGOLi388opTSbbdc2s0QcwSb40+pLiiAO5EF38Hh5QXI4b0L+tEJdXw= 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=quarantine dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1789733072177573.7592877588642; Fri, 18 Sep 2026 05:04:32 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x7XJu-0000LH-Qb; Fri, 18 Sep 2026 08:04:00 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x7UqI-0006qW-QF; Fri, 18 Sep 2026 05:25:14 -0400 Received: from canpmsgout02.his.huawei.com ([113.46.200.217]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x7UqB-0002IA-TH; Fri, 18 Sep 2026 05:25:13 -0400 Received: from mail.maildlp.com (unknown [172.19.162.140]) by canpmsgout02.his.huawei.com (SkyGuard) with ESMTPS id 4hmRkb0Dt3zcb44; Fri, 18 Sep 2026 17:13:43 +0800 (CST) Received: from dggpemr200003.china.huawei.com (unknown [7.185.36.25]) by mail.maildlp.com (Postfix) with ESMTPS id 245F920333; Fri, 18 Sep 2026 17:24:58 +0800 (CST) Received: from huawei.com (10.50.159.234) by dggpemr200003.china.huawei.com (7.185.36.25) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.46; Fri, 18 Sep 2026 17:24:57 +0800 dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=dtMd+wjWdeZCTRTx7A2HQTJCsoRVybQIeSHKRP1uVA4=; b=tv9V44Ie7oCBg3cmTYZ93b6UWbe3KcInLIdDQyef6TdjOTeHETlYfo54pKFqpM3GO/QOEDODa K51R7PH4MT4tk6NIahioNxl4Zg/XESMISDMRoACaJmLs5IjAWI+2hKi8x6xyQWllmWVHdE6W0ym CFuOydApr8+zIw8E4A8ZD1A= From: Yize Wang To: , CC: , , , , , , , Subject: [PATCH 2/4] hw/intc/arm_gicv3_kvm: Add batch helper structures and functions Date: Fri, 18 Sep 2026 17:18:54 +0800 Message-ID: <20260918092120.370805-3-wangyize7@huawei.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260918092120.370805-1-wangyize7@huawei.com> References: <20260918092120.370805-1-wangyize7@huawei.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Originating-IP: [10.50.159.234] X-ClientProxiedBy: kwepems200001.china.huawei.com (7.221.188.67) To dggpemr200003.china.huawei.com (7.185.36.25) 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=lists1p.gnu.org; Received-SPF: pass client-ip=113.46.200.217; envelope-from=wangyize7@huawei.com; helo=canpmsgout02.his.huawei.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_MSPIKE_H2=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Fri, 18 Sep 2026 08:02:13 -0400 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development 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 @huawei.com) X-ZM-MESSAGEID: 1789733074829158500 Content-Type: text/plain; charset="utf-8" Add GICv3BatchEntry typedef and three helper functions for batch register access to KVM ARM64 VGICv3: - kvm_arm_gic_batch_add: Accumulates register operations into a dynamic arr= ay - kvm_arm_gic_batch_commit: Submits the batch array to kernel via a single = ioctl - kvm_arm_gic_batch_supported: Probes kernel support for the batch interface These helpers will be used by kvm_arm_gicv3_get and kvm_arm_gicv3_put in su= bsequent patches to enable efficient batch register access. Signed-off-by: Chuan Zheng Signed-off-by: Yize Wang --- hw/intc/arm_gicv3_kvm.c | 95 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c index 22fcac1668..ea6c8462c7 100644 --- a/hw/intc/arm_gicv3_kvm.c +++ b/hw/intc/arm_gicv3_kvm.c @@ -118,6 +118,101 @@ static inline void kvm_gic_line_level_access(GICv3Sta= te *s, int irq, int cpu, val, write, &error_abort); } =20 +typedef struct { + uint32_t group; + uint64_t attr; + uint32_t *val; +} GICv3BatchEntry; + +/* Accumulates register operations into a dynamic array. */ +static void kvm_arm_gic_batch_add(GICv3BatchEntry **entries, int *n, + int *capacity, uint32_t group, + uint64_t attr, uint32_t *val) +{ + if (*n >=3D *capacity) { + *capacity =3D MAX(*capacity * 2, 256); + *entries =3D g_renew(GICv3BatchEntry, *entries, *capacity); + } + (*entries)[*n].group =3D group; + (*entries)[*n].attr =3D attr; + /* Store the pointer, not the value, to avoid copying data now. */ + (*entries)[*n].val =3D val; + (*n)++; +} + +/* + * Submit the batched GIC register operations to the kernel via a single i= octl. + * + * Workflow: + * 1. Allocate a kernel-compatible structure array + * (kvm_dev_arm_vgic_batch_entry). + * 2. Convert QEMU's internal format to the kernel's expected format. + * - For WRITE: Copy the actual values from QEMU's buffers into the + * kernel struct. + * - For READ: Only set the register IDs; the kernel will fill in + * the values. + * 3. Perform a single ioctl() to send/receive all data at once. + * 4. For READ: Copy the values returned by the kernel back into QEMU's + * buffers. + */ +static void kvm_arm_gic_batch_commit(int dev_fd, GICv3BatchEntry *entries, + int n, bool write) +{ + struct kvm_dev_arm_vgic_batch_entry *batch; + struct kvm_device_attr attr; + int i, ret; + + if (!n) { + return; + } + + batch =3D g_new0(struct kvm_dev_arm_vgic_batch_entry, n); + for (i =3D 0; i < n; i++) { + batch[i].group =3D entries[i].group; + batch[i].attr =3D entries[i].attr; + if (write) { + batch[i].val =3D *entries[i].val; + } + } + + attr.group =3D KVM_DEV_ARM_VGIC_GRP_BATCH_REGS; + attr.addr =3D (uint64_t)batch; + attr.attr =3D n; + + if (write) { + ret =3D kvm_device_ioctl(dev_fd, KVM_SET_DEVICE_ATTR, &attr); + } else { + ret =3D kvm_device_ioctl(dev_fd, KVM_GET_DEVICE_ATTR, &attr); + } + + if (ret < 0) { + error_report("KVM_%s_DEVICE_ATTR failed on batch regs: %s", + write ? "SET" : "GET", strerror(-ret)); + abort(); + } + + if (!write) { + for (i =3D 0; i < n; i++) { + *entries[i].val =3D batch[i].val; + } + } + + g_free(batch); +} + +/* + * Check if the kernel supports GIC batch register operations. + * Returns: true if the kernel supports the BATCH_REGS group, + * false otherwise. + */ +static bool kvm_arm_gic_batch_supported(int dev_fd) +{ + struct kvm_device_attr attr =3D { + .group =3D KVM_DEV_ARM_VGIC_GRP_BATCH_REGS, + }; + return kvm_device_ioctl(dev_fd, KVM_HAS_DEVICE_ATTR, &attr) =3D=3D 0; +} + /* Loop through each distributor IRQ related register; since bits * corresponding to SPIs and PPIs are RAZ/WI when affinity routing * is enabled, we skip those. --=20 2.43.0 From nobody Sat Sep 26 21:36:42 2026 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=quarantine dis=none) header.from=huawei.com ARC-Seal: i=1; a=rsa-sha256; t=1789733072; cv=none; d=zohomail.com; s=zohoarc; b=EYT4piemcV/iZCfoFK1UXozO6R3ghqdvfv46JPPPrpXLfzKUDvtNx5nzq6qaBheaiL9LrmRnAProWXs6aSjRWsfLarUDaKZz9s7zRqyUCnNr01LSKgPYLzkvyyxYiXEVhh0jtauxqGq5hTocEQGzrrNf4JiidOE4mpKPjIyYocU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1789733072; h=Content-Type: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:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=I/XWlbU9dLJPE5pSPEJjU6isaIAOGtOn1+56ifWRmvQ=; b=O7nUOPE+Hpq4jch0QaPdExfLmKogUESIads6LKELG+slev+0bzK6mIJE3yCDg+iIv8krW+XZj9CXq/FAjMQ7v+G4KhWjTQzp5VtaRleRgw/rC+gcySoLRYJ2riy9krTiswi0PhVyTFzbLujQEtkMFtmzBpUQJvBLZpaTm8sxFy0= 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=quarantine dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1789733072248651.8603466359409; Fri, 18 Sep 2026 05:04:32 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x7XJl-0000Cp-RH; Fri, 18 Sep 2026 08:03:50 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x7UqL-0006ts-9w; Fri, 18 Sep 2026 05:25:17 -0400 Received: from canpmsgout02.his.huawei.com ([113.46.200.217]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x7UqE-0002IG-J4; Fri, 18 Sep 2026 05:25:15 -0400 Received: from mail.maildlp.com (unknown [172.19.162.197]) by canpmsgout02.his.huawei.com (SkyGuard) with ESMTPS id 4hmRkb6nv7zcb4D; Fri, 18 Sep 2026 17:13:43 +0800 (CST) Received: from dggpemr200003.china.huawei.com (unknown [7.185.36.25]) by mail.maildlp.com (Postfix) with ESMTPS id 0E37140593; Fri, 18 Sep 2026 17:24:59 +0800 (CST) Received: from huawei.com (10.50.159.234) by dggpemr200003.china.huawei.com (7.185.36.25) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.46; Fri, 18 Sep 2026 17:24:58 +0800 dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=I/XWlbU9dLJPE5pSPEJjU6isaIAOGtOn1+56ifWRmvQ=; b=BWYCkJdLwQdQkFQQhzcg4v+78AqJqvyvQA9zb4MmYFLR9ZRdNSm219Gy8KoiEqxJ+xnu3u4t6 sVXNvFl1A5VeJzwVxoACIfpNhzszDvtHRlTE+qduhnNeHma+q9ALYtebUq4a3ZocjBluvOLp4sU MeMaYP+QQRY1uaJRguRWNfc= From: Yize Wang To: , CC: , , , , , , , Subject: [PATCH 3/4] hw/intc/arm_gicv3_kvm: Refactor kvm_arm_gicv3_put for batch register access Date: Fri, 18 Sep 2026 17:18:55 +0800 Message-ID: <20260918092120.370805-4-wangyize7@huawei.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260918092120.370805-1-wangyize7@huawei.com> References: <20260918092120.370805-1-wangyize7@huawei.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Originating-IP: [10.50.159.234] X-ClientProxiedBy: kwepems200001.china.huawei.com (7.221.188.67) To dggpemr200003.china.huawei.com (7.185.36.25) 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=lists1p.gnu.org; Received-SPF: pass client-ip=113.46.200.217; envelope-from=wangyize7@huawei.com; helo=canpmsgout02.his.huawei.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_MSPIKE_H2=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Fri, 18 Sep 2026 08:02:42 -0400 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development 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 @huawei.com) X-ZM-MESSAGEID: 1789733074923158500 Content-Type: text/plain; charset="utf-8" Refactor kvm_arm_gicv3_put and add auxiliary functions to implement batch register access. Auxiliary functions: -kvm_arm_gic_batch_write_plpis: batch write to LPI -kvm_arm_gic_batch_write_redist: batch write to Redistributor -kvm_arm_gic_batch_write_cpuif: batch write to CPU Interface Signed-off-by: Chuan Zheng Signed-off-by: Yize Wang --- hw/intc/arm_gicv3_kvm.c | 524 ++++++++++++++++++++++++++++++++-------- 1 file changed, 425 insertions(+), 99 deletions(-) diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c index ea6c8462c7..1fdc554fe0 100644 --- a/hw/intc/arm_gicv3_kvm.c +++ b/hw/intc/arm_gicv3_kvm.c @@ -34,6 +34,7 @@ #include "migration/misc.h" #include "qom/object.h" #include "target/arm/cpregs.h" +#include "exec/cpu-defs.h" =20 =20 #define TYPE_KVM_ARM_GICV3 "kvm-arm-gicv3" @@ -409,11 +410,298 @@ static void kvm_arm_gicv3_check(GICv3State *s) } } =20 +/* Write to the LPI base address registers in batches */ +static void kvm_arm_gic_batch_write_plpis(GICv3State *s, + GICv3BatchEntry **entries, + uint64_t redist_typer, + int *batch_n, + int *batch_capacity) +{ + if (!(redist_typer & GICR_TYPER_PLPIS)) { + return; + } + + /* + * Allocate temporary buffers for the LPI base addresses + * of all CPUs. + */ + uint32_t *plpis =3D g_new(uint32_t, s->num_cpu * 4); + + for (int ncpu =3D 0; ncpu < s->num_cpu; ncpu++) { + GICv3CPUState *c =3D &s->cpu[ncpu]; + int base =3D ncpu * 4; + + /* Split the 64-bit base address into two 32-bit values. */ + plpis[base] =3D (uint32_t)c->gicr_propbaser; + plpis[base + 1] =3D (uint32_t)(c->gicr_propbaser >> 32); + plpis[base + 2] =3D (uint32_t)c->gicr_pendbaser; + plpis[base + 3] =3D (uint32_t)(c->gicr_pendbaser >> 32); + + /* Add to batch queueing */ + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_REDIST_REGS, + KVM_VGIC_ATTR(GICR_PROPBASER, c->gicr_typer), + &plpis[base]); + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_REDIST_REGS, + KVM_VGIC_ATTR(GICR_PROPBASER + 4, c->gicr_ty= per), + &plpis[base + 1]); + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_REDIST_REGS, + KVM_VGIC_ATTR(GICR_PENDBASER, c->gicr_typer), + &plpis[base + 2]); + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_REDIST_REGS, + KVM_VGIC_ATTR(GICR_PENDBASER + 4, c->gicr_ty= per), + &plpis[base + 3]); + } + + /* + * Submit the LPI base address immediately. + * Note: After submission, the caller is responsible for resetting bat= ch_n + * to reuse the entries array. + */ + kvm_arm_gic_batch_commit(s->dev_fd, *entries, *batch_n, true); + g_free(plpis); +} + +/* Write to the Redistributor common registers in batches */ +static void kvm_arm_gic_batch_write_redist(GICv3State *s, + GICv3BatchEntry **entries, + int *batch_n, + int *batch_capacity) +{ + uint32_t clear_all =3D ~0; + uint32_t *redist_icfgr1 =3D g_new(uint32_t, s->num_cpu); + uint32_t *redist_priority =3D g_new(uint32_t, + s->num_cpu * (GIC_INTERNAL / 4)); + + for (int ncpu =3D 0; ncpu < s->num_cpu; ncpu++) { + GICv3CPUState *c =3D &s->cpu[ncpu]; + int pri_base =3D ncpu * (GIC_INTERNAL / 4); + + redist_icfgr1[ncpu] =3D half_shuffle32(c->edge_trigger >> 16) << 1; + + /* control and status register */ + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_REDIST_REGS, + KVM_VGIC_ATTR(GICR_CTLR, c->gicr_typer), + &c->gicr_ctlr); + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_REDIST_REGS, + KVM_VGIC_ATTR(GICR_STATUSR, c->gicr_typer), + &c->gicr_statusr[GICV3_NS]); + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_REDIST_REGS, + KVM_VGIC_ATTR(GICR_WAKER, c->gicr_typer), + &c->gicr_waker); + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_REDIST_REGS, + KVM_VGIC_ATTR(GICR_IGROUPR0, c->gicr_typer), + &c->gicr_igroupr0); + + /* Enable register (clear-set mode) */ + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_REDIST_REGS, + KVM_VGIC_ATTR(GICR_ICENABLER0, c->gicr_typer= ), + &clear_all); + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_REDIST_REGS, + KVM_VGIC_ATTR(GICR_ISENABLER0, c->gicr_typer= ), + &c->gicr_ienabler0); + + /* Configure register */ + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_REDIST_REGS, + KVM_VGIC_ATTR(GICR_ICFGR1, c->gicr_typer), + &redist_icfgr1[ncpu]); + + /* Level information */ + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO, + KVM_VGIC_ATTR(0, c->gicr_typer) | + (VGIC_LEVEL_INFO_LINE_LEVEL << + KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT), + &c->level); + + /* Suspend register (Clear-Set mode) */ + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_REDIST_REGS, + KVM_VGIC_ATTR(GICR_ICPENDR0, c->gicr_typer), + &clear_all); + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_REDIST_REGS, + KVM_VGIC_ATTR(GICR_ISPENDR0, c->gicr_typer), + &c->gicr_ipendr0); + + /* Activation register (Clear-Set mode) */ + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_REDIST_REGS, + KVM_VGIC_ATTR(GICR_ICACTIVER0, c->gicr_typer= ), + &clear_all); + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_REDIST_REGS, + KVM_VGIC_ATTR(GICR_ISACTIVER0, c->gicr_typer= ), + &c->gicr_iactiver0); + + /* Priority register (written in packet mode) */ + for (int i =3D 0; i < GIC_INTERNAL; i +=3D 4) { + redist_priority[pri_base + i / 4] =3D + c->gicr_ipriorityr[i] | + (c->gicr_ipriorityr[i + 1] << 8) | + (c->gicr_ipriorityr[i + 2] << 16) | + (c->gicr_ipriorityr[i + 3] << 24); + + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_REDIST_REGS, + KVM_VGIC_ATTR(GICR_IPRIORITYR + i, + c->gicr_typer), + &redist_priority[pri_base + i / 4]); + } + } + + /* Submit all Redistributor statuses */ + kvm_arm_gic_batch_commit(s->dev_fd, *entries, *batch_n, true); + + g_free(redist_icfgr1); + g_free(redist_priority); +} + +/* Batch Write to CPU Interface */ +static void kvm_arm_gic_batch_write_cpuif(GICv3State *s, + GICv3BatchEntry **entries, + int *batch_n, + int *batch_capacity) +{ + uint32_t *cpuif_sre =3D g_new0(uint32_t, s->num_cpu); + uint32_t *cpuif_ctlr =3D g_new0(uint32_t, s->num_cpu); + uint32_t *cpuif_igrpen0 =3D g_new0(uint32_t, s->num_cpu); + uint32_t *cpuif_igrpen1 =3D g_new0(uint32_t, s->num_cpu); + uint32_t *cpuif_pmr =3D g_new0(uint32_t, s->num_cpu); + uint32_t *cpuif_bpr0 =3D g_new0(uint32_t, s->num_cpu); + uint32_t *cpuif_bpr1 =3D g_new0(uint32_t, s->num_cpu); + + for (int ncpu =3D 0; ncpu < s->num_cpu; ncpu++) { + GICv3CPUState *c =3D &s->cpu[ncpu]; + int num_pri_bits; + + /* Basic system registers */ + cpuif_sre[ncpu] =3D c->icc_sre_el1; + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, + KVM_VGIC_ATTR(ICC_SRE_EL1, c->gicr_typer), + &cpuif_sre[ncpu]); + + cpuif_ctlr[ncpu] =3D c->icc_ctlr_el1[GICV3_NS]; + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, + KVM_VGIC_ATTR(ICC_CTLR_EL1, c->gicr_typer), + &cpuif_ctlr[ncpu]); + + cpuif_igrpen0[ncpu] =3D c->icc_igrpen[GICV3_G0]; + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, + KVM_VGIC_ATTR(ICC_IGRPEN0_EL1, c->gicr_typer= ), + &cpuif_igrpen0[ncpu]); + + cpuif_igrpen1[ncpu] =3D c->icc_igrpen[GICV3_G1NS]; + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, + KVM_VGIC_ATTR(ICC_IGRPEN1_EL1, c->gicr_typer= ), + &cpuif_igrpen1[ncpu]); + + cpuif_pmr[ncpu] =3D c->icc_pmr_el1; + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, + KVM_VGIC_ATTR(ICC_PMR_EL1, c->gicr_typer), + &cpuif_pmr[ncpu]); + + cpuif_bpr0[ncpu] =3D c->icc_bpr[GICV3_G0]; + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, + KVM_VGIC_ATTR(ICC_BPR0_EL1, c->gicr_typer), + &cpuif_bpr0[ncpu]); + + cpuif_bpr1[ncpu] =3D c->icc_bpr[GICV3_G1NS]; + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, + KVM_VGIC_ATTR(ICC_BPR1_EL1, c->gicr_typer), + &cpuif_bpr1[ncpu]); + + /* Calculate the number of priority bits */ + num_pri_bits =3D ((c->icc_ctlr_el1[GICV3_NS] & + ICC_CTLR_EL1_PRIBITS_MASK) >> + ICC_CTLR_EL1_PRIBITS_SHIFT) + 1; + + /* Group 0 APR */ + switch (num_pri_bits) { + case 7: + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, + KVM_VGIC_ATTR(ICC_AP0R_EL1(3), c->gicr_t= yper), + (uint32_t *)&c->icc_apr[GICV3_G0][3]); + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, + KVM_VGIC_ATTR(ICC_AP0R_EL1(2), c->gicr_t= yper), + (uint32_t *)&c->icc_apr[GICV3_G0][2]); + /* fall through */ + case 6: + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, + KVM_VGIC_ATTR(ICC_AP0R_EL1(1), c->gicr_t= yper), + (uint32_t *)&c->icc_apr[GICV3_G0][1]); + /* fall through */ + default: + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, + KVM_VGIC_ATTR(ICC_AP0R_EL1(0), c->gicr_t= yper), + (uint32_t *)&c->icc_apr[GICV3_G0][0]); + } + + /* Group 1 APR */ + switch (num_pri_bits) { + case 7: + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, + KVM_VGIC_ATTR(ICC_AP1R_EL1(3), c->gicr_t= yper), + (uint32_t *)&c->icc_apr[GICV3_G1NS][3]); + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, + KVM_VGIC_ATTR(ICC_AP1R_EL1(2), c->gicr_t= yper), + (uint32_t *)&c->icc_apr[GICV3_G1NS][2]); + /* fall through */ + case 6: + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, + KVM_VGIC_ATTR(ICC_AP1R_EL1(1), c->gicr_t= yper), + (uint32_t *)&c->icc_apr[GICV3_G1NS][1]); + /* fall through */ + default: + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, + KVM_VGIC_ATTR(ICC_AP1R_EL1(0), c->gicr_t= yper), + (uint32_t *)&c->icc_apr[GICV3_G1NS][0]); + } + } + + /* Submit all CPU Interface statuses */ + kvm_arm_gic_batch_commit(s->dev_fd, *entries, *batch_n, true); + + g_free(cpuif_sre); + g_free(cpuif_ctlr); + g_free(cpuif_igrpen0); + g_free(cpuif_igrpen1); + g_free(cpuif_pmr); + g_free(cpuif_bpr0); + g_free(cpuif_bpr1); +} + static void kvm_arm_gicv3_put(GICv3State *s) { uint32_t regl, regh, reg; uint64_t reg64, redist_typer; int ncpu, i; + bool batch_supported; int64_t start_time =3D qemu_clock_get_ms(QEMU_CLOCK_REALTIME); =20 kvm_arm_gicv3_check(s); @@ -425,71 +713,95 @@ static void kvm_arm_gicv3_put(GICv3State *s) reg =3D s->gicd_ctlr; kvm_gicd_access(s, GICD_CTLR, ®, true); =20 - if (redist_typer & GICR_TYPER_PLPIS) { - /* - * Restore base addresses before LPIs are potentially enabled by - * GICR_CTLR write - */ - for (ncpu =3D 0; ncpu < s->num_cpu; ncpu++) { - GICv3CPUState *c =3D &s->cpu[ncpu]; + batch_supported =3D kvm_arm_gic_batch_supported(s->dev_fd); + + if (batch_supported) { + { + GICv3BatchEntry *entries =3D g_new(GICv3BatchEntry, 256); + int batch_n =3D 0; + int batch_capacity =3D 256; + + /* write LPI */ + kvm_arm_gic_batch_write_plpis(s, &entries, redist_typer, + &batch_n, &batch_capacity); + + /* reset batch_n */ + batch_n =3D 0; + + /* write Redistributor status */ + kvm_arm_gic_batch_write_redist(s, &entries, &batch_n, + &batch_capacity); =20 - reg64 =3D c->gicr_propbaser; - regl =3D (uint32_t)reg64; - kvm_gicr_access(s, GICR_PROPBASER, ncpu, ®l, true); - regh =3D (uint32_t)(reg64 >> 32); - kvm_gicr_access(s, GICR_PROPBASER + 4, ncpu, ®h, true); - - reg64 =3D c->gicr_pendbaser; - regl =3D (uint32_t)reg64; - kvm_gicr_access(s, GICR_PENDBASER, ncpu, ®l, true); - regh =3D (uint32_t)(reg64 >> 32); - kvm_gicr_access(s, GICR_PENDBASER + 4, ncpu, ®h, true); + g_free(entries); + } + } else { + if (redist_typer & GICR_TYPER_PLPIS) { + /* + * Restore base addresses before LPIs are potentially enabled = by + * GICR_CTLR write + */ + for (ncpu =3D 0; ncpu < s->num_cpu; ncpu++) { + GICv3CPUState *c =3D &s->cpu[ncpu]; + + reg64 =3D c->gicr_propbaser; + regl =3D (uint32_t)reg64; + kvm_gicr_access(s, GICR_PROPBASER, ncpu, ®l, true); + regh =3D (uint32_t)(reg64 >> 32); + kvm_gicr_access(s, GICR_PROPBASER + 4, ncpu, ®h, true); + + reg64 =3D c->gicr_pendbaser; + regl =3D (uint32_t)reg64; + kvm_gicr_access(s, GICR_PENDBASER, ncpu, ®l, true); + regh =3D (uint32_t)(reg64 >> 32); + kvm_gicr_access(s, GICR_PENDBASER + 4, ncpu, ®h, true); + } } - } =20 - /* Redistributor state (one per CPU) */ + /* Redistributor state (one per CPU) */ =20 - for (ncpu =3D 0; ncpu < s->num_cpu; ncpu++) { - GICv3CPUState *c =3D &s->cpu[ncpu]; + for (ncpu =3D 0; ncpu < s->num_cpu; ncpu++) { + GICv3CPUState *c =3D &s->cpu[ncpu]; + uint32_t clear_all =3D ~0; =20 - reg =3D c->gicr_ctlr; - kvm_gicr_access(s, GICR_CTLR, ncpu, ®, true); + reg =3D c->gicr_ctlr; + kvm_gicr_access(s, GICR_CTLR, ncpu, ®, true); =20 - reg =3D c->gicr_statusr[GICV3_NS]; - kvm_gicr_access(s, GICR_STATUSR, ncpu, ®, true); + reg =3D c->gicr_statusr[GICV3_NS]; + kvm_gicr_access(s, GICR_STATUSR, ncpu, ®, true); =20 - reg =3D c->gicr_waker; - kvm_gicr_access(s, GICR_WAKER, ncpu, ®, true); + reg =3D c->gicr_waker; + kvm_gicr_access(s, GICR_WAKER, ncpu, ®, true); =20 - reg =3D c->gicr_igroupr0; - kvm_gicr_access(s, GICR_IGROUPR0, ncpu, ®, true); + reg =3D c->gicr_igroupr0; + kvm_gicr_access(s, GICR_IGROUPR0, ncpu, ®, true); =20 - reg =3D ~0; - kvm_gicr_access(s, GICR_ICENABLER0, ncpu, ®, true); - reg =3D c->gicr_ienabler0; - kvm_gicr_access(s, GICR_ISENABLER0, ncpu, ®, true); + reg =3D clear_all; + kvm_gicr_access(s, GICR_ICENABLER0, ncpu, ®, true); + reg =3D c->gicr_ienabler0; + kvm_gicr_access(s, GICR_ISENABLER0, ncpu, ®, true); =20 - /* Restore config before pending so we treat level/edge correctly = */ - reg =3D half_shuffle32(c->edge_trigger >> 16) << 1; - kvm_gicr_access(s, GICR_ICFGR1, ncpu, ®, true); + /* Restore config before pending so we treat level/edge correc= tly */ + reg =3D half_shuffle32(c->edge_trigger >> 16) << 1; + kvm_gicr_access(s, GICR_ICFGR1, ncpu, ®, true); =20 - reg =3D c->level; - kvm_gic_line_level_access(s, 0, ncpu, ®, true); + reg =3D c->level; + kvm_gic_line_level_access(s, 0, ncpu, ®, true); =20 - reg =3D c->gicr_ipendr0; - kvm_gicr_access(s, GICR_ISPENDR0, ncpu, ®, true); + reg =3D c->gicr_ipendr0; + kvm_gicr_access(s, GICR_ISPENDR0, ncpu, ®, true); =20 - reg =3D ~0; - kvm_gicr_access(s, GICR_ICACTIVER0, ncpu, ®, true); - reg =3D c->gicr_iactiver0; - kvm_gicr_access(s, GICR_ISACTIVER0, ncpu, ®, true); + reg =3D clear_all; + kvm_gicr_access(s, GICR_ICACTIVER0, ncpu, ®, true); + reg =3D c->gicr_iactiver0; + kvm_gicr_access(s, GICR_ISACTIVER0, ncpu, ®, true); =20 - for (i =3D 0; i < GIC_INTERNAL; i +=3D 4) { - reg =3D c->gicr_ipriorityr[i] | - (c->gicr_ipriorityr[i + 1] << 8) | - (c->gicr_ipriorityr[i + 2] << 16) | - (c->gicr_ipriorityr[i + 3] << 24); - kvm_gicr_access(s, GICR_IPRIORITYR + i, ncpu, ®, true); + for (i =3D 0; i < GIC_INTERNAL; i +=3D 4) { + reg =3D c->gicr_ipriorityr[i] | + (c->gicr_ipriorityr[i + 1] << 8) | + (c->gicr_ipriorityr[i + 2] << 16) | + (c->gicr_ipriorityr[i + 3] << 24); + kvm_gicr_access(s, GICR_IPRIORITYR + i, ncpu, ®, true); + } } } =20 @@ -540,57 +852,71 @@ static void kvm_arm_gicv3_put(GICv3State *s) /* s->gicd_ipriority[] -> GICD_IPRIORITYRn */ kvm_dist_put_priority(s, GICD_IPRIORITYR, s->gicd_ipriority); =20 - /* CPU Interface state (one per CPU) */ - - for (ncpu =3D 0; ncpu < s->num_cpu; ncpu++) { - GICv3CPUState *c =3D &s->cpu[ncpu]; - int num_pri_bits; + /* write CPU Interface status */ + if (batch_supported) { + { + GICv3BatchEntry *entries =3D g_new(GICv3BatchEntry, 256); + int batch_n =3D 0; + int batch_capacity =3D 256; =20 - kvm_gicc_access(s, ICC_SRE_EL1, ncpu, &c->icc_sre_el1, true); - kvm_gicc_access(s, ICC_CTLR_EL1, ncpu, - &c->icc_ctlr_el1[GICV3_NS], true); - kvm_gicc_access(s, ICC_IGRPEN0_EL1, ncpu, - &c->icc_igrpen[GICV3_G0], true); - kvm_gicc_access(s, ICC_IGRPEN1_EL1, ncpu, - &c->icc_igrpen[GICV3_G1NS], true); - kvm_gicc_access(s, ICC_PMR_EL1, ncpu, &c->icc_pmr_el1, true); - kvm_gicc_access(s, ICC_BPR0_EL1, ncpu, &c->icc_bpr[GICV3_G0], true= ); - kvm_gicc_access(s, ICC_BPR1_EL1, ncpu, &c->icc_bpr[GICV3_G1NS], tr= ue); + kvm_arm_gic_batch_write_cpuif(s, &entries, &batch_n, + &batch_capacity); =20 - num_pri_bits =3D ((c->icc_ctlr_el1[GICV3_NS] & - ICC_CTLR_EL1_PRIBITS_MASK) >> - ICC_CTLR_EL1_PRIBITS_SHIFT) + 1; - - switch (num_pri_bits) { - case 7: - reg64 =3D c->icc_apr[GICV3_G0][3]; - kvm_gicc_access(s, ICC_AP0R_EL1(3), ncpu, ®64, true); - reg64 =3D c->icc_apr[GICV3_G0][2]; - kvm_gicc_access(s, ICC_AP0R_EL1(2), ncpu, ®64, true); - /* fall through */ - case 6: - reg64 =3D c->icc_apr[GICV3_G0][1]; - kvm_gicc_access(s, ICC_AP0R_EL1(1), ncpu, ®64, true); - /* fall through */ - default: - reg64 =3D c->icc_apr[GICV3_G0][0]; - kvm_gicc_access(s, ICC_AP0R_EL1(0), ncpu, ®64, true); + g_free(entries); } - - switch (num_pri_bits) { - case 7: - reg64 =3D c->icc_apr[GICV3_G1NS][3]; - kvm_gicc_access(s, ICC_AP1R_EL1(3), ncpu, ®64, true); - reg64 =3D c->icc_apr[GICV3_G1NS][2]; - kvm_gicc_access(s, ICC_AP1R_EL1(2), ncpu, ®64, true); - /* fall through */ - case 6: - reg64 =3D c->icc_apr[GICV3_G1NS][1]; - kvm_gicc_access(s, ICC_AP1R_EL1(1), ncpu, ®64, true); - /* fall through */ - default: - reg64 =3D c->icc_apr[GICV3_G1NS][0]; - kvm_gicc_access(s, ICC_AP1R_EL1(0), ncpu, ®64, true); + } else { + /* CPU Interface state (one per CPU) */ + for (ncpu =3D 0; ncpu < s->num_cpu; ncpu++) { + GICv3CPUState *c =3D &s->cpu[ncpu]; + int num_pri_bits; + + kvm_gicc_access(s, ICC_SRE_EL1, ncpu, &c->icc_sre_el1, true); + kvm_gicc_access(s, ICC_CTLR_EL1, ncpu, + &c->icc_ctlr_el1[GICV3_NS], true); + kvm_gicc_access(s, ICC_IGRPEN0_EL1, ncpu, + &c->icc_igrpen[GICV3_G0], true); + kvm_gicc_access(s, ICC_IGRPEN1_EL1, ncpu, + &c->icc_igrpen[GICV3_G1NS], true); + kvm_gicc_access(s, ICC_PMR_EL1, ncpu, &c->icc_pmr_el1, true); + kvm_gicc_access(s, ICC_BPR0_EL1, ncpu, &c->icc_bpr[GICV3_G0], = true); + kvm_gicc_access(s, ICC_BPR1_EL1, ncpu, &c->icc_bpr[GICV3_G1NS], + true); + + num_pri_bits =3D ((c->icc_ctlr_el1[GICV3_NS] & + ICC_CTLR_EL1_PRIBITS_MASK) >> + ICC_CTLR_EL1_PRIBITS_SHIFT) + 1; + + switch (num_pri_bits) { + case 7: + reg64 =3D c->icc_apr[GICV3_G0][3]; + kvm_gicc_access(s, ICC_AP0R_EL1(3), ncpu, ®64, true); + reg64 =3D c->icc_apr[GICV3_G0][2]; + kvm_gicc_access(s, ICC_AP0R_EL1(2), ncpu, ®64, true); + /* fall through */ + case 6: + reg64 =3D c->icc_apr[GICV3_G0][1]; + kvm_gicc_access(s, ICC_AP0R_EL1(1), ncpu, ®64, true); + /* fall through */ + default: + reg64 =3D c->icc_apr[GICV3_G0][0]; + kvm_gicc_access(s, ICC_AP0R_EL1(0), ncpu, ®64, true); + } + + switch (num_pri_bits) { + case 7: + reg64 =3D c->icc_apr[GICV3_G1NS][3]; + kvm_gicc_access(s, ICC_AP1R_EL1(3), ncpu, ®64, true); + reg64 =3D c->icc_apr[GICV3_G1NS][2]; + kvm_gicc_access(s, ICC_AP1R_EL1(2), ncpu, ®64, true); + /* fall through */ + case 6: + reg64 =3D c->icc_apr[GICV3_G1NS][1]; + kvm_gicc_access(s, ICC_AP1R_EL1(1), ncpu, ®64, true); + /* fall through */ + default: + reg64 =3D c->icc_apr[GICV3_G1NS][0]; + kvm_gicc_access(s, ICC_AP1R_EL1(0), ncpu, ®64, true); + } } } int64_t end_time =3D qemu_clock_get_ms(QEMU_CLOCK_REALTIME); --=20 2.43.0 From nobody Sat Sep 26 21:36:42 2026 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=quarantine dis=none) header.from=huawei.com ARC-Seal: i=1; a=rsa-sha256; t=1789733072; cv=none; d=zohomail.com; s=zohoarc; b=mtETyOn3c8CxS+KP0BJuxq+XkVECrIz8wVPPE8OIH4BvMbGD0n7WQ8namYuBB/xZuKiq5t/9e5buFlQzs8JBWqfE/HNUGHL43JLm+C7zbDvrY+QhXV1AzYnyUol13+HDjhmhTkuhgAil7Yw+PV17/6TmI+AlnHlhUtlZuAt+3I4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1789733072; h=Content-Type: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:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=oiMc5094IuzNP38KU2sYyZD8Az71EFWawwwkB2DwgYQ=; b=c1yM3oXeAM7yqlTZ02Jvcw89QUuKzVs6UZECMrGH/gnn8Q4QR3KoWTJ/oTySM5bQW2NrBU3MucwB1NFyJg1WMk+zITp4/GjgBujvVVrylSG5WvfJDlVAO1CLjY8NphSikUq45M2m2viLko3tDmZsmum5/rssPEaEP5hLBsMpsQc= 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=quarantine dis=none) Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1789733072202610.975049417624; Fri, 18 Sep 2026 05:04:32 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x7XKB-0000Qq-3O; Fri, 18 Sep 2026 08:04:15 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x7UqL-0006tr-9O; Fri, 18 Sep 2026 05:25:17 -0400 Received: from canpmsgout03.his.huawei.com ([113.46.200.218]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x7UqE-0002IE-Ik; Fri, 18 Sep 2026 05:25:15 -0400 Received: from mail.maildlp.com (unknown [172.19.163.0]) by canpmsgout03.his.huawei.com (SkyGuard) with ESMTPS id 4hmRjy5SnPzpStW; Fri, 18 Sep 2026 17:13:10 +0800 (CST) Received: from dggpemr200003.china.huawei.com (unknown [7.185.36.25]) by mail.maildlp.com (Postfix) with ESMTPS id D6DB340537; Fri, 18 Sep 2026 17:24:59 +0800 (CST) Received: from huawei.com (10.50.159.234) by dggpemr200003.china.huawei.com (7.185.36.25) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.46; Fri, 18 Sep 2026 17:24:58 +0800 dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=oiMc5094IuzNP38KU2sYyZD8Az71EFWawwwkB2DwgYQ=; b=DZiCYfOrhjNQtsaH+HW+92ZqCJdDAViY+rvOKTXEQ2CKTfpt2wkgfQ1QdPjpsNTlCiqa05cjJ if0dsd1v6Fkz6aGYpHw5TvWRAqcW1NDgNzXZuIMp8CNmBlz+4i8f2pQsJuXGXKHiOgoBeON0ZDQ yDtklMs47L1+3rH5hU02YH0= From: Yize Wang To: , CC: , , , , , , , Subject: [PATCH 4/4] hw/intc/arm_gicv3_kvm: Refactor kvm_arm_gicv3_get for batch register access Date: Fri, 18 Sep 2026 17:18:56 +0800 Message-ID: <20260918092120.370805-5-wangyize7@huawei.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260918092120.370805-1-wangyize7@huawei.com> References: <20260918092120.370805-1-wangyize7@huawei.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Originating-IP: [10.50.159.234] X-ClientProxiedBy: kwepems200001.china.huawei.com (7.221.188.67) To dggpemr200003.china.huawei.com (7.185.36.25) 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=lists1p.gnu.org; Received-SPF: pass client-ip=113.46.200.218; envelope-from=wangyize7@huawei.com; helo=canpmsgout03.his.huawei.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_MSPIKE_H2=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Mailman-Approved-At: Fri, 18 Sep 2026 08:02:37 -0400 X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development 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 @huawei.com) X-ZM-MESSAGEID: 1789733075090158500 Content-Type: text/plain; charset="utf-8" Replace the kvm_arm_gicv3_get function with a batched implementation that uses the batch helpers added in Task 4. The new function: 1. Detects batch support using kvm_arm_gic_batch_supported() 2. When batch is supported: - Batches redistributor register accesses for all vCPUs and commits after the loop, with post-processing for ICFGR1 transformation and IPRIORITYR byte splitting - Batches PLPIS propbaser/pendbaser accesses when applicable - Batches CPU interface basic registers for all enabled vCPUs - Batches CPU interface APR registers based on num_pri_bits 3. Falls back to existing per-register ioctl calls when batch is not supported 4. Keeps all distributor accesses unchanged Also add auxiliary functions to implement batch operations: -kvm_arm_gic_batch_get_redist: read Redistributor common registers in batches -kvm_arm_gic_batch_get_plpis: read the LPI base address registers in batches -kvm_arm_gic_batch_get_cpuif_basic: read the CPU interface basic registers in batches -kvm_arm_gic_batch_get_cpuif_apr: read the CPU Interface APR Registers in batches This reduces the number of KVM device attribute ioctls from O(num_cpu * registers_per_cpu) to a small constant number of batch commits. Signed-off-by: Chuan Zheng Signed-off-by: Yize Wang --- hw/intc/arm_gicv3_kvm.c | 500 +++++++++++++++++++++++++++++++++------- 1 file changed, 412 insertions(+), 88 deletions(-) diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c index 1fdc554fe0..16f851b0ae 100644 --- a/hw/intc/arm_gicv3_kvm.c +++ b/hw/intc/arm_gicv3_kvm.c @@ -923,11 +923,293 @@ static void kvm_arm_gicv3_put(GICv3State *s) info_report("kvm_arm_gicv3_put, time=3D%ldms", end_time - start_time); } =20 +/* Read Redistributor common registers in batches */ +static void kvm_arm_gic_batch_get_redist(GICv3State *s, + GICv3BatchEntry **entries, + int *batch_n, + int *batch_capacity) +{ + uint32_t *redist_priority =3D g_new(uint32_t, + s->num_cpu * (GIC_INTERNAL / 4)); + + for (int ncpu =3D 0; ncpu < s->num_cpu; ncpu++) { + GICv3CPUState *c =3D &s->cpu[ncpu]; + int pri_base =3D ncpu * (GIC_INTERNAL / 4); + + /* Redistributor state (one per CPU) */ + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_REDIST_REGS, + KVM_VGIC_ATTR(GICR_CTLR, c->gicr_typer), + &c->gicr_ctlr); + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_REDIST_REGS, + KVM_VGIC_ATTR(GICR_STATUSR, c->gicr_typer), + &c->gicr_statusr[GICV3_NS]); + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_REDIST_REGS, + KVM_VGIC_ATTR(GICR_WAKER, c->gicr_typer), + &c->gicr_waker); + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_REDIST_REGS, + KVM_VGIC_ATTR(GICR_IGROUPR0, c->gicr_typer), + &c->gicr_igroupr0); + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_REDIST_REGS, + KVM_VGIC_ATTR(GICR_ISENABLER0, c->gicr_typer= ), + &c->gicr_ienabler0); + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_REDIST_REGS, + KVM_VGIC_ATTR(GICR_ICFGR1, c->gicr_typer), + &c->edge_trigger); + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO, + KVM_VGIC_ATTR(0, c->gicr_typer) | + (VGIC_LEVEL_INFO_LINE_LEVEL << + KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT), + &c->level); + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_REDIST_REGS, + KVM_VGIC_ATTR(GICR_ISPENDR0, c->gicr_typer), + &c->gicr_ipendr0); + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_REDIST_REGS, + KVM_VGIC_ATTR(GICR_ISACTIVER0, c->gicr_typer= ), + &c->gicr_iactiver0); + + for (int i =3D 0; i < GIC_INTERNAL; i +=3D 4) { + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_REDIST_REGS, + KVM_VGIC_ATTR(GICR_IPRIORITYR + i, + c->gicr_typer), + &redist_priority[pri_base + i / 4]); + } + } + kvm_arm_gic_batch_commit(s->dev_fd, *entries, *batch_n, false); + + /* Post-process redistributor results */ + for (int ncpu =3D 0; ncpu < s->num_cpu; ncpu++) { + GICv3CPUState *c =3D &s->cpu[ncpu]; + int pri_base =3D ncpu * (GIC_INTERNAL / 4); + + c->edge_trigger =3D half_unshuffle32(c->edge_trigger >> 1) << 16; + + for (int i =3D 0; i < GIC_INTERNAL; i +=3D 4) { + uint32_t val =3D redist_priority[pri_base + i / 4]; + c->gicr_ipriorityr[i] =3D extract32(val, 0, 8); + c->gicr_ipriorityr[i + 1] =3D extract32(val, 8, 8); + c->gicr_ipriorityr[i + 2] =3D extract32(val, 16, 8); + c->gicr_ipriorityr[i + 3] =3D extract32(val, 24, 8); + } + } + + g_free(redist_priority); +} + +/* Read the LPI base address registers in batches */ +static void kvm_arm_gic_batch_get_plpis(GICv3State *s, + GICv3BatchEntry **entries, + uint64_t redist_typer, + int *batch_n, + int *batch_capacity) +{ + if (!(redist_typer & GICR_TYPER_PLPIS)) { + return; + } + + uint32_t *plpis =3D g_new(uint32_t, s->num_cpu * 4); + + for (int ncpu =3D 0; ncpu < s->num_cpu; ncpu++) { + GICv3CPUState *c =3D &s->cpu[ncpu]; + int base =3D ncpu * 4; + + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_REDIST_REGS, + KVM_VGIC_ATTR(GICR_PROPBASER, c->gicr_typer), + &plpis[base]); + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_REDIST_REGS, + KVM_VGIC_ATTR(GICR_PROPBASER + 4, c->gicr_ty= per), + &plpis[base + 1]); + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_REDIST_REGS, + KVM_VGIC_ATTR(GICR_PENDBASER, c->gicr_typer), + &plpis[base + 2]); + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_REDIST_REGS, + KVM_VGIC_ATTR(GICR_PENDBASER + 4, c->gicr_ty= per), + &plpis[base + 3]); + } + + kvm_arm_gic_batch_commit(s->dev_fd, *entries, *batch_n, false); + + for (int ncpu =3D 0; ncpu < s->num_cpu; ncpu++) { + GICv3CPUState *c =3D &s->cpu[ncpu]; + int base =3D ncpu * 4; + + c->gicr_propbaser =3D ((uint64_t)plpis[base + 1] << 32) | plpis[ba= se]; + c->gicr_pendbaser =3D ((uint64_t)plpis[base + 3] << 32) | plpis[ba= se + 2]; + } + + g_free(plpis); +} + +/* Read the CPU interface basic registers in batches */ +static void kvm_arm_gic_batch_get_cpuif_basic(GICv3State *s, + GICv3BatchEntry **entries, + int *batch_n, + int *batch_capacity) +{ + uint32_t *cpuif_sre =3D g_new0(uint32_t, s->num_cpu); + uint32_t *cpuif_ctlr =3D g_new0(uint32_t, s->num_cpu); + uint32_t *cpuif_igrpen0 =3D g_new0(uint32_t, s->num_cpu); + uint32_t *cpuif_igrpen1 =3D g_new0(uint32_t, s->num_cpu); + uint32_t *cpuif_pmr =3D g_new0(uint32_t, s->num_cpu); + uint32_t *cpuif_bpr0 =3D g_new0(uint32_t, s->num_cpu); + uint32_t *cpuif_bpr1 =3D g_new0(uint32_t, s->num_cpu); + + /* CPU Interface - basic registers */ + for (int ncpu =3D 0; ncpu < s->num_cpu; ncpu++) { + GICv3CPUState *c =3D &s->cpu[ncpu]; + + cpuif_sre[ncpu] =3D c->icc_sre_el1; + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, + KVM_VGIC_ATTR(ICC_SRE_EL1, c->gicr_typer), + &cpuif_sre[ncpu]); + + cpuif_ctlr[ncpu] =3D c->icc_ctlr_el1[GICV3_NS]; + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, + KVM_VGIC_ATTR(ICC_CTLR_EL1, c->gicr_typer), + &cpuif_ctlr[ncpu]); + + cpuif_igrpen0[ncpu] =3D c->icc_igrpen[GICV3_G0]; + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, + KVM_VGIC_ATTR(ICC_IGRPEN0_EL1, c->gicr_typer= ), + &cpuif_igrpen0[ncpu]); + + cpuif_igrpen1[ncpu] =3D c->icc_igrpen[GICV3_G1NS]; + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, + KVM_VGIC_ATTR(ICC_IGRPEN1_EL1, c->gicr_typer= ), + &cpuif_igrpen1[ncpu]); + + cpuif_pmr[ncpu] =3D c->icc_pmr_el1; + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, + KVM_VGIC_ATTR(ICC_PMR_EL1, c->gicr_typer), + &cpuif_pmr[ncpu]); + + cpuif_bpr0[ncpu] =3D c->icc_bpr[GICV3_G0]; + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, + KVM_VGIC_ATTR(ICC_BPR0_EL1, c->gicr_typer), + &cpuif_bpr0[ncpu]); + + cpuif_bpr1[ncpu] =3D c->icc_bpr[GICV3_G1NS]; + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, + KVM_VGIC_ATTR(ICC_BPR1_EL1, c->gicr_typer), + &cpuif_bpr1[ncpu]); + } + kvm_arm_gic_batch_commit(s->dev_fd, *entries, *batch_n, false); + + /* Copy back basic CPU interface registers */ + for (int ncpu =3D 0; ncpu < s->num_cpu; ncpu++) { + GICv3CPUState *c =3D &s->cpu[ncpu]; + + c->icc_sre_el1 =3D cpuif_sre[ncpu]; + c->icc_ctlr_el1[GICV3_NS] =3D cpuif_ctlr[ncpu]; + c->icc_igrpen[GICV3_G0] =3D cpuif_igrpen0[ncpu]; + c->icc_igrpen[GICV3_G1NS] =3D cpuif_igrpen1[ncpu]; + c->icc_pmr_el1 =3D cpuif_pmr[ncpu]; + c->icc_bpr[GICV3_G0] =3D cpuif_bpr0[ncpu]; + c->icc_bpr[GICV3_G1NS] =3D cpuif_bpr1[ncpu]; + } + + g_free(cpuif_sre); + g_free(cpuif_ctlr); + g_free(cpuif_igrpen0); + g_free(cpuif_igrpen1); + g_free(cpuif_pmr); + g_free(cpuif_bpr0); + g_free(cpuif_bpr1); +} + +/* Read the CPU Interface APR Registers in Batches */ +static void kvm_arm_gic_batch_get_cpuif_apr(GICv3State *s, + GICv3BatchEntry **entries, + int *batch_n, + int *batch_capacity) +{ + for (int ncpu =3D 0; ncpu < s->num_cpu; ncpu++) { + GICv3CPUState *c =3D &s->cpu[ncpu]; + int num_pri_bits; + + num_pri_bits =3D ((c->icc_ctlr_el1[GICV3_NS] & + ICC_CTLR_EL1_PRIBITS_MASK) >> + ICC_CTLR_EL1_PRIBITS_SHIFT) + 1; + + /* Group 0 APR */ + switch (num_pri_bits) { + case 7: + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, + KVM_VGIC_ATTR(ICC_AP0R_EL1(3), c->gicr_t= yper), + (uint32_t *)&c->icc_apr[GICV3_G0][3]); + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, + KVM_VGIC_ATTR(ICC_AP0R_EL1(2), c->gicr_t= yper), + (uint32_t *)&c->icc_apr[GICV3_G0][2]); + /* fall through */ + case 6: + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, + KVM_VGIC_ATTR(ICC_AP0R_EL1(1), c->gicr_t= yper), + (uint32_t *)&c->icc_apr[GICV3_G0][1]); + /* fall through */ + default: + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, + KVM_VGIC_ATTR(ICC_AP0R_EL1(0), c->gicr_t= yper), + (uint32_t *)&c->icc_apr[GICV3_G0][0]); + } + + /* Group 1 APR */ + switch (num_pri_bits) { + case 7: + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, + KVM_VGIC_ATTR(ICC_AP1R_EL1(3), c->gicr_t= yper), + (uint32_t *)&c->icc_apr[GICV3_G1NS][3]); + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, + KVM_VGIC_ATTR(ICC_AP1R_EL1(2), c->gicr_t= yper), + (uint32_t *)&c->icc_apr[GICV3_G1NS][2]); + /* fall through */ + case 6: + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, + KVM_VGIC_ATTR(ICC_AP1R_EL1(1), c->gicr_t= yper), + (uint32_t *)&c->icc_apr[GICV3_G1NS][1]); + /* fall through */ + default: + kvm_arm_gic_batch_add(entries, batch_n, batch_capacity, + KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS, + KVM_VGIC_ATTR(ICC_AP1R_EL1(0), c->gicr_t= yper), + (uint32_t *)&c->icc_apr[GICV3_G1NS][0]); + } + } + kvm_arm_gic_batch_commit(s->dev_fd, *entries, *batch_n, false); +} + static void kvm_arm_gicv3_get(GICv3State *s) { uint32_t regl, regh, reg; uint64_t reg64, redist_typer; int ncpu, i; + bool batch_supported; int64_t start_time =3D qemu_clock_get_ms(QEMU_CLOCK_REALTIME); =20 kvm_arm_gicv3_check(s); @@ -939,58 +1221,80 @@ static void kvm_arm_gicv3_get(GICv3State *s) kvm_gicd_access(s, GICD_CTLR, ®, false); s->gicd_ctlr =3D reg; =20 - /* Redistributor state (one per CPU) */ + /* Check whether the kernel supports batch operations */ + batch_supported =3D kvm_arm_gic_batch_supported(s->dev_fd); =20 - for (ncpu =3D 0; ncpu < s->num_cpu; ncpu++) { - GICv3CPUState *c =3D &s->cpu[ncpu]; + if (batch_supported) { + { + GICv3BatchEntry *entries =3D g_new(GICv3BatchEntry, 256); + int batch_n =3D 0; + int batch_capacity =3D 256; =20 - kvm_gicr_access(s, GICR_CTLR, ncpu, ®, false); - c->gicr_ctlr =3D reg; - - kvm_gicr_access(s, GICR_STATUSR, ncpu, ®, false); - c->gicr_statusr[GICV3_NS] =3D reg; - - kvm_gicr_access(s, GICR_WAKER, ncpu, ®, false); - c->gicr_waker =3D reg; - - kvm_gicr_access(s, GICR_IGROUPR0, ncpu, ®, false); - c->gicr_igroupr0 =3D reg; - kvm_gicr_access(s, GICR_ISENABLER0, ncpu, ®, false); - c->gicr_ienabler0 =3D reg; - kvm_gicr_access(s, GICR_ICFGR1, ncpu, ®, false); - c->edge_trigger =3D half_unshuffle32(reg >> 1) << 16; - kvm_gic_line_level_access(s, 0, ncpu, ®, false); - c->level =3D reg; - kvm_gicr_access(s, GICR_ISPENDR0, ncpu, ®, false); - c->gicr_ipendr0 =3D reg; - kvm_gicr_access(s, GICR_ISACTIVER0, ncpu, ®, false); - c->gicr_iactiver0 =3D reg; - - for (i =3D 0; i < GIC_INTERNAL; i +=3D 4) { - kvm_gicr_access(s, GICR_IPRIORITYR + i, ncpu, ®, false); - c->gicr_ipriorityr[i] =3D extract32(reg, 0, 8); - c->gicr_ipriorityr[i + 1] =3D extract32(reg, 8, 8); - c->gicr_ipriorityr[i + 2] =3D extract32(reg, 16, 8); - c->gicr_ipriorityr[i + 3] =3D extract32(reg, 24, 8); - } - } + /* Redistributor state (one per CPU) */ + kvm_arm_gic_batch_get_redist(s, &entries, &batch_n, + &batch_capacity); + + /* reset batch_n */ + batch_n =3D 0; + + /* PLPIS */ + kvm_arm_gic_batch_get_plpis(s, &entries, redist_typer, + &batch_n, &batch_capacity); =20 - if (redist_typer & GICR_TYPER_PLPIS) { + g_free(entries); + } + } else { + /* Redistributor state (one per CPU) */ for (ncpu =3D 0; ncpu < s->num_cpu; ncpu++) { GICv3CPUState *c =3D &s->cpu[ncpu]; =20 - kvm_gicr_access(s, GICR_PROPBASER, ncpu, ®l, false); - kvm_gicr_access(s, GICR_PROPBASER + 4, ncpu, ®h, false); - c->gicr_propbaser =3D ((uint64_t)regh << 32) | regl; + kvm_gicr_access(s, GICR_CTLR, ncpu, ®, false); + c->gicr_ctlr =3D reg; + + kvm_gicr_access(s, GICR_STATUSR, ncpu, ®, false); + c->gicr_statusr[GICV3_NS] =3D reg; + + kvm_gicr_access(s, GICR_WAKER, ncpu, ®, false); + c->gicr_waker =3D reg; + + kvm_gicr_access(s, GICR_IGROUPR0, ncpu, ®, false); + c->gicr_igroupr0 =3D reg; + kvm_gicr_access(s, GICR_ISENABLER0, ncpu, ®, false); + c->gicr_ienabler0 =3D reg; + kvm_gicr_access(s, GICR_ICFGR1, ncpu, ®, false); + c->edge_trigger =3D half_unshuffle32(reg >> 1) << 16; + kvm_gic_line_level_access(s, 0, ncpu, ®, false); + c->level =3D reg; + kvm_gicr_access(s, GICR_ISPENDR0, ncpu, ®, false); + c->gicr_ipendr0 =3D reg; + kvm_gicr_access(s, GICR_ISACTIVER0, ncpu, ®, false); + c->gicr_iactiver0 =3D reg; + + for (i =3D 0; i < GIC_INTERNAL; i +=3D 4) { + kvm_gicr_access(s, GICR_IPRIORITYR + i, ncpu, ®, false); + c->gicr_ipriorityr[i] =3D extract32(reg, 0, 8); + c->gicr_ipriorityr[i + 1] =3D extract32(reg, 8, 8); + c->gicr_ipriorityr[i + 2] =3D extract32(reg, 16, 8); + c->gicr_ipriorityr[i + 3] =3D extract32(reg, 24, 8); + } + } + + if (redist_typer & GICR_TYPER_PLPIS) { + for (ncpu =3D 0; ncpu < s->num_cpu; ncpu++) { + GICv3CPUState *c =3D &s->cpu[ncpu]; =20 - kvm_gicr_access(s, GICR_PENDBASER, ncpu, ®l, false); - kvm_gicr_access(s, GICR_PENDBASER + 4, ncpu, ®h, false); - c->gicr_pendbaser =3D ((uint64_t)regh << 32) | regl; + kvm_gicr_access(s, GICR_PROPBASER, ncpu, ®l, false); + kvm_gicr_access(s, GICR_PROPBASER + 4, ncpu, ®h, false); + c->gicr_propbaser =3D ((uint64_t)regh << 32) | regl; + + kvm_gicr_access(s, GICR_PENDBASER, ncpu, ®l, false); + kvm_gicr_access(s, GICR_PENDBASER + 4, ncpu, ®h, false); + c->gicr_pendbaser =3D ((uint64_t)regh << 32) | regl; + } } } =20 /* Distributor state (shared between all CPUs */ - kvm_gicd_access(s, GICD_STATUSR, ®, false); s->gicd_statusr[GICV3_NS] =3D reg; =20 @@ -1025,58 +1329,78 @@ static void kvm_arm_gicv3_get(GICv3State *s) s->gicd_irouter[i] =3D ((uint64_t)regh << 32) | regl; } =20 - /***************************************************************** - * CPU Interface(s) State - */ + /* CPU Interface(s) State */ + if (batch_supported) { + { + GICv3BatchEntry *entries =3D g_new(GICv3BatchEntry, 256); + int batch_n =3D 0; + int batch_capacity =3D 256; =20 - for (ncpu =3D 0; ncpu < s->num_cpu; ncpu++) { - GICv3CPUState *c =3D &s->cpu[ncpu]; - int num_pri_bits; + /* CPU Interface - basic registers */ + kvm_arm_gic_batch_get_cpuif_basic(s, &entries, &batch_n, + &batch_capacity); =20 - kvm_gicc_access(s, ICC_SRE_EL1, ncpu, &c->icc_sre_el1, false); - kvm_gicc_access(s, ICC_CTLR_EL1, ncpu, - &c->icc_ctlr_el1[GICV3_NS], false); - kvm_gicc_access(s, ICC_IGRPEN0_EL1, ncpu, - &c->icc_igrpen[GICV3_G0], false); - kvm_gicc_access(s, ICC_IGRPEN1_EL1, ncpu, - &c->icc_igrpen[GICV3_G1NS], false); - kvm_gicc_access(s, ICC_PMR_EL1, ncpu, &c->icc_pmr_el1, false); - kvm_gicc_access(s, ICC_BPR0_EL1, ncpu, &c->icc_bpr[GICV3_G0], fals= e); - kvm_gicc_access(s, ICC_BPR1_EL1, ncpu, &c->icc_bpr[GICV3_G1NS], fa= lse); - num_pri_bits =3D ((c->icc_ctlr_el1[GICV3_NS] & - ICC_CTLR_EL1_PRIBITS_MASK) >> - ICC_CTLR_EL1_PRIBITS_SHIFT) + 1; + /* reset batch_n */ + batch_n =3D 0; =20 - switch (num_pri_bits) { - case 7: - kvm_gicc_access(s, ICC_AP0R_EL1(3), ncpu, ®64, false); - c->icc_apr[GICV3_G0][3] =3D reg64; - kvm_gicc_access(s, ICC_AP0R_EL1(2), ncpu, ®64, false); - c->icc_apr[GICV3_G0][2] =3D reg64; - /* fall through */ - case 6: - kvm_gicc_access(s, ICC_AP0R_EL1(1), ncpu, ®64, false); - c->icc_apr[GICV3_G0][1] =3D reg64; - /* fall through */ - default: - kvm_gicc_access(s, ICC_AP0R_EL1(0), ncpu, ®64, false); - c->icc_apr[GICV3_G0][0] =3D reg64; + /* CPU Interface - APR registers */ + kvm_arm_gic_batch_get_cpuif_apr(s, &entries, &batch_n, + &batch_capacity); + + g_free(entries); } + } else { + for (ncpu =3D 0; ncpu < s->num_cpu; ncpu++) { + GICv3CPUState *c =3D &s->cpu[ncpu]; + int num_pri_bits; =20 - switch (num_pri_bits) { - case 7: - kvm_gicc_access(s, ICC_AP1R_EL1(3), ncpu, ®64, false); - c->icc_apr[GICV3_G1NS][3] =3D reg64; - kvm_gicc_access(s, ICC_AP1R_EL1(2), ncpu, ®64, false); - c->icc_apr[GICV3_G1NS][2] =3D reg64; - /* fall through */ - case 6: - kvm_gicc_access(s, ICC_AP1R_EL1(1), ncpu, ®64, false); - c->icc_apr[GICV3_G1NS][1] =3D reg64; - /* fall through */ - default: - kvm_gicc_access(s, ICC_AP1R_EL1(0), ncpu, ®64, false); - c->icc_apr[GICV3_G1NS][0] =3D reg64; + kvm_gicc_access(s, ICC_SRE_EL1, ncpu, &c->icc_sre_el1, false); + kvm_gicc_access(s, ICC_CTLR_EL1, ncpu, + &c->icc_ctlr_el1[GICV3_NS], false); + kvm_gicc_access(s, ICC_IGRPEN0_EL1, ncpu, + &c->icc_igrpen[GICV3_G0], false); + kvm_gicc_access(s, ICC_IGRPEN1_EL1, ncpu, + &c->icc_igrpen[GICV3_G1NS], false); + kvm_gicc_access(s, ICC_PMR_EL1, ncpu, &c->icc_pmr_el1, false); + kvm_gicc_access(s, ICC_BPR0_EL1, ncpu, &c->icc_bpr[GICV3_G0], + false); + kvm_gicc_access(s, ICC_BPR1_EL1, ncpu, &c->icc_bpr[GICV3_G1NS], + false); + num_pri_bits =3D ((c->icc_ctlr_el1[GICV3_NS] & + ICC_CTLR_EL1_PRIBITS_MASK) >> + ICC_CTLR_EL1_PRIBITS_SHIFT) + 1; + + switch (num_pri_bits) { + case 7: + kvm_gicc_access(s, ICC_AP0R_EL1(3), ncpu, ®64, false); + c->icc_apr[GICV3_G0][3] =3D reg64; + kvm_gicc_access(s, ICC_AP0R_EL1(2), ncpu, ®64, false); + c->icc_apr[GICV3_G0][2] =3D reg64; + /* fall through */ + case 6: + kvm_gicc_access(s, ICC_AP0R_EL1(1), ncpu, ®64, false); + c->icc_apr[GICV3_G0][1] =3D reg64; + /* fall through */ + default: + kvm_gicc_access(s, ICC_AP0R_EL1(0), ncpu, ®64, false); + c->icc_apr[GICV3_G0][0] =3D reg64; + } + + switch (num_pri_bits) { + case 7: + kvm_gicc_access(s, ICC_AP1R_EL1(3), ncpu, ®64, false); + c->icc_apr[GICV3_G1NS][3] =3D reg64; + kvm_gicc_access(s, ICC_AP1R_EL1(2), ncpu, ®64, false); + c->icc_apr[GICV3_G1NS][2] =3D reg64; + /* fall through */ + case 6: + kvm_gicc_access(s, ICC_AP1R_EL1(1), ncpu, ®64, false); + c->icc_apr[GICV3_G1NS][1] =3D reg64; + /* fall through */ + default: + kvm_gicc_access(s, ICC_AP1R_EL1(0), ncpu, ®64, false); + c->icc_apr[GICV3_G1NS][0] =3D reg64; + } } } int64_t end_time =3D qemu_clock_get_ms(QEMU_CLOCK_REALTIME); --=20 2.43.0