Commit d3f8d37fe2d0c24ec8bac9c94d5b0e2dc09c0d2a

Authored by aliguori
1 parent 494ada42

kvm: Add sanity checks to slot management (Jan Kiszka)

Fail loudly if we run out of memory slot.

Make sure that dirty log start/stop works with consistent memory regions
by reporting invalid parameters. This reveals several inconsistencies in
the vga code, patch to fix them follows later in this series.

And, for simplicity reasons, also catch and report unaligned memory
regions passed to kvm_set_phys_mem (KVM works on page basis).

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@7138 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 2 changed files with 46 additions and 16 deletions
kvm-all.c
@@ -76,6 +76,25 @@ static KVMSlot *kvm_alloc_slot(KVMState *s) @@ -76,6 +76,25 @@ static KVMSlot *kvm_alloc_slot(KVMState *s)
76 return &s->slots[i]; 76 return &s->slots[i];
77 } 77 }
78 78
  79 + fprintf(stderr, "%s: no free slot available\n", __func__);
  80 + abort();
  81 +}
  82 +
  83 +static KVMSlot *kvm_lookup_matching_slot(KVMState *s,
  84 + target_phys_addr_t start_addr,
  85 + target_phys_addr_t end_addr)
  86 +{
  87 + int i;
  88 +
  89 + for (i = 0; i < ARRAY_SIZE(s->slots); i++) {
  90 + KVMSlot *mem = &s->slots[i];
  91 +
  92 + if (start_addr == mem->start_addr &&
  93 + end_addr == mem->start_addr + mem->memory_size) {
  94 + return mem;
  95 + }
  96 + }
  97 +
79 return NULL; 98 return NULL;
80 } 99 }
81 100
@@ -163,14 +182,16 @@ int kvm_sync_vcpus(void) @@ -163,14 +182,16 @@ int kvm_sync_vcpus(void)
163 /* 182 /*
164 * dirty pages logging control 183 * dirty pages logging control
165 */ 184 */
166 -static int kvm_dirty_pages_log_change(target_phys_addr_t phys_addr, target_phys_addr_t end_addr,  
167 - unsigned flags, 185 +static int kvm_dirty_pages_log_change(target_phys_addr_t phys_addr,
  186 + ram_addr_t size, unsigned flags,
168 unsigned mask) 187 unsigned mask)
169 { 188 {
170 KVMState *s = kvm_state; 189 KVMState *s = kvm_state;
171 - KVMSlot *mem = kvm_lookup_slot(s, phys_addr); 190 + KVMSlot *mem = kvm_lookup_matching_slot(s, phys_addr, phys_addr + size);
172 if (mem == NULL) { 191 if (mem == NULL) {
173 - dprintf("invalid parameters %llx-%llx\n", phys_addr, end_addr); 192 + fprintf(stderr, "BUG: %s: invalid parameters " TARGET_FMT_plx "-"
  193 + TARGET_FMT_plx "\n", __func__, phys_addr,
  194 + phys_addr + size - 1);
174 return -EINVAL; 195 return -EINVAL;
175 } 196 }
176 197
@@ -184,16 +205,16 @@ static int kvm_dirty_pages_log_change(target_phys_addr_t phys_addr, target_phys_ @@ -184,16 +205,16 @@ static int kvm_dirty_pages_log_change(target_phys_addr_t phys_addr, target_phys_
184 return kvm_set_user_memory_region(s, mem); 205 return kvm_set_user_memory_region(s, mem);
185 } 206 }
186 207
187 -int kvm_log_start(target_phys_addr_t phys_addr, target_phys_addr_t end_addr) 208 +int kvm_log_start(target_phys_addr_t phys_addr, ram_addr_t size)
188 { 209 {
189 - return kvm_dirty_pages_log_change(phys_addr, end_addr, 210 + return kvm_dirty_pages_log_change(phys_addr, size,
190 KVM_MEM_LOG_DIRTY_PAGES, 211 KVM_MEM_LOG_DIRTY_PAGES,
191 KVM_MEM_LOG_DIRTY_PAGES); 212 KVM_MEM_LOG_DIRTY_PAGES);
192 } 213 }
193 214
194 -int kvm_log_stop(target_phys_addr_t phys_addr, target_phys_addr_t end_addr) 215 +int kvm_log_stop(target_phys_addr_t phys_addr, ram_addr_t size)
195 { 216 {
196 - return kvm_dirty_pages_log_change(phys_addr, end_addr, 217 + return kvm_dirty_pages_log_change(phys_addr, size,
197 0, 218 0,
198 KVM_MEM_LOG_DIRTY_PAGES); 219 KVM_MEM_LOG_DIRTY_PAGES);
199 } 220 }
@@ -203,21 +224,24 @@ int kvm_log_stop(target_phys_addr_t phys_addr, target_phys_addr_t end_addr) @@ -203,21 +224,24 @@ int kvm_log_stop(target_phys_addr_t phys_addr, target_phys_addr_t end_addr)
203 * This function updates qemu's dirty bitmap using cpu_physical_memory_set_dirty(). 224 * This function updates qemu's dirty bitmap using cpu_physical_memory_set_dirty().
204 * This means all bits are set to dirty. 225 * This means all bits are set to dirty.
205 * 226 *
206 - * @start_add: start of logged region. This is what we use to search the memslot 227 + * @start_add: start of logged region.
207 * @end_addr: end of logged region. 228 * @end_addr: end of logged region.
208 */ 229 */
209 -void kvm_physical_sync_dirty_bitmap(target_phys_addr_t start_addr, target_phys_addr_t end_addr) 230 +void kvm_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
  231 + target_phys_addr_t end_addr)
210 { 232 {
211 KVMState *s = kvm_state; 233 KVMState *s = kvm_state;
212 KVMDirtyLog d; 234 KVMDirtyLog d;
213 - KVMSlot *mem = kvm_lookup_slot(s, start_addr); 235 + KVMSlot *mem = kvm_lookup_matching_slot(s, start_addr, end_addr);
214 unsigned long alloc_size; 236 unsigned long alloc_size;
215 ram_addr_t addr; 237 ram_addr_t addr;
216 target_phys_addr_t phys_addr = start_addr; 238 target_phys_addr_t phys_addr = start_addr;
217 239
218 - dprintf("sync addr: %llx into %lx\n", start_addr, mem->phys_offset); 240 + dprintf("sync addr: " TARGET_FMT_lx " into %lx\n", start_addr,
  241 + mem->phys_offset);
219 if (mem == NULL) { 242 if (mem == NULL) {
220 - fprintf(stderr, "BUG: %s: invalid parameters\n", __func__); 243 + fprintf(stderr, "BUG: %s: invalid parameters " TARGET_FMT_plx "-"
  244 + TARGET_FMT_plx "\n", __func__, phys_addr, end_addr - 1);
221 return; 245 return;
222 } 246 }
223 247
@@ -545,6 +569,11 @@ void kvm_set_phys_mem(target_phys_addr_t start_addr, @@ -545,6 +569,11 @@ void kvm_set_phys_mem(target_phys_addr_t start_addr,
545 ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK; 569 ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK;
546 KVMSlot *mem; 570 KVMSlot *mem;
547 571
  572 + if (start_addr & ~TARGET_PAGE_MASK) {
  573 + fprintf(stderr, "Only page-aligned memory slots supported\n");
  574 + abort();
  575 + }
  576 +
548 /* KVM does not support read-only slots */ 577 /* KVM does not support read-only slots */
549 phys_offset &= ~IO_MEM_ROM; 578 phys_offset &= ~IO_MEM_ROM;
550 579
@@ -40,10 +40,11 @@ void kvm_set_phys_mem(target_phys_addr_t start_addr, @@ -40,10 +40,11 @@ void kvm_set_phys_mem(target_phys_addr_t start_addr,
40 ram_addr_t size, 40 ram_addr_t size,
41 ram_addr_t phys_offset); 41 ram_addr_t phys_offset);
42 42
43 -void kvm_physical_sync_dirty_bitmap(target_phys_addr_t start_addr, target_phys_addr_t end_addr); 43 +void kvm_physical_sync_dirty_bitmap(target_phys_addr_t start_addr,
  44 + target_phys_addr_t end_addr);
44 45
45 -int kvm_log_start(target_phys_addr_t phys_addr, target_phys_addr_t len);  
46 -int kvm_log_stop(target_phys_addr_t phys_addr, target_phys_addr_t len); 46 +int kvm_log_start(target_phys_addr_t phys_addr, ram_addr_t size);
  47 +int kvm_log_stop(target_phys_addr_t phys_addr, ram_addr_t size);
47 48
48 int kvm_has_sync_mmu(void); 49 int kvm_has_sync_mmu(void);
49 50