三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

麒麟版 V10 海光 10G 板载网卡驱动排查记录

麒麟版 V10 海光 10G 板载网卡驱动排查记录

状态:已解决,重启后网卡可正常使用 记录日期:2026-08-05


一、环境信息

项目内容
整机联想(hostname:lenovo-pc),海光平台
操作系统银河麒麟桌面操作系统V10
KYLIN_RELEASE_ID020
系统基线ID_LIKE=debian
内核版本5.4.18-87.76-generic
架构x86_64
网卡海光(Chengdu Haiguang IC Design)集成 10 Gb Ethernet Controller ×4
PCI 地址06:00.4/06:00.5/06:00.6/06:00.7
PCI ID1d94:1458(Port 0/1)、1d94:1459(Port 2/3)
板载标识DeviceName: LOM 1

二、故障现象

系统安装完成后无任何有线网络接口,ip link show仅有lo

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 ...

dmesg没有任何ethfirmware failed相关报错,说明并非固件缺失,而是驱动根本没有被触发。


三、排查过程

3.1 确认硬件与驱动状态

lspci -nn | grep -iE 'ethernet|network'

输出显示四个海光 10G 控制器,PCI ID 为1d94:1458/1d94:1459

海光 CPU 基于 AMD 授权架构,其集成网卡对应 AMD 的amd-xgbe驱动(AMD 侧 PCI ID 为1022:1458/1022:1459)。

lspci -k -s 06:00.4

关键输出:

06:00.4 Ethernet controller: Chengdu Haiguang IC Design Co., Ltd. 10 Gb Ethernet Controller Port 0/Port1 DeviceName: LOM 1 Subsystem: ...

既没有Kernel driver in use,也没有Kernel modules

这是本次定位的关键判据:

  • driver in use→ 驱动已绑定,问题在配置层

  • 只有Kernel modulesin use→ 模块存在但未绑定

  • 两者都无 → PCI ID 匹配表里根本没有这个设备

3.2 确认驱动模块本身存在

modinfo amd-xgbe | head -5 ls /lib/modules/$(uname -r)/kernel/drivers/net/ethernet/amd/xgbe/

结果:

filename: /lib/modules/5.4.18-87.76-generic/kernel/drivers/net/ethernet/amd/xgbe/amd-xgbe.ko description: AMD 10 Gigabit Ethernet Driver version: 1.0.3 license: Dual BSD/GPL

模块文件存在且完好。说明不需要重新编译驱动本体。

3.3 定位根因:PCI ID 匹配表缺失

grep -i "v0000102[2]d00001458" /lib/modules/$(uname -r)/modules.alias grep -i "1d94" /lib/modules/$(uname -r)/modules.alias

结果:

# AMD 的 ID 在 alias pci:v00001022d00001458sv*sd*bc*sc*i* amd_xgbe ​ # 海光的 ID 里,其他驱动都有,唯独没有 xgbe alias pci:v00001D94d0000790Bsv*sd*bc*sc*i* i2c_piix4 alias pci:v00001D94d00001463sv*sd*bc*sc*i* k10temp alias pci:v00001D94d00001486sv*sd*bc*sc*i* ccp alias pci:v00001D94d00001468sv*sd*bc*sc*i* ccp alias pci:v00001D94d00001456sv*sd*bc*sc*i* ccp alias pci:v00001D94d00001537sv*sd*bc*sc*i* ccp

根本原因确认:

amd-xgbe驱动的xgbe_pci_table[]中只收录了 AMD 厂商 ID0x1022,未收录海光厂商 ID0x1d94。内核 PCI 子系统按 ID 匹配失败,因此设备永远不会触发amd-xgbe的 probe 流程。

补充判断依据:ccpk10tempi2c_piix4均已收录1d94系列 ID,说明该内核确实做过海光适配,只是 xgbe 被遗漏。这提示大概率只是 ID 缺失,而非需要额外的板级适配代码 —— 后续验证证实了这一判断。


四、解决方案

4.1 关键技术点:new_id必须携带driver_data

内核提供/sys/bus/pci/drivers/<driver>/new_id接口,可在运行时向驱动动态注册 PCI ID。

new_id的字段顺序(全部按十六进制解析):

vendor device subvendor subdevice class class_mask driver_data

⚠️ 重要陷阱:

