win-pvdrivers

view xenpci/xenpci_highsync.c @ 537:2a74ac2f43bb

more big updates
dma now working under xp
author James Harper <james.harper@bendigoit.com.au>
date Wed Feb 18 22:18:23 2009 +1100 (2009-02-18)
parents 1d39de3ab8d6
children 5bdb7251370c
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 /*
23 we need these intrinsics as even going to HIGH_LEVEL doesn't ensure that interrupts are completely disabled
24 */
25 #pragma intrinsic(_disable)
26 #pragma intrinsic(_enable)
28 struct {
29 volatile ULONG do_spin;
30 volatile LONG nr_spinning;
31 KDPC dpcs[MAX_VIRT_CPUS];
32 KEVENT highsync_complete_event;
33 KIRQL sync_level;
34 PXENPCI_HIGHSYNC_FUNCTION function0;
35 PXENPCI_HIGHSYNC_FUNCTION functionN;
36 PVOID context;
37 } typedef highsync_info_t;
39 static DDKAPI VOID
40 XenPci_HighSyncCallFunction0(
41 PRKDPC Dpc,
42 PVOID Context,
43 PVOID SystemArgument1,
44 PVOID SystemArgument2)
45 {
46 highsync_info_t *highsync_info = Context;
47 ULONG ActiveProcessorCount;
48 KIRQL old_irql;
50 UNREFERENCED_PARAMETER(Dpc);
51 UNREFERENCED_PARAMETER(SystemArgument1);
52 UNREFERENCED_PARAMETER(SystemArgument2);
54 FUNCTION_ENTER();
55 ActiveProcessorCount = (ULONG)KeNumberProcessors;
56 _disable(); //__asm cli;
57 KeRaiseIrql(highsync_info->sync_level, &old_irql);
58 while (highsync_info->nr_spinning < (LONG)ActiveProcessorCount - 1)
59 {
60 KeStallExecutionProcessor(1);
61 KeMemoryBarrier();
62 }
63 highsync_info->function0(highsync_info->context);
64 KeLowerIrql(old_irql);
65 _enable(); //__asm sti;
66 highsync_info->do_spin = FALSE;
67 KeMemoryBarrier();
69 /* wait for all the other processors to complete spinning, just in case it matters */
70 while (highsync_info->nr_spinning)
71 {
72 KeStallExecutionProcessor(1);
73 KeMemoryBarrier();
74 }
75 KeSetEvent(&highsync_info->highsync_complete_event, IO_NO_INCREMENT, FALSE);
77 FUNCTION_EXIT();
78 }
80 static VOID
81 XenPci_HighSyncCallFunctionN(
82 PRKDPC Dpc,
83 PVOID Context,
84 PVOID SystemArgument1,
85 PVOID SystemArgument2)
86 {
87 highsync_info_t *highsync_info = Context;
88 KIRQL old_irql;
90 UNREFERENCED_PARAMETER(Dpc);
91 UNREFERENCED_PARAMETER(SystemArgument1);
92 UNREFERENCED_PARAMETER(SystemArgument2);
94 FUNCTION_ENTER();
95 FUNCTION_MSG("(CPU = %d)\n", KeGetCurrentProcessorNumber());
97 KdPrint((__DRIVER_NAME " CPU %d spinning...\n", KeGetCurrentProcessorNumber()));
98 KeRaiseIrql(highsync_info->sync_level, &old_irql);
99 InterlockedIncrement(&highsync_info->nr_spinning);
100 while(highsync_info->do_spin)
101 {
102 KeStallExecutionProcessor(1);
103 KeMemoryBarrier();
104 }
105 highsync_info->functionN(highsync_info->context);
106 KeLowerIrql(old_irql);
107 InterlockedDecrement(&highsync_info->nr_spinning);
108 FUNCTION_EXIT();
109 return;
110 }
112 VOID
113 XenPci_HighSync(PXENPCI_HIGHSYNC_FUNCTION function0, PXENPCI_HIGHSYNC_FUNCTION functionN, PVOID context)
114 {
115 ULONG ActiveProcessorCount;
116 ULONG i;
117 highsync_info_t *highsync_info;
118 KIRQL old_irql;
120 UNREFERENCED_PARAMETER(context);
121 FUNCTION_ENTER();
123 highsync_info = ExAllocatePoolWithTag(NonPagedPool, sizeof(highsync_info_t), XENPCI_POOL_TAG);
124 RtlZeroMemory(highsync_info, sizeof(highsync_info_t));
125 KeInitializeEvent(&highsync_info->highsync_complete_event, SynchronizationEvent, FALSE);
126 highsync_info->function0 = function0;
127 highsync_info->functionN = functionN;
128 highsync_info->context = context;
129 highsync_info->sync_level = HIGH_LEVEL;
131 ActiveProcessorCount = (ULONG)KeNumberProcessors;
133 /* Go to HIGH_LEVEL to prevent any races with Dpc's on the current processor */
134 KeRaiseIrql(highsync_info->sync_level, &old_irql);
136 highsync_info->do_spin = TRUE;
137 for (i = 0; i < ActiveProcessorCount; i++)
138 {
139 if (i == 0)
140 KeInitializeDpc(&highsync_info->dpcs[i], XenPci_HighSyncCallFunction0, highsync_info);
141 else
142 KeInitializeDpc(&highsync_info->dpcs[i], XenPci_HighSyncCallFunctionN, highsync_info);
143 KeSetTargetProcessorDpc(&highsync_info->dpcs[i], (CCHAR)i);
144 KeSetImportanceDpc(&highsync_info->dpcs[i], HighImportance);
145 KdPrint((__DRIVER_NAME " queuing Dpc for CPU %d\n", i));
146 KeInsertQueueDpc(&highsync_info->dpcs[i], NULL, NULL);
147 }
148 KdPrint((__DRIVER_NAME " All Dpc's queued\n"));
150 KeMemoryBarrier();
151 KeLowerIrql(old_irql);
153 KdPrint((__DRIVER_NAME " Waiting for highsync_complete_event\n"));
154 KeWaitForSingleObject(&highsync_info->highsync_complete_event, Executive, KernelMode, FALSE, NULL);
155 FUNCTION_EXIT();
156 }