public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
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

  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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox