1 /** @file
2   GCC inline implementation of BaseLib processor specific functions.
3 
4   Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5   Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
6   SPDX-License-Identifier: BSD-2-Clause-Patent
7 
8 **/
9 
10 
11 #include "BaseLibInternals.h"
12 
13 
14 
15 
16 /**
17   Used to serialize load and store operations.
18 
19   All loads and stores that proceed calls to this function are guaranteed to be
20   globally visible when this function returns.
21 
22 **/
23 VOID
24 EFIAPI
MemoryFence(VOID)25 MemoryFence (
26   VOID
27   )
28 {
29   // This is a little bit of overkill and it is more about the compiler that it is
30   // actually processor synchronization. This is like the _ReadWriteBarrier
31   // Microsoft specific intrinsic
32   __asm__ __volatile__ ("":::"memory");
33 }
34 
35 
36 /**
37   Enables CPU interrupts.
38 
39   Enables CPU interrupts.
40 
41 **/
42 VOID
43 EFIAPI
EnableInterrupts(VOID)44 EnableInterrupts (
45   VOID
46   )
47 {
48   __asm__ __volatile__ ("sti"::: "memory");
49 }
50 
51 
52 /**
53   Disables CPU interrupts.
54 
55   Disables CPU interrupts.
56 
57 **/
58 VOID
59 EFIAPI
DisableInterrupts(VOID)60 DisableInterrupts (
61   VOID
62   )
63 {
64   __asm__ __volatile__ ("cli"::: "memory");
65 }
66 
67 
68 
69 
70 /**
71   Requests CPU to pause for a short period of time.
72 
73   Requests CPU to pause for a short period of time. Typically used in MP
74   systems to prevent memory starvation while waiting for a spin lock.
75 
76 **/
77 VOID
78 EFIAPI
CpuPause(VOID)79 CpuPause (
80   VOID
81   )
82 {
83   __asm__ __volatile__ ("pause");
84 }
85 
86 
87 /**
88   Generates a breakpoint on the CPU.
89 
90   Generates a breakpoint on the CPU. The breakpoint must be implemented such
91   that code can resume normal execution after the breakpoint.
92 
93 **/
94 VOID
95 EFIAPI
CpuBreakpoint(VOID)96 CpuBreakpoint (
97   VOID
98   )
99 {
100   __asm__ __volatile__ ("int $3");
101 }
102 
103 
104 
105 /**
106   Returns a 64-bit Machine Specific Register(MSR).
107 
108   Reads and returns the 64-bit MSR specified by Index. No parameter checking is
109   performed on Index, and some Index values may cause CPU exceptions. The
110   caller must either guarantee that Index is valid, or the caller must set up
111   exception handlers to catch the exceptions. This function is only available
112   on IA-32 and X64.
113 
114   @param  Index The 32-bit MSR index to read.
115 
116   @return The value of the MSR identified by Index.
117 
118 **/
119 UINT64
120 EFIAPI
AsmReadMsr64(IN UINT32 Index)121 AsmReadMsr64 (
122   IN      UINT32                    Index
123   )
124 {
125   UINT32 LowData;
126   UINT32 HighData;
127 
128   __asm__ __volatile__ (
129     "rdmsr"
130     : "=a" (LowData),   // %0
131       "=d" (HighData)   // %1
132     : "c"  (Index)      // %2
133     );
134 
135   return (((UINT64)HighData) << 32) | LowData;
136 }
137 
138 /**
139   Writes a 64-bit value to a Machine Specific Register(MSR), and returns the
140   value.
141 
142   Writes the 64-bit value specified by Value to the MSR specified by Index. The
143   64-bit value written to the MSR is returned. No parameter checking is
144   performed on Index or Value, and some of these may cause CPU exceptions. The
145   caller must either guarantee that Index and Value are valid, or the caller
146   must establish proper exception handlers. This function is only available on
147   IA-32 and X64.
148 
149   @param  Index The 32-bit MSR index to write.
150   @param  Value The 64-bit value to write to the MSR.
151 
152   @return Value
153 
154 **/
155 UINT64
156 EFIAPI
AsmWriteMsr64(IN UINT32 Index,IN UINT64 Value)157 AsmWriteMsr64 (
158   IN      UINT32                    Index,
159   IN      UINT64                    Value
160   )
161 {
162   UINT32 LowData;
163   UINT32 HighData;
164 
165   LowData  = (UINT32)(Value);
166   HighData = (UINT32)(Value >> 32);
167 
168   __asm__ __volatile__ (
169     "wrmsr"
170     :
171     : "c" (Index),
172       "a" (LowData),
173       "d" (HighData)
174     );
175 
176   return Value;
177 }
178 
179 
180 
181 /**
182   Reads the current value of the EFLAGS register.
183 
184   Reads and returns the current value of the EFLAGS register. This function is
185   only available on IA-32 and X64. This returns a 32-bit value on IA-32 and a
186   64-bit value on X64.
187 
188   @return EFLAGS on IA-32 or RFLAGS on X64.
189 
190 **/
191 UINTN
192 EFIAPI
AsmReadEflags(VOID)193 AsmReadEflags (
194   VOID
195   )
196 {
197   UINTN Eflags;
198 
199   __asm__ __volatile__ (
200     "pushfq         \n\t"
201     "pop     %0         "
202     : "=r" (Eflags)       // %0
203     );
204 
205   return Eflags;
206 }
207 
208 
209 
210 /**
211   Reads the current value of the Control Register 0 (CR0).
212 
213   Reads and returns the current value of CR0. This function is only available
214   on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
215   X64.
216 
217   @return The value of the Control Register 0 (CR0).
218 
219 **/
220 UINTN
221 EFIAPI
AsmReadCr0(VOID)222 AsmReadCr0 (
223   VOID
224   )
225 {
226   UINTN   Data;
227 
228   __asm__ __volatile__ (
229     "mov  %%cr0,%0"
230     : "=r" (Data)           // %0
231     );
232 
233   return Data;
234 }
235 
236 
237 /**
238   Reads the current value of the Control Register 2 (CR2).
239 
240   Reads and returns the current value of CR2. This function is only available
241   on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
242   X64.
243 
244   @return The value of the Control Register 2 (CR2).
245 
246 **/
247 UINTN
248 EFIAPI
AsmReadCr2(VOID)249 AsmReadCr2 (
250   VOID
251   )
252 {
253   UINTN Data;
254 
255   __asm__ __volatile__ (
256     "mov  %%cr2,  %0"
257     : "=r" (Data)           // %0
258     );
259 
260   return Data;
261 }
262 
263 /**
264   Reads the current value of the Control Register 3 (CR3).
265 
266   Reads and returns the current value of CR3. This function is only available
267   on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
268   X64.
269 
270   @return The value of the Control Register 3 (CR3).
271 
272 **/
273 UINTN
274 EFIAPI
AsmReadCr3(VOID)275 AsmReadCr3 (
276   VOID
277   )
278 {
279   UINTN Data;
280 
281   __asm__ __volatile__ (
282     "mov  %%cr3,  %0"
283     : "=r" (Data)           // %0
284     );
285 
286   return Data;
287 }
288 
289 
290 /**
291   Reads the current value of the Control Register 4 (CR4).
292 
293   Reads and returns the current value of CR4. This function is only available
294   on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
295   X64.
296 
297   @return The value of the Control Register 4 (CR4).
298 
299 **/
300 UINTN
301 EFIAPI
AsmReadCr4(VOID)302 AsmReadCr4 (
303   VOID
304   )
305 {
306   UINTN Data;
307 
308   __asm__ __volatile__ (
309     "mov  %%cr4,  %0"
310     : "=r" (Data)           // %0
311     );
312 
313   return Data;
314 }
315 
316 
317 /**
318   Writes a value to Control Register 0 (CR0).
319 
320   Writes and returns a new value to CR0. This function is only available on
321   IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
322 
323   @param  Cr0 The value to write to CR0.
324 
325   @return The value written to CR0.
326 
327 **/
328 UINTN
329 EFIAPI
AsmWriteCr0(UINTN Cr0)330 AsmWriteCr0 (
331   UINTN  Cr0
332   )
333 {
334   __asm__ __volatile__ (
335     "mov  %0, %%cr0"
336     :
337     : "r" (Cr0)
338     );
339   return Cr0;
340 }
341 
342 
343 /**
344   Writes a value to Control Register 2 (CR2).
345 
346   Writes and returns a new value to CR2. This function is only available on
347   IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
348 
349   @param  Cr2 The value to write to CR2.
350 
351   @return The value written to CR2.
352 
353 **/
354 UINTN
355 EFIAPI
AsmWriteCr2(UINTN Cr2)356 AsmWriteCr2 (
357   UINTN  Cr2
358   )
359 {
360   __asm__ __volatile__ (
361     "mov  %0, %%cr2"
362     :
363     : "r" (Cr2)
364     );
365   return Cr2;
366 }
367 
368 
369 /**
370   Writes a value to Control Register 3 (CR3).
371 
372   Writes and returns a new value to CR3. This function is only available on
373   IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
374 
375   @param  Cr3 The value to write to CR3.
376 
377   @return The value written to CR3.
378 
379 **/
380 UINTN
381 EFIAPI
AsmWriteCr3(UINTN Cr3)382 AsmWriteCr3 (
383   UINTN  Cr3
384   )
385 {
386   __asm__ __volatile__ (
387     "mov  %0, %%cr3"
388     :
389     : "r" (Cr3)
390     );
391   return Cr3;
392 }
393 
394 
395 /**
396   Writes a value to Control Register 4 (CR4).
397 
398   Writes and returns a new value to CR4. This function is only available on
399   IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
400 
401   @param  Cr4 The value to write to CR4.
402 
403   @return The value written to CR4.
404 
405 **/
406 UINTN
407 EFIAPI
AsmWriteCr4(UINTN Cr4)408 AsmWriteCr4 (
409   UINTN  Cr4
410   )
411 {
412   __asm__ __volatile__ (
413     "mov  %0, %%cr4"
414     :
415     : "r" (Cr4)
416     );
417   return Cr4;
418 }
419 
420 
421 /**
422   Reads the current value of Debug Register 0 (DR0).
423 
424   Reads and returns the current value of DR0. This function is only available
425   on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
426   X64.
427 
428   @return The value of Debug Register 0 (DR0).
429 
430 **/
431 UINTN
432 EFIAPI
AsmReadDr0(VOID)433 AsmReadDr0 (
434   VOID
435   )
436 {
437   UINTN Data;
438 
439   __asm__ __volatile__ (
440     "mov  %%dr0, %0"
441     : "=r" (Data)
442     );
443 
444   return Data;
445 }
446 
447 
448 /**
449   Reads the current value of Debug Register 1 (DR1).
450 
451   Reads and returns the current value of DR1. This function is only available
452   on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
453   X64.
454 
455   @return The value of Debug Register 1 (DR1).
456 
457 **/
458 UINTN
459 EFIAPI
AsmReadDr1(VOID)460 AsmReadDr1 (
461   VOID
462   )
463 {
464   UINTN Data;
465 
466   __asm__ __volatile__ (
467     "mov  %%dr1, %0"
468     : "=r" (Data)
469     );
470 
471   return Data;
472 }
473 
474 
475 /**
476   Reads the current value of Debug Register 2 (DR2).
477 
478   Reads and returns the current value of DR2. This function is only available
479   on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
480   X64.
481 
482   @return The value of Debug Register 2 (DR2).
483 
484 **/
485 UINTN
486 EFIAPI
AsmReadDr2(VOID)487 AsmReadDr2 (
488   VOID
489   )
490 {
491   UINTN Data;
492 
493   __asm__ __volatile__ (
494     "mov  %%dr2, %0"
495     : "=r" (Data)
496     );
497 
498   return Data;
499 }
500 
501 
502 /**
503   Reads the current value of Debug Register 3 (DR3).
504 
505   Reads and returns the current value of DR3. This function is only available
506   on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
507   X64.
508 
509   @return The value of Debug Register 3 (DR3).
510 
511 **/
512 UINTN
513 EFIAPI
AsmReadDr3(VOID)514 AsmReadDr3 (
515   VOID
516   )
517 {
518   UINTN Data;
519 
520   __asm__ __volatile__ (
521     "mov  %%dr3, %0"
522     : "=r" (Data)
523     );
524 
525   return Data;
526 }
527 
528 
529 /**
530   Reads the current value of Debug Register 4 (DR4).
531 
532   Reads and returns the current value of DR4. This function is only available
533   on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
534   X64.
535 
536   @return The value of Debug Register 4 (DR4).
537 
538 **/
539 UINTN
540 EFIAPI
AsmReadDr4(VOID)541 AsmReadDr4 (
542   VOID
543   )
544 {
545   UINTN Data;
546 
547   __asm__ __volatile__ (
548     "mov  %%dr4, %0"
549     : "=r" (Data)
550     );
551 
552   return Data;
553 }
554 
555 
556 /**
557   Reads the current value of Debug Register 5 (DR5).
558 
559   Reads and returns the current value of DR5. This function is only available
560   on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
561   X64.
562 
563   @return The value of Debug Register 5 (DR5).
564 
565 **/
566 UINTN
567 EFIAPI
AsmReadDr5(VOID)568 AsmReadDr5 (
569   VOID
570   )
571 {
572   UINTN Data;
573 
574   __asm__ __volatile__ (
575     "mov  %%dr5, %0"
576     : "=r" (Data)
577     );
578 
579   return Data;
580 }
581 
582 
583 /**
584   Reads the current value of Debug Register 6 (DR6).
585 
586   Reads and returns the current value of DR6. This function is only available
587   on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
588   X64.
589 
590   @return The value of Debug Register 6 (DR6).
591 
592 **/
593 UINTN
594 EFIAPI
AsmReadDr6(VOID)595 AsmReadDr6 (
596   VOID
597   )
598 {
599   UINTN Data;
600 
601   __asm__ __volatile__ (
602     "mov  %%dr6, %0"
603     : "=r" (Data)
604     );
605 
606   return Data;
607 }
608 
609 
610 /**
611   Reads the current value of Debug Register 7 (DR7).
612 
613   Reads and returns the current value of DR7. This function is only available
614   on IA-32 and X64. This returns a 32-bit value on IA-32 and a 64-bit value on
615   X64.
616 
617   @return The value of Debug Register 7 (DR7).
618 
619 **/
620 UINTN
621 EFIAPI
AsmReadDr7(VOID)622 AsmReadDr7 (
623   VOID
624   )
625 {
626   UINTN Data;
627 
628   __asm__ __volatile__ (
629     "mov  %%dr7, %0"
630     : "=r" (Data)
631     );
632 
633   return Data;
634 }
635 
636 
637 /**
638   Writes a value to Debug Register 0 (DR0).
639 
640   Writes and returns a new value to DR0. This function is only available on
641   IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
642 
643   @param  Dr0 The value to write to Dr0.
644 
645   @return The value written to Debug Register 0 (DR0).
646 
647 **/
648 UINTN
649 EFIAPI
AsmWriteDr0(UINTN Dr0)650 AsmWriteDr0 (
651   UINTN  Dr0
652   )
653 {
654   __asm__ __volatile__ (
655     "mov  %0, %%dr0"
656     :
657     : "r" (Dr0)
658     );
659   return Dr0;
660 }
661 
662 
663 /**
664   Writes a value to Debug Register 1 (DR1).
665 
666   Writes and returns a new value to DR1. This function is only available on
667   IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
668 
669   @param  Dr1 The value to write to Dr1.
670 
671   @return The value written to Debug Register 1 (DR1).
672 
673 **/
674 UINTN
675 EFIAPI
AsmWriteDr1(UINTN Dr1)676 AsmWriteDr1 (
677   UINTN  Dr1
678   )
679 {
680   __asm__ __volatile__ (
681     "mov  %0, %%dr1"
682     :
683     : "r" (Dr1)
684     );
685   return Dr1;
686 }
687 
688 
689 /**
690   Writes a value to Debug Register 2 (DR2).
691 
692   Writes and returns a new value to DR2. This function is only available on
693   IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
694 
695   @param  Dr2 The value to write to Dr2.
696 
697   @return The value written to Debug Register 2 (DR2).
698 
699 **/
700 UINTN
701 EFIAPI
AsmWriteDr2(UINTN Dr2)702 AsmWriteDr2 (
703   UINTN  Dr2
704   )
705 {
706   __asm__ __volatile__ (
707     "mov  %0, %%dr2"
708     :
709     : "r" (Dr2)
710     );
711   return Dr2;
712 }
713 
714 
715 /**
716   Writes a value to Debug Register 3 (DR3).
717 
718   Writes and returns a new value to DR3. This function is only available on
719   IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
720 
721   @param  Dr3 The value to write to Dr3.
722 
723   @return The value written to Debug Register 3 (DR3).
724 
725 **/
726 UINTN
727 EFIAPI
AsmWriteDr3(UINTN Dr3)728 AsmWriteDr3 (
729   UINTN  Dr3
730   )
731 {
732   __asm__ __volatile__ (
733     "mov  %0, %%dr3"
734     :
735     : "r" (Dr3)
736     );
737   return Dr3;
738 }
739 
740 
741 /**
742   Writes a value to Debug Register 4 (DR4).
743 
744   Writes and returns a new value to DR4. This function is only available on
745   IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
746 
747   @param  Dr4 The value to write to Dr4.
748 
749   @return The value written to Debug Register 4 (DR4).
750 
751 **/
752 UINTN
753 EFIAPI
AsmWriteDr4(UINTN Dr4)754 AsmWriteDr4 (
755   UINTN  Dr4
756   )
757 {
758   __asm__ __volatile__ (
759     "mov  %0, %%dr4"
760     :
761     : "r" (Dr4)
762     );
763   return Dr4;
764 }
765 
766 
767 /**
768   Writes a value to Debug Register 5 (DR5).
769 
770   Writes and returns a new value to DR5. This function is only available on
771   IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
772 
773   @param  Dr5 The value to write to Dr5.
774 
775   @return The value written to Debug Register 5 (DR5).
776 
777 **/
778 UINTN
779 EFIAPI
AsmWriteDr5(UINTN Dr5)780 AsmWriteDr5 (
781   UINTN  Dr5
782   )
783 {
784   __asm__ __volatile__ (
785     "mov  %0, %%dr5"
786     :
787     : "r" (Dr5)
788     );
789   return Dr5;
790 }
791 
792 
793 /**
794   Writes a value to Debug Register 6 (DR6).
795 
796   Writes and returns a new value to DR6. This function is only available on
797   IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
798 
799   @param  Dr6 The value to write to Dr6.
800 
801   @return The value written to Debug Register 6 (DR6).
802 
803 **/
804 UINTN
805 EFIAPI
AsmWriteDr6(UINTN Dr6)806 AsmWriteDr6 (
807   UINTN  Dr6
808   )
809 {
810   __asm__ __volatile__ (
811     "mov  %0, %%dr6"
812     :
813     : "r" (Dr6)
814     );
815   return Dr6;
816 }
817 
818 
819 /**
820   Writes a value to Debug Register 7 (DR7).
821 
822   Writes and returns a new value to DR7. This function is only available on
823   IA-32 and X64. This writes a 32-bit value on IA-32 and a 64-bit value on X64.
824 
825   @param  Dr7 The value to write to Dr7.
826 
827   @return The value written to Debug Register 7 (DR7).
828 
829 **/
830 UINTN
831 EFIAPI
AsmWriteDr7(UINTN Dr7)832 AsmWriteDr7 (
833   UINTN  Dr7
834   )
835 {
836   __asm__ __volatile__ (
837     "mov  %0, %%dr7"
838     :
839     : "r" (Dr7)
840     );
841   return Dr7;
842 }
843 
844 
845 /**
846   Reads the current value of Code Segment Register (CS).
847 
848   Reads and returns the current value of CS. This function is only available on
849   IA-32 and X64.
850 
851   @return The current value of CS.
852 
853 **/
854 UINT16
855 EFIAPI
AsmReadCs(VOID)856 AsmReadCs (
857   VOID
858   )
859 {
860   UINT16  Data;
861 
862   __asm__ __volatile__ (
863     "mov   %%cs, %0"
864     :"=a" (Data)
865     );
866 
867   return Data;
868 }
869 
870 
871 /**
872   Reads the current value of Data Segment Register (DS).
873 
874   Reads and returns the current value of DS. This function is only available on
875   IA-32 and X64.
876 
877   @return The current value of DS.
878 
879 **/
880 UINT16
881 EFIAPI
AsmReadDs(VOID)882 AsmReadDs (
883   VOID
884   )
885 {
886   UINT16  Data;
887 
888   __asm__ __volatile__ (
889     "mov  %%ds, %0"
890     :"=a" (Data)
891     );
892 
893   return Data;
894 }
895 
896 
897 /**
898   Reads the current value of Extra Segment Register (ES).
899 
900   Reads and returns the current value of ES. This function is only available on
901   IA-32 and X64.
902 
903   @return The current value of ES.
904 
905 **/
906 UINT16
907 EFIAPI
AsmReadEs(VOID)908 AsmReadEs (
909   VOID
910   )
911 {
912   UINT16  Data;
913 
914   __asm__ __volatile__ (
915     "mov  %%es, %0"
916     :"=a" (Data)
917     );
918 
919   return Data;
920 }
921 
922 
923 /**
924   Reads the current value of FS Data Segment Register (FS).
925 
926   Reads and returns the current value of FS. This function is only available on
927   IA-32 and X64.
928 
929   @return The current value of FS.
930 
931 **/
932 UINT16
933 EFIAPI
AsmReadFs(VOID)934 AsmReadFs (
935   VOID
936   )
937 {
938   UINT16  Data;
939 
940   __asm__ __volatile__ (
941     "mov  %%fs, %0"
942     :"=a" (Data)
943     );
944 
945   return Data;
946 }
947 
948 
949 /**
950   Reads the current value of GS Data Segment Register (GS).
951 
952   Reads and returns the current value of GS. This function is only available on
953   IA-32 and X64.
954 
955   @return The current value of GS.
956 
957 **/
958 UINT16
959 EFIAPI
AsmReadGs(VOID)960 AsmReadGs (
961   VOID
962   )
963 {
964   UINT16  Data;
965 
966   __asm__ __volatile__ (
967     "mov  %%gs, %0"
968     :"=a" (Data)
969     );
970 
971   return Data;
972 }
973 
974 
975 /**
976   Reads the current value of Stack Segment Register (SS).
977 
978   Reads and returns the current value of SS. This function is only available on
979   IA-32 and X64.
980 
981   @return The current value of SS.
982 
983 **/
984 UINT16
985 EFIAPI
AsmReadSs(VOID)986 AsmReadSs (
987   VOID
988   )
989 {
990   UINT16  Data;
991 
992   __asm__ __volatile__ (
993     "mov  %%ds, %0"
994     :"=a" (Data)
995     );
996 
997   return Data;
998 }
999 
1000 
1001 /**
1002   Reads the current value of Task Register (TR).
1003 
1004   Reads and returns the current value of TR. This function is only available on
1005   IA-32 and X64.
1006 
1007   @return The current value of TR.
1008 
1009 **/
1010 UINT16
1011 EFIAPI
AsmReadTr(VOID)1012 AsmReadTr (
1013   VOID
1014   )
1015 {
1016   UINT16  Data;
1017 
1018   __asm__ __volatile__ (
1019     "str  %0"
1020     : "=r" (Data)
1021     );
1022 
1023   return Data;
1024 }
1025 
1026 
1027 /**
1028   Reads the current Global Descriptor Table Register(GDTR) descriptor.
1029 
1030   Reads and returns the current GDTR descriptor and returns it in Gdtr. This
1031   function is only available on IA-32 and X64.
1032 
1033   @param  Gdtr  The pointer to a GDTR descriptor.
1034 
1035 **/
1036 VOID
1037 EFIAPI
InternalX86ReadGdtr(OUT IA32_DESCRIPTOR * Gdtr)1038 InternalX86ReadGdtr (
1039   OUT     IA32_DESCRIPTOR           *Gdtr
1040   )
1041 {
1042   __asm__ __volatile__ (
1043     "sgdt %0"
1044     : "=m" (*Gdtr)
1045     );
1046 }
1047 
1048 
1049 /**
1050   Writes the current Global Descriptor Table Register (GDTR) descriptor.
1051 
1052   Writes and the current GDTR descriptor specified by Gdtr. This function is
1053   only available on IA-32 and X64.
1054 
1055   @param  Gdtr  The pointer to a GDTR descriptor.
1056 
1057 **/
1058 VOID
1059 EFIAPI
InternalX86WriteGdtr(IN CONST IA32_DESCRIPTOR * Gdtr)1060 InternalX86WriteGdtr (
1061   IN      CONST IA32_DESCRIPTOR     *Gdtr
1062   )
1063 {
1064   __asm__ __volatile__ (
1065     "lgdt %0"
1066     :
1067     : "m" (*Gdtr)
1068     );
1069 
1070 }
1071 
1072 
1073 /**
1074   Reads the current Interrupt Descriptor Table Register(GDTR) descriptor.
1075 
1076   Reads and returns the current IDTR descriptor and returns it in Idtr. This
1077   function is only available on IA-32 and X64.
1078 
1079   @param  Idtr  The pointer to a IDTR descriptor.
1080 
1081 **/
1082 VOID
1083 EFIAPI
InternalX86ReadIdtr(OUT IA32_DESCRIPTOR * Idtr)1084 InternalX86ReadIdtr (
1085   OUT     IA32_DESCRIPTOR           *Idtr
1086   )
1087 {
1088   __asm__ __volatile__ (
1089     "sidt  %0"
1090     : "=m" (*Idtr)
1091     );
1092 }
1093 
1094 
1095 /**
1096   Writes the current Interrupt Descriptor Table Register(GDTR) descriptor.
1097 
1098   Writes the current IDTR descriptor and returns it in Idtr. This function is
1099   only available on IA-32 and X64.
1100 
1101   @param  Idtr  The pointer to a IDTR descriptor.
1102 
1103 **/
1104 VOID
1105 EFIAPI
InternalX86WriteIdtr(IN CONST IA32_DESCRIPTOR * Idtr)1106 InternalX86WriteIdtr (
1107   IN      CONST IA32_DESCRIPTOR     *Idtr
1108   )
1109 {
1110   __asm__ __volatile__ (
1111     "lidt %0"
1112     :
1113     : "m" (*Idtr)
1114     );
1115 }
1116 
1117 
1118 /**
1119   Reads the current Local Descriptor Table Register(LDTR) selector.
1120 
1121   Reads and returns the current 16-bit LDTR descriptor value. This function is
1122   only available on IA-32 and X64.
1123 
1124   @return The current selector of LDT.
1125 
1126 **/
1127 UINT16
1128 EFIAPI
AsmReadLdtr(VOID)1129 AsmReadLdtr (
1130   VOID
1131   )
1132 {
1133   UINT16  Data;
1134 
1135   __asm__ __volatile__ (
1136     "sldt  %0"
1137     : "=g" (Data)   // %0
1138     );
1139 
1140   return Data;
1141 }
1142 
1143 
1144 /**
1145   Writes the current Local Descriptor Table Register (GDTR) selector.
1146 
1147   Writes and the current LDTR descriptor specified by Ldtr. This function is
1148   only available on IA-32 and X64.
1149 
1150   @param  Ldtr  16-bit LDTR selector value.
1151 
1152 **/
1153 VOID
1154 EFIAPI
AsmWriteLdtr(IN UINT16 Ldtr)1155 AsmWriteLdtr (
1156   IN      UINT16                    Ldtr
1157   )
1158 {
1159   __asm__ __volatile__ (
1160     "lldtw  %0"
1161     :
1162     : "g" (Ldtr)   // %0
1163     );
1164 }
1165 
1166 
1167 /**
1168   Save the current floating point/SSE/SSE2 context to a buffer.
1169 
1170   Saves the current floating point/SSE/SSE2 state to the buffer specified by
1171   Buffer. Buffer must be aligned on a 16-byte boundary. This function is only
1172   available on IA-32 and X64.
1173 
1174   @param  Buffer  The pointer to a buffer to save the floating point/SSE/SSE2 context.
1175 
1176 **/
1177 VOID
1178 EFIAPI
InternalX86FxSave(OUT IA32_FX_BUFFER * Buffer)1179 InternalX86FxSave (
1180   OUT     IA32_FX_BUFFER            *Buffer
1181   )
1182 {
1183   __asm__ __volatile__ (
1184     "fxsave %0"
1185     :
1186     : "m" (*Buffer)  // %0
1187     );
1188 }
1189 
1190 
1191 /**
1192   Restores the current floating point/SSE/SSE2 context from a buffer.
1193 
1194   Restores the current floating point/SSE/SSE2 state from the buffer specified
1195   by Buffer. Buffer must be aligned on a 16-byte boundary. This function is
1196   only available on IA-32 and X64.
1197 
1198   @param  Buffer  The pointer to a buffer to save the floating point/SSE/SSE2 context.
1199 
1200 **/
1201 VOID
1202 EFIAPI
InternalX86FxRestore(IN CONST IA32_FX_BUFFER * Buffer)1203 InternalX86FxRestore (
1204   IN      CONST IA32_FX_BUFFER      *Buffer
1205   )
1206 {
1207   __asm__ __volatile__ (
1208     "fxrstor %0"
1209     :
1210     : "m" (*Buffer)  // %0
1211     );
1212 }
1213 
1214 
1215 /**
1216   Reads the current value of 64-bit MMX Register #0 (MM0).
1217 
1218   Reads and returns the current value of MM0. This function is only available
1219   on IA-32 and X64.
1220 
1221   @return The current value of MM0.
1222 
1223 **/
1224 UINT64
1225 EFIAPI
AsmReadMm0(VOID)1226 AsmReadMm0 (
1227   VOID
1228   )
1229 {
1230   UINT64  Data;
1231 
1232   __asm__ __volatile__ (
1233     "movd   %%mm0,  %0    \n\t"
1234     : "=r"  (Data)       // %0
1235     );
1236 
1237   return Data;
1238 }
1239 
1240 
1241 /**
1242   Reads the current value of 64-bit MMX Register #1 (MM1).
1243 
1244   Reads and returns the current value of MM1. This function is only available
1245   on IA-32 and X64.
1246 
1247   @return The current value of MM1.
1248 
1249 **/
1250 UINT64
1251 EFIAPI
AsmReadMm1(VOID)1252 AsmReadMm1 (
1253   VOID
1254   )
1255 {
1256   UINT64  Data;
1257 
1258   __asm__ __volatile__ (
1259     "movd   %%mm1,  %0    \n\t"
1260     : "=r"  (Data)       // %0
1261     );
1262 
1263   return Data;
1264 }
1265 
1266 
1267 /**
1268   Reads the current value of 64-bit MMX Register #2 (MM2).
1269 
1270   Reads and returns the current value of MM2. This function is only available
1271   on IA-32 and X64.
1272 
1273   @return The current value of MM2.
1274 
1275 **/
1276 UINT64
1277 EFIAPI
AsmReadMm2(VOID)1278 AsmReadMm2 (
1279   VOID
1280   )
1281 {
1282   UINT64  Data;
1283 
1284   __asm__ __volatile__ (
1285     "movd  %%mm2,  %0    \n\t"
1286     : "=r"  (Data)       // %0
1287     );
1288 
1289   return Data;
1290 }
1291 
1292 
1293 /**
1294   Reads the current value of 64-bit MMX Register #3 (MM3).
1295 
1296   Reads and returns the current value of MM3. This function is only available
1297   on IA-32 and X64.
1298 
1299   @return The current value of MM3.
1300 
1301 **/
1302 UINT64
1303 EFIAPI
AsmReadMm3(VOID)1304 AsmReadMm3 (
1305   VOID
1306   )
1307 {
1308   UINT64  Data;
1309 
1310   __asm__ __volatile__ (
1311     "movd  %%mm3,  %0    \n\t"
1312     : "=r"  (Data)       // %0
1313     );
1314 
1315   return Data;
1316 }
1317 
1318 
1319 /**
1320   Reads the current value of 64-bit MMX Register #4 (MM4).
1321 
1322   Reads and returns the current value of MM4. This function is only available
1323   on IA-32 and X64.
1324 
1325   @return The current value of MM4.
1326 
1327 **/
1328 UINT64
1329 EFIAPI
AsmReadMm4(VOID)1330 AsmReadMm4 (
1331   VOID
1332   )
1333 {
1334   UINT64  Data;
1335 
1336   __asm__ __volatile__ (
1337     "movd  %%mm4,  %0    \n\t"
1338     : "=r"  (Data)       // %0
1339     );
1340 
1341   return Data;
1342 }
1343 
1344 
1345 /**
1346   Reads the current value of 64-bit MMX Register #5 (MM5).
1347 
1348   Reads and returns the current value of MM5. This function is only available
1349   on IA-32 and X64.
1350 
1351   @return The current value of MM5.
1352 
1353 **/
1354 UINT64
1355 EFIAPI
AsmReadMm5(VOID)1356 AsmReadMm5 (
1357   VOID
1358   )
1359 {
1360   UINT64  Data;
1361 
1362   __asm__ __volatile__ (
1363     "movd  %%mm5,  %0    \n\t"
1364     : "=r"  (Data)       // %0
1365     );
1366 
1367   return Data;
1368 }
1369 
1370 
1371 /**
1372   Reads the current value of 64-bit MMX Register #6 (MM6).
1373 
1374   Reads and returns the current value of MM6. This function is only available
1375   on IA-32 and X64.
1376 
1377   @return The current value of MM6.
1378 
1379 **/
1380 UINT64
1381 EFIAPI
AsmReadMm6(VOID)1382 AsmReadMm6 (
1383   VOID
1384   )
1385 {
1386   UINT64  Data;
1387 
1388   __asm__ __volatile__ (
1389     "movd  %%mm6,  %0    \n\t"
1390     : "=r"  (Data)       // %0
1391     );
1392 
1393   return Data;
1394 }
1395 
1396 
1397 /**
1398   Reads the current value of 64-bit MMX Register #7 (MM7).
1399 
1400   Reads and returns the current value of MM7. This function is only available
1401   on IA-32 and X64.
1402 
1403   @return The current value of MM7.
1404 
1405 **/
1406 UINT64
1407 EFIAPI
AsmReadMm7(VOID)1408 AsmReadMm7 (
1409   VOID
1410   )
1411 {
1412   UINT64  Data;
1413 
1414   __asm__ __volatile__ (
1415     "movd  %%mm7,  %0    \n\t"
1416     : "=r"  (Data)       // %0
1417     );
1418 
1419   return Data;
1420 }
1421 
1422 
1423 /**
1424   Writes the current value of 64-bit MMX Register #0 (MM0).
1425 
1426   Writes the current value of MM0. This function is only available on IA32 and
1427   X64.
1428 
1429   @param  Value The 64-bit value to write to MM0.
1430 
1431 **/
1432 VOID
1433 EFIAPI
AsmWriteMm0(IN UINT64 Value)1434 AsmWriteMm0 (
1435   IN      UINT64                    Value
1436   )
1437 {
1438   __asm__ __volatile__ (
1439     "movd  %0, %%mm0"  // %0
1440     :
1441     : "m" (Value)
1442     );
1443 }
1444 
1445 
1446 /**
1447   Writes the current value of 64-bit MMX Register #1 (MM1).
1448 
1449   Writes the current value of MM1. This function is only available on IA32 and
1450   X64.
1451 
1452   @param  Value The 64-bit value to write to MM1.
1453 
1454 **/
1455 VOID
1456 EFIAPI
AsmWriteMm1(IN UINT64 Value)1457 AsmWriteMm1 (
1458   IN      UINT64                    Value
1459   )
1460 {
1461   __asm__ __volatile__ (
1462     "movd  %0, %%mm1"  // %0
1463     :
1464     : "m" (Value)
1465     );
1466 }
1467 
1468 
1469 /**
1470   Writes the current value of 64-bit MMX Register #2 (MM2).
1471 
1472   Writes the current value of MM2. This function is only available on IA32 and
1473   X64.
1474 
1475   @param  Value The 64-bit value to write to MM2.
1476 
1477 **/
1478 VOID
1479 EFIAPI
AsmWriteMm2(IN UINT64 Value)1480 AsmWriteMm2 (
1481   IN      UINT64                    Value
1482   )
1483 {
1484   __asm__ __volatile__ (
1485     "movd  %0, %%mm2"  // %0
1486     :
1487     : "m" (Value)
1488     );
1489 }
1490 
1491 
1492 /**
1493   Writes the current value of 64-bit MMX Register #3 (MM3).
1494 
1495   Writes the current value of MM3. This function is only available on IA32 and
1496   X64.
1497 
1498   @param  Value The 64-bit value to write to MM3.
1499 
1500 **/
1501 VOID
1502 EFIAPI
AsmWriteMm3(IN UINT64 Value)1503 AsmWriteMm3 (
1504   IN      UINT64                    Value
1505   )
1506 {
1507   __asm__ __volatile__ (
1508     "movd  %0, %%mm3"  // %0
1509     :
1510     : "m" (Value)
1511     );
1512 }
1513 
1514 
1515 /**
1516   Writes the current value of 64-bit MMX Register #4 (MM4).
1517 
1518   Writes the current value of MM4. This function is only available on IA32 and
1519   X64.
1520 
1521   @param  Value The 64-bit value to write to MM4.
1522 
1523 **/
1524 VOID
1525 EFIAPI
AsmWriteMm4(IN UINT64 Value)1526 AsmWriteMm4 (
1527   IN      UINT64                    Value
1528   )
1529 {
1530   __asm__ __volatile__ (
1531     "movd  %0, %%mm4"  // %0
1532     :
1533     : "m" (Value)
1534     );
1535 }
1536 
1537 
1538 /**
1539   Writes the current value of 64-bit MMX Register #5 (MM5).
1540 
1541   Writes the current value of MM5. This function is only available on IA32 and
1542   X64.
1543 
1544   @param  Value The 64-bit value to write to MM5.
1545 
1546 **/
1547 VOID
1548 EFIAPI
AsmWriteMm5(IN UINT64 Value)1549 AsmWriteMm5 (
1550   IN      UINT64                    Value
1551   )
1552 {
1553   __asm__ __volatile__ (
1554     "movd  %0, %%mm5"  // %0
1555     :
1556     : "m" (Value)
1557     );
1558 }
1559 
1560 
1561 /**
1562   Writes the current value of 64-bit MMX Register #6 (MM6).
1563 
1564   Writes the current value of MM6. This function is only available on IA32 and
1565   X64.
1566 
1567   @param  Value The 64-bit value to write to MM6.
1568 
1569 **/
1570 VOID
1571 EFIAPI
AsmWriteMm6(IN UINT64 Value)1572 AsmWriteMm6 (
1573   IN      UINT64                    Value
1574   )
1575 {
1576   __asm__ __volatile__ (
1577     "movd  %0, %%mm6"  // %0
1578     :
1579     : "m" (Value)
1580     );
1581 }
1582 
1583 
1584 /**
1585   Writes the current value of 64-bit MMX Register #7 (MM7).
1586 
1587   Writes the current value of MM7. This function is only available on IA32 and
1588   X64.
1589 
1590   @param  Value The 64-bit value to write to MM7.
1591 
1592 **/
1593 VOID
1594 EFIAPI
AsmWriteMm7(IN UINT64 Value)1595 AsmWriteMm7 (
1596   IN      UINT64                    Value
1597   )
1598 {
1599   __asm__ __volatile__ (
1600     "movd  %0, %%mm7"  // %0
1601     :
1602     : "m" (Value)
1603     );
1604 }
1605 
1606 
1607 /**
1608   Reads the current value of Time Stamp Counter (TSC).
1609 
1610   Reads and returns the current value of TSC. This function is only available
1611   on IA-32 and X64.
1612 
1613   @return The current value of TSC
1614 
1615 **/
1616 UINT64
1617 EFIAPI
AsmReadTsc(VOID)1618 AsmReadTsc (
1619   VOID
1620   )
1621 {
1622   UINT32  LowData;
1623   UINT32  HiData;
1624 
1625   __asm__ __volatile__ (
1626     "rdtsc"
1627     : "=a" (LowData),
1628       "=d" (HiData)
1629     );
1630 
1631   return (((UINT64)HiData) << 32) | LowData;
1632 }
1633 
1634 
1635 /**
1636   Reads the current value of a Performance Counter (PMC).
1637 
1638   Reads and returns the current value of performance counter specified by
1639   Index. This function is only available on IA-32 and X64.
1640 
1641   @param  Index The 32-bit Performance Counter index to read.
1642 
1643   @return The value of the PMC specified by Index.
1644 
1645 **/
1646 UINT64
1647 EFIAPI
AsmReadPmc(IN UINT32 Index)1648 AsmReadPmc (
1649   IN      UINT32                    Index
1650   )
1651 {
1652   UINT32  LowData;
1653   UINT32  HiData;
1654 
1655   __asm__ __volatile__ (
1656     "rdpmc"
1657     : "=a" (LowData),
1658       "=d" (HiData)
1659     : "c"  (Index)
1660     );
1661 
1662   return (((UINT64)HiData) << 32) | LowData;
1663 }
1664 
1665 
1666 /**
1667   Sets up a monitor buffer that is used by AsmMwait().
1668 
1669   Executes a MONITOR instruction with the register state specified by Eax, Ecx
1670   and Edx. Returns Eax. This function is only available on IA-32 and X64.
1671 
1672   @param  Eax The value to load into EAX or RAX before executing the MONITOR
1673               instruction.
1674   @param  Ecx The value to load into ECX or RCX before executing the MONITOR
1675               instruction.
1676   @param  Edx The value to load into EDX or RDX before executing the MONITOR
1677               instruction.
1678 
1679   @return Eax
1680 
1681 **/
1682 UINTN
1683 EFIAPI
AsmMonitor(IN UINTN Eax,IN UINTN Ecx,IN UINTN Edx)1684 AsmMonitor (
1685   IN      UINTN                     Eax,
1686   IN      UINTN                     Ecx,
1687   IN      UINTN                     Edx
1688   )
1689 {
1690   __asm__ __volatile__ (
1691     "monitor"
1692     :
1693     : "a" (Eax),
1694       "c" (Ecx),
1695       "d" (Edx)
1696     );
1697 
1698   return Eax;
1699 }
1700 
1701 
1702 /**
1703   Executes an MWAIT instruction.
1704 
1705   Executes an MWAIT instruction with the register state specified by Eax and
1706   Ecx. Returns Eax. This function is only available on IA-32 and X64.
1707 
1708   @param  Eax The value to load into EAX or RAX before executing the MONITOR
1709               instruction.
1710   @param  Ecx The value to load into ECX or RCX before executing the MONITOR
1711               instruction.
1712 
1713   @return Eax
1714 
1715 **/
1716 UINTN
1717 EFIAPI
AsmMwait(IN UINTN Eax,IN UINTN Ecx)1718 AsmMwait (
1719   IN      UINTN                     Eax,
1720   IN      UINTN                     Ecx
1721   )
1722 {
1723   __asm__ __volatile__ (
1724     "mwait"
1725     :
1726     : "a"  (Eax),
1727       "c"  (Ecx)
1728     );
1729 
1730   return Eax;
1731 }
1732 
1733 
1734 /**
1735   Executes a WBINVD instruction.
1736 
1737   Executes a WBINVD instruction. This function is only available on IA-32 and
1738   X64.
1739 
1740 **/
1741 VOID
1742 EFIAPI
AsmWbinvd(VOID)1743 AsmWbinvd (
1744   VOID
1745   )
1746 {
1747   __asm__ __volatile__ ("wbinvd":::"memory");
1748 }
1749 
1750 
1751 /**
1752   Executes a INVD instruction.
1753 
1754   Executes a INVD instruction. This function is only available on IA-32 and
1755   X64.
1756 
1757 **/
1758 VOID
1759 EFIAPI
AsmInvd(VOID)1760 AsmInvd (
1761   VOID
1762   )
1763 {
1764   __asm__ __volatile__ ("invd":::"memory");
1765 
1766 }
1767 
1768 
1769 /**
1770   Flushes a cache line from all the instruction and data caches within the
1771   coherency domain of the CPU.
1772 
1773   Flushed the cache line specified by LinearAddress, and returns LinearAddress.
1774   This function is only available on IA-32 and X64.
1775 
1776   @param  LinearAddress The address of the cache line to flush. If the CPU is
1777                         in a physical addressing mode, then LinearAddress is a
1778                         physical address. If the CPU is in a virtual
1779                         addressing mode, then LinearAddress is a virtual
1780                         address.
1781 
1782   @return LinearAddress
1783 **/
1784 VOID *
1785 EFIAPI
AsmFlushCacheLine(IN VOID * LinearAddress)1786 AsmFlushCacheLine (
1787   IN      VOID                      *LinearAddress
1788   )
1789 {
1790   __asm__ __volatile__ (
1791     "clflush (%0)"
1792     :
1793     : "r" (LinearAddress)
1794     : "memory"
1795     );
1796 
1797     return LinearAddress;
1798 }
1799 
1800 
1801