drm/nouveau: add support for GH100

This commit enables basic support for Hopper GPUs, and is intended
primarily as a base supporting Blackwell GPUs, which reuse most of
the code added here.

Advanced features such as Confidential Compute are not supported.

Beyond a few miscellaneous register moves and HW class ID plumbing,
the bulk of the changes implemented here are to support the GSP-RM
boot sequence used on Hopper/Blackwell GPUs, as well as a new page
table layout.

There should be no changes here that impact prior GPUs.

Signed-off-by: Ben Skeggs <bskeggs@nvidia.com>
Co-developed-by: Timur Tabi <ttabi@nvidia.com>
Signed-off-by: Timur Tabi <ttabi@nvidia.com>
Reviewed-by: Dave Airlie <airlied@redhat.com>
Reviewed-by: Timur Tabi <ttabi@nvidia.com>
Tested-by: Timur Tabi <ttabi@nvidia.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
Ben Skeggs
2024-11-25 10:21:18 +10:00
committed by Dave Airlie
parent 76b8f81a5b
commit 44f93b209e
61 changed files with 1680 additions and 9 deletions

View File

@@ -0,0 +1,20 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*/
#ifndef __gh100_dev_falcon_v4_h__
#define __gh100_dev_falcon_v4_h__
#define NV_PFALCON_FALCON_MAILBOX0 0x00000040 /* RW-4R */
#define NV_PFALCON_FALCON_MAILBOX0_DATA 31:0 /* RWIVF */
#define NV_PFALCON_FALCON_MAILBOX0_DATA_INIT 0x00000000 /* RWI-V */
#define NV_PFALCON_FALCON_MAILBOX1 0x00000044 /* RW-4R */
#define NV_PFALCON_FALCON_MAILBOX1_DATA 31:0 /* RWIVF */
#define NV_PFALCON_FALCON_MAILBOX1_DATA_INIT 0x00000000 /* RWI-V */
#define NV_PFALCON_FALCON_HWCFG2 0x000000f4 /* R--4R */
#define NV_PFALCON_FALCON_HWCFG2_RISCV_BR_PRIV_LOCKDOWN 13:13 /* R--VF */
#define NV_PFALCON_FALCON_HWCFG2_RISCV_BR_PRIV_LOCKDOWN_LOCK 0x00000001 /* R---V */
#define NV_PFALCON_FALCON_HWCFG2_RISCV_BR_PRIV_LOCKDOWN_UNLOCK 0x00000000 /* R---V */
#endif // __gh100_dev_falcon_v4_h__

View File

@@ -0,0 +1,15 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*/
#ifndef __gh100_dev_fb_h_
#define __gh100_dev_fb_h_
#define NV_PFB_NISO_FLUSH_SYSMEM_ADDR_SHIFT 8 /* */
#define NV_PFB_FBHUB_PCIE_FLUSH_SYSMEM_ADDR_LO 0x00100A34 /* RW-4R */
#define NV_PFB_FBHUB_PCIE_FLUSH_SYSMEM_ADDR_LO_ADR 31:0 /* RWIVF */
#define NV_PFB_FBHUB_PCIE_FLUSH_SYSMEM_ADDR_HI 0x00100A38 /* RW-4R */
#define NV_PFB_FBHUB_PCIE_FLUSH_SYSMEM_ADDR_HI_ADR 31:0 /* RWIVF */
#define NV_PFB_FBHUB_PCIE_FLUSH_SYSMEM_ADDR_HI_ADR_MASK 0x000FFFFF /* ----V */
#endif // __gh100_dev_fb_h_

View File

@@ -0,0 +1,28 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*/
#ifndef __gh100_dev_fsp_pri_h__
#define __gh100_dev_fsp_pri_h__
#define NV_PFSP 0x8F3FFF:0x8F0000 /* RW--D */
#define NV_PFSP_MSGQ_HEAD(i) (0x008F2c80+(i)*8) /* RW-4A */
#define NV_PFSP_MSGQ_HEAD__SIZE_1 8 /* */
#define NV_PFSP_MSGQ_HEAD_VAL 31:0 /* RWIUF */
#define NV_PFSP_MSGQ_HEAD_VAL_INIT 0x00000000 /* RWI-V */
#define NV_PFSP_MSGQ_TAIL(i) (0x008F2c84+(i)*8) /* RW-4A */
#define NV_PFSP_MSGQ_TAIL__SIZE_1 8 /* */
#define NV_PFSP_MSGQ_TAIL_VAL 31:0 /* RWIUF */
#define NV_PFSP_MSGQ_TAIL_VAL_INIT 0x00000000 /* RWI-V */
#define NV_PFSP_QUEUE_HEAD(i) (0x008F2c00+(i)*8) /* RW-4A */
#define NV_PFSP_QUEUE_HEAD__SIZE_1 8 /* */
#define NV_PFSP_QUEUE_HEAD_ADDRESS 31:0 /* RWIVF */
#define NV_PFSP_QUEUE_HEAD_ADDRESS_INIT 0x00000000 /* RWI-V */
#define NV_PFSP_QUEUE_TAIL(i) (0x008F2c04+(i)*8) /* RW-4A */
#define NV_PFSP_QUEUE_TAIL__SIZE_1 8 /* */
#define NV_PFSP_QUEUE_TAIL_ADDRESS 31:0 /* RWIVF */
#define NV_PFSP_QUEUE_TAIL_ADDRESS_INIT 0x00000000 /* RWI-V */
#endif // __gh100_dev_fsp_pri_h__

View File

