Re: [Qemu-devel] [PATCH 11/23] memory: add ioeventfd support

2011-07-26 Thread Avi Kivity

On 07/25/2011 10:08 PM, Anthony Liguori wrote:


+static void as_memory_ioeventfd_add(AddressSpace *as, 
MemoryRegionIoeventfd *fd)

+{
+int r;
+
+if (!fd-match_data || fd-addr.size != 4) {
+abort();
+}
+
+r = kvm_set_ioeventfd_mmio_long(fd-fd, fd-addr.start, 
fd-data, true);

+if (r  0) {
+abort();
+}



asserts would be friendlier.


I thought asserts were disabled by default.  But I see it isn't so; will 
update.




I really dislike baking ioeventfd into this API.  There is only one 
user of ioeventfd in the tree.


Two: virtio-pci and ivshmem.



I worry that by having things like ioeventfd the API, we're making it 
too difficult to side-step the API which prevents future optimizations.


I'd prefer virtio-pci to have ugliness in it where it circumvented the 
layering vs. having such a device specific thing in generic code.


It's impossible (or at least, impossible without further information 
from the API) to do this and retain correctness.  Currently virtio-pci 
is broken wrt bridges and overlapping BARs; it's probably also broken on 
targets that bridge the I/O address space to MMIO.


With the memory API, this is fixed in a natural way by making the I/O 
address space a subregion of the bridge which does the conversion; the 
code will automatically add the needed offset and use MMIO ioeventfd 
instead of portio.


On a more general note, I don't want this to be a lean and mean API that 
throws any complexity to the users; instead I want to make writing 
devices as simple as possible and own all the smarts.


(an example - undecoded address bits can be specified to the API which 
then takes care of replication or shifting).


--
error compiling committee.c: too many arguments to function




[Qemu-devel] [PATCH 11/23] memory: add ioeventfd support

2011-07-25 Thread Avi Kivity
As with the rest of the memory API, the caller associates an eventfd
with an address, and the memory API takes care of registering or
unregistering when the address is made visible or invisible to the
guest.

Signed-off-by: Avi Kivity a...@redhat.com
---
 memory.c |  230 ++
 memory.h |   20 ++
 2 files changed, 250 insertions(+), 0 deletions(-)

diff --git a/memory.c b/memory.c
index e4446a0..a5cde0c 100644
--- a/memory.c
+++ b/memory.c
@@ -15,6 +15,7 @@
 #include exec-memory.h
 #include ioport.h
 #include bitops.h
+#include kvm.h
 #include assert.h
 
 typedef struct AddrRange AddrRange;
@@ -64,6 +65,50 @@ struct CoalescedMemoryRange {
 QTAILQ_ENTRY(CoalescedMemoryRange) link;
 };
 
+struct MemoryRegionIoeventfd {
+AddrRange addr;
+bool match_data;
+uint64_t data;
+int fd;
+};
+
+static bool memory_region_ioeventfd_before(MemoryRegionIoeventfd a,
+   MemoryRegionIoeventfd b)
+{
+if (a.addr.start  b.addr.start) {
+return true;
+} else if (a.addr.start  b.addr.start) {
+return false;
+} else if (a.addr.size  b.addr.size) {
+return true;
+} else if (a.addr.size  b.addr.size) {
+return false;
+} else if (a.match_data  b.match_data) {
+return true;
+} else  if (a.match_data  b.match_data) {
+return false;
+} else if (a.match_data) {
+if (a.data  b.data) {
+return true;
+} else if (a.data  b.data) {
+return false;
+}
+}
+if (a.fd  b.fd) {
+return true;
+} else if (a.fd  b.fd) {
+return false;
+}
+return false;
+}
+
+static bool memory_region_ioeventfd_equal(MemoryRegionIoeventfd a,
+  MemoryRegionIoeventfd b)
+{
+return !memory_region_ioeventfd_before(a, b)
+ !memory_region_ioeventfd_before(b, a);
+}
+
 typedef struct FlatRange FlatRange;
 typedef struct FlatView FlatView;
 
