Hello.

I have problem with multiple ioreq_servers
server 1 (emulates VGA) and server 2 (qemu).

Emulation VGA server maps VGA PIO registers (3c0-3cf, 3b4-3b5 ...)
Qemu maps "all" PIO space (0-ffff)
(ref: 
http://xenbits.xen.org/gitweb/?p=qemu-xen.git;a=blob;f=exec.c;h=46fe70ed49f85d0638061aa5b09f1f9d521b0bd3;hb=18f2ce4bfe67f9b38143d9d96207e49c92b6881c#l2007
  )
Xen does not check overlap errors between ioreq_servers
(ref: 
http://xenbits.xen.org/gitweb/?p=xen.git;a=blob;f=xen/arch/x86/hvm/hvm.c;h=186e01e3b05a0264e8f4538b226da2feed50d11a;hb=d77bac5c064ffb9dbb5b89b55b89853f1b784ebf#l1252
 )
Xen choose "first match"
(ref: 
http://xenbits.xen.org/gitweb/?p=xen.git;a=blob;f=xen/arch/x86/hvm/hvm.c;h=186e01e3b05a0264e8f4538b226da2feed50d11a;hb=d77bac5c064ffb9dbb5b89b55b89853f1b784ebf#l2594
 )

In my case all requests to VGA PIO are sent to qemu (qemu VGA is disabled with parameter "-display none"/"-vga none") and dropped.
Emulation VGA server receives only memory updates (eg. a0000-bffff).

Is this problem resolved in updates (actual code looks the same (ioreq.c)) ?
Is there any prioritization between ioreq_servers (but it is probably bad idea) 
?
Should the IO mapping check overlap between ioreq_servers (but it is probably 
bad idea) ?
Should the qemu IO map only emulated areas (why it needs all ?) ?
Any other solution ?

Thanks for answers, Martin Cerveny

PS: I programmed workaround to select sever with smaller mapped range 
(attached).

CC: Paolo Bonzini <pbonz...@redhat.com> - Maintainer qemu - exec.c
CC: Paul Durrant <paul.durr...@citrix.com> - Maintainer X86 I/O EMULATION - 
ioreq.c
--- /root/src/xen/xen/arch/x86/hvm/hvm.c        2016-04-20 23:15:33.728000000 
+0200
+++ xen-4.6.1/xen/arch/x86/hvm/hvm.c    2016-04-25 14:58:40.040000000 +0200
@@ -2524,6 +2524,9 @@
     uint8_t type;
     uint64_t addr;
 
+    uint64_t range_best = ~0ull;
+    struct hvm_ioreq_server *s_best = NULL;
+
     if ( list_empty(&d->arch.hvm_domain.ioreq_server.list) )
         return NULL;
 
@@ -2572,6 +2575,7 @@
                           list_entry )
     {
         struct rangeset *r;
+        uint64_t _range;
 
         if ( s == d->arch.hvm_domain.default_ioreq_server )
             continue;
@@ -2590,14 +2594,24 @@
 
         case IOREQ_TYPE_PIO:
             end = addr + p->size - 1;
-            if ( rangeset_contains_range(r, addr, end) )
-                return s;
+            if ( 0 < (_range = rangeset_contains_range_size(r, addr, end)) ) {
+                if (_range < range_best) {
+                    s_best = s;
+                    range_best = _range;
+                }
+                continue;
+            }
 
             break;
         case IOREQ_TYPE_COPY:
             end = addr + (p->size * p->count) - 1;
-            if ( rangeset_contains_range(r, addr, end) )
-                return s;
+            if ( 0 < (_range = rangeset_contains_range_size(r, addr, end)) ) {
+                if (_range < range_best) {
+                    s_best = s;
+                    range_best = _range;
+                }
+                continue;
+            }
 
             break;
         case IOREQ_TYPE_PCI_CONFIG:
@@ -2611,6 +2625,10 @@
             break;
         }
     }
+    
+
+    if (s_best) 
+        return s_best;
 
     return d->arch.hvm_domain.default_ioreq_server;
 }
--- /root/src/xen/xen/include/xen/rangeset.h    2016-04-18 13:15:29.828000000 
+0200
+++ xen-4.6.1/xen/include/xen/rangeset.h        2016-04-25 13:12:57.203994380 
+0200
@@ -67,6 +67,8 @@
 int rangeset_report_ranges(
     struct rangeset *r, unsigned long s, unsigned long e,
     int (*cb)(unsigned long s, unsigned long e, void *), void *ctxt);
+unsigned long rangeset_contains_range_size(
+    struct rangeset *r, unsigned long s, unsigned long e);
 
 /* Add/remove/query a single number. */
 int __must_check rangeset_add_singleton(
--- /root/src/xen/xen/common/rangeset.c 2016-04-18 13:15:29.740000000 +0200
+++ xen-4.6.1/xen/common/rangeset.c     2016-04-25 13:12:57.203994380 +0200
@@ -264,6 +264,23 @@
     return contains;
 }
 
+unsigned long rangeset_contains_range_size(
+    struct rangeset *r, unsigned long s, unsigned long e)
+{
+    struct range *x;
+    unsigned long size;
+
+    ASSERT(s <= e);
+
+    read_lock(&r->lock);
+    x = find_range(r, s);
+    if (x && (x->e >= e)) size = x->e - x->s + 1;
+    else size = 0;
+    read_unlock(&r->lock);
+
+    return size;
+}
+
 bool_t rangeset_overlaps_range(
     struct rangeset *r, unsigned long s, unsigned long e)
 {
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

Reply via email to