qemu-kvm的suberror错误探索

引言

在使用qemu-kvm时,有时候会遇到报“KVM internal error. Suberror: 1”或者“KVM internal error. Suberror: 3”错误,但是这类报错又没有其他报错信息辅助我们进行问题的定位和处理,而且kvm驱动中,也并未提供这类问题的debug信息调试手段。在kvm驱动中,将kvm emulation failure问题统一报“KVM internal error. Suberror: 1”或者“KVM internal error. Suberror: 3”错误。用户在错误时无法通过日志来甄别问题原因,只能知道原因是kvm外部原因(诸如启动kvm的配置选项,vcpu状态异常,cpu特性功能检测异常)。

其实报“KVM internal error. Suberror: 1”或者“KVM internal error. Suberror: 3”错误的原因最终都和cpu状态或者特性相关,kvm在启用vcpu时,如果检测到KVM_EXIT_INTERNAL_ERROR异常时就会报错并停止运行,例如-m 1配置下如下现象:

QEMU 4.2.0 monitor - type 'help' for more information
(qemu) KVM internal error. Suberror: 1
emulation failure
EAX=000082c6 EBX=0010ae38 ECX=000082d2 EDX=80ffffff
ESI=00100000 EDI=0000832a EBP=0007fff0 ESP=0007fff4
EIP=0010a000 EFL=00010086 [--S--P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
CS =0008 00000000 ffffffff 00c09b00 DPL=0 CS32 [-RA]
SS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
DS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
FS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
GS =0010 00000000 ffffffff 00c09300 DPL=0 DS   [-WA]
LDT=0000 00000000 0000ffff 00008200 DPL=0 LDT
TR =0000 00000000 0000ffff 00008b00 DPL=0 TSS32-busy
GDT=     00008280 00000027
IDT=     00000000 00000000
CR0=00000011 CR2=00000000 CR3=00000000 CR4=00000000
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000
DR6=00000000ffff0ff0 DR7=0000000000000400
EFER=0000000000000000
Code=02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 02 <00> 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

异常触发流程

首先在qemu-kvm启动kvm时,它出现异常的过程如下:

|____kvm_cpu_exec
     |_____trace_kvm_run_exit
           |____case KVM_EXIT_INTERNAL_ERROR
                |____kvm_handle_interal_error

kvm_cpu_exec->trace_kvm_run_exit-> case KVM_EXIT_INTERNAL_ERROR->kvm_handle_internal_error

1.	static int kvm_handle_internal_error(CPUState *cpu, struct kvm_run *run)
2.	{
3.	    //触发KVM internal error. Suberror(Suberror:1或者Suberror:3)
4.	    fprintf(stderr, "KVM internal error. Suberror: %d\n",
5.	            run->internal.suberror);
6.	
7.	    // Suberror:3时会进这个条件,打印extra data[%d]信息
8.	    if (kvm_check_extension(kvm_state, KVM_CAP_INTERNAL_ERROR_DATA)) {
9.	        int i;
10.	
11.	        for (i = 0; i < run->internal.ndata; ++i) {
12.	            fprintf(stderr, "extra data[%d]: %"PRIx64"\n",
13.	                    i, (uint64_t)run->internal.data[i]);
14.	        }
15.	    }
16.	    //Suberror:3和Suberror:1时,打印当前寄存器信息
17.	    if (run->internal.suberror == KVM_INTERNAL_ERROR_EMULATION) {
18.	        fprintf(stderr, "emulation failure\n");
19.	        if (!kvm_arch_stop_on_emulation_error(cpu)) {
20.	             //通过cpu_synchronize_state获取CPU各寄存器运行环境,打印出来
21.	            cpu_dump_state(cpu, stderr, CPU_DUMP_CODE);
22.	            return EXCP_INTERRUPT;
23.	        }
24.	    }
25.	    /* FIXME: Should trigger a qmp message to let management know
26.	     * something went wrong.
27.	     */
28.	    return -1;
29.	}

异常触发原因

而KVM_EXIT_INTERNAL_ERROR异常是由kvm驱动在模拟kvm时候传入的,而最常见的suberror错误码有1)KVM_INTERNAL_ERROR_EMULATION,对应suberror:1;2)KVM_CAP_INTERNAL_ERROR_DATA,对应suberror:3。kvm触发KVM_EXIT_INTERNAL_ERROR可以总结有以下场景,内核代码大致如下:

通过驱动代码层总结,发生suberror报错时,所有的场景都和cpu和内存异常相关。首先内存配置应该满足kvm的启动需求,如果-m 1时将会导致linux kvm出现suberror:1报错异常;其次配置vcpu特性时,应该注意cpu是否能够支持需要配置的cpu特性,如果cpu特性不支持,或驱动检测到cpu特性异常,也将出现suberror:1报错异常。详细总结如下:

No.

场景描述

配置

是否可避免

说明

驱动测处理

1

内存配置过小

-m 1时

事实上,当内存配置小于200M时,在启动linux kvm时,都必然将导致kvm启动异常,尤其内存配置为1009k-1064k时将必然导致KVM internal error. Suberror: 1

arch/x86/kvm/x86.c代码中kvm_handle_memory_failure函数被调用,且内存异常不是由于page fault导致的,将会导致suberror:1异常

2

迁移场景中,配置了host无法支持的一些特性

-cpu host,hv-vapic,hv-evmcs(此特性的配置将导致一些虚拟化特性不能使用)

确保host能够支持该特性,且迁移时也要确定目标主机支持该特性(此问题可以通过增加内核打印信息判断是否被触发,内核打印语句pr_debug_ratelimited,对应打印级别为8,修改 /proc/sys/kernel/printk中的日志打印级别可以观察)

arch/x86/kvm/vmx/nested.c中调用以下两个接口时:1)nested_get_vmcs12_pages时在 vmcs12 中不支持 APIC 访问地址;2)调用vmx_get_nested_state_pages时由于hv_evmcs迁移后(L2 运行时)可能最终未映射,无法正确反映 vmcs12的更改导致“enlightened vmptrld failed”。

这两个场景都会最终导致suberror:1异常

3

配置了显卡直通,kvm休眠或待机唤醒时

显卡直通配置

尽量不用显卡直通配置,如需使用显卡直通需要确保host支持并开启了intel_iommu=on配置,如果host不支持或未开启iommu时,在使用过程中可能导致报错

NA

4

其它cpu特性异常场景

NA

NA

1.Kvm cupid 0x12异常时

2. X86_FEATURE_SGX2特性异常时

3. guest异常退出, emulation_required条件仍成立, vcpu处于pending状态

arch/x86/kvm/x86.c代码中kvm_prepare_emulation_failure_exit在一些cpu异常场景下被调用,将会导致suberror:1异常。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不会写代码的小可爱&&

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值