Internal ioreq servers are always processed first, and ioreqs are
dispatched by calling the handler function. If no internal servers have
registered for an ioreq it's then forwarded to external callers.

Signed-off-by: Roger Pau Monné <roger....@citrix.com>
---
 xen/arch/x86/hvm/ioreq.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/xen/arch/x86/hvm/ioreq.c b/xen/arch/x86/hvm/ioreq.c
index 23ef9b0c02..3fb6fe9585 100644
--- a/xen/arch/x86/hvm/ioreq.c
+++ b/xen/arch/x86/hvm/ioreq.c
@@ -1305,6 +1305,7 @@ struct hvm_ioreq_server *hvm_select_ioreq_server(struct 
domain *d,
     uint8_t type;
     uint64_t addr;
     unsigned int id;
+    bool internal = true;
 
     if ( p->type != IOREQ_TYPE_COPY && p->type != IOREQ_TYPE_PIO )
         return NULL;
@@ -1345,11 +1346,12 @@ struct hvm_ioreq_server *hvm_select_ioreq_server(struct 
domain *d,
         addr = p->addr;
     }
 
+ retry:
     FOR_EACH_IOREQ_SERVER(d, id, s)
     {
         struct rangeset *r;
 
-        if ( !s->enabled )
+        if ( !s->enabled || s->internal != internal )
             continue;
 
         r = s->range[type];
@@ -1387,6 +1389,12 @@ struct hvm_ioreq_server *hvm_select_ioreq_server(struct 
domain *d,
         }
     }
 
+    if ( internal )
+    {
+        internal = false;
+        goto retry;
+    }
+
     return NULL;
 }
 
@@ -1492,9 +1500,18 @@ int hvm_send_ioreq(struct hvm_ioreq_server *s, ioreq_t 
*proto_p,
 
     ASSERT(s);
 
+    if ( s->internal && buffered )
+    {
+        ASSERT_UNREACHABLE();
+        return X86EMUL_UNHANDLEABLE;
+    }
+
     if ( buffered )
         return hvm_send_buffered_ioreq(s, proto_p);
 
+    if ( s->internal )
+        return s->handler(curr, proto_p);
+
     if ( unlikely(!vcpu_start_shutdown_deferral(curr)) )
         return X86EMUL_RETRY;
 
-- 
2.22.0


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xenproject.org
https://lists.xenproject.org/mailman/listinfo/xen-devel

Reply via email to