*/
void hvmemul_cancel(struct vcpu *v)
{
- struct hvm_vcpu_io *vio = &v->arch.hvm.hvm_io;
+ struct hvm_vcpu_io *hvio = &v->arch.hvm.hvm_io;
- vio->io_req.state = STATE_IOREQ_NONE;
- vio->io_completion = HVMIO_no_completion;
- vio->mmio_cache_count = 0;
- vio->mmio_insn_bytes = 0;
- vio->mmio_access = (struct npfec){};
- vio->mmio_retry = false;
- vio->g2m_ioport = NULL;
+ v->io.req.state = STATE_IOREQ_NONE;
+ v->io.completion = VIO_no_completion;
+ hvio->mmio_cache_count = 0;
+ hvio->mmio_insn_bytes = 0;
+ hvio->mmio_access = (struct npfec){};
+ hvio->mmio_retry = false;
+ hvio->g2m_ioport = NULL;
hvmemul_cache_disable(v);
}
{
struct vcpu *curr = current;
struct domain *currd = curr->domain;
- struct hvm_vcpu_io *vio = &curr->arch.hvm.hvm_io;
+ struct vcpu_io *vio = &curr->io;
ioreq_t p = {
.type = is_mmio ? IOREQ_TYPE_COPY : IOREQ_TYPE_PIO,
.addr = addr,
return X86EMUL_UNHANDLEABLE;
}
- switch ( vio->io_req.state )
+ switch ( vio->req.state )
{
case STATE_IOREQ_NONE:
break;
case STATE_IORESP_READY:
- vio->io_req.state = STATE_IOREQ_NONE;
- p = vio->io_req;
+ vio->req.state = STATE_IOREQ_NONE;
+ p = vio->req;
/* Verify the emulation request has been correctly re-issued */
if ( (p.type != (is_mmio ? IOREQ_TYPE_COPY : IOREQ_TYPE_PIO)) ||
}
ASSERT(p.count);
- vio->io_req = p;
+ vio->req = p;
rc = hvm_io_intercept(&p);
* our callers and mirror this into latched state.
*/
ASSERT(p.count <= *reps);
- *reps = vio->io_req.count = p.count;
+ *reps = vio->req.count = p.count;
switch ( rc )
{
case X86EMUL_OKAY:
- vio->io_req.state = STATE_IOREQ_NONE;
+ vio->req.state = STATE_IOREQ_NONE;
break;
case X86EMUL_UNHANDLEABLE:
{
if ( s == NULL )
{
rc = X86EMUL_RETRY;
- vio->io_req.state = STATE_IOREQ_NONE;
+ vio->req.state = STATE_IOREQ_NONE;
break;
}
if ( dir == IOREQ_READ )
{
rc = hvm_process_io_intercept(&ioreq_server_handler, &p);
- vio->io_req.state = STATE_IOREQ_NONE;
+ vio->req.state = STATE_IOREQ_NONE;
break;
}
}
if ( !s )
{
rc = hvm_process_io_intercept(&null_handler, &p);
- vio->io_req.state = STATE_IOREQ_NONE;
+ vio->req.state = STATE_IOREQ_NONE;
}
else
{
rc = hvm_send_ioreq(s, &p, 0);
if ( rc != X86EMUL_RETRY || currd->is_shutting_down )
- vio->io_req.state = STATE_IOREQ_NONE;
- else if ( !ioreq_needs_completion(&vio->io_req) )
+ vio->req.state = STATE_IOREQ_NONE;
+ else if ( !ioreq_needs_completion(&vio->req) )
rc = X86EMUL_OKAY;
}
break;
* cache indexed by linear MMIO address.
*/
static struct hvm_mmio_cache *hvmemul_find_mmio_cache(
- struct hvm_vcpu_io *vio, unsigned long gla, uint8_t dir, bool create)
+ struct hvm_vcpu_io *hvio, unsigned long gla, uint8_t dir, bool create)
{
unsigned int i;
struct hvm_mmio_cache *cache;
- for ( i = 0; i < vio->mmio_cache_count; i ++ )
+ for ( i = 0; i < hvio->mmio_cache_count; i ++ )
{
- cache = &vio->mmio_cache[i];
+ cache = &hvio->mmio_cache[i];
if ( gla == cache->gla &&
dir == cache->dir )
if ( !create )
return NULL;
- i = vio->mmio_cache_count;
- if( i == ARRAY_SIZE(vio->mmio_cache) )
+ i = hvio->mmio_cache_count;
+ if( i == ARRAY_SIZE(hvio->mmio_cache) )
return NULL;
- ++vio->mmio_cache_count;
+ ++hvio->mmio_cache_count;
- cache = &vio->mmio_cache[i];
+ cache = &hvio->mmio_cache[i];
memset(cache, 0, sizeof (*cache));
cache->gla = gla;
return cache;
}
-static void latch_linear_to_phys(struct hvm_vcpu_io *vio, unsigned long gla,
+static void latch_linear_to_phys(struct hvm_vcpu_io *hvio, unsigned long gla,
unsigned long gpa, bool_t write)
{
- if ( vio->mmio_access.gla_valid )
+ if ( hvio->mmio_access.gla_valid )
return;
- vio->mmio_gla = gla & PAGE_MASK;
- vio->mmio_gpfn = PFN_DOWN(gpa);
- vio->mmio_access = (struct npfec){ .gla_valid = 1,
- .read_access = 1,
- .write_access = write };
+ hvio->mmio_gla = gla & PAGE_MASK;
+ hvio->mmio_gpfn = PFN_DOWN(gpa);
+ hvio->mmio_access = (struct npfec){ .gla_valid = 1,
+ .read_access = 1,
+ .write_access = write };
}
static int hvmemul_linear_mmio_access(
unsigned long gla, unsigned int size, uint8_t dir, void *buffer,
uint32_t pfec, struct hvm_emulate_ctxt *hvmemul_ctxt, bool_t known_gpfn)
{
- struct hvm_vcpu_io *vio = ¤t->arch.hvm.hvm_io;
+ struct hvm_vcpu_io *hvio = ¤t->arch.hvm.hvm_io;
unsigned long offset = gla & ~PAGE_MASK;
- struct hvm_mmio_cache *cache = hvmemul_find_mmio_cache(vio, gla, dir, true);
+ struct hvm_mmio_cache *cache = hvmemul_find_mmio_cache(hvio, gla, dir, true);
unsigned int chunk, buffer_offset = 0;
paddr_t gpa;
unsigned long one_rep = 1;
chunk = min_t(unsigned int, size, PAGE_SIZE - offset);
if ( known_gpfn )
- gpa = pfn_to_paddr(vio->mmio_gpfn) | offset;
+ gpa = pfn_to_paddr(hvio->mmio_gpfn) | offset;
else
{
rc = hvmemul_linear_to_phys(gla, &gpa, chunk, &one_rep, pfec,
if ( rc != X86EMUL_OKAY )
return rc;
- latch_linear_to_phys(vio, gla, gpa, dir == IOREQ_WRITE);
+ latch_linear_to_phys(hvio, gla, gpa, dir == IOREQ_WRITE);
}
for ( ;; )
static bool known_gla(unsigned long addr, unsigned int bytes, uint32_t pfec)
{
- const struct hvm_vcpu_io *vio = ¤t->arch.hvm.hvm_io;
+ const struct hvm_vcpu_io *hvio = ¤t->arch.hvm.hvm_io;
if ( pfec & PFEC_write_access )
{
- if ( !vio->mmio_access.write_access )
+ if ( !hvio->mmio_access.write_access )
return false;
}
else if ( pfec & PFEC_insn_fetch )
{
- if ( !vio->mmio_access.insn_fetch )
+ if ( !hvio->mmio_access.insn_fetch )
return false;
}
- else if ( !vio->mmio_access.read_access )
+ else if ( !hvio->mmio_access.read_access )
return false;
- return (vio->mmio_gla == (addr & PAGE_MASK) &&
+ return (hvio->mmio_gla == (addr & PAGE_MASK) &&
(addr & ~PAGE_MASK) + bytes <= PAGE_SIZE);
}
uint32_t pfec, struct hvm_emulate_ctxt *hvmemul_ctxt)
{
pagefault_info_t pfinfo;
- struct hvm_vcpu_io *vio = ¤t->arch.hvm.hvm_io;
+ struct hvm_vcpu_io *hvio = ¤t->arch.hvm.hvm_io;
unsigned int offset = addr & ~PAGE_MASK;
int rc = HVMTRANS_bad_gfn_to_mfn;
* we handle this access in the same way to guarantee completion and hence
* clean up any interim state.
*/
- if ( !hvmemul_find_mmio_cache(vio, addr, IOREQ_READ, false) )
+ if ( !hvmemul_find_mmio_cache(hvio, addr, IOREQ_READ, false) )
rc = hvm_copy_from_guest_linear(p_data, addr, bytes, pfec, &pfinfo);
switch ( rc )
uint32_t pfec, struct hvm_emulate_ctxt *hvmemul_ctxt)
{
pagefault_info_t pfinfo;
- struct hvm_vcpu_io *vio = ¤t->arch.hvm.hvm_io;
+ struct hvm_vcpu_io *hvio = ¤t->arch.hvm.hvm_io;
unsigned int offset = addr & ~PAGE_MASK;
int rc = HVMTRANS_bad_gfn_to_mfn;
* we handle this access in the same way to guarantee completion and hence
* clean up any interim state.
*/
- if ( !hvmemul_find_mmio_cache(vio, addr, IOREQ_WRITE, false) )
+ if ( !hvmemul_find_mmio_cache(hvio, addr, IOREQ_WRITE, false) )
rc = hvm_copy_to_guest_linear(addr, p_data, bytes, pfec, &pfinfo);
switch ( rc )
struct vcpu *curr = current;
unsigned long addr;
uint32_t pfec = PFEC_page_present | PFEC_write_access;
- struct hvm_vcpu_io *vio = &curr->arch.hvm.hvm_io;
+ struct hvm_vcpu_io *hvio = &curr->arch.hvm.hvm_io;
int rc;
void *mapping = NULL;
/* Fix this in case the guest is really relying on r-m-w atomicity. */
return hvmemul_linear_mmio_write(addr, bytes, p_new, pfec,
hvmemul_ctxt,
- vio->mmio_access.write_access &&
- vio->mmio_gla == (addr & PAGE_MASK));
+ hvio->mmio_access.write_access &&
+ hvio->mmio_gla == (addr & PAGE_MASK));
}
switch ( bytes )
struct hvm_emulate_ctxt *hvmemul_ctxt =
container_of(ctxt, struct hvm_emulate_ctxt, ctxt);
struct vcpu *curr = current;
- struct hvm_vcpu_io *vio = &curr->arch.hvm.hvm_io;
+ struct hvm_vcpu_io *hvio = &curr->arch.hvm.hvm_io;
unsigned long saddr, daddr, bytes;
paddr_t sgpa, dgpa;
uint32_t pfec = PFEC_page_present;
if ( hvmemul_ctxt->seg_reg[x86_seg_ss].dpl == 3 )
pfec |= PFEC_user_mode;
- if ( vio->mmio_access.read_access &&
- (vio->mmio_gla == (saddr & PAGE_MASK)) &&
+ if ( hvio->mmio_access.read_access &&
+ (hvio->mmio_gla == (saddr & PAGE_MASK)) &&
/*
* Upon initial invocation don't truncate large batches just because
* of a hit for the translation: Doing the guest page table walk is
* cheaper than multiple round trips through the device model. Yet
* when processing a response we can always re-use the translation.
*/
- (vio->io_req.state == STATE_IORESP_READY ||
+ (curr->io.req.state == STATE_IORESP_READY ||
((!df || *reps == 1) &&
PAGE_SIZE - (saddr & ~PAGE_MASK) >= *reps * bytes_per_rep)) )
- sgpa = pfn_to_paddr(vio->mmio_gpfn) | (saddr & ~PAGE_MASK);
+ sgpa = pfn_to_paddr(hvio->mmio_gpfn) | (saddr & ~PAGE_MASK);
else
{
rc = hvmemul_linear_to_phys(saddr, &sgpa, bytes_per_rep, reps, pfec,
}
bytes = PAGE_SIZE - (daddr & ~PAGE_MASK);
- if ( vio->mmio_access.write_access &&
- (vio->mmio_gla == (daddr & PAGE_MASK)) &&
+ if ( hvio->mmio_access.write_access &&
+ (hvio->mmio_gla == (daddr & PAGE_MASK)) &&
/* See comment above. */
- (vio->io_req.state == STATE_IORESP_READY ||
+ (curr->io.req.state == STATE_IORESP_READY ||
((!df || *reps == 1) &&
PAGE_SIZE - (daddr & ~PAGE_MASK) >= *reps * bytes_per_rep)) )
- dgpa = pfn_to_paddr(vio->mmio_gpfn) | (daddr & ~PAGE_MASK);
+ dgpa = pfn_to_paddr(hvio->mmio_gpfn) | (daddr & ~PAGE_MASK);
else
{
rc = hvmemul_linear_to_phys(daddr, &dgpa, bytes_per_rep, reps,
if ( sp2mt == p2m_mmio_dm )
{
- latch_linear_to_phys(vio, saddr, sgpa, 0);
+ latch_linear_to_phys(hvio, saddr, sgpa, 0);
return hvmemul_do_mmio_addr(
sgpa, reps, bytes_per_rep, IOREQ_READ, df, dgpa);
}
if ( dp2mt == p2m_mmio_dm )
{
- latch_linear_to_phys(vio, daddr, dgpa, 1);
+ latch_linear_to_phys(hvio, daddr, dgpa, 1);
return hvmemul_do_mmio_addr(
dgpa, reps, bytes_per_rep, IOREQ_WRITE, df, sgpa);
}
struct hvm_emulate_ctxt *hvmemul_ctxt =
container_of(ctxt, struct hvm_emulate_ctxt, ctxt);
struct vcpu *curr = current;
- struct hvm_vcpu_io *vio = &curr->arch.hvm.hvm_io;
+ struct hvm_vcpu_io *hvio = &curr->arch.hvm.hvm_io;
unsigned long addr, bytes;
paddr_t gpa;
p2m_type_t p2mt;
return rc;
bytes = PAGE_SIZE - (addr & ~PAGE_MASK);
- if ( vio->mmio_access.write_access &&
- (vio->mmio_gla == (addr & PAGE_MASK)) &&
+ if ( hvio->mmio_access.write_access &&
+ (hvio->mmio_gla == (addr & PAGE_MASK)) &&
/* See respective comment in MOVS processing. */
- (vio->io_req.state == STATE_IORESP_READY ||
+ (curr->io.req.state == STATE_IORESP_READY ||
((!df || *reps == 1) &&
PAGE_SIZE - (addr & ~PAGE_MASK) >= *reps * bytes_per_rep)) )
- gpa = pfn_to_paddr(vio->mmio_gpfn) | (addr & ~PAGE_MASK);
+ gpa = pfn_to_paddr(hvio->mmio_gpfn) | (addr & ~PAGE_MASK);
else
{
uint32_t pfec = PFEC_page_present | PFEC_write_access;
return X86EMUL_UNHANDLEABLE;
case p2m_mmio_dm:
- latch_linear_to_phys(vio, addr, gpa, 1);
+ latch_linear_to_phys(hvio, addr, gpa, 1);
return hvmemul_do_mmio_buffer(gpa, reps, bytes_per_rep, IOREQ_WRITE, df,
p_data);
}
};
/*
- * Note that passing HVMIO_no_completion into this function serves as kind
+ * Note that passing VIO_no_completion into this function serves as kind
* of (but not fully) an "auto select completion" indicator. When there's
* no completion needed, the passed in value will be ignored in any case.
*/
static int _hvm_emulate_one(struct hvm_emulate_ctxt *hvmemul_ctxt,
const struct x86_emulate_ops *ops,
- enum hvm_io_completion completion)
+ enum vio_completion completion)
{
const struct cpu_user_regs *regs = hvmemul_ctxt->ctxt.regs;
struct vcpu *curr = current;
uint32_t new_intr_shadow;
- struct hvm_vcpu_io *vio = &curr->arch.hvm.hvm_io;
+ struct hvm_vcpu_io *hvio = &curr->arch.hvm.hvm_io;
int rc;
/*
* untouched if it's already enabled, for re-execution to consume
* entries populated by an earlier pass.
*/
- if ( vio->cache->num_ents > vio->cache->max_ents )
+ if ( hvio->cache->num_ents > hvio->cache->max_ents )
{
- ASSERT(vio->io_req.state == STATE_IOREQ_NONE);
- vio->cache->num_ents = 0;
+ ASSERT(curr->io.req.state == STATE_IOREQ_NONE);
+ hvio->cache->num_ents = 0;
}
else
- ASSERT(vio->io_req.state == STATE_IORESP_READY);
+ ASSERT(curr->io.req.state == STATE_IORESP_READY);
- hvm_emulate_init_per_insn(hvmemul_ctxt, vio->mmio_insn,
- vio->mmio_insn_bytes);
+ hvm_emulate_init_per_insn(hvmemul_ctxt, hvio->mmio_insn,
+ hvio->mmio_insn_bytes);
- vio->mmio_retry = 0;
+ hvio->mmio_retry = 0;
rc = x86_emulate(&hvmemul_ctxt->ctxt, ops);
- if ( rc == X86EMUL_OKAY && vio->mmio_retry )
+ if ( rc == X86EMUL_OKAY && hvio->mmio_retry )
rc = X86EMUL_RETRY;
- if ( !ioreq_needs_completion(&vio->io_req) )
- completion = HVMIO_no_completion;
- else if ( completion == HVMIO_no_completion )
- completion = (vio->io_req.type != IOREQ_TYPE_PIO ||
- hvmemul_ctxt->is_mem_access) ? HVMIO_mmio_completion
- : HVMIO_pio_completion;
+ if ( !ioreq_needs_completion(&curr->io.req) )
+ completion = VIO_no_completion;
+ else if ( completion == VIO_no_completion )
+ completion = (curr->io.req.type != IOREQ_TYPE_PIO ||
+ hvmemul_ctxt->is_mem_access) ? VIO_mmio_completion
+ : VIO_pio_completion;
- switch ( vio->io_completion = completion )
+ switch ( curr->io.completion = completion )
{
- case HVMIO_no_completion:
- case HVMIO_pio_completion:
- vio->mmio_cache_count = 0;
- vio->mmio_insn_bytes = 0;
- vio->mmio_access = (struct npfec){};
+ case VIO_no_completion:
+ case VIO_pio_completion:
+ hvio->mmio_cache_count = 0;
+ hvio->mmio_insn_bytes = 0;
+ hvio->mmio_access = (struct npfec){};
hvmemul_cache_disable(curr);
break;
- case HVMIO_mmio_completion:
- case HVMIO_realmode_completion:
- BUILD_BUG_ON(sizeof(vio->mmio_insn) < sizeof(hvmemul_ctxt->insn_buf));
- vio->mmio_insn_bytes = hvmemul_ctxt->insn_buf_bytes;
- memcpy(vio->mmio_insn, hvmemul_ctxt->insn_buf, vio->mmio_insn_bytes);
+ case VIO_mmio_completion:
+ case VIO_realmode_completion:
+ BUILD_BUG_ON(sizeof(hvio->mmio_insn) < sizeof(hvmemul_ctxt->insn_buf));
+ hvio->mmio_insn_bytes = hvmemul_ctxt->insn_buf_bytes;
+ memcpy(hvio->mmio_insn, hvmemul_ctxt->insn_buf, hvio->mmio_insn_bytes);
break;
default:
int hvm_emulate_one(
struct hvm_emulate_ctxt *hvmemul_ctxt,
- enum hvm_io_completion completion)
+ enum vio_completion completion)
{
return _hvm_emulate_one(hvmemul_ctxt, &hvm_emulate_ops, completion);
}
guest_cpu_user_regs());
ctxt.ctxt.data = &mmio_ro_ctxt;
- switch ( rc = _hvm_emulate_one(&ctxt, ops, HVMIO_no_completion) )
+ switch ( rc = _hvm_emulate_one(&ctxt, ops, VIO_no_completion) )
{
case X86EMUL_UNHANDLEABLE:
case X86EMUL_UNIMPLEMENTED:
{
case EMUL_KIND_NOWRITE:
rc = _hvm_emulate_one(&ctx, &hvm_emulate_ops_no_write,
- HVMIO_no_completion);
+ VIO_no_completion);
break;
case EMUL_KIND_SET_CONTEXT_INSN: {
struct vcpu *curr = current;
- struct hvm_vcpu_io *vio = &curr->arch.hvm.hvm_io;
+ struct hvm_vcpu_io *hvio = &curr->arch.hvm.hvm_io;
- BUILD_BUG_ON(sizeof(vio->mmio_insn) !=
+ BUILD_BUG_ON(sizeof(hvio->mmio_insn) !=
sizeof(curr->arch.vm_event->emul.insn.data));
- ASSERT(!vio->mmio_insn_bytes);
+ ASSERT(!hvio->mmio_insn_bytes);
/*
* Stash insn buffer into mmio buffer here instead of ctx
* to avoid having to add more logic to hvm_emulate_one.
*/
- vio->mmio_insn_bytes = sizeof(vio->mmio_insn);
- memcpy(vio->mmio_insn, curr->arch.vm_event->emul.insn.data,
- vio->mmio_insn_bytes);
+ hvio->mmio_insn_bytes = sizeof(hvio->mmio_insn);
+ memcpy(hvio->mmio_insn, curr->arch.vm_event->emul.insn.data,
+ hvio->mmio_insn_bytes);
}
/* Fall-through */
default:
ctx.set_context = (kind == EMUL_KIND_SET_CONTEXT_DATA);
- rc = hvm_emulate_one(&ctx, HVMIO_no_completion);
+ rc = hvm_emulate_one(&ctx, VIO_no_completion);
}
switch ( rc )