@@ -92,6 +137,8 @@ struct AddressSpace {
 const AddressSpaceOps *ops;
 MemoryRegion *root;
 FlatView current_map;
+int ioeventfd_nb;
+MemoryRegionIoeventfd *ioeventfds;
 };
 
 struct AddressSpaceOps {
@@ -99,6 +146,8 @@ struct AddressSpaceOps {
 void (*range_del)(AddressSpace *as, FlatRange *fr);
 void (*log_start)(AddressSpace *as, FlatRange *fr);
 void (*log_stop)(AddressSpace *as, FlatRange *fr);
+void (*ioeventfd_add)(AddressSpace *as, MemoryRegionIoeventfd *fd);
+void (*ioeventfd_del)(AddressSpace *as, MemoryRegionIoeventfd *fd);
 };
 
 #define FOR_EACH_FLAT_RANGE(var, view)  \
@@ -201,11 +250,37 @@ static void as_memory_log_stop(AddressSpace *as, 
FlatRange *fr)
 cpu_physical_log_stop(fr-addr.start, fr-addr.size);
 }
 
+static void as_memory_ioeventfd_add(AddressSpace *as, MemoryRegionIoeventfd 
*fd)
+{
+int r;
+
+if (!fd-match_data || fd-addr.size != 4) {
+abort();
+}
+
+r = kvm_set_ioeventfd_mmio_long(fd-fd, fd-addr.start, fd-data, true);
+if (r  0) {
+abort();
+}
+}
+
+static void as_memory_ioeventfd_del(AddressSpace *as, MemoryRegionIoeventfd 
*fd)
+{
+int r;
+
+r = kvm_set_ioeventfd_mmio_long(fd-fd, fd-addr.start, fd-data, false);
+if (r  0) {
+abort();
+}
+}
+
 static const AddressSpaceOps address_space_ops_memory = {
 .range_add = as_memory_range_add,
 .range_del = as_memory_range_del,
 .log_start = as_memory_log_start,
 .log_stop = as_memory_log_stop,
+.ioeventfd_add = as_memory_ioeventfd_add,
+.ioeventfd_del = as_memory_ioeventfd_del,
 };
 
 static AddressSpace address_space_memory = {
@@ -281,9 +356,35 @@ static void as_io_range_del(AddressSpace *as, FlatRange 
*fr)
 isa_unassign_ioport(fr-addr.start, fr-addr.size);
 }
 
+static void as_io_ioeventfd_add(AddressSpace *as, MemoryRegionIoeventfd *fd)
+{
+int r;
+
+if (!fd-match_data || fd-addr.size != 2) {
+abort();
+}
+
+r = kvm_set_ioeventfd_pio_word(fd-fd, fd-addr.start, fd-data, true);
+if (r  0) {
+abort();
+}
+}
+
+static void as_io_ioeventfd_del(AddressSpace *as, MemoryRegionIoeventfd *fd)
+{
+int r;
+
+r = kvm_set_ioeventfd_pio_word(fd-fd, fd-addr.start, fd-data, false);
+if (r  0) {
+abort();
+}
+}
+
 static const AddressSpaceOps address_space_ops_io = {
 .range_add = as_io_range_add,
 .range_del = as_io_range_del,
+.ioeventfd_add = as_io_ioeventfd_add,
+.ioeventfd_del = as_io_ioeventfd_del,
 };
 
 static AddressSpace address_space_io = {
@@ -382,6 +483,69 @@ static FlatView generate_memory_topology(MemoryRegion *mr)
 return view;
 }
 
