固件

固件布局

基于 CSS 的固件结构用于所有平台上的 GuC 版本以及 DG1 之前的 HuC 版本。 从 DG2/MTL 开始,HuC 使用 GSC 布局代替。 CSS 固件布局如下所示

+======================================================================+
|  Firmware blob                                                       |
+===============+===============+============+============+============+
|  CSS header   |     uCode     |  RSA key   |  modulus   |  exponent  |
+===============+===============+============+============+============+
 <-header size->                 <---header size continued ----------->
 <--- size ----------------------------------------------------------->
                                 <-key size->
                                              <-mod size->
                                                           <-exp size->

固件可能具有也可能不具有模数密钥和指数数据。 标头、uCode 和 RSA 签名是驱动程序必须使用的组件。 每个组件的长度,均以 dword 为单位,可以在标头中找到。 如果 fw 中不存在模数和指数(即截断的图像),则长度值仍会出现在标头中。

驱动程序将根据以下规则执行一些基本的 fw 大小验证

  1. 标头、uCode 和 RSA 是必备组件。

  2. 所有固件组件(如果存在)都按照上面布局表中所示的顺序排列。

  3. 每个组件的长度信息可以在标头中找到,以 dword 为单位。

  4. 驱动程序不需要模数和指数密钥。 它们可能不会出现在 fw 中。 因此,驱动程序在这种情况下会加载截断的固件。

基于 GSC 的固件结构用于所有平台上的 GSC 版本以及从 DG2/MTL 开始的 HuC 版本。 较早的 HuC 版本则使用基于 CSS 的布局。 与 CSS 标头不同,GSC 标头使用目录 + 条目结构(即,存在指向由名称标识的特定标头扩展的地址数组)。 虽然标头结构相同,但某些条目特定于 GSC,而其他条目特定于 HuC。 清单标头条目(包括关于二进制文件的基本信息,如版本)始终存在,但根据二进制文件类型,其命名方式有所不同。

HuC 二进制文件以代码分区目录 (CPD) 标头开头。 我们感兴趣的驱动程序中使用的条目是

  1. “HUCP.man”:指向 HuC 的清单标头。

  2. “huc_fw”:指向 FW 代码。 在支持通过 DMA 加载和 2 步 HuC 身份验证(即 MTL+)的平台上,这是一个完整的基于 CSS 的二进制文件,而如果 GSC 正在执行加载(仅在 DG2 上发生),则此部分仅包含 uCode。

基于 GSC 的 HuC 固件布局如下所示

+================================================+
|  CPD Header                                    |
+================================================+
|  CPD entries[]                                 |
|      entry1                                    |
|      ...                                       |
|      entryX                                    |
|          "HUCP.man"                            |
|           ...                                  |
|           offset  >----------------------------|------o
|      ...                                       |      |
|      entryY                                    |      |
|          "huc_fw"                              |      |
|           ...                                  |      |
|           offset  >----------------------------|----------o
+================================================+      |   |
                                                        |   |
+================================================+      |   |
|  Manifest Header                               |<-----o   |
|      ...                                       |          |
|      FW version                                |          |
|      ...                                       |          |
+================================================+          |
                                                            |
+================================================+          |
|  FW binary                                     |<---------o
|      CSS (MTL+ only)                           |
|      uCode                                     |
|      RSA Key (MTL+ only)                       |
|      ...                                       |
+================================================+

GSC 二进制文件改为以布局标头开头,该标头包含二进制文件的各个分区的位置。 我们感兴趣的是 boot1 分区,我们可以在其中找到 BPDT 标头,后跟条目,其中一个条目指向分区的 RBE 子部分,其中包含 CPD。 GSC blob 不包含基于 CSS 的二进制文件,因此我们只需要查找清单,该清单位于 “RBEP.man” CPD 条目下。 请注意,我们无需找到实际 FW 代码在图像中的位置,因为 GSC ROM 本身将解析标头以找到它并加载它。 GSC 固件标头布局如下所示

+================================================+
|  Layout Pointers                               |
|      ...                                       |
|      Boot1 offset  >---------------------------|------o
|      ...                                       |      |
+================================================+      |
                                                        |
+================================================+      |
|  BPDT header                                   |<-----o
+================================================+
|  BPDT entries[]                                |
|      entry1                                    |
|      ...                                       |
|      entryX                                    |
|          type == GSC_RBE                       |
|          offset  >-----------------------------|------o
|      ...                                       |      |
+================================================+      |
                                                        |
+================================================+      |
|  CPD Header                                    |<-----o
+================================================+
|  CPD entries[]                                 |
|      entry1                                    |
|      ...                                       |
|      entryX                                    |
|          "RBEP.man"                            |
|           ...                                  |
|           offset  >----------------------------|------o
|      ...                                       |      |
+================================================+      |
                                                        |
