/////////////////////////////////////////////////////////////////////////////// // // 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; }