| /** @file | |
| C based implementation of IA32 interrupt handling only | |
| requiring a minimal assembly interrupt entry point. | |
| Copyright (c) 2006 - 2021, Intel Corporation. All rights reserved.<BR> | |
| SPDX-License-Identifier: BSD-2-Clause-Patent | |
| **/ | |
| #include "CpuDxe.h" | |
| #include "CpuGdt.h" | |
| // | |
| // Global descriptor table (GDT) Template | |
| // | |
| STATIC GDT_ENTRIES mGdtTemplate = { | |
| // | |
| // NULL_SEL | |
| // | |
| { | |
| 0x0, // limit 15:0 | |
| 0x0, // base 15:0 | |
| 0x0, // base 23:16 | |
| 0x0, // type | |
| 0x0, // limit 19:16, flags | |
| 0x0, // base 31:24 | |
| }, | |
| // | |
| // LINEAR_SEL | |
| // | |
| { | |
| 0x0FFFF, // limit 15:0 | |
| 0x0, // base 15:0 | |
| 0x0, // base 23:16 | |
| 0x092, // present, ring 0, data, read/write | |
| 0x0CF, // page-granular, 32-bit | |
| 0x0, | |
| }, | |
| // | |
| // LINEAR_CODE_SEL | |
| // | |
| { | |
| 0x0FFFF, // limit 15:0 | |
| 0x0, // base 15:0 | |
| 0x0, // base 23:16 | |
| 0x09F, // present, ring 0, code, execute/read, conforming, accessed | |
| 0x0CF, // page-granular, 32-bit | |
| 0x0, | |
| }, | |
| // | |
| // SYS_DATA_SEL | |
| // | |
| { | |
| 0x0FFFF, // limit 15:0 | |
| 0x0, // base 15:0 | |
| 0x0, // base 23:16 | |
| 0x093, // present, ring 0, data, read/write, accessed | |
| 0x0CF, // page-granular, 32-bit | |
| 0x0, | |
| }, | |
| // | |
| // SYS_CODE_SEL | |
| // | |
| { | |
| 0x0FFFF, // limit 15:0 | |
| 0x0, // base 15:0 | |
| 0x0, // base 23:16 | |
| 0x09A, // present, ring 0, code, execute/read | |
| 0x0CF, // page-granular, 32-bit | |
| 0x0, | |
| }, | |
| // | |
| // SYS_CODE16_SEL | |
| // | |
| { | |
| 0x0FFFF, // limit 15:0 | |
| 0x0, // base 15:0 | |
| 0x0, // base 23:16 | |
| 0x09A, // present, ring 0, code, execute/read | |
| 0x08F, // page-granular, 16-bit | |
| 0x0, // base 31:24 | |
| }, | |
| // | |
| // LINEAR_DATA64_SEL | |
| // | |
| { | |
| 0x0FFFF, // limit 15:0 | |
| 0x0, // base 15:0 | |
| 0x0, // base 23:16 | |
| 0x092, // present, ring 0, data, read/write | |
| 0x0CF, // page-granular, 32-bit | |
| 0x0, | |
| }, | |
| // | |
| // LINEAR_CODE64_SEL | |
| // | |
| { | |
| 0x0FFFF, // limit 15:0 | |
| 0x0, // base 15:0 | |
| 0x0, // base 23:16 | |
| 0x09A, // present, ring 0, code, execute/read | |
| 0x0AF, // page-granular, 64-bit code | |
| 0x0, // base (high) | |
| }, | |
| // | |
| // SPARE5_SEL | |
| // | |
| { | |
| 0x0, // limit 15:0 | |
| 0x0, // base 15:0 | |
| 0x0, // base 23:16 | |
| 0x0, // type | |
| 0x0, // limit 19:16, flags | |
| 0x0, // base 31:24 | |
| }, | |
| }; | |
| /** | |
| Initialize Global Descriptor Table. | |
| **/ | |
| VOID | |
| InitGlobalDescriptorTable ( | |
| VOID | |
| ) | |
| { | |
| EFI_STATUS Status; | |
| GDT_ENTRIES *Gdt; | |
| IA32_DESCRIPTOR Gdtr; | |
| EFI_PHYSICAL_ADDRESS Memory; | |
| // | |
| // Allocate Runtime Data below 4GB for the GDT | |
| // AP uses the same GDT when it's waken up from real mode so | |
| // the GDT needs to be below 4GB. | |
| // | |
| Memory = SIZE_4GB - 1; | |
| Status = gBS->AllocatePages ( | |
| AllocateMaxAddress, | |
| EfiRuntimeServicesData, | |
| EFI_SIZE_TO_PAGES (sizeof (mGdtTemplate)), | |
| &Memory | |
| ); | |
| ASSERT_EFI_ERROR (Status); | |
| ASSERT ((Memory != 0) && (Memory < SIZE_4GB)); | |
| Gdt = (GDT_ENTRIES *)(UINTN)Memory; | |
| // | |
| // Initialize all GDT entries | |
| // | |
| CopyMem (Gdt, &mGdtTemplate, sizeof (mGdtTemplate)); | |
| // | |
| // Write GDT register | |
| // | |
| Gdtr.Base = (UINT32)(UINTN)Gdt; | |
| Gdtr.Limit = (UINT16)(sizeof (mGdtTemplate) - 1); | |
| AsmWriteGdtr (&Gdtr); | |
| // | |
| // Update selector (segment) registers base on new GDT | |
| // | |
| SetCodeSelector ((UINT16)CPU_CODE_SEL); | |
| SetDataSelectors ((UINT16)CPU_DATA_SEL); | |
| } |