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