@@ -0,0 +1,173 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*/
#ifndef __gh100_dev_mmu_h__
#define __gh100_dev_mmu_h__
#define NV_MMU_PTE /* ----G */
#define NV_MMU_PTE_APERTURE (1*32+2):(1*32+1) /* RWXVF */
#define NV_MMU_PTE_APERTURE_VIDEO_MEMORY 0x00000000 /* RW--V */
#define NV_MMU_PTE_APERTURE_PEER_MEMORY 0x00000001 /* RW--V */
#define NV_MMU_PTE_APERTURE_SYSTEM_COHERENT_MEMORY 0x00000002 /* RW--V */
#define NV_MMU_PTE_APERTURE_SYSTEM_NON_COHERENT_MEMORY 0x00000003 /* RW--V */
#define NV_MMU_PTE_KIND (1*32+7):(1*32+4) /* RWXVF */
#define NV_MMU_PTE_KIND_INVALID 0x07 /* R---V */
#define NV_MMU_PTE_KIND_PITCH 0x00 /* R---V */
#define NV_MMU_PTE_KIND_GENERIC_MEMORY 0x6 /* R---V */
#define NV_MMU_PTE_KIND_Z16 0x1 /* R---V */
#define NV_MMU_PTE_KIND_S8 0x2 /* R---V */
#define NV_MMU_PTE_KIND_S8Z24 0x3 /* R---V */
#define NV_MMU_PTE_KIND_ZF32_X24S8 0x4 /* R---V */
#define NV_MMU_PTE_KIND_Z24S8 0x5 /* R---V */
#define NV_MMU_PTE_KIND_GENERIC_MEMORY_COMPRESSIBLE 0x8 /* R---V */
#define NV_MMU_PTE_KIND_GENERIC_MEMORY_COMPRESSIBLE_DISABLE_PLC 0x9 /* R---V */
#define NV_MMU_PTE_KIND_S8_COMPRESSIBLE_DISABLE_PLC 0xA /* R---V */
#define NV_MMU_PTE_KIND_Z16_COMPRESSIBLE_DISABLE_PLC 0xB /* R---V */
#define NV_MMU_PTE_KIND_S8Z24_COMPRESSIBLE_DISABLE_PLC 0xC /* R---V */
#define NV_MMU_PTE_KIND_ZF32_X24S8_COMPRESSIBLE_DISABLE_PLC 0xD /* R---V */
#define NV_MMU_PTE_KIND_Z24S8_COMPRESSIBLE_DISABLE_PLC 0xE /* R---V */
#define NV_MMU_PTE_KIND_SMSKED_MESSAGE 0xF /* R---V */
#define NV_MMU_VER3_PDE /* ----G */
#define NV_MMU_VER3_PDE_IS_PTE 0:0 /* RWXVF */
#define NV_MMU_VER3_PDE_IS_PTE_TRUE 0x1 /* RW--V */
#define NV_MMU_VER3_PDE_IS_PTE_FALSE 0x0 /* RW--V */
#define NV_MMU_VER3_PDE_VALID 0:0 /* RWXVF */
#define NV_MMU_VER3_PDE_VALID_TRUE 0x1 /* RW--V */
#define NV_MMU_VER3_PDE_VALID_FALSE 0x0 /* RW--V */
#define NV_MMU_VER3_PDE_APERTURE 2:1 /* RWXVF */
#define NV_MMU_VER3_PDE_APERTURE_INVALID 0x00000000 /* RW--V */
#define NV_MMU_VER3_PDE_APERTURE_VIDEO_MEMORY 0x00000001 /* RW--V */
#define NV_MMU_VER3_PDE_APERTURE_SYSTEM_COHERENT_MEMORY 0x00000002 /* RW--V */
#define NV_MMU_VER3_PDE_APERTURE_SYSTEM_NON_COHERENT_MEMORY 0x00000003 /* RW--V */
#define NV_MMU_VER3_PDE_PCF 5:3 /* RWXVF */
#define NV_MMU_VER3_PDE_PCF_VALID_CACHED_ATS_ALLOWED__OR__INVALID_ATS_ALLOWED 0x00000000 /* RW--V */
#define NV_MMU_VER3_PDE_PCF_VALID_CACHED_ATS_ALLOWED 0x00000000 /* RW--V */
#define NV_MMU_VER3_PDE_PCF_INVALID_ATS_ALLOWED 0x00000000 /* RW--V */
#define NV_MMU_VER3_PDE_PCF_VALID_UNCACHED_ATS_ALLOWED__OR__SPARSE_ATS_ALLOWED 0x00000001 /* RW--V */
#define NV_MMU_VER3_PDE_PCF_VALID_UNCACHED_ATS_ALLOWED 0x00000001 /* RW--V */
#define NV_MMU_VER3_PDE_PCF_SPARSE_ATS_ALLOWED 0x00000001 /* RW--V */
#define NV_MMU_VER3_PDE_PCF_VALID_CACHED_ATS_NOT_ALLOWED__OR__INVALID_ATS_NOT_ALLOWED 0x00000002 /* RW--V */
#define NV_MMU_VER3_PDE_PCF_VALID_CACHED_ATS_NOT_ALLOWED 0x00000002 /* RW--V */
#define NV_MMU_VER3_PDE_PCF_INVALID_ATS_NOT_ALLOWED 0x00000002 /* RW--V */
#define NV_MMU_VER3_PDE_PCF_VALID_UNCACHED_ATS_NOT_ALLOWED__OR__SPARSE_ATS_NOT_ALLOWED 0x00000003 /* RW--V */
#define NV_MMU_VER3_PDE_PCF_VALID_UNCACHED_ATS_NOT_ALLOWED 0x00000003 /* RW--V */
#define NV_MMU_VER3_PDE_PCF_SPARSE_ATS_NOT_ALLOWED 0x00000003 /* RW--V */
#define NV_MMU_VER3_PDE_ADDRESS 51:12 /* RWXVF */
#define NV_MMU_VER3_PDE_ADDRESS_SHIFT 0x0000000c /* */
#define NV_MMU_VER3_PDE__SIZE 8
#define NV_MMU_VER3_DUAL_PDE /* ----G */
#define NV_MMU_VER3_DUAL_PDE_IS_PTE 0:0 /* RWXVF */
#define NV_MMU_VER3_DUAL_PDE_IS_PTE_TRUE 0x1 /* RW--V */
#define NV_MMU_VER3_DUAL_PDE_IS_PTE_FALSE 0x0 /* RW--V */
#define NV_MMU_VER3_DUAL_PDE_VALID 0:0 /* RWXVF */
#define NV_MMU_VER3_DUAL_PDE_VALID_TRUE 0x1 /* RW--V */
#define NV_MMU_VER3_DUAL_PDE_VALID_FALSE 0x0 /* RW--V */
#define NV_MMU_VER3_DUAL_PDE_APERTURE_BIG 2:1 /* RWXVF */
#define NV_MMU_VER3_DUAL_PDE_APERTURE_BIG_INVALID 0x00000000 /* RW--V */
#define NV_MMU_VER3_DUAL_PDE_APERTURE_BIG_VIDEO_MEMORY 0x00000001 /* RW--V */
#define NV_MMU_VER3_DUAL_PDE_APERTURE_BIG_SYSTEM_COHERENT_MEMORY 0x00000002 /* RW--V */
#define NV_MMU_VER3_DUAL_PDE_APERTURE_BIG_SYSTEM_NON_COHERENT_MEMORY 0x00000003 /* RW--V */
#define NV_MMU_VER3_DUAL_PDE_PCF_BIG 5:3 /* RWXVF */
#define NV_MMU_VER3_DUAL_PDE_PCF_BIG_VALID_CACHED_ATS_ALLOWED__OR__INVALID_ATS_ALLOWED 0x00000000 /* RW--V */
#define NV_MMU_VER3_DUAL_PDE_PCF_BIG_VALID_CACHED_ATS_ALLOWED 0x00000000 /* RW--V */
#define NV_MMU_VER3_DUAL_PDE_PCF_BIG_INVALID_ATS_ALLOWED 0x00000000 /* RW--V */
#define NV_MMU_VER3_DUAL_PDE_PCF_BIG_VALID_UNCACHED_ATS_ALLOWED__OR__SPARSE_ATS_ALLOWED 0x00000001 /* RW--V */
#define NV_MMU_VER3_DUAL_PDE_PCF_BIG_VALID_UNCACHED_ATS_ALLOWED 0x00000001 /* RW--V */
#define NV_MMU_VER3_DUAL_PDE_PCF_BIG_SPARSE_ATS_ALLOWED 0x00000001 /* RW--V */
#define NV_MMU_VER3_DUAL_PDE_PCF_BIG_VALID_CACHED_ATS_NOT_ALLOWED__OR__INVALID_ATS_NOT_ALLOWED 0x00000002 /* RW--V */
#define NV_MMU_VER3_DUAL_PDE_PCF_BIG_VALID_CACHED_ATS_NOT_ALLOWED 0x00000002 /* RW--V */
#define NV_MMU_VER3_DUAL_PDE_PCF_BIG_INVALID_ATS_NOT_ALLOWED 0x00000002 /* RW--V */
#define NV_MMU_VER3_DUAL_PDE_PCF_BIG_VALID_UNCACHED_ATS_NOT_ALLOWED__OR__SPARSE_ATS_NOT_ALLOWED 0x00000003 /* RW--V */
#define NV_MMU_VER3_DUAL_PDE_PCF_BIG_VALID_UNCACHED_ATS_NOT_ALLOWED 0x00000003 /* RW--V */
#define NV_MMU_VER3_DUAL_PDE_PCF_BIG_SPARSE_ATS_NOT_ALLOWED 0x00000003 /* RW--V */
#define NV_MMU_VER3_DUAL_PDE_ADDRESS_BIG 51:8 /* RWXVF */
#define NV_MMU_VER3_DUAL_PDE_APERTURE_SMALL 66:65 /* RWXVF */
#define NV_MMU_VER3_DUAL_PDE_APERTURE_SMALL_INVALID 0x00000000 /* RW--V */
#define NV_MMU_VER3_DUAL_PDE_APERTURE_SMALL_VIDEO_MEMORY 0x00000001 /* RW--V */
#define NV_MMU_VER3_DUAL_PDE_APERTURE_SMALL_SYSTEM_COHERENT_MEMORY 0x00000002 /* RW--V */
#define NV_MMU_VER3_DUAL_PDE_APERTURE_SMALL_SYSTEM_NON_COHERENT_MEMORY 0x00000003 /* RW--V */
#define NV_MMU_VER3_DUAL_PDE_PCF_SMALL 69:67 /* RWXVF */
#define NV_MMU_VER3_DUAL_PDE_PCF_SMALL_VALID_CACHED_ATS_ALLOWED__OR__INVALID_ATS_ALLOWED 0x00000000 /* RW--V */
#define NV_MMU_VER3_DUAL_PDE_PCF_SMALL_VALID_CACHED_ATS_ALLOWED 0x00000000 /* RW--V */
#define NV_MMU_VER3_DUAL_PDE_PCF_SMALL_INVALID_ATS_ALLOWED 0x00000000 /* RW--V */
#define NV_MMU_VER3_DUAL_PDE_PCF_SMALL_VALID_UNCACHED_ATS_ALLOWED__OR__SPARSE_ATS_ALLOWED 0x00000001 /* RW--V */
#define NV_MMU_VER3_DUAL_PDE_PCF_SMALL_VALID_UNCACHED_ATS_ALLOWED 0x00000001 /* RW--V */
#define NV_MMU_VER3_DUAL_PDE_PCF_SMALL_SPARSE_ATS_ALLOWED 0x00000001 /* RW--V */
#define NV_MMU_VER3_DUAL_PDE_PCF_SMALL_VALID_CACHED_ATS_NOT_ALLOWED__OR__INVALID_ATS_NOT_ALLOWED 0x00000002 /* RW--V */
#define NV_MMU_VER3_DUAL_PDE_PCF_SMALL_VALID_CACHED_ATS_NOT_ALLOWED 0x00000002 /* RW--V */
#define NV_MMU_VER3_DUAL_PDE_PCF_SMALL_INVALID_ATS_NOT_ALLOWED 0x00000002 /* RW--V */
#define NV_MMU_VER3_DUAL_PDE_PCF_SMALL_VALID_UNCACHED_ATS_NOT_ALLOWED__OR__SPARSE_ATS_NOT_ALLOWED 0x00000003 /* RW--V */
#define NV_MMU_VER3_DUAL_PDE_PCF_SMALL_VALID_UNCACHED_ATS_NOT_ALLOWED 0x00000003 /* RW--V */
#define NV_MMU_VER3_DUAL_PDE_PCF_SMALL_SPARSE_ATS_NOT_ALLOWED 0x00000003 /* RW--V */
#define NV_MMU_VER3_DUAL_PDE_ADDRESS_SMALL 115:76 /* RWXVF */
#define NV_MMU_VER3_DUAL_PDE_ADDRESS_SHIFT 0x0000000c /* */
#define NV_MMU_VER3_DUAL_PDE_ADDRESS_BIG_SHIFT 8 /* */
#define NV_MMU_VER3_DUAL_PDE__SIZE 16
#define NV_MMU_VER3_PTE /* ----G */
#define NV_MMU_VER3_PTE_VALID 0:0 /* RWXVF */
#define NV_MMU_VER3_PTE_VALID_TRUE 0x1 /* RW--V */
#define NV_MMU_VER3_PTE_VALID_FALSE 0x0 /* RW--V */
#define NV_MMU_VER3_PTE_APERTURE 2:1 /* RWXVF */
#define NV_MMU_VER3_PTE_APERTURE_VIDEO_MEMORY 0x00000000 /* RW--V */
#define NV_MMU_VER3_PTE_APERTURE_PEER_MEMORY 0x00000001 /* RW--V */
#define NV_MMU_VER3_PTE_APERTURE_SYSTEM_COHERENT_MEMORY 0x00000002 /* RW--V */
#define NV_MMU_VER3_PTE_APERTURE_SYSTEM_NON_COHERENT_MEMORY 0x00000003 /* RW--V */
#define NV_MMU_VER3_PTE_PCF 7:3 /* RWXVF */
#define NV_MMU_VER3_PTE_PCF_INVALID 0x00000000 /* RW--V */
#define NV_MMU_VER3_PTE_PCF_SPARSE 0x00000001 /* RW--V */
#define NV_MMU_VER3_PTE_PCF_MAPPING_NOWHERE 0x00000002 /* RW--V */
#define NV_MMU_VER3_PTE_PCF_NO_VALID_4KB_PAGE 0x00000003 /* RW--V */
#define NV_MMU_VER3_PTE_PCF_REGULAR_RW_ATOMIC_CACHED_ACE 0x00000000 /* RW--V */
#define NV_MMU_VER3_PTE_PCF_REGULAR_RW_ATOMIC_UNCACHED_ACE 0x00000001 /* RW--V */
#define NV_MMU_VER3_PTE_PCF_PRIVILEGE_RW_ATOMIC_CACHED_ACE 0x00000002 /* RW--V */
#define NV_MMU_VER3_PTE_PCF_PRIVILEGE_RW_ATOMIC_UNCACHED_ACE 0x00000003 /* RW--V */
#define NV_MMU_VER3_PTE_PCF_REGULAR_RO_ATOMIC_CACHED_ACE 0x00000004 /* RW--V */
#define NV_MMU_VER3_PTE_PCF_REGULAR_RO_ATOMIC_UNCACHED_ACE 0x00000005 /* RW--V */
#define NV_MMU_VER3_PTE_PCF_PRIVILEGE_RO_ATOMIC_CACHED_ACE 0x00000006 /* RW--V */
#define NV_MMU_VER3_PTE_PCF_PRIVILEGE_RO_ATOMIC_UNCACHED_ACE 0x00000007 /* RW--V */
#define NV_MMU_VER3_PTE_PCF_REGULAR_RW_NO_ATOMIC_CACHED_ACE 0x00000008 /* RW--V */
#define NV_MMU_VER3_PTE_PCF_REGULAR_RW_NO_ATOMIC_UNCACHED_ACE 0x00000009 /* RW--V */
#define NV_MMU_VER3_PTE_PCF_PRIVILEGE_RW_NO_ATOMIC_CACHED_ACE 0x0000000A /* RW--V */
#define NV_MMU_VER3_PTE_PCF_PRIVILEGE_RW_NO_ATOMIC_UNCACHED_ACE 0x0000000B /* RW--V */
#define NV_MMU_VER3_PTE_PCF_REGULAR_RO_NO_ATOMIC_CACHED_ACE 0x0000000C /* RW--V */
#define NV_MMU_VER3_PTE_PCF_REGULAR_RO_NO_ATOMIC_UNCACHED_ACE 0x0000000D /* RW--V */
#define NV_MMU_VER3_PTE_PCF_PRIVILEGE_RO_NO_ATOMIC_CACHED_ACE 0x0000000E /* RW--V */
#define NV_MMU_VER3_PTE_PCF_PRIVILEGE_RO_NO_ATOMIC_UNCACHED_ACE 0x0000000F /* RW--V */
#define NV_MMU_VER3_PTE_PCF_REGULAR_RW_ATOMIC_CACHED_ACD 0x00000010 /* RW--V */
#define NV_MMU_VER3_PTE_PCF_REGULAR_RW_ATOMIC_UNCACHED_ACD 0x00000011 /* RW--V */
#define NV_MMU_VER3_PTE_PCF_PRIVILEGE_RW_ATOMIC_CACHED_ACD 0x00000012 /* RW--V */
#define NV_MMU_VER3_PTE_PCF_PRIVILEGE_RW_ATOMIC_UNCACHED_ACD 0x00000013 /* RW--V */
#define NV_MMU_VER3_PTE_PCF_REGULAR_RO_ATOMIC_CACHED_ACD 0x00000014 /* RW--V */
#define NV_MMU_VER3_PTE_PCF_REGULAR_RO_ATOMIC_UNCACHED_ACD 0x00000015 /* RW--V */
#define NV_MMU_VER3_PTE_PCF_PRIVILEGE_RO_ATOMIC_CACHED_ACD 0x00000016 /* RW--V */
#define NV_MMU_VER3_PTE_PCF_PRIVILEGE_RO_ATOMIC_UNCACHED_ACD 0x00000017 /* RW--V */
#define NV_MMU_VER3_PTE_PCF_REGULAR_RW_NO_ATOMIC_CACHED_ACD 0x00000018 /* RW--V */
#define NV_MMU_VER3_PTE_PCF_REGULAR_RW_NO_ATOMIC_UNCACHED_ACD 0x00000019 /* RW--V */
#define NV_MMU_VER3_PTE_PCF_PRIVILEGE_RW_NO_ATOMIC_CACHED_ACD 0x0000001A /* RW--V */
#define NV_MMU_VER3_PTE_PCF_PRIVILEGE_RW_NO_ATOMIC_UNCACHED_ACD 0x0000001B /* RW--V */
#define NV_MMU_VER3_PTE_PCF_REGULAR_RO_NO_ATOMIC_CACHED_ACD 0x0000001C /* RW--V */
#define NV_MMU_VER3_PTE_PCF_REGULAR_RO_NO_ATOMIC_UNCACHED_ACD 0x0000001D /* RW--V */
#define NV_MMU_VER3_PTE_PCF_PRIVILEGE_RO_NO_ATOMIC_CACHED_ACD 0x0000001E /* RW--V */
#define NV_MMU_VER3_PTE_PCF_PRIVILEGE_RO_NO_ATOMIC_UNCACHED_ACD 0x0000001F /* RW--V */
#define NV_MMU_VER3_PTE_KIND 11:8 /* RWXVF */
#define NV_MMU_VER3_PTE_ADDRESS 51:12 /* RWXVF */
#define NV_MMU_VER3_PTE_ADDRESS_SYS 51:12 /* RWXVF */
#define NV_MMU_VER3_PTE_ADDRESS_PEER 51:12 /* RWXVF */
#define NV_MMU_VER3_PTE_ADDRESS_VID 39:12 /* RWXVF */
#define NV_MMU_VER3_PTE_PEER_ID 63:(64-3) /* RWXVF */
#define NV_MMU_VER3_PTE_PEER_ID_0 0x00000000 /* RW--V */
#define NV_MMU_VER3_PTE_PEER_ID_1 0x00000001 /* RW--V */
#define NV_MMU_VER3_PTE_PEER_ID_2 0x00000002 /* RW--V */
#define NV_MMU_VER3_PTE_PEER_ID_3 0x00000003 /* RW--V */
#define NV_MMU_VER3_PTE_PEER_ID_4 0x00000004 /* RW--V */
#define NV_MMU_VER3_PTE_PEER_ID_5 0x00000005 /* RW--V */
#define NV_MMU_VER3_PTE_PEER_ID_6 0x00000006 /* RW--V */
#define NV_MMU_VER3_PTE_PEER_ID_7 0x00000007 /* RW--V */
#define NV_MMU_VER3_PTE_ADDRESS_SHIFT 0x0000000c /* */
#define NV_MMU_VER3_PTE__SIZE 8
#endif // __gh100_dev_mmu_h__

