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