From nobody Tue Apr 7 11:23:58 2026 Received: from PH8PR06CU001.outbound.protection.outlook.com (mail-westus3azon11012038.outbound.protection.outlook.com [40.107.209.38]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 52856389116; Fri, 13 Mar 2026 16:54:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=fail smtp.client-ip=40.107.209.38 ARC-Seal: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773420893; cv=fail; b=PE9fn3IdMoDc8Gt1UPLwNSyOf/OBTBju9GDWoeL2Q833Bh2+b735ENLnbZ1fnLuyfP5hTyweQNubEe/A7RhLd784w/OZfroMC3NugXNxoLldENpwfSINByWfOkT6PRQDmQEez5DfmrlE+Pl9f42wiprE6zGYg/nkE3v27uGxn3c= ARC-Message-Signature: i=2; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773420893; c=relaxed/simple; bh=JDmn1Xfmyg+iQAMIuceZzrcGuQhXgBkyKHVTt7GmtrA=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=rN3DzrYmTBYTZABNT+lTF93Jtst79wLUktlYNvOM+saFiJzR/EhBXNsf5txHwkQ6HdDas9Dxtb1765CzycCKHq79XNIkjKe1BVcR1uaeEJfeSBEm9iixYleE4++/M8p4NUNv8vsYDaQWhu7HR/KULtxAQZSjmNMqG2IeAuiTU0M= ARC-Authentication-Results: i=2; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com; spf=fail smtp.mailfrom=nvidia.com; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b=ERMw6Z0a; arc=fail smtp.client-ip=40.107.209.38 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=nvidia.com Authentication-Results: smtp.subspace.kernel.org; spf=fail smtp.mailfrom=nvidia.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=Nvidia.com header.i=@Nvidia.com header.b="ERMw6Z0a" ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=IENqiEsf7eHfMr2bbTURDnWnwZEjxGigbYFNWCUGG61GEVLG2Emm/ePSHYuPloW2H77VBDsKCBaCfERRxt1eeCSrqtt0oLo2+CxS3suL3rFzBjvqtEjdXggx66kLOWWABmn8zw6kltttmBFM1FbLj09OkZavTDXTCMpUE4eFQi7CDuDQdD/wvMqFSdAl+yyud0rLsO+TqvMo+Fe1qoKpOeCm4hk4e2EUqgNxPbybovzf83YpCd2O5w9ECep7p2ngnB3o3J3advWbcgAUz412fZ+7NQCHjEk6VL+voJ1EABfgVZ3ghAExZVHK18Fte5984CWtxYMKkyVvPLzeb3yBHQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=GYGuZBCSPheyjzoevHlLwSM5DAiBVW3XG0PR7uXV3no=; b=JjeQhrCvpZw4AouAE/96Ci8rdVOxHDc2QlDpNsQwl5YVl8ev2a44Mv+hn5bOTDfw1mYgV6EMNMRGKT8w5XNFFjtYJnDfdVoNILWrC3KieBYHHnTe4MgSvnG1pPkPGLoGtSU2hDfTj7AzjnY44bl7I3CKwW3dLBCRgddS7wwRiOS9CiIm/QaSXXFtiL/6yyQyXf7j3FeBkaws1i2895B1hlUZXCTRwxMPokYqbibCRSMBwmabzrlrG1V8T7rtO1eHziEK1nMfP9TMP20tqjZBBtynrFF3p3zmTyJiponB2tcEF9LZdWpeIJyBbF8Wl3TctDMeLbASuJ3z6JC7OLjHxw== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 216.228.117.161) smtp.rcpttodomain=kernel.org smtp.mailfrom=nvidia.com; dmarc=pass (p=reject sp=reject pct=100) action=none header.from=nvidia.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=Nvidia.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=GYGuZBCSPheyjzoevHlLwSM5DAiBVW3XG0PR7uXV3no=; b=ERMw6Z0a+UVUzKqiEgGfP/BXQlZ0ktvdb86XtK894/K8Wrr7CYEkRYs6dfH6RNQj0PsMmqJaEeTevZtkEWh9HpjLm3ZEdIh6EhiwxGh2vcVeA+btGVxxWHuNWiLkyExo8Zv0c7Q+U8SnpfQ20/x9oo2DF+atmDEQHx1Dgmi9qgKPl1nClOKrXbjz0Kpw4qy1jygE+qk0XPZqGpvMPW1GkxsoQ++cnjexcCIt+AVULGyiVaqtDeblSFiL1zy7egR5+GTdB+XdP7MJzXVZ4UDoQg1tTveCNmCpqXvgE4Iw6LBp0QFV4lN9byObakKCOt01fIKfYlqfQnFfYrCfS1xcyQ== Received: from BLAPR05CA0001.namprd05.prod.outlook.com (2603:10b6:208:36e::6) by CY8PR12MB8195.namprd12.prod.outlook.com (2603:10b6:930:77::17) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9723.8; Fri, 13 Mar 2026 16:54:45 +0000 Received: from BL02EPF00029929.namprd02.prod.outlook.com (2603:10b6:208:36e:cafe::c8) by BLAPR05CA0001.outlook.office365.com (2603:10b6:208:36e::6) with Microsoft SMTP Server (version=TLS1_3, cipher=TLS_AES_256_GCM_SHA384) id 15.20.9700.17 via Frontend Transport; Fri, 13 Mar 2026 16:54:43 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 216.228.117.161) smtp.mailfrom=nvidia.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=nvidia.com; Received-SPF: Pass (protection.outlook.com: domain of nvidia.com designates 216.228.117.161 as permitted sender) receiver=protection.outlook.com; client-ip=216.228.117.161; helo=mail.nvidia.com; pr=C Received: from mail.nvidia.com (216.228.117.161) by BL02EPF00029929.mail.protection.outlook.com (10.167.249.54) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.9700.17 via Frontend Transport; Fri, 13 Mar 2026 16:54:44 +0000 Received: from rnnvmail204.nvidia.com (10.129.68.6) by mail.nvidia.com (10.129.200.67) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.20; Fri, 13 Mar 2026 09:54:26 -0700 Received: from rnnvmail201.nvidia.com (10.129.68.8) by rnnvmail204.nvidia.com (10.129.68.6) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.20; Fri, 13 Mar 2026 09:54:25 -0700 Received: from inno-dell.nvidia.com (10.127.8.11) by mail.nvidia.com (10.129.68.8) with Microsoft SMTP Server id 15.2.2562.20 via Frontend Transport; Fri, 13 Mar 2026 09:54:17 -0700 From: Zhi Wang To: , , , , , , CC: , , , , , , , , , , , , , , , , "Zhi Wang" Subject: [RFC v2 04/10] gpu: nova-core: read vGPU mode from FSP via PRC protocol Date: Fri, 13 Mar 2026 18:53:28 +0200 Message-ID: <20260313165336.935771-5-zhiw@nvidia.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: <20260313165336.935771-1-zhiw@nvidia.com> References: <20260313165336.935771-1-zhiw@nvidia.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-NV-OnPremToCloud: ExternallySecured X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: BL02EPF00029929:EE_|CY8PR12MB8195:EE_ X-MS-Office365-Filtering-Correlation-Id: 028d2122-17bc-45df-f04a-08de81213aa7 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|36860700016|82310400026|7416014|1800799024|376014|22082099003|18002099003|56012099003; X-Microsoft-Antispam-Message-Info: ZuwZTB60SHd9EjbEIxktFnHfvS8/WqAd4XvbQlUOlVhkbR9HwXMuWB2+9dBHWfo1uOGvdaescfeD1VJOH7atR0W9Eggt88sa7ypbwP3mgdXyTD2rQZ/S0iZKOArC1yg/KCZAcq/sxrFkGyfO4dmdl5nUsmHmIivUje0y6INrNc55jRspz2ijGH6oINeO9SsctpLsSHqUf0McF4n5uh4wNAvdPJzvF7Fjq1oYeyNlaaZN3j/Gpyy/eB0JVYfmfTzVCKNG8MjFWQ44jVCwsJ9uCvTTKq8q8Ka8DATy7L89vtGuoaF2KcTUy3beDDDxMDDhCOXYHqdr0RJsjLkLAVG18uzqdYSdukpRoc2ojrDvpLcyTar2DoJlm/QfeIz6Z/LVHYitzftaKDlLQUUYtmSut397hG5j6JlfIbOIqCa6YDUoxwofNLv2AXgpMmFXtp3bVgGxBxc3UBOWoO+eAXZU+a2LnyVouop3H7JokIv7gUYenM0ig3cj/35jZD/8PIVYVK3TaefdxeqFPJXP2x7TxbtAXGLROoWg09DnoETDXj8w7e3Tu7mMaQDILtHxiSbtFQZ0XwIXgX+VDLGH90NAaxNFWTlRmSGFONOdRJwLvvKkMl1xtYz58fWfo02gO/EM537Z1dR0nXj4vB6ZWes6XUtjQrvK+PDlgHAbZVMmDXJA+u3WjhgmXyj4OAHKzPT9OwOJG5SbmQZ5QYlUXR/DdvozGFDp0EQUZNxAoEOAsTMAd2J5v5IPocHjGLbq9hc1f2VmBodk3R7nUdHBibiX/Q== X-Forefront-Antispam-Report: CIP:216.228.117.161;CTRY:US;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:mail.nvidia.com;PTR:dc6edge2.nvidia.com;CAT:NONE;SFS:(13230040)(36860700016)(82310400026)(7416014)(1800799024)(376014)(22082099003)(18002099003)(56012099003);DIR:OUT;SFP:1101; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: THsrPl5pJ4V28/sC9EOA/HYd+pXg3+pRU6rbl7HHelSwxv2fNXihkORRTpzTV4r7hyhk/j8F7eR4IKeYLAnJgjeIDfpjyfGE5jeAeddt42qv1i1/GH8CtaA1+MLccUVfrHEp44kXSTiotvZyRL675hAvuZ4KDqxqioDxAK88adGxR7EvOmNPIjRhSZ9lCnOlNPj3H5pEWEUCPcJ5AzOHLLgQDgZ1s+B+pTpgTaJ5EVvO8SzaGqFuYRSCms9XZe+WK2knJ8DNxRgJf3CJTHCfvnkLOXHjJ81Pw264XYQ2+uCj1kNgXCC+pDMQHOFhRCGqtQS0eznW2CI90INFuhL9IByOKUXdN5fSRATsqnBtIJQvCiT5K/RUGqM+nTqB9BeDbt2J8HHB9ILieCVJ/TynZd7YA8NPWx3roo5SzNe49YZbBdd0bgKwRoxmJRMJrjVC X-OriginatorOrg: Nvidia.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 13 Mar 2026 16:54:44.9381 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 028d2122-17bc-45df-f04a-08de81213aa7 X-MS-Exchange-CrossTenant-Id: 43083d15-7273-40c1-b7db-39efd9ccc17a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=43083d15-7273-40c1-b7db-39efd9ccc17a;Ip=[216.228.117.161];Helo=[mail.nvidia.com] X-MS-Exchange-CrossTenant-AuthSource: BL02EPF00029929.namprd02.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY8PR12MB8195 Content-Type: text/plain; charset="utf-8" Add support for querying the vGPU mode configuration from FSP using the PRC (Product Reconfiguration Control) protocol. PRC is an API system exposed through FSP's Management Partition that allows querying device configuration "knobs" without firmware updates. Add a VgpuMode enum that validates the raw PRC response value, returning an error for unexpected values. Signed-off-by: Zhi Wang --- drivers/gpu/nova-core/fsp.rs | 175 +++++++++++++++++++++++++++++++--- drivers/gpu/nova-core/mctp.rs | 2 + 2 files changed, 165 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/nova-core/fsp.rs b/drivers/gpu/nova-core/fsp.rs index 69e48b655879..e342bbf733b3 100644 --- a/drivers/gpu/nova-core/fsp.rs +++ b/drivers/gpu/nova-core/fsp.rs @@ -23,12 +23,18 @@ }, }; =20 -use crate::regs; - -use crate::mctp::{ - MctpHeader, - NvdmHeader, - NvdmType, // +use crate::{ + driver::Bar0, + falcon::{ + fsp::Fsp as FspEngine, + Falcon, // + }, + mctp::{ + MctpHeader, + NvdmHeader, + NvdmType, // + }, + regs, }; =20 /// FSP Chain of Trust protocol version. @@ -55,6 +61,23 @@ pub(crate) const fn raw(self) -> u16 { /// FSP secure boot completion timeout in milliseconds. const FSP_SECURE_BOOT_TIMEOUT_MS: i64 =3D 4000; =20 +/// PRC (Product Reconfiguration Control) protocol constants. +/// +/// PRC is an API system exposed through FSP's Management Partition that a= llows +/// querying and modifying device configuration "knobs" without firmware u= pdates. +/// Each knob is identified by a unique object ID and controls a specific = device +/// behavior (e.g., vGPU mode, ECC, confidential computing). +mod prc { + /// Sub-command to read a PRC knob value. + pub(super) const SUBCMD_READ: u8 =3D 0x0c; + + /// PRC object ID for vGPU mode configuration (knob ID 41). + pub(super) const OBJECT_VGPU_MODE: u8 =3D 0x29; + + /// Request the active knob value (currently effective this boot). + pub(super) const FLAG_ACTIVE: u8 =3D 1 << 1; +} + /// GSP FMC initialization parameters. #[repr(C)] #[derive(Debug, Clone, Copy, Default)] @@ -171,7 +194,61 @@ struct NvdmPayloadCommandResponse { error_code: u32, } =20 -/// NVDM (NVIDIA Device Management) COT (Chain of Trust) payload structure. +// SAFETY: NvdmPayloadCommandResponse is a packed C struct with only integ= ral fields. +unsafe impl FromBytes for NvdmPayloadCommandResponse {} + +/// vGPU operating mode as reported by FSP via the PRC protocol. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub(crate) enum VgpuMode { + /// vGPU support is disabled on this GPU. + Disabled =3D 0, + /// vGPU support is enabled on this GPU. + Enabled =3D 1, +} + +impl TryFrom for VgpuMode { + type Error =3D kernel::error::Error; + + fn try_from(value: u16) -> Result { + match value { + 0 =3D> Ok(VgpuMode::Disabled), + 1 =3D> Ok(VgpuMode::Enabled), + _ =3D> Err(EINVAL), + } + } +} + +/// PRC message payload. +/// +/// Sent to FSP to query or modify a device configuration knob. +/// The response includes the common FSP response header followed by +/// a [`NvdmPayloadPrcResponse`] with the knob's current state value. +#[repr(C, packed)] +#[derive(Clone, Copy)] +struct NvdmPayloadPrc { + sub_message_id: u8, + flags: u8, + object_id: u8, + reserved: u8, +} + +// SAFETY: NvdmPayloadPrc is a packed C struct with only integral fields. +unsafe impl AsBytes for NvdmPayloadPrc {} + +/// PRC response payload containing the knob state value. +#[repr(C, packed)] +#[derive(Clone, Copy)] +struct NvdmPayloadPrcResponse { + value_low: u8, + value_high: u8, + reserved1: u8, + reserved2: u8, +} + +// SAFETY: NvdmPayloadPrcResponse is a packed C struct with only integral = fields. +unsafe impl FromBytes for NvdmPayloadPrcResponse {} + +/// NVDM (NVIDIA Vendor Defined Message) COT (Chain of Trust) payload stru= cture. /// This is the main message payload sent to FSP for Chain of Trust. #[repr(C, packed)] #[derive(Clone, Copy)] @@ -224,6 +301,17 @@ struct FspCotMessage { // SAFETY: FspCotMessage is a packed C struct with only integral fields. unsafe impl AsBytes for FspCotMessage {} =20 +/// Complete FSP PRC message. +#[repr(C, packed)] +#[derive(Clone, Copy)] +struct FspPrcMessage { + header: FspMessageHeader, + prc: NvdmPayloadPrc, +} + +// SAFETY: FspPrcMessage is a packed C struct with only integral fields. +unsafe impl AsBytes for FspPrcMessage {} + /// Complete FSP response structure with MCTP and NVDM headers. #[repr(C, packed)] #[derive(Clone, Copy)] @@ -235,6 +323,18 @@ struct FspResponse { // SAFETY: FspResponse is a packed C struct with only integral fields. unsafe impl FromBytes for FspResponse {} =20 +/// Complete FSP PRC response including the knob state payload. +#[repr(C, packed)] +#[derive(Clone, Copy)] +struct FspPrcResponse { + header: FspMessageHeader, + response: NvdmPayloadCommandResponse, + prc_data: NvdmPayloadPrcResponse, +} + +// SAFETY: FspPrcResponse is a packed C struct with only integral fields. +unsafe impl FromBytes for FspPrcResponse {} + /// Trait implemented by types representing a message to send to FSP. /// /// This provides [`Fsp::send_sync_fsp`] with the information it needs to = send @@ -305,17 +405,68 @@ pub(crate) fn boot_params_dma_handle(&self) -> u64 { } } =20 +impl MessageToFsp for FspPrcMessage { + const NVDM_TYPE: u32 =3D NvdmType::Prc as u32; +} + /// FSP interface for Hopper/Blackwell GPUs. pub(crate) struct Fsp; =20 impl Fsp { + /// Read vGPU mode from FSP using the PRC protocol. + /// + /// Queries FSP's Management Partition for the active vGPU mode knob v= alue. + /// Returns [`VgpuMode::Enabled`] if vGPU support is active on this GP= U, + /// [`VgpuMode::Disabled`] otherwise. + pub(crate) fn read_vgpu_mode( + dev: &device::Device, + bar: &Bar0, + fsp_falcon: &Falcon, + ) -> Result { + let msg =3D KBox::new( + FspPrcMessage { + header: FspMessageHeader::new(NvdmType::Prc), + prc: NvdmPayloadPrc { + sub_message_id: prc::SUBCMD_READ, + flags: prc::FLAG_ACTIVE, + object_id: prc::OBJECT_VGPU_MODE, + reserved: 0, + }, + }, + GFP_KERNEL, + )?; + + let response_buf =3D Self::send_sync_fsp(dev, bar, fsp_falcon, &*m= sg)?; + + let prc_resp_size =3D core::mem::size_of::(); + if response_buf.len() < prc_resp_size { + dev_err!( + dev, + "PRC response too small: {} bytes (expected {})\n", + response_buf.len(), + prc_resp_size + ); + return Err(EIO); + } + + let prc_response =3D + FspPrcResponse::from_bytes(&response_buf[..prc_resp_size]).ok_= or(EIO)?; + + let raw_value =3D u16::from(prc_response.prc_data.value_low) + | (u16::from(prc_response.prc_data.value_high) << 8); + + VgpuMode::try_from(raw_value).inspect_err(|_| { + dev_err!(dev, "unexpected vGPU mode value: {:#x}\n", raw_value= ); + }) + } + /// Wait for FSP secure boot completion. /// /// Polls the thermal scratch register until FSP signals boot completi= on /// or timeout occurs. pub(crate) fn wait_secure_boot( dev: &device::Device, - bar: &crate::driver::Bar0, + bar: &Bar0, arch: crate::gpu::Architecture, ) -> Result { debug_assert!( @@ -403,8 +554,8 @@ pub(crate) fn extract_fmc_signatures( /// to FSP, and waits for the response. pub(crate) fn boot_fmc( dev: &device::Device, - bar: &crate::driver::Bar0, - fsp_falcon: &crate::falcon::Falcon, + bar: &Bar0, + fsp_falcon: &Falcon, args: &FmcBootArgs<'_>, ) -> Result { dev_dbg!(dev, "Starting FSP boot sequence for {}\n", args.chipset); @@ -457,8 +608,8 @@ pub(crate) fn boot_fmc( /// Returns the raw response buffer for protocol-specific parsing. fn send_sync_fsp( dev: &device::Device, - bar: &crate::driver::Bar0, - fsp_falcon: &crate::falcon::Falcon, + bar: &Bar0, + fsp_falcon: &Falcon, msg: &M, ) -> Result> where diff --git a/drivers/gpu/nova-core/mctp.rs b/drivers/gpu/nova-core/mctp.rs index c4e36a46fd69..5c53e156d482 100644 --- a/drivers/gpu/nova-core/mctp.rs +++ b/drivers/gpu/nova-core/mctp.rs @@ -10,6 +10,8 @@ #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[repr(u32)] pub(crate) enum NvdmType { + /// PRC (Product Reconfiguration Control) message. + Prc =3D 0x13, /// Chain of Trust boot message. Cot =3D 0x14, /// FSP command response. --=20 2.51.0