]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/Library/CpuExceptionHandlerLib/X64/ArchExceptionHandler.c
1. Separated DxeSmmCpuExceptionHandlerLib.inf into 2 instance DxeCpuExceptionHandlerL...
[mirror_edk2.git] / UefiCpuPkg / Library / CpuExceptionHandlerLib / X64 / ArchExceptionHandler.c
index 664472a6678ecf1fa76af84f8fffab3f2f59bf51..1af2999ac0b237533b24fbf372c956c5779a9021 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   x64 CPU Exception Hanlder.\r
 \r
-  Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2012 - 2013, 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
 #include "CpuExceptionCommon.h"\r
 \r
 /**\r
-  Internal function to setup CPU exception handlers.\r
+  Return address map of exception handler template so that C code can generate\r
+  exception tables.\r
 \r
+  @param IdtEntry          Pointer to IDT entry to be updated.\r
+  @param InterruptHandler  IDT handler value.\r
 **/\r
 VOID\r
-InternalSetupCpuExceptionHandlers (\r
-  VOID\r
+ArchUpdateIdtEntry (\r
+  IN IA32_IDT_GATE_DESCRIPTOR        *IdtEntry,\r
+  IN UINTN                           InterruptHandler\r
   )\r
 {\r
-  IA32_DESCRIPTOR                     IdtDescriptor;\r
-  UINTN                               IdtSize;\r
-  EXCEPTION_HANDLER_TEMPLATE_MAP      TemplateMap;\r
-  UINT16                              CodeSegment;\r
-  IA32_IDT_GATE_DESCRIPTOR            *IdtEntry;\r
-  UINTN                               Index;\r
-  UINTN                               InterruptHandler;\r
+  IdtEntry->Bits.OffsetLow   = (UINT16)(UINTN)InterruptHandler;\r
+  IdtEntry->Bits.OffsetHigh  = (UINT16)((UINTN)InterruptHandler >> 16);\r
+  IdtEntry->Bits.OffsetUpper = (UINT32)((UINTN)InterruptHandler >> 32);        \r
+  IdtEntry->Bits.GateType    = IA32_IDT_GATE_TYPE_INTERRUPT_32;\r
+}\r
+\r
+/**\r
+  Read IDT handler value from IDT entry.\r
+\r
+  @param IdtEntry          Pointer to IDT entry to be read.\r
+\r
+**/\r
+UINTN\r
+ArchGetIdtHandler (\r
+  IN IA32_IDT_GATE_DESCRIPTOR        *IdtEntry\r
+  )\r
+{\r
+  return IdtEntry->Bits.OffsetLow + (((UINTN) IdtEntry->Bits.OffsetHigh)  << 16) +\r
+                                    (((UINTN) IdtEntry->Bits.OffsetUpper) << 32);\r
+}\r
 \r
+/**\r
+  Save CPU exception context when handling EFI_VECTOR_HANDOFF_HOOK_AFTER case.\r
+\r
+  @param ExceptionType  Exception type.\r
+  @param SystemContext  Pointer to EFI_SYSTEM_CONTEXT.\r
+**/\r
+VOID\r
+ArchSaveExceptionContext (\r
+  IN UINTN                ExceptionType,\r
+  IN EFI_SYSTEM_CONTEXT   SystemContext \r
+  )\r
+{\r
+  IA32_EFLAGS32           Eflags;\r
   //\r
-  // Read IDT descriptor and calculate IDT size\r
+  // Save Exception context in global variable\r
   //\r
-  AsmReadIdtr (&IdtDescriptor);\r
-  IdtSize = (IdtDescriptor.Limit + 1) / sizeof (IA32_IDT_GATE_DESCRIPTOR);\r
-  if (IdtSize > CPU_EXCEPTION_NUM) {\r
-    //\r
-    // CPU exeption library only setup CPU_EXCEPTION_NUM exception handler at most\r
-    //\r
-    IdtSize = CPU_EXCEPTION_NUM;\r
-  }\r
-\r
+  mReservedVectors[ExceptionType].OldSs         = SystemContext.SystemContextX64->Ss;\r
+  mReservedVectors[ExceptionType].OldSp         = SystemContext.SystemContextX64->Rsp;\r
+  mReservedVectors[ExceptionType].OldFlags      = SystemContext.SystemContextX64->Rflags;\r
+  mReservedVectors[ExceptionType].OldCs         = SystemContext.SystemContextX64->Cs;\r
+  mReservedVectors[ExceptionType].OldIp         = SystemContext.SystemContextX64->Rip;\r
+  mReservedVectors[ExceptionType].ExceptionData = SystemContext.SystemContextX64->ExceptionData;\r
   //\r
-  // Use current CS as the segment selector of interrupt gate in IDT\r
+  // Clear IF flag to avoid old IDT handler enable interrupt by IRET\r
   //\r
-  CodeSegment = AsmReadCs ();\r
-  IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;\r
-\r
-  GetTemplateAddressMap (&TemplateMap);\r
-\r
-  for (Index = 0; Index < IdtSize; Index ++) {\r
-    InterruptHandler = TemplateMap.ExceptionStart + Index * TemplateMap.ExceptionStubHeaderSize;\r
-    IdtEntry[Index].Bits.OffsetLow       = (UINT16)(UINTN)InterruptHandler;\r
-    IdtEntry[Index].Bits.OffsetHigh      = (UINT16)((UINTN)InterruptHandler >> 16);\r
-    IdtEntry[Index].Bits.OffsetUpper     = (UINT32)((UINTN)InterruptHandler >> 32);\r
-    IdtEntry[Index].Bits.Selector        = CodeSegment;\r
-    IdtEntry[Index].Bits.GateType        = IA32_IDT_GATE_TYPE_INTERRUPT_32;\r
-  }\r
+  Eflags.UintN = SystemContext.SystemContextX64->Rflags;\r
+  Eflags.Bits.IF = 0; \r
+  SystemContext.SystemContextX64->Rflags = Eflags.UintN;\r
+  //\r
+  // Modify the EIP in stack, then old IDT handler will return to the stub code\r
+  //\r
+  SystemContext.SystemContextX64->Rip = (UINTN) mReservedVectors[ExceptionType].HookAfterStubHeaderCode;\r
 }\r
 \r
 /**\r
-  Common exception handler.\r
+  Restore CPU exception context when handling EFI_VECTOR_HANDOFF_HOOK_AFTER case.\r
 \r
   @param ExceptionType  Exception type.\r
   @param SystemContext  Pointer to EFI_SYSTEM_CONTEXT.\r
 **/\r
 VOID\r
-DumpCpuContent (\r
+ArchRestoreExceptionContext (\r
   IN UINTN                ExceptionType,\r
+  IN EFI_SYSTEM_CONTEXT   SystemContext \r
+  )\r
+{\r
+  SystemContext.SystemContextX64->Ss            = mReservedVectors[ExceptionType].OldSs;\r
+  SystemContext.SystemContextX64->Rsp           = mReservedVectors[ExceptionType].OldSp;\r
+  SystemContext.SystemContextX64->Rflags        = mReservedVectors[ExceptionType].OldFlags;\r
+  SystemContext.SystemContextX64->Cs            = mReservedVectors[ExceptionType].OldCs;\r
+  SystemContext.SystemContextX64->Rip           = mReservedVectors[ExceptionType].OldIp;\r
+  SystemContext.SystemContextX64->ExceptionData = mReservedVectors[ExceptionType].ExceptionData;\r
+}\r
+\r
+/**\r
+  Dump CPU content information.\r
+\r
+  @param ExceptionType  Exception type.\r
+  @param SystemContext  Pointer to EFI_SYSTEM_CONTEXT.\r
+**/\r
+VOID\r
+DumpCpuContent (\r
+  IN EFI_EXCEPTION_TYPE   ExceptionType,\r
   IN EFI_SYSTEM_CONTEXT   SystemContext\r
   )\r
 {\r