mirror of https://github.com/xemu-project/xemu.git
kvm: Improve reporting of fatal errors
Report KVM_EXIT_UNKNOWN, KVM_EXIT_FAIL_ENTRY, and KVM_EXIT_EXCEPTION with more details to stderr. The latter two are so far x86-only, so move them into the arch-specific handler. Integrate the Intel real mode warning on KVM_EXIT_FAIL_ENTRY that qemu-kvm carries, but actually restrict it to Intel CPUs. Moreover, always dump the CPU state in case we fail. Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
This commit is contained in:
parent
73aaec4a39
commit
bb44e0d12d
22
kvm-all.c
22
kvm-all.c
|
@ -817,22 +817,22 @@ static int kvm_handle_io(uint16_t port, void *data, int direction, int size,
|
||||||
#ifdef KVM_CAP_INTERNAL_ERROR_DATA
|
#ifdef KVM_CAP_INTERNAL_ERROR_DATA
|
||||||
static int kvm_handle_internal_error(CPUState *env, struct kvm_run *run)
|
static int kvm_handle_internal_error(CPUState *env, struct kvm_run *run)
|
||||||
{
|
{
|
||||||
|
fprintf(stderr, "KVM internal error.");
|
||||||
if (kvm_check_extension(kvm_state, KVM_CAP_INTERNAL_ERROR_DATA)) {
|
if (kvm_check_extension(kvm_state, KVM_CAP_INTERNAL_ERROR_DATA)) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
fprintf(stderr, "KVM internal error. Suberror: %d\n",
|
fprintf(stderr, " Suberror: %d\n", run->internal.suberror);
|
||||||
run->internal.suberror);
|
|
||||||
|
|
||||||
for (i = 0; i < run->internal.ndata; ++i) {
|
for (i = 0; i < run->internal.ndata; ++i) {
|
||||||
fprintf(stderr, "extra data[%d]: %"PRIx64"\n",
|
fprintf(stderr, "extra data[%d]: %"PRIx64"\n",
|
||||||
i, (uint64_t)run->internal.data[i]);
|
i, (uint64_t)run->internal.data[i]);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
cpu_dump_state(env, stderr, fprintf, 0);
|
|
||||||
if (run->internal.suberror == KVM_INTERNAL_ERROR_EMULATION) {
|
if (run->internal.suberror == KVM_INTERNAL_ERROR_EMULATION) {
|
||||||
fprintf(stderr, "emulation failure\n");
|
fprintf(stderr, "emulation failure\n");
|
||||||
if (!kvm_arch_stop_on_emulation_error(env)) {
|
if (!kvm_arch_stop_on_emulation_error(env)) {
|
||||||
|
cpu_dump_state(env, stderr, fprintf, 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -966,15 +966,8 @@ int kvm_cpu_exec(CPUState *env)
|
||||||
ret = 1;
|
ret = 1;
|
||||||
break;
|
break;
|
||||||
case KVM_EXIT_UNKNOWN:
|
case KVM_EXIT_UNKNOWN:
|
||||||
DPRINTF("kvm_exit_unknown\n");
|
fprintf(stderr, "KVM: unknown exit, hardware reason %" PRIx64 "\n",
|
||||||
ret = -1;
|
(uint64_t)run->hw.hardware_exit_reason);
|
||||||
break;
|
|
||||||
case KVM_EXIT_FAIL_ENTRY:
|
|
||||||
DPRINTF("kvm_exit_fail_entry\n");
|
|
||||||
ret = -1;
|
|
||||||
break;
|
|
||||||
case KVM_EXIT_EXCEPTION:
|
|
||||||
DPRINTF("kvm_exit_exception\n");
|
|
||||||
ret = -1;
|
ret = -1;
|
||||||
break;
|
break;
|
||||||
#ifdef KVM_CAP_INTERNAL_ERROR_DATA
|
#ifdef KVM_CAP_INTERNAL_ERROR_DATA
|
||||||
|
@ -1001,6 +994,7 @@ int kvm_cpu_exec(CPUState *env)
|
||||||
} while (ret > 0);
|
} while (ret > 0);
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
cpu_dump_state(env, stderr, fprintf, 0);
|
||||||
vm_stop(0);
|
vm_stop(0);
|
||||||
env->exit_request = 1;
|
env->exit_request = 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -874,6 +874,8 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
|
||||||
uint32_t *ecx, uint32_t *edx);
|
uint32_t *ecx, uint32_t *edx);
|
||||||
int cpu_x86_register (CPUX86State *env, const char *cpu_model);
|
int cpu_x86_register (CPUX86State *env, const char *cpu_model);
|
||||||
void cpu_clear_apic_feature(CPUX86State *env);
|
void cpu_clear_apic_feature(CPUX86State *env);
|
||||||
|
void host_cpuid(uint32_t function, uint32_t count,
|
||||||
|
uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx);
|
||||||
|
|
||||||
/* helper.c */
|
/* helper.c */
|
||||||
int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
|
int cpu_x86_handle_mmu_fault(CPUX86State *env, target_ulong addr,
|
||||||
|
|
|
@ -103,9 +103,8 @@ typedef struct model_features_t {
|
||||||
int check_cpuid = 0;
|
int check_cpuid = 0;
|
||||||
int enforce_cpuid = 0;
|
int enforce_cpuid = 0;
|
||||||
|
|
||||||
static void host_cpuid(uint32_t function, uint32_t count,
|
void host_cpuid(uint32_t function, uint32_t count,
|
||||||
uint32_t *eax, uint32_t *ebx,
|
uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
|
||||||
uint32_t *ecx, uint32_t *edx)
|
|
||||||
{
|
{
|
||||||
#if defined(CONFIG_KVM)
|
#if defined(CONFIG_KVM)
|
||||||
uint32_t vec[4];
|
uint32_t vec[4];
|
||||||
|
|
|
@ -1525,8 +1525,19 @@ static int kvm_handle_halt(CPUState *env)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool host_supports_vmx(void)
|
||||||
|
{
|
||||||
|
uint32_t ecx, unused;
|
||||||
|
|
||||||
|
host_cpuid(1, 0, &unused, &unused, &ecx, &unused);
|
||||||
|
return ecx & CPUID_EXT_VMX;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define VMX_INVALID_GUEST_STATE 0x80000021
|
||||||
|
|
||||||
int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
|
int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
|
||||||
{
|
{
|
||||||
|
uint64_t code;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
switch (run->exit_reason) {
|
switch (run->exit_reason) {
|
||||||
|
@ -1537,6 +1548,28 @@ int kvm_arch_handle_exit(CPUState *env, struct kvm_run *run)
|
||||||
case KVM_EXIT_SET_TPR:
|
case KVM_EXIT_SET_TPR:
|
||||||
ret = 1;
|
ret = 1;
|
||||||
break;
|
break;
|
||||||
|
case KVM_EXIT_FAIL_ENTRY:
|
||||||
|
code = run->fail_entry.hardware_entry_failure_reason;
|
||||||
|
fprintf(stderr, "KVM: entry failed, hardware error 0x%" PRIx64 "\n",
|
||||||
|
code);
|
||||||
|
if (host_supports_vmx() && code == VMX_INVALID_GUEST_STATE) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"\nIf you're runnning a guest on an Intel machine without "
|
||||||
|
"unrestricted mode\n"
|
||||||
|
"support, the failure can be most likely due to the guest "
|
||||||
|
"entering an invalid\n"
|
||||||
|
"state for Intel VT. For example, the guest maybe running "
|
||||||
|
"in big real mode\n"
|
||||||
|
"which is not supported on less recent Intel processors."
|
||||||
|
"\n\n");
|
||||||
|
}
|
||||||
|
ret = -1;
|
||||||
|
break;
|
||||||
|
case KVM_EXIT_EXCEPTION:
|
||||||
|
fprintf(stderr, "KVM: exception %d exit (error code 0x%x)\n",
|
||||||
|
run->ex.exception, run->ex.error_code);
|
||||||
|
ret = -1;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
|
fprintf(stderr, "KVM: unknown exit reason %d\n", run->exit_reason);
|
||||||
ret = -1;
|
ret = -1;
|
||||||
|
|
Loading…
Reference in New Issue