From nobody Sat Sep 26 20:01:52 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=reject dis=none) header.from=oss.qualcomm.com ARC-Seal: i=1; a=rsa-sha256; t=1788781150; cv=none; d=zohomail.com; s=zohoarc; b=IDDKPIhr0853gdl8wdH5de9MQuXzdy4v0ErSP9bGgJlAwsVQKOrAhY4rIsbyKxAIUAfuiEASQTwRRfY5srKgyikL2ELUsLxVtzSKZZnDHtWSB6wQQq8DrSQdW8bKTa/0pRxiGx/T945IXP9pkuzUE/zWWImRS4t9jZz4QR6krzU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1788781150; 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=BcuMX8mUG+dsbQ6cqjgCndsKBhltgsCH1RoIWi0mIN4=; b=kD+MpD9+FirwaeW9D17TECaWPEQgl/omh/dYMtiPL0uPcOrv2q1hgVWLOliLN7wIFqsS3iARtNWsaAhLnWcYX4IQU1wYjWYVErxUCI11QuyLvQDoiC2/eNXmJVOuYlHGLaxICDVE7/g43yGoyXwondxlGRxh3QgLoRgytlEAMN0= 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 lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 178878115080994.42796441285941; Mon, 7 Sep 2026 04:39:10 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x3Xft-0007zp-6b; Mon, 07 Sep 2026 07:38:09 -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 1x3Xfq-0007z8-QK for qemu-devel@nongnu.org; Mon, 07 Sep 2026 07:38:07 -0400 Received: from mx0b-0031df01.pphosted.com ([205.220.180.131]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x3Xfo-0001j1-1t for qemu-devel@nongnu.org; Mon, 07 Sep 2026 07:38:06 -0400 Received: from pps.filterd (m0279872.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 687An3ji3230474 for ; Mon, 7 Sep 2026 11:38:02 GMT Received: from mail-pj1-f71.google.com (mail-pj1-f71.google.com [209.85.216.71]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4ghfxktgnn-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Mon, 07 Sep 2026 11:38:02 +0000 (GMT) Received: by mail-pj1-f71.google.com with SMTP id 98e67ed59e1d1-398d3a12589so854849a91.1 for ; Mon, 07 Sep 2026 04:38:02 -0700 (PDT) Received: from hu-slingapp-blr.qualcomm.com (blr-bdr-fw-01_GlobalNAT_AllZones-Outside.qualcomm.com. [103.229.18.19]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-33517b57ac8sm17169507eec.28.2026.09.07.04.37.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 07 Sep 2026 04:38:00 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=qcppdkim1; bh=BcuMX8mUG+d sbQ6cqjgCndsKBhltgsCH1RoIWi0mIN4=; b=b9umomPbOLsXqPjulAmyiFUaELy rXfGo3+op26Yr38bUUxAXntsAU2PFkpaznGIRjum8CQ5E3/7LUWej+U0Fq3oTx0a /FRgMxHDj2mxdcWPQ9GiNtV0DRZGJMhbRpEL+nEE5RIywexvt/XG13NKYWHkjFpl 44GVAu6nBOszmajbblbRmn6f39+W6yfIEdWyXxDotlqfghsx0KiNqFqrJgKHLBT7 TWHptIoNjEqR+N7iGjVIc/X1B/lp6YTmE1Vcm79ZJqsB75RVWUzv4IRUKfe6WlIr +46a6Q5dO0+ONKZVjpjfQuKiAQKHuSno2lcR2dqvnw0a/O6K6z0sVoejIOA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1788781081; x=1789385881; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=BcuMX8mUG+dsbQ6cqjgCndsKBhltgsCH1RoIWi0mIN4=; b=iAvXoaCAkkrK6v7kTkcGs1kKEd0fnqtfljvXqnaVttYHvBJxn480ZqptvILj5bvnHO m7DoG9x8PZijP/NmpkEYvQw8LSpsI2OVbLzv5yISzWvrOkf9JBqnBkrTz/6syCh8Fz/A h/mV+u5nBAOkKmnOwjNQHpj1voxX3aO+BPif56AIIp7TNhe1gtfLcsj64XXnWk+5/cum EGNX7xJRKMbI0EIQrZXnwo1ezEpHyFZreQ1M0SDgZke2BuHd0ugsI6ypEaCWm5Crytn7 gAuQwGpkmIgd4H3hycTdxjJjSGTZIOL7arrVCXw306mUgpa6s36Y/18QuBUwjXINKksG ls6Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788781081; x=1789385881; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=BcuMX8mUG+dsbQ6cqjgCndsKBhltgsCH1RoIWi0mIN4=; b=lEL2euDUjD1XM/FlR8bH2g5MttQbVARis9XPFMfixR6jpNNkEM6xZX0K0ueWAlsr2N P2wdHQHe+/txYfsdq0nHJZXJRtXTH2e5H0ssDVWK0agBv8Oc4fLev4kHOTupab/3OVla Ak0cSv/2+uRYYqj6ujBE1WcpT1q41iMGo4TDxm81/lH4+8vur4OUta2Jx+3SnidPWa03 cpBiwPRaHDUM9BXuGJSXWCSZDbrhJ1V3z94oy1qOA5VhPTtnv34hqMhA0eGWN0oxEeiY ycMy1Fq2Y9LP8zeDlL6EGFcClmhKQy4Nxjb0MsoF2S9YISwNVkyCnEeDq/OBTKvrUR0J PJvQ== X-Gm-Message-State: AFuF++kVD8Wyl2DuLmnGpkE82ug/7P+PMD9ihTonVDX5jZgAAJubUMBm 9ERNpK9Z9d/lJzUbUA7dl8IV8zpjqwaiQDd+2pofQkPrgN6McFKhAqAex64RF9OMNhYJNxXCmUp /t76ObABj0lIzq6O6BWX77S/n8/RT/czqc5GnGx1xF7KuvzS7trGW02pRm6EXuFKWYg== X-Gm-Gg: AYBFou3u9y3DIL29aDa/VJlTev1o4H/a8o9NtqGhu4Ptmns72MA+9SLlCG7kc+xMyYw Sev4S6QgYpTksDHwZ3tIm1A0c8UPGuDla/G/TCzMmpReUK019BVSvpjUQrAWcpKM7v7SRpvrPWI AnsxNMlk/FCOB9nmfMXUtF1yUppRhAS1+gBpPYxHbPv3wJT3qsbEqCnILu1ESBANOUrJKKRtVFG xCEiJ6td7zJGWUvjc7cGNy/Ud6jjQNC8cvUkEQCcl5Yhsg1tL5+ts4I1wNOuPF6Od46GUHwhZ45 k0iGTTG/2wTi+gRGU/+8F3lldwrlproIRYEhuBEu81kDZ35Hb8i4HmZIDZp+1ygg+k29+ogZS/G biAGCddvg0XgI3+BmAK9dtgXFVvMwsSR/L+LXkM2dgmLL05ElfSDy4/olsfSMI8fO0zNU/1aSZo F91ZiJKKYRLyLHk0DxGAgfVhHBOMYeK4A= X-Received: by 2002:a17:90b:4c03:b0:398:bac7:72d0 with SMTP id 98e67ed59e1d1-39b3d86acf2mr14261639a91.5.1788781081202; Mon, 07 Sep 2026 04:38:01 -0700 (PDT) X-Received: by 2002:a17:90b:4c03:b0:398:bac7:72d0 with SMTP id 98e67ed59e1d1-39b3d86acf2mr14261577a91.5.1788781080614; Mon, 07 Sep 2026 04:38:00 -0700 (PDT) From: Subrahmanya Lingappa To: qemu-devel@nongnu.org Cc: qemu-riscv@nongnu.org, Subrahmanya Lingappa , Pierrick Bouvier , Paolo Bonzini , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Chao Liu , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Subject: [PATCH v1 1/2] hw/riscv: add RPMI support for server reference platform Date: Mon, 7 Sep 2026 17:07:14 +0530 Message-ID: <20260907113715.1219775-2-subrahmanya.lingappa@oss.qualcomm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260907113715.1219775-1-subrahmanya.lingappa@oss.qualcomm.com> References: <20260907113715.1219775-1-subrahmanya.lingappa@oss.qualcomm.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwOTA3MDEyOCBTYWx0ZWRfX9Z8+HdkRnCb3 rMKxa5Qbap41/n4ebj3ZnO0dAl1Kp8hEayStLbkqNvEtH650sjK1qGPbcAPUp+Jj8S3hLj1/MB4 U8i1hWCJBY3i7HdvJG9s5+MWf/byOIIq4M0rYmVaQFORmivTEp1MEASsb87hBDO5/uXaR+10qtR 4/5xhmC1G94WX3uax8JrI639wi0iy3bRV/ZfAa8nQTxBn+xVcrxLlf02pHbJ2UcFYsPwgw1Ra1X fX+vuKT/g8tWSCPsxciNMu4dLfmghcypZ7dYl8Zn3jv4R+qC1voIEbjE3ZonWN9OxxDVxXUT7UT GX1UHf3tXL6lA7kYMocxgLe7ut3FwbOD70BlAZB88wfSO4PfGPwAJrMQx+xIlbhj0aAGSf9O4DK WjnIw3W1QrmwNltiwYkWICv3UuWvmYhlmTp7umn52ZEpMLeI8fF7O1BNGaOZdkLOjGmKVh13D6z bPYCxcX4rJDwtO9yDhQ== X-Proofpoint-GUID: FreN1kKJgli95xP4mPVXW-AtpsvgU_iD X-Proofpoint-Spam-Info: AW1haW4tMjYwOTA3MDEyOCBTYWx0ZWRfXybKMGcD0t+0h 1cupCzqbESBQbrOY9o0APN9da8YnX/4XUvylT8cwV+2iEpaW3n4N8mKYR9Z8sK+RQIiDv8Q5bwo oQe+p/2LUi/gyaYy/qiZG9ao27176uc= X-Authority-Analysis: v=2.4 cv=daOwG3Xe c=1 sm=1 tr=0 ts=6a9ea21a cx=c_pps a=UNFcQwm+pnOIJct1K4W+Mw==:117 a=Ou0eQOY4+eZoSc0qltEV5Q==:17 a=VdqzKS8jKosA:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=yx91gb_oNiZeI1HMLzn7:22 a=NEAV23lmAAAA:8 a=NLiCwHATAAAA:8 a=V1jnuoLLAAAA:20 a=EUspDBNiAAAA:8 a=916E8NSIVdlGVQu2ioMA:9 a=uKXjsCUrEbL0IQVhDsJ9:22 a=F9tHCgz3TLBaZgltkx5D:22 a=bA3UWDv6hWIuX7UZL3qL:22 X-Proofpoint-ORIG-GUID: FreN1kKJgli95xP4mPVXW-AtpsvgU_iD X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-09-07_03,2026-09-07_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 suspectscore=0 priorityscore=1501 bulkscore=0 spamscore=0 phishscore=0 lowpriorityscore=0 adultscore=0 malwarescore=0 impostorscore=0 clxscore=1015 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2609070128 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=205.220.180.131; envelope-from=subrahmanya.lingappa@oss.qualcomm.com; helo=mx0b-0031df01.pphosted.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 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_DNSWL_LOW=-0.7, 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: 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 @qualcomm.com) X-ZM-MESSAGEID: 1788781153998158500 Content-Type: text/plain; charset="utf-8" Wire the common RISC-V RPMI device into the riscv-server-ref machine so firmware can discover platform management services through the generated device tree. The board exposes RPMI unconditionally when QEMU is built with librpmi support and does not provide an rpmi=3Don|off machine option. Advertise Base, System Reset, HSM, and System Suspend service groups for the board. Reset, shutdown, hart management, and suspend requests are routed through the shared RPMI implementation and server-ref machine callbacks. When RPMI is available, omit the legacy syscon reboot and poweroff nodes so firmware uses RPMI for those operations. Keep riscv-server-ref buildable when librpmi is not available. In that case the board boots without RPMI support, configure reports a warning, and the machine emits a runtime warning. Signed-off-by: Subrahmanya Lingappa --- docs/system/riscv/riscv-server-ref.rst | 41 +++++++ hw/riscv/Kconfig | 1 + hw/riscv/server_platform_ref.c | 146 ++++++++++++++++++++++++- meson.build | 4 + 4 files changed, 190 insertions(+), 2 deletions(-) diff --git a/docs/system/riscv/riscv-server-ref.rst b/docs/system/riscv/ris= cv-server-ref.rst index 0573b4e07c..22b215223e 100644 --- a/docs/system/riscv/riscv-server-ref.rst +++ b/docs/system/riscv/riscv-server-ref.rst @@ -25,6 +25,7 @@ The main features included in the riscv-server-ref board = are: * No fw_cfg device * No ACPI table * Minimal device tree nodes +* RISC-V RPMI platform management =20 There are multiple ways of using this reference board. The spec compliant= way is using an EDK2 image and a TPM device. The board was tested with the TPM @@ -57,6 +58,46 @@ And then start QEMU with: -device tpm-tis-device,tpmdev=3Dtpm0 \ -nographic =20 +RPMI support +------------ + +The ``riscv-server-ref`` machine always exposes RISC-V RPMI platform manag= ement +when QEMU is built with librpmi support. There is no ``rpmi=3Don|off`` ma= chine +option for this board. If QEMU is built without librpmi, the board still = boots +without RPMI and reports a warning. + +The initial ``riscv-server-ref`` RPMI implementation exposes Base, System +Reset, HSM, and System Suspend service groups. System Reset handles guest +shutdown and cold reboot requests through RPMI. +HSM uses the machine hart IDs for hart discovery, status, start, stop, and +suspend commands. System Suspend uses QEMU's suspend and wakeup path. + +When RPMI is compiled in, the generated device tree advertises reset, shut= down, +HSM, and suspend through RPMI service nodes. The legacy syscon reboot and +poweroff nodes are omitted so firmware routes reset and shutdown through t= he +RPMI System Reset service. Without RPMI support, the generated device tre= e uses +the legacy syscon reboot and poweroff nodes. RPMI is currently described +through FDT only; this machine does not emit ACPI tables for the RPMI tran= sport +or service groups. + +RPMI support targets the RISC-V Platform Management Interface (RPMI) +Specification v1.0 Ratified (`server-ref RPMI v1.0 specification`_). The +build dependency is provided by `server-ref librpmi`_. After installing +librpmi, configure QEMU with ``--enable-librpmi`` or ``-Dlibrpmi=3Denabled= `` to +make the build fail if librpmi is unavailable. + +.. code-block:: bash + + qemu-system-riscv64 -M riscv-server-ref \ + -bios fw_dynamic.bin \ + -kernel EDK2.fd \ + -drive file=3Dnvme_disk.ext2,format=3Draw,id=3Dhd0,if=3Dnone \ + -device ahci,id=3Dahci \ + -device ide-hd,drive=3Dhd0,bus=3Dahci.0 \ + -nographic + =20 .. _spec: https://github.com/riscv-non-isa/riscv-server-platform .. _tpm: https://qemu-project.gitlab.io/qemu/specs/tpm.html +.. _server-ref RPMI v1.0 specification: https://github.com/riscv-non-isa/r= iscv-rpmi/releases/download/v1.0/riscv-rpmi.pdf +.. _server-ref librpmi: https://github.com/riscv-software-src/librpmi diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig index e147c830be..ee87be1d2a 100644 --- a/hw/riscv/Kconfig +++ b/hw/riscv/Kconfig @@ -85,6 +85,7 @@ config RISCV_SERVER_PLATFORM_REF select RISCV_APLIC select RISCV_IMSIC select RISCV_IOMMU + select RISCV_RPMI if LIBRPMI =20 config SHAKTI_C bool diff --git a/hw/riscv/server_platform_ref.c b/hw/riscv/server_platform_ref.c index 4d27dcd6c0..97a191de65 100644 --- a/hw/riscv/server_platform_ref.c +++ b/hw/riscv/server_platform_ref.c @@ -30,18 +30,20 @@ #include "hw/riscv/fdt-common.h" #include "hw/riscv/machines-qom.h" #include "hw/riscv/numa.h" +#include "hw/riscv/rpmi-fdt.h" #include "hw/riscv/iommu.h" #include "hw/riscv/riscv-iommu.h" #include "hw/riscv/riscv-iommu-bits.h" +#include "hw/misc/riscv_rpmi.h" #include "hw/intc/riscv_aclint.h" #include "hw/intc/riscv_aplic.h" #include "hw/intc/riscv_imsic.h" #include "chardev/char.h" #include "hw/char/serial-mm.h" #include "system/device_tree.h" +#include "system/kvm.h" #include "system/runstate.h" #include "system/system.h" -#include "system/kvm.h" #include "system/tcg.h" #include "kvm/kvm_riscv.h" #include "system/tpm.h" @@ -70,6 +72,9 @@ =20 #define RVSERVER_PLATFORM_BUS_NUM_IRQS 8 =20 +#define RVSERVER_RPMI_A2P_REQ_SIZE (16 * RPMI_QUEUE_SLOT_SIZE) +#define RVSERVER_RPMI_P2A_REQ_SIZE 0 + #define TYPE_RISCV_SERVER_REF_MACHINE MACHINE_TYPE_NAME("riscv-server-ref") OBJECT_DECLARE_SIMPLE_TYPE(RISCVServerRefMachineState, RISCV_SERVER_REF_MA= CHINE) =20 @@ -96,6 +101,8 @@ enum { RVSERVER_RESET_SYSCON, RVSERVER_RTC, RVSERVER_IOMMU_SYS, + RVSERVER_RPMI_SHMEM, + RVSERVER_RPMI_DOORBELL, RVSERVER_ACLINT, RVSERVER_APLIC_M, RVSERVER_APLIC_S, @@ -147,6 +154,8 @@ static const MemMapEntry rvserver_ref_memmap[] =3D { [RVSERVER_RESET_SYSCON] =3D { 0x100000, 0x1000 }, [RVSERVER_RTC] =3D { 0x101000, 0x1000 }, [RVSERVER_IOMMU_SYS] =3D { 0x102000, 0x1000 }, + [RVSERVER_RPMI_SHMEM] =3D { 0x110000, 0x20000 }, + [RVSERVER_RPMI_DOORBELL] =3D { 0x140000, 0x1000 }, [RVSERVER_ACLINT] =3D { 0x2000000, 0x10000 }, [RVSERVER_PCIE_PIO] =3D { 0x3000000, 0x10000 }, [RVSERVER_PLATFORM_BUS] =3D { 0x4000000, 0x2000000 }, @@ -287,12 +296,107 @@ static void create_fdt_sockets(RISCVServerRefMachine= State *s, riscv_socket_fdt_write_distance_matrix(ms); } =20 +#ifdef CONFIG_LIBRPMI +static const RiscvRpmiServiceConfig rvserver_ref_rpmi_services[] =3D { + { + .node_name =3D "sysreset", + .compatible =3D "riscv,rpmi-system-reset", + .service_group =3D RPMI_SRVGRP_SYSTEM_RESET, + }, + { + .node_name =3D "hsm", + .compatible =3D "riscv,rpmi-hsm", + .service_group =3D RPMI_SRVGRP_HSM, + }, + { + .node_name =3D "suspend", + .compatible =3D "riscv,rpmi-system-suspend", + .service_group =3D RPMI_SRVGRP_SYSTEM_SUSPEND, + }, +}; + +static void rvserver_ref_rpmi_system_reset(void) +{ + qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); +} + +static void rvserver_ref_rpmi_system_shutdown(void) +{ + qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); +} + +static void rvserver_ref_rpmi_system_suspend(void) +{ + qemu_system_suspend_request(); +} + +static void rvserver_ref_rpmi_register_wakeup_support(void) +{ + qemu_register_wakeup_support(); +} + +static bool rvserver_ref_rpmi_system_can_resume(void) +{ + return runstate_check(RUN_STATE_RUNNING); +} + +static const RiscvRpmiMachineOps rvserver_ref_rpmi_machine_ops =3D { + .system_reset =3D rvserver_ref_rpmi_system_reset, + .system_shutdown =3D rvserver_ref_rpmi_system_shutdown, + .system_suspend =3D rvserver_ref_rpmi_system_suspend, + .register_wakeup_support =3D rvserver_ref_rpmi_register_wakeup_support, + .system_can_resume =3D rvserver_ref_rpmi_system_can_resume, +}; + +static RiscvRpmiConfig rvserver_ref_rpmi_config( + RISCVServerRefMachineState *s, const uint32_t *hart_ids, + uint32_t hart_count) +{ + return (RiscvRpmiConfig) { + .doorbell_base =3D s->memmap[RVSERVER_RPMI_DOORBELL].base, + .shmem_base =3D s->memmap[RVSERVER_RPMI_SHMEM].base, + .shmem_size =3D s->memmap[RVSERVER_RPMI_SHMEM].size, + .a2p_req_size =3D RVSERVER_RPMI_A2P_REQ_SIZE, + .p2a_req_size =3D RVSERVER_RPMI_P2A_REQ_SIZE, + .platform_info =3D "QEMU RISC-V server-ref RPMI", + .machine_ops =3D &rvserver_ref_rpmi_machine_ops, + .hart_ids =3D hart_ids, + .hart_count =3D hart_count, + .services =3D rvserver_ref_rpmi_services, + .service_count =3D ARRAY_SIZE(rvserver_ref_rpmi_services), + }; +} + +static void create_fdt_rpmi(RISCVServerRefMachineState *s, uint32_t *phand= le) +{ + RiscvRpmiConfig rpmi_cfg =3D rvserver_ref_rpmi_config(s, NULL, 0); + uint32_t rpmi_mbox_handle; + RiscvRpmiFdtMboxConfig cfg =3D { + .shmem_base =3D rpmi_cfg.shmem_base, + .doorbell_base =3D rpmi_cfg.doorbell_base, + .a2p_req_size =3D rpmi_cfg.a2p_req_size, + .p2a_req_size =3D rpmi_cfg.p2a_req_size, + .doorbell_size =3D s->memmap[RVSERVER_RPMI_DOORBELL].size, + }; + + riscv_rpmi_fdt_add_mbox(MACHINE(s)->fdt, &cfg, phandle, + &rpmi_mbox_handle); + + for (uint32_t i =3D 0; i < rpmi_cfg.service_count; i++) { + riscv_rpmi_fdt_add_service_node(MACHINE(s)->fdt, rpmi_cfg.shmem_ba= se, + &rpmi_cfg.services[i], + rpmi_mbox_handle); + } +} +#endif + static void finalize_fdt(RISCVServerRefMachineState *s) { uint32_t phandle =3D 1, irq_mmio_phandle =3D 1, msi_pcie_phandle =3D 1; uint32_t irq_pcie_phandle =3D 1, iommu_sys_phandle; g_autofree char *name =3D NULL; MachineState *ms =3D MACHINE(s); + bool create_reset_nodes =3D true; =20 create_fdt_sockets(s, rvserver_ref_memmap, &phandle, &irq_mmio_phandle, &irq_pcie_phandle, &msi_pcie_phandle); @@ -311,10 +415,16 @@ static void finalize_fdt(RISCVServerRefMachineState *= s) irq_pcie_phandle, msi_pcie_phandle, iommu_sys_phandle, RVSERVER_PCIE_IRQ); =20 +#ifdef CONFIG_LIBRPMI + create_fdt_rpmi(s, &phandle); + create_reset_nodes =3D false; +#endif + riscv_create_fdt_syscon(ms->fdt, &phandle, rvserver_ref_memmap[RVSERVER_RESET_SYSCON].bas= e, rvserver_ref_memmap[RVSERVER_RESET_SYSCON].siz= e, - SYSCON_RESET, SYSCON_POWEROFF, false, true); + SYSCON_RESET, SYSCON_POWEROFF, false, + create_reset_nodes); =20 riscv_create_fdt_uart(ms->fdt, &rvserver_ref_memmap[RVSERVER_UART0], RVSERVER_UART0_IRQ, AIA_TYPE_APLIC_IMSIC, @@ -523,6 +633,13 @@ static void rvserver_ref_machine_init(MachineState *ma= chine) =20 s->memmap =3D rvserver_ref_memmap; =20 +#ifdef CONFIG_LIBRPMI + if (kvm_enabled()) { + error_report("RISC-V RPMI support is not available with KVM"); + exit(1); + } +#endif + /* Initialize sockets */ mmio_irqchip =3D pcie_irqchip =3D NULL; for (i =3D 0; i < socket_count; i++) { @@ -604,6 +721,31 @@ static void rvserver_ref_machine_init(MachineState *ma= chine) memmap[RVSERVER_RESET_SYSCON].base, reset_syscon_io); =20 +#ifdef CONFIG_LIBRPMI + { + MachineClass *mc =3D MACHINE_GET_CLASS(machine); + const CPUArchIdList *possible_cpus =3D mc->possible_cpu_arch_ids(m= achine); + g_autofree uint32_t *rpmi_hart_ids =3D + g_new0(uint32_t, machine->smp.cpus); + RiscvRpmiConfig rpmi_cfg; + Error *local_err =3D NULL; + + for (i =3D 0; i < machine->smp.cpus; i++) { + rpmi_hart_ids[i] =3D possible_cpus->cpus[i].arch_id; + } + + rpmi_cfg =3D rvserver_ref_rpmi_config(s, rpmi_hart_ids, + machine->smp.cpus); + if (!riscv_rpmi_create(&rpmi_cfg, &local_err)) { + error_report_err(local_err); + exit(1); + } + } +#else + warn_report("riscv-server-ref: RPMI support is not compiled in; " + "booting without RPMI"); +#endif + gpex_host =3D riscv_gpex_pcie_init(system_memory, pcie_irqchip, &rvserver_ref_memmap[RVSERVER_PCIE_EC= AM], &rvserver_ref_memmap[RVSERVER_PCIE_MM= IO], diff --git a/meson.build b/meson.build index 1e1e19e655..00584d0eba 100644 --- a/meson.build +++ b/meson.build @@ -3423,6 +3423,10 @@ foreach target : target_dirs foreach k, v: config_devices config_devices_data.set(k, 1) endforeach + if target =3D=3D 'riscv64-softmmu' and get_option('default_devices') a= nd \ + not librpmi.found() + warning('riscv-server-ref machine will be built without RPMI support= ; install librpmi and configure with --enable-librpmi to enable RPMI') + endif config_devices_mak_list +=3D config_devices_mak config_devices_h +=3D {target: configure_file(output: target + '-confi= g-devices.h', configuration: config_devi= ces_data)} --=20 2.43.0 From nobody Sat Sep 26 20:01:52 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=reject dis=none) header.from=oss.qualcomm.com ARC-Seal: i=1; a=rsa-sha256; t=1788781149; cv=none; d=zohomail.com; s=zohoarc; b=d95r9nEn/Sb9l5idFuet8EAEOAn32AaJ/s4VNCmIo6dW/LvArpitcNVf9LrWMEumkbZFGy8YVRwZi6r8SiUWTX6dC5Y3nlKSOhIGYIdFPlTi99R8Ne6BB9Be2t0iZkftcpJpgIibDqY7nrxsZFGinVI++6dLtrNik5kAX7TY4yA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1788781149; 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=bK2Bi1T8fbPpeePoq9EgpY53Rpm2m0RKlNUMJXuHLC4=; b=aU/bq4dw8YKYfe7iOkXds62yNdKrl1ppf3QtN4IosQPWNfmVkaKVKOJaNNoctDWnmwrfw0K1uCESLTuebI9At54wVTGP+Tgs00YoicykLT6Yu1j4IKsAQUywAZdlyw127x2HCzCT9WPqLiMCxzPkW1icpjtjUlcK4CLE756bWqU= 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 lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 17887811499653.692626717504254; Mon, 7 Sep 2026 04:39:09 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x3Xg2-00083U-O1; Mon, 07 Sep 2026 07:38:18 -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 1x3Xg0-00080A-NM for qemu-devel@nongnu.org; Mon, 07 Sep 2026 07:38:16 -0400 Received: from mx0b-0031df01.pphosted.com ([205.220.180.131]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x3Xfw-0001jZ-IR for qemu-devel@nongnu.org; Mon, 07 Sep 2026 07:38:16 -0400 Received: from pps.filterd (m0279868.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 687AnMMd3777241 for ; Mon, 7 Sep 2026 11:38:11 GMT Received: from mail-pj1-f71.google.com (mail-pj1-f71.google.com [209.85.216.71]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4ghsfygvvd-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Mon, 07 Sep 2026 11:38:11 +0000 (GMT) Received: by mail-pj1-f71.google.com with SMTP id 98e67ed59e1d1-399271df9d8so812602a91.2 for ; Mon, 07 Sep 2026 04:38:10 -0700 (PDT) Received: from hu-slingapp-blr.qualcomm.com (blr-bdr-fw-01_GlobalNAT_AllZones-Outside.qualcomm.com. [103.229.18.19]) by smtp.gmail.com with ESMTPSA id 5a478bee46e88-33517b57ac8sm17169507eec.28.2026.09.07.04.38.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 07 Sep 2026 04:38:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:date:from:in-reply-to:message-id :mime-version:references:subject:to; s=qcppdkim1; bh=bK2Bi1T8fbP peePoq9EgpY53Rpm2m0RKlNUMJXuHLC4=; b=EWQW5qWCkm821KGuHfVNujTj50+ PXmnb2Ep/2XUUidoV9lA76Lip1X6TVUw1xUHVwToiTYFdDicQwluPOMM3k0lwCEE EQQgZBmWKgnNcerlRelSODfwmjCGKJy7iiC8aJTzWfNRFWZwoBxjefHs0idi0qmJ GR3MYY7M4cDhUqFY6e8ZPuByEjSBA5+ct9HHuhp0gsm6bCtRjejheOYcsAWcQr9L KTj18AZV6MI+Pd31UJZ7QQHBKJAnjFr/xT8G5Uu76GrzCuYUqnVJwh2vcCHwhK5r Vl9b18UgYrMjtGmjQvaTtQzQ9R9zmSsW24/04rZCO3ATXAJ2POVcdTr15zA== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1788781090; x=1789385890; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=bK2Bi1T8fbPpeePoq9EgpY53Rpm2m0RKlNUMJXuHLC4=; b=apyOaRZV+QzcIvLoaedNjEDv50annnbPL/9q93pzOwRsBmvIna/GbyIu78SDuW2kCW RcskGTBHEOd7xJkFZyJ9KJE3s2y2tzds0jbTjdbUSv342HvNnM9F9m/Qv/UiSNOxg7gk EsU75v0LbVGpwt9cyysClt0eSWCw7GTEajUKi2sUrBVoPXOIRUJXNtV6NLTCpsuHgrE/ WSZ67x27AHAVfeCGp/+xzLk8MEaKwiZEE3NAc3BsKjrAsooBdJGHO1TtpA1lFhfWzym+ W2YrkEQHlcpOtX0pUZYUVyvTG4CWahxw2xCXX4Lhxm55v2V2r6GeuzJkBvsCwIl+aCIe KTtw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1788781090; x=1789385890; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=bK2Bi1T8fbPpeePoq9EgpY53Rpm2m0RKlNUMJXuHLC4=; b=UQw/WyEsQz1y8HMnOhirsMEEPmngdMG8gIT1NP4VIuGcfEiewVTN+LxxdAeVZ8C+nh +CWYBMNxmOXWCPY/q4fwf4ajQAaG4L67cHtKEo8yFgVM7mhWotZ4xQUnNJTmCJ7gl4cf +te0FefoXIjBQLtGOFFaLW8ZIR6YcdN8x77xowTlk5adMpLHLfEo9AjU8qT81Qxvp5iq J38f+pVIm/1TJIGEQcq+VkZ+KJh/fnEHAlwbgrTkfwVkwHp+SbiGOUSvulc3PKW4IQFD CBhY1iKLEtBjskgPV/QstC95AaoJfF6kr0S+uzOf9px08R2JTrS9IIzI/knn3YWm7ago DS9Q== X-Gm-Message-State: AFuF++nykmdkbDMHvyxMxrWiKd40MK9yU/wSjRVdLnwgAGJcNklb9s3A F0y8pgmq9fUg9rT3kaKGqVlJQbrUc/RX88cs/TGgtQsTZROiOZr8SjvyF4crDFpjpf6k/ZhK/l6 n5hODCXRABB6CKrLty5F+rV6a8T3yOYJiRf4/JDt7l6zi88ciOoq1igkh11N5RcutGg== X-Gm-Gg: AYBFou1ALh5jbcINaoWSvvxXqQ8u7d0JfsemhCwND3KWDF1w6IQPoCKJxetsLNSNEoQ 4ErmlLutjSOb+4vgCB4al5SpYTbA2VyEcQa/CmY/LgpCol3b1NFS6VpPk7UoO/8mPrbt0U0Buac LvBdfR9O7UK5EySDRa1NqGxt3ztJ3MYjFJiCeqqneC+LirT5nUxglDmcMATXz4o02xIvrn78/zc G2W8Xh+46WTg+L7LSsA2mnoHNJrpXVkD6VBucLlUYisE/aTaMoQ/tiSDhgFqXcTs23lleBINm6q xt6EzCjU2heCuZVwG+j8eO/1tdIreO6UucB2TofwRMLDrixW7ogi8IaGTP4u139sGan4+IfUIQp 9LNoPX/b6nbIPeO/36Y34+kUMqlhJL4xIX2gr5y6d4wUyp++1SiQ7sdI2CJpCJyqkGFDaCrqFhr uzW6U/n1HK4Q+r78iLIXew7dV+qwEwH4g= X-Received: by 2002:a17:90b:2786:b0:395:4df3:8800 with SMTP id 98e67ed59e1d1-39b3d3eb82fmr14689596a91.0.1788781089772; Mon, 07 Sep 2026 04:38:09 -0700 (PDT) X-Received: by 2002:a17:90b:2786:b0:395:4df3:8800 with SMTP id 98e67ed59e1d1-39b3d3eb82fmr14689537a91.0.1788781089026; Mon, 07 Sep 2026 04:38:09 -0700 (PDT) From: Subrahmanya Lingappa To: qemu-devel@nongnu.org Cc: qemu-riscv@nongnu.org, Subrahmanya Lingappa , Fabiano Rosas , Laurent Vivier , Paolo Bonzini , Palmer Dabbelt , Alistair Francis , Weiwei Li , Daniel Henrique Barboza , Liu Zhiwei , Chao Liu Subject: [PATCH v1 2/2] tests/qtest: split RISC-V RPMI tests by machine Date: Mon, 7 Sep 2026 17:07:15 +0530 Message-ID: <20260907113715.1219775-3-subrahmanya.lingappa@oss.qualcomm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260907113715.1219775-1-subrahmanya.lingappa@oss.qualcomm.com> References: <20260907113715.1219775-1-subrahmanya.lingappa@oss.qualcomm.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Proofpoint-ORIG-GUID: 4T-87PaD1OYzK_M36vD6-yjm8_wgpvmy X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwOTA3MDEyOCBTYWx0ZWRfX9wdzEWDe02Er TDwuDSeMMMImrMkWrRuSwPNsiNqs/ZO3ZdwvELuAqoHd4JQZR11J3zTLskMWPOADEkkCyH3D9zH /QH4QUPew/TdjB32tJrL/nGHPIJA+32MPcnk6yXGi4XBHSiXmSDfopsiChb1+qyO5r9+cwPv6jn 1hEIU759Cf/IWi8xz+A5AXtYO7YlYW6wYqXLLxC49ToqH3tQES41pX/AuCJsLK1/zE8Bd9d+KNT kfYs2sT/j78LUqxOm033/DqDi3T4MSN7Z9pAT/PMK7gKWn3QVl9TBtDQXH05YDztI7m4SWXkXwB SEZU70fOQktKSOEXaAUSJJuZpm14iZ5uDYb/t0kRxfgR3P+xee450pv08bNH+1dq0mJsx82ITSN BJZQpWzmrhZYuuvvpnXemn1dP8ZnQXgkbnFOzq647kBWp7HekvuqlX88dgCJp8IacvW6fhjf2No Z2kRl0fq80G6diEgxjg== X-Proofpoint-GUID: 4T-87PaD1OYzK_M36vD6-yjm8_wgpvmy X-Proofpoint-Spam-Info: AW1haW4tMjYwOTA3MDEyOCBTYWx0ZWRfXz4mC0SACbu0s q+emsi8G4QXCp2JOD94ei3f75EKwQGxiG7EwJyvFDUyUyi6FcErUndebFxvkLlsipdxA586vvRM ih0/yvpKtJU9YL8L/zLWvLCzVXTtuno= X-Authority-Analysis: v=2.4 cv=AduB2XXG c=1 sm=1 tr=0 ts=6a9ea223 cx=c_pps a=UNFcQwm+pnOIJct1K4W+Mw==:117 a=Ou0eQOY4+eZoSc0qltEV5Q==:17 a=VdqzKS8jKosA:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=ZpdpYltYx_vBUK5n70dp:22 a=EUspDBNiAAAA:8 a=01Cn3ppf6CKYpVBXuLwA:9 a=uKXjsCUrEbL0IQVhDsJ9:22 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1176,Hydra:6.1.134,FMLib:17.12.100.49 definitions=2026-09-07_03,2026-09-07_01,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 impostorscore=0 lowpriorityscore=0 spamscore=0 bulkscore=0 adultscore=0 phishscore=0 clxscore=1015 suspectscore=0 priorityscore=1501 malwarescore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2606150000 definitions=main-2609070128 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=205.220.180.131; envelope-from=subrahmanya.lingappa@oss.qualcomm.com; helo=mx0b-0031df01.pphosted.com X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 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_DNSWL_LOW=-0.7, SPF_HELO_NONE=0.001, 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 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 @qualcomm.com) X-ZM-MESSAGEID: 1788781152237154100 Content-Type: text/plain; charset="utf-8" Keep the reusable RPMI protocol tests in riscv-rpmi-test.c and expose them through a common registration helper. The machine-specific test files now only describe board policy and select the common coverage they can run. Move virt-only policy checks into riscv-rpmi-virt-test.c, including the rpmi=3Don/off coverage and the virt max-hart rejection case. The virt test binary continues to register the full RPMI protocol coverage. Add a riscv-server-ref test binary that rejects the virt-only rpmi property and then registers the meaningful shared protocol subset for the board: Base, System Reset, reset cleanup, negative doorbell/queue handling, migration blocking, HSM, and System Suspend. Server-ref intentionally skips only the virt-specific optional-machine-property cases and the extra virt-only topology/reset stress cases. Keeping the common protocol body shared avoids duplicating the virt test implementation as more RISC-V machines add RPMI coverage. Update MAINTAINERS so the split RPMI qtest files continue to reach the RISC-V maintainers. Signed-off-by: Subrahmanya Lingappa --- MAINTAINERS | 2 +- tests/qtest/meson.build | 4 +- tests/qtest/riscv-rpmi-server-ref-test.c | 36 ++ tests/qtest/riscv-rpmi-test.c | 476 ++++++++++++----------- tests/qtest/riscv-rpmi-test.h | 131 +++++++ tests/qtest/riscv-rpmi-virt-test.c | 45 +++ 6 files changed, 469 insertions(+), 225 deletions(-) create mode 100644 tests/qtest/riscv-rpmi-server-ref-test.c create mode 100644 tests/qtest/riscv-rpmi-test.h create mode 100644 tests/qtest/riscv-rpmi-virt-test.c diff --git a/MAINTAINERS b/MAINTAINERS index d2577f66b6..d85385213f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -374,7 +374,7 @@ F: hw/riscv/ F: hw/intc/riscv* F: hw/misc/riscv_rpmi* F: include/hw/misc/riscv_rpmi.h -F: tests/qtest/riscv-rpmi-test.c +F: tests/qtest/riscv-rpmi* F: include/hw/char/riscv_htif.h F: include/hw/riscv/ F: common-user/host/riscv* diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build index 96f9ba9d4b..5b1cb4b9a3 100644 --- a/tests/qtest/meson.build +++ b/tests/qtest/meson.build @@ -297,7 +297,7 @@ qtests_riscv32 =3D \ qtests_riscv64 =3D ['riscv-csr-test'] + \ (unpack_edk2_blobs ? ['bios-tables-test'] : []) + \ (config_all_devices.has_key('CONFIG_RISCV_RPMI') ? - ['riscv-rpmi-test'] : []) + \ + ['riscv-rpmi-virt-test', 'riscv-rpmi-server-ref-test'] : []) + \ (config_all_devices.has_key('CONFIG_IOMMU_TESTDEV') and config_all_devices.has_key('CONFIG_RISCV_IOMMU') ? ['iommu-riscv-test'] : []) + \ @@ -412,6 +412,8 @@ qtests =3D { 'ivshmem-test': [rt, '../../contrib/ivshmem-server/ivshmem-server.c'], 'migration-test': test_migration_files + migration_tls_files + migration= _colo_files, 'pxe-test': files('boot-sector.c'), + 'riscv-rpmi-server-ref-test': files('riscv-rpmi-test.c'), + 'riscv-rpmi-virt-test': files('riscv-rpmi-test.c'), 'pnv-xive2-test': files('pnv-xive2-common.c', 'pnv-xive2-flush-sync.c', 'pnv-xive2-nvpg_bar.c'), 'qos-test': [chardev, io, qos_test_ss.apply({}).sources()], diff --git a/tests/qtest/riscv-rpmi-server-ref-test.c b/tests/qtest/riscv-r= pmi-server-ref-test.c new file mode 100644 index 0000000000..bed6f586bc --- /dev/null +++ b/tests/qtest/riscv-rpmi-server-ref-test.c @@ -0,0 +1,36 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * + * QTests for riscv-server-ref RPMI support. + * + * Copyright (c) 2026 Qualcomm Technologies, Inc. + * Author: + * Subrahmanya Lingappa + */ + +#include "qemu/osdep.h" +#include "riscv-rpmi-test.h" + +static void test_rpmi_rvserver_ref_rejects_rpmi_property(void) +{ + rpmi_expect_qemu_failure( + "-machine riscv-server-ref,rpmi=3Doff -display none -S", + "Property 'riscv-server-ref-machine.rpmi' not found"); +} + +int main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + + if (!qtest_has_machine("riscv-server-ref")) { + return g_test_run(); + } + + qtest_add_func("/riscv/rpmi/rvserver-ref/machine/rejects-rpmi-property= ", + test_rpmi_rvserver_ref_rejects_rpmi_property); + rpmi_register_common_tests("/riscv/rpmi/rvserver-ref", + &rvserver_ref_rpmi_machine, + RPMI_QTEST_SERVER_REF); + + return g_test_run(); +} diff --git a/tests/qtest/riscv-rpmi-test.c b/tests/qtest/riscv-rpmi-test.c index fa23ab73db..e0557ccffa 100644 --- a/tests/qtest/riscv-rpmi-test.c +++ b/tests/qtest/riscv-rpmi-test.c @@ -1,7 +1,7 @@ /* * SPDX-License-Identifier: GPL-2.0-or-later * - * QTests for RISC-V RPMI devices. + * Common helpers for RISC-V RPMI qtests. * * Copyright (c) 2026 Qualcomm Technologies, Inc. * Author: @@ -9,71 +9,49 @@ */ =20 #include "qemu/osdep.h" -#include -#include "libqtest.h" +#include "riscv-rpmi-test.h" #include "qobject/qdict.h" =20 -#define RPMI_SHMEM_BASE 0x10200000ULL -#define RPMI_DOORBELL_BASE 0x10230000ULL -#define RPMI_SLOT_SIZE 64 - -#define RPMI_A2P_HEAD RPMI_SHMEM_BASE -#define RPMI_A2P_TAIL (RPMI_SHMEM_BASE + RPMI_SLOT_SIZE) -#define RPMI_A2P_SLOT0 (RPMI_SHMEM_BASE + 2 * RPMI_SLOT_SIZE) - -#define RPMI_SRVGRP_BASE 0x0001 -#define RPMI_SRVGRP_SYSTEM_RESET 0x0003 -#define RPMI_SRVGRP_SYSTEM_SUSPEND 0x0004 -#define RPMI_SRVGRP_HSM 0x0005 -#define RPMI_BASE_SRV_GET_PLATFORM_INFO 0x05 -#define RPMI_BASE_SRV_PROBE_SERVICE_GROUP 0x06 -#define RPMI_SYSRST_SRV_GET_ATTRIBUTES 0x02 -#define RPMI_SYSRST_SRV_SYSTEM_RESET 0x03 -#define RPMI_HSM_SRV_GET_HART_STATUS 0x02 -#define RPMI_HSM_SRV_GET_HART_LIST 0x03 -#define RPMI_HSM_SRV_GET_SUSPEND_TYPES 0x04 -#define RPMI_HSM_SRV_GET_SUSPEND_INFO 0x05 -#define RPMI_HSM_SRV_HART_START 0x06 -#define RPMI_HSM_SRV_HART_STOP 0x07 -#define RPMI_HSM_SRV_HART_SUSPEND 0x08 -#define RPMI_SYSSUSP_SRV_GET_ATTRIBUTES 0x02 -#define RPMI_SYSSUSP_SRV_SYSTEM_SUSPEND 0x03 -#define RPMI_MSG_NORMAL_REQUEST 0x00 -#define RPMI_MSG_POSTED_REQUEST 0x01 -#define RPMI_MSG_ACKNOWLEDGEMENT 0x02 -#define RPMI_SYSRST_TYPE_SHUTDOWN 0x00 -#define RPMI_SYSRST_TYPE_COLD_REBOOT 0x01 -#define RPMI_SYSRST_TYPE_INVALID 0x03 -#define RPMI_SYSRST_ATTRS_FLAGS_RESETTYPE 1 -#define RPMI_TOKEN 0x55aa -#define RPMI_ERR_NOTSUPP 0xfffffffeU -#define RPMI_ERR_INVALID_PARAM 0xfffffffdU -#define RPMI_ERR_INVALID_ADDR 0xfffffffbU -#define RPMI_ERR_DENIED 0xfffffffcU -#define RPMI_HSM_HART_STATE_STARTED 0x00 -#define RPMI_HSM_HART_STATE_STOPPED 0x01 -#define RPMI_HSM_HART_STATE_SUSPENDED 0x04 -#define RPMI_HSM_TEST_START_ADDR 0x80000000ULL -#define RPMI_HSM_TEST_RESUME_ADDR 0x80001000ULL - -#define RPMI_P2A_ACK_BASE (RPMI_SHMEM_BASE + 16 * RPMI_SLOT_SIZE) -#define RPMI_P2A_ACK_HEAD RPMI_P2A_ACK_BASE -#define RPMI_P2A_ACK_TAIL (RPMI_P2A_ACK_BASE + RPMI_SLOT_SIZE) -#define RPMI_P2A_ACK_SLOT0 (RPMI_P2A_ACK_BASE + 2 * RPMI_SLOT_SIZE) - +const RiscvRpmiQTestMachine virt_rpmi_machine =3D { + .machine_opts =3D "virt,rpmi=3Don", + .service_group_extra_args =3D ",aia=3Daplic-imsic", + .shmem_base =3D RPMI_SHMEM_BASE, + .doorbell_base =3D RPMI_DOORBELL_BASE, + .platform_info =3D "QEMU RISC-V virt RPMI", +}; + +const RiscvRpmiQTestMachine rvserver_ref_rpmi_machine =3D { + .machine_opts =3D "riscv-server-ref", + .service_group_extra_args =3D "", + .shmem_base =3D RVSERVER_RPMI_SHMEM_BASE, + .doorbell_base =3D RVSERVER_RPMI_DOORBELL_BASE, + .platform_info =3D "QEMU RISC-V server-ref RPMI", +}; + +uint64_t rpmi_shmem_base =3D RPMI_SHMEM_BASE; +uint64_t rpmi_doorbell_base =3D RPMI_DOORBELL_BASE; static uint64_t rpmi_response_base; =20 +QTestState *rpmi_qtest_init(const RiscvRpmiQTestMachine *machine, + const char *extra_args) +{ + rpmi_shmem_base =3D machine->shmem_base; + rpmi_doorbell_base =3D machine->doorbell_base; + + return qtest_initf("-machine %s%s", machine->machine_opts, extra_args); +} + static uint64_t rpmi_queue_slot(uint64_t queue_base, uint32_t index) { return queue_base + (index + 2) * RPMI_SLOT_SIZE; } =20 -static void rpmi_send_request(QTestState *qts, uint16_t service_group, - uint8_t service_id, uint8_t request_type, - const uint32_t *data, size_t data_words) +void rpmi_send_request(QTestState *qts, uint16_t service_group, + uint8_t service_id, uint8_t request_type, + const uint32_t *data, size_t data_words) { uint32_t tail =3D qtest_readl(qts, RPMI_A2P_TAIL); - uint64_t slot =3D rpmi_queue_slot(RPMI_SHMEM_BASE, tail); + uint64_t slot =3D rpmi_queue_slot(rpmi_shmem_base, tail); size_t i; =20 qtest_writew(qts, slot, service_group); @@ -90,21 +68,21 @@ static void rpmi_send_request(QTestState *qts, uint16_t= service_group, "RPMI_A2P_REQ shmem=3D0x%016" PRIx64 " doorbell=3D0x%016" PRIx64 " group=3D0x%04x service=3D0x%02x type=3D0x%02x data_len=3D%zu" " token=3D0x%04x a2p_tail=3D%u slot=3D0x%016" PRIx64, - (uint64_t)RPMI_SHMEM_BASE, (uint64_t)RPMI_DOORBELL_BASE, + (uint64_t)rpmi_shmem_base, (uint64_t)rpmi_doorbell_base, service_group, service_id, request_type, data_words * sizeof(*data= ), RPMI_TOKEN, tail, slot); =20 qtest_writel(qts, RPMI_A2P_TAIL, (tail + 1) % 16); - qtest_writel(qts, RPMI_DOORBELL_BASE, 1); + qtest_writel(qts, rpmi_doorbell_base, 1); } =20 -static uint32_t rpmi_response_word(QTestState *qts, unsigned int word) +uint32_t rpmi_response_word(QTestState *qts, unsigned int word) { return qtest_readl(qts, rpmi_response_base + 8 + word * sizeof(uint32_= t)); } =20 -static void rpmi_expect_ack(QTestState *qts, uint16_t service_group, - uint8_t service_id, uint16_t data_len) +void rpmi_expect_ack(QTestState *qts, uint16_t service_group, + uint8_t service_id, uint16_t data_len) { uint32_t head =3D qtest_readl(qts, RPMI_P2A_ACK_HEAD); uint32_t tail =3D qtest_readl(qts, RPMI_P2A_ACK_TAIL); @@ -124,23 +102,23 @@ static void rpmi_expect_ack(QTestState *qts, uint16_t= service_group, " group=3D0x%04x service=3D0x%02x type=3D0x%02x data_len=3D%u" " token=3D0x%04x p2a_head=3D%u slot=3D0x%016" PRIx64 " status=3D0x%08x", - (uint64_t)RPMI_SHMEM_BASE, service_group, service_id, + (uint64_t)rpmi_shmem_base, service_group, service_id, RPMI_MSG_ACKNOWLEDGEMENT, data_len, RPMI_TOKEN, head, rpmi_response_base, data_len >=3D sizeof(uint32_t) ? rpmi_response_word(qts, 0) : 0); qtest_writel(qts, RPMI_P2A_ACK_HEAD, (head + 1) % 16); } =20 -static void rpmi_send_sysreset(QTestState *qts, uint32_t reset_type, - uint8_t request_type) +void rpmi_send_sysreset(QTestState *qts, uint32_t reset_type, + uint8_t request_type) { rpmi_send_request(qts, RPMI_SRVGRP_SYSTEM_RESET, RPMI_SYSRST_SRV_SYSTEM_RESET, request_type, &reset_type, 1); } =20 -static void rpmi_expect_qemu_failure(const char *extra_args, - const char *stderr_needle) +void rpmi_expect_qemu_failure(const char *extra_args, + const char *stderr_needle) { g_autoptr(GError) error =3D NULL; g_auto(GStrv) split_args =3D NULL; @@ -169,47 +147,37 @@ static void rpmi_expect_qemu_failure(const char *extr= a_args, g_assert_nonnull(strstr(stderr_data, stderr_needle)); } =20 -static void test_rpmi_machine_realize_off(void) -{ - QTestState *qts; - - qts =3D qtest_init("-machine virt,rpmi=3Doff"); - qtest_quit(qts); -} - -static void test_rpmi_machine_rejects_too_many_harts(void) -{ - rpmi_expect_qemu_failure( - "-machine virt,rpmi=3Don -smp 513 -display none -S", - "max CPUs supported by machine 'virt' is 512"); -} - -static void test_rpmi_base_platform_info(void) +void rpmi_check_platform_info(QTestState *qts, const char *expected) { - static const char expected[] =3D "QEMU RISC-V virt RPMI"; - QTestState *qts; + size_t expected_len =3D strlen(expected) + 1; size_t i; =20 - qts =3D qtest_init("-machine virt,rpmi=3Don"); rpmi_send_request(qts, RPMI_SRVGRP_BASE, RPMI_BASE_SRV_GET_PLATFORM_INFO, RPMI_MSG_NORMAL_REQUEST, NULL, 0); =20 rpmi_expect_ack(qts, RPMI_SRVGRP_BASE, RPMI_BASE_SRV_GET_PLATFORM_INFO, - 2 * sizeof(uint32_t) + sizeof(expected)); + 2 * sizeof(uint32_t) + expected_len); g_assert_cmphex(rpmi_response_word(qts, 0), =3D=3D, 0); - g_assert_cmphex(rpmi_response_word(qts, 1), =3D=3D, sizeof(expected)); - for (i =3D 0; i < sizeof(expected); i++) { + g_assert_cmphex(rpmi_response_word(qts, 1), =3D=3D, expected_len); + for (i =3D 0; i < expected_len; i++) { g_assert_cmphex(qtest_readb(qts, RPMI_P2A_ACK_SLOT0 + 16 + i), =3D= =3D, expected[i]); } +} + +void rpmi_test_platform_info(const RiscvRpmiQTestMachine *machine) +{ + QTestState *qts; + + qts =3D rpmi_qtest_init(machine, ""); + rpmi_check_platform_info(qts, machine->platform_info); =20 qtest_quit(qts); } =20 -static void rpmi_probe_group(QTestState *qts, uint32_t service_group, - bool present) +void rpmi_probe_group(QTestState *qts, uint32_t service_group, bool presen= t) { rpmi_send_request(qts, RPMI_SRVGRP_BASE, RPMI_BASE_SRV_PROBE_SERVICE_GROUP, @@ -226,11 +194,8 @@ static void rpmi_probe_group(QTestState *qts, uint32_t= service_group, } } =20 -static void test_rpmi_base_probe_service_groups(void) +void rpmi_check_service_groups(QTestState *qts) { - QTestState *qts; - - qts =3D qtest_init("-machine virt,rpmi=3Don,aia=3Daplic-imsic"); rpmi_probe_group(qts, RPMI_SRVGRP_BASE, true); qtest_system_reset(qts); rpmi_probe_group(qts, RPMI_SRVGRP_SYSTEM_RESET, true); @@ -238,16 +203,102 @@ static void test_rpmi_base_probe_service_groups(void) rpmi_probe_group(qts, RPMI_SRVGRP_HSM, true); qtest_system_reset(qts); rpmi_probe_group(qts, RPMI_SRVGRP_SYSTEM_SUSPEND, true); +} + +void rpmi_test_service_groups(const RiscvRpmiQTestMachine *machine, + const char *extra_args) +{ + QTestState *qts; + + qts =3D rpmi_qtest_init(machine, extra_args); + rpmi_check_service_groups(qts); =20 qtest_quit(qts); } =20 -static void test_rpmi_sysreset_attrs(void) +void rpmi_check_hsm_hart_list(QTestState *qts, uint32_t hart_count) +{ + uint32_t start_index =3D 0; + + rpmi_send_request(qts, RPMI_SRVGRP_HSM, RPMI_HSM_SRV_GET_HART_LIST, + RPMI_MSG_NORMAL_REQUEST, &start_index, 1); + + rpmi_expect_ack(qts, RPMI_SRVGRP_HSM, RPMI_HSM_SRV_GET_HART_LIST, + (3 + hart_count) * sizeof(uint32_t)); + g_assert_cmphex(rpmi_response_word(qts, 0), =3D=3D, 0); + g_assert_cmphex(rpmi_response_word(qts, 1), =3D=3D, 0); + g_assert_cmphex(rpmi_response_word(qts, 2), =3D=3D, hart_count); + for (uint32_t i =3D 0; i < hart_count; i++) { + g_assert_cmphex(rpmi_response_word(qts, i + 3), =3D=3D, i); + } +} + +void rpmi_test_hsm_hart_list(const RiscvRpmiQTestMachine *machine, + const char *extra_args) { QTestState *qts; + + qts =3D rpmi_qtest_init(machine, extra_args); + rpmi_check_hsm_hart_list(qts, 4); + + qtest_quit(qts); +} + +void rpmi_expect_hsm_status(QTestState *qts, uint32_t hart_id, + uint32_t expected_state) +{ + rpmi_send_request(qts, RPMI_SRVGRP_HSM, RPMI_HSM_SRV_GET_HART_STATUS, + RPMI_MSG_NORMAL_REQUEST, &hart_id, 1); + rpmi_expect_ack(qts, RPMI_SRVGRP_HSM, RPMI_HSM_SRV_GET_HART_STATUS, + 2 * sizeof(uint32_t)); + g_assert_cmphex(rpmi_response_word(qts, 0), =3D=3D, 0); + g_assert_cmphex(rpmi_response_word(qts, 1), =3D=3D, expected_state); +} + +uint64_t rpmi_hart_pc(QTestState *qts, uint32_t cpu_index) +{ + g_autofree char *registers =3D qtest_hmp(qts, "info registers %u", + cpu_index); + const char *pc_line; + uint64_t pc; + + pc_line =3D strstr(registers, "\n pc"); + g_assert_nonnull(pc_line); + g_assert_cmpint(sscanf(pc_line, "\n pc %" SCNx64, &pc), =3D=3D, 1); + + return pc; +} + +static void rpmi_add_common_test(const char *prefix, const char *name, + const RiscvRpmiQTestMachine *machine, + void (*fn)(const void *)) +{ + g_autofree char *path =3D g_strdup_printf("%s/%s", prefix, name); + + qtest_add_data_func(path, machine, fn); +} + +static void test_rpmi_common_base_platform_info(const void *opaque) +{ + const RiscvRpmiQTestMachine *machine =3D opaque; + + rpmi_test_platform_info(machine); +} + +static void test_rpmi_common_base_probe_service_groups(const void *opaque) +{ + const RiscvRpmiQTestMachine *machine =3D opaque; + + rpmi_test_service_groups(machine, machine->service_group_extra_args); +} + +static void test_rpmi_common_sysreset_attrs(const void *opaque) +{ + const RiscvRpmiQTestMachine *machine =3D opaque; + QTestState *qts; uint32_t reset_type =3D RPMI_SYSRST_TYPE_SHUTDOWN; =20 - qts =3D qtest_init("-machine virt,rpmi=3Don"); + qts =3D rpmi_qtest_init(machine, ""); rpmi_send_request(qts, RPMI_SRVGRP_SYSTEM_RESET, RPMI_SYSRST_SRV_GET_ATTRIBUTES, RPMI_MSG_NORMAL_REQUEST, &reset_type, 1); @@ -281,33 +332,36 @@ static void test_rpmi_sysreset_attrs(void) qtest_quit(qts); } =20 -static void test_rpmi_sysreset_shutdown(void) +static void test_rpmi_common_sysreset_shutdown(const void *opaque) { + const RiscvRpmiQTestMachine *machine =3D opaque; QTestState *qts; =20 - qts =3D qtest_init("-machine virt,rpmi=3Don"); + qts =3D rpmi_qtest_init(machine, ""); rpmi_send_sysreset(qts, RPMI_SYSRST_TYPE_SHUTDOWN, RPMI_MSG_POSTED_REQUEST); qtest_qmp_eventwait(qts, "SHUTDOWN"); qtest_quit(qts); } =20 -static void test_rpmi_sysreset_cold_reboot(void) +static void test_rpmi_common_sysreset_cold_reboot(const void *opaque) { + const RiscvRpmiQTestMachine *machine =3D opaque; QTestState *qts; =20 - qts =3D qtest_init("-machine virt,rpmi=3Don -no-reboot"); + qts =3D rpmi_qtest_init(machine, " -no-reboot"); rpmi_send_sysreset(qts, RPMI_SYSRST_TYPE_COLD_REBOOT, RPMI_MSG_POSTED_REQUEST); qtest_qmp_eventwait(qts, "SHUTDOWN"); qtest_quit(qts); } =20 -static void test_rpmi_sysreset_invalid_type(void) +static void test_rpmi_common_sysreset_invalid_type(const void *opaque) { + const RiscvRpmiQTestMachine *machine =3D opaque; QTestState *qts; =20 - qts =3D qtest_init("-machine virt,rpmi=3Don"); + qts =3D rpmi_qtest_init(machine, ""); rpmi_send_sysreset(qts, RPMI_SYSRST_TYPE_INVALID, RPMI_MSG_NORMAL_REQUEST); =20 @@ -319,12 +373,13 @@ static void test_rpmi_sysreset_invalid_type(void) qtest_quit(qts); } =20 -static void test_rpmi_repeated_reset_after_traffic(void) +static void test_rpmi_common_repeated_reset_after_traffic(const void *opaq= ue) { + const RiscvRpmiQTestMachine *machine =3D opaque; QTestState *qts; uint32_t reset_type =3D RPMI_SYSRST_TYPE_SHUTDOWN; =20 - qts =3D qtest_init("-machine virt,rpmi=3Don,aia=3Daplic-imsic"); + qts =3D rpmi_qtest_init(machine, machine->service_group_extra_args); for (uint32_t i =3D 0; i < 5; i++) { rpmi_send_request(qts, RPMI_SRVGRP_SYSTEM_RESET, RPMI_SYSRST_SRV_GET_ATTRIBUTES, @@ -339,11 +394,12 @@ static void test_rpmi_repeated_reset_after_traffic(vo= id) qtest_quit(qts); } =20 -static void test_rpmi_reset_clears_transport(void) +static void test_rpmi_common_reset_clears_transport(const void *opaque) { + const RiscvRpmiQTestMachine *machine =3D opaque; QTestState *qts; =20 - qts =3D qtest_init("-machine virt,rpmi=3Don"); + qts =3D rpmi_qtest_init(machine, ""); rpmi_send_sysreset(qts, RPMI_SYSRST_TYPE_INVALID, RPMI_MSG_NORMAL_REQUEST); rpmi_expect_ack(qts, RPMI_SRVGRP_SYSTEM_RESET, @@ -353,43 +409,46 @@ static void test_rpmi_reset_clears_transport(void) =20 g_assert_cmphex(qtest_readl(qts, RPMI_A2P_TAIL), =3D=3D, 0); g_assert_cmphex(qtest_readl(qts, RPMI_P2A_ACK_TAIL), =3D=3D, 0); - g_assert_cmphex(qtest_readl(qts, RPMI_DOORBELL_BASE), =3D=3D, 0); + g_assert_cmphex(qtest_readl(qts, rpmi_doorbell_base), =3D=3D, 0); =20 qtest_quit(qts); } =20 -static void test_rpmi_doorbell_invalid_access(void) +static void test_rpmi_common_doorbell_invalid_access(const void *opaque) { + const RiscvRpmiQTestMachine *machine =3D opaque; QTestState *qts; =20 - qts =3D qtest_init("-machine virt,rpmi=3Don"); - qtest_writeb(qts, RPMI_DOORBELL_BASE, 1); - qtest_writel(qts, RPMI_DOORBELL_BASE + 4, 1); - g_assert_cmphex(qtest_readl(qts, RPMI_DOORBELL_BASE), =3D=3D, 0); + qts =3D rpmi_qtest_init(machine, ""); + qtest_writeb(qts, rpmi_doorbell_base, 1); + qtest_writel(qts, rpmi_doorbell_base + 4, 1); + g_assert_cmphex(qtest_readl(qts, rpmi_doorbell_base), =3D=3D, 0); =20 qtest_quit(qts); } =20 -static void test_rpmi_queue_bounds(void) +static void test_rpmi_common_queue_bounds(const void *opaque) { + const RiscvRpmiQTestMachine *machine =3D opaque; QTestState *qts; =20 - qts =3D qtest_init("-machine virt,rpmi=3Don"); + qts =3D rpmi_qtest_init(machine, ""); qtest_writel(qts, RPMI_A2P_TAIL, 0x1000); - qtest_writel(qts, RPMI_DOORBELL_BASE, 1); + qtest_writel(qts, rpmi_doorbell_base, 1); g_assert_cmphex(qtest_readl(qts, RPMI_A2P_HEAD), =3D=3D, 0); g_assert_cmphex(qtest_readl(qts, RPMI_P2A_ACK_TAIL), =3D=3D, 0); =20 qtest_quit(qts); } =20 -static void test_rpmi_migration_blocked(void) +static void test_rpmi_common_migration_blocked(const void *opaque) { + const RiscvRpmiQTestMachine *machine =3D opaque; QTestState *qts; QDict *error; const char *desc; =20 - qts =3D qtest_init("-machine virt,rpmi=3Don -S"); + qts =3D rpmi_qtest_init(machine, " -S"); error =3D qtest_qmp_assert_failure_ref(qts, "{ 'execute': 'migrate'," " 'arguments': { 'uri': 'exec:cat > /dev/null' } }"); @@ -403,57 +462,32 @@ static void test_rpmi_migration_blocked(void) qtest_quit(qts); } =20 -static void test_rpmi_hsm_hart_list(void) +static void test_rpmi_common_hsm_hart_list(const void *opaque) { - QTestState *qts; - uint32_t start_index =3D 0; - - qts =3D qtest_init("-machine virt,rpmi=3Don -smp 4"); - rpmi_send_request(qts, RPMI_SRVGRP_HSM, RPMI_HSM_SRV_GET_HART_LIST, - RPMI_MSG_NORMAL_REQUEST, &start_index, 1); - - rpmi_expect_ack(qts, RPMI_SRVGRP_HSM, RPMI_HSM_SRV_GET_HART_LIST, - 7 * sizeof(uint32_t)); - g_assert_cmphex(rpmi_response_word(qts, 0), =3D=3D, 0); - g_assert_cmphex(rpmi_response_word(qts, 1), =3D=3D, 0); - g_assert_cmphex(rpmi_response_word(qts, 2), =3D=3D, 4); - g_assert_cmphex(rpmi_response_word(qts, 3), =3D=3D, 0); - g_assert_cmphex(rpmi_response_word(qts, 4), =3D=3D, 1); - g_assert_cmphex(rpmi_response_word(qts, 5), =3D=3D, 2); - g_assert_cmphex(rpmi_response_word(qts, 6), =3D=3D, 3); + const RiscvRpmiQTestMachine *machine =3D opaque; =20 - qtest_quit(qts); + rpmi_test_hsm_hart_list(machine, " -smp 4"); } =20 -static void test_rpmi_hsm_multi_socket_hart_list(void) +static void test_rpmi_common_hsm_multi_socket_hart_list(const void *opaque) { + const RiscvRpmiQTestMachine *machine =3D opaque; QTestState *qts; - uint32_t start_index =3D 0; =20 - qts =3D qtest_init("-machine virt,rpmi=3Don " - "-smp 4,sockets=3D2,cores=3D2,threads=3D1"); - rpmi_send_request(qts, RPMI_SRVGRP_HSM, RPMI_HSM_SRV_GET_HART_LIST, - RPMI_MSG_NORMAL_REQUEST, &start_index, 1); - - rpmi_expect_ack(qts, RPMI_SRVGRP_HSM, RPMI_HSM_SRV_GET_HART_LIST, - 7 * sizeof(uint32_t)); - g_assert_cmphex(rpmi_response_word(qts, 0), =3D=3D, 0); - g_assert_cmphex(rpmi_response_word(qts, 1), =3D=3D, 0); - g_assert_cmphex(rpmi_response_word(qts, 2), =3D=3D, 4); - g_assert_cmphex(rpmi_response_word(qts, 3), =3D=3D, 0); - g_assert_cmphex(rpmi_response_word(qts, 4), =3D=3D, 1); - g_assert_cmphex(rpmi_response_word(qts, 5), =3D=3D, 2); - g_assert_cmphex(rpmi_response_word(qts, 6), =3D=3D, 3); + qts =3D rpmi_qtest_init(machine, + " -smp 4,sockets=3D2,cores=3D2,threads=3D1"); + rpmi_check_hsm_hart_list(qts, 4); =20 qtest_quit(qts); } =20 -static void test_rpmi_hsm_hart_status(void) +static void test_rpmi_common_hsm_hart_status(const void *opaque) { + const RiscvRpmiQTestMachine *machine =3D opaque; QTestState *qts; uint32_t hart_id =3D 3; =20 - qts =3D qtest_init("-machine virt,rpmi=3Don -smp 4"); + qts =3D rpmi_qtest_init(machine, " -smp 4"); rpmi_send_request(qts, RPMI_SRVGRP_HSM, RPMI_HSM_SRV_GET_HART_STATUS, RPMI_MSG_NORMAL_REQUEST, &hart_id, 1); =20 @@ -466,33 +500,9 @@ static void test_rpmi_hsm_hart_status(void) qtest_quit(qts); } =20 -static void rpmi_expect_hsm_status(QTestState *qts, uint32_t hart_id, - uint32_t expected_state) -{ - rpmi_send_request(qts, RPMI_SRVGRP_HSM, RPMI_HSM_SRV_GET_HART_STATUS, - RPMI_MSG_NORMAL_REQUEST, &hart_id, 1); - rpmi_expect_ack(qts, RPMI_SRVGRP_HSM, RPMI_HSM_SRV_GET_HART_STATUS, - 2 * sizeof(uint32_t)); - g_assert_cmphex(rpmi_response_word(qts, 0), =3D=3D, 0); - g_assert_cmphex(rpmi_response_word(qts, 1), =3D=3D, expected_state); -} - -static uint64_t rpmi_hart_pc(QTestState *qts, uint32_t cpu_index) -{ - g_autofree char *registers =3D qtest_hmp(qts, "info registers %u", - cpu_index); - const char *pc_line; - uint64_t pc; - - pc_line =3D strstr(registers, "\n pc"); - g_assert_nonnull(pc_line); - g_assert_cmpint(sscanf(pc_line, "\n pc %" SCNx64, &pc), =3D=3D, 1); - - return pc; -} - -static void test_rpmi_hsm_hart_control(void) +static void test_rpmi_common_hsm_hart_control(const void *opaque) { + const RiscvRpmiQTestMachine *machine =3D opaque; QTestState *qts; uint32_t hart_id =3D 1; uint32_t stop_request[] =3D { hart_id }; @@ -501,7 +511,7 @@ static void test_rpmi_hsm_hart_control(void) uint32_t start_index =3D 0; uint32_t suspend_type =3D 0; =20 - qts =3D qtest_init("-machine virt,rpmi=3Don -smp 2"); + qts =3D rpmi_qtest_init(machine, " -smp 2"); rpmi_send_request(qts, RPMI_SRVGRP_HSM, RPMI_HSM_SRV_GET_SUSPEND_TYPES, RPMI_MSG_NORMAL_REQUEST, &start_index, 1); rpmi_expect_ack(qts, RPMI_SRVGRP_HSM, RPMI_HSM_SRV_GET_SUSPEND_TYPES, @@ -547,13 +557,14 @@ static void test_rpmi_hsm_hart_control(void) qtest_quit(qts); } =20 -static void test_rpmi_syssusp_attrs_and_suspend(void) +static void test_rpmi_common_syssusp_attrs_and_suspend(const void *opaque) { + const RiscvRpmiQTestMachine *machine =3D opaque; QTestState *qts; uint32_t suspend_type =3D 0; uint32_t suspend_request[] =3D { 0, 0, 0x80000000, 0 }; =20 - qts =3D qtest_init("-machine virt,rpmi=3Don -smp 1"); + qts =3D rpmi_qtest_init(machine, " -smp 1"); rpmi_send_request(qts, RPMI_SRVGRP_SYSTEM_SUSPEND, RPMI_SYSSUSP_SRV_GET_ATTRIBUTES, RPMI_MSG_NORMAL_REQUEST, &suspend_type, 1); @@ -578,48 +589,67 @@ static void test_rpmi_syssusp_attrs_and_suspend(void) qtest_quit(qts); } =20 -int main(int argc, char **argv) -{ - g_test_init(&argc, &argv, NULL); - - if (qtest_has_machine("virt")) { - qtest_add_func("/riscv/rpmi/machine/realize-off", - test_rpmi_machine_realize_off); - qtest_add_func("/riscv/rpmi/machine/rejects-too-many-harts", - test_rpmi_machine_rejects_too_many_harts); - qtest_add_func("/riscv/rpmi/base/platform-info", - test_rpmi_base_platform_info); - qtest_add_func("/riscv/rpmi/base/probe-service-groups", - test_rpmi_base_probe_service_groups); - qtest_add_func("/riscv/rpmi/sysreset/attrs", - test_rpmi_sysreset_attrs); - qtest_add_func("/riscv/rpmi/sysreset/shutdown", - test_rpmi_sysreset_shutdown); - qtest_add_func("/riscv/rpmi/sysreset/cold-reboot", - test_rpmi_sysreset_cold_reboot); - qtest_add_func("/riscv/rpmi/sysreset/invalid-type", - test_rpmi_sysreset_invalid_type); - qtest_add_func("/riscv/rpmi/reset/clears-transport", - test_rpmi_reset_clears_transport); - qtest_add_func("/riscv/rpmi/negative/doorbell-invalid-access", - test_rpmi_doorbell_invalid_access); - qtest_add_func("/riscv/rpmi/negative/queue-bounds", - test_rpmi_queue_bounds); - qtest_add_func("/riscv/rpmi/reset/repeated-after-traffic", - test_rpmi_repeated_reset_after_traffic); - qtest_add_func("/riscv/rpmi/migration/blocked", - test_rpmi_migration_blocked); - qtest_add_func("/riscv/rpmi/hsm/hart-list", - test_rpmi_hsm_hart_list); - qtest_add_func("/riscv/rpmi/hsm/multi-socket-hart-list", - test_rpmi_hsm_multi_socket_hart_list); - qtest_add_func("/riscv/rpmi/hsm/hart-status", - test_rpmi_hsm_hart_status); - qtest_add_func("/riscv/rpmi/hsm/hart-control", - test_rpmi_hsm_hart_control); - qtest_add_func("/riscv/rpmi/syssusp/attrs-and-suspend", - test_rpmi_syssusp_attrs_and_suspend); +void rpmi_register_common_tests(const char *prefix, + const RiscvRpmiQTestMachine *machine, + unsigned int coverage) +{ + if (coverage & RPMI_QTEST_BASE) { + rpmi_add_common_test(prefix, "base/platform-info", machine, + test_rpmi_common_base_platform_info); + rpmi_add_common_test(prefix, "base/probe-service-groups", machine, + test_rpmi_common_base_probe_service_groups); } =20 - return g_test_run(); + if (coverage & RPMI_QTEST_SYSRESET) { + rpmi_add_common_test(prefix, "sysreset/attrs", machine, + test_rpmi_common_sysreset_attrs); + rpmi_add_common_test(prefix, "sysreset/shutdown", machine, + test_rpmi_common_sysreset_shutdown); + rpmi_add_common_test(prefix, "sysreset/cold-reboot", machine, + test_rpmi_common_sysreset_cold_reboot); + rpmi_add_common_test(prefix, "sysreset/invalid-type", machine, + test_rpmi_common_sysreset_invalid_type); + } + + if (coverage & RPMI_QTEST_RESET) { + rpmi_add_common_test(prefix, "reset/clears-transport", machine, + test_rpmi_common_reset_clears_transport); + } + + if (coverage & RPMI_QTEST_NEGATIVE) { + rpmi_add_common_test(prefix, "negative/doorbell-invalid-access", + machine, + test_rpmi_common_doorbell_invalid_access); + rpmi_add_common_test(prefix, "negative/queue-bounds", machine, + test_rpmi_common_queue_bounds); + } + + if (coverage & RPMI_QTEST_REPEATED_RESET) { + rpmi_add_common_test(prefix, "reset/repeated-after-traffic", machi= ne, + test_rpmi_common_repeated_reset_after_traffic= ); + } + + if (coverage & RPMI_QTEST_MIGRATION) { + rpmi_add_common_test(prefix, "migration/blocked", machine, + test_rpmi_common_migration_blocked); + } + + if (coverage & RPMI_QTEST_HSM) { + rpmi_add_common_test(prefix, "hsm/hart-list", machine, + test_rpmi_common_hsm_hart_list); + rpmi_add_common_test(prefix, "hsm/hart-status", machine, + test_rpmi_common_hsm_hart_status); + rpmi_add_common_test(prefix, "hsm/hart-control", machine, + test_rpmi_common_hsm_hart_control); + } + + if (coverage & RPMI_QTEST_HSM_MULTI_SOCKET) { + rpmi_add_common_test(prefix, "hsm/multi-socket-hart-list", machine, + test_rpmi_common_hsm_multi_socket_hart_list); + } + + if (coverage & RPMI_QTEST_SYSSUSP) { + rpmi_add_common_test(prefix, "syssusp/attrs-and-suspend", machine, + test_rpmi_common_syssusp_attrs_and_suspend); + } } diff --git a/tests/qtest/riscv-rpmi-test.h b/tests/qtest/riscv-rpmi-test.h new file mode 100644 index 0000000000..2fce0bb293 --- /dev/null +++ b/tests/qtest/riscv-rpmi-test.h @@ -0,0 +1,131 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * + * Common helpers for RISC-V RPMI qtests. + * + * Copyright (c) 2026 Qualcomm Technologies, Inc. + * Author: + * Subrahmanya Lingappa + */ + +#ifndef QTEST_RISCV_RPMI_TEST_H +#define QTEST_RISCV_RPMI_TEST_H + +#include "libqtest.h" + +#define RPMI_SHMEM_BASE 0x10200000ULL +#define RPMI_DOORBELL_BASE 0x10230000ULL +#define RVSERVER_RPMI_SHMEM_BASE 0x110000ULL +#define RVSERVER_RPMI_DOORBELL_BASE 0x140000ULL +#define RPMI_SLOT_SIZE 64 + +#define RPMI_A2P_HEAD rpmi_shmem_base +#define RPMI_A2P_TAIL (rpmi_shmem_base + RPMI_SLOT_SIZE) +#define RPMI_A2P_SLOT0 (rpmi_shmem_base + 2 * RPMI_SLOT_SIZE) + +#define RPMI_SRVGRP_BASE 0x0001 +#define RPMI_SRVGRP_SYSTEM_RESET 0x0003 +#define RPMI_SRVGRP_SYSTEM_SUSPEND 0x0004 +#define RPMI_SRVGRP_HSM 0x0005 +#define RPMI_BASE_SRV_GET_PLATFORM_INFO 0x05 +#define RPMI_BASE_SRV_PROBE_SERVICE_GROUP 0x06 +#define RPMI_SYSRST_SRV_GET_ATTRIBUTES 0x02 +#define RPMI_SYSRST_SRV_SYSTEM_RESET 0x03 +#define RPMI_HSM_SRV_GET_HART_STATUS 0x02 +#define RPMI_HSM_SRV_GET_HART_LIST 0x03 +#define RPMI_HSM_SRV_GET_SUSPEND_TYPES 0x04 +#define RPMI_HSM_SRV_GET_SUSPEND_INFO 0x05 +#define RPMI_HSM_SRV_HART_START 0x06 +#define RPMI_HSM_SRV_HART_STOP 0x07 +#define RPMI_HSM_SRV_HART_SUSPEND 0x08 +#define RPMI_SYSSUSP_SRV_GET_ATTRIBUTES 0x02 +#define RPMI_SYSSUSP_SRV_SYSTEM_SUSPEND 0x03 +#define RPMI_MSG_NORMAL_REQUEST 0x00 +#define RPMI_MSG_POSTED_REQUEST 0x01 +#define RPMI_MSG_ACKNOWLEDGEMENT 0x02 +#define RPMI_SYSRST_TYPE_SHUTDOWN 0x00 +#define RPMI_SYSRST_TYPE_COLD_REBOOT 0x01 +#define RPMI_SYSRST_TYPE_INVALID 0x03 +#define RPMI_SYSRST_ATTRS_FLAGS_RESETTYPE 1 +#define RPMI_TOKEN 0x55aa +#define RPMI_ERR_NOTSUPP 0xfffffffeU +#define RPMI_ERR_INVALID_PARAM 0xfffffffdU +#define RPMI_ERR_INVALID_ADDR 0xfffffffbU +#define RPMI_ERR_DENIED 0xfffffffcU +#define RPMI_HSM_HART_STATE_STARTED 0x00 +#define RPMI_HSM_HART_STATE_STOPPED 0x01 +#define RPMI_HSM_HART_STATE_SUSPENDED 0x04 +#define RPMI_HSM_TEST_START_ADDR 0x80000000ULL +#define RPMI_HSM_TEST_RESUME_ADDR 0x80001000ULL + +#define RPMI_P2A_ACK_BASE (rpmi_shmem_base + 16 * RPMI_SLOT_SIZE) +#define RPMI_P2A_ACK_HEAD RPMI_P2A_ACK_BASE +#define RPMI_P2A_ACK_TAIL (RPMI_P2A_ACK_BASE + RPMI_SLOT_SIZE) +#define RPMI_P2A_ACK_SLOT0 (RPMI_P2A_ACK_BASE + 2 * RPMI_SLOT_SIZE) + +typedef struct RiscvRpmiQTestMachine { + const char *machine_opts; + const char *service_group_extra_args; + uint64_t shmem_base; + uint64_t doorbell_base; + const char *platform_info; +} RiscvRpmiQTestMachine; + +typedef enum RiscvRpmiQTestCoverage { + RPMI_QTEST_BASE =3D 1 << 0, + RPMI_QTEST_SYSRESET =3D 1 << 1, + RPMI_QTEST_RESET =3D 1 << 2, + RPMI_QTEST_NEGATIVE =3D 1 << 3, + RPMI_QTEST_MIGRATION =3D 1 << 4, + RPMI_QTEST_HSM =3D 1 << 5, + RPMI_QTEST_HSM_MULTI_SOCKET =3D 1 << 6, + RPMI_QTEST_SYSSUSP =3D 1 << 7, + RPMI_QTEST_REPEATED_RESET =3D 1 << 8, +} RiscvRpmiQTestCoverage; + +#define RPMI_QTEST_ALL \ + (RPMI_QTEST_BASE | RPMI_QTEST_SYSRESET | RPMI_QTEST_RESET | \ + RPMI_QTEST_NEGATIVE | RPMI_QTEST_MIGRATION | RPMI_QTEST_HSM | \ + RPMI_QTEST_HSM_MULTI_SOCKET | RPMI_QTEST_SYSSUSP | \ + RPMI_QTEST_REPEATED_RESET) + +#define RPMI_QTEST_SERVER_REF \ + (RPMI_QTEST_BASE | RPMI_QTEST_SYSRESET | RPMI_QTEST_RESET | \ + RPMI_QTEST_NEGATIVE | RPMI_QTEST_MIGRATION | RPMI_QTEST_HSM | \ + RPMI_QTEST_SYSSUSP) + +extern const RiscvRpmiQTestMachine virt_rpmi_machine; +extern const RiscvRpmiQTestMachine rvserver_ref_rpmi_machine; + +extern uint64_t rpmi_shmem_base; +extern uint64_t rpmi_doorbell_base; + +QTestState *rpmi_qtest_init(const RiscvRpmiQTestMachine *machine, + const char *extra_args); +void rpmi_send_request(QTestState *qts, uint16_t service_group, + uint8_t service_id, uint8_t request_type, + const uint32_t *data, size_t data_words); +uint32_t rpmi_response_word(QTestState *qts, unsigned int word); +void rpmi_expect_ack(QTestState *qts, uint16_t service_group, + uint8_t service_id, uint16_t data_len); +void rpmi_send_sysreset(QTestState *qts, uint32_t reset_type, + uint8_t request_type); +void rpmi_expect_qemu_failure(const char *extra_args, + const char *stderr_needle); +void rpmi_check_platform_info(QTestState *qts, const char *expected); +void rpmi_test_platform_info(const RiscvRpmiQTestMachine *machine); +void rpmi_probe_group(QTestState *qts, uint32_t service_group, bool presen= t); +void rpmi_check_service_groups(QTestState *qts); +void rpmi_test_service_groups(const RiscvRpmiQTestMachine *machine, + const char *extra_args); +void rpmi_check_hsm_hart_list(QTestState *qts, uint32_t hart_count); +void rpmi_test_hsm_hart_list(const RiscvRpmiQTestMachine *machine, + const char *extra_args); +void rpmi_expect_hsm_status(QTestState *qts, uint32_t hart_id, + uint32_t expected_state); +uint64_t rpmi_hart_pc(QTestState *qts, uint32_t cpu_index); +void rpmi_register_common_tests(const char *prefix, + const RiscvRpmiQTestMachine *machine, + unsigned int coverage); + +#endif diff --git a/tests/qtest/riscv-rpmi-virt-test.c b/tests/qtest/riscv-rpmi-vi= rt-test.c new file mode 100644 index 0000000000..3aa73d3286 --- /dev/null +++ b/tests/qtest/riscv-rpmi-virt-test.c @@ -0,0 +1,45 @@ +/* + * SPDX-License-Identifier: GPL-2.0-or-later + * + * QTests for virt machine RPMI support. + * + * Copyright (c) 2026 Qualcomm Technologies, Inc. + * Author: + * Subrahmanya Lingappa + */ + +#include "qemu/osdep.h" +#include "riscv-rpmi-test.h" + +static void test_rpmi_machine_realize_off(void) +{ + QTestState *qts; + + qts =3D qtest_init("-machine virt,rpmi=3Doff"); + qtest_quit(qts); +} + +static void test_rpmi_machine_rejects_too_many_harts(void) +{ + rpmi_expect_qemu_failure( + "-machine virt,rpmi=3Don -smp 513 -display none -S", + "max CPUs supported by machine 'virt' is 512"); +} + +int main(int argc, char **argv) +{ + g_test_init(&argc, &argv, NULL); + + if (!qtest_has_machine("virt")) { + return g_test_run(); + } + + qtest_add_func("/riscv/rpmi/virt/machine/realize-off", + test_rpmi_machine_realize_off); + qtest_add_func("/riscv/rpmi/virt/machine/rejects-too-many-harts", + test_rpmi_machine_rejects_too_many_harts); + rpmi_register_common_tests("/riscv/rpmi/virt", &virt_rpmi_machine, + RPMI_QTEST_ALL); + + return g_test_run(); +} --=20 2.43.0