]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/Library/BaseXApicLib/BaseXApicLib.c
Add DisableLvtInterrupts() for the Local APIC library class.
[mirror_edk2.git] / UefiCpuPkg / Library / BaseXApicLib / BaseXApicLib.c
index 16dbd4be6ed47a4154e635d0734d74ee9e768c0e..79a0fcd413332c3a17dd97c98beec768c86c47ba 100644 (file)
@@ -202,6 +202,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
@@ -381,43 +442,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
@@ -510,6 +572,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