|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH RFCv3 3/8] xen: introduce XEN_DOMCTL_set_recipient
New operation sets the 'recipient' domain which will recieve all
memory pages from a particular domain when these pages are freed.
Signed-off-by: Vitaly Kuznetsov <vkuznets@xxxxxxxxxx>
---
xen/common/domain.c | 3 +++
xen/common/domctl.c | 27 +++++++++++++++++++++++++++
xen/common/page_alloc.c | 26 ++++++++++++++++++++++----
xen/include/public/domctl.h | 19 +++++++++++++++++++
xen/include/xen/sched.h | 1 +
5 files changed, 72 insertions(+), 4 deletions(-)
diff --git a/xen/common/domain.c b/xen/common/domain.c
index 62514b0..6bceb64 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -822,6 +822,9 @@ static void complete_domain_destroy(struct rcu_head *head)
if ( d->target != NULL )
put_domain(d->target);
+ if ( d->recipient != NULL )
+ put_domain(d->recipient);
+
evtchn_destroy_final(d);
radix_tree_destroy(&d->pirq_tree, free_pirq_struct);
diff --git a/xen/common/domctl.c b/xen/common/domctl.c
index 1ad0729..38cd10a 100644
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -1152,6 +1152,33 @@ long do_domctl(XEN_GUEST_HANDLE_PARAM(xen_domctl_t)
u_domctl)
}
break;
+ case XEN_DOMCTL_set_recipient:
+ {
+ struct domain *recipient_dom;
+
+ if ( op->u.recipient.recipient == DOMID_INVALID )
+ {
+ if ( d->recipient )
+ {
+ put_domain(d->recipient);
+ }
+ d->recipient = NULL;
+ break;
+ }
+
+ recipient_dom = get_domain_by_id(op->u.recipient.recipient);
+ if ( recipient_dom == NULL )
+ {
+ ret = -ESRCH;
+ break;
+ }
+ else
+ {
+ d->recipient = recipient_dom;
+ }
+ }
+ break;
+
default:
ret = arch_do_domctl(op, d, u_domctl);
break;
diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c
index 7b4092d..abb2ef3 100644
--- a/xen/common/page_alloc.c
+++ b/xen/common/page_alloc.c
@@ -1707,6 +1707,7 @@ void free_domheap_pages(struct page_info *pg, unsigned
int order)
{
struct domain *d = page_get_owner(pg);
unsigned int i;
+ unsigned long mfn, gmfn;
bool_t drop_dom_ref;
ASSERT(!in_irq());
@@ -1764,11 +1765,28 @@ void free_domheap_pages(struct page_info *pg, unsigned
int order)
scrub = 1;
}
- if ( unlikely(scrub) )
- for ( i = 0; i < (1 << order); i++ )
- scrub_one_page(&pg[i]);
+ if ( !d || !d->recipient || d->recipient->is_dying )
+ {
+ if ( unlikely(scrub) )
+ for ( i = 0; i < (1 << order); i++ )
+ scrub_one_page(&pg[i]);
- free_heap_pages(pg, order);
+ free_heap_pages(pg, order);
+ }
+ else
+ {
+ mfn = page_to_mfn(pg);
+ gmfn = mfn_to_gmfn(d, mfn);
+
+ page_set_owner(pg, NULL);
+ assign_pages(d->recipient, pg, order, 0);
+
+ if ( guest_physmap_add_page(d->recipient, gmfn, mfn, order) )
+ {
+ gdprintk(XENLOG_INFO, "Failed to add page to domain's physmap"
+ " mfn: %lx\n", mfn);
+ }
+ }
}
if ( drop_dom_ref )
diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
index cfa39b3..7fcb6db 100644
--- a/xen/include/public/domctl.h
+++ b/xen/include/public/domctl.h
@@ -965,6 +965,23 @@ struct xen_domctl_vnuma {
typedef struct xen_domctl_vnuma xen_domctl_vnuma_t;
DEFINE_XEN_GUEST_HANDLE(xen_domctl_vnuma_t);
+/*
+ * XEN_DOMCTL_set_recipient - sets the 'recipient' domain which will recieve
+ * all the domain's memory after its death or when and memory page from
+ * domain's heap is being freed. Pages from xen heap belonging to the domain
+ * are not copied. An additional reference link to the destination domain is
+ * being taken to prevent it from dying.
+ * When DOMID_INVALID is supplied as a recipient the source domain returns to
+ * its original state when memory pages are freed normally, reference link to
+ * the destination domain is being dropped.
+ */
+struct xen_domctl_set_recipient {
+ domid_t recipient;
+};
+typedef struct xen_domctl_set_recipient xen_domctl_set_recipient_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_set_recipient_t);
+
+
struct xen_domctl {
uint32_t cmd;
#define XEN_DOMCTL_createdomain 1
@@ -1038,6 +1055,7 @@ struct xen_domctl {
#define XEN_DOMCTL_get_vcpu_msrs 72
#define XEN_DOMCTL_set_vcpu_msrs 73
#define XEN_DOMCTL_setvnumainfo 74
+#define XEN_DOMCTL_set_recipient 75
#define XEN_DOMCTL_gdbsx_guestmemio 1000
#define XEN_DOMCTL_gdbsx_pausevcpu 1001
#define XEN_DOMCTL_gdbsx_unpausevcpu 1002
@@ -1099,6 +1117,7 @@ struct xen_domctl {
struct xen_domctl_gdbsx_pauseunp_vcpu gdbsx_pauseunp_vcpu;
struct xen_domctl_gdbsx_domstatus gdbsx_domstatus;
struct xen_domctl_vnuma vnuma;
+ struct xen_domctl_set_recipient recipient;
uint8_t pad[128];
} u;
};
diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
index c5157e6..d00d655 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -366,6 +366,7 @@ struct domain
bool_t is_privileged;
/* Which guest this guest has privileges on */
struct domain *target;
+ struct domain *recipient;
/* Is this guest being debugged by dom0? */
bool_t debugger_attached;
/* Is this guest dying (i.e., a zombie)? */
--
1.9.3
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |