]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/CpuDxe/CpuDxe.c
Prevent infinite recursion when ASSERT(), DEBUG(), or any other use of ReportStatusCo...
[mirror_edk2.git] / UefiCpuPkg / CpuDxe / CpuDxe.c
index 25131febf20a0fc098ffdb98eca905e562bfa7ca..c5f3bb76f4a0bc2c21ad7bce8fd60e4c61e9a27e 100644 (file)
@@ -1,8 +1,8 @@
 /** @file\r
   CPU DXE Module.\r
 \r
-  Copyright (c) 2008 - 2009, Intel Corporation\r
-  All rights reserved. This program and the accompanying materials\r
+  Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.<BR>\r
+  This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
   which accompanies this distribution.  The full text of the license may be found at\r
   http://opensource.org/licenses/bsd-license.php\r
@@ -111,6 +111,23 @@ EFI_CPU_ARCH_PROTOCOL  gCpu = {
 //\r
 UINT32 mErrorCodeFlag = 0x00027d00;\r
 \r
+//\r
+// Local function prototypes\r
+//\r
+\r
+/**\r
+  Set Interrupt Descriptor Table Handler Address.\r
+\r
+  @param Index        The Index of the interrupt descriptor table handle.\r
+  @param Handler      Handler address.\r
+\r
+**/\r
+VOID\r
+SetInterruptDescriptorTableHandlerAddress (\r
+  IN UINTN Index,\r
+  IN VOID  *Handler  OPTIONAL\r
+  );\r
+\r
 //\r
 // CPU Arch Protocol Functions\r
 //\r
@@ -136,7 +153,7 @@ CommonExceptionHandler (
     "!!!! IA32 Exception Type - %08x !!!!\n",\r
     InterruptType\r
     ));\r
