]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Library/VirtioMmioDeviceLib/VirtioMmioDeviceFunctions.c
OvmfPkg/VirtioMmioDeviceLib: virtio 1.0: Fix SetQueueAddress
[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
18 IN VIRTIO_DEVICE_PROTOCOL *This,\r
bc8fde6f 19 OUT UINT64 *DeviceFeatures\r
6fb4e772
OM
20 )\r
21{\r
22 VIRTIO_MMIO_DEVICE *Device;\r
23\r
24 if (DeviceFeatures == NULL) {\r
25 return EFI_INVALID_PARAMETER;\r
26 }\r
27\r
28 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
29\r
30 *DeviceFeatures = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_HOST_FEATURES);\r
31\r
32 return EFI_SUCCESS;\r
33}\r
34\r
6fb4e772
OM
35EFI_STATUS\r
36EFIAPI\r
37VirtioMmioGetQueueSize (\r
38 IN VIRTIO_DEVICE_PROTOCOL *This,\r
39 OUT UINT16 *QueueNumMax\r
40 )\r
41{\r
42 VIRTIO_MMIO_DEVICE *Device;\r
43\r
44 if (QueueNumMax == NULL) {\r
45 return EFI_INVALID_PARAMETER;\r
46 }\r
47\r
48 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
49\r
50 *QueueNumMax = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_QUEUE_NUM_MAX) & 0xFFFF;\r
51\r
52 return EFI_SUCCESS;\r
53}\r
54\r
55EFI_STATUS\r
56EFIAPI\r
57VirtioMmioGetDeviceStatus (\r
58 IN VIRTIO_DEVICE_PROTOCOL *This,\r
59 OUT UINT8 *DeviceStatus\r
60 )\r
61{\r
62 VIRTIO_MMIO_DEVICE *Device;\r
63\r
64 if (DeviceStatus == NULL) {\r
65 return EFI_INVALID_PARAMETER;\r
66 }\r
67\r
68 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
69\r
70 *DeviceStatus = VIRTIO_CFG_READ (Device, VIRTIO_MMIO_OFFSET_STATUS) & 0xFF;\r
71\r
72 return EFI_SUCCESS;\r
73}\r
74\r
75EFI_STATUS\r
76EFIAPI\r
77VirtioMmioSetQueueSize (\r
22701a3d
BS
78 IN VIRTIO_DEVICE_PROTOCOL *This,\r
79 IN UINT16 QueueSize\r
6fb4e772
OM
80 )\r
81{\r
82 VIRTIO_MMIO_DEVICE *Device;\r
83\r
84 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
85\r
86 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_NUM, QueueSize);\r
87\r
88 return EFI_SUCCESS;\r
89}\r
90\r
91EFI_STATUS\r
92EFIAPI\r
93VirtioMmioSetDeviceStatus (\r
22701a3d
BS
94 IN VIRTIO_DEVICE_PROTOCOL *This,\r
95 IN UINT8 DeviceStatus\r
6fb4e772
OM
96 )\r
97{\r
98 VIRTIO_MMIO_DEVICE *Device;\r
99\r
100 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
101\r
102 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_STATUS, DeviceStatus);\r
103\r
104 return EFI_SUCCESS;\r
105}\r
106\r
107EFI_STATUS\r
108EFIAPI\r
109VirtioMmioSetQueueNotify (\r
22701a3d
BS
110 IN VIRTIO_DEVICE_PROTOCOL *This,\r
111 IN UINT16 QueueNotify\r
6fb4e772
OM
112 )\r
113{\r
114 VIRTIO_MMIO_DEVICE *Device;\r
115\r
116 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
117\r
118 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_NOTIFY, QueueNotify);\r
119\r
120 return EFI_SUCCESS;\r
121}\r
122\r
123EFI_STATUS\r
124EFIAPI\r
125VirtioMmioSetQueueAlignment (\r
22701a3d
BS
126 IN VIRTIO_DEVICE_PROTOCOL *This,\r
127 IN UINT32 Alignment\r
6fb4e772
OM
128 )\r
129{\r
130 VIRTIO_MMIO_DEVICE *Device;\r
131\r
132 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
133\r
134 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_ALIGN, Alignment);\r
135\r
136 return EFI_SUCCESS;\r
137}\r
138\r
139EFI_STATUS\r
140EFIAPI\r
141VirtioMmioSetPageSize (\r
22701a3d
BS
142 IN VIRTIO_DEVICE_PROTOCOL *This,\r
143 IN UINT32 PageSize\r
6fb4e772
OM
144 )\r
145{\r
146 VIRTIO_MMIO_DEVICE *Device;\r
147\r
148 if (PageSize != EFI_PAGE_SIZE) {\r
149 return EFI_UNSUPPORTED;\r
150 }\r
151\r
152 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
153\r
212a2b9b
GH
154 if (Device->Version == VIRTIO_MMIO_DEVICE_VERSION_0_95) {\r
155 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_GUEST_PAGE_SIZE, PageSize);\r
156 }\r
6fb4e772
OM
157\r
158 return EFI_SUCCESS;\r
159}\r
160\r
161EFI_STATUS\r
162EFIAPI\r
163VirtioMmioSetQueueSel (\r
22701a3d
BS
164 IN VIRTIO_DEVICE_PROTOCOL *This,\r
165 IN UINT16 Sel\r
6fb4e772
OM
166 )\r
167{\r
168 VIRTIO_MMIO_DEVICE *Device;\r
169\r
170 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
171\r
172 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_SEL, Sel);\r
173\r
174 return EFI_SUCCESS;\r
175}\r
176\r
177EFI_STATUS\r
75e9154f 178EFIAPI\r
6fb4e772 179VirtioMmioSetQueueAddress (\r
07af4eee 180 IN VIRTIO_DEVICE_PROTOCOL *This,\r
53a4c604
BS
181 IN VRING *Ring,\r
182 IN UINT64 RingBaseShift\r
6fb4e772
OM
183 )\r
184{\r
185 VIRTIO_MMIO_DEVICE *Device;\r
537a7244 186 UINT64 Address;\r
6fb4e772 187\r
53a4c604
BS
188 ASSERT (RingBaseShift == 0);\r
189\r
6fb4e772
OM
190 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
191\r
537a7244
GH
192 if (Device->Version == VIRTIO_MMIO_DEVICE_VERSION_0_95) {\r
193 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_PFN,\r
194 (UINT32)((UINTN)Ring->Base >> EFI_PAGE_SHIFT));\r
195 } else {\r
196 Address = (UINTN)Ring->Base;\r
197 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_DESC_LO,\r
198 (UINT32)Address);\r
199 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_DESC_HI,\r
200 (UINT32)RShiftU64(Address, 32));\r
201\r
202 Address = (UINTN)Ring->Avail.Flags;\r
203 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_AVAIL_LO,\r
204 (UINT32)Address);\r
205 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_AVAIL_HI,\r
206 (UINT32)RShiftU64(Address, 32));\r
207\r
208 Address = (UINTN)Ring->Used.Flags;\r
209 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_USED_LO,\r
210 (UINT32)Address);\r
211 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_USED_HI,\r
212 (UINT32)RShiftU64(Address, 32));\r
213\r
214 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_QUEUE_READY, 1);\r
215 }\r
6fb4e772
OM
216\r
217 return EFI_SUCCESS;\r
218}\r
219\r
220EFI_STATUS\r
221EFIAPI\r
222VirtioMmioSetGuestFeatures (\r
22701a3d
BS
223 IN VIRTIO_DEVICE_PROTOCOL *This,\r
224 IN UINT64 Features\r
6fb4e772
OM
225 )\r
226{\r
227 VIRTIO_MMIO_DEVICE *Device;\r
228\r
229 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
230\r
bc8fde6f
LE
231 if (Features > MAX_UINT32) {\r
232 return EFI_UNSUPPORTED;\r
233 }\r
234 VIRTIO_CFG_WRITE (Device, VIRTIO_MMIO_OFFSET_GUEST_FEATURES,\r
235 (UINT32)Features);\r
6fb4e772
OM
236\r
237 return EFI_SUCCESS;\r
238}\r
239\r
240EFI_STATUS\r
241EFIAPI\r
242VirtioMmioDeviceWrite (\r
243 IN VIRTIO_DEVICE_PROTOCOL *This,\r
244 IN UINTN FieldOffset,\r
245 IN UINTN FieldSize,\r
246 IN UINT64 Value\r
247 )\r
248{\r
249 UINTN DstBaseAddress;\r
250 VIRTIO_MMIO_DEVICE *Device;\r
251\r
252 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
253\r
254 //\r
255 // Double-check fieldsize\r
256 //\r
257 if ((FieldSize != 1) && (FieldSize != 2) &&\r
258 (FieldSize != 4) && (FieldSize != 8)) {\r
259 return EFI_INVALID_PARAMETER;\r
260 }\r
261\r
262 //\r
263 // Compute base address\r
264 //\r
265 DstBaseAddress = Device->BaseAddress +\r
266 VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO + FieldOffset;\r
267\r
268 //\r
269 // The device-specific memory area of Virtio-MMIO can only be written in\r
270 // byte accesses. This is not currently in the Virtio spec.\r
271 //\r
272 MmioWriteBuffer8 (DstBaseAddress, FieldSize, (UINT8*)&Value);\r
273\r
274 return EFI_SUCCESS;\r
275}\r
276\r
277EFI_STATUS\r
278EFIAPI\r
279VirtioMmioDeviceRead (\r
280 IN VIRTIO_DEVICE_PROTOCOL *This,\r
281 IN UINTN FieldOffset,\r
282 IN UINTN FieldSize,\r
283 IN UINTN BufferSize,\r
284 OUT VOID *Buffer\r
285 )\r
286{\r
287 UINTN SrcBaseAddress;\r
288 VIRTIO_MMIO_DEVICE *Device;\r
289\r
290 Device = VIRTIO_MMIO_DEVICE_FROM_VIRTIO_DEVICE (This);\r
291\r
292 //\r
293 // Parameter validation\r
294 //\r
295 ASSERT (FieldSize == BufferSize);\r
296\r
297 //\r
298 // Double-check fieldsize\r
299 //\r
300 if ((FieldSize != 1) && (FieldSize != 2) &&\r
301 (FieldSize != 4) && (FieldSize != 8)) {\r
302 return EFI_INVALID_PARAMETER;\r
303 }\r
304\r
305 //\r
306 // Compute base address\r
307 //\r
308 SrcBaseAddress = Device->BaseAddress +\r
309 VIRTIO_DEVICE_SPECIFIC_CONFIGURATION_OFFSET_MMIO + FieldOffset;\r
310\r
311 //\r
312 // The device-specific memory area of Virtio-MMIO can only be read in\r
313 // byte reads. This is not currently in the Virtio spec.\r
314 //\r
315 MmioReadBuffer8 (SrcBaseAddress, BufferSize, Buffer);\r
316\r
317 return EFI_SUCCESS;\r
318}\r
084cfc1a
BS
319\r
320EFI_STATUS\r
321EFIAPI\r
322VirtioMmioAllocateSharedPages (\r
323 IN VIRTIO_DEVICE_PROTOCOL *This,\r
324 IN UINTN NumPages,\r
325 OUT VOID **HostAddress\r
326 )\r
327{\r
328 VOID *Buffer;\r
329\r
330 Buffer = AllocatePages (NumPages);\r
331 if (Buffer == NULL) {\r
332 return EFI_OUT_OF_RESOURCES;\r
333 }\r
334\r
335 *HostAddress = Buffer;\r
336 return EFI_SUCCESS;\r
337}\r
338\r
339VOID\r
340EFIAPI\r
341VirtioMmioFreeSharedPages (\r
342 IN VIRTIO_DEVICE_PROTOCOL *This,\r
343 IN UINTN NumPages,\r
344 IN VOID *HostAddress\r
345 )\r
346{\r
347 FreePages (HostAddress, NumPages);\r
348}\r
349\r
350EFI_STATUS\r
351EFIAPI\r
352VirtioMmioMapSharedBuffer (\r
353 IN VIRTIO_DEVICE_PROTOCOL *This,\r
354 IN VIRTIO_MAP_OPERATION Operation,\r
355 IN VOID *HostAddress,\r
356 IN OUT UINTN *NumberOfBytes,\r
357 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,\r
358 OUT VOID **Mapping\r
359 )\r
360{\r
361 *DeviceAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;\r
362 *Mapping = NULL;\r
363\r
364 return EFI_SUCCESS;\r
365}\r
366\r
367EFI_STATUS\r
368EFIAPI\r
369VirtioMmioUnmapSharedBuffer (\r
370 IN VIRTIO_DEVICE_PROTOCOL *This,\r
371 IN VOID *Mapping\r
372 )\r
373{\r
374 return EFI_SUCCESS;\r
375}\r