321 lines
11 KiB
C++
321 lines
11 KiB
C++
|
///////////////////////////////////////////////////////////////////////////////
|
||
|
//
|
||
|
// Microsoft Research Singularity
|
||
|
//
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//
|
||
|
// File: halkdarm.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 KdpArmSetControlReport(IN OUT PDBGKD_CONTROL_REPORT report);
|
||
|
|
||
|
//////////////////////////////////////////////// User visible progress beacon.
|
||
|
//
|
||
|
void KdpSpin()
|
||
|
{
|
||
|
#if 0
|
||
|
extern uint16 * videoBuffer;
|
||
|
static uint16 values[] = { 0x0000, 0xffff, 0xfc00, 0x03f0, 0x000f };
|
||
|
|
||
|
|
||
|
if (videoBuffer != 0) {
|
||
|
static UINT8 state = 0;
|
||
|
|
||
|
videoBuffer[0] = values[state];
|
||
|
videoBuffer[1] = values[state];
|
||
|
videoBuffer[2] = values[state];
|
||
|
videoBuffer[3] = values[state];
|
||
|
videoBuffer[4] = values[state];
|
||
|
videoBuffer[5] = values[state];
|
||
|
videoBuffer[6] = values[state];
|
||
|
videoBuffer[7] = values[state];
|
||
|
|
||
|
state++;
|
||
|
if (state >= arrayof(values)) {
|
||
|
state = 0;
|
||
|
}
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
void KdpToKdContext(IN CONST Struct_Microsoft_Singularity_Isal_SpillContext *singularity,
|
||
|
OUT CONTEXT *windbg)
|
||
|
{
|
||
|
windbg->ContextFlags = (CONTEXT_CONTROL |
|
||
|
CONTEXT_INTEGER);
|
||
|
|
||
|
windbg->Sp = singularity->sp;
|
||
|
windbg->Lr = singularity->lr;
|
||
|
windbg->Pc = singularity->pc;
|
||
|
windbg->R0 = singularity->r0;
|
||
|
windbg->R1 = singularity->r1;
|
||
|
windbg->R2 = singularity->r2;
|
||
|
windbg->R3 = singularity->r3;
|
||
|
windbg->R4 = singularity->r4;
|
||
|
windbg->R5 = singularity->r5;
|
||
|
windbg->R6 = singularity->r6;
|
||
|
windbg->R7 = singularity->r7;
|
||
|
windbg->R8 = singularity->r8;
|
||
|
windbg->R9 = singularity->r9;
|
||
|
windbg->R10 = singularity->r10;
|
||
|
windbg->R11 = singularity->r11;
|
||
|
windbg->R12 = singularity->r12;
|
||
|
windbg->Cpsr = singularity->cpsr;
|
||
|
}
|
||
|
|
||
|
void KdpFromKdContext(IN CONST CONTEXT *windbg,
|
||
|
OUT Struct_Microsoft_Singularity_Isal_SpillContext *singularity)
|
||
|
{
|
||
|
singularity->sp = windbg->Sp;
|
||
|
singularity->lr = windbg->Lr;
|
||
|
singularity->pc = windbg->Pc;
|
||
|
singularity->r0 = windbg->R0;
|
||
|
singularity->r1 = windbg->R1;
|
||
|
singularity->r2 = windbg->R2;
|
||
|
singularity->r3 = windbg->R3;
|
||
|
singularity->r4 = windbg->R4;
|
||
|
singularity->r5 = windbg->R5;
|
||
|
singularity->r6 = windbg->R6;
|
||
|
singularity->r7 = windbg->R7;
|
||
|
singularity->r8 = windbg->R8;
|
||
|
singularity->r9 = windbg->R9;
|
||
|
singularity->r10 = windbg->R10;
|
||
|
singularity->r11 = windbg->R11;
|
||
|
singularity->r12 = windbg->R12;
|
||
|
singularity->cpsr = windbg->Cpsr;
|
||
|
}
|
||
|
|
||
|
void KdpSetControlReport(IN OUT PDBGKD_CONTROL_REPORT report,
|
||
|
IN CONST Struct_Microsoft_Singularity_Isal_SpillContext *singularity)
|
||
|
{
|
||
|
KdpArmSetControlReport(report);
|
||
|
|
||
|
report->Cpsr = singularity->cpsr;
|
||
|
}
|
||
|
|
||
|
void KdpSetControlSet(IN CONST DBGKD_CONTROL_SET * control,
|
||
|
IN OUT Struct_Microsoft_Singularity_Isal_SpillContext *singularity)
|
||
|
{
|
||
|
// TODO: This needs to be filled in.
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
void KdpReadSpecialRegisters(KSPECIAL_REGISTERS *pksp,
|
||
|
IN CONST Struct_Microsoft_Singularity_Isal_SpillContext *singularity)
|
||
|
{
|
||
|
#if 0
|
||
|
internal struct ArmKSpecialRegisters {
|
||
|
internal uint Cp15Cr0Id;
|
||
|
internal uint Cp15Cr0Cachetype;
|
||
|
internal uint Cp15Cr1Control;
|
||
|
internal uint Cp15Cr2Ttb;
|
||
|
internal uint Cp15Cr3Dacr;
|
||
|
internal uint Cp15Cr5FaultStatus;
|
||
|
internal uint Cp15Cr5FaultAddress;
|
||
|
internal uint Cp15Cr13ProcessId;
|
||
|
};
|
||
|
#endif
|
||
|
|
||
|
#if 0
|
||
|
pksp->Cp15Cr0Id = _MoveFromCoprocessor(0, 15, 0, 7, 5, 0);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void KdpWriteSpecialRegisters(CONST KSPECIAL_REGISTERS *pksp)
|
||
|
{
|
||
|
#if 0
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void KdpFlushInstCache(void)
|
||
|
{
|
||
|
_MoveToCoprocessor(0, 15, 0, 7, 5, 0); // ICIALLU: Invalidate all instruction caches.
|
||
|
}
|
||
|
|
||
|
bool KdpReadMsr(UINT32 msr, UINT32 *plo, UINT32 *phi)
|
||
|
{
|
||
|
*phi = 0;
|
||
|
|
||
|
switch (msr) {
|
||
|
#undef VALID_COPROC_REGISTER
|
||
|
#define VALID_COPROC_REGISTER(_Coproc, _OpCode1, _CoReg1, _CoReg2, _OpCode2) \
|
||
|
case (_Coproc << 16) | (_OpCode1 << 12) | (_CoReg1 << 8) | (_CoReg2 << 4) | _OpCode2 : \
|
||
|
*plo = _MoveFromCoprocessor(_Coproc, _OpCode1, _CoReg1, _CoReg2, _OpCode2); \
|
||
|
break;
|
||
|
#include "halkdmsr.h"
|
||
|
|
||
|
default:
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
|
||
|
}
|
||
|
|
||
|
bool KdpWriteMsr(UINT32 msr, UINT32 lo, UINT32 hi)
|
||
|
{
|
||
|
switch (msr) {
|
||
|
#undef VALID_COPROC_REGISTER
|
||
|
#define VALID_COPROC_REGISTER(_Coproc, _OpCode1, _CoReg1, _CoReg2, _OpCode2) \
|
||
|
case (_Coproc << 16) | (_OpCode1 << 12) | (_CoReg1 << 8) | (_CoReg2 << 4) | _OpCode2 : \
|
||
|
_MoveToCoprocessor(lo, _Coproc, _OpCode1, _CoReg1, _CoReg2, _OpCode2); \
|
||
|
break;
|
||
|
#include "halkdmsr.h"
|
||
|
default:
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
KdDebugTrapData * KdpIsDebugTrap(IN CONST Struct_Microsoft_Singularity_Isal_SpillContext *context,
|
||
|
int id)
|
||
|
{
|
||
|
if ((id == Struct_Microsoft_Singularity_Isal_Arm_ExceptionVector_SoftwareInterrupt) &&
|
||
|
(context->instruction == 0xefffff2e)) {
|
||
|
|
||
|
KDDBG("IsDebugTrap(%x) tag=%p\n", id, ((KdDebugTrapData *)(context->r0))->tag);
|
||
|
return (KdDebugTrapData *)(context->r0);
|
||
|
}
|
||
|
KDDBG("IsDebugTrap(%x) NULL\n", id);
|
||
|
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)
|
||
|
{
|
||
|
KDDBG("ConvertTrapToExc(%d)\n", id);
|
||
|
KDDBG(" pc=%p [%p]\n", context->pc, *((uint32*)context->pc));
|
||
|
KDDBG(" lr=%p r0=%p\n", context->lr, context->r0);
|
||
|
|
||
|
// Breakpoints:
|
||
|
switch (id) {
|
||
|
|
||
|
case Struct_Microsoft_Singularity_Isal_Arm_ExceptionVector_UndefinedInstruction: {
|
||
|
KDDBG("Illegal Instruction %08x\n", context->instruction);
|
||
|
per->ExceptionCode = STATUS_ILLEGAL_INSTRUCTION;
|
||
|
per->ExceptionAddress = SIGN_EXTEND(context->pc - 4);
|
||
|
per->NumberParameters = 0;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
case Struct_Microsoft_Singularity_Isal_Arm_ExceptionVector_PrefetchAbort: {
|
||
|
KDDBG("KD: Prefetch Exception %d\n", id);
|
||
|
per->ExceptionCode = STATUS_ACCESS_VIOLATION;
|
||
|
per->ExceptionAddress = SIGN_EXTEND(context->pc);
|
||
|
per->NumberParameters = 0;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
case Struct_Microsoft_Singularity_Isal_Arm_ExceptionVector_DataAbort: {
|
||
|
KDDBG("KD: Data Exception %d\n", id);
|
||
|
per->ExceptionCode = STATUS_ACCESS_VIOLATION;
|
||
|
// Should probably decode instruction to figure out the real faulty address.
|
||
|
per->ExceptionAddress = SIGN_EXTEND(context->pc);
|
||
|
per->NumberParameters = 0;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
case Struct_Microsoft_Singularity_Isal_Arm_ExceptionVector_Reset:
|
||
|
case Struct_Microsoft_Singularity_Isal_Arm_ExceptionVector_Irq:
|
||
|
case Struct_Microsoft_Singularity_Isal_Arm_ExceptionVector_Fiq: {
|
||
|
KDDBG("KD: Unexpected IRQ %d\n", id);
|
||
|
per->ExceptionCode = STATUS_UNHANDLED_EXCEPTION;
|
||
|
per->ExceptionAddress = SIGN_EXTEND(context->pc);
|
||
|
per->NumberParameters = 1;
|
||
|
per->ExceptionInformation0 = id;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
case Struct_Microsoft_Singularity_Isal_Arm_ExceptionVector_SoftwareInterrupt: {
|
||
|
switch (context->instruction) {
|
||
|
case 0xefffff01: { // aka KDP_BREAKPOINT_VALUE (swi 0xffff01)
|
||
|
KDDBG("KD Single or Bkpt\n");
|
||
|
per->ExceptionCode = STATUS_SINGLE_STEP;
|
||
|
per->ExceptionAddress = SIGN_EXTEND(context->pc);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
case 0xefffff03: { // Hard-coded break (swi 0xffff03)
|
||
|
KDDBG("Breakpoint\n");
|
||
|
per->ExceptionCode = STATUS_BREAKPOINT;
|
||
|
per->NumberParameters = 1;
|
||
|
per->ExceptionInformation0 = BREAKPOINT_BREAK;
|
||
|
per->ExceptionAddress = SIGN_EXTEND(context->pc - 4);
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
case 0xefffff2e: { // Debug notify (swi 0xffff2e)
|
||
|
KdDebugTrapData *trapData = (KdDebugTrapData *) (context->r0);
|
||
|
switch (trapData->tag) {
|
||
|
case KdDebugTrapData::FIRST_CHANCE_EXCEPTION:
|
||
|
context->r0 = 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 = SIGN_EXTEND(context->pc - 4);
|
||
|
per->NumberParameters = 1;
|
||
|
per->ExceptionInformation0 = BREAKPOINT_BREAK;
|
||
|
return;
|
||
|
|
||
|
default:
|
||
|
KDDBG("KD: Bad trap 0x%x\n", id);
|
||
|
per->ExceptionCode = STATUS_UNHANDLED_EXCEPTION;
|
||
|
per->ExceptionAddress = SIGN_EXTEND(context->pc - 4);
|
||
|
per->NumberParameters = 1;
|
||
|
per->ExceptionInformation0 = id;
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
default: {
|
||
|
KDDBG("KD: Unexpected SWI %08x\n", context->instruction);
|
||
|
per->ExceptionCode = STATUS_ILLEGAL_INSTRUCTION;
|
||
|
per->ExceptionAddress = SIGN_EXTEND(context->pc - 4);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
KDDBG("KD: Unexpected interrupt %d\n", id);
|
||
|
per->ExceptionCode = 0x80000000 + id;
|
||
|
per->ExceptionAddress = SIGN_EXTEND(context->pc);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//
|
||
|
// Read or Write I/O Space.
|
||
|
//
|
||
|
// Return: Silently does nothing on ARM. Could be implemented
|
||
|
// in the future to read/write from a simulated I/O space
|
||
|
// if an ARM platform has such a mapping.
|
||
|
//
|
||
|
// 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
|
||
|
)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|