首页 > Virtualization > KVM进入vmx模式产生general protection fault

KVM进入vmx模式产生general protection fault

Virtualization 2015-05-23

在SIMICS软件里面模拟最新的CPU进行虚拟化测试的时候,先把Dave的kernel patches拿到手,打补丁到v4.1-rc2上,每次启动qemu-kvm的时候,console上就打印了一堆信息,然后panic了,信息简略如下:

[   26.998321] general protection fault: 0000 [#1] SMP
[   27.000140] [<ffffffffa0517f6b>] hardware_enable+0x14b/0x180 [kvm_intel]
[   27.000140]  [<ffffffffa02c0a8a>] kvm_arch_hardware_enable+0x9a/0x280 [kvm]
[   27.000140]  [<ffffffffa02a81e0>] ? kvm_get_dirty_log+0x110/0x110 [kvm]
[   27.000140]  [<ffffffffa02a821e>] hardware_enable_nolock+0x3e/0x70 [kvm]
[   27.000140]  [<ffffffff8111d9e1>] flush_smp_call_function_queue+0x81/0x170

先是反汇编内核,看到了出问题的地方,在kvm_cpu_vmxon函数上,它就是汇编执行vmxon指令进入到vmx模式,vmxon也就接受一个参数phys_addr,来自于phys_addr = __pa(per_cpu(vmxarea, cpu)),而vmxarea在hardware_setup上初始化,在最后一句话:alloc_kvm_area,内容是vmcs = alloc_vmcs_cpu(cpu);per_cpu(vmxarea, cpu) = vmcs,怎么看都没发现Dave的patch和vmcs有关联,(去掉Dave的patch就OK了,但他完成的只是kernel部分,virtualization部分归我完成),Dave也认为和simics模拟有关,只好发给simics的Rechistov同事看一下,他让使用“log-level 4”的simics命令配合“break-exception General_Protection_Exception”可以抓取到更多日志,参照抓取日志,果然很不同:

[viper.mb.cpu0.core[2][0] info] GP fault. VMXON with unsupported CR4
[viper.mb.cpu0.core[2][0] trace-exception] Exception 13: General_Protection_Exception

vmxon不支持CR4,这是什么鬼,Rechistov指出去看SDM “23.8 RESTRICTIONS ON VMX OPERATION”,才发现vmxon对cr寄存器有限制:
在SDM “VMXON—Enter VMX Operation”章节中提到IF (CPL > 0) or (in A20M mode) or (the values of CR0 and CR4 are not supported in VMX operation; see Section 23.8) or (bit 0 (lock bit) of IA32_FEATURE_CONTROL MSR is clear) or (in SMX operation11 and bit 1 of IA32_FEATURE_CONTROL MSR is clear) or (outside SMX operation and bit 2 of IA32_FEATURE_CONTROL MSR is clear) THEN #GP(0); 这样就对上号。
而vmxon对cr的限制是:如果vmxon执行是,发现cr0和cr4的格式不满足要求,即某些位的值必须固定,则产生GP,格式要求来自于IA32_VMX_CR0_FIXED0(值为1的位对应到cr0必须为1),IA32_VMX_CR0_FIXED1(值为0的位对应到cr0必须为0),IA32_VMX_CR4_FIXED0(值为1的位对应到cr4必须为1), IA32_VMX_CR4_FIXED1(值为0的位对应到cr4必须为0),而且这些MSR值是(R/O),也就是硬件固定的,但是SDM中没有找到对应的说明。

虽然kernel代码里面有如下的宏:

#define MSR_IA32_VMX_CR0_FIXED0 0x00000486
#define MSR_IA32_VMX_CR0_FIXED1 0x00000487
#define MSR_IA32_VMX_CR4_FIXED0 0x00000488
#define MSR_IA32_VMX_CR4_FIXED1 0x00000489

但实际只有vmx使用这些宏做模拟,另外一个方法就是直接读取一个实际CPU系统的值,IA32_VMX_CR4_FIXED1结果如下:

./rdmsr -p 0 -x 0x00000489
3467ff

这样就比较清楚了,Dave的patch更新了cr4的第22位,而simics并没有将22位添加到IA32_VMX_CR4_FIXED1中,这样就GP了。
解决方法:simics> viper.mb.cpu0.core[x][y]->ia32_vmx_cr4_fixed1 = 0x7467FF。

至于IA32_VMX_CR4_FIXED1的其他位有什么要求,可以对照下图看一下:
cpu-cr4-oenhan

 

 


KVM进入vmx模式产生general protection fault来自于OenHan,链接为:http://oenhan.com/kvm-vmxon-gp-error
更多阅读