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