singrdk/base/Kernel/Native/ix64/halkdx.cpp

361 lines
13 KiB
C++
Raw Normal View History

2008-11-17 18:29:00 -05:00
///////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// File: halkdx64.cpp - Processor-specific support routines for halkd.cpp.
//
#include "hal.h"
#include "halkd.h"
#define KDDBG if (0) kdprintf
extern "C" void * __cdecl memcpy(void *, const void *, size_t);
void KdpX64GetSegmentRegisters(OUT CONTEXT * windbg);
UINT64 KdpX64ReadMsr(UINT32 msr);
void KdpX64WriteMsr(UINT32 msr, UINT64 value);
void KdpX64SetControlReport(IN OUT PDBGKD_CONTROL_REPORT report);
void KdpX64SetControlSet(IN CONST DBGKD_CONTROL_SET *report);
void KdpX64ReadSpecialRegisters(IN OUT KSPECIAL_REGISTERS *pksp);
void KdpX64WriteSpecialRegisters(IN CONST KSPECIAL_REGISTERS *pksp);
//////////////////////////////////////////////// User visible progress beacon.
//
static UINT16 KdpSpinBase = 0x2f00;
void KdpSpin()
{
if (KdpSpinBase != 0) {
static UINT8 state = 0;
// Write the spinner to the screen.
*((UINT16 *)0xb809e) = KdpSpinBase + ("+-|*" [state++ & 0x3]);
}
}
///////////////////////////////////////// Debugger Unique Interrupts Routines.
//
// Read a machine specific register (MSR on x86 & x64).
bool KdpReadMsr(UINT32 msr, UINT32 *plo, UINT32 *phi)
{
UINT64 value = KdpX64ReadMsr(msr);
*phi = (UINT32)(value >> 32);
*plo = (UINT32)(value >> 0);
return true;
}
// Write a machine specific register (MSR on x86 & x64).
bool KdpWriteMsr(UINT32 msr, UINT32 lo, UINT32 hi)
{
UINT64 value = (((UINT64)hi) << 32) | (((UINT64)lo) << 0);
KdpX64WriteMsr(msr, value);
return true;
}
//////////////////////////////////////////////////////////////////////////////
void KdpToKdContext(IN CONST Struct_Microsoft_Singularity_Isal_SpillContext *singularity,
OUT CONTEXT *windbg)
{
windbg->ContextFlags = (CONTEXT_CONTROL |
CONTEXT_INTEGER |
CONTEXT_SEGMENTS |
CONTEXT_FLOATING_POINT);
// CONTEXT_FULL;
windbg->Rax = singularity->ax;
windbg->Rbx = singularity->bx;
windbg->Rcx = singularity->cx;
windbg->Rdx = singularity->dx;
windbg->Rsp = singularity->sp;
windbg->Rbp = singularity->bp;
windbg->Rsi = singularity->si;
windbg->Rdi = singularity->di;
windbg->Rip = singularity->ip;
windbg->R8 = singularity->r8;
windbg->R9 = singularity->r9;
windbg->R10 = singularity->r10;
windbg->R11 = singularity->r11;
windbg->R12 = singularity->r12;
windbg->R13 = singularity->r13;
windbg->R14 = singularity->r14;
windbg->R15 = singularity->r15;
windbg->EFlags = (uint32)singularity->fl;
windbg->FltSave.ControlWord = singularity->mmx.fcw;
windbg->FltSave.StatusWord = singularity->mmx.fsw;
windbg->FltSave.TagWord = singularity->mmx.ftw;
windbg->FltSave.ErrorAddress = singularity->mmx.ip;
windbg->FltSave.DataAddress = singularity->mmx.dp;
memcpy(&windbg->FltSave.St0, &singularity->mmx.st0, 16);
memcpy(&windbg->FltSave.St1, &singularity->mmx.st1, 16);
memcpy(&windbg->FltSave.St2, &singularity->mmx.st2, 16);
memcpy(&windbg->FltSave.St3, &singularity->mmx.st3, 16);
memcpy(&windbg->FltSave.St4, &singularity->mmx.st4, 16);
memcpy(&windbg->FltSave.St5, &singularity->mmx.st5, 16);
memcpy(&windbg->FltSave.St6, &singularity->mmx.st6, 16);
memcpy(&windbg->FltSave.St7, &singularity->mmx.st7, 16);
KdpX64GetSegmentRegisters(windbg);
//
// This section is specified/returned if the
// ContextFlags word contains the flag CONTEXT_CONTROL.
//
windbg->SegCs = (uint16)singularity->cs;
}
void KdpFromKdContext(IN CONST CONTEXT *windbg,
OUT Struct_Microsoft_Singularity_Isal_SpillContext *singularity)
{
singularity->ax = windbg->Rax;
singularity->bx = windbg->Rbx;
singularity->cx = windbg->Rcx;
singularity->dx = windbg->Rdx;
singularity->sp = windbg->Rsp;
singularity->bp = windbg->Rbp;
singularity->si = windbg->Rsi;
singularity->di = windbg->Rdi;
singularity->ip = windbg->Rip;
singularity->r8 = windbg->R8;
singularity->r9 = windbg->R9;
singularity->r10 = windbg->R10;
singularity->r11 = windbg->R11;
singularity->r12 = windbg->R12;
singularity->r13 = windbg->R13;
singularity->r14 = windbg->R14;
singularity->r15 = windbg->R15;
singularity->fl = windbg->EFlags;
// CONTEXT_FLOATING_POINT
if (windbg->ContextFlags & CONTEXT_FLOATING_POINT) {
singularity->mmx.fcw = windbg->FltSave.ControlWord;
singularity->mmx.fsw = windbg->FltSave.StatusWord;
singularity->mmx.ftw = windbg->FltSave.TagWord;
singularity->mmx.ip = windbg->FltSave.ErrorAddress;
singularity->mmx.dp = windbg->FltSave.DataAddress;
memcpy(&singularity->mmx.st0, &windbg->FltSave.St0, 16);
memcpy(&singularity->mmx.st1, &windbg->FltSave.St1, 16);
memcpy(&singularity->mmx.st2, &windbg->FltSave.St2, 16);
memcpy(&singularity->mmx.st3, &windbg->FltSave.St3, 16);
memcpy(&singularity->mmx.st4, &windbg->FltSave.St4, 16);
memcpy(&singularity->mmx.st5, &windbg->FltSave.St5, 16);
memcpy(&singularity->mmx.st6, &windbg->FltSave.St6, 16);
memcpy(&singularity->mmx.st7, &windbg->FltSave.St7, 16);
}
}
void KdpSetControlReport(IN OUT PDBGKD_CONTROL_REPORT report,
IN CONST Struct_Microsoft_Singularity_Isal_SpillContext *x86Context)
// Routine Description:
// Fill in the DBGKD_CONTROL_REPORT record.
//
// Arguments:
// WaitStateChange - Supplies pointer to record to fill in
// x86Context - Supplies a pointer to a context record.
{
KdpX64SetControlReport(report);
// report->EFlags = (uint32)x86Context->efl;
report->ReportFlags = X86_REPORT_INCLUDES_SEGS;
#if !PAGING
// Let the debugger know so that it doesn't have to retrieve the CS descriptor.
report->ReportFlags |= X86_REPORT_STANDARD_CS;
#endif
}
void KdpSetControlSet(IN CONST DBGKD_CONTROL_SET * control,
IN OUT Struct_Microsoft_Singularity_Isal_SpillContext *x86Context)
{
if (control->TraceFlag) {
//KDDBG("KD: Warning - trace flag set prev efl=%x\n",x86Context->efl);
x86Context->fl |= Struct_Microsoft_Singularity_Isal_IX_EFlags_TF;
}
else {
//KDDBG("KD: turning off tracing in efl\n");
x86Context->fl &= ~Struct_Microsoft_Singularity_Isal_IX_EFlags_TF;
}
KdpX64SetControlSet(control);
}
//////////////////////////////////////////////////////////////////////////////
void KdpReadSpecialRegisters(KSPECIAL_REGISTERS *pksp,
IN CONST Struct_Microsoft_Singularity_Isal_SpillContext *x86Context)
{
KdpX64ReadSpecialRegisters(pksp);
}
void KdpWriteSpecialRegisters(CONST KSPECIAL_REGISTERS *pksp)
{
KdpX64WriteSpecialRegisters(pksp);
}
//////////////////////////////////////////////////////////////////////////////
KdDebugTrapData * KdpIsDebugTrap(IN CONST Struct_Microsoft_Singularity_Isal_SpillContext *context,
int id)
{
if (id == Struct_Microsoft_Singularity_Isal_IX_EVectors_FirstChanceException) {
return (KdDebugTrapData *)(context->ax);
}
return NULL;
}
// Convert a trap into a exception record.
void KdpConvertTrapToException(IN OUT EXCEPTION_RECORD64 *per,
IN OUT Struct_Microsoft_Singularity_Isal_SpillContext *context,
int id)
{
// Breakpoints:
switch (id) {
case Struct_Microsoft_Singularity_Isal_IX_EVectors_SingleStep:
KDDBG("SingleStep\n");
per->ExceptionCode = STATUS_SINGLE_STEP;
per->ExceptionAddress = (UINT64)context->ip;
// context->efl &= ~Struct_Microsoft_Singularity_Isal_IX_EFlags_TF;
break;
case Struct_Microsoft_Singularity_Isal_IX_EVectors_Breakpoint:
KDDBG("Breakpoint\n");
context->ip -= 1;
per->ExceptionCode = STATUS_BREAKPOINT;
per->NumberParameters = 1;
per->ExceptionInformation0 = BREAKPOINT_BREAK;
per->ExceptionAddress = (UINT64)context->ip;
break;
case Struct_Microsoft_Singularity_Isal_IX_EVectors_IllegalInstruction:
KDDBG("Illegal Instruction\n");
per->ExceptionCode = STATUS_ILLEGAL_INSTRUCTION;
break;
case Struct_Microsoft_Singularity_Isal_IX_EVectors_PageFault:
KDDBG("KD: 0x0E %d\n", id);
per->ExceptionCode = STATUS_ACCESS_VIOLATION;
per->ExceptionAddress = (UINT64)context->ip;
per->NumberParameters = 1;
per->ExceptionInformation0 = __readcr2();
break;
case Struct_Microsoft_Singularity_Isal_IX_EVectors_FirstChanceException: {
KdDebugTrapData *trapData = (KdDebugTrapData *) (context->ax);
switch (trapData->tag) {
case KdDebugTrapData::FIRST_CHANCE_EXCEPTION:
context->ax = trapData->firstChanceException.throwAddr;
KDDBG("KD: First chance C# exception\n");
// per->ExceptionCode = STATUS_CPP_EH_EXCEPTION; //0xe06d7363;
per->ExceptionCode = STATUS_VCPP_EXCEPTION; //0x8000ff1f;
per->ExceptionAddress = (UINT64)context->ip;
per->NumberParameters = 1;
per->ExceptionInformation0 = BREAKPOINT_BREAK;
break;
default:
KDDBG("KD: Unexpected interrupt %d\n", id);
per->ExceptionCode = 0x80000000 + id;
per->ExceptionAddress = (UINT64)context->ip;
break;
}
break;
}
case Struct_Microsoft_Singularity_Isal_IX_EVectors_SecondChanceException:
KDDBG("KD: Second chance C# exception\n");
per->ExceptionCode = STATUS_VCPP_EXCEPTION;
per->ExceptionAddress = (UINT64)context->ip;
break;
case Struct_Microsoft_Singularity_Isal_IX_EVectors_DebuggerBreakRequest:
KDDBG("KD: Debugger ctrl-break\n");
per->ExceptionCode = STATUS_BREAKPOINT;
per->ExceptionInformation0 = BREAKPOINT_BREAK;
per->ExceptionAddress = (UINT64)context->ip;
break;
case Struct_Microsoft_Singularity_Isal_IX_EVectors_Nmi:
KDDBG("KD: NMI exception\n");
per->ExceptionCode = STATUS_UNHANDLED_EXCEPTION;
per->ExceptionInformation0 = BREAKPOINT_BREAK;
per->ExceptionAddress = SIGN_EXTEND(context->ip);
break;
default:
KDDBG("KD: Unexpected interrupt %d\n", id);
per->ExceptionCode = 0x80000000 + id;
per->ExceptionAddress = (UINT64)context->ip;
break;
}
KDDBG("Trap: Context at %p\n", context);
KDDBG(" CXT=%08x THR=%08x\n",
context,
Class_Microsoft_Singularity_Processor::g_GetCurrentThreadContext()->_thread);
KDDBG(" RIP=%08x EFL=%08x ERR=%08x CR2=%08x\n",
context->ip, context->fl, id, __readcr2());
KDDBG(" RAX=%08x RBX=%08x RCX=%08x RDX=%08x\n",
context->ax, context->bx, context->cx, context->dx);
KDDBG(" RSP=%08x RBP=%08x RSI=%08x RDI=%08x\n",
context->sp, context->bp, context->si, context->di);
}
//
// Read or Write I/O Space.
//
// Return:
//
// iowrite == 0: value read from port
//
// iowrite !=0: zero
//
int KdpReadWriteIoSpace(
int size, // 1, 2, 4
int iowrite, // true if write, false if read
unsigned short addr,
unsigned int value
)
{
unsigned int retValue = 0;
if (iowrite != 0) {
// I/O Write's
if (size == 1) {
unsigned char byteValue = (unsigned char)value;
__outbyte(addr, value);
}
else if (size == 2) {
unsigned short wordValue = (unsigned short)value;
__outword(addr, value);
}
else if (size == 4) {
__outdword(addr, value);
}
}
else {
// I/O Read's
if (size == 1) {
retValue = __inbyte(addr);
}
else if (size == 2) {
retValue = __inword(addr);
}
else if (size == 4) {
retValue = __indword(addr);
}
}
return retValue;
}