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

[Xen-changelog] [xen-unstable] [HVM][SVM] Allow SVM to take advantage of flag_dr_dirty.



# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxxx
# Node ID b61b7478b3245daac1d76a2eadb6f33123aec85c
# Parent  fab84f9c0ce6d5d1fb89b31ef071148f781ae5a6
[HVM][SVM] Allow SVM to take advantage of flag_dr_dirty.

Signed-off-by: Travis Betak <travis.betak@xxxxxxx>
---
 xen/arch/x86/hvm/svm/svm.c         |  155 ++++++++++++++-----------------------
 xen/arch/x86/hvm/svm/vmcb.c        |    2 
 xen/include/asm-x86/hvm/svm/vmcb.h |   45 ++++++++++
 3 files changed, 105 insertions(+), 97 deletions(-)

diff -r fab84f9c0ce6 -r b61b7478b324 xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c        Mon Aug 28 12:09:36 2006 +0100
+++ b/xen/arch/x86/hvm/svm/svm.c        Mon Aug 28 12:35:43 2006 +0100
@@ -403,6 +403,50 @@ static inline int long_mode_do_msr_write
     return 1;
 }
 
+
+#define loaddebug(_v,_reg) \
+    __asm__ __volatile__ ("mov %0,%%db" #_reg : : "r" ((_v)->debugreg[_reg]))
+#define savedebug(_v,_reg) \
+    __asm__ __volatile__ ("mov %%db" #_reg ",%0" : : "r" 
((_v)->debugreg[_reg]))
+
+
+static inline void svm_save_dr(struct vcpu *v)
+{
+    if (v->arch.hvm_vcpu.flag_dr_dirty)
+    {
+        /* clear the DR dirty flag and re-enable intercepts for DR accesses */ 
+        v->arch.hvm_vcpu.flag_dr_dirty = 0;
+        v->arch.hvm_svm.vmcb->dr_intercepts = DR_INTERCEPT_ALL_WRITES;
+
+        savedebug(&v->arch.guest_context, 0);    
+        savedebug(&v->arch.guest_context, 1);    
+        savedebug(&v->arch.guest_context, 2);    
+        savedebug(&v->arch.guest_context, 3);    
+    }
+}
+
+
+static inline void __restore_debug_registers(struct vcpu *v)
+{
+    loaddebug(&v->arch.guest_context, 0);
+    loaddebug(&v->arch.guest_context, 1);
+    loaddebug(&v->arch.guest_context, 2);
+    loaddebug(&v->arch.guest_context, 3);
+}
+
+
+static inline void svm_restore_dr(struct vcpu *v)
+{
+    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+
+    if (!vmcb)
+        return;
+
+    if (unlikely(vmcb->dr7 & 0xFF))
+        __restore_debug_registers(v);
+}
+
+
 static int svm_realmode(struct vcpu *v)
 {
     unsigned long cr0 = v->arch.hvm_svm.cpu_shadow_cr0;
@@ -717,6 +761,7 @@ static void svm_ctxt_switch_from(struct 
 static void svm_ctxt_switch_from(struct vcpu *v)
 {
     svm_freeze_time(v);
+    svm_save_dr(v);
 }
 
 static void svm_ctxt_switch_to(struct vcpu *v)
@@ -732,6 +777,7 @@ static void svm_ctxt_switch_to(struct vc
     set_segment_register(es, 0);
     set_segment_register(ss, 0);
 #endif
+    svm_restore_dr(v);
 }
 
 
@@ -1183,55 +1229,16 @@ static inline void set_reg(unsigned int 
 }
                            
 
-static void svm_dr_access (struct vcpu *v, unsigned int reg, unsigned int type,
-                           struct cpu_user_regs *regs)
-{
-    unsigned long *reg_p = 0;
-    unsigned int gpreg = 0;
-    unsigned long eip;
-    int inst_len;
-    int index;
-    struct vmcb_struct *vmcb;
-    u8 buffer[MAX_INST_LEN];
-    u8 prefix = 0;
-
-    vmcb = v->arch.hvm_svm.vmcb;
-    
-    ASSERT(vmcb);
-
-    eip = vmcb->rip;
-    inst_copy_from_guest(buffer, svm_rip2pointer(vmcb), sizeof(buffer));
-    index = skip_prefix_bytes(buffer, sizeof(buffer));
-    
-    ASSERT(buffer[index+0] == 0x0f && (buffer[index+1] & 0xFD) == 0x21);
-
-    if (index > 0 && (buffer[index-1] & 0xF0) == 0x40)
-        prefix = buffer[index-1];
-
-    gpreg = decode_src_reg(prefix, buffer[index + 2]);
-    ASSERT(reg == decode_dest_reg(prefix, buffer[index + 2]));
-
-    HVM_DBG_LOG(DBG_LEVEL_1, "svm_dr_access : eip=%lx, reg=%d, gpreg = %x",
-                eip, reg, gpreg);
-
-    reg_p = get_reg_p(gpreg, regs, vmcb);
-        
-    switch (type) 
-    {
-    case TYPE_MOV_TO_DR: 
-        inst_len = __get_instruction_length(vmcb, INSTR_MOV2DR, buffer);
-        v->arch.guest_context.debugreg[reg] = *reg_p;
-        break;
-    case TYPE_MOV_FROM_DR:
-        inst_len = __get_instruction_length(vmcb, INSTR_MOVDR2, buffer);
-        *reg_p = v->arch.guest_context.debugreg[reg];
-        break;
-    default:
-        __hvm_bug(regs);
-        break;
-    }
-    ASSERT(inst_len > 0);
-    __update_guest_eip(vmcb, inst_len);
+static void svm_dr_access(struct vcpu *v, struct cpu_user_regs *regs)
+{
+    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+
+    v->arch.hvm_vcpu.flag_dr_dirty = 1;
+
+    __restore_debug_registers(v);
+
+    /* allow the guest full access to the debug registers */
+    vmcb->dr_intercepts = 0;
 }
 
 
@@ -2862,53 +2869,9 @@ asmlinkage void svm_vmexit_handler(struc
     case VMEXIT_CR8_WRITE:
         svm_cr_access(v, 8, TYPE_MOV_TO_CR, &regs);
         break;
-
-    case VMEXIT_DR0_READ:
-        svm_dr_access(v, 0, TYPE_MOV_FROM_DR, &regs);
-        break;
-
-    case VMEXIT_DR1_READ:
-        svm_dr_access(v, 1, TYPE_MOV_FROM_DR, &regs);
-        break;
-
-    case VMEXIT_DR2_READ:
-        svm_dr_access(v, 2, TYPE_MOV_FROM_DR, &regs);
-        break;
-
-    case VMEXIT_DR3_READ:
-        svm_dr_access(v, 3, TYPE_MOV_FROM_DR, &regs);
-        break;
-
-    case VMEXIT_DR6_READ:
-        svm_dr_access(v, 6, TYPE_MOV_FROM_DR, &regs);
-        break;
-
-    case VMEXIT_DR7_READ:
-        svm_dr_access(v, 7, TYPE_MOV_FROM_DR, &regs);
-        break;
-
-    case VMEXIT_DR0_WRITE:
-        svm_dr_access(v, 0, TYPE_MOV_TO_DR, &regs);
-        break;
-
-    case VMEXIT_DR1_WRITE:
-        svm_dr_access(v, 1, TYPE_MOV_TO_DR, &regs);
-        break;
-
-    case VMEXIT_DR2_WRITE:
-        svm_dr_access(v, 2, TYPE_MOV_TO_DR, &regs);
-        break;
-
-    case VMEXIT_DR3_WRITE:
-        svm_dr_access(v, 3, TYPE_MOV_TO_DR, &regs);
-        break;
-
-    case VMEXIT_DR6_WRITE:
-        svm_dr_access(v, 6, TYPE_MOV_TO_DR, &regs);
-        break;
-
-    case VMEXIT_DR7_WRITE:
-        svm_dr_access(v, 7, TYPE_MOV_TO_DR, &regs);
+       
+    case VMEXIT_DR0_WRITE ... VMEXIT_DR7_WRITE:
+        svm_dr_access(v, &regs);
         break;
 
     case VMEXIT_IOIO:
diff -r fab84f9c0ce6 -r b61b7478b324 xen/arch/x86/hvm/svm/vmcb.c
--- a/xen/arch/x86/hvm/svm/vmcb.c       Mon Aug 28 12:09:36 2006 +0100
+++ b/xen/arch/x86/hvm/svm/vmcb.c       Mon Aug 28 12:35:43 2006 +0100
@@ -121,7 +121,7 @@ static int construct_vmcb_controls(struc
         GENERAL2_INTERCEPT_SKINIT | GENERAL2_INTERCEPT_RDTSCP;
 
     /* read or write all debug registers 0 - 15 */
-    vmcb->dr_intercepts = 0;
+    vmcb->dr_intercepts = DR_INTERCEPT_ALL_WRITES;
 
     /* RD/WR all control registers 0 - 15, but not read CR2 */
     vmcb->cr_intercepts = ~(CR_INTERCEPT_CR2_READ | CR_INTERCEPT_CR2_WRITE);
diff -r fab84f9c0ce6 -r b61b7478b324 xen/include/asm-x86/hvm/svm/vmcb.h
--- a/xen/include/asm-x86/hvm/svm/vmcb.h        Mon Aug 28 12:09:36 2006 +0100
+++ b/xen/include/asm-x86/hvm/svm/vmcb.h        Mon Aug 28 12:35:43 2006 +0100
@@ -113,6 +113,51 @@ enum CRInterceptBits
     CR_INTERCEPT_CR14_WRITE = 1 << 30,
     CR_INTERCEPT_CR15_WRITE = 1 << 31,
 };
+
+
+/* debug register intercepts */
+enum DRInterceptBits
+{
+    DR_INTERCEPT_DR0_READ   = 1 << 0,
+    DR_INTERCEPT_DR1_READ   = 1 << 1,
+    DR_INTERCEPT_DR2_READ   = 1 << 2,
+    DR_INTERCEPT_DR3_READ   = 1 << 3,
+    DR_INTERCEPT_DR4_READ   = 1 << 4,
+    DR_INTERCEPT_DR5_READ   = 1 << 5,
+    DR_INTERCEPT_DR6_READ   = 1 << 6,
+    DR_INTERCEPT_DR7_READ   = 1 << 7,
+    DR_INTERCEPT_DR8_READ   = 1 << 8,
+    DR_INTERCEPT_DR9_READ   = 1 << 9,
+    DR_INTERCEPT_DR10_READ  = 1 << 10,
+    DR_INTERCEPT_DR11_READ  = 1 << 11,
+    DR_INTERCEPT_DR12_READ  = 1 << 12,
+    DR_INTERCEPT_DR13_READ  = 1 << 13,
+    DR_INTERCEPT_DR14_READ  = 1 << 14,
+    DR_INTERCEPT_DR15_READ  = 1 << 15,
+    DR_INTERCEPT_DR0_WRITE  = 1 << 16,
+    DR_INTERCEPT_DR1_WRITE  = 1 << 17,
+    DR_INTERCEPT_DR2_WRITE  = 1 << 18,
+    DR_INTERCEPT_DR3_WRITE  = 1 << 19,
+    DR_INTERCEPT_DR4_WRITE  = 1 << 20,
+    DR_INTERCEPT_DR5_WRITE  = 1 << 21,
+    DR_INTERCEPT_DR6_WRITE  = 1 << 22,
+    DR_INTERCEPT_DR7_WRITE  = 1 << 23,
+    DR_INTERCEPT_DR8_WRITE  = 1 << 24,
+    DR_INTERCEPT_DR9_WRITE  = 1 << 25,
+    DR_INTERCEPT_DR10_WRITE = 1 << 26,
+    DR_INTERCEPT_DR11_WRITE = 1 << 27,
+    DR_INTERCEPT_DR12_WRITE = 1 << 28,
+    DR_INTERCEPT_DR13_WRITE = 1 << 29,
+    DR_INTERCEPT_DR14_WRITE = 1 << 30,
+    DR_INTERCEPT_DR15_WRITE = 1 << 31,
+};
+
+/* for lazy save/restore we'd like to intercept all DR writes */
+#define DR_INTERCEPT_ALL_WRITES \
+    (DR_INTERCEPT_DR0_WRITE|DR_INTERCEPT_DR1_WRITE|DR_INTERCEPT_DR2_WRITE \
+    |DR_INTERCEPT_DR3_WRITE|DR_INTERCEPT_DR4_WRITE|DR_INTERCEPT_DR5_WRITE \
+    |DR_INTERCEPT_DR6_WRITE|DR_INTERCEPT_DR7_WRITE) 
+
 
 enum VMEXIT_EXITCODE
 {

_______________________________________________
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®.