USB4 和 Thunderbolt¶
USB4 是基于 Thunderbolt 3 协议的公共规范,除其他外,在寄存器级别存在一些差异。连接管理器是在主机路由器(主机控制器)上运行的实体,负责枚举路由器和建立隧道。连接管理器可以在固件或软件中实现。通常,PC 配备用于 Thunderbolt 3 和早期支持 USB4 的系统的固件连接管理器。另一方面,Apple 系统使用软件连接管理器,并且后来的 USB4 兼容设备也遵循该方法。
Linux Thunderbolt 驱动程序同时支持这两种方式,并且可以在运行时检测要使用哪种连接管理器实现。为了安全起见,Linux 中的软件连接管理器还宣布安全级别为 user
,这意味着默认情况下禁用 PCIe 隧道。以下文档适用于两种实现,但软件连接管理器仅支持 user
安全级别,并且应附带基于 IOMMU 的 DMA 保护。
安全级别以及如何使用它们¶
此处提供的接口并非供最终用户使用。相反,应该有一个用户空间工具来处理所有底层细节,维护授权设备的数据库,并提示用户进行新连接。
有关 Thunderbolt 设备的 sysfs 接口的更多详细信息,请参见 Documentation/ABI/testing/sysfs-bus-thunderbolt
。
那些只想连接任何设备而无需任何手动操作的用户可以在 /etc/udev/rules.d/99-local.rules
中添加以下行
ACTION=="add", SUBSYSTEM=="thunderbolt", ATTR{authorized}=="0", ATTR{authorized}="1"
这将自动授权所有出现的设备。但是,请记住,这会绕过安全级别,并使系统容易受到 DMA 攻击。
从 Intel Falcon Ridge Thunderbolt 控制器开始,有 4 个可用的安全级别。Intel Titan Ridge 添加了一个额外的安全级别 (usbonly)。这些的原因是,所连接的设备可以是 DMA 主设备,从而读取主机内存的内容,而 CPU 和 OS 不知情。可以通过设置 IOMMU 来防止这种情况,但由于各种原因,它并非总是可用。
一些 USB4 系统具有禁用 PCIe 隧道的 BIOS 设置。这被视为另一个安全级别 (nopcie)。
安全级别如下:
- none
所有设备都由固件自动连接。无需用户批准。在 BIOS 设置中,这通常称为传统模式。
- user
将询问用户是否允许连接设备。基于通过
/sys/bus/thunderbolt/devices
可用的设备识别信息,用户可以做出决定。在 BIOS 设置中,这通常称为唯一 ID。- secure
将询问用户是否允许连接设备。除了 UUID 之外,如果设备支持安全连接,还会向其发送一个挑战,该挑战应与基于写入
key
sysfs 属性的随机密钥的预期挑战相匹配。在 BIOS 设置中,这通常称为一次性保存密钥。- dponly
固件自动为显示端口和 USB 创建隧道。不执行 PCIe 隧道。在 BIOS 设置中,这通常称为仅显示端口。
- usbonly
固件自动为坞站中的 USB 控制器和显示端口创建隧道。删除坞站的所有 PCIe 下行链路。
- nopcie
BIOS 禁止/禁用 PCIe 隧道。在某些 USB4 系统中可用。
当前的安全级别可以从 /sys/bus/thunderbolt/devices/domainX/security
中读取,其中 domainX
是主机控制器管理的 Thunderbolt 域。每个 Thunderbolt 主机控制器通常有一个域。
如果安全级别读取为 user
或 secure
,则必须先由用户授权连接的设备,然后才能创建 PCIe 隧道(例如,出现 PCIe 设备)。
插入的每个 Thunderbolt 设备都将出现在 sysfs 中的 /sys/bus/thunderbolt/devices
下。设备目录包含可用于标识特定设备的信息,包括其名称和 UUID。
使用 IOMMU 的 DMA 保护¶
2018 年及以后配备 Thunderbolt 端口的最新系统可能原生支持 IOMMU。这意味着 Thunderbolt 安全由 IOMMU 处理,因此连接的设备无法访问驱动程序为其分配的内存区域之外的内存区域。当 Linux 在此类系统上运行时,如果用户尚未启用 IOMMU,它会自动启用 IOMMU。 可以通过读取 /sys/bus/thunderbolt/devices/domainX/iommu_dma_protection
属性中的 1
来识别这些系统。
在这种情况下,驱动程序不做任何特殊处理,但是由于 DMA 保护由 IOMMU 处理,因此安全级别(如果已设置)是多余的。因此,某些系统在出厂时将安全级别设置为 none
。其他系统将安全级别设置为 user
,以便支持降级到旧版操作系统,因此希望在启用 IOMMU DMA 保护时自动授权设备的用户可以使用以下 udev
规则
ACTION=="add", SUBSYSTEM=="thunderbolt", ATTRS{iommu_dma_protection}=="1", ATTR{authorized}=="0", ATTR{authorized}="1"
升级 Thunderbolt 设备、主机或中继器上的 NVM¶
由于大部分功能是在主机控制器或设备上运行的固件中处理的,因此重要的是,固件可以升级到最新版本,以便修复其中的潜在错误。通常,OEM 会在其支持站点上提供此固件。
还有一个中心站点,其中包含一些机器的固件下载链接
在升级设备、主机或中继器上的固件之前,请确保它是合适的升级。否则可能会导致设备处于无法正常使用的状态,而没有特殊工具!
Apple Mac 上不支持主机 NVM 升级。
下载 NVM 映像后,您需要插入一个 Thunderbolt 设备,以便主机控制器出现。连接哪个设备并不重要(除非您要升级设备上的 NVM - 那么您需要连接该特定设备)。
请注意,您的系统可能提供 OEM 特定的控制器上电方法(“强制上电”),在这种情况下,无需插入 Thunderbolt 设备。
之后,我们可以将固件写入主机或设备的 NVM 的非活动部分。例如,以下是如何升级 Intel NUC6i7KYK (Skull Canyon) Thunderbolt 控制器 NVM 的方法
# dd if=KYK_TBT_FW_0018.bin of=/sys/bus/thunderbolt/devices/0-0/nvm_non_active0/nvmem
操作完成后,我们可以按如下方式触发 NVM 身份验证和升级过程
# echo 1 > /sys/bus/thunderbolt/devices/0-0/nvm_authenticate
如果没有返回错误,则主机控制器会在短时间内消失。一旦它恢复,驱动程序会注意到它并启动完全断电循环。一段时间后,主机控制器再次出现,此时它应该是完全可用的。
我们可以通过运行以下命令来验证新的 NVM 固件是否已激活
# cat /sys/bus/thunderbolt/devices/0-0/nvm_authenticate
0x0
# cat /sys/bus/thunderbolt/devices/0-0/nvm_version
18.0
如果 nvm_authenticate
包含 0x0 以外的任何内容,则表示上次身份验证周期的错误代码,这意味着 NVM 映像的身份验证失败。
请注意,NVMem 设备 nvm_activeN
和 nvm_non_activeN
的名称取决于它们在 NVMem 子系统中注册的顺序。名称中的 N 是 NVMem 子系统添加的标识符。
在没有电缆连接的情况下升级板载中继器 NVM¶
如果平台支持,即使 USB4 端口上未连接任何设备,也可能可以升级中继器 NVM 固件。在这种情况下,usb4_portX
设备具有两个特殊属性:offline
和 rescan
。升级固件的方法是首先将 USB4 端口置于离线模式
# echo 1 > /sys/bus/thunderbolt/devices/0-0/usb4_port1/offline
此步骤确保端口不响应任何热插拔事件,并确保中继器已上电。下一步是扫描中继器
# echo 1 > /sys/bus/thunderbolt/devices/0-0/usb4_port1/rescan
这会枚举并添加板载中继器。现在,可以像连接电缆一样升级中继器 NVM(请参见上一节)。但是,中继器不会断开连接(因为我们处于离线模式),因此在将 1
写入 nvm_authenticate
后,应等待 5 秒或更长时间,然后再重新运行扫描
# echo 1 > /sys/bus/thunderbolt/devices/0-0/usb4_port1/rescan
如果一切顺利,此时端口可以恢复到功能状态
# echo 0 > /sys/bus/thunderbolt/devices/0-0/usb4_port1/offline
当主机控制器处于安全模式时升级 NVM¶
如果现有 NVM 未正确身份验证(或丢失),则主机控制器将进入安全模式,这意味着唯一可用的功能是刷写新的 NVM 映像。在此模式下,读取 nvm_version
会失败并返回 ENODATA
,并且设备识别信息丢失。
要从此模式恢复,需要以与上一章中相同的方式将有效的 NVM 映像刷写到主机控制器。
通过 Thunderbolt 电缆进行网络连接¶
Thunderbolt 技术允许通过 Thunderbolt 电缆连接的两个主机之间进行软件通信。
可以通过 Thunderbolt 链路传输任何类型的流量,但目前我们仅支持 Apple ThunderboltIP 协议。
如果另一台主机运行的是 Windows 或 macOS,您只需在两台主机之间连接一根 Thunderbolt 电缆即可;thunderbolt-net
驱动程序会自动加载。如果另一台主机也是 Linux,则应在一台主机上手动加载 thunderbolt-net
(哪一台主机都可以)
# modprobe thunderbolt-net
这会自动触发另一台主机上的模块加载。如果驱动程序内置到内核映像中,则无需执行任何操作。
驱动程序将为每个 Thunderbolt 端口创建一个虚拟以太网接口,其名称类似于 thunderbolt0
等。从这一点开始,您可以使用标准用户空间工具(如 ifconfig
)来配置接口,或者让您的 GUI 自动处理它。
强制上电¶
许多 OEM 都提供了一种方法,即使未连接任何设备,也可以使用该方法强制 Thunderbolt 控制器的电源进入“开启”状态。如果您的机器支持,则可以通过 WMI 总线公开此功能,并带有名为“force_power”的 sysfs 属性。
- 例如,intel-wmi-thunderbolt 驱动程序在以下位置公开此属性
/sys/bus/wmi/devices/86CCFD48-205E-4A77-9C48-2021CBEDE341/force_power
要强制上电,请将 1 写入此属性文件。要禁用强制上电,请将 0 写入此属性文件。
注意:目前无法查询平台的强制上电状态。