direct-io.hg
changeset 14773:400a3dca237e
hvm ioemu: Avoid accessing invalid pseudophysical addresses in HVM
guest's memory map.
Signed-off-by: Keir Fraser <keir@xensource.com>
guest's memory map.
Signed-off-by: Keir Fraser <keir@xensource.com>
author | Keir Fraser <keir@xensource.com> |
---|---|
date | Mon Apr 09 12:05:26 2007 +0100 (2007-04-09) |
parents | 73abcf9abbc1 |
children | 7cfe2a22462c 1bde28f762a6 fb0463b6094d |
files | tools/ioemu/target-i386-dm/exec-dm.c tools/ioemu/vl.c tools/ioemu/vl.h |
line diff
1.1 --- a/tools/ioemu/target-i386-dm/exec-dm.c Mon Apr 09 11:12:15 2007 +0100 1.2 +++ b/tools/ioemu/target-i386-dm/exec-dm.c Mon Apr 09 12:05:26 2007 +0100 1.3 @@ -128,12 +128,10 @@ char *logfilename = "/tmp/qemu.log"; 1.4 FILE *logfile; 1.5 int loglevel; 1.6 1.7 - 1.8 #ifdef MAPCACHE 1.9 pthread_mutex_t mapcache_mutex; 1.10 #endif 1.11 1.12 - 1.13 void cpu_exec_init(CPUState *env) 1.14 { 1.15 CPUState **penv; 1.16 @@ -427,21 +425,10 @@ int iomem_index(target_phys_addr_t addr) 1.17 return 0; 1.18 } 1.19 1.20 -static inline int paddr_is_ram(target_phys_addr_t addr) 1.21 -{ 1.22 - /* Is this guest physical address RAM-backed? */ 1.23 -#if defined(CONFIG_DM) && (defined(__i386__) || defined(__x86_64__)) 1.24 - return ((addr < HVM_BELOW_4G_MMIO_START) || 1.25 - (addr >= HVM_BELOW_4G_MMIO_START + HVM_BELOW_4G_MMIO_LENGTH)); 1.26 -#else 1.27 - return (addr < ram_size); 1.28 -#endif 1.29 -} 1.30 - 1.31 #if defined(__i386__) || defined(__x86_64__) 1.32 #define phys_ram_addr(x) (qemu_map_cache(x)) 1.33 #elif defined(__ia64__) 1.34 -#define phys_ram_addr(x) (phys_ram_base + (x)) 1.35 +#define phys_ram_addr(x) ((addr < ram_size) ? (phys_ram_base + (x)) : NULL) 1.36 #endif 1.37 1.38 extern unsigned long *logdirty_bitmap; 1.39 @@ -481,16 +468,15 @@ void cpu_physical_memory_rw(target_phys_ 1.40 io_mem_write[io_index][0](io_mem_opaque[io_index], addr, val); 1.41 l = 1; 1.42 } 1.43 - } else if (paddr_is_ram(addr)) { 1.44 + } else if ((ptr = phys_ram_addr(addr)) != NULL) { 1.45 /* Writing to RAM */ 1.46 - ptr = phys_ram_addr(addr); 1.47 memcpy(ptr, buf, l); 1.48 if (logdirty_bitmap != NULL) { 1.49 /* Record that we have dirtied this frame */ 1.50 unsigned long pfn = addr >> TARGET_PAGE_BITS; 1.51 if (pfn / 8 >= logdirty_bitmap_size) { 1.52 - fprintf(logfile, "dirtying pfn %x >= bitmap size %x\n", 1.53 - pfn, logdirty_bitmap_size * 8); 1.54 + fprintf(logfile, "dirtying pfn %lx >= bitmap " 1.55 + "size %lx\n", pfn, logdirty_bitmap_size * 8); 1.56 } else { 1.57 logdirty_bitmap[pfn / HOST_LONG_BITS] 1.58 |= 1UL << pfn % HOST_LONG_BITS; 1.59 @@ -518,9 +504,8 @@ void cpu_physical_memory_rw(target_phys_ 1.60 stb_raw(buf, val); 1.61 l = 1; 1.62 } 1.63 - } else if (paddr_is_ram(addr)) { 1.64 + } else if ((ptr = phys_ram_addr(addr)) != NULL) { 1.65 /* Reading from RAM */ 1.66 - ptr = phys_ram_addr(addr); 1.67 memcpy(buf, ptr, l); 1.68 } else { 1.69 /* Neither RAM nor known MMIO space */
2.1 --- a/tools/ioemu/vl.c Mon Apr 09 11:12:15 2007 +0100 2.2 +++ b/tools/ioemu/vl.c Mon Apr 09 12:05:26 2007 +0100 2.3 @@ -5894,7 +5894,32 @@ void suspend(int sig) 2.4 suspend_requested = 1; 2.5 } 2.6 2.7 -#if defined(__i386__) || defined(__x86_64__) 2.8 +#if defined(MAPCACHE) 2.9 + 2.10 +#if defined(__i386__) 2.11 +#define MAX_MCACHE_SIZE 0x40000000 /* 1GB max for x86 */ 2.12 +#define MCACHE_BUCKET_SHIFT 16 2.13 +#elif defined(__x86_64__) 2.14 +#define MAX_MCACHE_SIZE 0x1000000000 /* 64GB max for x86_64 */ 2.15 +#define MCACHE_BUCKET_SHIFT 20 2.16 +#endif 2.17 + 2.18 +#define MCACHE_BUCKET_SIZE (1UL << MCACHE_BUCKET_SHIFT) 2.19 + 2.20 +#define BITS_PER_LONG (sizeof(long)*8) 2.21 +#define BITS_TO_LONGS(bits) \ 2.22 + (((bits)+BITS_PER_LONG-1)/BITS_PER_LONG) 2.23 +#define DECLARE_BITMAP(name,bits) \ 2.24 + unsigned long name[BITS_TO_LONGS(bits)] 2.25 +#define test_bit(bit,map) \ 2.26 + (!!((map)[(bit)/BITS_PER_LONG] & (1UL << ((bit)%BITS_PER_LONG)))) 2.27 + 2.28 +struct map_cache { 2.29 + unsigned long paddr_index; 2.30 + uint8_t *vaddr_base; 2.31 + DECLARE_BITMAP(valid_mapping, MCACHE_BUCKET_SIZE>>PAGE_SHIFT); 2.32 +}; 2.33 + 2.34 static struct map_cache *mapcache_entry; 2.35 static unsigned long nr_buckets; 2.36 2.37 @@ -5928,6 +5953,44 @@ static int qemu_map_cache_init(void) 2.38 return 0; 2.39 } 2.40 2.41 +static void qemu_remap_bucket(struct map_cache *entry, 2.42 + unsigned long address_index) 2.43 +{ 2.44 + uint8_t *vaddr_base; 2.45 + unsigned long pfns[MCACHE_BUCKET_SIZE >> PAGE_SHIFT]; 2.46 + unsigned int i, j; 2.47 + 2.48 + if (entry->vaddr_base != NULL) { 2.49 + errno = munmap(entry->vaddr_base, MCACHE_BUCKET_SIZE); 2.50 + if (errno) { 2.51 + fprintf(logfile, "unmap fails %d\n", errno); 2.52 + exit(-1); 2.53 + } 2.54 + } 2.55 + 2.56 + for (i = 0; i < MCACHE_BUCKET_SIZE >> PAGE_SHIFT; i++) 2.57 + pfns[i] = (address_index << (MCACHE_BUCKET_SHIFT-PAGE_SHIFT)) + i; 2.58 + 2.59 + vaddr_base = xc_map_foreign_batch(xc_handle, domid, PROT_READ|PROT_WRITE, 2.60 + pfns, MCACHE_BUCKET_SIZE >> PAGE_SHIFT); 2.61 + if (vaddr_base == NULL) { 2.62 + fprintf(logfile, "xc_map_foreign_batch error %d\n", errno); 2.63 + exit(-1); 2.64 + } 2.65 + 2.66 + entry->vaddr_base = vaddr_base; 2.67 + entry->paddr_index = address_index; 2.68 + 2.69 + for (i = 0; i < MCACHE_BUCKET_SIZE >> PAGE_SHIFT; i += BITS_PER_LONG) { 2.70 + unsigned long word = 0; 2.71 + j = ((i + BITS_PER_LONG) > (MCACHE_BUCKET_SIZE >> PAGE_SHIFT)) ? 2.72 + (MCACHE_BUCKET_SIZE >> PAGE_SHIFT) % BITS_PER_LONG : BITS_PER_LONG; 2.73 + while (j > 0) 2.74 + word = (word << 1) | !(pfns[i + --j] & 0xF0000000UL); 2.75 + entry->valid_mapping[i / BITS_PER_LONG] = word; 2.76 + } 2.77 +} 2.78 + 2.79 uint8_t *qemu_map_cache(target_phys_addr_t phys_addr) 2.80 { 2.81 struct map_cache *entry; 2.82 @@ -5939,34 +6002,12 @@ uint8_t *qemu_map_cache(target_phys_addr 2.83 2.84 entry = &mapcache_entry[address_index % nr_buckets]; 2.85 2.86 - if (entry->vaddr_base == NULL || entry->paddr_index != address_index) { 2.87 - /* We need to remap a bucket. */ 2.88 - uint8_t *vaddr_base; 2.89 - unsigned long pfns[MCACHE_BUCKET_SIZE >> PAGE_SHIFT]; 2.90 - unsigned int i; 2.91 - 2.92 - if (entry->vaddr_base != NULL) { 2.93 - errno = munmap(entry->vaddr_base, MCACHE_BUCKET_SIZE); 2.94 - if (errno) { 2.95 - fprintf(logfile, "unmap fails %d\n", errno); 2.96 - exit(-1); 2.97 - } 2.98 - } 2.99 - 2.100 - for (i = 0; i < MCACHE_BUCKET_SIZE >> PAGE_SHIFT; i++) 2.101 - pfns[i] = (address_index << (MCACHE_BUCKET_SHIFT-PAGE_SHIFT)) + i; 2.102 - 2.103 - vaddr_base = xc_map_foreign_batch( 2.104 - xc_handle, domid, PROT_READ|PROT_WRITE, 2.105 - pfns, MCACHE_BUCKET_SIZE >> PAGE_SHIFT); 2.106 - if (vaddr_base == NULL) { 2.107 - fprintf(logfile, "xc_map_foreign_batch error %d\n", errno); 2.108 - exit(-1); 2.109 - } 2.110 - 2.111 - entry->vaddr_base = vaddr_base; 2.112 - entry->paddr_index = address_index;; 2.113 - } 2.114 + if (entry->vaddr_base == NULL || entry->paddr_index != address_index || 2.115 + !test_bit(address_offset>>PAGE_SHIFT, entry->valid_mapping)) 2.116 + qemu_remap_bucket(entry, address_index); 2.117 + 2.118 + if (!test_bit(address_offset>>PAGE_SHIFT, entry->valid_mapping)) 2.119 + return NULL; 2.120 2.121 last_address_index = address_index; 2.122 last_address_vaddr = entry->vaddr_base; 2.123 @@ -6001,7 +6042,8 @@ void qemu_invalidate_map_cache(void) 2.124 2.125 mapcache_unlock(); 2.126 } 2.127 -#endif 2.128 + 2.129 +#endif /* defined(MAPCACHE) */ 2.130 2.131 int main(int argc, char **argv) 2.132 {
3.1 --- a/tools/ioemu/vl.h Mon Apr 09 11:12:15 2007 +0100 3.2 +++ b/tools/ioemu/vl.h Mon Apr 09 12:05:26 2007 +0100 3.3 @@ -161,21 +161,6 @@ extern FILE *logfile; 3.4 3.5 #define MAPCACHE 3.6 3.7 -#if defined(__i386__) 3.8 -#define MAX_MCACHE_SIZE 0x40000000 /* 1GB max for x86 */ 3.9 -#define MCACHE_BUCKET_SHIFT 16 3.10 -#elif defined(__x86_64__) 3.11 -#define MAX_MCACHE_SIZE 0x1000000000 /* 64GB max for x86_64 */ 3.12 -#define MCACHE_BUCKET_SHIFT 20 3.13 -#endif 3.14 - 3.15 -#define MCACHE_BUCKET_SIZE (1UL << MCACHE_BUCKET_SHIFT) 3.16 - 3.17 -struct map_cache { 3.18 - unsigned long paddr_index; 3.19 - uint8_t *vaddr_base; 3.20 -}; 3.21 - 3.22 uint8_t *qemu_map_cache(target_phys_addr_t phys_addr); 3.23 void qemu_invalidate_map_cache(void); 3.24