ia64/xen-unstable

annotate xen/common/event_channel.c @ 1505:ead91151a0e6

bitkeeper revision 1.982 (40d300456_XUbFFOMxRh4MjyB7AfJA)

Hacked the scheduler interfaces in Xen.
We now have synchronous pause.
Suspend/death VIRQs have gone away; replace by dom-controller msgs.
Xen no longer knows about PS/2 keyboard/mouse; DOM0 can go straight
at them.
author kaf24@scramble.cl.cam.ac.uk
date Fri Jun 18 14:46:29 2004 +0000 (2004-06-18)
parents b4a9837c89b1
children 729cac1fb14e
rev   line source
kaf24@954 1 /******************************************************************************
kaf24@954 2 * event_channel.c
kaf24@954 3 *
kaf24@954 4 * Event channels between domains.
kaf24@954 5 *
kaf24@1127 6 * Copyright (c) 2003-2004, K A Fraser.
kaf24@954 7 *
kaf24@954 8 * This program is distributed in the hope that it will be useful,
kaf24@954 9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
kaf24@954 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
kaf24@954 11 * GNU General Public License for more details.
kaf24@954 12 *
kaf24@954 13 * You should have received a copy of the GNU General Public License
kaf24@954 14 * along with this program; if not, write to the Free Software
kaf24@954 15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
kaf24@954 16 */
kaf24@954 17
kaf24@1210 18 #include <xen/config.h>
kaf24@1210 19 #include <xen/init.h>
kaf24@1210 20 #include <xen/lib.h>
kaf24@1210 21 #include <xen/errno.h>
kaf24@1210 22 #include <xen/sched.h>
kaf24@1210 23 #include <xen/event.h>
kaf24@1239 24 #include <xen/irq.h>
kaf24@954 25
kaf24@1127 26 #include <hypervisor-ifs/hypervisor-if.h>
kaf24@1127 27 #include <hypervisor-ifs/event_channel.h>
kaf24@1127 28
kaf24@1218 29 #define INIT_EVENT_CHANNELS 16
kaf24@1218 30 #define MAX_EVENT_CHANNELS 1024
kaf24@954 31
kaf24@1505 32 static int get_free_port(struct domain *p)
kaf24@954 33 {
kaf24@1127 34 int max, port;
kaf24@1127 35 event_channel_t *chn;
kaf24@1127 36
kaf24@1127 37 max = p->max_event_channel;
kaf24@1127 38 chn = p->event_channel;
kaf24@1127 39
kaf24@1127 40 for ( port = 0; port < max; port++ )
kaf24@1127 41 if ( chn[port].state == ECS_FREE )
kaf24@1127 42 break;
kaf24@1127 43
kaf24@1127 44 if ( port == max )
kaf24@1127 45 {
kaf24@1127 46 if ( max == MAX_EVENT_CHANNELS )
kaf24@1127 47 return -ENOSPC;
kaf24@1127 48
kaf24@1258 49 max *= 2;
kaf24@1127 50
kaf24@1127 51 chn = kmalloc(max * sizeof(event_channel_t), GFP_KERNEL);
kaf24@1127 52 if ( unlikely(chn == NULL) )
kaf24@1127 53 return -ENOMEM;
kaf24@1127 54
kaf24@1127 55 memset(chn, 0, max * sizeof(event_channel_t));
kaf24@1127 56
kaf24@1127 57 if ( p->event_channel != NULL )
kaf24@1127 58 {
kaf24@1127 59 memcpy(chn, p->event_channel, (max/2) * sizeof(event_channel_t));
kaf24@1127 60 kfree(p->event_channel);
kaf24@1127 61 }
kaf24@1127 62
kaf24@1127 63 p->event_channel = chn;
kaf24@1127 64 p->max_event_channel = max;
kaf24@1127 65 }
kaf24@1127 66
kaf24@1127 67 return port;
kaf24@1127 68 }
kaf24@1127 69
kaf24@1218 70 static long evtchn_bind_interdomain(evtchn_bind_interdomain_t *bind)
kaf24@1127 71 {
kaf24@1505 72 struct domain *p1, *p2;
kaf24@1129 73 int port1 = 0, port2 = 0;
kaf24@1218 74 domid_t dom1 = bind->dom1, dom2 = bind->dom2;
kaf24@954 75 long rc = 0;
kaf24@954 76
kaf24@1127 77 if ( !IS_PRIV(current) )
kaf24@1127 78 return -EPERM;
kaf24@954 79
kaf24@1129 80 if ( dom1 == DOMID_SELF )
kaf24@1129 81 dom1 = current->domain;
kaf24@1129 82 if ( dom2 == DOMID_SELF )
kaf24@1135 83 dom2 = current->domain;
kaf24@1127 84
kaf24@1129 85 if ( ((p1 = find_domain_by_id(dom1)) == NULL) ||
kaf24@1129 86 ((p2 = find_domain_by_id(dom2)) == NULL) )
kaf24@1127 87 {
kaf24@1129 88 if ( p1 != NULL )
kaf24@1505 89 put_domain(p1);
kaf24@1127 90 return -ESRCH;
kaf24@1127 91 }
kaf24@1127 92
kaf24@1127 93 /* Avoid deadlock by first acquiring lock of domain with smaller id. */
kaf24@1129 94 if ( dom1 < dom2 )
kaf24@954 95 {
kaf24@1129 96 spin_lock(&p1->event_channel_lock);
kaf24@1129 97 spin_lock(&p2->event_channel_lock);
kaf24@954 98 }
kaf24@954 99 else
kaf24@954 100 {
kaf24@1135 101 if ( p1 != p2 )
kaf24@1135 102 spin_lock(&p2->event_channel_lock);
kaf24@1129 103 spin_lock(&p1->event_channel_lock);
kaf24@954 104 }
kaf24@954 105
kaf24@1129 106 if ( (port1 = get_free_port(p1)) < 0 )
kaf24@954 107 {
kaf24@1129 108 rc = port1;
kaf24@1127 109 goto out;
kaf24@954 110 }
kaf24@954 111
kaf24@1329 112 /* 'Allocate' port1 before searching for a free port2. */
kaf24@1329 113 p1->event_channel[port1].state = ECS_INTERDOMAIN;
kaf24@1329 114
kaf24@1129 115 if ( (port2 = get_free_port(p2)) < 0 )
kaf24@954 116 {
kaf24@1329 117 p1->event_channel[port1].state = ECS_FREE;
kaf24@1129 118 rc = port2;
kaf24@1127 119 goto out;
kaf24@1127 120 }
kaf24@954 121
kaf24@1218 122 p1->event_channel[port1].u.remote.dom = p2;
kaf24@1218 123 p1->event_channel[port1].u.remote.port = (u16)port2;
kaf24@954 124
kaf24@1218 125 p2->event_channel[port2].u.remote.dom = p1;
kaf24@1218 126 p2->event_channel[port2].u.remote.port = (u16)port1;
kaf24@1218 127 p2->event_channel[port2].state = ECS_INTERDOMAIN;
kaf24@1127 128
kaf24@1218 129 evtchn_set_pending(p1, port1);
kaf24@1218 130 evtchn_set_pending(p2, port2);
kaf24@954 131
kaf24@954 132 out:
kaf24@1129 133 spin_unlock(&p1->event_channel_lock);
kaf24@1135 134 if ( p1 != p2 )
kaf24@1135 135 spin_unlock(&p2->event_channel_lock);
kaf24@1127 136
kaf24@1505 137 put_domain(p1);
kaf24@1505 138 put_domain(p2);
kaf24@1127 139
kaf24@1218 140 bind->port1 = port1;
kaf24@1218 141 bind->port2 = port2;
kaf24@954 142
kaf24@954 143 return rc;
kaf24@954 144 }
kaf24@954 145
kaf24@954 146
kaf24@1218 147 static long evtchn_bind_virq(evtchn_bind_virq_t *bind)
kaf24@1218 148 {
kaf24@1505 149 struct domain *p = current;
kaf24@1218 150 int virq = bind->virq;
kaf24@1218 151 int port;
kaf24@1218 152
kaf24@1235 153 if ( virq >= ARRAY_SIZE(p->virq_to_evtchn) )
kaf24@1218 154 return -EINVAL;
kaf24@1218 155
kaf24@1218 156 spin_lock(&p->event_channel_lock);
kaf24@1218 157
kaf24@1218 158 /*
kaf24@1218 159 * Port 0 is the fallback port for VIRQs that haven't been explicitly
kaf24@1249 160 * bound yet. The exception is the 'misdirect VIRQ', which is permanently
kaf24@1218 161 * bound to port 0.
kaf24@1218 162 */
kaf24@1218 163 if ( ((port = p->virq_to_evtchn[virq]) != 0) ||
kaf24@1249 164 (virq == VIRQ_MISDIRECT) ||
kaf24@1218 165 ((port = get_free_port(p)) < 0) )
kaf24@1218 166 goto out;
kaf24@1218 167
kaf24@1218 168 p->event_channel[port].state = ECS_VIRQ;
kaf24@1218 169 p->event_channel[port].u.virq = virq;
kaf24@1218 170
kaf24@1218 171 p->virq_to_evtchn[virq] = port;
kaf24@1218 172
kaf24@1218 173 out:
kaf24@1218 174 spin_unlock(&p->event_channel_lock);
kaf24@1218 175
kaf24@1218 176 if ( port < 0 )
kaf24@1218 177 return port;
kaf24@1218 178
kaf24@1218 179 bind->port = port;
kaf24@1218 180 return 0;
kaf24@1218 181 }
kaf24@1218 182
kaf24@1218 183
kaf24@1235 184 static long evtchn_bind_pirq(evtchn_bind_pirq_t *bind)
kaf24@1235 185 {
kaf24@1505 186 struct domain *p = current;
kaf24@1235 187 int pirq = bind->pirq;
kaf24@1239 188 int port, rc;
kaf24@1235 189
kaf24@1235 190 if ( pirq >= ARRAY_SIZE(p->pirq_to_evtchn) )
kaf24@1235 191 return -EINVAL;
kaf24@1235 192
kaf24@1235 193 spin_lock(&p->event_channel_lock);
kaf24@1235 194
kaf24@1239 195 if ( ((rc = port = p->pirq_to_evtchn[pirq]) != 0) ||
kaf24@1239 196 ((rc = port = get_free_port(p)) < 0) )
kaf24@1235 197 goto out;
kaf24@1235 198
kaf24@1239 199 p->pirq_to_evtchn[pirq] = port;
kaf24@1253 200 rc = pirq_guest_bind(p, pirq,
kaf24@1253 201 !!(bind->flags & BIND_PIRQ__WILL_SHARE));
kaf24@1253 202 if ( rc != 0 )
kaf24@1239 203 {
kaf24@1239 204 p->pirq_to_evtchn[pirq] = 0;
kaf24@1251 205 DPRINTK("Couldn't bind to PIRQ %d (error=%d)\n", pirq, rc);
kaf24@1239 206 goto out;
kaf24@1239 207 }
kaf24@1239 208
kaf24@1235 209 p->event_channel[port].state = ECS_PIRQ;
kaf24@1235 210 p->event_channel[port].u.pirq = pirq;
kaf24@1235 211
kaf24@1235 212 out:
kaf24@1235 213 spin_unlock(&p->event_channel_lock);
kaf24@1235 214
kaf24@1239 215 if ( rc < 0 )
kaf24@1239 216 return rc;
kaf24@1235 217
kaf24@1235 218 bind->port = port;
kaf24@1235 219 return 0;
kaf24@1235 220 }
kaf24@1235 221
kaf24@1235 222
kaf24@1505 223 static long __evtchn_close(struct domain *p1, int port1)
kaf24@954 224 {
kaf24@1505 225 struct domain *p2 = NULL;
kaf24@1129 226 event_channel_t *chn1, *chn2;
kaf24@1129 227 int port2;
kaf24@954 228 long rc = 0;
kaf24@954 229
kaf24@954 230 again:
kaf24@1129 231 spin_lock(&p1->event_channel_lock);
kaf24@954 232
kaf24@1129 233 chn1 = p1->event_channel;
kaf24@954 234
kaf24@1249 235 /* NB. Port 0 is special (VIRQ_MISDIRECT). Never let it be closed. */
kaf24@1218 236 if ( (port1 <= 0) || (port1 >= p1->max_event_channel) )
kaf24@954 237 {
kaf24@954 238 rc = -EINVAL;
kaf24@954 239 goto out;
kaf24@954 240 }
kaf24@954 241
kaf24@1218 242 switch ( chn1[port1].state )
kaf24@954 243 {
kaf24@1218 244 case ECS_FREE:
kaf24@1218 245 rc = -EINVAL;
kaf24@1218 246 goto out;
kaf24@1218 247
kaf24@1218 248 case ECS_UNBOUND:
kaf24@1218 249 break;
kaf24@1218 250
kaf24@1218 251 case ECS_PIRQ:
kaf24@1239 252 if ( (rc = pirq_guest_unbind(p1, chn1[port1].u.pirq)) == 0 )
kaf24@1239 253 p1->pirq_to_evtchn[chn1[port1].u.pirq] = 0;
kaf24@1218 254 break;
kaf24@1218 255
kaf24@1218 256 case ECS_VIRQ:
kaf24@1218 257 p1->virq_to_evtchn[chn1[port1].u.virq] = 0;
kaf24@1218 258 break;
kaf24@1218 259
kaf24@1218 260 case ECS_INTERDOMAIN:
kaf24@1129 261 if ( p2 == NULL )
kaf24@954 262 {
kaf24@1218 263 p2 = chn1[port1].u.remote.dom;
kaf24@1505 264
kaf24@1505 265 /* If we unlock p1 then we could lose p2. Must get a reference. */
kaf24@1505 266 if ( unlikely(!get_domain(p2)) )
kaf24@1505 267 {
kaf24@1505 268 /*
kaf24@1505 269 * Failed to obtain a reference. No matter: p2 must be dying
kaf24@1505 270 * and so will close this event channel for us.
kaf24@1505 271 */
kaf24@1505 272 p2 = NULL;
kaf24@1505 273 goto out;
kaf24@1505 274 }
kaf24@1127 275
kaf24@1129 276 if ( p1->domain < p2->domain )
kaf24@954 277 {
kaf24@1129 278 spin_lock(&p2->event_channel_lock);
kaf24@954 279 }
kaf24@1135 280 else if ( p1 != p2 )
kaf24@954 281 {
kaf24@1129 282 spin_unlock(&p1->event_channel_lock);
kaf24@1129 283 spin_lock(&p2->event_channel_lock);
kaf24@954 284 goto again;
kaf24@954 285 }
kaf24@954 286 }
kaf24@1218 287 else if ( p2 != chn1[port1].u.remote.dom )
kaf24@954 288 {
kaf24@954 289 rc = -EINVAL;
kaf24@954 290 goto out;
kaf24@954 291 }
kaf24@1505 292
kaf24@1129 293 chn2 = p2->event_channel;
kaf24@1218 294 port2 = chn1[port1].u.remote.port;
kaf24@954 295
kaf24@1129 296 if ( port2 >= p2->max_event_channel )
kaf24@1127 297 BUG();
kaf24@1218 298 if ( chn2[port2].state != ECS_INTERDOMAIN )
kaf24@1127 299 BUG();
kaf24@1218 300 if ( chn2[port2].u.remote.dom != p1 )
kaf24@1127 301 BUG();
kaf24@954 302
kaf24@1258 303 chn2[port2].state = ECS_UNBOUND;
kaf24@1218 304 evtchn_set_exception(p2, port2);
kaf24@1218 305
kaf24@1218 306 break;
kaf24@1218 307
kaf24@1218 308 default:
kaf24@1218 309 BUG();
kaf24@954 310 }
kaf24@954 311
kaf24@1258 312 chn1[port1].state = ECS_FREE;
kaf24@1218 313 evtchn_set_exception(p1, port1);
kaf24@1133 314
kaf24@954 315 out:
kaf24@1129 316 if ( p2 != NULL )
kaf24@954 317 {
kaf24@1135 318 if ( p1 != p2 )
kaf24@1135 319 spin_unlock(&p2->event_channel_lock);
kaf24@1505 320 put_domain(p2);
kaf24@954 321 }
kaf24@954 322
kaf24@1145 323 spin_unlock(&p1->event_channel_lock);
kaf24@1145 324
kaf24@954 325 return rc;
kaf24@954 326 }
kaf24@954 327
kaf24@954 328
kaf24@1218 329 static long evtchn_close(evtchn_close_t *close)
kaf24@1127 330 {
kaf24@1505 331 struct domain *p;
kaf24@1127 332 long rc;
kaf24@1129 333 domid_t dom = close->dom;
kaf24@1127 334
kaf24@1129 335 if ( dom == DOMID_SELF )
kaf24@1129 336 dom = current->domain;
kaf24@1127 337 else if ( !IS_PRIV(current) )
kaf24@1127 338 return -EPERM;
kaf24@1127 339
kaf24@1129 340 if ( (p = find_domain_by_id(dom)) == NULL )
kaf24@1127 341 return -ESRCH;
kaf24@1127 342
kaf24@1218 343 rc = __evtchn_close(p, close->port);
kaf24@1127 344
kaf24@1505 345 put_domain(p);
kaf24@1127 346 return rc;
kaf24@1127 347 }
kaf24@1127 348
kaf24@1127 349
kaf24@1218 350 static long evtchn_send(int lport)
kaf24@954 351 {
kaf24@1505 352 struct domain *lp = current, *rp;
kaf24@1127 353 int rport;
kaf24@954 354
kaf24@954 355 spin_lock(&lp->event_channel_lock);
kaf24@954 356
kaf24@1127 357 if ( unlikely(lport < 0) ||
kaf24@1127 358 unlikely(lport >= lp->max_event_channel) ||
kaf24@1218 359 unlikely(lp->event_channel[lport].state != ECS_INTERDOMAIN) )
kaf24@954 360 {
kaf24@954 361 spin_unlock(&lp->event_channel_lock);
kaf24@954 362 return -EINVAL;
kaf24@954 363 }
kaf24@954 364
kaf24@1218 365 rp = lp->event_channel[lport].u.remote.dom;
kaf24@1218 366 rport = lp->event_channel[lport].u.remote.port;
kaf24@1127 367
kaf24@1505 368 evtchn_set_pending(rp, rport);
kaf24@954 369
kaf24@954 370 spin_unlock(&lp->event_channel_lock);
kaf24@954 371
kaf24@954 372 return 0;
kaf24@954 373 }
kaf24@954 374
kaf24@954 375
kaf24@1218 376 static long evtchn_status(evtchn_status_t *status)
kaf24@954 377 {
kaf24@1505 378 struct domain *p;
kaf24@1218 379 domid_t dom = status->dom;
kaf24@1218 380 int port = status->port;
kaf24@1129 381 event_channel_t *chn;
kaf24@1266 382 long rc = 0;
kaf24@1127 383
kaf24@1129 384 if ( dom == DOMID_SELF )
kaf24@1129 385 dom = current->domain;
kaf24@1127 386 else if ( !IS_PRIV(current) )
kaf24@1127 387 return -EPERM;
kaf24@1127 388
kaf24@1129 389 if ( (p = find_domain_by_id(dom)) == NULL )
kaf24@1127 390 return -ESRCH;
kaf24@954 391
kaf24@1129 392 spin_lock(&p->event_channel_lock);
kaf24@954 393
kaf24@1129 394 chn = p->event_channel;
kaf24@954 395
kaf24@1129 396 if ( (port < 0) || (port >= p->max_event_channel) )
kaf24@954 397 {
kaf24@1266 398 rc = -EINVAL;
kaf24@1266 399 goto out;
kaf24@1127 400 }
kaf24@1127 401
kaf24@1129 402 switch ( chn[port].state )
kaf24@1127 403 {
kaf24@1127 404 case ECS_FREE:
kaf24@1127 405 status->status = EVTCHNSTAT_closed;
kaf24@1127 406 break;
kaf24@1218 407 case ECS_UNBOUND:
kaf24@1218 408 status->status = EVTCHNSTAT_unbound;
kaf24@1127 409 break;
kaf24@1218 410 case ECS_INTERDOMAIN:
kaf24@1218 411 status->status = EVTCHNSTAT_interdomain;
kaf24@1218 412 status->u.interdomain.dom = chn[port].u.remote.dom->domain;
kaf24@1218 413 status->u.interdomain.port = chn[port].u.remote.port;
kaf24@1218 414 break;
kaf24@1218 415 case ECS_PIRQ:
kaf24@1218 416 status->status = EVTCHNSTAT_pirq;
kaf24@1218 417 status->u.pirq = chn[port].u.pirq;
kaf24@1218 418 break;
kaf24@1218 419 case ECS_VIRQ:
kaf24@1218 420 status->status = EVTCHNSTAT_virq;
kaf24@1218 421 status->u.virq = chn[port].u.virq;
kaf24@1127 422 break;
kaf24@1127 423 default:
kaf24@1127 424 BUG();
kaf24@954 425 }
kaf24@954 426
kaf24@1266 427 out:
kaf24@1129 428 spin_unlock(&p->event_channel_lock);
kaf24@1505 429 put_domain(p);
kaf24@1266 430 return rc;
kaf24@954 431 }
kaf24@954 432
kaf24@954 433
kaf24@1127 434 long do_event_channel_op(evtchn_op_t *uop)
kaf24@954 435 {
kaf24@954 436 long rc;
kaf24@1127 437 evtchn_op_t op;
kaf24@954 438
kaf24@1127 439 if ( copy_from_user(&op, uop, sizeof(op)) != 0 )
kaf24@1127 440 return -EFAULT;
kaf24@1127 441
kaf24@1127 442 switch ( op.cmd )
kaf24@954 443 {
kaf24@1218 444 case EVTCHNOP_bind_interdomain:
kaf24@1218 445 rc = evtchn_bind_interdomain(&op.u.bind_interdomain);
kaf24@1235 446 if ( (rc == 0) && (copy_to_user(uop, &op, sizeof(op)) != 0) )
kaf24@1218 447 rc = -EFAULT; /* Cleaning up here would be a mess! */
kaf24@1218 448 break;
kaf24@1218 449
kaf24@1218 450 case EVTCHNOP_bind_virq:
kaf24@1218 451 rc = evtchn_bind_virq(&op.u.bind_virq);
kaf24@1235 452 if ( (rc == 0) && (copy_to_user(uop, &op, sizeof(op)) != 0) )
kaf24@1235 453 rc = -EFAULT; /* Cleaning up here would be a mess! */
kaf24@1235 454 break;
kaf24@1235 455
kaf24@1235 456 case EVTCHNOP_bind_pirq:
kaf24@1235 457 rc = evtchn_bind_pirq(&op.u.bind_pirq);
kaf24@1235 458 if ( (rc == 0) && (copy_to_user(uop, &op, sizeof(op)) != 0) )
kaf24@1127 459 rc = -EFAULT; /* Cleaning up here would be a mess! */
kaf24@954 460 break;
kaf24@954 461
kaf24@954 462 case EVTCHNOP_close:
kaf24@1218 463 rc = evtchn_close(&op.u.close);
kaf24@954 464 break;
kaf24@954 465
kaf24@954 466 case EVTCHNOP_send:
kaf24@1218 467 rc = evtchn_send(op.u.send.local_port);
kaf24@954 468 break;
kaf24@954 469
kaf24@954 470 case EVTCHNOP_status:
kaf24@1218 471 rc = evtchn_status(&op.u.status);
kaf24@1235 472 if ( (rc == 0) && (copy_to_user(uop, &op, sizeof(op)) != 0) )
kaf24@1127 473 rc = -EFAULT;
kaf24@954 474 break;
kaf24@954 475
kaf24@954 476 default:
kaf24@954 477 rc = -ENOSYS;
kaf24@954 478 break;
kaf24@954 479 }
kaf24@954 480
kaf24@954 481 return rc;
kaf24@954 482 }
kaf24@954 483
kaf24@954 484
kaf24@1505 485 int init_event_channels(struct domain *p)
kaf24@1218 486 {
kaf24@1218 487 spin_lock_init(&p->event_channel_lock);
kaf24@1218 488 p->event_channel = kmalloc(INIT_EVENT_CHANNELS * sizeof(event_channel_t),
kaf24@1218 489 GFP_KERNEL);
kaf24@1218 490 if ( unlikely(p->event_channel == NULL) )
kaf24@1218 491 return -ENOMEM;
kaf24@1218 492 p->max_event_channel = INIT_EVENT_CHANNELS;
kaf24@1218 493 memset(p->event_channel, 0, INIT_EVENT_CHANNELS * sizeof(event_channel_t));
kaf24@1218 494 p->event_channel[0].state = ECS_VIRQ;
kaf24@1249 495 p->event_channel[0].u.virq = VIRQ_MISDIRECT;
kaf24@1218 496 return 0;
kaf24@1218 497 }
kaf24@1218 498
kaf24@1218 499
kaf24@1505 500 void destroy_event_channels(struct domain *p)
kaf24@954 501 {
kaf24@954 502 int i;
kaf24@954 503 if ( p->event_channel != NULL )
kaf24@954 504 {
kaf24@954 505 for ( i = 0; i < p->max_event_channel; i++ )
kaf24@1218 506 (void)__evtchn_close(p, i);
kaf24@954 507 kfree(p->event_channel);
kaf24@954 508 }
kaf24@954 509 }