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

[Xen-changelog] [xen-3.1-testing] SVM: handle page faults in emulated instruction fetches



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1206015794 0
# Node ID ccdea325953468a5172f5b9124a050fcbea0a6a3
# Parent  b45db6cdfa966513116e97a7b22609e3c7d20a79
SVM: handle page faults in emulated instruction fetches

Deal with failures in hvm_copy_from_guest_virt when fetching
instructions in the various SVM emulation paths.  Since we know that
the instruction was fetchable by the hardware, we can usually just
return from the VMEXIT and try again; whatever caused us to fail will
cause the hardware to fail next time and we'll get the correct exit
code.

Signed-off-by: Tim Deegan <Tim.Deegan@xxxxxxxxxx>
xen-unstable changeset:   17202:8325f200e19414d998b7625f2e3cf786a6d3d3a3
xen-unstable date:        Mon Mar 17 11:39:50 2008 +0000
---
 xen/arch/x86/hvm/svm/emulate.c |    4 +++-
 xen/arch/x86/hvm/svm/svm.c     |   27 +++++++++++++++++++--------
 2 files changed, 22 insertions(+), 9 deletions(-)

diff -r b45db6cdfa96 -r ccdea3259534 xen/arch/x86/hvm/svm/emulate.c
--- a/xen/arch/x86/hvm/svm/emulate.c    Thu Mar 20 12:17:57 2008 +0000
+++ b/xen/arch/x86/hvm/svm/emulate.c    Thu Mar 20 12:23:14 2008 +0000
@@ -434,7 +434,9 @@ int __get_instruction_length_from_list(s
     }
     else
     {
-        inst_copy_from_guest(buffer, svm_rip2pointer(v), MAX_INST_LEN);
+        if ( inst_copy_from_guest(buffer, svm_rip2pointer(v), MAX_INST_LEN)
+             != MAX_INST_LEN )
+            return 0;
         buf = buffer;
     }
 
diff -r b45db6cdfa96 -r ccdea3259534 xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c        Thu Mar 20 12:17:57 2008 +0000
+++ b/xen/arch/x86/hvm/svm/svm.c        Thu Mar 20 12:23:14 2008 +0000
@@ -1287,7 +1287,7 @@ static void svm_dr_access(struct vcpu *v
 }
 
 
-static void svm_get_prefix_info(struct vcpu *v, unsigned int dir, 
+static int svm_get_prefix_info(struct vcpu *v, unsigned int dir, 
                                 svm_segment_register_t **seg, 
                                 unsigned int *asize)
 {
@@ -1300,8 +1300,7 @@ static void svm_get_prefix_info(struct v
         != MAX_INST_LEN) 
     {
         gdprintk(XENLOG_ERR, "get guest instruction failed\n");
-        domain_crash(current->domain);
-        return;
+        return 0;
     }
 
     for (i = 0; i < MAX_INST_LEN; i++)
@@ -1359,8 +1358,9 @@ static void svm_get_prefix_info(struct v
         default:
             break;
         }
-        return;
-    }
+        break;
+    }
+    return 1;
 }
 
 
@@ -1395,7 +1395,8 @@ static int svm_get_io_address(
         isize --;
 
     if (isize > 1) 
-        svm_get_prefix_info(v, info.fields.type, &seg, &asize);
+        if ( !svm_get_prefix_info(v, info.fields.type, &seg, &asize) )
+            return 0;
 
     if (info.fields.type == IOREQ_WRITE)
     {
@@ -2006,7 +2007,10 @@ static int svm_cr_access(struct vcpu *v,
     enum instruction_index list_b[] = {INSTR_MOVCR2, INSTR_SMSW};
     enum instruction_index match;
 
-    inst_copy_from_guest(buffer, svm_rip2pointer(v), sizeof(buffer));
+    if ( inst_copy_from_guest(buffer, svm_rip2pointer(v), sizeof(buffer))
+         != sizeof buffer )
+        /* #PF will have been delivered if appropriate. */
+        return 0;
 
     /* get index to first actual instruction byte - as we will need to know 
        where the prefix lives later on */
@@ -2022,6 +2026,9 @@ static int svm_cr_access(struct vcpu *v,
         inst_len = __get_instruction_length_from_list(
             v, list_b, ARR_SIZE(list_b), &buffer[index], &match);
     }
+
+    if ( inst_len == 0 )
+        return 0;
 
     inst_len += index;
 
@@ -2286,7 +2293,7 @@ void svm_handle_invlpg(const short invlp
     if ( inst_copy_from_guest(opcode, svm_rip2pointer(v), length) < length )
     {
         gdprintk(XENLOG_ERR, "Error reading memory %d bytes\n", length);
-        goto crash;
+        return;
     }
 
     if (invlpga)
@@ -2487,6 +2494,8 @@ asmlinkage void svm_vmexit_handler(struc
             goto exit_and_crash;
         /* AMD Vol2, 15.11: INT3, INTO, BOUND intercepts do not update RIP. */
         inst_len = __get_instruction_length(v, INSTR_INT3, NULL);
+        if ( inst_len == 0 )
+            break;
         __update_guest_eip(vmcb, inst_len);
         domain_pause_for_debugger();
         break;
@@ -2556,6 +2565,8 @@ asmlinkage void svm_vmexit_handler(struc
 
     case VMEXIT_VMMCALL:
         inst_len = __get_instruction_length(v, INSTR_VMCALL, NULL);
+        if ( inst_len == 0 ) 
+            break;
         HVMTRACE_1D(VMMCALL, v, regs->eax);
         rc = hvm_do_hypercall(regs);
         if ( rc != HVM_HCALL_preempted )

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

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