# 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
|