summaryrefslogtreecommitdiffstats
path: root/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/CpuGdt.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/CpuGdt.c')
-rw-r--r--src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/CpuGdt.c183
1 files changed, 183 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/CpuGdt.c b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/CpuGdt.c
new file mode 100644
index 00000000..8fed6209
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/UefiCpuPkg/CpuDxe/CpuGdt.c
@@ -0,0 +1,183 @@
+/** @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
+ )
+{
+#ifndef VBOX
+ EFI_STATUS Status;
+#endif
+ GDT_ENTRIES *Gdt;
+ IA32_DESCRIPTOR Gdtr;
+#ifndef VBOX
+ EFI_PHYSICAL_ADDRESS Memory;
+#endif
+
+ //
+ // 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.
+ //
+#ifndef VBOX
+ 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;
+#else
+ /*
+ * Apples bootloader boot.efi for at least OS X Tiger, Leopard and Snow Leopard
+ * relocates runtime regions which doesn't make sense for the GDT as the GDTR is not
+ * updated and would point to invalid memory. Allocate the memory as reserved to hopefully
+ * keep the bootloaders hands off of it, see also OvmfPkg/PlatformPei/Platform.c
+ * (search for PeiServicesAllocatePages()) for a more detailed explanation of a
+ * related bug in Apples bootloader.
+ */
+ Gdt = AllocateReservedPool (sizeof (mGdtTemplate) + 8);
+ ASSERT (Gdt != NULL);
+ Gdt = ALIGN_POINTER (Gdt, 8);
+#endif
+
+ //
+ // 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);
+}