]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / OvmfPkg / Library / VirtioMmioDeviceLib / VirtioMmioDeviceFunctions.c
... / ...
CommitLineData
1/** @file\r
2\r
3 This driver produces Virtio Device Protocol instances for Virtio MMIO devices.\r
4\r
5 Copyright (C) 2012, Red Hat, Inc.\r
6 Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>\r
7 Copyright (C) 2013, ARM Ltd.\r
8\r
9 SPDX-License-Identifier: BSD-2-Clause-Patent\r
10\r
11**/\r
12\r
13#include "VirtioMmioDevice.h"\r
14\r
15EFI_STATUS\r
16EFIAPI\r
17VirtioMmioGetDeviceFeatures (\r
18 IN VIRTIO_DEVICE_PROTOCOL *This,\r
19 OUT UINT64 *DeviceFeatures\r
20 )\r
21{\r
22 VIRTIO_MMIO_DEVICE *Device;\r
23 UINT32 LowBits, HighBits;\r
24\r
25 if (DeviceFeatures == NULL) {\r
26 return EFI_INVALID_PARAMETER;\r
27 }\r
28\r
29 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
30\r
31 if (Device->Version == VIRTIO_MMIO_DEVICE_VERSION_0_95) {\r
32 *DeviceFeatures = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_HOST_FEATURES);\r
33 } else {\r
34 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_HOST_FEATURES_SEL, 0);\r
35 LowBits = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_HOST_FEATURES);\r
36 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_HOST_FEATURES_SEL, 1);\r
37 HighBits = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_HOST_FEATURES);\r
38 *DeviceFeatures = LShiftU64 (HighBits, 32) | LowBits;\r
39 }\r
40\r
41 return EFI_SUCCESS;\r
42}\r
43\r
44EFI_STATUS\r
45EFIAPI\r
46VirtioMmioGetQueueSize (\r
47 IN VIRTIO_DEVICE_PROTOCOL *This,\r
48 OUT UINT16 *QueueNumMax\r
49 )\r
50{\r
51 VIRTIO_MMIO_DEVICE *Device;\r
52\r
53 if (QueueNumMax == NULL) {\r
54 return EFI_INVALID_PARAMETER;\r
55 }\r
56\r
57 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
58\r
59 *QueueNumMax = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_QUEUE_NUM_MAX) & 0xFFFF;\r
60\r
61 return EFI_SUCCESS;\r
62}\r
63\r
64EFI_STATUS\r
65EFIAPI\r
66VirtioMmioGetDeviceStatus (\r
67 IN VIRTIO_DEVICE_PROTOCOL *This,\r
68 OUT UINT8 *DeviceStatus\r
69 )\r
70{\r
71 VIRTIO_MMIO_DEVICE *Device;\r
72\r
73 if (DeviceStatus == NULL) {\r
74 return EFI_INVALID_PARAMETER;\r
75 }\r
76\r
77 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
78\r
79 *DeviceStatus = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_STATUS) & 0xFF;\r
80\r
81 return EFI_SUCCESS;\r
82}\r
83\r
84EFI_STATUS\r
85EFIAPI\r
86VirtioMmioSetQueueSize (\r
87 IN VIRTIO_DEVICE_PROTOCOL *This,\r
88 IN UINT16 QueueSize\r
89 )\r
90{\r
91 VIRTIO_MMIO_DEVICE *Device;\r
92\r
93 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
94\r
95 if (Device->Version == VIRTIO_MMIO_DEVICE_VERSION_0_95) {\r
96 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_NUM, QueueSize);\r
97 } else {\r
98 Device->QueueNum = QueueSize;\r
99 }\r
100\r
101 return EFI_SUCCESS;\r
102}\r
103\r
104EFI_STATUS\r
105EFIAPI\r
106VirtioMmioSetDeviceStatus (\r
107 IN VIRTIO_DEVICE_PROTOCOL *This,\r
108 IN UINT8 DeviceStatus\r
109 )\r
110{\r
111 VIRTIO_MMIO_DEVICE *Device;\r
112\r
113 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
114\r
115 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_STATUS, DeviceStatus);\r
116\r
117 return EFI_SUCCESS;\r
118}\r
119\r
120EFI_STATUS\r
121EFIAPI\r
122VirtioMmioSetQueueNotify (\r
123 IN VIRTIO_DEVICE_PROTOCOL *This,\r
124 IN UINT16 QueueNotify\r
125 )\r
126{\r
127 VIRTIO_MMIO_DEVICE *Device;\r
128\r
129 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
130\r
131 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_NOTIFY, QueueNotify);\r
132\r
133 return EFI_SUCCESS;\r
134}\r
135\r
136EFI_STATUS\r
137EFIAPI\r
138VirtioMmioSetQueueAlignment (\r
139 IN VIRTIO_DEVICE_PROTOCOL *This,\r
140 IN UINT32 Alignment\r
141 )\r
142{\r
143 VIRTIO_MMIO_DEVICE *Device;\r
144\r
145 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
146\r
147 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_ALIGN, Alignment);\r
148\r
149 return EFI_SUCCESS;\r
150}\r
151\r
152EFI_STATUS\r
153EFIAPI\r
154VirtioMmioSetPageSize (\r
155 IN VIRTIO_DEVICE_PROTOCOL *This,\r
156 IN UINT32 PageSize\r
157 )\r
158{\r
159 VIRTIO_MMIO_DEVICE *Device;\r
160\r
161 if (PageSize != EFI_PAGE_SIZE) {\r
162 return EFI_UNSUPPORTED;\r
163 }\r
164\r
165 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
166\r
167 if (Device->Version == VIRTIO_MMIO_DEVICE_VERSION_0_95) {\r
168 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_GUEST_PAGE_SIZE, PageSize);\r
169 }\r
170\r
171 return EFI_SUCCESS;\r
172}\r
173\r
174EFI_STATUS\r
175EFIAPI\r
176VirtioMmioSetQueueSel (\r
177 IN VIRTIO_DEVICE_PROTOCOL *This,\r
178 IN UINT16 Sel\r
179 )\r
180{\r
181 VIRTIO_MMIO_DEVICE *Device;\r
182\r
183 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
184\r
185 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_SEL, Sel);\r
186\r
187 if (Device->Version == VIRTIO_MMIO_DEVICE_VERSION_0_95) {\r
188 Device->QueueNum = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_QUEUE_NUM_MAX) & 0xFFFF;\r
189 }\r
190\r
191 return EFI_SUCCESS;\r
192}\r
193\r
194EFI_STATUS\r
195EFIAPI\r
196VirtioMmioSetQueueAddress (\r
197 IN VIRTIO_DEVICE_PROTOCOL *This,\r
198 IN VRING *Ring,\r
199 IN UINT64 RingBaseShift\r
200 )\r
201{\r
202 VIRTIO_MMIO_DEVICE *Device;\r
203 UINT64 Address;\r
204\r
205 ASSERT (RingBaseShift == 0);\r
206\r
207 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
208\r
209 if (Device->Version == VIRTIO_MMIO_DEVICE_VERSION_0_95) {\r
210 VIRTIO_CFG_WRITE (\r
211 Device,\r
212 VIRTIO_MMIO_OFFSET_QUEUE_PFN,\r
213 (UINT32)((UINTN)Ring->Base >> EFI_PAGE_SHIFT)\r
214 );\r
215 } else {\r
216 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_NUM, Device->QueueNum);\r
217\r
218 Address = (UINTN)Ring->Base;\r
219 VIRTIO_CFG_WRITE (\r
220 Device,\r
221 VIRTIO_MMIO_OFFSET_QUEUE_DESC_LO,\r
222 (UINT32)Address\r
223 );\r
224 VIRTIO_CFG_WRITE (\r
225 Device,\r
226 VIRTIO_MMIO_OFFSET_QUEUE_DESC_HI,\r
227 (UINT32)RShiftU64 (Address, 32)\r
228 );\r
229\r
230 Address = (UINTN)Ring->Avail.Flags;\r
231 VIRTIO_CFG_WRITE (\r
232 Device,\r
233 VIRTIO_MMIO_OFFSET_QUEUE_AVAIL_LO,\r
234 (UINT32)Address\r
235 );\r
236 VIRTIO_CFG_WRITE (\r
237 Device,\r
238 VIRTIO_MMIO_OFFSET_QUEUE_AVAIL_HI,\r
239 (UINT32)RShiftU64 (Address, 32)\r
240 );\r
241\r
242 Address = (UINTN)Ring->Used.Flags;\r
243 VIRTIO_CFG_WRITE (\r
244 Device,\r
245 VIRTIO_MMIO_OFFSET_QUEUE_USED_LO,\r
246 (UINT32)Address\r
247 );\r
248 VIRTIO_CFG_WRITE (\r
249 Device,\r
250 VIRTIO_MMIO_OFFSET_QUEUE_USED_HI,\r
251 (UINT32)RShiftU64 (Address, 32)\r
252 );\r
253\r
254 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_READY, 1);\r
255 }\r
256\r
257 return EFI_SUCCESS;\r
258}\r
259\r
260EFI_STATUS\r
261EFIAPI\r
262VirtioMmioSetGuestFeatures (\r
263 IN VIRTIO_DEVICE_PROTOCOL *This,\r
264 IN UINT64 Features\r
265 )\r
266{\r
267 VIRTIO_MMIO_DEVICE *Device;\r
268\r
269 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
270\r
271 if (Device->Version == VIRTIO_MMIO_DEVICE_VERSION_0_95) {\r
272 if (Features > MAX_UINT32) {\r
273 return EFI_UNSUPPORTED;\r
274 }\r
275\r
276 VIRTIO_CFG_WRITE (\r
277 Device,\r
278 VIRTIO_MMIO_OFFSET_GUEST_FEATURES,\r
279 (UINT32)Features\r
280 );\r
281 } else {\r
282 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_GUEST_FEATURES_SEL, 0);\r
283 VIRTIO_CFG_WRITE (\r
284 Device,\r
285 VIRTIO_MMIO_OFFSET_GUEST_FEATURES,\r
286 (UINT32)Features\r
287 );\r
288 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_GUEST_FEATURES_SEL, 1);\r
289 VIRTIO_CFG_WRITE (\r
290 Device,\r
291 VIRTIO_MMIO_OFFSET_GUEST_FEATURES,\r
292 (UINT32)RShiftU64 (Features, 32)\r
293 );\r
294 }\r
295\r
296 return EFI_SUCCESS;\r
297}\r
298\r
299EFI_STATUS\r
300EFIAPI\r
301VirtioMmioDeviceWrite (\r
302 IN VIRTIO_DEVICE_PROTOCOL *This,\r
303 IN UINTN FieldOffset,\r
304 IN UINTN FieldSize,\r
305 IN UINT64 Value\r
306 )\r
307{\r
308 UINTN DstBaseAddress;\r
309 VIRTIO_MMIO_DEVICE *Device;\r
310\r
311 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
312\r
313 //\r
314 // Double-check fieldsize\r
315 //\r
316 if ((FieldSize != 1) && (FieldSize != 2) &&\r
317 (FieldSize != 4) && (FieldSize != 8))\r
318 {\r
319 return EFI_INVALID_PARAMETER;\r
320 }\r
321\r
322 //\r
323 // Compute base address\r
324 //\r
325 DstBaseAddress = Device->BaseAddress +\r
326 VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO + FieldOffset;\r
327\r
328 //\r
329 // The device-specific memory area of Virtio-MMIO can only be written in\r
330 // byte accesses. This is not currently in the Virtio spec.\r
331 //\r
332 MmioWriteBuffer8 (DstBaseAddress, FieldSize, (UINT8 *)&Value);\r
333\r
334 return EFI_SUCCESS;\r
335}\r
336\r
337EFI_STATUS\r
338EFIAPI\r
339VirtioMmioDeviceRead (\r
340 IN VIRTIO_DEVICE_PROTOCOL *This,\r
341 IN UINTN FieldOffset,\r
342 IN UINTN FieldSize,\r
343 IN UINTN BufferSize,\r
344 OUT VOID *Buffer\r
345 )\r
346{\r
347 UINTN SrcBaseAddress;\r
348 VIRTIO_MMIO_DEVICE *Device;\r
349\r
350 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
351\r
352 //\r
353 // Parameter validation\r
354 //\r
355 ASSERT (FieldSize == BufferSize);\r
356\r
357 //\r
358 // Double-check fieldsize\r
359 //\r
360 if ((FieldSize != 1) && (FieldSize != 2) &&\r
361 (FieldSize != 4) && (FieldSize != 8))\r
362 {\r
363 return EFI_INVALID_PARAMETER;\r
364 }\r
365\r
366 //\r
367 // Compute base address\r
368 //\r
369 SrcBaseAddress = Device->BaseAddress +\r
370 VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO + FieldOffset;\r
371\r
372 //\r
373 // The device-specific memory area of Virtio-MMIO can only be read in\r
374 // byte reads. This is not currently in the Virtio spec.\r
375 //\r
376 MmioReadBuffer8 (SrcBaseAddress, BufferSize, Buffer);\r
377\r
378 return EFI_SUCCESS;\r
379}\r
380\r
381EFI_STATUS\r
382EFIAPI\r
383VirtioMmioAllocateSharedPages (\r
384 IN VIRTIO_DEVICE_PROTOCOL *This,\r
385 IN UINTN NumPages,\r
386 OUT VOID **HostAddress\r
387 )\r
388{\r
389 VOID *Buffer;\r
390\r
391 Buffer = AllocatePages (NumPages);\r
392 if (Buffer == NULL) {\r
393 return EFI_OUT_OF_RESOURCES;\r
394 }\r
395\r
396 *HostAddress = Buffer;\r
397 return EFI_SUCCESS;\r
398}\r
399\r
400VOID\r
401EFIAPI\r
402VirtioMmioFreeSharedPages (\r
403 IN VIRTIO_DEVICE_PROTOCOL *This,\r
404 IN UINTN NumPages,\r
405 IN VOID *HostAddress\r
406 )\r
407{\r
408 FreePages (HostAddress, NumPages);\r
409}\r
410\r
411EFI_STATUS\r
412EFIAPI\r
413VirtioMmioMapSharedBuffer (\r
414 IN VIRTIO_DEVICE_PROTOCOL *This,\r
415 IN VIRTIO_MAP_OPERATION Operation,\r
416 IN VOID *HostAddress,\r
417 IN OUT UINTN *NumberOfBytes,\r
418 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,\r
419 OUT VOID **Mapping\r
420 )\r
421{\r
422 *DeviceAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress;\r
423 *Mapping = NULL;\r
424\r
425 return EFI_SUCCESS;\r
426}\r
427\r
428EFI_STATUS\r
429EFIAPI\r
430VirtioMmioUnmapSharedBuffer (\r
431 IN VIRTIO_DEVICE_PROTOCOL *This,\r
432 IN VOID *Mapping\r
433 )\r
434{\r
435 return EFI_SUCCESS;\r
436}\r