View File

@@ -0,0 +1,14 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*/
#ifndef __gh100_dev_riscv_pri_h__
#define __gh100_dev_riscv_pri_h__
#define NV_PRISCV_RISCV_CPUCTL 0x00000388 /* RW-4R */
#define NV_PRISCV_RISCV_CPUCTL_HALTED 4:4 /* R-IVF */
#define NV_PRISCV_RISCV_CPUCTL_HALTED_INIT 0x00000001 /* R-I-V */
#define NV_PRISCV_RISCV_CPUCTL_HALTED_TRUE 0x00000001 /* R---V */
#define NV_PRISCV_RISCV_CPUCTL_HALTED_FALSE 0x00000000 /* R---V */
#endif // __gh100_dev_riscv_pri_h__

View File

@@ -0,0 +1,17 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*/
#ifndef __gh100_dev_therm_h__
#define __gh100_dev_therm_h__
#define NV_THERM_I2CS_SCRATCH 0x000200bc /* RW-4R */
#define NV_THERM_I2CS_SCRATCH_DATA 31:0 /* RWIVF */
#define NV_THERM_I2CS_SCRATCH_DATA_INIT 0x00000000 /* RWI-V */
#define NV_THERM_I2CS_SCRATCH_FSP_BOOT_COMPLETE NV_THERM_I2CS_SCRATCH
#define NV_THERM_I2CS_SCRATCH_FSP_BOOT_COMPLETE_STATUS 31:0
#define NV_THERM_I2CS_SCRATCH_FSP_BOOT_COMPLETE_STATUS_SUCCESS 0x000000FF
#define NV_THERM_I2CS_SCRATCH_FSP_BOOT_COMPLETE_STATUS_FAILED 0x00000000
#endif // __gh100_dev_therm_h__

View File

@@ -0,0 +1,10 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*/
#ifndef __gh100_dev_xtl_ep_pri_h__
#define __gh100_dev_xtl_ep_pri_h__
#define NV_EP_PCFGM 0x92FFF:0x92000 /* RW--D */
#endif // __gh100_dev_xtl_ep_pri_h__

View File

@@ -0,0 +1,13 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*/
#ifndef __gh100_pri_nv_xal_ep_h__
#define __gh100_pri_nv_xal_ep_h__
#define NV_XAL_EP_BAR0_WINDOW_BASE_SHIFT 0x000010
#define NV_XAL_EP_BAR0_WINDOW_BASE 21:0
#define NV_XAL_EP_BAR0_WINDOW 0x0010fd40
#endif // __gh100_pri_nv_xal_ep_h__

View File

@@ -29,6 +29,7 @@ struct nv_device_info_v0 {
#define NV_DEVICE_INFO_V0_TURING 0x0c
#define NV_DEVICE_INFO_V0_AMPERE 0x0d
#define NV_DEVICE_INFO_V0_ADA 0x0e
#define NV_DEVICE_INFO_V0_HOPPER 0x0f
__u8 family;
__u8 pad06[2];
__u64 ram_size;

View File

@@ -63,6 +63,7 @@
#define VOLTA_USERMODE_A 0x0000c361
#define TURING_USERMODE_A 0x0000c461
#define AMPERE_USERMODE_A 0x0000c561
#define HOPPER_USERMODE_A 0x0000c661
#define MAXWELL_FAULT_BUFFER_A /* clb069.h */ 0x0000b069
#define VOLTA_FAULT_BUFFER_A /* clb069.h */ 0x0000c369
@@ -85,6 +86,7 @@
#define TURING_CHANNEL_GPFIFO_A /* if0020.h */ 0x0000c46f
#define AMPERE_CHANNEL_GPFIFO_A /* if0020.h */ 0x0000c56f
#define AMPERE_CHANNEL_GPFIFO_B /* if0020.h */ 0x0000c76f
#define HOPPER_CHANNEL_GPFIFO_A 0x0000c86f
#define NV50_DISP /* if0010.h */ 0x00005070
#define G82_DISP /* if0010.h */ 0x00008270
@@ -194,8 +196,11 @@
#define ADA_A /* cl9097.h */ 0x0000c997
#define HOPPER_A 0x0000cb97
#define NV74_BSP 0x000074b0
#define NVB8B0_VIDEO_DECODER 0x0000b8b0
#define NVC4B0_VIDEO_DECODER 0x0000c4b0
#define NVC6B0_VIDEO_DECODER 0x0000c6b0
#define NVC7B0_VIDEO_DECODER 0x0000c7b0
@@ -228,6 +233,7 @@
#define TURING_DMA_COPY_A 0x0000c5b5
#define AMPERE_DMA_COPY_A 0x0000c6b5
#define AMPERE_DMA_COPY_B 0x0000c7b5
#define HOPPER_DMA_COPY_A 0x0000c8b5
#define NVC4B7_VIDEO_ENCODER 0x0000c4b7
#define NVC7B7_VIDEO_ENCODER 0x0000c7b7
@@ -250,12 +256,15 @@
#define AMPERE_COMPUTE_A 0x0000c6c0
#define AMPERE_COMPUTE_B 0x0000c7c0
#define ADA_COMPUTE_A 0x0000c9c0
#define HOPPER_COMPUTE_A 0x0000cbc0
#define NV74_CIPHER 0x000074c1
#define NVB8D1_VIDEO_NVJPG 0x0000b8d1
#define NVC4D1_VIDEO_NVJPG 0x0000c4d1
#define NVC9D1_VIDEO_NVJPG 0x0000c9d1
#define NVB8FA_VIDEO_OFA 0x0000b8fa
#define NVC6FA_VIDEO_OFA 0x0000c6fa
#define NVC7FA_VIDEO_OFA 0x0000c7fa
#define NVC9FA_VIDEO_OFA 0x0000c9fa

View File

@@ -46,6 +46,7 @@ struct nvkm_device {
GV100 = 0x140,
TU100 = 0x160,
GA100 = 0x170,
GH100 = 0x180,
AD100 = 0x190,
} card_type;
u32 chipset;
@@ -131,6 +132,9 @@ struct nvkm_device *nvkm_device_find(u64 name);
_temp; \
})
#define NVKM_RD32_(p,o,dr) nvkm_rd32((p), (o) + (dr))
#define NVKM_RD32(p,A...) DRF_RV(NVKM_RD32_, (p), 0, ##A)
void nvkm_device_del(struct nvkm_device **);
struct nvkm_device_oclass {

View File

@@ -1,4 +1,5 @@
/* SPDX-License-Identifier: MIT */
NVKM_LAYOUT_ONCE(NVKM_SUBDEV_FSP , struct nvkm_fsp , fsp)
NVKM_LAYOUT_ONCE(NVKM_SUBDEV_GSP , struct nvkm_gsp , gsp)
NVKM_LAYOUT_ONCE(NVKM_SUBDEV_TOP , struct nvkm_top , top)
NVKM_LAYOUT_ONCE(NVKM_SUBDEV_VFN , struct nvkm_vfn , vfn)

View File

@@ -102,6 +102,7 @@ int gv100_fb_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct n
int tu102_fb_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fb **);
int ga100_fb_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fb **);
int ga102_fb_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fb **);
int gh100_fb_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fb **);
#include <subdev/bios.h>
#include <subdev/bios/ramcfg.h>

View File

@@ -0,0 +1,22 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*/
#ifndef __NVKM_FSP_H__
#define __NVKM_FSP_H__
#include <core/subdev.h>
#include <core/falcon.h>
struct nvkm_fsp {
const struct nvkm_fsp_func *func;
struct nvkm_subdev subdev;
struct nvkm_falcon falcon;
};
bool nvkm_fsp_verify_gsp_fmc(struct nvkm_fsp *, u32 hash_size, u32 pkey_size, u32 sig_size);
int nvkm_fsp_boot_gsp_fmc(struct nvkm_fsp *, u64 args_addr, u32 rsvd_size, bool resume,
u64 img_addr, const u8 *hash, const u8 *pkey, const u8 *sig);
int gh100_fsp_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fsp **);
#endif

View File

@@ -68,6 +68,9 @@ struct nvkm_gsp {
const struct firmware *load;
const struct firmware *unload;
} booter;
const struct firmware *fmc;
const struct firmware *bl;
const struct firmware *rm;
} fws;
@@ -113,6 +116,15 @@ struct nvkm_gsp {
struct nvkm_falcon_fw unload;
} booter;
struct {
struct nvkm_gsp_mem fw;
u8 *hash;
u8 *pkey;
u8 *sig;
struct nvkm_gsp_mem args;
} fmc;
struct {
struct nvkm_gsp_mem fw;
u32 code_offset;
@@ -478,5 +490,6 @@ int tu102_gsp_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_
int tu116_gsp_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_gsp **);
int ga100_gsp_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_gsp **);
int ga102_gsp_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_gsp **);
int gh100_gsp_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_gsp **);
int ad102_gsp_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_gsp **);
#endif

View File

@@ -36,4 +36,5 @@ int nv04_instmem_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nv
int nv40_instmem_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_instmem **);
int nv50_instmem_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_instmem **);
int gk20a_instmem_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_instmem **);
int gh100_instmem_new(struct nvkm_device *, enum nvkm_subdev_type, int, struct nvkm_instmem **);
#endif

View File

@@ -166,4 +166,5 @@ int gp100_mmu_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct
int gp10b_mmu_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_mmu **);
int gv100_mmu_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_mmu **);
int tu102_mmu_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_mmu **);
int gh100_mmu_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_mmu **);
#endif

View File

@@ -50,6 +50,7 @@ int gf100_pci_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct
int gf106_pci_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_pci **);
int gk104_pci_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_pci **);
int gp100_pci_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_pci **);
int gh100_pci_new(struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_pci **);
/* pcie functions */
int nvkm_pcie_set_link(struct nvkm_pci *, enum nvkm_pcie_speed, u8 width);

View File

