内核初始化写入per-cpu变量物理地址时遇VMware CPU禁用报错
解决VMware提示"The CPU is disabled on the guest operating system"的内核异常问题
看起来你遇到的是内核初始化阶段操作per-CPU变量触发的VMware硬件异常,我来帮你拆解问题并给出针对性的解决方案:
核心问题分析
你的代码在内核初始化阶段调用了get_cpu_ptr()/put_cpu_ptr()这类per-CPU操作,但这个阶段per-CPU子系统还没完成全量初始化——此时当前CPU的上下文管理、per-CPU内存映射可能还没准备就绪,直接操作会触发非法内存访问或者硬件状态异常,被VMware误判为CPU故障。
具体修复步骤
1. 延迟代码执行时机到per-CPU子系统就绪后
如果你的功能不需要在最早期初始化阶段运行,把代码延迟到late_initcall阶段(此时SMP和per-CPU子系统都已完成初始化):
// 替换原来的初始化调用,改用late_initcall static int __init my_func_init(void) { on_each_cpu(func, NULL, 1); return 0; } late_initcall(my_func_init);
2. 若必须用per-CPU变量,改用更安全的访问方式
避免在初始化阶段使用get_cpu_ptr(),改用this_cpu_ptr()(如果当前CPU已经在线),或者直接通过per_cpu()宏访问:
static void func(void *info) { // 改用this_cpu_ptr,确保当前CPU上下文有效 cpu_clock_t *ptr = this_cpu_ptr(&cpu_clock); uint64_t cpu_clock_pa = virt_to_phys(ptr); __asm__ __volatile__ ... // 传递物理地址给VMware // 不需要调用put_cpu_ptr,this_cpu_ptr不需要手动释放 }
3. 检查VMware交互的汇编指令合法性
你的内联汇编直接和VMware hypervisor交互,错误的指令格式或权限问题也会触发异常:
- 确保传递的物理地址属于内核可写区域,没有被标记为只读/保留
- 核对VMware hypercall的规范(比如使用正确的VMX指令格式),避免非法指令触发CPU故障
4. 调试定位具体异常点
如果以上方法还没解决,建议:
- 开启内核调试,查看
dmesg中的panic栈信息,找到具体的异常指令和内存地址 - 查看VMware的
vmware.log日志,里面会记录hypervisor捕获到的异常类型(比如页错误、通用保护故障),帮你精准定位问题
内容的提问来源于stack exchange,提问作者tomer.z
相关产品推荐
相关产品推荐

