[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] hvm ioemu: Avoid accessing invalid pseudophysical addresses in HVM
# HG changeset patch # User Keir Fraser <keir@xxxxxxxxxxxxx> # Date 1176116726 -3600 # Node ID 400a3dca237e856c53934f4b81137581d727fdb3 # Parent 73abcf9abbc1df3d5960461d448a725d7120fb13 hvm ioemu: Avoid accessing invalid pseudophysical addresses in HVM guest's memory map. Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx> --- tools/ioemu/target-i386-dm/exec-dm.c | 25 +---- tools/ioemu/vl.c | 162 ++++++++++++++++++++++------------- tools/ioemu/vl.h | 15 --- 3 files changed, 107 insertions(+), 95 deletions(-) diff -r 73abcf9abbc1 -r 400a3dca237e tools/ioemu/target-i386-dm/exec-dm.c --- a/tools/ioemu/target-i386-dm/exec-dm.c Mon Apr 09 11:12:15 2007 +0100 +++ b/tools/ioemu/target-i386-dm/exec-dm.c Mon Apr 09 12:05:26 2007 +0100 @@ -128,11 +128,9 @@ FILE *logfile; FILE *logfile; int loglevel; - #ifdef MAPCACHE pthread_mutex_t mapcache_mutex; #endif - void cpu_exec_init(CPUState *env) { @@ -427,21 +425,10 @@ int iomem_index(target_phys_addr_t addr) return 0; } -static inline int paddr_is_ram(target_phys_addr_t addr) -{ - /* Is this guest physical address RAM-backed? */ -#if defined(CONFIG_DM) && (defined(__i386__) || defined(__x86_64__)) - return ((addr < HVM_BELOW_4G_MMIO_START) || - (addr >= HVM_BELOW_4G_MMIO_START + HVM_BELOW_4G_MMIO_LENGTH)); -#else - return (addr < ram_size); -#endif -} - #if defined(__i386__) || defined(__x86_64__) #define phys_ram_addr(x) (qemu_map_cache(x)) #elif defined(__ia64__) -#define phys_ram_addr(x) (phys_ram_base + (x)) +#define phys_ram_addr(x) ((addr < ram_size) ? (phys_ram_base + (x)) : NULL) #endif extern unsigned long *logdirty_bitmap; @@ -481,16 +468,15 @@ void cpu_physical_memory_rw(target_phys_ io_mem_write[io_index][0](io_mem_opaque[io_index], addr, val); l = 1; } - } else if (paddr_is_ram(addr)) { + } else if ((ptr = phys_ram_addr(addr)) != NULL) { /* Writing to RAM */ - ptr = phys_ram_addr(addr); memcpy(ptr, buf, l); if (logdirty_bitmap != NULL) { /* Record that we have dirtied this frame */ unsigned long pfn = addr >> TARGET_PAGE_BITS; if (pfn / 8 >= logdirty_bitmap_size) { - fprintf(logfile, "dirtying pfn %x >= bitmap size %x\n", - pfn, logdirty_bitmap_size * 8); + fprintf(logfile, "dirtying pfn %lx >= bitmap " + "size %lx\n", pfn, logdirty_bitmap_size * 8); } else { logdirty_bitmap[pfn / HOST_LONG_BITS] |= 1UL << pfn % HOST_LONG_BITS; @@ -518,9 +504,8 @@ void cpu_physical_memory_rw(target_phys_ stb_raw(buf, val); l = 1; } - } else if (paddr_is_ram(addr)) { + } else if ((ptr = phys_ram_addr(addr)) != NULL) { /* Reading from RAM */ - ptr = phys_ram_addr(addr); memcpy(buf, ptr, l); } else { /* Neither RAM nor known MMIO space */ diff -r 73abcf9abbc1 -r 400a3dca237e tools/ioemu/vl.c --- a/tools/ioemu/vl.c Mon Apr 09 11:12:15 2007 +0100 +++ b/tools/ioemu/vl.c Mon Apr 09 12:05:26 2007 +0100 @@ -5894,7 +5894,32 @@ void suspend(int sig) suspend_requested = 1; } -#if defined(__i386__) || defined(__x86_64__) +#if defined(MAPCACHE) + +#if defined(__i386__) +#define MAX_MCACHE_SIZE 0x40000000 /* 1GB max for x86 */ +#define MCACHE_BUCKET_SHIFT 16 +#elif defined(__x86_64__) +#define MAX_MCACHE_SIZE 0x1000000000 /* 64GB max for x86_64 */ +#define MCACHE_BUCKET_SHIFT 20 +#endif + +#define MCACHE_BUCKET_SIZE (1UL << MCACHE_BUCKET_SHIFT) + +#define BITS_PER_LONG (sizeof(long)*8) +#define BITS_TO_LONGS(bits) \ + (((bits)+BITS_PER_LONG-1)/BITS_PER_LONG) +#define DECLARE_BITMAP(name,bits) \ + unsigned long name[BITS_TO_LONGS(bits)] +#define test_bit(bit,map) \ + (!!((map)[(bit)/BITS_PER_LONG] & (1UL << ((bit)%BITS_PER_LONG)))) + +struct map_cache { + unsigned long paddr_index; + uint8_t *vaddr_base; + DECLARE_BITMAP(valid_mapping, MCACHE_BUCKET_SIZE>>PAGE_SHIFT); +}; + static struct map_cache *mapcache_entry; static unsigned long nr_buckets; @@ -5928,69 +5953,85 @@ static int qemu_map_cache_init(void) return 0; } -uint8_t *qemu_map_cache(target_phys_addr_t phys_addr) -{ - struct map_cache *entry; - unsigned long address_index = phys_addr >> MCACHE_BUCKET_SHIFT; - unsigned long address_offset = phys_addr & (MCACHE_BUCKET_SIZE-1); - - if (address_index == last_address_index) - return last_address_vaddr + address_offset; - - entry = &mapcache_entry[address_index % nr_buckets]; - - if (entry->vaddr_base == NULL || entry->paddr_index != address_index) { - /* We need to remap a bucket. */ - uint8_t *vaddr_base; - unsigned long pfns[MCACHE_BUCKET_SIZE >> PAGE_SHIFT]; - unsigned int i; - - if (entry->vaddr_base != NULL) { - errno = munmap(entry->vaddr_base, MCACHE_BUCKET_SIZE); - if (errno) { - fprintf(logfile, "unmap fails %d\n", errno); - exit(-1); - } - } - - for (i = 0; i < MCACHE_BUCKET_SIZE >> PAGE_SHIFT; i++) - pfns[i] = (address_index << (MCACHE_BUCKET_SHIFT-PAGE_SHIFT)) + i; - - vaddr_base = xc_map_foreign_batch( - xc_handle, domid, PROT_READ|PROT_WRITE, - pfns, MCACHE_BUCKET_SIZE >> PAGE_SHIFT); - if (vaddr_base == NULL) { - fprintf(logfile, "xc_map_foreign_batch error %d\n", errno); - exit(-1); - } - - entry->vaddr_base = vaddr_base; - entry->paddr_index = address_index;; - } - - last_address_index = address_index; - last_address_vaddr = entry->vaddr_base; - - 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; - +static void qemu_remap_bucket(struct map_cache *entry, + unsigned long address_index) +{ + uint8_t *vaddr_base; + unsigned long pfns[MCACHE_BUCKET_SIZE >> PAGE_SHIFT]; + unsigned int i, j; + + if (entry->vaddr_base != NULL) { errno = munmap(entry->vaddr_base, MCACHE_BUCKET_SIZE); if (errno) { fprintf(logfile, "unmap fails %d\n", errno); exit(-1); } + } + + for (i = 0; i < MCACHE_BUCKET_SIZE >> PAGE_SHIFT; i++) + pfns[i] = (address_index << (MCACHE_BUCKET_SHIFT-PAGE_SHIFT)) + i; + + vaddr_base = xc_map_foreign_batch(xc_handle, domid, PROT_READ|PROT_WRITE, + pfns, MCACHE_BUCKET_SIZE >> PAGE_SHIFT); + if (vaddr_base == NULL) { + fprintf(logfile, "xc_map_foreign_batch error %d\n", errno); + exit(-1); + } + + entry->vaddr_base = vaddr_base; + entry->paddr_index = address_index; + + for (i = 0; i < MCACHE_BUCKET_SIZE >> PAGE_SHIFT; i += BITS_PER_LONG) { + unsigned long word = 0; + j = ((i + BITS_PER_LONG) > (MCACHE_BUCKET_SIZE >> PAGE_SHIFT)) ? + (MCACHE_BUCKET_SIZE >> PAGE_SHIFT) % BITS_PER_LONG : BITS_PER_LONG; + while (j > 0) + word = (word << 1) | !(pfns[i + --j] & 0xF0000000UL); + entry->valid_mapping[i / BITS_PER_LONG] = word; + } +} + +uint8_t *qemu_map_cache(target_phys_addr_t phys_addr) +{ + struct map_cache *entry; + unsigned long address_index = phys_addr >> MCACHE_BUCKET_SHIFT; + unsigned long address_offset = phys_addr & (MCACHE_BUCKET_SIZE-1); + + if (address_index == last_address_index) + return last_address_vaddr + address_offset; + + entry = &mapcache_entry[address_index % nr_buckets]; + + if (entry->vaddr_base == NULL || entry->paddr_index != address_index || + !test_bit(address_offset>>PAGE_SHIFT, entry->valid_mapping)) + qemu_remap_bucket(entry, address_index); + + if (!test_bit(address_offset>>PAGE_SHIFT, entry->valid_mapping)) + return NULL; + + last_address_index = address_index; + last_address_vaddr = entry->vaddr_base; + + 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; @@ -6001,7 +6042,8 @@ void qemu_invalidate_map_cache(void) mapcache_unlock(); } -#endif + +#endif /* defined(MAPCACHE) */ int main(int argc, char **argv) { diff -r 73abcf9abbc1 -r 400a3dca237e tools/ioemu/vl.h --- a/tools/ioemu/vl.h Mon Apr 09 11:12:15 2007 +0100 +++ b/tools/ioemu/vl.h Mon Apr 09 12:05:26 2007 +0100 @@ -161,21 +161,6 @@ extern FILE *logfile; #define MAPCACHE -#if defined(__i386__) -#define MAX_MCACHE_SIZE 0x40000000 /* 1GB max for x86 */ -#define MCACHE_BUCKET_SHIFT 16 -#elif defined(__x86_64__) -#define MAX_MCACHE_SIZE 0x1000000000 /* 64GB max for x86_64 */ -#define MCACHE_BUCKET_SHIFT 20 -#endif - -#define MCACHE_BUCKET_SIZE (1UL << MCACHE_BUCKET_SHIFT) - -struct map_cache { - unsigned long paddr_index; - uint8_t *vaddr_base; -}; - uint8_t *qemu_map_cache(target_phys_addr_t phys_addr); void qemu_invalidate_map_cache(void); _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |