mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-31 01:24:12 +02:00
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3233 GDT needs to be allocated below 4GB in 64bit environment because AP needs it for entering to protected mode. CPU running in big real mode cannot access above 4GB GDT. But CpuDxe driver contains below code: gdt = AllocateRuntimePool (sizeof (GdtTemplate) + 8); ..... gdtPtr.Base = (UINT32)(UINTN)(VOID*) gdt; The AllocateRuntimePool() may allocate memory above 4GB. Thus, we cannot use AllocateRuntimePool (), instead, we should use AllocatePages() to make sure GDT is below 4GB space. Signed-off-by: Ray Ni <ray.ni@intel.com> Reviewed-by: Eric Dong <eric.dong@intel.com> Reviewed-by: Laszlo Ersek <lersek@redhat.com> Cc: Rahul Kumar <rahul1.kumar@intel.com>
166 lines
3.9 KiB
C
166 lines
3.9 KiB
C
/** @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);
|
|
}
|