4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** @file
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync C based implemention of IA32 interrupt handling only
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync requiring a minimal assembly interrupt entry point.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This program and the accompanying materials
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync are licensed and made available under the terms and conditions of the BSD License
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync which accompanies this distribution. The full text of the license may be found at
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync http://opensource.org/licenses/bsd-license.php
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include "CpuDxe.h"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync//
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync// Local structure definitions
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync//
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#pragma pack (1)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync//
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync// Global Descriptor Entry structures
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync//
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynctypedef struct _GDT_ENTRY {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT16 Limit15_0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT16 Base15_0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 Base23_16;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 Type;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 Limit19_16_and_flags;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 Base31_24;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync} GDT_ENTRY;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynctypedef
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncstruct _GDT_ENTRIES {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync GDT_ENTRY Null;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync GDT_ENTRY Linear;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync GDT_ENTRY LinearCode;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync GDT_ENTRY SysData;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync GDT_ENTRY SysCode;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync GDT_ENTRY LinearCode64;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync GDT_ENTRY Spare4;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync GDT_ENTRY Spare5;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync} GDT_ENTRIES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define NULL_SEL OFFSET_OF (GDT_ENTRIES, Null)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define LINEAR_SEL OFFSET_OF (GDT_ENTRIES, Linear)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define LINEAR_CODE_SEL OFFSET_OF (GDT_ENTRIES, LinearCode)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define SYS_DATA_SEL OFFSET_OF (GDT_ENTRIES, SysData)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define SYS_CODE_SEL OFFSET_OF (GDT_ENTRIES, SysCode)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define LINEAR_CODE64_SEL OFFSET_OF (GDT_ENTRIES, LinearCode64)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define SPARE4_SEL OFFSET_OF (GDT_ENTRIES, Spare4)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define SPARE5_SEL OFFSET_OF (GDT_ENTRIES, Spare5)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#if defined (MDE_CPU_IA32)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define CPU_CODE_SEL LINEAR_CODE_SEL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define CPU_DATA_SEL LINEAR_SEL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#elif defined (MDE_CPU_X64)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define CPU_CODE_SEL LINEAR_CODE64_SEL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#define CPU_DATA_SEL LINEAR_SEL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#else
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#error CPU type not supported for CPU GDT initialization!
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#endif
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync//
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync// Global descriptor table (GDT) Template
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync//
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncSTATIC GDT_ENTRIES GdtTemplate = {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // NULL_SEL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0, // limit 15:0
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0, // base 15:0
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0, // base 23:16
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0, // type
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0, // limit 19:16, flags
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0, // base 31:24
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync },
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // LINEAR_SEL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0FFFF, // limit 0xFFFFF
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0, // base 0
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x092, // present, ring 0, data, expand-up, writable
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0CF, // page-granular, 32-bit
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync },
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // LINEAR_CODE_SEL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0FFFF, // limit 0xFFFFF
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0, // base 0
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x09A, // present, ring 0, data, expand-up, writable
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0CF, // page-granular, 32-bit
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync },
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // SYS_DATA_SEL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0FFFF, // limit 0xFFFFF
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0, // base 0
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x092, // present, ring 0, data, expand-up, writable
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0CF, // page-granular, 32-bit
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync },
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // SYS_CODE_SEL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0FFFF, // limit 0xFFFFF
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0, // base 0
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x09A, // present, ring 0, data, expand-up, writable
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0CF, // page-granular, 32-bit
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync },
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // LINEAR_CODE64_SEL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0FFFF, // limit 0xFFFFF
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0, // base 0
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x09B, // present, ring 0, code, expand-up, writable
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0AF, // LimitHigh (CS.L=1, CS.D=0)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0, // base (high)
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync },
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // SPARE4_SEL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0, // limit 0
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0, // base 0
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0, // present, ring 0, data, expand-up, writable
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0, // page-granular, 32-bit
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync },
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // SPARE5_SEL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0, // limit 0
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0, // base 0
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0, // present, ring 0, data, expand-up, writable
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0, // page-granular, 32-bit
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 0x0,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync },
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync};
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Initialize Global Descriptor Table.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncInitGlobalDescriptorTable (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync GDT_ENTRIES *gdt;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IA32_DESCRIPTOR gdtPtr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Allocate Runtime Data for the GDT
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gdt = AllocateReservedPool (sizeof (GdtTemplate) + 8);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (gdt != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gdt = ALIGN_POINTER (gdt, 8);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Initialize all GDT entries
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (gdt, &GdtTemplate, sizeof (GdtTemplate));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Write GDT register
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gdtPtr.Base = (UINT32)(UINTN)(VOID*) gdt;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync gdtPtr.Limit = (UINT16) (sizeof (GdtTemplate) - 1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AsmWriteGdtr (&gdtPtr);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Update selector (segment) registers base on new GDT
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SetCodeSelector ((UINT16)CPU_CODE_SEL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SetDataSelectors ((UINT16)CPU_DATA_SEL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync