Zentool:AMD Zen 微代码操作实用工具

该软件包提供了一套用于分析、操作和生成 AMD Zen 处理器微代码补丁的工具。

zentool 命令是各种实用程序的前端。 还有一个简单的汇编器 mcas 和一个简单的反汇编器 mcop

注意:我们还有一个微代码编程的介绍 和一个编程参考

用法

命令的一般格式是:

$ zentool [GLOBALOPTIONS] CMD [COMANDOPTIONS] [FILE...]

键入 zentool help 可查看可用命令的列表。

示例

你可以使用 print 命令检查微代码更新文件的标头:

$ zentool print data/cpu00860F01_ver0860010F_2024-11-18_785D74AB.bin
Date:    11182024 (Mon Nov 18 2024)
Revision:  0860010f
Format:   8004
Patchlen:  00
Init:    00
Checksum:  00000000
NorthBridge: 0000:0000
SouthBridge: 0000:0000
Cpuid:    00008601 AMD Ryzen (Grey Hawk, Renoir)
 Stepping  1
 Model:   0
 Extmodel: 6
 Extfam:  8
BiosRev:   00
Flags:    00
Reserved:  0000
Signature:  9c... (use --verbose to see) (GOOD)
Modulus:   c7... (use --verbose to see)
Check:    5a... (use --verbose to see) (GOOD)
Autorun:   false
Encrypted:  false
Revision:  0860010f (Signed)

让我们使用 edit 命令修改该修订号,并将结果保存到 modified.bin

$ zentool --output modified.bin edit --hdr-revision 0x8600141 data/cpu00860F01_ver0860010F_2024-11-18_785D74AB.bin
$ zentool print modified.bin | grep -m1 ^Revision:
Revision:  08600141

这有效,但现在签名将不正确:

$ zentool verify modified.bin
modified.bin: BAD

你可以使用 resign 命令来补偿你所做的更改:

$ zentool resign modified.bin
$ zentool verify modified.bin
modified.bin: GOOD

现在,你可以使用 load 命令将该更新应用于你的处理器,这需要 root 权限:

$ sudo zentool load --cpu=2 modified.bin

现在,我们可以通过查询微代码版本来验证它是否有效:

$ sudo rdmsr -c -a 0x8b
0x8608103
0x8608103
0x8608141 <---
0x8608103
0x8608103
0x8608103
0x8608103
0x8608103

我们指定的内核接受了微代码更新。

高级用法

你可以使用 print 命令检查微代码文件中的大多数结构,例如匹配寄存器和指令四元组。

$ zentool print --match-regs modified.bin
; Patch 0x8600141 Match Registers (22 total)
; (use --verbose to see empty slots)
	[0 ] 07CE
	[1 ] 092D
	[2 ] 1129
	[3 ] 12E9
	[4 ] 08F6
	[5 ] 0940
	[6 ] 0545
	[7 ] 08A5
	[8 ] 0BF8
	[9 ] 124D
	[10] 0526
	[11] 111A
	[12] 107D
	[13] 1026

你也可以使用 edit 更改其中的任何一个,例如:

$ zentool edit --match 0=0x1234 modified.bin

指定匹配寄存器的一般格式是 range=value,其中 range 可以是单个值 12、值列表 1,2,0x12、跨度 1,2,3-9 或特殊名称 all。 你还可以使用一些符号名称,方法是在它们前面加上 @。 例如,--match 0=@rdtsc 将尝试将第一个匹配寄存器设置为 rdtsc 的地址(如果处理器适用于此补丁)。

注意:这些符号名称存储在 data 目录中的 json 文件中。

反汇编

你还可以尝试反汇编指令四元组,如下所示:

$ zentool print --disassemble modified.bin
; Patch 0x8600141 OpQuad Disassembly (64 total)
; (use --verbose to see further details)
.quad 2, 0x04021ff3
	shr   	reg12, reg12, reg11
	mov.b  	reg10, reg10, reg17
	nop.q
	nop.q
.quad 4, 0x00221ffa
	mov   	reg9, reg9, 0x0006
	ld   	vs:[reg9+reg1], reg0
	ld.w  	reg9, 1:[reg1+reg1]
	sreg.w 	reg9, reg9, reg1