amd-xgbe的 probe 函数会直接解引用id->driver_data,该字段指向版本描述结构体xgbe_v2a/xgbe_v2b。若使用new_id时省略该字段(默认为 0),probe 会发生 NULL 指针解引用,直接导致内核 oops

因此必须从/proc/kallsyms取出符号地址一并传入。

4.2 手工验证步骤

# 1. 加载模块 sudo modprobe amd-xgbe # 2. 确认 sysfs 下驱动目录名(注意:alias 中是下划线 amd_xgbe,sysfs 中是连字符 amd-xgbe) ls /sys/bus/pci/drivers/ | grep -i xgbe # 输出: amd-xgbe # 3. 放开内核符号地址限制并取符号 sudo sysctl -w kernel.kptr_restrict=0 V2A=$(sudo awk '$3=="xgbe_v2a"{print $1}' /proc/kallsyms) V2B=$(sudo awk '$3=="xgbe_v2b"{print $1}' /proc/kallsyms) echo "V2A=$V2A V2B=$V2B" # 输出: V2A=ffffffffc1688900 V2B=ffffffffc16888c0 # ★ 必须为非零十六进制地址,若为空或全 0,禁止继续执行 # 4. 注册 PCI ID echo "1d94 1458 ffffffff ffffffff 0 0 $V2A" | sudo tee /sys/bus/pci/drivers/amd-xgbe/new_id echo "1d94 1459 ffffffff ffffffff 0 0 $V2B" | sudo tee /sys/bus/pci/drivers/amd-xgbe/new_id

4.3 验证结果

dmesg输出:

[1957.251814] libphy: amd-xgbe-mii: probed [1957.252339] amd-xgbe 0000:06:00.4 eth0: net device enabled [1957.252406] amd-xgbe 0000:06:00.5: enabling device (0140 -> 0142) [1957.253100] amd-xgbe 0000:06:00.5 eth1: net device enabled [1957.258274] amd-xgbe 0000:06:00.5 eno2: renamed from eth1 [1957.291714] amd-xgbe 0000:06:00.4 eno1: renamed from eth0 [1960.542990] amd-xgbe 0000:06:00.6 eth0: net device enabled [1960.543782] amd-xgbe 0000:06:00.7 eth1: net device enabled [1960.547106] amd-xgbe 0000:06:00.7 eno4: renamed from eth1 [1960.575571] amd-xgbe 0000:06:00.6 eno3: renamed from eth0 [1964.746361] amd-xgbe 0000:06:00.6 eno3: Link is Up - 1Gbps/Full - flow control rx/tx

ip link show

2: eno1: <BROADCAST,MULTICAST> ... link/ether e8:61:1a:6e:36:1d 3: eno2: <BROADCAST,MULTICAST> ... link/ether e8:61:1a:6e:36:1e 4: eno3: <BROADCAST,MULTICAST> ... link/ether e8:61:1a:6e:36:1f 5: eno4: <BROADCAST,MULTICAST> ... link/ether e8:61:1a:6e:36:20

lspci -k -s 06:00.4新增:

Kernel driver in use: amd-xgbe

四个网口全部识别,MAC 地址 OUIe8:61:1a为联想,驱动绑定成功。

4.4 开机固化

new_id为运行时注册,重启后失效。通过 systemd 服务在 NetworkManager 启动之前完成绑定。

绑定脚本/usr/local/sbin/hygon-xgbe-bind.sh

#!/bin/bash modprobe amd-xgbe # 已绑定则直接退出(防重复执行) [ -e /sys/bus/pci/drivers/amd-xgbe/0000:06:00.4 ] && exit 0 R=$(sysctl -n kernel.kptr_restrict); sysctl -qw kernel.kptr_restrict=0 A=$(awk '$3=="xgbe_v2a"{print $1}' /proc/kallsyms) B=$(awk '$3=="xgbe_v2b"{print $1}' /proc/kallsyms) sysctl -qw kernel.kptr_restrict=$R # 空值 / 全零保护,避免 probe 时 NULL 解引用 [ -n "$A" ] && [ "$A" != "0000000000000000" ] && \ echo "1d94 1458 ffffffff ffffffff 0 0 $A" > /sys/bus/pci/drivers/amd-xgbe/new_id [ -n "$B" ] && [ "$B" != "0000000000000000" ] && \ echo "1d94 1459 ffffffff ffffffff 0 0 $B" > /sys/bus/pci/drivers/amd-xgbe/new_id exit 0