@@ -923,6 +923,7 @@ nouveau_bo_move_init(struct nouveau_drm *drm)
struct ttm_resource *, struct ttm_resource *);
int (*init)(struct nouveau_channel *, u32 handle);
} _methods[] = {
{ "COPY", 4, 0xc8b5, nve0_bo_move_copy, nve0_bo_move_init },
{ "COPY", 4, 0xc7b5, nve0_bo_move_copy, nve0_bo_move_init },
{ "GRCE", 0, 0xc7b5, nve0_bo_move_copy, nvc0_bo_move_init },
{ "COPY", 4, 0xc6b5, nve0_bo_move_copy, nve0_bo_move_init },

View File

@@ -255,6 +255,7 @@ nouveau_channel_ctor(struct nouveau_cli *cli, bool priv, u64 runm,
struct nouveau_channel **pchan)
{
const struct nvif_mclass hosts[] = {
{ HOPPER_CHANNEL_GPFIFO_A, 0 },
{ AMPERE_CHANNEL_GPFIFO_B, 0 },
{ AMPERE_CHANNEL_GPFIFO_A, 0 },
{ TURING_CHANNEL_GPFIFO_A, 0 },

View File

@@ -509,6 +509,7 @@ nouveau_accel_init(struct nouveau_drm *drm)
case TURING_CHANNEL_GPFIFO_A:
case AMPERE_CHANNEL_GPFIFO_A:
case AMPERE_CHANNEL_GPFIFO_B:
case HOPPER_CHANNEL_GPFIFO_A:
ret = gv100_fence_create(drm);
break;
default:

View File

@@ -41,6 +41,7 @@ nvif_user_ctor(struct nvif_device *device, const char *name)
int version;
const struct nvif_user_func *func;
} users[] = {
{ HOPPER_USERMODE_A, -1, &nvif_userc361 },
{ AMPERE_USERMODE_A, -1, &nvif_userc361 },
{ TURING_USERMODE_A, -1, &nvif_userc361 },
{ VOLTA_USERMODE_A, -1, &nvif_userc361 },

View File

@@ -2681,6 +2681,22 @@ nv177_chipset = {
.sec2 = { 0x00000001, ga102_sec2_new },
};
static const struct nvkm_device_chip
nv180_chipset = {
.name = "GH100",
.bar = { 0x00000001, tu102_bar_new },
.fault = { 0x00000001, tu102_fault_new },
.fb = { 0x00000001, gh100_fb_new },
.fsp = { 0x00000001, gh100_fsp_new },
.gsp = { 0x00000001, gh100_gsp_new },
.imem = { 0x00000001, gh100_instmem_new },
.mmu = { 0x00000001, gh100_mmu_new },
.pci = { 0x00000001, gh100_pci_new },
.timer = { 0x00000001, gk20a_timer_new },
.vfn = { 0x00000001, ga100_vfn_new },
.fifo = { 0x00000001, ga102_fifo_new },
};
static const struct nvkm_device_chip
nv192_chipset = {
.name = "AD102",
@@ -3101,6 +3117,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
case 0x140: device->card_type = GV100; break;
case 0x160: device->card_type = TU100; break;
case 0x170: device->card_type = GA100; break;
case 0x180: device->card_type = GH100; break;
case 0x190: device->card_type = AD100; break;
default:
break;
@@ -3204,6 +3221,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
case 0x174: device->chip = &nv174_chipset; break;
case 0x176: device->chip = &nv176_chipset; break;
case 0x177: device->chip = &nv177_chipset; break;
case 0x180: device->chip = &nv180_chipset; break;
case 0x192: device->chip = &nv192_chipset; break;
case 0x193: device->chip = &nv193_chipset; break;
case 0x194: device->chip = &nv194_chipset; break;

View File

@@ -11,6 +11,7 @@
#include <subdev/devinit.h>
#include <subdev/fault.h>
#include <subdev/fb.h>
#include <subdev/fsp.h>
#include <subdev/fuse.h>
#include <subdev/gpio.h>
#include <subdev/gsp.h>

View File

@@ -148,6 +148,7 @@ nvkm_udevice_info(struct nvkm_udevice *udev, void *data, u32 size)
case TU100: args->v0.family = NV_DEVICE_INFO_V0_TURING; break;
case GA100: args->v0.family = NV_DEVICE_INFO_V0_AMPERE; break;
case AD100: args->v0.family = NV_DEVICE_INFO_V0_ADA; break;
case GH100: args->v0.family = NV_DEVICE_INFO_V0_HOPPER; break;
default:
args->v0.family = 0;
break;

View File

@@ -9,6 +9,7 @@ include $(src)/nvkm/subdev/fault/Kbuild
include $(src)/nvkm/subdev/fb/Kbuild
include $(src)/nvkm/subdev/fuse/Kbuild
include $(src)/nvkm/subdev/gpio/Kbuild
include $(src)/nvkm/subdev/fsp/Kbuild
include $(src)/nvkm/subdev/gsp/Kbuild
include $(src)/nvkm/subdev/i2c/Kbuild
include $(src)/nvkm/subdev/iccsense/Kbuild

View File

@@ -35,6 +35,7 @@ nvkm-y += nvkm/subdev/fb/gv100.o
nvkm-y += nvkm/subdev/fb/tu102.o
nvkm-y += nvkm/subdev/fb/ga100.o
nvkm-y += nvkm/subdev/fb/ga102.o
nvkm-y += nvkm/subdev/fb/gh100.o
nvkm-y += nvkm/subdev/fb/r535.o

View File

@@ -25,7 +25,7 @@
#include <subdev/gsp.h>
#include <engine/nvdec.h>
static u64
u64
ga102_fb_vidmem_size(struct nvkm_fb *fb)
{
return (u64)nvkm_rd32(fb->subdev.device, 0x1183a4) << 20;

View File

@@ -0,0 +1,30 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*/
#include "priv.h"
#include <nvhw/drf.h>
#include <nvhw/ref/gh100/dev_fb.h>
static void
gh100_fb_sysmem_flush_page_init(struct nvkm_fb *fb)
{
const u64 addr = fb->sysmem.flush_page_addr >> NV_PFB_NISO_FLUSH_SYSMEM_ADDR_SHIFT;
struct nvkm_device *device = fb->subdev.device;
nvkm_wr32(device, NV_PFB_FBHUB_PCIE_FLUSH_SYSMEM_ADDR_HI, upper_32_bits(addr));
nvkm_wr32(device, NV_PFB_FBHUB_PCIE_FLUSH_SYSMEM_ADDR_LO, lower_32_bits(addr));
}
static const struct nvkm_fb_func
gh100_fb = {
.sysmem.flush_page_init = gh100_fb_sysmem_flush_page_init,
.vidmem.size = ga102_fb_vidmem_size,
};
int
gh100_fb_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst, struct nvkm_fb **pfb)
{
return r535_fb_new(&gh100_fb, device, type, inst, pfb);
}

View File

@@ -98,4 +98,6 @@ int gp102_fb_vpr_scrub(struct nvkm_fb *);
int gv100_fb_init_page(struct nvkm_fb *);
bool tu102_fb_vpr_scrub_required(struct nvkm_fb *);
u64 ga102_fb_vidmem_size(struct nvkm_fb *);
#endif

View File

@@ -0,0 +1,6 @@
# SPDX-License-Identifier: MIT
#
# Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
nvkm-y += nvkm/subdev/fsp/base.o
nvkm-y += nvkm/subdev/fsp/gh100.o

View File

@@ -0,0 +1,66 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*/
#include "priv.h"
int
nvkm_fsp_boot_gsp_fmc(struct nvkm_fsp *fsp, u64 args_addr, u32 rsvd_size, bool resume,
u64 img_addr, const u8 *hash, const u8 *pkey, const u8 *sig)
{
return fsp->func->cot.boot_gsp_fmc(fsp, args_addr, rsvd_size, resume,
img_addr, hash, pkey, sig);
}
bool
nvkm_fsp_verify_gsp_fmc(struct nvkm_fsp *fsp, u32 hash_size, u32 pkey_size, u32 sig_size)
{
return hash_size == fsp->func->cot.size_hash &&
pkey_size == fsp->func->cot.size_pkey &&
sig_size == fsp->func->cot.size_sig;
}
static int
nvkm_fsp_preinit(struct nvkm_subdev *subdev)
{
struct nvkm_fsp *fsp = nvkm_fsp(subdev);
return fsp->func->wait_secure_boot(fsp);
}
static void *
nvkm_fsp_dtor(struct nvkm_subdev *subdev)
{
struct nvkm_fsp *fsp = nvkm_fsp(subdev);
nvkm_falcon_dtor(&fsp->falcon);
return fsp;
}
static const struct nvkm_falcon_func
nvkm_fsp_flcn = {
.emem_pio = &gp102_flcn_emem_pio,
};
static const struct nvkm_subdev_func
nvkm_fsp = {
.dtor = nvkm_fsp_dtor,
.preinit = nvkm_fsp_preinit,
};
int
nvkm_fsp_new_(const struct nvkm_fsp_func *func,
struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_fsp **pfsp)
{
struct nvkm_fsp *fsp;
fsp = *pfsp = kzalloc(sizeof(*fsp), GFP_KERNEL);
if (!fsp)
return -ENOMEM;
fsp->func = func;
nvkm_subdev_ctor(&nvkm_fsp, device, type, inst, &fsp->subdev);
return nvkm_falcon_ctor(&nvkm_fsp_flcn, &fsp->subdev, "fsp", 0x8f2000, &fsp->falcon);
}

View File

@@ -0,0 +1,275 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*/
#include "priv.h"
#include <nvhw/drf.h>
#include <nvhw/ref/gh100/dev_fsp_pri.h>
#include <nvhw/ref/gh100/dev_therm.h>
#include <nvrm/nvtypes.h>
#define MCTP_HEADER_VERSION 3:0
#define MCTP_HEADER_RSVD 7:4
#define MCTP_HEADER_DEID 15:8
#define MCTP_HEADER_SEID 23:16
#define MCTP_HEADER_TAG 26:24
#define MCTP_HEADER_TO 27:27
#define MCTP_HEADER_SEQ 29:28
#define MCTP_HEADER_EOM 30:30
#define MCTP_HEADER_SOM 31:31
#define MCTP_MSG_HEADER_TYPE 6:0
#define MCTP_MSG_HEADER_IC 7:7
#define MCTP_MSG_HEADER_VENDOR_ID 23:8
#define MCTP_MSG_HEADER_NVDM_TYPE 31:24
#define MCTP_MSG_HEADER_TYPE_VENDOR_PCI 0x7e
#define MCTP_MSG_HEADER_VENDOR_ID_NV 0x10de
#define NVDM_TYPE_COT 0x14
#define NVDM_TYPE_FSP_RESPONSE 0x15
#pragma pack(1)
typedef struct nvdm_payload_cot
{
NvU16 version;
NvU16 size;
NvU64 gspFmcSysmemOffset;
NvU64 frtsSysmemOffset;
NvU32 frtsSysmemSize;
// Note this is an offset from the end of FB
NvU64 frtsVidmemOffset;
NvU32 frtsVidmemSize;
// Authentication related fields
NvU32 hash384[12];
NvU32 publicKey[96];
NvU32 signature[96];
NvU64 gspBootArgsSysmemOffset;
} NVDM_PAYLOAD_COT;
#pragma pack()
#pragma pack(1)
typedef struct
{
NvU32 taskId;
NvU32 commandNvdmType;
NvU32 errorCode;
} NVDM_PAYLOAD_COMMAND_RESPONSE;
#pragma pack()
static u32
gh100_fsp_poll(struct nvkm_fsp *fsp)
{
struct nvkm_device *device = fsp->subdev.device;
u32 head, tail;
head = nvkm_rd32(device, NV_PFSP_MSGQ_HEAD(0));
tail = nvkm_rd32(device, NV_PFSP_MSGQ_TAIL(0));
if (head == tail)
return 0;
return (tail - head) + sizeof(u32); /* TAIL points at last DWORD written. */
}
static int
gh100_fsp_recv(struct nvkm_fsp *fsp, u8 *packet, u32 max_packet_size)
{
struct nvkm_device *device = fsp->subdev.device;
u32 packet_size;
int ret;
packet_size = gh100_fsp_poll(fsp);
if (!packet_size || WARN_ON(packet_size % 4 || packet_size > max_packet_size))
return -EINVAL;
ret = nvkm_falcon_pio_rd(&fsp->falcon, 0, EMEM, 0, packet, 0, packet_size);
if (ret)
return ret;
nvkm_wr32(device, NV_PFSP_MSGQ_TAIL(0), 0);
nvkm_wr32(device, NV_PFSP_MSGQ_HEAD(0), 0);
return packet_size;
}
static int
gh100_fsp_wait(struct nvkm_fsp *fsp)
{
int time = 1000;
do {
if (gh100_fsp_poll(fsp))
return 0;
usleep_range(1000, 2000);
} while(time--);
return -ETIMEDOUT;
}
static int
gh100_fsp_send(struct nvkm_fsp *fsp, const u8 *packet, u32 packet_size)
{
struct nvkm_device *device = fsp->subdev.device;
int time = 1000, ret;
if (WARN_ON(packet_size % sizeof(u32)))
return -EINVAL;
/* Ensure any previously sent message has been consumed. */
do {
u32 head = nvkm_rd32(device, NV_PFSP_QUEUE_HEAD(0));
u32 tail = nvkm_rd32(device, NV_PFSP_QUEUE_TAIL(0));
if (tail == head)
break;
usleep_range(1000, 2000);
} while(time--);
if (time < 0)
return -ETIMEDOUT;
/* Write message to EMEM. */
ret = nvkm_falcon_pio_wr(&fsp->falcon, packet, 0, 0, EMEM, 0, packet_size, 0, false);
if (ret)
return ret;
/* Update queue pointers - TAIL points at last DWORD written. */
nvkm_wr32(device, NV_PFSP_QUEUE_TAIL(0), packet_size - sizeof(u32));
nvkm_wr32(device, NV_PFSP_QUEUE_HEAD(0), 0);
return 0;
}
static int
gh100_fsp_send_sync(struct nvkm_fsp *fsp, u8 nvdm_type, const u8 *packet, u32 packet_size)
{
struct nvkm_subdev *subdev = &fsp->subdev;
struct {
u32 mctp_header;
u32 nvdm_header;
NVDM_PAYLOAD_COMMAND_RESPONSE response;
} reply;
int ret;
ret = gh100_fsp_send(fsp, packet, packet_size);
if (ret)
return ret;
ret = gh100_fsp_wait(fsp);
if (ret)
return ret;
ret = gh100_fsp_recv(fsp, (u8 *)&reply, sizeof(reply));
if (ret < 0)
return ret;
if (NVVAL_TEST(reply.mctp_header, MCTP, HEADER, SOM, !=, 1) ||
NVVAL_TEST(reply.mctp_header, MCTP, HEADER, EOM, !=, 1)) {
nvkm_error(subdev, "unexpected MCTP header in reply: 0x%08x\n", reply.mctp_header);
return -EIO;
}
if (NVDEF_TEST(reply.nvdm_header, MCTP, MSG_HEADER, TYPE, !=, VENDOR_PCI) ||
NVDEF_TEST(reply.nvdm_header, MCTP, MSG_HEADER, VENDOR_ID, !=, NV) ||
NVVAL_TEST(reply.nvdm_header, MCTP, MSG_HEADER, NVDM_TYPE, !=, NVDM_TYPE_FSP_RESPONSE)) {
nvkm_error(subdev, "unexpected NVDM header in reply: 0x%08x\n", reply.nvdm_header);
return -EIO;
}
if (reply.response.commandNvdmType != nvdm_type) {
nvkm_error(subdev, "expected NVDM type 0x%02x in reply, got 0x%02x\n",
nvdm_type, reply.response.commandNvdmType);
return -EIO;
}
if (reply.response.errorCode) {
nvkm_error(subdev, "NVDM command 0x%02x failed with error 0x%08x\n",
nvdm_type, reply.response.errorCode);
return -EIO;
}
return 0;
}
int
gh100_fsp_boot_gsp_fmc(struct nvkm_fsp *fsp, u64 args_addr, u32 rsvd_size, bool resume,
u64 img_addr, const u8 *hash, const u8 *pkey, const u8 *sig)
{
struct {
u32 mctp_header;
u32 nvdm_header;
NVDM_PAYLOAD_COT cot;
} msg = {};
msg.mctp_header = NVVAL(MCTP, HEADER, SOM, 1) |
NVVAL(MCTP, HEADER, EOM, 1) |
NVVAL(MCTP, HEADER, SEID, 0) |
NVVAL(MCTP, HEADER, SEQ, 0);
msg.nvdm_header = NVDEF(MCTP, MSG_HEADER, TYPE, VENDOR_PCI) |
NVDEF(MCTP, MSG_HEADER, VENDOR_ID, NV) |
NVVAL(MCTP, MSG_HEADER, NVDM_TYPE, NVDM_TYPE_COT);
msg.cot.version = fsp->func->cot.version;
msg.cot.size = sizeof(msg.cot);
msg.cot.gspFmcSysmemOffset = img_addr;
if (!resume) {
msg.cot.frtsVidmemOffset = ALIGN(rsvd_size, 0x200000);
msg.cot.frtsVidmemSize = 0x100000;
}
memcpy(msg.cot.hash384, hash, fsp->func->cot.size_hash);
memcpy(msg.cot.publicKey, pkey, fsp->func->cot.size_pkey);
memcpy(msg.cot.signature, sig, fsp->func->cot.size_sig);
msg.cot.gspBootArgsSysmemOffset = args_addr;
return gh100_fsp_send_sync(fsp, NVDM_TYPE_COT, (const u8 *)&msg, sizeof(msg));
}
static int
gh100_fsp_wait_secure_boot(struct nvkm_fsp *fsp)
{
struct nvkm_device *device = fsp->subdev.device;
unsigned timeout_ms = 4000;
do {
u32 status = NVKM_RD32(device, NV_THERM, I2CS_SCRATCH, FSP_BOOT_COMPLETE_STATUS);
if (status == NV_THERM_I2CS_SCRATCH_FSP_BOOT_COMPLETE_STATUS_SUCCESS)
return 0;
usleep_range(1000, 2000);
} while (timeout_ms--);
return -ETIMEDOUT;
}
static const struct nvkm_fsp_func
gh100_fsp = {
.wait_secure_boot = gh100_fsp_wait_secure_boot,
.cot = {
.version = 1,
.size_hash = 48,
.size_pkey = 384,
.size_sig = 384,
.boot_gsp_fmc = gh100_fsp_boot_gsp_fmc,
},
};
int
gh100_fsp_new(struct nvkm_device *device,
enum nvkm_subdev_type type, int inst, struct nvkm_fsp **pfsp)
{
return nvkm_fsp_new_(&gh100_fsp, device, type, inst, pfsp);
}

View File

@@ -0,0 +1,28 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*/
#ifndef __NVKM_FSP_PRIV_H__
#define __NVKM_FSP_PRIV_H__
#define nvkm_fsp(p) container_of((p), struct nvkm_fsp, subdev)
#include <subdev/fsp.h>
struct nvkm_fsp_func {
int (*wait_secure_boot)(struct nvkm_fsp *);
struct {
u32 version;
u32 size_hash;
u32 size_pkey;
u32 size_sig;
int (*boot_gsp_fmc)(struct nvkm_fsp *, u64 args_addr, u32 rsvd_size, bool resume,
u64 img_addr, const u8 *hash, const u8 *pkey, const u8 *sig);
} cot;
};
int nvkm_fsp_new_(const struct nvkm_fsp_func *,
struct nvkm_device *, enum nvkm_subdev_type, int inst, struct nvkm_fsp **);
int gh100_fsp_boot_gsp_fmc(struct nvkm_fsp *, u64 args_addr, u32 rsvd_size, bool resume,
u64 img_addr, const u8 *hash, const u8 *pkey, const u8 *sig);
#endif

View File

@@ -7,6 +7,7 @@ nvkm-y += nvkm/subdev/gsp/tu102.o
nvkm-y += nvkm/subdev/gsp/tu116.o
nvkm-y += nvkm/subdev/gsp/ga100.o
nvkm-y += nvkm/subdev/gsp/ga102.o
nvkm-y += nvkm/subdev/gsp/gh100.o
nvkm-y += nvkm/subdev/gsp/ad102.o
include $(src)/nvkm/subdev/gsp/rm/Kbuild

View File

@@ -83,6 +83,8 @@ nvkm_gsp_oneinit(struct nvkm_subdev *subdev)
void
nvkm_gsp_dtor_fws(struct nvkm_gsp *gsp)
{
nvkm_firmware_put(gsp->fws.fmc);
gsp->fws.fmc = NULL;
nvkm_firmware_put(gsp->fws.bl);
gsp->fws.bl = NULL;
nvkm_firmware_put(gsp->fws.booter.unload);

View File

@@ -0,0 +1,353 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*/
#include "priv.h"
#include <linux/elf.h>
#include <linux/crc32.h>
#include <subdev/fb.h>
#include <subdev/fsp.h>
#include <rm/r570/nvrm/gsp.h>
#include <nvhw/drf.h>
#include <nvhw/ref/gh100/dev_falcon_v4.h>
#include <nvhw/ref/gh100/dev_riscv_pri.h>
static int
gh100_gsp_fini(struct nvkm_gsp *gsp, bool suspend)
{
struct nvkm_falcon *falcon = &gsp->falcon;
int ret, time = 4000;
/* Shutdown RM. */
ret = r535_gsp_fini(gsp, suspend);
if (ret && suspend)
return ret;
/* Wait for RISC-V to halt. */
do {
u32 data = nvkm_falcon_rd32(falcon, falcon->addr2 + NV_PRISCV_RISCV_CPUCTL);
if (NVVAL_GET(data, NV_PRISCV, RISCV_CPUCTL, HALTED))
return 0;
usleep_range(1000, 2000);
} while(time--);
return -ETIMEDOUT;
}
static bool
gh100_gsp_lockdown_released(struct nvkm_gsp *gsp, u32 *mbox0)
{
u32 data;
/* Wait for GSP access via BAR0 to be allowed. */
*mbox0 = nvkm_falcon_rd32(&gsp->falcon, NV_PFALCON_FALCON_MAILBOX0);
if (*mbox0 && (*mbox0 & 0xffffff00) == 0xbadf4100)
return false;
/* Check if an error code has been reported. */
if (*mbox0) {
u32 mbox1 = nvkm_falcon_rd32(&gsp->falcon, NV_PFALCON_FALCON_MAILBOX1);
/* Any value that's not GSP_FMC_BOOT_PARAMS addr is an error. */
if ((((u64)mbox1 << 32) | *mbox0) != gsp->fmc.args.addr)
return true;
}
/* Check if lockdown has been released. */
data = nvkm_falcon_rd32(&gsp->falcon, NV_PFALCON_FALCON_HWCFG2);
return !NVVAL_GET(data, NV_PFALCON, FALCON_HWCFG2, RISCV_BR_PRIV_LOCKDOWN);
}
static int
gh100_gsp_init(struct nvkm_gsp *gsp)
{
struct nvkm_subdev *subdev = &gsp->subdev;
struct nvkm_device *device = subdev->device;
const bool resume = gsp->sr.meta.data != NULL;
struct nvkm_gsp_mem *meta;
GSP_FMC_BOOT_PARAMS *args;
int ret, time = 4000;
u32 mbox0;
if (!resume) {
ret = nvkm_gsp_mem_ctor(gsp, sizeof(*args), &gsp->fmc.args);
if (ret)
return ret;
meta = &gsp->wpr_meta;
} else {
gsp->rm->api->gsp->set_rmargs(gsp, true);
meta = &gsp->sr.meta;
}
args = gsp->fmc.args.data;
args->bootGspRmParams.gspRmDescOffset = meta->addr;
args->bootGspRmParams.gspRmDescSize = meta->size;
args->bootGspRmParams.target = GSP_DMA_TARGET_COHERENT_SYSTEM;
args->bootGspRmParams.bIsGspRmBoot = 1;
args->gspRmParams.target = GSP_DMA_TARGET_NONCOHERENT_SYSTEM;
args->gspRmParams.bootArgsOffset = gsp->libos.addr;
ret = nvkm_fsp_boot_gsp_fmc(device->fsp, gsp->fmc.args.addr, gsp->fb.heap.size, resume,
gsp->fmc.fw.addr, gsp->fmc.hash, gsp->fmc.pkey, gsp->fmc.sig);
if (ret)
return ret;
do {
if (gh100_gsp_lockdown_released(gsp, &mbox0))
break;
usleep_range(1000, 2000);
} while(time--);
if (time < 0) {
nvkm_error(subdev, "GSP-FMC boot timed out\n");
return -ETIMEDOUT;
}
if (mbox0) {
nvkm_error(subdev, "GSP-FMC boot failed (mbox: 0x%08x)\n", mbox0);
return -EIO;
}
return r535_gsp_init(gsp);
}
static int
gh100_gsp_wpr_meta_init(struct nvkm_gsp *gsp)
{
GspFwWprMeta *meta;
int ret;
ret = nvkm_gsp_mem_ctor(gsp, sizeof(*meta), &gsp->wpr_meta);
if (ret)
return ret;
gsp->fb.size = nvkm_fb_vidmem_size(gsp->subdev.device);
gsp->fb.bios.vga_workspace.size = 128 * 1024;
gsp->fb.heap.size = gsp->rm->wpr->heap_size_non_wpr;
meta = gsp->wpr_meta.data;
meta->magic = GSP_FW_WPR_META_MAGIC;
meta->revision = GSP_FW_WPR_META_REVISION;
meta->sizeOfRadix3Elf = gsp->fw.len;
meta->sysmemAddrOfRadix3Elf = gsp->radix3.lvl0.addr;
meta->sizeOfBootloader = gsp->boot.fw.size;
meta->sysmemAddrOfBootloader = gsp->boot.fw.addr;
meta->bootloaderCodeOffset = gsp->boot.code_offset;
meta->bootloaderDataOffset = gsp->boot.data_offset;
meta->bootloaderManifestOffset = gsp->boot.manifest_offset;
meta->sysmemAddrOfSignature = gsp->sig.addr;
meta->sizeOfSignature = gsp->sig.size;
meta->nonWprHeapSize = gsp->fb.heap.size;
meta->gspFwHeapSize = tu102_gsp_wpr_heap_size(gsp);
meta->frtsSize = 0x100000;
meta->vgaWorkspaceSize = gsp->fb.bios.vga_workspace.size;
meta->pmuReservedSize = 0;
return 0;
}
/* The sh_flags value for the binary blobs in the ELF image */
#define FMC_SHF_FLAGS (SHF_MASKPROC | SHF_MASKOS | SHF_OS_NONCONFORMING | SHF_ALLOC)
#define ELF_HDR_SIZE ((u8)sizeof(struct elf32_hdr))
#define ELF_SHDR_SIZE ((u8)sizeof(struct elf32_shdr))
/* The FMC ELF header must be exactly this */
static const u8 elf_header[] = {
0x7f, 'E', 'L', 'F', 1, 1, 1, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 0, 0, 0, /* e_type, e_machine, e_version */
0, 0, 0, 0, 0, 0, 0, 0, /* e_entry, e_phoff */
ELF_HDR_SIZE, 0, 0, 0, 0, 0, 0, 0, /* e_shoff, e_flags */
ELF_HDR_SIZE, 0, 0, 0, /* e_ehsize, e_phentsize */
0, 0, ELF_SHDR_SIZE, 0, /* e_phnum, e_shentsize */
6, 0, 1, 0, /* e_shnum, e_shstrndx */
};
/**
* elf_validate_sections - validate each section in the FMC ELF image
* @elf: ELF image
* @length: size of the entire ELF image
*/
static bool
elf_validate_sections(const void *elf, size_t length)
{
const struct elf32_hdr *ehdr = elf;
const struct elf32_shdr *shdr = elf + ehdr->e_shoff;
/* The offset of the first section */
Elf32_Off section_begin = ehdr->e_shoff + ehdr->e_shnum * ehdr->e_shentsize;
if (section_begin > length)
return false;
/* The first section header is the null section, so skip it */
for (unsigned int i = 1; i < ehdr->e_shnum; i++) {
if (i == ehdr->e_shstrndx) {
if (shdr[i].sh_type != SHT_STRTAB)
return false;
if (shdr[i].sh_flags != SHF_STRINGS)
return false;
} else {
if (shdr[i].sh_type != SHT_PROGBITS)
return false;
if (shdr[i].sh_flags != FMC_SHF_FLAGS)
return false;
}
/* Ensure that each section is inside the image */
if (shdr[i].sh_offset < section_begin ||
(u64)shdr[i].sh_offset + shdr[i].sh_size > length)
return false;
/* Non-zero sh_info is a CRC */
if (shdr[i].sh_info) {
/* The kernel's CRC32 needs a pre- and post-xor to match standard CRCs */
u32 crc32 = crc32_le(~0, elf + shdr[i].sh_offset, shdr[i].sh_size) ^ ~0;
if (shdr[i].sh_info != crc32)
return false;
}
}
return true;
}
/**
* elf_section - return a pointer to the data for a given section
* @elf: ELF image
* @name: section name to search for
* @len: pointer to returned length of found section
*/
static const void *
elf_section(const void *elf, const char *name, unsigned int *len)
{
const struct elf32_hdr *ehdr = elf;
const struct elf32_shdr *shdr = elf + ehdr->e_shoff;
const char *names = elf + shdr[ehdr->e_shstrndx].sh_offset;
for (unsigned int i = 1; i < ehdr->e_shnum; i++) {
if (!strcmp(&names[shdr[i].sh_name], name)) {
*len = shdr[i].sh_size;
return elf + shdr[i].sh_offset;
}
}
return NULL;
}
static int
gh100_gsp_oneinit(struct nvkm_gsp *gsp)
{
struct nvkm_subdev *subdev = &gsp->subdev;
struct nvkm_device *device = subdev->device;
struct nvkm_fsp *fsp = device->fsp;
const void *fw = gsp->fws.fmc->data;
const void *hash, *sig, *pkey, *img;
unsigned int img_len = 0, hash_len = 0, pkey_len = 0, sig_len = 0;
int ret;
if (gsp->fws.fmc->size < ELF_HDR_SIZE ||
memcmp(fw, elf_header, sizeof(elf_header)) ||
!elf_validate_sections(fw, gsp->fws.fmc->size)) {
nvkm_error(subdev, "fmc firmware image is invalid\n");
return -ENODATA;
}
hash = elf_section(fw, "hash", &hash_len);
sig = elf_section(fw, "signature", &sig_len);
pkey = elf_section(fw, "publickey", &pkey_len);
img = elf_section(fw, "image", &img_len);
if (!hash || !sig || !pkey || !img) {
nvkm_error(subdev, "fmc firmware image is invalid\n");
return -ENODATA;
}
if (!nvkm_fsp_verify_gsp_fmc(fsp, hash_len, pkey_len, sig_len))
return -EINVAL;
/* Load GSP-FMC FW into memory. */
ret = nvkm_gsp_mem_ctor(gsp, img_len, &gsp->fmc.fw);
if (ret)
return ret;
memcpy(gsp->fmc.fw.data, img, img_len);
gsp->fmc.hash = kmemdup(hash, hash_len, GFP_KERNEL);
gsp->fmc.pkey = kmemdup(pkey, pkey_len, GFP_KERNEL);
gsp->fmc.sig = kmemdup(sig, sig_len, GFP_KERNEL);
if (!gsp->fmc.hash || !gsp->fmc.pkey || !gsp->fmc.sig)
return -ENOMEM;
ret = r535_gsp_oneinit(gsp);
if (ret)
return ret;
return gh100_gsp_wpr_meta_init(gsp);
}
static const struct nvkm_gsp_func
gh100_gsp = {
.flcn = &ga102_gsp_flcn,
.sig_section = ".fwsignature_gh100",
.dtor = r535_gsp_dtor,
.oneinit = gh100_gsp_oneinit,
.init = gh100_gsp_init,
.fini = gh100_gsp_fini,
.rm.gpu = &gh100_gpu,
};
static int
gh100_gsp_load(struct nvkm_gsp *gsp, int ver, const struct nvkm_gsp_fwif *fwif)
{
int ret;
ret = tu102_gsp_load_rm(gsp, fwif);
if (ret)
goto done;
ret = nvkm_gsp_load_fw(gsp, "fmc", fwif->ver, &gsp->fws.fmc);
done:
if (ret)
nvkm_gsp_dtor_fws(gsp);
return ret;
}
static struct nvkm_gsp_fwif
gh100_gsps[] = {
{ 0, gh100_gsp_load, &gh100_gsp, &r570_rm_gh100, "570.144", true },
{}
};
int
gh100_gsp_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_gsp **pgsp)
{
return nvkm_gsp_new_(gh100_gsps, device, type, inst, pgsp);
}
NVKM_GSP_FIRMWARE_FMC(gh100, 570.144);

View File

@@ -22,7 +22,9 @@ int nvkm_gsp_load_fw(struct nvkm_gsp *, const char *name, const char *ver,
void nvkm_gsp_dtor_fws(struct nvkm_gsp *);
int gv100_gsp_nofw(struct nvkm_gsp *, int, const struct nvkm_gsp_fwif *);
int tu102_gsp_load(struct nvkm_gsp *, int, const struct nvkm_gsp_fwif *);
int tu102_gsp_load_rm(struct nvkm_gsp *, const struct nvkm_gsp_fwif *);
#define NVKM_GSP_FIRMWARE_BOOTER(chip,vers) \
MODULE_FIRMWARE("nvidia/"#chip"/gsp/booter_load-"#vers".bin"); \
@@ -30,6 +32,11 @@ MODULE_FIRMWARE("nvidia/"#chip"/gsp/booter_unload-"#vers".bin"); \
MODULE_FIRMWARE("nvidia/"#chip"/gsp/bootloader-"#vers".bin"); \
MODULE_FIRMWARE("nvidia/"#chip"/gsp/gsp-"#vers".bin")
#define NVKM_GSP_FIRMWARE_FMC(chip,vers) \
MODULE_FIRMWARE("nvidia/"#chip"/gsp/fmc-"#vers".bin"); \
MODULE_FIRMWARE("nvidia/"#chip"/gsp/bootloader-"#vers".bin"); \
MODULE_FIRMWARE("nvidia/"#chip"/gsp/gsp-"#vers".bin")
struct nvkm_gsp_func {
const struct nvkm_falcon_func *flcn;
const struct nvkm_falcon_fw_func *fwsec;
@@ -60,6 +67,7 @@ int tu102_gsp_oneinit(struct nvkm_gsp *);
int tu102_gsp_init(struct nvkm_gsp *);
int tu102_gsp_fini(struct nvkm_gsp *, bool suspend);
int tu102_gsp_reset(struct nvkm_gsp *);
u64 tu102_gsp_wpr_heap_size(struct nvkm_gsp *);
extern const struct nvkm_falcon_func ga102_gsp_flcn;
extern const struct nvkm_falcon_fw_func ga102_gsp_fwsec;

View File

@@ -11,6 +11,7 @@ nvkm-y += nvkm/subdev/gsp/rm/tu1xx.o
nvkm-y += nvkm/subdev/gsp/rm/ga100.o
nvkm-y += nvkm/subdev/gsp/rm/ga1xx.o
nvkm-y += nvkm/subdev/gsp/rm/ad10x.o
nvkm-y += nvkm/subdev/gsp/rm/gh100.o
include $(src)/nvkm/subdev/gsp/rm/r535/Kbuild
include $(src)/nvkm/subdev/gsp/rm/r570/Kbuild

View File

@@ -0,0 +1,27 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*/
#include "gpu.h"
#include <nvif/class.h>
const struct nvkm_rm_gpu
gh100_gpu = {
.usermode.class = HOPPER_USERMODE_A,
.fifo.chan = {
.class = HOPPER_CHANNEL_GPFIFO_A,
},
.ce.class = HOPPER_DMA_COPY_A,
.gr.class = {
.i2m = KEPLER_INLINE_TO_MEMORY_B,
.twod = FERMI_TWOD_A,
.threed = HOPPER_A,
.compute = HOPPER_COMPUTE_A,
},
.nvdec.class = NVB8B0_VIDEO_DECODER,
.nvjpg.class = NVB8D1_VIDEO_NVJPG,
.ofa.class = NVB8FA_VIDEO_OFA,
};

View File

@@ -62,4 +62,5 @@ extern const struct nvkm_rm_gpu tu1xx_gpu;
extern const struct nvkm_rm_gpu ga100_gpu;
extern const struct nvkm_rm_gpu ga1xx_gpu;
extern const struct nvkm_rm_gpu ad10x_gpu;
extern const struct nvkm_rm_gpu gh100_gpu;
#endif

View File

@@ -2073,6 +2073,12 @@ r535_gsp_dtor(struct nvkm_gsp *gsp)
nvkm_falcon_fw_dtor(&gsp->booter.unload);
nvkm_falcon_fw_dtor(&gsp->booter.load);
nvkm_gsp_mem_dtor(&gsp->fmc.args);
kfree(gsp->fmc.sig);
kfree(gsp->fmc.pkey);
kfree(gsp->fmc.hash);
nvkm_gsp_mem_dtor(&gsp->fmc.fw);
mutex_destroy(&gsp->msgq.mutex);
mutex_destroy(&gsp->cmdq.mutex);

View File

@@ -26,8 +26,10 @@ r570_gsp_sr_data_size(struct nvkm_gsp *gsp)
static void
r570_gsp_drop_post_nocat_record(struct nvkm_gsp *gsp)
{
if (gsp->subdev.debug < NV_DBG_DEBUG)
if (gsp->subdev.debug < NV_DBG_DEBUG) {
r535_gsp_msg_ntfy_add(gsp, NV_VGPU_MSG_EVENT_GSP_POST_NOCAT_RECORD, NULL, NULL);
r535_gsp_msg_ntfy_add(gsp, NV_VGPU_MSG_EVENT_GSP_LOCKDOWN_NOTICE, NULL, NULL);
}
}
static bool
@@ -102,6 +104,13 @@ r570_gsp_get_static_info(struct nvkm_gsp *gsp)
r535_gsp_get_static_info_fb(gsp, &rpc->fbRegionInfoParams);
if (gsp->rm->wpr->offset_set_by_acr) {
GspFwWprMeta *meta = gsp->wpr_meta.data;
meta->nonWprHeapOffset = rpc->fwWprLayoutOffset.nonWprHeapOffset;
meta->frtsOffset = rpc->fwWprLayoutOffset.frtsOffset;
}
nvkm_gsp_rpc_done(gsp, rpc);
ret = r570_gr_gpc_mask(gsp, &gpc_mask);

View File

@@ -573,4 +573,62 @@ typedef struct
(88u + (BULLSEYE_ROOT_HEAP_ALLOC_RM_DATA_SECTION_SIZE_DELTA) + \
(BULLSEYE_ROOT_HEAP_ALLOC_BAREMETAL_LIBOS_HEAP_SIZE_DELTA))
typedef struct GSP_FMC_INIT_PARAMS
{
// CC initialization "registry keys"
NvU32 regkeys;
} GSP_FMC_INIT_PARAMS;
typedef enum {
GSP_DMA_TARGET_LOCAL_FB,
GSP_DMA_TARGET_COHERENT_SYSTEM,
GSP_DMA_TARGET_NONCOHERENT_SYSTEM,
GSP_DMA_TARGET_COUNT
} GSP_DMA_TARGET;
typedef struct GSP_ACR_BOOT_GSP_RM_PARAMS
{
// Physical memory aperture through which gspRmDescPa is accessed
GSP_DMA_TARGET target;
// Size in bytes of the GSP-RM descriptor structure
NvU32 gspRmDescSize;
// Physical offset in the target aperture of the GSP-RM descriptor structure
NvU64 gspRmDescOffset;
// Physical offset in FB to set the start of the WPR containing GSP-RM
NvU64 wprCarveoutOffset;
// Size in bytes of the WPR containing GSP-RM
NvU32 wprCarveoutSize;
// Whether to boot GSP-RM or GSP-Proxy through ACR
NvBool bIsGspRmBoot;
} GSP_ACR_BOOT_GSP_RM_PARAMS;
typedef struct GSP_RM_PARAMS
{
// Physical memory aperture through which bootArgsOffset is accessed
GSP_DMA_TARGET target;
// Physical offset in the memory aperture that will be passed to GSP-RM
NvU64 bootArgsOffset;
} GSP_RM_PARAMS;
typedef struct GSP_SPDM_PARAMS
{
// Physical Memory Aperture through which all addresses are accessed
GSP_DMA_TARGET target;
// Physical offset in the memory aperture where SPDM payload is stored
NvU64 payloadBufferOffset;
// Size of the above payload buffer
NvU32 payloadBufferSize;
} GSP_SPDM_PARAMS;
typedef struct GSP_FMC_BOOT_PARAMS
{
GSP_FMC_INIT_PARAMS initParams;
GSP_ACR_BOOT_GSP_RM_PARAMS bootGspRmParams;
GSP_RM_PARAMS gspRmParams;
GSP_SPDM_PARAMS gspSpdmParams;
} GSP_FMC_BOOT_PARAMS;
#define GSP_FW_HEAP_PARAM_BASE_RM_SIZE_GH100 (14 << 20) // Hopper+
#endif

View File

@@ -20,6 +20,15 @@ r570_wpr_libos3 = {
.heap_size_min = GSP_FW_HEAP_SIZE_OVERRIDE_LIBOS3_BAREMETAL_MIN_MB,
};
static const struct nvkm_rm_wpr
r570_wpr_libos3_gh100 = {
.os_carveout_size = GSP_FW_HEAP_PARAM_OS_SIZE_LIBOS3_BAREMETAL,
.base_size = GSP_FW_HEAP_PARAM_BASE_RM_SIZE_GH100,
.heap_size_min = GSP_FW_HEAP_SIZE_OVERRIDE_LIBOS3_BAREMETAL_MIN_MB,
.heap_size_non_wpr = 0x200000,
.offset_set_by_acr = true,
};
static const struct nvkm_rm_api
r570_api = {
.gsp = &r570_gsp,
@@ -50,3 +59,9 @@ r570_rm_ga102 = {
.wpr = &r570_wpr_libos3,
.api = &r570_api,
};
const struct nvkm_rm_impl
r570_rm_gh100 = {
.wpr = &r570_wpr_libos3_gh100,
.api = &r570_api,
};

View File

@@ -25,6 +25,8 @@ struct nvkm_rm_wpr {
u32 os_carveout_size;
u32 base_size;
u64 heap_size_min;
u32 heap_size_non_wpr;
bool offset_set_by_acr;
};
struct nvkm_rm_api {
@@ -173,6 +175,7 @@ extern const struct nvkm_rm_api_engine r535_ofa;
extern const struct nvkm_rm_impl r570_rm_tu102;
extern const struct nvkm_rm_impl r570_rm_ga102;
extern const struct nvkm_rm_impl r570_rm_gh100;
extern const struct nvkm_rm_api_gsp r570_gsp;
extern const struct nvkm_rm_api_client r570_client;
extern const struct nvkm_rm_api_fbsr r570_fbsr;

View File

@@ -246,7 +246,7 @@ tu102_gsp_wpr_meta_init(struct nvkm_gsp *gsp)
return 0;
}
static u64
u64
tu102_gsp_wpr_heap_size(struct nvkm_gsp *gsp)
{
u32 fb_size_gb = DIV_ROUND_UP_ULL(gsp->fb.size, 1 << 30);
@@ -379,7 +379,7 @@ tu102_gsp = {
.rm.gpu = &tu1xx_gpu,
};
static int
int
tu102_gsp_load_rm(struct nvkm_gsp *gsp, const struct nvkm_gsp_fwif *fwif)
{
struct nvkm_subdev *subdev = &gsp->subdev;

View File

@@ -4,3 +4,4 @@ nvkm-y += nvkm/subdev/instmem/nv04.o
nvkm-y += nvkm/subdev/instmem/nv40.o
nvkm-y += nvkm/subdev/instmem/nv50.o
nvkm-y += nvkm/subdev/instmem/gk20a.o
nvkm-y += nvkm/subdev/instmem/gh100.o

View File

@@ -0,0 +1,28 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*/
#include "priv.h"
#include <nvhw/ref/gh100/pri_nv_xal_ep.h>
static void
gh100_instmem_set_bar0_window_addr(struct nvkm_device *device, u64 addr)
{
nvkm_wr32(device, NV_XAL_EP_BAR0_WINDOW, addr >> NV_XAL_EP_BAR0_WINDOW_BASE_SHIFT);
}
static const struct nvkm_instmem_func
gh100_instmem = {
.fini = nv50_instmem_fini,
.memory_new = nv50_instobj_new,
.memory_wrap = nv50_instobj_wrap,
.set_bar0_window_addr = gh100_instmem_set_bar0_window_addr,
};
int
gh100_instmem_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_instmem **pimem)
{
return r535_instmem_new(&gh100_instmem, device, type, inst, pimem);
}

View File

@@ -353,7 +353,7 @@ nv50_instobj_func = {
.map = nv50_instobj_map,
};
static int
int
nv50_instobj_wrap(struct nvkm_instmem *base,
struct nvkm_memory *memory, struct nvkm_memory **pmemory)
{
@@ -373,7 +373,7 @@ nv50_instobj_wrap(struct nvkm_instmem *base,
return 0;
}
static int
int
nv50_instobj_new(struct nvkm_instmem *imem, u32 size, u32 align, bool zero,
struct nvkm_memory **pmemory)
{
@@ -400,7 +400,7 @@ nv50_instmem_set_bar0_window_addr(struct nvkm_device *device, u64 addr)
nvkm_wr32(device, 0x001700, addr >> 16);
}
static void
void
nv50_instmem_fini(struct nvkm_instmem *base)
{
nv50_instmem(base)->addr = ~0ULL;

View File

@@ -21,6 +21,11 @@ struct nvkm_instmem_func {
int nv50_instmem_new_(const struct nvkm_instmem_func *, struct nvkm_device *,
enum nvkm_subdev_type, int, struct nvkm_instmem **);
void nv50_instmem_fini(struct nvkm_instmem *);
int nv50_instobj_new(struct nvkm_instmem *, u32 size, u32 align, bool zero,
struct nvkm_memory **);
int nv50_instobj_wrap(struct nvkm_instmem *, struct nvkm_memory *vram,
struct nvkm_memory **bar2);
void nvkm_instmem_ctor(const struct nvkm_instmem_func *, struct nvkm_device *,
enum nvkm_subdev_type, int, struct nvkm_instmem *);

View File

@@ -15,6 +15,7 @@ nvkm-y += nvkm/subdev/mmu/gp100.o
nvkm-y += nvkm/subdev/mmu/gp10b.o
nvkm-y += nvkm/subdev/mmu/gv100.o
nvkm-y += nvkm/subdev/mmu/tu102.o
nvkm-y += nvkm/subdev/mmu/gh100.o
nvkm-y += nvkm/subdev/mmu/mem.o
nvkm-y += nvkm/subdev/mmu/memnv04.o
@@ -36,6 +37,7 @@ nvkm-y += nvkm/subdev/mmu/vmmgp100.o
nvkm-y += nvkm/subdev/mmu/vmmgp10b.o
nvkm-y += nvkm/subdev/mmu/vmmgv100.o
nvkm-y += nvkm/subdev/mmu/vmmtu102.o
nvkm-y += nvkm/subdev/mmu/vmmgh100.o
nvkm-y += nvkm/subdev/mmu/umem.o
nvkm-y += nvkm/subdev/mmu/ummu.o

View File

@@ -0,0 +1,25 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*/
#include "mem.h"
#include "vmm.h"
#include <nvif/class.h>
static const struct nvkm_mmu_func
gh100_mmu = {
.dma_bits = 52,
.mmu = {{ -1, -1, NVIF_CLASS_MMU_GF100}},
.mem = {{ -1, 0, NVIF_CLASS_MEM_GF100}, gf100_mem_new, gf100_mem_map },
.vmm = {{ -1, 0, NVIF_CLASS_VMM_GP100}, gh100_vmm_new },
.kind = tu102_mmu_kind,
.kind_sys = true,
};
int
gh100_mmu_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_mmu **pmmu)
{
return r535_mmu_new(&gh100_mmu, device, type, inst, pmmu);
}

View File

@@ -53,6 +53,8 @@ const u8 *gf100_mmu_kind(struct nvkm_mmu *, int *count, u8 *invalid);
const u8 *gm200_mmu_kind(struct nvkm_mmu *, int *, u8 *);
const u8 *tu102_mmu_kind(struct nvkm_mmu *, int *, u8 *);
struct nvkm_mmu_pt {
union {
struct nvkm_mmu_ptc *ptc;

View File

@@ -28,7 +28,7 @@
#include <nvif/class.h>
static const u8 *
const u8 *
tu102_mmu_kind(struct nvkm_mmu *mmu, int *count, u8 *invalid)
{
static const u8

View File

@@ -143,6 +143,8 @@ struct nvkm_vmm_func {
int (*aper)(enum nvkm_memory_target);
int (*valid)(struct nvkm_vmm *, void *argv, u32 argc,
struct nvkm_vmm_map *);
int (*valid2)(struct nvkm_vmm *, bool ro, bool priv, u8 kind, u8 comp,
struct nvkm_vmm_map *);
void (*flush)(struct nvkm_vmm *, int depth);
int (*mthd)(struct nvkm_vmm *, struct nvkm_client *,
@@ -254,6 +256,8 @@ void gp100_vmm_invalidate_pdb(struct nvkm_vmm *, u64 addr);
int gv100_vmm_join(struct nvkm_vmm *, struct nvkm_memory *);
void tu102_vmm_flush(struct nvkm_vmm *, int depth);
int nv04_vmm_new(struct nvkm_mmu *, bool, u64, u64, void *, u32,
struct lock_class_key *, const char *, struct nvkm_vmm **);
int nv41_vmm_new(struct nvkm_mmu *, bool, u64, u64, void *, u32,
@@ -296,6 +300,9 @@ int gv100_vmm_new(struct nvkm_mmu *, bool, u64, u64, void *, u32,
int tu102_vmm_new(struct nvkm_mmu *, bool, u64, u64, void *, u32,
struct lock_class_key *, const char *,
struct nvkm_vmm **);
int gh100_vmm_new(struct nvkm_mmu *, bool, u64, u64, void *, u32,
struct lock_class_key *, const char *,
struct nvkm_vmm **);
#define VMM_PRINT(l,v,p,f,a...) do { \
struct nvkm_vmm *_vmm = (v); \

View File

@@ -0,0 +1,306 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*/
#include "vmm.h"
#include <subdev/fb.h>
#include <nvhw/drf.h>
#include <nvhw/ref/gh100/dev_mmu.h>
static inline void
gh100_vmm_pgt_pte(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes,
struct nvkm_vmm_map *map, u64 addr)
{
u64 data = addr | map->type;
while (ptes--) {
VMM_WO064(pt, vmm, ptei++ * NV_MMU_VER3_PTE__SIZE, data);
data += map->next;
}
}
static void
gh100_vmm_pgt_sgl(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes,
struct nvkm_vmm_map *map)
{
VMM_MAP_ITER_SGL(vmm, pt, ptei, ptes, map, gh100_vmm_pgt_pte);
}
static void
gh100_vmm_pgt_dma(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes,
struct nvkm_vmm_map *map)
{
if (map->page->shift == PAGE_SHIFT) {
VMM_SPAM(vmm, "DMAA %08x %08x PTE(s)", ptei, ptes);
nvkm_kmap(pt->memory);
while (ptes--) {
const u64 data = *map->dma++ | map->type;
VMM_WO064(pt, vmm, ptei++ * NV_MMU_VER3_PTE__SIZE, data);
}
nvkm_done(pt->memory);
return;
}
VMM_MAP_ITER_DMA(vmm, pt, ptei, ptes, map, gh100_vmm_pgt_pte);
}
static void
gh100_vmm_pgt_mem(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes,
struct nvkm_vmm_map *map)
{
VMM_MAP_ITER_MEM(vmm, pt, ptei, ptes, map, gh100_vmm_pgt_pte);
}
static void
gh100_vmm_pgt_sparse(struct nvkm_vmm *vmm,
struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes)
{
const u64 data = NVDEF(NV_MMU, VER3_PTE, PCF, SPARSE);
VMM_FO064(pt, vmm, ptei * NV_MMU_VER3_PTE__SIZE, data, ptes);
}
static const struct nvkm_vmm_desc_func
gh100_vmm_desc_spt = {
.unmap = gf100_vmm_pgt_unmap,
.sparse = gh100_vmm_pgt_sparse,
.mem = gh100_vmm_pgt_mem,
.dma = gh100_vmm_pgt_dma,
.sgl = gh100_vmm_pgt_sgl,
};
static void
gh100_vmm_lpt_invalid(struct nvkm_vmm *vmm,
struct nvkm_mmu_pt *pt, u32 ptei, u32 ptes)
{
const u64 data = NVDEF(NV_MMU, VER3_PTE, PCF, NO_VALID_4KB_PAGE);
VMM_FO064(pt, vmm, ptei * NV_MMU_VER3_PTE__SIZE, data, ptes);
}
static const struct nvkm_vmm_desc_func
gh100_vmm_desc_lpt = {
.invalid = gh100_vmm_lpt_invalid,
.unmap = gf100_vmm_pgt_unmap,
.sparse = gh100_vmm_pgt_sparse,
.mem = gh100_vmm_pgt_mem,
};
static inline void
gh100_vmm_pd0_pte(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt,
u32 ptei, u32 ptes, struct nvkm_vmm_map *map, u64 addr)
{
u64 data = addr | map->type;
while (ptes--) {
VMM_WO128(pt, vmm, ptei++ * NV_MMU_VER3_DUAL_PDE__SIZE, data, 0ULL);
data += map->next;
}
}
static void
gh100_vmm_pd0_mem(struct nvkm_vmm *vmm, struct nvkm_mmu_pt *pt,
u32 ptei, u32 ptes, struct nvkm_vmm_map *map)
{
VMM_MAP_ITER_MEM(vmm, pt, ptei, ptes, map, gh100_vmm_pd0_pte);
}
static inline bool
gh100_vmm_pde(struct nvkm_mmu_pt *pt, u64 *data)
{
switch (nvkm_memory_target(pt->memory)) {
case NVKM_MEM_TARGET_VRAM:
*data |= NVDEF(NV_MMU, VER3_PDE, APERTURE, VIDEO_MEMORY);
*data |= NVDEF(NV_MMU, VER3_PDE, PCF, VALID_CACHED_ATS_NOT_ALLOWED);
break;
case NVKM_MEM_TARGET_HOST:
*data |= NVDEF(NV_MMU, VER3_PDE, APERTURE, SYSTEM_COHERENT_MEMORY);
*data |= NVDEF(NV_MMU, VER3_PDE, PCF, VALID_UNCACHED_ATS_ALLOWED);
break;
case NVKM_MEM_TARGET_NCOH:
*data |= NVDEF(NV_MMU, VER3_PDE, APERTURE, SYSTEM_NON_COHERENT_MEMORY);
*data |= NVDEF(NV_MMU, VER3_PDE, PCF, VALID_CACHED_ATS_ALLOWED);
break;
default:
WARN_ON(1);
return false;
}
*data |= pt->addr;
return true;
}
static void
gh100_vmm_pd0_pde(struct nvkm_vmm *vmm, struct nvkm_vmm_pt *pgd, u32 pdei)
{
struct nvkm_vmm_pt *pgt = pgd->pde[pdei];
struct nvkm_mmu_pt *pd = pgd->pt[0];
u64 data[2] = {};
if (pgt->pt[0] && !gh100_vmm_pde(pgt->pt[0], &data[0]))
return;
if (pgt->pt[1] && !gh100_vmm_pde(pgt->pt[1], &data[1]))
return;
nvkm_kmap(pd->memory);
VMM_WO128(pd, vmm, pdei * NV_MMU_VER3_DUAL_PDE__SIZE, data[0], data[1]);
nvkm_done(pd->memory);
}
static void
gh100_vmm_pd0_sparse(struct nvkm_vmm *vmm,
struct nvkm_mmu_pt *pt, u32 pdei, u32 pdes)
{
const u64 data = NVDEF(NV_MMU, VER3_DUAL_PDE, PCF_BIG, SPARSE_ATS_ALLOWED);
VMM_FO128(pt, vmm, pdei * NV_MMU_VER3_DUAL_PDE__SIZE, data, 0ULL, pdes);
}
static void
gh100_vmm_pd0_unmap(struct nvkm_vmm *vmm,
struct nvkm_mmu_pt *pt, u32 pdei, u32 pdes)
{
VMM_FO128(pt, vmm, pdei * NV_MMU_VER3_DUAL_PDE__SIZE, 0ULL, 0ULL, pdes);
}
static const struct nvkm_vmm_desc_func
gh100_vmm_desc_pd0 = {
.unmap = gh100_vmm_pd0_unmap,
.sparse = gh100_vmm_pd0_sparse,
.pde = gh100_vmm_pd0_pde,
.mem = gh100_vmm_pd0_mem,
};
static void
gh100_vmm_pd1_pde(struct nvkm_vmm *vmm, struct nvkm_vmm_pt *pgd, u32 pdei)
{
struct nvkm_vmm_pt *pgt = pgd->pde[pdei];
struct nvkm_mmu_pt *pd = pgd->pt[0];
u64 data = 0;
if (!gh100_vmm_pde(pgt->pt[0], &data))
return;
nvkm_kmap(pd->memory);
VMM_WO064(pd, vmm, pdei * NV_MMU_VER3_PDE__SIZE, data);
nvkm_done(pd->memory);
}
static const struct nvkm_vmm_desc_func
gh100_vmm_desc_pd1 = {
.unmap = gf100_vmm_pgt_unmap,
.sparse = gh100_vmm_pgt_sparse,
.pde = gh100_vmm_pd1_pde,
};
static const struct nvkm_vmm_desc
gh100_vmm_desc_16[] = {
{ LPT, 5, 8, 0x0100, &gh100_vmm_desc_lpt },
{ PGD, 8, 16, 0x1000, &gh100_vmm_desc_pd0 },
{ PGD, 9, 8, 0x1000, &gh100_vmm_desc_pd1 },
{ PGD, 9, 8, 0x1000, &gh100_vmm_desc_pd1 },
{ PGD, 9, 8, 0x1000, &gh100_vmm_desc_pd1 },
{ PGD, 1, 8, 0x1000, &gh100_vmm_desc_pd1 },
{}
};
static const struct nvkm_vmm_desc
gh100_vmm_desc_12[] = {
{ SPT, 9, 8, 0x1000, &gh100_vmm_desc_spt },
{ PGD, 8, 16, 0x1000, &gh100_vmm_desc_pd0 },
{ PGD, 9, 8, 0x1000, &gh100_vmm_desc_pd1 },
{ PGD, 9, 8, 0x1000, &gh100_vmm_desc_pd1 },
{ PGD, 9, 8, 0x1000, &gh100_vmm_desc_pd1 },
{ PGD, 1, 8, 0x1000, &gh100_vmm_desc_pd1 },
{}
};
static int
gh100_vmm_valid(struct nvkm_vmm *vmm, bool ro, bool priv, u8 kind, u8 comp,
struct nvkm_vmm_map *map)
{
const enum nvkm_memory_target target = nvkm_memory_target(map->memory);
const bool vol = target == NVKM_MEM_TARGET_HOST;
const struct nvkm_vmm_page *page = map->page;
u8 kind_inv, pcf;
int kindn, aper;
const u8 *kindm;
map->next = 1ULL << page->shift;
map->type = 0;
aper = vmm->func->aper(target);
if (WARN_ON(aper < 0))
return aper;
kindm = vmm->mmu->func->kind(vmm->mmu, &kindn, &kind_inv);
if (kind >= kindn || kindm[kind] == kind_inv) {
VMM_DEBUG(vmm, "kind %02x", kind);
return -EINVAL;
}
if (priv) {
if (ro) {
if (vol)
pcf = NV_MMU_VER3_PTE_PCF_PRIVILEGE_RO_ATOMIC_UNCACHED_ACD;
else
pcf = NV_MMU_VER3_PTE_PCF_PRIVILEGE_RO_ATOMIC_CACHED_ACD;
} else {
if (vol)
pcf = NV_MMU_VER3_PTE_PCF_PRIVILEGE_RW_ATOMIC_UNCACHED_ACD;
else
pcf = NV_MMU_VER3_PTE_PCF_PRIVILEGE_RW_ATOMIC_CACHED_ACD;
}
} else {
if (ro) {
if (vol)
pcf = NV_MMU_VER3_PTE_PCF_REGULAR_RO_ATOMIC_UNCACHED_ACD;
else
pcf = NV_MMU_VER3_PTE_PCF_REGULAR_RO_ATOMIC_CACHED_ACD;
} else {
if (vol)
pcf = NV_MMU_VER3_PTE_PCF_REGULAR_RW_ATOMIC_UNCACHED_ACD;
else
pcf = NV_MMU_VER3_PTE_PCF_REGULAR_RW_ATOMIC_CACHED_ACD;
}
}
map->type |= NVDEF(NV_MMU, VER3_PTE, VALID, TRUE);
map->type |= NVVAL(NV_MMU, VER3_PTE, APERTURE, aper);
map->type |= NVVAL(NV_MMU, VER3_PTE, PCF, pcf);
map->type |= NVVAL(NV_MMU, VER3_PTE, KIND, kind);
return 0;
}
static const struct nvkm_vmm_func
gh100_vmm = {
.join = gv100_vmm_join,
.part = gf100_vmm_part,
.aper = gf100_vmm_aper,
.valid = gp100_vmm_valid,
.valid2 = gh100_vmm_valid,
.flush = tu102_vmm_flush,
.page = {
{ 56, &gh100_vmm_desc_16[5], NVKM_VMM_PAGE_Sxxx },
{ 47, &gh100_vmm_desc_16[4], NVKM_VMM_PAGE_Sxxx },
{ 38, &gh100_vmm_desc_16[3], NVKM_VMM_PAGE_Sxxx },
{ 29, &gh100_vmm_desc_16[2], NVKM_VMM_PAGE_SVxC },
{ 21, &gh100_vmm_desc_16[1], NVKM_VMM_PAGE_SVxC },
{ 16, &gh100_vmm_desc_16[0], NVKM_VMM_PAGE_SVxC },
{ 12, &gh100_vmm_desc_12[0], NVKM_VMM_PAGE_SVHx },
{}
}
};
int
gh100_vmm_new(struct nvkm_mmu *mmu, bool managed, u64 addr, u64 size,
void *argv, u32 argc, struct lock_class_key *key,
const char *name, struct nvkm_vmm **pvmm)
{
return gp100_vmm_new_(&gh100_vmm, mmu, managed, addr, size,
argv, argc, key, name, pvmm);
}

View File

@@ -436,6 +436,9 @@ gp100_vmm_valid(struct nvkm_vmm *vmm, void *argv, u32 argc,
return ret;
}
if (vmm->func->valid2)
return vmm->func->valid2(vmm, ro, priv, kind, 0, map);
aper = vmm->func->aper(target);
if (WARN_ON(aper < 0))
return aper;

View File

@@ -23,7 +23,7 @@
#include <subdev/timer.h>
static void
void
tu102_vmm_flush(struct nvkm_vmm *vmm, int depth)
{
struct nvkm_device *device = vmm->mmu->subdev.device;

View File

@@ -13,3 +13,4 @@ nvkm-y += nvkm/subdev/pci/gf100.o
nvkm-y += nvkm/subdev/pci/gf106.o
nvkm-y += nvkm/subdev/pci/gk104.o
nvkm-y += nvkm/subdev/pci/gp100.o
nvkm-y += nvkm/subdev/pci/gh100.o

View File

@@ -0,0 +1,30 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (c) 2025, NVIDIA CORPORATION. All rights reserved.
*/
#include "priv.h"
#include <nvhw/drf.h>
#include <nvhw/ref/gh100/dev_xtl_ep_pri.h>
static void
gh100_pci_msi_rearm(struct nvkm_pci *pci)
{
/* Handled by top-level intr ACK. */
}
static const struct nvkm_pci_func
gh100_pci = {
.cfg = {
.addr = DRF_LO(NV_EP_PCFGM),
.size = DRF_HI(NV_EP_PCFGM) - DRF_LO(NV_EP_PCFGM) + 1,
},
.msi_rearm = gh100_pci_msi_rearm,
};
int
gh100_pci_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
struct nvkm_pci **ppci)
{
return nvkm_pci_new_(&gh100_pci, device, type, inst, ppci);
}