////////////////////////////////////////////////////////////////////////////////////////////////// // // Microsoft Research Singularity // // Copyright (c) Microsoft Corporation. All rights reserved. // // This file defines an architecture-neutral encapsulation of the low-level information // saved during an interrupt dispatch. // using System; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; #if ISA_IX using Microsoft.Singularity.Isal.IX; #elif ISA_ARM using Microsoft.Singularity.Isal.Arm; #endif namespace Microsoft.Singularity.Isal { // InterruptContext is the lightweight context which is pushed on the stack // during interrupt generation. This is the minimal context save we will // perform for any interrupt processing. (Note that it includes caller // saved registers so we can use C code.) [NoCCtor] [AccessedByRuntime("referenced in c++", AllFields = true)] [CLSCompliant(false)] [StructLayout(LayoutKind.Sequential)] public struct InterruptContext { #if ISA_IX // Vector constants public const int VectorExceptionMax = 0x20; public const int VectorSchedulerMin = 0x21; #if ISA_IX64 // Caller-saved registers (which get saved by our handler routine) public UIntPtr r11; public UIntPtr r10; public UIntPtr r9; public UIntPtr r8; #endif //ISA_IX64 // Caller-saved registers (which get saved by our handler routine) public UIntPtr dx; public UIntPtr cx; public UIntPtr ax; // Interrupt information pushed as part of interrupt dispatch public UIntPtr vector; public UIntPtr err; // Interruption context public UIntPtr ip; public UIntPtr cs; public UIntPtr fl; // This stack info is valid only in cases of cross-ring interrupts; otherwise // we stay on the same stack and pop to this level (ignoring these two fields.) public UIntPtr sp; public UIntPtr ss; #elif ISA_ARM // Unbanked caller-saved registers. public uint r0; public uint r1; public uint r2; public uint r3; public uint r12; public uint pc; // aka r15 // Banked caller-saved registers. public uint sp; // aka r13 public uint lr; // aka r14 // Resume proessor status register. public uint cpsr; // Interrupt information. public uint vector; public uint instruction; #endif [NoHeapAllocation] public bool IsException() { #if ISA_IX return (vector < 0x20); #elif ISA_ARM return (vector < ExceptionVector.Irq); #endif } public byte ExceptionId { [NoHeapAllocation] get { return (byte)vector; } } public UIntPtr InstructionPointer { [NoHeapAllocation] get { #if ISA_IX return (UIntPtr)ip; #elif ISA_ARM return (UIntPtr)pc; #endif } } public UIntPtr StackPointer { [NoHeapAllocation] get { #if ISA_IX86 if ((cs & 0x3) == (Isa.GetCs() & 0x3)) { unsafe { fixed (UIntPtr *p = &sp) { return *p; } } } else { return sp; } #elif ISA_IX64 return sp; #elif ISA_ARM return sp; #endif } } [NoHeapAllocation] public unsafe void Display() { #if ISA_IX86 DebugStub.WriteLine(" eax={0:x8} ecx={1:x8} edx={2:x8}", __arglist(ax, cx, dx)); DebugStub.WriteLine(" esp[x-ring only]={0:x8}", __arglist(sp)); DebugStub.WriteLine(" eip={0:x8} efl={1:x8}", __arglist(ip, fl)); #elif ISA_IX64 DebugStub.WriteLine(" rax={0:x16} rcx={1:x16} rdx={2:x16}", __arglist(ax, cx, dx)); DebugStub.WriteLine(" rsp={0:x16}", __arglist(sp)); DebugStub.WriteLine(" rip={0:x16} rfl={1:x16}", __arglist(ip, fl)); #elif ISA_ARM DebugStub.WriteLine("pc={0:x8} sp={1:x8} lr={2:x8} sr={3:x8}", __arglist(pc, sp, lr, cpsr)); DebugStub.WriteLine("r0={0:x8} r1={1:x8} r2={2:x8} r3={3:x8}", __arglist(r0, r1, r2, r3)); #endif } } }