Skip to content

Commit 6f658cd

Browse files
committed
Update Hall of Fame screenshots and score to 30,511 (#66 single / #75 all)
1 parent 1318a39 commit 6f658cd

7 files changed

Lines changed: 163 additions & 8 deletions

File tree

‎README.md‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@
1313

1414
## Hall of Fame
1515

16-
**3DMark Time Spy Extreme Graphics Score: 30,331**
17-
Rank: **#86 (single GPU)** / **#95 (all)**
16+
**3DMark Time Spy Extreme Graphics Score: 30,511**
17+
Rank: **#66 (single GPU)** / **#75 (all)**
1818
GPU: NVIDIA GeForce RTX 5090 32 GB · CPU: AMD Ryzen 9 9950X3D2
19-
Result: [spy/65251803](http://www.3dmark.com/spy/65251803)
19+
Result: [spy/63597987](http://www.3dmark.com/spy/63597987)
2020

2121
![3DMark Time Spy Extreme Graphics Hall of Fame](./docs/images/hall-of-fame-main.png)
2222

23-
*Additional screenshots: [1](./docs/images/hall-of-fame-1.png) · [2](./docs/images/hall-of-fame-2.png) · [3](./docs/images/hall-of-fame-3.png)*
23+
*Additional screenshot: [1](./docs/images/hall-of-fame-1.png)*
2424

2525
---
2626

‎README.zh-CN.md‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@
1313

1414
## Hall of Fame
1515

16-
**3DMark Time Spy Extreme Graphics 分数:30,331**
17-
排名:**单卡第 86 名 / 全部第 95 名**
16+
**3DMark Time Spy Extreme Graphics 分数:30,511**
17+
排名:**单卡第 66 名 / 全部第 75 名**
1818
显卡:NVIDIA GeForce RTX 5090 32 GB · CPU:AMD Ryzen 9 9950X3D2
19-
结果页:[spy/65251803](http://www.3dmark.com/spy/65251803)
19+
结果页:[spy/63597987](http://www.3dmark.com/spy/63597987)
2020

2121
![3DMark Time Spy Extreme Graphics Hall of Fame](./docs/images/hall-of-fame-main.png)
2222

23-
*更多截图:[1](./docs/images/hall-of-fame-1.png) · [2](./docs/images/hall-of-fame-2.png) · [3](./docs/images/hall-of-fame-3.png)*
23+
*更多截图:[1](./docs/images/hall-of-fame-1.png)*
2424

2525
---
2626

‎docs/PERF_SET_RM_RESEARCH.md‎

Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
# PERF SET / RM 通道研究留底(持续更新)
2+
3+
> 状态:只读逆向 + 一次受控写测试(未生效)。所有 GPU 写入均需用户明确批准。
4+
> 本文件记录 RTX 5090 上绕过 PState20 上限、尝试 36 Gbps 显存的研究进度。
5+
6+
## 目标
7+
8+
- 当前 PState20 路径上限:显存 34 Gbps(17001 MHz = 17001000 kHz)
9+
- 目标:36 Gbps(18000 MHz = 18000000 kHz)
10+
- PState20 V2 SET 写 base/max 被忽略,delta 被 cap 在 +3000 MHz
11+
12+
## 关键结论(截至当前)
13+
14+
1. **NvAPI 用户态存在直达内核 RM 的通道**
15+
- `nvapi64_impl.dll` 导入 `CreateFileA` / `DeviceIoControl`
16+
- 打开 `\\.\NvAdminDevice`
17+
- `DeviceIoControl(0x8de0004)` 获取 client handle
18+
- `DeviceIoControl(0x8de0008)` 发送 RM control
19+
- 载荷格式:`NVDA 头 + 内联 NVOS54 载荷`
20+
21+
2. **内核 PERF SET 命令存在**
22+
- 命令 ID:`0x2080e0af`
23+
- 命令表大小:`0x13c08`
24+
- handler:`nvlddmkm.sys` RVA `0x4cd9b0`
25+
- handler 只读取参数前 12 字节(三个 dword),调用内部函数 `0x326cc0`
26+
- `0x2080e0ae`(小 SET)也存在,handler RVA `0x371ed0`,大小 `0x474`
27+
28+
3. **直连 RM 写当前不可行**
29+
- 直接 LoadLibrary `nvapi64_impl.dll` 拿到的模块不是 NvAPI 实际运行的实例
30+
- NvAPI 使用运行时展开的私有代码(公开 `QueryInterface` 返回的指针不在任何已加载模块范围内)
31+
- 直接调用磁盘上 `nvapi64_impl.dll` 的内部 RM 函数,GET/SET 均返回 `0x23`(参数结构被拒),未到达真正内核 handler
32+
- 已尝试正确 `hObject=0xb2000000` 仍为 `0x23`,确认问题在“用错实例”,不是 SET 参数
33+
34+
4. **公开 NvAPI 只读 GET 可用**
35+
- NvAPI ID `0xefcedd1f`(函数 RVA `0x28c0e0`)
36+
- 子命令 `0x4480c` / `0x6642c` / `0x7388c` 可返回 245 项 perf 表
37+
- 显存上限条目:entry 194,字段 `+0x18` / `+0x44` = `17001000` kHz(34 Gbps)
38+
- 核心条目:entry 63 / 67 等,`+0x18` / `+0x44` = `3210000` kHz
39+
40+
## SET 12 字节头假设(未验证)
41+
42+
基于内核 `0x326cc0` 和 GET 表结构推测:
43+
44+
| 偏移 | 含义 | 显存 36 Gbps 示例 |
45+
|---|---|---|
46+
| `+0x00` | 类型/标志(匹配 `flags & 2`) | `2` |
47+
| `+0x04` | 条目 RM ID | `208`(0xD0,显存) |
48+
| `+0x08` | 新频率 kHz | `18000000` |
49+
50+
- 核心 RM ID 示例:`67`(0x43)
51+
- 用户侧 key 与 RM ID 映射表见 `nvapi64_impl.dll` RVA `0x486350`
52+
53+
## 受控写测试记录
54+
55+
- 第一次尝试:hObject 传错(0x100 / 0x5c000003),返回 `0x23`,无状态变化
56+
- 第二次尝试:hObject 用正确值 `0xb2000000`,仍返回 `0x23`,无状态变化
57+
- 原因:直接加载的 `nvapi64_impl.dll` 不是 NvAPI 私有运行实例,RM 调用在入口被拒
58+
59+
## 公开 SET API(已修正,重要)
60+
61+
子代理静态分析 + 只读 GET 验证后确认:
62+
63+
- `0x55590bdb`(RVA `0x2806a0`)是 **GET**,版本 `0x100fc`,只发 `0x2080a0ab`,不写。
64+
- 真正写 `0x2080e0ae` 的是 **SET**:
65+
- NvAPI ID:`0x375e26cc`
66+
- RVA:`0x281f80`
67+
- 版本:`0x2121c`
68+
- 对应的 GET:
69+
- NvAPI ID:`0x139c77f6`
70+
- RVA:`0x27f5e0`
71+
- 版本:`0x2121c`
72+
73+
### `0x2121c` 表布局(已只读验证)
74+
75+
- `+0x00`:版本 `0x2121c`
76+
- `+0x94`:`u32` bitmask(当前 `0x1ff`,bit0~bit8 有效)
77+
- 每个 bit 的值槽起始 `+0x98`,步长 `0x44`
78+
- 实测:
79+
- bit0 → `+0x98` = 307000
80+
- bit1 → `+0xdc` = 1455000
81+
- **bit2 → `+0x120` = 17001000(显存频率)**
82+
- 写入显存 36 Gbps:把 `+0x120` 改为 `18000000`(`0x112A880`),bit2 已在 mask 中
83+
84+
### 安全写流程
85+
86+
1. 调用 GET `0x139c77f6` 填好整个 `0x2121c` buffer
87+
2. 修改 `+0x120 = 18000000`
88+
3. 调用 SET `0x375e26cc` 写回
89+
4. 用 GET `0x139c77f6` 读回验证
90+
91+
### 写测试结果(已执行)
92+
93+
- 非管理员调用 SET 返回 `-137`(NVAPI_INVALID_USER_PRIVILEGE)
94+
- 管理员下 SET 返回 `0x0`(成功)
95+
- 但 GET 读回仍为 `17001000`,没有变成 `18000000`
96+
- 降频诊断:SET 16000000 也返回 0,但 GET 仍 17001000,SET 完全没生效
97+
- 传入 buffer 在 SET 后仍保留 16000000,说明驱动没有回写/接受
98+
99+
### 子代理进一步分析(SET 为什么 no-op)
100+
101+
- SET `0x375e26cc` 支持 `0x10048` 和 `0x2121c`
102+
- `0x2121c` 分支会把以下字段拷贝进内部 buffer:
103+
- `+0x04` → internal `+0x40`(疑似域选择 mask)
104+
- `+0x08` → internal `+0x48`
105+
- `+0x0c` / `+0x0d` → internal `+0x50` / `+0x51`(疑似 clock type / apply 标志)
106+
- `+0x94` mask → internal `+0x374`
107+
- `+0x98 + n*0x44` 值槽 → internal `+0x378 + n*4`
108+
- `+0x918` qword → internal `+0x3c4`
109+
- `+0x91c + n*0x48` / `+0x920 + n*0x48` 扩展槽 → internal `+0x3c8 + n*8`
110+
- 直接照抄 GET buffer 只改 `+0x120` 的问题:`+0x04`、`+0x0c`、`+0x0d` 仍是 GET 输出的“当前/只读”状态,驱动不认为这是一次真正的 set;扩展槽 `+0x9ac/+0x9b0` 也可能仍指向旧目标。
111+
112+
### 最可能正确的 SET 构造(待实测)
113+
114+
```text
115+
version = 0x2121c
116+
+0x04 = 0x4 # 只选 bit2(memory)
117+
+0x0c = 2 # 或 1(clock type)
118+
+0x0d = 1 # 或 0(apply/commit 标志)
119+
+0x94 = 0x4 # mask 只含 bit2
120+
+0x120 = 18000000 # 目标频率
121+
+0x9ac = 18000000 # 扩展槽 min/max
122+
+0x9b0 = 18000000
123+
```
124+
125+
然后调用 SET `0x375e26cc`,最后用 GET `0x139c77f6` 回读 `+0x120` 验证。
126+
127+
### 修正版实测结果
128+
129+
- GET 原始值:`+0x04=0`、`+0x0c=0`、`+0x0d=0`、`+0x94=0x1ff`、`+0x120=17001000`、`+0x9ac=0`、`+0x9b0=0`
130+
- 把 `+0x04=4`、`+0x0c=2`、`+0x0d=1`、`+0x94=4`、`+0x120=18000000`、`+0x9ac/+0x9b0=18000000` 后 SET 返回 `-104`(`0xffffff98`),没有生效
131+
- 说明 `+0x04/+0x0c/+0x0d/+0x94` 不能按子代理猜的那样随便改
132+
- 下一步候选:保持 GET 原始控制字段(`+0x04=0,+0x0c=0,+0x0d=0,+0x94=0x1ff`),只补扩展槽 `+0x9ac/+0x9b0=18000000`,再试 SET
133+
134+
### 扩展槽实测结果
135+
136+
- 保持 GET 原始控制字段,只把 `+0x120/+0x9ac/+0x9b0` 设为 18000000
137+
- SET 返回 `0x0`,但 GET 仍 17001000,扩展槽仍 0
138+
- 结合之前 16000000 降频也不变,基本可以判定:**这个 SET 调用在当前驱动上不会真正写入该字段**
139+
- 可能原因:
140+
1. 缺少额外的“提交/应用”步骤(另一个 NvAPI 调用)
141+
2. `0x2121c` 不是该 GPU 实际生效的 SET 结构
142+
3. 驱动对该字段只读/被锁定,SET 静默忽略
143+
144+
## 下一步
145+
146+
- [ ] 逆向 `0x55590bdb` 的 `0x100fc` buffer 布局,重点是找到显存 entry 194 / RM ID 208 对应的写入字段
147+
- [ ] 若公开 SET 可用,构造安全 buffer:只改显存频率字段,其余保持当前值,走官方 API 写
148+
- [ ] 验证写后 GET 是否变为 `18000000`
149+
- [ ] 若失败,评估 hook NvAPI 私有实例或放弃该旁路
150+
151+
## 安全边界
152+
153+
- 任何写操作前必须向用户说明并获批准
154+
- 已有 VBIOS/驱动/核显备份
155+
- 出现黑屏/TDR 时通过核显或第二 GPU 恢复

‎docs/images/hall-of-fame-1.png‎

1.35 MB
Loading

‎docs/images/hall-of-fame-2.png‎

-74.4 KB
Binary file not shown.

‎docs/images/hall-of-fame-3.png‎

-67.5 KB
Binary file not shown.

‎docs/images/hall-of-fame-main.png‎

-267 KB
Loading

0 commit comments

Comments
 (0)