Changes

9,942 bytes added ,  09:23, 21 February 2023
Add kernel diff
Line 178: Line 178:  
=== BootImagePackages ===
 
=== BootImagePackages ===
 
All files in RomFs were updated.
 
All files in RomFs were updated.
 +
 +
====Kernel====
 +
* Compiler upgrade
 +
** Version is currently unknown, probably ~LLVM 15?
 +
** Many NOPs inserted to align branch destinations to 16 bytes, many ADRP + ADD pairs replaced with NOP + ADR
 +
*** This probably corresponds to this commit? https://github.com/llvm/llvm-project/commit/4450a2a23df0e7081ca7fee3ec641774afedc2bc
 +
**** Alexander Shaposhnikov, why did you do this, it makes diffing harder :(
 +
** Compiler now more frequently detecting a reusable computed offset for load/store
 +
* KThreadStackParameters:
 +
** Stack parameters are now 0x10 larger.
 +
** The additional 0x10 bytes appear to be completely unused, at least on prod NX builds of the kernel.
 +
* KScheduler changes:
 +
** Idle count tracking has been changed to use two fields ("idle count", "switch count").
 +
*** In UpdateHighestThreads(), switching to the idle thread does idle_count = ++switch_count, and switching to a non-kernel thread does ++switch_count.
 +
*** KProcess now has an additional array of counts ("running_thread_switch_counts"), UpdateHighestThreads() also sets running_thread_switch_counts[core] = switch_count.
 +
** KDebug::GetRunningThreadInfo() now only succeeds if running_thread_switch_counts[core] == Scheduler->switch_count + 1.
 +
*** Previously, this checked running_thread_idle_counts[core] == Scheduler->idle_count, which meant the thread had to have not switched to idle between its last execution and the GetRunningThreadInfo() wait finishing.
 +
*** Now, this requires the core to have switched directly from the target thread to GetRunningThreadInfo(), which is to say the condition is "The thread is actually running at the target time".
 +
*** In addition, now ResultNoThread is returned if switch_count == idle_count + 1, otherwise ResultUnknownThread is returned; previously only NoThread was returnable.
 +
**** switch_count == idle_count + 1 implies that the switch to GetRunningThreadInfo() happened from idle thread, so ResultNoThread is returned exactly when the running thread was the idle thread.
 +
**** Otherwise, if a thread other than the idle thread was the running thread, UnknownThread is returned.
 +
** KSchedulerLock::Lock() now always increments count, instead of setting count = 1 when the lock owner is not the current thread.
 +
** Note: Several KScheduler functions have big assembly changes, but this appears to be pure compiler optimization changes with no semantic differences.
 +
* KProcess had the creation time member deleted.
 +
* A new KPageTable::Operate operation was added ("ChangePermsAndRefreshWithFlushDataCache")
 +
** Previously, all calls to Operate with ChangePermsAndRefresh would flush data cache; now, calls to ChangePermsAndRefresh do not flush data cache and calls to ChangePermsAndRefreshWithFlushDataCache do.
 +
*** ChangePermsAndRefreshWithFlushDataCache is otherwise identical to ChangePermsAndRefresh semantically.
 +
* QueryIoMapping now supports querying memory regions with KMemoryState_Static in addition to KMemoryState_Io.
 +
* Some changes surrounding KIoRegion:
 +
** KIoRegion now uses an intrusive red black tree member for the pool list, rather than an intrusive list node.
 +
** KIoPool::AddIoRegion() uses the intrusive tree to check fewer regions for Contains().
 +
** KPageTableBase::UnmapIoRegion now takes the MemoryMapping as argument (which was passed to CreateIoRegion).
 +
*** When mapping is MemoryMapping_Memory, the mapping following is done before unmap:
 +
**** The region is permission changed to be uncached, using ChangePermsAndRefresh (without FlushDataCache).
 +
**** The table's lock is released.
 +
**** cpu::FlushDataCache() is called to flush the mapping.
 +
**** The table's lock is reacquired.
 +
*** All fallible operations now call KernelPanic() on failure, rather than returning the result code
 +
* KAddressSpaceInfo::GetAddressSpaceStart()/GetAddressSpaceSize() no longer use complicated switch logic to only examine the indices with the right bit-width, and instead just iterate all indices with an if to check bit width.
 +
* Big changes to KThread waiting/priority inheritance:
 +
** m_waiter_list, m_lock_owner fields were deleted.
 +
** New fields m_held_lock_info_list, m_waiting_lock_info were added.
 +
*** This is an intrusive list of new type KThreadLockInfo (storing info on all locks held), and a pointer to the lock this thread is waiting on, if any.
 +
*** There is one lock info for each address key.
 +
*** KThreadLockInfo is slab allocated, count = # of KThreads
 +
*** KThreadLockInfo has the following fields:
 +
**** LockWithPriorityInheritanceThreadTree m_cv_tree; // Tree of threads waiting on the lock, this re-uses the node for condvar/arbiter.
 +
**** KProcessAddress m_address_key;
 +
**** KThread *m_owner;
 +
**** u32 m_waiter_count;
 +
** This greatly simplifies RemoveWaiterByKey (as there is a single KThreadLockInfo representing all threads waiting on the key).
 +
*** RemoveWaiterByKey now also has an output bool pointer for whether the lock still has waiters, rather than an output s32 pointer for # of waiters.
 +
** RestorePriority has been shuffled to ensure the new CV tree inside lock info has its invariants maintained across the priority set.
 +
** Several calls to RestorePriority are now guarded by if statements, to only invoke RestorePriority if there is a possible change in inherited priority.
 +
* Big changes to crt0/Initialize0/KInitialPageTable/Sleep Manager:
 +
** KInitialPageTable::Map (and others) now take a new physical-to-virtual-offset argument, and add this to L1 table etc.
 +
** Changes to Initial Arguments:
 +
*** Initial arguments are now size 0x80.
 +
*** Initial argument pointers are no longer used; Init arguments array addresses are used directly, with presumption that no page boundary is crossed.
 +
*** Initial arguments no longer use setup function/etc.
 +
*** Instead of setting ep = HorizonKernelMain, Initial arguments now set ep = InvokeMain (this function was previously "InvokeEntryPoint")
 +
*** idle stack is now retrieved from KMemoryLayout inside InvokeMain, instead of being a field inside Initial Arguments.
 +
** After setting up initial arguments, Initialize0 now returns to crt0, which sets sp = InitArguments[0]->sp and calls new function ("Initialize1").
 +
*** All KInitialPageTable calls from here onward now pass g_LinearPhysToVirtDiff, and thus page table accesses are done using the Linear mapping set up by Initialize0.
 +
** Initialize1 does the following:
 +
*** The initial identity mapping is unmapped in its entirety.
 +
**** The single-page containing crt0 + interrupt vectors is re-identity-mapped as R-X.
 +
**** PageAllocator for this is an extremely simplified new InitialPageAllocator type, which always has exactly two free pages to be allocated.
 +
*** All remaining logic which used to be in Initialize0 happens here, with no changes.
 +
** TurnOnAllCores now calls a helper function ("TurnOnCore") to turn on the cores.
 +
*** void TurnOnCore(__int64 core, InitArguments *argument);
 +
*** TurnOnCore does virt->phys translation lookup (using at s1e1r) on StartOtherCore (from crt0 page) + argument, and calls smc::CpuOn directly.
 +
**** TurnOnCore is "probably" a KSystemControl function.
 +
** Sleep handler thread function now sets resume entry addr = StartOtherCore, and sets up an InitArguments for each core.
 +
*** ResumeEntry and ResumeEntryVirtual are now merged/simplified.
 +
* Changes to pool allocations:
 +
** Minimum non-secure system pool size is now ~2MB larger (0x2C04000 vs 0x2A0C000).
 +
** Slab heap gaps size is now 0x9000 smaller (0x1A7000 vs 0x1B0000).
 +
* KSystemControl::Initialize has been restructured (operations reordered), and now calls a helper which sets up the MT, creates system resource limit, etc.
 +
** This helper also modifies the KAddressSpaceInfo tables, when memory is large (these were previously read-only).
 +
** In particular, the following modifications are made to the 39-bit address space infos based on the total memory size:
 +
*** size <= 8 GB: No changes (Heap Region = 8 GB, Alias region = 64 GB)
 +
*** 8 GB < size <= 16 GB: Heap Region = size, Alias Region = 8 * size
 +
*** 16 GB < size <= 32 GB: Heap region = size, Alias region = 128 GB
 +
*** 32 GB <= size: Heap region = 32 GB, Alias region = 128 GB
 +
* KSystemControl::Init::GenerateRandomRange now supports min=0, max=0xFFFFFFFFFFFFFFFF (previously it was incorrect for this case).
 +
* New InfoType (0x1B) ("IoRegionHint")
 +
** This takes a handle to a KIoRegion, and returns the low bits of the region's address.
 +
*** If the region's size is < 0x10000, this is the low 12 bits, otherwise if size < 0x200000, this is the low 16 bits, otherwise it's the low 21 bits.
 +
* UserspaceAccess functions no longer do adr X30, fail in the loop, now do adr X#, fail before the loop and mov X30, X# in the loop.
 +
* All code which sets ThreadContext's pstate field now uses the mask 0xF0000000 for aarch64 threads and 0xFE0FFE20 for aarch32 threads.
 +
** Previously, this used the mask 0xFF0FFE20 for both.
 +
** This removes the ability to get/set the DIT bit for both aarch64 and aarch32, and removes many other bits for aarch64 only.
 +
* Interrupt disable logic was removed from a number of functions:
 +
** KAddressArbiter::SignalAndIncrementIfEqual, KAddressArbiter::SignalAndModifyBasedOnWaitingThreadCount, KAddressArbiter::WaitIfLessThan, KConditionVariable::SignalConditionVariableImpl
 +
* KConditionVariable::SignalToAddress now does dmb before copying updated value to userspace.
 +
* KDebugBase functions for DebugEvents were changed to take pointer to params + count, instead of 5 parameter arguments.
 +
** This propagates up to many/all caller functions.
 +
** The only variable length parameter counts are DebugEvent_Exception + DebugException_UserBreak/DebugException_DebuggerBreak
 +
*** This copies the variable-count parameters directly to the result exception info without maximum size check.
 +
**** This is not exploitable, because there is no way for userspace to control parameter count, and it will always remain in bounds.
 +
**** Presumably exception info type is larger if compiling for a target with more than 4 CPUs, to prevent out-of-bounds copies.
 +
    
==See Also==
 
==See Also==