kvm-guest-drivers-windows

Форк
0
208 строк · 7.0 Кб
1
/*
2
 * Implementation of virtio_system_ops VirtioLib callbacks
3
 *
4
 * Copyright (c) 2016-2017 Red Hat, Inc.
5
 *
6
 * Author(s):
7
 *  Ladi Prosek <lprosek@redhat.com>
8
 *
9
 * Redistribution and use in source and binary forms, with or without
10
 * modification, are permitted provided that the following conditions
11
 * are met :
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 * 2. Redistributions in binary form must reproduce the above copyright
15
 *    notice, this list of conditions and the following disclaimer in the
16
 *    documentation and / or other materials provided with the distribution.
17
 * 3. Neither the names of the copyright holders nor the names of their contributors
18
 *    may be used to endorse or promote products derived from this software
19
 *    without specific prior written permission.
20
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
21
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23
 * ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
24
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30
 * SUCH DAMAGE.
31
 */
32
#include "osdep.h"
33
#include "virtio_pci.h"
34
#include "VirtIOWdf.h"
35
#include "private.h"
36

37
static void *mem_alloc_contiguous_pages(void *context, size_t size)
38
{
39
    PVIRTIO_WDF_DRIVER pWdfDriver = context;
40

41
    return VirtIOWdfDeviceAllocDmaMemory(&pWdfDriver->VIODevice, size, 0);
42
}
43

44
static void mem_free_contiguous_pages(void *context, void *virt)
45
{
46
    PVIRTIO_WDF_DRIVER pWdfDriver = context;
47

48
    VirtIOWdfDeviceFreeDmaMemory(&pWdfDriver->VIODevice, virt);
49
}
50

51
static ULONGLONG mem_get_physical_address(void *context, void *virt)
52
{
53
    PVIRTIO_WDF_DRIVER pWdfDriver = context;
54
    PHYSICAL_ADDRESS pa;
55

56
    pa = VirtIOWdfDeviceGetPhysicalAddress(&pWdfDriver->VIODevice, virt);
57

58
    if (!pa.QuadPart) {
59
        DPrintf(0, "%s WARNING: got zero physical address\n", __FUNCTION__);
60
    }
61
    return pa.QuadPart;
62
}
63

64
static void *mem_alloc_nonpaged_block(void *context, size_t size)
65
{
66
    PVIRTIO_WDF_DRIVER pWdfDriver = (PVIRTIO_WDF_DRIVER)context;
67

68
    PVOID addr = ExAllocatePoolUninitialized(
69
        NonPagedPool,
70
        size,
71
        pWdfDriver->MemoryTag);
72
    if (addr) {
73
        RtlZeroMemory(addr, size);
74
    }
75
    return addr;
76
}
77

78
static void mem_free_nonpaged_block(void *context, void *addr)
79
{
80
    PVIRTIO_WDF_DRIVER pWdfDriver = (PVIRTIO_WDF_DRIVER)context;
81

82
    ExFreePoolWithTag(
83
        addr,
84
        pWdfDriver->MemoryTag);
85
}
86

87
static int pci_read_config_byte(void *context, int where, u8 *bVal)
88
{
89
    return PCIReadConfig((PVIRTIO_WDF_DRIVER)context, where, bVal, sizeof(*bVal));
90
}
91

92
static int pci_read_config_word(void *context, int where, u16 *wVal)
93
{
94
    return PCIReadConfig((PVIRTIO_WDF_DRIVER)context, where, wVal, sizeof(*wVal));
95
}
96

97
static int pci_read_config_dword(void *context, int where, u32 *dwVal)
98
{
99
    return PCIReadConfig((PVIRTIO_WDF_DRIVER)context, where, dwVal, sizeof(*dwVal));
100
}
101

102
static PVIRTIO_WDF_BAR find_bar(void *context, int bar)
103
{
104
    PVIRTIO_WDF_DRIVER pWdfDriver = (PVIRTIO_WDF_DRIVER)context;
105
    PSINGLE_LIST_ENTRY iter = &pWdfDriver->PCIBars;
106
    
107
    while (iter->Next != NULL) {
108
        PVIRTIO_WDF_BAR pBar = CONTAINING_RECORD(iter->Next, VIRTIO_WDF_BAR, ListEntry);
109
        if (pBar->iBar == bar) {
110
            return pBar;
111
        }
112
        iter = iter->Next;
113
    }
114
    return NULL;
115
}
116

117
static size_t pci_get_resource_len(void *context, int bar)
118
{
119
    PVIRTIO_WDF_BAR pBar = find_bar(context, bar);
120
    return (pBar ? pBar->uLength : 0);
121
}
122

