[XEN] Support VCPU reset via DOMCTL_setvcpucontext.

Signed-off-by: Andrei Petrov <andrei.petrov@xensource.com>
This commit is contained in:
kfraser@localhost.localdomain committed 2007-01-19 17:55:29 +00:00
1 parent 115209d91b
commit bbb6a715dc
5 files changed
+113 -52

No files matched your search

+3 -2
View File
@@ -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;
+68 -49
View File
@@ -50,6 +50,8 @@ DEFINE_PER_CPU(struct vcpu *, curr_vcpu);
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);
@@ -658,6 +660,13 @@ int arch_set_info_guest(
#undef c
}
int arch_vcpu_reset(struct vcpu *v)
{
destroy_gdt(v);
vcpu_destroy_pagetables(v);
return 0;
}
long
arch_do_vcpu_op(
int cmd, struct vcpu *v, XEN_GUEST_HANDLE(void) arg)
@@ -1380,63 +1389,73 @@ static void relinquish_memory(struct domain *d, struct list_head *list)
spin_unlock_recursive(&d->page_alloc_lock);
}
static void vcpu_destroy_pagetables(struct vcpu *v)
{
struct domain *d = v->domain;
unsigned long pfn;
#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));
}
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();
}
#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
v->arch.cr3 = 0;
}
void domain_relinquish_resources(struct domain *d)
{
struct vcpu *v;
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 ( 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();
}
#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
}
vcpu_destroy_pagetables(v);
/* Tear down shadow mode stuff. */
shadow_teardown(d);
+37 -1
View File
@@ -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 vcpuid, vcpu_guest_context_u ctxt)
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;
+2
View File
@@ -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
+3
View File
@@ -12,6 +12,7 @@ struct vcpu *alloc_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__ */
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.