首页 文章

为什么这个mov gs指令导致运行Windows 7操作系统的VMWare Workstation guest虚拟机出现故障?

提问于
浏览
3

当我在VMWare Workstation虚拟机中运行的Windows 7 x64的内核模式下运行以下汇编序列时:

xor eax, eax
mov ax, gs
mov gs, ax     ; this instruction

enter image description here

最后一条 mov gs, ax 指令会立即导致该VM崩溃(或可能是错误检查),并显示以下弹出消息:

enter image description here

发生故障导致虚拟CPU进入关闭状态 . 如果此故障发生在虚拟机之外,则会导致物理计算机重新启动 . 通过错误配置虚拟机,客户机操作系统中的错误或VMWare Workstation中的问题,可以达到关闭状态 .

重新加载 gs 注册会导致内核中的问题,还是虚拟化问题?

我在英特尔手册中没有看到任何关于 mov 指令的异常 .

PS . 顺便说一句,用 fs 替换 gs 寄存器不会导致此错误 .


Edit: 回答有关GDT中段描述符状态的问题 . 这里是:

0: kd> r gs
gs=002b
0: kd> dg 28
                                                    P Si Gr Pr Lo
Sel        Base              Limit          Type    l ze an es ng Flags
---- ----------------- ----------------- ---------- - -- -- -- -- --------
0028 00000000`00000000 00000000`ffffffff Data RW Ac 3 Bg Pg P  Nl 00000cf3

1 回答

  • 6

    我不确定为什么移动 mov gs,ax 会导致Windows立即三重故障,但很快就会导致它崩溃 . 在64位Windows内核中,GS段用作访问当前CPU的Processor Control Region(PCR)的指针 . 每个CPU具有指向不同PCR的不同GS基值 . 您的 mov ax,gs mov gs,ax 序列实际上会破坏它,因为它会将GS库的不正确值加载到描述符缓存中 .

    GDT实际上并不包含GS寄存器的正确基础 . 由于GDT只能保存32位地址,因此实际上并不用于加载GS基址 . 相反,IA32_GS_BASE和IA32_KERNEL_GS_BASE MSR(后者与SWAPGS指令组合)用于为GS段设置64位基址 . 存储在GS寄存器中的选择器值只是一个虚拟值 .

    因此, mov gs,ax 指令加载存储在GDT中的虚拟32位基值,而不是IA32_GS_BASE中存储的64位值 . 这意味着GS段的基地址设置为0,而不是当前CPU的PCR地址 . 在加载这个不正确的GS库之后,Windows内核尝试使用GS寄存器访问PCR(使用 mov rax, gs:[10] 之类的指令)只是时间问题,并最终读取可能未映射的内存,导致意外的内核页面错误并崩溃 .

相关问题