win-pvdrivers

view xenpci/evtchn.c @ 151:eae0adfa5cee

getting 64b stuff on 32b, use a different #define to fix
author Andy Grover <andy.grover@oracle.com>
date Wed Jan 23 12:21:27 2008 -0800 (2008-01-23)
parents 2efec00dd95f
children e5d11fe17633
line source
1 /*
2 PV Drivers for Windows Xen HVM Domains
3 Copyright (C) 2007 James Harper
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License
7 as published by the Free Software Foundation; either version 2
8 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
20 #include "xenpci.h"
22 #if defined(_WIN32)
23 #define xchg(p1, p2) _InterlockedExchange(p1, p2)
24 #define synch_clear_bit(p1, p2) _interlockedbittestandreset(p2, p1)
25 #define synch_set_bit(p1, p2) _interlockedbittestandset(p2, p1)
26 #define bit_scan_forward(p1, p2) _BitScanForward(p1, p2)
27 #else
28 #define xchg(p1, p2) _InterlockedExchange64(p1, p2)
29 #define synch_clear_bit(p1, p2) _interlockedbittestandreset64(p2, p1)
30 #define synch_set_bit(p1, p2) _interlockedbittestandset64(p2, p1)
31 #define bit_scan_forward(p1, p2) _BitScanForward64(p1, p2)
32 #endif
34 static VOID
35 EvtChn_DpcBounce(WDFDPC Dpc)
36 {
37 ev_action_t *Action;
39 Action = GetEvtChnDeviceData(Dpc)->Action;
40 Action->ServiceRoutine(NULL, Action->ServiceContext);
41 }
43 BOOLEAN
44 EvtChn_Interrupt(WDFINTERRUPT Interrupt, ULONG MessageID)
45 {
46 int cpu = KeGetCurrentProcessorNumber();
47 vcpu_info_t *vcpu_info;
48 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(WdfInterruptGetDevice(Interrupt));
49 shared_info_t *shared_info_area = xpdd->shared_info_area;
50 xen_ulong_t evt_words;
51 unsigned long evt_word;
52 unsigned long evt_bit;
53 unsigned int port;
54 ev_action_t *ev_action;
56 KdPrint((__DRIVER_NAME " --> " __FUNCTION__ " (cpu = %d)\n", cpu));
58 UNREFERENCED_PARAMETER(MessageID);
60 vcpu_info = &shared_info_area->vcpu_info[cpu];
62 vcpu_info->evtchn_upcall_pending = 0;
64 evt_words = xchg((volatile xen_ulong_t *)&vcpu_info->evtchn_pending_sel, 0);
66 while (bit_scan_forward(&evt_word, evt_words))
67 {
68 evt_words &= ~(1 << evt_word);
69 while (bit_scan_forward(&evt_bit, shared_info_area->evtchn_pending[evt_word] & ~shared_info_area->evtchn_mask[evt_word]))
70 {
71 port = (evt_word << 5) + evt_bit;
72 ev_action = &xpdd->ev_actions[port];
73 if (ev_action->ServiceRoutine == NULL)
74 {
75 KdPrint((__DRIVER_NAME " Unhandled Event!!!\n"));
76 }
77 else
78 {
79 if (ev_action->DpcFlag)
80 {
81 KdPrint((__DRIVER_NAME " --- Scheduling Dpc\n"));
82 WdfDpcEnqueue(ev_action->Dpc);
83 }
84 else
85 {
86 ev_action->ServiceRoutine(NULL, ev_action->ServiceContext);
87 }
88 }
89 synch_clear_bit(port, (volatile xen_ulong_t *)&shared_info_area->evtchn_pending[evt_word]);
90 }
91 }
93 KdPrint((__DRIVER_NAME " <-- " __FUNCTION__ "\n"));
95 return FALSE; // This needs to be FALSE so it can fall through to the scsiport ISR.
96 }
98 NTSTATUS
99 EvtChn_Bind(PVOID Context, evtchn_port_t Port, PKSERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
100 {
101 WDFDEVICE Device = Context;
102 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
104 KdPrint((__DRIVER_NAME " --> EvtChn_Bind (ServiceRoutine = %08X, ServiceContext = %08x)\n", ServiceRoutine, ServiceContext));
106 if(xpdd->ev_actions[Port].ServiceRoutine != NULL)
107 {
108 xpdd->ev_actions[Port].ServiceRoutine = NULL;
109 KeMemoryBarrier(); // make sure we don't call the old Service Routine with the new data...
110 KdPrint((__DRIVER_NAME " Handler for port %d already registered, replacing\n", Port));
111 }
113 xpdd->ev_actions[Port].DpcFlag = FALSE;
114 xpdd->ev_actions[Port].ServiceContext = ServiceContext;
115 KeMemoryBarrier();
116 xpdd->ev_actions[Port].ServiceRoutine = ServiceRoutine;
118 EvtChn_Unmask(Device, Port);
120 KdPrint((__DRIVER_NAME " <-- EvtChn_Bind\n"));
122 return STATUS_SUCCESS;
123 }
125 NTSTATUS
126 EvtChn_BindDpc(PVOID Context, evtchn_port_t Port, PKSERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
127 {
128 WDFDEVICE Device = Context;
129 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
130 WDF_DPC_CONFIG DpcConfig;
131 WDF_OBJECT_ATTRIBUTES DpcObjectAttributes;
133 KdPrint((__DRIVER_NAME " --> EvtChn_BindDpc\n"));
135 if(xpdd->ev_actions[Port].ServiceRoutine != NULL)
136 {
137 KdPrint((__DRIVER_NAME " Handler for port %d already registered, replacing\n", Port));
138 xpdd->ev_actions[Port].ServiceRoutine = NULL;
139 KeMemoryBarrier(); // make sure we don't call the old Service Routine with the new data...
140 }
142 xpdd->ev_actions[Port].ServiceContext = ServiceContext;
143 xpdd->ev_actions[Port].DpcFlag = TRUE;
145 WDF_DPC_CONFIG_INIT(&DpcConfig, EvtChn_DpcBounce);
146 WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&DpcObjectAttributes, EVTCHN_DEVICE_DATA);
147 DpcObjectAttributes.ParentObject = Device;
148 WdfDpcCreate(&DpcConfig, &DpcObjectAttributes, &xpdd->ev_actions[Port].Dpc);
149 GetEvtChnDeviceData(xpdd->ev_actions[Port].Dpc)->Action = &xpdd->ev_actions[Port];
151 KeMemoryBarrier(); // make sure that the new service routine is only called once the context is set up
152 xpdd->ev_actions[Port].ServiceRoutine = ServiceRoutine;
154 EvtChn_Unmask(Device, Port);
156 KdPrint((__DRIVER_NAME " <-- EvtChn_BindDpc\n"));
158 return STATUS_SUCCESS;
159 }
161 NTSTATUS
162 EvtChn_Unbind(PVOID Context, evtchn_port_t Port)
163 {
164 WDFDEVICE Device = Context;
165 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
167 EvtChn_Mask(Context, Port);
168 xpdd->ev_actions[Port].ServiceRoutine = NULL;
169 KeMemoryBarrier();
170 xpdd->ev_actions[Port].ServiceContext = NULL;
172 if (xpdd->ev_actions[Port].DpcFlag)
173 WdfDpcCancel(xpdd->ev_actions[Port].Dpc, TRUE);
175 //KdPrint((__DRIVER_NAME " <-- EvtChn_UnBind\n"));
177 return STATUS_SUCCESS;
178 }
180 NTSTATUS
181 EvtChn_Mask(PVOID Context, evtchn_port_t Port)
182 {
183 WDFDEVICE Device = Context;
184 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
185 //KdPrint((__DRIVER_NAME " --> EvtChn_Mask\n"));
187 synch_set_bit(Port,
188 (volatile xen_ulong_t *)&xpdd->shared_info_area->evtchn_mask[0]);
190 //KdPrint((__DRIVER_NAME " <-- EvtChn_Mask\n"));
192 return STATUS_SUCCESS;
193 }
195 NTSTATUS
196 EvtChn_Unmask(PVOID Context, evtchn_port_t Port)
197 {
198 WDFDEVICE Device = Context;
199 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
200 //KdPrint((__DRIVER_NAME " --> EvtChn_Unmask\n"));
202 synch_clear_bit(Port,
203 (volatile xen_ulong_t *)&xpdd->shared_info_area->evtchn_mask[0]);
204 // should we kick off pending interrupts here too???
206 //KdPrint((__DRIVER_NAME " <-- EvtChn_Unmask\n"));
208 return STATUS_SUCCESS;
209 }
211 NTSTATUS
212 EvtChn_Notify(PVOID Context, evtchn_port_t Port)
213 {
214 struct evtchn_send send;
216 //KdPrint((__DRIVER_NAME " --> EvtChn_Notify\n"));
218 send.port = Port;
220 (void)HYPERVISOR_event_channel_op(Context, EVTCHNOP_send, &send);
222 //KdPrint((__DRIVER_NAME " <-- EvtChn_Notify\n"));
224 return STATUS_SUCCESS;
225 }
227 evtchn_port_t
228 EvtChn_AllocUnbound(PVOID Context, domid_t Domain)
229 {
230 evtchn_alloc_unbound_t op;
232 //KdPrint((__DRIVER_NAME " --> AllocUnbound\n"));
234 op.dom = DOMID_SELF;
235 op.remote_dom = Domain;
236 HYPERVISOR_event_channel_op(Context, EVTCHNOP_alloc_unbound, &op);
238 //KdPrint((__DRIVER_NAME " <-- AllocUnbound\n"));
240 return op.port;
241 }
243 evtchn_port_t
244 EvtChn_GetXenStorePort(WDFDEVICE Device)
245 {
246 evtchn_port_t Port;
248 KdPrint((__DRIVER_NAME " --> EvtChn_GetStorePort\n"));
250 Port = (evtchn_port_t)hvm_get_parameter(Device, HVM_PARAM_STORE_EVTCHN);
252 KdPrint((__DRIVER_NAME " <-- EvtChn_GetStorePort\n"));
254 return Port;
255 }
257 PVOID
258 EvtChn_GetXenStoreRingAddr(WDFDEVICE Device)
259 {
260 PHYSICAL_ADDRESS pa_xen_store_interface;
261 PVOID xen_store_interface;
263 xen_ulong_t xen_store_mfn;
265 KdPrint((__DRIVER_NAME " --> EvtChn_GetRingAddr\n"));
267 xen_store_mfn = hvm_get_parameter(Device, HVM_PARAM_STORE_PFN);
269 pa_xen_store_interface.QuadPart = xen_store_mfn << PAGE_SHIFT;
270 xen_store_interface = MmMapIoSpace(pa_xen_store_interface, PAGE_SIZE, MmNonCached);
272 KdPrint((__DRIVER_NAME " xen_store_mfn = %08x\n", xen_store_mfn));
273 //KdPrint((__DRIVER_NAME " xen_store_evtchn = %08x\n", xen_store_evtchn));
274 KdPrint((__DRIVER_NAME " xen_store_interface = %08x\n", xen_store_interface));
276 KdPrint((__DRIVER_NAME " <-- EvtChn_GetRingAddr\n"));
278 return xen_store_interface;
279 }
281 NTSTATUS
282 EvtChn_Init(WDFDEVICE Device)
283 {
284 PXENPCI_DEVICE_DATA xpdd = GetDeviceData(Device);
285 int i;
287 for (i = 0; i < NR_EVENTS; i++)
288 {
289 EvtChn_Mask(Device, i);
290 xpdd->ev_actions[i].ServiceRoutine = NULL;
291 xpdd->ev_actions[i].ServiceContext = NULL;
292 xpdd->ev_actions[i].Count = 0;
293 }
295 for (i = 0; i < 8; i++)
296 {
297 xpdd->shared_info_area->evtchn_pending[i] = 0;
298 }
300 for (i = 0; i < MAX_VIRT_CPUS; i++)
301 {
302 xpdd->shared_info_area->vcpu_info[i].evtchn_upcall_pending = 0;
303 xpdd->shared_info_area->vcpu_info[i].evtchn_pending_sel = 0;
304 }
306 return STATUS_SUCCESS;
307 }