--- /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) {