ia64/xen-unstable

view extras/mini-os/events.c @ 17613:addfc2db07a3

minios: clear the event before calling the handler since (especially
in the SMP case) the handler may make another domain send an event
again, and that must not be lost.

Signed-off-by: Samuel Thibault <samuel.thibault@eu.citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Thu May 08 11:53:39 2008 +0100 (2008-05-08)
parents a16f7a9f8ea2
children 2197a263a300
line source
1 /* -*- Mode:C; c-basic-offset:4; tab-width:4 -*-
2 ****************************************************************************
3 * (C) 2003 - Rolf Neugebauer - Intel Research Cambridge
4 * (C) 2005 - Grzegorz Milos - Intel Research Cambridge
5 ****************************************************************************
6 *
7 * File: events.c
8 * Author: Rolf Neugebauer (neugebar@dcs.gla.ac.uk)
9 * Changes: Grzegorz Milos (gm281@cam.ac.uk)
10 *
11 * Date: Jul 2003, changes Jun 2005
12 *
13 * Environment: Xen Minimal OS
14 * Description: Deals with events recieved on event channels
15 *
16 ****************************************************************************
17 */
19 #include <os.h>
20 #include <mm.h>
21 #include <hypervisor.h>
22 #include <events.h>
23 #include <lib.h>
25 #define NR_EVS 1024
27 /* this represents a event handler. Chaining or sharing is not allowed */
28 typedef struct _ev_action_t {
29 evtchn_handler_t handler;
30 void *data;
31 u32 count;
32 } ev_action_t;
34 static ev_action_t ev_actions[NR_EVS];
35 void default_handler(evtchn_port_t port, struct pt_regs *regs, void *data);
37 static unsigned long bound_ports[NR_EVS/(8*sizeof(unsigned long))];
39 void unbind_all_ports(void)
40 {
41 int i;
43 for (i = 0; i < NR_EVS; i++)
44 {
45 if (test_and_clear_bit(i, bound_ports))
46 {
47 struct evtchn_close close;
48 mask_evtchn(i);
49 close.port = i;
50 HYPERVISOR_event_channel_op(EVTCHNOP_close, &close);
51 }
52 }
53 }
55 /*
56 * Demux events to different handlers.
57 */
58 int do_event(evtchn_port_t port, struct pt_regs *regs)
59 {
60 ev_action_t *action;
62 clear_evtchn(port);
64 if (port >= NR_EVS) {
65 printk("Port number too large: %d\n", port);
66 return 1;
67 }
69 action = &ev_actions[port];
70 action->count++;
72 /* call the handler */
73 action->handler(port, regs, action->data);
75 return 1;
77 }
79 evtchn_port_t bind_evtchn(evtchn_port_t port, evtchn_handler_t handler,
80 void *data)
81 {
82 if(ev_actions[port].handler != default_handler)
83 printk("WARN: Handler for port %d already registered, replacing\n",
84 port);
86 ev_actions[port].data = data;
87 wmb();
88 ev_actions[port].handler = handler;
90 return port;
91 }
93 void unbind_evtchn(evtchn_port_t port )
94 {
95 if (ev_actions[port].handler == default_handler)
96 printk("WARN: No handler for port %d when unbinding\n", port);
97 ev_actions[port].handler = default_handler;
98 wmb();
99 ev_actions[port].data = NULL;
100 }
102 evtchn_port_t bind_virq(uint32_t virq, evtchn_handler_t handler, void *data)
103 {
104 evtchn_bind_virq_t op;
106 /* Try to bind the virq to a port */
107 op.virq = virq;
108 op.vcpu = smp_processor_id();
110 if ( HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, &op) != 0 )
111 {
112 printk("Failed to bind virtual IRQ %d\n", virq);
113 return -1;
114 }
115 set_bit(op.port,bound_ports);
116 bind_evtchn(op.port, handler, data);
117 return op.port;
118 }
120 #if defined(__x86_64__)
121 char irqstack[2 * STACK_SIZE];
123 static struct pda
124 {
125 int irqcount; /* offset 0 (used in x86_64.S) */
126 char *irqstackptr; /* 8 */
127 } cpu0_pda;
128 #endif
130 /*
131 * Initially all events are without a handler and disabled
132 */
133 void init_events(void)
134 {
135 int i;
136 #if defined(__x86_64__)
137 asm volatile("movl %0,%%fs ; movl %0,%%gs" :: "r" (0));
138 wrmsrl(0xc0000101, &cpu0_pda); /* 0xc0000101 is MSR_GS_BASE */
139 cpu0_pda.irqcount = -1;
140 cpu0_pda.irqstackptr = (void*) (((unsigned long)irqstack + 2 * STACK_SIZE) & ~(STACK_SIZE - 1));
141 #endif
142 /* initialize event handler */
143 for ( i = 0; i < NR_EVS; i++ )
144 {
145 ev_actions[i].handler = default_handler;
146 mask_evtchn(i);
147 }
148 }
150 void default_handler(evtchn_port_t port, struct pt_regs *regs, void *ignore)
151 {
152 printk("[Port %d] - event received\n", port);
153 }
155 /* Create a port available to the pal for exchanging notifications.
156 Returns the result of the hypervisor call. */
158 /* Unfortunate confusion of terminology: the port is unbound as far
159 as Xen is concerned, but we automatically bind a handler to it
160 from inside mini-os. */
162 int evtchn_alloc_unbound(domid_t pal, evtchn_handler_t handler,
163 void *data, evtchn_port_t *port)
164 {
165 evtchn_alloc_unbound_t op;
166 op.dom = DOMID_SELF;
167 op.remote_dom = pal;
168 int err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &op);
169 if (err)
170 return err;
171 *port = bind_evtchn(op.port, handler, data);
172 return err;
173 }
175 /* Connect to a port so as to allow the exchange of notifications with
176 the pal. Returns the result of the hypervisor call. */
178 int evtchn_bind_interdomain(domid_t pal, evtchn_port_t remote_port,
179 evtchn_handler_t handler, void *data,
180 evtchn_port_t *local_port)
181 {
182 evtchn_bind_interdomain_t op;
183 op.remote_dom = pal;
184 op.remote_port = remote_port;
185 int err = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain, &op);
186 if (err)
187 return err;
188 set_bit(op.local_port,bound_ports);
189 evtchn_port_t port = op.local_port;
190 *local_port = bind_evtchn(port, handler, data);
191 return err;
192 }