服务单元/etc/systemd/system/hygon-xgbe.service

[Unit] Description=Bind Hygon 10G NIC to amd-xgbe DefaultDependencies=no After=sysinit.target Before=network-pre.target NetworkManager.service Wants=network-pre.target [Service] Type=oneshot RemainAfterExit=yes ExecStart=/usr/local/sbin/hygon-xgbe-bind.sh [Install] WantedBy=multi-user.target EOF

启用:

sudo chmod +x /usr/local/sbin/hygon-xgbe-bind.sh sudo systemctl daemon-reload sudo systemctl enable hygon-xgbe.service sudo sysctl -w kernel.kptr_restrict=1 # 恢复安全设置

Before=NetworkManager.service是刻意设计:既保证开机即有网,也顺带规避了下文的热添加崩溃问题。


五、过程中遇到的次生问题

5.1 NetworkManager 段错误

手工执行new_id后,dmesg 出现:

[1964.764505] NetworkManager[923]: segfault at 68 ip 0000557398eb1ef7 sp 00007ffc16063ba0 error 4 in NetworkManager[557398d2c000+1df000] Code: ... <48> 8b 5f 68 ...

反汇编48 8b 5f 68mov rbx,[rdi+0x68]rdi接近 NULL。

判断:NetworkManager 在处理"运行中途热添加的新网络设备"时踩了空指针。因 NM 已启动完成,设备才凭空出现,某个初始化路径被跳过。

影响:NM 崩溃后无人管理接口,四个口随即全部Link is Down

规避:通过 systemd 服务让设备在 NM 启动前就位,开机流程不会走到该热添加路径。经重启验证,问题未复现。

5.2 应急联网方式(NM 不可用时)

在 NM 故障期间可绕开它直接配置:

sudo ip link set eno3 up sudo dhclient -v eno3 # 或静态配置 sudo ip addr add 192.168.1.100/24 dev eno3 sudo ip route add default via 192.168.1.1 echo "nameserver 114.114.114.114" | sudo tee /etc/resolv.conf

Kylin V10 为 Debian 系,也可使用 ifupdown(/etc/network/interfaces)。


六、经验小结

  1. lspci -k的输出形态是快速分流的关键判据,可一眼区分"模块缺失"、"模块未绑定"、"已绑定但配置问题"三种情况,避免一上来就盲目编译驱动。

  2. 国产化平台常见问题模式:驱动代码是通用的,缺的只是厂商 PCI ID。海光/兆芯等基于授权架构的 CPU,其外设往往可直接复用上游驱动,只需补充 ID 匹配项。

  3. 交叉验证技巧:检查modules.alias中同厂商其他设备是否已收录。本例中ccpk10temp均有1d94条目,佐证了内核已做海光适配、xgbe 系遗漏,从而对"仅补 ID 即可"建立了信心。

  4. 使用new_id时务必确认驱动是否依赖driver_data盲目省略该字段可能触发内核 oops。操作前应先存盘。

  5. dmesg中的Link is Up - 1Gbps/Full是物理链路层的可靠证据,可据此排除线缆、接口形态(RJ45 / SFP+)等问题。


七、后续待办

事项说明优先级
向厂商反馈联想售后 + 麒麟软件技术支持,报1d94:1458/1459+KYLIN_RELEASE_ID 020+ 内核5.4.18-87.76,索取正式驱动适配补丁
反馈 NM segfault一并提交 NetworkManager 热添加设备时的空指针崩溃问题
内核升级后复验当前方案依赖运行时new_id。虽然脚本每次动态取符号地址(不受地址变动影响),但内核大版本升级后仍需验证服务是否生效
考虑重编模块更彻底的方案是在xgbe_pci_table[]中补充两条 ID 后重新编译amd-xgbe.ko,需linux-headers-5.4.18-87.76-generic严格同版本

合规提醒

  • 本机为国防版系统,若属涉密内网设备,自建 systemd 服务、加载非原厂配置、修改kernel.kptr_restrict等操作可能需向保密管理员报备。

  • 长期方案应以厂商官方适配包为准,自行编译的内核模块可能不符合相关管理规定。

  • 国防版系统的 KySec 安全机制可能拦截未签名内核模块。本机 dmesg 中 nvidia 模块以module verification failed ... tainting kernel形式成功加载,说明当前未处于强制签名状态。

← 返回列表