From: Anthony Liguori <anthony@codemonkey.ws>
To: Guillaume Thouvenin <guillaume.thouvenin@ext.bull.net>
Cc: Rik van Riel <riel@surriel.com>,
"kvm-devel@lists.sourceforge.net"
<kvm-devel@lists.sourceforge.net>, Avi Kivity <avi@qumranet.com>,
Alexander Graf <alex@csgraf.de>,
Mohammed Gamal <m.gamal005@gmail.com>
Subject: Re: Protected mode transitions and big real mode... still an issue
Date: Tue, 29 Apr 2008 13:16:57 -0500 [thread overview]
Message-ID: <48176619.1020602@codemonkey.ws> (raw)
In-Reply-To: <20080429150236.70c51b02@frecb000711.frec.bull.fr>
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
next prev parent reply other threads:[~2008-04-29 18:16 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-04-29 13:02 Protected mode transitions and big real mode... still an issue Guillaume Thouvenin
2008-04-29 16:41 ` Anthony Liguori
2008-04-29 17:09 ` Laurent Vivier
2008-04-29 17:22 ` Laurent Vivier
2008-04-29 23:20 ` Avi Kivity
2008-04-29 18:17 ` Anthony Liguori
2008-04-29 16:56 ` David Mair
2008-04-29 18:16 ` Anthony Liguori [this message]
2008-05-01 19:13 ` Marcelo Tosatti
2008-05-03 8:26 ` Balaji Rao
2008-05-05 12:40 ` Guillaume Thouvenin
2008-05-05 12:44 ` Balaji Rao
2008-05-05 12:57 ` Anthony Liguori
2008-05-05 13:29 ` Mohammed Gamal
2008-05-06 13:38 ` Guillaume Thouvenin
2008-05-06 14:30 ` Anthony Liguori
2008-05-06 17:05 ` Mohammed Gamal
2008-05-14 7:29 ` Guillaume Thouvenin
2008-05-14 21:29 ` Marcelo Tosatti
2008-05-15 7:33 ` Avi Kivity
2008-05-15 7:49 ` Guillaume Thouvenin
2008-05-15 18:07 ` Mohammed Gamal
2008-05-07 5:57 ` Guillaume Thouvenin
2008-05-05 6:27 ` Guillaume Thouvenin
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=48176619.1020602@codemonkey.ws \
--to=anthony@codemonkey.ws \
--cc=alex@csgraf.de \
--cc=avi@qumranet.com \
--cc=guillaume.thouvenin@ext.bull.net \
--cc=kvm-devel@lists.sourceforge.net \
--cc=m.gamal005@gmail.com \
--cc=riel@surriel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.