direct-io.hg

view extras/mini-os/events.c @ 15481:538c3d8aa4b1

Revert 15471:7ac7f147241405af83e7a9d748cf7b01279734fc

Block-device specifiers in ioemu can contain colons, so skipping
always past the first colon is not a good idea. Better solutions are
in the pipeline to solve the blktap issues.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kfraser@localhost.localdomain
date Fri Jul 06 15:01:20 2007 +0100 (2007-07-06)
parents 27a5a62552c0
children
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;
61 if (port >= NR_EVS) {
62 printk("Port number too large: %d\n", port);
63 goto out;
64 }
66 action = &ev_actions[port];
67 action->count++;
69 /* call the handler */
70 action->handler(port, regs, action->data);
72 out:
73 clear_evtchn(port);
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 /* Finally unmask the port */
91 unmask_evtchn(port);
93 return port;
94 }
96 void unbind_evtchn(evtchn_port_t port )
97 {
98 if (ev_actions[port].handler == default_handler)
99 printk("WARN: No handler for port %d when unbinding\n", port);
100 ev_actions[port].handler = default_handler;
101 wmb();
102 ev_actions[port].data = NULL;
103 }
105 int bind_virq(uint32_t virq, evtchn_handler_t handler, void *data)
106 {
107 evtchn_bind_virq_t op;
109 /* Try to bind the virq to a port */
110 op.virq = virq;
111 op.vcpu = smp_processor_id();
113 if ( HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, &op) != 0 )
114 {
115 printk("Failed to bind virtual IRQ %d\n", virq);
116 return 1;
117 }
118 set_bit(op.port,bound_ports);
119 bind_evtchn(op.port, handler, data);
120 return 0;
121 }
123 #if defined(__x86_64__)
124 /* Allocate 4 pages for the irqstack */
125 #define STACK_PAGES 4
126 char irqstack[1024 * 4 * STACK_PAGES];
128 static struct pda
129 {
130 int irqcount; /* offset 0 (used in x86_64.S) */
131 char *irqstackptr; /* 8 */
132 } cpu0_pda;
133 #endif
135 /*
136 * Initially all events are without a handler and disabled
137 */
138 void init_events(void)
139 {
140 int i;
141 #if defined(__x86_64__)
142 asm volatile("movl %0,%%fs ; movl %0,%%gs" :: "r" (0));
143 wrmsrl(0xc0000101, &cpu0_pda); /* 0xc0000101 is MSR_GS_BASE */
144 cpu0_pda.irqcount = -1;
145 cpu0_pda.irqstackptr = irqstack + 1024 * 4 * STACK_PAGES;
146 #endif
147 /* inintialise event handler */
148 for ( i = 0; i < NR_EVS; i++ )
149 {
150 ev_actions[i].handler = default_handler;
151 mask_evtchn(i);
152 }
153 }
155 void default_handler(evtchn_port_t port, struct pt_regs *regs, void *ignore)
156 {
157 printk("[Port %d] - event received\n", port);
158 }
160 /* Create a port available to the pal for exchanging notifications.
161 Returns the result of the hypervisor call. */
163 /* Unfortunate confusion of terminology: the port is unbound as far
164 as Xen is concerned, but we automatically bind a handler to it
165 from inside mini-os. */
167 int evtchn_alloc_unbound(domid_t pal, evtchn_handler_t handler,
168 void *data, evtchn_port_t *port)
169 {
170 evtchn_alloc_unbound_t op;
171 op.dom = DOMID_SELF;
172 op.remote_dom = pal;
173 int err = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &op);
174 if (err)
175 return err;
176 *port = bind_evtchn(op.port, handler, data);
177 return err;
178 }
180 /* Connect to a port so as to allow the exchange of notifications with
181 the pal. Returns the result of the hypervisor call. */
183 int evtchn_bind_interdomain(domid_t pal, evtchn_port_t remote_port,
184 evtchn_handler_t handler, void *data,
185 evtchn_port_t *local_port)
186 {
187 evtchn_bind_interdomain_t op;
188 op.remote_dom = pal;
189 op.remote_port = remote_port;
190 int err = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain, &op);
191 if (err)
192 return err;
193 set_bit(op.local_port,bound_ports);
194 evtchn_port_t port = op.local_port;
195 clear_evtchn(port); /* Without, handler gets invoked now! */
196 *local_port = bind_evtchn(port, handler, data);
197 return err;
198 }