WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] hvm ioemu: Avoid accessing invalid pseudo

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] hvm ioemu: Avoid accessing invalid pseudophysical addresses in HVM
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Mon, 09 Apr 2007 12:30:40 -0700
Delivery-date: Mon, 09 Apr 2007 12:30:10 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# 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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] hvm ioemu: Avoid accessing invalid pseudophysical addresses in HVM, Xen patchbot-unstable <=