Implement SvcGetThreadContext3

This commit is contained in:
gdkchan 2018-06-26 01:09:32 -03:00
parent c818093528
commit 65105c2a3b
10 changed files with 163 additions and 12 deletions

View file

@ -4,11 +4,13 @@ namespace ChocolArm64.Events
{
public class AInstExceptionEventArgs : EventArgs
{
public int Id { get; private set; }
public long Position { get; private set; }
public int Id { get; private set; }
public AInstExceptionEventArgs(int Id)
public AInstExceptionEventArgs(long Position, int Id)
{
this.Id = Id;
this.Position = Position;
this.Id = Id;
}
}
}

View file

@ -25,6 +25,7 @@ namespace ChocolArm64.Instruction
Context.EmitLdarg(ATranslatedSub.StateArgIdx);
Context.EmitLdc_I8(Op.Position);
Context.EmitLdc_I4(Op.Id);
Context.EmitPrivateCall(typeof(AThreadState), MthdName);

View file

@ -51,6 +51,17 @@ namespace ChocolArm64.State
public int Fpcr { get; set; }
public int Fpsr { get; set; }
public int Psr
{
get
{
return (Negative ? (int)APState.N : 0) |
(Zero ? (int)APState.Z : 0) |
(Carry ? (int)APState.C : 0) |
(Overflow ? (int)APState.V : 0);
}
}
public uint CtrEl0 => 0x8444c004;
public uint DczidEl0 => 0x00000004;
@ -89,14 +100,14 @@ namespace ChocolArm64.State
TickCounter.Start();
}
internal void OnBreak(int Imm)
internal void OnBreak(long Position, int Imm)
{
Break?.Invoke(this, new AInstExceptionEventArgs(Imm));
Break?.Invoke(this, new AInstExceptionEventArgs(Position, Imm));
}
internal void OnSvcCall(int Imm)
internal void OnSvcCall(long Position, int Imm)
{
SvcCall?.Invoke(this, new AInstExceptionEventArgs(Imm));
SvcCall?.Invoke(this, new AInstExceptionEventArgs(Position, Imm));
}
internal void OnUndefined(long Position, int RawOpCode)

View file

@ -47,6 +47,8 @@ namespace Ryujinx.HLE.OsHle.Handles
if (TryAddToCore(Thread))
{
SchedThread.IsRunning = true;
Thread.Thread.Execute();
PrintDbgThreadInfo(Thread, "running.");
@ -94,10 +96,7 @@ namespace Ryujinx.HLE.OsHle.Handles
public void SetThreadActivity(KThread Thread, bool Active)
{
if (!AllThreads.TryGetValue(Thread, out SchedulerThread SchedThread))
{
throw new InvalidOperationException();
}
SchedulerThread SchedThread = AllThreads[Thread];
SchedThread.IsActive = Active;
@ -111,6 +110,16 @@ namespace Ryujinx.HLE.OsHle.Handles
}
}
public bool IsThreadRunning(KThread Thread)
{
if (!AllThreads.TryGetValue(Thread, out SchedulerThread SchedThread))
{
return false;
}
return SchedThread.IsRunning;
}
public void EnterWait(KThread Thread, int TimeoutMs = Timeout.Infinite)
{
SchedulerThread SchedThread = AllThreads[Thread];
@ -161,6 +170,8 @@ namespace Ryujinx.HLE.OsHle.Handles
{
lock (SchedLock)
{
AllThreads[Thread].IsRunning = false;
PrintDbgThreadInfo(Thread, "suspended.");
int ActualCore = Thread.ActualCore;
@ -252,6 +263,8 @@ namespace Ryujinx.HLE.OsHle.Handles
private void TryResumingExecution(SchedulerThread SchedThread)
{
SchedThread.IsRunning = false;
KThread Thread = SchedThread.Thread;
PrintDbgThreadInfo(Thread, "trying to resume...");
@ -262,6 +275,8 @@ namespace Ryujinx.HLE.OsHle.Handles
{
if (TryAddToCore(Thread))
{
SchedThread.IsRunning = true;
PrintDbgThreadInfo(Thread, "resuming execution...");
return;
@ -291,6 +306,8 @@ namespace Ryujinx.HLE.OsHle.Handles
{
PrintDbgThreadInfo(SchedThread.Thread, "running.");
}
SchedThread.IsRunning = true;
}
public void Resort(KThread Thread)

View file

@ -29,6 +29,8 @@ namespace Ryujinx.HLE.OsHle.Handles
public int WaitHandle { get; set; }
public long LastPc { get; set; }
public int ThreadId => Thread.ThreadId;
public KThread(

View file

@ -11,6 +11,8 @@ namespace Ryujinx.HLE.OsHle.Handles
public bool IsActive { get; set; }
public bool IsRunning { get; set; }
public AutoResetEvent WaitSync { get; private set; }
public ManualResetEvent WaitActivity { get; private set; }
public AutoResetEvent WaitSched { get; private set; }

View file

@ -13,5 +13,7 @@ namespace Ryujinx.HLE.OsHle.Kernel
public const int Canceled = 118;
public const int CountOutOfRange = 119;
public const int InvalidInfo = 120;
public const int InvalidThread = 122;
public const int InvalidState = 125;
}
}

View file

@ -72,7 +72,8 @@ namespace Ryujinx.HLE.OsHle.Kernel
{ 0x29, SvcGetInfo },
{ 0x2c, SvcMapPhysicalMemory },
{ 0x2d, SvcUnmapPhysicalMemory },
{ 0x32, SvcSetThreadActivity }
{ 0x32, SvcSetThreadActivity },
{ 0x33, SvcGetThreadContext3 }
};
this.Ns = Ns;

View file

@ -280,5 +280,116 @@ namespace Ryujinx.HLE.OsHle.Kernel
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
}
}
private void SvcGetThreadContext3(AThreadState ThreadState)
{
long Position = (long)ThreadState.X0;
int Handle = (int)ThreadState.X1;
KThread Thread = Process.HandleTable.GetData<KThread>(Handle);
if (Thread == null)
{
Ns.Log.PrintWarning(LogClass.KernelSvc, $"Invalid thread handle 0x{Handle:x8}!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle);
return;
}
if (Process.GetThread(ThreadState.Tpidr) == Thread)
{
Ns.Log.PrintWarning(LogClass.KernelSvc, $"Thread handle 0x{Handle:x8} is current thread!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidThread);
return;
}
if (Process.Scheduler.IsThreadRunning(Thread))
{
Ns.Log.PrintWarning(LogClass.KernelSvc, $"Thread handle 0x{Handle:x8} is running!");
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidState);
return;
}
Memory.WriteUInt64(Position + 0x0, ThreadState.X0);
Memory.WriteUInt64(Position + 0x8, ThreadState.X1);
Memory.WriteUInt64(Position + 0x10, ThreadState.X2);
Memory.WriteUInt64(Position + 0x18, ThreadState.X3);
Memory.WriteUInt64(Position + 0x20, ThreadState.X4);
Memory.WriteUInt64(Position + 0x28, ThreadState.X5);
Memory.WriteUInt64(Position + 0x30, ThreadState.X6);
Memory.WriteUInt64(Position + 0x38, ThreadState.X7);
Memory.WriteUInt64(Position + 0x40, ThreadState.X8);
Memory.WriteUInt64(Position + 0x48, ThreadState.X9);
Memory.WriteUInt64(Position + 0x50, ThreadState.X10);
Memory.WriteUInt64(Position + 0x58, ThreadState.X11);
Memory.WriteUInt64(Position + 0x60, ThreadState.X12);
Memory.WriteUInt64(Position + 0x68, ThreadState.X13);
Memory.WriteUInt64(Position + 0x70, ThreadState.X14);
Memory.WriteUInt64(Position + 0x78, ThreadState.X15);
Memory.WriteUInt64(Position + 0x80, ThreadState.X16);
Memory.WriteUInt64(Position + 0x88, ThreadState.X17);
Memory.WriteUInt64(Position + 0x90, ThreadState.X18);
Memory.WriteUInt64(Position + 0x98, ThreadState.X19);
Memory.WriteUInt64(Position + 0xa0, ThreadState.X20);
Memory.WriteUInt64(Position + 0xa8, ThreadState.X21);
Memory.WriteUInt64(Position + 0xb0, ThreadState.X22);
Memory.WriteUInt64(Position + 0xb8, ThreadState.X23);
Memory.WriteUInt64(Position + 0xc0, ThreadState.X24);
Memory.WriteUInt64(Position + 0xc8, ThreadState.X25);
Memory.WriteUInt64(Position + 0xd0, ThreadState.X26);
Memory.WriteUInt64(Position + 0xd8, ThreadState.X27);
Memory.WriteUInt64(Position + 0xe0, ThreadState.X28);
Memory.WriteUInt64(Position + 0xe8, ThreadState.X29);
Memory.WriteUInt64(Position + 0xf0, ThreadState.X30);
Memory.WriteUInt64(Position + 0xf8, ThreadState.X31);
Memory.WriteInt64(Position + 0x100, Thread.LastPc);
Memory.WriteUInt64(Position + 0x108, (ulong)ThreadState.Psr);
Memory.WriteVector128(Position + 0x110, ThreadState.V0);
Memory.WriteVector128(Position + 0x120, ThreadState.V1);
Memory.WriteVector128(Position + 0x130, ThreadState.V2);
Memory.WriteVector128(Position + 0x140, ThreadState.V3);
Memory.WriteVector128(Position + 0x150, ThreadState.V4);
Memory.WriteVector128(Position + 0x160, ThreadState.V5);
Memory.WriteVector128(Position + 0x170, ThreadState.V6);
Memory.WriteVector128(Position + 0x180, ThreadState.V7);
Memory.WriteVector128(Position + 0x190, ThreadState.V8);
Memory.WriteVector128(Position + 0x1a0, ThreadState.V9);
Memory.WriteVector128(Position + 0x1b0, ThreadState.V10);
Memory.WriteVector128(Position + 0x1c0, ThreadState.V11);
Memory.WriteVector128(Position + 0x1d0, ThreadState.V12);
Memory.WriteVector128(Position + 0x1e0, ThreadState.V13);
Memory.WriteVector128(Position + 0x1f0, ThreadState.V14);
Memory.WriteVector128(Position + 0x200, ThreadState.V15);
Memory.WriteVector128(Position + 0x210, ThreadState.V16);
Memory.WriteVector128(Position + 0x220, ThreadState.V17);
Memory.WriteVector128(Position + 0x230, ThreadState.V18);
Memory.WriteVector128(Position + 0x240, ThreadState.V19);
Memory.WriteVector128(Position + 0x250, ThreadState.V20);
Memory.WriteVector128(Position + 0x260, ThreadState.V21);
Memory.WriteVector128(Position + 0x270, ThreadState.V22);
Memory.WriteVector128(Position + 0x280, ThreadState.V23);
Memory.WriteVector128(Position + 0x290, ThreadState.V24);
Memory.WriteVector128(Position + 0x2a0, ThreadState.V25);
Memory.WriteVector128(Position + 0x2b0, ThreadState.V26);
Memory.WriteVector128(Position + 0x2c0, ThreadState.V27);
Memory.WriteVector128(Position + 0x2d0, ThreadState.V28);
Memory.WriteVector128(Position + 0x2e0, ThreadState.V29);
Memory.WriteVector128(Position + 0x2f0, ThreadState.V30);
Memory.WriteVector128(Position + 0x300, ThreadState.V31);
Memory.WriteInt32(Position + 0x310, ThreadState.Fpcr);
Memory.WriteInt32(Position + 0x314, ThreadState.Fpsr);
Memory.WriteInt64(Position + 0x318, ThreadState.Tpidr);
ThreadState.X0 = 0;
}
}
}

View file

@ -205,6 +205,8 @@ namespace Ryujinx.HLE.OsHle
KThread Thread = new KThread(CpuThread, this, ProcessorId, Priority);
Thread.LastPc = EntryPoint;
int Handle = HandleTable.OpenHandle(Thread);
int ThreadId = GetFreeTlsSlot(CpuThread);