为什么此mov gs指令在运行Windows 7 OS的VMWare Workstation guest虚拟机中引起故障?

时间:2018-06-29 04:39:16

标签: assembly kernel vmware virtualization windows-kernel

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

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

enter image description here

最后一条mov gs, ax指令立即导致虚拟机崩溃,并显示以下弹出消息:

enter image description here

  

发生故障,导致虚拟CPU进入关机状态   州。如果此错误发生在虚拟机外部,则它   会导致物理机重新启动。关机状态   错误地配置虚拟机可以解决这个问题   来宾操作系统中出现问题,或者VMWare Workstation中出现问题。

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

在英特尔手册中,我没有看到关于该mov指令的任何异常信息。

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


编辑:回答有关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 个答案:

答案 0 :(得分:6)

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

GDT实际上没有包含GS寄存器的正确基数。由于GDT只能保存32位地址,因此实际上并未用于加载GS base。取而代之的是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]这样的指令)并最终读取可能导致未预期内核的未映射内存,只是时间问题页面错误和崩溃。