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] [xen-unstable] svm: support VMCB cleanbits

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] svm: support VMCB cleanbits
From: Xen patchbot-unstable <patchbot-unstable@xxxxxxxxxxxxxxxxxxx>
Date: Thu, 23 Dec 2010 05:34:50 -0800
Delivery-date: Thu, 23 Dec 2010 05:45:05 -0800
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Keir Fraser <keir@xxxxxxx>
# Date 1292430851 0
# Node ID 8d9ca1012ffa46fe063cb634a6a335d56bb6fcf3
# Parent  764e95f64b28b381abcc40ddad5e77d47572f4d6
svm: support VMCB cleanbits

Attached patch implements the VMCB cleanbits SVM feature.
Upcoming AMD CPUs introduce them and they are basically hints
for the CPU which vmcb values can be re-used from the previous
VMRUN instruction.

Each bit represents a certain set of fields in the VMCB.
Setting a bit tells the cpu it can re-use the cached value
from the previous VMRUN.
Clearing a bit tells the cpu to reload the values from the given VMCB.

Signed-off-by: Wei Huang <Wei.Huang2@xxxxxxx>
Signed-off-by: Christoph Egger <Christoph.Egger@xxxxxxx>
Signed-off-by: Keir Fraser <keir@xxxxxxx>
---
 xen/arch/x86/hvm/svm/asid.c        |    9 -
 xen/arch/x86/hvm/svm/emulate.c     |    4 
 xen/arch/x86/hvm/svm/intr.c        |   16 +--
 xen/arch/x86/hvm/svm/svm.c         |  186 +++++++++++++++++++++++++------------
 xen/arch/x86/hvm/svm/vmcb.c        |  103 ++++++++++----------
 xen/include/asm-x86/hvm/svm/svm.h  |    2 
 xen/include/asm-x86/hvm/svm/vmcb.h |  153 +++++++++++++++++++++++-------
 7 files changed, 320 insertions(+), 153 deletions(-)

diff -r 764e95f64b28 -r 8d9ca1012ffa xen/arch/x86/hvm/svm/asid.c
--- a/xen/arch/x86/hvm/svm/asid.c       Wed Dec 15 14:16:03 2010 +0000
+++ b/xen/arch/x86/hvm/svm/asid.c       Wed Dec 15 16:34:11 2010 +0000
@@ -41,18 +41,19 @@ asmlinkage void svm_asid_handle_vmrun(vo
 asmlinkage void svm_asid_handle_vmrun(void)
 {
     struct vcpu *curr = current;
+    struct vmcb_struct *vmcb = curr->arch.hvm_svm.vmcb;
     bool_t need_flush = hvm_asid_handle_vmenter();
 
     /* ASID 0 indicates that ASIDs are disabled. */
     if ( curr->arch.hvm_vcpu.asid == 0 )
     {
-        curr->arch.hvm_svm.vmcb->guest_asid  = 1;
-        curr->arch.hvm_svm.vmcb->tlb_control = 1;
+        vmcb_set_guest_asid(vmcb, 1);
+        vmcb->tlb_control = 1;
         return;
     }
 
-    curr->arch.hvm_svm.vmcb->guest_asid  = curr->arch.hvm_vcpu.asid;
-    curr->arch.hvm_svm.vmcb->tlb_control = need_flush;
+    vmcb_set_guest_asid(vmcb, curr->arch.hvm_vcpu.asid);
+    vmcb->tlb_control = need_flush;
 }
 
 /*
diff -r 764e95f64b28 -r 8d9ca1012ffa xen/arch/x86/hvm/svm/emulate.c
--- a/xen/arch/x86/hvm/svm/emulate.c    Wed Dec 15 14:16:03 2010 +0000
+++ b/xen/arch/x86/hvm/svm/emulate.c    Wed Dec 15 16:34:11 2010 +0000
@@ -120,7 +120,9 @@ static const u8 *opc_bytes[INSTR_MAX_COU
 
 static int fetch(struct vcpu *v, u8 *buf, unsigned long addr, int len)
 {
-    uint32_t pfec = (v->arch.hvm_svm.vmcb->cpl == 3) ? PFEC_user_mode : 0;
+    uint32_t pfec;
+
+    pfec = (vmcb_get_cpl(v->arch.hvm_svm.vmcb) == 3) ? PFEC_user_mode : 0;
 
     switch ( hvm_fetch_from_guest_virt(buf, addr, len, pfec) )
     {
diff -r 764e95f64b28 -r 8d9ca1012ffa xen/arch/x86/hvm/svm/intr.c
--- a/xen/arch/x86/hvm/svm/intr.c       Wed Dec 15 14:16:03 2010 +0000
+++ b/xen/arch/x86/hvm/svm/intr.c       Wed Dec 15 16:34:11 2010 +0000
@@ -42,6 +42,7 @@ static void svm_inject_nmi(struct vcpu *
 static void svm_inject_nmi(struct vcpu *v)
 {
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+    u32 general1_intercepts = vmcb_get_general1_intercepts(vmcb);
     eventinj_t event;
 
     event.bytes = 0;
@@ -56,9 +57,10 @@ static void svm_inject_nmi(struct vcpu *
      * SVM does not virtualise the NMI mask, so we emulate it by intercepting
      * the next IRET and blocking NMI injection until the intercept triggers.
      */
-    vmcb->general1_intercepts |= GENERAL1_INTERCEPT_IRET;
+    vmcb_set_general1_intercepts(
+        vmcb, general1_intercepts | GENERAL1_INTERCEPT_IRET);
 }
