direct-io.hg

view extras/mini-os/events.c @ 11356:af7c87d42bc6

[XEN][POWERPC] Fix PHDR issues with large .data.percpu sections

This patch tells the link to only create one PHDR and place all sections
in it, also removing an unrequired mapping for the .data.percpu section.

This avoids the "Not enough room for program headers (allocated 2, need 3)"

Booted on a JS20.

Signed-off-by: Tony Breeds <tony@bakeyournoodle.com>
Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
author Jimi Xenidis <jimix@watson.ibm.com>
date Thu Aug 17 07:10:57 2006 -0400 (2006-08-17)
parents cbfced5fcdb3
children fc8ae086f706
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;
35 static ev_action_t ev_actions[NR_EVS];
36 void default_handler(evtchn_port_t port, struct pt_regs *regs, void *data);
39 /*
40 * Demux events to different handlers.
41 */
42 int do_event(evtchn_port_t port, struct pt_regs *regs)
43 {
44 ev_action_t *action;
45 if (port >= NR_EVS) {
46 printk("Port number too large: %d\n", port);
47 goto out;
48 }
50 action = &ev_actions[port];
51 action->count++;
53 /* call the handler */
54 action->handler(port, regs, action->data);
56 out:
57 clear_evtchn(port);
59 return 1;
61 }
63 evtchn_port_t bind_evtchn(evtchn_port_t port, evtchn_handler_t handler,
64 void *data)
65 {
66 if(ev_actions[port].handler != default_handler)
67 printk("WARN: Handler for port %d already registered, replacing\n",
68 port);
70 ev_actions[port].data = data;
71 wmb();
72 ev_actions[port].handler = handler;
74 /* Finally unmask the port */
75 unmask_evtchn(port);
77 return port;
78 }
80 void unbind_evtchn(evtchn_port_t port )
81 {
82 if (ev_actions[port].handler == default_handler)
83 printk("WARN: No handler for port %d when unbinding\n", port);
84 ev_actions[port].handler = default_handler;
85 wmb();
86 ev_actions[port].data = NULL;
87 }
89 int bind_virq(uint32_t virq, evtchn_handler_t handler, void *data)
90 {
91 evtchn_op_t op;
93 /* Try to bind the virq to a port */
94 op.cmd = EVTCHNOP_bind_virq;
95 op.u.bind_virq.virq = virq;
96 op.u.bind_virq.vcpu = smp_processor_id();
98 if ( HYPERVISOR_event_channel_op(&op) != 0 )
99 {
100 printk("Failed to bind virtual IRQ %d\n", virq);
101 return 1;
102 }
103 bind_evtchn(op.u.bind_virq.port, handler, data);
104 return 0;
105 }
107 #if defined(__x86_64__)
108 /* Allocate 4 pages for the irqstack */
109 #define STACK_PAGES 4
110 char irqstack[1024 * 4 * STACK_PAGES];
112 static struct pda
113 {
114 int irqcount; /* offset 0 (used in x86_64.S) */
115 char *irqstackptr; /* 8 */
116 } cpu0_pda;
117 #endif
119 /*
120 * Initially all events are without a handler and disabled
121 */
122 void init_events(void)
123 {
124 int i;
125 #if defined(__x86_64__)
126 asm volatile("movl %0,%%fs ; movl %0,%%gs" :: "r" (0));
127 wrmsrl(0xc0000101, &cpu0_pda); /* 0xc0000101 is MSR_GS_BASE */
128 cpu0_pda.irqcount = -1;
129 cpu0_pda.irqstackptr = irqstack + 1024 * 4 * STACK_PAGES;
130 #endif
131 /* inintialise event handler */
132 for ( i = 0; i < NR_EVS; i++ )
133 {
134 ev_actions[i].handler = default_handler;
135 mask_evtchn(i);
136 }
137 }
139 void default_handler(evtchn_port_t port, struct pt_regs *regs, void *ignore)
140 {
141 printk("[Port %d] - event received\n", port);
142 }
144 /* Create a port available to the pal for exchanging notifications.
145 Returns the result of the hypervisor call. */
147 /* Unfortunate confusion of terminology: the port is unbound as far
148 as Xen is concerned, but we automatically bind a handler to it
149 from inside mini-os. */
151 int evtchn_alloc_unbound(domid_t pal, evtchn_handler_t handler,
152 void *data, evtchn_port_t *port)
153 {
154 evtchn_op_t op;
155 op.cmd = EVTCHNOP_alloc_unbound;
156 op.u.alloc_unbound.dom = DOMID_SELF;
157 op.u.alloc_unbound.remote_dom = pal;
158 int err = HYPERVISOR_event_channel_op(&op);
159 if (err)
160 return err;
161 *port = bind_evtchn(op.u.alloc_unbound.port, handler, data);
162 return err;
163 }
165 /* Connect to a port so as to allow the exchange of notifications with
166 the pal. Returns the result of the hypervisor call. */
168 int evtchn_bind_interdomain(domid_t pal, evtchn_port_t remote_port,
169 evtchn_handler_t handler, void *data,
170 evtchn_port_t *local_port)
171 {
172 evtchn_op_t op;
173 op.cmd = EVTCHNOP_bind_interdomain;
174 op.u.bind_interdomain.remote_dom = pal;
175 op.u.bind_interdomain.remote_port = remote_port;
176 int err = HYPERVISOR_event_channel_op(&op);
177 if (err)
178 return err;
179 evtchn_port_t port = op.u.bind_interdomain.local_port;
180 clear_evtchn(port); /* Without, handler gets invoked now! */
181 *local_port = bind_evtchn(port, handler, data);
182 return err;
183 }