[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 09/11] evtchn: implement EVTCHNOP_set_limit
From: David Vrabel <david.vrabel@xxxxxxxxxx> Add max_evtchn_port to struct domain as the maximum port number that a domain may bind. Allow a suitably privileged domain to set this limit so it may restrict the other domain's usage of Xen resources for event channels (primarily global mapping entries for the shared data structures). The default values for this limit is unlimited for control domains or NR_EVENT_CHANNELS - 1 for other domains. These defaults ensure that no domain will regress in the number of event channels they may use. If a domain is expected to use the FIFO-based event channel ABI, a toolstack may wish to set the limit to 1023 or lower to ensure a minimum number of global mapping entries is used. Signed-off-by: David Vrabel <david.vrabel@xxxxxxxxxx> Cc: Daniel De Graaf <dgdegra@xxxxxxxxxxxxx> --- xen/common/event_channel.c | 47 +++++++++++++++++++++++++++++++++++- xen/include/public/event_channel.h | 3 ++ xen/include/xen/sched.h | 1 + xen/include/xsm/dummy.h | 6 ++++ xen/include/xsm/xsm.h | 6 ++++ 5 files changed, 62 insertions(+), 1 deletions(-) diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c index d583d54..45ff115 100644 --- a/xen/common/event_channel.c +++ b/xen/common/event_channel.c @@ -132,10 +132,14 @@ static int get_free_port(struct domain *d) return -EINVAL; for ( port = 0; port_is_valid(d, port); port++ ) + { + if (port > d->max_evtchn_port ) + return -ENOSPC; if ( evtchn_from_port(d, port)->state == ECS_FREE ) return port; + } - if ( port == d->max_evtchns ) + if ( port == d->max_evtchns || port > d->max_evtchn_port ) return -ENOSPC; if ( unlikely(group_from_port(d, port) == NULL ) ) @@ -956,6 +960,34 @@ static long evtchn_set_priority(const struct evtchn_set_priority *set_priority) return ret; } +static long evtchn_set_limit(const struct evtchn_set_limit *set_limit) +{ + struct domain *d; + unsigned max_port = set_limit->max_port; + long ret; + + if ( max_port > EVTCHN_MAX_PORT_UNLIMITED ) + return -EINVAL; + + d = rcu_lock_domain_by_id(set_limit->domid); + if ( !d ) + return -ESRCH; + + ret = xsm_evtchn_set_limit(XSM_DM_PRIV, d); + if ( ret ) + goto out; + + spin_lock(&d->event_lock); + + d->max_evtchn_port = max_port; + + spin_unlock(&d->event_lock); + +out: + rcu_unlock_domain(d); + return ret; +} + long do_event_channel_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg) { long rc; @@ -1072,6 +1104,14 @@ long do_event_channel_op(int cmd, XEN_GUEST_HANDLE_PARAM(void) arg) break; } + case EVTCHNOP_set_limit: { + struct evtchn_set_limit set_limit; + if ( copy_from_guest(&set_limit, arg, 1) != 0 ) + return -EFAULT; + rc = evtchn_set_limit(&set_limit); + break; + } + default: rc = -ENOSYS; break; @@ -1189,6 +1229,11 @@ void evtchn_check_pollers(struct domain *d, unsigned port) int evtchn_init(struct domain *d) { + if ( is_control_domain(d) ) + d->max_evtchn_port = EVTCHN_MAX_PORT_UNLIMITED; + else + d->max_evtchn_port = EVTCHN_MAX_PORT_DEFAULT; + /* Default to N-level ABI. */ evtchn_2l_init(d); diff --git a/xen/include/public/event_channel.h b/xen/include/public/event_channel.h index 031366a..30a233c 100644 --- a/xen/include/public/event_channel.h +++ b/xen/include/public/event_channel.h @@ -308,6 +308,9 @@ struct evtchn_set_limit { }; typedef struct evtchn_set_limit evtchn_set_limit_t; +#define EVTCHN_MAX_PORT_UNLIMITED ((1u << 31) - 1) +#define EVTCHN_MAX_PORT_DEFAULT (NR_EVENT_CHANNELS - 1) + /* * ` enum neg_errnoval * ` HYPERVISOR_event_channel_op_compat(struct evtchn_op *op) diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h index b348232..ba3714d 100644 --- a/xen/include/xen/sched.h +++ b/xen/include/xen/sched.h @@ -287,6 +287,7 @@ struct domain /* Event channel information. */ struct evtchn ***evtchn; unsigned max_evtchns; + unsigned max_evtchn_port; spinlock_t event_lock; const struct evtchn_port_ops *evtchn_port_ops; diff --git a/xen/include/xsm/dummy.h b/xen/include/xsm/dummy.h index cc0a5a8..3f1f3c1 100644 --- a/xen/include/xsm/dummy.h +++ b/xen/include/xsm/dummy.h @@ -296,6 +296,12 @@ static XSM_INLINE int xsm_evtchn_reset(XSM_DEFAULT_ARG struct domain *d1, struct return xsm_default_action(action, d1, d2); } +static XSM_INLINE int xsm_evtchn_set_limit(XSM_DEFAULT_ARG struct domain *d) +{ + XSM_ASSERT_ACTION(XSM_DM_PRIV); + return xsm_default_action(action, current->domain, d); +} + static XSM_INLINE int xsm_alloc_security_evtchn(struct evtchn *chn) { return 0; diff --git a/xen/include/xsm/xsm.h b/xen/include/xsm/xsm.h index 1939453..ae79ca9 100644 --- a/xen/include/xsm/xsm.h +++ b/xen/include/xsm/xsm.h @@ -70,6 +70,7 @@ struct xsm_operations { int (*evtchn_send) (struct domain *d, struct evtchn *chn); int (*evtchn_status) (struct domain *d, struct evtchn *chn); int (*evtchn_reset) (struct domain *d1, struct domain *d2); + int (*evtchn_set_limit) (struct domain *d); int (*grant_mapref) (struct domain *d1, struct domain *d2, uint32_t flags); int (*grant_unmapref) (struct domain *d1, struct domain *d2); @@ -255,6 +256,11 @@ static inline int xsm_evtchn_reset (xsm_default_t def, struct domain *d1, struct return xsm_ops->evtchn_reset(d1, d2); } +static inline int xsm_evtchn_set_limit (xsm_default_t def, struct domain *d) +{ + return xsm_ops->evtchn_set_limit(d); +} + static inline int xsm_grant_mapref (xsm_default_t def, struct domain *d1, struct domain *d2, uint32_t flags) { -- 1.7.2.5 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |