windows-nt/Source/XPSP1/NT/base/wow64/mscpu/cpumain/cpumain.c
2020-09-26 16:20:57 +08:00

382 lines
6.8 KiB
C

/*++
Copyright (c) 1995-2000 Microsoft Corporation
Module Name:
cpumain.c
Abstract:
This module implements the public interface to the CPU.
Author:
03-Jul-1995 BarryBo
Revision History:
--*/
#include <nt.h>
#include <ntrtl.h>
#include <nturtl.h>
#include <windows.h>
#include <stdio.h>
#define _WX86CPUAPI_
#include "wx86nt.h"
#include "wx86cpu.h"
#include "cpuassrt.h"
#include "config.h"
#include "instr.h"
#include "threadst.h"
#include "cpunotif.h"
#include "cpuregs.h"
#include "entrypt.h"
#include "compiler.h"
#include "instr.h"
#include "frag.h"
#include "entrypt.h"
#include "mrsw.h"
#include "tc.h"
#include "cpumain.h"
#include "wx86.h"
#include "atomic.h"
#ifdef CODEGEN_PROFILE
#include <coded.h>
#endif
#include "wow64t.h"
#include <wow64.h>
ASSERTNAME;
//
// Identify the CPU type for the debugger extensions
//
WX86_CPUTYPE Wx86CpuType = Wx86CpuCpu;
//
// Per-process CpuNotify bits. These are different than the per-thread
// bits.
//
DWORD ProcessCpuNotify;
NTSTATUS
MsCpuProcessInit(
VOID
)
/*++
Routine Description:
Initialize the CPU. Must be called once at process initialization.
Arguments:
None
Return Value:
None
--*/
{
#if 0
DbgBreakPoint();
#endif
//
// Read all configuration data from the registry
//
GetConfigurationData();
MrswInitializeObject(&MrswEP);
MrswInitializeObject(&MrswTC);
MrswInitializeObject(&MrswIndirTable);
if (!InitializeTranslationCache()) {
return STATUS_UNSUCCESSFUL;
}
if (!initEPAlloc()) {
#if DBG
LOGPRINT((TRACELOG, "CpuProcessInit: Entry Point allocator initialization failed"));
#endif
return STATUS_UNSUCCESSFUL;
}
if (!initializeEntryPointModule()) {
#if DBG
LOGPRINT((TRACELOG, "CpuProcessInit: Entry Point module initialization failed"));
#endif
return STATUS_UNSUCCESSFUL;
}
#if 0
if (!(Wx86LockSynchMutexHandle = CreateMutex(NULL, FALSE, "Wx86LockSynchMutex"))) {
#if DBG
LOGPRINT((TRACELOG, "CpuProcessInit: Cannot create Wx86LockSynchMutex"));
#endif
return STATUS_UNSUCCESSFUL;
}
#endif
RtlInitializeCriticalSection(&Wx86LockSynchCriticalSection);
SynchObjectType = USECRITICALSECTION;
#ifdef CODEGEN_PROFILE
InitCodegenProfile();
#endif
return STATUS_SUCCESS;
}
BOOL
MsCpuProcessTerm(
BOOL OFlyInit
)
{
#if 0
NtClose(Wx86LockSynchMutexHandle);
termEPAlloc();
#endif
return TRUE;
}
BOOL
MsCpuThreadInit(
VOID
)
/*++
Routine Description:
Initialize the CPU. Must be called once for each thread.
Arguments:
None.
Return Value:
TRUE if successful initialization, FALSE if init failed.
--*/
{
DWORD StackBase;
PTEB32 Teb32 = WOW64_GET_TEB32(NtCurrentTeb());
DECLARE_CPU;
if (!FragLibInit(cpu, Teb32->NtTib.StackBase)) {
return FALSE;
}
//
// Mark the callstack as valid
//
cpu->CSTimestamp = TranslationCacheTimestamp;
//
// Mark the TC as being unlocked
//
cpu->fTCUnlocked = TRUE;
//
// All done.
//
return TRUE;
}
VOID
CpuResetToConsistentState(
PEXCEPTION_POINTERS pExceptionPointers
)
/*++
Routine Description:
Called by WX86 when the exception filter around CpuSimulate() fires.
Arguments:
pExceptionPointers - state of the thread at the time the exception
occurred.
Return Value:
None
--*/
{
DECLARE_CPU;
if (!cpu->fTCUnlocked) {
//
// We must unlock the TC before continuing
//
MrswReaderExit(&MrswTC);
cpu->fTCUnlocked = TRUE;
//
// Call the compiler to deduce where Eip should be pointing
// based on the RISC exception record. It is called with
// the Entrypoint write lock because it calls the compiler.
// The compiler's global vars are usable only with EP write.
//
MrswWriterEnter(&MrswEP);
GetEipFromException(cpu, pExceptionPointers);
MrswWriterExit(&MrswEP);
}
Wow64TlsSetValue(WOW64_TLS_EXCEPTIONADDR, LongToPtr(cpu->eipReg.i4));
}
VOID
CpuPrepareToContinue(
PEXCEPTION_POINTERS pExceptionPointers
)
/*++
Routine Description:
Called by WX86 prior to resuming execution on EXCEPTION_CONTINUE_EXECUTION
Arguments:
pExceptionPointers - alpha context with which execution will be resumed.
Return Value:
None
--*/
{
}
BOOLEAN
CpuMapNotify(
PVOID DllBase,
BOOLEAN Mapped
)
/*++
Routine Description:
Called by WX86 when an x86 DLL is loaded or unloaded.
Arguments:
DllBase -- address where x86 DLL was loaded.
Mapped -- TRUE if x86 DLL was just mapped in, FALSE if DLL is just about
to be unmapped.
Return Value:
TRUE on success, FALSE on failure.
--*/
{
if (Mapped) {
NTSTATUS st;
MEMORY_BASIC_INFORMATION mbi;
ULONG Length;
st = NtQueryVirtualMemory(NtCurrentProcess(),
DllBase,
MemoryBasicInformation,
&mbi,
sizeof(mbi),
NULL);
if (NT_SUCCESS(st)) {
Length = (ULONG)mbi.RegionSize;
} else {
// Flush the whole translation cache
DllBase = 0;
Length = 0xffffffff;
}
CpuFlushInstructionCache(DllBase, Length);
}
return TRUE;
}
VOID
CpuEnterIdle(
BOOL OFly
)
/*++
Routine Description:
Called by WX86 when Wx86 ofly is going idle, or when Wx86 is out of
memory and needs some pages. The CPU must free as many resources
as possible.
Arguments:
OFly - TRUE if called from on-the-fly, FALSE if called due to
out of memory.
Return Value:
None.
--*/
{
CpuFlushInstructionCache(0, 0xffffffff);
}
BOOL
CpuIsProcessorFeaturePresent(
DWORD ProcessorFeature
)
/*++
Routine Description:
Called by whkrnl32!whIsProcessorFeaturePresent(). The CPU gets to
fill in its own feature set.
Arguments:
ProcessorFeature -- feature to query (see winnt.h PF_*)
Return Value:
TRUE if feature present, FALSE if not.
--*/
{
BOOL fRet;
switch (ProcessorFeature) {
case PF_FLOATING_POINT_PRECISION_ERRATA:
case PF_COMPARE_EXCHANGE_DOUBLE:
case PF_MMX_INSTRUCTIONS_AVAILABLE:
fRet = FALSE;
break;
case PF_FLOATING_POINT_EMULATED:
//
// TRUE when winpxem.dll used to emulate floating-point with x86
// integer instructions.
//
fRet = fUseNPXEM;
break;
default:
//
// Look up the native feature set
//
fRet = ProxyIsProcessorFeaturePresent(ProcessorFeature);
}
return fRet;
}