]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/BaseIoLibIntrinsic/IoLibGcc.c
MdePkg: Support IoRead/IoWrite for Tdx guest in BaseIoLibIntrinsic
[mirror_edk2.git] / MdePkg / Library / BaseIoLibIntrinsic / IoLibGcc.c
CommitLineData
e1f414b6 1/** @file\r
2 I/O Library. This file has compiler specifics for GCC as there is no\r
3 ANSI C standard for doing IO.\r
4\r
5 GCC - uses EFIAPI assembler. __asm__ calls GAS. __volatile__ makes sure the\r
6 compiler puts the assembler in this exact location. The complex GNUC\r
7 operations are not optimzed. It would be possible to also write these\r
8 with EFIAPI assembler.\r
9\r
10 We don't advocate putting compiler specifics in libraries or drivers but there\r
11 is no other way to make this work.\r
12\r
38c8be12 13 Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR>\r
9344f092 14 SPDX-License-Identifier: BSD-2-Clause-Patent\r
e1f414b6 15\r
e1f414b6 16**/\r
17\r
f734a10a 18#include "BaseIoLibIntrinsicInternal.h"\r
3571fc90 19#include "IoLibTdx.h"\r
e1f414b6 20\r
2281e7a9 21/**\r
22 Reads an 8-bit I/O port.\r
23\r
24 Reads the 8-bit I/O port specified by Port. The 8-bit read value is returned.\r
25 This function must guarantee that all I/O read and write operations are\r
26 serialized.\r
27\r
3571fc90
MX
28 If 8-bit I/O port operations are not supported, then ASSERT()\r
29\r
30 For Td guest TDVMCALL_IO is invoked to read I/O port.\r
2281e7a9 31\r
32 @param Port The I/O port to read.\r
33\r
34 @return The value read.\r
35\r
36**/\r
e1f414b6 37UINT8\r
38EFIAPI\r
39IoRead8 (\r
2f88bd3a 40 IN UINTN Port\r
e1f414b6 41 )\r
42{\r
2f88bd3a
MK
43 UINT8 Data;\r
44 BOOLEAN Flag;\r
38c8be12
DB
45\r
46 Flag = FilterBeforeIoRead (FilterWidth8, Port, &Data);\r
47 if (Flag) {\r
3571fc90
MX
48 if (IsTdxGuest ()) {\r
49 Data = TdIoRead8 (Port);\r
50 } else {\r
51 __asm__ __volatile__ ("inb %w1,%b0" : "=a" (Data) : "d" ((UINT16)Port));\r
52 }\r
38c8be12 53 }\r
2f88bd3a 54\r
38c8be12 55 FilterAfterIoRead (FilterWidth8, Port, &Data);\r
e1f414b6 56\r
e1f414b6 57 return Data;\r
58}\r
59\r
2281e7a9 60/**\r
61 Writes an 8-bit I/O port.\r
62\r
63 Writes the 8-bit I/O port specified by Port with the value specified by Value\r
64 and returns Value. This function must guarantee that all I/O read and write\r
65 operations are serialized.\r
66\r
67 If 8-bit I/O port operations are not supported, then ASSERT().\r
68\r
3571fc90
MX
69 For Td guest TDVMCALL_IO is invoked to write I/O port.\r
70\r
2281e7a9 71 @param Port The I/O port to write.\r
72 @param Value The value to write to the I/O port.\r
73\r
74 @return The value written the I/O port.\r
75\r
76**/\r
e1f414b6 77UINT8\r
78EFIAPI\r
79IoWrite8 (\r
2f88bd3a
MK
80 IN UINTN Port,\r
81 IN UINT8 Value\r
e1f414b6 82 )\r
83{\r
2f88bd3a 84 BOOLEAN Flag;\r
38c8be12
DB
85\r
86 Flag = FilterBeforeIoWrite (FilterWidth8, Port, &Value);\r
87 if (Flag) {\r
3571fc90
MX
88 if (IsTdxGuest ()) {\r
89 TdIoWrite8 (Port, Value);\r
90 } else {\r
91 __asm__ __volatile__ ("outb %b0,%w1" : : "a" (Value), "d" ((UINT16)Port));\r
92 }\r
38c8be12 93 }\r
2f88bd3a 94\r
38c8be12
DB
95 FilterAfterIoWrite (FilterWidth8, Port, &Value);\r
96\r
2f88bd3a 97 return Value;\r
e1f414b6 98}\r
99\r
2281e7a9 100/**\r
101 Reads a 16-bit I/O port.\r
102\r
103 Reads the 16-bit I/O port specified by Port. The 16-bit read value is returned.\r
104 This function must guarantee that all I/O read and write operations are\r
105 serialized.\r
106\r
107 If 16-bit I/O port operations are not supported, then ASSERT().\r
108 If Port is not aligned on a 16-bit boundary, then ASSERT().\r
109\r
3571fc90
MX
110 For Td guest TDVMCALL_IO is invoked to read I/O port.\r
111\r
2281e7a9 112 @param Port The I/O port to read.\r
113\r
114 @return The value read.\r
115\r
116**/\r
e1f414b6 117UINT16\r
118EFIAPI\r
119IoRead16 (\r
2f88bd3a 120 IN UINTN Port\r
e1f414b6 121 )\r
122{\r
123 UINT16 Data;\r
38c8be12 124 BOOLEAN Flag;\r
e1f414b6 125\r
126 ASSERT ((Port & 1) == 0);\r
38c8be12
DB
127\r
128 Flag = FilterBeforeIoRead (FilterWidth16, Port, &Data);\r
129 if (Flag) {\r
3571fc90
MX
130 if (IsTdxGuest ()) {\r
131 Data = TdIoRead16 (Port);\r
132 } else {\r
133 __asm__ __volatile__ ("inw %w1,%w0" : "=a" (Data) : "d" ((UINT16)Port));\r
134 }\r
38c8be12 135 }\r
2f88bd3a 136\r
38c8be12
DB
137 FilterAfterIoRead (FilterWidth16, Port, &Data);\r
138\r
e1f414b6 139 return Data;\r
140}\r
141\r
2281e7a9 142/**\r
143 Writes a 16-bit I/O port.\r
144\r
145 Writes the 16-bit I/O port specified by Port with the value specified by Value\r
146 and returns Value. This function must guarantee that all I/O read and write\r
147 operations are serialized.\r
148\r
149 If 16-bit I/O port operations are not supported, then ASSERT().\r
150 If Port is not aligned on a 16-bit boundary, then ASSERT().\r
9095d37b 151\r
3571fc90
MX
152 For Td guest TDVMCALL_IO is invoked to write I/O port.\r
153\r
2281e7a9 154 @param Port The I/O port to write.\r
155 @param Value The value to write to the I/O port.\r
156\r
157 @return The value written the I/O port.\r
158\r
159**/\r
e1f414b6 160UINT16\r
161EFIAPI\r
162IoWrite16 (\r
2f88bd3a
MK
163 IN UINTN Port,\r
164 IN UINT16 Value\r
e1f414b6 165 )\r
166{\r
2f88bd3a 167 BOOLEAN Flag;\r
38c8be12 168\r
e1f414b6 169 ASSERT ((Port & 1) == 0);\r
38c8be12
DB
170\r
171 Flag = FilterBeforeIoWrite (FilterWidth16, Port, &Value);\r
172 if (Flag) {\r
3571fc90
MX
173 if (IsTdxGuest ()) {\r
174 TdIoWrite16 (Port, Value);\r
175 } else {\r
176 __asm__ __volatile__ ("outw %w0,%w1" : : "a" (Value), "d" ((UINT16)Port));\r
177 }\r
38c8be12 178 }\r
2f88bd3a 179\r
38c8be12
DB
180 FilterAfterIoWrite (FilterWidth16, Port, &Value);\r
181\r
2f88bd3a 182 return Value;\r
e1f414b6 183}\r
184\r
2281e7a9 185/**\r
186 Reads a 32-bit I/O port.\r
187\r
188 Reads the 32-bit I/O port specified by Port. The 32-bit read value is returned.\r
189 This function must guarantee that all I/O read and write operations are\r
190 serialized.\r
191\r
192 If 32-bit I/O port operations are not supported, then ASSERT().\r
193 If Port is not aligned on a 32-bit boundary, then ASSERT().\r
9095d37b 194\r
3571fc90
MX
195 For Td guest TDVMCALL_IO is invoked to read I/O port.\r
196\r
2281e7a9 197 @param Port The I/O port to read.\r
198\r
199 @return The value read.\r
200\r
201**/\r
e1f414b6 202UINT32\r
203EFIAPI\r
204IoRead32 (\r
2f88bd3a 205 IN UINTN Port\r
e1f414b6 206 )\r
207{\r
208 UINT32 Data;\r
38c8be12 209 BOOLEAN Flag;\r
e1f414b6 210\r
211 ASSERT ((Port & 3) == 0);\r
38c8be12
DB
212\r
213 Flag = FilterBeforeIoRead (FilterWidth32, Port, &Data);\r
214 if (Flag) {\r
3571fc90
MX
215 if (IsTdxGuest ()) {\r
216 Data = TdIoRead32 (Port);\r
217 } else {\r
218 __asm__ __volatile__ ("inl %w1,%0" : "=a" (Data) : "d" ((UINT16)Port));\r
219 }\r
38c8be12 220 }\r
2f88bd3a 221\r
38c8be12
DB
222 FilterAfterIoRead (FilterWidth32, Port, &Data);\r
223\r
e1f414b6 224 return Data;\r
225}\r
226\r
2281e7a9 227/**\r
228 Writes a 32-bit I/O port.\r
229\r
230 Writes the 32-bit I/O port specified by Port with the value specified by Value\r
231 and returns Value. This function must guarantee that all I/O read and write\r
232 operations are serialized.\r
233\r
234 If 32-bit I/O port operations are not supported, then ASSERT().\r
235 If Port is not aligned on a 32-bit boundary, then ASSERT().\r
9095d37b 236\r
3571fc90
MX
237 For Td guest TDVMCALL_IO is invoked to write I/O port.\r
238\r
2281e7a9 239 @param Port The I/O port to write.\r
240 @param Value The value to write to the I/O port.\r
241\r
242 @return The value written the I/O port.\r
243\r
244**/\r
e1f414b6 245UINT32\r
246EFIAPI\r
247IoWrite32 (\r
2f88bd3a
MK
248 IN UINTN Port,\r
249 IN UINT32 Value\r
e1f414b6 250 )\r
251{\r
38c8be12
DB
252 BOOLEAN Flag;\r
253\r
e1f414b6 254 ASSERT ((Port & 3) == 0);\r
38c8be12
DB
255\r
256 Flag = FilterBeforeIoWrite (FilterWidth32, Port, &Value);\r
257 if (Flag) {\r
3571fc90
MX
258 if (IsTdxGuest ()) {\r
259 TdIoWrite32 (Port, Value);\r
260 } else {\r
261 __asm__ __volatile__ ("outl %0,%w1" : : "a" (Value), "d" ((UINT16)Port));\r
262 }\r
38c8be12 263 }\r
2f88bd3a 264\r
38c8be12
DB
265 FilterAfterIoWrite (FilterWidth32, Port, &Value);\r
266\r
e1f414b6 267 return Value;\r
268}\r