+static void address_space_add_del_ioeventfds(AddressSpace *as,
+ MemoryRegionIoeventfd *fds_new,
+ unsigned fds_new_nb,
+ MemoryRegionIoeventfd 

Re: [Qemu-devel] [PATCH 11/23] memory: add ioeventfd support

2011-07-25 Thread malc
On Mon, 25 Jul 2011, Avi Kivity wrote:

 As with the rest of the memory API, the caller associates an eventfd
 with an address, and the memory API takes care of registering or
 unregistering when the address is made visible or invisible to the
 guest.
 
 Signed-off-by: Avi Kivity a...@redhat.com
[..snip..]

 +static bool memory_region_ioeventfd_before(MemoryRegionIoeventfd a,
 +   MemoryRegionIoeventfd b)
 +{
 +if (a.addr.start  b.addr.start) {
 +return true;
 +} else if (a.addr.start  b.addr.start) {
 +return false;
 +} else if (a.addr.size  b.addr.size) {
 +return true;
 +} else if (a.addr.size  b.addr.size) {
 +return false;
 +} else if (a.match_data  b.match_data) {
 +return true;
 +} else  if (a.match_data  b.match_data) {
 +return false;
 +} else if (a.match_data) {
 +if (a.data  b.data) {
 +return true;
 +} else if (a.data  b.data) {
 +return false;
 +}
 +}
 +if (a.fd  b.fd) {
 +return true;
 +} else if (a.fd  b.fd) {
 +return false;
 +}

Braces..

 +return false;
 +}
 +

[..snip..]

-- 
mailto:av1...@comtv.ru



Re: [Qemu-devel] [PATCH 11/23] memory: add ioeventfd support

2011-07-25 Thread Avi Kivity

On 07/25/2011 06:16 PM, malc wrote:

On Mon, 25 Jul 2011, Avi Kivity wrote:

  As with the rest of the memory API, the caller associates an eventfd
  with an address, and the memory API takes care of registering or
  unregistering when the address is made visible or invisible to the
  guest.

  Signed-off-by: Avi Kivitya...@redhat.com
[..snip..]

  +static bool memory_region_ioeventfd_before(MemoryRegionIoeventfd a,
  +   MemoryRegionIoeventfd b)
  +{
  +if (a.addr.start  b.addr.start) {
  +return true;
  +} else if (a.addr.start  b.addr.start) {
  +return false;
  +} else if (a.addr.size  b.addr.size) {
  +return true;
  +} else if (a.addr.size  b.addr.size) {
  +return false;
  +} else if (a.match_data  b.match_data) {
  +return true;
  +} else  if (a.match_data  b.match_data) {
  +return false;
  +} else if (a.match_data) {
  +if (a.data  b.data) {
  +return true;
  +} else if (a.data  b.data) {
  +return false;
  +}
  +}
  +if (a.fd  b.fd) {
  +return true;
  +} else if (a.fd  b.fd) {
  +return false;
  +}

Braces..



Where? add? remove?

--
error compiling committee.c: too many arguments to function




Re: [Qemu-devel] [PATCH 11/23] memory: add ioeventfd support

2011-07-25 Thread malc
On Mon, 25 Jul 2011, Avi Kivity wrote:

 On 07/25/2011 06:16 PM, malc wrote:
  On Mon, 25 Jul 2011, Avi Kivity wrote:
  
As with the rest of the memory API, the caller associates an eventfd
with an address, and the memory API takes care of registering or
unregistering when the address is made visible or invisible to the
guest.
  
Signed-off-by: Avi Kivitya...@redhat.com
  [..snip..]
  
+static bool memory_region_ioeventfd_before(MemoryRegionIoeventfd a,
+   MemoryRegionIoeventfd b)
+{
+if (a.addr.start  b.addr.start) {
+return true;
+} else if (a.addr.start  b.addr.start) {
+return false;
+} else if (a.addr.size  b.addr.size) {
+return true;
+} else if (a.addr.size  b.addr.size) {
+return false;
+} else if (a.match_data  b.match_data) {
+return true;
+} else  if (a.match_data  b.match_data) {
+return false;
+} else if (a.match_data) {
+if (a.data  b.data) {
+return true;
+} else if (a.data  b.data) {
+return false;
+}
+}
+if (a.fd  b.fd) {
+return true;
+} else {
   if (a.fd  b.fd) {
   +return false;
   +}
}
  
  Braces..
  
 
 Where? add? remove?
 

You authored the coding_style document btw. 


-- 
mailto:av1...@comtv.ru



Re: [Qemu-devel] [PATCH 11/23] memory: add ioeventfd support

2011-07-25 Thread Avi Kivity

On 07/25/2011 06:22 PM, malc wrote:

   +}
   +if (a.fd   b.fd) {
   +return true;
   +} else {
if (a.fd   b.fd) {
   +return false;
   +}
 }


CODING_STYLE permits braceless else if.


  
Braces..
  

  Where? add? remove?


You authored the coding_style document btw.


It's CODING_STYLE.

--
error compiling committee.c: too many arguments to function




Re: [Qemu-devel] [PATCH 11/23] memory: add ioeventfd support

2011-07-25 Thread malc
On Mon, 25 Jul 2011, Avi Kivity wrote:

 On 07/25/2011 06:22 PM, malc wrote:
 +}
 +if (a.fd   b.fd) {
 +return true;
 +} else {
  if (a.fd   b.fd) {
 +return false;
 +}
   }
 
 CODING_STYLE permits braceless else if.

The example uses it, the text however suggests it's illegal.

[..snip..]

-- 
mailto:av1...@comtv.ru



Re: [Qemu-devel] [PATCH 11/23] memory: add ioeventfd support

2011-07-25 Thread Avi Kivity

On 07/25/2011 06:38 PM, malc wrote:

On Mon, 25 Jul 2011, Avi Kivity wrote:

  On 07/25/2011 06:22 PM, malc wrote:
  +}
  +if (a.fdb.fd) {
  +return true;
  +} else {
if (a.fdb.fd) {
  +return false;
  +}
 }

  CODING_STYLE permits braceless else if.

