# HG changeset patch
# User Travis Betak <travis.betak@xxxxxxx>
# Date 1173133045 21600
# Node ID 437774e497353b4b87249c3a07a644b7d35c8cfd
# Parent e85f685fb99f5f6badd4f14b848247c4d95a5353
[SVM] Remove SVM cpu_state and add EFER shadow to svm structure.
The SVM cpu state was being used inconsistently and, besides, it makes
more sense to instead rely on the guest's shadow registers to determine
the current guest state.
Signed-off-by: Travis Betak <travis.betak@xxxxxxx>
---
xen/arch/x86/hvm/svm/svm.c | 90 +++++++++++++++++++------------------
xen/include/asm-x86/hvm/svm/vmcb.h | 16 +-----
2 files changed, 52 insertions(+), 54 deletions(-)
diff -r e85f685fb99f -r 437774e49735 xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c Mon Mar 05 22:42:13 2007 +0000
+++ b/xen/arch/x86/hvm/svm/svm.c Mon Mar 05 16:17:25 2007 -0600
@@ -148,30 +148,34 @@ static void svm_store_cpu_guest_regs(
}
}
+static int svm_lme_is_set(struct vcpu *v)
+{
+ u64 guest_efer = v->arch.hvm_svm.cpu_shadow_efer;
+ return guest_efer & EFER_LME;
+}
+
+static int svm_cr4_pae_is_set(struct vcpu *v)
+{
+ unsigned long guest_cr4 = v->arch.hvm_svm.cpu_shadow_cr4;
+ return guest_cr4 & X86_CR4_PAE;
+}
+
static int svm_paging_enabled(struct vcpu *v)
{
- unsigned long cr0;
-
- cr0 = v->arch.hvm_svm.cpu_shadow_cr0;
-
- return (cr0 & X86_CR0_PE) && (cr0 & X86_CR0_PG);
+ unsigned long guest_cr0 = v->arch.hvm_svm.cpu_shadow_cr0;
+ return (guest_cr0 & X86_CR0_PE) && (guest_cr0 & X86_CR0_PG);
}
static int svm_pae_enabled(struct vcpu *v)
{
- unsigned long cr4;
-
- if(!svm_paging_enabled(v))
- return 0;
-
- cr4 = v->arch.hvm_svm.cpu_shadow_cr4;
-
- return (cr4 & X86_CR4_PAE);
+ unsigned long guest_cr4 = v->arch.hvm_svm.cpu_shadow_cr4;
+ return svm_paging_enabled(v) && (guest_cr4 & X86_CR4_PAE);
}
static int svm_long_mode_enabled(struct vcpu *v)
{
- return test_bit(SVM_CPU_STATE_LMA_ENABLED, &v->arch.hvm_svm.cpu_state);
+ u64 guest_efer = v->arch.hvm_svm.cpu_shadow_efer;
+ return guest_efer & EFER_LMA;
}
static inline int long_mode_do_msr_read(struct cpu_user_regs *regs)
@@ -257,18 +261,22 @@ static inline int long_mode_do_msr_write
#ifdef __x86_64__
/* LME: 0 -> 1 */
- if ( msr_content & EFER_LME &&
- !test_bit(SVM_CPU_STATE_LME_ENABLED, &v->arch.hvm_svm.cpu_state))
+ if ( (msr_content & EFER_LME)
+ && !svm_lme_is_set(v) )
{
+ /*
+ * setting EFER.LME is illegal if the guest currently has
+ * enabled or CR4.PAE is not set
+ */
if ( svm_paging_enabled(v) ||
- !test_bit(SVM_CPU_STATE_PAE_ENABLED,
- &v->arch.hvm_svm.cpu_state) )
+ !svm_cr4_pae_is_set(v) )
{
gdprintk(XENLOG_WARNING, "Trying to set LME bit when "
"in paging mode or PAE bit is not set\n");
goto gp_fault;
}
- set_bit(SVM_CPU_STATE_LME_ENABLED, &v->arch.hvm_svm.cpu_state);
+
+ v->arch.hvm_svm.cpu_shadow_efer |= EFER_LME;
}
/* We have already recorded that we want LME, so it will be set
@@ -468,22 +476,25 @@ int svm_vmcb_restore(struct vcpu *v, str
c->cr4);
#endif
- if (!svm_paging_enabled(v)) {
+ if ( !svm_paging_enabled(v) )
+ {
printk("%s: paging not enabled.", __func__);
goto skip_cr3;
}
- if (c->cr3 == v->arch.hvm_svm.cpu_cr3) {
+ if ( c->cr3 == v->arch.hvm_svm.cpu_cr3 )
+ {
/*
* This is simple TLB flush, implying the guest has
* removed some translation or changed page attributes.
* We simply invalidate the shadow.
*/
mfn = gmfn_to_mfn(v->domain, c->cr3 >> PAGE_SHIFT);
- if (mfn != pagetable_get_pfn(v->arch.guest_table)) {
+ if ( mfn != pagetable_get_pfn(v->arch.guest_table) )
goto bad_cr3;
- }
- } else {
+ }
+ else
+ {
/*
* If different, make a shadow. Check if the PDBR is valid
* first.
@@ -491,9 +502,9 @@ int svm_vmcb_restore(struct vcpu *v, str
HVM_DBG_LOG(DBG_LEVEL_VMMU, "CR3 c->cr3 = %"PRIx64"", c->cr3);
/* current!=vcpu as not called by arch_vmx_do_launch */
mfn = gmfn_to_mfn(v->domain, c->cr3 >> PAGE_SHIFT);
- if( !mfn_valid(mfn) || !get_page(mfn_to_page(mfn), v->domain)) {
+ if( !mfn_valid(mfn) || !get_page(mfn_to_page(mfn), v->domain) )
goto bad_cr3;
- }
+
old_base_mfn = pagetable_get_pfn(v->arch.guest_table);
v->arch.guest_table = pagetable_from_pfn(mfn);
if (old_base_mfn)
@@ -1727,7 +1738,8 @@ static int svm_set_cr0(unsigned long val
HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR0 value = %lx\n", value);
- if ((value & X86_CR0_PE) && (value & X86_CR0_PG) && !paging_enabled)
+ if ( ((value & (X86_CR0_PE | X86_CR0_PG)) == (X86_CR0_PE | X86_CR0_PG))
+ && !paging_enabled )
{
/* The guest CR3 must be pointing to the guest physical. */
mfn = get_mfn_from_gpfn(v->arch.hvm_svm.cpu_cr3 >> PAGE_SHIFT);
@@ -1740,18 +1752,16 @@ static int svm_set_cr0(unsigned long val
}
#if defined(__x86_64__)
- if (test_bit(SVM_CPU_STATE_LME_ENABLED, &v->arch.hvm_svm.cpu_state)
- && !test_bit(SVM_CPU_STATE_PAE_ENABLED,
- &v->arch.hvm_svm.cpu_state))
+ if ( svm_lme_is_set(v) && !svm_cr4_pae_is_set(v) )
{
HVM_DBG_LOG(DBG_LEVEL_1, "Enable paging before PAE enable\n");
svm_inject_exception(v, TRAP_gp_fault, 1, 0);
}
- if (test_bit(SVM_CPU_STATE_LME_ENABLED, &v->arch.hvm_svm.cpu_state))
+ if ( svm_lme_is_set(v) )
{
HVM_DBG_LOG(DBG_LEVEL_1, "Enable the Long mode\n");
- set_bit(SVM_CPU_STATE_LMA_ENABLED, &v->arch.hvm_svm.cpu_state);
+ v->arch.hvm_svm.cpu_shadow_efer |= EFER_LMA;
vmcb->efer |= EFER_LMA | EFER_LME;
}
#endif /* __x86_64__ */
@@ -1791,7 +1801,7 @@ static int svm_set_cr0(unsigned long val
if ( svm_long_mode_enabled(v) )
{
vmcb->efer &= ~EFER_LMA;
- clear_bit(SVM_CPU_STATE_LMA_ENABLED, &v->arch.hvm_svm.cpu_state);
+ v->arch.hvm_svm.cpu_shadow_efer &= ~EFER_LMA;
}
/* we should take care of this kind of situation */
paging_update_paging_modes(v);
@@ -1933,7 +1943,6 @@ static int mov_to_cr(int gpreg, int cr,
old_cr = v->arch.hvm_svm.cpu_shadow_cr4;
if ( value & X86_CR4_PAE && !(old_cr & X86_CR4_PAE) )
{
- set_bit(SVM_CPU_STATE_PAE_ENABLED, &v->arch.hvm_svm.cpu_state);
if ( svm_pgbit_test(v) )
{
/* The guest is a 32-bit PAE guest. */
@@ -1962,15 +1971,13 @@ static int mov_to_cr(int gpreg, int cr,
v->arch.hvm_svm.cpu_cr3, mfn);
#endif
}
- }
- else 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)) {
+ }
+ else if ( !(value & X86_CR4_PAE) )
+ {
+ if ( svm_long_mode_enabled(v) )
+ {
svm_inject_exception(v, TRAP_gp_fault, 1, 0);
}
- clear_bit(SVM_CPU_STATE_PAE_ENABLED, &v->arch.hvm_svm.cpu_state);
}
v->arch.hvm_svm.cpu_shadow_cr4 = value;
@@ -2369,7 +2376,6 @@ static int svm_do_vmmcall_reset_to_realm
vmcb->cr4 = SVM_CR4_HOST_MASK;
v->arch.hvm_svm.cpu_shadow_cr4 = 0;
- clear_bit(SVM_CPU_STATE_PAE_ENABLED, &v->arch.hvm_svm.cpu_state);
/* This will jump to ROMBIOS */
vmcb->rip = 0xFFF0;
diff -r e85f685fb99f -r 437774e49735 xen/include/asm-x86/hvm/svm/vmcb.h
--- a/xen/include/asm-x86/hvm/svm/vmcb.h Mon Mar 05 22:42:13 2007 +0000
+++ b/xen/include/asm-x86/hvm/svm/vmcb.h Mon Mar 05 16:17:25 2007 -0600
@@ -302,14 +302,6 @@ enum VMEXIT_EXITCODE
VMEXIT_NPF = 1024, /* nested paging fault */
VMEXIT_INVALID = -1
};
-
-enum {
- SVM_CPU_STATE_PG_ENABLED=0,
- SVM_CPU_STATE_PAE_ENABLED,
- SVM_CPU_STATE_LME_ENABLED,
- SVM_CPU_STATE_LMA_ENABLED,
- SVM_CPU_STATE_ASSIST_ENABLED,
-};
/* Definitions of segment state are borrowed by the generic HVM code. */
typedef segment_attributes_t svm_segment_attributes_t;
@@ -457,12 +449,12 @@ struct arch_svm_struct {
int saved_irq_vector;
u32 launch_core;
- unsigned long flags; /* VMCB flags */
- unsigned long cpu_shadow_cr0; /* Guest value for CR0 */
- unsigned long cpu_shadow_cr4; /* Guest value for CR4 */
+ unsigned long flags; /* VMCB flags */
+ unsigned long cpu_shadow_cr0; /* Guest value for CR0 */
+ unsigned long cpu_shadow_cr4; /* Guest value for CR4 */
+ unsigned long cpu_shadow_efer; /* Guest value for EFER */
unsigned long cpu_cr2;
unsigned long cpu_cr3;
- unsigned long cpu_state;
};
struct vmcb_struct *alloc_vmcb(void);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|