win-pvdrivers

view xenpci/xenpci_highsync.c @ 716:5bdb7251370c

Use WinDDK 7600.16385.0
Update userspace binaries to build for XP not 2K (2K not supported in new DDK)
Fix lots of PREfast errors
Make build and installer less dependant on DDK version
Fix IRQL crash in DpgPrint hooking
author James Harper <james.harper@bendigoit.com.au>
date Tue Dec 22 22:44:07 2009 +1100 (2009-12-22)
parents 2a74ac2f43bb
children 358a1bf4efaf
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 /* Not really necessary but keeps PREfast happy */
23 static KDEFERRED_ROUTINE XenPci_HighSyncCallFunction0;
24 static KDEFERRED_ROUTINE XenPci_HighSyncCallFunctionN;
26 /*
27 we need these intrinsics as even going to HIGH_LEVEL doesn't ensure that interrupts are completely disabled
28 */
29 #pragma intrinsic(_disable)
30 #pragma intrinsic(_enable)
32 struct {
33 volatile ULONG do_spin;
34 volatile LONG nr_spinning;
35 KDPC dpcs[MAX_VIRT_CPUS];
36 KEVENT highsync_complete_event;
37 KIRQL sync_level;
38 PXENPCI_HIGHSYNC_FUNCTION function0;
39 PXENPCI_HIGHSYNC_FUNCTION functionN;
40 PVOID context;
41 } typedef highsync_info_t;
43 static DDKAPI VOID
44 XenPci_HighSyncCallFunction0(
45 PRKDPC Dpc,
46 PVOID Context,
47 PVOID SystemArgument1,
48 PVOID SystemArgument2)
49 {
50 highsync_info_t *highsync_info = Context;
51 ULONG ActiveProcessorCount;
52 KIRQL old_irql;
54 UNREFERENCED_PARAMETER(Dpc);
55 UNREFERENCED_PARAMETER(SystemArgument1);
56 UNREFERENCED_PARAMETER(SystemArgument2);
58 FUNCTION_ENTER();
59 ActiveProcessorCount = (ULONG)KeNumberProcessors;
60 _disable(); //__asm cli;
61 KeRaiseIrql(highsync_info->sync_level, &old_irql);
62 while (highsync_info->nr_spinning < (LONG)ActiveProcessorCount - 1)
63 {
64 KeStallExecutionProcessor(1);
65 KeMemoryBarrier();
66 }
67 highsync_info->function0(highsync_info->context);
68 KeLowerIrql(old_irql);
69 _enable(); //__asm sti;
70 highsync_info->do_spin = FALSE;
71 KeMemoryBarrier();
73 /* wait for all the other processors to complete spinning, just in case it matters */
74 while (highsync_info->nr_spinning)
75 {
76 KeStallExecutionProcessor(1);
77 KeMemoryBarrier();
78 }
79 KeSetEvent(&highsync_info->highsync_complete_event, IO_NO_INCREMENT, FALSE);
81 FUNCTION_EXIT();
82 }
84 static VOID
85 XenPci_HighSyncCallFunctionN(
86 PRKDPC Dpc,
87 PVOID Context,
88 PVOID SystemArgument1,
89 PVOID SystemArgument2)
90 {
91 highsync_info_t *highsync_info = Context;
92 KIRQL old_irql;
94 UNREFERENCED_PARAMETER(Dpc);
95 UNREFERENCED_PARAMETER(SystemArgument1);
96 UNREFERENCED_PARAMETER(SystemArgument2);
98 FUNCTION_ENTER();
99 FUNCTION_MSG("(CPU = %d)\n", KeGetCurrentProcessorNumber());
101 KdPrint((__DRIVER_NAME " CPU %d spinning...\n", KeGetCurrentProcessorNumber()));
102 KeRaiseIrql(highsync_info->sync_level, &old_irql);
103 InterlockedIncrement(&highsync_info->nr_spinning);
104 while(highsync_info->do_spin)
105 {
106 KeStallExecutionProcessor(1);
107 KeMemoryBarrier();
108 }
109 highsync_info->functionN(highsync_info->context);
110 KeLowerIrql(old_irql);
111 InterlockedDecrement(&highsync_info->nr_spinning);
112 FUNCTION_EXIT();
113 return;
114 }
116 VOID
117 XenPci_HighSync(PXENPCI_HIGHSYNC_FUNCTION function0, PXENPCI_HIGHSYNC_FUNCTION functionN, PVOID context)
118 {
119 ULONG ActiveProcessorCount;
120 ULONG i;
121 highsync_info_t *highsync_info;
122 KIRQL old_irql;
124 UNREFERENCED_PARAMETER(context);
125 FUNCTION_ENTER();
127 highsync_info = ExAllocatePoolWithTag(NonPagedPool, sizeof(highsync_info_t), XENPCI_POOL_TAG);
128 RtlZeroMemory(highsync_info, sizeof(highsync_info_t));
129 KeInitializeEvent(&highsync_info->highsync_complete_event, SynchronizationEvent, FALSE);
130 highsync_info->function0 = function0;
131 highsync_info->functionN = functionN;
132 highsync_info->context = context;
133 highsync_info->sync_level = HIGH_LEVEL;
135 ActiveProcessorCount = (ULONG)KeNumberProcessors;
137 /* Go to HIGH_LEVEL to prevent any races with Dpc's on the current processor */
138 KeRaiseIrql(highsync_info->sync_level, &old_irql);
140 highsync_info->do_spin = TRUE;
141 for (i = 0; i < ActiveProcessorCount; i++)
142 {
143 if (i == 0)
144 KeInitializeDpc(&highsync_info->dpcs[i], XenPci_HighSyncCallFunction0, highsync_info);
145 else
146 KeInitializeDpc(&highsync_info->dpcs[i], XenPci_HighSyncCallFunctionN, highsync_info);
147 KeSetTargetProcessorDpc(&highsync_info->dpcs[i], (CCHAR)i);
148 KeSetImportanceDpc(&highsync_info->dpcs[i], HighImportance);
149 KdPrint((__DRIVER_NAME " queuing Dpc for CPU %d\n", i));
150 KeInsertQueueDpc(&highsync_info->dpcs[i], NULL, NULL);
151 }
152 KdPrint((__DRIVER_NAME " All Dpc's queued\n"));
154 KeMemoryBarrier();
155 KeLowerIrql(old_irql);
157 KdPrint((__DRIVER_NAME " Waiting for highsync_complete_event\n"));
158 KeWaitForSingleObject(&highsync_info->highsync_complete_event, Executive, KernelMode, FALSE, NULL);
159 FUNCTION_EXIT();
160 }