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 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 98 return NULL;
80 99 }
81 100  
... ... @@ -163,14 +182,16 @@ int kvm_sync_vcpus(void)
163 182 /*
164 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 187 unsigned mask)
169 188 {
170 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 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 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 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 211 KVM_MEM_LOG_DIRTY_PAGES,
191 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 218 0,
198 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 224 * This function updates qemu's dirty bitmap using cpu_physical_memory_set_dirty().
204 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 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 233 KVMState *s = kvm_state;
212 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 236 unsigned long alloc_size;
215 237 ram_addr_t addr;
216 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 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 245 return;
222 246 }
223 247  
... ... @@ -545,6 +569,11 @@ void kvm_set_phys_mem(target_phys_addr_t start_addr,
545 569 ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK;
546 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 577 /* KVM does not support read-only slots */
549 578 phys_offset &= ~IO_MEM_ROM;
550 579  
... ...
... ... @@ -40,10 +40,11 @@ void kvm_set_phys_mem(target_phys_addr_t start_addr,
40 40 ram_addr_t size,
41 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 49 int kvm_has_sync_mmu(void);
49 50  
... ...