kvm-guest-drivers-windows

Форк
0
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
#endif
36

37

38
#ifdef ALLOC_PRAGMA
39
#pragma alloc_text (PAGE, VIOSockEvtVqInit)
40
#pragma alloc_text (PAGE, VIOSockEvtVqCleanup)
41
#endif
42

43
_IRQL_requires_max_(DISPATCH_LEVEL)
44
static
45
BOOLEAN
46
VIOSockEvtPktInsert(
47
    IN PDEVICE_CONTEXT pContext,
48
    IN PVIRTIO_VSOCK_EVENT pEvent
49
)
50
{
51
    BOOLEAN bRes = TRUE;
52
    VIOSOCK_SG_DESC sg;
53
    int ret;
54

55
    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_HW_ACCESS, "--> %s\n", __FUNCTION__);
56

57
    sg.length = sizeof(VIRTIO_VSOCK_EVENT);
58
    sg.physAddr.QuadPart = pContext->EvtPA.QuadPart +
59
        (ULONGLONG)((PCHAR)pEvent - (PCHAR)pContext->EvtVA);
60

61
    ret = virtqueue_add_buf(pContext->EvtVq, &sg, 0, 1, pEvent, NULL, 0);
62

63
    ASSERT(ret >= 0);
64
    if (ret < 0)
65
    {
66
        TraceEvents(TRACE_LEVEL_ERROR, DBG_HW_ACCESS,
67
            "Error adding buffer to Evt queue (ret = %d)\n", ret);
68
        return FALSE;
69
    }
70

71
    return TRUE;
72
}
73

74
_IRQL_requires_max_(PASSIVE_LEVEL)
75
VOID
76
VIOSockEvtVqCleanup(
77
    IN PDEVICE_CONTEXT pContext
78
)
79
{
80
    PAGED_CODE();
81

82
    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_HW_ACCESS, "--> %s\n", __FUNCTION__);
83

84
    ASSERT(pContext->EvtVq && pContext->EvtVA);
85

86
    //drain queue
87
    while (virtqueue_detach_unused_buf(pContext->EvtVq));
88

89
    if (pContext->EvtVA)
90
    {
91
        VirtIOWdfDeviceFreeDmaMemory(&pContext->VDevice.VIODevice, pContext->EvtVA);
92
        pContext->EvtVA = NULL;
93
    }
94

95
    pContext->EvtVq = NULL;
96
}
97

98
_IRQL_requires_max_(PASSIVE_LEVEL)
99
NTSTATUS
100
VIOSockEvtVqInit(
101
    IN PDEVICE_CONTEXT pContext
102
)
103
{
104
    NTSTATUS status = STATUS_SUCCESS;
105
    ULONG uRingSize, uHeapSize, uBufferSize;
106

107
    PAGED_CODE();
108

109
    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_HW_ACCESS, "--> %s\n", __FUNCTION__);
110

111
    uBufferSize = sizeof(VIRTIO_VSOCK_EVENT) * VIRTIO_VSOCK_MAX_EVENTS;
112

113
    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_HW_ACCESS, "Allocating common buffer of %u bytes for %u Events\n",
114
        uBufferSize, VIRTIO_VSOCK_MAX_EVENTS);
115

116
    pContext->EvtVA = (PVIRTIO_VSOCK_EVENT)VirtIOWdfDeviceAllocDmaMemory(&pContext->VDevice.VIODevice,
117
        uBufferSize, VIOSOCK_DRIVER_MEMORY_TAG);
118

119
    ASSERT(pContext->EvtVA);
120
    if (!pContext->EvtVA)
121
    {
122
        TraceEvents(TRACE_LEVEL_ERROR, DBG_HW_ACCESS,
123
            "VirtIOWdfDeviceAllocDmaMemory(%u bytes for Events) failed\n", uBufferSize);
124
        status = STATUS_INSUFFICIENT_RESOURCES;
125
        pContext->EvtVq = NULL;
126
    }
127
    else
128
    {
129
        ULONG i;
130

131
        pContext->EvtPA = VirtIOWdfDeviceGetPhysicalAddress(&pContext->VDevice.VIODevice, pContext->EvtVA);
132
        ASSERT(pContext->EvtPA.QuadPart);
133

134
        //fill queue
135
        for (i = 0; i < VIRTIO_VSOCK_MAX_EVENTS; i++)
136
        {
137
            if (!VIOSockEvtPktInsert(pContext, &pContext->EvtVA[i]))
138
            {
139
                status = STATUS_UNSUCCESSFUL;
140
                TraceEvents(TRACE_LEVEL_ERROR, DBG_HW_ACCESS, "VIOSockEventInsert[%u] failed\n", i);
141
            }
142
        }
143
        if (!NT_SUCCESS(status))
144
            VIOSockEvtVqCleanup(pContext);
145
    }
146

147
    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_HW_ACCESS, "<-- %s\n", __FUNCTION__);
148

149
    return status;
150
}
151

152
_IRQL_requires_max_(DISPATCH_LEVEL)
153
VOID
154
VIOSockEvtVqProcess(
155
    IN PDEVICE_CONTEXT pContext
156
)
157
{
158
    PVIRTIO_VSOCK_EVENT pEvt;
159
    BOOLEAN bNotify = FALSE, bKick = FALSE;
160
    UINT len;
161

162
    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_HW_ACCESS, "--> %s\n", __FUNCTION__);
163

164
    do
165
    {
166
        virtqueue_disable_cb(pContext->EvtVq);
167

168
        while ((pEvt = (PVIRTIO_VSOCK_EVENT)virtqueue_get_buf(pContext->EvtVq, &len)) != NULL)
169
        {
170
            /* Drop short/long events */
171

172
            if (len != sizeof(pEvt))
173
            {
174
                TraceEvents(TRACE_LEVEL_ERROR, DBG_HW_ACCESS, "Invalid event\n");
175
            }
176
            else
177
            {
178
                ASSERT(pEvt->id == VIRTIO_VSOCK_EVENT_TRANSPORT_RESET);
179
                if (pEvt->id == VIRTIO_VSOCK_EVENT_TRANSPORT_RESET)
180
                {
181
                    TraceEvents(TRACE_LEVEL_INFORMATION, DBG_HW_ACCESS, "Reset event occurred\n");
182
                    ++pContext->EvtRstOccured;
183
                    bNotify = TRUE;
184
                }
185
            }
186
            VIOSockEvtPktInsert(pContext, pEvt);
187
            bKick = TRUE;
188
        }
189
    } while (!virtqueue_enable_cb(pContext->EvtVq));
190

191

192
    if (bNotify)
193
    {
194
        VirtIOWdfDeviceGet(&pContext->VDevice,
195
            0,
196
            &pContext->Config,
197
            sizeof(pContext->Config));
198

199
        TraceEvents(TRACE_LEVEL_INFORMATION, DBG_HW_ACCESS,
200
            "New guest_cid %lld\n", pContext->Config.guest_cid);
201

202
        VIOSockHandleTransportReset(pContext);
203

204
    }
205

206
    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_HW_ACCESS, "<-- %s\n", __FUNCTION__);
207
}
208

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.