mirror of
https://github.com/xen-project/xen.git
synced 2026-10-30 03:00:05 +01:00
[HVM] MMIO/PIO fixes and cleanups.
1. Fix MMIO/PIO cross page boundary copy for MOVS and OUTS/INS
handling.
2. Clean up send_mmio_req/send_pio_req interface.
3. Clean up handle_mmio.
Signed-off-by: Xin Li <xin.b.li@intel.com>
Signed-off-by: Xiaowei Yang <xiaowei.yang@intel.com>
Signed-off-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
1 parent
3943db7763
commit
a20cc3e41a
8 files changed
+503
-512
No files matched your search
@@ -61,49 +61,39 @@ static inline void hvm_mmio_access(struct vcpu *v,
|
||||
hvm_mmio_read_t read_handler,
|
||||
hvm_mmio_write_t write_handler)
|
||||
{
|
||||
ioreq_t *req;
|
||||
vcpu_iodata_t *vio = get_vio(v->domain, v->vcpu_id);
|
||||
unsigned int tmp1, tmp2;
|
||||
unsigned long data;
|
||||
|
||||
if (vio == NULL) {
|
||||
printk("vlapic_access: bad shared page\n");
|
||||
domain_crash_synchronous();
|
||||
}
|
||||
|
||||
req = &vio->vp_ioreq;
|
||||
|
||||
switch (req->type) {
|
||||
switch ( p->type ) {
|
||||
case IOREQ_TYPE_COPY:
|
||||
{
|
||||
int sign = (req->df) ? -1 : 1, i;
|
||||
if ( !p->pdata_valid ) {
|
||||
if ( p->dir == IOREQ_READ )
|
||||
p->u.data = read_handler(v, p->addr, p->size);
|
||||
else /* p->dir == IOREQ_WRITE */
|
||||
write_handler(v, p->addr, p->size, p->u.data);
|
||||
} else { /* !p->pdata_valid */
|
||||
int i, sign = (p->df) ? -1 : 1;
|
||||
|
||||
if (!req->pdata_valid) {
|
||||
if (req->dir == IOREQ_READ){
|
||||
req->u.data = read_handler(v, req->addr, req->size);
|
||||
} else { /* req->dir != IOREQ_READ */
|
||||
write_handler(v, req->addr, req->size, req->u.data);
|
||||
}
|
||||
} else { /* !req->pdata_valid */
|
||||
if (req->dir == IOREQ_READ) {
|
||||
for (i = 0; i < req->count; i++) {
|
||||
if ( p->dir == IOREQ_READ ) {
|
||||
for ( i = 0; i < p->count; i++ ) {
|
||||
data = read_handler(v,
|
||||
req->addr + (sign * i * req->size),
|
||||
req->size);
|
||||
(void)hvm_copy_to_guest_virt(
|
||||
(unsigned long)p->u.pdata + (sign * i * req->size),
|
||||
p->addr + (sign * i * p->size),
|
||||
p->size);
|
||||
(void)hvm_copy_to_guest_phys(
|
||||
(unsigned long)p->u.pdata + (sign * i * p->size),
|
||||
&data,
|
||||
p->size);
|
||||
}
|
||||
} else { /* !req->dir == IOREQ_READ */
|
||||
for (i = 0; i < req->count; i++) {
|
||||
(void)hvm_copy_from_guest_virt(
|
||||
} else {/* p->dir == IOREQ_WRITE */
|
||||
for ( i = 0; i < p->count; i++ ) {
|
||||
(void)hvm_copy_from_guest_phys(
|
||||
&data,
|
||||
(unsigned long)p->u.pdata + (sign * i * req->size),
|
||||
(unsigned long)p->u.pdata + (sign * i * p->size),
|
||||
p->size);
|
||||
write_handler(v,
|
||||
req->addr + (sign * i * req->size),
|
||||
req->size, data);
|
||||
p->addr + (sign * i * p->size),
|
||||
p->size, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -111,44 +101,44 @@ static inline void hvm_mmio_access(struct vcpu *v,
|
||||
}
|
||||
|
||||
case IOREQ_TYPE_AND:
|
||||
tmp1 = read_handler(v, req->addr, req->size);
|
||||
if (req->dir == IOREQ_WRITE) {
|
||||
tmp2 = tmp1 & (unsigned long) req->u.data;
|
||||
write_handler(v, req->addr, req->size, tmp2);
|
||||
tmp1 = read_handler(v, p->addr, p->size);
|
||||
if ( p->dir == IOREQ_WRITE ) {
|
||||
tmp2 = tmp1 & (unsigned long) p->u.data;
|
||||
write_handler(v, p->addr, p->size, tmp2);
|
||||
}
|
||||
req->u.data = tmp1;
|
||||
p->u.data = tmp1;
|
||||
break;
|
||||
|
||||
case IOREQ_TYPE_OR:
|
||||
tmp1 = read_handler(v, req->addr, req->size);
|
||||
if (req->dir == IOREQ_WRITE) {
|
||||
tmp2 = tmp1 | (unsigned long) req->u.data;
|
||||
write_handler(v, req->addr, req->size, tmp2);
|
||||
tmp1 = read_handler(v, p->addr, p->size);
|
||||
if ( p->dir == IOREQ_WRITE ) {
|
||||
tmp2 = tmp1 | (unsigned long) p->u.data;
|
||||
write_handler(v, p->addr, p->size, tmp2);
|
||||
}
|
||||
req->u.data = tmp1;
|
||||
p->u.data = tmp1;
|
||||
break;
|
||||
|
||||
case IOREQ_TYPE_XOR:
|
||||
tmp1 = read_handler(v, req->addr, req->size);
|
||||
if (req->dir == IOREQ_WRITE) {
|
||||
tmp2 = tmp1 ^ (unsigned long) req->u.data;
|
||||
write_handler(v, req->addr, req->size, tmp2);
|
||||
tmp1 = read_handler(v, p->addr, p->size);
|
||||
if ( p->dir == IOREQ_WRITE ) {
|
||||
tmp2 = tmp1 ^ (unsigned long) p->u.data;
|
||||
write_handler(v, p->addr, p->size, tmp2);
|
||||
}
|
||||
req->u.data = tmp1;
|
||||
p->u.data = tmp1;
|
||||
break;
|
||||
|
||||
case IOREQ_TYPE_XCHG:
|
||||
/*
|
||||
/*
|
||||
* Note that we don't need to be atomic here since VCPU is accessing
|
||||
* its own local APIC.
|
||||
*/
|
||||
tmp1 = read_handler(v, req->addr, req->size);
|
||||
write_handler(v, req->addr, req->size, (unsigned long) req->u.data);
|
||||
req->u.data = tmp1;
|
||||
tmp1 = read_handler(v, p->addr, p->size);
|
||||
write_handler(v, p->addr, p->size, (unsigned long) p->u.data);
|
||||
p->u.data = tmp1;
|
||||
break;
|
||||
|
||||
default:
|
||||
printk("error ioreq type for local APIC %x\n", req->type);
|
||||
printk("hvm_mmio_access: error ioreq type %x\n", p->type);
|
||||
domain_crash_synchronous();
|
||||
break;
|
||||
}
|
||||
|
||||
+20
-17
@@ -369,18 +369,18 @@ static void hvm_pio_assist(struct cpu_user_regs *regs, ioreq_t *p,
|
||||
{
|
||||
if ( pio_opp->flags & REPZ )
|
||||
regs->ecx -= p->count;
|
||||
|
||||
if ( p->dir == IOREQ_READ )
|
||||
{
|
||||
regs->edi += sign * p->count * p->size;
|
||||
if ( pio_opp->flags & OVERLAP )
|
||||
{
|
||||
unsigned long addr = regs->edi;
|
||||
if (hvm_realmode(current))
|
||||
addr += regs->es << 4;
|
||||
if (sign > 0)
|
||||
addr -= p->size;
|
||||
(void)hvm_copy_to_guest_virt(addr, &p->u.data, p->size);
|
||||
unsigned long addr = pio_opp->addr;
|
||||
if ( hvm_paging_enabled(current) )
|
||||
(void)hvm_copy_to_guest_virt(addr, &p->u.data, p->size);
|
||||
else
|
||||
(void)hvm_copy_to_guest_phys(addr, &p->u.data, p->size);
|
||||
}
|
||||
regs->edi += sign * p->count * p->size;
|
||||
}
|
||||
else /* p->dir == IOREQ_WRITE */
|
||||
{
|
||||
@@ -485,19 +485,22 @@ static void hvm_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p,
|
||||
|
||||
case INSTR_MOVS:
|
||||
sign = p->df ? -1 : 1;
|
||||
regs->esi += sign * p->count * p->size;
|
||||
regs->edi += sign * p->count * p->size;
|
||||
|
||||
if ((mmio_opp->flags & OVERLAP) && p->dir == IOREQ_READ) {
|
||||
unsigned long addr = regs->edi;
|
||||
|
||||
if (sign > 0)
|
||||
addr -= p->size;
|
||||
(void)hvm_copy_to_guest_virt(addr, &p->u.data, p->size);
|
||||
}
|
||||
|
||||
if (mmio_opp->flags & REPZ)
|
||||
regs->ecx -= p->count;
|
||||
|
||||
if ((mmio_opp->flags & OVERLAP) && p->dir == IOREQ_READ) {
|
||||
unsigned long addr = mmio_opp->addr;
|
||||
|
||||
if (hvm_paging_enabled(current))
|
||||
(void)hvm_copy_to_guest_virt(addr, &p->u.data, p->size);
|
||||
else
|
||||
(void)hvm_copy_to_guest_phys(addr, &p->u.data, p->size);
|
||||
}
|
||||
|
||||
regs->esi += sign * p->count * p->size;
|
||||
regs->edi += sign * p->count * p->size;
|
||||
|
||||
break;
|
||||
|
||||
case INSTR_STOS:
|
||||
|
||||
+354
-370
File diff suppressed because it is too large.
Load diff
+23
-11
@@ -59,8 +59,6 @@ extern int inst_copy_from_guest(unsigned char *buf, unsigned long guest_eip,
|
||||
int inst_len);
|
||||
extern uint32_t vlapic_update_ppr(struct vlapic *vlapic);
|
||||
extern asmlinkage void do_IRQ(struct cpu_user_regs *);
|
||||
extern void send_pio_req(struct cpu_user_regs *regs, unsigned long port,
|
||||
unsigned long count, int size, long value, int dir, int pvalid);
|
||||
extern void svm_dump_inst(unsigned long eip);
|
||||
extern int svm_dbg_on;
|
||||
void svm_dump_regs(const char *from, struct cpu_user_regs *regs);
|
||||
@@ -1410,7 +1408,7 @@ static void svm_io_instruction(struct vcpu *v)
|
||||
struct cpu_user_regs *regs;
|
||||
struct hvm_io_op *pio_opp;
|
||||
unsigned int port;
|
||||
unsigned int size, dir;
|
||||
unsigned int size, dir, df;
|
||||
ioio_info_t info;
|
||||
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
|
||||
|
||||
@@ -1429,6 +1427,8 @@ static void svm_io_instruction(struct vcpu *v)
|
||||
|
||||
port = info.fields.port; /* port used to be addr */
|
||||
dir = info.fields.type; /* direction */
|
||||
df = regs->eflags & X86_EFLAGS_DF ? 1 : 0;
|
||||
|
||||
if (info.fields.sz32)
|
||||
size = 4;
|
||||
else if (info.fields.sz16)
|
||||
@@ -1445,7 +1445,7 @@ static void svm_io_instruction(struct vcpu *v)
|
||||
if (info.fields.str)
|
||||
{
|
||||
unsigned long addr, count;
|
||||
int sign = regs->eflags & EF_DF ? -1 : 1;
|
||||
int sign = regs->eflags & X86_EFLAGS_DF ? -1 : 1;
|
||||
|
||||
if (!svm_get_io_address(v, regs, dir, &count, &addr))
|
||||
{
|
||||
@@ -1475,25 +1475,37 @@ static void svm_io_instruction(struct vcpu *v)
|
||||
unsigned long value = 0;
|
||||
|
||||
pio_opp->flags |= OVERLAP;
|
||||
pio_opp->addr = addr;
|
||||
|
||||
if (dir == IOREQ_WRITE)
|
||||
(void)hvm_copy_from_guest_virt(&value, addr, size);
|
||||
if (dir == IOREQ_WRITE) /* OUTS */
|
||||
{
|
||||
if (hvm_paging_enabled(current))
|
||||
(void)hvm_copy_from_guest_virt(&value, addr, size);
|
||||
else
|
||||
(void)hvm_copy_from_guest_phys(&value, addr, size);
|
||||
}
|
||||
|
||||
send_pio_req(regs, port, 1, size, value, dir, 0);
|
||||
if (count == 1)
|
||||
regs->eip = vmcb->exitinfo2;
|
||||
|
||||
send_pio_req(port, 1, size, value, dir, df, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((addr & PAGE_MASK) != ((addr + count * size - 1) & PAGE_MASK))
|
||||
unsigned long last_addr = sign > 0 ? addr + count * size - 1
|
||||
: addr - (count - 1) * size;
|
||||
|
||||
if ((addr & PAGE_MASK) != (last_addr & PAGE_MASK))
|
||||
{
|
||||
if (sign > 0)
|
||||
count = (PAGE_SIZE - (addr & ~PAGE_MASK)) / size;
|
||||
else
|
||||
count = (addr & ~PAGE_MASK) / size;
|
||||
count = (addr & ~PAGE_MASK) / size + 1;
|
||||
}
|
||||
else
|
||||
regs->eip = vmcb->exitinfo2;
|
||||
|
||||
send_pio_req(regs, port, count, size, addr, dir, 1);
|
||||
send_pio_req(port, count, size, addr, dir, df, 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1507,7 +1519,7 @@ static void svm_io_instruction(struct vcpu *v)
|
||||
if (port == 0xe9 && dir == IOREQ_WRITE && size == 1)
|
||||
hvm_print_line(v, regs->eax); /* guest debug output */
|
||||
|
||||
send_pio_req(regs, port, 1, size, regs->eax, dir, 0);
|
||||
send_pio_req(port, 1, size, regs->eax, dir, df, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+48
-34
@@ -1041,14 +1041,20 @@ static void vmx_vmexit_do_invlpg(unsigned long va)
|
||||
}
|
||||
|
||||
|
||||
static int check_for_null_selector(unsigned long eip)
|
||||
static int check_for_null_selector(unsigned long eip, int inst_len, int dir)
|
||||
{
|
||||
unsigned char inst[MAX_INST_LEN];
|
||||
unsigned long sel;
|
||||
int i, inst_len;
|
||||
int i;
|
||||
int inst_copy_from_guest(unsigned char *, unsigned long, int);
|
||||
|
||||
inst_len = __get_instruction_length(); /* Safe: INS/OUTS */
|
||||
/* INS can only use ES segment register, and it can't be overridden */
|
||||
if ( dir == IOREQ_READ )
|
||||
{
|
||||
__vmread(GUEST_ES_SELECTOR, &sel);
|
||||
return sel == 0 ? 1 : 0;
|
||||
}
|
||||
|
||||
memset(inst, 0, MAX_INST_LEN);
|
||||
if ( inst_copy_from_guest(inst, eip, inst_len) != inst_len )
|
||||
{
|
||||
@@ -1093,18 +1099,13 @@ static int check_for_null_selector(unsigned long eip)
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern void send_pio_req(struct cpu_user_regs *regs, unsigned long port,
|
||||
unsigned long count, int size, long value,
|
||||
int dir, int pvalid);
|
||||
|
||||
static void vmx_io_instruction(unsigned long exit_qualification,
|
||||
unsigned long inst_len)
|
||||
{
|
||||
struct cpu_user_regs *regs;
|
||||
struct hvm_io_op *pio_opp;
|
||||
unsigned long eip, cs, eflags;
|
||||
unsigned long port, size, dir;
|
||||
int vm86;
|
||||
unsigned long port, size;
|
||||
int dir, df, vm86;
|
||||
|
||||
pio_opp = ¤t->arch.hvm_vcpu.io_op;
|
||||
pio_opp->instr = INSTR_PIO;
|
||||
@@ -1116,28 +1117,26 @@ static void vmx_io_instruction(unsigned long exit_qualification,
|
||||
memcpy(regs, guest_cpu_user_regs(), HVM_CONTEXT_STACK_BYTES);
|
||||
hvm_store_cpu_guest_regs(current, regs, NULL);
|
||||
|
||||
eip = regs->eip;
|
||||
cs = regs->cs;
|
||||
eflags = regs->eflags;
|
||||
vm86 = regs->eflags & X86_EFLAGS_VM ? 1 : 0;
|
||||
df = regs->eflags & X86_EFLAGS_DF ? 1 : 0;
|
||||
|
||||
vm86 = eflags & X86_EFLAGS_VM ? 1 : 0;
|
||||
|
||||
HVM_DBG_LOG(DBG_LEVEL_IO,
|
||||
"vmx_io_instruction: vm86 %d, eip=%lx:%lx, "
|
||||
HVM_DBG_LOG(DBG_LEVEL_IO, "vm86 %d, eip=%x:%lx, "
|
||||
"exit_qualification = %lx",
|
||||
vm86, cs, eip, exit_qualification);
|
||||
vm86, regs->cs, (unsigned long)regs->eip, exit_qualification);
|
||||
|
||||
if (test_bit(6, &exit_qualification))
|
||||
if ( test_bit(6, &exit_qualification) )
|
||||
port = (exit_qualification >> 16) & 0xFFFF;
|
||||
else
|
||||
port = regs->edx & 0xffff;
|
||||
TRACE_VMEXIT(1, port);
|
||||
|
||||
TRACE_VMEXIT(1,port);
|
||||
|
||||
size = (exit_qualification & 7) + 1;
|
||||
dir = test_bit(3, &exit_qualification); /* direction */
|
||||
|
||||
if (test_bit(4, &exit_qualification)) { /* string instruction */
|
||||
if ( test_bit(4, &exit_qualification) ) { /* string instruction */
|
||||
unsigned long addr, count = 1;
|
||||
int sign = regs->eflags & EF_DF ? -1 : 1;
|
||||
int sign = regs->eflags & X86_EFLAGS_DF ? -1 : 1;
|
||||
|
||||
__vmread(GUEST_LINEAR_ADDRESS, &addr);
|
||||
|
||||
@@ -1145,10 +1144,10 @@ static void vmx_io_instruction(unsigned long exit_qualification,
|
||||
* In protected mode, guest linear address is invalid if the
|
||||
* selector is null.
|
||||
*/
|
||||
if (!vm86 && check_for_null_selector(eip))
|
||||
if ( !vm86 && check_for_null_selector(regs->eip, inst_len, dir) )
|
||||
addr = dir == IOREQ_WRITE ? regs->esi : regs->edi;
|
||||
|
||||
if (test_bit(5, &exit_qualification)) { /* "rep" prefix */
|
||||
if ( test_bit(5, &exit_qualification) ) { /* "rep" prefix */
|
||||
pio_opp->flags |= REPZ;
|
||||
count = vm86 ? regs->ecx & 0xFFFF : regs->ecx;
|
||||
}
|
||||
@@ -1157,30 +1156,45 @@ static void vmx_io_instruction(unsigned long exit_qualification,
|
||||
* Handle string pio instructions that cross pages or that
|
||||
* are unaligned. See the comments in hvm_domain.c/handle_mmio()
|
||||
*/
|
||||
if ((addr & PAGE_MASK) != ((addr + size - 1) & PAGE_MASK)) {
|
||||
if ( (addr & PAGE_MASK) != ((addr + size - 1) & PAGE_MASK) ) {
|
||||
unsigned long value = 0;
|
||||
|
||||
pio_opp->flags |= OVERLAP;
|
||||
if (dir == IOREQ_WRITE)
|
||||
(void)hvm_copy_from_guest_virt(&value, addr, size);
|
||||
send_pio_req(regs, port, 1, size, value, dir, 0);
|
||||
|
||||
if ( dir == IOREQ_WRITE ) /* OUTS */
|
||||
{
|
||||
if ( hvm_paging_enabled(current) )
|
||||
(void)hvm_copy_from_guest_virt(&value, addr, size);
|
||||
else
|
||||
(void)hvm_copy_from_guest_phys(&value, addr, size);
|
||||
} else
|
||||
pio_opp->addr = addr;
|
||||
|
||||
if ( count == 1 )
|
||||
regs->eip += inst_len;
|
||||
|
||||
send_pio_req(port, 1, size, value, dir, df, 0);
|
||||
} else {
|
||||
if ((addr & PAGE_MASK) != ((addr + count * size - 1) & PAGE_MASK)) {
|
||||
if (sign > 0)
|
||||
unsigned long last_addr = sign > 0 ? addr + count * size - 1
|
||||
: addr - (count - 1) * size;
|
||||
|
||||
if ( (addr & PAGE_MASK) != (last_addr & PAGE_MASK) )
|
||||
{
|
||||
if ( sign > 0 )
|
||||
count = (PAGE_SIZE - (addr & ~PAGE_MASK)) / size;
|
||||
else
|
||||
count = (addr & ~PAGE_MASK) / size;
|
||||
count = (addr & ~PAGE_MASK) / size + 1;
|
||||
} else
|
||||
regs->eip += inst_len;
|
||||
|
||||
send_pio_req(regs, port, count, size, addr, dir, 1);
|
||||
send_pio_req(port, count, size, addr, dir, df, 1);
|
||||
}
|
||||
} else {
|
||||
if (port == 0xe9 && dir == IOREQ_WRITE && size == 1)
|
||||
if ( port == 0xe9 && dir == IOREQ_WRITE && size == 1 )
|
||||
hvm_print_line(current, regs->eax); /* guest debug output */
|
||||
|
||||
regs->eip += inst_len;
|
||||
send_pio_req(regs, port, 1, size, regs->eax, dir, 0);
|
||||
send_pio_req(port, 1, size, regs->eax, dir, df, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2880,7 +2880,7 @@ static int sh_page_fault(struct vcpu *v,
|
||||
shadow_audit_tables(v);
|
||||
reset_early_unshadow(v);
|
||||
shadow_unlock(d);
|
||||
handle_mmio(va, gpa);
|
||||
handle_mmio(gpa);
|
||||
return EXCRET_fault_fixed;
|
||||
|
||||
not_a_shadow_fault:
|
||||
|
||||
@@ -25,11 +25,6 @@
|
||||
#include <public/hvm/ioreq.h>
|
||||
#include <public/event_channel.h>
|
||||
|
||||
#define MAX_OPERAND_NUM 2
|
||||
|
||||
#define mk_operand(size_reg, index, seg, flag) \
|
||||
(((size_reg) << 24) | ((index) << 16) | ((seg) << 8) | (flag))
|
||||
|
||||
#define operand_size(operand) \
|
||||
((operand >> 24) & 0xFF)
|
||||
|
||||
@@ -70,29 +65,23 @@
|
||||
#define INSTR_XCHG 14
|
||||
#define INSTR_SUB 15
|
||||
|
||||
struct instruction {
|
||||
__s8 instr; /* instruction type */
|
||||
__s16 op_size; /* the operand's bit size, e.g. 16-bit or 32-bit */
|
||||
__u64 immediate;
|
||||
__u16 seg_sel; /* segmentation selector */
|
||||
__u32 operand[MAX_OPERAND_NUM]; /* order is AT&T assembly */
|
||||
__u32 flags;
|
||||
};
|
||||
|
||||
#define MAX_INST_LEN 15 /* Maximum instruction length = 15 bytes */
|
||||
|
||||
struct hvm_io_op {
|
||||
int flags;
|
||||
int instr; /* instruction */
|
||||
unsigned long operand[2]; /* operands */
|
||||
unsigned long immediate; /* immediate portion */
|
||||
struct cpu_user_regs io_context; /* current context */
|
||||
unsigned int instr; /* instruction */
|
||||
unsigned int flags;
|
||||
unsigned long addr; /* virt addr for overlap PIO/MMIO */
|
||||
struct {
|
||||
unsigned int operand[2]; /* operands */
|
||||
unsigned long immediate; /* immediate portion */
|
||||
};
|
||||
struct cpu_user_regs io_context; /* current context */
|
||||
};
|
||||
|
||||
#define MAX_IO_HANDLER 8
|
||||
|
||||
#define VMX_PORTIO 0
|
||||
#define VMX_MMIO 1
|
||||
#define HVM_PORTIO 0
|
||||
#define HVM_MMIO 1
|
||||
|
||||
typedef int (*intercept_action_t)(ioreq_t *);
|
||||
typedef unsigned long (*hvm_mmio_read_t)(struct vcpu *v,
|
||||
@@ -131,16 +120,17 @@ extern int register_io_handler(unsigned long addr, unsigned long size,
|
||||
|
||||
static inline int hvm_portio_intercept(ioreq_t *p)
|
||||
{
|
||||
return hvm_io_intercept(p, VMX_PORTIO);
|
||||
return hvm_io_intercept(p, HVM_PORTIO);
|
||||
}
|
||||
|
||||
int hvm_mmio_intercept(ioreq_t *p);
|
||||
extern int hvm_mmio_intercept(ioreq_t *p);
|
||||
extern int hvm_buffered_io_intercept(ioreq_t *p);
|
||||
|
||||
static inline int register_portio_handler(unsigned long addr,
|
||||
unsigned long size,
|
||||
intercept_action_t action)
|
||||
{
|
||||
return register_io_handler(addr, size, action, VMX_PORTIO);
|
||||
return register_io_handler(addr, size, action, HVM_PORTIO);
|
||||
}
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
@@ -150,7 +140,9 @@ static inline int irq_masked(unsigned long eflags)
|
||||
}
|
||||
#endif
|
||||
|
||||
extern void handle_mmio(unsigned long, unsigned long);
|
||||
extern void send_pio_req(unsigned long port, unsigned long count, int size,
|
||||
long value, int dir, int df, int pvalid);
|
||||
extern void handle_mmio(unsigned long gpa);
|
||||
extern void hvm_interrupt_post(struct vcpu *v, int vector, int type);
|
||||
extern void hvm_io_assist(struct vcpu *v);
|
||||
extern void pic_irq_request(void *data, int level);
|
||||
|
||||
@@ -142,10 +142,6 @@ int hvm_copy_to_guest_virt(unsigned long vaddr, void *buf, int size);
|
||||
int hvm_copy_from_guest_virt(void *buf, unsigned long vaddr, int size);
|
||||
|
||||
void hvm_setup_platform(struct domain* d);
|
||||
int hvm_mmio_intercept(ioreq_t *p);
|
||||
int hvm_io_intercept(ioreq_t *p, int type);
|
||||
int hvm_buffered_io_intercept(ioreq_t *p);
|
||||
void hvm_hooks_assist(struct vcpu *v);
|
||||
void hvm_print_line(struct vcpu *v, const char c);
|
||||
void hlt_timer_fn(void *data);
|
||||
|
||||
|
||||