Commit 62d60e8cc4c4c8aebdfd97f10087456d2690c0a0

Authored by aliguori
1 parent 87006d13

Make KVM slot management more robust

KVM keeps track of physical memory based on slots in the kernel.  The current
code that translates QEMU memory mappings to slots work but is not robust
in the fact of reregistering partial regions of memory.

This patch does the right thing for reregistering partial regions of memory.  It
also prevents QEMU from using KVM private slots.

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>



git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@5734 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 40 additions and 2 deletions
kvm-all.c
@@ -50,6 +50,9 @@ static KVMSlot *kvm_alloc_slot(KVMState *s) @@ -50,6 +50,9 @@ static KVMSlot *kvm_alloc_slot(KVMState *s)
50 int i; 50 int i;
51 51
52 for (i = 0; i < ARRAY_SIZE(s->slots); i++) { 52 for (i = 0; i < ARRAY_SIZE(s->slots); i++) {
  53 + /* KVM private memory slots */
  54 + if (i >= 8 && i < 12)
  55 + continue;
53 if (s->slots[i].memory_size == 0) 56 if (s->slots[i].memory_size == 0)
54 return &s->slots[i]; 57 return &s->slots[i];
55 } 58 }
@@ -327,10 +330,45 @@ void kvm_set_phys_mem(target_phys_addr_t start_addr, @@ -327,10 +330,45 @@ void kvm_set_phys_mem(target_phys_addr_t start_addr,
327 330
328 kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION, mem); 331 kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION, mem);
329 } else if (start_addr >= mem->guest_phys_addr && 332 } else if (start_addr >= mem->guest_phys_addr &&
330 - (start_addr + size) <= (mem->guest_phys_addr + mem->memory_size)) 333 + (start_addr + size) <= (mem->guest_phys_addr +
  334 + mem->memory_size)) {
  335 + KVMSlot slot;
  336 + target_phys_addr_t mem_start;
  337 + ram_addr_t mem_size, mem_offset;
  338 +
  339 + /* Not splitting */
  340 + if ((phys_offset - (start_addr - mem->guest_phys_addr)) ==
  341 + ((uint8_t *)mem->userspace_addr - phys_ram_base))
  342 + return;
  343 +
  344 + /* unregister whole slot */
  345 + memcpy(&slot, mem, sizeof(slot));
  346 + mem->memory_size = 0;
  347 + kvm_vm_ioctl(s, KVM_SET_USER_MEMORY_REGION, mem);
  348 +
  349 + /* register prefix slot */
  350 + mem_start = slot.guest_phys_addr;
  351 + mem_size = start_addr - slot.guest_phys_addr;
  352 + mem_offset = (uint8_t *)slot.userspace_addr - phys_ram_base;
  353 + if (mem_size)
  354 + kvm_set_phys_mem(mem_start, mem_size, mem_offset);
  355 +
  356 + /* register new slot */
  357 + kvm_set_phys_mem(start_addr, size, phys_offset);
  358 +
  359 + /* register suffix slot */
  360 + mem_start = start_addr + size;
  361 + mem_offset += mem_size + size;
  362 + mem_size = slot.memory_size - mem_size - size;
  363 + if (mem_size)
  364 + kvm_set_phys_mem(mem_start, mem_size, mem_offset);
  365 +
331 return; 366 return;
  367 + } else {
  368 + printf("Registering overlapping slot\n");
  369 + abort();
  370 + }
332 } 371 }
333 -  
334 /* KVM does not need to know about this memory */ 372 /* KVM does not need to know about this memory */
335 if (flags >= IO_MEM_UNASSIGNED) 373 if (flags >= IO_MEM_UNASSIGNED)
336 return; 374 return;