一个关于 AMDGPU Page Fault 的报错排查
背景 最近在做一个项目,其中涉及到构建一个函数,函数的输入是一个内存地址,函数需要解析这个内存地址中的值然后执行相应的动作。已知的是输入的内存地址是 int64 类型的数值,代表的是 amdgpu scratch memory 中的一个地址。 基于项目当前的架构,我的设计是在 opencl 中实现这个函数,然后将这个函数编译到一个 bitcode 文件中,作为一个 bitcode 文件,它可以在项目编译的时候通过 -mlink-builtin-bitcode 链接进来,调用方只需要在模块中正确地声明这个函数就可以。 这个函数是在 runtime 执行的,因为在编译期间不能获取到内存中存的数值。 问题浮现 当我完成函数代码的编写,并且成功编译到可执行文件,看起来一切顺利。但是当我运行可执行文件的时候,意外发生了,出现了 Page Fault 的错误。 原因分析 经过一盘排查之后,发现问题出在加载了非法的指针地址。输入的指针地址指向的是 scratch 地址空间(i8 addrspace(5)),为了可以访问这个地址,我通过 inttoptr 将其转换到了 generic 地址空间的指针(i8),然后再访问这个地址。我用下面的伪代码来表达一下这番操作: define protected void void @foo(i64 %0) { Entry: %1 = inttoptr i64 %0 to i8* %2 = load i8, i8* %1, align 1 ... } 而调用方首先通过 ptrtoint 将 i8 addrspace(5)* 转成了 int64,所以整个流程可以简化为下面的伪代码: define amdgpu_kernel void @bar(...) { Entry: %0 = ptrtoint i8 addrspace(5)* %ptr to i64 %1 = inttoptr i64 %0 to i8* %2 = load i8, i8* %1, align 1 ... } 看起来一切都符合逻辑,除了 scratch 的地址空间被转到了 generic 的地址空间,但是理论上 generic 指针也可以处理 scratch 的指针,只要指针指向的地址没有改变就可以了。但是指针指向的地址确实被改变了! ...