]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / OvmfPkg / Library / VirtioMmioDeviceLib / VirtioMmioDeviceFunctions.c
CommitLineData
6fb4e772
OM
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
b26f0cf9 9 SPDX-License-Identifier: BSD-2-Clause-Patent\r
6fb4e772
OM
10\r
11**/\r
12\r
13#include "VirtioMmioDevice.h"\r
14\r
15EFI_STATUS\r
16EFIAPI\r
17VirtioMmioGetDeviceFeatures (\r
ac0a286f
MK
18 IN VIRTIO_DEVICE_PROTOCOL *This,\r
19 OUT UINT64 *DeviceFeatures\r
6fb4e772
OM
20 )\r
21{\r
ac0a286f
MK
22 VIRTIO_MMIO_DEVICE *Device;\r
23 UINT32 LowBits, HighBits;\r
6fb4e772
OM
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
ae12188c
GH
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
ac0a286f
MK
37 HighBits = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_HOST_FEATURES);\r
38 *DeviceFeatures = LShiftU64 (HighBits, 32) | LowBits;\r
ae12188c 39 }\r
6fb4e772
OM
40\r
41 return EFI_SUCCESS;\r
42}\r
43\r
6fb4e772
OM
44EFI_STATUS\r
45EFIAPI\r
46VirtioMmioGetQueueSize (\r
47 IN VIRTIO_DEVICE_PROTOCOL *This,\r
48 OUT UINT16 *QueueNumMax\r
49 )\r
50{\r
ac0a286f 51 VIRTIO_MMIO_DEVICE *Device;\r
6fb4e772
OM
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
ac0a286f 71 VIRTIO_MMIO_DEVICE *Device;\r
6fb4e772
OM
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
ac0a286f 87 IN VIRTIO_DEVICE_PROTOCOL *This,\r
22701a3d 88 IN UINT16 QueueSize\r
6fb4e772
OM
89 )\r
90{\r
ac0a286f 91 VIRTIO_MMIO_DEVICE *Device;\r
6fb4e772
OM
92\r
93 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
94\r
6a3e9576
GH
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
6fb4e772
OM
100\r
101 return EFI_SUCCESS;\r
102}\r
103\r
104EFI_STATUS\r
105EFIAPI\r
106VirtioMmioSetDeviceStatus (\r
ac0a286f 107 IN VIRTIO_DEVICE_PROTOCOL *This,\r
22701a3d 108 IN UINT8 DeviceStatus\r
6fb4e772
OM
109 )\r
110{\r
ac0a286f 111 VIRTIO_MMIO_DEVICE *Device;\r
6fb4e772
OM
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
ac0a286f 123 IN VIRTIO_DEVICE_PROTOCOL *This,\r
22701a3d 124 IN UINT16 QueueNotify\r
6fb4e772
OM
125 )\r
126{\r
ac0a286f 127 VIRTIO_MMIO_DEVICE *Device;\r
6fb4e772
OM
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
ac0a286f 139 IN VIRTIO_DEVICE_PROTOCOL *This,\r
22701a3d 140 IN UINT32 Alignment\r
6fb4e772
OM
141 )\r
142{\r
ac0a286f 143 VIRTIO_MMIO_DEVICE *Device;\r
6fb4e772
OM
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
ac0a286f 155 IN VIRTIO_DEVICE_PROTOCOL *This,\r
22701a3d 156 IN UINT32 PageSize\r
6fb4e772
OM
157 )\r
158{\r
ac0a286f 159 VIRTIO_MMIO_DEVICE *Device;\r
6fb4e772
OM
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
212a2b9b
GH
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
6fb4e772
OM
170\r
171 return EFI_SUCCESS;\r
172}\r
173\r
174EFI_STATUS\r
175EFIAPI\r
176VirtioMmioSetQueueSel (\r
ac0a286f 177 IN VIRTIO_DEVICE_PROTOCOL *This,\r
22701a3d 178 IN UINT16 Sel\r
6fb4e772
OM
179 )\r
180{\r
ac0a286f 181 VIRTIO_MMIO_DEVICE *Device;\r
6fb4e772
OM
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
6a3e9576
GH
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
6fb4e772
OM
191 return EFI_SUCCESS;\r
192}\r
193\r
194EFI_STATUS\r
75e9154f 195EFIAPI\r
6fb4e772 196VirtioMmioSetQueueAddress (\r
07af4eee 197 IN VIRTIO_DEVICE_PROTOCOL *This,\r
53a4c604
BS
198 IN VRING *Ring,\r
199 IN UINT64 RingBaseShift\r
6fb4e772
OM
200 )\r
201{\r
ac0a286f
MK
202 VIRTIO_MMIO_DEVICE *Device;\r
203 UINT64 Address;\r
6fb4e772 204\r
53a4c604
BS
205 ASSERT (RingBaseShift == 0);\r
206\r
6fb4e772
OM
207 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
208\r
537a7244 209 if (Device->Version == VIRTIO_MMIO_DEVICE_VERSION_0_95) {\r
ac0a286f
MK
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
537a7244 215 } else {\r
6a3e9576
GH
216 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_NUM, Device->QueueNum);\r
217\r
537a7244 218 Address = (UINTN)Ring->Base;\r
ac0a286f
MK
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
537a7244
GH
229\r
230 Address = (UINTN)Ring->Avail.Flags;\r
ac0a286f
MK
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
537a7244
GH
241\r
242 Address = (UINTN)Ring->Used.Flags;\r
ac0a286f
MK
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
537a7244
GH
253\r
254 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_READY, 1);\r
255 }\r
6fb4e772
OM
256\r
257 return EFI_SUCCESS;\r
258}\r
259\r
260EFI_STATUS\r
261EFIAPI\r
262VirtioMmioSetGuestFeatures (\r
ac0a286f 263 IN VIRTIO_DEVICE_PROTOCOL *This,\r
22701a3d 264 IN UINT64 Features\r
6fb4e772
OM
265 )\r
266{\r
ac0a286f 267 VIRTIO_MMIO_DEVICE *Device;\r
6fb4e772
OM
268\r
269 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
270\r
ae12188c
GH
271 if (Device->Version == VIRTIO_MMIO_DEVICE_VERSION_0_95) {\r
272 if (Features > MAX_UINT32) {\r
273 return EFI_UNSUPPORTED;\r
274 }\r
ac0a286f
MK
275\r
276 VIRTIO_CFG_WRITE (\r
277 Device,\r
278 VIRTIO_MMIO_OFFSET_GUEST_FEATURES,\r
279 (UINT32)Features\r
280 );\r
ae12188c
GH
281 } else {\r
282 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_GUEST_FEATURES_SEL, 0);\r
ac0a286f
MK
283 VIRTIO_CFG_WRITE (\r
284 Device,\r
285 VIRTIO_MMIO_OFFSET_GUEST_FEATURES,\r
286 (UINT32)Features\r
287 );\r
ae12188c 288 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_GUEST_FEATURES_SEL, 1);\r
ac0a286f
MK
289 VIRTIO_CFG_WRITE (\r
290 Device,\r
291 VIRTIO_MMIO_OFFSET_GUEST_FEATURES,\r
292 (UINT32)RShiftU64 (Features, 32)\r
293 );\r
bc8fde6f 294 }\r
6fb4e772
OM
295\r
296 return EFI_SUCCESS;\r
297}\r
298\r
299EFI_STATUS\r
300EFIAPI\r
301VirtioMmioDeviceWrite (\r
ac0a286f
MK
302 IN VIRTIO_DEVICE_PROTOCOL *This,\r
303 IN UINTN FieldOffset,\r
304 IN UINTN FieldSize,\r
305 IN UINT64 Value\r
6fb4e772
OM
306 )\r
307{\r
ac0a286f
MK
308 UINTN DstBaseAddress;\r
309 VIRTIO_MMIO_DEVICE *Device;\r
6fb4e772
OM
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
ac0a286f
MK
317 (FieldSize != 4) && (FieldSize != 8))\r
318 {\r
6fb4e772
OM
319 return EFI_INVALID_PARAMETER;\r
320 }\r
321\r
322 //\r
323 // Compute base address\r
324 //\r
325 DstBaseAddress = Device->BaseAddress +\r
ac0a286f 326 VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO + FieldOffset;\r
6fb4e772
OM
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
ac0a286f 332 MmioWriteBuffer8 (DstBaseAddress, FieldSize, (UINT8 *)&Value);\r
6fb4e772
OM
333\r
334 return EFI_SUCCESS;\r
335}\r
336\r
337EFI_STATUS\r
338EFIAPI\r
339VirtioMmioDeviceRead (\r
ac0a286f
MK
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
6fb4e772
OM
345 )\r
346{\r
ac0a286f
MK
347 UINTN SrcBaseAddress;\r
348 VIRTIO_MMIO_DEVICE *Device;\r
6fb4e772
OM
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
ac0a286f
MK
361 (FieldSize != 4) && (FieldSize != 8))\r
362 {\r
6fb4e772
OM
363 return EFI_INVALID_PARAMETER;\r
364 }\r
365\r
366 //\r
367 // Compute base address\r
368 //\r
369 SrcBaseAddress = Device->BaseAddress +\r
ac0a286f 370 VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO + FieldOffset;\r
6fb4e772
OM
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
084cfc1a
BS
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
ac0a286f 389 VOID *Buffer;\r
084cfc1a
BS
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
ac0a286f
MK
422 *DeviceAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress;\r
423 *Mapping = NULL;\r
084cfc1a
BS
424\r
425 return EFI_SUCCESS;\r
426}\r
427\r
428EFI_STATUS\r
429EFIAPI\r
430VirtioMmioUnmapSharedBuffer (\r
ac0a286f
MK
431 IN VIRTIO_DEVICE_PROTOCOL *This,\r
432 IN VOID *Mapping\r
084cfc1a
BS
433 )\r
434{\r
435 return EFI_SUCCESS;\r
436}\r