[xen master] x86/HVM: fix hvmemul_rep_outs_set_context()

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[xen master] x86/HVM: fix hvmemul_rep_outs_set_context()

patchbot
commit 378d31ab3e007d7a059b3e26d4062d7ac318eef4
Author:     Jan Beulich <[hidden email]>
AuthorDate: Fri Dec 15 11:11:36 2017 +0100
Commit:     Jan Beulich <[hidden email]>
CommitDate: Fri Dec 15 11:11:36 2017 +0100

    x86/HVM: fix hvmemul_rep_outs_set_context()
   
    There were two issues with this function: Its use of
    hvmemul_do_pio_buffer() was wrong (the function deals only with
    individual port accesses, not repeated ones, i.e. passing it
    "*reps * bytes_per_rep" does not have the intended effect). And it
    could have processed a larger set of operations in one go than was
    probably intended (limited just by the size that xmalloc() can hand
    back).
   
    By converting to proper use of hvmemul_do_pio_buffer(), no intermediate
    buffer is needed at all. As a result a preemption check is being added.
   
    Also drop unused parameters from the function.
   
    Signed-off-by: Jan Beulich <[hidden email]>
    Reviewed-by: Razvan Cojocaru <[hidden email]>
    Reviewed-by: Paul Durrant <[hidden email]>
---
 xen/arch/x86/hvm/emulate.c | 44 ++++++++++++++++++++++++++++----------------
 1 file changed, 28 insertions(+), 16 deletions(-)

diff --git a/xen/arch/x86/hvm/emulate.c b/xen/arch/x86/hvm/emulate.c
index c9fae88..3b82455 100644
--- a/xen/arch/x86/hvm/emulate.c
+++ b/xen/arch/x86/hvm/emulate.c
@@ -1349,28 +1349,41 @@ static int hvmemul_rep_ins(
 }
 
 static int hvmemul_rep_outs_set_context(
-    enum x86_segment src_seg,
-    unsigned long src_offset,
     uint16_t dst_port,
     unsigned int bytes_per_rep,
-    unsigned long *reps,
-    struct x86_emulate_ctxt *ctxt)
+    unsigned long *reps)
 {
-    unsigned int bytes = *reps * bytes_per_rep;
-    char *buf;
-    int rc;
-
-    buf = xmalloc_array(char, bytes);
+    const struct arch_vm_event *ev = current->arch.vm_event;
+    const uint8_t *ptr;
+    unsigned int avail;
+    unsigned long done;
+    int rc = X86EMUL_OKAY;
 
-    if ( buf == NULL )
+    ASSERT(bytes_per_rep <= 4);
+    if ( !ev )
         return X86EMUL_UNHANDLEABLE;
 
-    rc = set_context_data(buf, bytes);
+    ptr = ev->emul.read.data;
+    avail = ev->emul.read.size;
 
-    if ( rc == X86EMUL_OKAY )
-        rc = hvmemul_do_pio_buffer(dst_port, bytes, IOREQ_WRITE, buf);
+    for ( done = 0; done < *reps; ++done )
+    {
+        unsigned int size = min(bytes_per_rep, avail);
+        uint32_t data = 0;
 
-    xfree(buf);
+        if ( done && hypercall_preempt_check() )
+            break;
+
+        memcpy(&data, ptr, size);
+        avail -= size;
+        ptr += size;
+
+        rc = hvmemul_do_pio_buffer(dst_port, bytes_per_rep, IOREQ_WRITE, &data);
+        if ( rc != X86EMUL_OKAY )
+            break;
+    }
+
+    *reps = done;
 
     return rc;
 }
@@ -1392,8 +1405,7 @@ static int hvmemul_rep_outs(
     int rc;
 
     if ( unlikely(hvmemul_ctxt->set_context) )
-        return hvmemul_rep_outs_set_context(src_seg, src_offset, dst_port,
-                                            bytes_per_rep, reps, ctxt);
+        return hvmemul_rep_outs_set_context(dst_port, bytes_per_rep, reps);
 
     rc = hvmemul_virtual_to_linear(
         src_seg, src_offset, bytes_per_rep, reps, hvm_access_read,
--
generated by git-patchbot for /home/xen/git/xen.git#master

_______________________________________________
Xen-changelog mailing list
[hidden email]
https://lists.xenproject.org/xen-changelog