]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c
Fix build break when doing 32-bit build with some certain C compiler option combinations.
[mirror_edk2.git] / UefiCpuPkg / Library / BaseXApicX2ApicLib / BaseXApicX2ApicLib.c
index bff66eeb1bcc802a976361af62d55b1b5ebc6dbc..9f08f5d188c14d9ec5313275b0ce0b67aa16c9e0 100644 (file)
@@ -151,7 +151,7 @@ SendIpi (
     // For x2APIC, A single MSR write to the Interrupt Command Register is required for dispatching an \r
     // interrupt in x2APIC mode.\r
     //\r
-    MsrValue = (((UINT64)ApicId) << 32) | IcrLow;\r
+    MsrValue = LShiftU64 ((UINT64) ApicId, 32) | IcrLow;\r
     AsmWriteMsr64 (X2APIC_MSR_ICR_ADDRESS, MsrValue);\r
   }\r
 }\r
@@ -285,6 +285,67 @@ GetApicId (
   return ApicId;\r
 }\r
 \r
+/**\r
+  Get the value of the local APIC version register.\r
+\r
+  @return  the value of the local APIC version register.\r
+**/\r
+UINT32\r
+EFIAPI\r
+GetApicVersion (\r
+  VOID\r
+  )\r
+{\r
+  return ReadLocalApicReg (XAPIC_VERSION_OFFSET);\r
+}\r
+\r
+/**\r
+  Send a Fixed IPI to a specified target processor.\r
+\r
+  This function returns after the IPI has been accepted by the target processor. \r
+\r
+  @param  ApicId   The local APIC ID of the target processor.\r
+  @param  Vector   The vector number of the interrupt being sent.\r
+**/\r
+VOID\r
+EFIAPI\r
+SendFixedIpi (\r
+  IN UINT32          ApicId,\r
+  IN UINT8           Vector\r
+  )\r
+{\r
+  LOCAL_APIC_ICR_LOW IcrLow;\r
+\r
+  IcrLow.Uint32 = 0;\r
+  IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_FIXED;\r
+  IcrLow.Bits.Level = 1;\r
+  IcrLow.Bits.Vector = Vector;\r
+  SendIpi (IcrLow.Uint32, ApicId);\r
+}\r
+\r
+/**\r
+  Send a Fixed IPI to all processors excluding self.\r
+\r
+  This function returns after the IPI has been accepted by the target processors. \r
+\r
+  @param  Vector   The vector number of the interrupt being sent.\r
+**/\r
+VOID\r
+EFIAPI\r
+SendFixedIpiAllExcludingSelf (\r
+  IN UINT8           Vector\r
+  )\r
+{\r
+  LOCAL_APIC_ICR_LOW IcrLow;\r
+\r
+  IcrLow.Uint32 = 0;\r
+  IcrLow.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_FIXED;\r
+  IcrLow.Bits.Level = 1;\r
+  IcrLow.Bits.DestinationShorthand = LOCAL_APIC_DESTINATION_SHORTHAND_ALL_EXCLUDING_SELF;\r
+  IcrLow.Bits.Vector = Vector;\r
+  SendIpi (IcrLow.Uint32, 0);\r
+}\r
+\r
 /**\r
   Send a SMI IPI to a specified target processor.\r
 \r
@@ -464,43 +525,44 @@ ProgramVirtualWireMode (
   //\r
   // Program the LINT0 vector entry as ExtInt. Not masked, edge, active high.\r
   //\r
-  Lint.Uint32 = ReadLocalApicReg (XAPIC_LINT0_VECTOR_OFFSET);\r
+  Lint.Uint32 = ReadLocalApicReg (XAPIC_LVT_LINT0_OFFSET);\r
   Lint.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_EXTINT;\r
   Lint.Bits.InputPinPolarity = 0;\r
   Lint.Bits.TriggerMode = 0;\r
   Lint.Bits.Mask = 0;\r
-  WriteLocalApicReg (XAPIC_LINT0_VECTOR_OFFSET, Lint.Uint32);\r
+  WriteLocalApicReg (XAPIC_LVT_LINT0_OFFSET, Lint.Uint32);\r
 \r
   //\r
   // Program the LINT0 vector entry as NMI. Not masked, edge, active high.\r
   //\r
-  Lint.Uint32 = ReadLocalApicReg (XAPIC_LINT1_VECTOR_OFFSET);\r
+  Lint.Uint32 = ReadLocalApicReg (XAPIC_LVT_LINT1_OFFSET);\r
   Lint.Bits.DeliveryMode = LOCAL_APIC_DELIVERY_MODE_NMI;\r
   Lint.Bits.InputPinPolarity = 0;\r
   Lint.Bits.TriggerMode = 0;\r
   Lint.Bits.Mask = 0;\r
-  WriteLocalApicReg (XAPIC_LINT1_VECTOR_OFFSET, Lint.Uint32);\r
+  WriteLocalApicReg (XAPIC_LVT_LINT1_OFFSET, Lint.Uint32);\r
 }\r
 \r
 /**\r
-  Get the divide value from the DCR (Divide Configuration Register) by which\r
-  the processor's bus clock is divided to form the time base for the APIC timer.\r
+  Disable LINT0 & LINT1 interrupts.\r
 \r
-  @return The divide value is one of 1,2,4,8,16,32,64,128.\r
+  This function sets the mask flag in the LVT LINT0 & LINT1 registers.\r
 **/\r