123
static void *pci_map_address_range(void *context, int bar, size_t offset, size_t maxlen)
124
{
125
    PVIRTIO_WDF_BAR pBar = find_bar(context, bar);
126
    if (pBar) {
127
        if (pBar->pBase == NULL) {
128
            ASSERT(!pBar->bPortSpace);
129
#if defined(NTDDI_WINTHRESHOLD) && (NTDDI_VERSION >= NTDDI_WINTHRESHOLD)
130
            pBar->pBase = MmMapIoSpaceEx(
131
                pBar->BasePA,
132
                pBar->uLength,
133
                PAGE_READWRITE | PAGE_NOCACHE);
134
#else
135
            pBar->pBase = MmMapIoSpace(pBar->BasePA, pBar->uLength, MmNonCached);
136
#endif
137
        }
138
        if (pBar->pBase != NULL && offset < pBar->uLength) {
139
            return (char *)pBar->pBase + offset;
140
        }
141
    }
142
    return NULL;
143
}
144

145
static u16 vdev_get_msix_vector(void *context, int queue)
146
{
147
    PVIRTIO_WDF_DRIVER pWdfDriver = (PVIRTIO_WDF_DRIVER)context;
148
    u16 vector = VIRTIO_MSI_NO_VECTOR;
149

150
    if (queue >= 0) {
151
        /* queue interrupt */
152
        if (pWdfDriver->pQueueParams != NULL) {
153
            vector = PCIGetMSIInterruptVector(pWdfDriver->pQueueParams[queue].Interrupt);
154
        }
155
    }
156
    else {
157
        /* on-device-config-change interrupt */
158
        vector = PCIGetMSIInterruptVector(pWdfDriver->ConfigInterrupt);
159
    }
160

161
    return vector;
162
}
163

164
static void vdev_sleep(void *context, unsigned int msecs)
165
{
166
    NTSTATUS status = STATUS_UNSUCCESSFUL;
167

168
    UNREFERENCED_PARAMETER(context);
169

170
    if (KeGetCurrentIrql() <= APC_LEVEL) {
171
        LARGE_INTEGER delay;
172
        delay.QuadPart = Int32x32To64(msecs, -10000);
173
        status = KeDelayExecutionThread(KernelMode, FALSE, &delay);
174
    }
175

176
    if (!NT_SUCCESS(status)) {
177
        /* fall back to busy wait if we're not allowed to sleep */
178
        KeStallExecutionProcessor(1000 * msecs);
179
    }
180
}
181

182
extern u32 ReadVirtIODeviceRegister(ULONG_PTR ulRegister);
183
extern void WriteVirtIODeviceRegister(ULONG_PTR ulRegister, u32 ulValue);
184
extern u8 ReadVirtIODeviceByte(ULONG_PTR ulRegister);
185
extern void WriteVirtIODeviceByte(ULONG_PTR ulRegister, u8 bValue);
186
extern u16 ReadVirtIODeviceWord(ULONG_PTR ulRegister);
187
extern void WriteVirtIODeviceWord(ULONG_PTR ulRegister, u16 bValue);
188

189
VirtIOSystemOps VirtIOWdfSystemOps = {
190
    .vdev_read_byte = ReadVirtIODeviceByte,
191
    .vdev_read_word = ReadVirtIODeviceWord,
192
    .vdev_read_dword = ReadVirtIODeviceRegister,
193
    .vdev_write_byte = WriteVirtIODeviceByte,
194
    .vdev_write_word = WriteVirtIODeviceWord,
195
    .vdev_write_dword = WriteVirtIODeviceRegister,
196
    .mem_alloc_contiguous_pages = mem_alloc_contiguous_pages,
197
    .mem_free_contiguous_pages = mem_free_contiguous_pages,
198
    .mem_get_physical_address = mem_get_physical_address,
199
    .mem_alloc_nonpaged_block = mem_alloc_nonpaged_block,
200
    .mem_free_nonpaged_block = mem_free_nonpaged_block,
201
    .pci_read_config_byte = pci_read_config_byte,
202
    .pci_read_config_word = pci_read_config_word,
203
    .pci_read_config_dword = pci_read_config_dword,
204
    .pci_get_resource_len = pci_get_resource_len,
205
    .pci_map_address_range = pci_map_address_range,
206
    .vdev_get_msix_vector = vdev_get_msix_vector,
207
    .vdev_sleep = vdev_sleep,
208
};
209

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

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

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

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