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