singrdk/base/Kernel/Native/hal.cpp

357 lines
9.8 KiB
C++

////////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: Hal.cpp
//
// Note:
//
#include "hal.h"
#if SINGULARITY_KERNEL
#include "halkd.h"
#include "printf.cpp"
#endif // SINGULARITY_KERNEL
//////////////////////////////////////////////////////////////////////////////
extern "C" int _fltused = 0x9875;
//////////////////////////////////////////////////////////////////////////////
// debugging code. Put it here for now.
#if SINGULARITY_KERNEL
void Halt()
{
uintptr _ebp;
__asm mov _ebp, ebp;
for (int i = 0; i < 30 && _ebp >= 0x4000; i++) {
uintptr next = ((uintptr *)_ebp)[0];
uintptr code = ((uintptr *)_ebp)[1];
printf(" %p: %p %p\n", _ebp, next, code);
_ebp = next;
}
printf("---- Halting. --------------------------------------------------------");
__asm int 3;
}
void Cls()
{
KdPutChar('\n');
for (uint16 n = 0; n < 79; n++) {
KdPutChar('-');
}
KdPutChar('\n');
}
void __cdecl PutChar(char cOut)
{
KdPutChar(cOut);
}
void fail_assert(const char *expr)
{
printf("%s\n", expr);
printf("----- Frame --- EBP ---- Code ----------------------------- Assert Failure\n");
Halt();
__asm int 3;
}
#elif SINGULARITY_PROCESS
void fail_assert(Class_System_String *message)
{
Struct_Microsoft_Singularity_V1_Services_DebugService::g_Print((bartok_char*)&message->m_firstChar,
message->m_stringLength);
//Struct_Microsoft_Singularity_V1_Services_DebugService::g_Break();
Class_Microsoft_Singularity_DebugStub::g_Break();
}
#endif // SINGULARITY_KERNEL
//////////////////////////////////////////////////////////////////////////////
//
extern "C" int __cdecl _cinit(void);
extern "C" int __cdecl _cfini(void);
#if SINGULARITY_KERNEL
void Class_Microsoft_Singularity_Kernel::g_Kill(int32 action)
{
((Struct_Microsoft_Singularity_BootInfo *)g_pBootInfo)->KillAction = action;
void (__cdecl *pfKill)(void) = (void (__cdecl *)(void))g_pBootInfo->Kill32;
printf("About to call pfKill(%p) with %08x [g_pBootInfo=%p]\n",
pfKill, g_pBootInfo->KillAction, g_pBootInfo);
pfKill();
Halt();
}
extern wchar_t _LinkDate[];
bartok_char *
Class_Microsoft_Singularity_Kernel::g_HalGetLinkDate()
{
return (bartok_char *)_LinkDate;
}
// Hoisted this out of checkHinges because VC appears to have changed its name
// mangling strategy for structs in functions.
struct CheckedHingeEntry { uint32 i; char *a; char *b; };
void checkHinges()
{
// Check for a broken image produce when Bartok compiles through an assembler.
int busted = false;
extern CheckedHingeEntry checkedHingeTable[];
for (CheckedHingeEntry *che = checkedHingeTable; che->a; che++) {
if (che->a+1 != che->b) {
printf("%06d: 0x%08x 0x%08x\n", che->i, che->a+1, che->b);
busted = true;
}
}
if (busted) {
printf("----- Frame --- EBP ---- Code ------------------------------ Busted Hinges\n");
Halt();
}
}
extern "C" static void __cdecl
HalBspEnter(Struct_Microsoft_Singularity_BootInfo *bi)
{
g_pBootInfo = bi;
kdprintf("Singularity HAL [%ls]\n", _LinkDate);
_cinit();
kdprintf("DebugPort: %04x\n", bi->DebugBasePort);
KdInitialize(bi);
Cls();
printf("Singularity Hardware Abstraction Layer [%ls]\n", _LinkDate);
printf("\n");
IdtInitialize();
IdtLoad();
ProcessorInitialize(&bi->Cpu0, 0);
checkHinges();
Class_Microsoft_Singularity_Tracing::g_Initialize();
Class_Microsoft_Singularity_Tracing::g_Log(0);
Class_Microsoft_Singularity_Tracing::g_Log(1);
Class_Microsoft_Singularity_Tracing::g_Log(2);
Class_Microsoft_Singularity_Tracing::g_Log(3);
printf("----------------------------------------------------------------------\n");
printf("Calling Kernel.Main:\n");
Class_Microsoft_Singularity_Kernel::g_Main();
// We should not rely on or use any C++ finalizers.
// _cfini();
}
extern "C" static void __cdecl
HalApEnter(const Struct_Microsoft_Singularity_BootInfo *bi, int cpu)
{
IdtLoad();
const Struct_Microsoft_Singularity_CpuInfo *cpuInfo = &bi->Cpu0 + cpu;
ProcessorInitialize(cpuInfo, cpu);
Class_Microsoft_Singularity_Kernel::g_MpMain(cpu);
Class_Microsoft_Singularity_Processor::g_DisableInterrupts();
for (int i = 0; i != i + 1; i++) {
uint16* p = (uint16*)(0xb8000 + (cpu - 1) * 2 * 8);
for (int r = 0; r < 8; r++) {
uint16 t = (uint16)(i >> (28 - r * 4));
t &= 0xf;
if (t > 9) {
t += 0x1f00 + 'a' - 10;
}
else {
t += 0x1f00 + '0';
}
*p++ = t;
if (Class_Microsoft_Singularity_DebugStub::g_PollForBreak() == true) {
__asm int 3;
}
for (int i = 0; i < 50000; i++) {
__asm nop;
}
}
}
}
extern "C" void __cdecl
Hal(Struct_Microsoft_Singularity_BootInfo *bi, int cpu)
{
if (cpu == 0) {
HalBspEnter(bi);
}
else {
HalApEnter(bi, cpu);
}
}
#elif SINGULARITY_PROCESS
BOOL KdDebuggerNotPresent;
extern Class_System_RuntimeType * brtmainClass;
extern int (*brtmain)(ClassVector_Class_System_String *args);
extern int brtmainReturnsInt;
// Note: CallMain's return value is only meaningful if brtmainReturnsInt is true.
// Example:
// int ret = CallMain(args);
// if (!MainReturnsInt()) ret = 0;
__declspec(naked) int Class_Microsoft_Singularity_AppRuntime::
g_CallMain(ClassVector_Class_System_String *args)
{
// To avoid creating an unmanaged stack frame, jmp directly to the main function:
__asm {
mov eax, brtmain;
jmp eax;
}
}
bool Class_Microsoft_Singularity_AppRuntime::
g_MainReturnsInt()
{
return (brtmainReturnsInt != 0);
}
void Class_Microsoft_Singularity_AppRuntime::
g_SetDebuggerPresence(bool debuggerPresent)
{
KdDebuggerNotPresent = !debuggerPresent;
}
extern "C" int32 __fastcall RuntimeEntryPoint(int threadIndex)
{
int32 ret = 0;
Struct_Microsoft_Singularity_X86_ThreadContext * context =
Class_Microsoft_Singularity_Processor::g_GetCurrentThreadContext();
if (!Struct_Microsoft_Singularity_X86_ThreadContext::m_IsInKernelMode(
context)) {
// fail assertion in uninitialized process mode:
__asm int 3
}
Struct_Microsoft_Singularity_X86_ThreadContext::m_SetProcessMode(context);
if (threadIndex == -1) {
_cinit();
Class_Microsoft_Singularity_Tracing::g_Initialize();
Class_Microsoft_Singularity_Tracing::g_Log(0, "RuntimeEntryPoint:Main");
Class_Microsoft_Singularity_Monitoring::g_Initialize();
ret = Class_Microsoft_Singularity_AppRuntime::g_AppStart(brtmainClass);
}
else {
Class_Microsoft_Singularity_Tracing::g_Log(0, "RuntimeEntryPoint:Thread");
Class_System_Threading_Thread::g_ThreadStub(threadIndex);
}
Struct_Microsoft_Singularity_X86_ThreadContext::m_SetKernelMode(context);
return ret;
}
#endif // SINGULARITY_PROCESS
//////////////////////////////////////////////////////////////////////////////
// Need to put the following marker variables into the .CRT section.
// The .CRT section contains arrays of function pointers.
// The compiler creates functions and adds pointers to this section
// for things like C++ global constructors.
//
// The XIA, XCA etc are group names with in the section.
// The compiler sorts the contributions by the group name.
// For example, .CRT$XCA followed by .CRT$XCB, ... .CRT$XCZ.
// The marker variables below let us get pointers
// to the beginning/end of the arrays of function pointers.
//
// For example, standard groups are
// XCA used here, for begin marker
// XCC "compiler" inits
// XCL "library" inits
// XCU "user" inits
// XCZ used here, for end marker
//
typedef void (__cdecl *_PVFV)(void);
// typedef int (__cdecl *_PIFV)(void);
typedef _PVFV _PIFV;
#pragma comment(linker, "/merge:.CRT=.DATA")
#pragma data_seg(".CRT$XIA", "DATA")
extern "C" _PIFV __xi_a[] = { NULL }; // C initializers.
#pragma data_seg(".CRT$XIZ", "DATA")
extern "C" _PIFV __xi_z[] = { NULL };
#pragma data_seg(".CRT$XCA", "DATA")
extern "C" _PVFV __xc_a[] = { NULL }; // C++ initializers.
#pragma data_seg(".CRT$XCZ", "DATA")
extern "C" _PVFV __xc_z[] = { NULL };
#pragma data_seg(".CRT$XPA", "DATA")
extern "C" _PVFV __xp_a[] = { NULL }; // C pre-terminators.
#pragma data_seg(".CRT$XPZ", "DATA")
extern "C" _PVFV __xp_z[] = { NULL };
#pragma data_seg(".CRT$XTA", "DATA")
extern "C" _PVFV __xt_a[] = { NULL }; // C terminators.
#pragma data_seg(".CRT$XTZ", "DATA")
extern "C" _PVFV __xt_z[] = { NULL };
#pragma data_seg()
// Walk an array of function pointers, call non-NULL ones.
void __cdecl _initterm(_PVFV *pfbegin, _PVFV *pfend)
{
for (; pfbegin < pfend; pfbegin++) {
if (*pfbegin != NULL) {
(**pfbegin)();
}
}
}
// Call all of the C++ static constructors.
//
int __cdecl _cinit(void)
{
// do C initializations
_initterm( __xi_a, __xi_z );
// do C++ initializations
_initterm( __xc_a, __xc_z );
return 0;
}
int __cdecl _cfini(void)
{
// do C initializations
_initterm( __xp_a, __xp_z );
// do C++ terminations
_initterm( __xt_a, __xt_z );
return 0;
}