repository: /home/avi/kvm
branch: master
commit ced78769c339ae967d683487dc805eba390481da
Author: Izik Eidus <[EMAIL PROTECTED]>
Date:   Sat Oct 27 21:18:15 2007 +0200

    make kvmctl allocate memory slot numbers automaticly
    this make the registation of memory slot safer, and make it more easy to
    vmctl integrate with qemu.
    
    note: if the kernel have no set tss ioctl, then slot 0 must be saved and 
used
    only by the extended memory.
    
    Signed-off-by: Izik Eidus <[EMAIL PROTECTED]>

diff --git a/qemu/hw/cirrus_vga.c b/qemu/hw/cirrus_vga.c
index 1693ed5..4c585a4 100644
--- a/qemu/hw/cirrus_vga.c
+++ b/qemu/hw/cirrus_vga.c
@@ -2617,7 +2617,7 @@ void *set_vram_mapping(unsigned long begin, unsigned long 
end)
     end = begin + VGA_RAM_SIZE;
     end = (end + TARGET_PAGE_SIZE -1 ) & TARGET_PAGE_MASK;
 
-    vram_pointer = kvm_create_phys_mem(kvm_context, begin, end - begin, 1, 
+    vram_pointer = kvm_create_phys_mem(kvm_context, begin, end - begin,
                                       1, 1);
 
     if (vram_pointer == NULL) {
@@ -2637,12 +2637,13 @@ int unset_vram_mapping(unsigned long begin, unsigned 
long end)
     begin = begin & TARGET_PAGE_MASK;
     end = (end + TARGET_PAGE_SIZE -1 ) & TARGET_PAGE_MASK;
 
-    kvm_destroy_phys_mem(kvm_context, begin, end - begin, 1);
+    kvm_destroy_phys_mem(kvm_context, begin, end - begin);
 
     return 0;
 }
 
-static void kvm_update_vga_alias(CirrusVGAState *s, int ok, int bank)
+static void kvm_update_vga_alias(CirrusVGAState *s, int ok, int bank,
+                                 unsigned long phys_addr)
 {
     unsigned limit, base;
 
@@ -2656,22 +2657,22 @@ static void kvm_update_vga_alias(CirrusVGAState *s, int 
ok, int bank)
        if (!s->aliases_enabled
            || base != s->aliased_bank_base[bank]
            || limit != s->aliased_bank_limit[bank]) {
-           kvm_create_memory_alias(kvm_context, bank,
+           kvm_create_memory_alias(kvm_context, phys_addr,
                                    0xa0000 + bank * 0x8000,
                                    limit, base);
            s->aliased_bank_base[bank] = base;
            s->aliased_bank_limit[bank] = limit;
        }
     } else {
-       kvm_destroy_memory_alias(kvm_context, bank);
+       kvm_destroy_memory_alias(kvm_context, phys_addr);
     }
 }
 
 static void kvm_update_vga_aliases(CirrusVGAState *s, int ok)
 {
     if (kvm_allowed) {
-       kvm_update_vga_alias(s, ok, 0);
-       kvm_update_vga_alias(s, ok, 1);
+       kvm_update_vga_alias(s, ok, 0, 0xc0000);
+       kvm_update_vga_alias(s, ok, 1, s->map_addr);
     }
     s->aliases_enabled = ok;
 }
diff --git a/qemu/hw/pc.c b/qemu/hw/pc.c
index 0ba0c90..16ad0bd 100644
--- a/qemu/hw/pc.c
+++ b/qemu/hw/pc.c
@@ -796,7 +796,7 @@ static void pc_init1(ram_addr_t ram_size, int vga_ram_size, 
int boot_device,
 #ifdef USE_KVM
     if (kvm_allowed) {
            bios_mem = kvm_create_phys_mem(kvm_context, (uint32_t)(-bios_size),
-                                          bios_size, 2, 0, 1);
+                                          bios_size, 0, 1);
            if (!bios_mem)
                    exit(1);
            memcpy(bios_mem, phys_ram_base + bios_offset, bios_size);
diff --git a/qemu/hw/vga.c b/qemu/hw/vga.c
index b309369..3841b78 100644
--- a/qemu/hw/vga.c
+++ b/qemu/hw/vga.c
@@ -1452,7 +1452,7 @@ static void vga_draw_graphic(VGAState *s, int full_update)
     int r;
 
     if (kvm_allowed) {
-           r = kvm_get_dirty_pages(kvm_context, 1, &bitmap);
+           r = kvm_get_dirty_pages(kvm_context, s->map_addr, &bitmap);
            if (r < 0)
                    fprintf(stderr, "kvm: get_dirty_pages returned %d\n", r);
     }
diff --git a/user/kvmctl.c b/user/kvmctl.c
index 90df2f3..054d007 100644
--- a/user/kvmctl.c
+++ b/user/kvmctl.c
@@ -45,6 +45,8 @@ static int kvm_abi = EXPECTED_KVM_API_VERSION;
 /* FIXME: share this number with kvm */
 /* FIXME: or dynamically alloc/realloc regions */
 #define KVM_MAX_NUM_MEM_REGIONS 8u
+int free_slots[KVM_MAX_NUM_MEM_REGIONS];
+unsigned long phys_addr_slots[KVM_MAX_NUM_MEM_REGIONS];
 #define MAX_VCPUS 4
 
 /**
@@ -73,6 +75,57 @@ struct kvm_context {
        int irqchip_in_kernel;
 };
 
+static void init_slots()
+{
+       int i;
+
+       for (i = 0; i < KVM_MAX_NUM_MEM_REGIONS; ++i)
+               free_slots[i] = 0;
+}
+
+static int get_free_slot(kvm_context_t kvm)
+{
+       int i;
+       int tss_ext;
+
+#ifdef KVM_CAP_SET_TSS_ADDR
+       tss_ext = ioctl(kvm->fd, KVM_CHECK_EXTENSION, KVM_CAP_SET_TSS_ADDR);
+#else
+       tss_ext = 0;
+#endif
+
+       /*
+        * on older kernels where the set tss ioctl is not supprted we must save
+        * slot 0 to hold the extended memory, as the vmx will use the last 3
+        * pages of this slot.
+        */
+       if (tss_ext > 0)
+               i = 0;
+       else
+               i = 1;
+
+       for (; i < KVM_MAX_NUM_MEM_REGIONS; ++i)
+               if (!free_slots[i])
+                       return i;
+       return -1;
+}
+
+static void register_slot(int slot, unsigned long phys_addr)
+{
+       free_slots[slot] = 1;
+       phys_addr_slots[slot] = phys_addr;
+}
+
+static int get_slot(unsigned long phys_addr)
+{
+       int i;
+
+       for (i = 0; i < KVM_MAX_NUM_MEM_REGIONS; ++i)
+               if (free_slots[i] && phys_addr_slots[i] == phys_addr)
+                       return i;
+       return -1;
+}
+
 /*
  * memory regions parameters
  */
@@ -300,45 +353,61 @@ int kvm_alloc_kernel_memory(kvm_context_t kvm, unsigned 
long memory,
        unsigned long exmem = 0xc0000;
        unsigned long pcimem = 0xf0000000;
        int r;
+       int tss_ext;
        struct kvm_memory_region low_memory = {
-               .slot = 3,
                .memory_size = memory  < dosmem ? memory : dosmem,
                .guest_phys_addr = 0,
        };
        struct kvm_memory_region extended_memory = {
-               .slot = 0,
                .memory_size = memory < exmem ? 0 : memory - exmem,
                .guest_phys_addr = exmem,
        };
        struct kvm_memory_region above_4g_memory = {
-               .slot = 4,
                .memory_size = memory < pcimem ? 0 : memory - pcimem,
                .guest_phys_addr = 0x100000000ULL,
        };
 
+#ifdef KVM_CAP_SET_TSS_ADDR
+       tss_ext = ioctl(kvm->fd, KVM_CHECK_EXTENSION, KVM_CAP_SET_TSS_ADDR);
+#else
+       tss_ext = 0;
+#endif
+
        if (memory >= pcimem)
                extended_memory.memory_size = pcimem - exmem;
 
        /* 640K should be enough. */
+       low_memory.slot = get_free_slot(kvm);
        r = ioctl(kvm->vm_fd, KVM_SET_MEMORY_REGION, &low_memory);
        if (r == -1) {
                fprintf(stderr, "kvm_create_memory_region: %m\n");
                return -1;
        }
+       register_slot(low_memory.slot, low_memory.guest_phys_addr);
+
        if (extended_memory.memory_size) {
+               if (tss_ext > 0)
+                       extended_memory.slot = get_free_slot(kvm);
+               else
+                       extended_memory.slot = 0;
                r = ioctl(kvm->vm_fd, KVM_SET_MEMORY_REGION, &extended_memory);
                if (r == -1) {
                        fprintf(stderr, "kvm_create_memory_region: %m\n");
                        return -1;
                }
+               register_slot(extended_memory.slot,
+                             extended_memory.guest_phys_addr);
        }
 
        if (above_4g_memory.memory_size) {
+               above_4g_memory.slot = get_free_slot(kvm);
                r = ioctl(kvm->vm_fd, KVM_SET_MEMORY_REGION, &above_4g_memory);
                if (r == -1) {
                        fprintf(stderr, "kvm_create_memory_region: %m\n");
                        return -1;
                }
+               register_slot(above_4g_memory.slot,
+                             above_4g_memory.guest_phys_addr);
        }
 
        kvm_memory_region_save_params(kvm, &low_memory);
@@ -359,22 +428,26 @@ int kvm_alloc_userspace_memory(kvm_context_t kvm, 
unsigned long memory,
        unsigned long exmem = 0xc0000;
        unsigned long pcimem = 0xf0000000;
        int r;
+       int tss_ext;
        struct kvm_userspace_memory_region low_memory = {
-               .slot = 3,
                .memory_size = memory  < dosmem ? memory : dosmem,
                .guest_phys_addr = 0,
        };
        struct kvm_userspace_memory_region extended_memory = {
-               .slot = 0,
                .memory_size = memory < exmem ? 0 : memory - exmem,
                .guest_phys_addr = exmem,
        };
        struct kvm_userspace_memory_region above_4g_memory = {
-               .slot = 4,
                .memory_size = memory < pcimem ? 0 : memory - pcimem,
                .guest_phys_addr = 0x100000000ULL,
        };
 
+#ifdef KVM_CAP_SET_TSS_ADDR
+       tss_ext = ioctl(kvm->fd, KVM_CHECK_EXTENSION, KVM_CAP_SET_TSS_ADDR);
+#else
+       tss_ext = 0;
+#endif
+
        if (memory >= pcimem) {
                extended_memory.memory_size = pcimem - exmem;
                *vm_mem = mmap(NULL, memory + 0x100000000ULL - pcimem,
@@ -389,14 +462,16 @@ int kvm_alloc_userspace_memory(kvm_context_t kvm, 
unsigned long memory,
                return -1;
        }
 
-
        low_memory.userspace_addr = (unsigned long)*vm_mem;
+       low_memory.slot = get_free_slot(kvm);
        /* 640K should be enough. */
        r = ioctl(kvm->vm_fd, KVM_SET_USER_MEMORY_REGION, &low_memory);
        if (r == -1) {
                fprintf(stderr, "kvm_create_memory_region: %m\n");
                return -1;
        }
+       register_slot(low_memory.slot, low_memory.guest_phys_addr);
+
        if (extended_memory.memory_size) {
                r = munmap(*vm_mem + dosmem, exmem - dosmem);
                if (r == -1) {
@@ -405,11 +480,17 @@ int kvm_alloc_userspace_memory(kvm_context_t kvm, 
unsigned long memory,
                        return -1;
                }
                extended_memory.userspace_addr = (unsigned long)(*vm_mem + 
exmem);
+               if (tss_ext > 0)
+                       extended_memory.slot = get_free_slot(kvm);
+               else
+                       extended_memory.slot = 0;
                r = ioctl(kvm->vm_fd, KVM_SET_USER_MEMORY_REGION, 
&extended_memory);
                if (r == -1) {
                        fprintf(stderr, "kvm_create_memory_region: %m\n");
                        return -1;
                }
+               register_slot(extended_memory.slot,
+                             extended_memory.guest_phys_addr);
        }
 
        if (above_4g_memory.memory_size) {
@@ -420,11 +501,14 @@ int kvm_alloc_userspace_memory(kvm_context_t kvm, 
unsigned long memory,
                        return -1;
                }
                above_4g_memory.userspace_addr = (unsigned long)(*vm_mem + 
0x100000000ULL);
+               above_4g_memory.slot = get_free_slot(kvm);
                r = ioctl(kvm->vm_fd, KVM_SET_USER_MEMORY_REGION, 
&above_4g_memory);
                if (r == -1) {
                        fprintf(stderr, "kvm_create_memory_region: %m\n");
                        return -1;
                }
+               register_slot(above_4g_memory.slot,
+                             above_4g_memory.guest_phys_addr);
        }
 
        kvm_userspace_memory_region_save_params(kvm, &low_memory);
@@ -547,6 +631,7 @@ int kvm_create(kvm_context_t kvm, unsigned long 
phys_mem_bytes, void **vm_mem)
        r = kvm_init_tss(kvm);
        if (r < 0)
                return r;
+       init_slots();
        r = kvm_create_default_phys_mem(kvm, phys_mem_bytes, vm_mem);
        if (r < 0)
                return r;
@@ -559,23 +644,24 @@ int kvm_create(kvm_context_t kvm, unsigned long 
phys_mem_bytes, void **vm_mem)
 }
 
 void *kvm_create_kernel_phys_mem(kvm_context_t kvm, unsigned long phys_start,
-                       unsigned long len, int slot, int log, int writable)
+                       unsigned long len, int log, int writable)
 {
        int r;
        int prot = PROT_READ;
        void *ptr;
        struct kvm_memory_region memory = {
-               .slot = slot,
                .memory_size = len,
                .guest_phys_addr = phys_start,
                .flags = log ? KVM_MEM_LOG_DIRTY_PAGES : 0,
        };
 
+       memory.slot = get_free_slot(kvm);
        r = ioctl(kvm->vm_fd, KVM_SET_MEMORY_REGION, &memory);
        if (r == -1) {
                fprintf(stderr, "create_kernel_phys_mem: %s", strerror(errno));
                return 0;
        }
+       register_slot(memory.slot, memory.guest_phys_addr);
        kvm_memory_region_save_params(kvm, &memory);
 
        if (writable)
@@ -593,13 +679,12 @@ void *kvm_create_kernel_phys_mem(kvm_context_t kvm, 
unsigned long phys_start,
 #ifdef KVM_CAP_USER_MEMORY
 
 void *kvm_create_userspace_phys_mem(kvm_context_t kvm, unsigned long 
phys_start,
-                       unsigned long len, int slot, int log, int writable)
+                       unsigned long len, int log, int writable)
 {
        int r;
        int prot = PROT_READ;
        void *ptr;
        struct kvm_userspace_memory_region memory = {
-               .slot = slot,
                .memory_size = len,
                .guest_phys_addr = phys_start,
                .flags = log ? KVM_MEM_LOG_DIRTY_PAGES : 0,
@@ -617,11 +702,13 @@ void *kvm_create_userspace_phys_mem(kvm_context_t kvm, 
unsigned long phys_start,
        memset(ptr, 0, len);
 
        memory.userspace_addr = (unsigned long)ptr;
+       memory.slot = get_free_slot(kvm);
        r = ioctl(kvm->vm_fd, KVM_SET_USER_MEMORY_REGION, &memory);
        if (r == -1) {
                fprintf(stderr, "create_userspace_phys_mem: %s", 
strerror(errno));
                return 0;
        }
+       register_slot(memory.slot, memory.guest_phys_addr);
 
        kvm_userspace_memory_region_save_params(kvm, &memory);
 
@@ -631,28 +718,27 @@ void *kvm_create_userspace_phys_mem(kvm_context_t kvm, 
unsigned long phys_start,
 #endif
 
 void *kvm_create_phys_mem(kvm_context_t kvm, unsigned long phys_start,
-                         unsigned long len, int slot, int log, int writable)
+                         unsigned long len, int log, int writable)
 {
 #ifdef KVM_CAP_USER_MEMORY
        int r;
 
        r = ioctl(kvm->fd, KVM_CHECK_EXTENSION, KVM_CAP_USER_MEMORY);
        if (r > 0)
-               return kvm_create_userspace_phys_mem(kvm, phys_start, len, slot,
+               return kvm_create_userspace_phys_mem(kvm, phys_start, len,
                                                                log, writable);
        else
 #endif
-               return kvm_create_kernel_phys_mem(kvm, phys_start, len, slot,
+               return kvm_create_kernel_phys_mem(kvm, phys_start, len,
                                                                log, writable);
 }
 
 int kvm_register_userspace_phys_mem(kvm_context_t kvm,
                        unsigned long phys_start, void *userspace_addr,
-                       unsigned long len, int slot, int log)
+                       unsigned long len, int log)
 {
 #ifdef KVM_CAP_USER_MEMORY
        struct kvm_userspace_memory_region memory = {
-               .slot = slot,
                .memory_size = len,
                .guest_phys_addr = phys_start,
                .userspace_addr = (intptr_t)userspace_addr,
@@ -663,11 +749,13 @@ int kvm_register_userspace_phys_mem(kvm_context_t kvm,
        if (!kvm->physical_memory)
                kvm->physical_memory = userspace_addr - phys_start;
 
+       memory.slot = get_free_slot(kvm);
        r = ioctl(kvm->vm_fd, KVM_SET_USER_MEMORY_REGION, &memory);
        if (r == -1) {
                fprintf(stderr, "create_userspace_phys_mem: %s\n", 
strerror(errno));
                return -1;
        }
+       register_slot(memory.slot, memory.guest_phys_addr);
 
        kvm_userspace_memory_region_save_params(kvm, &memory);
         return 0;
@@ -681,10 +769,13 @@ int kvm_register_userspace_phys_mem(kvm_context_t kvm,
  * phys_start, len and slot are the params passed to kvm_create_phys_mem()
  */
 void kvm_destroy_phys_mem(kvm_context_t kvm, unsigned long phys_start, 
-                         unsigned long len, int slot)
+                         unsigned long len)
 {
+       int slot;
        struct kvm_memory_region *mem;
 
+       slot = get_slot(phys_start);
+
        if (slot >= KVM_MAX_NUM_MEM_REGIONS) {
                fprintf(stderr, "BUG: %s: invalid parameters (slot=%d)\n",
                        __FUNCTION__, slot);
@@ -697,17 +788,16 @@ void kvm_destroy_phys_mem(kvm_context_t kvm, unsigned 
long phys_start,
                        __FUNCTION__, phys_start, mem->guest_phys_addr);
                phys_start = mem->guest_phys_addr;
        }
-       kvm_create_phys_mem(kvm, phys_start, 0, slot, 0, 0);
+       kvm_create_phys_mem(kvm, phys_start, 0, 0, 0);
 }
 
 int kvm_create_memory_alias(kvm_context_t kvm,
-                           int slot,
+                           uint64_t phys_addr,
                            uint64_t phys_start,
                            uint64_t len,
                            uint64_t target_phys)
 {
        struct kvm_memory_alias alias = {
-               .slot = slot,
                .flags = 0,
                .guest_phys_addr = phys_start,
                .memory_size = len,
@@ -716,6 +806,8 @@ int kvm_create_memory_alias(kvm_context_t kvm,
        int fd = kvm->vm_fd;
        int r;
 
+       alias.slot = get_slot(phys_addr);
+
        r = ioctl(fd, KVM_SET_MEMORY_ALIAS, &alias);
        if (r == -1)
            return -errno;
@@ -723,9 +815,9 @@ int kvm_create_memory_alias(kvm_context_t kvm,
        return 0;
 }
 
-int kvm_destroy_memory_alias(kvm_context_t kvm, int slot)
+int kvm_destroy_memory_alias(kvm_context_t kvm, uint64_t phys_addr)
 {
-       return kvm_create_memory_alias(kvm, slot, 0, 0, 0);
+       return kvm_create_memory_alias(kvm, phys_addr, 0, 0, 0);
 }
 
 static int kvm_get_map(kvm_context_t kvm, int ioctl_num, int slot, void *buf)
@@ -743,13 +835,19 @@ static int kvm_get_map(kvm_context_t kvm, int ioctl_num, 
int slot, void *buf)
        return 0;
 }
 
-int kvm_get_dirty_pages(kvm_context_t kvm, int slot, void *buf)
+int kvm_get_dirty_pages(kvm_context_t kvm, unsigned long phys_addr, void *buf)
 {
+       int slot;
+
+       slot = get_slot(phys_addr);
        return kvm_get_map(kvm, KVM_GET_DIRTY_LOG, slot, buf);
 }
 
-int kvm_get_mem_map(kvm_context_t kvm, int slot, void *buf)
+int kvm_get_mem_map(kvm_context_t kvm, unsigned long phys_addr, void *buf)
 {
+       int slot;
+
+       slot = get_slot(phys_addr);
 #ifdef KVM_GET_MEM_MAP
        return kvm_get_map(kvm, KVM_GET_MEM_MAP, slot, buf);
 #else /* not KVM_GET_MEM_MAP ==> fake it: all pages exist */
diff --git a/user/kvmctl.h b/user/kvmctl.h
index 26a6eee..56859b2 100644
--- a/user/kvmctl.h
+++ b/user/kvmctl.h
@@ -415,13 +415,13 @@ void kvm_show_regs(kvm_context_t kvm, int vcpu);
 int kvm_set_tss_addr(kvm_context_t kvm, unsigned long addr);
 
 void *kvm_create_phys_mem(kvm_context_t, unsigned long phys_start, 
-                         unsigned long len, int slot, int log, int writable);
+                         unsigned long len, int log, int writable);
 void kvm_destroy_phys_mem(kvm_context_t, unsigned long phys_start, 
-                         unsigned long len, int slot);
+                         unsigned long len);
 int kvm_register_userspace_phys_mem(kvm_context_t kvm,
                        unsigned long phys_start, void *userspace_addr,
-                       unsigned long len, int slot, int log);
-int kvm_get_dirty_pages(kvm_context_t, int slot, void *buf);
+                       unsigned long len, int log);
+int kvm_get_dirty_pages(kvm_context_t, unsigned long phys_addr, void *buf);
 
 
 /*!
@@ -431,7 +431,7 @@ int kvm_get_dirty_pages(kvm_context_t, int slot, void *buf);
  * accesses the alias region, it will behave exactly as if it accessed
  * the target memory.
  */
-int kvm_create_memory_alias(kvm_context_t, int slot,
+int kvm_create_memory_alias(kvm_context_t, uint64_t phys_addr,
                            uint64_t phys_start, uint64_t len,
                            uint64_t target_phys);
 
@@ -440,16 +440,16 @@ int kvm_create_memory_alias(kvm_context_t, int slot,
  *
  * Removes an alias created with kvm_create_memory_alias().
  */
-int kvm_destroy_memory_alias(kvm_context_t, int slot);
+int kvm_destroy_memory_alias(kvm_context_t, uint64_t phys_addr);
 
 /*!
  * \brief Get a bitmap of guest ram pages which are allocated to the guest.
  *
  * \param kvm Pointer to the current kvm_context
- * \param slot Memory slot number
+ * \param phys_addr Memory slot phys addr
  * \param bitmap Long aligned address of a big enough bitmap (one bit per page)
  */
-int kvm_get_mem_map(kvm_context_t kvm, int slot, void *bitmap);
+int kvm_get_mem_map(kvm_context_t kvm, unsigned long phys_addr, void *bitmap);
 int kvm_set_irq_level(kvm_context_t kvm, int irq, int level);
 
 /*!

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
kvm-commits mailing list
kvm-commits@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/kvm-commits

Reply via email to