WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] SVM patch to add 64bit hv support.

# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID a376bab39768941c46cb57f3a3ce2dca2edb4173
# Parent  a66763eb86fee0a215712245be4f49e871d74ac4
SVM patch to add 64bit hv support.
This patch only modifies svm files.
Tested with c/s 9015 with 32bit hv using UP Dom0, with UP linux and
winxpsp1 unmodified guests.
Tested with c/s 9015 with 64bit hv using UP Dom0, with 32bit and 64bit
UP linux and 32bit winxpsp1.

Signed-off-by: Tom Woller <thomas.woller@xxxxxxx>

diff -r a66763eb86fe -r a376bab39768 xen/arch/x86/hvm/svm/emulate.c
--- a/xen/arch/x86/hvm/svm/emulate.c    Tue Feb 28 18:00:15 2006
+++ b/xen/arch/x86/hvm/svm/emulate.c    Tue Feb 28 21:57:38 2006
@@ -86,7 +86,7 @@
     case 0x7:
         value = regs->edi;
         break;
-#if X86_64
+#if __x86_64__
     case 0x8:
         value = regs->r8;
         break;
@@ -318,20 +318,14 @@
 
 
 /* Get the register/mode number of src register in ModRM register. */
-unsigned int decode_dest_reg(u8 m)
-{
-#if __x86_64__
-    ASSERT(0); /* Need to adjust for REX prefix if applicable */
-#endif
-    return (m >> 3) & 7;
-}
-
-unsigned int decode_src_reg(u8 m)
-{
-#if __x86_64__
-    ASSERT(0); /* Need to adjust for REX prefix if applicable */
-#endif
-    return m & 7;
+unsigned int decode_dest_reg(u8 prefix, u8 m)
+{
+    return DECODE_MODRM_REG(prefix, m);
+}
+
+unsigned int decode_src_reg(u8 prefix, u8 m)
+{
+    return DECODE_MODRM_RM(prefix, m);
 }
 
 
@@ -431,7 +425,7 @@
  * The caller can either pass a NULL pointer to the guest_eip_buf, or a pointer
  * to enough bytes to satisfy the instruction including prefix bytes.
  */
-unsigned int __get_instruction_length_from_list(struct vmcb_struct *vmcb,
+int __get_instruction_length_from_list(struct vmcb_struct *vmcb,
         enum instruction_index *list, unsigned int list_count, 
         u8 *guest_eip_buf, enum instruction_index *match)
 {
diff -r a66763eb86fe -r a376bab39768 xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c        Tue Feb 28 18:00:15 2006
+++ b/xen/arch/x86/hvm/svm/svm.c        Tue Feb 28 21:57:38 2006
@@ -164,7 +164,7 @@
 }
 
 static inline void svm_inject_exception(struct vmcb_struct *vmcb, 
-                                        int trap, int error_code)
+                                        int trap, int ev, int error_code)
 {
     eventinj_t event;
 
@@ -172,7 +172,7 @@
     event.fields.v = 1;
     event.fields.type = EVENTTYPE_EXCEPTION;
     event.fields.vector = trap;
-    event.fields.ev = 1;
+    event.fields.ev = ev;
     event.fields.errorcode = error_code;
 
     ASSERT(vmcb->eventinj.fields.v == 0);
@@ -237,61 +237,16 @@
 }
 
 #ifdef __x86_64__
-static struct svm_msr_state percpu_msr[NR_CPUS];
-
-static u32 msr_data_index[VMX_MSR_COUNT] =
-{
-    MSR_LSTAR, MSR_STAR, MSR_CSTAR,
-    MSR_SYSCALL_MASK, MSR_EFER,
-};
 
 void svm_save_segments(struct vcpu *v)
 {
-    rdmsrl(MSR_SHADOW_GS_BASE, v->arch.hvm_svm.msr_content.shadow_gs);
-}
-
-/*
- * To avoid MSR save/restore at every VM exit/entry time, we restore
- * the x86_64 specific MSRs at domain switch time. Since those MSRs are
- * are not modified once set for generic domains, we don't save them,
- * but simply reset them to the values set at percpu_traps_init().
- */
+}
 void svm_load_msrs(void)
 {
-    struct svm_msr_state *host_state = &percpu_msr[smp_processor_id()];
-    int i;
-
-    while ( host_state->flags )
-    {
-        i = find_first_set_bit(host_state->flags);
-        wrmsrl(msr_data_index[i], host_state->msr_items[i]);
-        clear_bit(i, &host_state->flags);
-    }
-}
-
-static void svm_save_init_msrs(void)
-{
-    struct svm_msr_state *host_state = &percpu_msr[smp_processor_id()];
-    int i;
-
-    for ( i = 0; i < SVM_MSR_COUNT; i++ )
-        rdmsrl(msr_data_index[i], host_state->msr_items[i]);
-}
-
-#define CASE_READ_MSR(address)                               \
-    case MSR_ ## address:                                    \
-    msr_content = msr->msr_items[SVM_INDEX_MSR_ ## address]; \
-    break
-
-#define CASE_WRITE_MSR(address)                              \
-    case MSR_ ## address:                                    \
-    msr->msr_items[SVM_INDEX_MSR_ ## address] = msr_content; \
-    if (!test_bit(SVM_INDEX_MSR_ ## address, &msr->flags))   \
-    {                                                        \
-        set_bit(SVM_INDEX_MSR_ ## address, &msr->flags);     \
-    }                                                        \
-    break
-
+}
+void svm_restore_msrs(struct vcpu *v)
+{
+}
 
 #define IS_CANO_ADDRESS(add) 1
 
@@ -299,47 +254,45 @@
 {
     u64 msr_content = 0;
     struct vcpu *vc = current;
-    struct svm_msr_state *msr = &vc->arch.hvm_svm.msr_content;
+    //    struct svm_msr_state *msr = &vc->arch.hvm_svm.msr_content;
     struct vmcb_struct *vmcb = vc->arch.hvm_svm.vmcb;
 
     switch (regs->ecx)
     {
     case MSR_EFER:
-        msr_content = msr->msr_items[SVM_INDEX_MSR_EFER];
-        HVM_DBG_LOG(DBG_LEVEL_2, "EFER msr_content %llx\n", 
-                (unsigned long long)msr_content);
-
-        if (test_bit(SVM_CPU_STATE_LME_ENABLED, &vc->arch.hvm_svm.cpu_state))
-            msr_content |= 1 << _EFER_LME;
-
-        if (SVM_LONG_GUEST(vc))
-            msr_content |= 1 << _EFER_LMA;
-
+        // msr_content = msr->msr_items[SVM_INDEX_MSR_EFER];
+        msr_content = vmcb->efer;      
+        msr_content &= ~EFER_SVME;
         break;
 
     case MSR_FS_BASE:
-        if (!(SVM_LONG_GUEST(vc)))
-            /* XXX should it be GP fault */
-            domain_crash_synchronous();
-        
         msr_content = vmcb->fs.base;
         break;
 
     case MSR_GS_BASE:
-        if (!(SVM_LONG_GUEST(vc)))
-            domain_crash_synchronous();
-
         msr_content = vmcb->gs.base;
         break;
 
     case MSR_SHADOW_GS_BASE:
-        msr_content = msr->shadow_gs;
-        break;
-
-    CASE_READ_MSR(STAR);
-    CASE_READ_MSR(LSTAR);
-    CASE_READ_MSR(CSTAR);
-    CASE_READ_MSR(SYSCALL_MASK);
+        msr_content = vmcb->kerngsbase;
+        break;
+
+    case MSR_STAR:
+         msr_content = vmcb->star;
+         break;
+ 
+    case MSR_LSTAR:
+         msr_content = vmcb->lstar;
+         break;
+ 
+    case MSR_CSTAR:
+         msr_content = vmcb->cstar;
+         break;
+ 
+    case MSR_SYSCALL_MASK:
+         msr_content = vmcb->sfmask;
+         break;
+
     default:
         return 0;
     }
@@ -356,8 +309,6 @@
 {
     u64 msr_content = regs->eax | ((u64)regs->edx << 32); 
     struct vcpu *vc = current;
-    struct svm_msr_state *msr = &vc->arch.hvm_svm.msr_content;
-    struct svm_msr_state *host_state = &percpu_msr[smp_processor_id()];
     struct vmcb_struct *vmcb = vc->arch.hvm_svm.vmcb;
 
     HVM_DBG_LOG(DBG_LEVEL_1, "mode_do_msr_write msr %lx msr_content %lx\n", 
@@ -373,26 +324,20 @@
                     || !test_bit(SVM_CPU_STATE_PAE_ENABLED,
                                  &vc->arch.hvm_svm.cpu_state))
             {
-                svm_inject_exception(vmcb, TRAP_gp_fault, 0);
+                svm_inject_exception(vmcb, TRAP_gp_fault, 1, 0);
             }
         }
 
         if (msr_content & EFER_LME)
             set_bit(SVM_CPU_STATE_LME_ENABLED, &vc->arch.hvm_svm.cpu_state);
 
+        /* We have already recorded that we want LME, so it will be set 
+         * next time CR0 gets updated. So we clear that bit and continue.
+         */
+        if ((msr_content ^ vmcb->efer) & EFER_LME)
+            msr_content &= ~EFER_LME;  
         /* No update for LME/LMA since it have no effect */
-        msr->msr_items[SVM_INDEX_MSR_EFER] = msr_content;
-        if (msr_content & ~(EFER_LME | EFER_LMA))
-        {
-            msr->msr_items[SVM_INDEX_MSR_EFER] = msr_content;
-            if (!test_bit(SVM_INDEX_MSR_EFER, &msr->flags))
-            { 
-                rdmsrl(MSR_EFER, host_state->msr_items[SVM_INDEX_MSR_EFER]);
-                set_bit(SVM_INDEX_MSR_EFER, &host_state->flags);
-                set_bit(SVM_INDEX_MSR_EFER, &msr->flags);  
-                wrmsrl(MSR_EFER, msr_content);
-            }
-        }
+        vmcb->efer = msr_content | EFER_SVME;
         break;
 
     case MSR_FS_BASE:
@@ -403,63 +348,42 @@
         if (!IS_CANO_ADDRESS(msr_content))
         {
             HVM_DBG_LOG(DBG_LEVEL_1, "Not cano address of msr write\n");
-            svm_inject_exception(vmcb, TRAP_gp_fault, 0);
+            svm_inject_exception(vmcb, TRAP_gp_fault, 1, 0);
         }
 
         if (regs->ecx == MSR_FS_BASE)
-           vmcb->fs.base = msr_content;
+            vmcb->fs.base = msr_content;
         else 
-           vmcb->gs.base = msr_content;
+            vmcb->gs.base = msr_content;
         break;
 
     case MSR_SHADOW_GS_BASE:
-        if (!(SVM_LONG_GUEST(vc)))
-            domain_crash_synchronous();
-
-        vc->arch.hvm_svm.msr_content.shadow_gs = msr_content;
-        wrmsrl(MSR_SHADOW_GS_BASE, msr_content);
-        break;
-
-    CASE_WRITE_MSR(STAR);
-    CASE_WRITE_MSR(LSTAR);
-    CASE_WRITE_MSR(CSTAR);
-    CASE_WRITE_MSR(SYSCALL_MASK);
+         vmcb->kerngsbase = msr_content;
+         break;
+ 
+    case MSR_STAR:
+         vmcb->star = msr_content;
+         break;
+ 
+    case MSR_LSTAR:
+         vmcb->lstar = msr_content;
+         break;
+ 
+    case MSR_CSTAR:
+         vmcb->cstar = msr_content;
+         break;
+ 
+    case MSR_SYSCALL_MASK:
+         vmcb->sfmask = msr_content;
+         break;
+
     default:
         return 0;
     }
     return 1;
 }
 
-void
-svm_restore_msrs(struct vcpu *v)
-{
-    int i = 0;
-    struct svm_msr_state *guest_state;
-    struct svm_msr_state *host_state;
-    unsigned long guest_flags;
-
-    guest_state = &v->arch.hvm_svm.msr_content;;
-    host_state = &percpu_msr[smp_processor_id()];
-
-    wrmsrl(MSR_SHADOW_GS_BASE, guest_state->shadow_gs);
-    guest_flags = guest_state->flags;
-    if (!guest_flags)
-        return;
-
-    while (guest_flags){
-        i = find_first_set_bit(guest_flags);
-
-        HVM_DBG_LOG(DBG_LEVEL_2,
-                    "restore guest's index %d msr %lx with %lx\n",
-                    i, (unsigned long) msr_data_index[i], (unsigned long) 
guest_state->msr_items[i]);
-        set_bit(i, &host_state->flags);
-        wrmsrl(msr_data_index[i], guest_state->msr_items[i]);
-        clear_bit(i, &guest_flags);
-    }
-}
 #else
-#define        svm_save_init_msrs()    ((void)0)
-
 static inline int long_mode_do_msr_read(struct cpu_user_regs *regs)
 {
     return 0;
@@ -497,9 +421,28 @@
 {
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
     unsigned long cr0 = vmcb->cr0, eflags = vmcb->rflags, mode;
-
-    mode = (eflags & X86_EFLAGS_VM) || !(cr0 & X86_CR0_PE) ? 2 : 4;
+    /* check which operating mode the guest is running */
+    if( vmcb->efer & EFER_LMA )
+        mode = vmcb->cs.attributes.fields.l ? 8 : 4;
+    else
+        mode = (eflags & X86_EFLAGS_VM) || !(cr0 & X86_CR0_PE) ? 2 : 4;
     return svm_instrlen(guest_cpu_user_regs(), mode);
+}
+
+unsigned long svm_get_ctrl_reg(struct vcpu *v, unsigned int num)
+{
+    switch ( num )
+    {
+    case 0:
+        return v->arch.hvm_svm.cpu_shadow_cr0;
+    case 2:
+        return v->arch.hvm_svm.cpu_cr2;
+    case 3:
+        return v->arch.hvm_svm.cpu_cr3;
+    default:
+        BUG();
+    }
+    return 0;                   /* dummy */
 }
 
 int start_svm(void)
@@ -519,8 +462,6 @@
     asidpool_init(smp_processor_id());    
     printk("AMD SVM Extension is enabled for cpu %d.\n", smp_processor_id());
     
-    svm_save_init_msrs();
-
     /* Setup HVM interfaces */
     hvm_funcs.disable = stop_svm;
 
@@ -542,6 +483,7 @@
     hvm_funcs.realmode = svm_realmode;
     hvm_funcs.paging_enabled = svm_paging_enabled;
     hvm_funcs.instruction_length = svm_instruction_length;
+    hvm_funcs.get_guest_ctrl_reg = svm_get_ctrl_reg;
 
     hvm_enabled = 1;    
 
@@ -631,8 +573,17 @@
 }
 
 #if defined (__x86_64__)
-void svm_store_cpu_user_regs(struct cpu_user_regs *regs, struct vcpu *c )
-{
+void svm_store_cpu_user_regs(struct cpu_user_regs *regs, struct vcpu *v )
+{
+    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+
+    regs->rip    = vmcb->rip;
+    regs->rsp    = vmcb->rsp;
+    regs->rflags = vmcb->rflags;
+    regs->cs     = vmcb->cs.sel;
+    regs->ds     = vmcb->ds.sel;
+    regs->es     = vmcb->es.sel;
+    regs->ss     = vmcb->ss.sel;
 }
 #elif defined (__i386__)
 void svm_store_cpu_user_regs(struct cpu_user_regs *regs, struct vcpu *v)
@@ -882,9 +833,9 @@
        /* No support for APIC */
         if (!hvm_apic_support(v->domain) && gpa >= 0xFEC00000)
         { 
-            unsigned long inst_len;
-           inst_len = svm_instruction_length(v);
-            if (inst_len == (unsigned long)-1)
+            int inst_len;
+            inst_len = svm_instruction_length(v);
+            if (inst_len == -1)
             {
                 printf("%s: INST_LEN - Unable to decode properly.\n", 
__func__);
                 domain_crash_synchronous();
@@ -936,6 +887,14 @@
 
     eip = vmcb->rip;
     error_code = vmcb->exitinfo1;
+
+    if (vmcb->idtr.limit == 0) {
+        printf("Huh? We got a GP Fault with an invalid IDTR!\n");
+        svm_dump_vmcb(__func__, vmcb);
+        svm_dump_regs(__func__, regs);
+        svm_dump_inst(vmcb->rip); 
+        __hvm_bug(regs);
+    }
 
     HVM_DBG_LOG(DBG_LEVEL_1,
                 "svm_general_protection_fault: eip = %lx, erro_code = %lx",
@@ -949,7 +908,7 @@
 
     
     /* Reflect it back into the guest */
-    svm_inject_exception(vmcb, TRAP_gp_fault, error_code);
+    svm_inject_exception(vmcb, TRAP_gp_fault, 1, error_code);
 }
 
 /* Reserved bits: [31:14], [12:1] */
@@ -961,7 +920,7 @@
     unsigned int eax, ebx, ecx, edx;
     unsigned long eip;
     struct vcpu *v = current;
-    unsigned int inst_len;
+    int inst_len;
 
     ASSERT(vmcb);
 
@@ -978,8 +937,10 @@
 
     if (input == 1)
     {
+#ifndef __x86_64__
         if ( hvm_apic_support(v->domain) &&
                 !vlapic_global_enabled((VLAPIC(v))) )
+#endif
             clear_bit(X86_FEATURE_APIC, &edx);
            
 #if CONFIG_PAGING_LEVELS < 3
@@ -1019,6 +980,7 @@
             eip, input, eax, ebx, ecx, edx);
 
     inst_len = __get_instruction_length(vmcb, INSTR_CPUID, NULL);
+    ASSERT(inst_len > 0);
     __update_guest_eip(vmcb, inst_len);
 }
 
@@ -1111,9 +1073,11 @@
     unsigned long *reg_p = 0;
     unsigned int gpreg = 0;
     unsigned long eip;
-    unsigned int inst_len; 
+    int inst_len; 
+    int index;
     struct vmcb_struct *vmcb;
     u8 buffer[MAX_INST_LEN];
+    u8 prefix = 0;
 
     vmcb = v->arch.hvm_svm.vmcb;
     
@@ -1121,13 +1085,15 @@
 
     eip = vmcb->rip;
     inst_copy_from_guest(buffer, svm_rip2pointer(vmcb), sizeof(buffer));
-
-    ASSERT(buffer[0] == 0x0f && (buffer[1] & 0xFD) == 0x21);
-
-    gpreg = decode_src_reg(buffer[2]);
-#if DEBUG
-    ASSERT(reg == decode_dest_reg(buffer[2]));
-#endif
+    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);
@@ -1148,6 +1114,7 @@
         __hvm_bug(regs);
         break;
     }
+    ASSERT(inst_len > 0);
     __update_guest_eip(vmcb, inst_len);
 }
 
@@ -1405,7 +1372,7 @@
                     &v->arch.hvm_svm.cpu_state))
         {
             HVM_DBG_LOG(DBG_LEVEL_1, "Enable paging before PAE enable\n");
-            svm_inject_exception(vmcb, TRAP_gp_fault, 0);
+            svm_inject_exception(vmcb, TRAP_gp_fault, 1, 0);
         }
 
         if (test_bit(SVM_CPU_STATE_LME_ENABLED, &v->arch.hvm_svm.cpu_state))
@@ -1468,7 +1435,7 @@
      */
     if ((value & X86_CR0_PE) == 0) {
        if (value & X86_CR0_PG) {
-            svm_inject_exception(vmcb, TRAP_gp_fault, 0);
+            svm_inject_exception(vmcb, TRAP_gp_fault, 1, 0);
             return 0;
         }
 
@@ -1503,7 +1470,7 @@
         value = (unsigned long) v->arch.hvm_svm.cpu_cr3;
         break;
     case 4:
-        value = vmcb->cr4;
+        value = (unsigned long) v->arch.hvm_svm.cpu_shadow_cr4;
         break;
     case 8:
 #if 0
@@ -1602,12 +1569,19 @@
 
     case 4:         
         /* CR4 */
-        if (value & X86_CR4_PAE)
-            __hvm_bug(regs);    /* not implemented */
-
-        old_cr = vmcb->cr4;
-        
-        vmcb->cr4 = value;
+        if (value & X86_CR4_PAE) {
+            set_bit(SVM_CPU_STATE_PAE_ENABLED, &v->arch.hvm_svm.cpu_state);
+        } else {
+            if (test_bit(SVM_CPU_STATE_LMA_ENABLED,
+                         &v->arch.hvm_svm.cpu_state)) {
+                svm_inject_exception(vmcb, TRAP_gp_fault, 1, 0);
+            }
+            clear_bit(SVM_CPU_STATE_PAE_ENABLED, &v->arch.hvm_svm.cpu_state);
+        }
+
+        old_cr = v->arch.hvm_svm.cpu_shadow_cr4;
+        v->arch.hvm_svm.cpu_shadow_cr4 = value;
+        vmcb->cr4 = value | SVM_CR4_HOST_MASK;
   
         /*
          * Writing to CR4 to modify the PSE, PGE, or PAE flag invalidates
@@ -1636,10 +1610,12 @@
         struct cpu_user_regs *regs)
 {
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
-    unsigned int inst_len = 0;
+    int inst_len = 0;
+    int index;
     unsigned int gpreg;
     unsigned long value;
-    u8 buffer[6];   
+    u8 buffer[MAX_INST_LEN];   
+    u8 prefix = 0;
     int result = 1;
     enum instruction_index list_a[] = {INSTR_MOV2CR, INSTR_CLTS, INSTR_LMSW};
     enum instruction_index list_b[] = {INSTR_MOVCR2, INSTR_SMSW};
@@ -1648,29 +1624,41 @@
     ASSERT(vmcb);
 
     inst_copy_from_guest(buffer, svm_rip2pointer(vmcb), sizeof(buffer));
+    /* get index to first actual instruction byte - as we will need to know 
where the 
+     * prefix lives later on
+     */
+    index = skip_prefix_bytes(buffer, sizeof(buffer));
     
     if (type == TYPE_MOV_TO_CR) 
     {
         inst_len = __get_instruction_length_from_list(vmcb, list_a, 
-                ARR_SIZE(list_a), buffer, &match);
+                ARR_SIZE(list_a), &buffer[index], &match);
     }
     else
     {
         inst_len = __get_instruction_length_from_list(vmcb, list_b, 
-                ARR_SIZE(list_b), buffer, &match);
-    }
+                ARR_SIZE(list_b), &buffer[index], &match);
+    }
+
+    ASSERT(inst_len > 0);
+
+    inst_len += index;
+
+    /* Check for REX prefix - it's ALWAYS the last byte of any prefix bytes */
+    if (index > 0 && (buffer[index-1] & 0xF0) == 0x40)
+        prefix = buffer[index-1];
 
     HVM_DBG_LOG(DBG_LEVEL_1, "eip = %lx", (unsigned long) vmcb->rip);
 
     switch (match) 
     {
     case INSTR_MOV2CR:
-        gpreg = decode_src_reg(buffer[2]);
+        gpreg = decode_src_reg(prefix, buffer[index+2]);
         result = mov_to_cr(gpreg, cr, regs);
         break;
 
     case INSTR_MOVCR2:
-        gpreg = decode_src_reg(buffer[2]);
+        gpreg = decode_src_reg(prefix, buffer[index+2]);
         mov_from_cr(cr, gpreg, regs);
         break;
 
@@ -1686,7 +1674,7 @@
         if (svm_dbg_on)
             svm_dump_inst(svm_rip2pointer(vmcb));
         
-        gpreg = decode_src_reg(buffer[2]);
+        gpreg = decode_src_reg(prefix, buffer[index+2]);
         value = get_reg(gpreg, regs, vmcb) & 0xF;
 
         if (svm_dbg_on)
@@ -1704,7 +1692,7 @@
     case INSTR_SMSW:
         svm_dump_inst(svm_rip2pointer(vmcb));
         value = v->arch.hvm_svm.cpu_shadow_cr0;
-        gpreg = decode_src_reg(buffer[2]);
+        gpreg = decode_src_reg(prefix, buffer[index+2]);
         set_reg(gpreg, value, regs, vmcb);
 
         if (svm_dbg_on)
@@ -1727,7 +1715,7 @@
 static inline void svm_do_msr_access(struct vcpu *v, struct cpu_user_regs 
*regs)
 {
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
-    unsigned int  inst_len;
+    int  inst_len;
     int64_t tsc_sum;
 
     ASSERT(vmcb);
@@ -1868,7 +1856,7 @@
     struct vcpu *v = current;
     u8 opcode[MAX_INST_SIZE], prefix, length = MAX_INST_SIZE;
     unsigned long g_vaddr;
-    unsigned int inst_len;
+    int inst_len;
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
 
     ASSERT(vmcb);
@@ -1885,6 +1873,7 @@
     if (invlpga)
     {
         inst_len = __get_instruction_length(vmcb, INSTR_INVLPGA, opcode);
+        ASSERT(inst_len > 0);
         __update_guest_eip(vmcb, inst_len);
 
         /* 
@@ -1898,6 +1887,7 @@
         /* What about multiple prefix codes? */
         prefix = (is_prefix(opcode[0])?opcode[0]:0);
         inst_len = __get_instruction_length(vmcb, INSTR_INVLPG, opcode);
+        ASSERT(inst_len > 0);
 
         inst_len--;
         length -= inst_len;
@@ -1949,7 +1939,10 @@
     v->arch.hvm_svm.cpu_shadow_cr0 = X86_CR0_ET;
 
     vmcb->cr2 = 0;
-    vmcb->cr4 = 0;
+    vmcb->efer = EFER_SVME;
+
+    vmcb->cr4 = SVM_CR4_HOST_MASK;
+    v->arch.hvm_svm.cpu_shadow_cr4 = 0;
 
     /* This will jump to ROMBIOS */
     vmcb->rip = 0xFFF0;
@@ -2019,12 +2012,13 @@
 static int svm_do_vmmcall(struct vcpu *v, struct cpu_user_regs *regs)
 {
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
-    unsigned int inst_len;
+    int inst_len;
 
     ASSERT(vmcb);
     ASSERT(regs);
 
     inst_len = __get_instruction_length(vmcb, INSTR_VMCALL, NULL);
+    ASSERT(inst_len > 0);
 
     /* VMMCALL sanity check */
     if (vmcb->cpl > get_vmmcall_cpl(regs->edi))
@@ -2478,7 +2472,7 @@
         {
             v->arch.hvm_svm.injecting_event = 1;
             /* Inject #PG using Interruption-Information Fields */
-            svm_inject_exception(vmcb, TRAP_page_fault, regs.error_code);
+            svm_inject_exception(vmcb, TRAP_page_fault, 1, regs.error_code);
 
             v->arch.hvm_svm.cpu_cr2 = va;
             vmcb->cr2 = va;
diff -r a66763eb86fe -r a376bab39768 xen/arch/x86/hvm/svm/vmcb.c
--- a/xen/arch/x86/hvm/svm/vmcb.c       Tue Feb 28 18:00:15 2006
+++ b/xen/arch/x86/hvm/svm/vmcb.c       Tue Feb 28 21:57:38 2006
@@ -190,7 +190,6 @@
     unsigned long eflags;
     unsigned long shadow_cr;
     struct vmcb_struct *vmcb = arch_svm->vmcb;
-    struct Xgt_desc_struct desc;
 
     /* Allows IRQs to be shares */
     vmcb->vintr.fields.intr_masking = 1;
@@ -224,9 +223,9 @@
     vmcb->fs.base = 0;
     vmcb->gs.base = 0;
 
-    __asm__ __volatile__ ("sidt  (%0) \n" :: "a"(&desc) : "memory");
-    vmcb->idtr.base = desc.address;
-    vmcb->idtr.limit = desc.size;
+    /* Guest Interrupt descriptor table */
+    vmcb->idtr.base = 0;
+    vmcb->idtr.limit = 0;
 
     /* Set up segment attributes */
     attrib.bytes = 0;
@@ -248,15 +247,11 @@
     attrib.fields.type = 0xb;   /* type=0xb -> executable/readable, accessed */
     vmcb->cs.attributes = attrib;
 
-    /* Global descriptor table */
-    //NMERGE7500 - can probably remove access to gdtr
-    vmcb->gdtr.base = regs->edx;
-    regs->edx = 0;
-    ASSERT(regs->eax <= 0xFFFF); /* Make sure we're in the limit */
-    vmcb->gdtr.limit = regs->eax;
-    regs->eax = 0;
-
-    /* Local Descriptor Table */
+    /* Guest Global descriptor table */
+    vmcb->gdtr.base = 0;
+    vmcb->gdtr.limit = 0;
+
+    /* Guest Local Descriptor Table */
     attrib.fields.s = 0; /* not code or data segement */
     attrib.fields.type = 0x2; /* LDT */
     attrib.fields.db = 0; /* 16-bit */
@@ -279,11 +274,10 @@
     /* CR3 is set in svm_final_setup_guest */
 
     __asm__ __volatile__ ("mov %%cr4,%0" : "=r" (crn) :); 
-    shadow_cr = crn;
-    vmcb->cr4 = shadow_cr;
-
-//MERGE7500 - should write a 0 instead to rsp?
-    vmcb->rsp = regs->esp;
+    arch_svm->cpu_shadow_cr4 = crn & ~(X86_CR4_PGE | X86_CR4_PSE);
+    vmcb->cr4 = crn | SVM_CR4_HOST_MASK;
+
+    vmcb->rsp = 0;
     vmcb->rip = regs->eip;
 
     eflags = regs->eflags & ~HVM_EFLAGS_RESERVED_0; /* clear 0s */
diff -r a66763eb86fe -r a376bab39768 xen/arch/x86/hvm/svm/x86_64/exits.S
--- a/xen/arch/x86/hvm/svm/x86_64/exits.S       Tue Feb 28 18:00:15 2006
+++ b/xen/arch/x86/hvm/svm/x86_64/exits.S       Tue Feb 28 21:57:38 2006
@@ -107,8 +107,6 @@
         movq %rax, VMCB_rax(%rcx)
         movq VCPU_svm_hsa_pa(%rbx), %rax
         VMSAVE
-       /* XXX FPU SAVE */
-       /* XXX DO TSC OFFSET */
 
         movq VCPU_svm_vmcb_pa(%rbx), %rax
         popq %r15
@@ -137,9 +135,7 @@
         VMSAVE
         /* rax is the only register we're allowed to touch here... */
 
-       /* XXX FPU SAVE */
         GET_CURRENT(%rax)
-       /* XXX DO TSC OFFSET */
         movq VCPU_svm_hsa_pa(%rax), %rax
         VMLOAD
 
diff -r a66763eb86fe -r a376bab39768 xen/include/asm-x86/hvm/svm/emulate.h
--- a/xen/include/asm-x86/hvm/svm/emulate.h     Tue Feb 28 18:00:15 2006
+++ b/xen/include/asm-x86/hvm/svm/emulate.h     Tue Feb 28 21:57:38 2006
@@ -83,15 +83,15 @@
         struct cpu_user_regs *regs, const u8 prefix, const u8 *operand, 
         u8 *size);
 extern OPERATING_MODE get_operating_mode (struct vmcb_struct *vmcb);
-extern unsigned int decode_dest_reg(u8 modrm);
-extern unsigned int decode_src_reg(u8 modrm);
+extern unsigned int decode_dest_reg(u8 prefix, u8 modrm);
+extern unsigned int decode_src_reg(u8 prefix, u8 modrm);
 extern unsigned long svm_rip2pointer(struct vmcb_struct *vmcb);
-extern unsigned int __get_instruction_length_from_list(struct vmcb_struct 
*vmcb,
+extern int __get_instruction_length_from_list(struct vmcb_struct *vmcb,
         enum instruction_index *list, unsigned int list_count, 
         u8 *guest_eip_buf, enum instruction_index *match);
 
 
-static inline unsigned int __get_instruction_length(struct vmcb_struct *vmcb, 
+static inline int __get_instruction_length(struct vmcb_struct *vmcb, 
         enum instruction_index instr, u8 *guest_eip_buf)
 {
     return __get_instruction_length_from_list(vmcb, &instr, 1, guest_eip_buf, 
@@ -138,9 +138,20 @@
 }
 
 
+static inline int skip_prefix_bytes(u8 *buf, size_t size)
+{
+    int index;
+    for (index = 0; index < size && is_prefix(buf[index]); index ++)  
+        /* do nothing */ ;
+    return index;
+}
+
+
+
 static void inline __update_guest_eip(struct vmcb_struct *vmcb, 
-        unsigned long inst_len) 
+        int inst_len) 
 {
+    ASSERT(inst_len > 0);
     vmcb->rip += inst_len;
 }
 
diff -r a66763eb86fe -r a376bab39768 xen/include/asm-x86/hvm/svm/vmcb.h
--- a/xen/include/asm-x86/hvm/svm/vmcb.h        Tue Feb 28 18:00:15 2006
+++ b/xen/include/asm-x86/hvm/svm/vmcb.h        Tue Feb 28 21:57:38 2006
@@ -269,21 +269,6 @@
 #define SVM_LONG_GUEST(ed)    \
   (test_bit(SVM_CPU_STATE_LMA_ENABLED, &ed->arch.hvm_svm.cpu_state))
 
-enum {
-    SVM_INDEX_MSR_LSTAR = 0,
-    SVM_INDEX_MSR_STAR,
-    SVM_INDEX_MSR_CSTAR,
-    SVM_INDEX_MSR_SYSCALL_MASK,
-    SVM_INDEX_MSR_EFER,
-
-    SVM_MSR_COUNT,
-};
-
-struct svm_msr_state {
-    unsigned long flags;
-    unsigned long msr_items[SVM_MSR_COUNT];
-    unsigned long shadow_gs;
-};
 
 /* 
  * Attribute for segment selector. This is a copy of bit 40:47 & 52:55 of the
@@ -449,7 +434,7 @@
 
 struct arch_svm_struct {
     struct vmcb_struct *vmcb;
-    void               *host_save_area;
+    void                       *host_save_area;
     u64                 host_save_pa;
     u64                 vmcb_pa;
     u32                 *iopm;
@@ -461,11 +446,11 @@
     u32                 asid_core;
     
     unsigned long       flags;      /* VMCB flags */
-    unsigned long       cpu_shadow_cr0; /* copy of guest read shadow CR0 */
+    unsigned long       cpu_shadow_cr0; /* Guest value for CR0 */
+    unsigned long       cpu_shadow_cr4; /* Guest value for CR4 */
     unsigned long       cpu_cr2;
     unsigned long       cpu_cr3;
     unsigned long       cpu_state;
-    struct svm_msr_state msr_content;
     struct timer        hlt_timer;  /* hlt ins emulation wakeup timer */
 };
 
@@ -486,6 +471,14 @@
 
 #define VMCB_EFLAGS_RESERVED_0          0xffc08028 /* bitmap for 0 */
 #define VMCB_EFLAGS_RESERVED_1          0x00000002 /* bitmap for 1 */
+
+/* These bits in the CR4 are owned by the host */
+#ifdef __i386__
+#define SVM_CR4_HOST_MASK (0)
+#else
+#define SVM_CR4_HOST_MASK (X86_CR4_PAE)
+#endif
+
 
 #endif /* ASM_X86_HVM_SVM_VMCS_H__ */
 

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

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] SVM patch to add 64bit hv support., Xen patchbot -unstable <=