diff --git a/README.md b/README.md index 0bbfc24..40bcef8 100644 --- a/README.md +++ b/README.md @@ -69,10 +69,22 @@ sudo ./install.sh --mclk-ndiv=70 # → 1890 MHz Values below stock downclock the card, which is the way to stabilise a card that fails at stock. -Without the flag, patches `0009` and `0010` are not applied at all. The multiplier is compiled into the modules, so changing it means re-running `install.sh`. In a mixed 8GB+10GB system the same multiplier lands on every card. +Without the flag, patches `0008` and `0009` are not applied at all. The multiplier is compiled into the modules, so changing it means re-running `install.sh`. In a mixed 8GB+10GB system the same multiplier lands on every card. If a value turns out to be unstable - reinstall without `--mclk-ndiv` (or run `./remove.sh`) from a working state. +### IOMMU + +NVIDIA recommends `iommu=pt` (passthrough) for all GPUs. In this mode, DMA between the GPU and system memory bypasses IOMMU translation, avoiding extra latency and potential mapping errors. + +The installer does **not** touch the kernel command line by default. To have it add `iommu=pt` automatically: + +```bash +sudo ./install.sh --iommu +``` + +Or add `iommu=pt` to your kernel cmdline manually (via GRUB, systemd-boot, etc.). IOMMU must also be enabled in BIOS (VT-d on Intel, AMD-Vi / SVM on AMD). + ## What Gets Unlocked | Feature | Status | diff --git a/common/constants.yaml b/common/constants.yaml deleted file mode 100644 index 859c60a..0000000 --- a/common/constants.yaml +++ /dev/null @@ -1,88 +0,0 @@ -driver_versions: - - "610.43.03" - - "610.43.02" - -gpu: - vendor_id: "10de" - device_ids: - - "20c2" - - "2082" - -compute: - ss0: "0x88888888" - ss1: "0x00000008" - -pcie: - target_gen: 2 - link_speed_gen2: "0x2" - xve_link_control_status: "0x00088088" - xve_link_control_2: "0x000880a8" - pl_link_rate_addr: "0x0008c1c0" - pl_link_rate_value: "0x00240036" - vsec_hierarchy_addr: "0x00088610" - vsec_device_addr: "0x0008860c" - xp_fuse_override_base: "0x0008e110" - xp_fuse_override_val_base: "0x0008e120" - opt_gen23_addr: "0x0082057c" - opt_magic_a100: "0x00200000" - -mclk_overclock: - supported_device_ids: - - "20c2" - - "2082" - ndiv_min: 30 - ndiv_max: 80 - mhz_per_ndiv: 27 - stock_ndiv: - "10gb": 45 # 1215 MHz - "8gb_250w": 54 # 1458 MHz - "8gb_300w": 64 # 1728 MHz, VBIOS 92.00.6D.00.0A - # PLM addresses opened by patch 0001 (SEC2 Booter) to allow PLL access - plm: - fbpa_pll0: "0x009a3c7c" # value 0xffffffff - fbpa_pll1: "0x009a3c80" # value 0xffffffff - fbpa_pll2: "0x009a3c84" # value 0xffffffff - # Pre-GSP path (patch 0009, kernel_gsp_tu102.c) - pre_gsp: - fbpa0_pll_plm: "0x00903c7c" # PLM readback, bit4 = PLL access open - fbpa0_pll_coeff: "0x00903c98" # read stock NDIV from bits [15:8] - fbio_memclk_change_alert: "0x009a0590" # bit31 = MEMCLK_CHANGE_ALERT - hbm_self_refresh: "0x009a031c" # write 1 = enter, 0 = exit - fbpa_base: "0x00900000" - fbpa_stride: "0x00004000" - fbpa_count: 12 - fbpa_pll_cfg_offset: "0x3c90" # base + idx*stride + offset - fbpa_pll_coeff_offset: "0x3c98" # base + idx*stride + offset, NDIV bits [15:8] - ddll_control: "0x009a11dc" # bit6 = trigger DDLL calibration - ddll_cal_status0: "0x009a0674" - ddll_cal_status1: "0x009a0678" - # Post-GSP path (patch 0010, kernel_gsp.c) - post_gsp: - fbpa_multicast_pll_coeff: "0x0098bc98" # multicast COEFF write (all FBPAs at once) - pri_fence: "0x001211fc" # PRI write fence, write 0x0 to flush - fbpa0_pll_cfg: "0x00903c90" # poll bit5 for PLL lock - # COEFF register layout (shared by pre-GSP and post-GSP paths) - coeff_layout: - ndiv_shift: 8 - ndiv_mask: "0x0000ff00" - preserve_mask: "0xffff00ff" # MDIV/PDIV bits kept in read-modify-write - fallback_300w: "0x00010001" # MDIV=1, PDIV=1 (used when PRI read returns 0 or BAD) - pll_cfg_bits: - enable: "0x09" # bits 0,3 - lock: "0x20" # bit 5 - ddll_reset: "0x1000" # bit 12 - comment: "HBM2 memory clock via the FBPA PLL NDIV. The patches ship an XX placeholder that build.sh substitutes from --mclk-ndiv." - -profiles: - "8gb": - stock_mib: 8192 - unlocked_mib: 65536 - cfg1: "0x02779000" - lmr: "0x0000020B" - fb_bytes: "0x0000001000000000" - "10gb": - stock_mib: 10240 - unlocked_mib: 40960 - cfg1: "0x02669000" - lmr: "0x0000028A" - fb_bytes: "0x0000000A00000000" diff --git a/driver/build.sh b/driver/build.sh index dbcdfa6..49ad2ee 100755 --- a/driver/build.sh +++ b/driver/build.sh @@ -77,7 +77,7 @@ if [[ -n "${MCLK_NDIV}" ]]; then fi for p in "${patches[@]}"; do base="$(basename "${p}")" - if [[ ("${base}" == "0009-mclk-overclock.patch" || "${base}" == "0010-mclk-overclock-post-gsp.patch") && -z "${MCLK_NDIV}" ]]; then + if [[ ("${base}" == "0008-mclk-overclock.patch" || "${base}" == "0009-mclk-overclock-post-gsp.patch") && -z "${MCLK_NDIV}" ]]; then warn "Skipping ${base} (no --mclk-ndiv)" continue fi diff --git a/driver/patches/0001-sec2-postbl-plm-ss-cfg.patch b/driver/patches/0001-sec2-postbl-plm-ss-cfg.patch index bba89b7..1a25b1e 100644 --- a/driver/patches/0001-sec2-postbl-plm-ss-cfg.patch +++ b/driver/patches/0001-sec2-postbl-plm-ss-cfg.patch @@ -1,7 +1,6 @@ -diff -Naur a/src/nvidia/generated/g_kernel_gsp_nvoc.h b/src/nvidia/generated/g_kernel_gsp_nvoc.h ---- a/src/nvidia/generated/g_kernel_gsp_nvoc.h 2026-07-18 11:26:26.833302560 -0700 -+++ b/src/nvidia/generated/g_kernel_gsp_nvoc.h 2026-07-18 11:26:26.834341525 -0700 -@@ -544,6 +544,8 @@ +--- a/src/nvidia/generated/g_kernel_gsp_nvoc.h 2026-07-07 18:23:15.000000000 +0200 ++++ b/src/nvidia/generated/g_kernel_gsp_nvoc.h 2026-07-31 00:43:24.962804310 +0200 +@@ -544,6 +544,8 @@ struct KernelGsp { RM_RISCV_UCODE_DESC *pGspRmBootUcodeDesc; MEMORY_DESCRIPTOR *pGspUCodeRadix3Descriptor; MEMORY_DESCRIPTOR *pSignatureMemdesc; @@ -10,9 +9,8 @@ diff -Naur a/src/nvidia/generated/g_kernel_gsp_nvoc.h b/src/nvidia/generated/g_k GspSystemInfo *pSystemInfo; NvU32 regTableSize; PACKED_REGISTRY_TABLE *pRegTable; -diff -Naur a/src/nvidia/src/kernel/gpu/gsp/kernel_gsp.c b/src/nvidia/src/kernel/gpu/gsp/kernel_gsp.c ---- a/src/nvidia/src/kernel/gpu/gsp/kernel_gsp.c 2026-07-18 11:26:26.827164897 -0700 -+++ b/src/nvidia/src/kernel/gpu/gsp/kernel_gsp.c 2026-07-18 11:26:26.828254361 -0700 +--- a/src/nvidia/src/kernel/gpu/gsp/kernel_gsp.c 2026-07-07 18:23:15.000000000 +0200 ++++ b/src/nvidia/src/kernel/gpu/gsp/kernel_gsp.c 2026-07-31 00:43:51.261744520 +0200 @@ -102,6 +102,23 @@ #include "crashcat/crashcat_report.h" @@ -37,7 +35,7 @@ diff -Naur a/src/nvidia/src/kernel/gpu/gsp/kernel_gsp.c b/src/nvidia/src/kernel/ struct MIG_CI_UPDATE_CALLBACK_PARAMS { -@@ -4805,14 +4824,23 @@ +@@ -4805,14 +4822,23 @@ _kgspBootGspRm(OBJGPU *pGpu, KernelGsp * if (kgspIsWpr2Up_HAL(pGpu, pKernelGsp) && (!pGpu->getProperty(pGpu, PDB_PROP_GPU_PREINITIALIZED_WPR_REGION))) { @@ -64,7 +62,7 @@ diff -Naur a/src/nvidia/src/kernel/gpu/gsp/kernel_gsp.c b/src/nvidia/src/kernel/ { // If the new FB layout requires a scrubber ucode to scrub additional space, prepare it now NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, _kgspPrepareScrubberImageIfNeeded(pGpu, pKernelGsp)); -@@ -4821,6 +4849,125 @@ +@@ -4821,6 +4847,130 @@ _kgspBootGspRm(OBJGPU *pGpu, KernelGsp * // Setup arguments for bootstrapping GSP NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, kgspPrepareForBootstrap_HAL(pGpu, pKernelGsp, KGSP_BOOT_MODE_NORMAL)); @@ -87,6 +85,11 @@ diff -Naur a/src/nvidia/src/kernel/gpu/gsp/kernel_gsp.c b/src/nvidia/src/kernel/ + { 0x009a3c7cU, 0xffffffffU, "FBPA_PLL0" }, + { 0x009a3c80U, 0xffffffffU, "FBPA_PLL1" }, + { 0x009a3c84U, 0xffffffffU, "FBPA_PLL2" }, ++ { 0x00088fe8U, 0xffffffffU, "XVE_PLM" }, ++ { 0x00088fecU, 0xffffffffU, "XVE_CYA_PLM" }, ++ { 0x0008872cU, 0x0000000aU, "XVE_FUSE_OVR" }, ++ { 0x0008841cU, 0x4034ad00U, "XVE_CYA_SPD" }, ++ { 0x000880a8U, 0x00000002U, "XVE_TARGET" }, + }; + + NvU32 wpr2Lo = GPU_REG_RD32(pGpu, 0x001fa824U); @@ -190,7 +193,7 @@ diff -Naur a/src/nvidia/src/kernel/gpu/gsp/kernel_gsp.c b/src/nvidia/src/kernel/ // Release the API lock if relaxed locking for parallel init is enabled NvBool bRelaxedLocking = _kgspShouldRelaxGspInitLocking(pGpu); if (bRelaxedLocking) -@@ -5164,6 +5292,53 @@ +@@ -5164,6 +5314,53 @@ kgspInitRm_IMPL goto done; } @@ -244,7 +247,7 @@ diff -Naur a/src/nvidia/src/kernel/gpu/gsp/kernel_gsp.c b/src/nvidia/src/kernel/ NV_ASSERT_OK_OR_GOTO(status, kgspInitGspTraceCrashBuffer(pGpu, pKernelGsp), done); // Set PDB properties as per data from GSP. -@@ -5662,6 +5834,84 @@ +@@ -5662,6 +5859,84 @@ _kgspFreeBootBinaryImage pKernelGsp->gspRmBootUcodeSize = 0; } @@ -329,7 +332,7 @@ diff -Naur a/src/nvidia/src/kernel/gpu/gsp/kernel_gsp.c b/src/nvidia/src/kernel/ static NV_STATUS _kgspCreateSignatureMemdesc ( -@@ -5672,6 +5922,9 @@ +@@ -5672,6 +5947,9 @@ _kgspCreateSignatureMemdesc { NV_STATUS status = NV_OK; NvU8 *pSignatureVa = NULL; @@ -339,7 +342,7 @@ diff -Naur a/src/nvidia/src/kernel/gpu/gsp/kernel_gsp.c b/src/nvidia/src/kernel/ NvU64 flags = MEMDESC_FLAGS_NONE; if (confComputeForceUnprotAlloc(pGpu)) -@@ -5682,7 +5935,7 @@ +@@ -5682,7 +5960,7 @@ _kgspCreateSignatureMemdesc // NOTE: align to 256 because that's the alignment needed for Booter DMA NV_CHECK_OK_OR_RETURN(LEVEL_ERROR, memdescCreate(&pKernelGsp->pSignatureMemdesc, pGpu, @@ -348,7 +351,7 @@ diff -Naur a/src/nvidia/src/kernel/gpu/gsp/kernel_gsp.c b/src/nvidia/src/kernel/ NV_TRUE, ADDR_SYSMEM, NV_MEMORY_CACHED, flags)); memdescTagAlloc(status, -@@ -5694,8 +5947,48 @@ +@@ -5694,8 +5972,48 @@ _kgspCreateSignatureMemdesc (pSignatureVa != NULL) ? NV_OK : NV_ERR_INSUFFICIENT_RESOURCES, fail_alloc); @@ -399,7 +402,7 @@ diff -Naur a/src/nvidia/src/kernel/gpu/gsp/kernel_gsp.c b/src/nvidia/src/kernel/ memdescUnmapInternal(pGpu, pKernelGsp->pSignatureMemdesc, 0); pSignatureVa = NULL; -@@ -5709,6 +6002,69 @@ +@@ -5709,6 +6027,69 @@ fail_create: memdescDestroy(pKernelGsp->pSignatureMemdesc); pKernelGsp->pSignatureMemdesc = NULL; diff --git a/driver/patches/0007-pcie-gen2.patch b/driver/patches/0007-pcie-gen2.patch index db73e34..6e5ba03 100644 --- a/driver/patches/0007-pcie-gen2.patch +++ b/driver/patches/0007-pcie-gen2.patch @@ -1,310 +1,73 @@ ---- a/src/nvidia/src/kernel/gpu/gsp/kernel_gsp.c -+++ b/src/nvidia/src/kernel/gpu/gsp/kernel_gsp.c -@@ -4942,6 +4942,260 @@ +--- a/src/nvidia/src/kernel/gpu/gsp/kernel_gsp.c 2026-07-31 00:43:51.261744520 +0200 ++++ b/src/nvidia/src/kernel/gpu/gsp/kernel_gsp.c 2026-07-31 00:44:47.811484740 +0200 +@@ -4951,6 +4951,70 @@ devId); } -+ ++ // PCIe Gen2: directed speed change via XP LTSSM ++ // PLM gates (XVE_PLM, XVE_CYA_PLM, XVE_FUSE_OVR, XVE_CYA_SPD, XVE_TARGET) ++ // are already opened by the main plmTable above. + { -+ #define PCIE_GEN2_LINK_CAP_ADDR 0x00088084U -+ #define PCIE_GEN2_LINK_CAP2_ADDR 0x000880a4U -+ #define PCIE_GEN2_LINK_CTRL_2_ADDR 0x000880a8U -+ #define PCIE_GEN2_LINK_CTRL_STATUS_ADDR 0x00088088U -+ #define PCIE_GEN2_PL_LINK_RATE_ADDR 0x0008c1c0U -+ #define PCIE_GEN2_LTSSM_ADDR 0x0008872cU -+ #define PCIE_GEN2_VSEC_DEVICE_ADDR 0x0008860cU -+ #define PCIE_GEN2_VSEC_HIERARCHY_ADDR 0x00088610U -+ #define PCIE_GEN2_XP3G_OVR_BASE 0x0008e110U -+ #define PCIE_GEN2_XP3G_VAL_BASE 0x0008e120U -+ #define PCIE_GEN2_XP3G_STATUS_BASE 0x0008e100U -+ #define PCIE_GEN2_OPT_GEN23_ADDR 0x0082057cU -+ #define PCIE_GEN2_OPT_GEN3_ADDR 0x00820580U -+ #define PCIE_GEN2_OPT_MAGIC_ADDR 0x00820520U -+ #define PCIE_LINK_SPEED_OF(stat) (((stat) >> 16) & 0xFU) -+ const NvU32 PCIE_GEN2_LINK_SPEED = 0x00000002U; -+ const NvU32 PCIE_GEN2_PL_LINK_RATE_VALUE = 0x00240036U; ++ NvU32 xpCfg0 = GPU_REG_RD32(pGpu, 0x0008C040U); ++ NvU32 xpLctrl2 = GPU_REG_RD32(pGpu, 0x0008C1C0U); ++ NvU32 xpCya0 = GPU_REG_RD32(pGpu, 0x0008C2C0U); + -+ NvU32 capBefore = GPU_REG_RD32(pGpu, PCIE_GEN2_LINK_CAP_ADDR); -+ NvU32 statBefore = GPU_REG_RD32(pGpu, PCIE_GEN2_LINK_CTRL_STATUS_ADDR); -+ NvU32 vsecDev = GPU_REG_RD32(pGpu, PCIE_GEN2_VSEC_DEVICE_ADDR); -+ NvU32 vsecHier = GPU_REG_RD32(pGpu, PCIE_GEN2_VSEC_HIERARCHY_ADDR); + NV_PRINTF(LEVEL_ERROR, -+ "SEC2_DEBUG: PCIe pre CAP=0x%08x CAP2=0x%08x LC2=0x%08x PL=0x%08x " -+ "STAT=0x%08x VSEC dev=0x%08x hier=0x%08x OPT=%08x/%08x/%08x " -+ "XP3G st0=0x%08x ovr0=0x%08x val0=0x%08x " -+ "st3=0x%08x ovr3=0x%08x val3=0x%08x speed=%u\n", -+ capBefore, -+ GPU_REG_RD32(pGpu, PCIE_GEN2_LINK_CAP2_ADDR), -+ GPU_REG_RD32(pGpu, PCIE_GEN2_LINK_CTRL_2_ADDR), -+ GPU_REG_RD32(pGpu, PCIE_GEN2_PL_LINK_RATE_ADDR), -+ statBefore, -+ vsecDev, -+ vsecHier, -+ GPU_REG_RD32(pGpu, PCIE_GEN2_OPT_GEN23_ADDR), -+ GPU_REG_RD32(pGpu, PCIE_GEN2_OPT_GEN3_ADDR), -+ GPU_REG_RD32(pGpu, PCIE_GEN2_OPT_MAGIC_ADDR), -+ GPU_REG_RD32(pGpu, PCIE_GEN2_XP3G_STATUS_BASE), -+ GPU_REG_RD32(pGpu, PCIE_GEN2_XP3G_OVR_BASE), -+ GPU_REG_RD32(pGpu, PCIE_GEN2_XP3G_VAL_BASE), -+ GPU_REG_RD32(pGpu, PCIE_GEN2_XP3G_STATUS_BASE + 0xCU), -+ GPU_REG_RD32(pGpu, PCIE_GEN2_XP3G_OVR_BASE + 0xCU), -+ GPU_REG_RD32(pGpu, PCIE_GEN2_XP3G_VAL_BASE + 0xCU), -+ PCIE_LINK_SPEED_OF(statBefore)); -+ -+ { -+ static const struct { NvU32 addr; NvU32 value; const char *name; } xp3gTable[] = { -+ { 0x0008e1b0U, 0xffffffffU, "XP3G_PLM" }, -+ { 0x0008e1b4U, 0xffffffffU, "XP3G_PLM4" }, -+ { 0x0008e1b8U, 0xffffffffU, "XP3G_PLM8" }, -+ { 0x0008e1bcU, 0xffffffffU, "XP3G_PLMC" }, -+ { 0x00088fe8U, 0xffffffffU, "XVE_D0" }, -+ { 0x00088fecU, 0xffffffffU, "XVE_D4" }, -+ { 0x00088ff0U, 0xffffffffU, "XVE_D8" }, -+ { 0x008200d0U, 0xffffffffU, "OPTB_D0" }, -+ { 0x008200d4U, 0xffffffffU, "OPTB_D4" }, -+ { 0x008200d8U, 0xffffffffU, "OPTB_D8" }, -+ { 0x008200dcU, 0xffffffffU, "OPTB_DC" }, -+ { 0x008200e0U, 0xffffffffU, "OPTB_E0" }, -+ { 0x008200e4U, 0xffffffffU, "OPTB_E4" }, -+ { 0x008200e8U, 0xffffffffU, "OPTB_E8" }, -+ { 0x008200ecU, 0xffffffffU, "OPTB_EC" }, -+ { 0x008200f0U, 0xffffffffU, "OPTB_F0" }, -+ { 0x008200f4U, 0xffffffffU, "OPTB_F4" }, -+ { 0x00823800U, 0xffffffffU, "FEAT_OVR_ECC_PLM" }, -+ { 0x0082057cU, 0x00000000U, "OPT_GEN23" }, -+ { 0x0008e120U, 0x00000000U, "XP3G_VAL0" }, -+ { 0x0008e110U, 0x00000001U, "XP3G_OVR0" }, -+ { 0x0008e12cU, 0x00200000U, "XP3G_VAL3" }, -+ { 0x0008e11cU, 0x00000004U, "XP3G_OVR3" }, -+ }; -+ NvU32 xi, xattempt; -+ NV_STATUS xpStatus; -+ const NvU32 xp3gCount = sizeof(xp3gTable) / sizeof(xp3gTable[0]); -+ #define PCIE_GEN2_PRIV_MISC_1_ADDR 0x0008841cU -+ #define PCIE_GEN2_PRIV_MISC_1_GEN2_EN ((1U << 11) | (1U << 13)) -+ #define PCIE_GEN2_PRIV_MISC_1_GEN2_VAL ((1U << 12) | (1U << 14)) -+ -+ for (xi = 0; xi < xp3gCount; xi++) -+ { -+ NvBool wrote = NV_FALSE; -+ for (xattempt = 0; xattempt < 2 && !wrote; xattempt++) -+ { -+ GPU_REG_WR32(pGpu, 0x001fa824U, wpr2Lo); -+ GPU_REG_WR32(pGpu, 0x001fa828U, wpr2Hi); ++ "SEC2_DEBUG: PCIe pre: CFG0=0x%08x LCTRL2=0x%08x CYA0=0x%08x\n", ++ xpCfg0, xpLctrl2, xpCya0); + -+ xpStatus = kgspSec2PostblTimingRefillPayload(pGpu, pKernelGsp, -+ xp3gTable[xi].addr, xp3gTable[xi].value); -+ if (xpStatus != NV_OK) -+ continue; -+ -+ xpStatus = kgspExecuteBooterLoad_HAL(pGpu, pKernelGsp, -+ memdescGetPhysAddr(pKernelGsp->pWprMetaDescriptor, AT_GPU, 0)); -+ -+ NvU32 tgtRd = GPU_REG_RD32(pGpu, xp3gTable[xi].addr); -+ NvU32 ovr0Rd = GPU_REG_RD32(pGpu, PCIE_GEN2_XP3G_OVR_BASE); -+ NvU32 val0Rd = GPU_REG_RD32(pGpu, PCIE_GEN2_XP3G_VAL_BASE); -+ NvU32 ovr3Rd = GPU_REG_RD32(pGpu, PCIE_GEN2_XP3G_OVR_BASE + 0xCU); -+ NvU32 val3Rd = GPU_REG_RD32(pGpu, PCIE_GEN2_XP3G_VAL_BASE + 0xCU); -+ NV_PRINTF(LEVEL_ERROR, -+ "SEC2_DEBUG: PCIe xp3g booter %s(0x%x)=0x%08x attempt=%u " -+ "status=0x%x rd=0x%08x OVR0=0x%08x VAL0=0x%08x " -+ "OVR3=0x%08x VAL3=0x%08x\n", -+ xp3gTable[xi].name, xp3gTable[xi].addr, -+ xp3gTable[xi].value, xattempt, xpStatus, -+ tgtRd, ovr0Rd, val0Rd, ovr3Rd, val3Rd); -+ if (tgtRd == xp3gTable[xi].value) -+ wrote = NV_TRUE; -+ } -+ if (!wrote) -+ NV_PRINTF(LEVEL_ERROR, -+ "SEC2_DEBUG: PCIe xp3g booter FAILED to set %s\n", -+ xp3gTable[xi].name); -+ } ++ GPU_REG_WR32(pGpu, 0x0008C2C0U, xpCya0 & ~0x00802005U); ++ GPU_REG_WR32(pGpu, 0x0008C040U, (xpCfg0 & ~0xC0000U) | 0x80000U); ++ GPU_REG_WR32(pGpu, 0x0008C1C0U, (xpLctrl2 & ~0xF0000U) | 0x20000U); + ++ { ++ OBJCL *pCl = SYS_GET_CL(SYS_GET_INSTANCE()); ++ PORTDATA *pUpPort = &pGpu->gpuClData.upstreamPort; ++ if (pCl != NULL && pUpPort->addr.valid) + { -+ NvU32 capNow = GPU_REG_RD32(pGpu, PCIE_GEN2_LINK_CAP_ADDR); -+ NvU32 cap2Now = GPU_REG_RD32(pGpu, PCIE_GEN2_LINK_CAP2_ADDR); -+ NvU32 opt23Now = GPU_REG_RD32(pGpu, 0x0082057cU); -+ NvU32 plmXp = GPU_REG_RD32(pGpu, 0x0008e1b0U); ++ NvU32 lnkCtl2Off = pUpPort->PCIECapPtr + 0x30U; ++ NvU16 rpLnkCtl2 = clPcieReadWord(pCl, ++ pUpPort->addr.domain, pUpPort->addr.bus, ++ pUpPort->addr.device, pUpPort->addr.func, lnkCtl2Off); ++ NvU16 rpLnkCtl2New = (rpLnkCtl2 & ~0xFU) | 0x2U; ++ clPcieWriteWord(pCl, ++ pUpPort->addr.domain, pUpPort->addr.bus, ++ pUpPort->addr.device, pUpPort->addr.func, ++ lnkCtl2Off, rpLnkCtl2New); + NV_PRINTF(LEVEL_ERROR, -+ "SEC2_DEBUG: PCIe Cap oracle CAP=0x%08x CAP2=0x%08x " -+ "OPT_GEN23=0x%08x XP3G_PLM=0x%08x\n", -+ capNow, cap2Now, opt23Now, plmXp); ++ "SEC2_DEBUG: PCIe root port LnkCtl2 @ 0x%x: 0x%04x -> 0x%04x\n", ++ lnkCtl2Off, rpLnkCtl2, rpLnkCtl2New); + } ++ } + -+ { -+ NvU32 vsecDevNow = GPU_REG_RD32(pGpu, PCIE_GEN2_VSEC_DEVICE_ADDR); -+ NvU32 vsecDevWant = vsecDevNow | (1U << 0); -+ NvBool wrote = NV_FALSE; -+ NV_PRINTF(LEVEL_ERROR, -+ "SEC2_DEBUG: PCIe VSEC_DEVICE pre=0x%08x want=0x%08x\n", -+ vsecDevNow, vsecDevWant); -+ for (xattempt = 0; xattempt < 2 && !wrote; xattempt++) -+ { -+ GPU_REG_WR32(pGpu, 0x001fa824U, wpr2Lo); -+ GPU_REG_WR32(pGpu, 0x001fa828U, wpr2Hi); -+ xpStatus = kgspSec2PostblTimingRefillPayload(pGpu, pKernelGsp, -+ PCIE_GEN2_VSEC_DEVICE_ADDR, vsecDevWant); -+ if (xpStatus != NV_OK) -+ continue; -+ xpStatus = kgspExecuteBooterLoad_HAL(pGpu, pKernelGsp, -+ memdescGetPhysAddr(pKernelGsp->pWprMetaDescriptor, AT_GPU, 0)); -+ NvU32 rd = GPU_REG_RD32(pGpu, PCIE_GEN2_VSEC_DEVICE_ADDR); -+ NV_PRINTF(LEVEL_ERROR, -+ "SEC2_DEBUG: PCIe VSEC_DEVICE booter attempt=%u " -+ "status=0x%x rd=0x%08x\n", -+ xattempt, xpStatus, rd); -+ if (rd == vsecDevWant) -+ wrote = NV_TRUE; -+ } -+ if (!wrote) -+ NV_PRINTF(LEVEL_ERROR, -+ "SEC2_DEBUG: PCIe VSEC_DEVICE booter FAILED\n"); -+ } ++ { ++ NvU32 cfg0Now = GPU_REG_RD32(pGpu, 0x0008C040U); ++ NvU32 cfg0After; ++ NvU32 linkCtrlStat; ++ NvU32 i; ++ ++ GPU_REG_WR32(pGpu, 0x0008C040U, (cfg0Now & ~0xFU) | 0x1U); + ++ for (i = 0; i < 50; i++) + { -+ NvU32 misc1 = GPU_REG_RD32(pGpu, PCIE_GEN2_PRIV_MISC_1_ADDR); -+ NvU32 misc1Want = (misc1 | PCIE_GEN2_PRIV_MISC_1_GEN2_EN) -+ & ~PCIE_GEN2_PRIV_MISC_1_GEN2_VAL; -+ NvBool wrote = NV_FALSE; -+ NV_PRINTF(LEVEL_ERROR, -+ "SEC2_DEBUG: PCIe PRIV_MISC_1 pre=0x%08x want=0x%08x\n", -+ misc1, misc1Want); -+ for (xattempt = 0; xattempt < 2 && !wrote; xattempt++) -+ { -+ GPU_REG_WR32(pGpu, 0x001fa824U, wpr2Lo); -+ GPU_REG_WR32(pGpu, 0x001fa828U, wpr2Hi); -+ xpStatus = kgspSec2PostblTimingRefillPayload(pGpu, pKernelGsp, -+ PCIE_GEN2_PRIV_MISC_1_ADDR, misc1Want); -+ if (xpStatus != NV_OK) -+ continue; -+ xpStatus = kgspExecuteBooterLoad_HAL(pGpu, pKernelGsp, -+ memdescGetPhysAddr(pKernelGsp->pWprMetaDescriptor, AT_GPU, 0)); -+ NvU32 rd = GPU_REG_RD32(pGpu, PCIE_GEN2_PRIV_MISC_1_ADDR); -+ NV_PRINTF(LEVEL_ERROR, -+ "SEC2_DEBUG: PCIe PRIV_MISC_1 booter attempt=%u " -+ "status=0x%x rd=0x%08x\n", -+ xattempt, xpStatus, rd); -+ if (rd == misc1Want) -+ wrote = NV_TRUE; -+ } -+ if (!wrote) -+ NV_PRINTF(LEVEL_ERROR, -+ "SEC2_DEBUG: PCIe PRIV_MISC_1 booter FAILED\n"); ++ osDelay(10); ++ if ((GPU_REG_RD32(pGpu, 0x0008C040U) & 0x10U) == 0) ++ break; + } + -+ GPU_REG_WR32(pGpu, 0x001fa824U, wpr2Lo); -+ GPU_REG_WR32(pGpu, 0x001fa828U, wpr2Hi); -+ } -+ -+ { -+ NvU32 hier = GPU_REG_RD32(pGpu, PCIE_GEN2_VSEC_HIERARCHY_ADDR); -+ hier = (hier & ~(1U << 12)) | (1U << 0); -+ GPU_REG_WR32(pGpu, PCIE_GEN2_VSEC_HIERARCHY_ADDR, hier); -+ NV_PRINTF(LEVEL_ERROR, -+ "SEC2_DEBUG: PCIe vsec hierarchy=0x%08x device=0x%08x\n", -+ GPU_REG_RD32(pGpu, PCIE_GEN2_VSEC_HIERARCHY_ADDR), -+ GPU_REG_RD32(pGpu, PCIE_GEN2_VSEC_DEVICE_ADDR)); -+ } ++ cfg0After = GPU_REG_RD32(pGpu, 0x0008C040U); ++ GPU_REG_WR32(pGpu, 0x0008C040U, cfg0After & ~0xFU); + -+ { -+ NvU32 lc2 = GPU_REG_RD32(pGpu, PCIE_GEN2_LINK_CTRL_2_ADDR); -+ NvU32 linkCfg; -+ NvU32 cya0; -+ lc2 = (lc2 & ~0x0000000FU) | PCIE_GEN2_LINK_SPEED; -+ lc2 = (lc2 & ~0x000F0000U) | 0x000F0000U; -+ GPU_REG_WR32(pGpu, PCIE_GEN2_LINK_CTRL_2_ADDR, lc2); -+ cya0 = GPU_REG_RD32(pGpu, 0x0008c2c0U); -+ cya0 = cya0 & ~(1U << 2); -+ GPU_REG_WR32(pGpu, 0x0008c2c0U, cya0); -+ NV_PRINTF(LEVEL_ERROR, -+ "SEC2_DEBUG: PCIe CYA_0 after clear DIS_G2: 0x%08x (bit2=%u)\n", -+ GPU_REG_RD32(pGpu, 0x0008c2c0U), -+ (GPU_REG_RD32(pGpu, 0x0008c2c0U) >> 2) & 1U); -+ linkCfg = GPU_REG_RD32(pGpu, 0x0008c040U); -+ linkCfg = (linkCfg & ~0x000C0000U) | (0x2U << 18); -+ GPU_REG_WR32(pGpu, 0x0008c040U, linkCfg); -+ NV_PRINTF(LEVEL_ERROR, -+ "SEC2_DEBUG: PCIe LINK_CONFIG_0 after MAX_RATE=2: 0x%08x\n", -+ GPU_REG_RD32(pGpu, 0x0008c040U)); -+ GPU_REG_WR32(pGpu, PCIE_GEN2_PL_LINK_RATE_ADDR, PCIE_GEN2_PL_LINK_RATE_VALUE); -+ GPU_REG_WR32(pGpu, 0x0008872cU, 0x00000006U); ++ linkCtrlStat = GPU_REG_RD32(pGpu, 0x00088088U); + NV_PRINTF(LEVEL_ERROR, -+ "SEC2_DEBUG: PCIe XVE_OVR@8872c=0x%08x; skip mid-boot retrain\n", -+ GPU_REG_RD32(pGpu, 0x0008872cU)); ++ "SEC2_DEBUG: PCIe retrain done (polls=%u): " ++ "LinkCtrlStat=0x%08x speed=%u width=x%u\n", ++ i, linkCtrlStat, ++ (linkCtrlStat >> 16) & 0xFU, ++ (linkCtrlStat >> 20) & 0x3FU); + } -+ -+ NvU32 statAfter = GPU_REG_RD32(pGpu, PCIE_GEN2_LINK_CTRL_STATUS_ADDR); -+ NV_PRINTF(LEVEL_ERROR, -+ "SEC2_DEBUG: PCIe retrain done CAP=0x%08x CAP2=0x%08x LC2=0x%08x " -+ "PL=0x%08x STAT=0x%08x hier=0x%08x dev=0x%08x OPT=%08x/%08x/%08x " -+ "XP3G ovr0=0x%08x val0=0x%08x ovr3=0x%08x val3=0x%08x " -+ "MISC1=0x%08x speed=%u\n", -+ GPU_REG_RD32(pGpu, PCIE_GEN2_LINK_CAP_ADDR), -+ GPU_REG_RD32(pGpu, PCIE_GEN2_LINK_CAP2_ADDR), -+ GPU_REG_RD32(pGpu, PCIE_GEN2_LINK_CTRL_2_ADDR), -+ GPU_REG_RD32(pGpu, PCIE_GEN2_PL_LINK_RATE_ADDR), -+ statAfter, -+ GPU_REG_RD32(pGpu, PCIE_GEN2_VSEC_HIERARCHY_ADDR), -+ GPU_REG_RD32(pGpu, PCIE_GEN2_VSEC_DEVICE_ADDR), -+ GPU_REG_RD32(pGpu, PCIE_GEN2_OPT_GEN23_ADDR), -+ GPU_REG_RD32(pGpu, PCIE_GEN2_OPT_GEN3_ADDR), -+ GPU_REG_RD32(pGpu, PCIE_GEN2_OPT_MAGIC_ADDR), -+ GPU_REG_RD32(pGpu, PCIE_GEN2_XP3G_OVR_BASE), -+ GPU_REG_RD32(pGpu, PCIE_GEN2_XP3G_VAL_BASE), -+ GPU_REG_RD32(pGpu, PCIE_GEN2_XP3G_OVR_BASE + 0xCU), -+ GPU_REG_RD32(pGpu, PCIE_GEN2_XP3G_VAL_BASE + 0xCU), -+ GPU_REG_RD32(pGpu, 0x0008841cU), -+ PCIE_LINK_SPEED_OF(statAfter)); + } + plmStatus = kgspSec2PostblTimingRebuildStockSignature(pGpu, pKernelGsp); if (plmStatus != NV_OK) { ---- a/src/nvidia/src/kernel/gpu/gsp/arch/turing/kernel_gsp_tu102.c -+++ b/src/nvidia/src/kernel/gpu/gsp/arch/turing/kernel_gsp_tu102.c -@@ -611,6 +611,44 @@ - } - } - -+ -+ { -+ NvU32 lateDevId = pGpu->idInfo.PCIDeviceID >> 16; -+ if ((lateDevId == 0x20C2 || lateDevId == 0x2082) && status == NV_OK) -+ { -+ #define PCIE_GEN2_PRIV_MISC_1_ADDR_LATE 0x0008841cU -+ #define PCIE_GEN2_PRIV_MISC_1_GEN2_EN_LATE ((1U << 11) | (1U << 13)) -+ #define PCIE_GEN2_PRIV_MISC_1_GEN2_VAL_LATE ((1U << 12) | (1U << 14)) -+ NvU32 misc1Late = GPU_REG_RD32(pGpu, PCIE_GEN2_PRIV_MISC_1_ADDR_LATE); -+ NvU32 misc1WantLate = (misc1Late | PCIE_GEN2_PRIV_MISC_1_GEN2_EN_LATE) -+ & ~PCIE_GEN2_PRIV_MISC_1_GEN2_VAL_LATE; -+ GPU_REG_WR32(pGpu, PCIE_GEN2_PRIV_MISC_1_ADDR_LATE, misc1WantLate); -+ NV_PRINTF(LEVEL_ERROR, -+ "SEC2_DEBUG: PCIe PRIV_MISC_1 late pre=0x%08x post=0x%08x\n", -+ misc1Late, -+ GPU_REG_RD32(pGpu, PCIE_GEN2_PRIV_MISC_1_ADDR_LATE)); -+ { -+ NvU32 cyaLate = GPU_REG_RD32(pGpu, 0x0008c2c0U); -+ cyaLate = cyaLate & ~(1U << 2); -+ GPU_REG_WR32(pGpu, 0x0008c2c0U, cyaLate); -+ NV_PRINTF(LEVEL_ERROR, -+ "SEC2_DEBUG: PCIe CYA_0 late clear DIS_G2: 0x%08x (bit2=%u)\n", -+ GPU_REG_RD32(pGpu, 0x0008c2c0U), -+ (GPU_REG_RD32(pGpu, 0x0008c2c0U) >> 2) & 1U); -+ NvU32 linkCfgLate = GPU_REG_RD32(pGpu, 0x0008c040U); -+ linkCfgLate = (linkCfgLate & ~0x000C0000U) | (0x2U << 18); -+ GPU_REG_WR32(pGpu, 0x0008c040U, linkCfgLate); -+ NV_PRINTF(LEVEL_ERROR, -+ "SEC2_DEBUG: PCIe LINK_CONFIG_0 late MAX_RATE=2: 0x%08x\n", -+ GPU_REG_RD32(pGpu, 0x0008c040U)); -+ GPU_REG_WR32(pGpu, 0x0008872cU, 0x00000006U); -+ NV_PRINTF(LEVEL_ERROR, -+ "SEC2_DEBUG: PCIe XVE_OVR late=0x%08x\n", -+ GPU_REG_RD32(pGpu, 0x0008872cU)); -+ } -+ } -+ } -+ - if (status != NV_OK) - { - NV_PRINTF(LEVEL_ERROR, "failed to execute Booter Load (ucode for initial boot): 0x%x\n", status); diff --git a/driver/patches/0009-mclk-overclock.patch b/driver/patches/0008-mclk-overclock.patch similarity index 98% rename from driver/patches/0009-mclk-overclock.patch rename to driver/patches/0008-mclk-overclock.patch index 07ac0ed..9c52605 100644 --- a/driver/patches/0009-mclk-overclock.patch +++ b/driver/patches/0008-mclk-overclock.patch @@ -1,6 +1,6 @@ ---- a/src/nvidia/src/kernel/gpu/gsp/arch/turing/kernel_gsp_tu102.c -+++ b/src/nvidia/src/kernel/gpu/gsp/arch/turing/kernel_gsp_tu102.c -@@ -649,6 +649,144 @@ +--- a/src/nvidia/src/kernel/gpu/gsp/arch/turing/kernel_gsp_tu102.c 2026-07-31 00:17:22.670241348 +0200 ++++ b/src/nvidia/src/kernel/gpu/gsp/arch/turing/kernel_gsp_tu102.c 2026-07-31 00:18:28.686969052 +0200 +@@ -611,6 +611,144 @@ kgspBootstrap_TU102 } } diff --git a/driver/patches/0008-pcie-gen2-probe-retrain.patch b/driver/patches/0008-pcie-gen2-probe-retrain.patch deleted file mode 100644 index 4f2e90b..0000000 --- a/driver/patches/0008-pcie-gen2-probe-retrain.patch +++ /dev/null @@ -1,110 +0,0 @@ ---- a/kernel-open/nvidia/nv.c -+++ b/kernel-open/nvidia/nv.c -@@ -65,6 +65,10 @@ - - #include - #include -+#include -+#include -+#include -+#include - - #include /* HDA struct snd_card */ - -@@ -1360,6 +1364,87 @@ - #if defined(NV_UVM_ENABLE) - nv_uvm_resume_P2P(pUuid); - #endif -+} -+ -+static void -+nv_cmp170hx_retrain_gen2(nv_state_t *nv) -+{ -+ nv_linux_state_t *nvl = NV_GET_NVL_FROM_NV_STATE(nv); -+ struct pci_dev *gpu = nvl->pci_dev; -+ struct pci_dev *upstream; -+ void __iomem *bar0; -+ u16 gpu_ctl2, upstream_ctl2, upstream_ctl, link_status = 0; -+ u32 cya0, link_config; -+ int ret, attempt; -+ -+ if ((gpu == NULL) || -+ ((gpu->device != 0x20c2) && (gpu->device != 0x2082))) -+ return; -+ -+ upstream = pci_upstream_bridge(gpu); -+ if (upstream == NULL) -+ { -+ NV_DEV_PRINTF(NV_DBG_ERRORS, nv, -+ "CMP Gen2: no upstream PCIe bridge; skipping link retrain\n"); -+ return; -+ } -+ bar0 = ioremap(pci_resource_start(gpu, 0), 0x90000); -+ if (bar0 == NULL) -+ { -+ NV_DEV_PRINTF(NV_DBG_ERRORS, nv, -+ "CMP Gen2: cannot map BAR0; skipping link retrain\n"); -+ return; -+ } -+ cya0 = readl(bar0 + 0x8c2c0); -+ writel(cya0 & ~(1U << 2), bar0 + 0x8c2c0); -+ link_config = readl(bar0 + 0x8c040); -+ writel((link_config & ~0x000c0000U) | (2U << 18), bar0 + 0x8c040); -+ writel(0x00000006U, bar0 + 0x8872c); -+ (void)readl(bar0 + 0x8872c); -+ iounmap(bar0); -+ msleep(50); -+ ret = pcie_capability_read_word(gpu, PCI_EXP_LNKCTL2, &gpu_ctl2); -+ if (ret) -+ goto capability_error; -+ ret = pcie_capability_read_word(upstream, PCI_EXP_LNKCTL2, &upstream_ctl2); -+ if (ret) -+ goto capability_error; -+ gpu_ctl2 = (gpu_ctl2 & ~PCI_EXP_LNKCTL2_TLS) | PCI_EXP_LNKCTL2_TLS_5_0GT; -+ upstream_ctl2 = (upstream_ctl2 & ~PCI_EXP_LNKCTL2_TLS) | PCI_EXP_LNKCTL2_TLS_5_0GT; -+ ret = pcie_capability_write_word(gpu, PCI_EXP_LNKCTL2, gpu_ctl2); -+ if (ret) -+ goto capability_error; -+ ret = pcie_capability_write_word(upstream, PCI_EXP_LNKCTL2, upstream_ctl2); -+ if (ret) -+ goto capability_error; -+ ret = pcie_capability_read_word(upstream, PCI_EXP_LNKCTL, &upstream_ctl); -+ if (ret) -+ goto capability_error; -+ ret = pcie_capability_write_word(upstream, PCI_EXP_LNKCTL, -+ upstream_ctl | PCI_EXP_LNKCTL_RL); -+ if (ret) -+ goto capability_error; -+ -+ for (attempt = 0; attempt < 20; attempt++) -+ { -+ msleep(100); -+ ret = pcie_capability_read_word(gpu, PCI_EXP_LNKSTA, &link_status); -+ if (!ret && -+ ((link_status & PCI_EXP_LNKSTA_CLS) >= PCI_EXP_LNKSTA_CLS_5_0GB)) -+ { -+ NV_DEV_PRINTF(NV_DBG_INFO, nv, "CMP Gen2: PCIe link trained to Gen%u\n", -+ link_status & PCI_EXP_LNKSTA_CLS); -+ return; -+ } -+ } -+ -+ NV_DEV_PRINTF(NV_DBG_ERRORS, nv, -+ "CMP Gen2: PCIe retrain completed without Gen2 link (status=0x%04x, ret=%d)\n", -+ link_status, ret); -+ return; -+capability_error: -+ NV_DEV_PRINTF(NV_DBG_ERRORS, nv, -+ "CMP Gen2: PCIe capability access failed (%d); skipping link retrain\n", ret); - } - - /* -@@ -1530,6 +1624,8 @@ - nv->flags |= NV_FLAG_PERSISTENT_SW_STATE; - } - -+ nv_cmp170hx_retrain_gen2(nv); -+ - /* Generate and cache the UUID for future callers */ - (void)rm_get_gpu_uuid_raw(sp, nv); - diff --git a/driver/patches/0010-mclk-overclock-post-gsp.patch b/driver/patches/0009-mclk-overclock-post-gsp.patch similarity index 92% rename from driver/patches/0010-mclk-overclock-post-gsp.patch rename to driver/patches/0009-mclk-overclock-post-gsp.patch index 94e232a..194effa 100644 --- a/driver/patches/0010-mclk-overclock-post-gsp.patch +++ b/driver/patches/0009-mclk-overclock-post-gsp.patch @@ -1,6 +1,6 @@ ---- a/src/nvidia/src/kernel/gpu/gsp/kernel_gsp.c -+++ b/src/nvidia/src/kernel/gpu/gsp/kernel_gsp.c -@@ -5620,6 +5620,56 @@ +--- a/src/nvidia/src/kernel/gpu/gsp/kernel_gsp.c 2026-07-31 00:47:41.953643183 +0200 ++++ b/src/nvidia/src/kernel/gpu/gsp/kernel_gsp.c 2026-07-31 00:47:45.933556620 +0200 +@@ -5435,6 +5435,56 @@ NV_CHECK_OK_OR_GOTO(status, LEVEL_ERROR, kgspStartLogPolling(pGpu, pKernelGsp), done); diff --git a/install.sh b/install.sh index 6949a82..3d4f4b0 100755 --- a/install.sh +++ b/install.sh @@ -9,35 +9,26 @@ mkdir -p "${LOG_DIR}" LOG_FILE="${LOG_DIR}/install_$(date +%Y%m%d_%H%M%S).log" PROFILE_OVERRIDE="" -CONFIGURE_IOMMU=1 -CONFIGURE_GEN2_SERVICE=1 +CONFIGURE_IOMMU=0 MCLK_NDIV="" for arg in "$@"; do case "${arg}" in --profile=8gb|--profile=8GB) PROFILE_OVERRIDE="8gb" ;; --profile=10gb|--profile=10GB) PROFILE_OVERRIDE="10gb" ;; - --no-iommu) CONFIGURE_IOMMU=0 ;; - --no-gen2-service) CONFIGURE_GEN2_SERVICE=0 ;; + --iommu) CONFIGURE_IOMMU=1 ;; --mclk-ndiv=*) MCLK_NDIV="${arg#*=}" ;; -h|--help) cat <<'EOF' -Usage: sudo ./install.sh [--profile=8gb|10gb] [--no-iommu] [--no-gen2-service] - [--mclk-ndiv=N] +Usage: sudo ./install.sh [--profile=8gb|10gb] [--iommu] [--mclk-ndiv=N] --profile=8gb Force 8GB metadata label (geometry is still chosen per PCI ID) --profile=10gb Force 10GB metadata label (geometry is still chosen per PCI ID) - --no-iommu Do not touch the kernel command line (leave IOMMU settings alone) - --no-gen2-service - Do not install the early-boot PCIe Gen2 retrain service + --iommu Add iommu=pt to the kernel command line (see README for details) --mclk-ndiv=N HBM memory clock: set PLL multiplier (30-80), N * 27 MHz. Works on any VBIOS, on both 0x20C2 and 0x2082. Stock is 64 on 8GB 300W, 54 on 8GB 250W, 45 on 10GB. Without this flag the overclock patches are not applied at all. -By default the installer appends intel_iommu=on / amd_iommu=on plus iommu=pt to -the kernel command line so the IOMMU runs in passthrough mode. This takes effect -on the next reboot. - Without --profile, each unlockable GPU is classified by PCI device ID: 10de:20c2 → 8gb / 64GB unlock 10de:2082 → 10gb / 40GB unlock @@ -306,33 +297,7 @@ CMPUNLOCKER_MCLK_NDIV="${MCLK_NDIV}" \ "${SCRIPT_DIR}/driver/build.sh" ok "Patched modules installed (profile ${CARD_PROFILE})" -step "Step 5b/6: Configuring PCIe Gen2" -cat > /etc/modprobe.d/cmp-pcie-gen2.conf <<'EOF' -options nvidia NVreg_RegistryDwords="RmForceEnableGen2=1;RMPcieLinkSpeed=0x1" -EOF -ok "Wrote /etc/modprobe.d/cmp-pcie-gen2.conf" - -for legacy_unit in cmpretrain.service cmp-gen2-retrain.service; do - systemctl disable --now "${legacy_unit}" 2>/dev/null || true - systemctl reset-failed "${legacy_unit}" 2>/dev/null || true -done -rm -f /etc/systemd/system/cmpretrain.service \ - /etc/systemd/system/cmp-gen2-retrain.service \ - /usr/local/sbin/retrain.sh \ - /usr/local/sbin/cmp-gen2-retrain.sh -systemctl daemon-reload -ok "Removed legacy PCIe retrain helpers" - -if (( CONFIGURE_GEN2_SERVICE == 1 )); then - chmod +x "${SCRIPT_DIR}/tools/hammer.sh" \ - "${SCRIPT_DIR}/tools/service.sh" - "${SCRIPT_DIR}/tools/service.sh" install - ok "Early-boot Gen2 retrain service armed (not started in this session)" -else - warn "--no-gen2-service given; early-boot PCIe retraining is not installed" -fi - -step "Step 5c/6: Configuring IOMMU (passthrough)" +step "Step 5b/6: Configuring IOMMU (passthrough)" IOMMU_STATUS="skipped" IOMMU_PARAMS="" @@ -473,7 +438,7 @@ configure_iommu_kernel_cmdline() { } if (( CONFIGURE_IOMMU == 0 )); then - warn "--no-iommu given; leaving kernel command line untouched" + info "IOMMU: not requested (use --iommu to configure passthrough)" else IOMMU_PARAMS="$(iommu_params_for_cpu)" if [[ -z "${IOMMU_PARAMS}" ]]; then @@ -532,10 +497,8 @@ echo -e " 5. Unlock logs: ${CYAN}sudo dmesg | grep SEC2_DEBUG${NC}" if [[ -n "${MCLK_NDIV}" ]]; then echo -e " Memory clock logs: ${CYAN}sudo dmesg | grep HBMPLL_OC${NC} (expect NDIV=${MCLK_NDIV})" fi -echo -e " 6. Verify IOMMU after reboot: ${CYAN}cat /proc/cmdline${NC} and ${CYAN}ls /sys/class/iommu${NC}" -if (( CONFIGURE_GEN2_SERVICE == 1 )); then - echo -e " 7. Verify negotiated Gen2: ${CYAN}sudo ./tools/service.sh verify${NC}" - echo -e " Recovery boot option: ${CYAN}systemd.mask=gen2.service${NC}" +if [[ -n "${IOMMU_PARAMS}" && "${IOMMU_STATUS}" != "skipped" ]]; then + echo -e " 6. Verify IOMMU after reboot: ${CYAN}cat /proc/cmdline${NC} and ${CYAN}ls /sys/class/iommu${NC}" fi echo "" echo "Log saved to: ${LOG_FILE}" diff --git a/systemd/gen2.service b/systemd/gen2.service deleted file mode 100644 index fae8005..0000000 --- a/systemd/gen2.service +++ /dev/null @@ -1,15 +0,0 @@ -[Unit] -Description=CMP 170HX early-boot PCIe Gen2 retrain -DefaultDependencies=no -After=sysinit.target -Before=basic.target multi-user.target graphical.target -ConditionPathExists=/usr/local/sbin/gen2-hammer - -[Service] -Type=oneshot -ExecStart=/usr/local/sbin/gen2-hammer -TimeoutStartSec=45 -RemainAfterExit=no - -[Install] -WantedBy=sysinit.target diff --git a/tools/hammer.sh b/tools/hammer.sh deleted file mode 100755 index 2b914a1..0000000 --- a/tools/hammer.sh +++ /dev/null @@ -1,161 +0,0 @@ -#!/bin/bash -# Early-boot PCIe Gen2 retrain loop for CMP 170HX (10de:20c2 / 10de:2082). -# -# The Gen2 capability the driver's probe-time patch exposes -# (driver/patches/0008-pcie-gen2-probe-retrain.patch) is only open for a -# short window during GSP bootstrap. If the driver's own one-shot retrain -# misses that window, this script keeps requesting Gen2 from the GPU's -# upstream bridge every ~50ms until it lands or the attempt budget runs out. -# Installed/removed via tools/service.sh; runs as -# systemd/gen2.service before basic.target. -set -uo pipefail - -PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin - -readonly VENDOR_ID="10de" -readonly LOG_FILE="/var/log/gen2.log" -readonly TARGET_GEN="${CMP170HX_GEN2_TARGET:-2}" -readonly MAX_ITERATIONS="${CMP170HX_GEN2_MAX_ITERATIONS:-600}" -readonly RETRAIN_INTERVAL="${CMP170HX_GEN2_RETRAIN_INTERVAL:-0.05}" - -log() { - local line - line="[$(date -Is)] $*" - echo "${line}" - echo "${line}" >> "${LOG_FILE}" 2>/dev/null || true -} - -read_link_status() { - setpci -s "$1" CAP_EXP+12.w 2>/dev/null || true -} - -link_generation() { - local status - status="$(read_link_status "$1")" - if [[ "${status}" =~ ^[[:xdigit:]]{4}$ ]]; then - echo $((0x${status} & 0x0f)) - else - echo "?" - fi -} - -is_supported_gpu() { - local bdf="$1" - local vendor device - [[ -r "/sys/bus/pci/devices/${bdf}/vendor" ]] || return 1 - [[ -r "/sys/bus/pci/devices/${bdf}/device" ]] || return 1 - vendor="$(<"/sys/bus/pci/devices/${bdf}/vendor")" - device="$(<"/sys/bus/pci/devices/${bdf}/device")" - [[ "${vendor,,}" == "0x${VENDOR_ID}" ]] || return 1 - [[ "${device,,}" == "0x20c2" || "${device,,}" == "0x2082" ]] -} - -upstream_bridge() { - local bdf="$1" - local parent - parent="$(basename "$(dirname "$(readlink -f "/sys/bus/pci/devices/${bdf}")")")" - [[ "${parent}" != "${bdf}" ]] || return 1 - [[ -e "/sys/bus/pci/devices/${parent}" ]] || return 1 - echo "${parent}" -} - -is_pci_bridge() { - local bdf="$1" - local class - [[ -r "/sys/bus/pci/devices/${bdf}/class" ]] || return 1 - class="$(<"/sys/bus/pci/devices/${bdf}/class")" - [[ "${class,,}" == 0x0604* ]] -} - -retrain_one() { - local gpu="$1" - local bridge status generation cap2 iteration initial - - if ! is_supported_gpu "${gpu}"; then - log "${gpu}: vendor/device guard failed; refusing to touch the device" - return 1 - fi - bridge="$(upstream_bridge "${gpu}" || true)" - if [[ -z "${bridge}" ]] || ! is_pci_bridge "${bridge}"; then - log "${gpu}: no valid upstream PCI bridge found; skipping" - return 1 - fi - - initial="$(link_generation "${gpu}")" - if [[ "${initial}" =~ ^[0-9]+$ ]] && (( initial >= TARGET_GEN )); then - log "${gpu}: already Gen${initial}; no retrain needed" - return 0 - fi - - log "${gpu}: start via upstream ${bridge}; initial Gen${initial}; target Gen${TARGET_GEN}" - for ((iteration = 1; iteration <= MAX_ITERATIONS; iteration++)); do - if ! is_supported_gpu "${gpu}"; then - log "${gpu}: disappeared during retrain; stopping immediately" - return 1 - fi - - # Preserve all unrelated bits; the endpoint may clamp this to Gen1 - # until the driver's probe-time patch briefly exposes Gen2. - setpci -s "${bridge}" CAP_EXP+30.w=0002:000f 2>/dev/null || true - setpci -s "${gpu}" CAP_EXP+30.w=0002:000f 2>/dev/null || true - - # Retraining must be initiated by the upstream bridge. - setpci -s "${bridge}" CAP_EXP+10.w=0020:0020 2>/dev/null || true - - status="$(read_link_status "${gpu}")" - if [[ "${status}" =~ ^[[:xdigit:]]{4}$ ]]; then - generation=$((0x${status} & 0x0f)) - if (( generation >= TARGET_GEN )); then - cap2="$(setpci -s "${gpu}" CAP_EXP+2c.l 2>/dev/null || echo unreadable)" - log "${gpu}: SUCCESS Gen${generation} at iteration ${iteration}; LnkSta=0x${status}; LnkCap2=0x${cap2}" - return 0 - fi - fi - sleep "${RETRAIN_INTERVAL}" - done - - generation="$(link_generation "${gpu}")" - log "${gpu}: no Gen2 window caught after ${MAX_ITERATIONS} attempts; final Gen${generation}" - return 1 -} - -main() { - local rc=0 - local -a gpus=() - - if [[ "${EUID}" -ne 0 ]]; then - echo "gen2-hammer must run as root" >&2 - exit 1 - fi - if [[ "${TARGET_GEN}" != "2" ]]; then - echo "Only Gen2 is supported by this safety-constrained helper" >&2 - exit 1 - fi - if ! [[ "${MAX_ITERATIONS}" =~ ^[1-9][0-9]*$ ]]; then - echo "CMP170HX_GEN2_MAX_ITERATIONS must be a positive integer" >&2 - exit 1 - fi - command -v lspci >/dev/null || { echo "lspci is required" >&2; exit 1; } - command -v setpci >/dev/null || { echo "setpci is required" >&2; exit 1; } - - : > "${LOG_FILE}" - log "early retrain started (attempts=${MAX_ITERATIONS}, interval=${RETRAIN_INTERVAL}s)" - - mapfile -t gpus < <( - for id in 20c2 2082; do - lspci -D -d "${VENDOR_ID}:${id}" 2>/dev/null | awk '{print $1}' - done - ) - if [[ ${#gpus[@]} -eq 0 ]]; then - log "no supported CMP 170HX found; nothing touched" - return 0 - fi - - for gpu in "${gpus[@]}"; do - retrain_one "${gpu}" || rc=1 - done - log "early retrain finished (rc=${rc})" - return "${rc}" -} - -main "$@" diff --git a/tools/retrain.sh b/tools/retrain.sh deleted file mode 100755 index 020566b..0000000 --- a/tools/retrain.sh +++ /dev/null @@ -1,106 +0,0 @@ -#!/bin/bash -set -euo pipefail - -SYS=/sys/bus/pci/devices/0000:0a:00.0 -for i in $(seq 1 120); do - if [[ -e $SYS/resource0 ]] && nvidia-smi -L &>/dev/null; then - break - fi - sleep 1 -done -if ! nvidia-smi -L &>/dev/null; then - exit 0 -fi - -mem="$(nvidia-smi --query-gpu=memory.total --format=csv,noheader,nounits 2>/dev/null | head -1 | tr -d ' ' || true)" -if [[ -z "${mem}" || "${mem}" == "[N/A]" ]]; then - exit 0 -fi - -cur="$(nvidia-smi --query-gpu=pcie.link.gen.current --format=csv,noheader 2>/dev/null | head -1 | tr -d ' ' || true)" -if [[ "${cur}" == "2" ]]; then - exit 0 -fi - -max="$(nvidia-smi --query-gpu=pcie.link.gen.max --format=csv,noheader 2>/dev/null | head -1 | tr -d ' ' || true)" -if [[ "${max}" != "2" && "${max}" != "3" && "${max}" != "4" ]]; then - exit 0 -fi - -python3 - <<'PY' -import os, mmap, struct, time, subprocess - -GPU, UP = "0a:00.0", "09:01.0" -PATH = "/sys/bus/pci/devices/0000:0a:00.0/resource0" - -def run(cmd): - return subprocess.check_output(cmd, text=True).strip() - -def bar0_open(): - fd = os.open(PATH, os.O_RDWR | os.O_SYNC) - m = mmap.mmap(fd, os.path.getsize(PATH), access=mmap.ACCESS_WRITE) - return fd, m - -def r(m, off): - return struct.unpack_from(">2)&1} " - f"MAX={(link>>18)&3} CAP={cap:08x} XVE={xve:08x} MISC1={misc1:08x}" -) -if bar0 == 0xFFFFFFFF or cya == 0xFFFFFFFF: - print("retrain: BAR0 dead; skip") - m.close(); os.close(fd) - raise SystemExit(0) -if ((cya >> 2) & 1) != 0: - print("retrain: DIS_G2 still set; skip") - m.close(); os.close(fd) - raise SystemExit(0) -if (cap & 0xF) < 2: - print(f"retrain: Cap Gen{cap & 0xF}; skip") - m.close(); os.close(fd) - raise SystemExit(0) -m.close(); os.close(fd) - -for bdf in (UP, GPU): - cur = int(run(["setpci", "-s", bdf, "CAP_EXP+30.w"]), 16) - subprocess.check_call(["setpci", "-s", bdf, f"CAP_EXP+30.w={(cur & ~0xF) | 0x2:04x}"]) - print(f"retrain: TLS {bdf} {cur:04x} -> {run(['setpci','-s',bdf,'CAP_EXP+30.w'])}") - -time.sleep(0.2) -fd, m = bar0_open() -if r(m, 0) == 0xFFFFFFFF: - print("retrain: BAR0 dead after TLS; skip") - m.close(); os.close(fd) - raise SystemExit(0) - -w(m, 0x8C2C0, r(m, 0x8C2C0) & ~(1 << 2)) -w(m, 0x8C040, (r(m, 0x8C040) & ~0xC0000) | (2 << 18)) -time.sleep(0.05) -cya = r(m, 0x8C2C0) -mx = (r(m, 0x8C040) >> 18) & 3 -alive = r(m, 0) != 0xFFFFFFFF -print(f"retrain: post CYA={cya:08x} DIS_G2={(cya>>2)&1} MAX={mx} bar0={r(m,0):08x}") -m.close(); os.close(fd) - -if not alive or ((cya >> 2) & 1) != 0 or mx != 2: - print("retrain: preconditions failed; skip") - raise SystemExit(0) - -cur = int(run(["setpci", "-s", UP, "CAP_EXP+10.w"]), 16) -subprocess.check_call(["setpci", "-s", UP, f"CAP_EXP+10.w={(cur | 0x20):04x}"]) -time.sleep(2.0) - -sta = int(run(["setpci", "-s", GPU, "CAP_EXP+12.w"]), 16) -print(f"retrain: speed_after={sta & 0xF}") -PY diff --git a/tools/service.sh b/tools/service.sh deleted file mode 100755 index c775ca1..0000000 --- a/tools/service.sh +++ /dev/null @@ -1,161 +0,0 @@ -#!/bin/bash -# Install/remove/verify the early-boot PCIe Gen2 retrain service -# (systemd/gen2.service + tools/hammer.sh). -# Wired into install.sh (Step 5b/6), remove.sh, and verify.sh. -set -euo pipefail - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -PROJECT_DIR="$(cd "${SCRIPT_DIR}/.." && pwd)" -SERVICE_NAME="gen2.service" -SERVICE_SOURCE="${PROJECT_DIR}/systemd/${SERVICE_NAME}" -SERVICE_TARGET="/etc/systemd/system/${SERVICE_NAME}" -HAMMER_SOURCE="${SCRIPT_DIR}/hammer.sh" -HAMMER_TARGET="/usr/local/sbin/gen2-hammer" -LOG_FILE="/var/log/gen2.log" - -info() { echo "==> $*"; } -ok() { echo "✓ $*"; } -warn() { echo "! $*" >&2; } -die() { echo "✗ $*" >&2; exit 1; } - -usage() { - cat </dev/null | awk '{print $1}' - done -} - -link_generation() { - local status - status="$(setpci -s "$1" CAP_EXP+12.w 2>/dev/null || true)" - if [[ "${status}" =~ ^[[:xdigit:]]{4}$ ]]; then - echo $((0x${status} & 0x0f)) - else - echo "?" - fi -} - -install_service() { - local module="/lib/modules/$(uname -r)/updates/cmpunlocker/nvidia.ko" - local -a gpus=() - - require_root - command -v install >/dev/null || die "install command not found" - command -v lspci >/dev/null || die "lspci not found (install pciutils)" - command -v setpci >/dev/null || die "setpci not found (install pciutils)" - [[ -f "${HAMMER_SOURCE}" ]] || die "Missing ${HAMMER_SOURCE}" - [[ -f "${SERVICE_SOURCE}" ]] || die "Missing ${SERVICE_SOURCE}" - - mapfile -t gpus < <(supported_gpus) - [[ ${#gpus[@]} -gt 0 ]] || die "No supported CMP 170HX found (10de:20c2 / 10de:2082)" - info "Detected: ${gpus[*]}" - - if [[ ! -f "${module}" ]]; then - die "Patched cmpunlocker module not found: ${module}" - fi - if ! grep -aFq 'CMP Gen2:' "${module}" 2>/dev/null; then - die "Installed module does not contain the Gen2 probe-retrain patch; refusing to arm a useless retrain service" - fi - ok "Installed NVIDIA module contains the Gen2 probe-retrain patch" - - install -m 0755 "${HAMMER_SOURCE}" "${HAMMER_TARGET}" - install -m 0644 "${SERVICE_SOURCE}" "${SERVICE_TARGET}" - systemctl daemon-reload - systemctl enable "${SERVICE_NAME}" >/dev/null - ok "Enabled ${SERVICE_NAME} for the next boot" - info "The service was not started now; the active desktop PCIe link was not touched." - info "Recovery boot option: systemd.mask=${SERVICE_NAME}" -} - -remove_service() { - require_root - systemctl disable --now "${SERVICE_NAME}" 2>/dev/null || true - rm -f "${SERVICE_TARGET}" "${HAMMER_TARGET}" - systemctl daemon-reload - systemctl reset-failed "${SERVICE_NAME}" 2>/dev/null || true - ok "Removed ${SERVICE_NAME}; cmpunlocker driver and memory unlock were left intact" - if [[ -f "${LOG_FILE}" ]]; then - info "Preserved diagnostic log: ${LOG_FILE}" - fi -} - -show_status() { - if [[ -f "${SERVICE_TARGET}" ]]; then - ok "Service file installed: ${SERVICE_TARGET}" - else - warn "Service file is not installed" - fi - systemctl is-enabled "${SERVICE_NAME}" 2>/dev/null || true - systemctl status "${SERVICE_NAME}" --no-pager 2>/dev/null || true -} - -verify_links() { - local gpu bridge status generation speed width max_speed result - local failures=0 - local -a gpus=() - - require_root - mapfile -t gpus < <(supported_gpus) - [[ ${#gpus[@]} -gt 0 ]] || die "No supported CMP 170HX found" - - printf '%-16s %-16s %-8s %-14s %-8s %s\n' "GPU" "Upstream" "LnkSta" "Current speed" "Width" "Result" - for gpu in "${gpus[@]}"; do - bridge="$(basename "$(dirname "$(readlink -f "/sys/bus/pci/devices/${gpu}")")")" - status="$(setpci -s "${gpu}" CAP_EXP+12.w 2>/dev/null || echo unreadable)" - generation="$(link_generation "${gpu}")" - speed="$(cat "/sys/bus/pci/devices/${gpu}/current_link_speed" 2>/dev/null || echo unknown)" - width="$(cat "/sys/bus/pci/devices/${gpu}/current_link_width" 2>/dev/null || echo unknown)" - max_speed="$(cat "/sys/bus/pci/devices/${gpu}/max_link_speed" 2>/dev/null || echo unknown)" - if [[ "${generation}" =~ ^[0-9]+$ ]] && (( generation >= 2 )); then - result="GEN2 OK" - else - result="GEN1" - failures=$((failures + 1)) - fi - printf '%-16s %-16s %-8s %-14s x%-7s %s\n' "${gpu}" "${bridge}" "0x${status}" "${speed}" "${width}" "${result}" - info "${gpu}: sysfs max=${max_speed}; negotiated generation is authoritative" - done - - if command -v nvidia-smi >/dev/null; then - echo - nvidia-smi --query-gpu=pci.bus_id,memory.total,pcie.link.gen.current,pcie.link.gen.max --format=csv 2>/dev/null || true - fi - - echo - if [[ -f "${LOG_FILE}" ]]; then - info "Last early-retrain log:" - tail -n 30 "${LOG_FILE}" - else - warn "No ${LOG_FILE}; the early service has not run yet" - fi - - if (( failures > 0 )); then - die "${failures} GPU(s) are still negotiated at Gen1" - fi - ok "All supported GPUs are negotiated at Gen2 or better" -} - -case "${1:-}" in - install) install_service ;; - remove) remove_service ;; - verify) verify_links ;; - status) show_status ;; - -h|--help|"") usage ;; - *) usage >&2; exit 1 ;; -esac diff --git a/verify.sh b/verify.sh index bcdac67..ea44a8c 100755 --- a/verify.sh +++ b/verify.sh @@ -202,12 +202,20 @@ fi echo "" ok "All ${#GPU_BDFS[@]} unlockable GPU(s) report unlocked memory" -if [[ -x "${SCRIPT_DIR}/tools/service.sh" ]]; then +pcie_info="$(nvidia-smi --query-gpu=pci.bus_id,pcie.link.gen.current --format=csv,noheader 2>/dev/null || true)" +if [[ -n "${pcie_info}" ]]; then echo "" - info "Checking negotiated PCIe generation" - if ! "${SCRIPT_DIR}/tools/service.sh" verify; then - warn "Memory unlock is healthy, but PCIe Gen2 is not active" - exit 1 - fi + info "PCIe link speed:" + while IFS=, read -r bus gen; do + bus="$(echo "${bus}" | tr -d '[:space:]')" + gen="$(echo "${gen}" | tr -d '[:space:]')" + if [[ "${gen}" == "2" ]]; then + ok "${bus}: Gen${gen}" + elif [[ "${gen}" == "1" ]]; then + warn "${bus}: Gen${gen} (Gen2 retrain may not have completed)" + else + info "${bus}: Gen${gen}" + fi + done <<< "${pcie_info}" fi exit 0