Re: [Qemu-devel] [PATCH v6 03/12] dataplane: add host memory mapping code

2012-12-17 Thread Stefan Hajnoczi
On Sun, Dec 16, 2012 at 06:11:14PM +0200, Michael S. Tsirkin wrote:
 On Fri, Dec 14, 2012 at 12:45:16PM +0100, Stefan Hajnoczi wrote:
  On Wed, Dec 12, 2012 at 4:49 PM, Michael S. Tsirkin m...@redhat.com wrote:
   On Wed, Dec 12, 2012 at 04:34:21PM +0100, Stefan Hajnoczi wrote:
   On Tue, Dec 11, 2012 at 08:09:56PM +0200, Michael S. Tsirkin wrote:
On Tue, Dec 11, 2012 at 10:32:28AM -0600, Anthony Liguori wrote:
 Michael S. Tsirkin m...@redhat.com writes:

  On Tue, Dec 11, 2012 at 04:27:49PM +0100, Stefan Hajnoczi wrote:
  On Tue, Dec 11, 2012 at 3:13 PM, Michael S. Tsirkin 
  m...@redhat.com wrote:
   On Mon, Dec 10, 2012 at 02:09:36PM +0100, Stefan Hajnoczi wrote:
   The data plane thread needs to map guest physical addresses to 
   host
   pointers.  Normally this is done with 
   cpu_physical_memory_map() but the
   function assumes the global mutex is held.  The data plane 
   thread does
   not touch the global mutex and therefore needs a thread-safe 
   memory
   mapping mechanism.
  
   Hostmem registers a MemoryListener similar to how vhost 
   collects and
   pushes memory region information into the kernel.  There is a
   fine-grained lock on the regions list which is held during 
   lookup and
   when installing a new regions list.
  
   Can we export and reuse the vhost code for this?
   I think you will find this advantageous when you add migration
   support down the line.
   And if you find it necessary to use MemoryListener e.g. for 
   performance
   reasons, then vhost will likely benefit too.
 
  It's technically possible and not hard to do but it prevents
  integrating deeper with core QEMU as the memory API becomes
  thread-safe.
 
  There are two ways to implement dirty logging:
  1. The vhost log approach which syncs dirty information 
  periodically.
  2. A cheap thread-safe way to mark dirty outside the global mutex,
  i.e. a thread-safe memory_region_set_dirty().
 
  You don't normally want to dirty the whole region,
  you want to do this to individual pages.
 
  If we can get thread-safe guest memory load/store in QEMU then #2 
  is
  included.  We can switch to using hw/virtio.c instead of
  hw/dataplane/vring.c, we get dirty logging for free, we can drop
  hostmem.c completely, etc.
 
  Stefan
 
  So why not reuse existing code? If you drop it later it won't
  matter what you used ...

 Let's not lose sight of the forest for the trees here...

 This whole series is not reusing existing code.  That's really the 
 whole
 point.

 The point is to take the code (duplication and all) and then do all 
 of
 the refactoring to use common code in the tree itself.

 If we want to put this in a hw/staging/ directory, that's fine by me
 too.

 Regards,

 Anthony Liguori
   
Yes I agree. I think lack of handling for cross regin descriptors
bothers me a bit more.
  
   The two things you've mentioned both aren't handled by hw/virtio.c:
  
   1. Issue: Indirect descriptors have no alignment restrictions and can
  cross regions.
  
  hw/virtio.c uses vring_desc_flags() and other accessor functions,
  which do lduw_phys() - there is no memory region boundary checking
  here.
  
   Since addresses are aligned this one is fine I think.
  
   2. Issue: Virtio buffers can cross memory region boundaries.
  
  hw/virtio.c maps buffers 1:1 using virtqueue_map_sg() and exits if
  mapping fails.  It does not split buffers if they cross a memory
  region.
  
   These are definitely ugly corner cases but hw/virtio.c is proof that
   we're not hitting them in practice.
  
   Stefan
  
   Yes, this one seems ugly. Maybe add a TODO?
  
   OK let's assume we want to put it in staging/
   I worry about the virtio-blk changes being isolated.
   Can you put ifdef CONFIG_VIRTIO_BLK_DATA_PLANE around
   them all to avoid dependency on that header completely
   if configured out?
  
  Okay, I'll move the #ifdefs.  I like the stubs in the header file
  because it reduces the amount of #ifdefs, but this is easy to change.
  
  Stefan
 
 Okay.
 Another option (if you prefer stubs) is to add a stub for access to
 s-dataplane field, and surround just the field with ifdefs.
 As it is, this code:
   if (s-dataplane) {
   return;
   }
 can't be compiled out since compiler is not smart enough to
 figure out dataplane is never set.

It's okay, I have already implemented your previous suggestion in the v7
patches that I sent out on Friday and I'm okay with it.

Stefan



Re: [Qemu-devel] [PATCH v6 03/12] dataplane: add host memory mapping code

