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

Commit 996ba96a authored by Rusty Russell's avatar Rusty Russell
Browse files

lguest: Fix in/out emulation



We were blatting too much of the register.  Linux didn't care, but in
theory it might.

Reported-by: default avatarJonas Maebe <jonas.maebe@elis.ugent.be>
Signed-off-by: default avatarRusty Russell <rusty@rustcorp.com.au>
parent 8d431f41
Loading
Loading
Loading
Loading
+11 −9
Original line number Diff line number Diff line
@@ -269,7 +269,7 @@ void lguest_arch_run_guest(struct lg_cpu *cpu)
static int emulate_insn(struct lg_cpu *cpu)
{
	u8 insn;
	unsigned int insnlen = 0, in = 0, shift = 0;
	unsigned int insnlen = 0, in = 0, small_operand = 0;
	/*
	 * The eip contains the *virtual* address of the Guest's instruction:
	 * walk the Guest's page tables to find the "physical" address.
@@ -300,11 +300,10 @@ static int emulate_insn(struct lg_cpu *cpu)
	}

	/*
	 * 0x66 is an "operand prefix".  It means it's using the upper 16 bits
	 * of the eax register.
	 * 0x66 is an "operand prefix".  It means a 16, not 32 bit in/out.
	 */
	if (insn == 0x66) {
		shift = 16;
		small_operand = 1;
		/* The instruction is 1 byte so far, read the next byte. */
		insnlen = 1;
		insn = lgread(cpu, physaddr + insnlen, u8);
@@ -340,11 +339,14 @@ static int emulate_insn(struct lg_cpu *cpu)
	 * traditionally means "there's nothing there".
	 */
	if (in) {
		/* Lower bit tells is whether it's a 16 or 32 bit access */
		if (insn & 0x1)
			cpu->regs->eax = 0xFFFFFFFF;
		/* Lower bit tells means it's a 32/16 bit access */
		if (insn & 0x1) {
			if (small_operand)
				cpu->regs->eax |= 0xFFFF;
			else
			cpu->regs->eax |= (0xFFFF << shift);
				cpu->regs->eax = 0xFFFFFFFF;
		} else
			cpu->regs->eax |= 0xFF;
	}
	/* Finally, we've "done" the instruction, so move past it. */
	cpu->regs->eip += insnlen;