public static AOpCode DecodeOpCode(AThreadState State, AMemory Memory, long Position) { int OpCode = Memory.ReadInt32(Position); AInst Inst; if (State.ExecutionMode == AExecutionMode.AArch64) { Inst = AOpCodeTable.GetInstA64(OpCode); } else { //TODO: Thumb support. Inst = AOpCodeTable.GetInstA32(OpCode); } AOpCode DecodedOpCode = new AOpCode(AInst.Undefined, Position, OpCode); if (Inst.Type != null) { DecodedOpCode = MakeOpCode(Inst.Type, Inst, Position, OpCode); } return(DecodedOpCode); }
private void UploadTexture(AMemory Memory, long BasePosition, int TexIndex, int HndIndex) { long Position = BasePosition + HndIndex * 4; int TextureHandle = Memory.ReadInt32(Position); int TicIndex = (TextureHandle >> 0) & 0xfffff; int TscIndex = (TextureHandle >> 20) & 0xfff; TryGetCpuAddr(NvGpuEngine3dReg.TexHeaderPoolOffset, out long TicPosition); TryGetCpuAddr(NvGpuEngine3dReg.TexSamplerPoolOffset, out long TscPosition); TicPosition += TicIndex * 0x20; TscPosition += TscIndex * 0x20; GalTextureSampler Sampler = TextureFactory.MakeSampler(Gpu, Memory, TscPosition); long TextureAddress = Memory.ReadInt64(TicPosition + 4) & 0xffffffffffff; if (FrameBuffers.Contains(TextureAddress)) { //This texture is a frame buffer texture, //we shouldn't read anything from memory and bind //the frame buffer texture instead, since we're not //really writing anything to memory. Gpu.Renderer.BindFrameBufferTexture(TextureAddress, TexIndex, Sampler); } else { GalTexture Texture = TextureFactory.MakeTexture(Gpu, Memory, TicPosition); Gpu.Renderer.SetTextureAndSampler(TexIndex, Texture, Sampler); Gpu.Renderer.BindTexture(TexIndex); } }
public static ulong WaitForAddressIfLessThan(Process Process, AThreadState ThreadState, AMemory Memory, long Address, int Value, ulong Timeout, bool ShouldDecrement) { Memory.SetExclusive(ThreadState, Address); int CurrentValue = Memory.ReadInt32(Address); while (true) { if (Memory.TestExclusive(ThreadState, Address)) { if (CurrentValue < Value) { if (ShouldDecrement) { Memory.WriteInt32(Address, CurrentValue - 1); } Memory.ClearExclusiveForStore(ThreadState); } else { Memory.ClearExclusiveForStore(ThreadState); return(MakeError(ErrorModule.Kernel, KernelErr.InvalidState)); } break; } Memory.SetExclusive(ThreadState, Address); CurrentValue = Memory.ReadInt32(Address); } if (Timeout == 0) { return(MakeError(ErrorModule.Kernel, KernelErr.Timeout)); } return(WaitForAddress(Process, ThreadState, Address, Timeout)); }
public int ReadInt32() { int Value = Memory.ReadInt32(Position); Position += 4; return(Value); }
private int ReadCb(AMemory Memory, int Cbuf, int Offset) { long Position = ConstBuffers[Cbuf].Position; int Value = Memory.ReadInt32(Position + Offset); return(Value); }
private void FetchOpCode(AMemory Memory) { OpCode = PipeOp; PipeOp = Memory.ReadInt32(Pc); Pc += 4; }
private static int[] ReadWords(AMemory Memory, long Position, int Count) { int[] Words = new int[Count]; for (int Index = 0; Index < Count; Index++, Position += 4) { Words[Index] = Memory.ReadInt32(Position); } return(Words); }
private bool UserToKernelInt32(AMemory Memory, long Address, out int Value) { if (Memory.IsMapped(Address)) { Value = Memory.ReadInt32(Address); return(true); } Value = 0; return(false); }
public long ArbitrateLock( Process Process, AMemory Memory, int OwnerHandle, long MutexAddress, int RequesterHandle) { System.CriticalSectionLock.Lock(); KThread CurrentThread = System.Scheduler.GetCurrentThread(); CurrentThread.SignaledObj = null; CurrentThread.ObjSyncResult = 0; int MutexValue = Memory.ReadInt32(MutexAddress); if (MutexValue != (OwnerHandle | HasListenersMask)) { System.CriticalSectionLock.Unlock(); return(0); } KThread MutexOwner = Process.HandleTable.GetData <KThread>(OwnerHandle); if (MutexOwner == null) { System.CriticalSectionLock.Unlock(); return(MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle)); } CurrentThread.MutexAddress = MutexAddress; CurrentThread.ThreadHandleForUserMutex = RequesterHandle; MutexOwner.AddMutexWaiter(CurrentThread); CurrentThread.Reschedule(ThreadSchedState.Paused); System.CriticalSectionLock.Unlock(); System.CriticalSectionLock.Lock(); if (CurrentThread.MutexOwner != null) { CurrentThread.MutexOwner.TransferMutexTo(CurrentThread); } System.CriticalSectionLock.Unlock(); return((uint)CurrentThread.ObjSyncResult); }
private void SendTexture(AMemory Memory) { long TicPos = (long)GetRegister(NsGpuRegister._3dTicAddressHigh) << 32 | (long)GetRegister(NsGpuRegister._3dTicAddressLow) << 0; int CbData = GetRegister(NsGpuRegister._3dCbData0); int TicIndex = (CbData >> 0) & 0xfffff; int TscIndex = (CbData >> 20) & 0xfff; //I guess? TicPos = Gpu.MemoryMgr.GetCpuAddr(TicPos + TicIndex * 0x20); if (TicPos != -1) { int Word0 = Memory.ReadInt32(TicPos + 0x0); int Word1 = Memory.ReadInt32(TicPos + 0x4); int Word2 = Memory.ReadInt32(TicPos + 0x8); int Word3 = Memory.ReadInt32(TicPos + 0xc); int Word4 = Memory.ReadInt32(TicPos + 0x10); int Word5 = Memory.ReadInt32(TicPos + 0x14); int Word6 = Memory.ReadInt32(TicPos + 0x18); int Word7 = Memory.ReadInt32(TicPos + 0x1c); long TexAddress = Word1; TexAddress |= (long)(Word2 & 0xff) << 32; TexAddress = Gpu.MemoryMgr.GetCpuAddr(TexAddress); if (TexAddress != -1) { NsGpuTextureFormat Format = (NsGpuTextureFormat)(Word0 & 0x7f); int Width = (Word4 & 0xffff) + 1; int Height = (Word5 & 0xffff) + 1; byte[] Buffer = GetDecodedTexture(Memory, Format, TexAddress, Width, Height); if (Buffer != null) { Gpu.Renderer.QueueAction(delegate() { Gpu.Renderer.SendR8G8B8A8Texture(0, Buffer, Width, Height); }); } } } }
public void WaitForLock(AThread RequestingThread, int RequestingThreadHandle) { lock (EnterWaitLock) { int CurrentThreadHandle = Memory.ReadInt32(MutexAddress) & ~MutexHasListenersMask; if (CurrentThreadHandle == RequestingThreadHandle || CurrentThreadHandle == 0) { return; } if (CurrRequestingThreadHandle == 0 || RequestingThread.Priority < HighestPriority) { CurrRequestingThreadHandle = RequestingThreadHandle; HighestPriority = RequestingThread.Priority; } } ThreadEvent.Reset(); ThreadEvent.WaitOne(); }
public Executable(IExecutable Exe, AMemory Memory, long ImageBase) { this.Memory = Memory; this.ImageBase = ImageBase; this.ImageEnd = ImageBase; WriteData(ImageBase + Exe.TextOffset, Exe.Text, MemoryType.CodeStatic, AMemoryPerm.RX); WriteData(ImageBase + Exe.ROOffset, Exe.RO, MemoryType.Normal, AMemoryPerm.Read); WriteData(ImageBase + Exe.DataOffset, Exe.Data, MemoryType.Normal, AMemoryPerm.RW); if (Exe.Mod0Offset == 0) { MapBss(ImageBase + Exe.DataOffset + Exe.Data.Count, Exe.BssSize); return; } long Mod0Offset = ImageBase + Exe.Mod0Offset; int Mod0Magic = Memory.ReadInt32(Mod0Offset + 0x0); long DynamicOffset = Memory.ReadInt32(Mod0Offset + 0x4) + Mod0Offset; long BssStartOffset = Memory.ReadInt32(Mod0Offset + 0x8) + Mod0Offset; long BssEndOffset = Memory.ReadInt32(Mod0Offset + 0xc) + Mod0Offset; long EhHdrStartOffset = Memory.ReadInt32(Mod0Offset + 0x10) + Mod0Offset; long EhHdrEndOffset = Memory.ReadInt32(Mod0Offset + 0x14) + Mod0Offset; long ModObjOffset = Memory.ReadInt32(Mod0Offset + 0x18) + Mod0Offset; MapBss(BssStartOffset, BssEndOffset - BssStartOffset); ImageEnd = BssEndOffset; List <ElfDyn> Dynamic = new List <ElfDyn>(); while (true) { long TagVal = Memory.ReadInt64(DynamicOffset + 0); long Value = Memory.ReadInt64(DynamicOffset + 8); DynamicOffset += 0x10; ElfDynTag Tag = (ElfDynTag)TagVal; if (Tag == ElfDynTag.DT_NULL) { break; } Dynamic.Add(new ElfDyn(Tag, Value)); } this.Dynamic = Dynamic.ToArray(); }
public static AOpCode DecodeOpCode(AMemory Memory, long Position) { int OpCode = Memory.ReadInt32(Position); AInst Inst = AOpCodeTable.GetInst(OpCode); AOpCode DecodedOpCode = new AOpCode(AInst.Undefined, Position, OpCode); if (Inst.Type != null) { DecodedOpCode = CreateOpCode(Inst.Type, Inst, Position, OpCode); } return(DecodedOpCode); }
private ElfSym GetSymbol(long Position, long StrTblAddr) { int NameIndex = Memory.ReadInt32(Position + 0); int Info = Memory.ReadByte(Position + 4); int Other = Memory.ReadByte(Position + 5); int SHIdx = Memory.ReadInt16(Position + 6); long Value = Memory.ReadInt64(Position + 8); long Size = Memory.ReadInt64(Position + 16); string Name = string.Empty; for (int Chr; (Chr = Memory.ReadByte(StrTblAddr + NameIndex++)) != 0;) { Name += (char)Chr; } return(new ElfSym(Name, Info, Other, SHIdx, Value, Size)); }
private void UploadTexture(AMemory Memory, long BasePosition, int TexIndex, int HndIndex) { long Position = BasePosition + HndIndex * 4; int TextureHandle = Memory.ReadInt32(Position); int TicIndex = (TextureHandle >> 0) & 0xfffff; int TscIndex = (TextureHandle >> 20) & 0xfff; TryGetCpuAddr(NvGpuEngine3dReg.TexHeaderPoolOffset, out long TicPosition); TryGetCpuAddr(NvGpuEngine3dReg.TexSamplerPoolOffset, out long TscPosition); TicPosition += TicIndex * 0x20; TscPosition += TscIndex * 0x20; Gpu.Renderer.SetTexture(TexIndex, TextureFactory.MakeTexture(Gpu, Memory, TicPosition)); Gpu.Renderer.SetSampler(TexIndex, TextureFactory.MakeSampler(Gpu, Memory, TscPosition)); }
public long SignalAndIncrementIfEqual(AMemory Memory, long Address, int Value, int Count) { System.CriticalSectionLock.Lock(); Memory.SetExclusive(0, Address); if (!UserToKernelInt32(Memory, Address, out int CurrentValue)) { System.CriticalSectionLock.Unlock(); return(MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm)); } while (CurrentValue == Value) { if (Memory.TestExclusive(0, Address)) { Memory.WriteInt32(Address, CurrentValue + 1); Memory.ClearExclusiveForStore(0); break; } Memory.SetExclusive(0, Address); CurrentValue = Memory.ReadInt32(Address); } Memory.ClearExclusive(0); if (CurrentValue != Value) { System.CriticalSectionLock.Unlock(); return(MakeError(ErrorModule.Kernel, KernelErr.InvalidState)); } WakeArbiterThreads(Address, Count); System.CriticalSectionLock.Unlock(); return(0); }
public static ulong WaitForAddressIfEqual(Process Process, AThreadState ThreadState, AMemory Memory, long Address, int Value, ulong Timeout) { if (Memory.ReadInt32(Address) != Value) { return(MakeError(ErrorModule.Kernel, KernelErr.InvalidState)); } if (Timeout == 0) { return(MakeError(ErrorModule.Kernel, KernelErr.Timeout)); } return(WaitForAddress(Process, ThreadState, Address, Timeout)); }
public void WaitForSignal(int ThreadHandle) { int Count = Memory.ReadInt32(CondVarAddress); if (Count <= 0) { return; } Memory.WriteInt32(CondVarAddress, Count - 1); ManualResetEvent Event = new ManualResetEvent(false); WaitingThreads.Enqueue(new WaitingThread(ThreadHandle, Event)); if (Timeout != -1) { Event.WaitOne((int)(Timeout / 1000000)); } else { Event.WaitOne(); } }
public Executable(IExecutable Exe, AMemory Memory, long ImageBase) { Dynamic = new List <ElfDyn>(); m_SymbolTable = new Dictionary <long, string>(); Name = Exe.Name; this.Memory = Memory; this.ImageBase = ImageBase; this.ImageEnd = ImageBase; WriteData(ImageBase + Exe.TextOffset, Exe.Text, MemoryType.CodeStatic, AMemoryPerm.RX); WriteData(ImageBase + Exe.ROOffset, Exe.RO, MemoryType.CodeMutable, AMemoryPerm.Read); WriteData(ImageBase + Exe.DataOffset, Exe.Data, MemoryType.CodeMutable, AMemoryPerm.RW); if (Exe.Mod0Offset == 0) { int BssOffset = Exe.DataOffset + Exe.Data.Length; int BssSize = Exe.BssSize; MapBss(ImageBase + BssOffset, BssSize); ImageEnd = ImageBase + BssOffset + BssSize; return; } long Mod0Offset = ImageBase + Exe.Mod0Offset; int Mod0Magic = Memory.ReadInt32(Mod0Offset + 0x0); long DynamicOffset = Memory.ReadInt32(Mod0Offset + 0x4) + Mod0Offset; long BssStartOffset = Memory.ReadInt32(Mod0Offset + 0x8) + Mod0Offset; long BssEndOffset = Memory.ReadInt32(Mod0Offset + 0xc) + Mod0Offset; long EhHdrStartOffset = Memory.ReadInt32(Mod0Offset + 0x10) + Mod0Offset; long EhHdrEndOffset = Memory.ReadInt32(Mod0Offset + 0x14) + Mod0Offset; long ModObjOffset = Memory.ReadInt32(Mod0Offset + 0x18) + Mod0Offset; MapBss(BssStartOffset, BssEndOffset - BssStartOffset); ImageEnd = BssEndOffset; while (true) { long TagVal = Memory.ReadInt64(DynamicOffset + 0); long Value = Memory.ReadInt64(DynamicOffset + 8); DynamicOffset += 0x10; ElfDynTag Tag = (ElfDynTag)TagVal; if (Tag == ElfDynTag.DT_NULL) { break; } Dynamic.Add(new ElfDyn(Tag, Value)); } long StrTblAddr = ImageBase + GetFirstValue(ElfDynTag.DT_STRTAB); long SymTblAddr = ImageBase + GetFirstValue(ElfDynTag.DT_SYMTAB); long SymEntSize = GetFirstValue(ElfDynTag.DT_SYMENT); while ((ulong)SymTblAddr < (ulong)StrTblAddr) { ElfSym Sym = GetSymbol(SymTblAddr, StrTblAddr); m_SymbolTable.TryAdd(Sym.Value, Sym.Name); SymTblAddr += SymEntSize; } }
public long WaitForAddressIfLessThan( AMemory Memory, long Address, int Value, bool ShouldDecrement, long Timeout) { KThread CurrentThread = System.Scheduler.GetCurrentThread(); System.CriticalSectionLock.Lock(); if (CurrentThread.ShallBeTerminated || CurrentThread.SchedFlags == ThreadSchedState.TerminationPending) { System.CriticalSectionLock.Unlock(); return(MakeError(ErrorModule.Kernel, KernelErr.ThreadTerminating)); } CurrentThread.SignaledObj = null; CurrentThread.ObjSyncResult = (int)MakeError(ErrorModule.Kernel, KernelErr.Timeout); //If ShouldDecrement is true, do atomic decrement of the value at Address. Memory.SetExclusive(0, Address); if (!UserToKernelInt32(Memory, Address, out int CurrentValue)) { System.CriticalSectionLock.Unlock(); return(MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm)); } if (ShouldDecrement) { while (CurrentValue < Value) { if (Memory.TestExclusive(0, Address)) { Memory.WriteInt32(Address, CurrentValue - 1); Memory.ClearExclusiveForStore(0); break; } Memory.SetExclusive(0, Address); CurrentValue = Memory.ReadInt32(Address); } } Memory.ClearExclusive(0); if (CurrentValue < Value) { if (Timeout == 0) { System.CriticalSectionLock.Unlock(); return(MakeError(ErrorModule.Kernel, KernelErr.Timeout)); } CurrentThread.MutexAddress = Address; CurrentThread.WaitingInArbitration = true; InsertSortedByPriority(ArbiterThreads, CurrentThread); CurrentThread.Reschedule(ThreadSchedState.Paused); if (Timeout > 0) { System.TimeManager.ScheduleFutureInvocation(CurrentThread, Timeout); } System.CriticalSectionLock.Unlock(); if (Timeout > 0) { System.TimeManager.UnscheduleFutureInvocation(CurrentThread); } System.CriticalSectionLock.Lock(); if (CurrentThread.WaitingInArbitration) { ArbiterThreads.Remove(CurrentThread); CurrentThread.WaitingInArbitration = false; } System.CriticalSectionLock.Unlock(); return(CurrentThread.ObjSyncResult); } System.CriticalSectionLock.Unlock(); return(MakeError(ErrorModule.Kernel, KernelErr.InvalidState)); }
public long SignalAndModifyIfEqual(AMemory Memory, long Address, int Value, int Count) { System.CriticalSectionLock.Lock(); int Offset; //The value is decremented if the number of threads waiting is less //or equal to the Count of threads to be signaled, or Count is zero //or negative. It is incremented if there are no threads waiting. int WaitingCount = 0; foreach (KThread Thread in ArbiterThreads.Where(x => x.MutexAddress == Address)) { if (++WaitingCount > Count) { break; } } if (WaitingCount > 0) { Offset = WaitingCount <= Count || Count <= 0 ? -1 : 0; } else { Offset = 1; } Memory.SetExclusive(0, Address); if (!UserToKernelInt32(Memory, Address, out int CurrentValue)) { System.CriticalSectionLock.Unlock(); return(MakeError(ErrorModule.Kernel, KernelErr.NoAccessPerm)); } while (CurrentValue == Value) { if (Memory.TestExclusive(0, Address)) { Memory.WriteInt32(Address, CurrentValue + Offset); Memory.ClearExclusiveForStore(0); break; } Memory.SetExclusive(0, Address); CurrentValue = Memory.ReadInt32(Address); } Memory.ClearExclusive(0); if (CurrentValue != Value) { System.CriticalSectionLock.Unlock(); return(MakeError(ErrorModule.Kernel, KernelErr.InvalidState)); } WakeArbiterThreads(Address, Count); System.CriticalSectionLock.Unlock(); return(0); }
public Executable(IExecutable Exe, KMemoryManager MemoryManager, AMemory Memory, long ImageBase) { Dynamic = new List <ElfDyn>(); FilePath = Exe.FilePath; if (FilePath != null) { Name = Path.GetFileNameWithoutExtension(FilePath.Replace(Homebrew.TemporaryNroSuffix, "")); } this.Memory = Memory; this.MemoryManager = MemoryManager; this.ImageBase = ImageBase; this.ImageEnd = ImageBase; long TextPosition = ImageBase + (uint)Exe.TextOffset; long ROPosition = ImageBase + (uint)Exe.ROOffset; long DataPosition = ImageBase + (uint)Exe.DataOffset; long TextSize = (uint)IntUtils.AlignUp(Exe.Text.Length, KMemoryManager.PageSize); long ROSize = (uint)IntUtils.AlignUp(Exe.RO.Length, KMemoryManager.PageSize); long DataSize = (uint)IntUtils.AlignUp(Exe.Data.Length, KMemoryManager.PageSize); long DataAndBssSize = (uint)IntUtils.AlignUp(Exe.BssSize, KMemoryManager.PageSize) + DataSize; ImageEnd = DataPosition + DataAndBssSize; MemoryManager.HleMapProcessCode(TextPosition, TextSize + ROSize + DataAndBssSize); MemoryManager.SetProcessMemoryPermission(ROPosition, ROSize, MemoryPermission.Read); MemoryManager.SetProcessMemoryPermission(DataPosition, DataAndBssSize, MemoryPermission.ReadAndWrite); Memory.WriteBytes(TextPosition, Exe.Text); Memory.WriteBytes(ROPosition, Exe.RO); Memory.WriteBytes(DataPosition, Exe.Data); if (Exe.Mod0Offset == 0) { return; } long Mod0Offset = ImageBase + Exe.Mod0Offset; int Mod0Magic = Memory.ReadInt32(Mod0Offset + 0x0); long DynamicOffset = Memory.ReadInt32(Mod0Offset + 0x4) + Mod0Offset; long BssStartOffset = Memory.ReadInt32(Mod0Offset + 0x8) + Mod0Offset; long BssEndOffset = Memory.ReadInt32(Mod0Offset + 0xc) + Mod0Offset; long EhHdrStartOffset = Memory.ReadInt32(Mod0Offset + 0x10) + Mod0Offset; long EhHdrEndOffset = Memory.ReadInt32(Mod0Offset + 0x14) + Mod0Offset; long ModObjOffset = Memory.ReadInt32(Mod0Offset + 0x18) + Mod0Offset; while (true) { long TagVal = Memory.ReadInt64(DynamicOffset + 0); long Value = Memory.ReadInt64(DynamicOffset + 8); DynamicOffset += 0x10; ElfDynTag Tag = (ElfDynTag)TagVal; if (Tag == ElfDynTag.DT_NULL) { break; } Dynamic.Add(new ElfDyn(Tag, Value)); } long StrTblAddr = ImageBase + GetFirstValue(ElfDynTag.DT_STRTAB); long SymTblAddr = ImageBase + GetFirstValue(ElfDynTag.DT_SYMTAB); long SymEntSize = GetFirstValue(ElfDynTag.DT_SYMENT); List <ElfSym> Symbols = new List <ElfSym>(); while ((ulong)SymTblAddr < (ulong)StrTblAddr) { ElfSym Sym = GetSymbol(SymTblAddr, StrTblAddr); Symbols.Add(Sym); SymTblAddr += SymEntSize; } SymbolTable = Array.AsReadOnly(Symbols.OrderBy(x => x.Value).ToArray()); }
private KThread TryAcquireMutex(Process Process, AMemory Memory, KThread Requester) { int Core = Requester.CurrentCore; long Address = Requester.MutexAddress; Memory.SetExclusive(Core, Address); int MutexValue = Memory.ReadInt32(Address); while (MutexValue != 0) { if (Memory.TestExclusive(Core, Address)) { if (MutexValue != 0) { //Update value to indicate there is a mutex waiter now. Memory.WriteInt32(Address, MutexValue | HasListenersMask); } else { //No thread owning the mutex, assign to requesting thread. Memory.WriteInt32(Address, Requester.ThreadHandleForUserMutex); } Memory.ClearExclusiveForStore(Core); break; } Memory.SetExclusive(Core, Address); MutexValue = Memory.ReadInt32(Address); } if (MutexValue == 0) { //We now own the mutex. Requester.SignaledObj = null; Requester.ObjSyncResult = 0; Requester.ReleaseAndResume(); return(null); } MutexValue &= ~HasListenersMask; KThread MutexOwner = Process.HandleTable.GetData <KThread>(MutexValue); if (MutexOwner != null) { //Mutex already belongs to another thread, wait for it. MutexOwner.AddMutexWaiter(Requester); } else { //Invalid mutex owner. Requester.SignaledObj = null; Requester.ObjSyncResult = (int)MakeError(ErrorModule.Kernel, KernelErr.InvalidHandle); Requester.ReleaseAndResume(); } return(MutexOwner); }