[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen master] x86: make vcpu_reset() preemptible
commit 4939f9a6dee4280f38730fd3066e5dce353112f6 Author: Jan Beulich <jbeulich@xxxxxxxx> AuthorDate: Thu May 2 16:37:24 2013 +0200 Commit: Jan Beulich <jbeulich@xxxxxxxx> CommitDate: Thu May 2 16:37:24 2013 +0200 x86: make vcpu_reset() preemptible ... as dropping the old page tables may take significant amounts of time. This is part of CVE-2013-1918 / XSA-45. Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> Acked-by: Tim Deegan <tim@xxxxxxx> --- xen/arch/arm/domain.c | 3 ++- xen/arch/x86/domain.c | 13 ++++++------- xen/arch/x86/hvm/hvm.c | 5 ++++- xen/arch/x86/hvm/vlapic.c | 5 ++++- xen/arch/x86/mm.c | 6 +++--- xen/common/domain.c | 12 ++++++++++-- xen/common/domctl.c | 13 +++++++------ xen/include/asm-x86/mm.h | 2 +- xen/include/xen/domain.h | 4 ++-- xen/include/xen/sched.h | 3 +++ 10 files changed, 42 insertions(+), 24 deletions(-) diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c index 2af40a1..141aa0b 100644 --- a/xen/arch/arm/domain.c +++ b/xen/arch/arm/domain.c @@ -566,9 +566,10 @@ int arch_set_info_guest( return 0; } -void arch_vcpu_reset(struct vcpu *v) +int arch_vcpu_reset(struct vcpu *v) { vcpu_end_shutdown_deferral(v); + return 0; } static int relinquish_memory(struct domain *d, struct page_list_head *list) diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index bc1a31f..5bf52ff 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -939,17 +939,16 @@ int arch_set_info_guest( #undef c } -void arch_vcpu_reset(struct vcpu *v) +int arch_vcpu_reset(struct vcpu *v) { if ( !is_hvm_vcpu(v) ) { destroy_gdt(v); - vcpu_destroy_pagetables(v, 0); - } - else - { - vcpu_end_shutdown_deferral(v); + return vcpu_destroy_pagetables(v); } + + vcpu_end_shutdown_deferral(v); + return 0; } /* @@ -1960,7 +1959,7 @@ int domain_relinquish_resources(struct domain *d) /* Drop the in-use references to page-table bases. */ for_each_vcpu ( d, v ) { - ret = vcpu_destroy_pagetables(v, 1); + ret = vcpu_destroy_pagetables(v); if ( ret ) return ret; diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index c8487b8..7c3cb15 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -3555,8 +3555,11 @@ static void hvm_s3_suspend(struct domain *d) for_each_vcpu ( d, v ) { + int rc; + vlapic_reset(vcpu_vlapic(v)); - vcpu_reset(v); + rc = vcpu_reset(v); + ASSERT(!rc); } vpic_reset(d); diff --git a/xen/arch/x86/hvm/vlapic.c b/xen/arch/x86/hvm/vlapic.c index 9e1db88..8c6a7e2 100644 --- a/xen/arch/x86/hvm/vlapic.c +++ b/xen/arch/x86/hvm/vlapic.c @@ -240,6 +240,8 @@ static void vlapic_init_sipi_one(struct vcpu *target, uint32_t icr) { case APIC_DM_INIT: { bool_t fpu_initialised; + int rc; + /* No work on INIT de-assert for P4-type APIC. */ if ( (icr & (APIC_INT_LEVELTRIG | APIC_INT_ASSERT)) == APIC_INT_LEVELTRIG ) @@ -251,7 +253,8 @@ static void vlapic_init_sipi_one(struct vcpu *target, uint32_t icr) domain_lock(target->domain); /* Reset necessary VCPU state. This does not include FPU state. */ fpu_initialised = target->fpu_initialised; - vcpu_reset(target); + rc = vcpu_reset(target); + ASSERT(!rc); target->fpu_initialised = fpu_initialised; vlapic_reset(vcpu_vlapic(target)); domain_unlock(target->domain); diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index bada0bd..10e9217 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -2598,7 +2598,7 @@ static int put_old_guest_table(struct vcpu *v) return rc; } -int vcpu_destroy_pagetables(struct vcpu *v, bool_t preemptible) +int vcpu_destroy_pagetables(struct vcpu *v) { unsigned long mfn = pagetable_get_pfn(v->arch.guest_table); struct page_info *page; @@ -2620,7 +2620,7 @@ int vcpu_destroy_pagetables(struct vcpu *v, bool_t preemptible) if ( paging_mode_refcounts(v->domain) ) put_page(page); else - rc = put_page_and_type_preemptible(page, preemptible); + rc = put_page_and_type_preemptible(page, 1); } if ( l4tab ) @@ -2641,7 +2641,7 @@ int vcpu_destroy_pagetables(struct vcpu *v, bool_t preemptible) if ( paging_mode_refcounts(v->domain) ) put_page(page); else - rc = put_page_and_type_preemptible(page, preemptible); + rc = put_page_and_type_preemptible(page, 1); } if ( !rc ) v->arch.guest_table_user = pagetable_null(); diff --git a/xen/common/domain.c b/xen/common/domain.c index ce45d66..7cca655 100644 --- a/xen/common/domain.c +++ b/xen/common/domain.c @@ -868,14 +868,18 @@ void domain_unpause_by_systemcontroller(struct domain *d) domain_unpause(d); } -void vcpu_reset(struct vcpu *v) +int vcpu_reset(struct vcpu *v) { struct domain *d = v->domain; + int rc; vcpu_pause(v); domain_lock(d); - arch_vcpu_reset(v); + set_bit(_VPF_in_reset, &v->pause_flags); + rc = arch_vcpu_reset(v); + if ( rc ) + goto out_unlock; set_bit(_VPF_down, &v->pause_flags); @@ -891,9 +895,13 @@ void vcpu_reset(struct vcpu *v) #endif cpumask_clear(v->cpu_affinity_tmp); clear_bit(_VPF_blocked, &v->pause_flags); + clear_bit(_VPF_in_reset, &v->pause_flags); + out_unlock: domain_unlock(v->domain); vcpu_unpause(v); + + return rc; } diff --git a/xen/common/domctl.c b/xen/common/domctl.c index 73b12c8..1d00cfc 100644 --- a/xen/common/domctl.c +++ b/xen/common/domctl.c @@ -332,13 +332,15 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl) ret = -EINVAL; if ( (d == current->domain) || /* no domain_pause() */ (vcpu >= d->max_vcpus) || ((v = d->vcpu[vcpu]) == NULL) ) - goto svc_out; + break; if ( guest_handle_is_null(op->u.vcpucontext.ctxt) ) { - vcpu_reset(v); - ret = 0; - goto svc_out; + ret = vcpu_reset(v); + if ( ret == -EAGAIN ) + ret = hypercall_create_continuation( + __HYPERVISOR_domctl, "h", u_domctl); + break; } #ifdef CONFIG_COMPAT @@ -347,7 +349,7 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl) #endif ret = -ENOMEM; if ( (c.nat = alloc_vcpu_guest_context()) == NULL ) - goto svc_out; + break; #ifdef CONFIG_COMPAT if ( !is_pv_32on64_vcpu(v) ) @@ -368,7 +370,6 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t) u_domctl) domain_unpause(d); } - svc_out: free_vcpu_guest_context(c.nat); } break; diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h index 0f7297a..79c526f 100644 --- a/xen/include/asm-x86/mm.h +++ b/xen/include/asm-x86/mm.h @@ -556,7 +556,7 @@ void audit_domains(void); int new_guest_cr3(unsigned long pfn); void make_cr3(struct vcpu *v, unsigned long mfn); void update_cr3(struct vcpu *v); -int vcpu_destroy_pagetables(struct vcpu *, bool_t preemptible); +int vcpu_destroy_pagetables(struct vcpu *); void propagate_page_fault(unsigned long addr, u16 error_code); void *do_page_walk(struct vcpu *v, unsigned long addr); diff --git a/xen/include/xen/domain.h b/xen/include/xen/domain.h index d4ac50f..504a70f 100644 --- a/xen/include/xen/domain.h +++ b/xen/include/xen/domain.h @@ -13,7 +13,7 @@ typedef union { struct vcpu *alloc_vcpu( struct domain *d, unsigned int vcpu_id, unsigned int cpu_id); struct vcpu *alloc_dom0_vcpu0(void); -void vcpu_reset(struct vcpu *v); +int vcpu_reset(struct vcpu *); struct xen_domctl_getdomaininfo; void getdomaininfo(struct domain *d, struct xen_domctl_getdomaininfo *info); @@ -67,7 +67,7 @@ void arch_dump_vcpu_info(struct vcpu *v); void arch_dump_domain_info(struct domain *d); -void arch_vcpu_reset(struct vcpu *v); +int arch_vcpu_reset(struct vcpu *); extern spinlock_t vcpu_alloc_lock; bool_t domctl_lock_acquire(void); diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index beadc42..41f749e 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -682,6 +682,9 @@ static inline struct domain *next_domain_in_cpupool( /* VCPU is blocked due to missing mem_sharing ring. */ #define _VPF_mem_sharing 6 #define VPF_mem_sharing (1UL<<_VPF_mem_sharing) + /* VCPU is being reset. */ +#define _VPF_in_reset 7 +#define VPF_in_reset (1UL<<_VPF_in_reset) static inline int vcpu_runnable(struct vcpu *v) { -- generated by git-patchbot for /home/xen/git/xen.git#master _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |