singrdk/base/Kernel/Singularity/Isal/SpillContext.cs

395 lines
12 KiB
C#
Raw Permalink Normal View History

2008-11-17 18:29:00 -05:00
//////////////////////////////////////////////////////////////////////////////////////////////////
//
// Microsoft Research Singularity
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// This file defines an architecture-neutral encapsulation of the state which is saved
// during a thread context switch.
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
{
// SpillContext holds the CPU state which is local to a thread. Note this
// is a subset of the entire CPU context, as some of the context does not
// change from thread to thread.
[NoCCtor]
[AccessedByRuntime("referenced in c++", AllFields = true)]
[CLSCompliant(false)]
[StructLayout(LayoutKind.Sequential)]
[StructAlign(16)]
public struct SpillContext
{
#if ISA_IX
///////////////////////////////////////////////////////////////////////////
// ISA_IX86 Context
//
// Integer registers
//
public UIntPtr ax;
public UIntPtr bx;
public UIntPtr cx;
public UIntPtr dx;
public UIntPtr di;
public UIntPtr si;
#if ISA_IX64
public UIntPtr r8;
public UIntPtr r9;
public UIntPtr r10;
public UIntPtr r11;
public UIntPtr r12;
public UIntPtr r13;
public UIntPtr r14;
public UIntPtr r15;
#endif
//
// Control registers
//
public UIntPtr sp;
public UIntPtr ip;
public UIntPtr bp;
public UIntPtr fl;
//
// Mmx context. Note that this must be 16-byte aligned.
//
internal MmxContext mmx;
// We always store cs even though it never changes in non-paging builds,
// since it simplifies the context switching code. Also note we
// don't store any other segments because they either the same as cs (ss, ds, es) or
// never change (fs, gs)
public UIntPtr cs;
#if PAGING
//
// Page table base
//
public UIntPtr cr3;
#endif
#elif ISA_ARM
///////////////////////////////////////////////////////////////////////////
// Arm Context
//
// Unbanked integer and control registers.
//
public uint r0;
public uint r1;
public uint r2;
public uint r3;
public uint r4;
public uint r5;
public uint r6;
public uint r7;
public uint r8;
public uint r9;
public uint r10;
public uint r11;
public uint r12;
public uint pc; // aka r15
//
// Banked control Registers
//
public uint sp; // aka r13
public uint lr; // aka r14
//
// Processor status register.
//
public uint cpsr;
#endif
//
// Extra (unrestored) context information from InterruptContext.
//
#if ISA_ARM
public uint instruction;
#endif
///////////////////////////////////////////////////////////////////////////
// Common fields
public const int ContentsSpilled = 0x00000001;
// Stack limit is stored as part of the spill context.
public UIntPtr stackLimit;
// Field for storing various flags about the state of the spill.
public int spillFlags;
///////////////////////////////////////////////////////////////////////////
// Properties - these are ISA-neutral ways to access common aspects of the
// spill context.
public UIntPtr InstructionPointer
{
[NoHeapAllocation]
get {
#if ISA_IX
return ip;
#elif ISA_ARM
return pc;
#endif
}
[NoHeapAllocation]
set {
#if ISA_IX
ip = value;
#elif ISA_ARM
pc = (uint)value;
#endif
}
}
public UIntPtr StackPointer
{
[NoHeapAllocation]
get {
return sp;
}
}
public UIntPtr FramePointer
{
[NoHeapAllocation]
get {
#if ISA_IX
return bp;
#elif ISA_ARM
return r11; // ?
#endif
}
}
public UIntPtr Flags
{
[NoHeapAllocation]
get {
#if ISA_IX
return fl;
#elif ISA_ARM
return cpsr;
#endif
}
}
// IsSpilled indicates whether or not the context is in a spilled state - that is,
// whether the context represents a swapped-out thread (as opposed to the state
// where the thread is running.)
//
// This flag is set every time we save the context, and cleared when it is restored.
public bool IsSpilled
{
[NoHeapAllocation]
get {
return (spillFlags & ContentsSpilled) != 0;
}
}
[NoHeapAllocation]
public unsafe void Trace()
{
#if ISA_IX86
Tracing.Log(Tracing.Debug, "eax={0:x8} ebx={1:x8} ecx={2:x8} edx={3:x8}\n",
ax, bx, cx, dx);
Tracing.Log(Tracing.Debug, "esp={0:x8} ebp={1:x8} esi={2:x8} edi={3:x8}\n",
sp, bp, si, di);
Tracing.Log(Tracing.Debug, "eip={0:x8} efl={1:x8}\n", ip, fl);
#elif ISA_IX64
Tracing.Log(Tracing.Debug, "rax={0:x16} rbx={1:x16} rcx={2:x16} rdx={3:x16}\n",
ax, bx, cx, dx);
Tracing.Log(Tracing.Debug, "rsp={0:x16} rbp={1:x16} rsi={2:x16} rdi={3:x16}\n",
sp, bp, si, di);
Tracing.Log(Tracing.Debug, "r8={0:x16} r9={1:x16} r10={2:x16} r11={3:x16}\n",
r8, r9, r10, r11);
Tracing.Log(Tracing.Debug, "r12={0:x16} r13={1:x16} r14={2:x16} r15={3:x16}\n",
r12, r13, r14, r15);
Tracing.Log(Tracing.Debug, "rip={0:x16} rfl={1:x16}\n",
ip, fl);
#elif ISA_ARM
Tracing.Log(Tracing.Debug, "r0={0:x8} r1={1:x8} r2={2:x8} r3={3:x8}\n",
(UIntPtr) r0, (UIntPtr) r1, (UIntPtr) r2, (UIntPtr) r3);
Tracing.Log(Tracing.Debug, "r4={0:x8} r5={1:x8} r6={2:x8} r7={3:x8}\n",
(UIntPtr) r4, (UIntPtr) r5, (UIntPtr) r6, (UIntPtr) r7);
Tracing.Log(Tracing.Debug, "r8={0:x8} r9={1:x8} r10={2:x8} r11={3:x8}\n",
(UIntPtr) r8, (UIntPtr) r9, (UIntPtr) r10, (UIntPtr) r11);
Tracing.Log(Tracing.Debug, "r12={0:x8} sp={1:x8} lr={2:x8} pc={3:x8}\n",
(UIntPtr) r12, (UIntPtr) sp, (UIntPtr) lr, (UIntPtr) pc);
Tracing.Log(Tracing.Debug, "cpsr={0:x8}\n", (UIntPtr) cpsr);
#endif
}
[NoHeapAllocation]
public unsafe void Display()
{
#if ISA_IX86
DebugStub.WriteLine(" eax={0:x8} ebx={1:x8} ecx={2:x8} edx={3:x8}",
__arglist(ax, bx, cx, dx));
DebugStub.WriteLine(" esp={0:x8} ebp={1:x8} esi={2:x8} edi={3:x8}",
__arglist(sp, bp, si, di));
DebugStub.WriteLine(" eip={0:x8} efl={1:x8}",
__arglist(ip, fl));
#elif ISA_IX64
DebugStub.WriteLine(" rax={0:x16} rbx={1:x16} rcx={2:x16} rdx={3:x16}",
__arglist(ax, bx, cx, dx));
DebugStub.WriteLine(" rsp={0:x16} rbp={1:x16} rsi={2:x16} rdi={3:x16}",
__arglist(sp, bp, si, di));
DebugStub.WriteLine(" r8={0:x16} r9={1:x16} r10={2:x16} r11={3:x16}",
__arglist(r8, r9, r10, r11));
DebugStub.WriteLine(" r12={0:x16} r13={1:x16} r14={2:x16} r15={3:x16}",
__arglist(r12, r13, r14, r15));
DebugStub.WriteLine(" rip={0:x16} rfl={1:x16}",
__arglist(ip, fl));
#elif ISA_ARM
DebugStub.WriteLine(" r0={0:x8} r1={1:x8} r2={2:x8} r3={3:x8}",
__arglist(r0, r1, r2, r3));
DebugStub.WriteLine(" r4={0:x8} r5={1:x8} r6={2:x8} r7={3:x8}",
__arglist(r4, r5, r6, r7));
DebugStub.WriteLine(" r8={0:x8} r9={1:x8} r10={2:x8} r11={3:x8}",
__arglist(r8, r9, r10, r11));
DebugStub.WriteLine(" r12={0:x8} sp={1:x8} lr={2:x8} pc={3:x8}",
__arglist(r12, sp, lr, pc));
DebugStub.WriteLine(" psr={0:x8}", __arglist(cpsr));
#endif
}
#if SINGULARITY_KERNEL
///////////////////////////////////////////////////////////////////////////
// Methods
[AccessedByRuntime("defined in asm")]
[CLSCompliant(false)]
[MethodImpl(MethodImplOptions.InternalCall)]
[GCAnnotation(GCOption.NOGC)]
[StackBound(32)]
[NoHeapAllocation]
public extern unsafe bool Save();
[AccessedByRuntime("defined in asm")]
[CLSCompliant(false)]
[MethodImpl(MethodImplOptions.InternalCall)]
[GCAnnotation(GCOption.NOGC)]
[StackBound(32)]
[NoHeapAllocation]
public extern unsafe bool Save(InterruptContext *interrupt);
[AccessedByRuntime("defined in asm")]
[CLSCompliant(false)]
[MethodImpl(MethodImplOptions.InternalCall)]
[GCAnnotation(GCOption.NOGC)]
[StackBound(32)]
[NoHeapAllocation]
public extern unsafe void Resume();
[AccessedByRuntime("called from C++")]
[CLSCompliant(false)]
[NoHeapAllocation]
public unsafe void Initialize(UIntPtr stack, UIntPtr stackLimit,
UIntPtr start, int threadIndex, UIntPtr cr3)
{
#if ISA_IX
UIntPtr *sp = (UIntPtr *) stack;
*--sp = 0;
*--sp = 0;
this.bp = (uint) (UIntPtr) sp;
this.sp = (uint) (UIntPtr) sp;
this.ip = (uint) start;
this.cs = (uint) Isa.GetCs();
this.cx = (uint) threadIndex;
this.fl = EFlags.IF;
// If we are allowed (i.e. the kernel is ring 0), set IO priveleges in the context
if ((Isa.GetCs() & 0x3) == 0) {
this.fl |= EFlags.IOPL; // TODO: get rid of IOPL
}
this.fl = EFlags.IF;
this.mmx.fcw = 0x037f;
this.mmx.ftw = 0;
// mmx.mxcsr = 0x1f80;
this.stackLimit = stackLimit;
#if PAGING
this.cr3 = cr3;
#endif
#elif ISA_ARM
this.sp = (uint) stack;
this.r11 = (uint) stack;
this.pc = (uint) start;
this.r0 = (uint) threadIndex;
this.cpsr = ProcessorMode.System;
this.stackLimit = stackLimit;
#endif
// Mark thread as having valid contents
this.spillFlags = ContentsSpilled;
}
[AccessedByRuntime("defined in asm")]
[CLSCompliant(false)]
[MethodImpl(MethodImplOptions.InternalCall)]
[GCAnnotation(GCOption.NOGC)]
[StackBound(32)]
[NoHeapAllocation]
public extern unsafe static void ResetCurrent();
#endif // SINGULARITY_KERNEL
};
}