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

Commit 62266869 authored by Avi Kivity's avatar Avi Kivity
Browse files

KVM: x86 emulator: prefetch up to 15 bytes of the instruction executed



Instead of fetching one byte at a time, prefetch 15 bytes (or until the next
page boundary) to avoid guest page table walks.

Signed-off-by: default avatarAvi Kivity <avi@qumranet.com>
parent 93a0039c
Loading
Loading
Loading
Loading
+36 −2
Original line number Diff line number Diff line
@@ -414,8 +414,7 @@ static u16 twobyte_table[256] = {
/* Fetch next part of the instruction being emulated. */
#define insn_fetch(_type, _size, _eip)                                  \
({	unsigned long _x;						\
	rc = ops->read_std((unsigned long)(_eip) + ctxt->cs_base, &_x,	\
			   (_size), ctxt->vcpu);			\
	rc = do_insn_fetch(ctxt, ops, (_eip), &_x, (_size));		\
	if (rc != 0)							\
		goto done;						\
	(_eip) += (_size);						\
@@ -446,6 +445,41 @@ static u16 twobyte_table[256] = {
		register_address_increment(c->eip, rel);		\
	} while (0)

static int do_fetch_insn_byte(struct x86_emulate_ctxt *ctxt,
			      struct x86_emulate_ops *ops,
			      unsigned long linear, u8 *dest)
{
	struct fetch_cache *fc = &ctxt->decode.fetch;
	int rc;
	int size;

	if (linear < fc->start || linear >= fc->end) {
		size = min(15UL, PAGE_SIZE - offset_in_page(linear));
		rc = ops->read_std(linear, fc->data, size, ctxt->vcpu);
		if (rc)
			return rc;
		fc->start = linear;
		fc->end = linear + size;
	}
	*dest = fc->data[linear - fc->start];
	return 0;
}

static int do_insn_fetch(struct x86_emulate_ctxt *ctxt,
			 struct x86_emulate_ops *ops,
			 unsigned long eip, void *dest, unsigned size)
{
	int rc = 0;

	eip += ctxt->cs_base;
	while (size--) {
		rc = do_fetch_insn_byte(ctxt, ops, eip++, dest++);
		if (rc)
			return rc;
	}
	return 0;
}

/*
 * Given the 'reg' portion of a ModRM byte, and a register block, return a
 * pointer into the block that addresses the relevant register.
+7 −0
Original line number Diff line number Diff line
@@ -108,6 +108,12 @@ struct operand {
	unsigned long val, orig_val, *ptr;
};

struct fetch_cache {
	u8 data[15];
	unsigned long start;
	unsigned long end;
};

struct decode_cache {
	u8 twobyte;
	u8 b;
@@ -130,6 +136,7 @@ struct decode_cache {
	u8 use_modrm_ea;
	unsigned long modrm_ea;
	unsigned long modrm_val;
	struct fetch_cache fetch;
};

struct x86_emulate_ctxt {