[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] hvm: FPU management cleanups.
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1202034128 0 # Node ID e4edc310e949750065cb39588d87c335c7cd71a2 # Parent aecbf98aa7099458fe6895bbd8f15d506e0901b3 hvm: FPU management cleanups. Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx> --- xen/arch/x86/hvm/hvm.c | 3 - xen/arch/x86/hvm/svm/svm.c | 88 ++++++++++++++++++++---------------- xen/arch/x86/hvm/svm/vmcb.c | 7 +- xen/arch/x86/hvm/vmx/vmcs.c | 4 + xen/arch/x86/hvm/vmx/vmx.c | 101 ++++++++++++++++++++---------------------- xen/include/asm-x86/hvm/hvm.h | 6 -- 6 files changed, 105 insertions(+), 104 deletions(-) diff -r aecbf98aa709 -r e4edc310e949 xen/arch/x86/hvm/hvm.c --- a/xen/arch/x86/hvm/hvm.c Sun Feb 03 09:30:59 2008 +0000 +++ b/xen/arch/x86/hvm/hvm.c Sun Feb 03 10:22:08 2008 +0000 @@ -123,9 +123,6 @@ void hvm_do_resume(struct vcpu *v) void hvm_do_resume(struct vcpu *v) { ioreq_t *p; - - if ( !v->fpu_dirtied ) - hvm_funcs.stts(v); pt_restore_timer(v); diff -r aecbf98aa709 -r e4edc310e949 xen/arch/x86/hvm/svm/svm.c --- a/xen/arch/x86/hvm/svm/svm.c Sun Feb 03 09:30:59 2008 +0000 +++ b/xen/arch/x86/hvm/svm/svm.c Sun Feb 03 10:22:08 2008 +0000 @@ -426,6 +426,34 @@ static int svm_load_vmcb_ctxt(struct vcp return 0; } +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); +} + +static void svm_fpu_leave(struct vcpu *v) +{ + struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; + + ASSERT(!v->fpu_dirtied); + ASSERT(read_cr0() & X86_CR0_TS); + + /* + * 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_vcpu.guest_cr[0] & X86_CR0_TS) ) + { + v->arch.hvm_svm.vmcb->exception_intercepts |= 1U << TRAP_no_device; + vmcb->cr0 |= X86_CR0_TS; + } +} + static enum hvm_intblk svm_interrupt_blocked( struct vcpu *v, struct hvm_intack intack) { @@ -470,19 +498,22 @@ static void svm_update_guest_cr(struct v switch ( cr ) { - case 0: - /* TS cleared? Then initialise FPU now. */ - if ( (v == current) && !(v->arch.hvm_vcpu.guest_cr[0] & X86_CR0_TS) && - (vmcb->cr0 & X86_CR0_TS) ) + case 0: { + unsigned long hw_cr0_mask = 0; + + if ( !(v->arch.hvm_vcpu.guest_cr[0] & X86_CR0_TS) ) { - setup_fpu(v); - vmcb->exception_intercepts &= ~(1U << TRAP_no_device); - } - - vmcb->cr0 = v->arch.hvm_vcpu.guest_cr[0]; + if ( v != current ) + hw_cr0_mask |= X86_CR0_TS; + else if ( vmcb->cr0 & X86_CR0_TS ) + svm_fpu_enter(v); + } + + vmcb->cr0 = v->arch.hvm_vcpu.guest_cr[0] | hw_cr0_mask; if ( !paging_mode_hap(v->domain) ) vmcb->cr0 |= X86_CR0_PG | X86_CR0_WP; break; + } case 2: vmcb->cr2 = v->arch.hvm_vcpu.guest_cr[2]; break; @@ -664,24 +695,6 @@ static void svm_set_segment_register(str svm_vmload(vmcb); } -/* 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_vcpu.guest_cr[0] & X86_CR0_TS) ) - { - v->arch.hvm_svm.vmcb->exception_intercepts |= 1U << TRAP_no_device; - vmcb->cr0 |= X86_CR0_TS; - } -} - static void svm_set_tsc_offset(struct vcpu *v, u64 offset) { v->arch.hvm_svm.vmcb->tsc_offset = offset; @@ -710,6 +723,8 @@ static void svm_ctxt_switch_from(struct static void svm_ctxt_switch_from(struct vcpu *v) { int cpu = smp_processor_id(); + + svm_fpu_leave(v); svm_save_dr(v); @@ -883,7 +898,6 @@ static struct hvm_function_table svm_fun .update_guest_cr = svm_update_guest_cr, .update_guest_efer = svm_update_guest_efer, .flush_guest_tlbs = svm_flush_guest_tlbs, - .stts = svm_stts, .set_tsc_offset = svm_set_tsc_offset, .inject_exception = svm_inject_exception, .init_hypercall_page = svm_init_hypercall_page, @@ -964,12 +978,11 @@ static void svm_do_nested_pgfault(paddr_ static void svm_do_no_device_fault(struct vmcb_struct *vmcb) { - struct vcpu *v = current; - - setup_fpu(v); - vmcb->exception_intercepts &= ~(1U << TRAP_no_device); - - if ( !(v->arch.hvm_vcpu.guest_cr[0] & X86_CR0_TS) ) + struct vcpu *curr = current; + + svm_fpu_enter(curr); + + if ( !(curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_TS) ) vmcb->cr0 &= ~X86_CR0_TS; } @@ -1647,11 +1660,8 @@ static void svm_cr_access( break; case INSTR_CLTS: - /* TS being cleared means that it's time to restore fpu state. */ - setup_fpu(current); - vmcb->exception_intercepts &= ~(1U << TRAP_no_device); - vmcb->cr0 &= ~X86_CR0_TS; /* clear TS */ - v->arch.hvm_vcpu.guest_cr[0] &= ~X86_CR0_TS; /* clear TS */ + v->arch.hvm_vcpu.guest_cr[0] &= ~X86_CR0_TS; + svm_update_guest_cr(v, 0); HVMTRACE_0D(CLTS, current); break; diff -r aecbf98aa709 -r e4edc310e949 xen/arch/x86/hvm/svm/vmcb.c --- a/xen/arch/x86/hvm/svm/vmcb.c Sun Feb 03 09:30:59 2008 +0000 +++ b/xen/arch/x86/hvm/svm/vmcb.c Sun Feb 03 10:22:08 2008 +0000 @@ -212,20 +212,21 @@ static int construct_vmcb(struct vcpu *v vmcb->tr.base = 0; vmcb->tr.limit = 0xff; - v->arch.hvm_vcpu.guest_cr[0] = X86_CR0_PE | X86_CR0_TS; + v->arch.hvm_vcpu.guest_cr[0] = X86_CR0_PE | X86_CR0_ET; hvm_update_guest_cr(v, 0); v->arch.hvm_vcpu.guest_cr[4] = 0; hvm_update_guest_cr(v, 4); paging_update_paging_modes(v); + + 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 = 0x0007040600070406ULL; /* guest PAT */ vmcb->h_cr3 = pagetable_get_paddr(v->domain->arch.phys_table); - vmcb->exception_intercepts = HVM_TRAP_MASK; /* * No point in intercepting CR3 reads, because the hardware will return @@ -241,7 +242,7 @@ static int construct_vmcb(struct vcpu *v } else { - vmcb->exception_intercepts = HVM_TRAP_MASK | (1U << TRAP_page_fault); + vmcb->exception_intercepts |= (1U << TRAP_page_fault); } return 0; diff -r aecbf98aa709 -r e4edc310e949 xen/arch/x86/hvm/vmx/vmcs.c --- a/xen/arch/x86/hvm/vmx/vmcs.c Sun Feb 03 09:30:59 2008 +0000 +++ b/xen/arch/x86/hvm/vmx/vmcs.c Sun Feb 03 10:22:08 2008 +0000 @@ -570,7 +570,9 @@ static int construct_vmcs(struct vcpu *v __vmwrite(VMCS_LINK_POINTER_HIGH, ~0UL); #endif - __vmwrite(EXCEPTION_BITMAP, HVM_TRAP_MASK | (1U << TRAP_page_fault)); + __vmwrite(EXCEPTION_BITMAP, (HVM_TRAP_MASK | + (1U << TRAP_page_fault) | + (1U << TRAP_no_device))); v->arch.hvm_vcpu.guest_cr[0] = X86_CR0_PE | X86_CR0_ET; hvm_update_guest_cr(v, 0); diff -r aecbf98aa709 -r e4edc310e949 xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Sun Feb 03 09:30:59 2008 +0000 +++ b/xen/arch/x86/hvm/vmx/vmx.c Sun Feb 03 10:22:08 2008 +0000 @@ -740,15 +740,42 @@ static int vmx_load_vmcs_ctxt(struct vcp return 0; } -static void vmx_ctxt_switch_from(struct vcpu *v) -{ +static void vmx_fpu_enter(struct vcpu *v) +{ + setup_fpu(v); + __vm_clear_bit(EXCEPTION_BITMAP, TRAP_no_device); + v->arch.hvm_vmx.host_cr0 &= ~X86_CR0_TS; + __vmwrite(HOST_CR0, v->arch.hvm_vmx.host_cr0); +} + +static void vmx_fpu_leave(struct vcpu *v) +{ + ASSERT(!v->fpu_dirtied); ASSERT(read_cr0() & X86_CR0_TS); + if ( !(v->arch.hvm_vmx.host_cr0 & X86_CR0_TS) ) { v->arch.hvm_vmx.host_cr0 |= X86_CR0_TS; __vmwrite(HOST_CR0, v->arch.hvm_vmx.host_cr0); } + /* + * 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_vcpu.guest_cr[0] & X86_CR0_TS) ) + { + v->arch.hvm_vcpu.hw_cr[0] |= X86_CR0_TS; + __vmwrite(GUEST_CR0, v->arch.hvm_vcpu.hw_cr[0]); + __vm_set_bit(EXCEPTION_BITMAP, TRAP_no_device); + } +} + +static void vmx_ctxt_switch_from(struct vcpu *v) +{ + vmx_fpu_leave(v); vmx_save_guest_msrs(v); vmx_restore_host_msrs(); vmx_save_dr(v); @@ -951,26 +978,6 @@ static void vmx_set_segment_register(str vmx_vmcs_exit(v); } -/* Make sure that xen intercepts any FP accesses from current */ -static void vmx_stts(struct vcpu *v) -{ - /* 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. - */ - if ( !(v->arch.hvm_vcpu.guest_cr[0] & X86_CR0_TS) ) - { - v->arch.hvm_vcpu.hw_cr[0] |= X86_CR0_TS; - __vmwrite(GUEST_CR0, v->arch.hvm_vcpu.hw_cr[0]); - __vm_set_bit(EXCEPTION_BITMAP, TRAP_no_device); - } -} - static void vmx_set_tsc_offset(struct vcpu *v, u64 offset) { vmx_vmcs_enter(v); @@ -1042,21 +1049,24 @@ static void vmx_update_guest_cr(struct v switch ( cr ) { - case 0: - /* TS cleared? Then initialise FPU now. */ - if ( (v == current) && !(v->arch.hvm_vcpu.guest_cr[0] & X86_CR0_TS) && - (v->arch.hvm_vcpu.hw_cr[0] & X86_CR0_TS) ) + case 0: { + unsigned long hw_cr0_mask = + X86_CR0_NE | X86_CR0_PG | X86_CR0_WP | X86_CR0_PE; + + if ( !(v->arch.hvm_vcpu.guest_cr[0] & X86_CR0_TS) ) { - setup_fpu(v); - __vm_clear_bit(EXCEPTION_BITMAP, TRAP_no_device); + if ( v != current ) + hw_cr0_mask |= X86_CR0_TS; + else if ( v->arch.hvm_vcpu.hw_cr[0] & X86_CR0_TS ) + vmx_fpu_enter(v); } v->arch.hvm_vcpu.hw_cr[0] = - v->arch.hvm_vcpu.guest_cr[0] | - X86_CR0_NE | X86_CR0_PG | X86_CR0_WP | X86_CR0_PE; + v->arch.hvm_vcpu.guest_cr[0] | hw_cr0_mask; __vmwrite(GUEST_CR0, v->arch.hvm_vcpu.hw_cr[0]); __vmwrite(CR0_READ_SHADOW, v->arch.hvm_vcpu.guest_cr[0]); break; + } case 2: /* CR2 is updated in exit stub. */ break; @@ -1153,7 +1163,6 @@ static struct hvm_function_table vmx_fun .update_guest_cr = vmx_update_guest_cr, .update_guest_efer = vmx_update_guest_efer, .flush_guest_tlbs = vmx_flush_guest_tlbs, - .stts = vmx_stts, .set_tsc_offset = vmx_set_tsc_offset, .inject_exception = vmx_inject_exception, .init_hypercall_page = vmx_init_hypercall_page, @@ -1234,20 +1243,15 @@ static void __update_guest_eip(unsigned void vmx_do_no_device_fault(void) { - struct vcpu *v = current; - - setup_fpu(current); - __vm_clear_bit(EXCEPTION_BITMAP, TRAP_no_device); - - ASSERT(v->arch.hvm_vmx.host_cr0 & X86_CR0_TS); - v->arch.hvm_vmx.host_cr0 &= ~X86_CR0_TS; - __vmwrite(HOST_CR0, v->arch.hvm_vmx.host_cr0); + struct vcpu *curr = current; + + vmx_fpu_enter(curr); /* Disable TS in guest CR0 unless the guest wants the exception too. */ - if ( !(v->arch.hvm_vcpu.guest_cr[0] & X86_CR0_TS) ) - { - v->arch.hvm_vcpu.hw_cr[0] &= ~X86_CR0_TS; - __vmwrite(GUEST_CR0, v->arch.hvm_vcpu.hw_cr[0]); + if ( !(curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_TS) ) + { + curr->arch.hvm_vcpu.hw_cr[0] &= ~X86_CR0_TS; + __vmwrite(GUEST_CR0, curr->arch.hvm_vcpu.hw_cr[0]); } } @@ -2226,15 +2230,8 @@ static int vmx_cr_access(unsigned long e mov_from_cr(cr, gp, regs); break; case TYPE_CLTS: - /* We initialise the FPU now, to avoid needing another vmexit. */ - setup_fpu(v); - __vm_clear_bit(EXCEPTION_BITMAP, TRAP_no_device); - - v->arch.hvm_vcpu.hw_cr[0] &= ~X86_CR0_TS; /* clear TS */ - __vmwrite(GUEST_CR0, v->arch.hvm_vcpu.hw_cr[0]); - - v->arch.hvm_vcpu.guest_cr[0] &= ~X86_CR0_TS; /* clear TS */ - __vmwrite(CR0_READ_SHADOW, v->arch.hvm_vcpu.guest_cr[0]); + v->arch.hvm_vcpu.guest_cr[0] &= ~X86_CR0_TS; + vmx_update_guest_cr(v, 0); HVMTRACE_0D(CLTS, current); break; case TYPE_LMSW: diff -r aecbf98aa709 -r e4edc310e949 xen/include/asm-x86/hvm/hvm.h --- a/xen/include/asm-x86/hvm/hvm.h Sun Feb 03 09:30:59 2008 +0000 +++ b/xen/include/asm-x86/hvm/hvm.h Sun Feb 03 10:22:08 2008 +0000 @@ -105,12 +105,6 @@ struct hvm_function_table { */ void (*flush_guest_tlbs)(void); - /* - * 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 (*inject_exception)(unsigned int trapnr, int errcode, _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |