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