/** @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); | |
} |