2015-10-19 21:12:53 +02:00
|
|
|
/** @file
|
|
|
|
SMM profile internal header file.
|
|
|
|
|
2018-06-08 10:41:07 +02:00
|
|
|
Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.<BR>
|
2015-10-19 21:12:53 +02:00
|
|
|
This program and the accompanying materials
|
|
|
|
are licensed and made available under the terms and conditions of the BSD License
|
|
|
|
which accompanies this distribution. The full text of the license may be found at
|
|
|
|
http://opensource.org/licenses/bsd-license.php
|
|
|
|
|
|
|
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
|
|
|
|
|
|
**/
|
|
|
|
|
|
|
|
#ifndef _SMM_PROFILE_INTERNAL_H_
|
|
|
|
#define _SMM_PROFILE_INTERNAL_H_
|
|
|
|
|
|
|
|
#include <Protocol/SmmReadyToLock.h>
|
|
|
|
#include <Library/UefiRuntimeServicesTableLib.h>
|
|
|
|
#include <Library/DxeServicesTableLib.h>
|
|
|
|
#include <Library/CpuLib.h>
|
|
|
|
#include <IndustryStandard/Acpi.h>
|
|
|
|
|
|
|
|
#include "SmmProfileArch.h"
|
|
|
|
|
|
|
|
//
|
|
|
|
// Configure the SMM_PROFILE DTS region size
|
|
|
|
//
|
|
|
|
#define SMM_PROFILE_DTS_SIZE (4 * 1024 * 1024) // 4M
|
|
|
|
|
|
|
|
#define MAX_PF_PAGE_COUNT 0x2
|
|
|
|
|
|
|
|
#define PEBS_RECORD_NUMBER 0x2
|
|
|
|
|
|
|
|
#define MAX_PF_ENTRY_COUNT 10
|
|
|
|
|
|
|
|
//
|
|
|
|
// This MACRO just enable unit test for the profile
|
|
|
|
// Please disable it.
|
|
|
|
//
|
|
|
|
|
|
|
|
#define IA32_PF_EC_ID (1u << 4)
|
|
|
|
|
|
|
|
#define SMM_PROFILE_NAME L"SmmProfileData"
|
|
|
|
|
|
|
|
//
|
|
|
|
// CPU generic definition
|
|
|
|
//
|
|
|
|
#define CPUID1_EDX_XD_SUPPORT 0x100000
|
|
|
|
#define MSR_EFER 0xc0000080
|
|
|
|
#define MSR_EFER_XD 0x800
|
|
|
|
|
|
|
|
#define CPUID1_EDX_BTS_AVAILABLE 0x200000
|
|
|
|
|
|
|
|
#define DR6_SINGLE_STEP 0x4000
|
|
|
|
#define RFLAG_TF 0x100
|
|
|
|
|
|
|
|
#define MSR_DEBUG_CTL 0x1D9
|
|
|
|
#define MSR_DEBUG_CTL_LBR 0x1
|
|
|
|
#define MSR_DEBUG_CTL_TR 0x40
|
|
|
|
#define MSR_DEBUG_CTL_BTS 0x80
|
|
|
|
#define MSR_DEBUG_CTL_BTINT 0x100
|
|
|
|
#define MSR_DS_AREA 0x600
|
|
|
|
|
2018-08-20 05:35:58 +02:00
|
|
|
#define HEAP_GUARD_NONSTOP_MODE \
|
|
|
|
((PcdGet8 (PcdHeapGuardPropertyMask) & (BIT6|BIT3|BIT2)) > BIT6)
|
|
|
|
|
|
|
|
#define NULL_DETECTION_NONSTOP_MODE \
|
|
|
|
((PcdGet8 (PcdNullPointerDetectionPropertyMask) & (BIT6|BIT1)) > BIT6)
|
|
|
|
|
2015-10-19 21:12:53 +02:00
|
|
|
typedef struct {
|
|
|
|
EFI_PHYSICAL_ADDRESS Base;
|
|
|
|
EFI_PHYSICAL_ADDRESS Top;
|
|
|
|
} MEMORY_RANGE;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
MEMORY_RANGE Range;
|
|
|
|
BOOLEAN Present;
|
|
|
|
BOOLEAN Nx;
|
|
|
|
} MEMORY_PROTECTION_RANGE;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
UINT64 HeaderSize;
|
|
|
|
UINT64 MaxDataEntries;
|
|
|
|
UINT64 MaxDataSize;
|
|
|
|
UINT64 CurDataEntries;
|
|
|
|
UINT64 CurDataSize;
|
|
|
|
UINT64 TsegStart;
|
|
|
|
UINT64 TsegSize;
|
|
|
|
UINT64 NumSmis;
|
|
|
|
UINT64 NumCpus;
|
|
|
|
} SMM_PROFILE_HEADER;
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
UINT64 SmiNum;
|
|
|
|
UINT64 CpuNum;
|
|
|
|
UINT64 ApicId;
|
|
|
|
UINT64 ErrorCode;
|
|
|
|
UINT64 Instruction;
|
|
|
|
UINT64 Address;
|
|
|
|
UINT64 SmiCmd;
|
|
|
|
} SMM_PROFILE_ENTRY;
|
|
|
|
|
|
|
|
extern SMM_S3_RESUME_STATE *mSmmS3ResumeState;
|
|
|
|
extern UINTN gSmiExceptionHandlers[];
|
|
|
|
extern BOOLEAN mXdSupported;
|
UefiCpuPkg/PiSmmCpuDxeSmm: patch "XdSupported" with PatchInstructionX86()
"mXdSupported" is a global BOOLEAN variable, initialized to TRUE. The
CheckFeatureSupported() function is executed on all processors (not
concurrently though), called from SmmInitHandler(). If XD support is found
to be missing on any CPU, then "mXdSupported" is set to FALSE, and further
processors omit the check. Afterwards, "mXdSupported" is read by several
assembly and C code locations.
The tricky part is *where* "mXdSupported" is allocated (defined):
- Before commit 717fb60443fb ("UefiCpuPkg/PiSmmCpuDxeSmm: Add paging
protection.", 2016-11-17), it used to be a normal global variable,
defined (allocated) in "SmmProfile.c".
- With said commit, we moved the definition (allocation) of "mXdSupported"
into "SmiEntry.nasm". The variable was defined over the last byte of a
"mov al, 1" instruction, so that setting it to FALSE in
CheckFeatureSupported() would patch the instruction to "mov al, 0". The
subsequent conditional jump would change behavior, plus all further read
references to "mXdSupported" (in C and assembly code) would read back
the source (imm8) operand of the patched MOV instruction as data.
This trick required that the MOV instruction be encoded with DB.
In order to get rid of the DB, we have to split both roles: we need a
label for the code patching, and "mXdSupported" has to be defined
(allocated) independently of the code patching. Of course, their values
must always remain in sync.
(1) Reinstate the "mXdSupported" definition and initialization in
"SmmProfile.c" from before commit 717fb60443fb. Change the assembly
language definition ("global") to a declaration ("extern").
(2) Define the "gPatchXdSupported" label (type X86_ASSEMBLY_PATCH_LABEL)
in "SmiEntry.nasm", and add the C-language declaration to
"SmmProfileInternal.h". Replace the DB with the MOV mnemonic (keeping
the imm8 source operand with value 1).
(3) In CheckFeatureSupported(), whenever "mXdSupported" is set to FALSE,
patch the assembly code in sync, with PatchInstructionX86().
Cc: Eric Dong <eric.dong@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=866
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>
2018-02-02 00:17:13 +01:00
|
|
|
X86_ASSEMBLY_PATCH_LABEL gPatchXdSupported;
|
2015-10-19 21:12:53 +02:00
|
|
|
extern UINTN *mPFEntryCount;
|
|
|
|
extern UINT64 (*mLastPFEntryValue)[MAX_PF_ENTRY_COUNT];
|
|
|
|
extern UINT64 *(*mLastPFEntryPointer)[MAX_PF_ENTRY_COUNT];
|
|
|
|
|
|
|
|
//
|
|
|
|
// Internal functions
|
|
|
|
//
|
|
|
|
|
|
|
|
/**
|
|
|
|
Update IDT table to replace page fault handler and INT 1 handler.
|
|
|
|
|
|
|
|
**/
|
|
|
|
VOID
|
|
|
|
InitIdtr (
|
|
|
|
VOID
|
|
|
|
);
|
|
|
|
|
|
|
|
/**
|
|
|
|
Check if the memory address will be mapped by 4KB-page.
|
|
|
|
|
|
|
|
@param Address The address of Memory.
|
|
|
|
|
|
|
|
**/
|
|
|
|
BOOLEAN
|
|
|
|
IsAddressSplit (
|
|
|
|
IN EFI_PHYSICAL_ADDRESS Address
|
|
|
|
);
|
|
|
|
|
|
|
|
/**
|
|
|
|
Check if the memory address will be mapped by 4KB-page.
|
|
|
|
|
|
|
|
@param Address The address of Memory.
|
|
|
|
@param Nx The flag indicates if the memory is execute-disable.
|
|
|
|
|
|
|
|
**/
|
|
|
|
BOOLEAN
|
|
|
|
IsAddressValid (
|
|
|
|
IN EFI_PHYSICAL_ADDRESS Address,
|
|
|
|
IN BOOLEAN *Nx
|
|
|
|
);
|
|
|
|
|
|
|
|
/**
|
|
|
|
Page Fault handler for SMM use.
|
|
|
|
|
|
|
|
**/
|
|
|
|
VOID
|
|
|
|
SmiDefaultPFHandler (
|
|
|
|
VOID
|
|
|
|
);
|
|
|
|
|
|
|
|
/**
|
|
|
|
Clear TF in FLAGS.
|
|
|
|
|
|
|
|
@param SystemContext A pointer to the processor context when
|
|
|
|
the interrupt occurred on the processor.
|
|
|
|
|
|
|
|
**/
|
|
|
|
VOID
|
|
|
|
ClearTrapFlag (
|
|
|
|
IN OUT EFI_SYSTEM_CONTEXT SystemContext
|
|
|
|
);
|
|
|
|
|
|
|
|
#endif // _SMM_PROFILE_H_
|