From: Ian Jackson Date: Tue, 21 Jul 2009 14:33:30 +0000 (+0100) Subject: passthrough: Fix pci bar remapping when guest probes width with all-1 BAR X-Git-Tag: xen-4.0.0-rc1~50 X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=cdfe6bd8f1643706272b46c3a8c5e48179f504c8;p=qemu-xen-4.4-testing.git passthrough: Fix pci bar remapping when guest probes width with all-1 BAR When guest code tries to get the block size of mmio, it will write all "1"s into pci bar register and then qemu will return all "0"s to the don't care bits in the emulated bar register to indicate the block size to guest code. In this case, we should not create p2m mapping in pt_bar_reg_write() and pt_exp_rom_bar_reg_write(). Attached patch fixes this issue, additional comment can be found in the patch. Signed-off-by: Wei Wang --- diff --git a/hw/pass-through.c b/hw/pass-through.c index c1a9b42b6..f3d033b95 100644 --- a/hw/pass-through.c +++ b/hw/pass-through.c @@ -3401,7 +3401,16 @@ static int pt_bar_reg_write(struct pt_dev *ptdev, } /* update the corresponding virtual region address */ - r->addr = cfg_entry->data; + /* + * When guest code tries to get block size of mmio, it will write all "1"s + * into pci bar register. In this case, cfg_entry->data == writable_mask. + * Especially for devices with large mmio, the value of writable_mask + * is likely to be a guest physical address that has been mapped to ram + * rather than mmio. Remapping this value to mmio should be prevented. + */ + + if ( cfg_entry->data != writable_mask ) + r->addr = cfg_entry->data; exit: /* create value for writing to I/O device register */ @@ -3453,7 +3462,16 @@ static int pt_exp_rom_bar_reg_write(struct pt_dev *ptdev, cfg_entry->data = PT_MERGE_VALUE(*value, cfg_entry->data, writable_mask); /* update the corresponding virtual region address */ - r->addr = cfg_entry->data; + /* + * When guest code tries to get block size of mmio, it will write all "1"s + * into pci bar register. In this case, cfg_entry->data == writable_mask. + * Especially for devices with large mmio, the value of writable_mask + * is likely to be a guest physical address that has been mapped to ram + * rather than mmio. Remapping this value to mmio should be prevented. + */ + + if ( cfg_entry->data != writable_mask ) + r->addr = cfg_entry->data; /* create value for writing to I/O device register */ throughable_mask = ~bar_emu_mask & valid_mask;