mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
Fix a regression in hvm_pio_assist() when booting Windows
on VT-x. Clean up the function also. Signed-off-by: Keir Fraser <keir@xensource.com>
This commit is contained in:
1 parent
beac48024f
commit
ec74700a6b
1 file changed
+33
-44
+33
-44
@@ -365,57 +365,46 @@ static void hvm_pio_assist(struct cpu_user_regs *regs, ioreq_t *p,
|
||||
unsigned long old_eax;
|
||||
int sign = p->df ? -1 : 1;
|
||||
|
||||
if (p->pdata_valid || (mmio_opp->flags & OVERLAP)) {
|
||||
if (mmio_opp->flags & REPZ)
|
||||
if ( p->pdata_valid || (mmio_opp->flags & OVERLAP) )
|
||||
{
|
||||
if ( mmio_opp->flags & REPZ )
|
||||
regs->ecx -= p->count;
|
||||
if (p->dir == IOREQ_READ) {
|
||||
if ( p->dir == IOREQ_READ )
|
||||
{
|
||||
regs->edi += sign * p->count * p->size;
|
||||
|
||||
if (mmio_opp->flags & OVERLAP) {
|
||||
/*
|
||||
* If we are doing in IN and it's overlapping a page boundary,
|
||||
* we need to copy the data back to user's page with hvm_copy.
|
||||
* Note that overlap * can only be set with paging enabled, so
|
||||
* we don't need to worry about * real-mode stuff.
|
||||
*/
|
||||
unsigned long addr;
|
||||
{
|
||||
/*
|
||||
* We completely ignore segment registers here -
|
||||
* it's not a good idea. We also may use upper bits
|
||||
* in edi when in 16-bit real/protected mode.
|
||||
* We really need to get the actual address back from
|
||||
* the arch-dependant HVM portion.
|
||||
*/
|
||||
struct vcpu *v = current;
|
||||
if (hvm_realmode(v))
|
||||
__hvm_bug(regs);
|
||||
}
|
||||
addr = regs->edi;
|
||||
if ( mmio_opp->flags & OVERLAP )
|
||||
{
|
||||
unsigned long addr = regs->edi;
|
||||
if (hvm_realmode(current))
|
||||
addr += regs->es << 4;
|
||||
if (sign > 0)
|
||||
addr -= p->size;
|
||||
hvm_copy(&p->u.data, addr, p->size, HVM_COPY_OUT);
|
||||
}
|
||||
} else
|
||||
}
|
||||
else /* p->dir == IOREQ_WRITE */
|
||||
{
|
||||
ASSERT(p->dir == IOREQ_WRITE);
|
||||
regs->esi += sign * p->count * p->size;
|
||||
|
||||
} else {
|
||||
if (p->dir == IOREQ_READ) {
|
||||
old_eax = regs->eax;
|
||||
switch (p->size) {
|
||||
case 1:
|
||||
regs->eax = (old_eax & 0xffffff00) | (p->u.data & 0xff);
|
||||
break;
|
||||
case 2:
|
||||
regs->eax = (old_eax & 0xffff0000) | (p->u.data & 0xffff);
|
||||
break;
|
||||
case 4:
|
||||
regs->eax = (p->u.data & 0xffffffff);
|
||||
break;
|
||||
default:
|
||||
printk("Error: %s unknown port size\n", __FUNCTION__);
|
||||
domain_crash_synchronous();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( p->dir == IOREQ_READ )
|
||||
{
|
||||
old_eax = regs->eax;
|
||||
switch ( p->size )
|
||||
{
|
||||
case 1:
|
||||
regs->eax = (old_eax & 0xffffff00) | (p->u.data & 0xff);
|
||||
break;
|
||||
case 2:
|
||||
regs->eax = (old_eax & 0xffff0000) | (p->u.data & 0xffff);
|
||||
break;
|
||||
case 4:
|
||||
regs->eax = (p->u.data & 0xffffffff);
|
||||
break;
|
||||
default:
|
||||
printk("Error: %s unknown port size\n", __FUNCTION__);
|
||||
domain_crash_synchronous();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||