75 lines
2.7 KiB
Diff
75 lines
2.7 KiB
Diff
|
# HG changeset patch
|
||
|
# User kfraser@localhost.localdomain
|
||
|
# Date 1181157846 -3600
|
||
|
# Node ID 677731eb734d8d7afa37a2e31ca2ed85fbebc2a5
|
||
|
# Parent f5a71c9771a81f220926ac11e4c9a2a27530c20a
|
||
|
[HVM] Prevent usb driver crashes in Windows
|
||
|
|
||
|
Use atomic updates to read/write usb controller data.
|
||
|
This can be done because:
|
||
|
a) word copies on x86 are atomic
|
||
|
b) The USB spec requires word alignment
|
||
|
|
||
|
This will need to be enhanced once USB 1.2 is supported.
|
||
|
|
||
|
Signed-off-by: Steve Ofsthun <sofsthun@virtualiron.com>
|
||
|
|
||
|
Update to copy 'longword'-sized atoms.
|
||
|
|
||
|
Signed-off-by: Keir Fraser <keir@xensource.com>
|
||
|
|
||
|
Index: xen-3.1-testing/tools/ioemu/target-i386-dm/exec-dm.c
|
||
|
===================================================================
|
||
|
--- xen-3.1-testing.orig/tools/ioemu/target-i386-dm/exec-dm.c
|
||
|
+++ xen-3.1-testing/tools/ioemu/target-i386-dm/exec-dm.c
|
||
|
@@ -434,6 +434,31 @@ int iomem_index(target_phys_addr_t addr)
|
||
|
extern unsigned long *logdirty_bitmap;
|
||
|
extern unsigned long logdirty_bitmap_size;
|
||
|
|
||
|
+/*
|
||
|
+ * Replace the standard byte memcpy with a word memcpy for appropriately sized
|
||
|
+ * memory copy operations. Some users (USB-UHCI) can not tolerate the possible
|
||
|
+ * word tearing that can result from a guest concurrently writing a memory
|
||
|
+ * structure while the qemu device model is modifying the same location.
|
||
|
+ * Forcing a word-sized read/write prevents the guest from seeing a partially
|
||
|
+ * written word-sized atom.
|
||
|
+ */
|
||
|
+void memcpy_words(void *dst, void *src, size_t n)
|
||
|
+{
|
||
|
+ while (n >= sizeof(long)) {
|
||
|
+ *((long *)dst)++ = *((long *)src)++;
|
||
|
+ n -= sizeof(long);
|
||
|
+ }
|
||
|
+
|
||
|
+ if (n & 4)
|
||
|
+ *((uint32_t *)dst)++ = *((uint32_t *)src)++;
|
||
|
+
|
||
|
+ if (n & 2)
|
||
|
+ *((uint16_t *)dst)++ = *((uint16_t *)src)++;
|
||
|
+
|
||
|
+ if (n & 1)
|
||
|
+ *((uint8_t *)dst)++ = *((uint8_t *)src)++;
|
||
|
+}
|
||
|
+
|
||
|
void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
|
||
|
int len, int is_write)
|
||
|
{
|
||
|
@@ -470,7 +495,7 @@ void cpu_physical_memory_rw(target_phys_
|
||
|
}
|
||
|
} else if ((ptr = phys_ram_addr(addr)) != NULL) {
|
||
|
/* Writing to RAM */
|
||
|
- memcpy(ptr, buf, l);
|
||
|
+ memcpy_words(ptr, buf, l);
|
||
|
if (logdirty_bitmap != NULL) {
|
||
|
/* Record that we have dirtied this frame */
|
||
|
unsigned long pfn = addr >> TARGET_PAGE_BITS;
|
||
|
@@ -506,7 +531,7 @@ void cpu_physical_memory_rw(target_phys_
|
||
|
}
|
||
|
} else if ((ptr = phys_ram_addr(addr)) != NULL) {
|
||
|
/* Reading from RAM */
|
||
|
- memcpy(buf, ptr, l);
|
||
|
+ memcpy_words(buf, ptr, l);
|
||
|
} else {
|
||
|
/* Neither RAM nor known MMIO space */
|
||
|
memset(buf, 0xff, len);
|