The example uses it, the text however suggests it's illegal.


I'll post a patch.  It's perfectly reasonable IMO, and there ~1800 
instances in the tree.


--
error compiling committee.c: too many arguments to function




Re: [Qemu-devel] [PATCH 11/23] memory: add ioeventfd support

2011-07-25 Thread Anthony Liguori

On 07/25/2011 09:02 AM, Avi Kivity wrote:

As with the rest of the memory API, the caller associates an eventfd
with an address, and the memory API takes care of registering or
unregistering when the address is made visible or invisible to the
guest.

Signed-off-by: Avi Kivitya...@redhat.com
---
  memory.c |  230 ++
  memory.h |   20 ++
  2 files changed, 250 insertions(+), 0 deletions(-)

diff --git a/memory.c b/memory.c
index e4446a0..a5cde0c 100644
--- a/memory.c
+++ b/memory.c
@@ -15,6 +15,7 @@
  #include exec-memory.h
  #include ioport.h
  #include bitops.h
+#include kvm.h
  #includeassert.h

  typedef struct AddrRange AddrRange;
@@ -64,6 +65,50 @@ struct CoalescedMemoryRange {
  QTAILQ_ENTRY(CoalescedMemoryRange) link;
  };

+struct MemoryRegionIoeventfd {
+AddrRange addr;
+bool match_data;
+uint64_t data;
+int fd;
+};
+
+static bool memory_region_ioeventfd_before(MemoryRegionIoeventfd a,
+   MemoryRegionIoeventfd b)
+{
+if (a.addr.start  b.addr.start) {
+return true;
+} else if (a.addr.start  b.addr.start) {
+return false;
+} else if (a.addr.size  b.addr.size) {
+return true;
+} else if (a.addr.size  b.addr.size) {
+return false;
+} else if (a.match_data  b.match_data) {
+return true;
+} else  if (a.match_data  b.match_data) {
+return false;
+} else if (a.match_data) {
+if (a.data  b.data) {
+return true;
+} else if (a.data  b.data) {
+return false;
+}
+}
+if (a.fd  b.fd) {
+return true;
+} else if (a.fd  b.fd) {
+return false;
+}
+return false;
+}
+
+static bool memory_region_ioeventfd_equal(MemoryRegionIoeventfd a,
+  MemoryRegionIoeventfd b)
+{
+return !memory_region_ioeventfd_before(a, b)
+  !memory_region_ioeventfd_before(b, a);
+}
+
  typedef struct FlatRange FlatRange;
  typedef struct FlatView FlatView;

