Example #1
0
        public int GetId()
        {
            lock (_idMasks)
            {
                int id = 0;

                if (!TestBit(_nextFreeBitHint))
                {
                    id = _nextFreeBitHint;
                }
                else
                {
                    for (int index = 0; index < IdMasksCount; index++)
                    {
                        int mask = _idMasks[index];

                        int firstFreeBit = BitUtils.CountLeadingZeros32((mask + 1) & ~mask);

                        if (firstFreeBit < 32)
                        {
                            int baseBit = index * 32 + 31;

                            id = baseBit - firstFreeBit;

                            break;
                        }
                        else if (index == IdMasksCount - 1)
                        {
                            throw new InvalidOperationException("Maximum number of Ids reached!");
                        }
                    }
                }

                _nextFreeBitHint = id + 1;

                SetBit(id);

                return(id);
            }
        }
Example #2
0
        public int GetId()
        {
            lock (IdMasks)
            {
                int Id = 0;

                if (!TestBit(NextFreeBitHint))
                {
                    Id = NextFreeBitHint;
                }
                else
                {
                    for (int Index = 0; Index < IdMasksCount; Index++)
                    {
                        int Mask = IdMasks[Index];

                        int FirstFreeBit = BitUtils.CountLeadingZeros32((Mask + 1) & ~Mask);

                        if (FirstFreeBit < 32)
                        {
                            int BaseBit = Index * 32 + 31;

                            Id = BaseBit - FirstFreeBit;

                            break;
                        }
                        else if (Index == IdMasksCount - 1)
                        {
                            throw new InvalidOperationException("Maximum number of Ids reached!");
                        }
                    }
                }

                NextFreeBitHint = Id + 1;

                SetBit(Id);

                return(Id);
            }
        }
Example #3
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 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);
        }