# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1261031275 0
# Node ID 66e29f42247a2f5342d6b748c1e026ebf5dba74e
# Parent a1ab94c514b80b3f0845465752ed72cfe4fafa73
domctl support for generic memory event handling.
Signed-off-by: Patrick Colp <Patrick.Colp@xxxxxxxxxx>
---
xen/arch/x86/domctl.c | 18 +++++++
xen/arch/x86/mm/mem_event.c | 91 ++++++++++++++++++++++++++++++++++++++++
xen/include/asm-x86/mem_event.h | 3 +
xen/include/public/domctl.h | 26 +++++++++++
4 files changed, 138 insertions(+)
diff -r a1ab94c514b8 -r 66e29f42247a xen/arch/x86/domctl.c
--- a/xen/arch/x86/domctl.c Thu Dec 17 06:27:55 2009 +0000
+++ b/xen/arch/x86/domctl.c Thu Dec 17 06:27:55 2009 +0000
@@ -30,6 +30,8 @@
#include <asm/hypercall.h> /* for arch_do_domctl */
#include <xsm/xsm.h>
#include <xen/iommu.h>
+#include <asm/mem_event.h>
+#include <public/mem_event.h>
#ifdef XEN_GDBSX_CONFIG
#ifdef XEN_KDB_CONFIG
@@ -1299,6 +1301,22 @@ long arch_do_domctl(
break;
#endif /* XEN_GDBSX_CONFIG */
+ case XEN_DOMCTL_mem_event_op:
+ {
+ struct domain *d;
+
+ ret = -ESRCH;
+ d = rcu_lock_domain_by_id(domctl->domain);
+ if ( d != NULL )
+ {
+ ret = mem_event_domctl(d, &domctl->u.mem_event_op,
+ guest_handle_cast(u_domctl, void));
+ rcu_unlock_domain(d);
+ copy_to_guest(u_domctl, domctl, 1);
+ }
+ }
+ break;
+
default:
ret = -ENOSYS;
break;
diff -r a1ab94c514b8 -r 66e29f42247a xen/arch/x86/mm/mem_event.c
--- a/xen/arch/x86/mm/mem_event.c Thu Dec 17 06:27:55 2009 +0000
+++ b/xen/arch/x86/mm/mem_event.c Thu Dec 17 06:27:55 2009 +0000
@@ -188,6 +188,97 @@ int mem_event_check_ring(struct domain *
return ring_full;
}
+int mem_event_domctl(struct domain *d, xen_domctl_mem_event_op_t *mec,
+ XEN_GUEST_HANDLE(void) u_domctl)
+{
+ int rc;
+
+ if ( unlikely(d == current->domain) )
+ {
+ gdprintk(XENLOG_INFO, "Tried to do a memory paging op on itself.\n");
+ return -EINVAL;
+ }
+
+ if ( unlikely(d->is_dying) )
+ {
+ gdprintk(XENLOG_INFO, "Ignoring memory paging op on dying domain %u\n",
+ d->domain_id);
+ return 0;
+ }
+
+ if ( unlikely(d->vcpu == NULL) || unlikely(d->vcpu[0] == NULL) )
+ {
+ MEM_EVENT_ERROR("Memory paging op on a domain (%u) with no vcpus\n",
+ d->domain_id);
+ return -EINVAL;
+ }
+
+ /* TODO: XSM hook */
+#if 0
+ rc = xsm_mem_event_control(d, mec->op);
+ if ( rc )
+ return rc;
+#endif
+
+ if ( mec->mode == 0 )
+ {
+ switch( mec->op )
+ {
+ case XEN_DOMCTL_MEM_EVENT_OP_ENABLE:
+ {
+ struct domain *dom_mem_event = current->domain;
+ struct vcpu *v = current;
+ unsigned long ring_addr = mec->ring_addr;
+ unsigned long shared_addr = mec->shared_addr;
+ l1_pgentry_t l1e;
+ unsigned long gfn;
+ p2m_type_t p2mt;
+ mfn_t ring_mfn;
+ mfn_t shared_mfn;
+
+ /* Get MFN of ring page */
+ guest_get_eff_l1e(v, ring_addr, &l1e);
+ gfn = l1e_get_pfn(l1e);
+ ring_mfn = gfn_to_mfn(dom_mem_event, gfn, &p2mt);
+
+ rc = -EINVAL;
+ if ( unlikely(!mfn_valid(mfn_x(ring_mfn))) )
+ break;
+
+ /* Get MFN of shared page */
+ guest_get_eff_l1e(v, shared_addr, &l1e);
+ gfn = l1e_get_pfn(l1e);
+ shared_mfn = gfn_to_mfn(dom_mem_event, gfn, &p2mt);
+
+ rc = -EINVAL;
+ if ( unlikely(!mfn_valid(mfn_x(shared_mfn))) )
+ break;
+
+ rc = -EINVAL;
+ if ( mem_event_enable(d, ring_mfn, shared_mfn) != 0 )
+ break;
+
+ rc = 0;
+ }
+ break;
+
+ case XEN_DOMCTL_MEM_EVENT_OP_DISABLE:
+ {
+ rc = mem_event_disable(d);
+ }
+ break;
+
+ default:
+ rc = -ENOSYS;
+ break;
+ }
+ }
+ else
+ rc = -ENOSYS;
+
+ return rc;
+}
+
/*
* Local variables:
diff -r a1ab94c514b8 -r 66e29f42247a xen/include/asm-x86/mem_event.h
--- a/xen/include/asm-x86/mem_event.h Thu Dec 17 06:27:55 2009 +0000
+++ b/xen/include/asm-x86/mem_event.h Thu Dec 17 06:27:55 2009 +0000
@@ -54,6 +54,9 @@ void mem_event_get_response(struct domai
void mem_event_get_response(struct domain *d, mem_event_response_t *rsp);
void mem_event_unpause_vcpus(struct domain *d);
+int mem_event_domctl(struct domain *d, xen_domctl_mem_event_op_t *mec,
+ XEN_GUEST_HANDLE(void) u_domctl);
+
#endif /* __MEM_EVENT_H__ */
diff -r a1ab94c514b8 -r 66e29f42247a xen/include/public/domctl.h
--- a/xen/include/public/domctl.h Thu Dec 17 06:27:55 2009 +0000
+++ b/xen/include/public/domctl.h Thu Dec 17 06:27:55 2009 +0000
@@ -690,6 +690,31 @@ struct xen_domctl_gdbsx_domstatus {
uint32_t vcpu_ev; /* if yes, what event? */
};
+
+/*
+ * Memory event operations
+ */
+
+#define XEN_DOMCTL_mem_event_op 56
+
+/* Add and remove memory handlers */
+#define XEN_DOMCTL_MEM_EVENT_OP_ENABLE 0
+#define XEN_DOMCTL_MEM_EVENT_OP_DISABLE 1
+
+struct xen_domctl_mem_event_op {
+ uint32_t op; /* XEN_DOMCTL_MEM_EVENT_OP_* */
+ uint32_t mode; /* XEN_DOMCTL_MEM_EVENT_ENABLE_* */
+
+ /* OP_ENABLE */
+ unsigned long shared_addr; /* IN: Virtual address of shared page */
+ unsigned long ring_addr; /* IN: Virtual address of ring page */
+
+ /* Other OPs */
+ unsigned long gfn; /* IN: gfn of page being operated on */
+};
+typedef struct xen_domctl_mem_event_op xen_domctl_mem_event_op_t;
+DEFINE_XEN_GUEST_HANDLE(xen_domctl_mem_event_op_t);
+
struct xen_domctl {
uint32_t cmd;
@@ -734,6 +759,7 @@ struct xen_domctl {
struct xen_domctl_set_target set_target;
struct xen_domctl_subscribe subscribe;
struct xen_domctl_debug_op debug_op;
+ struct xen_domctl_mem_event_op mem_event_op;
#if defined(__i386__) || defined(__x86_64__)
struct xen_domctl_cpuid cpuid;
#endif
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|