[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[xen master] x86/pv: Rework guest_io_okay() to return X86EMUL_*



commit 7429e1cc071b0e20ea9581da4893fb9b2f6d21d4
Author:     Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
AuthorDate: Mon Sep 30 16:09:51 2024 +0100
Commit:     Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
CommitDate: Tue Oct 1 14:58:18 2024 +0100

    x86/pv: Rework guest_io_okay() to return X86EMUL_*
    
    In order to fix a bug with guest_io_okay() (subsequent patch), rework
    guest_io_okay() to take in an emulation context, and return X86EMUL_* rather
    than a boolean.
    
    For the failing case, take the opportunity to inject #GP explicitly, rather
    than returning X86EMUL_UNHANDLEABLE.  There is a logical difference between
    "we know what this is, and it's #GP", vs "we don't know what this is".
    
    There is no change in practice as emulation is the final step on general #GP
    resolution, but returning X86EMUL_UNHANDLEABLE would be a latent bug if a
    subsequent action were to appear.
    
    No practical change.
    
    Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
    Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx>
---
 xen/arch/x86/pv/emul-priv-op.c | 36 +++++++++++++++++++++++-------------
 1 file changed, 23 insertions(+), 13 deletions(-)

diff --git a/xen/arch/x86/pv/emul-priv-op.c b/xen/arch/x86/pv/emul-priv-op.c
index b90f745c75..cc66ffbf8e 100644
--- a/xen/arch/x86/pv/emul-priv-op.c
+++ b/xen/arch/x86/pv/emul-priv-op.c
@@ -156,14 +156,16 @@ static bool iopl_ok(const struct vcpu *v, const struct 
cpu_user_regs *regs)
 }
 
 /* Has the guest requested sufficient permission for this I/O access? */
-static bool guest_io_okay(unsigned int port, unsigned int bytes,
-                          struct vcpu *v, struct cpu_user_regs *regs)
+static int guest_io_okay(unsigned int port, unsigned int bytes,
+                         struct x86_emulate_ctxt *ctxt)
 {
+    const struct cpu_user_regs *regs = ctxt->regs;
+    struct vcpu *v = current;
     /* If in user mode, switch to kernel mode just to read I/O bitmap. */
     const bool user_mode = !(v->arch.flags & TF_kernel_mode);
 
     if ( iopl_ok(v, regs) )
-        return true;
+        return X86EMUL_OKAY;
 
     if ( (port + bytes) <= v->arch.pv.iobmp_limit )
     {
@@ -190,10 +192,12 @@ static bool guest_io_okay(unsigned int port, unsigned int 
bytes,
             toggle_guest_pt(v);
 
         if ( (x.mask & (((1 << bytes) - 1) << (port & 7))) == 0 )
-            return true;
+            return X86EMUL_OKAY;
     }
 
-    return false;
+    x86_emul_hw_exception(X86_EXC_GP, 0, ctxt);
+
+    return X86EMUL_EXCEPTION;
 }
 
 /* Has the administrator granted sufficient permission for this I/O access? */
@@ -353,12 +357,14 @@ static int cf_check read_io(
     struct priv_op_ctxt *poc = container_of(ctxt, struct priv_op_ctxt, ctxt);
     struct vcpu *curr = current;
     struct domain *currd = current->domain;
+    int rc;
 
     /* INS must not come here. */
     ASSERT((ctxt->opcode & ~9) == 0xe4);
 
-    if ( !guest_io_okay(port, bytes, curr, ctxt->regs) )
-        return X86EMUL_UNHANDLEABLE;
+    rc = guest_io_okay(port, bytes, ctxt);
+    if ( rc != X86EMUL_OKAY )
+        return rc;
 
     poc->bpmatch = check_guest_io_breakpoint(curr, port, bytes);
 
@@ -458,12 +464,14 @@ static int cf_check write_io(
     struct priv_op_ctxt *poc = container_of(ctxt, struct priv_op_ctxt, ctxt);
     struct vcpu *curr = current;
     struct domain *currd = current->domain;
+    int rc;
 
     /* OUTS must not come here. */
     ASSERT((ctxt->opcode & ~9) == 0xe6);
 
-    if ( !guest_io_okay(port, bytes, curr, ctxt->regs) )
-        return X86EMUL_UNHANDLEABLE;
+    rc = guest_io_okay(port, bytes, ctxt);
+    if ( rc != X86EMUL_OKAY )
+        return rc;
 
     poc->bpmatch = check_guest_io_breakpoint(curr, port, bytes);
 
@@ -612,8 +620,9 @@ static int cf_check rep_ins(
 
     *reps = 0;
 
-    if ( !guest_io_okay(port, bytes_per_rep, curr, ctxt->regs) )
-        return X86EMUL_UNHANDLEABLE;
+    rc = guest_io_okay(port, bytes_per_rep, ctxt);
+    if ( rc != X86EMUL_OKAY )
+        return rc;
 
     rc = read_segment(x86_seg_es, &sreg, ctxt);
     if ( rc != X86EMUL_OKAY )
@@ -678,8 +687,9 @@ static int cf_check rep_outs(
 
     *reps = 0;
 
-    if ( !guest_io_okay(port, bytes_per_rep, curr, ctxt->regs) )
-        return X86EMUL_UNHANDLEABLE;
+    rc = guest_io_okay(port, bytes_per_rep, ctxt);
+    if ( rc != X86EMUL_OKAY )
+        return rc;
 
     rc = read_segment(seg, &sreg, ctxt);
     if ( rc != X86EMUL_OKAY )
--
generated by git-patchbot for /home/xen/git/xen.git#master



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.