direct-io.hg

changeset 11261:b61b7478b324

[HVM][SVM] Allow SVM to take advantage of flag_dr_dirty.

Signed-off-by: Travis Betak <travis.betak@amd.com>
author kaf24@localhost.localdomain
date Mon Aug 28 12:35:43 2006 +0100 (2006-08-28)
parents fab84f9c0ce6
children 0cecfb11b76b
files xen/arch/x86/hvm/svm/svm.c xen/arch/x86/hvm/svm/vmcb.c xen/include/asm-x86/hvm/svm/vmcb.h
line diff
     1.1 --- a/xen/arch/x86/hvm/svm/svm.c	Mon Aug 28 12:09:36 2006 +0100
     1.2 +++ b/xen/arch/x86/hvm/svm/svm.c	Mon Aug 28 12:35:43 2006 +0100
     1.3 @@ -403,6 +403,50 @@ static inline int long_mode_do_msr_write
     1.4      return 1;
     1.5  }
     1.6  
     1.7 +
     1.8 +#define loaddebug(_v,_reg) \
     1.9 +    __asm__ __volatile__ ("mov %0,%%db" #_reg : : "r" ((_v)->debugreg[_reg]))
    1.10 +#define savedebug(_v,_reg) \
    1.11 +    __asm__ __volatile__ ("mov %%db" #_reg ",%0" : : "r" ((_v)->debugreg[_reg]))
    1.12 +
    1.13 +
    1.14 +static inline void svm_save_dr(struct vcpu *v)
    1.15 +{
    1.16 +    if (v->arch.hvm_vcpu.flag_dr_dirty)
    1.17 +    {
    1.18 +        /* clear the DR dirty flag and re-enable intercepts for DR accesses */ 
    1.19 +        v->arch.hvm_vcpu.flag_dr_dirty = 0;
    1.20 +        v->arch.hvm_svm.vmcb->dr_intercepts = DR_INTERCEPT_ALL_WRITES;
    1.21 +
    1.22 +        savedebug(&v->arch.guest_context, 0);    
    1.23 +        savedebug(&v->arch.guest_context, 1);    
    1.24 +        savedebug(&v->arch.guest_context, 2);    
    1.25 +        savedebug(&v->arch.guest_context, 3);    
    1.26 +    }
    1.27 +}
    1.28 +
    1.29 +
    1.30 +static inline void __restore_debug_registers(struct vcpu *v)
    1.31 +{
    1.32 +    loaddebug(&v->arch.guest_context, 0);
    1.33 +    loaddebug(&v->arch.guest_context, 1);
    1.34 +    loaddebug(&v->arch.guest_context, 2);
    1.35 +    loaddebug(&v->arch.guest_context, 3);
    1.36 +}
    1.37 +
    1.38 +
    1.39 +static inline void svm_restore_dr(struct vcpu *v)
    1.40 +{
    1.41 +    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
    1.42 +
    1.43 +    if (!vmcb)
    1.44 +        return;
    1.45 +
    1.46 +    if (unlikely(vmcb->dr7 & 0xFF))
    1.47 +        __restore_debug_registers(v);
    1.48 +}
    1.49 +
    1.50 +
    1.51  static int svm_realmode(struct vcpu *v)
    1.52  {
    1.53      unsigned long cr0 = v->arch.hvm_svm.cpu_shadow_cr0;
    1.54 @@ -717,6 +761,7 @@ static void svm_freeze_time(struct vcpu 
    1.55  static void svm_ctxt_switch_from(struct vcpu *v)
    1.56  {
    1.57      svm_freeze_time(v);
    1.58 +    svm_save_dr(v);
    1.59  }
    1.60  
    1.61  static void svm_ctxt_switch_to(struct vcpu *v)
    1.62 @@ -732,6 +777,7 @@ static void svm_ctxt_switch_to(struct vc
    1.63      set_segment_register(es, 0);
    1.64      set_segment_register(ss, 0);
    1.65  #endif
    1.66 +    svm_restore_dr(v);
    1.67  }
    1.68  
    1.69  
    1.70 @@ -1183,55 +1229,16 @@ static inline void set_reg(unsigned int 
    1.71  }
    1.72                             
    1.73  
    1.74 -static void svm_dr_access (struct vcpu *v, unsigned int reg, unsigned int type,
    1.75 -                           struct cpu_user_regs *regs)
    1.76 +static void svm_dr_access(struct vcpu *v, struct cpu_user_regs *regs)
    1.77  {
    1.78 -    unsigned long *reg_p = 0;
    1.79 -    unsigned int gpreg = 0;
    1.80 -    unsigned long eip;
    1.81 -    int inst_len;
    1.82 -    int index;
    1.83 -    struct vmcb_struct *vmcb;
    1.84 -    u8 buffer[MAX_INST_LEN];
    1.85 -    u8 prefix = 0;
    1.86 -
    1.87 -    vmcb = v->arch.hvm_svm.vmcb;
    1.88 -    
    1.89 -    ASSERT(vmcb);
    1.90 -
    1.91 -    eip = vmcb->rip;
    1.92 -    inst_copy_from_guest(buffer, svm_rip2pointer(vmcb), sizeof(buffer));
    1.93 -    index = skip_prefix_bytes(buffer, sizeof(buffer));
    1.94 -    
    1.95 -    ASSERT(buffer[index+0] == 0x0f && (buffer[index+1] & 0xFD) == 0x21);
    1.96 -
    1.97 -    if (index > 0 && (buffer[index-1] & 0xF0) == 0x40)
    1.98 -        prefix = buffer[index-1];
    1.99 -
   1.100 -    gpreg = decode_src_reg(prefix, buffer[index + 2]);
   1.101 -    ASSERT(reg == decode_dest_reg(prefix, buffer[index + 2]));
   1.102 -
   1.103 -    HVM_DBG_LOG(DBG_LEVEL_1, "svm_dr_access : eip=%lx, reg=%d, gpreg = %x",
   1.104 -                eip, reg, gpreg);
   1.105 -
   1.106 -    reg_p = get_reg_p(gpreg, regs, vmcb);
   1.107 -        
   1.108 -    switch (type) 
   1.109 -    {
   1.110 -    case TYPE_MOV_TO_DR: 
   1.111 -        inst_len = __get_instruction_length(vmcb, INSTR_MOV2DR, buffer);
   1.112 -        v->arch.guest_context.debugreg[reg] = *reg_p;
   1.113 -        break;
   1.114 -    case TYPE_MOV_FROM_DR:
   1.115 -        inst_len = __get_instruction_length(vmcb, INSTR_MOVDR2, buffer);
   1.116 -        *reg_p = v->arch.guest_context.debugreg[reg];
   1.117 -        break;
   1.118 -    default:
   1.119 -        __hvm_bug(regs);
   1.120 -        break;
   1.121 -    }
   1.122 -    ASSERT(inst_len > 0);
   1.123 -    __update_guest_eip(vmcb, inst_len);
   1.124 +    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
   1.125 +
   1.126 +    v->arch.hvm_vcpu.flag_dr_dirty = 1;
   1.127 +
   1.128 +    __restore_debug_registers(v);
   1.129 +
   1.130 +    /* allow the guest full access to the debug registers */
   1.131 +    vmcb->dr_intercepts = 0;
   1.132  }
   1.133  
   1.134  
   1.135 @@ -2862,53 +2869,9 @@ asmlinkage void svm_vmexit_handler(struc
   1.136      case VMEXIT_CR8_WRITE:
   1.137          svm_cr_access(v, 8, TYPE_MOV_TO_CR, &regs);
   1.138          break;
   1.139 -
   1.140 -    case VMEXIT_DR0_READ:
   1.141 -        svm_dr_access(v, 0, TYPE_MOV_FROM_DR, &regs);
   1.142 -        break;
   1.143 -
   1.144 -    case VMEXIT_DR1_READ:
   1.145 -        svm_dr_access(v, 1, TYPE_MOV_FROM_DR, &regs);
   1.146 -        break;
   1.147 -
   1.148 -    case VMEXIT_DR2_READ:
   1.149 -        svm_dr_access(v, 2, TYPE_MOV_FROM_DR, &regs);
   1.150 -        break;
   1.151 -
   1.152 -    case VMEXIT_DR3_READ:
   1.153 -        svm_dr_access(v, 3, TYPE_MOV_FROM_DR, &regs);
   1.154 -        break;
   1.155 -
   1.156 -    case VMEXIT_DR6_READ:
   1.157 -        svm_dr_access(v, 6, TYPE_MOV_FROM_DR, &regs);
   1.158 -        break;
   1.159 -
   1.160 -    case VMEXIT_DR7_READ:
   1.161 -        svm_dr_access(v, 7, TYPE_MOV_FROM_DR, &regs);
   1.162 -        break;
   1.163 -
   1.164 -    case VMEXIT_DR0_WRITE:
   1.165 -        svm_dr_access(v, 0, TYPE_MOV_TO_DR, &regs);
   1.166 -        break;
   1.167 -
   1.168 -    case VMEXIT_DR1_WRITE:
   1.169 -        svm_dr_access(v, 1, TYPE_MOV_TO_DR, &regs);
   1.170 -        break;
   1.171 -
   1.172 -    case VMEXIT_DR2_WRITE:
   1.173 -        svm_dr_access(v, 2, TYPE_MOV_TO_DR, &regs);
   1.174 -        break;
   1.175 -
   1.176 -    case VMEXIT_DR3_WRITE:
   1.177 -        svm_dr_access(v, 3, TYPE_MOV_TO_DR, &regs);
   1.178 -        break;
   1.179 -
   1.180 -    case VMEXIT_DR6_WRITE:
   1.181 -        svm_dr_access(v, 6, TYPE_MOV_TO_DR, &regs);
   1.182 -        break;
   1.183 -
   1.184 -    case VMEXIT_DR7_WRITE:
   1.185 -        svm_dr_access(v, 7, TYPE_MOV_TO_DR, &regs);
   1.186 +	
   1.187 +    case VMEXIT_DR0_WRITE ... VMEXIT_DR7_WRITE:
   1.188 +        svm_dr_access(v, &regs);
   1.189          break;
   1.190  
   1.191      case VMEXIT_IOIO:
     2.1 --- a/xen/arch/x86/hvm/svm/vmcb.c	Mon Aug 28 12:09:36 2006 +0100
     2.2 +++ b/xen/arch/x86/hvm/svm/vmcb.c	Mon Aug 28 12:35:43 2006 +0100
     2.3 @@ -121,7 +121,7 @@ static int construct_vmcb_controls(struc
     2.4          GENERAL2_INTERCEPT_SKINIT | GENERAL2_INTERCEPT_RDTSCP;
     2.5  
     2.6      /* read or write all debug registers 0 - 15 */
     2.7 -    vmcb->dr_intercepts = 0;
     2.8 +    vmcb->dr_intercepts = DR_INTERCEPT_ALL_WRITES;
     2.9  
    2.10      /* RD/WR all control registers 0 - 15, but not read CR2 */
    2.11      vmcb->cr_intercepts = ~(CR_INTERCEPT_CR2_READ | CR_INTERCEPT_CR2_WRITE);
     3.1 --- a/xen/include/asm-x86/hvm/svm/vmcb.h	Mon Aug 28 12:09:36 2006 +0100
     3.2 +++ b/xen/include/asm-x86/hvm/svm/vmcb.h	Mon Aug 28 12:35:43 2006 +0100
     3.3 @@ -114,6 +114,51 @@ enum CRInterceptBits
     3.4      CR_INTERCEPT_CR15_WRITE = 1 << 31,
     3.5  };
     3.6  
     3.7 +
     3.8 +/* debug register intercepts */
     3.9 +enum DRInterceptBits
    3.10 +{
    3.11 +    DR_INTERCEPT_DR0_READ   = 1 << 0,
    3.12 +    DR_INTERCEPT_DR1_READ   = 1 << 1,
    3.13 +    DR_INTERCEPT_DR2_READ   = 1 << 2,
    3.14 +    DR_INTERCEPT_DR3_READ   = 1 << 3,
    3.15 +    DR_INTERCEPT_DR4_READ   = 1 << 4,
    3.16 +    DR_INTERCEPT_DR5_READ   = 1 << 5,
    3.17 +    DR_INTERCEPT_DR6_READ   = 1 << 6,
    3.18 +    DR_INTERCEPT_DR7_READ   = 1 << 7,
    3.19 +    DR_INTERCEPT_DR8_READ   = 1 << 8,
    3.20 +    DR_INTERCEPT_DR9_READ   = 1 << 9,
    3.21 +    DR_INTERCEPT_DR10_READ  = 1 << 10,
    3.22 +    DR_INTERCEPT_DR11_READ  = 1 << 11,
    3.23 +    DR_INTERCEPT_DR12_READ  = 1 << 12,
    3.24 +    DR_INTERCEPT_DR13_READ  = 1 << 13,
    3.25 +    DR_INTERCEPT_DR14_READ  = 1 << 14,
    3.26 +    DR_INTERCEPT_DR15_READ  = 1 << 15,
    3.27 +    DR_INTERCEPT_DR0_WRITE  = 1 << 16,
    3.28 +    DR_INTERCEPT_DR1_WRITE  = 1 << 17,
    3.29 +    DR_INTERCEPT_DR2_WRITE  = 1 << 18,
    3.30 +    DR_INTERCEPT_DR3_WRITE  = 1 << 19,
    3.31 +    DR_INTERCEPT_DR4_WRITE  = 1 << 20,
    3.32 +    DR_INTERCEPT_DR5_WRITE  = 1 << 21,
    3.33 +    DR_INTERCEPT_DR6_WRITE  = 1 << 22,
    3.34 +    DR_INTERCEPT_DR7_WRITE  = 1 << 23,
    3.35 +    DR_INTERCEPT_DR8_WRITE  = 1 << 24,
    3.36 +    DR_INTERCEPT_DR9_WRITE  = 1 << 25,
    3.37 +    DR_INTERCEPT_DR10_WRITE = 1 << 26,
    3.38 +    DR_INTERCEPT_DR11_WRITE = 1 << 27,
    3.39 +    DR_INTERCEPT_DR12_WRITE = 1 << 28,
    3.40 +    DR_INTERCEPT_DR13_WRITE = 1 << 29,
    3.41 +    DR_INTERCEPT_DR14_WRITE = 1 << 30,
    3.42 +    DR_INTERCEPT_DR15_WRITE = 1 << 31,
    3.43 +};
    3.44 +
    3.45 +/* for lazy save/restore we'd like to intercept all DR writes */
    3.46 +#define DR_INTERCEPT_ALL_WRITES \
    3.47 +    (DR_INTERCEPT_DR0_WRITE|DR_INTERCEPT_DR1_WRITE|DR_INTERCEPT_DR2_WRITE \
    3.48 +    |DR_INTERCEPT_DR3_WRITE|DR_INTERCEPT_DR4_WRITE|DR_INTERCEPT_DR5_WRITE \
    3.49 +    |DR_INTERCEPT_DR6_WRITE|DR_INTERCEPT_DR7_WRITE) 
    3.50 +
    3.51 +
    3.52  enum VMEXIT_EXITCODE
    3.53  {
    3.54      /* control register read exitcodes */