目录
CMP 170HX 和 A100 同核心(GA100,10DE:20C2),被熔丝加固件寄存器多重限速。解锁可以分成两层:应用层躲 FMA,以及固件层改寄存器。下面按硬件、L1、L2、显存卡点、风险和应用场景整理。
两层分别干什么
| 层次 | 做法 | 算力大致变化 | 风险 | 成熟度 |
|---|---|---|---|---|
| L1 应用层 | 编译器禁用 FMA(-fmad=false / OpenCL pragma) | FP32 约 0.39→6.25 TFLOPS(约 16×) | 不动固件 | 2023 年起常用 |
| L2 固件层 | SEC2 DMA 溢出 + ROP 写寄存器 | 工具声称 FP32 ~12、FP64 ~6.3 TFLOPS | 动 GSP 固件 | 2026-07 新路径,实现仍带 bug |
L1 已经能稳定用;L2 机理说得通,代码还有洞。L2 成功后节流寄存器被拿掉,L1 那套就不再需要。
FMA 限制是什么意思
FMA(Fused Multiply-Add)是 GPU 上极常见的一条浮点指令:一次做完 a * b + c,比「先乘再加」少一次舍入,也更快。CUDA/OpenCL 编译器默认会大量生成 FMA(对应 PTX 里的 fma / SASS 里的 FFMA 一类)。
CMP 170HX 上的「FMA 限制」不是把卡做成半残,而是:一旦流水线在跑 FMA(以及相关的 IMLA 等融合乘加),吞吐被固件/熔丝压到大约 1/32。所以:
- 用 clpeak 之类测「默认 FP32」会惨到约 0.39 TFLOPS
- 同样测「刻意不生成 FMA」的 FP32,可以到约 6.25 TFLOPS(大约 16×)
- FP16、INT32 往往不踩这条限,所以半精度推理、整数路径看起来「正常」
- Tensor Core 另有一套 dispatch 限制,和这条 FMA 闸不完全是一回事
具体会影响什么(按常见负载):
| 场景 | 影响 |
|---|---|
| 默认 FP32 CUDA/OpenCL(科学计算、很多物理仿真内核) | 极慢,几乎被 FMA 闸住 |
| llama.cpp / 自编译推理,仍用默认 FMA | FP32 路径很慢 |
同上,编译加 -fmad=false(L1) | FP32 大幅回升;精度多一次舍入,推理里通常可接受 |
| FP16 / BF16 / INT8 推理 | 往往不走被限的 FP32 FMA,体感好很多 |
| Blender 等闭源、FMA 密集渲染 | 改不了编译选项就只能吃亏 |
| 显存带宽、Hashcat 一类整数算力 | 基本不受这条 FMA 闸影响 |
| 卡间拷数据 / 模型加载 | 主要吃 PCIe Gen1,不是 FMA 的问题 |
一句话:FMA 限制 = FP32 融合乘加被限速;能改编译、躲开 FMA,或改走 FP16/整数,就能绕开大部分痛点。固件层(L2)则是直接把节流寄存器关掉,让「正常生成 FMA」也能满速。
硬件与限制
- GA100 die;HBM2e 有真 binning,不是纯软件锁:
- 8GB:56 SM、4096-bit、2 个 HBM2e stack,Subsystem
0x1585 - 10GB:70 SM、5120-bit、5 个 stack,Subsystem
0x1557 - 16GB 档有人提过,证据不足
- 8GB:56 SM、4096-bit、2 个 HBM2e stack,Subsystem
- 带宽实测约 1,355 GB/s(接近 A100 PCIe 40GB)
- FP16 约 42 TFLOPS、INT32 约 12.5 TIOPS(通常不节流)
- PCB 接近 A100,二手价远低于正经 A100
| 限制 | 强制层 | 现状 |
|---|---|---|
| FMA/IMLA 节流(约 1/32) | 熔丝 + SS0/SS1 | L1 可绕,L2 可卸 |
| 显存容量 | FBPA_CFG1 + GSP-RM 几何校验 | 寄存器级能动,GSP-RM 覆写未解透 |
| PCIe Gen1 速率 | 签名 VBIOS + Falcon PRIV | 固件级未破 |
| PCIe x4 宽度 | PCB 缺 24 颗 0.22µF 耦合电容 | 补焊可到 x16(2026-04 有人确认),速率仍 Gen1 |
| NVLink | 熔丝 + 缺件 + 固件 | 基本不现实 |
| 主 Device ID | 硬件根植 | 未见公开突破 |
Ampere 启动大致:BROM → Booter(HS/SEC2) → GSP-RM(LS) → FWSEC(HS/GSP) → DEVINIT(LS/PMU) → SEC2-RTOS(LS)。FWSEC 在显存建 WPR2。GA100 用 FalconUCodeDescV2(不是 V3),公开审视相对少,和被打过的 Turing 签名栈更近一些。
L1:躲 FMA
节流主要卡在执行 FMA 时。让编译器别生成 FMA(拆成乘加),就能绕开。多一次舍入,推理里通常能忍。
| 框架 | 做法 |
|---|---|
| OpenCL | #pragma OPENCL FP_CONTRACT OFF,再把 fma 宏成 ((a)*(b)+(c)) |
| CUDA | nvcc -fmad=false |
| llama.cpp | CMake -DCMAKE_CUDA_FLAGS="-fmad=false",架构 80 |
| PoCL | -DENABLE_FMA=OFF |
| 标准 PyTorch | 不走这条,多用 FP16 |
社区 + arXiv 2505.03782 一类数据(clpeak 等):
- FP32 FMA 节流约 0.39 → no-FMA 约 6.25 TFLOPS
- FluidX3D:约 2,276 → 7,684 MLUPs/s(接近同场景 A100 的九成)
- FP16 / INT32 本就不限
- Tensor Core 另有 dispatch gate,约 6.2 TFLOPS,不是同一把锁
L1 解决不了:FP64 仍低、PCIe 仍约 0.85 GB/s、显存仍 8/10GB、闭源 FMA 密集软件(例如部分 Blender CUDA 路径)还是慢。
L2:固件路径(2026-07)
大致链路:
- 改 GSP 固件 ELF 的
.fwsignature_ga100段塞 ROP,并改sh_size(否则驱动只拷 4096 字节,溢不出来) - DMA 灌约 0xF800 进 4096 缓冲 → canary
0xFACEB13D→ ROP - gadget
0x10B9绕 MMIO 防火墙,经 CSB 写 FBPA_CFG1 / LMR / PLM - Phase1 ROP(GSP 预期失败)→ FLR(always-on 域寄存器还能活)→ Phase2 原厂固件正常起 CUDA
- FLR 后宿主 BAR0 补写 SS0/SS1
硬约束:Linux x86-64、内核 ≥6.8、nvidia-open 580.173.02(610/595 在 GA100 rev a1 上 GSP-RM 起不来)、gadget 绑 580、root,首次往往要拔电冷启清 WPR2。
工具侧已知未修问题:
compute.py读feat_ovr_plm,constants.yaml只有ss0/ss1→TypeErrordriver.py缺enumerate_gpu(),没 persistenced 时驱动可能不 probe,洞触发不了- 显存目标键名乱(
unlocked_40gb/ 文档里的 64GB 等对不上)
170th Street 在 2026-04 还写「固件级 FMA 未破」;公开工具大约 2026-07-15 才出现,晚于那次评估,同行验证仍少。
显存:先认版本
| 版本 | SM | stack | 总线 | 原生 | 物理上限粗估 |
|---|---|---|---|---|---|
| 8GB | 56 | 2 | 4096-bit | 8GB | 受 2 stack 限制,别指望 40/80 |
| 10GB | 70 | 5 | 5120-bit | 10GB | 5×8→40 或 5×16→80(看颗粒) |
8GB 是少焊 stack,不是 5 个被软件锁死。unlocked_40gb / 80gb 这类目标只对 10GB 版有意义;8GB 硬写会被几何校验打回。先用 nvidia-smi 看容量,lspci -nn 看 Subsystem(0x1585 / 0x1557)。
卡点:
- 间接 MMIO 把地址截成 16 位,写
0x9A0204会落到错位;直接 Falcon/CSB 路径才能到完整 BAR0 FBPA_CFG1/LMR/CSTATUS等要互相匹配,否则 GSP-RM 按熔丝重配- BAR0 写能活过驱动重载,活不过 DEVINIT 和掉电
所以会出现「寄存器改对了,nvidia-smi 容量不变」。
可行性粗评
相对靠谱:L1;PCIe x4→x16 补电容;L2 算力(修完 bug、锁 580)。
半成品:L2 显存(寄存器能动,GSP-RM 未彻底服;只有 10GB 版有戏)。
基本没戏 / 未破:PCIe Gen1 速率;未签名 VBIOS(Ampere 证书链);NVLink;改主 Device ID;610/595 驱动。
补充:VBIOS 并不只是纯 RSA-3072。签名区之外还有 Davies-Meyer 一类 MAC(170HX 大约盖住 0x2200–0x43A00)。MAC 外字段(功率限制等)有人用 SPI 改过;签名区乱改仍会不起机。OMGVflash/nvflashk 在 Ampere 上基本只能已签名 ROM 互刷。
应用怎么选
做便宜推理:多数情况 先 L1(llama.cpp -fmad=false),FP16 路径本身就不限。显存是硬墙——8GB 大概 7B 级;10GB 若 L2 显存真到 40GB,才谈得上更大量化模型。带宽高,长上下文 KV 受益;PCIe ~0.85 GB/s,适合常驻,不适合频繁换模型。
做固件安全研究:SEC2 DMA + ROP + CSB + canary 这条链完整;V2 描述符值得盯。工具里的 ELF 补丁、BAR0 mmap、watchdog 思路可复用。
配套:dartraiden/NVIDIA-patcher(矿卡开 CUDA/OpenCL);OMGVflash/nvflashk(已签名互刷);电容补焊;retimer 思路(Gen1 速率,需定制);L2 工具(2026-07,带 bug)。
适合:低算术强度、能改代码躲 FMA、FP16/INT、带宽/$ 优先。不适合:标准 FP32/BF16 训练、FMA 密集闭源渲染、要大显存却只有 8GB、要快的 CPU↔GPU 搬运、要开箱即用。
社区与文献
| 仓库 | 角色 | 备注 |
|---|---|---|
kinako404/cmpunlocker | L2 实现 | GPL-2.0,约 2026-07-15 |
abobasixseven/unlock-cmp-170hx | 研究笔记 | Issue #1 记了上述 bug |
fulracoco/cmpunlocker | 早期草稿 | 已 404 |
dartraiden/NVIDIA-patcher | 驱动补丁 | 维护中 |
| 170th-street.gitbook.io/hx | 社区站 | 约到 2026-04 |
另见 arXiv 2505.03782、Zenodo 18994970 / 19002983、Jon Pry 关于 DMA/canary 的写法。
风险
违反 NVIDIA EULA、无保修;作者通常限定自有硬件。L2 绑死 580.173.02,洞一修或驱动一换就废;gadget 要重逆;首次常要冷启;固件补丁有变砖面,一般靠 .stock + FLR。这是研究路径,不是生产方案。
性能对照(社区 / 论文量级)
| 项 | 大约 |
|---|---|
| FP32 FMA / no-FMA | 0.39 / 6.25 TFLOPS |
| FP16 | 42 TFLOPS |
| FP64 FMA / no-FMA | 0.18 / 0.094 TFLOPS |
| INT32 | 12.5 TIOPS |
| Tensor Core | 6.2 TFLOPS(gated) |
| 内存带宽 | 1,355 GB/s |
| PCIe | ~0.85 GB/s(Gen1 x4) |
附录:环境、补丁与流程备忘
系统倾向 Ubuntu 24.04、内核 ≥6.8、仅 nvidia-driver-580-open。先备份:
bashsudo cp /lib/firmware/nvidia/580.173.02/gsp_tu10x.bin \
/lib/firmware/nvidia/580.173.02/gsp_tu10x.bin.stock
lspci -nn | grep -i nvidia
nvidia-smi --query-gpu=memory.total --format=csv,noheader
constants.yaml 的 host_bar0_writes 需有 plm(否则 compute 崩):
yamlhost_bar0_writes:
plm:
addr: 0x00823804
value: 0xFFFFFFFF
note: "FEAT_OVR_PLM"
ss0:
addr: 0x0082381C
value: 0x88888888
ss1:
addr: 0x00823820
value: 0x00000008
compute.py 里把 feat_ovr_plm 改成 plm。driver.py 加 enumerate_gpu()(内部跑一次 nvidia-smi),在 pipeline.py 的 load_module() 之后调用。
寄存器探针示例(PCI 地址改成自己的):
python#!/usr/bin/env python3
import mmap, struct, os
PCI_DEV = "0000:01:00.0"
RESOURCE_PATH = f"/sys/bus/pci/devices/{PCI_DEV}/resource0"
REGISTERS = [
(0x00823804, "FEAT_OVR_PLM", 0xFFFFFFFF),
(0x0082381C, "FEAT_OVR_SM_SPD", 0x88888888),
(0x00823820, "FEAT_OVR_SM_SPD_1", 0x00000008),
(0x009A0204, "FBPA_CFG1", 0x02669000), # 40GB 目标,仅 10GB 版有意义
(0x00100CE0, "LMR", 0x0000020B),
]
fd = os.open(RESOURCE_PATH, os.O_RDONLY)
mm = mmap.mmap(fd, 16777216, mmap.MAP_SHARED, mmap.PROT_READ)
for offset, name, target in REGISTERS:
val = struct.unpack_from('<I', mm, offset)[0]
print(f"[0x{offset:08X}] {name:20s} = 0x{val:08X} {'OK' if val == target else 'DIFF'}")
mm.close(); os.close(fd)
ROP 大致:DMEM 填零 → canary 0xFACEB13D @ 0x6340 → 三帧写 FBPA_CFG1 / LMR / PLM → 尾帧回 0x810D(不要用会重置 SEC2 的成功路径)。SS0/SS1 不进 ROP,PLM 开后由宿主 BAR0 补。补丁签名段后必须更新 sh_size。
跑 pipeline 前冷启、清旧备份,再:
bashcd /path/to/cmpunlocker
sudo python3 payload/pipeline.py "0000:01:00.0" \
"/lib/firmware/nvidia/580.173.02/gsp_tu10x.bin"
出问题先还原 .stock、rmmod/modprobe,必要时 PCI remove/rescan 或拔电。
源码树常见布局:common/constants.yaml、payload/{build,gsp_patch,pipeline,driver,bar0,gpu}.py、unlock/{compute,vram}.py、daemon/watchdog.py。
ai协作,人工编辑