public KProcess(Horizon system) : base(system) { _processLock = new object(); _threadingLock = new object(); CpuMemory = new MemoryManager(system.Device.Memory.RamPointer); CpuMemory.InvalidAccess += InvalidAccessHandler; AddressArbiter = new KAddressArbiter(system); MemoryManager = new KMemoryManager(system, CpuMemory); _fullTlsPages = new SortedDictionary <ulong, KTlsPageInfo>(); _freeTlsPages = new SortedDictionary <ulong, KTlsPageInfo>(); Capabilities = new KProcessCapabilities(); RandomEntropy = new long[KScheduler.CpuCoresCount]; _threads = new LinkedList <KThread>(); Translator = new Translator(); Translator.CpuTrace += CpuTraceHandler; _svcHandler = new SvcHandler(system.Device, this); Debugger = new HleProcessDebugger(this); }
public KernelResult MapIntoProcess( KMemoryManager MemoryManager, ulong Address, ulong Size, KProcess Process, MemoryPermission Permission) { ulong PagesCountRounded = BitUtils.DivRoundUp(Size, KMemoryManager.PageSize); if (PageList.GetPagesCount() != PagesCountRounded) { return(KernelResult.InvalidSize); } MemoryPermission ExpectedPermission = Process.Pid == OwnerPid ? OwnerPermission : UserPermission; if (Permission != ExpectedPermission) { return(KernelResult.InvalidPermission); } return(MemoryManager.MapPages(Address, PageList, MemoryState.SharedMemory, Permission)); }
public KernelResult MapIntoProcess( KMemoryManager memoryManager, ulong address, ulong size, KProcess process, MemoryPermission permission) { ulong pagesCountRounded = BitUtils.DivRoundUp(size, KMemoryManager.PageSize); if (_pageList.GetPagesCount() != pagesCountRounded) { return(KernelResult.InvalidSize); } MemoryPermission expectedPermission = process.Pid == _ownerPid ? _ownerPermission : _userPermission; if (permission != expectedPermission) { return(KernelResult.InvalidPermission); } return(memoryManager.MapPages(address, _pageList, MemoryState.SharedMemory, permission)); }
public KernelResult InitializeForKernel(int[] caps, KMemoryManager memoryManager) { AllowedCpuCoresMask = 0xf; AllowedThreadPriosMask = -1; DebuggingFlags &= ~3; KernelReleaseVersion = KProcess.KernelVersionPacked; return(Parse(caps, memoryManager)); }
public KernelContext( ITickSource tickSource, Switch device, MemoryBlock memory, MemorySize memorySize, MemoryArrange memoryArrange) { TickSource = tickSource; Device = device; Memory = memory; Running = true; Syscall = new Syscall(this); SyscallHandler = new SyscallHandler(this); ResourceLimit = new KResourceLimit(this); KernelInit.InitializeResourceLimit(ResourceLimit, memorySize); MemoryManager = new KMemoryManager(memorySize, memoryArrange); LargeMemoryBlockSlabManager = new KMemoryBlockSlabManager(KernelConstants.MemoryBlockAllocatorSize * 2); SmallMemoryBlockSlabManager = new KMemoryBlockSlabManager(KernelConstants.MemoryBlockAllocatorSize); UserSlabHeapPages = new KSlabHeap( KernelConstants.UserSlabHeapBase, KernelConstants.UserSlabHeapItemSize, KernelConstants.UserSlabHeapSize); memory.Commit(KernelConstants.UserSlabHeapBase - DramMemoryMap.DramBase, KernelConstants.UserSlabHeapSize); CriticalSection = new KCriticalSection(this); Schedulers = new KScheduler[KScheduler.CpuCoresCount]; PriorityQueue = new KPriorityQueue(); TimeManager = new KTimeManager(this); Synchronization = new KSynchronization(this); ContextIdManager = new KContextIdManager(); for (int core = 0; core < KScheduler.CpuCoresCount; core++) { Schedulers[core] = new KScheduler(this, core); } StartPreemptionThread(); KernelInitialized = true; Processes = new ConcurrentDictionary <ulong, KProcess>(); AutoObjectNames = new ConcurrentDictionary <string, KAutoObject>(); _kipId = KernelConstants.InitialKipId; _processId = KernelConstants.InitialProcessId; }
public KernelResult UnmapFromProcess( KMemoryManager MemoryManager, ulong Address, ulong Size, KProcess Process) { ulong PagesCountRounded = BitUtils.DivRoundUp(Size, KMemoryManager.PageSize); if (PageList.GetPagesCount() != PagesCountRounded) { return(KernelResult.InvalidSize); } return(MemoryManager.UnmapPages(Address, PageList, MemoryState.SharedMemory)); }
public KernelResult UnmapFromProcess( KMemoryManager memoryManager, ulong address, ulong size, KProcess process) { ulong pagesCountRounded = BitUtils.DivRoundUp(size, KMemoryManager.PageSize); if (_pageList.GetPagesCount() != pagesCountRounded) { return(KernelResult.InvalidSize); } return(memoryManager.UnmapPages(address, _pageList, MemoryState.SharedMemory)); }
private KernelResult Parse(int[] caps, KMemoryManager memoryManager) { int mask0 = 0; int mask1 = 0; for (int index = 0; index < caps.Length; index++) { int cap = caps[index]; if (((cap + 1) & ~cap) != 0x40) { KernelResult result = ParseCapability(cap, ref mask0, ref mask1, memoryManager); if (result != KernelResult.Success) { return(result); } } else { if ((uint)index + 1 >= caps.Length) { return(KernelResult.InvalidCombination); } int prevCap = cap; cap = caps[++index]; if (((cap + 1) & ~cap) != 0x40) { return(KernelResult.InvalidCombination); } if ((cap & 0x78000000) != 0) { return(KernelResult.MaximumExceeded); } if ((cap & 0x7ffff80) == 0) { return(KernelResult.InvalidSize); } long address = ((long)(uint)prevCap << 5) & 0xffffff000; long size = ((long)(uint)cap << 5) & 0xfffff000; if (((ulong)(address + size - 1) >> 36) != 0) { return(KernelResult.InvalidAddress); } MemoryPermission perm = (prevCap >> 31) != 0 ? MemoryPermission.Read : MemoryPermission.ReadAndWrite; KernelResult result; if ((cap >> 31) != 0) { result = memoryManager.MapNormalMemory(address, size, perm); } else { result = memoryManager.MapIoMemory(address, size, perm); } if (result != KernelResult.Success) { return(result); } } } return(KernelResult.Success); }
public KernelResult InitializeForUser(int[] caps, KMemoryManager memoryManager) { return(Parse(caps, memoryManager)); }
private KernelResult ParseCapability(int cap, ref int mask0, ref int mask1, KMemoryManager memoryManager) { int code = (cap + 1) & ~cap; if (code == 1) { return(KernelResult.InvalidCapability); } else if (code == 0) { return(KernelResult.Success); } int codeMask = 1 << (32 - BitUtils.CountLeadingZeros32(code + 1)); //Check if the property was already set. if (((mask0 & codeMask) & 0x1e008) != 0) { return(KernelResult.InvalidCombination); } mask0 |= codeMask; switch (code) { case 8: { if (AllowedCpuCoresMask != 0 || AllowedThreadPriosMask != 0) { return(KernelResult.InvalidCapability); } int lowestCpuCore = (cap >> 16) & 0xff; int highestCpuCore = (cap >> 24) & 0xff; if (lowestCpuCore > highestCpuCore) { return(KernelResult.InvalidCombination); } int highestThreadPrio = (cap >> 4) & 0x3f; int lowestThreadPrio = (cap >> 10) & 0x3f; if (lowestThreadPrio > highestThreadPrio) { return(KernelResult.InvalidCombination); } if (highestCpuCore >= KScheduler.CpuCoresCount) { return(KernelResult.InvalidCpuCore); } AllowedCpuCoresMask = GetMaskFromMinMax(lowestCpuCore, highestCpuCore); AllowedThreadPriosMask = GetMaskFromMinMax(lowestThreadPrio, highestThreadPrio); break; } case 0x10: { int slot = (cap >> 29) & 7; int svcSlotMask = 1 << slot; if ((mask1 & svcSlotMask) != 0) { return(KernelResult.InvalidCombination); } mask1 |= svcSlotMask; int svcMask = (cap >> 5) & 0xffffff; int baseSvc = slot * 24; for (int index = 0; index < 24; index++) { if (((svcMask >> index) & 1) == 0) { continue; } int svcId = baseSvc + index; if (svcId > 0x7f) { return(KernelResult.MaximumExceeded); } SvcAccessMask[svcId / 8] |= (byte)(1 << (svcId & 7)); } break; } case 0x80: { long address = ((long)(uint)cap << 4) & 0xffffff000; memoryManager.MapIoMemory(address, KMemoryManager.PageSize, MemoryPermission.ReadAndWrite); break; } case 0x800: { //TODO: GIC distributor check. int irq0 = (cap >> 12) & 0x3ff; int irq1 = (cap >> 22) & 0x3ff; if (irq0 != 0x3ff) { IrqAccessMask[irq0 / 8] |= (byte)(1 << (irq0 & 7)); } if (irq1 != 0x3ff) { IrqAccessMask[irq1 / 8] |= (byte)(1 << (irq1 & 7)); } break; } case 0x2000: { int applicationType = cap >> 14; if ((uint)applicationType > 7) { return(KernelResult.ReservedValue); } ApplicationType = applicationType; break; } case 0x4000: { //Note: This check is bugged on kernel too, we are just replicating the bug here. if ((KernelReleaseVersion >> 17) != 0 || cap < 0x80000) { return(KernelResult.ReservedValue); } KernelReleaseVersion = cap; break; } case 0x8000: { int handleTableSize = cap >> 26; if ((uint)handleTableSize > 0x3ff) { return(KernelResult.ReservedValue); } HandleTableSize = handleTableSize; break; } case 0x10000: { int debuggingFlags = cap >> 19; if ((uint)debuggingFlags > 3) { return(KernelResult.ReservedValue); } DebuggingFlags &= ~3; DebuggingFlags |= debuggingFlags; break; } default: return(KernelResult.InvalidCapability); } return(KernelResult.Success); }
private KernelResult Parse(int[] Caps, KMemoryManager MemoryManager) { int Mask0 = 0; int Mask1 = 0; for (int Index = 0; Index < Caps.Length; Index++) { int Cap = Caps[Index]; if (((Cap + 1) & ~Cap) != 0x40) { KernelResult Result = ParseCapability(Cap, ref Mask0, ref Mask1, MemoryManager); if (Result != KernelResult.Success) { return(Result); } } else { if ((uint)Index + 1 >= Caps.Length) { return(KernelResult.InvalidCombination); } int PrevCap = Cap; Cap = Caps[++Index]; if (((Cap + 1) & ~Cap) != 0x40) { return(KernelResult.InvalidCombination); } if ((Cap & 0x78000000) != 0) { return(KernelResult.MaximumExceeded); } if ((Cap & 0x7ffff80) == 0) { return(KernelResult.InvalidSize); } long Address = ((long)(uint)PrevCap << 5) & 0xffffff000; long Size = ((long)(uint)Cap << 5) & 0xfffff000; if (((ulong)(Address + Size - 1) >> 36) != 0) { return(KernelResult.InvalidAddress); } MemoryPermission Perm = (PrevCap >> 31) != 0 ? MemoryPermission.Read : MemoryPermission.ReadAndWrite; KernelResult Result; if ((Cap >> 31) != 0) { Result = MemoryManager.MapNormalMemory(Address, Size, Perm); } else { Result = MemoryManager.MapIoMemory(Address, Size, Perm); } if (Result != KernelResult.Success) { return(Result); } } } return(KernelResult.Success); }
public KernelResult InitializeForUser(int[] Caps, KMemoryManager MemoryManager) { return(Parse(Caps, MemoryManager)); }
private KernelResult ParseCapability(int Cap, ref int Mask0, ref int Mask1, KMemoryManager MemoryManager) { int Code = (Cap + 1) & ~Cap; if (Code == 1) { return(KernelResult.InvalidCapability); } else if (Code == 0) { return(KernelResult.Success); } int CodeMask = 1 << (32 - BitUtils.CountLeadingZeros32(Code + 1)); //Check if the property was already set. if (((Mask0 & CodeMask) & 0x1e008) != 0) { return(KernelResult.InvalidCombination); } Mask0 |= CodeMask; switch (Code) { case 8: { if (AllowedCpuCoresMask != 0 || AllowedThreadPriosMask != 0) { return(KernelResult.InvalidCapability); } int LowestCpuCore = (Cap >> 16) & 0xff; int HighestCpuCore = (Cap >> 24) & 0xff; if (LowestCpuCore > HighestCpuCore) { return(KernelResult.InvalidCombination); } int HighestThreadPrio = (Cap >> 4) & 0x3f; int LowestThreadPrio = (Cap >> 10) & 0x3f; if (LowestThreadPrio > HighestThreadPrio) { return(KernelResult.InvalidCombination); } if (HighestCpuCore >= KScheduler.CpuCoresCount) { return(KernelResult.InvalidCpuCore); } AllowedCpuCoresMask = GetMaskFromMinMax(LowestCpuCore, HighestCpuCore); AllowedThreadPriosMask = GetMaskFromMinMax(LowestThreadPrio, HighestThreadPrio); break; } case 0x10: { int Slot = (Cap >> 29) & 7; int SvcSlotMask = 1 << Slot; if ((Mask1 & SvcSlotMask) != 0) { return(KernelResult.InvalidCombination); } Mask1 |= SvcSlotMask; int SvcMask = (Cap >> 5) & 0xffffff; int BaseSvc = Slot * 24; for (int Index = 0; Index < 24; Index++) { if (((SvcMask >> Index) & 1) == 0) { continue; } int SvcId = BaseSvc + Index; if (SvcId > 0x7f) { return(KernelResult.MaximumExceeded); } SvcAccessMask[SvcId / 8] |= (byte)(1 << (SvcId & 7)); } break; } case 0x80: { long Address = ((long)(uint)Cap << 4) & 0xffffff000; MemoryManager.MapIoMemory(Address, KMemoryManager.PageSize, MemoryPermission.ReadAndWrite); break; } case 0x800: { //TODO: GIC distributor check. int Irq0 = (Cap >> 12) & 0x3ff; int Irq1 = (Cap >> 22) & 0x3ff; if (Irq0 != 0x3ff) { IrqAccessMask[Irq0 / 8] |= (byte)(1 << (Irq0 & 7)); } if (Irq1 != 0x3ff) { IrqAccessMask[Irq1 / 8] |= (byte)(1 << (Irq1 & 7)); } break; } case 0x2000: { int ApplicationType = Cap >> 14; if ((uint)ApplicationType > 7) { return(KernelResult.ReservedValue); } this.ApplicationType = ApplicationType; break; } case 0x4000: { //Note: This check is bugged on kernel too, we are just replicating the bug here. if ((KernelReleaseVersion >> 17) != 0 || Cap < 0x80000) { return(KernelResult.ReservedValue); } KernelReleaseVersion = Cap; break; } case 0x8000: { int HandleTableSize = Cap >> 26; if ((uint)HandleTableSize > 0x3ff) { return(KernelResult.ReservedValue); } this.HandleTableSize = HandleTableSize; break; } case 0x10000: { int DebuggingFlags = Cap >> 19; if ((uint)DebuggingFlags > 3) { return(KernelResult.ReservedValue); } this.DebuggingFlags &= ~3; this.DebuggingFlags |= DebuggingFlags; break; } default: return(KernelResult.InvalidCapability); } return(KernelResult.Success); }