+================================================+      |
| Manifest Header                                |<-----o
|  ...                                           |
|  FW version                                    |
|  ...                                           |
|  Security version                              |
|  ...                                           |
+================================================+

一次写入保护内容存储器 (WOPCM) 布局

在写入 GuC WOPCM 大小和偏移寄存器之后,WOPCM 的布局将固定,这些寄存器的值由 HuC/GuC 固件大小和一组硬件要求/限制计算和确定,如下所示

  +=========> +====================+ <== WOPCM Top
  ^           |  HW contexts RSVD  |
  |     +===> +====================+ <== GuC WOPCM Top
  |     ^     |                    |
  |     |     |                    |
  |     |     |                    |
  |    GuC    |                    |
  |   WOPCM   |                    |
  |    Size   +--------------------+
WOPCM   |     |    GuC FW RSVD     |
  |     |     +--------------------+
  |     |     |   GuC Stack RSVD   |
  |     |     +------------------- +
  |     v     |   GuC WOPCM RSVD   |
  |     +===> +====================+ <== GuC WOPCM base
  |           |     WOPCM RSVD     |
  |           +------------------- + <== HuC Firmware Top
  v           |      HuC FW        |
  +=========> +====================+ <== WOPCM Base

GuC 可访问的 WOPCM 从 GuC WOPCM 基地址开始,到 GuC WOPCM 顶部地址结束。 WOPCM 的顶部部分保留给硬件上下文(例如 RC6 上下文)。

GuC CTB Blob

我们分配单个 blob 来保存 CTB 描述符和缓冲区

偏移量

内容

大小

0x0000

H2G CTB 描述符(发送)

4K

0x0800

G2H CTB 描述符 (g2h)

0x1000

H2G CT 缓冲区(发送)

n*4K

0x1000 + n*4K

G2H CT 缓冲区 (g2h)

m*4K

每个 CT Buffer 的大小必须是 4K 的倍数。 我们预计在任何时候都不会有太多的消息在传输中,除非我们使用 GuC 提交。 在这种情况下,每个请求至少需要 2 个 dword,这给我们提供了最多 256 个排队的请求。 希望这有足够的空间来避免驱动程序上的反压。 我们增加了接收缓冲区的大小(相对于发送缓冲区)以确保 G2H 响应 CTB 具有着陆点。

除了提交之外,G2H 缓冲区还需要能够容纳足够的空间来处理可恢复的页面错误通知。 页面错误的数量是中断驱动的,并且可能与可用的计算资源数量一样多。 但是,这些的大部分实际工作都在单独的页面错误工作线程中。 因此,我们只需要确保队列有足够的空间来处理所有的提交和响应,以及一个用于传入页面错误的额外缓冲区。

GuC 功耗节省 (PC)

GuC 功耗节省 (PC) 支持多种功能,以便在启用 GuC 提交时,以最有效和性能最高的方式使用 GT,包括频率管理、Render-C 状态管理以及各种功率平衡算法。

单循环功耗节省 (SLPC) 是 GuC 固件中连接的功耗节省功能的套件的名称。 固件公开了一个编程接口,供主机控制 SLPC。

PCIe Gen5 限制

独立显卡的默认链路速度由存储在其闪存中的配置参数决定,这些参数可以通过用户发起的固件更新来覆盖。 已经观察到,配置为将 PCIe Gen5 作为其默认链路速度的设备可能会遇到链路质量问题,这是由于主机或主板的限制造成的,并且在 Gen5 下面临不稳定链路时可能不得不将其链路自动降级为 PCIe Gen4 速度,这使得此类设置上的固件更新相当冒险。 需要确保设备能够在推送将 PCIe Gen5 作为默认配置的固件映像之前,将其链路自动降级为 PCIe Gen4 速度。 这可以通过读取 auto_link_downgrade_capable sysfs 条目来完成,该条目将表示设备是否能够将其链路自动降级为 PCIe Gen4 速度,并带有布尔输出值 01,分别表示 不具备能力具备能力

$ cat /sys/bus/pci/devices/<bdf>/auto_link_downgrade_capable

在自动链路降级不具备能力的设备上推送将 PCIe Gen5 作为默认配置的固件映像,并且由于主机或主板的限制而面临链路不稳定,可能会导致驱动程序无法绑定到该设备,从而无法进行进一步的固件更新,只能求助于 RMA 作为最后的手段。

自动链路降级具备能力的设备的链路降级状态可以通过 auto_link_downgrade_status sysfs 条目获得,并带有布尔输出值 01,其中 0 表示链路训练期间不需要自动降级(这是最佳情况),而 1 表示该设备由于 Gen5 链路不稳定而将其链路自动降级为 PCIe Gen4 速度。

$ cat /sys/bus/pci/devices/<bdf>/auto_link_downgrade_status

内部 API

待办事项