[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [XEN] Support VCPU reset via DOMCTL_setvcpucontext.
# HG changeset patch # User kfraser@xxxxxxxxxxxxxxxxxxxxx # Date 1169229329 0 # Node ID 0bf0672528cff1dbe666971b99201e3ba89fc286 # Parent 62e2e515febe4ccdfa60056f0e4210e051bdc3e6 [XEN] Support VCPU reset via DOMCTL_setvcpucontext. Signed-off-by: Andrei Petrov <andrei.petrov@xxxxxxxxxxxxx> --- tools/libxc/xc_domain.c | 5 +- xen/arch/x86/domain.c | 109 +++++++++++++++++++++++++++-------------------- xen/common/domain.c | 38 +++++++++++++++- xen/include/xen/compat.h | 2 xen/include/xen/domain.h | 3 + 5 files changed, 109 insertions(+), 48 deletions(-) diff -r 62e2e515febe -r 0bf0672528cf tools/libxc/xc_domain.c --- a/tools/libxc/xc_domain.c Fri Jan 19 17:20:57 2007 +0000 +++ b/tools/libxc/xc_domain.c Fri Jan 19 17:55:29 2007 +0000 @@ -602,12 +602,13 @@ int xc_vcpu_setcontext(int xc_handle, domctl.u.vcpucontext.vcpu = vcpu; set_xen_guest_handle(domctl.u.vcpucontext.ctxt, ctxt); - if ( (rc = lock_pages(ctxt, sizeof(*ctxt))) != 0 ) + if ( (ctxt != NULL) && ((rc = lock_pages(ctxt, sizeof(*ctxt))) != 0) ) return rc; rc = do_domctl(xc_handle, &domctl); - unlock_pages(ctxt, sizeof(*ctxt)); + if ( ctxt != NULL ) + unlock_pages(ctxt, sizeof(*ctxt)); return rc; diff -r 62e2e515febe -r 0bf0672528cf xen/arch/x86/domain.c --- a/xen/arch/x86/domain.c Fri Jan 19 17:20:57 2007 +0000 +++ b/xen/arch/x86/domain.c Fri Jan 19 17:55:29 2007 +0000 @@ -50,6 +50,8 @@ static void paravirt_ctxt_switch_from(st static void paravirt_ctxt_switch_from(struct vcpu *v); static void paravirt_ctxt_switch_to(struct vcpu *v); +static void vcpu_destroy_pagetables(struct vcpu *v); + static void continue_idle_domain(struct vcpu *v) { reset_stack_and_jump(idle_loop); @@ -656,6 +658,13 @@ int arch_set_info_guest( return 0; #undef c +} + +int arch_vcpu_reset(struct vcpu *v) +{ + destroy_gdt(v); + vcpu_destroy_pagetables(v); + return 0; } long @@ -1380,63 +1389,73 @@ static void relinquish_memory(struct dom spin_unlock_recursive(&d->page_alloc_lock); } -void domain_relinquish_resources(struct domain *d) -{ - struct vcpu *v; +static void vcpu_destroy_pagetables(struct vcpu *v) +{ + struct domain *d = v->domain; unsigned long pfn; - BUG_ON(!cpus_empty(d->domain_dirty_cpumask)); - - /* Drop the in-use references to page-table bases. */ - for_each_vcpu ( d, v ) - { - /* Drop ref to guest_table (from new_guest_cr3(), svm/vmx cr3 handling, - * or sh_update_paging_modes()) */ #ifdef CONFIG_COMPAT - if ( IS_COMPAT(d) ) - { - if ( is_hvm_vcpu(v) ) - pfn = pagetable_get_pfn(v->arch.guest_table); - else - pfn = l4e_get_pfn(*(l4_pgentry_t *)__va(pagetable_get_paddr(v->arch.guest_table))); - - if ( pfn != 0 ) - { - if ( shadow_mode_refcounts(d) ) - put_page(mfn_to_page(pfn)); - else - put_page_and_type(mfn_to_page(pfn)); - } - continue; - } -#endif - pfn = pagetable_get_pfn(v->arch.guest_table); + if ( IS_COMPAT(d) ) + { + if ( is_hvm_vcpu(v) ) + pfn = pagetable_get_pfn(v->arch.guest_table); + else + pfn = l4e_get_pfn(*(l4_pgentry_t *) + __va(pagetable_get_paddr(v->arch.guest_table))); + if ( pfn != 0 ) { if ( shadow_mode_refcounts(d) ) put_page(mfn_to_page(pfn)); else put_page_and_type(mfn_to_page(pfn)); + } + + v->arch.guest_table = pagetable_null(); + v->arch.cr3 = 0; + return; + } +#endif + + pfn = pagetable_get_pfn(v->arch.guest_table); + if ( pfn != 0 ) + { + if ( shadow_mode_refcounts(d) ) + put_page(mfn_to_page(pfn)); + else + put_page_and_type(mfn_to_page(pfn)); #ifdef __x86_64__ - if ( pfn == pagetable_get_pfn(v->arch.guest_table_user) ) - v->arch.guest_table_user = pagetable_null(); -#endif - v->arch.guest_table = pagetable_null(); - } + if ( pfn == pagetable_get_pfn(v->arch.guest_table_user) ) + v->arch.guest_table_user = pagetable_null(); +#endif + v->arch.guest_table = pagetable_null(); + } #ifdef __x86_64__ - /* Drop ref to guest_table_user (from MMUEXT_NEW_USER_BASEPTR) */ - pfn = pagetable_get_pfn(v->arch.guest_table_user); - if ( pfn != 0 ) - { - if ( shadow_mode_refcounts(d) ) - put_page(mfn_to_page(pfn)); - else - put_page_and_type(mfn_to_page(pfn)); - v->arch.guest_table_user = pagetable_null(); - } -#endif - } + /* Drop ref to guest_table_user (from MMUEXT_NEW_USER_BASEPTR) */ + pfn = pagetable_get_pfn(v->arch.guest_table_user); + if ( pfn != 0 ) + { + if ( shadow_mode_refcounts(d) ) + put_page(mfn_to_page(pfn)); + else + put_page_and_type(mfn_to_page(pfn)); + v->arch.guest_table_user = pagetable_null(); + } +#endif + + v->arch.cr3 = 0; +} + +void domain_relinquish_resources(struct domain *d) +{ + struct vcpu *v; + + BUG_ON(!cpus_empty(d->domain_dirty_cpumask)); + + /* Drop the in-use references to page-table bases. */ + for_each_vcpu ( d, v ) + vcpu_destroy_pagetables(v); /* Tear down shadow mode stuff. */ shadow_teardown(d); diff -r 62e2e515febe -r 0bf0672528cf xen/common/domain.c --- a/xen/common/domain.c Fri Jan 19 17:20:57 2007 +0000 +++ b/xen/common/domain.c Fri Jan 19 17:55:29 2007 +0000 @@ -5,6 +5,7 @@ */ #include <xen/config.h> +#include <xen/compat.h> #include <xen/init.h> #include <xen/lib.h> #include <xen/errno.h> @@ -467,7 +468,12 @@ int set_info_guest(struct domain *d, if ( (vcpu >= MAX_VIRT_CPUS) || ((v = d->vcpu[vcpu]) == NULL) ) return -EINVAL; - + + if ( IS_COMPAT(v->domain) + ? compat_handle_is_null(vcpucontext.cmp->ctxt) + : guest_handle_is_null(vcpucontext.nat->ctxt) ) + return vcpu_reset(v); + #ifdef CONFIG_COMPAT BUILD_BUG_ON(sizeof(struct vcpu_guest_context) < sizeof(struct compat_vcpu_guest_context)); @@ -521,6 +527,36 @@ int boot_vcpu(struct domain *d, int vcpu return arch_set_info_guest(v, ctxt); } +int vcpu_reset(struct vcpu *v) +{ + struct domain *d = v->domain; + int rc; + + domain_pause(d); + LOCK_BIGLOCK(d); + + rc = arch_vcpu_reset(v); + if ( rc != 0 ) + goto out; + + set_bit(_VCPUF_down, &v->vcpu_flags); + + clear_bit(_VCPUF_fpu_initialised, &v->vcpu_flags); + clear_bit(_VCPUF_fpu_dirtied, &v->vcpu_flags); + clear_bit(_VCPUF_blocked, &v->vcpu_flags); + clear_bit(_VCPUF_initialised, &v->vcpu_flags); + clear_bit(_VCPUF_nmi_pending, &v->vcpu_flags); + clear_bit(_VCPUF_nmi_masked, &v->vcpu_flags); + clear_bit(_VCPUF_polling, &v->vcpu_flags); + + out: + UNLOCK_BIGLOCK(v->domain); + domain_unpause(d); + + return rc; +} + + long do_vcpu_op(int cmd, int vcpuid, XEN_GUEST_HANDLE(void) arg) { struct domain *d = current->domain; diff -r 62e2e515febe -r 0bf0672528cf xen/include/xen/compat.h --- a/xen/include/xen/compat.h Fri Jan 19 17:20:57 2007 +0000 +++ b/xen/include/xen/compat.h Fri Jan 19 17:55:29 2007 +0000 @@ -173,6 +173,8 @@ int switch_native(struct domain *); #else +#define compat_handle_is_null(hnd) 0 + #define BITS_PER_GUEST_LONG(d) BITS_PER_LONG #endif diff -r 62e2e515febe -r 0bf0672528cf xen/include/xen/domain.h --- a/xen/include/xen/domain.h Fri Jan 19 17:20:57 2007 +0000 +++ b/xen/include/xen/domain.h Fri Jan 19 17:55:29 2007 +0000 @@ -12,6 +12,7 @@ int boot_vcpu( int boot_vcpu( struct domain *d, int vcpuid, vcpu_guest_context_u ctxt); struct vcpu *alloc_idle_vcpu(unsigned int cpu_id); +int vcpu_reset(struct vcpu *v); struct domain *alloc_domain(domid_t domid); void free_domain(struct domain *d); @@ -56,4 +57,6 @@ void arch_dump_vcpu_info(struct vcpu *v) void arch_dump_domain_info(struct domain *d); +int arch_vcpu_reset(struct vcpu *v); + #endif /* __XEN_DOMAIN_H__ */ _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |