ia64/xen-unstable

changeset 15283:677731eb734d

[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>
author kfraser@localhost.localdomain
date Wed Jun 06 20:24:06 2007 +0100 (2007-06-06)
parents f5a71c9771a8
children 6d45351273da
files tools/ioemu/target-i386-dm/exec-dm.c
line diff
     1.1 --- a/tools/ioemu/target-i386-dm/exec-dm.c	Wed Jun 06 17:49:39 2007 +0100
     1.2 +++ b/tools/ioemu/target-i386-dm/exec-dm.c	Wed Jun 06 20:24:06 2007 +0100
     1.3 @@ -437,6 +437,31 @@ int iomem_index(target_phys_addr_t addr)
     1.4  extern unsigned long *logdirty_bitmap;
     1.5  extern unsigned long logdirty_bitmap_size;
     1.6  
     1.7 +/*
     1.8 + * Replace the standard byte memcpy with a word memcpy for appropriately sized
     1.9 + * memory copy operations.  Some users (USB-UHCI) can not tolerate the possible
    1.10 + * word tearing that can result from a guest concurrently writing a memory
    1.11 + * structure while the qemu device model is modifying the same location.
    1.12 + * Forcing a word-sized read/write prevents the guest from seeing a partially
    1.13 + * written word-sized atom.
    1.14 + */
    1.15 +void memcpy_words(void *dst, void *src, size_t n)
    1.16 +{
    1.17 +    while (n >= sizeof(long)) {
    1.18 +        *((long *)dst)++ = *((long *)src)++;
    1.19 +        n -= sizeof(long);
    1.20 +    }
    1.21 +
    1.22 +    if (n & 4)
    1.23 +        *((uint32_t *)dst)++ = *((uint32_t *)src)++;
    1.24 +
    1.25 +    if (n & 2)
    1.26 +        *((uint16_t *)dst)++ = *((uint16_t *)src)++;
    1.27 +
    1.28 +    if (n & 1)
    1.29 +        *((uint8_t *)dst)++ = *((uint8_t *)src)++;
    1.30 +}
    1.31 +
    1.32  void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, 
    1.33                              int len, int is_write)
    1.34  {
    1.35 @@ -473,7 +498,7 @@ void cpu_physical_memory_rw(target_phys_
    1.36                  }
    1.37              } else if ((ptr = phys_ram_addr(addr)) != NULL) {
    1.38                  /* Writing to RAM */
    1.39 -                memcpy(ptr, buf, l);
    1.40 +                memcpy_words(ptr, buf, l);
    1.41                  if (logdirty_bitmap != NULL) {
    1.42                      /* Record that we have dirtied this frame */
    1.43                      unsigned long pfn = addr >> TARGET_PAGE_BITS;
    1.44 @@ -509,7 +534,7 @@ void cpu_physical_memory_rw(target_phys_
    1.45                  }
    1.46              } else if ((ptr = phys_ram_addr(addr)) != NULL) {
    1.47                  /* Reading from RAM */
    1.48 -                memcpy(buf, ptr, l);
    1.49 +                memcpy_words(buf, ptr, l);
    1.50              } else {
    1.51                  /* Neither RAM nor known MMIO space */
    1.52                  memset(buf, 0xff, len);