-  if (mErrorCodeFlag & (1 << InterruptType)) {\r
+  if ((mErrorCodeFlag & (1 << InterruptType)) != 0) {\r
     DEBUG ((\r
       EFI_D_ERROR,\r
       "ExceptionData - %08x\n",\r
@@ -217,7 +234,7 @@ CommonExceptionHandler (
     "!!!! X64 Exception Type - %016lx !!!!\n",\r
     (UINT64)InterruptType\r
     ));\r
-  if (mErrorCodeFlag & (1 << InterruptType)) {\r
+  if ((mErrorCodeFlag & (1 << InterruptType)) != 0) {\r
     DEBUG ((\r
       EFI_D_ERROR,\r
       "ExceptionData - %016lx\n",\r
@@ -504,6 +521,7 @@ CpuRegisterInterruptHandler (
     return EFI_ALREADY_STARTED;\r
   }\r
 \r
+  SetInterruptDescriptorTableHandlerAddress ((UINTN)InterruptType, NULL);\r
   ExternalVectorTable[InterruptType] = InterruptHandler;\r
   return EFI_SUCCESS;\r
 }\r
@@ -590,6 +608,10 @@ CpuSetMemoryAttributes (
   RETURN_STATUS             Status;\r
   MTRR_MEMORY_CACHE_TYPE    CacheType;\r
 \r
+  if (!IsMtrrSupported ()) {\r
+    return EFI_UNSUPPORTED;\r
+  }\r
+\r
   DEBUG((EFI_D_ERROR, "CpuAp: SetMemorySpaceAttributes(BA=%08x, Len=%08x, Attr=%08x)\n", BaseAddress, Length, Attributes));\r
 \r
   //\r
@@ -672,11 +694,11 @@ InitializeMtrrMask (
 }\r
 \r
 /**\r
-  Gets GCD Mem Space type from MTRR Type\r
+  Gets GCD Mem Space type from MTRR Type.\r
 \r
-  This function gets GCD Mem Space type from MTRR Type\r
+  This function gets GCD Mem Space type from MTRR Type.\r
 \r
-  @param  MtrrAttribute  MTRR memory type\r
+  @param  MtrrAttributes  MTRR memory type\r
 \r
   @return GCD Mem Space type\r
 \r
@@ -854,6 +876,14 @@ RefreshGcdMemoryAttributes (
   UINT64                              DefaultAttributes;\r
   VARIABLE_MTRR                       VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];\r
   MTRR_FIXED_SETTINGS                 MtrrFixedSettings;\r
+  UINT32                              FirmwareVariableMtrrCount;\r
+\r
+  if (!IsMtrrSupported ()) {\r
+    return;\r
+  }\r
+\r
+  FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount ();\r
+  ASSERT (FirmwareVariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);\r
 \r
 //  mIsFlushingGCD = TRUE;\r
   mIsFlushingGCD = FALSE;\r
@@ -902,7 +932,7 @@ RefreshGcdMemoryAttributes (
   //\r
   // Go for variable MTRRs with WB attribute\r
   //\r
-  for (Index = 0; Index < FIRMWARE_VARIABLE_MTRR_NUMBER; Index++) {\r
+  for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {\r
     if (VariableMtrr[Index].Valid &&\r
         VariableMtrr[Index].Type == MTRR_CACHE_WRITE_BACK) {\r
       SetGcdMemorySpaceAttributes (\r
@@ -917,7 +947,7 @@ RefreshGcdMemoryAttributes (
   //\r
   // Go for variable MTRRs with Non-WB attribute\r
   //\r
-  for (Index = 0; Index < FIRMWARE_VARIABLE_MTRR_NUMBER; Index++) {\r
+  for (Index = 0; Index < FirmwareVariableMtrrCount; Index++) {\r
     if (VariableMtrr[Index].Valid &&\r
         VariableMtrr[Index].Type != MTRR_CACHE_WRITE_BACK) {\r
       Attributes = GetMemorySpaceAttributeFromMtrrType ((UINT8) VariableMtrr[Index].Type);\r
@@ -992,39 +1022,98 @@ RefreshGcdMemoryAttributes (
   mIsFlushingGCD = FALSE;\r
 }\r
 \r
+/**\r
+  Set Interrupt Descriptor Table Handler Address.\r
+\r
+  @param Index        The Index of the interrupt descriptor table handle.\r
+  @param Handler      Handler address.\r
+\r
+**/\r
+VOID\r
+SetInterruptDescriptorTableHandlerAddress (\r
+  IN UINTN Index,\r
+  IN VOID  *Handler  OPTIONAL\r
+  )\r
+{\r
+  UINTN                     UintnHandler;\r
+\r
+  if (Handler != NULL) {\r
+    UintnHandler = (UINTN) Handler;\r
+  } else {\r
+    UintnHandler = ((UINTN) AsmIdtVector00) + (8 * Index);\r
+  }\r
+\r
+  gIdtTable[Index].Bits.OffsetLow   = (UINT16)UintnHandler;\r
+  gIdtTable[Index].Bits.Reserved_0  = 0;\r
+  gIdtTable[Index].Bits.GateType    = IA32_IDT_GATE_TYPE_INTERRUPT_32;\r
+  gIdtTable[Index].Bits.OffsetHigh  = (UINT16)(UintnHandler >> 16);\r
+#if defined (MDE_CPU_X64)\r
+  gIdtTable[Index].Bits.OffsetUpper = (UINT32)(UintnHandler >> 32);\r
+  gIdtTable[Index].Bits.Reserved_1  = 0;\r
+#endif\r
+}\r
+\r
 \r
 /**\r
   Initialize Interrupt Descriptor Table for interrupt handling.\r
 \r
 **/\r
-STATIC\r
 VOID\r
 InitInterruptDescriptorTable (\r
   VOID\r
   )\r
 {\r
-  EFI_STATUS      Status;\r
-  VOID            *IdtPtrAlignmentBuffer;\r
-  IA32_DESCRIPTOR *IdtPtr;\r
-  UINTN           Index;\r
-  UINTN           CurrentHandler;\r
+  EFI_STATUS                Status;\r
+  IA32_DESCRIPTOR           OldIdtPtr;\r
+  IA32_IDT_GATE_DESCRIPTOR  *OldIdt;\r
+  UINTN                     OldIdtSize;\r
+  VOID                      *IdtPtrAlignmentBuffer;\r
+  IA32_DESCRIPTOR           *IdtPtr;\r
+  UINTN                     Index;\r
+  UINT16                    CurrentCs;\r
+  VOID                      *IntHandler;\r
 \r
   SetMem (ExternalVectorTable, sizeof(ExternalVectorTable), 0);\r
 \r
+  //\r
+  // Get original IDT address and size.\r
+  //\r
+  AsmReadIdtr ((IA32_DESCRIPTOR *) &OldIdtPtr);\r
+\r
+  if ((OldIdtPtr.Base != 0) && ((OldIdtPtr.Limit & 7) == 7)) {\r
+    OldIdt = (IA32_IDT_GATE_DESCRIPTOR*) OldIdtPtr.Base;\r
+    OldIdtSize = (OldIdtPtr.Limit + 1) / 8;\r
+  } else {\r
+    OldIdt = NULL;\r
+    OldIdtSize = 0;\r
+  }\r
+\r
   //\r
   // Intialize IDT\r
   //\r
-  CurrentHandler = (UINTN)AsmIdtVector00;\r
-  for (Index = 0; Index < INTERRUPT_VECTOR_NUMBER; Index ++, CurrentHandler += 0x08) {\r
-    gIdtTable[Index].Bits.OffsetLow   = (UINT16)CurrentHandler;\r
-    gIdtTable[Index].Bits.Selector    = AsmReadCs();\r
-    gIdtTable[Index].Bits.Reserved_0  = 0;\r
-    gIdtTable[Index].Bits.GateType    = IA32_IDT_GATE_TYPE_INTERRUPT_32;\r
-    gIdtTable[Index].Bits.OffsetHigh  = (UINT16)(CurrentHandler >> 16);\r
+  CurrentCs = AsmReadCs();\r
+  for (Index = 0; Index < INTERRUPT_VECTOR_NUMBER; Index ++) {\r
+    //\r
+    // If the old IDT had a handler for this interrupt, then\r
+    // preserve it.\r
+    //\r
+    if (Index < OldIdtSize) {\r
+      IntHandler = \r
+        (VOID*) (\r
+          OldIdt[Index].Bits.OffsetLow +\r
+          (OldIdt[Index].Bits.OffsetHigh << 16)\r
 #if defined (MDE_CPU_X64)\r
-    gIdtTable[Index].Bits.OffsetUpper = (UINT32)(CurrentHandler >> 32);\r
-    gIdtTable[Index].Bits.Reserved_1  = 0;\r
+            + (((UINTN) OldIdt[Index].Bits.OffsetUpper) << 32)\r
 #endif\r
+          );\r
+    } else {\r
+      IntHandler = NULL;\r
+    }\r
+\r
+    gIdtTable[Index].Bits.Selector    = CurrentCs;\r
+    gIdtTable[Index].Bits.Reserved_0  = 0;\r
+    gIdtTable[Index].Bits.GateType    = IA32_IDT_GATE_TYPE_INTERRUPT_32;\r
+    SetInterruptDescriptorTableHandlerAddress (Index, IntHandler);\r
   }\r
 \r
   //\r
@@ -1033,8 +1122,10 @@ InitInterruptDescriptorTable (
   IdtPtrAlignmentBuffer = AllocatePool (sizeof (*IdtPtr) + 16);\r
   IdtPtr = ALIGN_POINTER (IdtPtrAlignmentBuffer, 16);\r
   IdtPtr->Base = (UINT32)(((UINTN)(VOID*) gIdtTable) & (BASE_4GB-1));\r
-  IdtPtr->Limit = sizeof (gIdtTable) - 1;\r
+  IdtPtr->Limit = (UINT16) (sizeof (gIdtTable) - 1);\r
+\r
   AsmWriteIdtr (IdtPtr);\r
+\r
   FreePool (IdtPtrAlignmentBuffer);\r
 \r
   //\r