kvm-guest-drivers-windows
602 строки · 19.6 Кб
1/*
2* Virtio PCI driver - modern (virtio 1.0) device support
3*
4* Copyright IBM Corp. 2007
5* Copyright Red Hat, Inc. 2014
6*
7* Authors:
8* Anthony Liguori <aliguori@us.ibm.com>
9* Rusty Russell <rusty@rustcorp.com.au>
10* Michael S. Tsirkin <mst@redhat.com>
11*
12* Redistribution and use in source and binary forms, with or without
13* modification, are permitted provided that the following conditions
14* are met :
15* 1. Redistributions of source code must retain the above copyright
16* notice, this list of conditions and the following disclaimer.
17* 2. Redistributions in binary form must reproduce the above copyright
18* notice, this list of conditions and the following disclaimer in the
19* documentation and / or other materials provided with the distribution.
20* 3. Neither the names of the copyright holders nor the names of their contributors
21* may be used to endorse or promote products derived from this software
22* without specific prior written permission.
23* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
24* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26* ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
27* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33* SUCH DAMAGE.
34*/
35#include "osdep.h"
36#define VIRTIO_PCI_NO_LEGACY
37#include "virtio_pci.h"
38#include "virtio.h"
39#include "kdebugprint.h"
40#include "virtio_ring.h"
41#include "virtio_pci_common.h"
42#include "windows\virtio_ring_allocation.h"
43#include <stddef.h>
44
45#ifdef WPP_EVENT_TRACING
46#include "VirtIOPCIModern.tmh"
47#endif
48
49static void *vio_modern_map_capability(VirtIODevice *vdev, int cap_offset,
50size_t minlen, u32 alignment,
51u32 start, u32 size, size_t *len)
52{
53u8 bar;
54u32 bar_offset, bar_length;
55void *addr;
56
57pci_read_config_byte(vdev, cap_offset + offsetof(struct virtio_pci_cap, bar), &bar);
58pci_read_config_dword(vdev, cap_offset + offsetof(struct virtio_pci_cap, offset), &bar_offset);
59pci_read_config_dword(vdev, cap_offset + offsetof(struct virtio_pci_cap, length), &bar_length);
60
61if (start + minlen > bar_length) {
62DPrintf(0, "bar %i cap is not large enough to map %zu bytes at offset %u\n", bar, minlen, start);
63return NULL;
64}
65
66bar_length -= start;
67bar_offset += start;
68
69if (bar_offset & (alignment - 1)) {
70DPrintf(0, "bar %i offset %u not aligned to %u\n", bar, bar_offset, alignment);
71return NULL;
72}
73
74if (bar_length > size) {
75bar_length = size;
76}
77
78if (len) {
79*len = bar_length;
80}
81
82if (bar_offset + minlen > pci_get_resource_len(vdev, bar)) {
83DPrintf(0, "bar %i is not large enough to map %zu bytes at offset %u\n", bar, minlen, bar_offset);
84return NULL;
85}
86
87addr = pci_map_address_range(vdev, bar, bar_offset, bar_length);
88if (!addr) {
89DPrintf(0, "unable to map %u bytes at bar %i offset %u\n", bar_length, bar, bar_offset);
90}
91return addr;
92}
93
94static void *vio_modern_map_simple_capability(VirtIODevice *vdev, int cap_offset, size_t length, u32 alignment)
95{
96return vio_modern_map_capability(
97vdev,
98cap_offset,
99length, // minlen
100alignment,
1010, // offset
102(u32)length, // size is equal to minlen
103NULL); // not interested in the full length
104}
105
106static void vio_modern_get_config(VirtIODevice *vdev, unsigned offset,
107void *buf, unsigned len)
108{
109if (!vdev->config) {
110ASSERT(!"Device has no config to read");
111return;
112}
113if (offset + len > vdev->config_len) {
114ASSERT(!"Can't read beyond the config length");
115return;
116}
117
118switch (len) {
119case 1:
120*(u8 *)buf = ioread8(vdev, vdev->config + offset);
121break;
122case 2:
123*(u16 *)buf = ioread16(vdev, vdev->config + offset);
124break;
125case 4:
126*(u32 *)buf = ioread32(vdev, vdev->config + offset);
127break;
128default:
129ASSERT(!"Only 1, 2, 4 byte config reads are supported");
130}
131}
132
133static void vio_modern_set_config(VirtIODevice *vdev, unsigned offset,
134const void *buf, unsigned len)
135{
136if (!vdev->config) {
137ASSERT(!"Device has no config to write");
138return;
139}
140if (offset + len > vdev->config_len) {
141ASSERT(!"Can't write beyond the config length");
142return;
143}
144
145switch (len) {
146case 1:
147iowrite8(vdev, *(u8 *)buf, vdev->config + offset);
148break;
149case 2:
150iowrite16(vdev, *(u16 *)buf, vdev->config + offset);
151break;
152case 4:
153iowrite32(vdev, *(u32 *)buf, vdev->config + offset);
154break;
155default:
156ASSERT(!"Only 1, 2, 4 byte config writes are supported");
157}
158}
159
160static u32 vio_modern_get_generation(VirtIODevice *vdev)
161{
162return ioread8(vdev, &vdev->common->config_generation);
163}
164
165static u8 vio_modern_get_status(VirtIODevice *vdev)
166{
167return ioread8(vdev, &vdev->common->device_status);
168}
169
170static void vio_modern_set_status(VirtIODevice *vdev, u8 status)
171{
172/* We should never be setting status to 0. */
173ASSERT(status != 0);
174iowrite8(vdev, status, &vdev->common->device_status);
175}
176
177static void vio_modern_reset(VirtIODevice *vdev)
178{
179/* 0 status means a reset. */
180iowrite8(vdev, 0, &vdev->common->device_status);
181/* After writing 0 to device_status, the driver MUST wait for a read of
182* device_status to return 0 before reinitializing the device.
183* This will flush out the status write, and flush in device writes,
184* including MSI-X interrupts, if any.
185*/
186while (ioread8(vdev, &vdev->common->device_status)) {
187u16 val;
188if (pci_read_config_word(vdev, 0, &val) || val == 0xffff) {
189DPrintf(0, ("PCI config space is not readable, probably the device is removed\n"));
190break;
191}
192vdev_sleep(vdev, 1);
193}
194}
195
196static u64 vio_modern_get_features(VirtIODevice *vdev)
197{
198u64 features;
199
200iowrite32(vdev, 0, &vdev->common->device_feature_select);
201features = ioread32(vdev, &vdev->common->device_feature);
202iowrite32(vdev, 1, &vdev->common->device_feature_select);
203features |= ((u64)ioread32(vdev, &vdev->common->device_feature) << 32);
204
205return features;
206}
207
208static NTSTATUS vio_modern_set_features(VirtIODevice *vdev, u64 features)
209{
210/* Give virtio_ring a chance to accept features. */
211vring_transport_features(vdev, &features);
212
213if (!virtio_is_feature_enabled(features, VIRTIO_F_VERSION_1)) {
214DPrintf(0, ("virtio: device uses modern interface but does not have VIRTIO_F_VERSION_1\n"));
215return STATUS_INVALID_PARAMETER;
216}
217
218iowrite32(vdev, 0, &vdev->common->guest_feature_select);
219iowrite32(vdev, (u32)features, &vdev->common->guest_feature);
220iowrite32(vdev, 1, &vdev->common->guest_feature_select);
221iowrite32(vdev, features >> 32, &vdev->common->guest_feature);
222
223return STATUS_SUCCESS;
224}
225
226static u16 vio_modern_set_config_vector(VirtIODevice *vdev, u16 vector)
227{
228/* Setup the vector used for configuration events */
229iowrite16(vdev, vector, &vdev->common->msix_config);
230/* Verify we had enough resources to assign the vector */
231/* Will also flush the write out to device */
232return ioread16(vdev, &vdev->common->msix_config);
233}
234
235static u16 vio_modern_set_queue_vector(struct virtqueue *vq, u16 vector)
236{
237VirtIODevice *vdev = vq->vdev;
238volatile struct virtio_pci_common_cfg *cfg = vdev->common;
239
240iowrite16(vdev, (u16)vq->index, &cfg->queue_select);
241iowrite16(vdev, vector, &cfg->queue_msix_vector);
242return ioread16(vdev, &cfg->queue_msix_vector);
243}
244
245static size_t vring_pci_size(u16 num, bool packed)
246{
247/* We only need a cacheline separation. */
248return (size_t)ROUND_TO_PAGES(vring_size(num, SMP_CACHE_BYTES, packed));
249}
250
251static NTSTATUS vio_modern_query_vq_alloc(VirtIODevice *vdev,
252unsigned index,
253unsigned short *pNumEntries,
254unsigned long *pRingSize,
255unsigned long *pHeapSize)
256{
257volatile struct virtio_pci_common_cfg *cfg = vdev->common;
258u16 num;
259
260if (index >= ioread16(vdev, &cfg->num_queues)) {
261return STATUS_NOT_FOUND;
262}
263
264/* Select the queue we're interested in */
265iowrite16(vdev, (u16)index, &cfg->queue_select);
266
267/* Check if queue is either not available or already active. */
268num = ioread16(vdev, &cfg->queue_size);
269/* QEMU has a bug where queues don't revert to inactive on device
270* reset. Skip checking the queue_enable field until it is fixed.
271*/
272if (!num /*|| ioread16(vdev, &cfg->queue_enable)*/) {
273return STATUS_NOT_FOUND;
274}
275
276if (num & (num - 1)) {
277DPrintf(0, "%p: bad queue size %u", vdev, num);
278return STATUS_INVALID_PARAMETER;
279}
280
281*pNumEntries = num;
282*pRingSize = (unsigned long)vring_pci_size(num, vdev->packed_ring);
283*pHeapSize = vring_control_block_size(num, vdev->packed_ring);
284
285return STATUS_SUCCESS;
286}
287
288static NTSTATUS vio_modern_setup_vq(struct virtqueue **queue,
289VirtIODevice *vdev,
290VirtIOQueueInfo *info,
291unsigned index,
292u16 msix_vec)
293{
294volatile struct virtio_pci_common_cfg *cfg = vdev->common;
295struct virtqueue *vq;
296void *vq_addr;
297u16 off;
298unsigned long ring_size, heap_size;
299NTSTATUS status;
300
301/* select the queue and query allocation parameters */
302status = vio_modern_query_vq_alloc(vdev, index, &info->num, &ring_size, &heap_size);
303if (!NT_SUCCESS(status)) {
304return status;
305}
306
307/* get offset of notification word for this vq */
308off = ioread16(vdev, &cfg->queue_notify_off);
309
310/* try to allocate contiguous pages, scale down on failure */
311while (!(info->queue = mem_alloc_contiguous_pages(vdev, vring_pci_size(info->num, vdev->packed_ring)))) {
312if (info->num > 0) {
313info->num /= 2;
314} else {
315return STATUS_INSUFFICIENT_RESOURCES;
316}
317}
318
319vq_addr = mem_alloc_nonpaged_block(vdev, heap_size);
320if (vq_addr == NULL) {
321return STATUS_INSUFFICIENT_RESOURCES;
322}
323
324/* create the vring */
325if (vdev->packed_ring) {
326vq = vring_new_virtqueue_packed(index, info->num,
327SMP_CACHE_BYTES, vdev,
328info->queue, vp_notify, vq_addr);
329} else {
330vq = vring_new_virtqueue_split(index, info->num,
331SMP_CACHE_BYTES, vdev,
332info->queue, vp_notify, vq_addr);
333}
334
335if (!vq) {
336status = STATUS_INSUFFICIENT_RESOURCES;
337goto err_new_queue;
338}
339
340/* activate the queue */
341iowrite16(vdev, info->num, &cfg->queue_size);
342iowrite64_twopart(vdev, mem_get_physical_address(vdev, info->queue),
343&cfg->queue_desc_lo, &cfg->queue_desc_hi);
344iowrite64_twopart(vdev, mem_get_physical_address(vdev, vq->avail_va),
345&cfg->queue_avail_lo, &cfg->queue_avail_hi);
346iowrite64_twopart(vdev, mem_get_physical_address(vdev, vq->used_va),
347&cfg->queue_used_lo, &cfg->queue_used_hi);
348
349if (vdev->notify_base) {
350/* offset should not wrap */
351if ((u64)off * vdev->notify_offset_multiplier + 2
352> vdev->notify_len) {
353DPrintf(0,
354"%p: bad notification offset %u (x %u) "
355"for queue %u > %zd",
356vdev,
357off, vdev->notify_offset_multiplier,
358index, vdev->notify_len);
359status = STATUS_INVALID_PARAMETER;
360goto err_map_notify;
361}
362vq->notification_addr = (void *)(vdev->notify_base +
363off * vdev->notify_offset_multiplier);
364} else {
365vq->notification_addr = vio_modern_map_capability(vdev,
366vdev->notify_map_cap, 2, 2,
367off * vdev->notify_offset_multiplier, 2,
368NULL);
369}
370
371if (!vq->notification_addr) {
372status = STATUS_INSUFFICIENT_RESOURCES;
373goto err_map_notify;
374}
375
376if (msix_vec != VIRTIO_MSI_NO_VECTOR) {
377msix_vec = vdev->device->set_queue_vector(vq, msix_vec);
378if (msix_vec == VIRTIO_MSI_NO_VECTOR) {
379status = STATUS_DEVICE_BUSY;
380goto err_assign_vector;
381}
382}
383
384/* enable the queue */
385iowrite16(vdev, 1, &vdev->common->queue_enable);
386
387*queue = vq;
388return STATUS_SUCCESS;
389
390err_assign_vector:
391err_map_notify:
392virtqueue_shutdown(vq);
393err_new_queue:
394mem_free_nonpaged_block(vdev, vq_addr);
395mem_free_contiguous_pages(vdev, info->queue);
396return status;
397}
398
399static void vio_modern_del_vq(VirtIOQueueInfo *info)
400{
401struct virtqueue *vq = info->vq;
402VirtIODevice *vdev = vq->vdev;
403
404iowrite16(vdev, (u16)vq->index, &vdev->common->queue_select);
405
406if (vdev->msix_used) {
407iowrite16(vdev, VIRTIO_MSI_NO_VECTOR, &vdev->common->queue_msix_vector);
408/* Flush the write out to device */
409ioread16(vdev, &vdev->common->queue_msix_vector);
410}
411
412virtqueue_shutdown(vq);
413
414mem_free_nonpaged_block(vdev, vq);
415mem_free_contiguous_pages(vdev, info->queue);
416}
417
418static const struct virtio_device_ops virtio_pci_device_ops = {
419.get_config = vio_modern_get_config,
420.set_config = vio_modern_set_config,
421.get_config_generation = vio_modern_get_generation,
422.get_status = vio_modern_get_status,
423.set_status = vio_modern_set_status,
424.reset = vio_modern_reset,
425.get_features = vio_modern_get_features,
426.set_features = vio_modern_set_features,
427.set_config_vector = vio_modern_set_config_vector,
428.set_queue_vector = vio_modern_set_queue_vector,
429.query_queue_alloc = vio_modern_query_vq_alloc,
430.setup_queue = vio_modern_setup_vq,
431.delete_queue = vio_modern_del_vq,
432};
433
434static u8 find_next_pci_vendor_capability(VirtIODevice *vdev, u8 offset)
435{
436u8 id = 0;
437int iterations = 48;
438
439if (pci_read_config_byte(vdev, offset, &offset) != 0) {
440return 0;
441}
442
443while (iterations-- && offset >= 0x40) {
444offset &= ~3;
445if (pci_read_config_byte(vdev, offset + offsetof(PCI_CAPABILITIES_HEADER,
446CapabilityID), &id) != 0) {
447break;
448}
449if (id == 0xFF) {
450break;
451}
452if (id == PCI_CAPABILITY_ID_VENDOR_SPECIFIC) {
453return offset;
454}
455if (pci_read_config_byte(vdev, offset + offsetof(PCI_CAPABILITIES_HEADER,
456Next), &offset) != 0) {
457break;
458}
459}
460return 0;
461}
462
463static u8 find_first_pci_vendor_capability(VirtIODevice *vdev)
464{
465u8 hdr_type, offset;
466u16 status;
467
468if (pci_read_config_byte(vdev, offsetof(PCI_COMMON_HEADER, HeaderType), &hdr_type) != 0) {
469return 0;
470}
471if (pci_read_config_word(vdev, offsetof(PCI_COMMON_HEADER, Status), &status) != 0) {
472return 0;
473}
474if ((status & PCI_STATUS_CAPABILITIES_LIST) == 0) {
475return 0;
476}
477
478switch (hdr_type & ~PCI_MULTIFUNCTION) {
479case PCI_BRIDGE_TYPE:
480offset = offsetof(PCI_COMMON_HEADER, u.type1.CapabilitiesPtr);
481break;
482case PCI_CARDBUS_BRIDGE_TYPE:
483offset = offsetof(PCI_COMMON_HEADER, u.type2.CapabilitiesPtr);
484break;
485default:
486offset = offsetof(PCI_COMMON_HEADER, u.type0.CapabilitiesPtr);
487break;
488}
489
490if (offset != 0) {
491offset = find_next_pci_vendor_capability(vdev, offset);
492}
493return offset;
494}
495
496/* Populate Offsets with virtio vendor capability offsets within the PCI config space */
497static void find_pci_vendor_capabilities(VirtIODevice *vdev, int *Offsets, size_t nOffsets)
498{
499u8 offset = find_first_pci_vendor_capability(vdev);
500while (offset > 0) {
501u8 cfg_type, bar;
502pci_read_config_byte(vdev, offset + offsetof(struct virtio_pci_cap, cfg_type), &cfg_type);
503pci_read_config_byte(vdev, offset + offsetof(struct virtio_pci_cap, bar), &bar);
504
505if (bar < PCI_TYPE0_ADDRESSES &&
506cfg_type < nOffsets &&
507pci_get_resource_len(vdev, bar) > 0) {
508Offsets[cfg_type] = offset;
509}
510
511offset = find_next_pci_vendor_capability(vdev, offset + offsetof(PCI_CAPABILITIES_HEADER, Next));
512}
513}
514
515/* Modern device initialization */
516NTSTATUS vio_modern_initialize(VirtIODevice *vdev)
517{
518int capabilities[VIRTIO_PCI_CAP_PCI_CFG];
519
520u32 notify_length;
521u32 notify_offset;
522
523RtlZeroMemory(capabilities, sizeof(capabilities));
524find_pci_vendor_capabilities(vdev, capabilities, VIRTIO_PCI_CAP_PCI_CFG);
525
526/* Check for a common config, if not found use legacy mode */
527if (!capabilities[VIRTIO_PCI_CAP_COMMON_CFG]) {
528DPrintf(0, "%s(%p): device not found\n", __FUNCTION__, vdev);
529return STATUS_DEVICE_NOT_CONNECTED;
530}
531
532/* Check isr and notify caps, if not found fail */
533if (!capabilities[VIRTIO_PCI_CAP_ISR_CFG] || !capabilities[VIRTIO_PCI_CAP_NOTIFY_CFG]) {
534DPrintf(0, "%s(%p): missing capabilities %i/%i/%i\n",
535__FUNCTION__, vdev,
536capabilities[VIRTIO_PCI_CAP_COMMON_CFG],
537capabilities[VIRTIO_PCI_CAP_ISR_CFG],
538capabilities[VIRTIO_PCI_CAP_NOTIFY_CFG]);
539return STATUS_INVALID_PARAMETER;
540}
541
542/* Map bars according to the capabilities */
543vdev->common = vio_modern_map_simple_capability(vdev,
544capabilities[VIRTIO_PCI_CAP_COMMON_CFG],
545sizeof(struct virtio_pci_common_cfg), 4);
546if (!vdev->common) {
547return STATUS_INVALID_PARAMETER;
548}
549
550vdev->isr = vio_modern_map_simple_capability(vdev,
551capabilities[VIRTIO_PCI_CAP_ISR_CFG],
552sizeof(u8), 1);
553if (!vdev->isr) {
554return STATUS_INVALID_PARAMETER;
555}
556
557/* Read notify_off_multiplier from config space. */
558pci_read_config_dword(vdev,
559capabilities[VIRTIO_PCI_CAP_NOTIFY_CFG] + offsetof(struct virtio_pci_notify_cap,
560notify_off_multiplier),
561&vdev->notify_offset_multiplier);
562
563/* Read notify length and offset from config space. */
564pci_read_config_dword(vdev,
565capabilities[VIRTIO_PCI_CAP_NOTIFY_CFG] + offsetof(struct virtio_pci_notify_cap,
566cap.length),
567¬ify_length);
568pci_read_config_dword(vdev,
569capabilities[VIRTIO_PCI_CAP_NOTIFY_CFG] + offsetof(struct virtio_pci_notify_cap,
570cap.offset),
571¬ify_offset);
572
573/* Map the notify capability if it's small enough.
574* Otherwise, map each VQ individually later.
575*/
576if (notify_length + (notify_offset % PAGE_SIZE) <= PAGE_SIZE) {
577vdev->notify_base = vio_modern_map_capability(vdev,
578capabilities[VIRTIO_PCI_CAP_NOTIFY_CFG], 2, 2,
5790, notify_length,
580&vdev->notify_len);
581if (!vdev->notify_base) {
582return STATUS_INVALID_PARAMETER;
583}
584} else {
585vdev->notify_map_cap = capabilities[VIRTIO_PCI_CAP_NOTIFY_CFG];
586}
587
588/* Map the device config capability, the PAGE_SIZE size is a guess */
589if (capabilities[VIRTIO_PCI_CAP_DEVICE_CFG]) {
590vdev->config = vio_modern_map_capability(vdev,
591capabilities[VIRTIO_PCI_CAP_DEVICE_CFG], 0, 4,
5920, PAGE_SIZE,
593&vdev->config_len);
594if (!vdev->config) {
595return STATUS_INVALID_PARAMETER;
596}
597}
598
599vdev->device = &virtio_pci_device_ops;
600
601return STATUS_SUCCESS;
602}
603