ia64/xen-unstable

changeset 1218:fc8ea15b6dcf

bitkeeper revision 1.825.1.2 (4062c7cfNjG5kiKHfguNA2SIXnllng)

Many files:
New IRQ upcall world.
evtchn.c:
Rename: xenolinux-2.4.25-sparse/arch/xen/kernel/hypervisor.c -> xenolinux-2.4.25-sparse/arch/xen/kernel/evtchn.c
author kaf24@scramble.cl.cam.ac.uk
date Thu Mar 25 11:51:43 2004 +0000 (2004-03-25)
parents e6d3daf193d9
children d75495926616 0b18f5295cff
files .rootkeys tools/xc/lib/xc.h tools/xc/lib/xc_evtchn.c tools/xc/lib/xc_linux_build.c tools/xc/lib/xc_netbsd_build.c tools/xc/py/Xc.c tools/xend/lib/main.py tools/xend/lib/utils.c xen/arch/i386/entry.S xen/arch/i386/traps.c xen/common/debug.c xen/common/domain.c xen/common/event_channel.c xen/common/keyhandler.c xen/common/physdev.c xen/common/schedule.c xen/drivers/block/xen_block.c xen/drivers/block/xen_vbd.c xen/drivers/char/console.c xen/drivers/char/keyboard.c xen/include/hypervisor-ifs/event_channel.h xen/include/hypervisor-ifs/hypervisor-if.h xen/include/xen/event.h xen/include/xen/sched.h xen/net/dev.c xenolinux-2.4.25-sparse/arch/xen/drivers/block/block.c xenolinux-2.4.25-sparse/arch/xen/drivers/console/console.c xenolinux-2.4.25-sparse/arch/xen/drivers/evtchn/evtchn.c xenolinux-2.4.25-sparse/arch/xen/drivers/network/network.c xenolinux-2.4.25-sparse/arch/xen/drivers/vnetif/vnetif.c xenolinux-2.4.25-sparse/arch/xen/kernel/Makefile xenolinux-2.4.25-sparse/arch/xen/kernel/entry.S xenolinux-2.4.25-sparse/arch/xen/kernel/evtchn.c xenolinux-2.4.25-sparse/arch/xen/kernel/hypervisor.c xenolinux-2.4.25-sparse/arch/xen/kernel/i386_ksyms.c xenolinux-2.4.25-sparse/arch/xen/kernel/physirq.c xenolinux-2.4.25-sparse/arch/xen/kernel/setup.c xenolinux-2.4.25-sparse/arch/xen/kernel/time.c xenolinux-2.4.25-sparse/include/asm-xen/evtchn.h xenolinux-2.4.25-sparse/include/asm-xen/hypervisor.h xenolinux-2.4.25-sparse/include/asm-xen/irq.h xenolinux-2.4.25-sparse/include/asm-xen/keyboard.h xenolinux-2.4.25-sparse/include/asm-xen/system.h
line diff
     1.1 --- a/.rootkeys	Thu Mar 25 09:50:46 2004 +0000
     1.2 +++ b/.rootkeys	Thu Mar 25 11:51:43 2004 +0000
     1.3 @@ -628,8 +628,8 @@ 405853f2wg7JXZJNltspMwOZJklxgw xenolinux
     1.4  405853f6nbeazrNyEWNHBuoSg2PiPA xenolinux-2.4.25-sparse/arch/xen/drivers/vnetif/vnetif.c
     1.5  3e5a4e65lWzkiPXsZdzPt2RNnJGG1g xenolinux-2.4.25-sparse/arch/xen/kernel/Makefile
     1.6  3e5a4e65_hqfuxtGG8IUy6wRM86Ecg xenolinux-2.4.25-sparse/arch/xen/kernel/entry.S
     1.7 +3e5a4e65ibVQmwlOn0j3sVH_j_6hAg xenolinux-2.4.25-sparse/arch/xen/kernel/evtchn.c
     1.8  3e5a4e65Hy_1iUvMTPsNqGNXd9uFpg xenolinux-2.4.25-sparse/arch/xen/kernel/head.S
     1.9 -3e5a4e65ibVQmwlOn0j3sVH_j_6hAg xenolinux-2.4.25-sparse/arch/xen/kernel/hypervisor.c
    1.10  3e5a4e65RMGcuA-HCn3-wNx3fFQwdg xenolinux-2.4.25-sparse/arch/xen/kernel/i386_ksyms.c
    1.11  3e5a4e65MEvZhlr070sK5JsfAQlv7Q xenolinux-2.4.25-sparse/arch/xen/kernel/ioport.c
    1.12  3e5a4e653U6cELGv528IxOLHvCq8iA xenolinux-2.4.25-sparse/arch/xen/kernel/irq.c
     2.1 --- a/tools/xc/lib/xc.h	Thu Mar 25 09:50:46 2004 +0000
     2.2 +++ b/tools/xc/lib/xc.h	Thu Mar 25 11:51:43 2004 +0000
     2.3 @@ -165,25 +165,38 @@ int xc_vbd_probe(int xc_handle,
     2.4                   xc_vbd_t *vbds);
     2.5  
     2.6  #define DOMID_SELF              (~1ULL)
     2.7 -#define EVTCHNSTAT_closed       0  /* Chennel is not in use.              */
     2.8 -#define EVTCHNSTAT_disconnected 1  /* Channel is not connected to remote. */
     2.9 -#define EVTCHNSTAT_connected    2  /* Channel is connected to remote.     */
    2.10 -int xc_evtchn_open(int xc_handle,
    2.11 -                   u64 dom1,   /* may be DOMID_SELF */
    2.12 -                   u64 dom2,   /* may be DOMID_SELF */
    2.13 -                   int *port1,
    2.14 -                   int *port2);
    2.15 +
    2.16 +typedef struct {
    2.17 +#define EVTCHNSTAT_closed       0  /* Chennel is not in use.                 */
    2.18 +#define EVTCHNSTAT_unbound      1  /* Channel is not bound to a source.      */
    2.19 +#define EVTCHNSTAT_interdomain  2  /* Channel is connected to remote domain. */
    2.20 +#define EVTCHNSTAT_pirq         3  /* Channel is bound to a phys IRQ line.   */
    2.21 +#define EVTCHNSTAT_virq         4  /* Channel is bound to a virtual IRQ line */
    2.22 +    int status;
    2.23 +    union {
    2.24 +        struct {
    2.25 +            u64 dom;
    2.26 +            int port;
    2.27 +        } interdomain;
    2.28 +        int pirq;
    2.29 +        int virq;
    2.30 +    } u;
    2.31 +} xc_evtchn_status_t;
    2.32 +
    2.33 +int xc_evtchn_bind_interdomain(int xc_handle,
    2.34 +                               u64 dom1,   /* may be DOMID_SELF */
    2.35 +                               u64 dom2,   /* may be DOMID_SELF */
    2.36 +                               int *port1,
    2.37 +                               int *port2);
    2.38  int xc_evtchn_close(int xc_handle,
    2.39                      u64 dom,   /* may be DOMID_SELF */
    2.40                      int port);
    2.41  int xc_evtchn_send(int xc_handle,
    2.42                     int local_port);
    2.43  int xc_evtchn_status(int xc_handle,
    2.44 -                     u64 dom1, /* may be DOMID_SELF */
    2.45 -                     int port1,
    2.46 -                     u64 *dom2,
    2.47 -                     int *port2,
    2.48 -                     int *chn_status);
    2.49 +                     u64 dom, /* may be DOMID_SELF */
    2.50 +                     int port,
    2.51 +                     xc_evtchn_status_t *status);
    2.52  
    2.53  int xc_physdev_pci_access_modify(int xc_handle,
    2.54                                   u64 domid,
     3.1 --- a/tools/xc/lib/xc_evtchn.c	Thu Mar 25 09:50:46 2004 +0000
     3.2 +++ b/tools/xc/lib/xc_evtchn.c	Thu Mar 25 11:51:43 2004 +0000
     3.3 @@ -29,25 +29,25 @@ static int do_evtchn_op(int xc_handle, e
     3.4   out1: return ret;
     3.5  }
     3.6  
     3.7 -int xc_evtchn_open(int xc_handle,
     3.8 -                   u64 dom1,
     3.9 -                   u64 dom2,
    3.10 -                   int *port1,
    3.11 -                   int *port2)
    3.12 +int xc_evtchn_bind_interdomain(int xc_handle,
    3.13 +                               u64 dom1,
    3.14 +                               u64 dom2,
    3.15 +                               int *port1,
    3.16 +                               int *port2)
    3.17  {
    3.18      evtchn_op_t op;
    3.19      int         rc;
    3.20  
    3.21 -    op.cmd = EVTCHNOP_open;
    3.22 -    op.u.open.dom1 = (domid_t)dom1;
    3.23 -    op.u.open.dom2 = (domid_t)dom2;
    3.24 +    op.cmd = EVTCHNOP_bind_interdomain;
    3.25 +    op.u.bind_interdomain.dom1 = (domid_t)dom1;
    3.26 +    op.u.bind_interdomain.dom2 = (domid_t)dom2;
    3.27     
    3.28      if ( (rc = do_evtchn_op(xc_handle, &op)) == 0 )
    3.29      {
    3.30          if ( port1 != NULL )
    3.31 -            *port1 = op.u.open.port1;
    3.32 +            *port1 = op.u.bind_interdomain.port1;
    3.33          if ( port2 != NULL )
    3.34 -            *port2 = op.u.open.port2;
    3.35 +            *port2 = op.u.bind_interdomain.port2;
    3.36      }
    3.37      
    3.38      return rc;
    3.39 @@ -77,27 +77,32 @@ int xc_evtchn_send(int xc_handle,
    3.40  
    3.41  
    3.42  int xc_evtchn_status(int xc_handle,
    3.43 -                     u64 dom1,
    3.44 -                     int port1,
    3.45 -                     u64 *dom2,
    3.46 -                     int *port2,
    3.47 -                     int *chn_status)
    3.48 +                     u64 dom,
    3.49 +                     int port,
    3.50 +                     xc_evtchn_status_t *status)
    3.51  {
    3.52      evtchn_op_t op;
    3.53      int         rc;
    3.54  
    3.55      op.cmd = EVTCHNOP_status;
    3.56 -    op.u.status.dom1  = (domid_t)dom1;
    3.57 -    op.u.status.port1 = port1;
    3.58 +    op.u.status.dom  = (domid_t)dom;
    3.59 +    op.u.status.port = port;
    3.60     
    3.61      if ( (rc = do_evtchn_op(xc_handle, &op)) == 0 )
    3.62      {
    3.63 -        if ( dom2 != NULL )
    3.64 -            *dom2 = (u64)op.u.status.dom2;
    3.65 -        if ( port2 != NULL )
    3.66 -            *port2 = op.u.status.port2;
    3.67 -        if ( chn_status != NULL )
    3.68 -            *chn_status = op.u.status.status;
    3.69 +        switch ( status->status = op.u.status.status )
    3.70 +        {
    3.71 +        case EVTCHNSTAT_interdomain:
    3.72 +            status->u.interdomain.dom  = (u64)op.u.status.u.interdomain.dom;
    3.73 +            status->u.interdomain.port = op.u.status.u.interdomain.port;
    3.74 +            break;
    3.75 +        case EVTCHNSTAT_pirq:
    3.76 +            status->u.pirq = op.u.status.u.pirq;
    3.77 +            break;
    3.78 +        case EVTCHNSTAT_virq:
    3.79 +            status->u.virq = op.u.status.u.virq;
    3.80 +            break;
    3.81 +        }
    3.82      }
    3.83      
    3.84      return rc;
     4.1 --- a/tools/xc/lib/xc_linux_build.c	Thu Mar 25 09:50:46 2004 +0000
     4.2 +++ b/tools/xc/lib/xc_linux_build.c	Thu Mar 25 11:51:43 2004 +0000
     4.3 @@ -248,6 +248,7 @@ static int setup_guestos(int xc_handle,
     4.4      /* shared_info page starts its life empty. */
     4.5      shared_info = map_pfn_writeable(pm_handle, shared_info_frame);
     4.6      memset(shared_info, 0, PAGE_SIZE);
     4.7 +    shared_info->evtchn_upcall_mask = ~0UL; /* mask all upcalls */
     4.8      unmap_pfn(pm_handle, shared_info);
     4.9  
    4.10      /* Send the page update requests down to the hypervisor. */
     5.1 --- a/tools/xc/lib/xc_netbsd_build.c	Thu Mar 25 09:50:46 2004 +0000
     5.2 +++ b/tools/xc/lib/xc_netbsd_build.c	Thu Mar 25 11:51:43 2004 +0000
     5.3 @@ -183,6 +183,7 @@ static int setup_guestos(int xc_handle,
     5.4      /* shared_info page starts its life empty. */
     5.5      shared_info = map_pfn_writeable(pm_handle, shared_info_frame);
     5.6      memset(shared_info, 0, PAGE_SIZE);
     5.7 +    shared_info->evtchn_upcall_mask = ~0UL; /* mask all upcalls */
     5.8      unmap_pfn(pm_handle, shared_info);
     5.9  
    5.10      /* Send the page update requests down to the hypervisor. */
     6.1 --- a/tools/xc/py/Xc.c	Thu Mar 25 09:50:46 2004 +0000
     6.2 +++ b/tools/xc/py/Xc.c	Thu Mar 25 11:51:43 2004 +0000
     6.3 @@ -687,9 +687,9 @@ static PyObject *pyxc_vbd_probe(PyObject
     6.4      return list;
     6.5  }
     6.6  
     6.7 -static PyObject *pyxc_evtchn_open(PyObject *self,
     6.8 -                                  PyObject *args,
     6.9 -                                  PyObject *kwds)
    6.10 +static PyObject *pyxc_evtchn_bind_interdomain(PyObject *self,
    6.11 +                                              PyObject *args,
    6.12 +                                              PyObject *kwds)
    6.13  {
    6.14      XcObject *xc = (XcObject *)self;
    6.15  
    6.16 @@ -702,7 +702,8 @@ static PyObject *pyxc_evtchn_open(PyObje
    6.17                                        &dom1, &dom2) )
    6.18          return NULL;
    6.19  
    6.20 -    if ( xc_evtchn_open(xc->xc_handle, dom1, dom2, &port1, &port2) != 0 )
    6.21 +    if ( xc_evtchn_bind_interdomain(xc->xc_handle, dom1, 
    6.22 +                                    dom2, &port1, &port2) != 0 )
    6.23          return PyErr_SetFromErrno(xc_error);
    6.24  
    6.25      return Py_BuildValue("{s:i,s:i}", 
    6.26 @@ -759,34 +760,45 @@ static PyObject *pyxc_evtchn_status(PyOb
    6.27      XcObject *xc = (XcObject *)self;
    6.28      PyObject *dict;
    6.29  
    6.30 -    u64 dom1 = DOMID_SELF, dom2;
    6.31 -    int port1, port2, status, ret;
    6.32 +    u64 dom = DOMID_SELF;
    6.33 +    int port, ret;
    6.34 +    xc_evtchn_status_t status;
    6.35  
    6.36      static char *kwd_list[] = { "port", "dom", NULL };
    6.37  
    6.38      if ( !PyArg_ParseTupleAndKeywords(args, kwds, "i|L", kwd_list, 
    6.39 -                                      &port1, &dom1) )
    6.40 +                                      &port, &dom) )
    6.41          return NULL;
    6.42  
    6.43 -    ret = xc_evtchn_status(xc->xc_handle, dom1, port1, &dom2, &port2, &status);
    6.44 +    ret = xc_evtchn_status(xc->xc_handle, dom, port, &status);
    6.45      if ( ret != 0 )
    6.46          return PyErr_SetFromErrno(xc_error);
    6.47  
    6.48 -    switch ( status )
    6.49 +    switch ( status.status )
    6.50      {
    6.51      case EVTCHNSTAT_closed:
    6.52          dict = Py_BuildValue("{s:s}", 
    6.53                               "status", "closed");
    6.54          break;
    6.55 -    case EVTCHNSTAT_disconnected:
    6.56 +    case EVTCHNSTAT_unbound:
    6.57          dict = Py_BuildValue("{s:s}", 
    6.58 -                             "status", "disconnected");
    6.59 +                             "status", "unbound");
    6.60 +        break;
    6.61 +    case EVTCHNSTAT_interdomain:
    6.62 +        dict = Py_BuildValue("{s:s,s:L,s:i}", 
    6.63 +                             "status", "interdomain",
    6.64 +                             "dom", status.u.interdomain.dom,
    6.65 +                             "port", status.u.interdomain.port);
    6.66          break;
    6.67 -    case EVTCHNSTAT_connected:
    6.68 -        dict = Py_BuildValue("{s:s,s:L,s:i}", 
    6.69 -                             "status", "connected",
    6.70 -                             "dom", dom2,
    6.71 -                             "port", port2);
    6.72 +    case EVTCHNSTAT_pirq:
    6.73 +        dict = Py_BuildValue("{s:s,s:i}", 
    6.74 +                             "status", "pirq",
    6.75 +                             "irq", status.u.pirq);
    6.76 +        break;
    6.77 +    case EVTCHNSTAT_virq:
    6.78 +        dict = Py_BuildValue("{s:s,s:i}", 
    6.79 +                             "status", "virq",
    6.80 +                             "irq", status.u.virq);
    6.81          break;
    6.82      default:
    6.83          dict = Py_BuildValue("{}");
    6.84 @@ -1134,8 +1146,8 @@ static PyMethodDef pyxc_methods[] = {
    6.85        " writeable  [int]:  Bool - is this VBD writeable?\n"
    6.86        " nr_sectors [long]: Size of this VBD, in 512-byte sectors.\n" },
    6.87  
    6.88 -    { "evtchn_open", 
    6.89 -      (PyCFunction)pyxc_evtchn_open, 
    6.90 +    { "evtchn_bind_interdomain", 
    6.91 +      (PyCFunction)pyxc_evtchn_bind_interdomain, 
    6.92        METH_VARARGS | METH_KEYWORDS, "\n"
    6.93        "Open an event channel between two domains.\n"
    6.94        " dom1 [long, SELF]: First domain to be connected.\n"
    6.95 @@ -1166,10 +1178,13 @@ static PyMethodDef pyxc_methods[] = {
    6.96        " dom  [long, SELF]: Dom-id of one endpoint of the channel.\n"
    6.97        " port [int]:        Port-id of one endpoint of the channel.\n\n"
    6.98        "Returns: [dict] dictionary is empty on failure.\n"
    6.99 -      " status [str]:  'closed', 'disconnected', or 'connected'.\n"
   6.100 -      "The following are also returned if 'status' is 'connected':\n"
   6.101 -      " dom  [long]: Port-id for endpoint at dom1.\n"
   6.102 -      " port [int]:  Port-id for endpoint at dom2.\n" },
   6.103 +      " status [str]:  'closed', 'unbound', 'interdomain', 'pirq',"
   6.104 +      " or 'virq'.\n"
   6.105 +      "The following are returned if 'status' is 'interdomain':\n"
   6.106 +      " dom  [long]: Dom-id of remote endpoint.\n"
   6.107 +      " port [int]:  Port-id of remote endpoint.\n"
   6.108 +      "The following are returned if 'status' is 'pirq' or 'virq':\n"
   6.109 +      " irq  [int]:  IRQ number.\n" },
   6.110  
   6.111      { "physdev_pci_access_modify",
   6.112        (PyCFunction)pyxc_physdev_pci_access_modify,
     7.1 --- a/tools/xend/lib/main.py	Thu Mar 25 09:50:46 2004 +0000
     7.2 +++ b/tools/xend/lib/main.py	Thu Mar 25 11:51:43 2004 +0000
     7.3 @@ -175,16 +175,16 @@ def daemon_loop():
     7.4              # getting clogged with stale connections.
     7.5              if type == notifier.DISCONNECT:
     7.6                  ret = xc.evtchn_status(idx)
     7.7 -                if ret['status'] != 'connected':
     7.8 +                if ret['status'] == 'interdomain':
     7.9                      notifier.clear(idx, notifier.NORMAL)
    7.10                      notifier.clear(idx, notifier.DISCONNECT)
    7.11                      if control_list.has_key(idx):
    7.12                          (port, rbuf, wbuf, con_if) =  control_list[idx]
    7.13                          con_if.close()
    7.14                          del control_list[idx], port, rbuf, wbuf, con_if
    7.15 -                    elif ret['status'] == 'disconnected':
    7.16 -                        # There's noone to do the closure for us...
    7.17 -                        xc.evtchn_close(idx)
    7.18 +                elif ret['status'] == 'unbound':
    7.19 +                    # There's noone to do the closure for us...
    7.20 +                    xc.evtchn_close(idx)
    7.21  
    7.22              # A standard notification: probably means there are messages to
    7.23              # read or that there is space to write messages.
     8.1 --- a/tools/xend/lib/utils.c	Thu Mar 25 09:50:46 2004 +0000
     8.2 +++ b/tools/xend/lib/utils.c	Thu Mar 25 11:51:43 2004 +0000
     8.3 @@ -632,7 +632,8 @@ static PyObject *xu_port_new(PyObject *s
     8.4          goto fail2;
     8.5      }
     8.6  
     8.7 -    if ( xc_evtchn_open(xup->xc_handle, DOMID_SELF, dom, &port1, &port2) != 0 )
     8.8 +    if ( xc_evtchn_bind_interdomain(xup->xc_handle, 
     8.9 +                                    DOMID_SELF, dom, &port1, &port2) != 0 )
    8.10      {
    8.11          PyErr_SetString(port_error, "Could not open channel to domain");
    8.12          goto fail3;
     9.1 --- a/xen/arch/i386/entry.S	Thu Mar 25 09:50:46 2004 +0000
     9.2 +++ b/xen/arch/i386/entry.S	Thu Mar 25 11:51:43 2004 +0000
     9.3 @@ -112,8 +112,8 @@ FAILSAFE_SEL    = 32
     9.4  FAILSAFE_ADDR   = 36
     9.5  
     9.6  /* Offsets in shared_info_t */
     9.7 -EVENTS          =  0
     9.8 -EVENTS_MASK     =  4
     9.9 +UPCALL_PENDING  = 0
    9.10 +UPCALL_MASK     = 4
    9.11  
    9.12  /* Offsets in guest_trap_bounce */
    9.13  GTB_ERROR_CODE   =  0
    9.14 @@ -368,15 +368,12 @@ test_all_events:
    9.15          jnz  process_hyp_events
    9.16  /*test_guest_events:*/
    9.17          movl SHARED_INFO(%ebx),%eax
    9.18 -        shl  $31,%ecx                   # %ecx = EVENTS_MASTER_ENABLE_MASK
    9.19 -        test %ecx,EVENTS_MASK(%eax)     
    9.20 -        jz   restore_all_guest          # only notify if master switch enabled
    9.21 -        movl EVENTS(%eax),%ecx
    9.22 -        andl EVENTS_MASK(%eax),%ecx
    9.23 -        jz   restore_all_guest          # skip if no events to deliver
    9.24 +        movl UPCALL_MASK(%eax),%ecx
    9.25          notl %ecx
    9.26 -        btrl $31,%ecx                   # NB. We clear all events that are
    9.27 -        andl %ecx,EVENTS_MASK(%eax)     # being delivered + master enable.
    9.28 +        andl UPCALL_PENDING(%eax),%ecx  # ECX = pending & ~mask
    9.29 +        andl $1,%ecx                    # Is bit 0 pending and not masked?
    9.30 +        jz   restore_all_guest
    9.31 +        orl  %ecx,UPCALL_MASK(%eax)     # Upcalls are masked during delivery
    9.32  /*process_guest_events:*/
    9.33          movzwl PROCESSOR(%ebx),%edx
    9.34          shl  $4,%edx                    # sizeof(guest_trap_bounce) == 16
    10.1 --- a/xen/arch/i386/traps.c	Thu Mar 25 09:50:46 2004 +0000
    10.2 +++ b/xen/arch/i386/traps.c	Thu Mar 25 11:51:43 2004 +0000
    10.3 @@ -205,7 +205,7 @@ static inline void do_trap(int trapnr, c
    10.4      gtb->cs         = ti->cs;
    10.5      gtb->eip        = ti->address;
    10.6      if ( TI_GET_IF(ti) )
    10.7 -        clear_bit(EVENTS_MASTER_ENABLE_BIT, &p->shared_info->events_mask);
    10.8 +        set_bit(0, &p->shared_info->evtchn_upcall_mask);
    10.9      return; 
   10.10  
   10.11   fault_in_hypervisor:
   10.12 @@ -276,7 +276,7 @@ asmlinkage void do_int3(struct pt_regs *
   10.13      gtb->cs         = ti->cs;
   10.14      gtb->eip        = ti->address;
   10.15      if ( TI_GET_IF(ti) )
   10.16 -        clear_bit(EVENTS_MASTER_ENABLE_BIT, &p->shared_info->events_mask);
   10.17 +        set_bit(0, &p->shared_info->evtchn_upcall_mask);
   10.18      return;
   10.19  
   10.20  }
   10.21 @@ -346,7 +346,7 @@ asmlinkage void do_page_fault(struct pt_
   10.22      gtb->cs         = ti->cs;
   10.23      gtb->eip        = ti->address;
   10.24      if ( TI_GET_IF(ti) )
   10.25 -        clear_bit(EVENTS_MASTER_ENABLE_BIT, &p->shared_info->events_mask);
   10.26 +        set_bit(0, &p->shared_info->evtchn_upcall_mask);
   10.27      return; 
   10.28  
   10.29   fault_in_hypervisor:
   10.30 @@ -434,7 +434,7 @@ asmlinkage void do_general_protection(st
   10.31      gtb->cs         = ti->cs;
   10.32      gtb->eip        = ti->address;
   10.33      if ( TI_GET_IF(ti) )
   10.34 -        clear_bit(EVENTS_MASTER_ENABLE_BIT, &p->shared_info->events_mask);
   10.35 +        set_bit(0, &p->shared_info->evtchn_upcall_mask);
   10.36      return;
   10.37  
   10.38   gp_in_kernel:
    11.1 --- a/xen/common/debug.c	Thu Mar 25 09:50:46 2004 +0000
    11.2 +++ b/xen/common/debug.c	Thu Mar 25 11:51:43 2004 +0000
    11.3 @@ -224,16 +224,12 @@ void pdb_do_debug (dom0_op_t *op)
    11.4  
    11.5          case 's' :
    11.6  	{
    11.7 -	    unsigned long cpu_mask;
    11.8  	    struct task_struct * p = find_domain_by_id(op->u.debug.domain);
    11.9  
   11.10  	    if (p != NULL)
   11.11  	    {
   11.12  	        if (p->state != TASK_STOPPED)
   11.13 -		{
   11.14 -		    cpu_mask = mark_guest_event(p, _EVENT_STOP);
   11.15 -		    guest_event_notify(cpu_mask);
   11.16 -		}
   11.17 +                    send_guest_virq(p, VIRQ_STOP);
   11.18  		put_task_struct(p);
   11.19  	    }
   11.20  	    else
    12.1 --- a/xen/common/domain.c	Thu Mar 25 09:50:46 2004 +0000
    12.2 +++ b/xen/common/domain.c	Thu Mar 25 11:51:43 2004 +0000
    12.3 @@ -53,14 +53,19 @@ struct task_struct *do_createdomain(domi
    12.4  
    12.5      if ( p->domain != IDLE_DOMAIN_ID )
    12.6      {
    12.7 +        if ( init_event_channels(p) != 0 )
    12.8 +        {
    12.9 +            free_task_struct(p);
   12.10 +            return NULL;
   12.11 +        }
   12.12 +        
   12.13          /* We use a large intermediate to avoid overflow in sprintf. */
   12.14          sprintf(buf, "Domain-%llu", dom_id);
   12.15          strncpy(p->name, buf, MAX_DOMAIN_NAME);
   12.16          p->name[MAX_DOMAIN_NAME-1] = '\0';
   12.17  
   12.18          spin_lock_init(&p->blk_ring_lock);
   12.19 -        spin_lock_init(&p->event_channel_lock);
   12.20 -        
   12.21 +
   12.22          p->addr_limit = USER_DS;
   12.23          
   12.24          spin_lock_init(&p->page_list_lock);
   12.25 @@ -133,8 +138,6 @@ void kill_domain_with_errmsg(const char 
   12.26  
   12.27  void __kill_domain(struct task_struct *p)
   12.28  {
   12.29 -    extern void destroy_event_channels(struct task_struct *);
   12.30 -
   12.31      int i;
   12.32      struct task_struct **pp;
   12.33      unsigned long flags;
   12.34 @@ -197,25 +200,16 @@ void kill_domain(void)
   12.35  long kill_other_domain(domid_t dom, int force)
   12.36  {
   12.37      struct task_struct *p;
   12.38 -    unsigned long cpu_mask = 0;
   12.39  
   12.40 -    p = find_domain_by_id(dom);
   12.41 -    if ( p == NULL ) return -ESRCH;
   12.42 +    if ( (p = find_domain_by_id(dom)) == NULL )
   12.43 +        return -ESRCH;
   12.44  
   12.45      if ( p->state == TASK_STOPPED )
   12.46 -    {
   12.47          __kill_domain(p);
   12.48 -    }
   12.49      else if ( force )
   12.50 -    {
   12.51 -        cpu_mask = mark_hyp_event(p, _HYP_EVENT_DIE);
   12.52 -        hyp_event_notify(cpu_mask);
   12.53 -    }
   12.54 +        send_hyp_event(p, _HYP_EVENT_DIE);
   12.55      else
   12.56 -    {
   12.57 -        cpu_mask = mark_guest_event(p, _EVENT_DIE);
   12.58 -        guest_event_notify(cpu_mask);
   12.59 -    }
   12.60 +        send_guest_virq(p, VIRQ_DIE);
   12.61  
   12.62      put_task_struct(p);
   12.63      return 0;
   12.64 @@ -234,7 +228,6 @@ void stop_domain(void)
   12.65  
   12.66  long stop_other_domain(domid_t dom)
   12.67  {
   12.68 -    unsigned long cpu_mask;
   12.69      struct task_struct *p;
   12.70      
   12.71      if ( dom == 0 )
   12.72 @@ -244,10 +237,7 @@ long stop_other_domain(domid_t dom)
   12.73      if ( p == NULL) return -ESRCH;
   12.74      
   12.75      if ( p->state != TASK_STOPPED )
   12.76 -    {
   12.77 -        cpu_mask = mark_guest_event(p, _EVENT_STOP);
   12.78 -        guest_event_notify(cpu_mask);
   12.79 -    }
   12.80 +        send_guest_virq(p, VIRQ_STOP);
   12.81      
   12.82      put_task_struct(p);
   12.83      return 0;
   12.84 @@ -757,6 +747,7 @@ int setup_guestos(struct task_struct *p,
   12.85      /* Set up shared info area. */
   12.86      update_dom_time(p->shared_info);
   12.87      p->shared_info->domain_time = 0;
   12.88 +    p->shared_info->evtchn_upcall_mask = ~0UL; /* mask all upcalls */
   12.89  
   12.90      virt_startinfo_address = (start_info_t *)
   12.91          (virt_load_address + ((alloc_index - 1) << PAGE_SHIFT));
    13.1 --- a/xen/common/event_channel.c	Thu Mar 25 09:50:46 2004 +0000
    13.2 +++ b/xen/common/event_channel.c	Thu Mar 25 11:51:43 2004 +0000
    13.3 @@ -25,7 +25,8 @@
    13.4  #include <hypervisor-ifs/hypervisor-if.h>
    13.5  #include <hypervisor-ifs/event_channel.h>
    13.6  
    13.7 -#define MAX_EVENT_CHANNELS 1024
    13.8 +#define INIT_EVENT_CHANNELS   16
    13.9 +#define MAX_EVENT_CHANNELS  1024
   13.10  
   13.11  static int get_free_port(struct task_struct *p)
   13.12  {
   13.13 @@ -65,28 +66,11 @@ static int get_free_port(struct task_str
   13.14      return port;
   13.15  }
   13.16  
   13.17 -static inline unsigned long set_event_pending(struct task_struct *p, int port)
   13.18 -{
   13.19 -    if ( !test_and_set_bit(port,    &p->shared_info->event_channel_pend[0]) &&
   13.20 -         !test_and_set_bit(port>>5, &p->shared_info->event_channel_pend_sel) )
   13.21 -        return mark_guest_event(p, _EVENT_EVTCHN);
   13.22 -    return 0;
   13.23 -}
   13.24 -
   13.25 -static inline unsigned long set_event_disc(struct task_struct *p, int port)
   13.26 -{
   13.27 -    if ( !test_and_set_bit(port,    &p->shared_info->event_channel_disc[0]) &&
   13.28 -         !test_and_set_bit(port>>5, &p->shared_info->event_channel_disc_sel) )
   13.29 -        return mark_guest_event(p, _EVENT_EVTCHN);
   13.30 -    return 0;
   13.31 -}
   13.32 -
   13.33 -static long event_channel_open(evtchn_open_t *open)
   13.34 +static long evtchn_bind_interdomain(evtchn_bind_interdomain_t *bind)
   13.35  {
   13.36      struct task_struct *p1, *p2;
   13.37      int                 port1 = 0, port2 = 0;
   13.38 -    unsigned long       cpu_mask;
   13.39 -    domid_t             dom1 = open->dom1, dom2 = open->dom2;
   13.40 +    domid_t             dom1 = bind->dom1, dom2 = bind->dom2;
   13.41      long                rc = 0;
   13.42  
   13.43      if ( !IS_PRIV(current) )
   13.44 @@ -130,21 +114,16 @@ static long event_channel_open(evtchn_op
   13.45          goto out;
   13.46      }
   13.47  
   13.48 -    p1->event_channel[port1].remote_dom  = p2;
   13.49 -    p1->event_channel[port1].remote_port = (u16)port2;
   13.50 -    p1->event_channel[port1].state       = ECS_CONNECTED;
   13.51 -
   13.52 -    p2->event_channel[port2].remote_dom  = p1;
   13.53 -    p2->event_channel[port2].remote_port = (u16)port1;
   13.54 -    p2->event_channel[port2].state       = ECS_CONNECTED;
   13.55 +    p1->event_channel[port1].u.remote.dom  = p2;
   13.56 +    p1->event_channel[port1].u.remote.port = (u16)port2;
   13.57 +    p1->event_channel[port1].state         = ECS_INTERDOMAIN;
   13.58  
   13.59 -    /* Ensure that the disconnect signal is not asserted. */
   13.60 -    clear_bit(port1, &p1->shared_info->event_channel_disc[0]);
   13.61 -    clear_bit(port2, &p2->shared_info->event_channel_disc[0]);
   13.62 +    p2->event_channel[port2].u.remote.dom  = p1;
   13.63 +    p2->event_channel[port2].u.remote.port = (u16)port1;
   13.64 +    p2->event_channel[port2].state         = ECS_INTERDOMAIN;
   13.65  
   13.66 -    cpu_mask  = set_event_pending(p1, port1);
   13.67 -    cpu_mask |= set_event_pending(p2, port2);
   13.68 -    guest_event_notify(cpu_mask);
   13.69 +    evtchn_set_pending(p1, port1);
   13.70 +    evtchn_set_pending(p2, port2);
   13.71      
   13.72   out:
   13.73      spin_unlock(&p1->event_channel_lock);
   13.74 @@ -154,19 +133,55 @@ static long event_channel_open(evtchn_op
   13.75      put_task_struct(p1);
   13.76      put_task_struct(p2);
   13.77  
   13.78 -    open->port1 = port1;
   13.79 -    open->port2 = port2;
   13.80 +    bind->port1 = port1;
   13.81 +    bind->port2 = port2;
   13.82  
   13.83      return rc;
   13.84  }
   13.85  
   13.86  
   13.87 -static long __event_channel_close(struct task_struct *p1, int port1)
   13.88 +static long evtchn_bind_virq(evtchn_bind_virq_t *bind)
   13.89 +{
   13.90 +    struct task_struct *p = current;
   13.91 +    int virq = bind->virq;
   13.92 +    int port;
   13.93 +
   13.94 +    if ( virq >= NR_VIRQS )
   13.95 +        return -EINVAL;
   13.96 +
   13.97 +    spin_lock(&p->event_channel_lock);
   13.98 +
   13.99 +    /*
  13.100 +     * Port 0 is the fallback port for VIRQs that haven't been explicitly
  13.101 +     * bound yet. The exception is the 'error VIRQ', which is permanently 
  13.102 +     * bound to port 0.
  13.103 +     */
  13.104 +    if ( ((port = p->virq_to_evtchn[virq]) != 0) ||
  13.105 +         (virq == VIRQ_ERROR) ||
  13.106 +         ((port = get_free_port(p)) < 0) )
  13.107 +        goto out;
  13.108 +
  13.109 +    p->event_channel[port].state  = ECS_VIRQ;
  13.110 +    p->event_channel[port].u.virq = virq;
  13.111 +
  13.112 +    p->virq_to_evtchn[virq] = port;
  13.113 +
  13.114 + out:
  13.115 +    spin_unlock(&p->event_channel_lock);
  13.116 +
  13.117 +    if ( port < 0 )
  13.118 +        return port;
  13.119 +
  13.120 +    bind->port = port;
  13.121 +    return 0;
  13.122 +}
  13.123 +
  13.124 +
  13.125 +static long __evtchn_close(struct task_struct *p1, int port1)
  13.126  {
  13.127      struct task_struct *p2 = NULL;
  13.128      event_channel_t    *chn1, *chn2;
  13.129      int                 port2;
  13.130 -    unsigned long       cpu_mask = 0;
  13.131      long                rc = 0;
  13.132  
  13.133   again:
  13.134 @@ -174,18 +189,34 @@ static long __event_channel_close(struct
  13.135  
  13.136      chn1 = p1->event_channel;
  13.137  
  13.138 -    if ( (port1 < 0) || (port1 >= p1->max_event_channel) || 
  13.139 -         (chn1[port1].state == ECS_FREE) )
  13.140 +    /* NB. Port 0 is special (VIRQ_ERROR). Never let it be closed. */
  13.141 +    if ( (port1 <= 0) || (port1 >= p1->max_event_channel) )
  13.142      {
  13.143          rc = -EINVAL;
  13.144          goto out;
  13.145      }
  13.146  
  13.147 -    if ( chn1[port1].state == ECS_CONNECTED )
  13.148 +    switch ( chn1[port1].state )
  13.149      {
  13.150 +    case ECS_FREE:
  13.151 +        rc = -EINVAL;
  13.152 +        goto out;
  13.153 +
  13.154 +    case ECS_UNBOUND:
  13.155 +        break;
  13.156 +
  13.157 +    case ECS_PIRQ:
  13.158 +        p1->pirq_to_evtchn[chn1[port1].u.pirq] = 0;
  13.159 +        break;
  13.160 +
  13.161 +    case ECS_VIRQ:
  13.162 +        p1->virq_to_evtchn[chn1[port1].u.virq] = 0;
  13.163 +        break;
  13.164 +
  13.165 +    case ECS_INTERDOMAIN:
  13.166          if ( p2 == NULL )
  13.167          {
  13.168 -            p2 = chn1[port1].remote_dom;
  13.169 +            p2 = chn1[port1].u.remote.dom;
  13.170              get_task_struct(p2);
  13.171  
  13.172              if ( p1->domain < p2->domain )
  13.173 @@ -199,35 +230,39 @@ static long __event_channel_close(struct
  13.174                  goto again;
  13.175              }
  13.176          }
  13.177 -        else if ( p2 != chn1[port1].remote_dom )
  13.178 +        else if ( p2 != chn1[port1].u.remote.dom )
  13.179          {
  13.180              rc = -EINVAL;
  13.181              goto out;
  13.182          }
  13.183          
  13.184          chn2  = p2->event_channel;
  13.185 -        port2 = chn1[port1].remote_port;
  13.186 +        port2 = chn1[port1].u.remote.port;
  13.187  
  13.188          if ( port2 >= p2->max_event_channel )
  13.189              BUG();
  13.190 -        if ( chn2[port2].state != ECS_CONNECTED )
  13.191 +        if ( chn2[port2].state != ECS_INTERDOMAIN )
  13.192              BUG();
  13.193 -        if ( chn2[port2].remote_dom != p1 )
  13.194 +        if ( chn2[port2].u.remote.dom != p1 )
  13.195              BUG();
  13.196  
  13.197 -        chn2[port2].state       = ECS_DISCONNECTED;
  13.198 -        chn2[port2].remote_dom  = NULL;
  13.199 -        chn2[port2].remote_port = 0xFFFF;
  13.200 +        chn2[port2].state         = ECS_UNBOUND;
  13.201 +        chn2[port2].u.remote.dom  = NULL;
  13.202 +        chn2[port2].u.remote.port = 0xFFFF;
  13.203  
  13.204 -        cpu_mask |= set_event_disc(p2, port2);
  13.205 +        evtchn_set_exception(p2, port2);
  13.206 +
  13.207 +        break;
  13.208 +
  13.209 +    default:
  13.210 +        BUG();
  13.211      }
  13.212  
  13.213 -    chn1[port1].state       = ECS_FREE;
  13.214 -    chn1[port1].remote_dom  = NULL;
  13.215 -    chn1[port1].remote_port = 0xFFFF;
  13.216 +    chn1[port1].state         = ECS_FREE;
  13.217 +    chn1[port1].u.remote.dom  = NULL;
  13.218 +    chn1[port1].u.remote.port = 0xFFFF;
  13.219      
  13.220 -    cpu_mask |= set_event_disc(p1, port1);
  13.221 -    guest_event_notify(cpu_mask);
  13.222 +    evtchn_set_exception(p1, port1);
  13.223  
  13.224   out:
  13.225      if ( p2 != NULL )
  13.226 @@ -243,7 +278,7 @@ static long __event_channel_close(struct
  13.227  }
  13.228  
  13.229  
  13.230 -static long event_channel_close(evtchn_close_t *close)
  13.231 +static long evtchn_close(evtchn_close_t *close)
  13.232  {
  13.233      struct task_struct *p;
  13.234      long                rc;
  13.235 @@ -257,38 +292,36 @@ static long event_channel_close(evtchn_c
  13.236      if ( (p = find_domain_by_id(dom)) == NULL )
  13.237          return -ESRCH;
  13.238  
  13.239 -    rc = __event_channel_close(p, close->port);
  13.240 +    rc = __evtchn_close(p, close->port);
  13.241  
  13.242      put_task_struct(p);
  13.243      return rc;
  13.244  }
  13.245  
  13.246  
  13.247 -static long event_channel_send(int lport)
  13.248 +static long evtchn_send(int lport)
  13.249  {
  13.250      struct task_struct *lp = current, *rp;
  13.251      int                 rport;
  13.252 -    unsigned long       cpu_mask;
  13.253  
  13.254      spin_lock(&lp->event_channel_lock);
  13.255  
  13.256      if ( unlikely(lport < 0) ||
  13.257           unlikely(lport >= lp->max_event_channel) || 
  13.258 -         unlikely(lp->event_channel[lport].state != ECS_CONNECTED) )
  13.259 +         unlikely(lp->event_channel[lport].state != ECS_INTERDOMAIN) )
  13.260      {
  13.261          spin_unlock(&lp->event_channel_lock);
  13.262          return -EINVAL;
  13.263      }
  13.264  
  13.265 -    rp    = lp->event_channel[lport].remote_dom;
  13.266 -    rport = lp->event_channel[lport].remote_port;
  13.267 +    rp    = lp->event_channel[lport].u.remote.dom;
  13.268 +    rport = lp->event_channel[lport].u.remote.port;
  13.269  
  13.270      get_task_struct(rp);
  13.271  
  13.272      spin_unlock(&lp->event_channel_lock);
  13.273  
  13.274 -    cpu_mask = set_event_pending(rp, rport);
  13.275 -    guest_event_notify(cpu_mask);
  13.276 +    evtchn_set_pending(rp, rport);
  13.277  
  13.278      put_task_struct(rp);
  13.279  
  13.280 @@ -296,11 +329,11 @@ static long event_channel_send(int lport
  13.281  }
  13.282  
  13.283  
  13.284 -static long event_channel_status(evtchn_status_t *status)
  13.285 +static long evtchn_status(evtchn_status_t *status)
  13.286  {
  13.287      struct task_struct *p;
  13.288 -    domid_t             dom = status->dom1;
  13.289 -    int                 port = status->port1;
  13.290 +    domid_t             dom = status->dom;
  13.291 +    int                 port = status->port;
  13.292      event_channel_t    *chn;
  13.293  
  13.294      if ( dom == DOMID_SELF )
  13.295 @@ -326,13 +359,21 @@ static long event_channel_status(evtchn_
  13.296      case ECS_FREE:
  13.297          status->status = EVTCHNSTAT_closed;
  13.298          break;
  13.299 -    case ECS_DISCONNECTED:
  13.300 -        status->status = EVTCHNSTAT_disconnected;
  13.301 +    case ECS_UNBOUND:
  13.302 +        status->status = EVTCHNSTAT_unbound;
  13.303 +        break;
  13.304 +    case ECS_INTERDOMAIN:
  13.305 +        status->status = EVTCHNSTAT_interdomain;
  13.306 +        status->u.interdomain.dom  = chn[port].u.remote.dom->domain;
  13.307 +        status->u.interdomain.port = chn[port].u.remote.port;
  13.308          break;
  13.309 -    case ECS_CONNECTED:
  13.310 -        status->status = EVTCHNSTAT_connected;
  13.311 -        status->dom2   = chn[port].remote_dom->domain;
  13.312 -        status->port2  = chn[port].remote_port;
  13.313 +    case ECS_PIRQ:
  13.314 +        status->status = EVTCHNSTAT_pirq;
  13.315 +        status->u.pirq = chn[port].u.pirq;
  13.316 +        break;
  13.317 +    case ECS_VIRQ:
  13.318 +        status->status = EVTCHNSTAT_virq;
  13.319 +        status->u.virq = chn[port].u.virq;
  13.320          break;
  13.321      default:
  13.322          BUG();
  13.323 @@ -353,22 +394,28 @@ long do_event_channel_op(evtchn_op_t *uo
  13.324  
  13.325      switch ( op.cmd )
  13.326      {
  13.327 -    case EVTCHNOP_open:
  13.328 -        rc = event_channel_open(&op.u.open);
  13.329 +    case EVTCHNOP_bind_interdomain:
  13.330 +        rc = evtchn_bind_interdomain(&op.u.bind_interdomain);
  13.331 +        if ( copy_to_user(uop, &op, sizeof(op)) != 0 )
  13.332 +            rc = -EFAULT; /* Cleaning up here would be a mess! */
  13.333 +        break;
  13.334 +
  13.335 +    case EVTCHNOP_bind_virq:
  13.336 +        rc = evtchn_bind_virq(&op.u.bind_virq);
  13.337          if ( copy_to_user(uop, &op, sizeof(op)) != 0 )
  13.338              rc = -EFAULT; /* Cleaning up here would be a mess! */
  13.339          break;
  13.340  
  13.341      case EVTCHNOP_close:
  13.342 -        rc = event_channel_close(&op.u.close);
  13.343 +        rc = evtchn_close(&op.u.close);
  13.344          break;
  13.345  
  13.346      case EVTCHNOP_send:
  13.347 -        rc = event_channel_send(op.u.send.local_port);
  13.348 +        rc = evtchn_send(op.u.send.local_port);
  13.349          break;
  13.350  
  13.351      case EVTCHNOP_status:
  13.352 -        rc = event_channel_status(&op.u.status);
  13.353 +        rc = evtchn_status(&op.u.status);
  13.354          if ( copy_to_user(uop, &op, sizeof(op)) != 0 )
  13.355              rc = -EFAULT;
  13.356          break;
  13.357 @@ -382,13 +429,28 @@ long do_event_channel_op(evtchn_op_t *uo
  13.358  }
  13.359  
  13.360  
  13.361 +int init_event_channels(struct task_struct *p)
  13.362 +{
  13.363 +    spin_lock_init(&p->event_channel_lock);
  13.364 +    p->event_channel = kmalloc(INIT_EVENT_CHANNELS * sizeof(event_channel_t), 
  13.365 +                               GFP_KERNEL);
  13.366 +    if ( unlikely(p->event_channel == NULL) )
  13.367 +        return -ENOMEM;
  13.368 +    p->max_event_channel = INIT_EVENT_CHANNELS;
  13.369 +    memset(p->event_channel, 0, INIT_EVENT_CHANNELS * sizeof(event_channel_t));
  13.370 +    p->event_channel[0].state  = ECS_VIRQ;
  13.371 +    p->event_channel[0].u.virq = VIRQ_ERROR;
  13.372 +    return 0;
  13.373 +}
  13.374 +
  13.375 +
  13.376  void destroy_event_channels(struct task_struct *p)
  13.377  {
  13.378      int i;
  13.379      if ( p->event_channel != NULL )
  13.380      {
  13.381          for ( i = 0; i < p->max_event_channel; i++ )
  13.382 -            (void)__event_channel_close(p, i);
  13.383 +            (void)__evtchn_close(p, i);
  13.384          kfree(p->event_channel);
  13.385      }
  13.386  }
    14.1 --- a/xen/common/keyhandler.c	Thu Mar 25 09:50:46 2004 +0000
    14.2 +++ b/xen/common/keyhandler.c	Thu Mar 25 11:51:43 2004 +0000
    14.3 @@ -99,7 +99,7 @@ static char *task_states[] =
    14.4  
    14.5  void do_task_queues(u_char key, void *dev_id, struct pt_regs *regs) 
    14.6  {
    14.7 -    unsigned long       flags, cpu_mask = 0; 
    14.8 +    unsigned long       flags;
    14.9      struct task_struct *p; 
   14.10      shared_info_t      *s; 
   14.11      s_time_t            now = NOW();
   14.12 @@ -116,15 +116,13 @@ void do_task_queues(u_char key, void *de
   14.13                 p->domain, p->processor, p->has_cpu ? 'T':'F', 
   14.14                 task_states[p->state], p->hyp_events); 
   14.15          s = p->shared_info; 
   14.16 -        printk("Guest: events = %08lx, events_mask = %08lx\n", 
   14.17 -               s->events, s->events_mask); 
   14.18 +        printk("Guest: upcall_pend = %08lx, upcall_mask = %08lx\n", 
   14.19 +               s->evtchn_upcall_pending, s->evtchn_upcall_mask);
   14.20          printk("Notifying guest...\n"); 
   14.21 -        cpu_mask |= mark_guest_event(p, _EVENT_DEBUG);
   14.22 +        send_guest_virq(p, VIRQ_DEBUG);
   14.23      }
   14.24  
   14.25      read_unlock_irqrestore(&tasklist_lock, flags); 
   14.26 -
   14.27 -    guest_event_notify(cpu_mask);
   14.28  }
   14.29  
   14.30  extern void perfc_printall (u_char key, void *dev_id, struct pt_regs *regs);
    15.1 --- a/xen/common/physdev.c	Thu Mar 25 09:50:46 2004 +0000
    15.2 +++ b/xen/common/physdev.c	Thu Mar 25 11:51:43 2004 +0000
    15.3 @@ -576,28 +576,16 @@ static long pci_find_irq(int seg, int bu
    15.4  static void phys_dev_interrupt(int irq, void *dev_id, struct pt_regs *ptregs)
    15.5  {
    15.6      phys_dev_t          *pdev;
    15.7 -    struct task_struct  *p;
    15.8 -    unsigned long cpu_mask = 0;
    15.9  
   15.10 -    if ( !(pdev = (phys_dev_t *)dev_id) )
   15.11 +    if ( (pdev = (phys_dev_t *)dev_id) == NULL )
   15.12      {
   15.13          printk("spurious interrupt, no proper device id, %d\n", irq);
   15.14          return;
   15.15      }
   15.16      
   15.17 -    p = pdev->owner;
   15.18 -
   15.19 -    if ( test_bit(irq, &p->shared_info->physirq_pend) )
   15.20 -    {
   15.21 -        /* Some interrupt already delivered to guest */
   15.22 -        return;
   15.23 -    }
   15.24 -
   15.25 -    /* notify guest */
   15.26 -    set_bit(irq, &p->shared_info->physirq_pend);
   15.27 +    /* XXX KAF: introduced race here? */
   15.28      set_bit(ST_IRQ_DELIVERED, &pdev->state);
   15.29 -    cpu_mask |= mark_guest_event(p, _EVENT_PHYSIRQ);
   15.30 -    guest_event_notify(cpu_mask);
   15.31 +    send_guest_pirq(pdev->owner, irq);
   15.32  }
   15.33  
   15.34  /* this is called instead of the PICs original end handler. 
   15.35 @@ -767,11 +755,13 @@ static long pci_finished_irq(int irq)
   15.36          return -EINVAL;
   15.37      }
   15.38  
   15.39 +#if 0 /* XXX KAF: do we need this? */
   15.40      if ( test_bit(irq, &current->shared_info->physirq_pend) )
   15.41      {
   15.42          printk("finished_irq called for un-acknowleged irq %d\n", irq);        
   15.43          return -EINVAL;
   15.44      }
   15.45 +#endif
   15.46  
   15.47      clear_bit(ST_IRQ_DELIVERED, &pdev->state);
   15.48  
    16.1 --- a/xen/common/schedule.c	Thu Mar 25 09:50:46 2004 +0000
    16.2 +++ b/xen/common/schedule.c	Thu Mar 25 11:51:43 2004 +0000
    16.3 @@ -218,7 +218,7 @@ void wake_up(struct task_struct *p)
    16.4  static long do_block(void)
    16.5  {
    16.6      ASSERT(current->domain != IDLE_DOMAIN_ID);
    16.7 -    set_bit(EVENTS_MASTER_ENABLE_BIT, &current->shared_info->events_mask);
    16.8 +    clear_bit(0, &current->shared_info->evtchn_upcall_mask);
    16.9      current->state = TASK_INTERRUPTIBLE;
   16.10      TRACE_2D(TRC_SCHED_BLOCK, current->domain, current);
   16.11      __enter_scheduler();
   16.12 @@ -351,7 +351,7 @@ long sched_adjdom(struct sched_adjdom_cm
   16.13   */
   16.14  unsigned long __reschedule(struct task_struct *p)
   16.15  {
   16.16 -       int cpu = p->processor;
   16.17 +    int cpu = p->processor;
   16.18      struct task_struct *curr;
   16.19      s_time_t now, min_time;
   16.20  
   16.21 @@ -385,9 +385,13 @@ void reschedule(struct task_struct *p)
   16.22  
   16.23      spin_lock_irqsave(&schedule_lock[p->processor], flags);
   16.24      cpu_mask = __reschedule(p);
   16.25 +    spin_unlock_irqrestore(&schedule_lock[p->processor], flags);
   16.26  
   16.27 -    spin_unlock_irqrestore(&schedule_lock[p->processor], flags);
   16.28 -    hyp_event_notify(cpu_mask);
   16.29 +#ifdef CONFIG_SMP
   16.30 +    cpu_mask &= ~(1 << smp_processor_id());
   16.31 +    if ( cpu_mask != 0 )
   16.32 +        smp_send_event_check_mask(cpu_mask);
   16.33 +#endif
   16.34  }
   16.35  
   16.36  /* 
   16.37 @@ -489,7 +493,7 @@ asmlinkage void __enter_scheduler(void)
   16.38  
   16.39      /* Mark a timer event for the newly-scheduled domain. */
   16.40      if ( !is_idle_task(next) )
   16.41 -        set_bit(_EVENT_TIMER, &next->shared_info->events);
   16.42 +        evtchn_set_pending(next, VIRQ_TIMER);
   16.43      
   16.44      schedule_tail(next);
   16.45  
   16.46 @@ -528,8 +532,8 @@ static void t_timer_fn(unsigned long unu
   16.47  
   16.48      TRACE_0D(TRC_SCHED_T_TIMER_FN);
   16.49  
   16.50 -    if ( !is_idle_task(p) ) 
   16.51 -        set_bit(_EVENT_TIMER, &p->shared_info->events);
   16.52 +    if ( !is_idle_task(p) )
   16.53 +        send_guest_virq(p, VIRQ_TIMER);
   16.54  
   16.55      t_timer[p->processor].expires = NOW() + MILLISECS(10);
   16.56      add_ac_timer(&t_timer[p->processor]);
   16.57 @@ -538,13 +542,9 @@ static void t_timer_fn(unsigned long unu
   16.58  /* Domain timer function, sends a virtual timer interrupt to domain */
   16.59  static void dom_timer_fn(unsigned long data)
   16.60  {
   16.61 -    unsigned long cpu_mask = 0;
   16.62      struct task_struct *p = (struct task_struct *)data;
   16.63 -
   16.64      TRACE_0D(TRC_SCHED_DOM_TIMER_FN);
   16.65 -
   16.66 -    cpu_mask |= mark_guest_event(p, _EVENT_TIMER);
   16.67 -    guest_event_notify(cpu_mask);
   16.68 +    send_guest_virq(p, VIRQ_TIMER);
   16.69  }
   16.70  
   16.71  
    17.1 --- a/xen/drivers/block/xen_block.c	Thu Mar 25 09:50:46 2004 +0000
    17.2 +++ b/xen/drivers/block/xen_block.c	Thu Mar 25 11:51:43 2004 +0000
    17.3 @@ -539,7 +539,6 @@ static void dispatch_rw_block_io(struct 
    17.4  static void make_response(struct task_struct *p, unsigned long id, 
    17.5  			  unsigned short op, unsigned long st)
    17.6  {
    17.7 -    unsigned long cpu_mask;
    17.8      blk_ring_resp_entry_t *resp;
    17.9  
   17.10      /* Place on the response ring for the relevant domain. */ 
   17.11 @@ -553,8 +552,7 @@ static void make_response(struct task_st
   17.12      spin_unlock(&p->blk_ring_lock);
   17.13      
   17.14      /* Kick the relevant domain. */
   17.15 -    cpu_mask = mark_guest_event(p, _EVENT_BLKDEV);
   17.16 -    guest_event_notify(cpu_mask); 
   17.17 +    send_guest_virq(p, VIRQ_BLKDEV);
   17.18  }
   17.19  
   17.20  static void dump_blockq(u_char key, void *dev_id, struct pt_regs *regs) 
    18.1 --- a/xen/drivers/block/xen_vbd.c	Thu Mar 25 09:50:46 2004 +0000
    18.2 +++ b/xen/drivers/block/xen_vbd.c	Thu Mar 25 11:51:43 2004 +0000
    18.3 @@ -29,7 +29,6 @@ long __vbd_create(struct task_struct *p,
    18.4      vbd_t *vbd; 
    18.5      rb_node_t **rb_p, *rb_parent = NULL;
    18.6      long ret = 0;
    18.7 -    unsigned long cpu_mask;
    18.8  
    18.9      spin_lock(&p->vbd_lock);
   18.10  
   18.11 @@ -69,8 +68,7 @@ long __vbd_create(struct task_struct *p,
   18.12      rb_link_node(&vbd->rb, rb_parent, rb_p);
   18.13      rb_insert_color(&vbd->rb, &p->vbd_rb);
   18.14  
   18.15 -    cpu_mask = mark_guest_event(p, _EVENT_VBD_UPD);
   18.16 -    guest_event_notify(cpu_mask);
   18.17 +    send_guest_virq(p, VIRQ_VBD_UPD);
   18.18  
   18.19   out:
   18.20      spin_unlock(&p->vbd_lock);
   18.21 @@ -110,7 +108,6 @@ long __vbd_grow(struct task_struct *p,
   18.22      vbd_t *vbd = NULL;
   18.23      rb_node_t *rb;
   18.24      long ret = 0;
   18.25 -    unsigned long cpu_mask;
   18.26  
   18.27      spin_lock(&p->vbd_lock);
   18.28  
   18.29 @@ -150,8 +147,7 @@ long __vbd_grow(struct task_struct *p,
   18.30  
   18.31      *px = x;
   18.32  
   18.33 -    cpu_mask = mark_guest_event(p, _EVENT_VBD_UPD);
   18.34 -    guest_event_notify(cpu_mask);
   18.35 +    send_guest_virq(p, VIRQ_VBD_UPD);
   18.36  
   18.37   out:
   18.38      spin_unlock(&p->vbd_lock);
   18.39 @@ -190,7 +186,6 @@ long vbd_shrink(vbd_shrink_t *shrink)
   18.40      vbd_t *vbd = NULL;
   18.41      rb_node_t *rb;
   18.42      long ret = 0;
   18.43 -    unsigned long cpu_mask;
   18.44  
   18.45      if ( !IS_PRIV(current) )
   18.46          return -EPERM; 
   18.47 @@ -233,8 +228,7 @@ long vbd_shrink(vbd_shrink_t *shrink)
   18.48      *px = x->next;
   18.49      kfree(x);
   18.50  
   18.51 -    cpu_mask = mark_guest_event(p, _EVENT_VBD_UPD);
   18.52 -    guest_event_notify(cpu_mask);
   18.53 +    send_guest_virq(p, VIRQ_VBD_UPD);
   18.54  
   18.55   out:
   18.56      spin_unlock(&p->vbd_lock);
   18.57 @@ -252,7 +246,6 @@ long vbd_setextents(vbd_setextents_t *se
   18.58      rb_node_t *rb;
   18.59      int i;
   18.60      long ret = 0;
   18.61 -    unsigned long cpu_mask;
   18.62  
   18.63      if ( !IS_PRIV(current) )
   18.64          return -EPERM; 
   18.65 @@ -323,8 +316,7 @@ long vbd_setextents(vbd_setextents_t *se
   18.66      /* Make the new list visible. */
   18.67      vbd->extents = new_extents;
   18.68  
   18.69 -    cpu_mask = mark_guest_event(p, _EVENT_VBD_UPD);
   18.70 -    guest_event_notify(cpu_mask);
   18.71 +    send_guest_virq(p, VIRQ_VBD_UPD);
   18.72  
   18.73   out:
   18.74      spin_unlock(&p->vbd_lock);
   18.75 @@ -348,7 +340,6 @@ long vbd_delete(vbd_delete_t *delete)
   18.76      vbd_t *vbd;
   18.77      rb_node_t *rb;
   18.78      xen_extent_le_t *x, *t;
   18.79 -    unsigned long cpu_mask;
   18.80  
   18.81      if( !IS_PRIV(current) )
   18.82          return -EPERM; 
   18.83 @@ -392,8 +383,7 @@ long vbd_delete(vbd_delete_t *delete)
   18.84          x = t;
   18.85      }
   18.86      
   18.87 -    cpu_mask = mark_guest_event(p, _EVENT_VBD_UPD);
   18.88 -    guest_event_notify(cpu_mask);
   18.89 +    send_guest_virq(p, VIRQ_VBD_UPD);
   18.90     
   18.91      spin_unlock(&p->vbd_lock);
   18.92      put_task_struct(p);
   18.93 @@ -406,7 +396,6 @@ void destroy_all_vbds(struct task_struct
   18.94      vbd_t *vbd;
   18.95      rb_node_t *rb;
   18.96      xen_extent_le_t *x, *t;
   18.97 -    unsigned long cpu_mask;
   18.98  
   18.99      spin_lock(&p->vbd_lock);
  18.100  
  18.101 @@ -426,8 +415,7 @@ void destroy_all_vbds(struct task_struct
  18.102          }          
  18.103      }
  18.104  
  18.105 -    cpu_mask = mark_guest_event(p, _EVENT_VBD_UPD);
  18.106 -    guest_event_notify(cpu_mask);
  18.107 +    send_guest_virq(p, VIRQ_VBD_UPD);
  18.108  
  18.109      spin_unlock(&p->vbd_lock);
  18.110  }
    19.1 --- a/xen/drivers/char/console.c	Thu Mar 25 09:50:46 2004 +0000
    19.2 +++ b/xen/drivers/char/console.c	Thu Mar 25 11:51:43 2004 +0000
    19.3 @@ -243,7 +243,6 @@ static void switch_serial_input(void)
    19.4  static void __serial_rx(unsigned char c, struct pt_regs *regs)
    19.5  {
    19.6      key_handler *handler;
    19.7 -    unsigned long cpu_mask;
    19.8      struct task_struct *p;
    19.9  
   19.10      if ( xen_rx )
   19.11 @@ -257,8 +256,7 @@ static void __serial_rx(unsigned char c,
   19.12          if ( serial_rx_prod++ == serial_rx_cons )
   19.13          {
   19.14              p = find_domain_by_id(0); /* only DOM0 reads the serial buffer */
   19.15 -            cpu_mask = mark_guest_event(p, _EVENT_CONSOLE);
   19.16 -            guest_event_notify(cpu_mask);
   19.17 +            send_guest_virq(p, VIRQ_CONSOLE);
   19.18              put_task_struct(p);
   19.19          }
   19.20      }
    20.1 --- a/xen/drivers/char/keyboard.c	Thu Mar 25 09:50:46 2004 +0000
    20.2 +++ b/xen/drivers/char/keyboard.c	Thu Mar 25 11:51:43 2004 +0000
    20.3 @@ -193,7 +193,7 @@ static void keyboard_interrupt(int irq, 
    20.4  {
    20.5      unsigned char status=0, scancode;
    20.6      unsigned int work = 1000;
    20.7 -    unsigned long cpu_mask = 0, flags;
    20.8 +    unsigned long flags;
    20.9      struct task_struct *p = CONSOLE_OWNER;
   20.10  
   20.11      spin_lock_irqsave(&kbd_lock, flags);
   20.12 @@ -227,7 +227,7 @@ static void keyboard_interrupt(int irq, 
   20.13          if ( p != NULL )
   20.14          {
   20.15              kbd_ring_push(status, scancode);
   20.16 -            cpu_mask |= mark_guest_event(p, _EVENT_PS2);
   20.17 +            send_guest_virq(p, VIRQ_PS2);
   20.18          }
   20.19      }
   20.20      
   20.21 @@ -237,10 +237,7 @@ static void keyboard_interrupt(int irq, 
   20.22      spin_unlock_irqrestore(&kbd_lock, flags);
   20.23  
   20.24      if ( p != NULL )
   20.25 -    {
   20.26          put_task_struct(p);
   20.27 -        guest_event_notify(cpu_mask);
   20.28 -    }
   20.29  }
   20.30      
   20.31      
    21.1 --- a/xen/include/hypervisor-ifs/event_channel.h	Thu Mar 25 09:50:46 2004 +0000
    21.2 +++ b/xen/include/hypervisor-ifs/event_channel.h	Thu Mar 25 11:51:43 2004 +0000
    21.3 @@ -10,20 +10,34 @@
    21.4  #define __HYPERVISOR_IFS__EVENT_CHANNEL_H__
    21.5  
    21.6  /*
    21.7 - * EVTCHNOP_open: Open a communication channel between <dom1> and <dom2>.
    21.8 + * EVTCHNOP_bind_interdomain: Open an event channel between <dom1> and <dom2>.
    21.9   * NOTES:
   21.10   *  1. <dom1> and/or <dom2> may be specified as DOMID_SELF.
   21.11   *  2. Only a sufficiently-privileged domain may create an event channel.
   21.12   *  3. <port1> and <port2> are only supplied if the op succeeds.
   21.13   */
   21.14 -#define EVTCHNOP_open           0
   21.15 -typedef struct evtchn_open
   21.16 +#define EVTCHNOP_bind_interdomain 0
   21.17 +typedef struct evtchn_bind_interdomain
   21.18  {
   21.19      /* IN parameters. */
   21.20      domid_t dom1, dom2;
   21.21      /* OUT parameters. */
   21.22      int     port1, port2;
   21.23 -} evtchn_open_t;
   21.24 +} evtchn_bind_interdomain_t;
   21.25 +
   21.26 +/*
   21.27 + * EVTCHNOP_bind_virq: Bind a local event channel to IRQ <irq>.
   21.28 + * NOTES:
   21.29 + *  1. A virtual IRQ may be bound to at most one event channel per domain.
   21.30 + */
   21.31 +#define EVTCHNOP_bind_virq    1
   21.32 +typedef struct evtchn_bind_virq
   21.33 +{
   21.34 +    /* IN parameters. */
   21.35 +    int virq;
   21.36 +    /* OUT parameters. */
   21.37 +    int port;
   21.38 +} evtchn_bind_virq_t;
   21.39  
   21.40  /*
   21.41   * EVTCHNOP_close: Close the communication channel which has an endpoint at
   21.42 @@ -33,7 +47,7 @@ typedef struct evtchn_open
   21.43   *  2. Only a sufficiently-privileged domain may close an event channel
   21.44   *     for which <dom> is not DOMID_SELF.
   21.45   */
   21.46 -#define EVTCHNOP_close          1
   21.47 +#define EVTCHNOP_close            2
   21.48  typedef struct evtchn_close
   21.49  {
   21.50      /* IN parameters. */
   21.51 @@ -46,7 +60,7 @@ typedef struct evtchn_close
   21.52   * EVTCHNOP_send: Send an event to the remote end of the channel whose local
   21.53   * endpoint is <DOMID_SELF, local_port>.
   21.54   */
   21.55 -#define EVTCHNOP_send           2
   21.56 +#define EVTCHNOP_send             3
   21.57  typedef struct evtchn_send
   21.58  {
   21.59      /* IN parameters. */
   21.60 @@ -56,36 +70,45 @@ typedef struct evtchn_send
   21.61  
   21.62  /*
   21.63   * EVTCHNOP_status: Get the current status of the communication channel which
   21.64 - * has an endpoint at <dom1, port1>.
   21.65 + * has an endpoint at <dom, port>.
   21.66   * NOTES:
   21.67 - *  1. <dom1> may be specified as DOMID_SELF.
   21.68 + *  1. <dom> may be specified as DOMID_SELF.
   21.69   *  2. Only a sufficiently-privileged domain may obtain the status of an event
   21.70 - *     channel for which <dom1> is not DOMID_SELF.
   21.71 - *  3. <dom2, port2> is only supplied if status is 'connected'.
   21.72 + *     channel for which <dom> is not DOMID_SELF.
   21.73   */
   21.74 -#define EVTCHNOP_status         3  /* Get status of <channel id>.         */
   21.75 +#define EVTCHNOP_status           4
   21.76  typedef struct evtchn_status
   21.77  {
   21.78      /* IN parameters */
   21.79 -    domid_t dom1;
   21.80 -    int     port1;
   21.81 +    domid_t dom;
   21.82 +    int     port;
   21.83      /* OUT parameters */
   21.84 -    domid_t dom2;
   21.85 -    int     port2;
   21.86 -#define EVTCHNSTAT_closed       0  /* Chennel is not in use.              */
   21.87 -#define EVTCHNSTAT_disconnected 1  /* Channel is not connected to remote. */
   21.88 -#define EVTCHNSTAT_connected    2  /* Channel is connected to remote.     */
   21.89 +#define EVTCHNSTAT_closed       0  /* Chennel is not in use.                 */
   21.90 +#define EVTCHNSTAT_unbound      1  /* Channel is not bound to a source.      */
   21.91 +#define EVTCHNSTAT_interdomain  2  /* Channel is connected to remote domain. */
   21.92 +#define EVTCHNSTAT_pirq     3      /* Channel is bound to a phys IRQ line.   */
   21.93 +#define EVTCHNSTAT_virq     4      /* Channel is bound to a virtual IRQ line */
   21.94      int     status;
   21.95 +    union {
   21.96 +        int __none;    /* EVTCHNSTAT_closed, EVTCHNSTAT_unbound */
   21.97 +        struct {
   21.98 +            domid_t dom;
   21.99 +            int     port;
  21.100 +        } interdomain; /* EVTCHNSTAT_interdomain */
  21.101 +        int pirq;      /* EVTCHNSTAT_pirq        */
  21.102 +        int virq;      /* EVTCHNSTAT_virq        */
  21.103 +    } u;
  21.104  } evtchn_status_t;
  21.105  
  21.106  typedef struct evtchn_op
  21.107  {
  21.108      int cmd; /* EVTCHNOP_* */
  21.109      union {
  21.110 -        evtchn_open_t   open;
  21.111 -        evtchn_close_t  close;
  21.112 -        evtchn_send_t   send;
  21.113 -        evtchn_status_t status;
  21.114 +        evtchn_bind_interdomain_t bind_interdomain;
  21.115 +        evtchn_bind_virq_t        bind_virq;
  21.116 +        evtchn_close_t            close;
  21.117 +        evtchn_send_t             send;
  21.118 +        evtchn_status_t           status;
  21.119      } u;
  21.120  } evtchn_op_t;
  21.121  
    22.1 --- a/xen/include/hypervisor-ifs/hypervisor-if.h	Thu Mar 25 09:50:46 2004 +0000
    22.2 +++ b/xen/include/hypervisor-ifs/hypervisor-if.h	Thu Mar 25 11:51:43 2004 +0000
    22.3 @@ -50,40 +50,25 @@
    22.4  #define ARGS_PER_MULTICALL_ENTRY 8
    22.5  
    22.6  
    22.7 -/* EVENT MESSAGES
    22.8 - *
    22.9 - * Here, as in the interrupts to the guestos, additional network interfaces
   22.10 - * are defined.	 These definitions server as placeholders for the event bits,
   22.11 - * however, in the code these events will allways be referred to as shifted
   22.12 - * offsets from the base NET events.
   22.13 +/* 
   22.14 + * VIRTUAL INTERRUPTS
   22.15 + * 
   22.16 + * Virtual interrupts that a guest OS may receive from the hypervisor.
   22.17   */
   22.18  
   22.19 -/* Events that a guest OS may receive from the hypervisor. */
   22.20 -#define EVENT_BLKDEV   0x01  /* A block device response has been queued. */
   22.21 -#define EVENT_TIMER    0x02  /* A timeout has been updated. */
   22.22 -#define EVENT_DIE      0x04  /* OS is about to be killed. Clean up please! */
   22.23 -#define EVENT_DEBUG    0x08  /* Request guest to dump debug info (gross!) */
   22.24 -#define EVENT_NET      0x10  /* There are packets for transmission. */
   22.25 -#define EVENT_PS2      0x20  /* PS/2 keyboard or mouse event(s) */
   22.26 -#define EVENT_STOP     0x40  /* Prepare for stopping and possible pickling */
   22.27 -#define EVENT_EVTCHN   0x80  /* Event pending on an event channel */
   22.28 -#define EVENT_VBD_UPD  0x100 /* Event to signal VBDs should be reprobed */
   22.29 -#define EVENT_CONSOLE  0x200 /* This is only for domain-0 initial console. */
   22.30 -#define EVENT_PHYSIRQ  0x400 /* Event to signal pending physical IRQs. */
   22.31 -
   22.32 -/* Bit offsets, as opposed to the above masks. */
   22.33 -#define _EVENT_BLKDEV    0
   22.34 -#define _EVENT_TIMER     1
   22.35 -#define _EVENT_DIE       2
   22.36 -#define _EVENT_DEBUG     3
   22.37 -#define _EVENT_NET       4
   22.38 -#define _EVENT_PS2       5
   22.39 -#define _EVENT_STOP      6
   22.40 -#define _EVENT_EVTCHN    7
   22.41 -#define _EVENT_VBD_UPD   8
   22.42 -#define _EVENT_CONSOLE   9
   22.43 -#define _EVENT_PHYSIRQ  10
   22.44 -
   22.45 +#define VIRQ_BLKDEV    0  /* A block device response has been queued. */
   22.46 +#define VIRQ_TIMER     1  /* A timeout has been updated. */
   22.47 +#define VIRQ_DIE       2  /* OS is about to be killed. Clean up please! */
   22.48 +#define VIRQ_DEBUG     3  /* Request guest to dump debug info (gross!) */
   22.49 +#define VIRQ_NET       4  /* There are packets for transmission. */
   22.50 +#define VIRQ_PS2       5  /* PS/2 keyboard or mouse event(s) */
   22.51 +#define VIRQ_STOP      6  /* Prepare for stopping and possible pickling */
   22.52 +#define VIRQ_EVTCHN    7  /* Event pending on an event channel */
   22.53 +#define VIRQ_VBD_UPD   8  /* Event to signal VBDs should be reprobed */
   22.54 +#define VIRQ_CONSOLE   9  /* This is only for domain-0 initial console. */
   22.55 +#define VIRQ_PHYSIRQ  10  /* Event to signal pending physical IRQs. */
   22.56 +#define VIRQ_ERROR    11  /* Catch-all virtual interrupt. */
   22.57 +#define NR_VIRQS      12
   22.58  
   22.59  /*
   22.60   * MMU_XXX: specified in least 2 bits of 'ptr' field. These bits are masked
   22.61 @@ -121,12 +106,6 @@
   22.62  #define UVMF_FLUSH_TLB          1 /* Flush entire TLB. */
   22.63  #define UVMF_INVLPG             2 /* Flush the VA mapping being updated. */
   22.64  
   22.65 -/*
   22.66 - * Master "switch" for enabling/disabling event delivery.
   22.67 - */
   22.68 -#define EVENTS_MASTER_ENABLE_MASK 0x80000000UL
   22.69 -#define EVENTS_MASTER_ENABLE_BIT  31
   22.70 -
   22.71  
   22.72  /*
   22.73   * SCHEDOP_* - Scheduler hypercall operations.
   22.74 @@ -172,45 +151,57 @@ typedef struct
   22.75   * Xen/guestos shared data -- pointer provided in start_info.
   22.76   * NB. We expect that this struct is smaller than a page.
   22.77   */
   22.78 -typedef struct shared_info_st {
   22.79 -
   22.80 -    /* Bitmask of outstanding event notifications hypervisor -> guest OS. */
   22.81 -    unsigned long events;
   22.82 +typedef struct shared_info_st
   22.83 +{
   22.84      /*
   22.85 -     * Hypervisor will only signal event delivery via the "callback exception"
   22.86 -     * when a pending event is not masked. The mask also contains a "master
   22.87 -     * enable" which prevents any event delivery. This mask can be used to
   22.88 -     * prevent unbounded reentrancy and stack overflow (in this way, acts as a
   22.89 -     * kind of interrupt-enable flag).
   22.90 +     * If bit 0 in evtchn_upcall_pending is transitioned 0->1, and bit 0 in 
   22.91 +     * evtchn_upcall_mask is clear, then an asynchronous upcall is scheduled. 
   22.92 +     * The upcall mask can be used to prevent unbounded reentrancy and stack 
   22.93 +     * overflow (in this way, acts as a kind of interrupt-enable flag).
   22.94       */
   22.95 -    unsigned long events_mask;
   22.96 +    unsigned long evtchn_upcall_pending;
   22.97 +    unsigned long evtchn_upcall_mask;
   22.98  
   22.99      /*
  22.100 -     * A domain can have up to 1024 bidirectional event channels to/from other
  22.101 -     * domains. Domains must agree out-of-band to set up a connection, and then
  22.102 -     * each must explicitly request a connection to the other. When both have
  22.103 -     * made the request the channel is fully allocated and set up.
  22.104 -     * 
  22.105 -     * An event channel is a single sticky 'bit' of information. Setting the
  22.106 -     * sticky bit also causes an upcall into the target domain. In this way
  22.107 -     * events can be seen as an IPI [Inter-Process(or) Interrupt].
  22.108 +     * A domain can have up to 1024 "event channels" on which it can send
  22.109 +     * and receive asynchronous event notifications. There are three classes
  22.110 +     * of event that are delivered by this mechanism:
  22.111 +     *  1. Bi-directional inter- and intra-domain connections. Domains must
  22.112 +     *     arrange out-of-band to set up a connection (usually the setup
  22.113 +     *     is initiated and organised by a privileged third party such as
  22.114 +     *     software running in domain 0).
  22.115 +     *  2. Physical interrupts. A domain with suitable hardware-access
  22.116 +     *     privileges can bind an event-channel port to a physical interrupt
  22.117 +     *     source.
  22.118 +     *  3. Virtual interrupts ('events'). A domain can bind an event-channel
  22.119 +     *     port to a virtual interrupt source, such as the virtual-timer
  22.120 +     *     device or the emergency console.
  22.121       * 
  22.122 -     * A guest can see which of its event channels are pending by reading the
  22.123 -     * 'event_channel_pend' bitfield. To avoid a linear scan of the entire
  22.124 -     * bitfield there is a 'selector' which indicates which words in the
  22.125 -     * bitfield contain at least one set bit.
  22.126 +     * Event channels are addressed by a "port index" between 0 and 1023.
  22.127 +     * Each channel is associated with three bits of information:
  22.128 +     *  1. PENDING -- notifies the domain that there is a pending notification
  22.129 +     *     to be processed. This bit is cleared by the guest.
  22.130 +     *  2. EXCEPTION -- notifies the domain that there has been some
  22.131 +     *     exceptional event associated with this channel (e.g. remote
  22.132 +     *     disconnect, physical IRQ error). This bit is cleared by the guest.
  22.133 +     *  3. MASK -- if this bit is clear then a 0->1 transition of PENDING
  22.134 +     *     or EXCEPTION will cause an asynchronous upcall to be scheduled.
  22.135 +     *     This bit is only updated by the guest. It is read-only within Xen.
  22.136 +     *     If a channel becomes pending or an exceptional event occurs while
  22.137 +     *     the channel is masked then the 'edge' is lost (i.e., when the
  22.138 +     *     channel is unmasked, the guest must manually handle pending
  22.139 +     *     notifications as no upcall will be scheduled by Xen).
  22.140       * 
  22.141 -     * There is a similar bitfield to indicate which event channels have been
  22.142 -     * disconnected by the remote end. There is also a 'selector' for this
  22.143 -     * field.
  22.144 +     * To expedite scanning of pending notifications and exceptions, any 
  22.145 +     * 0->1 transition on an unmasked channel causes a corresponding bit in
  22.146 +     * a 32-bit selector to be set. Each bit in the selector covers a 32-bit
  22.147 +     * word in the PENDING or EXCEPTION bitfield array.
  22.148       */
  22.149 -    u32 event_channel_pend[32];
  22.150 -    u32 event_channel_pend_sel;
  22.151 -    u32 event_channel_disc[32];
  22.152 -    u32 event_channel_disc_sel;
  22.153 -
  22.154 -    /* Bitmask of physical IRQ lines that are pending for this domain. */
  22.155 -    unsigned long physirq_pend;
  22.156 +    u32 evtchn_pending[32];
  22.157 +    u32 evtchn_pending_sel;
  22.158 +    u32 evtchn_exception[32];
  22.159 +    u32 evtchn_exception_sel;
  22.160 +    u32 evtchn_mask[32];
  22.161  
  22.162      /*
  22.163       * Time: The following abstractions are exposed: System Time, Clock Time,
    23.1 --- a/xen/include/xen/event.h	Thu Mar 25 09:50:46 2004 +0000
    23.2 +++ b/xen/include/xen/event.h	Thu Mar 25 11:51:43 2004 +0000
    23.3 @@ -6,33 +6,23 @@
    23.4   * Copyright (c) 2002, K A Fraser
    23.5   */
    23.6  
    23.7 +#ifndef __XEN_EVENT_H__
    23.8 +#define __XEN_EVENT_H__
    23.9 +
   23.10  #include <xen/config.h>
   23.11  #include <xen/sched.h>
   23.12  #include <asm/bitops.h>
   23.13  
   23.14 -#ifdef CONFIG_SMP
   23.15 +/*
   23.16 + * GENERIC SCHEDULING CALLBACK MECHANISMS
   23.17 + */
   23.18  
   23.19 -/*
   23.20 - * mark_guest_event:
   23.21 - *  @p:        Domain to which event should be passed
   23.22 - *  @event:    Event number
   23.23 - *  RETURNS:   "Bitmask" of CPU on which process is currently running
   23.24 - * 
   23.25 - * Idea is that caller may loop on task_list, looking for domains
   23.26 - * to pass events to (using this function). The caller accumulates the
   23.27 - * bits returned by this function (ORing them together) then calls
   23.28 - * event_notify().
   23.29 - * 
   23.30 - * Guest_events are per-domain events passed directly to the guest OS
   23.31 - * in ring 1. 
   23.32 - */
   23.33 -static inline unsigned long mark_guest_event(struct task_struct *p, int event)
   23.34 +/* Schedule an asynchronous callback for the specified domain. */
   23.35 +static inline void __guest_notify(struct task_struct *p)
   23.36  {
   23.37 +#ifdef CONFIG_SMP
   23.38      unsigned long flags, cpu_mask;
   23.39  
   23.40 -    if ( test_and_set_bit(event, &p->shared_info->events) )
   23.41 -        return 0;
   23.42 -
   23.43      spin_lock_irqsave(&schedule_lock[p->processor], flags);
   23.44      if ( p->state == TASK_INTERRUPTIBLE )
   23.45          __wake_up(p);
   23.46 @@ -41,75 +31,85 @@ static inline unsigned long mark_guest_e
   23.47          cpu_mask |= 1 << p->processor;
   23.48      spin_unlock_irqrestore(&schedule_lock[p->processor], flags);
   23.49  
   23.50 -    return cpu_mask;
   23.51 +    cpu_mask &= ~(1 << smp_processor_id());
   23.52 +    if ( cpu_mask != 0 )
   23.53 +        smp_send_event_check_mask(cpu_mask);
   23.54 +#else
   23.55 +    if ( p->state == TASK_INTERRUPTIBLE )
   23.56 +        wake_up(p);
   23.57 +    reschedule(p);
   23.58 +#endif
   23.59  }
   23.60  
   23.61 -/* As above, but hyp_events are handled within the hypervisor. */
   23.62 -static inline unsigned long mark_hyp_event(struct task_struct *p, int event)
   23.63 +static inline void guest_notify(struct task_struct *p)
   23.64  {
   23.65 -    unsigned long flags, cpu_mask;
   23.66 -
   23.67 -    if ( test_and_set_bit(event, &p->hyp_events) )
   23.68 -        return 0;
   23.69 -
   23.70 -    spin_lock_irqsave(&schedule_lock[p->processor], flags);
   23.71 -    if ( p->state == TASK_INTERRUPTIBLE )
   23.72 -        __wake_up(p);
   23.73 -    cpu_mask = __reschedule(p);
   23.74 -    if ( p->has_cpu )
   23.75 -        cpu_mask |= 1 << p->processor;
   23.76 -    spin_unlock_irqrestore(&schedule_lock[p->processor], flags);
   23.77 -
   23.78 -    return cpu_mask;
   23.79 +    /*
   23.80 +     * Upcall already pending or upcalls masked?
   23.81 +     * NB. Suitably synchronised on x86:
   23.82 +     *  We must set the pending bit before checking the mask, but this is
   23.83 +     *  guaranteed to occur because test_and_set_bit() is an ordering barrier.
   23.84 +     */
   23.85 +    if ( !test_and_set_bit(0, &p->shared_info->evtchn_upcall_pending) &&
   23.86 +         !test_bit(0, &p->shared_info->evtchn_upcall_mask) )
   23.87 +        __guest_notify(p);
   23.88  }
   23.89  
   23.90 -/* Notify the given set of CPUs that guest events may be outstanding. */
   23.91 -static inline void guest_event_notify(unsigned long cpu_mask)
   23.92 +
   23.93 +/*
   23.94 + * EVENT-CHANNEL NOTIFICATIONS
   23.95 + * NB. As in guest_notify, evtchn_set_* is suitably synchronised on x86.
   23.96 + */
   23.97 +
   23.98 +static inline void evtchn_set_pending(struct task_struct *p, int port)
   23.99  {
  23.100 -    cpu_mask &= ~(1 << smp_processor_id());
  23.101 -    if ( cpu_mask != 0 ) smp_send_event_check_mask(cpu_mask);
  23.102 +    shared_info_t *s = p->shared_info;
  23.103 +    if ( !test_and_set_bit(port,    &s->evtchn_pending[0]) &&
  23.104 +         !test_bit        (port,    &s->evtchn_mask[0])    &&
  23.105 +         !test_and_set_bit(port>>5, &s->evtchn_pending_sel) )
  23.106 +        guest_notify(p);
  23.107  }
  23.108  
  23.109 -#else
  23.110 -
  23.111 -static inline unsigned long mark_guest_event(struct task_struct *p, int event)
  23.112 +static inline void evtchn_set_exception(struct task_struct *p, int port)
  23.113  {
  23.114 -    if ( !test_and_set_bit(event, &p->shared_info->events) )
  23.115 -    {
  23.116 -        if ( p->state == TASK_INTERRUPTIBLE ) wake_up(p);
  23.117 -        reschedule(p);
  23.118 -    }
  23.119 -    return 0;
  23.120 +    shared_info_t *s = p->shared_info;
  23.121 +    if ( !test_and_set_bit(port,    &s->evtchn_exception[0]) &&
  23.122 +         !test_bit        (port,    &s->evtchn_mask[0])      &&
  23.123 +         !test_and_set_bit(port>>5, &s->evtchn_exception_sel) )
  23.124 +        guest_notify(p);
  23.125  }
  23.126  
  23.127 -static inline unsigned long mark_hyp_event(struct task_struct *p, int event)
  23.128 +/*
  23.129 + * send_guest_virq:
  23.130 + *  @p:        Domain to which virtual IRQ should be sent
  23.131 + *  @virq:     Virtual IRQ number (VIRQ_*)
  23.132 + */
  23.133 +static inline void send_guest_virq(struct task_struct *p, int virq)
  23.134 +{
  23.135 +    evtchn_set_pending(p, p->virq_to_evtchn[virq]);
  23.136 +}
  23.137 +
  23.138 +/*
  23.139 + * send_guest_pirq:
  23.140 + *  @p:        Domain to which physical IRQ should be sent
  23.141 + *  @pirq:     Physical IRQ number
  23.142 + */
  23.143 +static inline void send_guest_pirq(struct task_struct *p, int pirq)
  23.144 +{
  23.145 +    evtchn_set_pending(p, p->pirq_to_evtchn[pirq]);
  23.146 +}
  23.147 +
  23.148 +
  23.149 +/*
  23.150 + * HYPERVISOR-HANDLED EVENTS
  23.151 + */
  23.152 +
  23.153 +static inline void send_hyp_event(struct task_struct *p, int event)
  23.154  {
  23.155      if ( !test_and_set_bit(event, &p->hyp_events) )
  23.156 -    {
  23.157 -        if ( p->state == TASK_INTERRUPTIBLE ) wake_up(p);
  23.158 -        reschedule(p);
  23.159 -    }
  23.160 -    return 0;
  23.161 -}
  23.162 -
  23.163 -#define guest_event_notify(_mask) ((void)0)
  23.164 -
  23.165 -#endif
  23.166 -
  23.167 -/* Notify hypervisor events in thesame way as for guest OS events. */
  23.168 -#define hyp_event_notify(_mask) guest_event_notify(_mask)
  23.169 -
  23.170 -/* Clear a guest-OS event from a per-domain mask. */
  23.171 -static inline void clear_guest_event(struct task_struct *p, int event)
  23.172 -{
  23.173 -    clear_bit(event, &p->shared_info->events);
  23.174 -}
  23.175 -
  23.176 -/* Clear a hypervisor event from a per-domain mask. */
  23.177 -static inline void clear_hyp_event(struct task_struct *p, int event)
  23.178 -{
  23.179 -    clear_bit(event, &p->hyp_events);
  23.180 +        __guest_notify(p);
  23.181  }
  23.182  
  23.183  /* Called on return from (architecture-dependent) entry.S. */
  23.184  void do_hyp_events(void);
  23.185 +
  23.186 +#endif /* __XEN_EVENT_H__ */
    24.1 --- a/xen/include/xen/sched.h	Thu Mar 25 09:50:46 2004 +0000
    24.2 +++ b/xen/include/xen/sched.h	Thu Mar 25 11:51:43 2004 +0000
    24.3 @@ -51,14 +51,25 @@ struct task_struct;
    24.4  
    24.5  typedef struct event_channel_st
    24.6  {
    24.7 -    struct task_struct *remote_dom;
    24.8 -    u16                 remote_port;
    24.9 -#define ECS_FREE         0 /* Available for use.                            */
   24.10 -#define ECS_DISCONNECTED 1 /* Connection is closed. Remote is disconnected. */
   24.11 -#define ECS_CONNECTED    2 /* Connected to remote end.                      */
   24.12 -    u16                 state;
   24.13 +#define ECS_FREE         0 /* Channel is available for use.                  */
   24.14 +#define ECS_UNBOUND      1 /* Channel is not bound to a particular source.   */
   24.15 +#define ECS_INTERDOMAIN  2 /* Channel is bound to another domain.            */
   24.16 +#define ECS_PIRQ         3 /* Channel is bound to a physical IRQ line.       */
   24.17 +#define ECS_VIRQ         4 /* Channel is bound to a virtual IRQ line.        */
   24.18 +    u16 state;
   24.19 +    union {
   24.20 +        struct {
   24.21 +            u16 port;
   24.22 +            struct task_struct *dom;
   24.23 +        } __attribute__ ((packed)) remote; /* state == ECS_CONNECTED */
   24.24 +        u16 pirq; /* state == ECS_PIRQ */
   24.25 +        u16 virq; /* state == ECS_VIRQ */
   24.26 +    } u;
   24.27  } event_channel_t;
   24.28  
   24.29 +int  init_event_channels(struct task_struct *p);
   24.30 +void destroy_event_channels(struct task_struct *p);
   24.31 +
   24.32  struct task_struct 
   24.33  {
   24.34      /*
   24.35 @@ -145,6 +156,14 @@ struct task_struct
   24.36      unsigned int     max_event_channel;
   24.37      spinlock_t       event_channel_lock;
   24.38  
   24.39 +    /*
   24.40 +     * Interrupt to event-channel mappings. Updates should be protected by the 
   24.41 +     * domain's event-channel spinlock. Read accesses can also synchronise on 
   24.42 +     * the lock, but races don't usually matter.
   24.43 +     */
   24.44 +    u16 pirq_to_evtchn[64];
   24.45 +    u16 virq_to_evtchn[NR_VIRQS];
   24.46 +
   24.47      /* Physical I/O */
   24.48      spinlock_t       pcidev_lock;
   24.49      struct list_head pcidev_list;
   24.50 @@ -270,8 +289,9 @@ static inline long schedule_timeout(long
   24.51  }
   24.52  
   24.53  #define signal_pending(_p) \
   24.54 -    ((_p)->hyp_events ||   \
   24.55 -     ((_p)->shared_info->events & (_p)->shared_info->events_mask))
   24.56 +    (((_p)->hyp_events != 0) ||                                 \
   24.57 +     (test_bit(0, &(_p)->shared_info->evtchn_upcall_pending) && \
   24.58 +      !test_bit(0, &(_p)->shared_info->evtchn_upcall_mask)))
   24.59  
   24.60  void domain_init(void);
   24.61  
    25.1 --- a/xen/net/dev.c	Thu Mar 25 09:50:46 2004 +0000
    25.2 +++ b/xen/net/dev.c	Thu Mar 25 11:51:43 2004 +0000
    25.3 @@ -2335,10 +2335,7 @@ static void make_tx_response(net_vif_t  
    25.4  
    25.5      smp_mb(); /* Update producer before checking event threshold. */
    25.6      if ( i == vif->shared_idxs->tx_event )
    25.7 -    {
    25.8 -        unsigned long cpu_mask = mark_guest_event(vif->domain, _EVENT_NET);
    25.9 -        guest_event_notify(cpu_mask);    
   25.10 -    }
   25.11 +        send_guest_virq(vif->domain, VIRQ_NET);
   25.12  }
   25.13  
   25.14  
   25.15 @@ -2361,10 +2358,7 @@ static void make_rx_response(net_vif_t  
   25.16  
   25.17      smp_mb(); /* Update producer before checking event threshold. */
   25.18      if ( i == vif->shared_idxs->rx_event )
   25.19 -    {
   25.20 -        unsigned long cpu_mask = mark_guest_event(vif->domain, _EVENT_NET);
   25.21 -        guest_event_notify(cpu_mask);    
   25.22 -    }
   25.23 +        send_guest_virq(vif->domain, VIRQ_NET);
   25.24  }
   25.25  
   25.26  
    26.1 --- a/xenolinux-2.4.25-sparse/arch/xen/drivers/block/block.c	Thu Mar 25 09:50:46 2004 +0000
    26.2 +++ b/xenolinux-2.4.25-sparse/arch/xen/drivers/block/block.c	Thu Mar 25 11:51:43 2004 +0000
    26.3 @@ -18,15 +18,14 @@
    26.4  
    26.5  typedef unsigned char byte; /* from linux/ide.h */
    26.6  
    26.7 -#define XLBLK_RESPONSE_IRQ HYPEREVENT_IRQ(_EVENT_BLKDEV)
    26.8 -#define XLBLK_UPDATE_IRQ   HYPEREVENT_IRQ(_EVENT_VBD_UPD)
    26.9 -#define DEBUG_IRQ          HYPEREVENT_IRQ(_EVENT_DEBUG)
   26.10 -
   26.11  #define STATE_ACTIVE    0
   26.12  #define STATE_SUSPENDED 1
   26.13  #define STATE_CLOSED    2
   26.14  static unsigned int state = STATE_SUSPENDED;
   26.15  
   26.16 +/* Dynamically-mapped IRQs. */
   26.17 +static int xlblk_response_irq, xlblk_update_irq;
   26.18 +
   26.19  static blk_ring_t *blk_ring;
   26.20  static BLK_RING_IDX resp_cons; /* Response consumer for comms ring. */
   26.21  static BLK_RING_IDX req_prod;  /* Private request producer.         */
   26.22 @@ -552,7 +551,10 @@ int __init xlblk_init(void)
   26.23  
   26.24      reset_xlblk_interface();
   26.25  
   26.26 -    error = request_irq(XLBLK_RESPONSE_IRQ, xlblk_response_int, 
   26.27 +    xlblk_response_irq = bind_virq_to_irq(VIRQ_BLKDEV);
   26.28 +    xlblk_update_irq   = bind_virq_to_irq(VIRQ_VBD_UPD);
   26.29 +
   26.30 +    error = request_irq(xlblk_response_irq, xlblk_response_int, 
   26.31                          SA_SAMPLE_RANDOM, "blkdev", NULL);
   26.32      if ( error )
   26.33      {
   26.34 @@ -560,8 +562,8 @@ int __init xlblk_init(void)
   26.35          goto fail;
   26.36      }
   26.37  
   26.38 -    error = request_irq(XLBLK_UPDATE_IRQ, xlblk_update_int,
   26.39 -                        SA_INTERRUPT, "blkdev", NULL);
   26.40 +    error = request_irq(xlblk_update_irq, xlblk_update_int,
   26.41 +                        0, "blkdev", NULL);
   26.42  
   26.43      if ( error )
   26.44      {
   26.45 @@ -581,8 +583,10 @@ int __init xlblk_init(void)
   26.46  static void __exit xlblk_cleanup(void)
   26.47  {
   26.48      xlvbd_cleanup();
   26.49 -    free_irq(XLBLK_RESPONSE_IRQ, NULL);
   26.50 -    free_irq(XLBLK_UPDATE_IRQ, NULL);
   26.51 +    free_irq(xlblk_response_irq, NULL);
   26.52 +    free_irq(xlblk_update_irq, NULL);
   26.53 +    unbind_virq_from_irq(VIRQ_BLKDEV);
   26.54 +    unbind_virq_from_irq(VIRQ_VBD_UPD);
   26.55  }
   26.56  
   26.57  
    27.1 --- a/xenolinux-2.4.25-sparse/arch/xen/drivers/console/console.c	Thu Mar 25 09:50:46 2004 +0000
    27.2 +++ b/xenolinux-2.4.25-sparse/arch/xen/drivers/console/console.c	Thu Mar 25 11:51:43 2004 +0000
    27.3 @@ -119,6 +119,13 @@ static struct console kcons_info = {
    27.4  void xen_console_init(void)
    27.5  {
    27.6      register_console(&kcons_info);
    27.7 +
    27.8 +    /*
    27.9 +     * XXX This prevents a bogus 'VIRQ_ERROR' when interrupts are enabled
   27.10 +     * for the first time. This works because by this point all important
   27.11 +     * VIRQs (eg. timer) have been properly bound.
   27.12 +     */
   27.13 +    clear_bit(0, &HYPERVISOR_shared_info->evtchn_pending[0]);
   27.14  }
   27.15  
   27.16  
   27.17 @@ -149,6 +156,7 @@ static struct tty_struct *xen_console_ta
   27.18  static struct termios *xen_console_termios[1];
   27.19  static struct termios *xen_console_termios_locked[1];
   27.20  static struct tty_struct *xen_console_tty;
   27.21 +static int console_irq;
   27.22  
   27.23  #define WBUF_SIZE     1024
   27.24  #define WBUF_MASK(_i) ((_i)&(WBUF_SIZE-1))
   27.25 @@ -194,9 +202,6 @@ static void __do_console_io(void)
   27.26          return;
   27.27      }
   27.28  
   27.29 -    /* Acknowledge the notification. */
   27.30 -    evtchn_clear_port(0);
   27.31 -
   27.32      ctrl_if = (control_if_t *)((char *)HYPERVISOR_shared_info + 2048);
   27.33      
   27.34      /* Receive work. */
   27.35 @@ -259,17 +264,7 @@ static void __do_console_io(void)
   27.36      }
   27.37  }
   27.38  
   27.39 -/* This is the callback entry point for domains != 0. */
   27.40 -static void control_event(unsigned int port)
   27.41 -{
   27.42 -    unsigned long flags;
   27.43 -    spin_lock_irqsave(&xen_console_lock, flags);
   27.44 -    __do_console_io();
   27.45 -    spin_unlock_irqrestore(&xen_console_lock, flags);
   27.46 -}
   27.47 -
   27.48 -/* This is the callback entry point for domain 0. */
   27.49 -static void control_irq(int irq, void *dev_id, struct pt_regs *regs)
   27.50 +static void console_interrupt(int irq, void *dev_id, struct pt_regs *regs)
   27.51  {
   27.52      unsigned long flags;
   27.53      spin_lock_irqsave(&xen_console_lock, flags);
   27.54 @@ -472,17 +467,12 @@ int __init xen_con_init(void)
   27.55          panic("Couldn't register Xen virtual console driver\n");
   27.56  
   27.57      if ( !(start_info.flags & SIF_INITDOMAIN) )
   27.58 -    {
   27.59 -        if ( evtchn_request_port(0, control_event) != 0 )
   27.60 -            BUG();
   27.61 -        control_event(0); /* kickstart the console */
   27.62 -    }
   27.63 +        console_irq = bind_evtchn_to_irq(1);
   27.64      else
   27.65 -    {
   27.66 -        request_irq(HYPEREVENT_IRQ(_EVENT_CONSOLE), 
   27.67 -                    control_irq, 0, "console", NULL);
   27.68 -        control_irq(0, NULL, NULL); /* kickstart the console */
   27.69 -    }
   27.70 +        console_irq = bind_virq_to_irq(VIRQ_CONSOLE);
   27.71 +
   27.72 +    (void)request_irq(console_irq,
   27.73 +                      console_interrupt, 0, "console", NULL);
   27.74  
   27.75      printk("Xen virtual console successfully installed\n");
   27.76      
   27.77 @@ -497,8 +487,12 @@ void __exit xen_con_fini(void)
   27.78      if ( ret != 0 )
   27.79          printk(KERN_ERR "Unable to unregister Xen console driver: %d\n", ret);
   27.80  
   27.81 +    free_irq(console_irq, NULL);
   27.82 +
   27.83      if ( !(start_info.flags & SIF_INITDOMAIN) )
   27.84 -        (void)evtchn_free_port(0);
   27.85 +        unbind_evtchn_from_irq(1);
   27.86 +    else
   27.87 +        unbind_virq_from_irq(VIRQ_CONSOLE);
   27.88  }
   27.89  
   27.90  module_init(xen_con_init);
    28.1 --- a/xenolinux-2.4.25-sparse/arch/xen/drivers/evtchn/evtchn.c	Thu Mar 25 09:50:46 2004 +0000
    28.2 +++ b/xenolinux-2.4.25-sparse/arch/xen/drivers/evtchn/evtchn.c	Thu Mar 25 11:51:43 2004 +0000
    28.3 @@ -40,148 +40,54 @@ static unsigned int ring_cons, ring_prod
    28.4  static DECLARE_WAIT_QUEUE_HEAD(evtchn_wait);
    28.5  static struct fasync_struct *evtchn_async_queue;
    28.6  
    28.7 -static evtchn_receiver_t rx_fns[1024];
    28.8 -
    28.9 -static u32 pend_outstanding[32];
   28.10 -static u32 disc_outstanding[32];
   28.11 +/*
   28.12 + * Pending normal notifications and pending exceptional notifications.
   28.13 + * 'Pending' means that we received an upcall but this is not yet ack'ed
   28.14 + * from userspace by writing to /dev/xen/evtchn.
   28.15 + */
   28.16 +static u32 pend_nrm[32], pend_exc[32];
   28.17  
   28.18  static spinlock_t lock;
   28.19  
   28.20 -int evtchn_request_port(unsigned int port, evtchn_receiver_t rx_fn)
   28.21 +void evtchn_device_upcall(int port, int exception)
   28.22  {
   28.23 -    unsigned long flags;
   28.24 -    int rc;
   28.25 -
   28.26 -    spin_lock_irqsave(&lock, flags);
   28.27 +    u16 port_subtype;
   28.28  
   28.29 -    if ( rx_fns[port] != NULL )
   28.30 -    {
   28.31 -        printk(KERN_ALERT "Event channel port %d already in use.\n", port);
   28.32 -        rc = -EINVAL;
   28.33 -    }
   28.34 -    else
   28.35 -    {
   28.36 -        rx_fns[port] = rx_fn;
   28.37 -        rc = 0;
   28.38 -    }
   28.39 -
   28.40 -    spin_unlock_irqrestore(&lock, flags);
   28.41 -
   28.42 -    return rc;
   28.43 -}
   28.44 -
   28.45 -int evtchn_free_port(unsigned int port)
   28.46 -{
   28.47 -    unsigned long flags;
   28.48 -    int rc;
   28.49 -
   28.50 -    spin_lock_irqsave(&lock, flags);
   28.51 +    spin_lock(&lock);
   28.52  
   28.53 -    if ( rx_fns[port] == NULL )
   28.54 -    {
   28.55 -        printk(KERN_ALERT "Event channel port %d not in use.\n", port);
   28.56 -        rc = -EINVAL;
   28.57 -    }
   28.58 -    else
   28.59 -    {
   28.60 -        rx_fns[port] = NULL;
   28.61 -        rc = 0;
   28.62 -    }
   28.63 -
   28.64 -    spin_unlock_irqrestore(&lock, flags);
   28.65 -
   28.66 -    return rc;
   28.67 -}
   28.68 +    mask_evtchn(port);
   28.69  
   28.70 -/*
   28.71 - * NB. Clearing port can race a notification from remote end. Caller must
   28.72 - * therefore recheck notification status on return to avoid missing events.
   28.73 - */
   28.74 -void evtchn_clear_port(unsigned int port)
   28.75 -{
   28.76 -    unsigned int p = port & PORTIDX_MASK;
   28.77 -    unsigned long flags;
   28.78 -
   28.79 -    spin_lock_irqsave(&lock, flags);
   28.80 -
   28.81 -    if ( unlikely(port & PORT_DISCONNECT) )
   28.82 +    if ( likely(!exception) )
   28.83      {
   28.84 -        clear_bit(p, &disc_outstanding[0]);
   28.85 -        clear_bit(p, &HYPERVISOR_shared_info->event_channel_disc[0]);
   28.86 +        clear_evtchn(port);
   28.87 +        set_bit(port, &pend_nrm[0]);
   28.88 +        port_subtype = PORT_NORMAL;
   28.89      }
   28.90      else
   28.91      {
   28.92 -        clear_bit(p, &pend_outstanding[0]);
   28.93 -        clear_bit(p, &HYPERVISOR_shared_info->event_channel_pend[0]);
   28.94 +        clear_evtchn_exception(port);
   28.95 +        set_bit(port, &pend_exc[0]);
   28.96 +        port_subtype = PORT_EXCEPTION;
   28.97      }
   28.98  
   28.99 -    spin_unlock_irqrestore(&lock, flags);
  28.100 -}
  28.101 -
  28.102 -static inline void process_bitmask(u32 *sel, 
  28.103 -                                   u32 *mask,
  28.104 -                                   u32 *outstanding,
  28.105 -                                   unsigned int port_subtype)
  28.106 -{
  28.107 -    unsigned long l1, l2;
  28.108 -    unsigned int  l1_idx, l2_idx, port;
  28.109 -
  28.110 -    l1 = xchg(sel, 0);
  28.111 -    while ( (l1_idx = ffs(l1)) != 0 )
  28.112 +    if ( ring != NULL )
  28.113      {
  28.114 -        l1_idx--;
  28.115 -        l1 &= ~(1 << l1_idx);
  28.116 -
  28.117 -        l2 = mask[l1_idx] & ~outstanding[l1_idx];
  28.118 -        outstanding[l1_idx] |= l2;
  28.119 -        while ( (l2_idx = ffs(l2)) != 0 )
  28.120 +        if ( (ring_prod - ring_cons) < RING_SIZE )
  28.121          {
  28.122 -            l2_idx--;
  28.123 -            l2 &= ~(1 << l2_idx);
  28.124 -
  28.125 -            port = (l1_idx * 32) + l2_idx;
  28.126 -            if ( rx_fns[port] != NULL )
  28.127 -            {
  28.128 -                (*rx_fns[port])(port | port_subtype);
  28.129 -            }
  28.130 -            else if ( ring != NULL )
  28.131 +            ring[RING_MASK(ring_prod)] = (u16)port | port_subtype;
  28.132 +            if ( ring_cons == ring_prod++ )
  28.133              {
  28.134 -                if ( (ring_prod - ring_cons) < RING_SIZE )
  28.135 -                {
  28.136 -                    ring[RING_MASK(ring_prod)] = (u16)(port | port_subtype);
  28.137 -                    if ( ring_cons == ring_prod++ )
  28.138 -                    {
  28.139 -                        wake_up_interruptible(&evtchn_wait);
  28.140 -                        kill_fasync(&evtchn_async_queue, SIGIO, POLL_IN);
  28.141 -                    }
  28.142 -                }
  28.143 -                else
  28.144 -                {
  28.145 -                    ring_overflow = 1;
  28.146 -                }
  28.147 +                wake_up_interruptible(&evtchn_wait);
  28.148 +                kill_fasync(&evtchn_async_queue, SIGIO, POLL_IN);
  28.149              }
  28.150          }
  28.151 +        else
  28.152 +        {
  28.153 +            ring_overflow = 1;
  28.154 +        }
  28.155      }
  28.156 -}
  28.157 -
  28.158 -static void evtchn_interrupt(int irq, void *dev_id, struct pt_regs *regs)
  28.159 -{
  28.160 -    shared_info_t *si = HYPERVISOR_shared_info;
  28.161 -    unsigned long flags;
  28.162 -
  28.163 -    spin_lock_irqsave(&lock, flags);
  28.164  
  28.165 -    process_bitmask(&si->event_channel_pend_sel, 
  28.166 -                    &si->event_channel_pend[0],
  28.167 -                    &pend_outstanding[0],
  28.168 -                    PORT_NORMAL);
  28.169 -        
  28.170 -    process_bitmask(&si->event_channel_disc_sel,
  28.171 -                    &si->event_channel_disc[0],
  28.172 -                    &disc_outstanding[0],
  28.173 -                    PORT_DISCONNECT);
  28.174 -        
  28.175 -    spin_unlock_irqrestore(&lock, flags);
  28.176 +    spin_unlock(&lock);
  28.177  }
  28.178  
  28.179  static void __evtchn_reset_buffer_ring(void)
  28.180 @@ -194,20 +100,18 @@ static void __evtchn_reset_buffer_ring(v
  28.181  
  28.182      for ( i = 0; i < 32; i++ )
  28.183      {
  28.184 -        m = pend_outstanding[i];
  28.185 +        m = pend_exc[i];
  28.186          while ( (j = ffs(m)) != 0 )
  28.187          {
  28.188              m &= ~(1 << --j);
  28.189 -            if ( rx_fns[(i * 32) + j] == NULL )
  28.190 -                ring[ring_prod++] = (u16)(((i * 32) + j) | PORT_NORMAL);
  28.191 +            ring[ring_prod++] = (u16)(((i * 32) + j) | PORT_EXCEPTION);
  28.192          }
  28.193  
  28.194 -        m = disc_outstanding[i];
  28.195 +        m = pend_nrm[i];
  28.196          while ( (j = ffs(m)) != 0 )
  28.197          {
  28.198              m &= ~(1 << --j);
  28.199 -            if ( rx_fns[(i * 32) + j] == NULL )
  28.200 -                ring[ring_prod++] = (u16)(((i * 32) + j) | PORT_DISCONNECT);
  28.201 +            ring[ring_prod++] = (u16)(((i * 32) + j) | PORT_NORMAL);
  28.202          }
  28.203      }
  28.204  }
  28.205 @@ -326,8 +230,14 @@ static ssize_t evtchn_write(struct file 
  28.206          goto out;
  28.207      }
  28.208  
  28.209 +    spin_lock_irq(&lock);
  28.210      for ( i = 0; i < (count/2); i++ )
  28.211 -        evtchn_clear_port(kbuf[i]);
  28.212 +    {
  28.213 +        clear_bit(kbuf[i]&PORTIDX_MASK, 
  28.214 +                  (kbuf[i]&PORT_EXCEPTION) ? &pend_exc[0] : &pend_nrm[0]);
  28.215 +        unmask_evtchn(kbuf[i]&PORTIDX_MASK);
  28.216 +    }
  28.217 +    spin_unlock_irq(&lock);
  28.218  
  28.219      rc = count;
  28.220  
  28.221 @@ -455,25 +365,13 @@ static int __init init_module(void)
  28.222      /* (DEVFS) automatically destroy the symlink with its destination. */
  28.223      devfs_auto_unregister(evtchn_miscdev.devfs_handle, symlink_handle);
  28.224  
  28.225 -    err = request_irq(HYPEREVENT_IRQ(_EVENT_EVTCHN),
  28.226 -                      evtchn_interrupt, 0, "evtchn", NULL);
  28.227 -    if ( err != 0 )
  28.228 -    {
  28.229 -        printk(KERN_ALERT "Could not allocate evtchn receive interrupt\n");
  28.230 -        return err;
  28.231 -    }
  28.232 -
  28.233 -    /* Kickstart servicing of notifications. */
  28.234 -    evtchn_interrupt(0, NULL, NULL);
  28.235 -
  28.236 -    printk("Event-channel driver installed.\n");
  28.237 +    printk("Event-channel device installed.\n");
  28.238  
  28.239      return 0;
  28.240  }
  28.241  
  28.242  static void cleanup_module(void)
  28.243  {
  28.244 -    free_irq(HYPEREVENT_IRQ(_EVENT_EVTCHN), NULL);
  28.245      misc_deregister(&evtchn_miscdev);
  28.246  }
  28.247  
    29.1 --- a/xenolinux-2.4.25-sparse/arch/xen/drivers/network/network.c	Thu Mar 25 09:50:46 2004 +0000
    29.2 +++ b/xenolinux-2.4.25-sparse/arch/xen/drivers/network/network.c	Thu Mar 25 11:51:43 2004 +0000
    29.3 @@ -32,6 +32,9 @@ static void network_tx_buf_gc(struct net
    29.4  static void network_alloc_rx_buffers(struct net_device *dev);
    29.5  static void cleanup_module(void);
    29.6  
    29.7 +/* Dynamically-mapped IRQs. */
    29.8 +static int network_irq, debug_irq;
    29.9 +
   29.10  static struct list_head dev_list;
   29.11  
   29.12  struct net_private
   29.13 @@ -545,7 +548,10 @@ static int __init init_module(void)
   29.14      if ( start_info.flags & SIF_INITDOMAIN )
   29.15          (void)register_inetaddr_notifier(&notifier_inetdev);
   29.16  
   29.17 -    err = request_irq(HYPEREVENT_IRQ(_EVENT_NET), network_interrupt, 
   29.18 +    network_irq = bind_virq_to_irq(VIRQ_NET);
   29.19 +    debug_irq   = bind_virq_to_irq(VIRQ_DEBUG);
   29.20 +
   29.21 +    err = request_irq(network_irq, network_interrupt, 
   29.22                        SA_SAMPLE_RANDOM, "network", NULL);
   29.23      if ( err )
   29.24      {
   29.25 @@ -553,7 +559,7 @@ static int __init init_module(void)
   29.26          goto fail;
   29.27      }
   29.28      
   29.29 -    err = request_irq(HYPEREVENT_IRQ(_EVENT_DEBUG), dbg_network_int, 
   29.30 +    err = request_irq(debug_irq, dbg_network_int, 
   29.31                        SA_SHIRQ, "net_dbg", &dbg_network_int);
   29.32      if ( err )
   29.33          printk(KERN_WARNING "Non-fatal error -- no debug interrupt\n");
   29.34 @@ -624,6 +630,12 @@ static void cleanup_module(void)
   29.35  
   29.36      if ( start_info.flags & SIF_INITDOMAIN )
   29.37          (void)unregister_inetaddr_notifier(&notifier_inetdev);
   29.38 +
   29.39 +    free_irq(network_irq, NULL);
   29.40 +    free_irq(debug_irq, NULL);
   29.41 +
   29.42 +    unbind_virq_from_irq(VIRQ_NET);
   29.43 +    unbind_virq_from_irq(VIRQ_DEBUG);
   29.44  }
   29.45  
   29.46  
    30.1 --- a/xenolinux-2.4.25-sparse/arch/xen/drivers/vnetif/vnetif.c	Thu Mar 25 09:50:46 2004 +0000
    30.2 +++ b/xenolinux-2.4.25-sparse/arch/xen/drivers/vnetif/vnetif.c	Thu Mar 25 11:51:43 2004 +0000
    30.3 @@ -32,6 +32,9 @@ static void network_tx_buf_gc(struct net
    30.4  static void network_alloc_rx_buffers(struct net_device *dev);
    30.5  static void cleanup_module(void);
    30.6  
    30.7 +/* Dynamically-mapped IRQs. */
    30.8 +static int network_irq, debug_irq;
    30.9 +
   30.10  static struct list_head dev_list;
   30.11  
   30.12  struct net_private
   30.13 @@ -468,7 +471,10 @@ static int __init init_module(void)
   30.14  
   30.15      INIT_LIST_HEAD(&dev_list);
   30.16  
   30.17 -    err = request_irq(HYPEREVENT_IRQ(_EVENT_NET), network_interrupt, 
   30.18 +    network_irq = bind_virq_to_irq(VIRQ_NET);
   30.19 +    debug_irq   = bind_virq_to_irq(VIRQ_DEBUG);
   30.20 +
   30.21 +    err = request_irq(network_irq, network_interrupt, 
   30.22                        SA_SAMPLE_RANDOM, "network", NULL);
   30.23      if ( err )
   30.24      {
   30.25 @@ -476,7 +482,7 @@ static int __init init_module(void)
   30.26          goto fail;
   30.27      }
   30.28      
   30.29 -    err = request_irq(HYPEREVENT_IRQ(_EVENT_DEBUG), dbg_network_int, 
   30.30 +    err = request_irq(debug_irq, dbg_network_int, 
   30.31                        SA_SHIRQ, "net_dbg", &dbg_network_int);
   30.32      if ( err )
   30.33          printk(KERN_WARNING "Non-fatal error -- no debug interrupt\n");
   30.34 @@ -546,6 +552,12 @@ static void cleanup_module(void)
   30.35          unregister_netdev(dev);
   30.36          kfree(dev);
   30.37      }
   30.38 +
   30.39 +    free_irq(network_irq, NULL);
   30.40 +    free_irq(debug_irq, NULL);
   30.41 +
   30.42 +    unbind_virq_from_irq(VIRQ_NET);
   30.43 +    unbind_virq_from_irq(VIRQ_DEBUG);
   30.44  }
   30.45  
   30.46  
    31.1 --- a/xenolinux-2.4.25-sparse/arch/xen/kernel/Makefile	Thu Mar 25 09:50:46 2004 +0000
    31.2 +++ b/xenolinux-2.4.25-sparse/arch/xen/kernel/Makefile	Thu Mar 25 11:51:43 2004 +0000
    31.3 @@ -10,7 +10,7 @@ export-objs     := i386_ksyms.o
    31.4  
    31.5  obj-y	:= process.o semaphore.o signal.o entry.o traps.o irq.o  \
    31.6  		ptrace.o ioport.o ldt.o setup.o time.o sys_i386.o \
    31.7 -		i386_ksyms.o i387.o hypervisor.o physirq.o pci-dma.o
    31.8 +		i386_ksyms.o i387.o evtchn.o physirq.o pci-dma.o
    31.9  
   31.10  ifdef CONFIG_PCI
   31.11  obj-y	+= pci-i386.o pci-pc.o pci-irq.o
    32.1 --- a/xenolinux-2.4.25-sparse/arch/xen/kernel/entry.S	Thu Mar 25 09:50:46 2004 +0000
    32.2 +++ b/xenolinux-2.4.25-sparse/arch/xen/kernel/entry.S	Thu Mar 25 11:51:43 2004 +0000
    32.3 @@ -68,9 +68,7 @@ IF_MASK		= 0x00000200
    32.4  DF_MASK		= 0x00000400
    32.5  NT_MASK		= 0x00004000
    32.6  
    32.7 -/*
    32.8 - * these are offsets into the task-struct.
    32.9 - */
   32.10 +/* Offsets into task_struct. */
   32.11  state		=  0
   32.12  flags		=  4
   32.13  sigpending	=  8
   32.14 @@ -80,6 +78,10 @@ need_resched	= 20
   32.15  tsk_ptrace	= 24
   32.16  processor	= 52
   32.17  
   32.18 +/* Offsets into shared_info_t. */
   32.19 +#define evtchn_upcall_pending /* 0 */
   32.20 +#define evtchn_upcall_mask       4
   32.21 +
   32.22  ENOSYS = 38
   32.23  
   32.24  
   32.25 @@ -208,14 +210,14 @@ ENTRY(system_call)
   32.26  	movl %eax,EAX(%esp)		# save the return value
   32.27  ENTRY(ret_from_sys_call)
   32.28          movl SYMBOL_NAME(HYPERVISOR_shared_info),%esi
   32.29 -        btrl $EVENTS_MASTER_ENABLE_BIT,4(%esi) # make tests atomic
   32.30 +        btsl $0,evtchn_upcall_mask(%esi) # make tests atomic
   32.31  ret_syscall_tests:
   32.32  	cmpl $0,need_resched(%ebx)
   32.33  	jne reschedule
   32.34  	cmpl $0,sigpending(%ebx)
   32.35  	je   safesti                    # ensure need_resched updates are seen
   32.36  signal_return:
   32.37 -	btsl $EVENTS_MASTER_ENABLE_BIT,4(%esi) # reenable event callbacks
   32.38 +	btrl $0,evtchn_upcall_mask(%esi) # reenable event callbacks
   32.39  	movl %esp,%eax
   32.40  	xorl %edx,%edx
   32.41  	call SYMBOL_NAME(do_signal)
   32.42 @@ -252,7 +254,7 @@ ret_from_exception:
   32.43  
   32.44  	ALIGN
   32.45  reschedule:
   32.46 -        btsl $EVENTS_MASTER_ENABLE_BIT,4(%esi) # reenable event callbacks
   32.47 +        btrl $0,evtchn_upcall_mask(%esi)       # reenable event callbacks
   32.48  	call SYMBOL_NAME(schedule)             # test
   32.49  	jmp ret_from_sys_call
   32.50  
   32.51 @@ -309,18 +311,18 @@ ENTRY(hypervisor_callback)
   32.52          cmpl $ecrit,%eax
   32.53          jb   critical_region_fixup
   32.54  11:     push %esp
   32.55 -        call do_hypervisor_callback
   32.56 +        call evtchn_do_upcall
   32.57          add  $4,%esp
   32.58          movl SYMBOL_NAME(HYPERVISOR_shared_info),%esi
   32.59          movb CS(%esp),%cl
   32.60  	test $2,%cl          # slow return to ring 2 or 3
   32.61  	jne  ret_syscall_tests
   32.62 -safesti:btsl $EVENTS_MASTER_ENABLE_BIT,4(%esi) # reenable event callbacks
   32.63 +safesti:btrl $0,evtchn_upcall_mask(%esi) # reenable event callbacks
   32.64  scrit:  /**** START OF CRITICAL REGION ****/
   32.65 -        cmpl $0,(%esi)
   32.66 -        jne  14f              # process more events if necessary...
   32.67 +        testb $1,evtchn_upcall_pending(%esi)
   32.68 +        jnz  14f              # process more events if necessary...
   32.69          RESTORE_ALL
   32.70 -14:     btrl $EVENTS_MASTER_ENABLE_BIT,4(%esi)
   32.71 +14:     btsl $0,evtchn_upcall_mask(%esi)
   32.72          jmp  11b
   32.73  ecrit:  /**** END OF CRITICAL REGION ****/
   32.74  # [How we do the fixup]. We want to merge the current stack frame with the
   32.75 @@ -349,8 +351,8 @@ 16:     movl %edi,%esp        # final %e
   32.76          jmp  11b
   32.77          
   32.78  critical_fixup_table:        
   32.79 -        .byte 0x00,0x00,0x00                  # cmpl $0,(%esi)
   32.80 -        .byte 0x00,0x00                       # jne  14f
   32.81 +        .byte 0x00,0x00,0x00                  # testb $1,(%esi)
   32.82 +        .byte 0x00,0x00                       # jnz  14f
   32.83          .byte 0x00                            # pop  %ebx
   32.84          .byte 0x04                            # pop  %ecx
   32.85          .byte 0x08                            # pop  %edx
   32.86 @@ -362,7 +364,7 @@ critical_fixup_table:
   32.87          .byte 0x20                            # pop  %es
   32.88          .byte 0x24,0x24,0x24                  # add  $4,%esp
   32.89          .byte 0x28                            # iret
   32.90 -        .byte 0x00,0x00,0x00,0x00,0x00        # btrl $31,4(%esi)
   32.91 +        .byte 0x00,0x00,0x00,0x00,0x00        # btsl $0,4(%esi)
   32.92          .byte 0x00,0x00                       # jmp  11b
   32.93  
   32.94  # Hypervisor uses this for application faults while it executes.
    33.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    33.2 +++ b/xenolinux-2.4.25-sparse/arch/xen/kernel/evtchn.c	Thu Mar 25 11:51:43 2004 +0000
    33.3 @@ -0,0 +1,317 @@
    33.4 +/******************************************************************************
    33.5 + * evtchn.c
    33.6 + * 
    33.7 + * Communication via Xen event channels.
    33.8 + * 
    33.9 + * Copyright (c) 2002-2004, K A Fraser
   33.10 + */
   33.11 +
   33.12 +#include <linux/config.h>
   33.13 +#include <linux/irq.h>
   33.14 +#include <linux/interrupt.h>
   33.15 +#include <linux/sched.h>
   33.16 +#include <linux/kernel_stat.h>
   33.17 +#include <asm/atomic.h>
   33.18 +#include <asm/system.h>
   33.19 +#include <asm/ptrace.h>
   33.20 +#include <asm/hypervisor.h>
   33.21 +#include <asm/hypervisor-ifs/event_channel.h>
   33.22 +
   33.23 +/* Dynamic IRQ <-> event-channel mappings. */
   33.24 +static int evtchn_to_dynirq[1024];
   33.25 +static int dynirq_to_evtchn[NR_IRQS];
   33.26 +
   33.27 +/* Dynamic IRQ <-> VIRQ mapping. */
   33.28 +static int virq_to_dynirq[NR_VIRQS];
   33.29 +
   33.30 +/*
   33.31 + * Reference counts for bindings to dynamic IRQs.
   33.32 + * NB. This array is referenced with respect to DYNIRQ_BASE!
   33.33 + */
   33.34 +static int dynirq_bindcount[NR_DYNIRQS];
   33.35 +static spinlock_t dynirq_lock;
   33.36 +
   33.37 +/* Upcall to generic IRQ layer. */
   33.38 +extern asmlinkage unsigned int do_IRQ(int irq, struct pt_regs *regs);
   33.39 +
   33.40 +static void evtchn_handle_normal(shared_info_t *s, struct pt_regs *regs)
   33.41 +{
   33.42 +    unsigned long l1, l2;
   33.43 +    unsigned int  l1i, l2i, port;
   33.44 +    int           dynirq;
   33.45 +
   33.46 +    l1 = xchg(&s->evtchn_pending_sel, 0);
   33.47 +    while ( (l1i = ffs(l1)) != 0 )
   33.48 +    {
   33.49 +        l1i--;
   33.50 +        l1 &= ~(1 << l1i);
   33.51 +        
   33.52 +        l2 = s->evtchn_pending[l1i] & ~s->evtchn_mask[l1i];
   33.53 +        while ( (l2i = ffs(l2)) != 0 )
   33.54 +        {
   33.55 +            l2i--;
   33.56 +            l2 &= ~(1 << l2i);
   33.57 +            
   33.58 +            port = (l1i << 5) + l2i;
   33.59 +            if ( (dynirq = evtchn_to_dynirq[port]) != -1 )
   33.60 +                do_IRQ(dynirq + DYNIRQ_BASE, regs);
   33.61 +            else
   33.62 +                evtchn_device_upcall(port, 0);
   33.63 +        }
   33.64 +    }
   33.65 +}
   33.66 +
   33.67 +static void evtchn_handle_exceptions(shared_info_t *s, struct pt_regs *regs)
   33.68 +{
   33.69 +    unsigned long l1, l2;
   33.70 +    unsigned int  l1i, l2i, port;
   33.71 +    int           dynirq;
   33.72 +
   33.73 +    l1 = xchg(&s->evtchn_exception_sel, 0);
   33.74 +    while ( (l1i = ffs(l1)) != 0 )
   33.75 +    {
   33.76 +        l1i--;
   33.77 +        l1 &= ~(1 << l1i);
   33.78 +        
   33.79 +        l2 = s->evtchn_exception[l1i] & ~s->evtchn_mask[l1i];
   33.80 +        while ( (l2i = ffs(l2)) != 0 )
   33.81 +        {
   33.82 +            l2i--;
   33.83 +            l2 &= ~(1 << l2i);
   33.84 +            
   33.85 +            port = (l1i << 5) + l2i;
   33.86 +            if ( (dynirq = evtchn_to_dynirq[port]) != -1 )
   33.87 +            {
   33.88 +                printk(KERN_ALERT "Error on IRQ line %d!\n", 
   33.89 +                       dynirq + DYNIRQ_BASE);
   33.90 +                clear_bit(port, &s->evtchn_exception[0]);
   33.91 +            }
   33.92 +            else
   33.93 +                evtchn_device_upcall(port, 1);
   33.94 +        }
   33.95 +    }
   33.96 +}
   33.97 +
   33.98 +void evtchn_do_upcall(struct pt_regs *regs)
   33.99 +{
  33.100 +    unsigned long flags;
  33.101 +    shared_info_t *s = HYPERVISOR_shared_info;
  33.102 +
  33.103 +    local_irq_save(flags);
  33.104 +    
  33.105 +    while ( test_and_clear_bit(0, &s->evtchn_upcall_pending) )
  33.106 +    {
  33.107 +        if ( s->evtchn_pending_sel != 0 )
  33.108 +            evtchn_handle_normal(s, regs);
  33.109 +        if ( s->evtchn_exception_sel != 0 )
  33.110 +            evtchn_handle_exceptions(s, regs);
  33.111 +    }
  33.112 +
  33.113 +    local_irq_restore(flags);
  33.114 +}
  33.115 +
  33.116 +
  33.117 +static int find_unbound_dynirq(void)
  33.118 +{
  33.119 +    int i;
  33.120 +
  33.121 +    for ( i = 0; i < NR_DYNIRQS; i++ )
  33.122 +        if ( dynirq_bindcount[i] == 0 )
  33.123 +            break;
  33.124 +
  33.125 +    if ( i == NR_DYNIRQS )
  33.126 +        BUG();
  33.127 +
  33.128 +    return i;
  33.129 +}
  33.130 +
  33.131 +int bind_virq_to_irq(int virq)
  33.132 +{
  33.133 +    evtchn_op_t op;
  33.134 +    int evtchn, dynirq;
  33.135 +
  33.136 +    spin_lock(&dynirq_lock);
  33.137 +
  33.138 +    if ( (dynirq = virq_to_dynirq[virq]) == -1 )
  33.139 +    {
  33.140 +        op.cmd              = EVTCHNOP_bind_virq;
  33.141 +        op.u.bind_virq.virq = virq;
  33.142 +        if ( HYPERVISOR_event_channel_op(&op) != 0 )
  33.143 +            BUG();
  33.144 +        evtchn = op.u.bind_virq.port;
  33.145 +
  33.146 +        dynirq = find_unbound_dynirq();
  33.147 +        evtchn_to_dynirq[evtchn] = dynirq;
  33.148 +        dynirq_to_evtchn[dynirq] = evtchn;
  33.149 +
  33.150 +        virq_to_dynirq[virq] = dynirq;
  33.151 +    }
  33.152 +
  33.153 +    dynirq_bindcount[dynirq]++;
  33.154 +
  33.155 +    spin_unlock(&dynirq_lock);
  33.156 +    
  33.157 +    return dynirq + DYNIRQ_BASE;
  33.158 +}
  33.159 +
  33.160 +void unbind_virq_from_irq(int virq)
  33.161 +{
  33.162 +    evtchn_op_t op;
  33.163 +    int dynirq = virq_to_dynirq[virq];
  33.164 +    int evtchn = dynirq_to_evtchn[dynirq];
  33.165 +
  33.166 +    spin_lock(&dynirq_lock);
  33.167 +
  33.168 +    if ( --dynirq_bindcount[dynirq] == 0 )
  33.169 +    {
  33.170 +        op.cmd          = EVTCHNOP_close;
  33.171 +        op.u.close.dom  = DOMID_SELF;
  33.172 +        op.u.close.port = evtchn;
  33.173 +        if ( HYPERVISOR_event_channel_op(&op) != 0 )
  33.174 +            BUG();
  33.175 +
  33.176 +        evtchn_to_dynirq[evtchn] = -1;
  33.177 +        dynirq_to_evtchn[dynirq] = -1;
  33.178 +        virq_to_dynirq[virq]     = -1;
  33.179 +    }
  33.180 +
  33.181 +    spin_unlock(&dynirq_lock);
  33.182 +}
  33.183 +
  33.184 +int bind_evtchn_to_irq(int evtchn)
  33.185 +{
  33.186 +    int dynirq;
  33.187 +
  33.188 +    spin_lock(&dynirq_lock);
  33.189 +
  33.190 +    if ( (dynirq = evtchn_to_dynirq[evtchn]) == -1 )
  33.191 +    {
  33.192 +        dynirq = find_unbound_dynirq();
  33.193 +        evtchn_to_dynirq[evtchn] = dynirq;
  33.194 +        dynirq_to_evtchn[dynirq] = evtchn;
  33.195 +    }
  33.196 +
  33.197 +    dynirq_bindcount[dynirq]++;
  33.198 +
  33.199 +    spin_unlock(&dynirq_lock);
  33.200 +    
  33.201 +    return dynirq + DYNIRQ_BASE;
  33.202 +}
  33.203 +
  33.204 +void unbind_evtchn_from_irq(int evtchn)
  33.205 +{
  33.206 +    int dynirq = evtchn_to_dynirq[evtchn];
  33.207 +
  33.208 +    spin_lock(&dynirq_lock);
  33.209 +
  33.210 +    if ( --dynirq_bindcount[dynirq] == 0 )
  33.211 +    {
  33.212 +        evtchn_to_dynirq[evtchn] = -1;
  33.213 +        dynirq_to_evtchn[dynirq] = -1;
  33.214 +    }
  33.215 +
  33.216 +    spin_unlock(&dynirq_lock);
  33.217 +}
  33.218 +
  33.219 +
  33.220 +/*
  33.221 + * Interface to generic handling in irq.c
  33.222 + */
  33.223 +
  33.224 +static unsigned int startup_dynirq(unsigned int irq)
  33.225 +{
  33.226 +    int dynirq = irq - DYNIRQ_BASE;
  33.227 +    unmask_evtchn(dynirq_to_evtchn[dynirq]);
  33.228 +    return 0;
  33.229 +}
  33.230 +
  33.231 +static void shutdown_dynirq(unsigned int irq)
  33.232 +{
  33.233 +    int dynirq = irq - DYNIRQ_BASE;
  33.234 +    mask_evtchn(dynirq_to_evtchn[dynirq]);
  33.235 +}
  33.236 +
  33.237 +static void enable_dynirq(unsigned int irq)
  33.238 +{
  33.239 +    int dynirq = irq - DYNIRQ_BASE;
  33.240 +    unmask_evtchn(dynirq_to_evtchn[dynirq]);
  33.241 +}
  33.242 +
  33.243 +static void disable_dynirq(unsigned int irq)
  33.244 +{
  33.245 +    int dynirq = irq - DYNIRQ_BASE;
  33.246 +    mask_evtchn(dynirq_to_evtchn[dynirq]);
  33.247 +}
  33.248 +
  33.249 +static void ack_dynirq(unsigned int irq)
  33.250 +{
  33.251 +    int dynirq = irq - DYNIRQ_BASE;
  33.252 +    mask_evtchn(dynirq_to_evtchn[dynirq]);
  33.253 +    clear_evtchn(dynirq_to_evtchn[dynirq]);
  33.254 +}
  33.255 +
  33.256 +static void end_dynirq(unsigned int irq)
  33.257 +{
  33.258 +    int dynirq = irq - DYNIRQ_BASE;
  33.259 +    if ( !(irq_desc[irq].status & IRQ_DISABLED) )
  33.260 +        unmask_evtchn(dynirq_to_evtchn[dynirq]);
  33.261 +}
  33.262 +
  33.263 +static struct hw_interrupt_type dynirq_type = {
  33.264 +    "Dynamic-irq",
  33.265 +    startup_dynirq,
  33.266 +    shutdown_dynirq,
  33.267 +    enable_dynirq,
  33.268 +    disable_dynirq,
  33.269 +    ack_dynirq,
  33.270 +    end_dynirq,
  33.271 +    NULL
  33.272 +};
  33.273 +
  33.274 +static void error_interrupt(int irq, void *dev_id, struct pt_regs *regs)
  33.275 +{
  33.276 +    printk(KERN_ALERT "unexpected VIRQ_ERROR trap to vector %d\n", irq);
  33.277 +}
  33.278 +
  33.279 +static struct irqaction error_action = {
  33.280 +    error_interrupt, 
  33.281 +    SA_INTERRUPT, 
  33.282 +    0, 
  33.283 +    "error", 
  33.284 +    NULL, 
  33.285 +    NULL
  33.286 +};
  33.287 +
  33.288 +void __init init_IRQ(void)
  33.289 +{
  33.290 +    int i;
  33.291 +
  33.292 +    for ( i = 0; i < NR_VIRQS; i++ )
  33.293 +        virq_to_dynirq[i] = -1;
  33.294 +
  33.295 +    for ( i = 0; i < 1024; i++ )
  33.296 +        evtchn_to_dynirq[i] = -1;
  33.297 +
  33.298 +    for ( i = 0; i < NR_DYNIRQS; i++ )
  33.299 +    {
  33.300 +        dynirq_to_evtchn[i] = -1;
  33.301 +        dynirq_bindcount[i] = 0;
  33.302 +    }
  33.303 +
  33.304 +    spin_lock_init(&dynirq_lock);
  33.305 +
  33.306 +    for ( i = 0; i < NR_DYNIRQS; i++ )
  33.307 +    {
  33.308 +        irq_desc[i + DYNIRQ_BASE].status  = IRQ_DISABLED;
  33.309 +        irq_desc[i + DYNIRQ_BASE].action  = 0;
  33.310 +        irq_desc[i + DYNIRQ_BASE].depth   = 1;
  33.311 +        irq_desc[i + DYNIRQ_BASE].handler = &dynirq_type;
  33.312 +    }
  33.313 +
  33.314 +    (void)setup_irq(bind_virq_to_irq(VIRQ_ERROR), &error_action);
  33.315 +    
  33.316 +#ifdef CONFIG_PCI
  33.317 +    /* Also initialise the physical IRQ handlers. */
  33.318 +    physirq_init();
  33.319 +#endif
  33.320 +}
    34.1 --- a/xenolinux-2.4.25-sparse/arch/xen/kernel/hypervisor.c	Thu Mar 25 09:50:46 2004 +0000
    34.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    34.3 @@ -1,170 +0,0 @@
    34.4 -/******************************************************************************
    34.5 - * hypervisor.c
    34.6 - * 
    34.7 - * Communication to/from hypervisor.
    34.8 - * 
    34.9 - * Copyright (c) 2002, K A Fraser
   34.10 - */
   34.11 -
   34.12 -#include <linux/config.h>
   34.13 -#include <linux/irq.h>
   34.14 -#include <linux/kernel_stat.h>
   34.15 -#include <asm/atomic.h>
   34.16 -#include <asm/hypervisor.h>
   34.17 -#include <asm/system.h>
   34.18 -#include <asm/ptrace.h>
   34.19 -
   34.20 -multicall_entry_t multicall_list[8];
   34.21 -int nr_multicall_ents = 0;
   34.22 -
   34.23 -static unsigned long event_mask = 0;
   34.24 -
   34.25 -asmlinkage unsigned int do_physirq(int irq, struct pt_regs *regs)
   34.26 -{
   34.27 -    int cpu = smp_processor_id();
   34.28 -    unsigned long irqs;
   34.29 -    shared_info_t *shared = HYPERVISOR_shared_info;
   34.30 -
   34.31 -    /* do this manually */
   34.32 -    kstat.irqs[cpu][irq]++;
   34.33 -    ack_hypervisor_event(irq);
   34.34 -
   34.35 -    barrier();
   34.36 -    irqs  = xchg(&shared->physirq_pend, 0);
   34.37 -
   34.38 -    __asm__ __volatile__ (
   34.39 -        "   push %1                            ;"
   34.40 -        "   sub  $4,%%esp                      ;"
   34.41 -        "   jmp  3f                            ;"
   34.42 -        "1: btrl %%eax,%0                      ;" /* clear bit     */
   34.43 -        "   mov  %%eax,(%%esp)                 ;"
   34.44 -        "   call do_IRQ                        ;" /* do_IRQ(event) */
   34.45 -        "3: bsfl %0,%%eax                      ;" /* %eax == bit # */
   34.46 -        "   jnz  1b                            ;"
   34.47 -        "   add  $8,%%esp                      ;"
   34.48 -        /* we use %ebx because it is callee-saved */
   34.49 -        : : "b" (irqs), "r" (regs)
   34.50 -        /* clobbered by callback function calls */
   34.51 -        : "eax", "ecx", "edx", "memory" ); 
   34.52 -
   34.53 -    /* do this manually */
   34.54 -    end_hypervisor_event(irq);
   34.55 -
   34.56 -    return 0;
   34.57 -}
   34.58 -
   34.59 -void do_hypervisor_callback(struct pt_regs *regs)
   34.60 -{
   34.61 -    unsigned long events, flags;
   34.62 -    shared_info_t *shared = HYPERVISOR_shared_info;
   34.63 -
   34.64 -    do {
   34.65 -        /* Specialised local_irq_save(). */
   34.66 -        flags = test_and_clear_bit(EVENTS_MASTER_ENABLE_BIT, 
   34.67 -                                   &shared->events_mask);
   34.68 -        barrier();
   34.69 -
   34.70 -        events  = xchg(&shared->events, 0);
   34.71 -        events &= event_mask;
   34.72 -
   34.73 -        if ( (events & EVENT_PHYSIRQ) != 0 )
   34.74 -        {
   34.75 -            do_physirq(_EVENT_PHYSIRQ, regs);
   34.76 -            events &= ~EVENT_PHYSIRQ;
   34.77 -        }
   34.78 -
   34.79 -        __asm__ __volatile__ (
   34.80 -            "   push %1                            ;"
   34.81 -            "   sub  $4,%%esp                      ;"
   34.82 -            "   jmp  2f                            ;"
   34.83 -            "1: btrl %%eax,%0                      ;" /* clear bit     */
   34.84 -            "   add  %2,%%eax                      ;"
   34.85 -            "   mov  %%eax,(%%esp)                 ;"
   34.86 -            "   call do_IRQ                        ;" /* do_IRQ(event) */
   34.87 -            "2: bsfl %0,%%eax                      ;" /* %eax == bit # */
   34.88 -            "   jnz  1b                            ;"
   34.89 -            "   add  $8,%%esp                      ;"
   34.90 -            /* we use %ebx because it is callee-saved */
   34.91 -            : : "b" (events), "r" (regs), "i" (HYPEREVENT_IRQ_BASE)
   34.92 -            /* clobbered by callback function calls */
   34.93 -            : "eax", "ecx", "edx", "memory" ); 
   34.94 -
   34.95 -        /* Specialised local_irq_restore(). */
   34.96 -        if ( flags ) set_bit(EVENTS_MASTER_ENABLE_BIT, &shared->events_mask);
   34.97 -        barrier();
   34.98 -    }
   34.99 -    while ( shared->events );
  34.100 -}
  34.101 -
  34.102 -/*
  34.103 - * Define interface to generic handling in irq.c
  34.104 - */
  34.105 -
  34.106 -static void shutdown_hypervisor_event(unsigned int irq)
  34.107 -{
  34.108 -    clear_bit(HYPEREVENT_FROM_IRQ(irq), &event_mask);
  34.109 -    clear_bit(HYPEREVENT_FROM_IRQ(irq), &HYPERVISOR_shared_info->events_mask);
  34.110 -}
  34.111 -
  34.112 -static void enable_hypervisor_event(unsigned int irq)
  34.113 -{
  34.114 -    set_bit(HYPEREVENT_FROM_IRQ(irq), &event_mask);
  34.115 -    set_bit(HYPEREVENT_FROM_IRQ(irq), &HYPERVISOR_shared_info->events_mask);
  34.116 -    if ( test_bit(EVENTS_MASTER_ENABLE_BIT,
  34.117 -                  &HYPERVISOR_shared_info->events_mask) )
  34.118 -        do_hypervisor_callback(NULL);
  34.119 -}
  34.120 -
  34.121 -static void disable_hypervisor_event(unsigned int irq)
  34.122 -{
  34.123 -    clear_bit(HYPEREVENT_FROM_IRQ(irq), &event_mask);
  34.124 -    clear_bit(HYPEREVENT_FROM_IRQ(irq), &HYPERVISOR_shared_info->events_mask);
  34.125 -}
  34.126 -
  34.127 -static void ack_hypervisor_event(unsigned int irq)
  34.128 -{
  34.129 -    int ev = HYPEREVENT_FROM_IRQ(irq);
  34.130 -    if ( !(event_mask & (1<<ev)) )
  34.131 -    {
  34.132 -        printk("Unexpected hypervisor event %d\n", ev);
  34.133 -        atomic_inc(&irq_err_count);
  34.134 -    }
  34.135 -    set_bit(ev, &HYPERVISOR_shared_info->events_mask);
  34.136 -}
  34.137 -
  34.138 -static unsigned int startup_hypervisor_event(unsigned int irq)
  34.139 -{
  34.140 -    enable_hypervisor_event(irq);
  34.141 -    return 0;
  34.142 -}
  34.143 -
  34.144 -static void end_hypervisor_event(unsigned int irq)
  34.145 -{
  34.146 -}
  34.147 -
  34.148 -static struct hw_interrupt_type hypervisor_irq_type = {
  34.149 -    "Hypervisor-event",
  34.150 -    startup_hypervisor_event,
  34.151 -    shutdown_hypervisor_event,
  34.152 -    enable_hypervisor_event,
  34.153 -    disable_hypervisor_event,
  34.154 -    ack_hypervisor_event,
  34.155 -    end_hypervisor_event,
  34.156 -    NULL
  34.157 -};
  34.158 -
  34.159 -void __init init_IRQ(void)
  34.160 -{
  34.161 -    int i;
  34.162 -
  34.163 -    for ( i = 0; i < NR_HYPEREVENT_IRQS; i++ )
  34.164 -    {
  34.165 -        irq_desc[i + HYPEREVENT_IRQ_BASE].status  = IRQ_DISABLED;
  34.166 -        irq_desc[i + HYPEREVENT_IRQ_BASE].action  = 0;
  34.167 -        irq_desc[i + HYPEREVENT_IRQ_BASE].depth   = 1;
  34.168 -        irq_desc[i + HYPEREVENT_IRQ_BASE].handler = &hypervisor_irq_type;
  34.169 -    }
  34.170 -
  34.171 -    /* Also initialise the physical IRQ handlers. */
  34.172 -    physirq_init();
  34.173 -}
    35.1 --- a/xenolinux-2.4.25-sparse/arch/xen/kernel/i386_ksyms.c	Thu Mar 25 09:50:46 2004 +0000
    35.2 +++ b/xenolinux-2.4.25-sparse/arch/xen/kernel/i386_ksyms.c	Thu Mar 25 11:51:43 2004 +0000
    35.3 @@ -171,5 +171,5 @@ EXPORT_SYMBOL(xquad_portio);
    35.4  EXPORT_SYMBOL(create_xen_proc_entry);
    35.5  EXPORT_SYMBOL(remove_xen_proc_entry);
    35.6  
    35.7 -EXPORT_SYMBOL(do_hypervisor_callback);
    35.8 +EXPORT_SYMBOL(evtchn_do_upcall);
    35.9  EXPORT_SYMBOL(HYPERVISOR_shared_info);
    36.1 --- a/xenolinux-2.4.25-sparse/arch/xen/kernel/physirq.c	Thu Mar 25 09:50:46 2004 +0000
    36.2 +++ b/xenolinux-2.4.25-sparse/arch/xen/kernel/physirq.c	Thu Mar 25 11:51:43 2004 +0000
    36.3 @@ -13,6 +13,7 @@
    36.4   *              by the virq irq type.
    36.5   */
    36.6  
    36.7 +#ifdef CONFIG_PCI
    36.8  
    36.9  #include <linux/config.h>
   36.10  #include <asm/atomic.h>
   36.11 @@ -46,7 +47,7 @@ static unsigned int startup_physirq_even
   36.12      {
   36.13          printk("startup_physirq_event %d: setup event handler\n", irq);
   36.14          /* set up a event handler to demux virtualised physical interrupts */
   36.15 -        err = request_irq(HYPEREVENT_IRQ(_EVENT_PHYSIRQ), physirq_interrupt, 
   36.16 +        err = request_irq(IRQ_FROM_XEN_VIRQ(VIRQ_PHYSIRQ), physirq_interrupt, 
   36.17                            SA_SAMPLE_RANDOM, "physirq", NULL);
   36.18          if ( err )
   36.19          {
   36.20 @@ -106,13 +107,13 @@ static void shutdown_physirq_event(unsig
   36.21  static void enable_physirq_event(unsigned int irq)
   36.22  {
   36.23      /* XXX just enable all phys interrupts for now */
   36.24 -    enable_irq(HYPEREVENT_IRQ(_EVENT_PHYSIRQ));
   36.25 +    enable_irq(IRQ_FROM_XEN_VIRQ(VIRQ_PHYSIRQ));
   36.26  }
   36.27  
   36.28  static void disable_physirq_event(unsigned int irq)
   36.29  {
   36.30      /* XXX just disable all phys interrupts for now */
   36.31 -    disable_irq(HYPEREVENT_IRQ(_EVENT_PHYSIRQ));
   36.32 +    disable_irq(IRQ_FROM_XEN_VIRQ(VIRQ_PHYSIRQ));
   36.33  }
   36.34  
   36.35  static void ack_physirq_event(unsigned int irq)
   36.36 @@ -170,3 +171,5 @@ void __init physirq_init(void)
   36.37          irq_desc[i + PHYS_IRQ_BASE].handler = &physirq_irq_type;
   36.38      }
   36.39  }
   36.40 +
   36.41 +#endif
    37.1 --- a/xenolinux-2.4.25-sparse/arch/xen/kernel/setup.c	Thu Mar 25 09:50:46 2004 +0000
    37.2 +++ b/xenolinux-2.4.25-sparse/arch/xen/kernel/setup.c	Thu Mar 25 11:51:43 2004 +0000
    37.3 @@ -58,6 +58,9 @@ shared_info_t *HYPERVISOR_shared_info = 
    37.4  
    37.5  unsigned long *phys_to_machine_mapping;
    37.6  
    37.7 +multicall_entry_t multicall_list[8];
    37.8 +int nr_multicall_ents = 0;
    37.9 +
   37.10  /*
   37.11   * Machine setup..
   37.12   */
   37.13 @@ -860,7 +863,8 @@ void __init identify_cpu(struct cpuinfo_
   37.14          break;
   37.15          
   37.16      default:
   37.17 -        printk("Unsupported CPU vendor (%d) -- please report!\n");
   37.18 +        printk("Unsupported CPU vendor (%d) -- please report!\n",
   37.19 +               c->x86_vendor);
   37.20      }
   37.21  	
   37.22      printk(KERN_DEBUG "CPU: After vendor init, caps: %08x %08x %08x %08x\n",
   37.23 @@ -1116,7 +1120,10 @@ void __init cpu_init (void)
   37.24   * Time-to-die callback handling.
   37.25   */
   37.26  
   37.27 -static void die_irq(int irq, void *unused, struct pt_regs *regs)
   37.28 +/* Dynamically-mapped IRQ. */
   37.29 +static int die_irq;
   37.30 +
   37.31 +static void die_interrupt(int irq, void *unused, struct pt_regs *regs)
   37.32  {
   37.33      extern void ctrl_alt_del(void);
   37.34      ctrl_alt_del();
   37.35 @@ -1124,7 +1131,8 @@ static void die_irq(int irq, void *unuse
   37.36  
   37.37  static int __init setup_die_event(void)
   37.38  {
   37.39 -    (void)request_irq(HYPEREVENT_IRQ(_EVENT_DIE), die_irq, 0, "die", NULL);
   37.40 +    die_irq = bind_virq_to_irq(VIRQ_DIE);
   37.41 +    (void)request_irq(die_irq, die_interrupt, 0, "die", NULL);
   37.42      return 0;
   37.43  }
   37.44  
   37.45 @@ -1241,7 +1249,10 @@ static void stop_task(void *unused)
   37.46  
   37.47  static struct tq_struct stop_tq;
   37.48  
   37.49 -static void stop_irq(int irq, void *unused, struct pt_regs *regs)
   37.50 +/* Dynamically-mapped IRQ. */
   37.51 +static int stop_irq;
   37.52 +
   37.53 +static void stop_interrupt(int irq, void *unused, struct pt_regs *regs)
   37.54  {
   37.55      stop_tq.routine = stop_task;
   37.56      schedule_task(&stop_tq);
   37.57 @@ -1249,7 +1260,8 @@ static void stop_irq(int irq, void *unus
   37.58  
   37.59  static int __init setup_stop_event(void)
   37.60  {
   37.61 -    (void)request_irq(HYPEREVENT_IRQ(_EVENT_STOP), stop_irq, 0, "stop", NULL);
   37.62 +    stop_irq = bind_virq_to_irq(VIRQ_STOP);
   37.63 +    (void)request_irq(stop_irq, stop_interrupt, 0, "stop", NULL);
   37.64      return 0;
   37.65  }
   37.66  
    38.1 --- a/xenolinux-2.4.25-sparse/arch/xen/kernel/time.c	Thu Mar 25 09:50:46 2004 +0000
    38.2 +++ b/xenolinux-2.4.25-sparse/arch/xen/kernel/time.c	Thu Mar 25 11:51:43 2004 +0000
    38.3 @@ -115,6 +115,8 @@ static u64 processed_system_time;   /* S
    38.4          }                                  \
    38.5      } while ( 0 )
    38.6  
    38.7 +/* Dynamically-mapped IRQs. */
    38.8 +static int time_irq, debug_irq;
    38.9  
   38.10  /* Does this guest OS track Xen time, or set its wall clock independently? */
   38.11  static int independent_wallclock = 0;
   38.12 @@ -623,13 +625,13 @@ void __init time_init(void)
   38.13      __get_time_values_from_xen();
   38.14      processed_system_time = shadow_system_time;
   38.15  
   38.16 -    (void)setup_irq(HYPEREVENT_IRQ(_EVENT_TIMER), &irq_timer);
   38.17 +    time_irq  = bind_virq_to_irq(VIRQ_TIMER);
   38.18 +    debug_irq = bind_virq_to_irq(VIRQ_DEBUG);
   38.19  
   38.20 -    (void)setup_irq(HYPEREVENT_IRQ(_EVENT_DEBUG), &dbg_time);
   38.21 +    (void)setup_irq(time_irq, &irq_timer);
   38.22 +    (void)setup_irq(debug_irq, &dbg_time);
   38.23  
   38.24      rdtscll(alarm);
   38.25 -
   38.26 -    clear_bit(_EVENT_TIMER, &HYPERVISOR_shared_info->events);
   38.27  }
   38.28  
   38.29  
    39.1 --- a/xenolinux-2.4.25-sparse/include/asm-xen/evtchn.h	Thu Mar 25 09:50:46 2004 +0000
    39.2 +++ b/xenolinux-2.4.25-sparse/include/asm-xen/evtchn.h	Thu Mar 25 11:51:43 2004 +0000
    39.3 @@ -1,7 +1,8 @@
    39.4  /******************************************************************************
    39.5   * evtchn.h
    39.6   * 
    39.7 - * Driver for receiving and demuxing event-channel signals.
    39.8 + * Communication via Xen event channels.
    39.9 + * Also definitions for the device that demuxes notifications to userspace.
   39.10   * 
   39.11   * Copyright (c) 2004, K A Fraser
   39.12   */
   39.13 @@ -9,10 +10,81 @@
   39.14  #ifndef __ASM_EVTCHN_H__
   39.15  #define __ASM_EVTCHN_H__
   39.16  
   39.17 -typedef void (*evtchn_receiver_t)(unsigned int);
   39.18 -#define PORT_NORMAL     0x0000
   39.19 -#define PORT_DISCONNECT 0x8000
   39.20 -#define PORTIDX_MASK    0x7fff
   39.21 +#include <linux/config.h>
   39.22 +#include <asm/hypervisor.h>
   39.23 +#include <asm/ptrace.h>
   39.24 +
   39.25 +/*
   39.26 + * LOW-LEVEL DEFINITIONS
   39.27 + */
   39.28 +
   39.29 +/* Entry point for notifications into Linux subsystems. */
   39.30 +void evtchn_do_upcall(struct pt_regs *regs);
   39.31 +
   39.32 +/* Entry point for notifications into the userland character device. */
   39.33 +void evtchn_device_upcall(int port, int exception);
   39.34 +
   39.35 +static inline void mask_evtchn(int port)
   39.36 +{
   39.37 +    shared_info_t *s = HYPERVISOR_shared_info;
   39.38 +    set_bit(port, &s->evtchn_mask[0]);
   39.39 +}
   39.40 +
   39.41 +/*
   39.42 + * I haven't thought too much about the synchronisation in here against
   39.43 + * other CPUs, but all the bit-update operations are reorder barriers on
   39.44 + * x86 so reordering concerns aren't a problem for now. Some mb() calls
   39.45 + * would be required on weaker architectures I think. -- KAF (24/3/2004)
   39.46 + */
   39.47 +static inline void unmask_evtchn(int port)
   39.48 +{
   39.49 +    shared_info_t *s = HYPERVISOR_shared_info;
   39.50 +    int need_upcall = 0;
   39.51 +
   39.52 +    clear_bit(port, &s->evtchn_mask[0]);
   39.53 +
   39.54 +    /*
   39.55 +     * The following is basically the equivalent of 'hw_resend_irq'. Just like
   39.56 +     * a real IO-APIC we 'lose the interrupt edge' if the channel is masked.
   39.57 +     */
   39.58 +
   39.59 +    /* Asserted a standard notification? */
   39.60 +    if (  test_bit        (port,    &s->evtchn_pending[0]) && 
   39.61 +         !test_and_set_bit(port>>5, &s->evtchn_pending_sel) )
   39.62 +        need_upcall = 1;
   39.63 +
   39.64 +    /* Asserted an exceptional notification? */
   39.65 +    if (  test_bit        (port,    &s->evtchn_exception[0]) && 
   39.66 +         !test_and_set_bit(port>>5, &s->evtchn_exception_sel) )
   39.67 +        need_upcall = 1;
   39.68 +
   39.69 +    /* If asserted either type of notification, check the master flags. */
   39.70 +    if ( need_upcall &&
   39.71 +         !test_and_set_bit(0,       &s->evtchn_upcall_pending) &&
   39.72 +         !test_bit        (0,       &s->evtchn_upcall_mask) )
   39.73 +        evtchn_do_upcall(NULL);
   39.74 +}
   39.75 +
   39.76 +static inline void clear_evtchn(int port)
   39.77 +{
   39.78 +    shared_info_t *s = HYPERVISOR_shared_info;
   39.79 +    clear_bit(port, &s->evtchn_pending[0]);
   39.80 +}
   39.81 +
   39.82 +static inline void clear_evtchn_exception(int port)
   39.83 +{
   39.84 +    shared_info_t *s = HYPERVISOR_shared_info;
   39.85 +    clear_bit(port, &s->evtchn_exception[0]);
   39.86 +}
   39.87 +
   39.88 +
   39.89 +/*
   39.90 + * CHARACTER-DEVICE DEFINITIONS
   39.91 + */
   39.92 +
   39.93 +#define PORT_NORMAL    0x0000
   39.94 +#define PORT_EXCEPTION 0x8000
   39.95 +#define PORTIDX_MASK   0x7fff
   39.96  
   39.97  /* /dev/xen/evtchn resides at device number major=10, minor=200 */
   39.98  #define EVTCHN_MINOR 200
   39.99 @@ -21,9 +93,4 @@ typedef void (*evtchn_receiver_t)(unsign
  39.100  /* EVTCHN_RESET: Clear and reinit the event buffer. Clear error condition. */
  39.101  #define EVTCHN_RESET _IO('E', 1)
  39.102  
  39.103 -int evtchn_request_port(unsigned int port, evtchn_receiver_t rx_fn);
  39.104 -int evtchn_free_port(unsigned int port);
  39.105 -void evtchn_clear_port(unsigned int port);
  39.106 -
  39.107 -
  39.108  #endif /* __ASM_EVTCHN_H__ */
    40.1 --- a/xenolinux-2.4.25-sparse/include/asm-xen/hypervisor.h	Thu Mar 25 09:50:46 2004 +0000
    40.2 +++ b/xenolinux-2.4.25-sparse/include/asm-xen/hypervisor.h	Thu Mar 25 11:51:43 2004 +0000
    40.3 @@ -25,10 +25,6 @@ union start_info_union
    40.4  extern union start_info_union start_info_union;
    40.5  #define start_info (start_info_union.start_info)
    40.6  
    40.7 -/* arch/xen/kernel/hypervisor.c */
    40.8 -void do_hypervisor_callback(struct pt_regs *regs);
    40.9 -
   40.10 -
   40.11  /* arch/xen/mm/hypervisor.c */
   40.12  /*
   40.13   * NB. ptr values should be PHYSICAL, not MACHINE. 'vals' should be already
    41.1 --- a/xenolinux-2.4.25-sparse/include/asm-xen/irq.h	Thu Mar 25 09:50:46 2004 +0000
    41.2 +++ b/xenolinux-2.4.25-sparse/include/asm-xen/irq.h	Thu Mar 25 11:51:43 2004 +0000
    41.3 @@ -14,19 +14,32 @@
    41.4  #include <asm/hypervisor.h>
    41.5  #include <asm/ptrace.h>
    41.6  
    41.7 -#define NR_IRQS             256
    41.8 -
    41.9 -#define PHYS_IRQ_BASE         0
   41.10 -#define NR_PHYS_IRQS        128
   41.11 +/*
   41.12 + * The flat IRQ space is divided into two regions:
   41.13 + *  1. A one-to-one mapping of real physical IRQs. This space is only used
   41.14 + *     if we have physical device-access privilege. This region is at the 
   41.15 + *     start of the IRQ space so that existing device drivers do not need
   41.16 + *     to be modified to translate physical IRQ numbers into our IRQ space.
   41.17 + *  3. A dynamic mapping of inter-domain and Xen-sourced virtual IRQs. These
   41.18 + *     are bound using the provided bind/unbind functions.
   41.19 + */
   41.20  
   41.21 -#define HYPEREVENT_IRQ_BASE 128
   41.22 -#define NR_HYPEREVENT_IRQS  128
   41.23 +#define PIRQ_BASE   0
   41.24 +#define NR_PIRQS  128
   41.25  
   41.26 -#define HYPEREVENT_IRQ(_ev)       ((_ev)  + HYPEREVENT_IRQ_BASE)
   41.27 -#define HYPEREVENT_FROM_IRQ(_irq) ((_irq) - HYPEREVENT_IRQ_BASE)
   41.28 +#define DYNIRQ_BASE (PIRQ_BASE + NR_PIRQS)
   41.29 +#define NR_DYNIRQS  128
   41.30 +
   41.31 +#define NR_IRQS   (NR_PIRQS + NR_DYNIRQS)
   41.32  
   41.33  extern void physirq_init(void);
   41.34  
   41.35 +/* Dynamic binding of event channels and VIRQ sources to Linux IRQ space. */
   41.36 +extern int  bind_virq_to_irq(int virq);
   41.37 +extern void unbind_virq_from_irq(int virq);
   41.38 +extern int  bind_evtchn_to_irq(int evtchn);
   41.39 +extern void unbind_evtchn_from_irq(int evtchn);
   41.40 +
   41.41  #define irq_cannonicalize(_irq) (_irq)
   41.42  
   41.43  extern void disable_irq(unsigned int);
    42.1 --- a/xenolinux-2.4.25-sparse/include/asm-xen/keyboard.h	Thu Mar 25 09:50:46 2004 +0000
    42.2 +++ b/xenolinux-2.4.25-sparse/include/asm-xen/keyboard.h	Thu Mar 25 11:51:43 2004 +0000
    42.3 @@ -58,8 +58,11 @@ static inline int xen_kbd_controller_pre
    42.4  /* resource allocation */
    42.5  #define kbd_request_region()     \
    42.6      do { } while (0)
    42.7 -#define kbd_request_irq(handler) \
    42.8 -    request_irq(HYPEREVENT_IRQ(_EVENT_PS2), handler, 0, "ps/2", NULL)
    42.9 +#define kbd_request_irq(handler)                    \
   42.10 +    do {                                            \
   42.11 +        int irq = bind_virq_to_irq(VIRQ_PS2);       \
   42.12 +        request_irq(irq, handler, 0, "ps/2", NULL); \
   42.13 +    } while ( 0 )
   42.14  
   42.15  /* could implement these with command to xen to filter mouse stuff... */
   42.16  #define aux_request_irq(hand, dev_id) 0
    43.1 --- a/xenolinux-2.4.25-sparse/include/asm-xen/system.h	Thu Mar 25 09:50:46 2004 +0000
    43.2 +++ b/xenolinux-2.4.25-sparse/include/asm-xen/system.h	Thu Mar 25 11:51:43 2004 +0000
    43.3 @@ -7,6 +7,7 @@
    43.4  #include <asm/segment.h>
    43.5  #include <asm/hypervisor.h>
    43.6  #include <linux/bitops.h> /* for LOCK_PREFIX */
    43.7 +#include <asm/evtchn.h>
    43.8  
    43.9  #ifdef __KERNEL__
   43.10  
   43.11 @@ -319,29 +320,38 @@ static inline unsigned long __cmpxchg(vo
   43.12  
   43.13  #define set_wmb(var, value) do { var = value; wmb(); } while (0)
   43.14  
   43.15 +/*
   43.16 + * NB. ALl the following routines are SMP-safe on x86, even where they look
   43.17 + * possibly racy. For example, we must ensure that we clear the mask bit and
   43.18 + * /then/ check teh pending bit. But this will happen because the bit-update
   43.19 + * operations are ordering barriers.
   43.20 + * 
   43.21 + * For this reason also, many uses of 'barrier' here are rather anal. But
   43.22 + * they do no harm.
   43.23 + */
   43.24  
   43.25  #define __cli()                                                               \
   43.26  do {                                                                          \
   43.27 -    clear_bit(EVENTS_MASTER_ENABLE_BIT, &HYPERVISOR_shared_info->events_mask);\
   43.28 +    set_bit(0, &HYPERVISOR_shared_info->evtchn_upcall_mask);                  \
   43.29      barrier();                                                                \
   43.30  } while (0)
   43.31  
   43.32  #define __sti()                                                               \
   43.33  do {                                                                          \
   43.34      shared_info_t *_shared = HYPERVISOR_shared_info;                          \
   43.35 -    set_bit(EVENTS_MASTER_ENABLE_BIT, &_shared->events_mask);                 \
   43.36 +    clear_bit(0, &_shared->evtchn_upcall_mask);                               \
   43.37      barrier();                                                                \
   43.38 -    if ( unlikely(_shared->events) ) do_hypervisor_callback(NULL);            \
   43.39 +    if ( unlikely(test_bit(0, &_shared->evtchn_upcall_pending)) )             \
   43.40 +        evtchn_do_upcall(NULL);                                               \
   43.41  } while (0)
   43.42  
   43.43  #define __save_flags(x)                                                       \
   43.44  do {                                                                          \
   43.45 -    (x) = test_bit(EVENTS_MASTER_ENABLE_BIT,                                  \
   43.46 -                   &HYPERVISOR_shared_info->events_mask);                     \
   43.47 +    (x) = test_bit(0, &HYPERVISOR_shared_info->evtchn_upcall_mask);           \
   43.48      barrier();                                                                \
   43.49  } while (0)
   43.50  
   43.51 -#define __restore_flags(x)      do { if (x) __sti(); } while (0)
   43.52 +#define __restore_flags(x)      do { if (x) __cli(); else __sti(); } while (0)
   43.53  
   43.54  #define safe_halt()             ((void)0)
   43.55  
   43.56 @@ -350,8 +360,7 @@ do {                                    
   43.57  
   43.58  #define local_irq_save(x)                                                     \
   43.59  do {                                                                          \
   43.60 -    (x) = test_and_clear_bit(EVENTS_MASTER_ENABLE_BIT,                        \
   43.61 -                             &HYPERVISOR_shared_info->events_mask);           \
   43.62 +    (x) = test_and_set_bit(0, &HYPERVISOR_shared_info->evtchn_upcall_mask);   \
   43.63      barrier();                                                                \
   43.64  } while (0)
   43.65  #define local_irq_restore(x)    __restore_flags(x)