@@ -92,6 +137,8 @@ struct AddressSpace {
  const AddressSpaceOps *ops;
  MemoryRegion *root;
  FlatView current_map;
+int ioeventfd_nb;
+MemoryRegionIoeventfd *ioeventfds;
  };

  struct AddressSpaceOps {
@@ -99,6 +146,8 @@ struct AddressSpaceOps {
  void (*range_del)(AddressSpace *as, FlatRange *fr);
  void (*log_start)(AddressSpace *as, FlatRange *fr);
  void (*log_stop)(AddressSpace *as, FlatRange *fr);
+void (*ioeventfd_add)(AddressSpace *as, MemoryRegionIoeventfd *fd);
+void (*ioeventfd_del)(AddressSpace *as, MemoryRegionIoeventfd *fd);
  };

  #define FOR_EACH_FLAT_RANGE(var, view)  \
@@ -201,11 +250,37 @@ static void as_memory_log_stop(AddressSpace *as, 
FlatRange *fr)
  cpu_physical_log_stop(fr-addr.start, fr-addr.size);
  }

+static void as_memory_ioeventfd_add(AddressSpace *as, MemoryRegionIoeventfd 
*fd)
+{
+int r;
+
+if (!fd-match_data || fd-addr.size != 4) {
+abort();
+}
+
+r = kvm_set_ioeventfd_mmio_long(fd-fd, fd-addr.start, fd-data, true);
+if (r  0) {
+abort();
+}


asserts would be friendlier.

I really dislike baking ioeventfd into this API.  There is only one user 
of ioeventfd in the tree.


I worry that by having things like ioeventfd the API, we're making it 
too difficult to side-step the API which prevents future optimizations.


I'd prefer virtio-pci to have ugliness in it where it circumvented the 
layering vs. having such a device specific thing in generic code.


Regards,

Anthony Liguori


+}
+
+static void as_memory_ioeventfd_del(AddressSpace *as, MemoryRegionIoeventfd 
*fd)
+{
+int r;
+
+r = kvm_set_ioeventfd_mmio_long(fd-fd, fd-addr.start, fd-data, false);
+if (r  0) {
+abort();
+}
+}
+
  static const AddressSpaceOps address_space_ops_memory = {
  .range_add = as_memory_range_add,
  .range_del = as_memory_range_del,
  .log_start = as_memory_log_start,
  .log_stop = as_memory_log_stop,
+.ioeventfd_add = as_memory_ioeventfd_add,
+.ioeventfd_del = as_memory_ioeventfd_del,
  };

  static AddressSpace address_space_memory = {
@@ -281,9 +356,35 @@ static void as_io_range_del(AddressSpace *as, FlatRange 
*fr)
  isa_unassign_ioport(fr-addr.start, fr-addr.size);
  }

+static void as_io_ioeventfd_add(AddressSpace *as, MemoryRegionIoeventfd *fd)
+{
+int r;
+
+if (!fd-match_data || fd-addr.size != 2) {
+abort();
+}
+
+r = kvm_set_ioeventfd_pio_word(fd-fd, fd-addr.start, fd-data, true);
+if (r  0) {
+abort();
+}
+}
+
+static void as_io_ioeventfd_del(AddressSpace *as, MemoryRegionIoeventfd *fd)
+{
+int r;
+
+r = kvm_set_ioeventfd_pio_word(fd-fd, fd-addr.start, fd-data, false);
+if (r  0) {
+abort();
+}
+}
+
  static const AddressSpaceOps address_space_ops_io = {
  .range_add = as_io_range_add,
  .range_del = as_io_range_del,
+