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
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
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, ¤t->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, ¤t->shared_info->events_mask); 16.8 + clear_bit(0, ¤t->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(¬ifier_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(¬ifier_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)