]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/Library/VirtioLib/VirtioLib.c
OvmfPkg/VirtioMmioDeviceLib: list "VirtioMmioDevice.h" in the INF file
[mirror_edk2.git] / OvmfPkg / Library / VirtioLib / VirtioLib.c
1 /** @file
2
3 Utility functions used by virtio device drivers.
4
5 Copyright (C) 2012-2016, Red Hat, Inc.
6 Portion of Copyright (C) 2013, ARM Ltd.
7 Copyright (C) 2017, AMD Inc, All rights reserved.<BR>
8
9 This program and the accompanying materials are licensed and made available
10 under the terms and conditions of the BSD License which accompanies this
11 distribution. The full text of the license may be found at
12 http://opensource.org/licenses/bsd-license.php
13
14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
15 WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16
17 **/
18
19 #include <Library/BaseLib.h>
20 #include <Library/BaseMemoryLib.h>
21 #include <Library/DebugLib.h>
22 #include <Library/UefiBootServicesTableLib.h>
23
24 #include <Library/VirtioLib.h>
25
26
27 /**
28
29 Configure a virtio ring.
30
31 This function sets up internal storage (the guest-host communication area)
32 and lays out several "navigation" (ie. no-ownership) pointers to parts of
33 that storage.
34
35 Relevant sections from the virtio-0.9.5 spec:
36 - 1.1 Virtqueues,
37 - 2.3 Virtqueue Configuration.
38
39 @param[in] VirtIo The virtio device which will use the ring.
40
41 @param[in] The number of descriptors to allocate for the
42 virtio ring, as requested by the host.
43
44 @param[out] Ring The virtio ring to set up.
45
46 @return Status codes propagated from
47 VirtIo->AllocateSharedPages().
48
49 @retval EFI_SUCCESS Allocation and setup successful. Ring->Base
50 (and nothing else) is responsible for
51 deallocation.
52
53 **/
54 EFI_STATUS
55 EFIAPI
56 VirtioRingInit (
57 IN VIRTIO_DEVICE_PROTOCOL *VirtIo,
58 IN UINT16 QueueSize,
59 OUT VRING *Ring
60 )
61 {
62 EFI_STATUS Status;
63 UINTN RingSize;
64 volatile UINT8 *RingPagesPtr;
65
66 RingSize = ALIGN_VALUE (
67 sizeof *Ring->Desc * QueueSize +
68 sizeof *Ring->Avail.Flags +
69 sizeof *Ring->Avail.Idx +
70 sizeof *Ring->Avail.Ring * QueueSize +
71 sizeof *Ring->Avail.UsedEvent,
72 EFI_PAGE_SIZE);
73
74 RingSize += ALIGN_VALUE (
75 sizeof *Ring->Used.Flags +
76 sizeof *Ring->Used.Idx +
77 sizeof *Ring->Used.UsedElem * QueueSize +
78 sizeof *Ring->Used.AvailEvent,
79 EFI_PAGE_SIZE);
80
81 //
82 // Allocate a shared ring buffer
83 //
84 Ring->NumPages = EFI_SIZE_TO_PAGES (RingSize);
85 Status = VirtIo->AllocateSharedPages (
86 VirtIo,
87 Ring->NumPages,
88 &Ring->Base
89 );
90 if (EFI_ERROR (Status)) {
91 return Status;
92 }
93 SetMem (Ring->Base, RingSize, 0x00);
94 RingPagesPtr = Ring->Base;
95
96 Ring->Desc = (volatile VOID *) RingPagesPtr;
97 RingPagesPtr += sizeof *Ring->Desc * QueueSize;
98
99 Ring->Avail.Flags = (volatile VOID *) RingPagesPtr;
100 RingPagesPtr += sizeof *Ring->Avail.Flags;
101
102 Ring->Avail.Idx = (volatile VOID *) RingPagesPtr;
103 RingPagesPtr += sizeof *Ring->Avail.Idx;
104
105 Ring->Avail.Ring = (volatile VOID *) RingPagesPtr;
106 RingPagesPtr += sizeof *Ring->Avail.Ring * QueueSize;
107
108 Ring->Avail.UsedEvent = (volatile VOID *) RingPagesPtr;
109 RingPagesPtr += sizeof *Ring->Avail.UsedEvent;
110
111 RingPagesPtr = (volatile UINT8 *) Ring->Base +
112 ALIGN_VALUE (RingPagesPtr - (volatile UINT8 *) Ring->Base,
113 EFI_PAGE_SIZE);
114
115 Ring->Used.Flags = (volatile VOID *) RingPagesPtr;
116 RingPagesPtr += sizeof *Ring->Used.Flags;
117
118 Ring->Used.Idx = (volatile VOID *) RingPagesPtr;
119 RingPagesPtr += sizeof *Ring->Used.Idx;
120
121 Ring->Used.UsedElem = (volatile VOID *) RingPagesPtr;
122 RingPagesPtr += sizeof *Ring->Used.UsedElem * QueueSize;
123
124 Ring->Used.AvailEvent = (volatile VOID *) RingPagesPtr;
125 RingPagesPtr += sizeof *Ring->Used.AvailEvent;
126
127 Ring->QueueSize = QueueSize;
128 return EFI_SUCCESS;
129 }
130
131
132 /**
133
134 Tear down the internal resources of a configured virtio ring.
135
136 The caller is responsible to stop the host from using this ring before
137 invoking this function: the VSTAT_DRIVER_OK bit must be clear in
138 VhdrDeviceStatus.
139
140 @param[in] VirtIo The virtio device which was using the ring.
141
142 @param[out] Ring The virtio ring to clean up.
143
144 **/
145 VOID
146 EFIAPI
147 VirtioRingUninit (
148 IN VIRTIO_DEVICE_PROTOCOL *VirtIo,
149 IN OUT VRING *Ring
150 )
151 {
152 VirtIo->FreeSharedPages (VirtIo, Ring->NumPages, Ring->Base);
153 SetMem (Ring, sizeof *Ring, 0x00);
154 }
155
156
157 /**
158
159 Turn off interrupt notifications from the host, and prepare for appending
160 multiple descriptors to the virtio ring.
161
162 The calling driver must be in VSTAT_DRIVER_OK state.
163
164 @param[in,out] Ring The virtio ring we intend to append descriptors to.
165
166 @param[out] Indices The DESC_INDICES structure to initialize.
167
168 **/
169 VOID
170 EFIAPI
171 VirtioPrepare (
172 IN OUT VRING *Ring,
173 OUT DESC_INDICES *Indices
174 )
175 {
176 //
177 // Prepare for virtio-0.9.5, 2.4.2 Receiving Used Buffers From the Device.
178 // We're going to poll the answer, the host should not send an interrupt.
179 //
180 *Ring->Avail.Flags = (UINT16) VRING_AVAIL_F_NO_INTERRUPT;
181
182 //
183 // Prepare for virtio-0.9.5, 2.4.1 Supplying Buffers to the Device.
184 //
185 // Since we support only one in-flight descriptor chain, we can always build
186 // that chain starting at entry #0 of the descriptor table.
187 //
188 Indices->HeadDescIdx = 0;
189 Indices->NextDescIdx = Indices->HeadDescIdx;
190 }
191
192 /**
193
194 Append a contiguous buffer for transmission / reception via the virtio ring.
195
196 This function implements the following section from virtio-0.9.5:
197 - 2.4.1.1 Placing Buffers into the Descriptor Table
198
199 Free space is taken as granted, since the individual drivers support only
200 synchronous requests and host side status is processed in lock-step with
201 request submission. It is the calling driver's responsibility to verify the
202 ring size in advance.
203
204 The caller is responsible for initializing *Indices with VirtioPrepare()
205 first.
206
207 @param[in,out] Ring The virtio ring to append the buffer to,
208 as a descriptor.
209
210 @param[in] BufferDeviceAddress (Bus master device) start address of the
211 transmit / receive buffer.
212
213 @param[in] BufferSize Number of bytes to transmit or receive.
214
215 @param[in] Flags A bitmask of VRING_DESC_F_* flags. The
216 caller computes this mask dependent on
217 further buffers to append and transfer
218 direction. VRING_DESC_F_INDIRECT is
219 unsupported. The VRING_DESC.Next field is
220 always set, but the host only interprets
221 it dependent on VRING_DESC_F_NEXT.
222
223 @param[in,out] Indices Indices->HeadDescIdx is not accessed.
224 On input, Indices->NextDescIdx identifies
225 the next descriptor to carry the buffer.
226 On output, Indices->NextDescIdx is
227 incremented by one, modulo 2^16.
228
229 **/
230 VOID
231 EFIAPI
232 VirtioAppendDesc (
233 IN OUT VRING *Ring,
234 IN UINT64 BufferDeviceAddress,
235 IN UINT32 BufferSize,
236 IN UINT16 Flags,
237 IN OUT DESC_INDICES *Indices
238 )
239 {
240 volatile VRING_DESC *Desc;
241
242 Desc = &Ring->Desc[Indices->NextDescIdx++ % Ring->QueueSize];
243 Desc->Addr = BufferDeviceAddress;
244 Desc->Len = BufferSize;
245 Desc->Flags = Flags;
246 Desc->Next = Indices->NextDescIdx % Ring->QueueSize;
247 }
248
249
250 /**
251
252 Notify the host about the descriptor chain just built, and wait until the
253 host processes it.
254
255 @param[in] VirtIo The target virtio device to notify.
256
257 @param[in] VirtQueueId Identifies the queue for the target device.
258
259 @param[in,out] Ring The virtio ring with descriptors to submit.
260
261 @param[in] Indices Indices->NextDescIdx is not accessed.
262 Indices->HeadDescIdx identifies the head descriptor
263 of the descriptor chain.
264
265 @param[out] UsedLen On success, the total number of bytes, consecutively
266 across the buffers linked by the descriptor chain,
267 that the host wrote. May be NULL if the caller
268 doesn't care, or can compute the same information
269 from device-specific request structures linked by the
270 descriptor chain.
271
272 @return Error code from VirtIo->SetQueueNotify() if it fails.
273
274 @retval EFI_SUCCESS Otherwise, the host processed all descriptors.
275
276 **/
277 EFI_STATUS
278 EFIAPI
279 VirtioFlush (
280 IN VIRTIO_DEVICE_PROTOCOL *VirtIo,
281 IN UINT16 VirtQueueId,
282 IN OUT VRING *Ring,
283 IN DESC_INDICES *Indices,
284 OUT UINT32 *UsedLen OPTIONAL
285 )
286 {
287 UINT16 NextAvailIdx;
288 UINT16 LastUsedIdx;
289 EFI_STATUS Status;
290 UINTN PollPeriodUsecs;
291
292 //
293 // virtio-0.9.5, 2.4.1.2 Updating the Available Ring
294 //
295 // It is not exactly clear from the wording of the virtio-0.9.5
296 // specification, but each entry in the Available Ring references only the
297 // head descriptor of any given descriptor chain.
298 //
299 NextAvailIdx = *Ring->Avail.Idx;
300 //
301 // (Due to our lock-step progress, this is where the host will produce the
302 // used element with the head descriptor's index in it.)
303 //
304 LastUsedIdx = NextAvailIdx;
305 Ring->Avail.Ring[NextAvailIdx++ % Ring->QueueSize] =
306 Indices->HeadDescIdx % Ring->QueueSize;
307
308 //
309 // virtio-0.9.5, 2.4.1.3 Updating the Index Field
310 //
311 MemoryFence();
312 *Ring->Avail.Idx = NextAvailIdx;
313
314 //
315 // virtio-0.9.5, 2.4.1.4 Notifying the Device -- gratuitous notifications are
316 // OK.
317 //
318 MemoryFence();
319 Status = VirtIo->SetQueueNotify (VirtIo, VirtQueueId);
320 if (EFI_ERROR (Status)) {
321 return Status;
322 }
323
324 //
325 // virtio-0.9.5, 2.4.2 Receiving Used Buffers From the Device
326 // Wait until the host processes and acknowledges our descriptor chain. The
327 // condition we use for polling is greatly simplified and relies on the
328 // synchronous, lock-step progress.
329 //
330 // Keep slowing down until we reach a poll period of slightly above 1 ms.
331 //
332 PollPeriodUsecs = 1;
333 MemoryFence();
334 while (*Ring->Used.Idx != NextAvailIdx) {
335 gBS->Stall (PollPeriodUsecs); // calls AcpiTimerLib::MicroSecondDelay
336
337 if (PollPeriodUsecs < 1024) {
338 PollPeriodUsecs *= 2;
339 }
340 MemoryFence();
341 }
342
343 MemoryFence();
344
345 if (UsedLen != NULL) {
346 volatile CONST VRING_USED_ELEM *UsedElem;
347
348 UsedElem = &Ring->Used.UsedElem[LastUsedIdx % Ring->QueueSize];
349 ASSERT (UsedElem->Id == Indices->HeadDescIdx);
350 *UsedLen = UsedElem->Len;
351 }
352
353 return EFI_SUCCESS;
354 }
355
356
357 /**
358
359 Report the feature bits to the VirtIo 1.0 device that the VirtIo 1.0 driver
360 understands.
361
362 In VirtIo 1.0, a device can reject a self-inconsistent feature bitmap through
363 the new VSTAT_FEATURES_OK status bit. (For example if the driver requests a
364 higher level feature but clears a prerequisite feature.) This function is a
365 small wrapper around VIRTIO_DEVICE_PROTOCOL.SetGuestFeatures() that also
366 verifies if the VirtIo 1.0 device accepts the feature bitmap.
367
368 @param[in] VirtIo Report feature bits to this device.
369
370 @param[in] Features The set of feature bits that the driver wishes
371 to report. The caller is responsible to perform
372 any masking before calling this function; the
373 value is directly written with
374 VIRTIO_DEVICE_PROTOCOL.SetGuestFeatures().
375
376 @param[in,out] DeviceStatus On input, the status byte most recently written
377 to the device's status register. On output (even
378 on error), DeviceStatus will be updated so that
379 it is suitable for further status bit
380 manipulation and writing to the device's status
381 register.
382
383 @retval EFI_SUCCESS The device accepted the configuration in Features.
384
385 @return EFI_UNSUPPORTED The device rejected the configuration in Features.
386
387 @retval EFI_UNSUPPORTED VirtIo->Revision is smaller than 1.0.0.
388
389 @return Error codes from the SetGuestFeatures(),
390 SetDeviceStatus(), GetDeviceStatus() member
391 functions.
392
393 **/
394 EFI_STATUS
395 EFIAPI
396 Virtio10WriteFeatures (
397 IN VIRTIO_DEVICE_PROTOCOL *VirtIo,
398 IN UINT64 Features,
399 IN OUT UINT8 *DeviceStatus
400 )
401 {
402 EFI_STATUS Status;
403
404 if (VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) {
405 return EFI_UNSUPPORTED;
406 }
407
408 Status = VirtIo->SetGuestFeatures (VirtIo, Features);
409 if (EFI_ERROR (Status)) {
410 return Status;
411 }
412
413 *DeviceStatus |= VSTAT_FEATURES_OK;
414 Status = VirtIo->SetDeviceStatus (VirtIo, *DeviceStatus);
415 if (EFI_ERROR (Status)) {
416 return Status;
417 }
418
419 Status = VirtIo->GetDeviceStatus (VirtIo, DeviceStatus);
420 if (EFI_ERROR (Status)) {
421 return Status;
422 }
423
424 if ((*DeviceStatus & VSTAT_FEATURES_OK) == 0) {
425 Status = EFI_UNSUPPORTED;
426 }
427
428 return Status;
429 }
430
431 /**
432 Provides the virtio device address required to access system memory from a
433 DMA bus master.
434
435 The interface follows the same usage pattern as defined in UEFI spec 2.6
436 (Section 13.2 PCI Root Bridge I/O Protocol)
437
438 The VirtioMapAllBytesInSharedBuffer() is similar to VIRTIO_MAP_SHARED
439 with exception that NumberOfBytes is IN-only parameter. The function
440 maps all the bytes specified in NumberOfBytes param in one consecutive
441 range.
442
443 @param[in] VirtIo The virtio device for which the mapping is
444 requested.
445
446 @param[in] Operation Indicates if the bus master is going to
447 read or write to system memory.
448
449 @param[in] HostAddress The system memory address to map to shared
450 buffer address.
451
452 @param[in] NumberOfBytes Number of bytes to map.
453
454 @param[out] DeviceAddress The resulting shared map address for the
455 bus master to access the hosts HostAddress.
456
457 @param[out] Mapping A resulting token to pass to
458 VIRTIO_UNMAP_SHARED.
459
460
461 @retval EFI_SUCCESS The NumberOfBytes is succesfully mapped.
462 @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a
463 common buffer.
464 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
465 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to
466 a lack of resources. This includes the case
467 when NumberOfBytes bytes cannot be mapped
468 in one consecutive range.
469 @retval EFI_DEVICE_ERROR The system hardware could not map the
470 requested address.
471 **/
472 EFI_STATUS
473 EFIAPI
474 VirtioMapAllBytesInSharedBuffer (
475 IN VIRTIO_DEVICE_PROTOCOL *VirtIo,
476 IN VIRTIO_MAP_OPERATION Operation,
477 IN VOID *HostAddress,
478 IN UINTN NumberOfBytes,
479 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
480 OUT VOID **Mapping
481 )
482 {
483 EFI_STATUS Status;
484 VOID *MapInfo;
485 UINTN Size;
486 EFI_PHYSICAL_ADDRESS PhysicalAddress;
487
488 Size = NumberOfBytes;
489 Status = VirtIo->MapSharedBuffer (
490 VirtIo,
491 Operation,
492 HostAddress,
493 &Size,
494 &PhysicalAddress,
495 &MapInfo
496 );
497 if (EFI_ERROR (Status)) {
498 return Status;
499 }
500
501 if (Size < NumberOfBytes) {
502 goto Failed;
503 }
504
505 *Mapping = MapInfo;
506 *DeviceAddress = PhysicalAddress;
507
508 return EFI_SUCCESS;
509
510 Failed:
511 VirtIo->UnmapSharedBuffer (VirtIo, MapInfo);
512 return EFI_OUT_OF_RESOURCES;
513 }
514
515 /**
516
517 Map the ring buffer so that it can be accessed equally by both guest
518 and hypervisor.
519
520 @param[in] VirtIo The virtio device instance.
521
522 @param[in] Ring The virtio ring to map.
523
524 @param[out] RingBaseShift A resulting translation offset, to be
525 passed to VirtIo->SetQueueAddress().
526
527 @param[out] Mapping A resulting token to pass to
528 VirtIo->UnmapSharedBuffer().
529
530 @return Status code from VirtIo->MapSharedBuffer()
531 **/
532 EFI_STATUS
533 EFIAPI
534 VirtioRingMap (
535 IN VIRTIO_DEVICE_PROTOCOL *VirtIo,
536 IN VRING *Ring,
537 OUT UINT64 *RingBaseShift,
538 OUT VOID **Mapping
539 )
540 {
541 EFI_STATUS Status;
542 EFI_PHYSICAL_ADDRESS DeviceAddress;
543
544 Status = VirtioMapAllBytesInSharedBuffer (
545 VirtIo,
546 VirtioOperationBusMasterCommonBuffer,
547 Ring->Base,
548 EFI_PAGES_TO_SIZE (Ring->NumPages),
549 &DeviceAddress,
550 Mapping
551 );
552 if (EFI_ERROR (Status)) {
553 return Status;
554 }
555
556 *RingBaseShift = DeviceAddress - (UINT64)(UINTN)Ring->Base;
557 return EFI_SUCCESS;
558 }