[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH 13/23] kvm: convert to MemoryListener API



On 2011-12-19 15:13, Avi Kivity wrote:
> Drop the use of cpu_register_phys_memory_client() in favour of the new
> MemoryListener API.  The new API simplifies the caller, since there is no
> need to deal with splitting and merging slots; however this is not exploited
> in this patch.

This breaks graphical grub1 with cirrus-vga in KVM mode. Dunno why yet.

Jan

> 
> Signed-off-by: Avi Kivity <avi@xxxxxxxxxx>
> ---
>  kvm-all.c |  107 
> ++++++++++++++++++++++++++++++++++++++++---------------------
>  1 files changed, 70 insertions(+), 37 deletions(-)
> 
> diff --git a/kvm-all.c b/kvm-all.c
> index 4f58ae8..138e0a2 100644
> --- a/kvm-all.c
> +++ b/kvm-all.c
> @@ -27,6 +27,7 @@
>  #include "gdbstub.h"
>  #include "kvm.h"
>  #include "bswap.h"
> +#include "memory.h"
>  
>  /* This check must be after config-host.h is included */
>  #ifdef CONFIG_EVENTFD
> @@ -289,16 +290,28 @@ static int 
> kvm_dirty_pages_log_change(target_phys_addr_t phys_addr,
>      return kvm_slot_dirty_pages_log_change(mem, log_dirty);
>  }
>  
> -static int kvm_log_start(CPUPhysMemoryClient *client,
> -                         target_phys_addr_t phys_addr, ram_addr_t size)
> +static void kvm_log_start(MemoryListener *listener,
> +                          MemoryRegionSection *section)
>  {
> -    return kvm_dirty_pages_log_change(phys_addr, size, true);
> +    int r;
> +
> +    r = kvm_dirty_pages_log_change(section->offset_within_address_space,
> +                                   section->size, true);
> +    if (r < 0) {
> +        abort();
> +    }
>  }
>  
> -static int kvm_log_stop(CPUPhysMemoryClient *client,
> -                        target_phys_addr_t phys_addr, ram_addr_t size)
> +static void kvm_log_stop(MemoryListener *listener,
> +                          MemoryRegionSection *section)
>  {
> -    return kvm_dirty_pages_log_change(phys_addr, size, false);
> +    int r;
> +
> +    r = kvm_dirty_pages_log_change(section->offset_within_address_space,
> +                                   section->size, false);
> +    if (r < 0) {
> +        abort();
> +    }
>  }
>  
>  static int kvm_set_migration_log(int enable)
> @@ -519,13 +532,15 @@ static int kvm_check_many_ioeventfds(void)
>      return NULL;
>  }
>  
> -static void kvm_set_phys_mem(target_phys_addr_t start_addr, ram_addr_t size,
> -                             ram_addr_t phys_offset, bool log_dirty)
> +static void kvm_set_phys_mem(MemoryRegionSection *section, bool add)
>  {
>      KVMState *s = kvm_state;
> -    ram_addr_t flags = phys_offset & ~TARGET_PAGE_MASK;
>      KVMSlot *mem, old;
>      int err;
> +    MemoryRegion *mr = section->mr;
> +    bool log_dirty = memory_region_is_logging(mr);
> +    target_phys_addr_t start_addr = section->offset_within_address_space;
> +    ram_addr_t size = section->size;
>      void *ram = NULL;
>  
>      /* kvm works in page size chunks, but the function may be called
> @@ -533,20 +548,19 @@ static void kvm_set_phys_mem(target_phys_addr_t 
> start_addr, ram_addr_t size,
>      size = TARGET_PAGE_ALIGN(size);
>      start_addr = TARGET_PAGE_ALIGN(start_addr);
>  
> -    /* KVM does not support read-only slots */
> -    phys_offset &= ~IO_MEM_ROM;
> -
> -    if ((phys_offset & ~TARGET_PAGE_MASK) == IO_MEM_RAM) {
> -        ram = qemu_safe_ram_ptr(phys_offset);
> +    if (!memory_region_is_ram(mr)) {
> +        return;
>      }
>  
> +    ram = memory_region_get_ram_ptr(mr) + section->offset_within_region;
> +
>      while (1) {
>          mem = kvm_lookup_overlapping_slot(s, start_addr, start_addr + size);
>          if (!mem) {
>              break;
>          }
>  
> -        if (flags < IO_MEM_UNASSIGNED && start_addr >= mem->start_addr &&
> +        if (add && start_addr >= mem->start_addr &&
>              (start_addr + size <= mem->start_addr + mem->memory_size) &&
>              (ram - start_addr == mem->ram - mem->start_addr)) {
>              /* The new slot fits into the existing one and comes with
> @@ -575,8 +589,7 @@ static void kvm_set_phys_mem(target_phys_addr_t 
> start_addr, ram_addr_t size,
>           * slot comes around later, we will fail (not seen in practice so 
> far)
>           * - and actually require a recent KVM version. */
>          if (s->broken_set_mem_region &&
> -            old.start_addr == start_addr && old.memory_size < size &&
> -            flags < IO_MEM_UNASSIGNED) {
> +            old.start_addr == start_addr && old.memory_size < size && add) {
>              mem = kvm_alloc_slot(s);
>              mem->memory_size = old.memory_size;
>              mem->start_addr = old.start_addr;
> @@ -591,7 +604,6 @@ static void kvm_set_phys_mem(target_phys_addr_t 
> start_addr, ram_addr_t size,
>              }
>  
>              start_addr += old.memory_size;
> -            phys_offset += old.memory_size;
>              ram += old.memory_size;
>              size -= old.memory_size;
>              continue;
> @@ -642,8 +654,7 @@ static void kvm_set_phys_mem(target_phys_addr_t 
> start_addr, ram_addr_t size,
>      if (!size) {
>          return;
>      }
> -    /* KVM does not need to know about this memory */
> -    if (flags >= IO_MEM_UNASSIGNED) {
> +    if (!add) {
>          return;
>      }
>      mem = kvm_alloc_slot(s);
> @@ -660,33 +671,55 @@ static void kvm_set_phys_mem(target_phys_addr_t 
> start_addr, ram_addr_t size,
>      }
>  }
>  
> -static void kvm_client_set_memory(struct CPUPhysMemoryClient *client,
> -                                  target_phys_addr_t start_addr,
> -                                  ram_addr_t size, ram_addr_t phys_offset,
> -                                  bool log_dirty)
> +static void kvm_region_add(MemoryListener *listener,
> +                           MemoryRegionSection *section)
> +{
> +    kvm_set_phys_mem(section, true);
> +}
> +
> +static void kvm_region_del(MemoryListener *listener,
> +                           MemoryRegionSection *section)
>  {
> -    kvm_set_phys_mem(start_addr, size, phys_offset, log_dirty);
> +    kvm_set_phys_mem(section, false);
> +}
> +
> +static void kvm_log_sync(MemoryListener *listener,
> +                         MemoryRegionSection *section)
> +{
> +    target_phys_addr_t start = section->offset_within_address_space;
> +    target_phys_addr_t end = start + section->size;
> +    int r;
> +
> +    r = kvm_physical_sync_dirty_bitmap(start, end);
> +    if (r < 0) {
> +        abort();
> +    }
>  }
>  
> -static int kvm_client_sync_dirty_bitmap(struct CPUPhysMemoryClient *client,
> -                                        target_phys_addr_t start_addr,
> -                                        target_phys_addr_t end_addr)
> +static void kvm_log_global_start(struct MemoryListener *listener)
>  {
> -    return kvm_physical_sync_dirty_bitmap(start_addr, end_addr);
> +    int r;
> +
> +    r = kvm_set_migration_log(1);
> +    assert(r >= 0);
>  }
>  
> -static int kvm_client_migration_log(struct CPUPhysMemoryClient *client,
> -                                    int enable)
> +static void kvm_log_global_stop(struct MemoryListener *listener)
>  {
> -    return kvm_set_migration_log(enable);
> +    int r;
> +
> +    r = kvm_set_migration_log(0);
> +    assert(r >= 0);
>  }
>  
> -static CPUPhysMemoryClient kvm_cpu_phys_memory_client = {
> -    .set_memory = kvm_client_set_memory,
> -    .sync_dirty_bitmap = kvm_client_sync_dirty_bitmap,
> -    .migration_log = kvm_client_migration_log,
> +static MemoryListener kvm_memory_listener = {
> +    .region_add = kvm_region_add,
> +    .region_del = kvm_region_del,
>      .log_start = kvm_log_start,
>      .log_stop = kvm_log_stop,
> +    .log_sync = kvm_log_sync,
> +    .log_global_start = kvm_log_global_start,
> +    .log_global_stop = kvm_log_global_stop,
>  };
>  
>  static void kvm_handle_interrupt(CPUState *env, int mask)
> @@ -794,7 +827,7 @@ int kvm_init(void)
>      }
>  
>      kvm_state = s;
> -    cpu_register_phys_memory_client(&kvm_cpu_phys_memory_client);
> +    memory_listener_register(&kvm_memory_listener);
>  
>      s->many_ioeventfds = kvm_check_many_ioeventfds();
>  


Attachment: signature.asc
Description: OpenPGP digital signature

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.