Example #1
0
        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);
        }
Example #2
0
        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));
        }
Example #3
0
        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));
        }
Example #4
0
        public KernelResult InitializeForKernel(int[] caps, KMemoryManager memoryManager)
        {
            AllowedCpuCoresMask    = 0xf;
            AllowedThreadPriosMask = -1;
            DebuggingFlags        &= ~3;
            KernelReleaseVersion   = KProcess.KernelVersionPacked;

            return(Parse(caps, memoryManager));
        }
Example #5
0
        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;
        }
Example #6
0
        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));
        }
Example #7
0
        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));
        }
Example #8
0
        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);
        }
Example #9
0
 public KernelResult InitializeForUser(int[] caps, KMemoryManager memoryManager)
 {
     return(Parse(caps, memoryManager));
 }
Example #10
0
        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);
        }