aboutsummaryrefslogtreecommitdiffstats
path: root/xen/common
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2009-05-27 10:38:51 +0100
committerKeir Fraser <keir.fraser@citrix.com>2009-05-27 10:38:51 +0100
commitcf5e6f2d34413cac233939ab701191655a587ca7 (patch)
tree5fde2db2a07a672e7b4ca8d5d3c2d38d0d93fe3e /xen/common
parente3e8ff02c5f467b72078bf9246b2484844c4cadc (diff)
downloadxen-cf5e6f2d34413cac233939ab701191655a587ca7.tar.gz
xen-cf5e6f2d34413cac233939ab701191655a587ca7.tar.bz2
xen-cf5e6f2d34413cac233939ab701191655a587ca7.zip
x86: eliminate hard-coded NR_IRQS
... splitting it into global nr_irqs (determined at boot time) and per- domain nr_pirqs (derived from nr_irqs and a possibly command line specified value, which probably should later become a per-domain config setting). This has the (desirable imo) side effect of reducing the size of struct hvm_irq_dpci from requiring an order-3 page to order-2 (on x86-64), which nevertheless still is too large. However, there is now a variable size bit array on the stack in pt_irq_time_out() - while for the moment this probably is okay, it certainly doesn't look nice. However, replacing this with a static (pre-)allocation also seems less than ideal, because that would require at least min(d->nr_pirqs, NR_VECTORS) bit arrays of d->nr_pirqs bits, since this bit array is used outside of the serialized code region in that function, and keeping the domain's event lock acquired across pirq_guest_eoi() doesn't look like a good idea either. The IRQ- and vector-indexed arrays hanging off struct hvm_irq_dpci could in fact be changed further to dynamically use the smaller of the two ranges for indexing, since there are other assumptions about a one-to-one relationship between IRQs and vectors here and elsewhere. Additionally, it seems to me that struct hvm_mirq_dpci_mapping's digl_list and gmsi fields could really be overlayed, which would yield significant savings since this structure gets always instanciated in form of d->nr_pirqs (as per the above could also be the smaller of this and NR_VECTORS) dimensioned arrays. Signed-off-by: Jan Beulich <jbeulich@novell.com>
Diffstat (limited to 'xen/common')
-rw-r--r--xen/common/domain.c25
-rw-r--r--xen/common/domctl.c8
-rw-r--r--xen/common/event_channel.c2
3 files changed, 29 insertions, 6 deletions
diff --git a/xen/common/domain.c b/xen/common/domain.c
index 66694168a2..1d3b4d6b58 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -8,6 +8,7 @@
#include <xen/compat.h>
#include <xen/init.h>
#include <xen/lib.h>
+#include <xen/ctype.h>
#include <xen/errno.h>
#include <xen/sched.h>
#include <xen/domain.h>
@@ -198,6 +199,16 @@ struct vcpu *alloc_idle_vcpu(unsigned int cpu_id)
return v;
}
+static unsigned int extra_dom0_irqs, extra_domU_irqs = 8;
+static void __init parse_extra_guest_irqs(const char *s)
+{
+ if ( isdigit(*s) )
+ extra_domU_irqs = simple_strtoul(s, &s, 0);
+ if ( *s == ',' && isdigit(*++s) )
+ extra_dom0_irqs = simple_strtoul(s, &s, 0);
+}
+custom_param("extra_guest_irqs", parse_extra_guest_irqs);
+
struct domain *domain_create(
domid_t domid, unsigned int domcr_flags, ssidref_t ssidref)
{
@@ -244,9 +255,19 @@ struct domain *domain_create(
d->is_paused_by_controller = 1;
atomic_inc(&d->pause_count);
+ d->nr_pirqs = nr_irqs +
+ (domid ? extra_domU_irqs :
+ extra_dom0_irqs ?: nr_irqs);
if ( evtchn_init(d) != 0 )
goto fail;
init_status |= INIT_evtchn;
+ d->pirq_to_evtchn = xmalloc_array(u16, d->nr_pirqs);
+ d->pirq_mask = xmalloc_array(unsigned long,
+ BITS_TO_LONGS(d->nr_pirqs));
+ if ( !d->pirq_to_evtchn || !d->pirq_mask )
+ goto fail;
+ memset(d->pirq_to_evtchn, 0, d->nr_pirqs * sizeof(*d->pirq_to_evtchn));
+ bitmap_zero(d->pirq_mask, d->nr_pirqs);
if ( grant_table_create(d) != 0 )
goto fail;
@@ -289,7 +310,11 @@ struct domain *domain_create(
if ( init_status & INIT_gnttab )
grant_table_destroy(d);
if ( init_status & INIT_evtchn )
+ {
+ xfree(d->pirq_mask);
+ xfree(d->pirq_to_evtchn);
evtchn_destroy(d);
+ }
if ( init_status & INIT_rangeset )
rangeset_domain_destroy(d);
if ( init_status & INIT_xsm )
diff --git a/xen/common/domctl.c b/xen/common/domctl.c
index 4a8df90101..29e3885de2 100644
--- a/xen/common/domctl.c
+++ b/xen/common/domctl.c
@@ -774,16 +774,14 @@ long do_domctl(XEN_GUEST_HANDLE(xen_domctl_t) u_domctl)
struct domain *d;
unsigned int pirq = op->u.irq_permission.pirq;
- ret = -EINVAL;
- if ( pirq >= NR_IRQS )
- break;
-
ret = -ESRCH;
d = rcu_lock_domain_by_id(op->domain);
if ( d == NULL )
break;
- if ( op->u.irq_permission.allow_access )
+ if ( pirq >= d->nr_pirqs )
+ ret = -EINVAL;
+ else if ( op->u.irq_permission.allow_access )
ret = irq_permit_access(d, pirq);
else
ret = irq_deny_access(d, pirq);
diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c
index 3f36d09e83..c51fd10031 100644
--- a/xen/common/event_channel.c
+++ b/xen/common/event_channel.c
@@ -302,7 +302,7 @@ static long evtchn_bind_pirq(evtchn_bind_pirq_t *bind)
int port, pirq = bind->pirq;
long rc;
- if ( (pirq < 0) || (pirq >= ARRAY_SIZE(d->pirq_to_evtchn)) )
+ if ( (pirq < 0) || (pirq >= d->nr_pirqs) )
return -EINVAL;
if ( !irq_access_permitted(d, pirq) )