-    
+
 static void svm_inject_extint(struct vcpu *v, int vector)
 {
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
@@ -76,6 +78,7 @@ static void enable_intr_window(struct vc
 static void enable_intr_window(struct vcpu *v, struct hvm_intack intack)
 {
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+    u32 general1_intercepts = vmcb_get_general1_intercepts(vmcb);
     vintr_t intr;
 
     ASSERT(intack.source != hvm_intsrc_none);
@@ -100,16 +103,17 @@ static void enable_intr_window(struct vc
      * we inject a VINTR, ...).
      */
     if ( (intack.source == hvm_intsrc_nmi) &&
-         (vmcb->general1_intercepts & GENERAL1_INTERCEPT_IRET) )
+         (general1_intercepts & GENERAL1_INTERCEPT_IRET) )
         return;
 
-    intr = vmcb->vintr;
+    intr = vmcb_get_vintr(vmcb);
     intr.fields.irq     = 1;
     intr.fields.vector  = 0;
     intr.fields.prio    = intack.vector >> 4;
     intr.fields.ign_tpr = (intack.source != hvm_intsrc_lapic);
-    vmcb->vintr = intr;
-    vmcb->general1_intercepts |= GENERAL1_INTERCEPT_VINTR;
+    vmcb_set_vintr(vmcb, intr);
+    vmcb_set_general1_intercepts(
+        vmcb, general1_intercepts | GENERAL1_INTERCEPT_VINTR);
 }
 
 asmlinkage void svm_intr_assist(void) 
diff -r 764e95f64b28 -r 8d9ca1012ffa xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c        Wed Dec 15 14:16:03 2010 +0000
+++ b/xen/arch/x86/hvm/svm/svm.c        Wed Dec 15 16:34:11 2010 +0000
@@ -115,14 +115,14 @@ static void svm_save_dr(struct vcpu *v)
 
     /* 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 = ~0u;
+    vmcb_set_dr_intercepts(vmcb, ~0u);
 
     v->arch.guest_context.debugreg[0] = read_debugreg(0);
     v->arch.guest_context.debugreg[1] = read_debugreg(1);
     v->arch.guest_context.debugreg[2] = read_debugreg(2);
     v->arch.guest_context.debugreg[3] = read_debugreg(3);
-    v->arch.guest_context.debugreg[6] = vmcb->dr6;
-    v->arch.guest_context.debugreg[7] = vmcb->dr7;
+    v->arch.guest_context.debugreg[6] = vmcb_get_dr6(vmcb);
+    v->arch.guest_context.debugreg[7] = vmcb_get_dr7(vmcb);
 }
 
 static void __restore_debug_registers(struct vcpu *v)
@@ -133,14 +133,14 @@ static void __restore_debug_registers(st
         return;
 
     v->arch.hvm_vcpu.flag_dr_dirty = 1;
-    vmcb->dr_intercepts = 0;
+    vmcb_set_dr_intercepts(vmcb, 0);
 
     write_debugreg(0, v->arch.guest_context.debugreg[0]);
     write_debugreg(1, v->arch.guest_context.debugreg[1]);
     write_debugreg(2, v->arch.guest_context.debugreg[2]);
     write_debugreg(3, v->arch.guest_context.debugreg[3]);
-    vmcb->dr6 = v->arch.guest_context.debugreg[6];
-    vmcb->dr7 = v->arch.guest_context.debugreg[7];
+    vmcb_set_dr6(vmcb, v->arch.guest_context.debugreg[6]);
+    vmcb_set_dr7(vmcb, v->arch.guest_context.debugreg[7]);
 }
 
 /*
@@ -230,9 +230,9 @@ static int svm_vmcb_restore(struct vcpu 
 
     if ( paging_mode_hap(v->domain) )
     {
-        vmcb->np_enable = 1;
-        vmcb->g_pat = MSR_IA32_CR_PAT_RESET; /* guest PAT */
-        vmcb->h_cr3 = pagetable_get_paddr(p2m_get_pagetable(p2m));
+        vmcb_set_np_enable(vmcb, 1);
+        vmcb_set_g_pat(vmcb, MSR_IA32_CR_PAT_RESET /* guest PAT */);
+        vmcb_set_h_cr3(vmcb, pagetable_get_paddr(p2m_get_pagetable(p2m)));
     }
 
     if ( c->pending_valid ) 
@@ -247,6 +247,7 @@ static int svm_vmcb_restore(struct vcpu 
         }
     }
 
+    vmcb->cleanbits.bytes = 0;
     paging_update_paging_modes(v);
 
     return 0;
@@ -307,7 +308,8 @@ static void svm_fpu_enter(struct vcpu *v
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
 
     setup_fpu(v);
-    vmcb->exception_intercepts &= ~(1U << TRAP_no_device);
+    vmcb_set_exception_intercepts(
+        vmcb, vmcb_get_exception_intercepts(vmcb) & ~(1U << TRAP_no_device));
 }
 
 static void svm_fpu_leave(struct vcpu *v)
@@ -325,8 +327,10 @@ static void svm_fpu_leave(struct vcpu *v
      */
     if ( !(v->arch.hvm_vcpu.guest_cr[0] & X86_CR0_TS) )
     {
-        v->arch.hvm_svm.vmcb->exception_intercepts |= 1U << TRAP_no_device;
-        vmcb->cr0 |= X86_CR0_TS;
+        vmcb_set_exception_intercepts(
+            vmcb,
+            vmcb_get_exception_intercepts(vmcb) | (1U << TRAP_no_device));
+        vmcb_set_cr0(vmcb, vmcb_get_cr0(vmcb) | X86_CR0_TS);
     }
 }
 
@@ -338,7 +342,7 @@ static unsigned int svm_get_interrupt_sh
     if ( vmcb->interrupt_shadow )
         intr_shadow |= HVM_INTR_SHADOW_MOV_SS | HVM_INTR_SHADOW_STI;
 
-    if ( vmcb->general1_intercepts & GENERAL1_INTERCEPT_IRET )
+    if ( vmcb_get_general1_intercepts(vmcb) & GENERAL1_INTERCEPT_IRET )
         intr_shadow |= HVM_INTR_SHADOW_NMI;
 
     return intr_shadow;
