]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/Library/CpuExceptionHandlerLib/Ia32/ArchExceptionHandler.c
1. Separated DxeSmmCpuExceptionHandlerLib.inf into 2 instance DxeCpuExceptionHandlerL...
[mirror_edk2.git] / UefiCpuPkg / Library / CpuExceptionHandlerLib / Ia32 / ArchExceptionHandler.c
index a69f0d3d2bd0f70daba4442177dab7b49fb7fcd0..ba2cc6f227eb554fda36d6864204212070977aa3 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   IA32 CPU Exception Hanlder functons.\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
 **/\r
 VOID\r
-InternalSetupCpuExceptionHandlers (\r
-  VOID\r
+ArchUpdateIdtEntry (\r
+  IN IA32_IDT_GATE_DESCRIPTOR        *IdtEntry,\r
+  IN UINTN                           InterruptHandler\r
+  )\r
+{\r
+  IdtEntry->Bits.OffsetLow   = (UINT16)(UINTN)InterruptHandler;\r
+  IdtEntry->Bits.OffsetHigh  = (UINT16)((UINTN)InterruptHandler >> 16);\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
-  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
+  return (UINTN)IdtEntry->Bits.OffsetLow + (((UINTN)IdtEntry->Bits.OffsetHigh) << 16);\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
+**/\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].OldFlags      = SystemContext.SystemContextIa32->Eflags;\r
+  mReservedVectors[ExceptionType].OldCs         = SystemContext.SystemContextIa32->Cs;\r
+  mReservedVectors[ExceptionType].OldIp         = SystemContext.SystemContextIa32->Eip;\r
+  mReservedVectors[ExceptionType].ExceptionData = SystemContext.SystemContextIa32->ExceptionData;\r
+  //\r
+  // Clear IF flag to avoid old IDT handler enable interrupt by IRET\r
   //\r
-  // Use current CS as the segment selector of interrupt gate in IDT\r
+  Eflags.UintN = SystemContext.SystemContextIa32->Eflags;\r
+  Eflags.Bits.IF = 0; \r
+  SystemContext.SystemContextIa32->Eflags = Eflags.UintN;\r
   //\r
-  CodeSegment = AsmReadCs ();\r
-  IdtEntry = (IA32_IDT_GATE_DESCRIPTOR *) IdtDescriptor.Base;\r
+  // Modify the EIP in stack, then old IDT handler will return to the stub code\r
+  //\r
+  SystemContext.SystemContextIa32->Eip    = (UINTN) mReservedVectors[ExceptionType].HookAfterStubHeaderCode;\r
+}\r
 \r
-  GetTemplateAddressMap (&TemplateMap);\r
+/**\r
+  Restore CPU exception context when handling EFI_VECTOR_HANDOFF_HOOK_AFTER case.\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.Selector   = CodeSegment;\r
-    IdtEntry[Index].Bits.GateType   = IA32_IDT_GATE_TYPE_INTERRUPT_32;\r
-  }\r
+  @param ExceptionType  Exception type.\r
+  @param SystemContext  Pointer to EFI_SYSTEM_CONTEXT.\r
+**/\r
+VOID\r
+ArchRestoreExceptionContext (\r
+  IN UINTN                ExceptionType,\r
+  IN EFI_SYSTEM_CONTEXT   SystemContext \r
+  )\r
+{\r
+  SystemContext.SystemContextIa32->Eflags        = mReservedVectors[ExceptionType].OldFlags;\r
+  SystemContext.SystemContextIa32->Cs            = mReservedVectors[ExceptionType].OldCs;\r
+  SystemContext.SystemContextIa32->Eip           = mReservedVectors[ExceptionType].OldIp;\r
+  SystemContext.SystemContextIa32->ExceptionData = mReservedVectors[ExceptionType].ExceptionData;\r
 }\r
 \r
 /**\r
@@ -68,7 +106,7 @@ InternalSetupCpuExceptionHandlers (
 **/\r
 VOID\r
 DumpCpuContent (\r
-  IN UINTN                ExceptionType,\r
+  IN EFI_EXCEPTION_TYPE   ExceptionType,\r
   IN EFI_SYSTEM_CONTEXT   SystemContext\r
   )\r
 {\r