x86, hvm: Allow emulation of 'multi-cycle' MMIO reads and writes,

which may require multiple round trips to the device model.

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
This commit is contained in:
Keir Fraser committed 2008-04-17 12:37:35 +01:00
1 parent 74a02d2244
commit 29a3d669c7
2 files changed
+84 -7

No files matched your search

+76 -5
View File
@@ -28,6 +28,33 @@ static int hvmemul_do_io(
ioreq_t *p = &vio->vp_ioreq;
int rc;
/* Only retrieve the value from singleton (non-REP) reads. */
ASSERT((val == NULL) || ((dir == IOREQ_READ) && !value_is_ptr));
if ( is_mmio && !value_is_ptr )
{
/* Part of a multi-cycle read or write? */
if ( dir == IOREQ_WRITE )
{
paddr_t pa = curr->arch.hvm_vcpu.mmio_large_write_pa;
unsigned int bytes = curr->arch.hvm_vcpu.mmio_large_write_bytes;
if ( (addr >= pa) && ((addr + size) <= (pa + bytes)) )
return X86EMUL_OKAY;
}
else
{
paddr_t pa = curr->arch.hvm_vcpu.mmio_large_read_pa;
unsigned int bytes = curr->arch.hvm_vcpu.mmio_large_read_bytes;
if ( (addr >= pa) && ((addr + size) <= (pa + bytes)) )
{
*val = 0;
memcpy(val, &curr->arch.hvm_vcpu.mmio_large_read[addr - pa],
size);
return X86EMUL_OKAY;
}
}
}
switch ( curr->arch.hvm_vcpu.io_state )
{
case HVMIO_none:
@@ -36,8 +63,13 @@ static int hvmemul_do_io(
curr->arch.hvm_vcpu.io_state = HVMIO_none;
if ( val == NULL )
return X86EMUL_UNHANDLEABLE;
*val = curr->arch.hvm_vcpu.io_data;
return X86EMUL_OKAY;
goto finish_access;
case HVMIO_dispatched:
/* May have to wait for previous cycle of a multi-write to complete. */
if ( is_mmio && !value_is_ptr && (dir == IOREQ_WRITE) &&
(addr == (curr->arch.hvm_vcpu.mmio_large_write_pa +
curr->arch.hvm_vcpu.mmio_large_write_bytes)) )
return X86EMUL_RETRY;
default:
return X86EMUL_UNHANDLEABLE;
}
@@ -80,8 +112,6 @@ static int hvmemul_do_io(
*reps = p->count;
p->state = STATE_IORESP_READY;
hvm_io_assist();
if ( val != NULL )
*val = curr->arch.hvm_vcpu.io_data;
curr->arch.hvm_vcpu.io_state = HVMIO_none;
break;
case X86EMUL_UNHANDLEABLE:
@@ -92,7 +122,43 @@ static int hvmemul_do_io(
BUG();
}
return rc;
if ( rc != X86EMUL_OKAY )
return rc;
finish_access:
if ( val != NULL )
*val = curr->arch.hvm_vcpu.io_data;
if ( is_mmio && !value_is_ptr )
{
/* Part of a multi-cycle read or write? */
if ( dir == IOREQ_WRITE )
{
paddr_t pa = curr->arch.hvm_vcpu.mmio_large_write_pa;
unsigned int bytes = curr->arch.hvm_vcpu.mmio_large_write_bytes;
if ( bytes == 0 )
pa = curr->arch.hvm_vcpu.mmio_large_write_pa = addr;
if ( addr == (pa + bytes) )
curr->arch.hvm_vcpu.mmio_large_write_bytes += size;
}
else
{
paddr_t pa = curr->arch.hvm_vcpu.mmio_large_read_pa;
unsigned int bytes = curr->arch.hvm_vcpu.mmio_large_read_bytes;
if ( bytes == 0 )
pa = curr->arch.hvm_vcpu.mmio_large_read_pa = addr;
if ( (addr == (pa + bytes)) &&
((bytes + size) <
sizeof(curr->arch.hvm_vcpu.mmio_large_read)) )
{
memcpy(&curr->arch.hvm_vcpu.mmio_large_read[addr - pa],
val, size);
curr->arch.hvm_vcpu.mmio_large_read_bytes += size;
}
}
}
return X86EMUL_OKAY;
}
static int hvmemul_do_pio(
@@ -793,6 +859,11 @@ int hvm_emulate_one(
hvmemul_ctxt->exn_pending = 0;
rc = x86_emulate(&hvmemul_ctxt->ctxt, &hvm_emulate_ops);
if ( rc != X86EMUL_RETRY )
curr->arch.hvm_vcpu.mmio_large_read_bytes =
curr->arch.hvm_vcpu.mmio_large_write_bytes = 0;
if ( rc != X86EMUL_OKAY )
return rc;
+8 -2
View File
@@ -83,10 +83,16 @@ struct hvm_vcpu {
*/
unsigned long mmio_gva;
unsigned long mmio_gpfn;
/* Callback into x86_emulate when emulating FPU/MMX/XMM instructions. */
void (*fpu_exception_callback)(void *, struct cpu_user_regs *);
void *fpu_exception_callback_arg;
/* We may read up to m128 as a number of device-model transactions. */
paddr_t mmio_large_read_pa;
uint8_t mmio_large_read[16];
unsigned int mmio_large_read_bytes;
/* We may write up to m128 as a number of device-model transactions. */
paddr_t mmio_large_write_pa;
unsigned int mmio_large_write_bytes;
};
#endif /* __ASM_X86_HVM_VCPU_H__ */
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.