diff options
author | kaf24@localhost.localdomain <kaf24@localhost.localdomain> | 2007-01-27 13:32:27 +0000 |
---|---|---|
committer | kaf24@localhost.localdomain <kaf24@localhost.localdomain> | 2007-01-27 13:32:27 +0000 |
commit | 249c2a8ce6f2e8f193f73918dc1aeafe19b6a739 (patch) | |
tree | 38d12677f141c6cdf1ad53d08514f6ab4763ea79 | |
parent | f42eb8636f525fce8a8bec63dab14c24e3679641 (diff) | |
download | xen-249c2a8ce6f2e8f193f73918dc1aeafe19b6a739.tar.gz xen-249c2a8ce6f2e8f193f73918dc1aeafe19b6a739.tar.bz2 xen-249c2a8ce6f2e8f193f73918dc1aeafe19b6a739.zip |
[HVM] Allow HVM guest to request invalidation of foreign mappings via
an I/O port write.
Signed-off-by: Dexuan Cui <dexuan.cui@intel.com>
-rw-r--r-- | tools/ioemu/hw/xen_platform.c | 11 | ||||
-rw-r--r-- | tools/ioemu/target-i386-dm/exec-dm.c | 12 | ||||
-rw-r--r-- | tools/ioemu/vl.c | 38 | ||||
-rw-r--r-- | tools/ioemu/vl.h | 17 | ||||
-rw-r--r-- | unmodified_drivers/linux-2.6/platform-pci/platform-pci.c | 10 |
5 files changed, 64 insertions, 24 deletions
diff --git a/tools/ioemu/hw/xen_platform.c b/tools/ioemu/hw/xen_platform.c index a0e9f1e397..cdff19c9d8 100644 --- a/tools/ioemu/hw/xen_platform.c +++ b/tools/ioemu/hw/xen_platform.c @@ -31,19 +31,14 @@ extern FILE *logfile; static void platform_ioport_write(void *opaque, uint32_t addr, uint32_t val) { - return; -} - -static uint32_t platform_ioport_read(void *opaque, uint32_t addr) -{ - return 0; + if (val == 0) + qemu_invalidate_map_cache(); } static void platform_ioport_map(PCIDevice *pci_dev, int region_num, uint32_t addr, uint32_t size, int type) { - register_ioport_write(addr, 16, 4, platform_ioport_write, NULL); - register_ioport_read(addr, 16, 1, platform_ioport_read, NULL); + register_ioport_write(addr, 1, 1, platform_ioport_write, NULL); } static uint32_t platform_mmio_read(void *opaque, target_phys_addr_t addr) diff --git a/tools/ioemu/target-i386-dm/exec-dm.c b/tools/ioemu/target-i386-dm/exec-dm.c index cfc82dd221..35891ed064 100644 --- a/tools/ioemu/target-i386-dm/exec-dm.c +++ b/tools/ioemu/target-i386-dm/exec-dm.c @@ -129,18 +129,8 @@ FILE *logfile; int loglevel; -#if defined(__i386__) || defined(__x86_64__) -#define MAPCACHE -#endif - #ifdef MAPCACHE -#include <pthread.h> -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 --git a/tools/ioemu/vl.c b/tools/ioemu/vl.c index f5a79ad7e5..ed29028d41 100644 --- a/tools/ioemu/vl.c +++ b/tools/ioemu/vl.c @@ -285,7 +285,7 @@ int register_ioport_write(int start, int length, int size, 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 @@ void suspend(int sig) 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_t 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; @@ -5905,6 +5905,34 @@ uint8_t *qemu_map_cache(target_phys_addr_t phys_addr) return last_address_vaddr + address_offset; } + +void qemu_invalidate_map_cache(void) +{ + unsigned long i; + + mapcache_lock(); + + 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; + + mapcache_unlock(); +} #endif int main(int argc, char **argv) diff --git a/tools/ioemu/vl.h b/tools/ioemu/vl.h index 9e4d92a17b..8535ba689c 100644 --- a/tools/ioemu/vl.h +++ b/tools/ioemu/vl.h @@ -158,6 +158,9 @@ 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 +177,20 @@ struct map_cache { }; uint8_t *qemu_map_cache(target_phys_addr_t phys_addr); +void qemu_invalidate_map_cache(void); + +#include <pthread.h> +extern pthread_mutex_t mapcache_mutex; +#define mapcache_lock() pthread_mutex_lock(&mapcache_mutex) +#define mapcache_unlock() pthread_mutex_unlock(&mapcache_mutex) + +#else + +#define qemu_invalidate_map_cache() ((void)0) + +#define mapcache_lock() ((void)0) +#define mapcache_unlock() ((void)0) + #endif extern int xc_handle; diff --git a/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c b/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c index 7973f86820..e6ff4107cb 100644 --- a/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c +++ b/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c @@ -214,6 +214,14 @@ static uint64_t get_callback_via(struct pci_dev *pdev) #endif } +/* Invalidate foreign mappings (e.g., in qemu-based device model). */ +static uint16_t invlmap_port; +void xen_invalidate_foreign_mappings(void) +{ + outb(0, invlmap_port); +} +EXPORT_SYMBOL(xen_invalidate_foreign_mappings); + static int __devinit platform_pci_init(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -239,6 +247,8 @@ static int __devinit platform_pci_init(struct pci_dev *pdev, return -ENOENT; } + invlmap_port = ioaddr; + if (request_mem_region(mmio_addr, mmio_len, DRV_NAME) == NULL) { printk(KERN_ERR ":MEM I/O resource 0x%lx @ 0x%lx busy\n", |