麒麟版 V10 海光 10G 板载网卡驱动排查记录
状态:已解决,重启后网卡可正常使用 记录日期:2026-08-05
一、环境信息
| 项目 | 内容 |
|---|---|
| 整机 | 联想(hostname:lenovo-pc),海光平台 |
| 操作系统 | 银河麒麟桌面操作系统V10 |
KYLIN_RELEASE_ID | 020 |
| 系统基线 | 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 ID | 1d94: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中没有任何eth、firmware 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 modules无in 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 流程。
补充判断依据:
ccp、k10temp、i2c_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_id4.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 68即mov 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)。
六、经验小结
lspci -k的输出形态是快速分流的关键判据,可一眼区分"模块缺失"、"模块未绑定"、"已绑定但配置问题"三种情况,避免一上来就盲目编译驱动。国产化平台常见问题模式:驱动代码是通用的,缺的只是厂商 PCI ID。海光/兆芯等基于授权架构的 CPU,其外设往往可直接复用上游驱动,只需补充 ID 匹配项。
交叉验证技巧:检查
modules.alias中同厂商其他设备是否已收录。本例中ccp、k10temp均有1d94条目,佐证了内核已做海光适配、xgbe 系遗漏,从而对"仅补 ID 即可"建立了信心。使用
new_id时务必确认驱动是否依赖driver_data。盲目省略该字段可能触发内核 oops。操作前应先存盘。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形式成功加载,说明当前未处于强制签名状态。
