kvm-guest-drivers-windows

Форк
0
232 строки · 6.7 Кб
1
/*
2
 * This file contains driver routines
3
 *
4
 * Copyright (C) 2018 Virtuozzo International GmbH
5
 *
6
 */
7
#include "driver.h"
8
#include "fwcfg.h"
9
#include "trace.h"
10
#include "driver.tmh"
11

12
#ifdef ALLOC_PRAGMA
13
#pragma alloc_text(INIT, DriverEntry)
14
#pragma alloc_text(PAGE, FwCfgEvtDeviceAdd)
15
#pragma alloc_text(PAGE, FwCfgEvtDriverCleanup)
16
#endif
17

18
NTSTATUS VMCoreInfoFill(PDEVICE_CONTEXT ctx)
19
{
20
    NTSTATUS status;
21
    PUCHAR hdr_buf;
22
    ULONG bufSizeNeeded;
23

24
    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_ALL, "Obtaining header");
25

26
    hdr_buf = (PUCHAR)ctx->vmci_data.pNote + FIELD_OFFSET(VMCI_ELF64_NOTE, n_desc);
27
    status = KeInitializeCrashDumpHeader(DUMP_TYPE_FULL, 0, hdr_buf,
28
                                         DUMP_HDR_SIZE, &bufSizeNeeded);
29

30
    if (!NT_SUCCESS(status))
31
    {
32
        TraceEvents(TRACE_LEVEL_ERROR, DBG_ALL, "Failed to obtain header");
33
        return status;
34
    }
35

36
    /*
37
     * Original KDBG pointer was saved in header by system.
38
     * BugcheckParameter1 field is unused in live system and will be filled by QEMU.
39
     * So the pointer to decoded KDBG can be stored in this field.
40
     */
41
#ifdef _AMD64_
42
    *(PULONG64)(hdr_buf + DUMP_HDR_OFFSET_BUGCHECK_PARAM1) = (ULONG64)ctx->kdbg;
43
#else
44
    *(PULONG32)(hdr_buf + DUMP_HDR_OFFSET_BUGCHECK_PARAM1) = (ULONG32)ctx->kdbg;
45
#endif
46

47
    return status;
48
}
49

50
NTSTATUS VMCoreInfoSend(PDEVICE_CONTEXT ctx)
51
{
52
    NTSTATUS status;
53

54
    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_ALL, "Sending header");
55

56
    status = FWCfgDmaSend(ctx->ioBase, ctx->vmci_data.vmci_pa, ctx->index,
57
                          sizeof(VMCOREINFO), ctx->dma_access, ctx->dma_access_pa);
58

59
    return status;
60
}
61

62
VOID FwCfgEvtDriverCleanup(IN WDFOBJECT DriverObject)
63
{
64
    UNREFERENCED_PARAMETER(DriverObject);
65

66
    PAGED_CODE();
67

68
    WPP_CLEANUP(WdfDriverWdmGetDriverObject((WDFDRIVER)DriverObject));
69
}
70

71
NTSTATUS GetKdbg(PDEVICE_CONTEXT ctx)
72
{
73
    PUCHAR minidump;
74
    ULONG32 kdbg_offset;
75
    ULONG32 kdbg_size;
76
    CONTEXT context = { 0 };
77
    NTSTATUS status = STATUS_SUCCESS;
78

79
    minidump = ExAllocatePoolUninitialized(NonPagedPoolNx, MINIDUMP_BUFFER_SIZE, 'pmdm');
80
    if (!minidump)
81
    {
82
        return STATUS_MEMORY_NOT_ALLOCATED;
83
    }
84
    memset(minidump, 0, MINIDUMP_BUFFER_SIZE);
85

86
    KeCapturePersistentThreadState(&context, NULL, 0, 0, 0, 0, 0, minidump);
87

88
    kdbg_offset = *(PULONG32)(minidump + MINIDUMP_OFFSET_KDBG_OFFSET);
89
    kdbg_size = *(PULONG32)(minidump + MINIDUMP_OFFSET_KDBG_SIZE);
90

91
    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT,
92
        "KdDebuggerDataBlock size = %lx, offset = 0x%lx",
93
        kdbg_size, kdbg_offset);
94

95
    /*
96
     * KeCapturePersistentThreadState is supposed to save Small Memory Dump to the buffer.
97
     * But since it is undocumented function, the driver should check actual output data.
98
     */
99
    if (kdbg_size == 0 || (kdbg_offset + kdbg_size) > MINIDUMP_BUFFER_SIZE)
100
    {
101
        status = STATUS_INVALID_BUFFER_SIZE;
102
        goto out_free_minidump;
103
    }
104

105
    ctx->kdbg = ExAllocatePoolUninitialized(NonPagedPoolNx, kdbg_size, 'gbdk');
106
    if (!ctx->kdbg)
107
    {
108
        status = STATUS_MEMORY_NOT_ALLOCATED;
109
        goto out_free_minidump;
110
    }
111

112
    memcpy(ctx->kdbg, minidump + kdbg_offset, kdbg_size);
113

114
out_free_minidump:
115
    ExFreePool(minidump);
116

117
    return status;
118
}
119

