]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/BaseIoLibIntrinsic/IoLibInternalTdx.c
MdePkg: Probe Cc guest in BaseIoLibIntrinsicSev
[mirror_edk2.git] / MdePkg / Library / BaseIoLibIntrinsic / IoLibInternalTdx.c
CommitLineData
ab9d7909
MX
1/** @file\r
2 TDX I/O Library routines.\r
3\r
4 Copyright (c) 2020-2021, Intel Corporation. All rights reserved.<BR>\r
5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
6\r
7**/\r
8#include "BaseIoLibIntrinsicInternal.h"\r
9#include <Uefi/UefiBaseType.h>\r
10#include <Include/IndustryStandard/Tdx.h>\r
11#include <Library/TdxLib.h>\r
12#include <Register/Intel/Cpuid.h>\r
7012cb73 13#include <Library/CcProbeLib.h>\r
ab9d7909
MX
14#include "IoLibTdx.h"\r
15\r
16// Size of TDVMCALL Access, including IO and MMIO\r
17#define TDVMCALL_ACCESS_SIZE_1 1\r
18#define TDVMCALL_ACCESS_SIZE_2 2\r
19#define TDVMCALL_ACCESS_SIZE_4 4\r
20#define TDVMCALL_ACCESS_SIZE_8 8\r
21\r
22// Direction of TDVMCALL Access, including IO and MMIO\r
23#define TDVMCALL_ACCESS_READ 0\r
24#define TDVMCALL_ACCESS_WRITE 1\r
25\r
ab9d7909
MX
26/**\r
27 Check if it is Tdx guest.\r
28\r
29 @return TRUE It is Tdx guest\r
30 @return FALSE It is not Tdx guest\r
31\r
32**/\r
33BOOLEAN\r
34EFIAPI\r
35IsTdxGuest (\r
36 VOID\r
37 )\r
38{\r
7012cb73 39 return CcProbe () == CcGuestTypeIntelTdx;\r
ab9d7909
MX
40}\r
41\r
42/**\r
43 Reads an 8-bit I/O port.\r
44\r
45 TDVMCALL_IO is invoked to read I/O port.\r
46\r
47 @param Port The I/O port to read.\r
48\r
49 @return The value read.\r
50\r
51**/\r
52UINT8\r
53EFIAPI\r
54TdIoRead8 (\r
55 IN UINTN Port\r
56 )\r
57{\r
58 UINT64 Status;\r
59 UINT64 Val;\r
60\r
61 Status = TdVmCall (TDVMCALL_IO, TDVMCALL_ACCESS_SIZE_1, TDVMCALL_ACCESS_READ, Port, 0, &Val);\r
62 if (Status != 0) {\r
63 TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0);\r
64 }\r
65\r
66 return (UINT8)Val;\r
67}\r
68\r
69/**\r
70 Reads a 16-bit I/O port.\r
71\r
72 TDVMCALL_IO is invoked to write I/O port.\r
73\r
74 @param Port The I/O port to read.\r
75\r
76 @return The value read.\r
77\r
78**/\r
79UINT16\r
80EFIAPI\r
81TdIoRead16 (\r
82 IN UINTN Port\r
83 )\r
84{\r
85 UINT64 Status;\r
86 UINT64 Val;\r
87\r
88 ASSERT ((Port & 1) == 0);\r
89\r
90 Status = TdVmCall (TDVMCALL_IO, TDVMCALL_ACCESS_SIZE_2, TDVMCALL_ACCESS_READ, Port, 0, &Val);\r
91 if (Status != 0) {\r
92 TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0);\r
93 }\r
94\r
95 return (UINT16)Val;\r
96}\r
97\r
98/**\r
99 Reads a 32-bit I/O port.\r
100\r
101 TDVMCALL_IO is invoked to read I/O port.\r
102\r
103 @param Port The I/O port to read.\r
104\r
105 @return The value read.\r
106\r
107**/\r
108UINT32\r
109EFIAPI\r
110TdIoRead32 (\r
111 IN UINTN Port\r
112 )\r
113{\r
114 UINT64 Status;\r
115 UINT64 Val;\r
116\r
117 ASSERT ((Port & 3) == 0);\r
118\r
119 Status = TdVmCall (TDVMCALL_IO, TDVMCALL_ACCESS_SIZE_4, TDVMCALL_ACCESS_READ, Port, 0, &Val);\r
120 if (Status != 0) {\r
121 TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0);\r
122 }\r
123\r
124 return (UINT32)Val;\r
125}\r
126\r
127/**\r
128 Writes an 8-bit I/O port.\r
129\r
130 TDVMCALL_IO is invoked to write I/O port.\r
131\r
132 @param Port The I/O port to write.\r
133 @param Value The value to write to the I/O port.\r
134\r
135 @return The value written the I/O port.\r
136\r
137**/\r
138UINT8\r
139EFIAPI\r
140TdIoWrite8 (\r
141 IN UINTN Port,\r
142 IN UINT8 Value\r
143 )\r
144{\r
145 UINT64 Status;\r
146 UINT64 Val;\r
147\r
148 Val = Value;\r
149 Status = TdVmCall (TDVMCALL_IO, TDVMCALL_ACCESS_SIZE_1, TDVMCALL_ACCESS_WRITE, Port, Val, 0);\r
150 if (Status != 0) {\r
151 TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0);\r
152 }\r
153\r
154 return Value;\r
155}\r
156\r
157/**\r
158 Writes a 16-bit I/O port.\r
159\r
160 TDVMCALL_IO is invoked to write I/O port.\r
161\r
162 @param Port The I/O port to write.\r
163 @param Value The value to write to the I/O port.\r
164\r
165 @return The value written the I/O port.\r
166\r
167**/\r
168UINT16\r
169EFIAPI\r
170TdIoWrite16 (\r
171 IN UINTN Port,\r
172 IN UINT16 Value\r
173 )\r
174{\r
175 UINT64 Status;\r
176 UINT64 Val;\r
177\r
178 ASSERT ((Port & 1) == 0);\r
179 Val = Value;\r
180 Status = TdVmCall (TDVMCALL_IO, TDVMCALL_ACCESS_SIZE_2, TDVMCALL_ACCESS_WRITE, Port, Val, 0);\r
181 if (Status != 0) {\r
182 TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0);\r
183 }\r
184\r
185 return Value;\r
186}\r
187\r
188/**\r
189 Writes a 32-bit I/O port.\r
190\r
191 TDVMCALL_IO is invoked to write I/O port.\r
192\r
193 @param Port The I/O port to write.\r
194 @param Value The value to write to the I/O port.\r
195\r
196 @return The value written the I/O port.\r
197\r
198**/\r
199UINT32\r
200EFIAPI\r
201TdIoWrite32 (\r
202 IN UINTN Port,\r
203 IN UINT32 Value\r
204 )\r
205{\r
206 UINT64 Status;\r
207 UINT64 Val;\r
208\r
209 ASSERT ((Port & 3) == 0);\r
210 Val = Value;\r
211 Status = TdVmCall (TDVMCALL_IO, TDVMCALL_ACCESS_SIZE_4, TDVMCALL_ACCESS_WRITE, Port, Val, 0);\r
212 if (Status != 0) {\r
213 TdVmCall (TDVMCALL_HALT, 0, 0, 0, 0, 0);\r
214 }\r
215\r
216 return Value;\r
217}\r
218\r
219/**\r
220 Reads an 8-bit MMIO register.\r
221\r
222 TDVMCALL_MMIO is invoked to read MMIO registers.\r
223\r
224 @param Address The MMIO register to read.\r
225\r
226 @return The value read.\r
227\r
228**/\r
229UINT8\r
230EFIAPI\r
231TdMmioRead8 (\r
232 IN UINTN Address\r
233 )\r
234{\r
235 UINT64 Value;\r
236 UINT64 Status;\r
237\r
238 Status = TdVmCall (TDVMCALL_MMIO, TDVMCALL_ACCESS_SIZE_1, TDVMCALL_ACCESS_READ, Address | TdSharedPageMask (), 0, &Value);\r
239 if (Status != 0) {\r
240 Value = *(volatile UINT64 *)Address;\r
241 }\r
242\r
243 return (UINT8)Value;\r
244}\r
245\r
246/**\r
247 Writes an 8-bit MMIO register.\r
248\r
249 TDVMCALL_MMIO is invoked to read write registers.\r
250\r
251 @param Address The MMIO register to write.\r
252 @param Value The value to write to the MMIO register.\r
253\r
254 @return Value.\r
255\r
256**/\r
257UINT8\r
258EFIAPI\r
259TdMmioWrite8 (\r
260 IN UINTN Address,\r
261 IN UINT8 Value\r
262 )\r
263{\r
264 UINT64 Val;\r
265 UINT64 Status;\r
266\r
267 Val = Value;\r
268 Status = TdVmCall (TDVMCALL_MMIO, TDVMCALL_ACCESS_SIZE_1, TDVMCALL_ACCESS_WRITE, Address | TdSharedPageMask (), Val, 0);\r
269 if (Status != 0) {\r
270 *(volatile UINT8 *)Address = Value;\r
271 }\r
272\r
273 return Value;\r
274}\r
275\r
276/**\r
277 Reads a 16-bit MMIO register.\r
278\r
279 TDVMCALL_MMIO is invoked to read MMIO registers.\r
280\r
281 @param Address The MMIO register to read.\r
282\r
283 @return The value read.\r
284\r
285**/\r
286UINT16\r
287EFIAPI\r
288TdMmioRead16 (\r
289 IN UINTN Address\r
290 )\r
291{\r
292 UINT64 Value;\r
293 UINT64 Status;\r
294\r
295 Status = TdVmCall (TDVMCALL_MMIO, TDVMCALL_ACCESS_SIZE_2, TDVMCALL_ACCESS_READ, Address | TdSharedPageMask (), 0, &Value);\r
296 if (Status != 0) {\r
297 Value = *(volatile UINT64 *)Address;\r
298 }\r
299\r
300 return (UINT16)Value;\r
301}\r
302\r
303/**\r
304 Writes a 16-bit MMIO register.\r
305\r
306 TDVMCALL_MMIO is invoked to write MMIO registers.\r
307\r
308 @param Address The MMIO register to write.\r
309 @param Value The value to write to the MMIO register.\r
310\r
311 @return Value.\r
312\r
313**/\r
314UINT16\r
315EFIAPI\r
316TdMmioWrite16 (\r
317 IN UINTN Address,\r
318 IN UINT16 Value\r
319 )\r
320{\r
321 UINT64 Val;\r
322 UINT64 Status;\r
323\r
324 ASSERT ((Address & 1) == 0);\r
325\r
326 Val = Value;\r
327 Status = TdVmCall (TDVMCALL_MMIO, TDVMCALL_ACCESS_SIZE_2, TDVMCALL_ACCESS_WRITE, Address | TdSharedPageMask (), Val, 0);\r
328 if (Status != 0) {\r
329 *(volatile UINT16 *)Address = Value;\r
330 }\r
331\r
332 return Value;\r
333}\r
334\r
335/**\r
336 Reads a 32-bit MMIO register.\r
337\r
338 TDVMCALL_MMIO is invoked to read MMIO registers.\r
339\r
340 @param Address The MMIO register to read.\r
341\r
342 @return The value read.\r
343\r
344**/\r
345UINT32\r
346EFIAPI\r
347TdMmioRead32 (\r
348 IN UINTN Address\r
349 )\r
350{\r
351 UINT64 Value;\r
352 UINT64 Status;\r
353\r
354 Status = TdVmCall (TDVMCALL_MMIO, TDVMCALL_ACCESS_SIZE_4, TDVMCALL_ACCESS_READ, Address | TdSharedPageMask (), 0, &Value);\r
355 if (Status != 0) {\r
356 Value = *(volatile UINT64 *)Address;\r
357 }\r
358\r
359 return (UINT32)Value;\r
360}\r
361\r
362/**\r
363 Writes a 32-bit MMIO register.\r
364\r
365 TDVMCALL_MMIO is invoked to write MMIO registers.\r
366\r
367 @param Address The MMIO register to write.\r
368 @param Value The value to write to the MMIO register.\r
369\r
370 @return Value.\r
371\r
372**/\r
373UINT32\r
374EFIAPI\r
375TdMmioWrite32 (\r
376 IN UINTN Address,\r
377 IN UINT32 Value\r
378 )\r
379{\r
380 UINT64 Val;\r
381 UINT64 Status;\r
382\r
383 ASSERT ((Address & 3) == 0);\r
384\r
385 Val = Value;\r
386 Status = TdVmCall (TDVMCALL_MMIO, TDVMCALL_ACCESS_SIZE_4, TDVMCALL_ACCESS_WRITE, Address | TdSharedPageMask (), Val, 0);\r
387 if (Status != 0) {\r
388 *(volatile UINT32 *)Address = Value;\r
389 }\r
390\r
391 return Value;\r
392}\r
393\r
394/**\r
395 Reads a 64-bit MMIO register.\r
396\r
397 TDVMCALL_MMIO is invoked to read MMIO registers.\r
398\r
399 @param Address The MMIO register to read.\r
400\r
401 @return The value read.\r
402\r
403**/\r
404UINT64\r
405EFIAPI\r
406TdMmioRead64 (\r
407 IN UINTN Address\r
408 )\r
409{\r
410 UINT64 Value;\r
411 UINT64 Status;\r
412\r
413 Status = TdVmCall (TDVMCALL_MMIO, TDVMCALL_ACCESS_SIZE_8, TDVMCALL_ACCESS_READ, Address | TdSharedPageMask (), 0, &Value);\r
414 if (Status != 0) {\r
415 Value = *(volatile UINT64 *)Address;\r
416 }\r
417\r
418 return Value;\r
419}\r
420\r
421/**\r
422 Writes a 64-bit MMIO register.\r
423\r
424 TDVMCALL_MMIO is invoked to write MMIO registers.\r
425\r
426 @param Address The MMIO register to write.\r
427 @param Value The value to write to the MMIO register.\r
428\r
429**/\r
430UINT64\r
431EFIAPI\r
432TdMmioWrite64 (\r
433 IN UINTN Address,\r
434 IN UINT64 Value\r
435 )\r
436{\r
437 UINT64 Status;\r
438 UINT64 Val;\r
439\r
440 ASSERT ((Address & 7) == 0);\r
441\r
442 Val = Value;\r
443 Status = TdVmCall (TDVMCALL_MMIO, TDVMCALL_ACCESS_SIZE_8, TDVMCALL_ACCESS_WRITE, Address | TdSharedPageMask (), Val, 0);\r
444 if (Status != 0) {\r
445 *(volatile UINT64 *)Address = Value;\r
446 }\r
447\r
448 return Value;\r
449}\r
450\r
451/**\r
452 Reads an 8-bit I/O port fifo into a block of memory.\r
453\r
454 Reads the 8-bit I/O fifo port specified by Port.\r
455 The port is read Count times, and the read data is\r
456 stored in the provided Buffer.\r
457\r
458 This function must guarantee that all I/O read and write operations are\r
459 serialized.\r
460\r
461 If 8-bit I/O port operations are not supported, then ASSERT().\r
462\r
463 In TDX a serial of TdIoRead8 is invoked to read the I/O port fifo.\r
464\r
465 @param Port The I/O port to read.\r
466 @param Count The number of times to read I/O port.\r
467 @param Buffer The buffer to store the read data into.\r
468\r
469**/\r
470VOID\r
471EFIAPI\r
472TdIoReadFifo8 (\r
473 IN UINTN Port,\r
474 IN UINTN Count,\r
475 OUT VOID *Buffer\r
476 )\r
477{\r
478 UINT8 *Buf8;\r
479 UINTN Index;\r
480\r
481 Buf8 = (UINT8 *)Buffer;\r
482 for (Index = 0; Index < Count; Index++) {\r
483 Buf8[Index] = TdIoRead8 (Port);\r
484 }\r
485}\r
486\r
487/**\r
488 Writes a block of memory into an 8-bit I/O port fifo.\r
489\r
490 Writes the 8-bit I/O fifo port specified by Port.\r
491 The port is written Count times, and the write data is\r
492 retrieved from the provided Buffer.\r
493\r
494 This function must guarantee that all I/O write and write operations are\r
495 serialized.\r
496\r
497 If 8-bit I/O port operations are not supported, then ASSERT().\r
498\r
499 In TDX a serial of TdIoWrite8 is invoked to write data to the I/O port.\r
500\r
501 @param Port The I/O port to write.\r
502 @param Count The number of times to write I/O port.\r
503 @param Buffer The buffer to retrieve the write data from.\r
504\r
505**/\r
506VOID\r
507EFIAPI\r
508TdIoWriteFifo8 (\r
509 IN UINTN Port,\r
510 IN UINTN Count,\r
511 IN VOID *Buffer\r
512 )\r
513{\r
514 UINT8 *Buf8;\r
515 UINTN Index;\r
516\r
517 Buf8 = (UINT8 *)Buffer;\r
518 for (Index = 0; Index < Count; Index++) {\r
519 TdIoWrite8 (Port, Buf8[Index]);\r
520 }\r
521}\r
522\r
523/**\r
524 Reads a 16-bit I/O port fifo into a block of memory.\r
525\r
526 Reads the 16-bit I/O fifo port specified by Port.\r
527 The port is read Count times, and the read data is\r
528 stored in the provided Buffer.\r
529\r
530 This function must guarantee that all I/O read and write operations are\r
531 serialized.\r
532\r
533 If 16-bit I/O port operations are not supported, then ASSERT().\r
534\r
535 In TDX a serial of TdIoRead16 is invoked to read data from the I/O port.\r
536\r
537 @param Port The I/O port to read.\r
538 @param Count The number of times to read I/O port.\r
539 @param Buffer The buffer to store the read data into.\r
540\r
541**/\r
542VOID\r
543EFIAPI\r
544TdIoReadFifo16 (\r
545 IN UINTN Port,\r
546 IN UINTN Count,\r
547 OUT VOID *Buffer\r
548 )\r
549{\r
550 UINT16 *Buf16;\r
551 UINTN Index;\r
552\r
553 Buf16 = (UINT16 *)Buffer;\r
554 for (Index = 0; Index < Count; Index++) {\r
555 Buf16[Index] = TdIoRead16 (Port);\r
556 }\r
557}\r
558\r
559/**\r
560 Writes a block of memory into a 16-bit I/O port fifo.\r
561\r
562 Writes the 16-bit I/O fifo port specified by Port.\r
563 The port is written Count times, and the write data is\r
564 retrieved from the provided Buffer.\r
565\r
566 This function must guarantee that all I/O write and write operations are\r
567 serialized.\r
568\r
569 If 16-bit I/O port operations are not supported, then ASSERT().\r
570\r
571 In TDX a serial of TdIoWrite16 is invoked to write data to the I/O port.\r
572\r
573 @param Port The I/O port to write.\r
574 @param Count The number of times to write I/O port.\r
575 @param Buffer The buffer to retrieve the write data from.\r
576\r
577**/\r
578VOID\r
579EFIAPI\r
580TdIoWriteFifo16 (\r
581 IN UINTN Port,\r
582 IN UINTN Count,\r
583 IN VOID *Buffer\r
584 )\r
585{\r
586 UINT16 *Buf16;\r
587 UINTN Index;\r
588\r
589 Buf16 = (UINT16 *)Buffer;\r
590 for (Index = 0; Index < Count; Index++) {\r
591 TdIoWrite16 (Port, Buf16[Index]);\r
592 }\r
593}\r
594\r
595/**\r
596 Reads a 32-bit I/O port fifo into a block of memory.\r
597\r
598 Reads the 32-bit I/O fifo port specified by Port.\r
599 The port is read Count times, and the read data is\r
600 stored in the provided Buffer.\r
601\r
602 This function must guarantee that all I/O read and write operations are\r
603 serialized.\r
604\r
605 If 32-bit I/O port operations are not supported, then ASSERT().\r
606\r
607 In TDX a serial of TdIoRead32 is invoked to read data from the I/O port.\r
608\r
609 @param Port The I/O port to read.\r
610 @param Count The number of times to read I/O port.\r
611 @param Buffer The buffer to store the read data into.\r
612\r
613**/\r
614VOID\r
615EFIAPI\r
616TdIoReadFifo32 (\r
617 IN UINTN Port,\r
618 IN UINTN Count,\r
619 OUT VOID *Buffer\r
620 )\r
621{\r
622 UINT32 *Buf32;\r
623 UINTN Index;\r
624\r
625 Buf32 = (UINT32 *)Buffer;\r
626 for (Index = 0; Index < Count; Index++) {\r
627 Buf32[Index] = TdIoRead32 (Port);\r
628 }\r
629}\r
630\r
631/**\r
632 Writes a block of memory into a 32-bit I/O port fifo.\r
633\r
634 Writes the 32-bit I/O fifo port specified by Port.\r
635 The port is written Count times, and the write data is\r
636 retrieved from the provided Buffer.\r
637\r
638 This function must guarantee that all I/O write and write operations are\r
639 serialized.\r
640\r
641 If 32-bit I/O port operations are not supported, then ASSERT().\r
642\r
643 In TDX a serial of TdIoWrite32 is invoked to write data to the I/O port.\r
644\r
645 @param Port The I/O port to write.\r
646 @param Count The number of times to write I/O port.\r
647 @param Buffer The buffer to retrieve the write data from.\r
648\r
649**/\r
650VOID\r
651EFIAPI\r
652TdIoWriteFifo32 (\r
653 IN UINTN Port,\r
654 IN UINTN Count,\r
655 IN VOID *Buffer\r
656 )\r
657{\r
658 UINT32 *Buf32;\r
659 UINTN Index;\r
660\r
661 Buf32 = (UINT32 *)Buffer;\r
662 for (Index = 0; Index < Count; Index++) {\r
663 TdIoWrite32 (Port, Buf32[Index]);\r
664 }\r
665}\r