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