Guillaume Thouvenin wrote: > Hello, > > It's strange because handle_vmentry_failure() is not called. I'm trying > to see where is the problem, any comments are welcome >
[ 979.761321] handle_exception: unexpected, vectoring info 0x80000306 intr info 0x80000b0d Is the error I'm seeing. Regards, Anthony Liguori > Regards, > Guillaume > > > > arch/x86/kvm/vmx.c | 68 +++++++++++++++++++++++++++ > arch/x86/kvm/vmx.h | 3 + > arch/x86/kvm/x86.c | 12 ++-- > arch/x86/kvm/x86_emulate.c | 112 > +++++++++++++++++++++++++++++++++++++++++++-- > include/asm-x86/kvm_host.h | 4 + > 5 files changed, 190 insertions(+), 9 deletions(-) > > --- > > diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c > index 79cdbe8..a0a13b8 100644 > --- a/arch/x86/kvm/vmx.c > +++ b/arch/x86/kvm/vmx.c > @@ -1272,7 +1272,9 @@ static void enter_pmode(struct kvm_vcpu *vcpu) > fix_pmode_dataseg(VCPU_SREG_GS, &vcpu->arch.rmode.gs); > fix_pmode_dataseg(VCPU_SREG_FS, &vcpu->arch.rmode.fs); > > +#if 0 > vmcs_write16(GUEST_SS_SELECTOR, 0); > +#endif > vmcs_write32(GUEST_SS_AR_BYTES, 0x93); > > vmcs_write16(GUEST_CS_SELECTOR, > @@ -2635,6 +2637,66 @@ static int handle_ept_violation(struct kvm_vcpu *vcpu, > struct kvm_run *kvm_run) > return 1; > } > > +static int invalid_guest_state(struct kvm_vcpu *vcpu, > + struct kvm_run *kvm_run, u32 failure_reason) > +{ > + u16 ss, cs; > + u8 opcodes[4]; > + unsigned long rip = vcpu->arch.rip; > + unsigned long rip_linear; > + > + ss = vmcs_read16(GUEST_SS_SELECTOR); > + cs = vmcs_read16(GUEST_CS_SELECTOR); > + > + if ((ss & 0x03) != (cs & 0x03)) { > + int err; > + rip_linear = rip + vmx_get_segment_base(vcpu, VCPU_SREG_CS); > + emulator_read_std(rip_linear, (void *)opcodes, 4, vcpu); > + printk(KERN_INFO "emulation at (%lx) rip %lx: %02x %02x %02x > %02x\n", > + rip_linear, > + rip, opcodes[0], opcodes[1], opcodes[2], > opcodes[3]); > + err = emulate_instruction(vcpu, kvm_run, 0, 0, 0); > + switch (err) { > + case EMULATE_DONE: > + printk(KERN_INFO "successfully emulated > instruction\n"); > + return 1; > + case EMULATE_DO_MMIO: > + printk(KERN_INFO "mmio?\n"); > + return 0; > + default: > + kvm_report_emulation_failure(vcpu, "vmentry > failure"); > + break; > + } > + } > + > + kvm_run->exit_reason = KVM_EXIT_UNKNOWN; > + kvm_run->hw.hardware_exit_reason = failure_reason; > + return 0; > +} > + > +static int handle_vmentry_failure(struct kvm_vcpu *vcpu, > + struct kvm_run *kvm_run, > + u32 failure_reason) > +{ > + unsigned long exit_qualification = vmcs_readl(EXIT_QUALIFICATION); > + > + printk(KERN_INFO "Failed vm entry (exit reason 0x%x) ", failure_reason); > + switch (failure_reason) { > + case EXIT_REASON_INVALID_GUEST_STATE: > + printk("invalid guest state \n"); > + return invalid_guest_state(vcpu, kvm_run, > failure_reason); > + case EXIT_REASON_MSR_LOADING: > + printk("caused by MSR entry %ld loading.\n", > exit_qualification); > + break; > + case EXIT_REASON_MACHINE_CHECK: > + printk("caused by machine check.\n"); > + break; > + default: > + printk("reason not known yet!\n"); > + break; > + } > + return 0; > +} > /* > * The exit handlers return 1 if the exit was handled fully and guest > execution > * may resume. Otherwise they set the kvm_run parameter to indicate what > needs > @@ -2696,6 +2758,12 @@ static int kvm_handle_exit(struct kvm_run *kvm_run, > struct kvm_vcpu *vcpu) > exit_reason != EXIT_REASON_EPT_VIOLATION)) > printk(KERN_WARNING "%s: unexpected, valid vectoring info and " > "exit reason is 0x%x\n", __func__, exit_reason); > + > + if ((exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY)) { > + exit_reason &= ~VMX_EXIT_REASONS_FAILED_VMENTRY; > + return handle_vmentry_failure(vcpu, kvm_run, exit_reason); > + } > + > if (exit_reason < kvm_vmx_max_exit_handlers > && kvm_vmx_exit_handlers[exit_reason]) > return kvm_vmx_exit_handlers[exit_reason](vcpu, kvm_run); > diff --git a/arch/x86/kvm/vmx.h b/arch/x86/kvm/vmx.h > index 79d94c6..2cebf48 100644 > --- a/arch/x86/kvm/vmx.h > +++ b/arch/x86/kvm/vmx.h > @@ -238,7 +238,10 @@ enum vmcs_field { > #define EXIT_REASON_IO_INSTRUCTION 30 > #define EXIT_REASON_MSR_READ 31 > #define EXIT_REASON_MSR_WRITE 32 > +#define EXIT_REASON_INVALID_GUEST_STATE 33 > +#define EXIT_REASON_MSR_LOADING 34 > #define EXIT_REASON_MWAIT_INSTRUCTION 36 > +#define EXIT_REASON_MACHINE_CHECK 41 > #define EXIT_REASON_TPR_BELOW_THRESHOLD 43 > #define EXIT_REASON_APIC_ACCESS 44 > #define EXIT_REASON_EPT_VIOLATION 48 > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c > index 578a0c1..9e5d687 100644 > --- a/arch/x86/kvm/x86.c > +++ b/arch/x86/kvm/x86.c > @@ -3027,8 +3027,8 @@ int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, > struct kvm_regs *regs) > return 0; > } > > -static void get_segment(struct kvm_vcpu *vcpu, > - struct kvm_segment *var, int seg) > +void get_segment(struct kvm_vcpu *vcpu, > + struct kvm_segment *var, int seg) > { > kvm_x86_ops->get_segment(vcpu, var, seg); > } > @@ -3111,8 +3111,8 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu > *vcpu, > return 0; > } > > -static void set_segment(struct kvm_vcpu *vcpu, > - struct kvm_segment *var, int seg) > +void set_segment(struct kvm_vcpu *vcpu, > + struct kvm_segment *var, int seg) > { > kvm_x86_ops->set_segment(vcpu, var, seg); > } > @@ -3270,8 +3270,8 @@ static int load_segment_descriptor_to_kvm_desct(struct > kvm_vcpu *vcpu, > return 0; > } > > -static int load_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector, > - int type_bits, int seg) > +int load_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector, > + int type_bits, int seg) > { > struct kvm_segment kvm_seg; > > diff --git a/arch/x86/kvm/x86_emulate.c b/arch/x86/kvm/x86_emulate.c > index 2ca0838..f6b9dad 100644 > --- a/arch/x86/kvm/x86_emulate.c > +++ b/arch/x86/kvm/x86_emulate.c > @@ -138,7 +138,8 @@ static u16 opcode_table[256] = { > /* 0x88 - 0x8F */ > ByteOp | DstMem | SrcReg | ModRM | Mov, DstMem | SrcReg | ModRM | Mov, > ByteOp | DstReg | SrcMem | ModRM | Mov, DstReg | SrcMem | ModRM | Mov, > - 0, ModRM | DstReg, 0, Group | Group1A, > + DstMem | SrcReg | ModRM | Mov, ModRM | DstReg, > + DstReg | SrcMem | ModRM | Mov, Group | Group1A, > /* 0x90 - 0x9F */ > 0, 0, 0, 0, 0, 0, 0, 0, > 0, 0, 0, 0, ImplicitOps | Stack, ImplicitOps | Stack, 0, 0, > @@ -152,7 +153,8 @@ static u16 opcode_table[256] = { > ByteOp | ImplicitOps | Mov | String, ImplicitOps | Mov | String, > ByteOp | ImplicitOps | String, ImplicitOps | String, > /* 0xB0 - 0xBF */ > - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, > + 0, 0, 0, 0, 0, 0, 0, 0, > + DstReg | SrcImm | Mov, 0, 0, 0, 0, 0, 0, 0, > /* 0xC0 - 0xC7 */ > ByteOp | DstMem | SrcImm | ModRM, DstMem | SrcImmByte | ModRM, > 0, ImplicitOps | Stack, 0, 0, > @@ -168,7 +170,7 @@ static u16 opcode_table[256] = { > /* 0xE0 - 0xE7 */ > 0, 0, 0, 0, 0, 0, 0, 0, > /* 0xE8 - 0xEF */ > - ImplicitOps | Stack, SrcImm|ImplicitOps, 0, SrcImmByte|ImplicitOps, > + ImplicitOps | Stack, SrcImm | ImplicitOps, ImplicitOps, SrcImmByte | > ImplicitOps, > 0, 0, 0, 0, > /* 0xF0 - 0xF7 */ > 0, 0, 0, 0, > @@ -1511,14 +1513,90 @@ special_insn: > break; > case 0x88 ... 0x8b: /* mov */ > goto mov; > + case 0x8c: { /* mov r/m, sreg */ > + struct kvm_segment segreg; > + > + if (c->modrm_mod == 0x3) > + c->src.val = c->modrm_val; > + > + switch ( c->modrm_reg ) { > + case 0: > + get_segment(ctxt->vcpu, &segreg, VCPU_SREG_ES); > + break; > + case 1: > + get_segment(ctxt->vcpu, &segreg, VCPU_SREG_CS); > + break; > + case 2: > + get_segment(ctxt->vcpu, &segreg, VCPU_SREG_SS); > + break; > + case 3: > + get_segment(ctxt->vcpu, &segreg, VCPU_SREG_DS); > + break; > + case 4: > + get_segment(ctxt->vcpu, &segreg, VCPU_SREG_FS); > + break; > + case 5: > + get_segment(ctxt->vcpu, &segreg, VCPU_SREG_GS); > + break; > + default: > + printk(KERN_INFO "0x8c: Invalid segreg in modrm byte > 0x%02x\n", > + c->modrm); > + goto cannot_emulate; > + } > + c->dst.val = segreg.selector; > + c->dst.bytes = 2; > + c->dst.ptr = (unsigned long *)decode_register(c->modrm_rm, > c->regs, > + c->d & ByteOp); > + break; > + } > case 0x8d: /* lea r16/r32, m */ > c->dst.val = c->modrm_ea; > break; > + case 0x8e: { /* mov seg, r/m16 */ > + uint16_t sel; > + > + sel = c->src.val; > + switch ( c->modrm_reg ) { > + case 0: > + if (load_segment_descriptor(ctxt->vcpu, sel, 1, > VCPU_SREG_ES) < 0) > + goto cannot_emulate; > + break; > + case 1: > + if (load_segment_descriptor(ctxt->vcpu, sel, 9, > VCPU_SREG_CS) < 0) > + goto cannot_emulate; > + break; > + case 2: > + if (load_segment_descriptor(ctxt->vcpu, sel, 1, > VCPU_SREG_SS) < 0) > + goto cannot_emulate; > + break; > + case 3: > + if (load_segment_descriptor(ctxt->vcpu, sel, 1, > VCPU_SREG_DS) < 0) > + goto cannot_emulate; > + break; > + case 4: > + if (load_segment_descriptor(ctxt->vcpu, sel, 1, > VCPU_SREG_FS) < 0) > + goto cannot_emulate; > + break; > + case 5: > + if (load_segment_descriptor(ctxt->vcpu, sel, 1, > VCPU_SREG_GS) < 0) > + goto cannot_emulate; > + break; > + default: > + printk(KERN_INFO "Invalid segreg in modrm byte > 0x%02x\n", > + c->modrm); > + goto cannot_emulate; > + } > + > + c->dst.type = OP_NONE; /* Disable writeback. */ > + break; > + } > case 0x8f: /* pop (sole member of Grp1a) */ > rc = emulate_grp1a(ctxt, ops); > if (rc != 0) > goto done; > break; > + case 0xb8: /* mov r, imm */ > + goto mov; > case 0x9c: /* pushf */ > c->src.val = (unsigned long) ctxt->eflags; > emulate_push(ctxt); > @@ -1657,6 +1735,34 @@ special_insn: > break; > } > case 0xe9: /* jmp rel */ > + jmp_rel(c, c->src.val); > + c->dst.type = OP_NONE; /* Disable writeback. */ > + break; > + case 0xea: /* jmp far */ { > + uint32_t eip; > + uint16_t sel; > + > + switch (c->op_bytes) { > + case 2: > + eip = insn_fetch(u16, 2, c->eip); > + eip = eip & 0x0000FFFF; /* clear upper 16 bits */ > + break; > + case 4: > + eip = insn_fetch(u32, 4, c->eip); > + break; > + default: > + DPRINTF("jmp far: Invalid op_bytes\n"); > + goto cannot_emulate; > + } > + sel = insn_fetch(u16, 2, c->eip); > + if (load_segment_descriptor(ctxt->vcpu, sel, 9, VCPU_SREG_CS) < > 0) { > + DPRINTF("jmp far: Failed to load CS descriptor\n"); > + goto cannot_emulate; > + } > + > + c->eip = eip; > + break; > + } > case 0xeb: /* jmp rel short */ > jmp_rel(c, c->src.val); > c->dst.type = OP_NONE; /* Disable writeback. */ > diff --git a/include/asm-x86/kvm_host.h b/include/asm-x86/kvm_host.h > index 4baa9c9..7a0846a 100644 > --- a/include/asm-x86/kvm_host.h > +++ b/include/asm-x86/kvm_host.h > @@ -495,6 +495,10 @@ int emulator_get_dr(struct x86_emulate_ctxt *ctxt, int > dr, > int emulator_set_dr(struct x86_emulate_ctxt *ctxt, int dr, > unsigned long value); > > +void set_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg); > +void get_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg); > +int load_segment_descriptor(struct kvm_vcpu *vcpu, u16 selector, > + int type_bits, int seg); > int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason); > > void kvm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0); > ------------------------------------------------------------------------- This SF.net email is sponsored by the 2008 JavaOne(SM) Conference Don't miss this year's exciting event. There's still time to save $100. Use priority code J8TL2D2. http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone _______________________________________________ kvm-devel mailing list kvm-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/kvm-devel