2012-12-16 Thread Michael S. Tsirkin
On Fri, Dec 14, 2012 at 12:45:16PM +0100, Stefan Hajnoczi wrote:
 On Wed, Dec 12, 2012 at 4:49 PM, Michael S. Tsirkin m...@redhat.com wrote:
  On Wed, Dec 12, 2012 at 04:34:21PM +0100, Stefan Hajnoczi wrote:
  On Tue, Dec 11, 2012 at 08:09:56PM +0200, Michael S. Tsirkin wrote:
   On Tue, Dec 11, 2012 at 10:32:28AM -0600, Anthony Liguori wrote:
Michael S. Tsirkin m...@redhat.com writes:
   
 On Tue, Dec 11, 2012 at 04:27:49PM +0100, Stefan Hajnoczi wrote:
 On Tue, Dec 11, 2012 at 3:13 PM, Michael S. Tsirkin 
 m...@redhat.com wrote:
  On Mon, Dec 10, 2012 at 02:09:36PM +0100, Stefan Hajnoczi wrote:
  The data plane thread needs to map guest physical addresses to 
  host
  pointers.  Normally this is done with cpu_physical_memory_map() 
  but the
  function assumes the global mutex is held.  The data plane 
  thread does
  not touch the global mutex and therefore needs a thread-safe 
  memory
  mapping mechanism.
 
  Hostmem registers a MemoryListener similar to how vhost collects 
  and
  pushes memory region information into the kernel.  There is a
  fine-grained lock on the regions list which is held during 
  lookup and
  when installing a new regions list.
 
  Can we export and reuse the vhost code for this?
  I think you will find this advantageous when you add migration
  support down the line.
  And if you find it necessary to use MemoryListener e.g. for 
  performance
  reasons, then vhost will likely benefit too.

 It's technically possible and not hard to do but it prevents
 integrating deeper with core QEMU as the memory API becomes
 thread-safe.

 There are two ways to implement dirty logging:
 1. The vhost log approach which syncs dirty information 
 periodically.
 2. A cheap thread-safe way to mark dirty outside the global mutex,
 i.e. a thread-safe memory_region_set_dirty().

 You don't normally want to dirty the whole region,
 you want to do this to individual pages.

 If we can get thread-safe guest memory load/store in QEMU then #2 is
 included.  We can switch to using hw/virtio.c instead of
 hw/dataplane/vring.c, we get dirty logging for free, we can drop
 hostmem.c completely, etc.

 Stefan

 So why not reuse existing code? If you drop it later it won't
 matter what you used ...
   
Let's not lose sight of the forest for the trees here...
   
This whole series is not reusing existing code.  That's really the 
whole
point.
   
The point is to take the code (duplication and all) and then do all of
the refactoring to use common code in the tree itself.
   
If we want to put this in a hw/staging/ directory, that's fine by me
too.
   
Regards,
   
Anthony Liguori
  
   Yes I agree. I think lack of handling for cross regin descriptors
   bothers me a bit more.
 
  The two things you've mentioned both aren't handled by hw/virtio.c:
 
  1. Issue: Indirect descriptors have no alignment restrictions and can
 cross regions.
 
 hw/virtio.c uses vring_desc_flags() and other accessor functions,
 which do lduw_phys() - there is no memory region boundary checking
 here.
 
  Since addresses are aligned this one is fine I think.
 
  2. Issue: Virtio buffers can cross memory region boundaries.
 
 hw/virtio.c maps buffers 1:1 using virtqueue_map_sg() and exits if
 mapping fails.  It does not split buffers if they cross a memory
 region.
 
  These are definitely ugly corner cases but hw/virtio.c is proof that
  we're not hitting them in practice.
 
  Stefan
 
  Yes, this one seems ugly. Maybe add a TODO?
 
  OK let's assume we want to put it in staging/
  I worry about the virtio-blk changes being isolated.
  Can you put ifdef CONFIG_VIRTIO_BLK_DATA_PLANE around
  them all to avoid dependency on that header completely
  if configured out?
 
 Okay, I'll move the #ifdefs.  I like the stubs in the header file
 because it reduces the amount of #ifdefs, but this is easy to change.
 
 Stefan

Okay.
Another option (if you prefer stubs) is to add a stub for access to
s-dataplane field, and surround just the field with ifdefs.
As it is, this code:
if (s-dataplane) {
return;
}
can't be compiled out since compiler is not smart enough to
figure out dataplane is never set.
-- 
MST



Re: [Qemu-devel] [PATCH v6 03/12] dataplane: add host memory mapping code

2012-12-14 Thread Stefan Hajnoczi
On Wed, Dec 12, 2012 at 4:49 PM, Michael S. Tsirkin m...@redhat.com wrote:
 On Wed, Dec 12, 2012 at 04:34:21PM +0100, Stefan Hajnoczi wrote:
 On Tue, Dec 11, 2012 at 08:09:56PM +0200, Michael S. Tsirkin wrote:
  On Tue, Dec 11, 2012 at 10:32:28AM -0600, Anthony Liguori wrote:
   Michael S. Tsirkin m...@redhat.com writes:
  
