win-pvdrivers

view xenpci/evtchn.c @ 0:435e5753300f

Initial upload of files
author James Harper <james.harper@bendigoit.com.au>
date Sat Nov 10 14:40:56 2007 +1100 (2007-11-10)
parents
children 8f643f8e229b
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"
21 #include "hypercall.h"
23 #define NR_EVENTS 1024
25 typedef struct _ev_action_t {
26 PKSERVICE_ROUTINE ServiceRoutine;
27 PVOID ServiceContext;
28 ULONG Count;
29 } ev_action_t;
31 static ev_action_t ev_actions[NR_EVENTS];
33 static unsigned long bound_ports[NR_EVENTS/(8*sizeof(unsigned long))];
35 BOOLEAN
36 EvtChn_Interrupt(WDFINTERRUPT Interrupt, ULONG MessageID)
37 {
38 int cpu = 0;
39 vcpu_info_t *vcpu_info;
40 // int i;
41 unsigned long evt_words, evt_word;
42 unsigned long evt_bit;
43 unsigned long port;
44 ev_action_t *ev_action;
46 UNREFERENCED_PARAMETER(Interrupt);
47 UNREFERENCED_PARAMETER(MessageID);
49 //KdPrint((__DRIVER_NAME " I+\n"));
50 //KdPrint((__DRIVER_NAME " --> XenPCI_ISR\n"));
52 vcpu_info = &shared_info_area->vcpu_info[cpu];
54 vcpu_info->evtchn_upcall_pending = 0;
56 evt_words = _InterlockedExchange((volatile LONG *)&vcpu_info->evtchn_pending_sel, 0);
58 while (_BitScanForward(&evt_word, evt_words))
59 {
60 evt_words &= ~(1 << evt_word);
61 while (_BitScanForward(&evt_bit, shared_info_area->evtchn_pending[evt_word] & ~shared_info_area->evtchn_mask[evt_word]))
62 {
63 port = (evt_word << 5) + evt_bit;
64 ev_action = &ev_actions[port];
65 if (ev_action->ServiceRoutine == NULL)
66 {
67 KdPrint((__DRIVER_NAME " Unhandled Event!!!\n"));
68 }
69 else
70 {
71 //KdPrint((__DRIVER_NAME " Calling Handler for port %d\n", port));
72 ev_action->ServiceRoutine(NULL, ev_action->ServiceContext);
73 }
74 _interlockedbittestandreset((volatile LONG *)&shared_info_area->evtchn_pending[0], port);
75 }
76 }
78 //KdPrint((__DRIVER_NAME " <-- XenPCI_ISR\n"));
80 //KdPrint((__DRIVER_NAME " I-\n"));
82 return TRUE;
83 }
85 evtchn_port_t
86 EvtChn_AllocUnbound(domid_t Domain)
87 {
88 evtchn_alloc_unbound_t op;
90 //KdPrint((__DRIVER_NAME " --> AllocUnbound\n"));
92 op.dom = DOMID_SELF;
93 op.remote_dom = Domain;
94 HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, &op);
96 //KdPrint((__DRIVER_NAME " <-- AllocUnbound\n"));
98 return op.port;
99 }
102 NTSTATUS
103 EvtChn_Bind(evtchn_port_t Port, PKSERVICE_ROUTINE ServiceRoutine, PVOID ServiceContext)
104 {
105 //KdPrint((__DRIVER_NAME " --> EvtChn_Bind\n"));
107 if(ev_actions[Port].ServiceRoutine != ServiceRoutine)
108 {
109 KdPrint((__DRIVER_NAME " Handler for port %d already registered, replacing\n", Port));
110 }
112 ev_actions[Port].ServiceContext = ServiceContext;
113 //_WriteBarrier();
114 KeMemoryBarrier();
115 ev_actions[Port].ServiceRoutine = ServiceRoutine;
117 EvtChn_Unmask(Port);
119 //KdPrint((__DRIVER_NAME " <-- EvtChn_Bind\n"));
121 return STATUS_SUCCESS;
122 }
124 NTSTATUS
125 EvtChn_Unbind(evtchn_port_t Port)
126 {
127 //KdPrint((__DRIVER_NAME " --> EvtChn_UnBind\n"));
129 EvtChn_Mask(Port);
130 ev_actions[Port].ServiceContext = NULL;
131 ev_actions[Port].ServiceRoutine = NULL;
133 //KdPrint((__DRIVER_NAME " <-- EvtChn_UnBind\n"));
135 return STATUS_SUCCESS;
136 }
138 NTSTATUS
139 EvtChn_Mask(evtchn_port_t Port)
140 {
141 //KdPrint((__DRIVER_NAME " --> EvtChn_Mask\n"));
143 _interlockedbittestandset((volatile LONG *)&shared_info_area->evtchn_mask[0], Port);
145 //KdPrint((__DRIVER_NAME " <-- EvtChn_Mask\n"));
147 return STATUS_SUCCESS;
148 }
150 NTSTATUS
151 EvtChn_Unmask(evtchn_port_t Port)
152 {
153 //KdPrint((__DRIVER_NAME " --> EvtChn_Unmask\n"));
155 _interlockedbittestandreset((volatile LONG *)&shared_info_area->evtchn_mask[0], Port);
156 // should we kick off pending interrupts here too???
158 //KdPrint((__DRIVER_NAME " <-- EvtChn_Unmask\n"));
160 return STATUS_SUCCESS;
161 }
163 NTSTATUS
164 EvtChn_Notify(evtchn_port_t Port)
165 {
166 struct evtchn_send send;
168 //KdPrint((__DRIVER_NAME " --> EvtChn_Notify\n"));
170 send.port = Port;
172 (void)HYPERVISOR_event_channel_op(EVTCHNOP_send, &send);
174 //KdPrint((__DRIVER_NAME " <-- EvtChn_Notify\n"));
176 return STATUS_SUCCESS;
177 }
180 evtchn_port_t
181 EvtChn_GetXenStorePort()
182 {
183 evtchn_port_t Port;
185 //KdPrint((__DRIVER_NAME " --> EvtChn_GetStorePort\n"));
187 Port = (evtchn_port_t)hvm_get_parameter(HVM_PARAM_STORE_EVTCHN);
189 //KdPrint((__DRIVER_NAME " <-- EvtChn_GetStorePort\n"));
191 return Port;
192 }
194 PVOID
195 EvtChn_GetXenStoreRingAddr()
196 {
197 PHYSICAL_ADDRESS pa_xen_store_interface;
198 PVOID xen_store_interface;
200 ULONG xen_store_mfn;
202 //KdPrint((__DRIVER_NAME " --> EvtChn_GetRingAddr\n"));
204 xen_store_mfn = (ULONG)hvm_get_parameter(HVM_PARAM_STORE_PFN);
206 pa_xen_store_interface.QuadPart = xen_store_mfn << PAGE_SHIFT;
207 xen_store_interface = MmMapIoSpace(pa_xen_store_interface, PAGE_SIZE, MmNonCached);
209 //KdPrint((__DRIVER_NAME " xen_store_mfn = %08x\n", xen_store_mfn));
210 //KdPrint((__DRIVER_NAME " xen_store_evtchn = %08x\n", xen_store_evtchn));
211 //KdPrint((__DRIVER_NAME " xen_store_interface = %08x\n", xen_store_interface));
213 //KeInitializeEvent(&xenbus_waitevent, NotificationEvent, FALSE);
215 //KdPrint((__DRIVER_NAME " <-- EvtChn_GetRingAddr\n"));
217 return xen_store_interface;
218 }
220 NTSTATUS
221 EvtChn_Init()
222 {
223 int i;
225 for (i = 0; i < NR_EVENTS; i++)
226 {
227 EvtChn_Mask(i);
228 ev_actions[i].ServiceRoutine = NULL;
229 ev_actions[i].ServiceContext = NULL;
230 ev_actions[i].Count = 0;
231 }
233 for (i = 0; i < 8; i++) {
234 shared_info_area->evtchn_pending[i] = 0;
235 }
236 shared_info_area->vcpu_info[0].evtchn_upcall_pending = 0;
237 shared_info_area->vcpu_info[0].evtchn_pending_sel = 0;
239 return STATUS_SUCCESS;
240 }
242 static ev_action_t ev_actions[NR_EVENTS];