diff -r 271ffb1c12eb tools/ioemu/hw/xen_platform.c --- a/tools/ioemu/hw/xen_platform.c Fri Jan 26 18:38:40 2007 +0000 +++ b/tools/ioemu/hw/xen_platform.c Sat Jan 27 17:41:11 2007 +0800 @@ -82,6 +82,32 @@ static void platform_mmio_map(PCIDevice cpu_register_physical_memory(addr, 0x1000000, mmio_io_addr); } +#if defined(__i386__) || defined(__x86_64__) +static void invalidate_mapcache_ioport_write(void *opaque, + uint32_t addr, uint32_t val) +{ + mapcache_lock(); + qemu_invalidate_map_cache(); + mapcache_unlock(); +} + +static void mapcache_ioport_map(PCIDevice *pci_dev, int region_num, + uint32_t addr, uint32_t size, int type) +{ + register_ioport_write(addr, 1, 1, invalidate_mapcache_ioport_write, NULL); + register_ioport_write(addr, 2, 2, invalidate_mapcache_ioport_write, NULL); + register_ioport_write(addr, 4, 4, invalidate_mapcache_ioport_write, NULL); +} + +/* reserved 4 I/O ports for invalidating Qemu mapcache */ +#define pci_register_io_region_for_mapcache() do { \ + pci_register_io_region(d, region_num++, 4, PCI_ADDRESS_SPACE_IO, \ + mapcache_ioport_map); \ + } while (0) +#else +#define pci_register_io_region_for_mapcache() (void(0)) +#endif + struct pci_config_header { uint16_t vendor_id; uint16_t device_id; @@ -112,6 +138,7 @@ void pci_xen_platform_init(PCIBus *bus) { PCIDevice *d; struct pci_config_header *pch; + int region_num = 0; printf("Register xen platform.\n"); d = pci_register_device(bus, "xen-platform", sizeof(PCIDevice), -1, NULL, @@ -132,12 +159,14 @@ void pci_xen_platform_init(PCIBus *bus) pch->subsystem_vendor_id = pch->vendor_id; /* Duplicate vendor id. */ pch->subsystem_id = 0x0001; /* Hardcode sub-id as 1. */ - pci_register_io_region(d, 0, 0x100, PCI_ADDRESS_SPACE_IO, + pci_register_io_region(d, region_num++, 0x100, PCI_ADDRESS_SPACE_IO, platform_ioport_map); /* reserve 16MB mmio address for share memory*/ - pci_register_io_region(d, 1, 0x1000000, PCI_ADDRESS_SPACE_MEM_PREFETCH, - platform_mmio_map); + pci_register_io_region(d, region_num++, 0x1000000, + PCI_ADDRESS_SPACE_MEM_PREFETCH, platform_mmio_map); + + pci_register_io_region_for_mapcache(); register_savevm("platform", 0, 1, generic_pci_save, generic_pci_load, d); printf("Done register platform.\n"); diff -r 271ffb1c12eb tools/ioemu/target-i386-dm/exec-dm.c --- a/tools/ioemu/target-i386-dm/exec-dm.c Fri Jan 26 18:38:40 2007 +0000 +++ b/tools/ioemu/target-i386-dm/exec-dm.c Sat Jan 27 17:41:11 2007 +0800 @@ -129,18 +129,8 @@ int loglevel; int loglevel; -#if defined(__i386__) || defined(__x86_64__) -#define MAPCACHE -#endif - #ifdef MAPCACHE -#include -static pthread_mutex_t mapcache_mutex; -#define mapcache_lock() pthread_mutex_lock(&mapcache_mutex) -#define mapcache_unlock() pthread_mutex_unlock(&mapcache_mutex) -#else -#define mapcache_lock() ( (void)0 ) -#define mapcache_unlock() ( (void)0 ) +pthread_mutex_t mapcache_mutex; #endif diff -r 271ffb1c12eb tools/ioemu/vl.c --- a/tools/ioemu/vl.c Fri Jan 26 18:38:40 2007 +0000 +++ b/tools/ioemu/vl.c Sat Jan 27 17:41:11 2007 +0800 @@ -285,7 +285,7 @@ int register_ioport_write(int start, int for(i = start; i < start + length; i += size) { ioport_write_table[bsize][i] = func; if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque) - hw_error("register_ioport_read: invalid opaque"); + hw_error("register_ioport_write: invalid opaque"); ioport_opaque[i] = opaque; } return 0; @@ -5826,6 +5826,10 @@ static struct map_cache *mapcache_entry; static struct map_cache *mapcache_entry; static unsigned long nr_buckets; +/* For most cases (>99.9%), the page address is the same. */ +static unsigned long last_address_index = ~0UL; +static uint8_t *last_address_vaddr; + static int qemu_map_cache_init(unsigned long nr_pages) { unsigned long max_pages = MAX_MCACHE_SIZE >> PAGE_SHIFT; @@ -5862,10 +5866,6 @@ uint8_t *qemu_map_cache(target_phys_addr unsigned long address_index = phys_addr >> MCACHE_BUCKET_SHIFT; unsigned long address_offset = phys_addr & (MCACHE_BUCKET_SIZE-1); - /* For most cases (>99.9%), the page address is the same. */ - static unsigned long last_address_index = ~0UL; - static uint8_t *last_address_vaddr; - if (address_index == last_address_index) return last_address_vaddr + address_offset; @@ -5904,6 +5904,30 @@ uint8_t *qemu_map_cache(target_phys_addr last_address_vaddr = entry->vaddr_base; return last_address_vaddr + address_offset; +} + +void qemu_invalidate_map_cache(void) +{ + unsigned long i; + + for (i = 0; i < nr_buckets; i++) { + struct map_cache *entry = &mapcache_entry[i]; + + if (entry->vaddr_base == NULL) + continue; + + errno = munmap(entry->vaddr_base, MCACHE_BUCKET_SIZE); + if (errno) { + fprintf(logfile, "unmap fails %d\n", errno); + exit(-1); + } + + entry->paddr_index = 0; + entry->vaddr_base = NULL; + } + + last_address_index = ~0UL; + last_address_vaddr = NULL; } #endif diff -r 271ffb1c12eb tools/ioemu/vl.h --- a/tools/ioemu/vl.h Fri Jan 26 18:38:40 2007 +0000 +++ b/tools/ioemu/vl.h Sat Jan 27 17:41:11 2007 +0800 @@ -158,6 +158,7 @@ extern FILE *logfile; #if defined(__i386__) || defined(__x86_64__) +#define MAPCACHE #if defined(__i386__) #define MAX_MCACHE_SIZE 0x40000000 /* 1GB max for x86 */ #define MCACHE_BUCKET_SHIFT 16 @@ -174,6 +175,17 @@ struct map_cache { }; uint8_t *qemu_map_cache(target_phys_addr_t phys_addr); +void qemu_invalidate_map_cache(void); +#endif + +#ifdef MAPCACHE +#include +extern pthread_mutex_t mapcache_mutex; +#define mapcache_lock() pthread_mutex_lock(&mapcache_mutex) +#define mapcache_unlock() pthread_mutex_unlock(&mapcache_mutex) +#else +#define mapcache_lock() ((void)0) +#define mapcache_unlock() ((void)0) #endif extern int xc_handle; diff -r 271ffb1c12eb unmodified_drivers/linux-2.6/platform-pci/platform-pci.c --- a/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c Fri Jan 26 18:38:40 2007 +0000 +++ b/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c Sat Jan 27 18:20:36 2007 +0800 @@ -214,6 +214,18 @@ static uint64_t get_callback_via(struct #endif } +#if defined(__i386__) || defined(__x86_64__) +/* I/O port range for invalidating Qemu mapcache */ +static uint16_t ioaddr_qmc, iolen_qmc; + +/* tell Qemu to invalidate its mapcache */ +void qemu_invalidate_map_cache(void) +{ + outb(0, ioaddr_qmc); +} +EXPORT_SYMBOL(qemu_invalidate_map_cache); +#endif + static int __devinit platform_pci_init(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -231,6 +243,15 @@ static int __devinit platform_pci_init(s mmio_addr = pci_resource_start(pdev, 1); mmio_len = pci_resource_len(pdev, 1); + +#if defined(__i386__) || defined(__x86_64__) + ioaddr_qmc = pci_resource_start(pdev, 2); + iolen_qmc = pci_resource_len(pdev, 2); + if (ioaddr_qmc == 0 || iolen_qmc != 4) { + printk(KERN_ERR "Qemu_invalidate_mapcache:no resources found\n"); + return -ENOENT; + } +#endif callback_via = get_callback_via(pdev);