@@ -347,13 +351,15 @@ static void svm_set_interrupt_shadow(str
 static void svm_set_interrupt_shadow(struct vcpu *v, unsigned int intr_shadow)
 {
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+    u32 general1_intercepts = vmcb_get_general1_intercepts(vmcb);
 
     vmcb->interrupt_shadow =
         !!(intr_shadow & (HVM_INTR_SHADOW_MOV_SS|HVM_INTR_SHADOW_STI));
 
-    vmcb->general1_intercepts &= ~GENERAL1_INTERCEPT_IRET;
+    general1_intercepts &= ~GENERAL1_INTERCEPT_IRET;
     if ( intr_shadow & HVM_INTR_SHADOW_NMI )
-        vmcb->general1_intercepts |= GENERAL1_INTERCEPT_IRET;
+        general1_intercepts |= GENERAL1_INTERCEPT_IRET;
+    vmcb_set_general1_intercepts(vmcb, general1_intercepts);
 }
 
 static int svm_guest_x86_mode(struct vcpu *v)
@@ -377,6 +383,7 @@ static void svm_update_guest_cr(struct v
 static void svm_update_guest_cr(struct vcpu *v, unsigned int cr)
 {
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+    uint64_t value;
 
     switch ( cr )
     {
@@ -387,27 +394,29 @@ static void svm_update_guest_cr(struct v
         {
             if ( v != current )
                 hw_cr0_mask |= X86_CR0_TS;
-            else if ( vmcb->cr0 & X86_CR0_TS )
+            else if ( vmcb_get_cr0(vmcb) & X86_CR0_TS )
                 svm_fpu_enter(v);
         }
 
-        vmcb->cr0 = v->arch.hvm_vcpu.guest_cr[0] | hw_cr0_mask;
+        value = v->arch.hvm_vcpu.guest_cr[0] | hw_cr0_mask;
         if ( !paging_mode_hap(v->domain) )
-            vmcb->cr0 |= X86_CR0_PG | X86_CR0_WP;
+            value |= X86_CR0_PG | X86_CR0_WP;
+        vmcb_set_cr0(vmcb, value);
         break;
     }
     case 2:
-        vmcb->cr2 = v->arch.hvm_vcpu.guest_cr[2];
+        vmcb_set_cr2(vmcb, v->arch.hvm_vcpu.guest_cr[2]);
         break;
     case 3:
-        vmcb->cr3 = v->arch.hvm_vcpu.hw_cr[3];
+        vmcb_set_cr3(vmcb, v->arch.hvm_vcpu.hw_cr[3]);
         hvm_asid_flush_vcpu(v);
         break;
     case 4:
-        vmcb->cr4 = HVM_CR4_HOST_MASK;
+        value = HVM_CR4_HOST_MASK;
         if ( paging_mode_hap(v->domain) )
-            vmcb->cr4 &= ~X86_CR4_PAE;
-        vmcb->cr4 |= v->arch.hvm_vcpu.guest_cr[4];
+            value &= ~X86_CR4_PAE;
+        value |= v->arch.hvm_vcpu.guest_cr[4];
+        vmcb_set_cr4(vmcb, value);
         break;
     default:
         BUG();
@@ -418,10 +427,12 @@ static void svm_update_guest_efer(struct
 {
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
     bool_t lma = !!(v->arch.hvm_vcpu.guest_efer & EFER_LMA);
-
-    vmcb->efer = (v->arch.hvm_vcpu.guest_efer | EFER_SVME) & ~EFER_LME;
+    uint64_t new_efer;
+
+    new_efer = (v->arch.hvm_vcpu.guest_efer | EFER_SVME) & ~EFER_LME;
     if ( lma )
-        vmcb->efer |= EFER_LME;
+        new_efer |= EFER_LME;
+    vmcb_set_efer(vmcb, new_efer);
 
     /*
      * In legacy mode (EFER.LMA=0) we natively support SYSENTER/SYSEXIT with
@@ -481,7 +492,7 @@ static void svm_get_segment_register(str
         break;
     case x86_seg_ss:
         memcpy(reg, &vmcb->ss, sizeof(*reg));
-        reg->attr.fields.dpl = vmcb->cpl;
+        reg->attr.fields.dpl = vmcb->_cpl;
         if ( reg->attr.fields.type == 0 )
             reg->attr.fields.db = 0;
         break;
@@ -515,6 +526,16 @@ static void svm_set_segment_register(str
 
     switch ( seg )
     {
+    case x86_seg_cs:
+    case x86_seg_ds:
+    case x86_seg_es:
+    case x86_seg_ss: /* cpl */
+        vmcb->cleanbits.fields.seg = 0;
+        break;
+    case x86_seg_gdtr:
+    case x86_seg_idtr:
+        vmcb->cleanbits.fields.dt = 0;
+        break;
     case x86_seg_fs:
     case x86_seg_gs:
     case x86_seg_tr:
@@ -547,7 +568,7 @@ static void svm_set_segment_register(str
         break;
     case x86_seg_ss:
         memcpy(&vmcb->ss, reg, sizeof(*reg));
-        vmcb->cpl = vmcb->ss.attr.fields.dpl;
+        vmcb->_cpl = vmcb->ss.attr.fields.dpl;
         break;
     case x86_seg_tr:
         memcpy(&vmcb->tr, reg, sizeof(*reg));
@@ -573,15 +594,20 @@ static void svm_set_segment_register(str
 
 static void svm_set_tsc_offset(struct vcpu *v, u64 offset)
 {
-    v->arch.hvm_svm.vmcb->tsc_offset = offset;
+    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+    vmcb_set_tsc_offset(vmcb, offset);
 }
 
 static void svm_set_rdtsc_exiting(struct vcpu *v, bool_t enable)
 {
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
-    vmcb->general1_intercepts &= ~GENERAL1_INTERCEPT_RDTSC;
+    u32 general1_intercepts = vmcb_get_general1_intercepts(vmcb);
+
+    general1_intercepts &= ~GENERAL1_INTERCEPT_RDTSC;
     if ( enable )
-        vmcb->general1_intercepts |= GENERAL1_INTERCEPT_RDTSC;
+        general1_intercepts |= GENERAL1_INTERCEPT_RDTSC;
+
+    vmcb_set_general1_intercepts(vmcb, general1_intercepts);
 }
 
 static void svm_init_hypercall_page(struct domain *d, void *hypercall_page)
@@ -626,6 +652,7 @@ static void svm_ctxt_switch_from(struct 
 
 static void svm_ctxt_switch_to(struct vcpu *v)
 {
+    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
     int cpu = smp_processor_id();
 
 #ifdef  __x86_64__
@@ -651,7 +678,8 @@ static void svm_ctxt_switch_to(struct vc
     svm_restore_dr(v);
 
     svm_vmsave(per_cpu(root_vmcb, cpu));
-    svm_vmload(v->arch.hvm_svm.vmcb);
+    svm_vmload(vmcb);
+    vmcb->cleanbits.bytes = 0;
     vpmu_load(v);
 
     if ( cpu_has_rdtscp )
@@ -660,16 +688,17 @@ static void svm_ctxt_switch_to(struct vc
 
 static void svm_do_resume(struct vcpu *v) 
 {
+    struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
     bool_t debug_state = v->domain->debugger_attached;
+    vintr_t intr;
 
     if ( unlikely(v->arch.hvm_vcpu.debug_state_latch != debug_state) )
     {
+        uint32_t intercepts = vmcb_get_exception_intercepts(vmcb);
         uint32_t mask = (1U << TRAP_debug) | (1U << TRAP_int3);
         v->arch.hvm_vcpu.debug_state_latch = debug_state;
-        if ( debug_state )
-            v->arch.hvm_svm.vmcb->exception_intercepts |= mask;
-        else
-            v->arch.hvm_svm.vmcb->exception_intercepts &= ~mask;
+        vmcb_set_exception_intercepts(
+            vmcb, debug_state ? (intercepts | mask) : (intercepts & ~mask));
     }
 
     if ( v->arch.hvm_svm.launch_core != smp_processor_id() )
@@ -682,8 +711,10 @@ static void svm_do_resume(struct vcpu *v
     }
 
     /* Reflect the vlapic's TPR in the hardware vtpr */
-    v->arch.hvm_svm.vmcb->vintr.fields.tpr = 
+    intr = vmcb_get_vintr(vmcb);
+    intr.fields.tpr =
         (vlapic_get_reg(vcpu_vlapic(v), APIC_TASKPRI) & 0xFF) >> 4;
+    vmcb_set_vintr(vmcb, intr);
 
     hvm_do_resume(v);
     reset_stack_and_jump(svm_asm_do_resume);
@@ -740,7 +771,7 @@ static void svm_inject_exception(
         if ( guest_cpu_user_regs()->eflags & X86_EFLAGS_TF )
         {
             __restore_debug_registers(curr);
-            vmcb->dr6 |= 0x4000;
+            vmcb_set_dr6(vmcb, vmcb_get_dr6(vmcb) | 0x4000);
         }
     case TRAP_int3:
         if ( curr->domain->debugger_attached )
@@ -770,7 +801,8 @@ static void svm_inject_exception(
 
     if ( trapnr == TRAP_page_fault )
     {
-        vmcb->cr2 = curr->arch.hvm_vcpu.guest_cr[2] = cr2;
+        curr->arch.hvm_vcpu.guest_cr[2] = cr2;
+        vmcb_set_cr2(vmcb, cr2);
         HVMTRACE_LONG_2D(PF_INJECT, errcode, TRC_PAR_LONG(cr2));
     }
     else
@@ -885,6 +917,8 @@ static int svm_cpu_up(void)
 
 struct hvm_function_table * __init start_svm(void)
 {
+    bool_t printed = 0;
+
     if ( !test_bit(X86_FEATURE_SVME, &boot_cpu_data.x86_capability) )
         return NULL;
 
@@ -898,6 +932,19 @@ struct hvm_function_table * __init start
 
     svm_feature_flags = ((cpuid_eax(0x80000000) >= 0x8000000A) ?
                          cpuid_edx(0x8000000A) : 0);
+
+    printk("SVM: Supported advanced features:\n");
+
+#define P(p,s) if ( p ) { printk(" - %s\n", s); printed = 1; }
+    P(cpu_has_svm_npt, "Nested Page Tables (NPT)");
+    P(cpu_has_svm_lbrv, "Last Branch Record (LBR) Virtualisation");
+    P(cpu_has_svm_nrips, "Next-RIP Saved on #VMEXIT");
+    P(cpu_has_svm_cleanbits, "VMCB Clean Bits");
+    P(cpu_has_pause_filter, "Pause-Intercept Filter");
+#undef P
+
+    if ( !printed )
+        printk(" - none\n");
 
     svm_function_table.hap_supported = cpu_has_svm_npt;
     svm_function_table.hap_capabilities = HVM_HAP_SUPERPAGE_2MB |
@@ -950,7 +997,7 @@ static void svm_fpu_dirty_intercept(void
     svm_fpu_enter(curr);
 
     if ( !(curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_TS) )
-        vmcb->cr0 &= ~X86_CR0_TS;
+        vmcb_set_cr0(vmcb, vmcb_get_cr0(vmcb) & ~X86_CR0_TS);
 }
 
 #define bitmaskof(idx)  (1U << ((idx) & 31))
@@ -1040,23 +1087,23 @@ static int svm_msr_read_intercept(unsign
         goto gpf;
 
     case MSR_IA32_DEBUGCTLMSR:
-        *msr_content = vmcb->debugctlmsr;
+        *msr_content = vmcb_get_debugctlmsr(vmcb);
         break;
 
     case MSR_IA32_LASTBRANCHFROMIP:
-        *msr_content = vmcb->lastbranchfromip;
+        *msr_content = vmcb_get_lastbranchfromip(vmcb);
         break;
 
     case MSR_IA32_LASTBRANCHTOIP:
-        *msr_content = vmcb->lastbranchtoip;
+        *msr_content = vmcb_get_lastbranchtoip(vmcb);
         break;
 
     case MSR_IA32_LASTINTFROMIP:
-        *msr_content = vmcb->lastintfromip;
+        *msr_content = vmcb_get_lastintfromip(vmcb);
         break;
 
     case MSR_IA32_LASTINTTOIP:
-        *msr_content = vmcb->lastinttoip;
+        *msr_content = vmcb_get_lastinttoip(vmcb);
         break;
 
     case MSR_K7_PERFCTR0:
@@ -1112,7 +1159,7 @@ static int svm_msr_write_intercept(unsig
         break;
 
     case MSR_IA32_DEBUGCTLMSR:
-        vmcb->debugctlmsr = msr_content;
+        vmcb_set_debugctlmsr(vmcb, msr_content);
         if ( !msr_content || !cpu_has_svm_lbrv )
             break;
         vmcb->lbr_control.fields.enable = 1;
@@ -1124,19 +1171,19 @@ static int svm_msr_write_intercept(unsig
         break;
 
     case MSR_IA32_LASTBRANCHFROMIP:
-        vmcb->lastbranchfromip = msr_content;
+        vmcb_set_lastbranchfromip(vmcb, msr_content);
         break;
 
     case MSR_IA32_LASTBRANCHTOIP:
-        vmcb->lastbranchtoip = msr_content;
+        vmcb_set_lastbranchtoip(vmcb, msr_content);
         break;
 
     case MSR_IA32_LASTINTFROMIP:
-        vmcb->lastintfromip = msr_content;
+        vmcb_set_lastintfromip(vmcb, msr_content);
         break;
 
     case MSR_IA32_LASTINTTOIP:
-        vmcb->lastinttoip = msr_content;
+        vmcb_set_lastinttoip(vmcb, msr_content);
         break;
 
     case MSR_K7_PERFCTR0:
@@ -1379,9 +1426,11 @@ asmlinkage void svm_vmexit_handler(struc
     struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
     eventinj_t eventinj;
     int inst_len, rc;
+    vintr_t intr;
 
     if ( paging_mode_hap(v->domain) )
-        v->arch.hvm_vcpu.guest_cr[3] = v->arch.hvm_vcpu.hw_cr[3] = vmcb->cr3;
+        v->arch.hvm_vcpu.guest_cr[3] = v->arch.hvm_vcpu.hw_cr[3] =
+            vmcb_get_cr3(vmcb);
 
     /*
      * Before doing anything else, we need to sync up the VLAPIC's TPR with
@@ -1390,8 +1439,9 @@ asmlinkage void svm_vmexit_handler(struc
      * NB. We need to preserve the low bits of the TPR to make checked builds
      * of Windows work, even though they don't actually do anything.
      */
+    intr = vmcb_get_vintr(vmcb);
     vlapic_set_reg(vcpu_vlapic(v), APIC_TASKPRI,
-                   ((vmcb->vintr.fields.tpr & 0x0F) << 4) |
+                   ((intr.fields.tpr & 0x0F) << 4) |
                    (vlapic_get_reg(vcpu_vlapic(v), APIC_TASKPRI) & 0x0F));
 
     exit_reason = vmcb->exitcode;
@@ -1414,6 +1464,8 @@ asmlinkage void svm_vmexit_handler(struc
     perfc_incra(svmexits, exit_reason);
 
     hvm_maybe_deassert_evtchn_irq();
+
+    vmcb->cleanbits.bytes = cpu_has_svm_cleanbits ? ~0u : 0u;
 
     /* Event delivery caused this intercept? Queue for redelivery. */
     eventinj = vmcb->exitintinfo;
@@ -1495,10 +1547,17 @@ asmlinkage void svm_vmexit_handler(struc
         svm_vmexit_mce_intercept(v, regs);
         break;
 
-    case VMEXIT_VINTR:
-        vmcb->vintr.fields.irq = 0;
-        vmcb->general1_intercepts &= ~GENERAL1_INTERCEPT_VINTR;
-        break;
+    case VMEXIT_VINTR: {
+        u32 general1_intercepts = vmcb_get_general1_intercepts(vmcb);
+        intr = vmcb_get_vintr(vmcb);
+
+        intr.fields.irq = 0;
+        general1_intercepts &= ~GENERAL1_INTERCEPT_VINTR;
+
+        vmcb_set_vintr(vmcb, intr);
+        vmcb_set_general1_intercepts(vmcb, general1_intercepts);
+        break;
+    }
 
     case VMEXIT_INVD:
     case VMEXIT_WBINVD:
@@ -1613,7 +1672,9 @@ asmlinkage void svm_vmexit_handler(struc
         svm_do_nested_pgfault(vmcb->exitinfo2);
         break;
 
-    case VMEXIT_IRET:
+    case VMEXIT_IRET: {
+        u32 general1_intercepts = vmcb_get_general1_intercepts(vmcb);
+
         /*
          * IRET clears the NMI mask. However because we clear the mask
          * /before/ executing IRET, we set the interrupt shadow to prevent
@@ -1622,9 +1683,12 @@ asmlinkage void svm_vmexit_handler(struc
          * may inject an NMI before the NMI handler's IRET instruction is
          * retired.
          */
-        vmcb->general1_intercepts &= ~GENERAL1_INTERCEPT_IRET;
+        general1_intercepts &= ~GENERAL1_INTERCEPT_IRET;
         vmcb->interrupt_shadow = 1;
-        break;
+
+        vmcb_set_general1_intercepts(vmcb, general1_intercepts);
+        break;
+    }
 
     case VMEXIT_PAUSE:
         svm_vmexit_do_pause(regs);
@@ -1641,8 +1705,10 @@ asmlinkage void svm_vmexit_handler(struc
     }
 
     /* The exit may have updated the TPR: reflect this in the hardware vtpr */
-    vmcb->vintr.fields.tpr = 
+    intr = vmcb_get_vintr(vmcb);
+    intr.fields.tpr =
         (vlapic_get_reg(vcpu_vlapic(v), APIC_TASKPRI) & 0xFF) >> 4;
+    vmcb_set_vintr(vmcb, intr);
 }
 
 asmlinkage void svm_trace_vmentry(void)
diff -r 764e95f64b28 -r 8d9ca1012ffa xen/arch/x86/hvm/svm/vmcb.c
--- a/xen/arch/x86/hvm/svm/vmcb.c       Wed Dec 15 14:16:03 2010 +0000
+++ b/xen/arch/x86/hvm/svm/vmcb.c       Wed Dec 15 16:34:11 2010 +0000
@@ -109,12 +109,13 @@ void svm_intercept_msr(struct vcpu *v, u
     }
 }
 
+/* This function can directly access fields which are covered by clean bits. */
 static int construct_vmcb(struct vcpu *v)
 {
     struct arch_svm_struct *arch_svm = &v->arch.hvm_svm;
     struct vmcb_struct *vmcb = arch_svm->vmcb;
 
-    vmcb->general1_intercepts = 
+    vmcb->_general1_intercepts = 
         GENERAL1_INTERCEPT_INTR        | GENERAL1_INTERCEPT_NMI         |
         GENERAL1_INTERCEPT_SMI         | GENERAL1_INTERCEPT_INIT        |
         GENERAL1_INTERCEPT_CPUID       | GENERAL1_INTERCEPT_INVD        |
@@ -122,7 +123,7 @@ static int construct_vmcb(struct vcpu *v
         GENERAL1_INTERCEPT_INVLPGA     | GENERAL1_INTERCEPT_IOIO_PROT   |
         GENERAL1_INTERCEPT_MSR_PROT    | GENERAL1_INTERCEPT_SHUTDOWN_EVT|
         GENERAL1_INTERCEPT_TASK_SWITCH;
-    vmcb->general2_intercepts = 
+    vmcb->_general2_intercepts = 
         GENERAL2_INTERCEPT_VMRUN       | GENERAL2_INTERCEPT_VMMCALL     |
         GENERAL2_INTERCEPT_VMLOAD      | GENERAL2_INTERCEPT_VMSAVE      |
         GENERAL2_INTERCEPT_STGI        | GENERAL2_INTERCEPT_CLGI        |
@@ -131,13 +132,13 @@ static int construct_vmcb(struct vcpu *v
         GENERAL2_INTERCEPT_XSETBV;
 
     /* Intercept all debug-register writes. */
-    vmcb->dr_intercepts = ~0u;
+    vmcb->_dr_intercepts = ~0u;
 
     /* Intercept all control-register accesses except for CR2 and CR8. */
-    vmcb->cr_intercepts = ~(CR_INTERCEPT_CR2_READ |
-                            CR_INTERCEPT_CR2_WRITE |
-                            CR_INTERCEPT_CR8_READ |
-                            CR_INTERCEPT_CR8_WRITE);
+    vmcb->_cr_intercepts = ~(CR_INTERCEPT_CR2_READ |
+                             CR_INTERCEPT_CR2_WRITE |
+                             CR_INTERCEPT_CR8_READ |
+                             CR_INTERCEPT_CR8_WRITE);
 
     /* I/O and MSR permission bitmaps. */
     arch_svm->msrpm = alloc_xenheap_pages(get_order_from_bytes(MSRPM_SIZE), 0);
@@ -153,21 +154,21 @@ static int construct_vmcb(struct vcpu *v
     svm_disable_intercept_for_msr(v, MSR_STAR);
     svm_disable_intercept_for_msr(v, MSR_SYSCALL_MASK);
 
-    vmcb->msrpm_base_pa = (u64)virt_to_maddr(arch_svm->msrpm);
-    vmcb->iopm_base_pa  = (u64)virt_to_maddr(hvm_io_bitmap);
+    vmcb->_msrpm_base_pa = (u64)virt_to_maddr(arch_svm->msrpm);
+    vmcb->_iopm_base_pa  = (u64)virt_to_maddr(hvm_io_bitmap);
 
     /* Virtualise EFLAGS.IF and LAPIC TPR (CR8). */
-    vmcb->vintr.fields.intr_masking = 1;
+    vmcb->_vintr.fields.intr_masking = 1;
   
     /* Initialise event injection to no-op. */
     vmcb->eventinj.bytes = 0;
 
     /* TSC. */
-    vmcb->tsc_offset = 0;
+    vmcb->_tsc_offset = 0;
     if ( v->domain->arch.vtsc )
     {
-        vmcb->general1_intercepts |= GENERAL1_INTERCEPT_RDTSC;
-        vmcb->general2_intercepts |= GENERAL2_INTERCEPT_RDTSCP;
+        vmcb->_general1_intercepts |= GENERAL1_INTERCEPT_RDTSC;
+        vmcb->_general2_intercepts |= GENERAL2_INTERCEPT_RDTSCP;
     }
 
     /* Guest EFER. */
@@ -225,38 +226,42 @@ static int construct_vmcb(struct vcpu *v
 
     paging_update_paging_modes(v);
 
-    vmcb->exception_intercepts =
+    vmcb->_exception_intercepts =
         HVM_TRAP_MASK
         | (1U << TRAP_no_device);
 
     if ( paging_mode_hap(v->domain) )
     {
-        vmcb->np_enable = 1; /* enable nested paging */
-        vmcb->g_pat = MSR_IA32_CR_PAT_RESET; /* guest PAT */
-        vmcb->h_cr3 = 
pagetable_get_paddr(p2m_get_pagetable(p2m_get_hostp2m(v->domain)));
+        vmcb->_np_enable = 1; /* enable nested paging */
+        vmcb->_g_pat = MSR_IA32_CR_PAT_RESET; /* guest PAT */
+        vmcb->_h_cr3 = pagetable_get_paddr(
+            p2m_get_pagetable(p2m_get_hostp2m(v->domain)));
 
         /* No point in intercepting CR3 reads/writes. */
-        vmcb->cr_intercepts &= ~(CR_INTERCEPT_CR3_READ|CR_INTERCEPT_CR3_WRITE);
+        vmcb->_cr_intercepts &=
+            ~(CR_INTERCEPT_CR3_READ|CR_INTERCEPT_CR3_WRITE);
 
         /*
          * No point in intercepting INVLPG if we don't have shadow pagetables
          * that need to be fixed up.
          */
-        vmcb->general1_intercepts &= ~GENERAL1_INTERCEPT_INVLPG;
+        vmcb->_general1_intercepts &= ~GENERAL1_INTERCEPT_INVLPG;
 
         /* PAT is under complete control of SVM when using nested paging. */
         svm_disable_intercept_for_msr(v, MSR_IA32_CR_PAT);
     }
     else
     {
-        vmcb->exception_intercepts |= (1U << TRAP_page_fault);
+        vmcb->_exception_intercepts |= (1U << TRAP_page_fault);
     }
 
     if ( cpu_has_pause_filter )
     {
-        vmcb->pause_filter_count = 3000;
-        vmcb->general1_intercepts |= GENERAL1_INTERCEPT_PAUSE;
-    }
+        vmcb->_pause_filter_count = 3000;
+        vmcb->_general1_intercepts |= GENERAL1_INTERCEPT_PAUSE;
+    }
+
+    vmcb->cleanbits.bytes = 0;
 
     return 0;
 }
@@ -309,6 +314,7 @@ static void svm_dump_sel(char *name, svm
            (unsigned long long)s->base);
 }
 
+/* This function can directly access fields which are covered by clean bits. */
 void svm_dump_vmcb(const char *from, struct vmcb_struct *vmcb)
 {
     printk("Dumping guest's current state at %s...\n", from);
@@ -317,47 +323,48 @@ void svm_dump_vmcb(const char *from, str
 
     printk("cr_intercepts = 0x%08x dr_intercepts = 0x%08x "
            "exception_intercepts = 0x%08x\n", 
-           vmcb->cr_intercepts, vmcb->dr_intercepts, 
-           vmcb->exception_intercepts);
+           vmcb->_cr_intercepts, vmcb->_dr_intercepts, 
+           vmcb->_exception_intercepts);
     printk("general1_intercepts = 0x%08x general2_intercepts = 0x%08x\n", 
-           vmcb->general1_intercepts, vmcb->general2_intercepts);
+           vmcb->_general1_intercepts, vmcb->_general2_intercepts);
     printk("iopm_base_pa = 0x%016llx msrpm_base_pa = 0x%016llx tsc_offset = "
             "0x%016llx\n", 
-           (unsigned long long) vmcb->iopm_base_pa,
-           (unsigned long long) vmcb->msrpm_base_pa,
-           (unsigned long long) vmcb->tsc_offset);
+           (unsigned long long)vmcb->_iopm_base_pa,
+           (unsigned long long)vmcb->_msrpm_base_pa,
+           (unsigned long long)vmcb->_tsc_offset);
     printk("tlb_control = 0x%08x vintr = 0x%016llx interrupt_shadow = "
             "0x%016llx\n", vmcb->tlb_control,
-           (unsigned long long) vmcb->vintr.bytes,
-           (unsigned long long) vmcb->interrupt_shadow);
+           (unsigned long long)vmcb->_vintr.bytes,
+           (unsigned long long)vmcb->interrupt_shadow);
     printk("exitcode = 0x%016llx exitintinfo = 0x%016llx\n", 
-           (unsigned long long) vmcb->exitcode,
-           (unsigned long long) vmcb->exitintinfo.bytes);
+           (unsigned long long)vmcb->exitcode,
+           (unsigned long long)vmcb->exitintinfo.bytes);
     printk("exitinfo1 = 0x%016llx exitinfo2 = 0x%016llx \n",
-           (unsigned long long) vmcb->exitinfo1,
-           (unsigned long long) vmcb->exitinfo2);
+           (unsigned long long)vmcb->exitinfo1,
+           (unsigned long long)vmcb->exitinfo2);
     printk("np_enable = 0x%016llx guest_asid = 0x%03x\n", 
-           (unsigned long long) vmcb->np_enable, vmcb->guest_asid);
+           (unsigned long long)vmcb->_np_enable, vmcb->_guest_asid);
     printk("cpl = %d efer = 0x%016llx star = 0x%016llx lstar = 0x%016llx\n", 
-           vmcb->cpl, (unsigned long long) vmcb->efer,
-           (unsigned long long) vmcb->star, (unsigned long long) vmcb->lstar);
+           vmcb->_cpl, (unsigned long long)vmcb->_efer,
+           (unsigned long long)vmcb->star, (unsigned long long)vmcb->lstar);
     printk("CR0 = 0x%016llx CR2 = 0x%016llx\n",
-           (unsigned long long) vmcb->cr0, (unsigned long long) vmcb->cr2);
+           (unsigned long long)vmcb->_cr0, (unsigned long long)vmcb->_cr2);
     printk("CR3 = 0x%016llx CR4 = 0x%016llx\n", 
-           (unsigned long long) vmcb->cr3, (unsigned long long) vmcb->cr4);
+           (unsigned long long)vmcb->_cr3, (unsigned long long)vmcb->_cr4);
     printk("RSP = 0x%016llx  RIP = 0x%016llx\n", 
-           (unsigned long long) vmcb->rsp, (unsigned long long) vmcb->rip);
+           (unsigned long long)vmcb->rsp, (unsigned long long)vmcb->rip);
     printk("RAX = 0x%016llx  RFLAGS=0x%016llx\n",
-           (unsigned long long) vmcb->rax, (unsigned long long) vmcb->rflags);
+           (unsigned long long)vmcb->rax, (unsigned long long)vmcb->rflags);
     printk("DR6 = 0x%016llx, DR7 = 0x%016llx\n", 
-           (unsigned long long) vmcb->dr6, (unsigned long long) vmcb->dr7);
+           (unsigned long long)vmcb->_dr6, (unsigned long long)vmcb->_dr7);
     printk("CSTAR = 0x%016llx SFMask = 0x%016llx\n",
-           (unsigned long long) vmcb->cstar, 
-           (unsigned long long) vmcb->sfmask);
+           (unsigned long long)vmcb->cstar, 
+           (unsigned long long)vmcb->sfmask);
     printk("KernGSBase = 0x%016llx PAT = 0x%016llx \n", 
-           (unsigned long long) vmcb->kerngsbase,
-           (unsigned long long) vmcb->g_pat);
-    printk("H_CR3 = 0x%016llx\n", (unsigned long long)vmcb->h_cr3);
+           (unsigned long long)vmcb->kerngsbase,
+           (unsigned long long)vmcb->_g_pat);
+    printk("H_CR3 = 0x%016llx CleanBits = 0x%08x\n", 
+           (unsigned long long)vmcb->_h_cr3, vmcb->cleanbits.bytes);
 
     /* print out all the selectors */
     svm_dump_sel("CS", &vmcb->cs);
diff -r 764e95f64b28 -r 8d9ca1012ffa xen/include/asm-x86/hvm/svm/svm.h
--- a/xen/include/asm-x86/hvm/svm/svm.h Wed Dec 15 14:16:03 2010 +0000
+++ b/xen/include/asm-x86/hvm/svm/svm.h Wed Dec 15 16:34:11 2010 +0000
@@ -68,12 +68,14 @@ extern u32 svm_feature_flags;
 #define SVM_FEATURE_LBRV    1
 #define SVM_FEATURE_SVML    2
 #define SVM_FEATURE_NRIPS   3
+#define SVM_FEATURE_CLEAN   5
 #define SVM_FEATURE_PAUSEF  10
 
 #define cpu_has_svm_npt     test_bit(SVM_FEATURE_NPT, &svm_feature_flags)
 #define cpu_has_svm_lbrv    test_bit(SVM_FEATURE_LBRV, &svm_feature_flags)
 #define cpu_has_svm_svml    test_bit(SVM_FEATURE_SVML, &svm_feature_flags)
 #define cpu_has_svm_nrips   test_bit(SVM_FEATURE_NRIPS, &svm_feature_flags)
+#define cpu_has_svm_cleanbits test_bit(SVM_FEATURE_CLEAN, &svm_feature_flags)
 #define cpu_has_pause_filter  test_bit(SVM_FEATURE_PAUSEF, &svm_feature_flags)
 
 #endif /* __ASM_X86_HVM_SVM_H__ */
diff -r 764e95f64b28 -r 8d9ca1012ffa xen/include/asm-x86/hvm/svm/vmcb.h
--- a/xen/include/asm-x86/hvm/svm/vmcb.h        Wed Dec 15 14:16:03 2010 +0000
+++ b/xen/include/asm-x86/hvm/svm/vmcb.h        Wed Dec 15 16:34:11 2010 +0000
@@ -366,12 +366,44 @@ typedef union
     } fields;
 } __attribute__ ((packed)) lbrctrl_t;
 
+typedef union
+{
+    uint32_t bytes;
+    struct
+    {
+        /* cr_intercepts, dr_intercepts, exception_intercepts,
+         * general{1,2}_intercepts, pause_filter_count, tsc_offset */
+        uint32_t intercepts: 1;
+        /* iopm_base_pa, msrpm_base_pa */
+        uint32_t iopm: 1;
+        /* guest_asid */
+        uint32_t asid: 1;
+        /* vintr */
+        uint32_t tpr: 1;
+        /* np_enable, h_cr3, g_pat */
+        uint32_t np: 1;
+        /* cr0, cr3, cr4, efer */
+        uint32_t cr: 1;
+        /* dr6, dr7 */
+        uint32_t dr: 1;
+        /* gdtr, idtr */
+        uint32_t dt: 1;
+        /* cs, ds, es, ss, cpl */
+        uint32_t seg: 1;
+        /* cr2 */
+        uint32_t cr2: 1;
+        /* debugctlmsr, last{branch,int}{to,from}ip */
+        uint32_t lbr: 1;
+        uint32_t resv: 21;
+    } fields;
+} __attribute__ ((packed)) vmcbcleanbits_t;
+
 struct vmcb_struct {
-    u32 cr_intercepts;          /* offset 0x00 */
-    u32 dr_intercepts;          /* offset 0x04 */
-    u32 exception_intercepts;   /* offset 0x08 */
-    u32 general1_intercepts;    /* offset 0x0C */
-    u32 general2_intercepts;    /* offset 0x10 */
+    u32 _cr_intercepts;         /* offset 0x00 - cleanbit 0 */
+    u32 _dr_intercepts;         /* offset 0x04 - cleanbit 0 */
+    u32 _exception_intercepts;  /* offset 0x08 - cleanbit 0 */
+    u32 _general1_intercepts;   /* offset 0x0C - cleanbit 0 */
+    u32 _general2_intercepts;   /* offset 0x10 - cleanbit 0 */
     u32 res01;                  /* offset 0x14 */
     u64 res02;                  /* offset 0x18 */
     u64 res03;                  /* offset 0x20 */
@@ -379,49 +411,50 @@ struct vmcb_struct {
     u64 res05;                  /* offset 0x30 */
     u32 res06;                  /* offset 0x38 */
     u16 res06a;                 /* offset 0x3C */
-    u16 pause_filter_count;     /* offset 0x3E */
-    u64 iopm_base_pa;           /* offset 0x40 */
-    u64 msrpm_base_pa;          /* offset 0x48 */
-    u64 tsc_offset;             /* offset 0x50 */
-    u32 guest_asid;             /* offset 0x58 */
+    u16 _pause_filter_count;    /* offset 0x3E - cleanbit 0 */
+    u64 _iopm_base_pa;          /* offset 0x40 - cleanbit 1 */
+    u64 _msrpm_base_pa;         /* offset 0x48 - cleanbit 1 */
+    u64 _tsc_offset;            /* offset 0x50 - cleanbit 0 */
+    u32 _guest_asid;            /* offset 0x58 - cleanbit 2 */
     u8  tlb_control;            /* offset 0x5C */
     u8  res07[3];
-    vintr_t vintr;              /* offset 0x60 */
+    vintr_t _vintr;             /* offset 0x60 - cleanbit 3 */
     u64 interrupt_shadow;       /* offset 0x68 */
     u64 exitcode;               /* offset 0x70 */
     u64 exitinfo1;              /* offset 0x78 */
     u64 exitinfo2;              /* offset 0x80 */
     eventinj_t  exitintinfo;    /* offset 0x88 */
-    u64 np_enable;              /* offset 0x90 */
+    u64 _np_enable;             /* offset 0x90 - cleanbit 4 */
     u64 res08[2];
     eventinj_t  eventinj;       /* offset 0xA8 */
-    u64 h_cr3;                  /* offset 0xB0 */
+    u64 _h_cr3;                 /* offset 0xB0 - cleanbit 4 */
     lbrctrl_t lbr_control;      /* offset 0xB8 */
-    u64 res09;                  /* offset 0xC0 */
+    vmcbcleanbits_t cleanbits;  /* offset 0xC0 */
+    u32 res09;                  /* offset 0xC4 */
     u64 nextrip;                /* offset 0xC8 */
     u64 res10a[102];            /* offset 0xD0 pad to save area */
 
-    svm_segment_register_t es;      /* offset 1024 */
-    svm_segment_register_t cs;
-    svm_segment_register_t ss;
-    svm_segment_register_t ds;
+    svm_segment_register_t es;  /* offset 1024 - cleanbit 8 */
+    svm_segment_register_t cs;  /* cleanbit 8 */
+    svm_segment_register_t ss;  /* cleanbit 8 */
+    svm_segment_register_t ds;  /* cleanbit 8 */
     svm_segment_register_t fs;
     svm_segment_register_t gs;
-    svm_segment_register_t gdtr;
+    svm_segment_register_t gdtr; /* cleanbit 7 */
     svm_segment_register_t ldtr;
-    svm_segment_register_t idtr;
+    svm_segment_register_t idtr; /* cleanbit 7 */
     svm_segment_register_t tr;
     u64 res10[5];
     u8 res11[3];
-    u8 cpl;
+    u8 _cpl;                    /* cleanbit 8 */
     u32 res12;
-    u64 efer;                   /* offset 1024 + 0xD0 */
+    u64 _efer;                  /* offset 1024 + 0xD0  - cleanbit 5 */
     u64 res13[14];
-    u64 cr4;                    /* loffset 1024 + 0x148 */
-    u64 cr3;
-    u64 cr0;
-    u64 dr7;
-    u64 dr6;
+    u64 _cr4;                   /* offset 1024 + 0x148 - cleanbit 5 */
+    u64 _cr3;                   /* cleanbit 5 */
+    u64 _cr0;                   /* cleanbit 5 */
+    u64 _dr7;                   /* cleanbit 6 */
+    u64 _dr6;                   /* cleanbit 6 */
     u64 rflags;
     u64 rip;
     u64 res14[11];
@@ -436,17 +469,17 @@ struct vmcb_struct {
     u64 sysenter_cs;
     u64 sysenter_esp;
     u64 sysenter_eip;
-    u64 cr2;
+    u64 _cr2;                   /* cleanbit 9 */
     u64 pdpe0;
     u64 pdpe1;
     u64 pdpe2;
     u64 pdpe3;
-    u64 g_pat;
-    u64 debugctlmsr;
-    u64 lastbranchfromip;
-    u64 lastbranchtoip;
-    u64 lastintfromip;
-    u64 lastinttoip;
+    u64 _g_pat;                 /* cleanbit 4 */
+    u64 _debugctlmsr;           /* cleanbit 10 */
+    u64 _lastbranchfromip;      /* cleanbit 10 */
+    u64 _lastbranchtoip;        /* cleanbit 10 */
+    u64 _lastintfromip;         /* cleanbit 10 */
+    u64 _lastinttoip;           /* cleanbit 10 */
     u64 res16[301];
 } __attribute__ ((packed));
 
@@ -485,6 +518,58 @@ void svm_intercept_msr(struct vcpu *v, u
 void svm_intercept_msr(struct vcpu *v, uint32_t msr, int enable);
 #define svm_disable_intercept_for_msr(v, msr) svm_intercept_msr((v), (msr), 0)
 #define svm_enable_intercept_for_msr(v, msr) svm_intercept_msr((v), (msr), 1)
+
+/*
+ * VMCB accessor functions.
+ */
+
+#define VMCB_ACCESSORS(_type, _name, _cleanbit)                             \
+static inline void vmcb_set_##_name(struct vmcb_struct *vmcb, _type value)  \
+{                                                                           \
+    vmcb->_##_name = value;                                                 \
+    vmcb->cleanbits.fields._cleanbit = 0;                                   \
+}                                                                           \
+static inline _type vmcb_get_##_name(struct vmcb_struct *vmcb)              \
+{                                                                           \
+    return vmcb->_##_name;                                                  \
+}
+
+VMCB_ACCESSORS(u32, cr_intercepts, intercepts)
+VMCB_ACCESSORS(u32, dr_intercepts, intercepts)
+VMCB_ACCESSORS(u32, exception_intercepts, intercepts)
+VMCB_ACCESSORS(u32, general1_intercepts, intercepts)
+VMCB_ACCESSORS(u32, general2_intercepts, intercepts)
+VMCB_ACCESSORS(u16, pause_filter_count, intercepts)
+VMCB_ACCESSORS(u64, tsc_offset, intercepts)
+VMCB_ACCESSORS(u64, iopm_base_pa, iopm)
+VMCB_ACCESSORS(u64, msrpm_base_pa, iopm)
+VMCB_ACCESSORS(u32, guest_asid, asid)
+VMCB_ACCESSORS(vintr_t, vintr, tpr)
+VMCB_ACCESSORS(u64, np_enable, np)
+VMCB_ACCESSORS(u64, h_cr3, np)
+VMCB_ACCESSORS(u64, g_pat, np)
+VMCB_ACCESSORS(u64, cr0, cr)
+VMCB_ACCESSORS(u64, cr3, cr)
+VMCB_ACCESSORS(u64, cr4, cr)
+VMCB_ACCESSORS(u64, efer, cr)
+VMCB_ACCESSORS(u64, dr6, dr)
+VMCB_ACCESSORS(u64, dr7, dr)
+/* Updates are all via hvm_set_segment_register(). */
+/* VMCB_ACCESSORS(svm_segment_register_t, gdtr, dt) */
+/* VMCB_ACCESSORS(svm_segment_register_t, idtr, dt) */
+/* VMCB_ACCESSORS(svm_segment_register_t, cs, seg) */
+/* VMCB_ACCESSORS(svm_segment_register_t, ds, seg) */
+/* VMCB_ACCESSORS(svm_segment_register_t, es, seg) */
+/* VMCB_ACCESSORS(svm_segment_register_t, ss, seg) */
+VMCB_ACCESSORS(u8, cpl, seg)
+VMCB_ACCESSORS(u64, cr2, cr2)
+VMCB_ACCESSORS(u64, debugctlmsr, lbr)
+VMCB_ACCESSORS(u64, lastbranchfromip, lbr)
+VMCB_ACCESSORS(u64, lastbranchtoip, lbr)
+VMCB_ACCESSORS(u64, lastintfromip, lbr)
+VMCB_ACCESSORS(u64, lastinttoip, lbr)
+
+#undef VMCB_ACCESSORS
 
 #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] [xen-unstable] svm: support VMCB cleanbits, Xen patchbot-unstable <=