Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4d2179e1 authored by Gleb Natapov's avatar Gleb Natapov Committed by Avi Kivity
Browse files

KVM: x86 emulator: handle shadowed registers outside emulator



Emulator shouldn't access vcpu directly.

Signed-off-by: default avatarGleb Natapov <gleb@redhat.com>
Signed-off-by: default avatarAvi Kivity <avi@redhat.com>
parent bdb475a3
Loading
Loading
Loading
Loading
+0 −15
Original line number Diff line number Diff line
@@ -941,12 +941,9 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
	/* we cannot decode insn before we complete previous rep insn */
	WARN_ON(ctxt->restart);

	/* Shadow copy of register state. Committed on successful emulation. */
	memset(c, 0, sizeof(struct decode_cache));
	c->eip = ctxt->eip;
	c->fetch.start = c->fetch.end = c->eip;
	ctxt->cs_base = seg_base(ctxt, ops, VCPU_SREG_CS);
	memcpy(c->regs, ctxt->vcpu->arch.regs, sizeof c->regs);

	switch (mode) {
	case X86EMUL_MODE_REAL:
@@ -2486,16 +2483,13 @@ int emulator_task_switch(struct x86_emulate_ctxt *ctxt,
	struct decode_cache *c = &ctxt->decode;
	int rc;

	memset(c, 0, sizeof(struct decode_cache));
	c->eip = ctxt->eip;
	memcpy(c->regs, ctxt->vcpu->arch.regs, sizeof c->regs);
	c->dst.type = OP_NONE;

	rc = emulator_do_task_switch(ctxt, ops, tss_selector, reason,
				     has_error_code, error_code);

	if (rc == X86EMUL_CONTINUE) {
		memcpy(ctxt->vcpu->arch.regs, c->regs, sizeof c->regs);
		rc = writeback(ctxt, ops);
		if (rc == X86EMUL_CONTINUE)
			ctxt->eip = c->eip;
@@ -2525,13 +2519,6 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
	ctxt->interruptibility = 0;
	ctxt->decode.mem_read.pos = 0;

	/* Shadow copy of register state. Committed on successful emulation.
	 * NOTE: we can copy them from vcpu as x86_decode_insn() doesn't
	 * modify them.
	 */

	memcpy(c->regs, ctxt->vcpu->arch.regs, sizeof c->regs);

	if (ctxt->mode == X86EMUL_MODE_PROT64 && (c->d & No64)) {
		kvm_queue_exception(ctxt->vcpu, UD_VECTOR);
		goto done;
@@ -3031,8 +3018,6 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
	 * without decoding
	 */
	ctxt->decode.mem_read.end = 0;
	/* Commit shadow register state. */
	memcpy(ctxt->vcpu->arch.regs, c->regs, sizeof c->regs);
	ctxt->eip = c->eip;

done:
+12 −2
Original line number Diff line number Diff line
@@ -3844,7 +3844,7 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
			int emulation_type)
{
	int r, shadow_mask;
	struct decode_cache *c;
	struct decode_cache *c = &vcpu->arch.emulate_ctxt.decode;

	kvm_clear_exception_queue(vcpu);
	vcpu->arch.mmio_fault_cr2 = cr2;
@@ -3869,13 +3869,14 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
			? X86EMUL_MODE_VM86 : cs_l
			? X86EMUL_MODE_PROT64 :	cs_db
			? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16;
		memset(c, 0, sizeof(struct decode_cache));
		memcpy(c->regs, vcpu->arch.regs, sizeof c->regs);

		r = x86_decode_insn(&vcpu->arch.emulate_ctxt, &emulate_ops);
		trace_kvm_emulate_insn_start(vcpu);

		/* Only allow emulation of specific instructions on #UD
		 * (namely VMMCALL, sysenter, sysexit, syscall)*/
		c = &vcpu->arch.emulate_ctxt.decode;
		if (emulation_type & EMULTYPE_TRAP_UD) {
			if (!c->twobyte)
				return EMULATE_FAIL;
@@ -3916,6 +3917,10 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
		return EMULATE_DONE;
	}

	/* this is needed for vmware backdor interface to work since it
	   changes registers values  during IO operation */
	memcpy(c->regs, vcpu->arch.regs, sizeof c->regs);

restart:
	r = x86_emulate_insn(&vcpu->arch.emulate_ctxt, &emulate_ops);

@@ -3936,6 +3941,7 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
	shadow_mask = vcpu->arch.emulate_ctxt.interruptibility;
	kvm_x86_ops->set_interrupt_shadow(vcpu, shadow_mask);
	kvm_x86_ops->set_rflags(vcpu, vcpu->arch.emulate_ctxt.eflags);
	memcpy(vcpu->arch.regs, c->regs, sizeof c->regs);
	kvm_rip_write(vcpu, vcpu->arch.emulate_ctxt.eip);

	if (vcpu->arch.pio.count) {
@@ -4919,6 +4925,7 @@ int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason,
		    bool has_error_code, u32 error_code)
{
	struct decode_cache *c = &vcpu->arch.emulate_ctxt.decode;
	int cs_db, cs_l, ret;
	cache_all_regs(vcpu);

@@ -4933,6 +4940,8 @@ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason,
		? X86EMUL_MODE_VM86 : cs_l
		? X86EMUL_MODE_PROT64 :	cs_db
		? X86EMUL_MODE_PROT32 : X86EMUL_MODE_PROT16;
	memset(c, 0, sizeof(struct decode_cache));
	memcpy(c->regs, vcpu->arch.regs, sizeof c->regs);

	ret = emulator_task_switch(&vcpu->arch.emulate_ctxt, &emulate_ops,
				   tss_selector, reason, has_error_code,
@@ -4941,6 +4950,7 @@ int kvm_task_switch(struct kvm_vcpu *vcpu, u16 tss_selector, int reason,
	if (ret)
		return EMULATE_FAIL;

	memcpy(vcpu->arch.regs, c->regs, sizeof c->regs);
	kvm_rip_write(vcpu, vcpu->arch.emulate_ctxt.eip);
	kvm_x86_ops->set_rflags(vcpu, vcpu->arch.emulate_ctxt.eflags);
	return EMULATE_DONE;