1 /** @file
2   GCC inline implementation of BaseLib processor specific functions that use
3   privlidged instructions.
4 
5   Copyright (c) 2006 - 2020, Intel Corporation. All rights reserved.<BR>
6   Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
7   SPDX-License-Identifier: BSD-2-Clause-Patent
8 
9 **/
10 
11 
12 #include "BaseLibInternals.h"
13 
14 /**
15   Enables CPU interrupts.
16 
17   Enables CPU interrupts.
18 
19 **/
20 VOID
21 EFIAPI
22 EnableInterrupts (
23   VOID
24   )
25 {
26   __asm__ __volatile__ ("sti"::: "memory");
27 }
28 
29 
30 /**
31   Disables CPU interrupts.
32 
33   Disables CPU interrupts.
34 
35 **/
36 VOID
37 EFIAPI
38 DisableInterrupts (
39   VOID
40   )
41 {
42   __asm__ __volatile__ ("cli"::: "memory");
43 }
44 
45 /**
46   Returns a 64-bit Machine Specific Register(MSR).
47 
48   Reads and returns the 64-bit MSR specified by Index. No parameter checking is
49   performed on Index, and some Index values may cause CPU exceptions. The
50   caller must either guarantee that Index is valid, or the caller must set up
51   exception handlers to catch the exceptions. This function is only available
52   on IA-32 and X64.
53 
54   @param  Index The 32-bit MSR index to read.
55 
56   @return The value of the MSR identified by Index.
57 
58 **/
59 UINT64
60 EFIAPI
61 AsmReadMsr64 (
62   IN      UINT32                    Index
63   )
64 {
65   UINT32 LowData;
66   UINT32 HighData;
67 
68   __asm__ __volatile__ (
69     "rdmsr"
70     : "=a" (LowData),   // %0
71       "=d" (HighData)   // %1
72     : "c"  (Index)      // %2
73     );
74 
75   return (((UINT64)HighData) << 32) | LowData;
76 }
77 
78 /**
79   Writes a 64-bit value to a Machine Specific Register(MSR), and returns the
80   value.
81 
82   Writes the 64-bit value specified by Value to the MSR specified by Index. The
83   64-bit value written to the MSR is returned. No parameter checking is
84   performed on Index or Value, and some of these may cause CPU exceptions. The
85   caller must either guarantee that Index and Value are valid, or the caller
86   must establish proper exception handlers. This function is only available on
87   IA-32 and X64.
88 
89   @param  Index The 32-bit MSR index to write.
90   @param  Value The 64-bit value to write to the MSR.
91 
92   @return Value
93 
94 **/
95 UINT64
96 EFIAPI
97 AsmWriteMsr64 (
98   IN      UINT32                    Index,
99   IN      UINT64                    Value
100   )
101 {
102   UINT32 LowData;
103   UINT32 HighData;
104 
105   LowData  = (UINT32)(Value);
106   HighData = (UINT32)(Value >> 32);
107 
108   __asm__ __volatile__ (
109     "wrmsr"
110     :
111     : "c" (Index),
112       "a" (LowData),
113       "d" (HighData)
114     );
115 
116   return Value;
117 }
118 
119 /**
120   Reads the current value of the Control Register 0 (CR0).
121 
122   Reads and returns the current value of CR0. This function is only available
123   on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
124   X64.
125 
126   @return The value of the Control Register 0 (CR0).
127 
128 **/
129 UINTN
130 EFIAPI
131 AsmReadCr0 (
132   VOID
133   )
134 {
135   UINTN   Data;
136 
137   __asm__ __volatile__ (
138     "mov  %%cr0,%0"
139     : "=r" (Data)           // %0
140     );
141 
142   return Data;
143 }
144 
145 
146 /**
147   Reads the current value of the Control Register 2 (CR2).
148 
149   Reads and returns the current value of CR2. This function is only available
150   on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
151   X64.
152 
153   @return The value of the Control Register 2 (CR2).
154 
155 **/
156 UINTN
157 EFIAPI
158 AsmReadCr2 (
159   VOID
160   )
161 {
162   UINTN Data;
163 
164   __asm__ __volatile__ (
165     "mov  %%cr2,  %0"
166     : "=r" (Data)           // %0
167     );
168 
169   return Data;
170 }
171 
172 /**
173   Reads the current value of the Control Register 3 (CR3).
174 
175   Reads and returns the current value of CR3. This function is only available
176   on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
177   X64.
178 
179   @return The value of the Control Register 3 (CR3).
180 
181 **/
182 UINTN
183 EFIAPI
184 AsmReadCr3 (
185   VOID
186   )
187 {
188   UINTN Data;
189 
190   __asm__ __volatile__ (
191     "mov  %%cr3,  %0"
192     : "=r" (Data)           // %0
193     );
194 
195   return Data;
196 }
197 
198 
199 /**
200   Reads the current value of the Control Register 4 (CR4).
201 
202   Reads and returns the current value of CR4. This function is only available
203   on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
204   X64.
205 
206   @return The value of the Control Register 4 (CR4).
207 
208 **/
209 UINTN
210 EFIAPI
211 AsmReadCr4 (
212   VOID
213   )
214 {
215   UINTN Data;
216 
217   __asm__ __volatile__ (
218     "mov  %%cr4,  %0"
219     : "=r" (Data)           // %0
220     );
221 
222   return Data;
223 }
224 
225 
226 /**
227   Writes a value to Control Register 0 (CR0).
228 
229   Writes and returns a new value to CR0. This function is only available on
230   IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
231 
232   @param  Cr0 The value to write to CR0.
233 
234   @return The value written to CR0.
235 
236 **/
237 UINTN
238 EFIAPI
239 AsmWriteCr0 (
240   UINTN  Cr0
241   )
242 {
243   __asm__ __volatile__ (
244     "mov  %0, %%cr0"
245     :
246     : "r" (Cr0)
247     );
248   return Cr0;
249 }
250 
251 
252 /**
253   Writes a value to Control Register 2 (CR2).
254 
255   Writes and returns a new value to CR2. This function is only available on
256   IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
257 
258   @param  Cr2 The value to write to CR2.
259 
260   @return The value written to CR2.
261 
262 **/
263 UINTN
264 EFIAPI
265 AsmWriteCr2 (
266   UINTN  Cr2
267   )
268 {
269   __asm__ __volatile__ (
270     "mov  %0, %%cr2"
271     :
272     : "r" (Cr2)
273     );
274   return Cr2;
275 }
276 
277 
278 /**
279   Writes a value to Control Register 3 (CR3).
280 
281   Writes and returns a new value to CR3. This function is only available on
282   IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
283 
284   @param  Cr3 The value to write to CR3.
285 
286   @return The value written to CR3.
287 
288 **/
289 UINTN
290 EFIAPI
291 AsmWriteCr3 (
292   UINTN  Cr3
293   )
294 {
295   __asm__ __volatile__ (
296     "mov  %0, %%cr3"
297     :
298     : "r" (Cr3)
299     );
300   return Cr3;
301 }
302 
303 
304 /**
305   Writes a value to Control Register 4 (CR4).
306 
307   Writes and returns a new value to CR4. This function is only available on
308   IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
309 
310   @param  Cr4 The value to write to CR4.
311 
312   @return The value written to CR4.
313 
314 **/
315 UINTN
316 EFIAPI
317 AsmWriteCr4 (
318   UINTN  Cr4
319   )
320 {
321   __asm__ __volatile__ (
322     "mov  %0, %%cr4"
323     :
324     : "r" (Cr4)
325     );
326   return Cr4;
327 }
328 
329 
330 /**
331   Reads the current value of Debug Register 0 (DR0).
332 
333   Reads and returns the current value of DR0. This function is only available
334   on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
335   X64.
336 
337   @return The value of Debug Register 0 (DR0).
338 
339 **/
340 UINTN
341 EFIAPI
342 AsmReadDr0 (
343   VOID
344   )
345 {
346   UINTN Data;
347 
348   __asm__ __volatile__ (
349     "mov  %%dr0, %0"
350     : "=r" (Data)
351     );
352 
353   return Data;
354 }
355 
356 
357 /**
358   Reads the current value of Debug Register 1 (DR1).
359 
360   Reads and returns the current value of DR1. This function is only available
361   on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
362   X64.
363 
364   @return The value of Debug Register 1 (DR1).
365 
366 **/
367 UINTN
368 EFIAPI
369 AsmReadDr1 (
370   VOID
371   )
372 {
373   UINTN Data;
374 
375   __asm__ __volatile__ (
376     "mov  %%dr1, %0"
377     : "=r" (Data)
378     );
379 
380   return Data;
381 }
382 
383 
384 /**
385   Reads the current value of Debug Register 2 (DR2).
386 
387   Reads and returns the current value of DR2. This function is only available
388   on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
389   X64.
390 
391   @return The value of Debug Register 2 (DR2).
392 
393 **/
394 UINTN
395 EFIAPI
396 AsmReadDr2 (
397   VOID
398   )
399 {
400   UINTN Data;
401 
402   __asm__ __volatile__ (
403     "mov  %%dr2, %0"
404     : "=r" (Data)
405     );
406 
407   return Data;
408 }
409 
410 
411 /**
412   Reads the current value of Debug Register 3 (DR3).
413 
414   Reads and returns the current value of DR3. This function is only available
415   on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
416   X64.
417 
418   @return The value of Debug Register 3 (DR3).
419 
420 **/
421 UINTN
422 EFIAPI
423 AsmReadDr3 (
424   VOID
425   )
426 {
427   UINTN Data;
428 
429   __asm__ __volatile__ (
430     "mov  %%dr3, %0"
431     : "=r" (Data)
432     );
433 
434   return Data;
435 }
436 
437 
438 /**
439   Reads the current value of Debug Register 4 (DR4).
440 
441   Reads and returns the current value of DR4. This function is only available
442   on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
443   X64.
444 
445   @return The value of Debug Register 4 (DR4).
446 
447 **/
448 UINTN
449 EFIAPI
450 AsmReadDr4 (
451   VOID
452   )
453 {
454   UINTN Data;
455 
456   __asm__ __volatile__ (
457     "mov  %%dr4, %0"
458     : "=r" (Data)
459     );
460 
461   return Data;
462 }
463 
464 
465 /**
466   Reads the current value of Debug Register 5 (DR5).
467 
468   Reads and returns the current value of DR5. This function is only available
469   on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
470   X64.
471 
472   @return The value of Debug Register 5 (DR5).
473 
474 **/
475 UINTN
476 EFIAPI
477 AsmReadDr5 (
478   VOID
479   )
480 {
481   UINTN Data;
482 
483   __asm__ __volatile__ (
484     "mov  %%dr5, %0"
485     : "=r" (Data)
486     );
487 
488   return Data;
489 }
490 
491 
492 /**
493   Reads the current value of Debug Register 6 (DR6).
494 
495   Reads and returns the current value of DR6. This function is only available
496   on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
497   X64.
498 
499   @return The value of Debug Register 6 (DR6).
500 
501 **/
502 UINTN
503 EFIAPI
504 AsmReadDr6 (
505   VOID
506   )
507 {
508   UINTN Data;
509 
510   __asm__ __volatile__ (
511     "mov  %%dr6, %0"
512     : "=r" (Data)
513     );
514 
515   return Data;
516 }
517 
518 
519 /**
520   Reads the current value of Debug Register 7 (DR7).
521 
522   Reads and returns the current value of DR7. This function is only available
523   on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
524   X64.
525 
526   @return The value of Debug Register 7 (DR7).
527 
528 **/
529 UINTN
530 EFIAPI
531 AsmReadDr7 (
532   VOID
533   )
534 {
535   UINTN Data;
536 
537   __asm__ __volatile__ (
538     "mov  %%dr7, %0"
539     : "=r" (Data)
540     );
541 
542   return Data;
543 }
544 
545 
546 /**
547   Writes a value to Debug Register 0 (DR0).
548 
549   Writes and returns a new value to DR0. This function is only available on
550   IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
551 
552   @param  Dr0 The value to write to Dr0.
553 
554   @return The value written to Debug Register 0 (DR0).
555 
556 **/
557 UINTN
558 EFIAPI
559 AsmWriteDr0 (
560   UINTN  Dr0
561   )
562 {
563   __asm__ __volatile__ (
564     "mov  %0, %%dr0"
565     :
566     : "r" (Dr0)
567     );
568   return Dr0;
569 }
570 
571 
572 /**
573   Writes a value to Debug Register 1 (DR1).
574 
575   Writes and returns a new value to DR1. This function is only available on
576   IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
577 
578   @param  Dr1 The value to write to Dr1.
579 
580   @return The value written to Debug Register 1 (DR1).
581 
582 **/
583 UINTN
584 EFIAPI
585 AsmWriteDr1 (
586   UINTN  Dr1
587   )
588 {
589   __asm__ __volatile__ (
590     "mov  %0, %%dr1"
591     :
592     : "r" (Dr1)
593     );
594   return Dr1;
595 }
596 
597 
598 /**
599   Writes a value to Debug Register 2 (DR2).
600 
601   Writes and returns a new value to DR2. This function is only available on
602   IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
603 
604   @param  Dr2 The value to write to Dr2.
605 
606   @return The value written to Debug Register 2 (DR2).
607 
608 **/
609 UINTN
610 EFIAPI
611 AsmWriteDr2 (
612   UINTN  Dr2
613   )
614 {
615   __asm__ __volatile__ (
616     "mov  %0, %%dr2"
617     :
618     : "r" (Dr2)
619     );
620   return Dr2;
621 }
622 
623 
624 /**
625   Writes a value to Debug Register 3 (DR3).
626 
627   Writes and returns a new value to DR3. This function is only available on
628   IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
629 
630   @param  Dr3 The value to write to Dr3.
631 
632   @return The value written to Debug Register 3 (DR3).
633 
634 **/
635 UINTN
636 EFIAPI
637 AsmWriteDr3 (
638   UINTN  Dr3
639   )
640 {
641   __asm__ __volatile__ (
642     "mov  %0, %%dr3"
643     :
644     : "r" (Dr3)
645     );
646   return Dr3;
647 }
648 
649 
650 /**
651   Writes a value to Debug Register 4 (DR4).
652 
653   Writes and returns a new value to DR4. This function is only available on
654   IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
655 
656   @param  Dr4 The value to write to Dr4.
657 
658   @return The value written to Debug Register 4 (DR4).
659 
660 **/
661 UINTN
662 EFIAPI
663 AsmWriteDr4 (
664   UINTN  Dr4
665   )
666 {
667   __asm__ __volatile__ (
668     "mov  %0, %%dr4"
669     :
670     : "r" (Dr4)
671     );
672   return Dr4;
673 }
674 
675 
676 /**
677   Writes a value to Debug Register 5 (DR5).
678 
679   Writes and returns a new value to DR5. This function is only available on
680   IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
681 
682   @param  Dr5 The value to write to Dr5.
683 
684   @return The value written to Debug Register 5 (DR5).
685 
686 **/
687 UINTN
688 EFIAPI
689 AsmWriteDr5 (
690   UINTN  Dr5
691   )
692 {
693   __asm__ __volatile__ (
694     "mov  %0, %%dr5"
695     :
696     : "r" (Dr5)
697     );
698   return Dr5;
699 }
700 
701 
702 /**
703   Writes a value to Debug Register 6 (DR6).
704 
705   Writes and returns a new value to DR6. This function is only available on
706   IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
707 
708   @param  Dr6 The value to write to Dr6.
709 
710   @return The value written to Debug Register 6 (DR6).
711 
712 **/
713 UINTN
714 EFIAPI
715 AsmWriteDr6 (
716   UINTN  Dr6
717   )
718 {
719   __asm__ __volatile__ (
720     "mov  %0, %%dr6"
721     :
722     : "r" (Dr6)
723     );
724   return Dr6;
725 }
726 
727 
728 /**
729   Writes a value to Debug Register 7 (DR7).
730 
731   Writes and returns a new value to DR7. This function is only available on
732   IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
733 
734   @param  Dr7 The value to write to Dr7.
735 
736   @return The value written to Debug Register 7 (DR7).
737 
738 **/
739 UINTN
740 EFIAPI
741 AsmWriteDr7 (
742   UINTN  Dr7
743   )
744 {
745   __asm__ __volatile__ (
746     "mov  %0, %%dr7"
747     :
748     : "r" (Dr7)
749     );
750   return Dr7;
751 }
752 
753 
754 /**
755   Reads the current value of Code Segment Register (CS).
756 
757   Reads and returns the current value of CS. This function is only available on
758   IA-32 and X64.
759 
760   @return The current value of CS.
761 
762 **/
763 UINT16
764 EFIAPI
765 AsmReadCs (
766   VOID
767   )
768 {
769   UINT16  Data;
770 
771   __asm__ __volatile__ (
772     "mov   %%cs, %0"
773     :"=a" (Data)
774     );
775 
776   return Data;
777 }
778 
779 
780 /**
781   Reads the current value of Data Segment Register (DS).
782 
783   Reads and returns the current value of DS. This function is only available on
784   IA-32 and X64.
785 
786   @return The current value of DS.
787 
788 **/
789 UINT16
790 EFIAPI
791 AsmReadDs (
792   VOID
793   )
794 {
795   UINT16  Data;
796 
797   __asm__ __volatile__ (
798     "mov  %%ds, %0"
799     :"=a" (Data)
800     );
801 
802   return Data;
803 }
804 
805 
806 /**
807   Reads the current value of Extra Segment Register (ES).
808 
809   Reads and returns the current value of ES. This function is only available on
810   IA-32 and X64.
811 
812   @return The current value of ES.
813 
814 **/
815 UINT16
816 EFIAPI
817 AsmReadEs (
818   VOID
819   )
820 {
821   UINT16  Data;
822 
823   __asm__ __volatile__ (
824     "mov  %%es, %0"
825     :"=a" (Data)
826     );
827 
828   return Data;
829 }
830 
831 
832 /**
833   Reads the current value of FS Data Segment Register (FS).
834 
835   Reads and returns the current value of FS. This function is only available on
836   IA-32 and X64.
837 
838   @return The current value of FS.
839 
840 **/
841 UINT16
842 EFIAPI
843 AsmReadFs (
844   VOID
845   )
846 {
847   UINT16  Data;
848 
849   __asm__ __volatile__ (
850     "mov  %%fs, %0"
851     :"=a" (Data)
852     );
853 
854   return Data;
855 }
856 
857 
858 /**
859   Reads the current value of GS Data Segment Register (GS).
860 
861   Reads and returns the current value of GS. This function is only available on
862   IA-32 and X64.
863 
864   @return The current value of GS.
865 
866 **/
867 UINT16
868 EFIAPI
869 AsmReadGs (
870   VOID
871   )
872 {
873   UINT16  Data;
874 
875   __asm__ __volatile__ (
876     "mov  %%gs, %0"
877     :"=a" (Data)
878     );
879 
880   return Data;
881 }
882 
883 
884 /**
885   Reads the current value of Stack Segment Register (SS).
886 
887   Reads and returns the current value of SS. This function is only available on
888   IA-32 and X64.
889 
890   @return The current value of SS.
891 
892 **/
893 UINT16
894 EFIAPI
895 AsmReadSs (
896   VOID
897   )
898 {
899   UINT16  Data;
900 
901   __asm__ __volatile__ (
902     "mov  %%ds, %0"
903     :"=a" (Data)
904     );
905 
906   return Data;
907 }
908 
909 
910 /**
911   Reads the current value of Task Register (TR).
912 
913   Reads and returns the current value of TR. This function is only available on
914   IA-32 and X64.
915 
916   @return The current value of TR.
917 
918 **/
919 UINT16
920 EFIAPI
921 AsmReadTr (
922   VOID
923   )
924 {
925   UINT16  Data;
926 
927   __asm__ __volatile__ (
928     "str  %0"
929     : "=r" (Data)
930     );
931 
932   return Data;
933 }
934 
935 
936 /**
937   Reads the current Global Descriptor Table Register(GDTR) descriptor.
938 
939   Reads and returns the current GDTR descriptor and returns it in Gdtr. This
940   function is only available on IA-32 and X64.
941 
942   @param  Gdtr  The pointer to a GDTR descriptor.
943 
944 **/
945 VOID
946 EFIAPI
947 InternalX86ReadGdtr (
948   OUT     IA32_DESCRIPTOR           *Gdtr
949   )
950 {
951   __asm__ __volatile__ (
952     "sgdt %0"
953     : "=m" (*Gdtr)
954     );
955 }
956 
957 
958 /**
959   Writes the current Global Descriptor Table Register (GDTR) descriptor.
960 
961   Writes and the current GDTR descriptor specified by Gdtr. This function is
962   only available on IA-32 and X64.
963 
964   @param  Gdtr  The pointer to a GDTR descriptor.
965 
966 **/
967 VOID
968 EFIAPI
969 InternalX86WriteGdtr (
970   IN      CONST IA32_DESCRIPTOR     *Gdtr
971   )
972 {
973   __asm__ __volatile__ (
974     "lgdt %0"
975     :
976     : "m" (*Gdtr)
977     );
978 
979 }
980 
981 
982 /**
983   Reads the current Interrupt Descriptor Table Register(GDTR) descriptor.
984 
985   Reads and returns the current IDTR descriptor and returns it in Idtr. This
986   function is only available on IA-32 and X64.
987 
988   @param  Idtr  The pointer to a IDTR descriptor.
989 
990 **/
991 VOID
992 EFIAPI
993 InternalX86ReadIdtr (
994   OUT     IA32_DESCRIPTOR           *Idtr
995   )
996 {
997   __asm__ __volatile__ (
998     "sidt  %0"
999     : "=m" (*Idtr)
1000     );
1001 }
1002 
1003 
1004 /**
1005   Writes the current Interrupt Descriptor Table Register(GDTR) descriptor.
1006 
1007   Writes the current IDTR descriptor and returns it in Idtr. This function is
1008   only available on IA-32 and X64.
1009 
1010   @param  Idtr  The pointer to a IDTR descriptor.
1011 
1012 **/
1013 VOID
1014 EFIAPI
1015 InternalX86WriteIdtr (
1016   IN      CONST IA32_DESCRIPTOR     *Idtr
1017   )
1018 {
1019   __asm__ __volatile__ (
1020     "lidt %0"
1021     :
1022     : "m" (*Idtr)
1023     );
1024 }
1025 
1026 
1027 /**
1028   Reads the current Local Descriptor Table Register(LDTR) selector.
1029 
1030   Reads and returns the current 16-bit LDTR descriptor value. This function is
1031   only available on IA-32 and X64.
1032 
1033   @return The current selector of LDT.
1034 
1035 **/
1036 UINT16
1037 EFIAPI
1038 AsmReadLdtr (
1039   VOID
1040   )
1041 {
1042   UINT16  Data;
1043 
1044   __asm__ __volatile__ (
1045     "sldt  %0"
1046     : "=g" (Data)   // %0
1047     );
1048 
1049   return Data;
1050 }
1051 
1052 
1053 /**
1054   Writes the current Local Descriptor Table Register (GDTR) selector.
1055 
1056   Writes and the current LDTR descriptor specified by Ldtr. This function is
1057   only available on IA-32 and X64.
1058 
1059   @param  Ldtr  16-bit LDTR selector value.
1060 
1061 **/
1062 VOID
1063 EFIAPI
1064 AsmWriteLdtr (
1065   IN      UINT16                    Ldtr
1066   )
1067 {
1068   __asm__ __volatile__ (
1069     "lldtw  %0"
1070     :
1071     : "g" (Ldtr)   // %0
1072     );
1073 }
1074 
1075 /**
1076   Reads the current value of a Performance Counter (PMC).
1077 
1078   Reads and returns the current value of performance counter specified by
1079   Index. This function is only available on IA-32 and X64.
1080 
1081   @param  Index The 32-bit Performance Counter index to read.
1082 
1083   @return The value of the PMC specified by Index.
1084 
1085 **/
1086 UINT64
1087 EFIAPI
1088 AsmReadPmc (
1089   IN      UINT32                    Index
1090   )
1091 {
1092   UINT32  LowData;
1093   UINT32  HiData;
1094 
1095   __asm__ __volatile__ (
1096     "rdpmc"
1097     : "=a" (LowData),
1098       "=d" (HiData)
1099     : "c"  (Index)
1100     );
1101 
1102   return (((UINT64)HiData) << 32) | LowData;
1103 }
1104 
1105 /**
1106   Sets up a monitor buffer that is used by AsmMwait().
1107 
1108   Executes a MONITOR instruction with the register state specified by Eax, Ecx
1109   and Edx. Returns Eax. This function is only available on IA-32 and X64.
1110 
1111   @param  Eax The value to load into EAX or RAX before executing the MONITOR
1112               instruction.
1113   @param  Ecx The value to load into ECX or RCX before executing the MONITOR
1114               instruction.
1115   @param  Edx The value to load into EDX or RDX before executing the MONITOR
1116               instruction.
1117 
1118   @return Eax
1119 
1120 **/
1121 UINTN
1122 EFIAPI
1123 AsmMonitor (
1124   IN      UINTN                     Eax,
1125   IN      UINTN                     Ecx,
1126   IN      UINTN                     Edx
1127   )
1128 {
1129   __asm__ __volatile__ (
1130     "monitor"
1131     :
1132     : "a" (Eax),
1133       "c" (Ecx),
1134       "d" (Edx)
1135     );
1136 
1137   return Eax;
1138 }
1139 
1140 /**
1141   Executes an MWAIT instruction.
1142 
1143   Executes an MWAIT instruction with the register state specified by Eax and
1144   Ecx. Returns Eax. This function is only available on IA-32 and X64.
1145 
1146   @param  Eax The value to load into EAX or RAX before executing the MONITOR
1147               instruction.
1148   @param  Ecx The value to load into ECX or RCX before executing the MONITOR
1149               instruction.
1150 
1151   @return Eax
1152 
1153 **/
1154 UINTN
1155 EFIAPI
1156 AsmMwait (
1157   IN      UINTN                     Eax,
1158   IN      UINTN                     Ecx
1159   )
1160 {
1161   __asm__ __volatile__ (
1162     "mwait"
1163     :
1164     : "a"  (Eax),
1165       "c"  (Ecx)
1166     );
1167 
1168   return Eax;
1169 }
1170 
1171 /**
1172   Executes a WBINVD instruction.
1173 
1174   Executes a WBINVD instruction. This function is only available on IA-32 and
1175   X64.
1176 
1177 **/
1178 VOID
1179 EFIAPI
1180 AsmWbinvd (
1181   VOID
1182   )
1183 {
1184   __asm__ __volatile__ ("wbinvd":::"memory");
1185 }
1186 
1187 /**
1188   Executes a INVD instruction.
1189 
1190   Executes a INVD instruction. This function is only available on IA-32 and
1191   X64.
1192 
1193 **/
1194 VOID
1195 EFIAPI
1196 AsmInvd (
1197   VOID
1198   )
1199 {
1200   __asm__ __volatile__ ("invd":::"memory");
1201 
1202 }
1203 
1204 
1205 /**
1206   Flushes a cache line from all the instruction and data caches within the
1207   coherency domain of the CPU.
1208 
1209   Flushed the cache line specified by LinearAddress, and returns LinearAddress.
1210   This function is only available on IA-32 and X64.
1211 
1212   @param  LinearAddress The address of the cache line to flush. If the CPU is
1213                         in a physical addressing mode, then LinearAddress is a
1214                         physical address. If the CPU is in a virtual
1215                         addressing mode, then LinearAddress is a virtual
1216                         address.
1217 
1218   @return LinearAddress
1219 **/
1220 VOID *
1221 EFIAPI
1222 AsmFlushCacheLine (
1223   IN      VOID                      *LinearAddress
1224   )
1225 {
1226   __asm__ __volatile__ (
1227     "clflush (%0)"
1228     :
1229     : "r" (LinearAddress)
1230     : "memory"
1231     );
1232 
1233     return LinearAddress;
1234 }
1235