source: trunk/packages/xen-3.1/xen-3.1/extras/mini-os/events.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

File size: 5.0 KB
Line 
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 */
18
19#include <os.h>
20#include <mm.h>
21#include <hypervisor.h>
22#include <events.h>
23#include <lib.h>
24
25#define NR_EVS 1024
26
27/* this represents a event handler. Chaining or sharing is not allowed */
28typedef struct _ev_action_t {
29        evtchn_handler_t handler;
30        void *data;
31    u32 count;
32} ev_action_t;
33
34static ev_action_t ev_actions[NR_EVS];
35void default_handler(evtchn_port_t port, struct pt_regs *regs, void *data);
36
37static unsigned long bound_ports[NR_EVS/(8*sizeof(unsigned long))];
38
39void unbind_all_ports(void)
40{
41    int i;
42
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}
54 
55/*
56 * Demux events to different handlers.
57 */
58int 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    }
65
66    action = &ev_actions[port];
67    action->count++;
68
69    /* call the handler */
70        action->handler(port, regs, action->data);
71
72 out:
73        clear_evtchn(port);
74
75    return 1;
76
77}
78
79evtchn_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);
85
86        ev_actions[port].data = data;
87        wmb();
88        ev_actions[port].handler = handler;
89
90        /* Finally unmask the port */
91        unmask_evtchn(port);
92
93        return port;
94}
95
96void 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}
104
105int bind_virq(uint32_t virq, evtchn_handler_t handler, void *data)
106{
107        evtchn_bind_virq_t op;
108
109        /* Try to bind the virq to a port */
110        op.virq = virq;
111        op.vcpu = smp_processor_id();
112
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}
122
123#if defined(__x86_64__)
124/* Allocate 4 pages for the irqstack */
125#define STACK_PAGES 4
126char irqstack[1024 * 4 * STACK_PAGES];
127
128static struct pda
129{
130    int irqcount;       /* offset 0 (used in x86_64.S) */
131    char *irqstackptr;  /*        8 */
132} cpu0_pda;
133#endif
134
135/*
136 * Initially all events are without a handler and disabled
137 */
138void 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}
154
155void default_handler(evtchn_port_t port, struct pt_regs *regs, void *ignore)
156{
157    printk("[Port %d] - event received\n", port);
158}
159
160/* Create a port available to the pal for exchanging notifications.
161   Returns the result of the hypervisor call. */
162
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. */
166
167int 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}
179
180/* Connect to a port so as to allow the exchange of notifications with
181   the pal. Returns the result of the hypervisor call. */
182
183int 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}
Note: See TracBrowser for help on using the repository browser.