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 <[email protected]> - Maintainer qemu - exec.c
CC: Paul Durrant <[email protected]> - 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
[email protected]
http://lists.xen.org/xen-devel