On Tue, Dec 11, 2012 at 04:27:49PM +0100, Stefan Hajnoczi wrote:
On Tue, Dec 11, 2012 at 3:13 PM, Michael S. Tsirkin m...@redhat.com 
wrote:
 On Mon, Dec 10, 2012 at 02:09:36PM +0100, Stefan Hajnoczi wrote:
 The data plane thread needs to map guest physical addresses to host
 pointers.  Normally this is done with cpu_physical_memory_map() 
 but the
 function assumes the global mutex is held.  The data plane thread 
 does
 not touch the global mutex and therefore needs a thread-safe memory
 mapping mechanism.

 Hostmem registers a MemoryListener similar to how vhost collects 
 and
 pushes memory region information into the kernel.  There is a
 fine-grained lock on the regions list which is held during lookup 
 and
 when installing a new regions list.

 Can we export and reuse the vhost code for this?
 I think you will find this advantageous when you add migration
 support down the line.
 And if you find it necessary to use MemoryListener e.g. for 
 performance
 reasons, then vhost will likely benefit too.
   
It's technically possible and not hard to do but it prevents
integrating deeper with core QEMU as the memory API becomes
thread-safe.
   
There are two ways to implement dirty logging:
1. The vhost log approach which syncs dirty information periodically.
2. A cheap thread-safe way to mark dirty outside the global mutex,
i.e. a thread-safe memory_region_set_dirty().
   
You don't normally want to dirty the whole region,
you want to do this to individual pages.
   
If we can get thread-safe guest memory load/store in QEMU then #2 is
included.  We can switch to using hw/virtio.c instead of
hw/dataplane/vring.c, we get dirty logging for free, we can drop
hostmem.c completely, etc.
   
Stefan
   
So why not reuse existing code? If you drop it later it won't
matter what you used ...
  
   Let's not lose sight of the forest for the trees here...
  
   This whole series is not reusing existing code.  That's really the whole
   point.
  
   The point is to take the code (duplication and all) and then do all of
   the refactoring to use common code in the tree itself.
  
   If we want to put this in a hw/staging/ directory, that's fine by me
   too.
  
   Regards,
  
   Anthony Liguori
 
  Yes I agree. I think lack of handling for cross regin descriptors
  bothers me a bit more.

 The two things you've mentioned both aren't handled by hw/virtio.c:

 1. Issue: Indirect descriptors have no alignment restrictions and can
cross regions.

hw/virtio.c uses vring_desc_flags() and other accessor functions,
which do lduw_phys() - there is no memory region boundary checking
here.

 Since addresses are aligned this one is fine I think.

 2. Issue: Virtio buffers can cross memory region boundaries.

hw/virtio.c maps buffers 1:1 using virtqueue_map_sg() and exits if
mapping fails.  It does not split buffers if they cross a memory
region.

 These are definitely ugly corner cases but hw/virtio.c is proof that
 we're not hitting them in practice.

 Stefan

 Yes, this one seems ugly. Maybe add a TODO?

 OK let's assume we want to put it in staging/
 I worry about the virtio-blk changes being isolated.
 Can you put ifdef CONFIG_VIRTIO_BLK_DATA_PLANE around
 them all to avoid dependency on that header completely
 if configured out?

Okay, I'll move the #ifdefs.  I like the stubs in the header file
because it reduces the amount of #ifdefs, but this is easy to change.

Stefan



Re: [Qemu-devel] [PATCH v6 03/12] dataplane: add host memory mapping code

2012-12-12 Thread Stefan Hajnoczi
On Tue, Dec 11, 2012 at 08:09:56PM +0200, Michael S. Tsirkin wrote:
 On Tue, Dec 11, 2012 at 10:32:28AM -0600, Anthony Liguori wrote:
  Michael S. Tsirkin m...@redhat.com writes:
  
   On Tue, Dec 11, 2012 at 04:27:49PM +0100, Stefan Hajnoczi wrote:
   On Tue, Dec 11, 2012 at 3:13 PM, Michael S. Tsirkin m...@redhat.com 
   wrote:
On Mon, Dec 10, 2012 at 02:09:36PM +0100, Stefan Hajnoczi wrote:
The data plane thread needs to map guest physical addresses to host
pointers.  Normally this is done with cpu_physical_memory_map() but 
the
function assumes the global mutex is held.  The data plane thread does
not touch the global mutex and therefore needs a thread-safe memory
mapping mechanism.
   
Hostmem registers a MemoryListener similar to how vhost collects and
pushes memory region information into the kernel.  There is a
fine-grained lock on the regions list which is held during lookup and
when installing a new regions list.
   
