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