win-pvdrivers

view xenpci/xenpci_highsync.c @ 536:1d39de3ab8d6

mostly finished migration back to kmdf
author James Harper <james.harper@bendigoit.com.au>
date Sat Feb 14 13:35:48 2009 +1100 (2009-02-14)
parents 6a2d1517e10c
children 2a74ac2f43bb
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 struct {
23 volatile ULONG do_spin;
24 volatile LONG nr_spinning;
25 KDPC dpcs[MAX_VIRT_CPUS];
26 KEVENT highsync_complete_event;
27 KIRQL sync_level;
28 PXENPCI_HIGHSYNC_FUNCTION function0;
29 PXENPCI_HIGHSYNC_FUNCTION functionN;
30 PVOID context;
31 } typedef highsync_info_t;
33 static DDKAPI VOID
34 XenPci_HighSyncCallFunction0(
35 PRKDPC Dpc,
36 PVOID Context,
37 PVOID SystemArgument1,
38 PVOID SystemArgument2)
39 {
40 highsync_info_t *highsync_info = Context;
41 ULONG ActiveProcessorCount;
42 KIRQL old_irql;
44 UNREFERENCED_PARAMETER(Dpc);
45 UNREFERENCED_PARAMETER(SystemArgument1);
46 UNREFERENCED_PARAMETER(SystemArgument2);
48 FUNCTION_ENTER();
49 ActiveProcessorCount = (ULONG)KeNumberProcessors;
50 __asm cli;
51 KeRaiseIrql(highsync_info->sync_level, &old_irql);
52 while (highsync_info->nr_spinning < (LONG)ActiveProcessorCount - 1)
53 {
54 KeStallExecutionProcessor(1);
55 KeMemoryBarrier();
56 }
57 highsync_info->function0(highsync_info->context);
58 KeLowerIrql(old_irql);
59 __asm sti;
60 highsync_info->do_spin = FALSE;
61 KeMemoryBarrier();
63 /* wait for all the other processors to complete spinning, just in case it matters */
64 while (highsync_info->nr_spinning)
65 {
66 KeStallExecutionProcessor(1);
67 KeMemoryBarrier();
68 }
69 KeSetEvent(&highsync_info->highsync_complete_event, IO_NO_INCREMENT, FALSE);
71 FUNCTION_EXIT();
72 }
74 static VOID
75 XenPci_HighSyncCallFunctionN(
76 PRKDPC Dpc,
77 PVOID Context,
78 PVOID SystemArgument1,
79 PVOID SystemArgument2)
80 {
81 highsync_info_t *highsync_info = Context;
82 KIRQL old_irql;
84 UNREFERENCED_PARAMETER(Dpc);
85 UNREFERENCED_PARAMETER(SystemArgument1);
86 UNREFERENCED_PARAMETER(SystemArgument2);
88 FUNCTION_ENTER();
89 FUNCTION_MSG("(CPU = %d)\n", KeGetCurrentProcessorNumber());
91 KdPrint((__DRIVER_NAME " CPU %d spinning...\n", KeGetCurrentProcessorNumber()));
92 KeRaiseIrql(highsync_info->sync_level, &old_irql);
93 InterlockedIncrement(&highsync_info->nr_spinning);
94 while(highsync_info->do_spin)
95 {
96 KeStallExecutionProcessor(1);
97 KeMemoryBarrier();
98 }
99 highsync_info->functionN(highsync_info->context);
100 KeLowerIrql(old_irql);
101 InterlockedDecrement(&highsync_info->nr_spinning);
102 FUNCTION_EXIT();
103 return;
104 }
106 VOID
107 XenPci_HighSync(PXENPCI_HIGHSYNC_FUNCTION function0, PXENPCI_HIGHSYNC_FUNCTION functionN, PVOID context)
108 {
109 ULONG ActiveProcessorCount;
110 ULONG i;
111 highsync_info_t *highsync_info;
112 KIRQL old_irql;
114 UNREFERENCED_PARAMETER(context);
115 FUNCTION_ENTER();
117 highsync_info = ExAllocatePoolWithTag(NonPagedPool, sizeof(highsync_info_t), XENPCI_POOL_TAG);
118 RtlZeroMemory(highsync_info, sizeof(highsync_info_t));
119 KeInitializeEvent(&highsync_info->highsync_complete_event, SynchronizationEvent, FALSE);
120 highsync_info->function0 = function0;
121 highsync_info->functionN = functionN;
122 highsync_info->context = context;
123 highsync_info->sync_level = HIGH_LEVEL;
125 ActiveProcessorCount = (ULONG)KeNumberProcessors;
127 /* Go to HIGH_LEVEL to prevent any races with Dpc's on the current processor */
128 KeRaiseIrql(highsync_info->sync_level, &old_irql);
130 highsync_info->do_spin = TRUE;
131 for (i = 0; i < ActiveProcessorCount; i++)
132 {
133 if (i == 0)
134 KeInitializeDpc(&highsync_info->dpcs[i], XenPci_HighSyncCallFunction0, highsync_info);
135 else
136 KeInitializeDpc(&highsync_info->dpcs[i], XenPci_HighSyncCallFunctionN, highsync_info);
137 KeSetTargetProcessorDpc(&highsync_info->dpcs[i], (CCHAR)i);
138 KeSetImportanceDpc(&highsync_info->dpcs[i], HighImportance);
139 KdPrint((__DRIVER_NAME " queuing Dpc for CPU %d\n", i));
140 KeInsertQueueDpc(&highsync_info->dpcs[i], NULL, NULL);
141 }
142 KdPrint((__DRIVER_NAME " All Dpc's queued\n"));
144 KeMemoryBarrier();
145 KeLowerIrql(old_irql);
147 KdPrint((__DRIVER_NAME " Waiting for highsync_complete_event\n"));
148 KeWaitForSingleObject(&highsync_info->highsync_complete_event, Executive, KernelMode, FALSE, NULL);
149 FUNCTION_EXIT();
150 }