Can we export and reuse the vhost code for this?
I think you will find this advantageous when you add migration
support down the line.
And if you find it necessary to use MemoryListener e.g. for performance
reasons, then vhost will likely benefit too.
   
   It's technically possible and not hard to do but it prevents
   integrating deeper with core QEMU as the memory API becomes
   thread-safe.
   
   There are two ways to implement dirty logging:
   1. The vhost log approach which syncs dirty information periodically.
   2. A cheap thread-safe way to mark dirty outside the global mutex,
   i.e. a thread-safe memory_region_set_dirty().
  
   You don't normally want to dirty the whole region,
   you want to do this to individual pages.
  
   If we can get thread-safe guest memory load/store in QEMU then #2 is
   included.  We can switch to using hw/virtio.c instead of
   hw/dataplane/vring.c, we get dirty logging for free, we can drop
   hostmem.c completely, etc.
   
   Stefan
  
   So why not reuse existing code? If you drop it later it won't
   matter what you used ...
  
  Let's not lose sight of the forest for the trees here...
  
  This whole series is not reusing existing code.  That's really the whole
  point.
  
  The point is to take the code (duplication and all) and then do all of
  the refactoring to use common code in the tree itself.
  
  If we want to put this in a hw/staging/ directory, that's fine by me
  too.
  
  Regards,
  
  Anthony Liguori
 
 Yes I agree. I think lack of handling for cross regin descriptors
 bothers me a bit more.

The two things you've mentioned both aren't handled by hw/virtio.c:

1. Issue: Indirect descriptors have no alignment restrictions and can
   cross regions.

   hw/virtio.c uses vring_desc_flags() and other accessor functions,
   which do lduw_phys() - there is no memory region boundary checking
   here.

2. Issue: Virtio buffers can cross memory region boundaries.

   hw/virtio.c maps buffers 1:1 using virtqueue_map_sg() and exits if
   mapping fails.  It does not split buffers if they cross a memory
   region.

These are definitely ugly corner cases but hw/virtio.c is proof that
we're not hitting them in practice.

Stefan



Re: [Qemu-devel] [PATCH v6 03/12] dataplane: add host memory mapping code

2012-12-12 Thread Michael S. Tsirkin
On Wed, Dec 12, 2012 at 04:34:21PM +0100, Stefan Hajnoczi wrote:
 On Tue, Dec 11, 2012 at 08:09:56PM +0200, Michael S. Tsirkin wrote:
  On Tue, Dec 11, 2012 at 10:32:28AM -0600, Anthony Liguori wrote:
   Michael S. Tsirkin m...@redhat.com writes:
   
On Tue, Dec 11, 2012 at 04:27:49PM +0100, Stefan Hajnoczi wrote:
On Tue, Dec 11, 2012 at 3:13 PM, Michael S. Tsirkin m...@redhat.com 
wrote:
 On Mon, Dec 10, 2012 at 02:09:36PM +0100, Stefan Hajnoczi wrote:
 The data plane thread needs to map guest physical addresses to host
 pointers.  Normally this is done with cpu_physical_memory_map() but 
 the
 function assumes the global mutex is held.  The data plane thread 
 does
 not touch the global mutex and therefore needs a thread-safe memory
 mapping mechanism.

 Hostmem registers a MemoryListener similar to how vhost collects and
 pushes memory region information into the kernel.  There is a
 fine-grained lock on the regions list which is held during lookup 
 and
 when installing a new regions list.

 Can we export and reuse the vhost code for this?
 I think you will find this advantageous when you add migration
 support down the line.
 And if you find it necessary to use MemoryListener e.g. for 
 performance
 reasons, then vhost will likely benefit too.

It's technically possible and not hard to do but it prevents
integrating deeper with core QEMU as the memory API becomes
thread-safe.

There are two ways to implement dirty logging:
1. The vhost log approach which syncs dirty information periodically.
2. A cheap thread-safe way to mark dirty outside the global mutex,
i.e. a thread-safe memory_region_set_dirty().
   
You don't normally want to dirty the whole region,
you want to do this to individual pages.
   
If we can get thread-safe guest memory load/store in QEMU then #2 is
included.  We can switch to using hw/virtio.c instead of
hw/dataplane/vring.c, we get dirty logging for free, we can drop
hostmem.c completely, etc.

Stefan
   
So why not reuse existing code? If you drop it later it won't
matter what you used ...
   
   Let's not lose sight of the forest for the trees here...
   
   This whole series is not reusing existing code.  That's really the whole
   point.
   
   The point is to take the code (duplication and all) and then do all of
   the refactoring to use common code in the tree itself.
   
   If we want to put this in a hw/staging/ directory, that's fine by me
   too.
   
   Regards,
   
   Anthony Liguori
  
  Yes I agree. I think lack of handling for cross regin descriptors
  bothers me a bit more.
 
 The two things you've mentioned both aren't handled by hw/virtio.c:
 
 1. Issue: Indirect descriptors have no alignment restrictions and can
cross regions.
 
hw/virtio.c uses vring_desc_flags() and other accessor functions,
which do lduw_phys() - there is no memory region boundary checking
here.

Since addresses are aligned this one is fine I think.

 2. Issue: Virtio buffers can cross memory region boundaries.
 
hw/virtio.c maps buffers 1:1 using virtqueue_map_sg() and exits if
mapping fails.  It does not split buffers if they cross a memory
region.
 
 These are definitely ugly corner cases but hw/virtio.c is proof that
 we're not hitting them in practice.
 
 Stefan

Yes, this one seems ugly. Maybe add a TODO?