-UINTN\r
+VOID\r
 EFIAPI\r
-GetApicTimerDivisor (\r
+DisableLvtInterrupts (\r
   VOID\r
   )\r
 {\r
-  UINT32         DivideValue;\r
-  LOCAL_APIC_DCR Dcr;\r
+  LOCAL_APIC_LVT_LINT LvtLint;\r
+\r
+  LvtLint.Uint32 = ReadLocalApicReg (XAPIC_LVT_LINT0_OFFSET);\r
+  LvtLint.Bits.Mask = 1;\r
+  WriteLocalApicReg (XAPIC_LVT_LINT0_OFFSET, LvtLint.Uint32);\r
 \r
-  Dcr.Uint32 = ReadLocalApicReg (XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET);\r
-  DivideValue = Dcr.Bits.DivideValue1 | (Dcr.Bits.DivideValue2 << 2);\r
-  DivideValue = (DivideValue + 1) & 0x7;\r
-  return ((UINTN)1) << DivideValue;\r
+  LvtLint.Uint32 = ReadLocalApicReg (XAPIC_LVT_LINT1_OFFSET);\r
+  LvtLint.Bits.Mask = 1;\r
+  WriteLocalApicReg (XAPIC_LVT_LINT1_OFFSET, LvtLint.Uint32);\r
 }\r
 \r
 /**\r
@@ -593,6 +655,47 @@ InitializeApicTimer (
   WriteLocalApicReg (XAPIC_LVT_TIMER_OFFSET, LvtTimer.Uint32);\r
 }\r
 \r
+/**\r
+  Get the state of the local APIC timer.\r
+\r
+  @param DivideValue   Return the divide value for the DCR. It is one of 1,2,4,8,16,32,64,128.\r
+  @param PeriodicMode  Return the timer mode. If TRUE, timer mode is peridoic. Othewise, timer mode is one-shot.\r
+  @param Vector        Return the timer interrupt vector number.\r
+**/\r
+VOID\r
+EFIAPI\r
+GetApicTimerState (\r
+  OUT UINTN    *DivideValue  OPTIONAL,\r
+  OUT BOOLEAN  *PeriodicMode  OPTIONAL,\r
+  OUT UINT8    *Vector  OPTIONAL\r
+  )\r
+{\r
+  UINT32 Divisor;\r
+  LOCAL_APIC_DCR Dcr;\r
+  LOCAL_APIC_LVT_TIMER LvtTimer;\r
+\r
+  if (DivideValue != NULL) {\r
+    Dcr.Uint32 = ReadLocalApicReg (XAPIC_TIMER_DIVIDE_CONFIGURATION_OFFSET);\r
+    Divisor = Dcr.Bits.DivideValue1 | (Dcr.Bits.DivideValue2 << 2);\r
+    Divisor = (Divisor + 1) & 0x7;\r
+    *DivideValue = ((UINTN)1) << Divisor;\r
+  }\r
+\r
+  if (PeriodicMode != NULL || Vector != NULL) {\r
+    LvtTimer.Uint32 = ReadLocalApicReg (XAPIC_LVT_TIMER_OFFSET);\r
+    if (PeriodicMode != NULL) {\r
+      if (LvtTimer.Bits.TimerMode == 1) {\r
+        *PeriodicMode = TRUE;\r
+      } else {\r
+        *PeriodicMode = FALSE;\r
+      }\r
+    }\r
+    if (Vector != NULL) {\r
+      *Vector = (UINT8) LvtTimer.Bits.Vector;\r
+    }\r
+  }\r
+}\r
+\r
 /**\r
   Enable the local APIC timer interrupt.\r
 **/\r