# 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
|