Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 197700
b: refs/heads/master
c: 7b262e9
h: refs/heads/master
v: v3
  • Loading branch information
Gleb Natapov authored and Avi Kivity committed May 17, 2010
1 parent 943abb4 commit f497e91
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 6 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 5cd21917da245fbe98bd443de2c7f519b3df6814
refs/heads/master: 7b262e90fc20a49fddf3dad94c8cead1f0439751
7 changes: 7 additions & 0 deletions trunk/arch/x86/include/asm/kvm_emulate.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,12 @@ struct fetch_cache {
unsigned long end;
};

struct read_cache {
u8 data[1024];
unsigned long pos;
unsigned long end;
};

struct decode_cache {
u8 twobyte;
u8 b;
Expand Down Expand Up @@ -178,6 +184,7 @@ struct decode_cache {
void *modrm_ptr;
unsigned long modrm_val;
struct fetch_cache fetch;
struct read_cache io_read;
};

struct x86_emulate_ctxt {
Expand Down
46 changes: 41 additions & 5 deletions trunk/arch/x86/kvm/emulate.c
Original file line number Diff line number Diff line change
Expand Up @@ -1257,6 +1257,36 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
return (rc == X86EMUL_UNHANDLEABLE) ? -1 : 0;
}

static int pio_in_emulated(struct x86_emulate_ctxt *ctxt,
struct x86_emulate_ops *ops,
unsigned int size, unsigned short port,
void *dest)
{
struct read_cache *rc = &ctxt->decode.io_read;

if (rc->pos == rc->end) { /* refill pio read ahead */
struct decode_cache *c = &ctxt->decode;
unsigned int in_page, n;
unsigned int count = c->rep_prefix ?
address_mask(c, c->regs[VCPU_REGS_RCX]) : 1;
in_page = (ctxt->eflags & EFLG_DF) ?
offset_in_page(c->regs[VCPU_REGS_RDI]) :
PAGE_SIZE - offset_in_page(c->regs[VCPU_REGS_RDI]);
n = min(min(in_page, (unsigned int)sizeof(rc->data)) / size,
count);
if (n == 0)
n = 1;
rc->pos = rc->end = 0;
if (!ops->pio_in_emulated(size, port, rc->data, n, ctxt->vcpu))
return 0;
rc->end = n * size;
}

memcpy(dest, rc->data + rc->pos, size);
rc->pos += size;
return 1;
}

static u32 desc_limit_scaled(struct desc_struct *desc)
{
u32 limit = get_desc_limit(desc);
Expand Down Expand Up @@ -2622,8 +2652,8 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
kvm_inject_gp(ctxt->vcpu, 0);
goto done;
}
if (!ops->pio_in_emulated(c->dst.bytes, c->regs[VCPU_REGS_RDX],
&c->dst.val, 1, ctxt->vcpu))
if (!pio_in_emulated(ctxt, ops, c->dst.bytes,
c->regs[VCPU_REGS_RDX], &c->dst.val))
goto done; /* IO is needed, skip writeback */
break;
case 0x6e: /* outsb */
Expand Down Expand Up @@ -2839,8 +2869,8 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
kvm_inject_gp(ctxt->vcpu, 0);
goto done;
}
if (!ops->pio_in_emulated(c->dst.bytes, c->src.val,
&c->dst.val, 1, ctxt->vcpu))
if (!pio_in_emulated(ctxt, ops, c->dst.bytes, c->src.val,
&c->dst.val))
goto done; /* IO is needed */
break;
case 0xee: /* out al,dx */
Expand Down Expand Up @@ -2928,8 +2958,14 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
string_addr_inc(ctxt, es_base(ctxt), VCPU_REGS_RDI, &c->dst);

if (c->rep_prefix && (c->d & String)) {
struct read_cache *rc = &ctxt->decode.io_read;
register_address_increment(c, &c->regs[VCPU_REGS_RCX], -1);
if (!(c->regs[VCPU_REGS_RCX] & 0x3ff))
/*
* Re-enter guest when pio read ahead buffer is empty or,
* if it is not used, after each 1024 iteration.
*/
if ((rc->end == 0 && !(c->regs[VCPU_REGS_RCX] & 0x3ff)) ||
(rc->end != 0 && rc->end == rc->pos))
ctxt->restart = false;
}

Expand Down

0 comments on commit f497e91

Please sign in to comment.