kvm-guest-drivers-windows
207 строк · 6.2 Кб
1/*
2* Placeholder for the Event handling functions
3*
4* Copyright (c) 2020 Virtuozzo International GmbH
5*
6* Redistribution and use in source and binary forms, with or without
7* modification, are permitted provided that the following conditions
8* are met :
9* 1. Redistributions of source code must retain the above copyright
10* notice, this list of conditions and the following disclaimer.
11* 2. Redistributions in binary form must reproduce the above copyright
12* notice, this list of conditions and the following disclaimer in the
13* documentation and / or other materials provided with the distribution.
14* 3. Neither the names of the copyright holders nor the names of their contributors
15* may be used to endorse or promote products derived from this software
16* without specific prior written permission.
17* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
18* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20* ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
21* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27* SUCH DAMAGE.
28*/
29
30#include "precomp.h"31#include "viosock.h"32
33#if defined(EVENT_TRACING)34#include "Evt.tmh"35#endif36
37
38#ifdef ALLOC_PRAGMA39#pragma alloc_text (PAGE, VIOSockEvtVqInit)40#pragma alloc_text (PAGE, VIOSockEvtVqCleanup)41#endif42
43_IRQL_requires_max_(DISPATCH_LEVEL)44static
45BOOLEAN
46VIOSockEvtPktInsert(47IN PDEVICE_CONTEXT pContext,48IN PVIRTIO_VSOCK_EVENT pEvent
49)
50{
51BOOLEAN bRes = TRUE;52VIOSOCK_SG_DESC sg;53int ret;54
55TraceEvents(TRACE_LEVEL_VERBOSE, DBG_HW_ACCESS, "--> %s\n", __FUNCTION__);56
57sg.length = sizeof(VIRTIO_VSOCK_EVENT);58sg.physAddr.QuadPart = pContext->EvtPA.QuadPart +59(ULONGLONG)((PCHAR)pEvent - (PCHAR)pContext->EvtVA);60
61ret = virtqueue_add_buf(pContext->EvtVq, &sg, 0, 1, pEvent, NULL, 0);62
63ASSERT(ret >= 0);64if (ret < 0)65{66TraceEvents(TRACE_LEVEL_ERROR, DBG_HW_ACCESS,67"Error adding buffer to Evt queue (ret = %d)\n", ret);68return FALSE;69}70
71return TRUE;72}
73
74_IRQL_requires_max_(PASSIVE_LEVEL)75VOID
76VIOSockEvtVqCleanup(77IN PDEVICE_CONTEXT pContext
78)
79{
80PAGED_CODE();81
82TraceEvents(TRACE_LEVEL_VERBOSE, DBG_HW_ACCESS, "--> %s\n", __FUNCTION__);83
84ASSERT(pContext->EvtVq && pContext->EvtVA);85
86//drain queue87while (virtqueue_detach_unused_buf(pContext->EvtVq));88
89if (pContext->EvtVA)90{91VirtIOWdfDeviceFreeDmaMemory(&pContext->VDevice.VIODevice, pContext->EvtVA);92pContext->EvtVA = NULL;93}94
95pContext->EvtVq = NULL;96}
97
98_IRQL_requires_max_(PASSIVE_LEVEL)99NTSTATUS
100VIOSockEvtVqInit(101IN PDEVICE_CONTEXT pContext
102)
103{
104NTSTATUS status = STATUS_SUCCESS;105ULONG uRingSize, uHeapSize, uBufferSize;106
107PAGED_CODE();108
109TraceEvents(TRACE_LEVEL_VERBOSE, DBG_HW_ACCESS, "--> %s\n", __FUNCTION__);110
111uBufferSize = sizeof(VIRTIO_VSOCK_EVENT) * VIRTIO_VSOCK_MAX_EVENTS;112
113TraceEvents(TRACE_LEVEL_INFORMATION, DBG_HW_ACCESS, "Allocating common buffer of %u bytes for %u Events\n",114uBufferSize, VIRTIO_VSOCK_MAX_EVENTS);115
116pContext->EvtVA = (PVIRTIO_VSOCK_EVENT)VirtIOWdfDeviceAllocDmaMemory(&pContext->VDevice.VIODevice,117uBufferSize, VIOSOCK_DRIVER_MEMORY_TAG);118
119ASSERT(pContext->EvtVA);120if (!pContext->EvtVA)121{122TraceEvents(TRACE_LEVEL_ERROR, DBG_HW_ACCESS,123"VirtIOWdfDeviceAllocDmaMemory(%u bytes for Events) failed\n", uBufferSize);124status = STATUS_INSUFFICIENT_RESOURCES;125pContext->EvtVq = NULL;126}127else128{129ULONG i;130
131pContext->EvtPA = VirtIOWdfDeviceGetPhysicalAddress(&pContext->VDevice.VIODevice, pContext->EvtVA);132ASSERT(pContext->EvtPA.QuadPart);133
134//fill queue135for (i = 0; i < VIRTIO_VSOCK_MAX_EVENTS; i++)136{137if (!VIOSockEvtPktInsert(pContext, &pContext->EvtVA[i]))138{139status = STATUS_UNSUCCESSFUL;140TraceEvents(TRACE_LEVEL_ERROR, DBG_HW_ACCESS, "VIOSockEventInsert[%u] failed\n", i);141}142}143if (!NT_SUCCESS(status))144VIOSockEvtVqCleanup(pContext);145}146
147TraceEvents(TRACE_LEVEL_VERBOSE, DBG_HW_ACCESS, "<-- %s\n", __FUNCTION__);148
149return status;150}
151
152_IRQL_requires_max_(DISPATCH_LEVEL)153VOID
154VIOSockEvtVqProcess(155IN PDEVICE_CONTEXT pContext
156)
157{
158PVIRTIO_VSOCK_EVENT pEvt;159BOOLEAN bNotify = FALSE, bKick = FALSE;160UINT len;161
162TraceEvents(TRACE_LEVEL_VERBOSE, DBG_HW_ACCESS, "--> %s\n", __FUNCTION__);163
164do165{166virtqueue_disable_cb(pContext->EvtVq);167
168while ((pEvt = (PVIRTIO_VSOCK_EVENT)virtqueue_get_buf(pContext->EvtVq, &len)) != NULL)169{170/* Drop short/long events */171
172if (len != sizeof(pEvt))173{174TraceEvents(TRACE_LEVEL_ERROR, DBG_HW_ACCESS, "Invalid event\n");175}176else177{178ASSERT(pEvt->id == VIRTIO_VSOCK_EVENT_TRANSPORT_RESET);179if (pEvt->id == VIRTIO_VSOCK_EVENT_TRANSPORT_RESET)180{181TraceEvents(TRACE_LEVEL_INFORMATION, DBG_HW_ACCESS, "Reset event occurred\n");182++pContext->EvtRstOccured;183bNotify = TRUE;184}185}186VIOSockEvtPktInsert(pContext, pEvt);187bKick = TRUE;188}189} while (!virtqueue_enable_cb(pContext->EvtVq));190
191
192if (bNotify)193{194VirtIOWdfDeviceGet(&pContext->VDevice,1950,196&pContext->Config,197sizeof(pContext->Config));198
199TraceEvents(TRACE_LEVEL_INFORMATION, DBG_HW_ACCESS,200"New guest_cid %lld\n", pContext->Config.guest_cid);201
202VIOSockHandleTransportReset(pContext);203
204}205
206TraceEvents(TRACE_LEVEL_VERBOSE, DBG_HW_ACCESS, "<-- %s\n", __FUNCTION__);207}
208