win-pvdrivers

annotate 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
rev   line source
james@529 1 /*
james@529 2 PV Drivers for Windows Xen HVM Domains
james@529 3 Copyright (C) 2007 James Harper
james@529 4
james@529 5 This program is free software; you can redistribute it and/or
james@529 6 modify it under the terms of the GNU General Public License
james@529 7 as published by the Free Software Foundation; either version 2
james@529 8 of the License, or (at your option) any later version.
james@529 9
james@529 10 This program is distributed in the hope that it will be useful,
james@529 11 but WITHOUT ANY WARRANTY; without even the implied warranty of
james@529 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
james@529 13 GNU General Public License for more details.
james@529 14
james@529 15 You should have received a copy of the GNU General Public License
james@529 16 along with this program; if not, write to the Free Software
james@529 17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
james@529 18 */
james@529 19
james@529 20 #include "xenpci.h"
james@529 21
james@537 22 /*
james@537 23 we need these intrinsics as even going to HIGH_LEVEL doesn't ensure that interrupts are completely disabled
james@537 24 */
james@537 25 #pragma intrinsic(_disable)
james@537 26 #pragma intrinsic(_enable)
james@537 27
james@529 28 struct {
james@529 29 volatile ULONG do_spin;
james@529 30 volatile LONG nr_spinning;
james@529 31 KDPC dpcs[MAX_VIRT_CPUS];
james@529 32 KEVENT highsync_complete_event;
james@536 33 KIRQL sync_level;
james@529 34 PXENPCI_HIGHSYNC_FUNCTION function0;
james@529 35 PXENPCI_HIGHSYNC_FUNCTION functionN;
james@529 36 PVOID context;
james@529 37 } typedef highsync_info_t;
james@529 38
james@529 39 static DDKAPI VOID
james@529 40 XenPci_HighSyncCallFunction0(
james@529 41 PRKDPC Dpc,
james@529 42 PVOID Context,
james@529 43 PVOID SystemArgument1,
james@529 44 PVOID SystemArgument2)
james@529 45 {
james@529 46 highsync_info_t *highsync_info = Context;
james@529 47 ULONG ActiveProcessorCount;
james@529 48 KIRQL old_irql;
james@529 49
james@529 50 UNREFERENCED_PARAMETER(Dpc);
james@529 51 UNREFERENCED_PARAMETER(SystemArgument1);
james@529 52 UNREFERENCED_PARAMETER(SystemArgument2);
james@529 53
james@529 54 FUNCTION_ENTER();
james@529 55 ActiveProcessorCount = (ULONG)KeNumberProcessors;
james@537 56 _disable(); //__asm cli;
james@536 57 KeRaiseIrql(highsync_info->sync_level, &old_irql);
james@529 58 while (highsync_info->nr_spinning < (LONG)ActiveProcessorCount - 1)
james@529 59 {
james@529 60 KeStallExecutionProcessor(1);
james@529 61 KeMemoryBarrier();
james@529 62 }
james@529 63 highsync_info->function0(highsync_info->context);
james@529 64 KeLowerIrql(old_irql);
james@537 65 _enable(); //__asm sti;
james@529 66 highsync_info->do_spin = FALSE;
james@529 67 KeMemoryBarrier();
james@529 68
james@529 69 /* wait for all the other processors to complete spinning, just in case it matters */
james@529 70 while (highsync_info->nr_spinning)
james@529 71 {
james@529 72 KeStallExecutionProcessor(1);
james@529 73 KeMemoryBarrier();
james@529 74 }
james@529 75 KeSetEvent(&highsync_info->highsync_complete_event, IO_NO_INCREMENT, FALSE);
james@529 76
james@529 77 FUNCTION_EXIT();
james@529 78 }
james@529 79
james@529 80 static VOID
james@529 81 XenPci_HighSyncCallFunctionN(
james@529 82 PRKDPC Dpc,
james@529 83 PVOID Context,
james@529 84 PVOID SystemArgument1,
james@529 85 PVOID SystemArgument2)
james@529 86 {
james@529 87 highsync_info_t *highsync_info = Context;
james@529 88 KIRQL old_irql;
james@529 89
james@529 90 UNREFERENCED_PARAMETER(Dpc);
james@529 91 UNREFERENCED_PARAMETER(SystemArgument1);
james@529 92 UNREFERENCED_PARAMETER(SystemArgument2);
james@529 93
james@529 94 FUNCTION_ENTER();
james@529 95 FUNCTION_MSG("(CPU = %d)\n", KeGetCurrentProcessorNumber());
james@529 96
james@529 97 KdPrint((__DRIVER_NAME " CPU %d spinning...\n", KeGetCurrentProcessorNumber()));
james@536 98 KeRaiseIrql(highsync_info->sync_level, &old_irql);
james@529 99 InterlockedIncrement(&highsync_info->nr_spinning);
james@529 100 while(highsync_info->do_spin)
james@529 101 {
james@529 102 KeStallExecutionProcessor(1);
james@529 103 KeMemoryBarrier();
james@529 104 }
james@529 105 highsync_info->functionN(highsync_info->context);
james@529 106 KeLowerIrql(old_irql);
james@529 107 InterlockedDecrement(&highsync_info->nr_spinning);
james@529 108 FUNCTION_EXIT();
james@529 109 return;
james@529 110 }
james@529 111
james@529 112 VOID
james@529 113 XenPci_HighSync(PXENPCI_HIGHSYNC_FUNCTION function0, PXENPCI_HIGHSYNC_FUNCTION functionN, PVOID context)
james@529 114 {
james@529 115 ULONG ActiveProcessorCount;
james@529 116 ULONG i;
james@529 117 highsync_info_t *highsync_info;
james@529 118 KIRQL old_irql;
james@529 119
james@529 120 UNREFERENCED_PARAMETER(context);
james@529 121 FUNCTION_ENTER();
james@529 122
james@529 123 highsync_info = ExAllocatePoolWithTag(NonPagedPool, sizeof(highsync_info_t), XENPCI_POOL_TAG);
james@529 124 RtlZeroMemory(highsync_info, sizeof(highsync_info_t));
james@529 125 KeInitializeEvent(&highsync_info->highsync_complete_event, SynchronizationEvent, FALSE);
james@529 126 highsync_info->function0 = function0;
james@529 127 highsync_info->functionN = functionN;
james@529 128 highsync_info->context = context;
james@536 129 highsync_info->sync_level = HIGH_LEVEL;
james@529 130
james@529 131 ActiveProcessorCount = (ULONG)KeNumberProcessors;
james@529 132
james@529 133 /* Go to HIGH_LEVEL to prevent any races with Dpc's on the current processor */
james@536 134 KeRaiseIrql(highsync_info->sync_level, &old_irql);
james@529 135
james@529 136 highsync_info->do_spin = TRUE;
james@529 137 for (i = 0; i < ActiveProcessorCount; i++)
james@529 138 {
james@529 139 if (i == 0)
james@529 140 KeInitializeDpc(&highsync_info->dpcs[i], XenPci_HighSyncCallFunction0, highsync_info);
james@529 141 else
james@529 142 KeInitializeDpc(&highsync_info->dpcs[i], XenPci_HighSyncCallFunctionN, highsync_info);
james@529 143 KeSetTargetProcessorDpc(&highsync_info->dpcs[i], (CCHAR)i);
james@529 144 KeSetImportanceDpc(&highsync_info->dpcs[i], HighImportance);
james@529 145 KdPrint((__DRIVER_NAME " queuing Dpc for CPU %d\n", i));
james@529 146 KeInsertQueueDpc(&highsync_info->dpcs[i], NULL, NULL);
james@529 147 }
james@529 148 KdPrint((__DRIVER_NAME " All Dpc's queued\n"));
james@536 149
james@529 150 KeMemoryBarrier();
james@529 151 KeLowerIrql(old_irql);
james@529 152
james@529 153 KdPrint((__DRIVER_NAME " Waiting for highsync_complete_event\n"));
james@529 154 KeWaitForSingleObject(&highsync_info->highsync_complete_event, Executive, KernelMode, FALSE, NULL);
james@529 155 FUNCTION_EXIT();
james@529 156 }