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); } }
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); } }
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); }