win-pvdrivers

view xenpci/xenpci_highsync.c @ 804:6ea80e94e8cf

Added tag 0.11.0.218 for changeset bbc6c94b9621
author James Harper <james.harper@bendigoit.com.au>
date Sun Jun 27 16:15:21 2010 +1000 (2010-06-27)
parents 358a1bf4efaf
children ff77e2f26a3e
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 _disable(); //__asm cli;
103 KeRaiseIrql(highsync_info->sync_level, &old_irql);
104 InterlockedIncrement(&highsync_info->nr_spinning);
105 while(highsync_info->do_spin)
106 {
107 KeStallExecutionProcessor(1);
108 KeMemoryBarrier();
109 }
110 highsync_info->functionN(highsync_info->context);
111 KeLowerIrql(old_irql);
112 _enable(); //__asm sti;
113 InterlockedDecrement(&highsync_info->nr_spinning);
114 FUNCTION_EXIT();
115 return;
116 }
118 VOID
119 XenPci_HighSync(PXENPCI_HIGHSYNC_FUNCTION function0, PXENPCI_HIGHSYNC_FUNCTION functionN, PVOID context)
120 {
121 ULONG ActiveProcessorCount;
122 ULONG i;
123 highsync_info_t *highsync_info;
124 KIRQL old_irql;
126 UNREFERENCED_PARAMETER(context);
127 FUNCTION_ENTER();
129 highsync_info = ExAllocatePoolWithTag(NonPagedPool, sizeof(highsync_info_t), XENPCI_POOL_TAG);
130 RtlZeroMemory(highsync_info, sizeof(highsync_info_t));
131 KeInitializeEvent(&highsync_info->highsync_complete_event, SynchronizationEvent, FALSE);
132 highsync_info->function0 = function0;
133 highsync_info->functionN = functionN;
134 highsync_info->context = context;
135 highsync_info->sync_level = HIGH_LEVEL;
137 ActiveProcessorCount = (ULONG)KeNumberProcessors;
139 /* Go to HIGH_LEVEL to prevent any races with Dpc's on the current processor */
140 KeRaiseIrql(highsync_info->sync_level, &old_irql);
142 highsync_info->do_spin = TRUE;
143 for (i = 0; i < ActiveProcessorCount; i++)
144 {
145 if (i == 0)
146 KeInitializeDpc(&highsync_info->dpcs[i], XenPci_HighSyncCallFunction0, highsync_info);
147 else
148 KeInitializeDpc(&highsync_info->dpcs[i], XenPci_HighSyncCallFunctionN, highsync_info);
149 KeSetTargetProcessorDpc(&highsync_info->dpcs[i], (CCHAR)i);
150 KeSetImportanceDpc(&highsync_info->dpcs[i], HighImportance);
151 KdPrint((__DRIVER_NAME " queuing Dpc for CPU %d\n", i));
152 KeInsertQueueDpc(&highsync_info->dpcs[i], NULL, NULL);
153 }
154 KdPrint((__DRIVER_NAME " All Dpc's queued\n"));
156 KeMemoryBarrier();
157 KeLowerIrql(old_irql);
159 KdPrint((__DRIVER_NAME " Waiting for highsync_complete_event\n"));
160 KeWaitForSingleObject(&highsync_info->highsync_complete_event, Executive, KernelMode, FALSE, NULL);
161 FUNCTION_EXIT();
162 }