public Horizon(Switch Device) { this.Device = Device; Processes = new ConcurrentDictionary <int, Process>(); State = new SystemStateMgr(); Scheduler = new KScheduler(); TimeManager = new KTimeManager(); AddressArbiter = new KAddressArbiter(this); Synchronization = new KSynchronization(this); CriticalSectionLock = new KRecursiveLock(this); if (!Device.Memory.Allocator.TryAllocate(HidSize, out long HidPA) || !Device.Memory.Allocator.TryAllocate(FontSize, out long FontPA)) { throw new InvalidOperationException(); } HidSharedMem = new KSharedMemory(HidPA, HidSize); FontSharedMem = new KSharedMemory(FontPA, FontSize); Font = new SharedFontManager(Device, FontSharedMem.PA); VsyncEvent = new KEvent(this); }
private KernelResult CreateThread( ulong entrypoint, ulong argsPtr, ulong stackTop, int priority, int cpuCore, out int handle) { handle = 0; KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); if (cpuCore == -2) { cpuCore = currentProcess.DefaultCpuCore; } if ((uint)cpuCore >= KScheduler.CpuCoresCount || !currentProcess.IsCpuCoreAllowed(cpuCore)) { return(KernelResult.InvalidCpuCore); } if ((uint)priority >= KScheduler.PrioritiesCount || !currentProcess.IsPriorityAllowed(priority)) { return(KernelResult.InvalidPriority); } long timeout = KTimeManager.ConvertMillisecondsToNanoseconds(100); if (currentProcess.ResourceLimit != null && !currentProcess.ResourceLimit.Reserve(LimitableResource.Thread, 1, timeout)) { return(KernelResult.ResLimitExceeded); } KThread thread = new KThread(_system); KernelResult result = currentProcess.InitializeThread( thread, entrypoint, argsPtr, stackTop, priority, cpuCore); if (result == KernelResult.Success) { result = _process.HandleTable.GenerateHandle(thread, out handle); } else { currentProcess.ResourceLimit?.Release(LimitableResource.Thread, 1); } thread.DecrementReferenceCount(); return(result); }
public Horizon(Switch device, ContentManager contentManager) { ControlData = new BlitStruct <ApplicationControlProperty>(1); Device = device; State = new SystemStateMgr(); ResourceLimit = new KResourceLimit(this); KernelInit.InitializeResourceLimit(ResourceLimit); MemoryRegions = KernelInit.GetMemoryRegions(); LargeMemoryBlockAllocator = new KMemoryBlockAllocator(MemoryBlockAllocatorSize * 2); SmallMemoryBlockAllocator = new KMemoryBlockAllocator(MemoryBlockAllocatorSize); UserSlabHeapPages = new KSlabHeap( UserSlabHeapBase, UserSlabHeapItemSize, UserSlabHeapSize); CriticalSection = new KCriticalSection(this); Scheduler = new KScheduler(this); TimeManager = new KTimeManager(); Synchronization = new KSynchronization(this); ContextIdManager = new KContextIdManager(); _kipId = InitialKipId; _processId = InitialProcessId; Scheduler.StartAutoPreemptionThread(); KernelInitialized = true; ThreadCounter = new CountdownEvent(1); Processes = new SortedDictionary <long, KProcess>(); AutoObjectNames = new ConcurrentDictionary <string, KAutoObject>(); // Note: This is not really correct, but with HLE of services, the only memory // region used that is used is Application, so we can use the other ones for anything. KMemoryRegionManager region = MemoryRegions[(int)MemoryRegion.NvServices]; ulong hidPa = region.Address; ulong fontPa = region.Address + HidSize; ulong iirsPa = region.Address + HidSize + FontSize; ulong timePa = region.Address + HidSize + FontSize + IirsSize; HidBaseAddress = (long)(hidPa - DramMemoryMap.DramBase); KPageList hidPageList = new KPageList(); KPageList fontPageList = new KPageList(); KPageList iirsPageList = new KPageList(); KPageList timePageList = new KPageList(); hidPageList.AddRange(hidPa, HidSize / KMemoryManager.PageSize); fontPageList.AddRange(fontPa, FontSize / KMemoryManager.PageSize); iirsPageList.AddRange(iirsPa, IirsSize / KMemoryManager.PageSize); timePageList.AddRange(timePa, TimeSize / KMemoryManager.PageSize); HidSharedMem = new KSharedMemory(this, hidPageList, 0, 0, MemoryPermission.Read); FontSharedMem = new KSharedMemory(this, fontPageList, 0, 0, MemoryPermission.Read); IirsSharedMem = new KSharedMemory(this, iirsPageList, 0, 0, MemoryPermission.Read); KSharedMemory timeSharedMemory = new KSharedMemory(this, timePageList, 0, 0, MemoryPermission.Read); TimeServiceManager.Instance.Initialize(device, this, timeSharedMemory, (long)(timePa - DramMemoryMap.DramBase), TimeSize); AppletState = new AppletStateMgr(this); AppletState.SetFocus(true); Font = new SharedFontManager(device, (long)(fontPa - DramMemoryMap.DramBase)); IUserInterface.InitializePort(this); VsyncEvent = new KEvent(this); ContentManager = contentManager; // TODO: use set:sys (and get external clock source id from settings) // TODO: use "time!standard_steady_clock_rtc_update_interval_minutes" and implement a worker thread to be accurate. UInt128 clockSourceId = new UInt128(Guid.NewGuid().ToByteArray()); IRtcManager.GetExternalRtcValue(out ulong rtcValue); // We assume the rtc is system time. TimeSpanType systemTime = TimeSpanType.FromSeconds((long)rtcValue); // First init the standard steady clock TimeServiceManager.Instance.SetupStandardSteadyClock(null, clockSourceId, systemTime, TimeSpanType.Zero, TimeSpanType.Zero, false); TimeServiceManager.Instance.SetupStandardLocalSystemClock(null, new SystemClockContext(), systemTime.ToSeconds()); if (NxSettings.Settings.TryGetValue("time!standard_network_clock_sufficient_accuracy_minutes", out object standardNetworkClockSufficientAccuracyMinutes)) { TimeSpanType standardNetworkClockSufficientAccuracy = new TimeSpanType((int)standardNetworkClockSufficientAccuracyMinutes * 60000000000); TimeServiceManager.Instance.SetupStandardNetworkSystemClock(new SystemClockContext(), standardNetworkClockSufficientAccuracy); } TimeServiceManager.Instance.SetupStandardUserSystemClock(null, false, SteadyClockTimePoint.GetRandom()); // FIXME: TimeZone shoud be init here but it's actually done in ContentManager TimeServiceManager.Instance.SetupEphemeralNetworkSystemClock(); }
public Horizon(Switch device) { Device = device; State = new SystemStateMgr(); ResourceLimit = new KResourceLimit(this); KernelInit.InitializeResourceLimit(ResourceLimit); MemoryRegions = KernelInit.GetMemoryRegions(); LargeMemoryBlockAllocator = new KMemoryBlockAllocator(MemoryBlockAllocatorSize * 2); SmallMemoryBlockAllocator = new KMemoryBlockAllocator(MemoryBlockAllocatorSize); UserSlabHeapPages = new KSlabHeap( UserSlabHeapBase, UserSlabHeapItemSize, UserSlabHeapSize); CriticalSection = new KCriticalSection(this); Scheduler = new KScheduler(this); TimeManager = new KTimeManager(); Synchronization = new KSynchronization(this); ContextIdManager = new KContextIdManager(); _kipId = InitialKipId; _processId = InitialProcessId; Scheduler.StartAutoPreemptionThread(); KernelInitialized = true; ThreadCounter = new CountdownEvent(1); Processes = new SortedDictionary <long, KProcess>(); AutoObjectNames = new ConcurrentDictionary <string, KAutoObject>(); //Note: This is not really correct, but with HLE of services, the only memory //region used that is used is Application, so we can use the other ones for anything. KMemoryRegionManager region = MemoryRegions[(int)MemoryRegion.NvServices]; ulong hidPa = region.Address; ulong fontPa = region.Address + HidSize; HidBaseAddress = (long)(hidPa - DramMemoryMap.DramBase); KPageList hidPageList = new KPageList(); KPageList fontPageList = new KPageList(); hidPageList.AddRange(hidPa, HidSize / KMemoryManager.PageSize); fontPageList.AddRange(fontPa, FontSize / KMemoryManager.PageSize); HidSharedMem = new KSharedMemory(hidPageList, 0, 0, MemoryPermission.Read); FontSharedMem = new KSharedMemory(fontPageList, 0, 0, MemoryPermission.Read); AppletState = new AppletStateMgr(this); AppletState.SetFocus(true); Font = new SharedFontManager(device, (long)(fontPa - DramMemoryMap.DramBase)); VsyncEvent = new KEvent(this); LoadKeySet(); ContentManager = new ContentManager(device); }
private KernelResult GetInfo(uint id, int handle, long subId, out long value) { value = 0; switch (id) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 12: case 13: case 14: case 15: case 16: case 17: case 18: case 20: case 21: case 22: { if (subId != 0) { return(KernelResult.InvalidCombination); } KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); KProcess process = currentProcess.HandleTable.GetKProcess(handle); if (process == null) { return(KernelResult.InvalidHandle); } switch (id) { case 0: value = process.Capabilities.AllowedCpuCoresMask; break; case 1: value = process.Capabilities.AllowedThreadPriosMask; break; case 2: value = (long)process.MemoryManager.AliasRegionStart; break; case 3: value = (long)(process.MemoryManager.AliasRegionEnd - process.MemoryManager.AliasRegionStart); break; case 4: value = (long)process.MemoryManager.HeapRegionStart; break; case 5: value = (long)(process.MemoryManager.HeapRegionEnd - process.MemoryManager.HeapRegionStart); break; case 6: value = (long)process.GetMemoryCapacity(); break; case 7: value = (long)process.GetMemoryUsage(); break; case 12: value = (long)process.MemoryManager.GetAddrSpaceBaseAddr(); break; case 13: value = (long)process.MemoryManager.GetAddrSpaceSize(); break; case 14: value = (long)process.MemoryManager.StackRegionStart; break; case 15: value = (long)(process.MemoryManager.StackRegionEnd - process.MemoryManager.StackRegionStart); break; case 16: value = (long)process.PersonalMmHeapPagesCount * KMemoryManager.PageSize; break; case 17: if (process.PersonalMmHeapPagesCount != 0) { value = process.MemoryManager.GetMmUsedPages() * KMemoryManager.PageSize; } break; case 18: value = process.TitleId; break; case 20: value = (long)process.UserExceptionContextAddress; break; case 21: value = (long)process.GetMemoryCapacityWithoutPersonalMmHeap(); break; case 22: value = (long)process.GetMemoryUsageWithoutPersonalMmHeap(); break; } break; } case 8: { if (handle != 0) { return(KernelResult.InvalidHandle); } if (subId != 0) { return(KernelResult.InvalidCombination); } value = _system.Scheduler.GetCurrentProcess().Debug ? 1 : 0; break; } case 9: { if (handle != 0) { return(KernelResult.InvalidHandle); } if (subId != 0) { return(KernelResult.InvalidCombination); } KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); if (currentProcess.ResourceLimit != null) { KHandleTable handleTable = currentProcess.HandleTable; KResourceLimit resourceLimit = currentProcess.ResourceLimit; KernelResult result = handleTable.GenerateHandle(resourceLimit, out int resLimHandle); if (result != KernelResult.Success) { return(result); } value = (uint)resLimHandle; } break; } case 10: { if (handle != 0) { return(KernelResult.InvalidHandle); } int currentCore = _system.Scheduler.GetCurrentThread().CurrentCore; if (subId != -1 && subId != currentCore) { return(KernelResult.InvalidCombination); } value = _system.Scheduler.CoreContexts[currentCore].TotalIdleTimeTicks; break; } case 11: { if (handle != 0) { return(KernelResult.InvalidHandle); } if ((ulong)subId > 3) { return(KernelResult.InvalidCombination); } KProcess currentProcess = _system.Scheduler.GetCurrentProcess(); value = currentProcess.RandomEntropy[subId]; break; } case 0xf0000002u: { if (subId < -1 || subId > 3) { return(KernelResult.InvalidCombination); } KThread thread = _system.Scheduler.GetCurrentProcess().HandleTable.GetKThread(handle); if (thread == null) { return(KernelResult.InvalidHandle); } KThread currentThread = _system.Scheduler.GetCurrentThread(); int currentCore = currentThread.CurrentCore; if (subId != -1 && subId != currentCore) { return(KernelResult.Success); } KCoreContext coreContext = _system.Scheduler.CoreContexts[currentCore]; long timeDelta = PerformanceCounter.ElapsedMilliseconds - coreContext.LastContextSwitchTime; if (subId != -1) { value = KTimeManager.ConvertMillisecondsToTicks(timeDelta); } else { long totalTimeRunning = thread.TotalTimeRunning; if (thread == currentThread) { totalTimeRunning += timeDelta; } value = KTimeManager.ConvertMillisecondsToTicks(totalTimeRunning); } break; } default: return(KernelResult.InvalidEnumValue); } return(KernelResult.Success); }
public Horizon(Switch device) { ControlData = new Nacp(); Device = device; State = new SystemStateMgr(); ResourceLimit = new KResourceLimit(this); KernelInit.InitializeResourceLimit(ResourceLimit); MemoryRegions = KernelInit.GetMemoryRegions(); LargeMemoryBlockAllocator = new KMemoryBlockAllocator(MemoryBlockAllocatorSize * 2); SmallMemoryBlockAllocator = new KMemoryBlockAllocator(MemoryBlockAllocatorSize); UserSlabHeapPages = new KSlabHeap( UserSlabHeapBase, UserSlabHeapItemSize, UserSlabHeapSize); CriticalSection = new KCriticalSection(this); Scheduler = new KScheduler(this); TimeManager = new KTimeManager(); Synchronization = new KSynchronization(this); ContextIdManager = new KContextIdManager(); _kipId = InitialKipId; _processId = InitialProcessId; Scheduler.StartAutoPreemptionThread(); KernelInitialized = true; ThreadCounter = new CountdownEvent(1); Processes = new SortedDictionary <long, KProcess>(); AutoObjectNames = new ConcurrentDictionary <string, KAutoObject>(); // Note: This is not really correct, but with HLE of services, the only memory // region used that is used is Application, so we can use the other ones for anything. KMemoryRegionManager region = MemoryRegions[(int)MemoryRegion.NvServices]; ulong hidPa = region.Address; ulong fontPa = region.Address + HidSize; ulong iirsPa = region.Address + HidSize + FontSize; ulong timePa = region.Address + HidSize + FontSize + IirsSize; HidBaseAddress = (long)(hidPa - DramMemoryMap.DramBase); KPageList hidPageList = new KPageList(); KPageList fontPageList = new KPageList(); KPageList iirsPageList = new KPageList(); KPageList timePageList = new KPageList(); hidPageList.AddRange(hidPa, HidSize / KMemoryManager.PageSize); fontPageList.AddRange(fontPa, FontSize / KMemoryManager.PageSize); iirsPageList.AddRange(iirsPa, IirsSize / KMemoryManager.PageSize); timePageList.AddRange(timePa, TimeSize / KMemoryManager.PageSize); HidSharedMem = new KSharedMemory(this, hidPageList, 0, 0, MemoryPermission.Read); FontSharedMem = new KSharedMemory(this, fontPageList, 0, 0, MemoryPermission.Read); IirsSharedMem = new KSharedMemory(this, iirsPageList, 0, 0, MemoryPermission.Read); TimeSharedMem = new KSharedMemory(this, timePageList, 0, 0, MemoryPermission.Read); AppletState = new AppletStateMgr(this); AppletState.SetFocus(true); Font = new SharedFontManager(device, (long)(fontPa - DramMemoryMap.DramBase)); IUserInterface.InitializePort(this); VsyncEvent = new KEvent(this); LoadKeySet(); ContentManager = new ContentManager(device); // TODO: use set:sys (and set external clock source id from settings) // TODO: use "time!standard_steady_clock_rtc_update_interval_minutes" and implement a worker thread to be accurate. SteadyClockCore.Instance.ConfigureSetupValue(); if (Services.Set.NxSettings.Settings.TryGetValue("time!standard_network_clock_sufficient_accuracy_minutes", out object standardNetworkClockSufficientAccuracyMinutes)) { TimeSpanType standardNetworkClockSufficientAccuracy = new TimeSpanType((int)standardNetworkClockSufficientAccuracyMinutes * 60000000000); StandardNetworkSystemClockCore.Instance.SetStandardNetworkClockSufficientAccuracy(standardNetworkClockSufficientAccuracy); } }