]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/Library/BaseXApicX2ApicLib/BaseXApicX2ApicLib.c
Improve Local APIC library class. Add new library APIs: GetApicVersion(), SendFixedIp...
[mirror_edk2.git] / UefiCpuPkg / Library / BaseXApicX2ApicLib / BaseXApicX2ApicLib.c
index bff66eeb1bcc802a976361af62d55b1b5ebc6dbc..7ee13c3ba6f594e97820860eb7fa38ccb6c305d4 100644 (file)
@@ -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,22 @@ 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
-}\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
-\r
-  @return The divide value is one of 1,2,4,8,16,32,64,128.\r
-**/\r
-UINTN\r
-EFIAPI\r
-GetApicTimerDivisor (\r
-  VOID\r
-  )\r
-{\r
-  UINT32         DivideValue;\r
-  LOCAL_APIC_DCR Dcr;\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
+  WriteLocalApicReg (XAPIC_LVT_LINT1_OFFSET, Lint.Uint32);\r
 }\r
 \r
 /**\r
@@ -593,6 +633,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