aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xen/arch/x86/hvm/hvm.c52
-rw-r--r--xen/arch/x86/hvm/i8254.c2
-rw-r--r--xen/arch/x86/hvm/i8259.c9
-rw-r--r--xen/arch/x86/hvm/io.c31
-rw-r--r--xen/arch/x86/hvm/svm/emulate.c4
-rw-r--r--xen/arch/x86/hvm/svm/intr.c46
-rw-r--r--xen/arch/x86/hvm/svm/svm.c411
-rw-r--r--xen/arch/x86/hvm/svm/vmcb.c167
-rw-r--r--xen/arch/x86/hvm/svm/x86_32/exits.S8
-rw-r--r--xen/arch/x86/hvm/svm/x86_64/exits.S17
-rw-r--r--xen/arch/x86/hvm/vlapic.c2
-rw-r--r--xen/arch/x86/hvm/vmx/io.c88
-rw-r--r--xen/arch/x86/hvm/vmx/vmcs.c10
-rw-r--r--xen/arch/x86/hvm/vmx/vmx.c51
-rw-r--r--xen/arch/x86/hvm/vmx/x86_32/exits.S2
-rw-r--r--xen/arch/x86/hvm/vmx/x86_64/exits.S2
-rw-r--r--xen/arch/x86/x86_32/asm-offsets.c1
-rw-r--r--xen/arch/x86/x86_64/asm-offsets.c1
-rw-r--r--xen/include/asm-x86/hvm/hvm.h12
-rw-r--r--xen/include/asm-x86/hvm/io.h1
-rw-r--r--xen/include/asm-x86/hvm/svm/svm.h46
-rw-r--r--xen/include/asm-x86/hvm/svm/vmcb.h17
-rw-r--r--xen/include/asm-x86/hvm/vmx/vmcs.h1
-rw-r--r--xen/include/asm-x86/hvm/vmx/vmx.h25
-rw-r--r--xen/include/asm-x86/processor.h58
-rw-r--r--xen/include/asm-x86/system.h4
26 files changed, 526 insertions, 542 deletions
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 3e1cfa44d2..6c254e2a61 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -199,6 +199,55 @@ void hvm_create_event_channels(struct vcpu *v)
}
}
+
+void hvm_stts(struct vcpu *v)
+{
+ /* FPU state already dirty? Then no need to setup_fpu() lazily. */
+ if ( test_bit(_VCPUF_fpu_dirtied, &v->vcpu_flags) )
+ return;
+
+ hvm_funcs.stts(v);
+}
+
+void hvm_set_guest_time(struct vcpu *v, u64 gtime)
+{
+ u64 host_tsc;
+
+ rdtscll(host_tsc);
+
+ v->arch.hvm_vcpu.cache_tsc_offset = gtime - host_tsc;
+ hvm_funcs.set_tsc_offset(v, v->arch.hvm_vcpu.cache_tsc_offset);
+}
+
+void hvm_do_resume(struct vcpu *v)
+{
+ ioreq_t *p;
+ struct periodic_time *pt =
+ &v->domain->arch.hvm_domain.pl_time.periodic_tm;
+
+ hvm_stts(v);
+
+ /* pick up the elapsed PIT ticks and re-enable pit_timer */
+ if ( pt->enabled && pt->first_injected ) {
+ if ( v->arch.hvm_vcpu.guest_time ) {
+ hvm_set_guest_time(v, v->arch.hvm_vcpu.guest_time);
+ v->arch.hvm_vcpu.guest_time = 0;
+ }
+ pickup_deactive_ticks(pt);
+ }
+
+ p = &get_vio(v->domain, v->vcpu_id)->vp_ioreq;
+ wait_on_xen_event_channel(v->arch.hvm.xen_port,
+ p->state != STATE_IOREQ_READY &&
+ p->state != STATE_IOREQ_INPROCESS);
+ if ( p->state == STATE_IORESP_READY )
+ hvm_io_assist(v);
+ if ( p->state != STATE_INVALID ) {
+ printf("Weird HVM iorequest state %d.\n", p->state);
+ domain_crash(v->domain);
+ }
+}
+
void hvm_release_assist_channel(struct vcpu *v)
{
free_xen_event_channel(v, v->arch.hvm_vcpu.xen_port);
@@ -299,8 +348,7 @@ int cpu_get_interrupt(struct vcpu *v, int *type)
/*
* Copy from/to guest virtual.
*/
-int
-hvm_copy(void *buf, unsigned long vaddr, int size, int dir)
+int hvm_copy(void *buf, unsigned long vaddr, int size, int dir)
{
unsigned long mfn;
char *addr;
diff --git a/xen/arch/x86/hvm/i8254.c b/xen/arch/x86/hvm/i8254.c
index de2d5d3b94..6b817293b9 100644
--- a/xen/arch/x86/hvm/i8254.c
+++ b/xen/arch/x86/hvm/i8254.c
@@ -389,7 +389,7 @@ void pit_init(struct vcpu *v, unsigned long cpu_khz)
register_portio_handler(PIT_BASE, 4, handle_pit_io);
/* register the speaker port */
register_portio_handler(0x61, 1, handle_speaker_io);
- ticks_per_sec(v) = cpu_khz * (int64_t)1000;
+ ticks_per_sec(v) = cpu_khz * (int64_t)1000;
#ifdef DEBUG_PIT
printk("HVM_PIT: guest frequency =%lld\n", (long long)ticks_per_sec(v));
#endif
diff --git a/xen/arch/x86/hvm/i8259.c b/xen/arch/x86/hvm/i8259.c
index 1dbef23741..b2cdfdb9d9 100644
--- a/xen/arch/x86/hvm/i8259.c
+++ b/xen/arch/x86/hvm/i8259.c
@@ -480,7 +480,6 @@ void pic_init(struct hvm_virpic *s, void (*irq_request)(void *, int),
s->pics[1].elcr_mask = 0xde;
s->irq_request = irq_request;
s->irq_request_opaque = irq_request_opaque;
- return;
}
void pic_set_alt_irq_func(struct hvm_virpic *s,
@@ -568,10 +567,10 @@ static int intercept_elcr_io(ioreq_t *p)
}
void register_pic_io_hook (void)
{
- register_portio_handler(0x20, 2, intercept_pic_io);
- register_portio_handler(0x4d0, 1, intercept_elcr_io);
- register_portio_handler(0xa0, 2, intercept_pic_io);
- register_portio_handler(0x4d1, 1, intercept_elcr_io);
+ register_portio_handler(0x20, 2, intercept_pic_io);
+ register_portio_handler(0x4d0, 1, intercept_elcr_io);
+ register_portio_handler(0xa0, 2, intercept_pic_io);
+ register_portio_handler(0x4d1, 1, intercept_elcr_io);
}
diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c
index dec35b2f55..abb6b62d22 100644
--- a/xen/arch/x86/hvm/io.c
+++ b/xen/arch/x86/hvm/io.c
@@ -668,6 +668,37 @@ static void hvm_mmio_assist(struct cpu_user_regs *regs, ioreq_t *p,
}
}
+void hvm_interrupt_post(struct vcpu *v, int vector, int type)
+{
+ struct periodic_time *pt =
+ &(v->domain->arch.hvm_domain.pl_time.periodic_tm);
+
+ if ( is_pit_irq(v, vector, type) ) {
+ if ( !pt->first_injected ) {
+ pt->pending_intr_nr = 0;
+ pt->last_plt_gtime = hvm_get_guest_time(v);
+ pt->scheduled = NOW() + pt->period;
+ set_timer(&pt->timer, pt->scheduled);
+ pt->first_injected = 1;
+ } else {
+ pt->pending_intr_nr--;
+ pt->last_plt_gtime += pt->period_cycles;
+ hvm_set_guest_time(v, pt->last_plt_gtime);
+ pit_time_fired(v, pt->priv);
+ }
+ }
+
+ switch(type) {
+ case APIC_DM_EXTINT:
+ break;
+
+ default:
+ vlapic_post_injection(v, vector, type);
+ break;
+ }
+}
+
+
void hvm_io_assist(struct vcpu *v)
{
vcpu_iodata_t *vio;
diff --git a/xen/arch/x86/hvm/svm/emulate.c b/xen/arch/x86/hvm/svm/emulate.c
index 916a332783..194a8be7fc 100644
--- a/xen/arch/x86/hvm/svm/emulate.c
+++ b/xen/arch/x86/hvm/svm/emulate.c
@@ -78,7 +78,7 @@ static inline unsigned long DECODE_GPR_VALUE(struct vmcb_struct *vmcb,
case 0x4:
value = (unsigned long)vmcb->rsp;
case 0x5:
- value = regs->ebp;
+ value = regs->ebp;
break;
case 0x6:
value = regs->esi;
@@ -429,7 +429,7 @@ 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)
{
- unsigned int inst_len = 0;
+ unsigned int inst_len = 0;
unsigned int i;
unsigned int j;
int found = 0;
diff --git a/xen/arch/x86/hvm/svm/intr.c b/xen/arch/x86/hvm/svm/intr.c
index a2767df2ed..d0b5c2d6ce 100644
--- a/xen/arch/x86/hvm/svm/intr.c
+++ b/xen/arch/x86/hvm/svm/intr.c
@@ -42,48 +42,6 @@
* Most of this code is copied from vmx_io.c and modified
* to be suitable for SVM.
*/
-#define BSP_CPU(v) (!(v->vcpu_id))
-
-void svm_set_guest_time(struct vcpu *v, u64 gtime)
-{
- u64 host_tsc;
-
- rdtscll(host_tsc);
-
- v->arch.hvm_vcpu.cache_tsc_offset = gtime - host_tsc;
- v->arch.hvm_svm.vmcb->tsc_offset = v->arch.hvm_vcpu.cache_tsc_offset;
-}
-
-static inline void
-interrupt_post_injection(struct vcpu * v, int vector, int type)
-{
- struct periodic_time *pt = &(v->domain->arch.hvm_domain.pl_time.periodic_tm);
-
- if ( is_pit_irq(v, vector, type) ) {
- if ( !pt->first_injected ) {
- pt->pending_intr_nr = 0;
- pt->last_plt_gtime = hvm_get_guest_time(v);
- pt->scheduled = NOW() + pt->period;
- set_timer(&pt->timer, pt->scheduled);
- pt->first_injected = 1;
- } else {
- pt->pending_intr_nr--;
- pt->last_plt_gtime += pt->period_cycles;
- svm_set_guest_time(v, pt->last_plt_gtime);
- pit_time_fired(v, pt->priv);
- }
- }
-
- switch(type)
- {
- case APIC_DM_EXTINT:
- break;
-
- default:
- vlapic_post_injection(v, vector, type);
- break;
- }
-}
static inline int svm_inject_extint(struct vcpu *v, int trap, int error_code)
{
@@ -109,7 +67,7 @@ asmlinkage void svm_intr_assist(void)
{
struct vcpu *v = current;
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
- struct hvm_domain *plat=&v->domain->arch.hvm_domain;
+ struct hvm_domain *plat=&v->domain->arch.hvm_domain;
struct periodic_time *pt = &plat->pl_time.periodic_tm;
struct hvm_virpic *pic= &plat->vpic;
int callback_irq;
@@ -194,7 +152,7 @@ asmlinkage void svm_intr_assist(void)
/* let's inject this interrupt */
TRACE_3D(TRC_VMX_INT, v->domain->domain_id, intr_vector, 0);
svm_inject_extint(v, intr_vector, VMX_DELIVER_NO_ERROR_CODE);
- interrupt_post_injection(v, intr_vector, intr_type);
+ hvm_interrupt_post(v, intr_vector, intr_type);
break;
case APIC_DM_SMI:
case APIC_DM_NMI:
diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index e38a2fa3d1..3f6c66407c 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -54,8 +54,7 @@
#define set_segment_register(name, value) \
__asm__ __volatile__ ( "movw %%ax ,%%" STR(name) "" : : "a" (value) )
-/*
- * External functions, etc. We should move these to some suitable header file(s) */
+/* External functions. We should move these to some suitable header file(s) */
extern void do_nmi(struct cpu_user_regs *, unsigned long);
extern int inst_copy_from_guest(unsigned char *buf, unsigned long guest_eip,
@@ -72,12 +71,32 @@ static void svm_relinquish_guest_resources(struct domain *d);
static int svm_do_vmmcall_reset_to_realmode(struct vcpu *v,
struct cpu_user_regs *regs);
+/* va of hardware host save area */
+static void *hsa[NR_CPUS] __read_mostly;
+/* vmcb used for extended host state */
+static void *root_vmcb[NR_CPUS] __read_mostly;
-extern void set_hsa_to_guest( struct arch_svm_struct *arch_svm );
+/* physical address of above for host VMSAVE/VMLOAD */
+u64 root_vmcb_pa[NR_CPUS] __read_mostly;
+
+
+/* ASID API */
+enum {
+ ASID_AVAILABLE = 0,
+ ASID_INUSE,
+ ASID_RETIRED
+};
+#define INITIAL_ASID 0
+#define ASID_MAX 64
+
+struct asid_pool {
+ spinlock_t asid_lock;
+ u32 asid[ASID_MAX];
+};
+
+static DEFINE_PER_CPU(struct asid_pool, asid_pool);
-/* Host save area and ASID glogal data */
-struct svm_percore_globals svm_globals[NR_CPUS];
/*
* Initializes the POOL of ASID used by the guests per core.
@@ -86,25 +105,25 @@ void asidpool_init(int core)
{
int i;
- spin_lock_init(&svm_globals[core].ASIDpool.asid_lock);
+ spin_lock_init(&per_cpu(asid_pool,core).asid_lock);
/* Host ASID is always in use */
- svm_globals[core].ASIDpool.asid[INITIAL_ASID] = ASID_INUSE;
+ per_cpu(asid_pool,core).asid[INITIAL_ASID] = ASID_INUSE;
for ( i = 1; i < ASID_MAX; i++ )
- svm_globals[core].ASIDpool.asid[i] = ASID_AVAILABLE;
+ per_cpu(asid_pool,core).asid[i] = ASID_AVAILABLE;
}
/* internal function to get the next available ASID */
static int asidpool_fetch_next(struct vmcb_struct *vmcb, int core)
{
- int i;
+ int i;
for ( i = 1; i < ASID_MAX; i++ )
{
- if ( svm_globals[core].ASIDpool.asid[i] == ASID_AVAILABLE )
+ if ( per_cpu(asid_pool,core).asid[i] == ASID_AVAILABLE )
{
vmcb->guest_asid = i;
- svm_globals[core].ASIDpool.asid[i] = ASID_INUSE;
+ per_cpu(asid_pool,core).asid[i] = ASID_INUSE;
return i;
}
}
@@ -125,43 +144,46 @@ static int asidpool_fetch_next(struct vmcb_struct *vmcb, int core)
int asidpool_assign_next( struct vmcb_struct *vmcb, int retire_current,
int oldcore, int newcore )
{
- int i;
+ int i;
int res = 1;
static unsigned long cnt=0;
- spin_lock(&svm_globals[oldcore].ASIDpool.asid_lock);
+ spin_lock(&per_cpu(asid_pool,oldcore).asid_lock);
if( retire_current && vmcb->guest_asid ) {
- svm_globals[oldcore].ASIDpool.asid[ vmcb->guest_asid & (ASID_MAX-1) ] = ASID_RETIRED;
+ per_cpu(asid_pool,oldcore).asid[vmcb->guest_asid & (ASID_MAX-1)] =
+ ASID_RETIRED;
}
- spin_unlock(&svm_globals[oldcore].ASIDpool.asid_lock);
- spin_lock(&svm_globals[newcore].ASIDpool.asid_lock);
+ spin_unlock(&per_cpu(asid_pool,oldcore).asid_lock);
+ spin_lock(&per_cpu(asid_pool,newcore).asid_lock);
if( asidpool_fetch_next( vmcb, newcore ) < 0 ) {
if (svm_dbg_on)
printk( "SVM: tlb(%ld)\n", cnt++ );
/* FLUSH the TLB and all retired slots are made available */
vmcb->tlb_control = 1;
for( i = 1; i < ASID_MAX; i++ ) {
- if( svm_globals[newcore].ASIDpool.asid[i] == ASID_RETIRED ) {
- svm_globals[newcore].ASIDpool.asid[i] = ASID_AVAILABLE;
+ if( per_cpu(asid_pool,newcore).asid[i] == ASID_RETIRED ) {
+ per_cpu(asid_pool,newcore).asid[i] = ASID_AVAILABLE;
}
}
/* Get the First slot available */
res = asidpool_fetch_next( vmcb, newcore ) > 0;
}
- spin_unlock(&svm_globals[newcore].ASIDpool.asid_lock);
+ spin_unlock(&per_cpu(asid_pool,newcore).asid_lock);
return res;
}
void asidpool_retire( struct vmcb_struct *vmcb, int core )
{
- spin_lock(&svm_globals[core].ASIDpool.asid_lock);
+ spin_lock(&per_cpu(asid_pool,core).asid_lock);
if( vmcb->guest_asid ) {
- svm_globals[core].ASIDpool.asid[ vmcb->guest_asid & (ASID_MAX-1) ] = ASID_RETIRED;
+ per_cpu(asid_pool,core).asid[vmcb->guest_asid & (ASID_MAX-1)] =
+ ASID_RETIRED;
}
- spin_unlock(&svm_globals[core].ASIDpool.asid_lock);
+ spin_unlock(&per_cpu(asid_pool,core).asid_lock);
}
-static inline void svm_inject_exception(struct vcpu *v, int trap, int ev, int error_code)
+static inline void svm_inject_exception(struct vcpu *v, int trap,
+ int ev, int error_code)
{
eventinj_t event;
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
@@ -178,7 +200,7 @@ static inline void svm_inject_exception(struct vcpu *v, int trap, int ev, int er
vmcb->eventinj = event;
}
-void stop_svm(void)
+static void stop_svm(void)
{
u32 eax, edx;
int cpu = smp_processor_id();
@@ -189,22 +211,18 @@ void stop_svm(void)
wrmsr(MSR_EFER, eax, edx);
/* release the HSA */
- free_host_save_area( svm_globals[cpu].hsa );
- free_host_save_area( svm_globals[cpu].scratch_hsa );
- svm_globals[cpu].hsa = NULL;
- svm_globals[cpu].hsa_pa = 0;
- svm_globals[cpu].scratch_hsa = NULL;
- svm_globals[cpu].scratch_hsa_pa = 0;
+ free_host_save_area(hsa[cpu]);
+ hsa[cpu] = NULL;
wrmsr(MSR_K8_VM_HSAVE_PA, 0, 0 );
+ /* free up the root vmcb */
+ free_vmcb(root_vmcb[cpu]);
+ root_vmcb[cpu] = NULL;
+ root_vmcb_pa[cpu] = 0;
+
printk("AMD SVM Extension is disabled.\n");
}
-int svm_initialize_guest_resources(struct vcpu *v)
-{
- svm_final_setup_guest(v);
- return 1;
-}
static void svm_store_cpu_guest_regs(
struct vcpu *v, struct cpu_user_regs *regs, unsigned long *crs)
@@ -233,12 +251,16 @@ static void svm_store_cpu_guest_regs(
}
}
-static void svm_load_cpu_guest_regs(
- struct vcpu *v, struct cpu_user_regs *regs)
+static int svm_paging_enabled(struct vcpu *v)
{
- svm_load_cpu_user_regs(v, regs);
+ unsigned long cr0;
+
+ cr0 = v->arch.hvm_svm.cpu_shadow_cr0;
+
+ return (cr0 & X86_CR0_PE) && (cr0 & X86_CR0_PG);
}
+
#define IS_CANO_ADDRESS(add) 1
static inline int long_mode_do_msr_read(struct cpu_user_regs *regs)
@@ -281,7 +303,6 @@ static inline int long_mode_do_msr_read(struct cpu_user_regs *regs)
case MSR_SYSCALL_MASK:
msr_content = vmcb->sfmask;
break;
-
default:
return 0;
}
@@ -296,7 +317,7 @@ static inline int long_mode_do_msr_read(struct cpu_user_regs *regs)
static inline int long_mode_do_msr_write(struct cpu_user_regs *regs)
{
- u64 msr_content = regs->eax | ((u64)regs->edx << 32);
+ u64 msr_content = regs->eax | ((u64)regs->edx << 32);
struct vcpu *vc = current;
struct vmcb_struct *vmcb = vc->arch.hvm_svm.vmcb;
@@ -318,7 +339,7 @@ static inline int long_mode_do_msr_write(struct cpu_user_regs *regs)
/* LME: 0 -> 1 */
if ( msr_content & EFER_LME &&
- !test_bit(SVM_CPU_STATE_LME_ENABLED, &vc->arch.hvm_svm.cpu_state) )
+ !test_bit(SVM_CPU_STATE_LME_ENABLED, &vc->arch.hvm_svm.cpu_state))
{
if ( svm_paging_enabled(vc) ||
!test_bit(SVM_CPU_STATE_PAE_ENABLED,
@@ -385,7 +406,7 @@ static inline int long_mode_do_msr_write(struct cpu_user_regs *regs)
return 1;
}
-int svm_realmode(struct vcpu *v)
+static int svm_realmode(struct vcpu *v)
{
unsigned long cr0 = v->arch.hvm_svm.cpu_shadow_cr0;
unsigned long eflags = v->arch.hvm_svm.vmcb->rflags;
@@ -393,7 +414,7 @@ int svm_realmode(struct vcpu *v)
return (eflags & X86_EFLAGS_VM) || !(cr0 & X86_CR0_PE);
}
-int svm_instruction_length(struct vcpu *v)
+static int svm_instruction_length(struct vcpu *v)
{
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
unsigned long cr0 = vmcb->cr0, eflags = vmcb->rflags, mode;
@@ -405,7 +426,7 @@ int svm_instruction_length(struct vcpu *v)
return svm_instrlen(guest_cpu_user_regs(), mode);
}
-unsigned long svm_get_ctrl_reg(struct vcpu *v, unsigned int num)
+static unsigned long svm_get_ctrl_reg(struct vcpu *v, unsigned int num)
{
switch ( num )
{
@@ -422,9 +443,34 @@ unsigned long svm_get_ctrl_reg(struct vcpu *v, unsigned int num)
}
+/* Make sure that xen intercepts any FP accesses from current */
+static void svm_stts(struct vcpu *v)
+{
+ struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
+
+ /*
+ * If the guest does not have TS enabled then we must cause and handle an
+ * exception on first use of the FPU. If the guest *does* have TS enabled
+ * then this is not necessary: no FPU activity can occur until the guest
+ * clears CR0.TS, and we will initialise the FPU when that happens.
+ */
+ if ( !(v->arch.hvm_svm.cpu_shadow_cr0 & X86_CR0_TS) )
+ {
+ v->arch.hvm_svm.vmcb->exception_intercepts |= EXCEPTION_BITMAP_NM;
+ vmcb->cr0 |= X86_CR0_TS;
+ }
+}
+
+
+static void svm_set_tsc_offset(struct vcpu *v, u64 offset)
+{
+ v->arch.hvm_svm.vmcb->tsc_offset = offset;
+}
+
+
/* SVM-specific intitialization code for VCPU application processors */
-void svm_init_ap_context(struct vcpu_guest_context *ctxt,
- int vcpuid, int trampoline_vector)
+static void svm_init_ap_context(struct vcpu_guest_context *ctxt,
+ int vcpuid, int trampoline_vector)
{
int i;
struct vcpu *v, *bsp = current;
@@ -453,7 +499,7 @@ void svm_init_ap_context(struct vcpu_guest_context *ctxt,
* the code. We will execute this code in real mode.
*/
ctxt->user_regs.eip = 0x0;
- ctxt->user_regs.cs = (trampoline_vector << 8);
+ ctxt->user_regs.cs = (trampoline_vector << 8);
ctxt->flags = VGCF_HVM_GUEST;
}
@@ -479,60 +525,8 @@ static void svm_init_hypercall_page(struct domain *d, void *hypercall_page)
*(u16 *)(hypercall_page + (__HYPERVISOR_iret * 32)) = 0x0b0f; /* ud2 */
}
-int start_svm(void)
-{
- u32 eax, ecx, edx;
- u32 phys_hsa_lo, phys_hsa_hi;
- u64 phys_hsa;
- int cpu = smp_processor_id();
-
- /* Xen does not fill x86_capability words except 0. */
- ecx = cpuid_ecx(0x80000001);
- boot_cpu_data.x86_capability[5] = ecx;
-
- if (!(test_bit(X86_FEATURE_SVME, &boot_cpu_data.x86_capability)))
- return 0;
- svm_globals[cpu].hsa = alloc_host_save_area();
- if (! svm_globals[cpu].hsa)
- return 0;
-
- rdmsr(MSR_EFER, eax, edx);
- eax |= EFER_SVME;
- wrmsr(MSR_EFER, eax, edx);
- asidpool_init( cpu );
- printk("AMD SVM Extension is enabled for cpu %d.\n", cpu );
-
- /* Initialize the HSA for this core */
- phys_hsa = (u64) virt_to_maddr( svm_globals[cpu].hsa );
- phys_hsa_lo = (u32) phys_hsa;
- phys_hsa_hi = (u32) (phys_hsa >> 32);
- wrmsr(MSR_K8_VM_HSAVE_PA, phys_hsa_lo, phys_hsa_hi);
- svm_globals[cpu].hsa_pa = phys_hsa;
-
- svm_globals[cpu].scratch_hsa = alloc_host_save_area();
- svm_globals[cpu].scratch_hsa_pa = (u64)virt_to_maddr( svm_globals[cpu].scratch_hsa );
-
- /* Setup HVM interfaces */
- hvm_funcs.disable = stop_svm;
-
- hvm_funcs.initialize_guest_resources = svm_initialize_guest_resources;
- hvm_funcs.relinquish_guest_resources = svm_relinquish_guest_resources;
- hvm_funcs.store_cpu_guest_regs = svm_store_cpu_guest_regs;
- hvm_funcs.load_cpu_guest_regs = svm_load_cpu_guest_regs;
- 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_funcs.init_ap_context = svm_init_ap_context;
-
- hvm_funcs.init_hypercall_page = svm_init_hypercall_page;
-
- hvm_enabled = 1;
-
- return 1;
-}
int svm_dbg_on = 0;
@@ -596,7 +590,7 @@ static inline int svm_do_debugout(unsigned long exit_code)
return 1;
}
-void save_svm_cpu_user_regs(struct vcpu *v, struct cpu_user_regs *ctxt)
+static void save_svm_cpu_user_regs(struct vcpu *v, struct cpu_user_regs *ctxt)
{
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
@@ -615,7 +609,7 @@ void save_svm_cpu_user_regs(struct vcpu *v, struct cpu_user_regs *ctxt)
ctxt->ds = vmcb->ds.sel;
}
-void svm_store_cpu_user_regs(struct cpu_user_regs *regs, struct vcpu *v)
+static void svm_store_cpu_user_regs(struct cpu_user_regs *regs, struct vcpu *v)
{
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
@@ -629,7 +623,7 @@ void svm_store_cpu_user_regs(struct cpu_user_regs *regs, struct vcpu *v)
}
/* XXX Use svm_load_cpu_guest_regs instead */
-void svm_load_cpu_user_regs(struct vcpu *v, struct cpu_user_regs *regs)
+static void svm_load_cpu_user_regs(struct vcpu *v, struct cpu_user_regs *regs)
{
struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
u32 *intercepts = &v->arch.hvm_svm.vmcb->exception_intercepts;
@@ -647,37 +641,13 @@ void svm_load_cpu_user_regs(struct vcpu *v, struct cpu_user_regs *regs)
*intercepts &= ~EXCEPTION_BITMAP_DB;
}
-int svm_paging_enabled(struct vcpu *v)
+static void svm_load_cpu_guest_regs(
+ struct vcpu *v, struct cpu_user_regs *regs)
{
- unsigned long cr0;
-
- cr0 = v->arch.hvm_svm.cpu_shadow_cr0;
-
- return (cr0 & X86_CR0_PE) && (cr0 & X86_CR0_PG);
+ svm_load_cpu_user_regs(v, regs);
}
-/* Make sure that xen intercepts any FP accesses from current */
-void svm_stts(struct vcpu *v)
-{
- struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb;
-
- /* FPU state already dirty? Then no need to setup_fpu() lazily. */
- if ( test_bit(_VCPUF_fpu_dirtied, &v->vcpu_flags) )
- return;
-
- /*
- * If the guest does not have TS enabled then we must cause and handle an
- * exception on first use of the FPU. If the guest *does* have TS enabled
- * then this is not necessary: no FPU activity can occur until the guest
- * clears CR0.TS, and we will initialise the FPU when that happens.
- */
- if ( !(v->arch.hvm_svm.cpu_shadow_cr0 & X86_CR0_TS) )
- {
- v->arch.hvm_svm.vmcb->exception_intercepts |= EXCEPTION_BITMAP_NM;
- vmcb->cr0 |= X86_CR0_TS;
- }
-}
static void arch_svm_do_launch(struct vcpu *v)
{
@@ -708,9 +678,9 @@ static void arch_svm_do_launch(struct vcpu *v)
{
u16 cs_sel = regs->cs;
/*
- * This is the launch of an AP; set state so that we begin executing
+ * This is the launch of an AP; set state so that we begin executing
* the trampoline code in real-mode.
- */
+ */
svm_do_vmmcall_reset_to_realmode(v, regs);
/* Adjust the state to execute the trampoline code.*/
v->arch.hvm_svm.vmcb->rip = 0;
@@ -731,6 +701,7 @@ static void svm_freeze_time(struct vcpu *v)
}
}
+
static void svm_ctxt_switch_from(struct vcpu *v)
{
svm_freeze_time(v);
@@ -738,7 +709,7 @@ static void svm_ctxt_switch_from(struct vcpu *v)
static void svm_ctxt_switch_to(struct vcpu *v)
{
-#if __x86_64__
+#ifdef __x86_64__
/*
* This is required, because VMRUN does consistency check
* and some of the DOM0 selectors are pointing to
@@ -751,7 +722,8 @@ static void svm_ctxt_switch_to(struct vcpu *v)
#endif
}
-void svm_final_setup_guest(struct vcpu *v)
+
+static void svm_final_setup_guest(struct vcpu *v)
{
struct domain *d = v->domain;
struct vcpu *vc;
@@ -778,15 +750,82 @@ void svm_final_setup_guest(struct vcpu *v)
* Put the domain in shadow mode even though we're going to be using
* the shared 1:1 page table initially. It shouldn't hurt
*/
- shadow_mode_enable(d,
- SHM_enable|SHM_refcounts|
+ shadow_mode_enable(d, SHM_enable|SHM_refcounts|
SHM_translate|SHM_external|SHM_wr_pt_pte);
}
+static int svm_initialize_guest_resources(struct vcpu *v)
+{
+ svm_final_setup_guest(v);
+ return 1;
+}
+
+
+int start_svm(void)
+{
+ u32 eax, ecx, edx;
+ u32 phys_hsa_lo, phys_hsa_hi;
+ u64 phys_hsa;
+ int cpu = smp_processor_id();
+
+ /* Xen does not fill x86_capability words except 0. */
+ ecx = cpuid_ecx(0x80000001);
+ boot_cpu_data.x86_capability[5] = ecx;
+
+ if (!(test_bit(X86_FEATURE_SVME, &boot_cpu_data.x86_capability)))
+ return 0;
+
+ if (!(hsa[cpu] = alloc_host_save_area()))
+ return 0;
+
+ rdmsr(MSR_EFER, eax, edx);
+ eax |= EFER_SVME;
+ wrmsr(MSR_EFER, eax, edx);
+ asidpool_init( cpu );
+ printk("AMD SVM Extension is enabled for cpu %d.\n", cpu );
+
+ /* Initialize the HSA for this core */
+ phys_hsa = (u64) virt_to_maddr(hsa[cpu]);
+ phys_hsa_lo = (u32) phys_hsa;
+ phys_hsa_hi = (u32) (phys_hsa >> 32);
+ wrmsr(MSR_K8_VM_HSAVE_PA, phys_hsa_lo, phys_hsa_hi);
+
+ if (!(root_vmcb[cpu] = alloc_vmcb()))
+ return 0;
+ root_vmcb_pa[cpu] = virt_to_maddr(root_vmcb[cpu]);
+
+ if (cpu == 0)
+ setup_vmcb_dump();
+
+ /* Setup HVM interfaces */
+ hvm_funcs.disable = stop_svm;
+
+ hvm_funcs.initialize_guest_resources = svm_initialize_guest_resources;
+ hvm_funcs.relinquish_guest_resources = svm_relinquish_guest_resources;
+
+ hvm_funcs.store_cpu_guest_regs = svm_store_cpu_guest_regs;
+ hvm_funcs.load_cpu_guest_regs = svm_load_cpu_guest_regs;
+
+ 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_funcs.stts = svm_stts;
+ hvm_funcs.set_tsc_offset = svm_set_tsc_offset;
+
+ hvm_funcs.init_ap_context = svm_init_ap_context;
+ hvm_funcs.init_hypercall_page = svm_init_hypercall_page;
+
+ hvm_enabled = 1;
+
+ return 1;
+}
+
+
static void svm_relinquish_guest_resources(struct domain *d)
{
- extern void destroy_vmcb(struct arch_svm_struct *); /* XXX */
struct vcpu *v;
for_each_vcpu ( d, v )
@@ -817,11 +856,25 @@ static void svm_relinquish_guest_resources(struct domain *d)
}
+static void svm_migrate_timers(struct vcpu *v)
+{
+ struct periodic_time *pt =
+ &(v->domain->arch.hvm_domain.pl_time.periodic_tm);
+
+ if ( pt->enabled ) {
+ migrate_timer( &pt->timer, v->processor );
+ migrate_timer( &v->arch.hvm_svm.hlt_timer, v->processor );
+ }
+ if ( hvm_apic_support(v->domain) && VLAPIC( v ))
+ migrate_timer( &(VLAPIC(v)->vlapic_timer ), v->processor );
+}
+
+
void arch_svm_do_resume(struct vcpu *v)
{
/* pinning VCPU to a different core? */
if ( v->arch.hvm_svm.launch_core == smp_processor_id()) {
- svm_do_resume( v );
+ hvm_do_resume( v );
reset_stack_and_jump( svm_asm_do_resume );
}
else {
@@ -830,24 +883,12 @@ void arch_svm_do_resume(struct vcpu *v)
v->arch.hvm_svm.launch_core, smp_processor_id() );
v->arch.hvm_svm.launch_core = smp_processor_id();
svm_migrate_timers( v );
- svm_do_resume( v );
+ hvm_do_resume( v );
reset_stack_and_jump( svm_asm_do_resume );
}
}
-void svm_migrate_timers(struct vcpu *v)
-{
- struct periodic_time *pt = &(v->domain->arch.hvm_domain.pl_time.periodic_tm);
-
- if ( pt->enabled ) {
- migrate_timer( &pt->timer, v->processor );
- migrate_timer( &v->arch.hvm_svm.hlt_timer, v->processor );
- }
- if ( hvm_apic_support(v->domain) && VLAPIC( v ))
- migrate_timer( &(VLAPIC(v)->vlapic_timer ), v->processor );
-}
-
static int svm_do_page_fault(unsigned long va, struct cpu_user_regs *regs)
{
@@ -888,7 +929,7 @@ static int svm_do_page_fault(unsigned long va, struct cpu_user_regs *regs)
inst_len = svm_instruction_length(v);
if (inst_len == -1)
{
- printf("%s: INST_LEN - Unable to decode properly.\n", __func__);
+ printf("%s: INST_LEN - Unable to decode properly\n", __func__);
domain_crash_synchronous();
}
@@ -1137,7 +1178,7 @@ static inline unsigned long *get_reg_p(unsigned int gpreg,
case SVM_REG_ESP:
reg_p = (unsigned long *)&vmcb->rsp;
break;
-#if __x86_64__
+#ifdef __x86_64__
case SVM_REG_R8:
reg_p = (unsigned long *)&regs->r8;
break;
@@ -1195,7 +1236,7 @@ static void svm_dr_access (struct vcpu *v, unsigned int reg, unsigned int type,
unsigned long *reg_p = 0;
unsigned int gpreg = 0;
unsigned long eip;
- int inst_len;
+ int inst_len;
int index;
struct vmcb_struct *vmcb;
u8 buffer[MAX_INST_LEN];
@@ -1264,7 +1305,7 @@ static void svm_get_prefix_info(
case 0xf2: /* REPNZ */
case 0xf0: /* LOCK */
case 0x66: /* data32 */
-#if __x86_64__
+#ifdef __x86_64__
/* REX prefixes */
case 0x40:
case 0x41:
@@ -1330,7 +1371,7 @@ static inline int svm_get_io_address(
info.bytes = vmcb->exitinfo1;
- /* If we're in long mode, we shouldn't check the segment presence and limit */
+ /* If we're in long mode, we shouldn't check the segment presence & limit */
long_mode = vmcb->cs.attributes.fields.l && vmcb->efer & EFER_LMA;
/* d field of cs.attributes is 1 for 32-bit, 0 for 16 or 64 bit.
@@ -1832,7 +1873,8 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
* arch->shadow_table should hold the next CR3 for shadow
*/
- HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx, mfn = %lx",
+ HVM_DBG_LOG(DBG_LEVEL_VMMU,
+ "Update CR3 value = %lx, mfn = %lx",
v->arch.hvm_svm.cpu_cr3, mfn);
#endif
}
@@ -1847,7 +1889,7 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
* it must enable PG after that, and it is a 32-bit PAE
* guest */
- if ( !shadow_set_guest_paging_levels(v->domain, PAGING_L3) )
+ if ( !shadow_set_guest_paging_levels(v->domain, PAGING_L3))
{
printk("Unsupported guest paging levels\n");
domain_crash_synchronous();
@@ -1855,8 +1897,7 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs)
}
else
{
- if ( !shadow_set_guest_paging_levels(v->domain,
- PAGING_L4) )
+ if ( !shadow_set_guest_paging_levels(v->domain, PAGING_L4))
{
printk("Unsupported guest paging levels\n");
domain_crash_synchronous();
@@ -1920,9 +1961,9 @@ static int svm_cr_access(struct vcpu *v, unsigned int cr, unsigned int type,
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
- */
+
+ /* 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)
@@ -2071,7 +2112,7 @@ static inline void svm_do_msr_access(
switch (regs->ecx)
{
case MSR_IA32_TIME_STAMP_COUNTER:
- svm_set_guest_time(v, msr_content);
+ hvm_set_guest_time(v, msr_content);
break;
case MSR_IA32_SYSENTER_CS:
vmcb->sysenter_cs = msr_content;
@@ -2116,7 +2157,7 @@ static inline void svm_vmexit_do_hlt(struct vmcb_struct *vmcb)
/* check for interrupt not handled or new interrupt */
if ( vmcb->vintr.fields.irq || cpu_has_pending_irq(v) )
- return;
+ return;
if ( !v->vcpu_id )
next_pit = get_scheduled(v, pt->irq, pt);
@@ -2138,8 +2179,8 @@ static void svm_vmexit_do_invd(struct vmcb_struct *vmcb)
* have cache-snooping that solves it anyways. -- Mats P.
*/
- /* Tell the user that we did this - just in case someone runs some really weird
- * operating system and wants to know why it's not working as it should...
+ /* Tell the user that we did this - just in case someone runs some really
+ * weird operating system and wants to know why it's not working...
*/
printk("INVD instruction intercepted - ignored\n");
@@ -2198,7 +2239,8 @@ void svm_handle_invlpg(const short invlpga, struct cpu_user_regs *regs)
*/
if (inst_copy_from_guest(opcode, svm_rip2pointer(vmcb), length) < length)
{
- printk("svm_handle_invlpg (): Error reading memory %d bytes\n", length);
+ printk("svm_handle_invlpg (): Error reading memory %d bytes\n",
+ length);
__hvm_bug(regs);
}
@@ -2463,7 +2505,7 @@ void svm_dump_host_regs(const char *from)
__asm__ __volatile__ ("\tmov %%cr0,%0\n"
"\tmov %%cr3,%1\n"
- : "=r" (cr0), "=r"(cr3));
+ : "=r" (cr0), "=r"(cr3));
printf("%s: pt = %lx, cr3 = %lx, cr0 = %lx\n", __func__, pt, cr3, cr0);
}
@@ -2626,18 +2668,22 @@ void walk_shadow_and_guest_pt(unsigned long gva)
spte = l1e_empty();
- /* This is actually overkill - we only need to make sure the hl2 is in-sync. */
+ /* This is actually overkill - we only need to ensure the hl2 is in-sync.*/
shadow_sync_va(v, gva);
gpte.l1 = 0;
- __copy_from_user(&gpte, &linear_pg_table[ l1_linear_offset(gva) ], sizeof(gpte) );
+ __copy_from_user(&gpte, &linear_pg_table[ l1_linear_offset(gva) ],
+ sizeof(gpte) );
printk( "G-PTE = %x, flags=%x\n", gpte.l1, l1e_get_flags(gpte) );
- __copy_from_user( &spte, &phys_to_machine_mapping[ l1e_get_pfn( gpte ) ],
+ __copy_from_user( &spte, &phys_to_machine_mapping[ l1e_get_pfn( gpte ) ],
sizeof(spte) );
printk( "S-PTE = %x, flags=%x\n", spte.l1, l1e_get_flags(spte));
}
#endif /* SVM_WALK_GUEST_PAGES */
+
+
+
asmlinkage void svm_vmexit_handler(struct cpu_user_regs regs)
{
unsigned int exit_reason;
@@ -2654,6 +2700,13 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs regs)
vmcb->tlb_control = 1;
+
+ if (exit_reason == VMEXIT_INVALID)
+ {
+ svm_dump_vmcb(__func__, vmcb);
+ domain_crash_synchronous();
+ }
+
#ifdef SVM_EXTRA_DEBUG
{
#if defined(__i386__)
@@ -2666,8 +2719,8 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs regs)
{
if (svm_paging_enabled(v) && !mmio_space(gva_to_gpa(vmcb->exitinfo2)))
{
- printk("I%08ld,ExC=%s(%d),IP=%x:%llx,I1=%llx,I2=%llx,INT=%llx, gpa=%llx\n",
- intercepts_counter,
+ printk("I%08ld,ExC=%s(%d),IP=%x:%llx,I1=%llx,I2=%llx,INT=%llx, "
+ "gpa=%llx\n", intercepts_counter,
exit_reasons[exit_reason], exit_reason, regs.cs,
(unsigned long long) regs.rip,
(unsigned long long) vmcb->exitinfo1,
@@ -2750,13 +2803,6 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs regs)
}
#endif /* SVM_EXTRA_DEBUG */
- if (exit_reason == -1)
- {
- svm_dump_vmcb(__func__, vmcb);
- printk("%s: exit_reason == -1 - Did someone clobber the VMCB\n",
- __func__);
- domain_crash_synchronous();
- }
perfc_incra(svmexits, exit_reason);
eip = vmcb->rip;
@@ -3011,7 +3057,7 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs regs)
#ifdef SVM_EXTRA_DEBUG
if (do_debug)
{
- printk("%s: Done switch on vmexit_code\n", __func__);
+ printk("%s: Done switch on vmexit_code\n", __func__);
svm_dump_regs(__func__, &regs);
}
@@ -3058,9 +3104,6 @@ asmlinkage void svm_asid(void)
v->arch.hvm_svm.asid_core = v->arch.hvm_svm.launch_core;
clear_bit( ARCH_SVM_VMCB_ASSIGN_ASID, &v->arch.hvm_svm.flags );
}
-
- /* make sure the HSA is set for the current core */
- set_hsa_to_guest( &v->arch.hvm_svm );
}
/*
diff --git a/xen/arch/x86/hvm/svm/vmcb.c b/xen/arch/x86/hvm/svm/vmcb.c
index 7a644c351a..e2b11730ed 100644
--- a/xen/arch/x86/hvm/svm/vmcb.c
+++ b/xen/arch/x86/hvm/svm/vmcb.c
@@ -35,72 +35,61 @@
#include <xen/event.h>
#include <xen/kernel.h>
#include <xen/domain_page.h>
+#include <xen/keyhandler.h>
-extern struct svm_percore_globals svm_globals[];
extern int svm_dbg_on;
extern int asidpool_assign_next( struct vmcb_struct *vmcb, int retire_current,
int oldcore, int newcore);
-extern void set_hsa_to_guest( struct arch_svm_struct *arch_svm );
-
-#define round_pgdown(_p) ((_p)&PAGE_MASK) /* coped from domain.c */
#define GUEST_SEGMENT_LIMIT 0xffffffff
#define IOPM_SIZE (12 * 1024)
#define MSRPM_SIZE (8 * 1024)
+/* VMCBs and HSAs are architecturally defined to be a 4K page each */
+#define VMCB_ORDER 0
+#define HSA_ORDER 0
+
+
struct vmcb_struct *alloc_vmcb(void)
{
- struct vmcb_struct *vmcb = NULL;
- unsigned int order;
- order = get_order_from_bytes(sizeof(struct vmcb_struct));
- ASSERT(order >= 0);
- vmcb = alloc_xenheap_pages(order);
- ASSERT(vmcb);
+ struct vmcb_struct *vmcb = alloc_xenheap_pages(VMCB_ORDER);
- if (vmcb)
- memset(vmcb, 0, sizeof(struct vmcb_struct));
+ if (!vmcb) {
+ printk("Warning: failed to allocate vmcb.\n");
+ return NULL;
+ }
+ memset(vmcb, 0, (PAGE_SIZE << VMCB_ORDER));
return vmcb;
}
void free_vmcb(struct vmcb_struct *vmcb)
{
- unsigned int order;
-
- order = get_order_from_bytes(sizeof(struct vmcb_struct));
ASSERT(vmcb);
-
- if (vmcb)
- free_xenheap_pages(vmcb, order);
+ free_xenheap_pages(vmcb, VMCB_ORDER);
}
struct host_save_area *alloc_host_save_area(void)
{
- unsigned int order = 0;
- struct host_save_area *hsa = NULL;
-
- hsa = alloc_xenheap_pages(order);
- ASSERT(hsa);
+ struct host_save_area *hsa = alloc_xenheap_pages(HSA_ORDER);
- if (hsa)
- memset(hsa, 0, PAGE_SIZE);
+ if (!hsa) {
+ printk("Warning: failed to allocate vmcb.\n");
+ return NULL;
+ }
+ memset(hsa, 0, (PAGE_SIZE << HSA_ORDER));
return hsa;
}
void free_host_save_area(struct host_save_area *hsa)
{
- unsigned int order;
-
- order = get_order_from_bytes(PAGE_SIZE);
ASSERT(hsa);
-
- if (hsa)
- free_xenheap_pages(hsa, order);
+ free_xenheap_pages(hsa, HSA_ORDER);
}
@@ -187,7 +176,7 @@ static int construct_init_vmcb_guest(struct arch_svm_struct *arch_svm,
vmcb->cs.sel = regs->cs;
vmcb->es.sel = regs->es;
vmcb->ss.sel = regs->ss;
- vmcb->ds.sel = regs->ds;
+ vmcb->ds.sel = regs->ds;
vmcb->fs.sel = regs->fs;
vmcb->gs.sel = regs->gs;
@@ -221,7 +210,7 @@ static int construct_init_vmcb_guest(struct arch_svm_struct *arch_svm,
attrib.fields.g = 1; /* 4K pages in limit */
/* Data selectors */
- vmcb->es.attributes = attrib;
+ vmcb->es.attributes = attrib;
vmcb->ss.attributes = attrib;
vmcb->ds.attributes = attrib;
vmcb->fs.attributes = attrib;
@@ -257,7 +246,7 @@ static int construct_init_vmcb_guest(struct arch_svm_struct *arch_svm,
/* CR3 is set in svm_final_setup_guest */
- __asm__ __volatile__ ("mov %%cr4,%0" : "=r" (crn) :);
+ __asm__ __volatile__ ("mov %%cr4,%0" : "=r" (crn) :);
crn &= ~(X86_CR4_PGE | X86_CR4_PSE | X86_CR4_PAE);
arch_svm->cpu_shadow_cr4 = crn;
vmcb->cr4 = crn | SVM_CR4_HOST_MASK;
@@ -306,7 +295,8 @@ void destroy_vmcb(struct arch_svm_struct *arch_svm)
* construct the vmcb.
*/
-int construct_vmcb(struct arch_svm_struct *arch_svm, struct cpu_user_regs *regs)
+int construct_vmcb(struct arch_svm_struct *arch_svm,
+ struct cpu_user_regs *regs)
{
int error;
long rc=0;
@@ -320,7 +310,9 @@ int construct_vmcb(struct arch_svm_struct *arch_svm, struct cpu_user_regs *regs)
}
/* update the HSA for the current Core */
+#if 0
set_hsa_to_guest( arch_svm );
+#endif
arch_svm->vmcb_pa = (u64) virt_to_maddr(arch_svm->vmcb);
if ((error = construct_vmcb_controls(arch_svm)))
@@ -359,7 +351,7 @@ void svm_do_launch(struct vcpu *v)
ASSERT(vmcb);
/* Update CR3, GDT, LDT, TR */
- svm_stts(v);
+ hvm_stts(v);
/* current core is the one we intend to perform the VMRUN on */
v->arch.hvm_svm.launch_core = v->arch.hvm_svm.asid_core = core;
@@ -393,10 +385,8 @@ void svm_do_launch(struct vcpu *v)
printk("%s: phys_table = %lx\n", __func__, pt);
}
- if ( svm_paging_enabled(v) )
- vmcb->cr3 = pagetable_get_paddr(v->arch.guest_table);
- else
- vmcb->cr3 = pagetable_get_paddr(v->domain->arch.phys_table);
+ /* At launch we always use the phys_table */
+ vmcb->cr3 = pagetable_get_paddr(v->domain->arch.phys_table);
if (svm_dbg_on)
{
@@ -410,7 +400,7 @@ void svm_do_launch(struct vcpu *v)
v->arch.hvm_svm.saved_irq_vector = -1;
- svm_set_guest_time(v, 0);
+ hvm_set_guest_time(v, 0);
if (svm_dbg_on)
svm_dump_vmcb(__func__, vmcb);
@@ -419,61 +409,12 @@ void svm_do_launch(struct vcpu *v)
}
-void set_hsa_to_guest( struct arch_svm_struct *arch_svm )
-{
- arch_svm->host_save_pa = svm_globals[ smp_processor_id() ].scratch_hsa_pa;
-}
-/*
- * Resume the guest.
- */
-/* XXX svm_do_resume and vmx_do_resume are remarkably similar; could
- they be unified? */
-void svm_do_resume(struct vcpu *v)
-{
- struct periodic_time *pt = &v->domain->arch.hvm_domain.pl_time.periodic_tm;
- ioreq_t *p;
-
- svm_stts(v);
-
- /* pick up the elapsed PIT ticks and re-enable pit_timer */
- if ( pt->enabled && pt->first_injected ) {
- if ( v->arch.hvm_vcpu.guest_time ) {
- svm_set_guest_time(v, v->arch.hvm_vcpu.guest_time);
- v->arch.hvm_vcpu.guest_time = 0;
- }
- pickup_deactive_ticks(pt);
- }
-
- p = &get_vio(v->domain, v->vcpu_id)->vp_ioreq;
- wait_on_xen_event_channel(v->arch.hvm.xen_port,
- p->state != STATE_IOREQ_READY &&
- p->state != STATE_IOREQ_INPROCESS);
- if ( p->state == STATE_IORESP_READY )
- hvm_io_assist(v);
- if ( p->state != STATE_INVALID ) {
- printf("Weird HVM iorequest state %d.\n", p->state);
- domain_crash(v->domain);
- }
-}
-
-void svm_launch_fail(unsigned long eflags)
-{
- BUG();
-}
-
-
-void svm_resume_fail(unsigned long eflags)
-{
- BUG();
-}
-
-
-void svm_dump_sel(char *name, segment_selector_t *s)
+static void svm_dump_sel(char *name, segment_selector_t *s)
{
printf("%s: sel=0x%04x, attr=0x%04x, limit=0x%08x, base=0x%016llx\n",
name, s->sel, s->attributes.bytes, s->limit,
- (unsigned long long)s->base);
+ (unsigned long long)s->base);
}
@@ -483,9 +424,10 @@ void svm_dump_vmcb(const char *from, struct vmcb_struct *vmcb)
printf("Size of VMCB = %d, address = %p\n",
(int) sizeof(struct vmcb_struct), vmcb);
- printf("cr_intercepts = 0x%08x dr_intercepts = 0x%08x exception_intercepts "
- "= 0x%08x\n", vmcb->cr_intercepts, vmcb->dr_intercepts,
- vmcb->exception_intercepts);
+ printf("cr_intercepts = 0x%08x dr_intercepts = 0x%08x "
+ "exception_intercepts = 0x%08x\n",
+ vmcb->cr_intercepts, vmcb->dr_intercepts,
+ vmcb->exception_intercepts);
printf("general1_intercepts = 0x%08x general2_intercepts = 0x%08x\n",
vmcb->general1_intercepts, vmcb->general2_intercepts);
printf("iopm_base_pa = %016llx msrpm_base_pa = 0x%016llx tsc_offset = "
@@ -519,7 +461,8 @@ void svm_dump_vmcb(const char *from, struct vmcb_struct *vmcb)
printf("DR6 = 0x%016llx, DR7 = 0x%016llx\n",
(unsigned long long) vmcb->dr6, (unsigned long long) vmcb->dr7);
printf("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);
printf("KernGSBase = 0x%016llx PAT = 0x%016llx \n",
(unsigned long long) vmcb->kerngsbase,
(unsigned long long) vmcb->g_pat);
@@ -537,6 +480,38 @@ void svm_dump_vmcb(const char *from, struct vmcb_struct *vmcb)
svm_dump_sel("TR", &vmcb->tr);
}
+static void vmcb_dump(unsigned char ch)
+{
+ struct domain *d;
+ struct vcpu *v;
+
+ printk("*********** VMCB Areas **************\n");
+ for_each_domain(d) {
+ printk("\n>>> Domain %d <<<\n", d->domain_id);
+ for_each_vcpu(d, v) {
+
+ /*
+ * Presumably, if a domain is not an HVM guest,
+ * the very first CPU will not pass this test
+ */
+ if (!hvm_guest(v)) {
+ printk("\t\tNot HVM guest\n");
+ break;
+ }
+ printk("\tVCPU %d\n", v->vcpu_id);
+
+ svm_dump_vmcb("key_handler", v->arch.hvm_svm.vmcb);
+ }
+ }
+
+ printk("**************************************\n");
+}
+
+void setup_vmcb_dump(void)
+{
+ register_keyhandler('v', vmcb_dump, "dump AMD-V VMCBs");
+}
+
/*
* Local variables:
* mode: C
diff --git a/xen/arch/x86/hvm/svm/x86_32/exits.S b/xen/arch/x86/hvm/svm/x86_32/exits.S
index cfd9fbbd55..c477e5262a 100644
--- a/xen/arch/x86/hvm/svm/x86_32/exits.S
+++ b/xen/arch/x86/hvm/svm/x86_32/exits.S
@@ -95,7 +95,8 @@ ENTRY(svm_asm_do_launch)
movl VCPU_svm_vmcb(%ebx), %ecx
movl 24(%esp), %eax
movl %eax, VMCB_rax(%ecx)
- movl VCPU_svm_hsa_pa(%ebx), %eax
+ movl VCPU_processor(%ebx), %eax
+ movl root_vmcb_pa(,%eax,8), %eax
VMSAVE
movl VCPU_svm_vmcb_pa(%ebx), %eax
@@ -119,7 +120,8 @@ ENTRY(svm_asm_do_launch)
GET_CURRENT(%eax)
- movl VCPU_svm_hsa_pa(%eax), %eax
+ movl VCPU_processor(%eax), %eax
+ movl root_vmcb_pa(,%eax,8), %eax
VMLOAD
HVM_SAVE_ALL_NOSEGREGS
@@ -133,7 +135,7 @@ ENTRY(svm_asm_do_resume)
svm_test_all_events:
GET_CURRENT(%ebx)
pushl %ebx
- call svm_do_resume
+ call hvm_do_resume
addl $4, %esp
/*test_all_events:*/
xorl %ecx,%ecx
diff --git a/xen/arch/x86/hvm/svm/x86_64/exits.S b/xen/arch/x86/hvm/svm/x86_64/exits.S
index b3746b529d..78a01cf61c 100644
--- a/xen/arch/x86/hvm/svm/x86_64/exits.S
+++ b/xen/arch/x86/hvm/svm/x86_64/exits.S
@@ -105,7 +105,10 @@ ENTRY(svm_asm_do_launch)
movq VCPU_svm_vmcb(%rbx), %rcx
movq UREGS_rax(%rsp), %rax
movq %rax, VMCB_rax(%rcx)
- movq VCPU_svm_hsa_pa(%rbx), %rax
+ leaq root_vmcb_pa(%rip), %rax
+ movl VCPU_processor(%rbx), %ecx
+ shll $3, %ecx
+ addq %rcx, %rax
VMSAVE
movq VCPU_svm_vmcb_pa(%rbx), %rax
@@ -133,13 +136,15 @@ ENTRY(svm_asm_do_launch)
VMLOAD
VMRUN
VMSAVE
- /* rax is the only register we're allowed to touch here... */
+ HVM_SAVE_ALL_NOSEGREGS
- GET_CURRENT(%rax)
- movq VCPU_svm_hsa_pa(%rax), %rax
+ GET_CURRENT(%rbx)
+ movl VCPU_processor(%rbx), %ecx
+ leaq root_vmcb_pa(%rip), %rax
+ shll $3, %ecx
+ addq %rcx, %rax
VMLOAD
- HVM_SAVE_ALL_NOSEGREGS
STGI
call svm_vmexit_handler
jmp svm_asm_do_resume
@@ -148,7 +153,7 @@ ENTRY(svm_asm_do_resume)
svm_test_all_events:
GET_CURRENT(%rbx)
movq %rbx, %rdi
- call svm_do_resume
+ call hvm_do_resume
/*test_all_events:*/
cli # tests must not race interrupts
/*test_softirqs:*/
diff --git a/xen/arch/x86/hvm/vlapic.c b/xen/arch/x86/hvm/vlapic.c
index f6b60b45d8..7ebca89693 100644
--- a/xen/arch/x86/hvm/vlapic.c
+++ b/xen/arch/x86/hvm/vlapic.c
@@ -493,7 +493,7 @@ static void vlapic_read_aligned(struct vlapic *vlapic, unsigned int offset,
case APIC_ESR:
vlapic->err_write_count = 0;
- *result = vlapic_get_reg(vlapic, offset);
+ *result = vlapic_get_reg(vlapic, offset);
break;
default:
diff --git a/xen/arch/x86/hvm/vmx/io.c b/xen/arch/x86/hvm/vmx/io.c
index 0d8390e792..6ac5340181 100644
--- a/xen/arch/x86/hvm/vmx/io.c
+++ b/xen/arch/x86/hvm/vmx/io.c
@@ -38,57 +38,6 @@
#include <asm/hvm/vlapic.h>
#include <public/hvm/ioreq.h>
-#define BSP_CPU(v) (!(v->vcpu_id))
-
-static inline
-void __set_tsc_offset(u64 offset)
-{
- __vmwrite(TSC_OFFSET, offset);
-#if defined (__i386__)
- __vmwrite(TSC_OFFSET_HIGH, offset >> 32);
-#endif
-}
-
-void set_guest_time(struct vcpu *v, u64 gtime)
-{
- u64 host_tsc;
-
- rdtscll(host_tsc);
-
- v->arch.hvm_vcpu.cache_tsc_offset = gtime - host_tsc;
- __set_tsc_offset(v->arch.hvm_vcpu.cache_tsc_offset);
-}
-
-static inline void
-interrupt_post_injection(struct vcpu * v, int vector, int type)
-{
- struct periodic_time *pt = &(v->domain->arch.hvm_domain.pl_time.periodic_tm);
-
- if ( is_pit_irq(v, vector, type) ) {
- if ( !pt->first_injected ) {
- pt->pending_intr_nr = 0;
- pt->last_plt_gtime = hvm_get_guest_time(v);
- pt->scheduled = NOW() + pt->period;
- set_timer(&pt->timer, pt->scheduled);
- pt->first_injected = 1;
- } else {
- pt->pending_intr_nr--;
- pt->last_plt_gtime += pt->period_cycles;
- set_guest_time(v, pt->last_plt_gtime);
- pit_time_fired(v, pt->priv);
- }
- }
-
- switch(type)
- {
- case APIC_DM_EXTINT:
- break;
-
- default:
- vlapic_post_injection(v, vector, type);
- break;
- }
-}
static inline void
enable_irq_window(struct vcpu *v)
@@ -194,7 +143,8 @@ asmlinkage void vmx_intr_assist(void)
if (likely(!has_ext_irq)) return;
- if (unlikely(is_interruptibility_state())) { /* pre-cleared for emulated instruction */
+ if (unlikely(is_interruptibility_state())) {
+ /* pre-cleared for emulated instruction */
enable_irq_window(v);
HVM_DBG_LOG(DBG_LEVEL_1, "interruptibility");
return;
@@ -206,7 +156,7 @@ asmlinkage void vmx_intr_assist(void)
return;
}
- highest_vector = cpu_get_interrupt(v, &intr_type);
+ highest_vector = cpu_get_interrupt(v, &intr_type);
switch (intr_type) {
case APIC_DM_EXTINT:
case APIC_DM_FIXED:
@@ -224,39 +174,11 @@ asmlinkage void vmx_intr_assist(void)
BUG();
break;
}
-
- interrupt_post_injection(v, highest_vector, intr_type);
+
+ hvm_interrupt_post(v, highest_vector, intr_type);
return;
}
-void vmx_do_resume(struct vcpu *v)
-{
- ioreq_t *p;
- struct periodic_time *pt = &v->domain->arch.hvm_domain.pl_time.periodic_tm;
-
- vmx_stts();
-
- /* pick up the elapsed PIT ticks and re-enable pit_timer */
- if ( pt->enabled && pt->first_injected ) {
- if ( v->arch.hvm_vcpu.guest_time ) {
- set_guest_time(v, v->arch.hvm_vcpu.guest_time);
- v->arch.hvm_vcpu.guest_time = 0;
- }
- pickup_deactive_ticks(pt);
- }
-
- p = &get_vio(v->domain, v->vcpu_id)->vp_ioreq;
- wait_on_xen_event_channel(v->arch.hvm.xen_port,
- p->state != STATE_IOREQ_READY &&
- p->state != STATE_IOREQ_INPROCESS);
- if ( p->state == STATE_IORESP_READY )
- hvm_io_assist(v);
- if ( p->state != STATE_INVALID ) {
- printf("Weird HVM iorequest state %d.\n", p->state);
- domain_crash(v->domain);
- }
-}
-
/*
* Local variables:
* mode: C
diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c
index 0a5b7fff72..288c2ac034 100644
--- a/xen/arch/x86/hvm/vmx/vmcs.c
+++ b/xen/arch/x86/hvm/vmx/vmcs.c
@@ -261,7 +261,7 @@ static void vmx_do_launch(struct vcpu *v)
error |= __vmwrite(CR4_READ_SHADOW, cr4);
- vmx_stts();
+ hvm_stts(v);
if(hvm_apic_support(v->domain))
vlapic_init(v);
@@ -282,7 +282,7 @@ static void vmx_do_launch(struct vcpu *v)
v->arch.schedule_tail = arch_vmx_do_resume;
/* init guest tsc to start from 0 */
- set_guest_time(v, 0);
+ hvm_set_guest_time(v, 0);
}
/*
@@ -539,7 +539,7 @@ void arch_vmx_do_resume(struct vcpu *v)
vmx_set_host_env(v);
}
- vmx_do_resume(v);
+ hvm_do_resume(v);
reset_stack_and_jump(vmx_asm_do_vmentry);
}
@@ -642,13 +642,11 @@ static void vmcs_dump(unsigned char ch)
printk("**************************************\n");
}
-static int __init setup_vmcs_dump(void)
+void setup_vmcs_dump(void)
{
register_keyhandler('v', vmcs_dump, "dump Intel's VMCS");
- return 0;
}
-__initcall(setup_vmcs_dump);
/*
* Local variables:
diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c
index 1d0b120d95..0a85952d0b 100644
--- a/xen/arch/x86/hvm/vmx/vmx.c
+++ b/xen/arch/x86/hvm/vmx/vmx.c
@@ -628,6 +628,45 @@ static unsigned long vmx_get_ctrl_reg(struct vcpu *v, unsigned int num)
return 0; /* dummy */
}
+
+
+/* Make sure that xen intercepts any FP accesses from current */
+static void vmx_stts(struct vcpu *v)
+{
+ unsigned long cr0;
+
+ /* VMX depends on operating on the current vcpu */
+ ASSERT(v == current);
+
+ /*
+ * If the guest does not have TS enabled then we must cause and handle an
+ * exception on first use of the FPU. If the guest *does* have TS enabled
+ * then this is not necessary: no FPU activity can occur until the guest
+ * clears CR0.TS, and we will initialise the FPU when that happens.
+ */
+ __vmread_vcpu(v, CR0_READ_SHADOW, &cr0);
+ if ( !(cr0 & X86_CR0_TS) )
+ {
+ __vmread_vcpu(v, GUEST_CR0, &cr0);
+ __vmwrite(GUEST_CR0, cr0 | X86_CR0_TS);
+ __vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_NM);
+ }
+}
+
+
+static void vmx_set_tsc_offset(struct vcpu *v, u64 offset)
+{
+ /* VMX depends on operating on the current vcpu */
+ ASSERT(v == current);
+
+ __vmwrite(TSC_OFFSET, offset);
+#if defined (__i386__)
+ __vmwrite(TSC_OFFSET_HIGH, offset >> 32);
+#endif
+}
+
+
+
/* SMP VMX guest support */
static void vmx_init_ap_context(struct vcpu_guest_context *ctxt,
int vcpuid, int trampoline_vector)
@@ -717,6 +756,9 @@ static void vmx_setup_hvm_funcs(void)
hvm_funcs.instruction_length = vmx_instruction_length;
hvm_funcs.get_guest_ctrl_reg = vmx_get_ctrl_reg;
+ hvm_funcs.stts = vmx_stts;
+ hvm_funcs.set_tsc_offset = vmx_set_tsc_offset;
+
hvm_funcs.init_ap_context = vmx_init_ap_context;
hvm_funcs.init_hypercall_page = vmx_init_hypercall_page;
@@ -768,6 +810,8 @@ int start_vmx(void)
set_in_cr4(X86_CR4_VMXE);
vmx_init_vmcs_config();
+
+ setup_vmcs_dump();
if ( (vmcs = vmx_alloc_host_vmcs()) == NULL )
{
@@ -916,7 +960,7 @@ static void vmx_vmexit_do_cpuid(struct cpu_user_regs *regs)
if ( input == CPUID_LEAF_0x1 )
{
/* mask off reserved bits */
- ecx &= ~VMX_VCPU_CPUID_L1_ECX_RESERVED;
+ ecx &= ~VMX_VCPU_CPUID_L1_ECX_RESERVED;
if ( !hvm_apic_support(v->domain) ||
!vlapic_global_enabled((VLAPIC(v))) )
@@ -930,7 +974,7 @@ static void vmx_vmexit_do_cpuid(struct cpu_user_regs *regs)
#if CONFIG_PAGING_LEVELS < 3
edx &= ~(bitmaskof(X86_FEATURE_PAE) |
bitmaskof(X86_FEATURE_PSE) |
- bitmaskof(X86_FEATURE_PSE36));
+ bitmaskof(X86_FEATURE_PSE36));
#else
if ( v->domain->arch.ops->guest_paging_levels == PAGING_L2 )
{
@@ -1044,6 +1088,7 @@ static void vmx_vmexit_do_invlpg(unsigned long va)
shadow_invlpg(v, va);
}
+
static int check_for_null_selector(unsigned long eip)
{
unsigned char inst[MAX_INST_LEN];
@@ -1977,7 +2022,7 @@ static inline void vmx_do_msr_write(struct cpu_user_regs *regs)
switch (regs->ecx) {
case MSR_IA32_TIME_STAMP_COUNTER:
- set_guest_time(v, msr_content);
+ hvm_set_guest_time(v, msr_content);
break;
case MSR_IA32_SYSENTER_CS:
__vmwrite(GUEST_SYSENTER_CS, msr_content);
diff --git a/xen/arch/x86/hvm/vmx/x86_32/exits.S b/xen/arch/x86/hvm/vmx/x86_32/exits.S
index b4fea2fe7b..0435df9607 100644
--- a/xen/arch/x86/hvm/vmx/x86_32/exits.S
+++ b/xen/arch/x86/hvm/vmx/x86_32/exits.S
@@ -95,7 +95,7 @@ vmx_process_softirqs:
ENTRY(vmx_asm_do_vmentry)
GET_CURRENT(%ebx)
pushl %ebx
- call vmx_do_resume
+ call hvm_do_resume
addl $4, %esp
cli # tests must not race interrupts
diff --git a/xen/arch/x86/hvm/vmx/x86_64/exits.S b/xen/arch/x86/hvm/vmx/x86_64/exits.S
index a3cffcf64a..a0357fbdef 100644
--- a/xen/arch/x86/hvm/vmx/x86_64/exits.S
+++ b/xen/arch/x86/hvm/vmx/x86_64/exits.S
@@ -106,7 +106,7 @@ vmx_process_softirqs:
ENTRY(vmx_asm_do_vmentry)
GET_CURRENT(%rbx)
movq %rbx, %rdi
- call vmx_do_resume
+ call hvm_do_resume
cli # tests must not race interrupts
movl VCPU_processor(%rbx),%eax
diff --git a/xen/arch/x86/x86_32/asm-offsets.c b/xen/arch/x86/x86_32/asm-offsets.c
index 5a10d51018..3a994650ca 100644
--- a/xen/arch/x86/x86_32/asm-offsets.c
+++ b/xen/arch/x86/x86_32/asm-offsets.c
@@ -81,7 +81,6 @@ void __dummy__(void)
BLANK();
OFFSET(VCPU_svm_vmcb_pa, struct vcpu, arch.hvm_svm.vmcb_pa);
- OFFSET(VCPU_svm_hsa_pa, struct vcpu, arch.hvm_svm.host_save_pa);
OFFSET(VCPU_svm_vmcb, struct vcpu, arch.hvm_svm.vmcb);
OFFSET(VCPU_svm_vmexit_tsc, struct vcpu, arch.hvm_svm.vmexit_tsc);
BLANK();
diff --git a/xen/arch/x86/x86_64/asm-offsets.c b/xen/arch/x86/x86_64/asm-offsets.c
index 0a4db7d430..6744e6c9e2 100644
--- a/xen/arch/x86/x86_64/asm-offsets.c
+++ b/xen/arch/x86/x86_64/asm-offsets.c
@@ -75,7 +75,6 @@ void __dummy__(void)
BLANK();
OFFSET(VCPU_svm_vmcb_pa, struct vcpu, arch.hvm_svm.vmcb_pa);
- OFFSET(VCPU_svm_hsa_pa, struct vcpu, arch.hvm_svm.host_save_pa);
OFFSET(VCPU_svm_vmcb, struct vcpu, arch.hvm_svm.vmcb);
OFFSET(VCPU_svm_vmexit_tsc, struct vcpu, arch.hvm_svm.vmexit_tsc);
BLANK();
diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h
index 9361094688..e3a608438d 100644
--- a/xen/include/asm-x86/hvm/hvm.h
+++ b/xen/include/asm-x86/hvm/hvm.h
@@ -59,6 +59,14 @@ struct hvm_function_table {
int (*instruction_length)(struct vcpu *v);
unsigned long (*get_guest_ctrl_reg)(struct vcpu *v, unsigned int num);
+ /*
+ * Update specifics of the guest state:
+ * 1) TS bit in guest cr0
+ * 2) TSC offset in guest
+ */
+ void (*stts)(struct vcpu *v);
+ void (*set_tsc_offset)(struct vcpu *v, u64 offset);
+
void (*init_ap_context)(struct vcpu_guest_context *ctxt,
int vcpuid, int trampoline_vector);
@@ -142,6 +150,10 @@ hvm_get_guest_ctrl_reg(struct vcpu *v, unsigned int num)
return 0; /* force to fail */
}
+extern void hvm_stts(struct vcpu *v);
+extern void hvm_set_guest_time(struct vcpu *v, u64 gtime);
+extern void hvm_do_resume(struct vcpu *v);
+
static inline void
hvm_init_ap_context(struct vcpu_guest_context *ctxt,
int vcpuid, int trampoline_vector)
diff --git a/xen/include/asm-x86/hvm/io.h b/xen/include/asm-x86/hvm/io.h
index 646b5711de..0c594fdafa 100644
--- a/xen/include/asm-x86/hvm/io.h
+++ b/xen/include/asm-x86/hvm/io.h
@@ -150,6 +150,7 @@ static inline int irq_masked(unsigned long eflags)
#endif
extern void handle_mmio(unsigned long, unsigned long);
+extern void hvm_interrupt_post(struct vcpu *v, int vector, int type);
extern void hvm_io_assist(struct vcpu *v);
extern void pic_irq_request(void *data, int level);
extern void hvm_pic_assist(struct vcpu *v);
diff --git a/xen/include/asm-x86/hvm/svm/svm.h b/xen/include/asm-x86/hvm/svm/svm.h
index 311f7912cd..a97daae850 100644
--- a/xen/include/asm-x86/hvm/svm/svm.h
+++ b/xen/include/asm-x86/hvm/svm/svm.h
@@ -28,54 +28,12 @@
#include <asm/hvm/svm/vmcb.h>
#include <asm/i387.h>
-extern void asidpool_retire( struct vmcb_struct *vmcb, int core );
-
-extern void svm_asm_vmexit_handler(struct cpu_user_regs);
-extern void svm_setup_function_table(struct vcpu *v);
-
-extern int vmcb_size;
-extern unsigned int cpu_rev;
-
-extern void svm_stop(void);
-extern void svm_save_cpu_user_regs(struct vcpu *v, struct cpu_user_regs *regs);
-extern void svm_load_cpu_user_regs(struct vcpu *v, struct cpu_user_regs *regs);
-extern void svm_vmread(struct vcpu *v, int index, unsigned long *value);
-extern void svm_vmwrite(struct vcpu *v, int index, unsigned long value);
-extern void svm_final_setup_guest(struct vcpu *v);
-extern int svm_paging_enabled(struct vcpu *v);
+extern void asidpool_retire(struct vmcb_struct *vmcb, int core);
extern void svm_dump_vmcb(const char *from, struct vmcb_struct *vmcb);
-extern void svm_stts(struct vcpu *v);
extern void svm_do_launch(struct vcpu *v);
-extern void svm_do_resume(struct vcpu *v);
-extern void svm_set_guest_time(struct vcpu *v, u64 gtime);
extern void arch_svm_do_resume(struct vcpu *v);
-extern int load_vmcb(struct arch_svm_struct *arch_svm, u64 phys_hsa);
-/* For debugging. Remove when no longer needed. */
-extern void svm_dump_host_regs(const char *from);
-
-extern void svm_migrate_timers(struct vcpu *v);
-
-/* ASID API */
-enum {
- ASID_AVAILABLE = 0,
- ASID_INUSE,
- ASID_RETIRED
-};
-#define INITIAL_ASID 0
-#define ASID_MAX 64
-
-struct asid_pool {
- spinlock_t asid_lock;
- u32 asid[ASID_MAX];
-};
-struct svm_percore_globals {
- void *hsa;
- u64 hsa_pa;
- void *scratch_hsa;
- u64 scratch_hsa_pa;
- struct asid_pool ASIDpool;
-};
+extern u64 root_vmcb_pa[NR_CPUS];
#define SVM_REG_EAX (0)
#define SVM_REG_ECX (1)
diff --git a/xen/include/asm-x86/hvm/svm/vmcb.h b/xen/include/asm-x86/hvm/svm/vmcb.h
index 9262dd9e26..dbb8ca8c1e 100644
--- a/xen/include/asm-x86/hvm/svm/vmcb.h
+++ b/xen/include/asm-x86/hvm/svm/vmcb.h
@@ -434,8 +434,6 @@ struct vmcb_struct {
struct arch_svm_struct {
struct vmcb_struct *vmcb;
- void *host_save_area;
- u64 host_save_pa;
u64 vmcb_pa;
u32 *iopm;
u32 *msrpm;
@@ -453,12 +451,15 @@ struct arch_svm_struct {
struct timer hlt_timer; /* hlt ins emulation wakeup timer */
};
-struct vmcb_struct *alloc_vmcb(void);
-struct host_save_area *alloc_host_save_area(void);
-void free_vmcb(struct vmcb_struct *vmcb);
-void free_host_save_area(struct host_save_area *hsa);
-void dump_vmcb(void);
-int construct_vmcb(struct arch_svm_struct *, struct cpu_user_regs *);
+extern struct vmcb_struct *alloc_vmcb(void);
+extern struct host_save_area *alloc_host_save_area(void);
+extern void free_vmcb(struct vmcb_struct *vmcb);
+extern void free_host_save_area(struct host_save_area *hsa);
+
+extern int construct_vmcb(struct arch_svm_struct *, struct cpu_user_regs *);
+extern void destroy_vmcb(struct arch_svm_struct *);
+
+extern void setup_vmcb_dump(void);
#define VMCB_USE_HOST_ENV 1
#define VMCB_USE_SEPARATE_ENV 0
diff --git a/xen/include/asm-x86/hvm/vmx/vmcs.h b/xen/include/asm-x86/hvm/vmx/vmcs.h
index 2886f51b6d..90163a8883 100644
--- a/xen/include/asm-x86/hvm/vmx/vmcs.h
+++ b/xen/include/asm-x86/hvm/vmx/vmcs.h
@@ -27,6 +27,7 @@
extern int start_vmx(void);
extern void vmcs_dump_vcpu(void);
extern void vmx_init_vmcs_config(void);
+extern void setup_vmcs_dump(void);
enum {
VMX_CPU_STATE_PAE_ENABLED=0,
diff --git a/xen/include/asm-x86/hvm/vmx/vmx.h b/xen/include/asm-x86/hvm/vmx/vmx.h
index a7e4ab2649..38ae0e3b0f 100644
--- a/xen/include/asm-x86/hvm/vmx/vmx.h
+++ b/xen/include/asm-x86/hvm/vmx/vmx.h
@@ -395,31 +395,6 @@ static inline int __vmxon (u64 addr)
return rc;
}
-/* Make sure that xen intercepts any FP accesses from current */
-static inline void vmx_stts(void)
-{
- unsigned long cr0;
- struct vcpu *v = current;
-
- /* FPU state already dirty? Then no need to setup_fpu() lazily. */
- if ( test_bit(_VCPUF_fpu_dirtied, &v->vcpu_flags) )
- return;
-
- /*
- * If the guest does not have TS enabled then we must cause and handle an
- * exception on first use of the FPU. If the guest *does* have TS enabled
- * then this is not necessary: no FPU activity can occur until the guest
- * clears CR0.TS, and we will initialise the FPU when that happens.
- */
- __vmread_vcpu(v, CR0_READ_SHADOW, &cr0);
- if ( !(cr0 & X86_CR0_TS) )
- {
- __vmread_vcpu(v, GUEST_CR0, &cr0);
- __vmwrite(GUEST_CR0, cr0 | X86_CR0_TS);
- __vm_set_bit(EXCEPTION_BITMAP, EXCEPTION_BITMAP_NM);
- }
-}
-
/* Works only for vcpu == current */
static inline int vmx_paging_enabled(struct vcpu *v)
{
diff --git a/xen/include/asm-x86/processor.h b/xen/include/asm-x86/processor.h
index bc8d95b2c1..f7539d57ae 100644
--- a/xen/include/asm-x86/processor.h
+++ b/xen/include/asm-x86/processor.h
@@ -277,27 +277,43 @@ static always_inline unsigned int cpuid_edx(unsigned int op)
}
-#define read_cr0() ({ \
- unsigned long __dummy; \
- __asm__( \
- "mov %%cr0,%0\n\t" \
- :"=r" (__dummy)); \
- __dummy; \
-})
-
-#define write_cr0(x) \
- __asm__("mov %0,%%cr0": :"r" ((unsigned long)x));
-
-#define read_cr4() ({ \
- unsigned long __dummy; \
- __asm__( \
- "mov %%cr4,%0\n\t" \
- :"=r" (__dummy)); \
- __dummy; \
-})
-
-#define write_cr4(x) \
- __asm__("mov %0,%%cr4": :"r" ((unsigned long)x));
+
+static inline unsigned long read_cr0(void)
+{
+ unsigned long __cr0;
+ __asm__("mov %%cr0,%0\n\t" :"=r" (__cr0));
+ return __cr0;
+}
+
+static inline void write_cr0(unsigned long val)
+{
+ __asm__("mov %0,%%cr0": :"r" ((unsigned long)val));
+}
+
+static inline unsigned long read_cr4(void)
+{
+ unsigned long __cr4;
+ __asm__("mov %%cr4,%0\n\t" :"=r" (__cr4));
+ return __cr4;
+}
+
+static inline void write_cr4(unsigned long val)
+{
+ __asm__("mov %0,%%cr4": :"r" ((unsigned long)val));
+}
+
+
+/* Clear and set 'TS' bit respectively */
+static inline void clts(void)
+{
+ __asm__ __volatile__ ("clts");
+}
+
+static inline void stts(void)
+{
+ write_cr0(X86_CR0_TS|read_cr0());
+}
+
/*
* Save the cr4 feature set we're using (ie
diff --git a/xen/include/asm-x86/system.h b/xen/include/asm-x86/system.h
index 7e6b95a050..5166d3f656 100644
--- a/xen/include/asm-x86/system.h
+++ b/xen/include/asm-x86/system.h
@@ -11,10 +11,6 @@
__sel; \
})
-/* Clear and set 'TS' bit respectively */
-#define clts() __asm__ __volatile__ ("clts")
-#define stts() write_cr0(X86_CR0_TS|read_cr0())
-
#define wbinvd() \
__asm__ __volatile__ ("wbinvd": : :"memory");