.quad 5, 0x00400001
	mov   	reg9, reg9, 0x1ff0
	sreg.w 	reg9, reg9, reg1
	mov   	reg9, reg9, 0x0305
	nop.q

补丁指令

edit 命令可用于替换指令,从而有效地创建自定义微代码补丁。 一般格式为 --insn range=oprange 可以使用与匹配寄存器相同的格式指定(参见上文)。

注意:你也可以使用语法 q3i1 来引用 quad 3, instruction 1

op 是一个数值常量,或一个符号指令。

例如:

$ zentool edit --insn q0i0="xor rax, rax, rax" modified.bin

这将把第一个四元组的第一个指令设置为 xor rax, rax, rax

还有一个特殊的快捷方式 --nop,它将使指定的指令成为空操作。

把它们放在一起,下面是一个使 fpatan 指令在 rax 中放入一个常量的命令:

$ zentool edit --nop all                  \
        --match all=0                \
        --match 0,1=@fpatan             \
        --seq 0,1=7                 \
        --insn q1i0="xor rax, rax, rax"       \
        --insn q1i1="add rax, rax, 0x1337"     \
        --hdr-revlow 0xff              \
        modified.bin

当然,你还需要签署该文件然后加载它:

$ zentool resign modified.bin
$ sudo zentool load --cpu=2 modified.bin

然后你可以尝试使用 gcc 执行 fpatan (例如 asm volatile ("fpatan" : "=a"(result)))

注意:记住使用 taskset 选择具有新微代码的内核! 例如,taskset -c 2 ./a.out

反汇编

你已经看到 print 命令包含一个反汇编程序,但是你可能会发现简单的 mcop 实用程序更方便调试。

你只需给它一个十六进制的操作码,它就会描述每一位:

$ ./mcop 382E9C1108081337
	; 382E9C1108081337 0011100000101110100111000001000100001000000010000001001100110111
	; .imm16  : 1337                         0001001100110111
	; .isig   :  0                        0
	; .mode3  :  1                       1
	; .reg0   :  0                    00000
	; .reg1   :  2                 00010
	; .reg2   :  2               00010
	; .rmod   :  1              1
	; .cc    :  0            0000
	; .ss    :  0            0
	; .size   :  3           11
	; .sizemsb :  1          1
	; .pada   :  0         00
	; .type   :  5D     01011101
	; .ext   :  0   0000
	; .class  :  7  111
	add   	rax, rax, 0x1337

此外,mcop 可以为你更改命名字段:

$ ./mcop --set type=0x41 --set reg2=2 0x382E9C1108081337

汇编

mcop 命令的逆运算是 mcas

$ ./mcas "ld ls:[rax], rsi"
	; 204BDC3188009800 0010000001001011110111000011000110001000000000001001100000000000
	; .imm   :  0                            0000000000
	; .segment :  6                          0110
	; .unkn1  :  0                         0
	; .nop3   :  1                         1
	; .unkn2  :  0                        0
	; .mode   :  0                       00
	; .wordsz  :  0                       0
	; .unknf  :  0                      0
	; .reg0   :  0                    00000
	; .reg1   :  2                 00010
	; .reg2   :  3               00011
	; .rmod   :  1              1
	; .op3   :  1              1
	; .unkn6  :  0            0000
	; .size   :  3           11
	; .width  :  1          1
	; .ldst   :  0          0
	; .unkn3  :  2F       101111
	; .unknx  :  4     100
	; .type   :  0   0000
	; .class  :  4  100
	ld   	[rax], rsi

mcas 命令也可以接受来自 stdin 的指令。

开发

有几个脚本用于添加对新处理器的支持。

TODO: 描述

作者

该工具基于 Google 硬件安全团队成员的工作构建。 特别是,Josh Eads、Matteo Rizzo、Kristoffer Janke、Eduardo Vela Nava、Tavis Ormandy、Sophie Schmieg 等人。 这项工作还受到了《高性能微处理器解剖》一书(ISBN 0818684003)以及 Ruhr-Univeritat Bochum 研究人员 Koppe 等人在论文《逆向工程 x86 处理器微代码》中的工作的影响。