aboutsummaryrefslogtreecommitdiffstats
path: root/xen/common/event_channel.c
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2009-06-18 10:14:16 +0100
committerKeir Fraser <keir.fraser@citrix.com>2009-06-18 10:14:16 +0100
commitfb442e217186a5bc3ed7ec84f0b683b708609eac (patch)
treeb8f199e985285357b03ca679c4eb352c7000bb19 /xen/common/event_channel.c
parenta5c98899b234c23f43dae0f7dd58649a666d070e (diff)
downloadxen-fb442e217186a5bc3ed7ec84f0b683b708609eac.tar.gz
xen-fb442e217186a5bc3ed7ec84f0b683b708609eac.tar.bz2
xen-fb442e217186a5bc3ed7ec84f0b683b708609eac.zip
x86_64: allow more vCPU-s per guest
Since the shared info layout is fixed, guests are required to use VCPUOP_register_vcpu_info prior to booting any vCPU beyond the traditional limit of 32. MAX_VIRT_CPUS, being an implemetation detail of the hypervisor, is no longer being exposed in the public headers. The tools changes are clearly incomplete (and done only so things would build again), and the current state of the tools (using scalar variables all over the place to represent vCPU bitmaps) very likely doesn't permit booting DomU-s with more than the traditional number of vCPU-s. Testing of the extended functionality was done with Dom0 (96 vCPU-s, as well as 128 vCPU-s out of which the kernel elected - by way of a simple kernel side patch - to use only some, resulting in a sparse bitmap). ia64 changes only to make things build, and build-tested only (and the tools part only as far as the build would go without encountering unrelated problems in the blktap code). Signed-off-by: Jan Beulich <jbeulich@novell.com>
Diffstat (limited to 'xen/common/event_channel.c')
-rw-r--r--xen/common/event_channel.c41
1 files changed, 33 insertions, 8 deletions
diff --git a/xen/common/event_channel.c b/xen/common/event_channel.c
index c51fd10031..ccc709111f 100644
--- a/xen/common/event_channel.c
+++ b/xen/common/event_channel.c
@@ -240,10 +240,13 @@ static long evtchn_bind_virq(evtchn_bind_virq_t *bind)
if ( virq_is_global(virq) && (vcpu != 0) )
return -EINVAL;
- if ( (vcpu < 0) || (vcpu >= ARRAY_SIZE(d->vcpu)) ||
+ if ( (vcpu < 0) || (vcpu >= d->max_vcpus) ||
((v = d->vcpu[vcpu]) == NULL) )
return -ENOENT;
+ if ( unlikely(!v->vcpu_info) )
+ return -EAGAIN;
+
spin_lock(&d->event_lock);
if ( v->virq_to_evtchn[virq] != 0 )
@@ -273,10 +276,13 @@ static long evtchn_bind_ipi(evtchn_bind_ipi_t *bind)
int port, vcpu = bind->vcpu;
long rc = 0;
- if ( (vcpu < 0) || (vcpu >= ARRAY_SIZE(d->vcpu)) ||
+ if ( (vcpu < 0) || (vcpu >= d->max_vcpus) ||
(d->vcpu[vcpu] == NULL) )
return -ENOENT;
+ if ( unlikely(!d->vcpu[vcpu]->vcpu_info) )
+ return -EAGAIN;
+
spin_lock(&d->event_lock);
if ( (port = get_free_port(d)) < 0 )
@@ -555,13 +561,13 @@ static int evtchn_set_pending(struct vcpu *v, int port)
}
/* Check if some VCPU might be polling for this event. */
- if ( likely(bitmap_empty(d->poll_mask, MAX_VIRT_CPUS)) )
+ if ( likely(bitmap_empty(d->poll_mask, d->max_vcpus)) )
return 0;
/* Wake any interested (or potentially interested) pollers. */
- for ( vcpuid = find_first_bit(d->poll_mask, MAX_VIRT_CPUS);
- vcpuid < MAX_VIRT_CPUS;
- vcpuid = find_next_bit(d->poll_mask, MAX_VIRT_CPUS, vcpuid+1) )
+ for ( vcpuid = find_first_bit(d->poll_mask, d->max_vcpus);
+ vcpuid < d->max_vcpus;
+ vcpuid = find_next_bit(d->poll_mask, d->max_vcpus, vcpuid+1) )
{
v = d->vcpu[vcpuid];
if ( ((v->poll_evtchn <= 0) || (v->poll_evtchn == port)) &&
@@ -608,7 +614,7 @@ void send_guest_global_virq(struct domain *d, int virq)
ASSERT(virq_is_global(virq));
- if ( unlikely(d == NULL) )
+ if ( unlikely(d == NULL) || unlikely(d->vcpu == NULL) )
return;
v = d->vcpu[0];
@@ -717,9 +723,12 @@ long evtchn_bind_vcpu(unsigned int port, unsigned int vcpu_id)
struct evtchn *chn;
long rc = 0;
- if ( (vcpu_id >= ARRAY_SIZE(d->vcpu)) || (d->vcpu[vcpu_id] == NULL) )
+ if ( (vcpu_id >= d->max_vcpus) || (d->vcpu[vcpu_id] == NULL) )
return -ENOENT;
+ if ( unlikely(!d->vcpu[vcpu_id]->vcpu_info) )
+ return -EAGAIN;
+
spin_lock(&d->event_lock);
if ( !port_is_valid(d, port) )
@@ -943,6 +952,9 @@ int alloc_unbound_xen_event_channel(
struct domain *d = local_vcpu->domain;
int port;
+ if ( unlikely(!local_vcpu->vcpu_info) )
+ return -EAGAIN;
+
spin_lock(&d->event_lock);
if ( (port = get_free_port(d)) < 0 )
@@ -1016,6 +1028,14 @@ int evtchn_init(struct domain *d)
if ( get_free_port(d) != 0 )
return -EINVAL;
evtchn_from_port(d, 0)->state = ECS_RESERVED;
+
+#if MAX_VIRT_CPUS > BITS_PER_LONG
+ d->poll_mask = xmalloc_array(unsigned long, BITS_TO_LONGS(MAX_VIRT_CPUS));
+ if ( !d->poll_mask )
+ return -ENOMEM;
+ bitmap_zero(d->poll_mask, MAX_VIRT_CPUS);
+#endif
+
return 0;
}
@@ -1044,6 +1064,11 @@ void evtchn_destroy(struct domain *d)
d->evtchn[i] = NULL;
}
spin_unlock(&d->event_lock);
+
+#if MAX_VIRT_CPUS > BITS_PER_LONG
+ xfree(d->poll_mask);
+ d->poll_mask = NULL;
+#endif
}
static void domain_dump_evtchn_info(struct domain *d)