OK let's assume we want to put it in staging/
I worry about the virtio-blk changes being isolated.
Can you put ifdef CONFIG_VIRTIO_BLK_DATA_PLANE around
them all to avoid dependency on that header completely
if configured out?


-- 
MST



Re: [Qemu-devel] [PATCH v6 03/12] dataplane: add host memory mapping code

2012-12-11 Thread Michael S. Tsirkin
On Mon, Dec 10, 2012 at 02:09:36PM +0100, Stefan Hajnoczi wrote:
 The data plane thread needs to map guest physical addresses to host
 pointers.  Normally this is done with cpu_physical_memory_map() but the
 function assumes the global mutex is held.  The data plane thread does
 not touch the global mutex and therefore needs a thread-safe memory
 mapping mechanism.
 
 Hostmem registers a MemoryListener similar to how vhost collects and
 pushes memory region information into the kernel.  There is a
 fine-grained lock on the regions list which is held during lookup and
 when installing a new regions list.

Can we export and reuse the vhost code for this?
I think you will find this advantageous when you add migration
support down the line.
And if you find it necessary to use MemoryListener e.g. for performance
reasons, then vhost will likely benefit too.


 When the physical memory map changes the MemoryListener callbacks are
 invoked.  They build up a new list of memory regions which is finally
 installed when the list has been completed.
 
 Signed-off-by: Stefan Hajnoczi stefa...@redhat.com
 ---
  hw/Makefile.objs   |   2 +-
  hw/dataplane/Makefile.objs |   3 +
  hw/dataplane/hostmem.c | 176 
 +
  hw/dataplane/hostmem.h |  57 +++
  4 files changed, 237 insertions(+), 1 deletion(-)
  create mode 100644 hw/dataplane/Makefile.objs
  create mode 100644 hw/dataplane/hostmem.c
  create mode 100644 hw/dataplane/hostmem.h
 
 diff --git a/hw/Makefile.objs b/hw/Makefile.objs
 index d581d8d..cec84bc 100644
 --- a/hw/Makefile.objs
 +++ b/hw/Makefile.objs
 @@ -1,4 +1,4 @@
 -common-obj-y = usb/ ide/
 +common-obj-y = usb/ ide/ dataplane/
  common-obj-y += loader.o
  common-obj-$(CONFIG_VIRTIO) += virtio-console.o
  common-obj-$(CONFIG_VIRTIO) += virtio-rng.o
 diff --git a/hw/dataplane/Makefile.objs b/hw/dataplane/Makefile.objs
 new file mode 100644
 index 000..8c8dea1
 --- /dev/null
 +++ b/hw/dataplane/Makefile.objs
 @@ -0,0 +1,3 @@
 +ifeq ($(CONFIG_VIRTIO), y)
 +common-obj-$(CONFIG_VIRTIO_BLK_DATA_PLANE) += hostmem.o
 +endif
 diff --git a/hw/dataplane/hostmem.c b/hw/dataplane/hostmem.c
 new file mode 100644
 index 000..d5e1070
 --- /dev/null
 +++ b/hw/dataplane/hostmem.c
 @@ -0,0 +1,176 @@
 +/*
 + * Thread-safe guest to host memory mapping
 + *
 + * Copyright 2012 Red Hat, Inc. and/or its affiliates
 + *
 + * Authors:
 + *   Stefan Hajnoczi stefa...@redhat.com
 + *
 + * This work is licensed under the terms of the GNU GPL, version 2 or later.
 + * See the COPYING file in the top-level directory.
 + *
 + */
 +
 +#include exec-memory.h
 +#include hostmem.h
 +
 +static int hostmem_lookup_cmp(const void *phys_, const void *region_)
 +{
 +hwaddr phys = *(const hwaddr *)phys_;
 +const HostmemRegion *region = region_;
 +
 +if (phys  region-guest_addr) {
 +return -1;
 +} else if (phys = region-guest_addr + region-size) {
 +return 1;
 +} else {
 +return 0;
 +}
 +}
 +
 +/**
 + * Map guest physical address to host pointer
 + */
 +void *hostmem_lookup(Hostmem *hostmem, hwaddr phys, hwaddr len, bool 
 is_write)
 +{
 +HostmemRegion *region;
 +void *host_addr = NULL;
 +hwaddr offset_within_region;
 +
 +qemu_mutex_lock(hostmem-current_regions_lock);
 +region = bsearch(phys, hostmem-current_regions,
 + hostmem-num_current_regions,
 + sizeof(hostmem-current_regions[0]),
 + hostmem_lookup_cmp);
 +if (!region) {
 +goto out;
 +}
 +if (is_write  region-readonly) {
 +goto out;
 +}
 +offset_within_region = phys - region-guest_addr;
 +if (offset_within_region + len = region-size) {
 +host_addr = region-host_addr + offset_within_region;
 +}
 +out:
 +qemu_mutex_unlock(hostmem-current_regions_lock);
 +
 +return host_addr;
 +}
 +
 +/**
 + * Install new regions list
 + */
 +static void hostmem_listener_commit(MemoryListener *listener)
 +{
 +Hostmem *hostmem = container_of(listener, Hostmem, listener);
 +
 +qemu_mutex_lock(hostmem-current_regions_lock);
 +g_free(hostmem-current_regions);
 +hostmem-current_regions = hostmem-new_regions;
 +hostmem-num_current_regions = hostmem-num_new_regions;
 +qemu_mutex_unlock(hostmem-current_regions_lock);
 +
 +/* Reset new regions list */
 +hostmem-new_regions = NULL;
 +hostmem-num_new_regions = 0;
 +}
 +
 +/**
 + * Add a MemoryRegionSection to the new regions list
 + */
 +static void hostmem_append_new_region(Hostmem *hostmem,
 +  MemoryRegionSection *section)
 +{
 +void *ram_ptr = memory_region_get_ram_ptr(section-mr);
 +size_t num = hostmem-num_new_regions;
 +size_t new_size = (num + 1) * sizeof(hostmem-new_regions[0]);
 +
 +hostmem-new_regions = g_realloc(hostmem-new_regions, new_size);
 +hostmem-new_regions[num] = (HostmemRegion){
 +.host_addr = 

Re: [Qemu-devel] [PATCH v6 03/12] dataplane: add host memory mapping code

2012-12-11 Thread Stefan Hajnoczi
On Tue, Dec 11, 2012 at 3:13 PM, Michael S. Tsirkin m...@redhat.com wrote:
 On Mon, Dec 10, 2012 at 02:09:36PM +0100, Stefan Hajnoczi wrote:
 The data plane thread needs to map guest physical addresses to host
 pointers.  Normally this is done with cpu_physical_memory_map() but the
 function assumes the global mutex is held.  The data plane thread does
 not touch the global mutex and therefore needs a thread-safe memory
 mapping mechanism.

 Hostmem registers a MemoryListener similar to how vhost collects and
 pushes memory region information into the kernel.  There is a
 fine-grained lock on the regions list which is held during lookup and
 when installing a new regions list.

 Can we export and reuse the vhost code for this?
 I think you will find this advantageous when you add migration
 support down the line.
 And if you find it necessary to use MemoryListener e.g. for performance
 reasons, then vhost will likely benefit too.

It's technically possible and not hard to do but it prevents
integrating deeper with core QEMU as the memory API becomes
thread-safe.

There are two ways to implement dirty logging:
1. The vhost log approach which syncs dirty information periodically.
2. A cheap thread-safe way to mark dirty outside the global mutex,
i.e. a thread-safe memory_region_set_dirty().

If we can get thread-safe guest memory load/store in QEMU then #2 is
included.  We can switch to using hw/virtio.c instead of
hw/dataplane/vring.c, we get dirty logging for free, we can drop
hostmem.c completely, etc.

Stefan



Re: [Qemu-devel] [PATCH v6 03/12] dataplane: add host memory mapping code

2012-12-11 Thread Michael S. Tsirkin
On Tue, Dec 11, 2012 at 04:27:49PM +0100, Stefan Hajnoczi wrote:
 On Tue, Dec 11, 2012 at 3:13 PM, Michael S. Tsirkin m...@redhat.com wrote:
  On Mon, Dec 10, 2012 at 02:09:36PM +0100, Stefan Hajnoczi wrote:
  The data plane thread needs to map guest physical addresses to host
  pointers.  Normally this is done with cpu_physical_memory_map() but the
  function assumes the global mutex is held.  The data plane thread does
  not touch the global mutex and therefore needs a thread-safe memory
  mapping mechanism.
 
  Hostmem registers a MemoryListener similar to how vhost collects and
  pushes memory region information into the kernel.  There is a
  fine-grained lock on the regions list which is held during lookup and
  when installing a new regions list.
 
  Can we export and reuse the vhost code for this?
  I think you will find this advantageous when you add migration
  support down the line.
  And if you find it necessary to use MemoryListener e.g. for performance
  reasons, then vhost will likely benefit too.
 
 It's technically possible and not hard to do but it prevents
 integrating deeper with core QEMU as the memory API becomes
 thread-safe.
 
 There are two ways to implement dirty logging:
 1. The vhost log approach which syncs dirty information periodically.
 2. A cheap thread-safe way to mark dirty outside the global mutex,
 i.e. a thread-safe memory_region_set_dirty().

You don't normally want to dirty the whole region,
you want to do this to individual pages.

 If we can get thread-safe guest memory load/store in QEMU then #2 is
 included.  We can switch to using hw/virtio.c instead of
 hw/dataplane/vring.c, we get dirty logging for free, we can drop
 hostmem.c completely, etc.
 
 Stefan

So why not reuse existing code? If you drop it later it won't
matter what you used ...

-- 
MST



Re: [Qemu-devel] [PATCH v6 03/12] dataplane: add host memory mapping code

2012-12-11 Thread Anthony Liguori
Michael S. Tsirkin m...@redhat.com writes:

 On Tue, Dec 11, 2012 at 04:27:49PM +0100, Stefan Hajnoczi wrote:
 On Tue, Dec 11, 2012 at 3:13 PM, Michael S. Tsirkin m...@redhat.com wrote:
  On Mon, Dec 10, 2012 at 02:09:36PM +0100, Stefan Hajnoczi wrote:
  The data plane thread needs to map guest physical addresses to host
  pointers.  Normally this is done with cpu_physical_memory_map() but the
  function assumes the global mutex is held.  The data plane thread does
  not touch the global mutex and therefore needs a thread-safe memory
  mapping mechanism.
 
  Hostmem registers a MemoryListener similar to how vhost collects and
  pushes memory region information into the kernel.  There is a
  fine-grained lock on the regions list which is held during lookup and
  when installing a new regions list.
 
  Can we export and reuse the vhost code for this?
  I think you will find this advantageous when you add migration
  support down the line.
  And if you find it necessary to use MemoryListener e.g. for performance
  reasons, then vhost will likely benefit too.
 
 It's technically possible and not hard to do but it prevents
 integrating deeper with core QEMU as the memory API becomes
 thread-safe.
 
 There are two ways to implement dirty logging:
 1. The vhost log approach which syncs dirty information periodically.
 2. A cheap thread-safe way to mark dirty outside the global mutex,
 i.e. a thread-safe memory_region_set_dirty().

 You don't normally want to dirty the whole region,
 you want to do this to individual pages.

 If we can get thread-safe guest memory load/store in QEMU then #2 is
 included.  We can switch to using hw/virtio.c instead of
 hw/dataplane/vring.c, we get dirty logging for free, we can drop
 hostmem.c completely, etc.
 
 Stefan

 So why not reuse existing code? If you drop it later it won't
 matter what you used ...

Let's not lose sight of the forest for the trees here...

This whole series is not reusing existing code.  That's really the whole
point.

The point is to take the code (duplication and all) and then do all of
the refactoring to use common code in the tree itself.

If we want to put this in a hw/staging/ directory, that's fine by me
too.

Regards,

Anthony Liguori


 -- 
 MST




Re: [Qemu-devel] [PATCH v6 03/12] dataplane: add host memory mapping code

2012-12-11 Thread Michael S. Tsirkin
On Tue, Dec 11, 2012 at 10:32:28AM -0600, Anthony Liguori wrote:
 Michael S. Tsirkin m...@redhat.com writes:
 
  On Tue, Dec 11, 2012 at 04:27:49PM +0100, Stefan Hajnoczi wrote:
  On Tue, Dec 11, 2012 at 3:13 PM, Michael S. Tsirkin m...@redhat.com 
  wrote:
   On Mon, Dec 10, 2012 at 02:09:36PM +0100, Stefan Hajnoczi wrote:
   The data plane thread needs to map guest physical addresses to host
   pointers.  Normally this is done with cpu_physical_memory_map() but the
   function assumes the global mutex is held.  The data plane thread does
   not touch the global mutex and therefore needs a thread-safe memory
   mapping mechanism.
  
   Hostmem registers a MemoryListener similar to how vhost collects and
   pushes memory region information into the kernel.  There is a
   fine-grained lock on the regions list which is held during lookup and
   when installing a new regions list.
  
   Can we export and reuse the vhost code for this?
   I think you will find this advantageous when you add migration
   support down the line.
   And if you find it necessary to use MemoryListener e.g. for performance
   reasons, then vhost will likely benefit too.
  
  It's technically possible and not hard to do but it prevents
  integrating deeper with core QEMU as the memory API becomes
  thread-safe.
  
  There are two ways to implement dirty logging:
  1. The vhost log approach which syncs dirty information periodically.
  2. A cheap thread-safe way to mark dirty outside the global mutex,
  i.e. a thread-safe memory_region_set_dirty().
 
  You don't normally want to dirty the whole region,
  you want to do this to individual pages.
 
  If we can get thread-safe guest memory load/store in QEMU then #2 is
  included.  We can switch to using hw/virtio.c instead of
  hw/dataplane/vring.c, we get dirty logging for free, we can drop
  hostmem.c completely, etc.
  
  Stefan
 
  So why not reuse existing code? If you drop it later it won't
  matter what you used ...
 
 Let's not lose sight of the forest for the trees here...
 
 This whole series is not reusing existing code.  That's really the whole
 point.
 
 The point is to take the code (duplication and all) and then do all of
 the refactoring to use common code in the tree itself.
 
 If we want to put this in a hw/staging/ directory, that's fine by me
 too.
 
 Regards,
 
 Anthony Liguori

Yes I agree. I think lack of handling for cross regin descriptors
bothers me a bit more.

 
  -- 
  MST



[Qemu-devel] [PATCH v6 03/12] dataplane: add host memory mapping code

2012-12-10 Thread Stefan Hajnoczi
The data plane thread needs to map guest physical addresses to host
pointers.  Normally this is done with cpu_physical_memory_map() but the
function assumes the global mutex is held.  The data plane thread does
not touch the global mutex and therefore needs a thread-safe memory
mapping mechanism.

Hostmem registers a MemoryListener similar to how vhost collects and
pushes memory region information into the kernel.  There is a
fine-grained lock on the regions list which is held during lookup and
when installing a new regions list.

When the physical memory map changes the MemoryListener callbacks are
invoked.  They build up a new list of memory regions which is finally
installed when the list has been completed.

Signed-off-by: Stefan Hajnoczi stefa...@redhat.com
---
 hw/Makefile.objs   |   2 +-
 hw/dataplane/Makefile.objs |   3 +
 hw/dataplane/hostmem.c | 176 +
 hw/dataplane/hostmem.h |  57 +++
 4 files changed, 237 insertions(+), 1 deletion(-)
 create mode 100644 hw/dataplane/Makefile.objs
 create mode 100644 hw/dataplane/hostmem.c
 create mode 100644 hw/dataplane/hostmem.h

diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index d581d8d..cec84bc 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -1,4 +1,4 @@
-common-obj-y = usb/ ide/
+common-obj-y = usb/ ide/ dataplane/
 common-obj-y += loader.o
 common-obj-$(CONFIG_VIRTIO) += virtio-console.o
 common-obj-$(CONFIG_VIRTIO) += virtio-rng.o
diff --git a/hw/dataplane/Makefile.objs b/hw/dataplane/Makefile.objs
new file mode 100644
index 000..8c8dea1
--- /dev/null
+++ b/hw/dataplane/Makefile.objs
@@ -0,0 +1,3 @@
+ifeq ($(CONFIG_VIRTIO), y)
+common-obj-$(CONFIG_VIRTIO_BLK_DATA_PLANE) += hostmem.o
+endif
diff --git a/hw/dataplane/hostmem.c b/hw/dataplane/hostmem.c
new file mode 100644
index 000..d5e1070
--- /dev/null
+++ b/hw/dataplane/hostmem.c
@@ -0,0 +1,176 @@
+/*
+ * Thread-safe guest to host memory mapping
+ *
+ * Copyright 2012 Red Hat, Inc. and/or its affiliates
+ *
+ * Authors:
+ *   Stefan Hajnoczi stefa...@redhat.com
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ */
+
+#include exec-memory.h
+#include hostmem.h
+
+static int hostmem_lookup_cmp(const void *phys_, const void *region_)
+{
+hwaddr phys = *(const hwaddr *)phys_;
+const HostmemRegion *region = region_;
+
+if (phys  region-guest_addr) {
+return -1;
+} else if (phys = region-guest_addr + region-size) {
+return 1;
+} else {
+return 0;
+}
+}
+
+/**
+ * Map guest physical address to host pointer
+ */
+void *hostmem_lookup(Hostmem *hostmem, hwaddr phys, hwaddr len, bool is_write)
+{
+HostmemRegion *region;
+void *host_addr = NULL;
+hwaddr offset_within_region;
+
+qemu_mutex_lock(hostmem-current_regions_lock);
+region = bsearch(phys, hostmem-current_regions,
+ hostmem-num_current_regions,
+ sizeof(hostmem-current_regions[0]),
+ hostmem_lookup_cmp);
+if (!region) {
+goto out;
+}
+if (is_write  region-readonly) {
+goto out;
+}
+offset_within_region = phys - region-guest_addr;
+if (offset_within_region + len = region-size) {
+host_addr = region-host_addr + offset_within_region;
+}
+out:
+qemu_mutex_unlock(hostmem-current_regions_lock);
+
+return host_addr;
+}
+
+/**
+ * Install new regions list
+ */
+static void hostmem_listener_commit(MemoryListener *listener)
+{
+Hostmem *hostmem = container_of(listener, Hostmem, listener);
+
+qemu_mutex_lock(hostmem-current_regions_lock);
+g_free(hostmem-current_regions);
+hostmem-current_regions = hostmem-new_regions;
+hostmem-num_current_regions = hostmem-num_new_regions;
+qemu_mutex_unlock(hostmem-current_regions_lock);
+
+/* Reset new regions list */
+hostmem-new_regions = NULL;
+hostmem-num_new_regions = 0;
+}
+
+/**
+ * Add a MemoryRegionSection to the new regions list
+ */
+static void hostmem_append_new_region(Hostmem *hostmem,
+  MemoryRegionSection *section)
+{
+void *ram_ptr = memory_region_get_ram_ptr(section-mr);
+size_t num = hostmem-num_new_regions;
+size_t new_size = (num + 1) * sizeof(hostmem-new_regions[0]);
+
+hostmem-new_regions = g_realloc(hostmem-new_regions, new_size);
+hostmem-new_regions[num] = (HostmemRegion){
+.host_addr = ram_ptr + section-offset_within_region,
+.guest_addr = section-offset_within_address_space,
+.size = section-size,
+.readonly = section-readonly,
+};
+hostmem-num_new_regions++;
+}
+
+static void hostmem_listener_append_region(MemoryListener *listener,
+   MemoryRegionSection *section)
+{
+Hostmem *hostmem = container_of(listener, Hostmem, listener);
+
+/* Ignore non-RAM regions, we