120
static VOID FwCfgContextInit(PDEVICE_CONTEXT ctx)
121
{
122
    PCBUF_DATA pcbuf_data;
123
    LONGLONG pcbuf_data_pa;
124

125
    pcbuf_data = WdfCommonBufferGetAlignedVirtualAddress(ctx->cbuf);
126
    pcbuf_data_pa = WdfCommonBufferGetAlignedLogicalAddress(ctx->cbuf).QuadPart;
127

128
    ctx->vmci_data.pNote = &pcbuf_data->note;
129
    ctx->vmci_data.note_pa = pcbuf_data_pa + FIELD_OFFSET(CBUF_DATA, note);
130

131
    ctx->vmci_data.pVmci = &pcbuf_data->vmci;
132
    ctx->vmci_data.vmci_pa = pcbuf_data_pa + FIELD_OFFSET(CBUF_DATA, vmci);
133

134
    ctx->dma_access = &pcbuf_data->fwcfg_da;
135
    ctx->dma_access_pa = pcbuf_data_pa + FIELD_OFFSET(CBUF_DATA, fwcfg_da);
136
}
137

138
NTSTATUS FwCfgEvtDeviceAdd(IN WDFDRIVER Driver, IN PWDFDEVICE_INIT DeviceInit)
139
{
140
    NTSTATUS status;
141
    WDF_PNPPOWER_EVENT_CALLBACKS pnpPowerCallbacks;
142
    WDF_OBJECT_ATTRIBUTES attributes;
143
    WDFDEVICE device;
144
    PDEVICE_CONTEXT ctx;
145
    WDF_DMA_ENABLER_CONFIG dmaEnablerConfig;
146
    WDF_DEVICE_STATE devState;
147

148
    UNREFERENCED_PARAMETER(Driver);
149

150
    PAGED_CODE();
151

152
    WDF_PNPPOWER_EVENT_CALLBACKS_INIT(&pnpPowerCallbacks);
153

154
    pnpPowerCallbacks.EvtDevicePrepareHardware = FwCfgEvtDevicePrepareHardware;
155
    pnpPowerCallbacks.EvtDeviceReleaseHardware = FwCfgEvtDeviceReleaseHardware;
156
    pnpPowerCallbacks.EvtDeviceD0Entry = FwCfgEvtDeviceD0Entry;
157
    pnpPowerCallbacks.EvtDeviceD0Exit = FwCfgEvtDeviceD0Exit;
158

159
    WdfDeviceInitSetPnpPowerEventCallbacks(DeviceInit, &pnpPowerCallbacks);
160

161
    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&attributes, DEVICE_CONTEXT);
162

163
    status = WdfDeviceCreate(&DeviceInit, &attributes, &device);
164

165
    if (!NT_SUCCESS(status))
166
    {
167
        TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT,
168
            "WdfDeviceCreate failed: %!STATUS!", status);
169
        return status;
170
    }
171

172
    ctx = GetDeviceContext(device);
173
    memset(ctx, 0, sizeof(*ctx));
174

175
    WDF_DMA_ENABLER_CONFIG_INIT(&dmaEnablerConfig, WdfDmaProfilePacket64,
176
                                sizeof(CBUF_DATA));
177
    status = WdfDmaEnablerCreate(device, &dmaEnablerConfig,
178
                                 WDF_NO_OBJECT_ATTRIBUTES, &ctx->dmaEnabler);
179

180
    if (!NT_SUCCESS(status))
181
    {
182
        TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT,
183
            "Failed to create DMA enabler");
184
        return status;
185
    }
186

187
    TraceEvents(TRACE_LEVEL_VERBOSE, DBG_INIT,
188
        "DMA enabler created");
189

190
    status = WdfCommonBufferCreate(ctx->dmaEnabler, sizeof(CBUF_DATA),
191
                                   WDF_NO_OBJECT_ATTRIBUTES, &ctx->cbuf);
192
    if (!NT_SUCCESS(status))
193
    {
194
        TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT,
195
            "Failed to create common buffer");
196
        return status;
197
    }
198

199
    FwCfgContextInit(ctx);
200

201
    WDF_DEVICE_STATE_INIT(&devState);
202
    devState.NotDisableable = WdfFalse;
203
    WdfDeviceSetDeviceState(device, &devState);
204

205
    return STATUS_SUCCESS;
206
}
207

208
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
209
                     IN PUNICODE_STRING RegistryPath)
210
{
211
    NTSTATUS status;
212
    WDF_DRIVER_CONFIG config;
213
    WDF_OBJECT_ATTRIBUTES attributes;
214

215
    WPP_INIT_TRACING(DriverObject, RegistryPath);
216

217
    WDF_OBJECT_ATTRIBUTES_INIT(&attributes);
218
    attributes.EvtCleanupCallback = FwCfgEvtDriverCleanup;
219

220
    WDF_DRIVER_CONFIG_INIT(&config, FwCfgEvtDeviceAdd);
221

222
    status = WdfDriverCreate(DriverObject, RegistryPath, &attributes,
223
                             &config, WDF_NO_HANDLE);
224
    if (!NT_SUCCESS(status))
225
    {
226
        TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT,
227
                    "WdfDriverCreate failed: %!STATUS!", status);
228
        WPP_CLEANUP(DriverObject);
229
    }
230

231
    return status;
232
}
233

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

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

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

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