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