]> xenbits.xensource.com Git - qemu-xen-4.4-testing.git/commitdiff
passthrough: Fix pci bar remapping when guest probes width with all-1 BAR
authorIan Jackson <ian.jackson@eu.citrix.com>
Tue, 21 Jul 2009 14:33:30 +0000 (15:33 +0100)
committerIan Jackson <Ian.Jackson@eu.citrix.com>
Tue, 21 Jul 2009 14:33:30 +0000 (15:33 +0100)
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 <wei.wang2@amd.com>
hw/pass-through.c

index c1a9b42b656c4130cd78f31bc4bd2edbb85eee5c..f3d033b95773ab71363050c395d0a08625486746 100644 (file)
@@ -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;