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