Ascend 310 NPU 驱动适配 Linux Kernel 6.12.43 修复记录
概述
目前华为官方的提供的所有AI卡驱动都未支持高版本Linux内核(6.8以上)博主花了大量时间去研究华为驱动源码,最终功夫不负有心人成功将Atlas300I卡以及Atlas300I Pro的驱动适配到了Linux-6.12.43内核版本,按道理来讲6.8以上的版本都可以进行驱动包安装,适配工作不易请大家点个关注,在此小编谢谢大家的支持了,编译好的驱动包我也会开源,有需要的小伙伴自行获取即可。
资源获取
修复清单
1. do_exit() / complete_and_exit() → kthread_complete_and_exit()
原因 :Kernel 6.12 移除了 do_exit() 和 complete_and_exit() 的导出符号,仅保留 kthread_complete_and_exit()。
修改文件:
| 文件 | 修改内容 |
|---|---|
driver/kernel/drv_davinci_intf_host/davinci_intf_init.c |
在 #include <linux/version.h> 之后添加条件编译宏,将 do_exit(0) 替换为 kthread_complete_and_exit(NULL, 0) |
driver/kernel/drv_devmng/drv_devmng_host/ascend910/devdrv_manager.c |
同上 |
driver/kernel/dms/status/dms_osc_freq.c |
同上 |
修改方式 (以 davinci_intf_init.c 为例):
c
// 在 #include <linux/version.h> 之后添加:
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,0,0)
#ifndef do_exit
#define do_exit(x) do { kthread_complete_and_exit(NULL, x); } while(0)
#endif
#endif
同时将源文件中的 do_exit(0); 调用替换为 kthread_complete_and_exit(NULL, 0);。
2. profile_event_register() / profile_event_unregister() 移除
原因 :Kernel 6.12 完全移除了 profile_event_register 和 profile_event_unregister 及 PROFILE_TASK_EXIT。
修改方式一 --- Makefile_mini 全局宏替换:
makefile
# driver/kernel/Makefile_mini 中添加:
ccflags-y += -Dprofile_event_register\(a,b\)=0
ccflags-y += -Dprofile_event_unregister\(a,b\)=0
ccflags-y += -DPROFILE_TASK_EXIT=0
修改方式二 --- 源文件级别替换(Makefile 宏对部分编译单元不生效时需要):
| 文件 | 修改内容 |
|---|---|
driver/kernel/drv_devmng/drv_devmng_host/ascend910/devdrv_manager.c |
profile_event_register(...) → ret = 0; |
driver/kernel/dbl/uda/uda_access.c |
profile_event_register/unregister(...) → (void)0; |
driver/kernel/ts_drv_common/tsdrv_nvme/logic/logic_cq.c |
同上 |
driver/kernel/soft_fault/soft_fault.c |
同上 |
driver/kernel/dms/core/dms_init.c |
同上 |
3. pte_offset_map() → 内联宏替换
原因 :Kernel 6.12 中 pte_offset_map() 变为 static inline 函数,内部调用未导出的 __pte_offset_map() 外部函数。由于 pte_offset_map() 在 #include <linux/mm.h> 时已展开为内联调用,在 include 之后定义 __pte_offset_map 宏无效 ,必须 #undef pte_offset_map 并重新定义。
修改文件 (3 个 devmm_dev.c):
| 文件 |
|---|
driver/kernel/svmdrv/common/devmm_dev.c |
driver/kernel/svmdrv/pmaster/devmm_dev.c |
driver/kernel/svmdrv/pmaster/common/devmm_dev.c |
修改方式 :在所有 #include 之后、第一个非 include 行之前添加:
c
#if LINUX_VERSION_CODE >= KERNEL_VERSION(6,0,0)
/* pte_offset_map() in kernel 6.12 calls unexported __pte_offset_map(); override it */
#undef pte_offset_map
#define pte_offset_map(pmd, addr) ((pte_t *)pmd_page_vaddr(*(pmd)) + pte_index(addr))
#endif
注意 :此修复块必须放在 #ifdef CFG_FEATURE_VFIO 块之外,确保所有编译路径都能生效。
4. PDE_DATA() → pde_data()
原因 :Kernel 5.17+ 移除了 PDE_DATA() 宏,替换为 pde_data() 内联函数。
修改方式一 --- Makefile_mini 全局宏(仅对部分模块生效,不推荐作为唯一方案):
makefile
ccflags-y += -DPDE_DATA\(inode\)=pde_data\(inode\)
修改方式二 --- 源文件级别替换(推荐,更可靠):
在以下 11 个文件的 #include 区域之后添加:
c
#ifndef PDE_DATA
#define PDE_DATA(inode) pde_data(inode)
#endif
修改文件清单:
| 文件 |
|---|
driver/kernel/event_sched/comm/soft_sched/irq_sched/esched_table_proc_fs.c |
driver/kernel/drv_devmng/drv_devmng_host/ascend310/drv_log.c |
driver/kernel/drv_devmng/drv_devmng_host/ascend910/drv_log.c |
driver/kernel/ts_drv_common/tsdrv_dev/tsdrv_id_config_dfx.c |
driver/kernel/ts_drv_common/tsdrv_dev/tsdrv_ctx_dfx.c |
driver/kernel/ts_drv_common/tsdrv_dev/tsdrv_event_id_dfx.c |
driver/kernel/queue/common/queue_proc_fs.c |
driver/kernel/svmdrv/pmaster/comm/svm_master_proc_fs.c |
driver/kernel/svmdrv/pmaster/common/svm_proc_fs.c |
driver/kernel/svmdrv/pmaster/svm_shmem_procfs.c |
driver/kernel/svmdrv/common/svm_proc_fs.c |
注意 :使用 #ifndef PDE_DATA 而非 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5,17,0),因为部分文件未包含 <linux/version.h>,使用版本号检查会导致编译错误。
5. follow_pfn() → follow_pfnmap_start/end()
原因 :Kernel 6.12 移除了 follow_pfn() 导出符号,替换为 follow_pfnmap_start() / follow_pfnmap_end() API。
修改文件(已在华为官方代码中修复):
| 文件 | 修改内容 |
|---|---|
driver/kernel/dev_inc_open/inc/devdrv_interface.h |
提供兼容的内联 follow_pfn() 实现,内部调用 follow_pfnmap_start/end |
driver/kernel/dev_inc/inc/devdrv_interface.h |
同上 |
6. .ko.xz 解压 & __versions 段剥离
原因:
- Kernel 6.12 DKMS 编译后可能产生
.ko.xz压缩格式,需要解压后才能操作 - Intewell 内核未启用
CONFIG_MODVERSIONS,.ko中的__versions段 CRC 校验会失败,需用objcopy移除
修改文件 :driver/script/run_driver_install.sh
修改内容 :在 driver_dkms_insmod() 函数(约 line 612)中添加:
bash
# Decompress .ko.xz files and strip __versions (needed for Intewell kernel 6.12)
for __koxz in ${sys_path}/*.ko.xz; do
[ -f "$__koxz" ] || continue
log "[INFO]Decompressing ${__koxz##*/}"
unxz "$__koxz" 2>/dev/null
__ko="${__koxz%.xz}"
[ -f "$__ko" ] && objcopy --remove-section=__versions "$__ko" 2>/dev/null
done
for __ko in ${sys_path}/*.ko; do
[ -f "$__ko" ] && objcopy --remove-section=__versions "$__ko" 2>/dev/null
done
depmod -a > /dev/null 2>&1
7. grep 警告修复
原因 :makeself-header.sh 中 grep -o -E "\-\-[^ ]+" 导致 grep 报错 "多余的 " 和 "unrecognized option"。
修改文件 :driver/script/makeself-header.sh(line 354)
修改:
bash
# 修改前:
grep -o -E "\-\-[^ ]+"
# 修改后:
grep -o -E -e '--[^ ]*'
使用 -e 标志显式传递模式,避免 grep 将 --[^ ]* 解析为选项。
8. GCC 内置头文件路径
原因 :内核编译使用 -nostdinc,导致 GCC 内置头文件(stdarg.h, stdbool.h 等)找不到。
修改文件 :driver/kernel/Makefile_mini
makefile
ccflags-y += -isystem /usr/lib/gcc/aarch64-linux-gnu/12/include
ccflags-y += -isystem /usr/lib/gcc/aarch64-openEuler-linux/12/include
9. 警告抑制
原因 :Kernel 6.12 头文件变化导致原有代码触发大量 -Werror 警告。
修改文件 :driver/kernel/Makefile_mini
makefile
export CUSTOM_OS_CCFLAGS := -Wno-error=missing-prototypes -Wno-undef -Wall -Werror \
-Wno-error=vla -funsigned-char -Wno-error=implicit-function-declaration \
-Wno-error=unused-variable -Wno-error=return-type
CANN 层面修复(非驱动)
10. Ascend310.ini 平台配置缺失
原因 :CANN 8.3.RC1 将 Ascend310.ini 重命名为 Ascend031.ini,atc 使用 --soc_version=Ascend310 时找不到配置文件。
修复:创建符号链接:
bash
cd /usr/local/Ascend/ascend-toolkit/latest/aarch64-linux/data/platform_config/
ln -sf Ascend031.ini Ascend310.ini
# 如有其他 platform_config 目录也需处理:
cd /usr/local/Ascend/ascend-toolkit/8.3.RC1/compiler/data/platform_config/
ln -sf Ascend031.ini Ascend310.ini
11. Python _ctypes 模块缺失
原因 :自定义编译的 Python 3.12 编译时未正确链接 libffi-devel,导致 _ctypes 模块未构建。
修复 :重新全量编译 Python 3.12,确保安装了 libffi-devel、xz-devel 等开发库,并设置正确的编译环境变量。
完整修改文件清单
| # | 文件路径 | 修复内容 |
|---|---|---|
| 1 | driver/kernel/Makefile_mini |
GCC include 路径、profile_event 宏、PDE_DATA 宏、警告抑制 |
| 2 | driver/kernel/drv_davinci_intf_host/davinci_intf_init.c |
do_exit → kthread_complete_and_exit |
| 3 | driver/kernel/drv_devmng/drv_devmng_host/ascend910/devdrv_manager.c |
do_exit、profile_event 替换 |
| 4 | driver/kernel/dms/status/dms_osc_freq.c |
do_exit → kthread_complete_and_exit |
| 5 | driver/kernel/dbl/uda/uda_access.c |
profile_event 替换 |
| 6 | driver/kernel/ts_drv_common/tsdrv_nvme/logic/logic_cq.c |
profile_event 替换 |
| 7 | driver/kernel/soft_fault/soft_fault.c |
profile_event 替换 |
| 8 | driver/kernel/dms/core/dms_init.c |
profile_event 替换 |
| 9 | driver/kernel/svmdrv/common/devmm_dev.c |
pte_offset_map 重定义 |
| 10 | driver/kernel/svmdrv/pmaster/devmm_dev.c |
pte_offset_map 重定义 |
| 11 | driver/kernel/svmdrv/pmaster/common/devmm_dev.c |
pte_offset_map 重定义 |
| 12 | driver/kernel/event_sched/comm/soft_sched/irq_sched/esched_table_proc_fs.c |
PDE_DATA → pde_data |
| 13 | driver/kernel/drv_devmng/drv_devmng_host/ascend310/drv_log.c |
PDE_DATA → pde_data |
| 14 | driver/kernel/drv_devmng/drv_devmng_host/ascend910/drv_log.c |
PDE_DATA → pde_data |
| 15 | driver/kernel/ts_drv_common/tsdrv_dev/tsdrv_id_config_dfx.c |
PDE_DATA → pde_data |
| 16 | driver/kernel/ts_drv_common/tsdrv_dev/tsdrv_ctx_dfx.c |
PDE_DATA → pde_data |
| 17 | driver/kernel/ts_drv_common/tsdrv_dev/tsdrv_event_id_dfx.c |
PDE_DATA → pde_data |
| 18 | driver/kernel/queue/common/queue_proc_fs.c |
PDE_DATA → pde_data |
| 19 | driver/kernel/svmdrv/pmaster/comm/svm_master_proc_fs.c |
PDE_DATA → pde_data |
| 20 | driver/kernel/svmdrv/pmaster/common/svm_proc_fs.c |
PDE_DATA → pde_data |
| 21 | driver/kernel/svmdrv/pmaster/svm_shmem_procfs.c |
PDE_DATA → pde_data |
| 22 | driver/script/makeself-header.sh |
grep 警告修复 |
| 23 | driver/script/run_driver_install.sh |
.ko.xz 解压 & __versions 剥离 |
打包 .run 文件
前提条件
- 所有上述修改已应用到
Ascend_hdk_310_npu_driver_24.1.1.3/目录 - 系统已安装
pigz(用于压缩)
打包命令
bash
cd /home/xt/Ascend_Drv_asc310p_Rebuild/Ascend_hdk_310_npu_driver_24.1.1.3
./driver/script/makeself.sh \
--header ./driver/script/makeself-header.sh \
--help-header ./driver/script/help.info \
--pigz \
--complevel 4 \
--nomd5 \
--sha256 \
/home/xt/Ascend_Drv_asc310p_Rebuild/Ascend_hdk_310_npu_driver_24.1.1.3 \
/home/xt/Ascend_Drv_asc310p_Rebuild/output_rebuild/Ascend-hdk-310-npu-driver_24.1.1.3_linux-aarch64_k6.12.43.run \
"ASCEND DRIVER RUN PACKAGE" \
./driver/script/install.sh
输出
打包完成后,.run 文件位于:
output_rebuild/Ascend-hdk-310-npu-driver_24.1.1.3_linux-aarch64_k6.12.43.run
安装与验证
bash
# 卸载旧驱动
./Ascend-hdk-310-npu-driver_24.1.1.3_linux-aarch64_k6.12.43.run --uninstall
# 安装新驱动
./Ascend-hdk-310-npu-driver_24.1.1.3_linux-aarch64_k6.12.43.run --full --install-for-all
# 验证模块加载
lsmod | grep ascend
# 应看到 ascend_queue、drv_devmm_host 等所有模块
# 验证 ACL
python3 -c "import acl; acl.init(); ret = acl.rt.set_device(0); print('set_device ret =', ret); acl.finalize()"
# 预期输出: set_device ret = 0
Kernel 6.12 API 变更参考
| 旧 API | 新 API / 替代方案 | 影响模块 |
|---|---|---|
do_exit() |
kthread_complete_and_exit() |
davinci_intf, devmng, dms |
complete_and_exit() |
kthread_complete_and_exit() |
(未导出,同上) |
profile_event_register() |
无替代,设为 no-op | devmng, uda, tsdrv, soft_fault, dms |
profile_event_unregister() |
无替代,设为 no-op | 同上 |
__pte_offset_map() |
内联实现 pmd_page_vaddr() + pte_index() |
svmdrv (devmm_dev) |
PDE_DATA(inode) |
pde_data(inode) |
queue, svmdrv, event_sched, devmng, tsdrv |
follow_pfn() |
follow_pfnmap_start/end() |
svmdrv (devmm_dev) --- 已在 devdrv_interface.h 中处理 |
注意事项
-
Makefile_minivs 顶层Makefile:DKMS 编译使用的是顶层Makefile(从dkms.conf中MAKE[0]指定),不是Makefile_mini。确保两个文件的 ccflags 保持同步。 -
#ifndefvs#if LINUX_VERSION_CODE:在未包含<linux/version.h>的源文件中,使用#ifndef PDE_DATA比#if LINUX_VERSION_CODE >= KERNEL_VERSION(...)更安全,避免LINUX_VERSION_CODE未定义导致的编译错误。 -
objcopy --remove-section=__versions:Intewell 内核编译时未启用CONFIG_MODVERSIONS,但驱动模块中的__versions段包含 CRC 校验值,加载时校验不通过。必须剥离该段。
驱动适配结果

联系方式
- VX-GZH:CrazyNET
资源获取
- 回复:"ascend310drv"即可。