| Commit message (Collapse) | Author | Files | Lines |
|
Makes for less code that we need to maintain.
|
|
- This is decoupled from core functionality and used for debugging only.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- This is how the real kernel works, and is more accurate and simpler.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Squash attributes into the pointer's integer, making them an uintptr_t
pair containing 2 bits at the bottom and then the pointer. These bits
are currently unused thanks to alignment requirements.
Configure Dynarmic to mask out these bits on pointer reads.
While we are at it, remove some unused attributes carried over from
Citra.
Read/Write and other hot functions use a two step unpacking process that
is less readable to stop MSVC from emitting an extra AND instruction in
the hot path:
mov rdi,rcx
shr rdx,0Ch
mov r8,qword ptr [rax+8]
mov rax,qword ptr [r8+rdx*8]
mov rdx,rax
-and al,3
and rdx,0FFFFFFFFFFFFFFFCh
je Core::Memory::Memory::Impl::Read<unsigned char>
mov rax,qword ptr [vaddr]
movzx eax,byte ptr [rdx+rax]
|
|
|
|
- This is to allow service threads to defer destruction of themselves.
|
|
- Avoids the need to have a large map of host to guest thread IDs.
|
|
- For `std::same_as`, add missing include of `<concepts>`.
- For `std::convertible_to`, create a replacement in `common/concepts.h`
and use that instead.
This would also be found in `<concepts>`, but unlike `std::same_as`,
`std::convertible_to` is not yet implemented in libc++, LLVM's STL
implementation - not even in master. (In fact, `std::same_as` is the
*only* concept currently implemented. For some reason.)
|
|
This is needed as the header invokes methods on KernelCore.
|
|
This log is called often, and introduces a lot of noise when debug logging is enabled, making it difficult to see other debug logs.
|
|
- Fixes a circular dependency which prevented threads from being released on shutdown.
|
|
|
|
|
|
|
|
- This was kind of hacky, and no longer is necessary with service threads.
|
|
|
|
|
|
Simplifies and removes some casts. In all cases, these were generally
widening from a 32-bit unsigned type to a 64-bit unsigned type, so no
information would be lost from the conversion.
|
|
Follows the video core PR. fmt doesn't require casts for enum classes
anymore, so we can remove quite a few casts.
|
|
`PhysicalCore`'s move assignment operator was declared as `= default`,
but was implicitly deleted because `PhysicalCore` has fields
of reference type. Switch to explicitly deleting it to avoid a Clang
warning.
The move *constructor* is still defaulted, and is required to exist due
to the use of `std::vector<PhysicalCore>`.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- This is closer to pre-multicore behavior, and works a bit better.
|
|
|
|
- This breaks things, and is unnecessary, since emulation will be done at this point.
|
|
|
|
|
|
|
|
|
|
Cleans out the rest of the occurrences of variable shadowing and makes
any further occurrences of shadowing compiler errors.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The parameter is used in this function, so this suppression isn't
necessary.
|
|
Resolves numerous deprecation warnings throughout the codebase due to
inclusion of this header. Now building core should be significantly less
noisy (and also relying on less global state).
This also uncovered quite a few modules that were relying on indirect
includes, which have also been fixed.
|
|
Unicorn long-since lost most of its use, due to dynarmic gaining support
for handling most instructions. At this point any further issues
encountered should be used to make dynarmic better.
This also allows us to remove our dependency on Python.
|
|
Fixes compilation on MSVC
|
|
This member was only used on asserts and it triggered data races.
Remove it to fix them.
|
|
Use the current time, not zero, as the default RNG seed.
|
|
|
|
This slipped through the cracks due to another change being merged
before the compiler flag changes.
|
|
Recent changes to the build system that made more warnings be flagged as
errors caused building via clang to break.
Fixes #4795
|
|
Locks on GetCurrentHostThreadID were causing performance issues
according to Visual Studio's profiler. It was consuming twice the time
as arm_interface.Run(). The cost was not in the function itself but in
the lockinig it required.
Reimplement these functions using atomics and static storage instead of
an unordered_map. This is a side effect to avoid locking and using linked
lists for reads.
Replace unordered_map with a linear search.
|
|
Makes our error coverage a little more consistent across the board by
applying it to Linux side of things as well. This also makes it more
consistent with the warning settings in other libraries in the project.
This also updates httplib to 0.7.9, as there are several warning
cleanups made that allow us to enable several warnings as errors.
|
|
With this, the kernel finally doesn't depend directly on the global
system instance anymore.
|
|
As reported by tsan, SelectThreads could write to
is_context_switch_pending holding a mutex while SwitchToCurrent reads it
without holding any.
It is assumed that the author didn't want an atomic here, so the code is
reordered so that whenever is_context_switch_pending is read inside
SwitchToContext, the mutex is locked.
|
|
As reported by tsan, host_thread_ids could be read while
any of the RegisterHostThread variants were called.
To fix this, lock the register mutex when yuzu is running in multicore
mode and GetCurrentHostThreadID is called.
|
|
Allows the compiler to warn about cases where the constructor is used
but then immediately discarded, which is a potential cause of
locking/unlocking bugs.
|
|
|
|
These functions are only ever used internally as implementation details
for GenerateRandomRange(), so these can be given internal linkage.
|
|
Resolves a few compiler warnings.
|
|
|
|
Makes our type conversion explicit.
|
|
* ipc: Allow all trivially copyable objects to be passed directly into WriteBuffer
With the support of C++20, we can use concepts to deduce if a type is an STL container or not.
* More agressive concept for stl containers
* Add -fconcepts
* Move to common namespace
* Add Common::IsBaseOf
|
|
Makes the interface future-proofed for supporting other platforms in the event we ever support platforms with differing pointer sizes. This way, we have a type in place that is always guaranteed to be able to represent a pointer exactly.
|
|
This isn't used, so it can be removed.
|
|
Resolves some compiler warnings in the Linux build.
|
|
|
|
All these do are return std::function instances of static functions, so
these can be used without an instance of the CPU manager.
|
|
Enforces our desired time units directly with a concrete type.
|
|
|
|
These aren't directly important or commonly used within the process, so
we can move these to the bottom to allow everything else to be more
likely to be within a cache line.
|
|
Removes even more usages of the global system instance, trimming away
more dependencies on global variables and making them explicit in the
interface.
|
|
This is only used in one place, so we can fold it into the calling code,
eliminating a place for the global system instance to be used.
|
|
This isn't used, so it can be removed entirely, shrinking the structure
size by 8 bytes.
|
|
We can define an alias for the index arrays and then just reuse it to
make the code nicer to read.
|
|
We can alter the structure so that we can use designated initializers in
the array, eliminating the comments that indicate their field names.
|
|
Profiling shows that this is a highly contested mutex, causing dimishing
results compared to a OS lock. std::mutex implementations can spin for a
while before falling back to an OS lock.
This avoids wasting precious CPU cycles in a no-op.
|
|
* Switch game settings to use a pointer
In order to add full per-game settings, we need to be able to tell yuzu to switch
to using either the global or game configuration. Using a pointer makes it easier
to switch.
* configuration: add new UI without changing existing funcitonality
The new UI also adds General, System, Graphics, Advanced Graphics,
and Audio tabs, but as yet they do nothing. This commit keeps yuzu
to the same functionality as originally branched.
* configuration: Rename files
These weren't included in the last commit. Now they are.
* configuration: setup global configuration checkbox
Global config checkbox now enables/disables the appropriate tabs in the game
properties dialog. The use global configuration setting is now saved to the
config, defaulting to true. This also addresses some changes requested in the PR.
* configuration: swap to per-game config memory for properties dialog
Does not set memory going in-game. Swaps to game values when opening the
properties dialog, then swaps back when closing it. Uses a `memcpy` to swap.
Also implements saving config files, limited to certain groups of configurations
so as to not risk setting unsafe configurations.
* configuration: change config interfaces to use config-specific pointers
When a game is booted, we need to be able to open the configuration dialogs
without changing the settings pointer in the game's emualtion. A new pointer
specific to just the configuration dialogs can be used to separate changes
to just those config dialogs without affecting the emulation.
* configuration: boot a game using per-game settings
Swaps values where needed to boot a game.
* configuration: user correct config during emulation
Creates a new pointer specifically for modifying the configuration while
emulation is in progress. Both the regular configuration dialog and the game
properties dialog now use the pointer Settings::config_values to focus edits to
the correct struct.
* settings: split Settings::values into two different structs
By splitting the settings into two mutually exclusive structs, it becomes easier,
as a developer, to determine how to use the Settings structs after per-game
configurations is merged. Other benefits include only duplicating the required
settings in memory.
* settings: move use_docked_mode to Controls group
`use_docked_mode` is set in the input settings and cannot be accessed from the
system settings. Grouping it with system settings causes it to be saved with
per-game settings, which may make transferring configs more difficult later on,
especially since docked mode cannot be set from within the game properties
dialog.
* configuration: Fix the other yuzu executables and a regression
In main.cpp, we have to get the title ID before the ROM is loaded, else the
renderer will reflect only the global settings and now the user's game specific
settings.
* settings: use a template to duplicate memory for each setting
Replaces the type of each variable in the Settings::Values struct with a new
class that allows basic data reading and writing. The new struct
Settings::Setting duplicates the data in memory and can manage global overrides
per each setting.
* configuration: correct add-ons config and swap settings when apropriate
Any add-ons interaction happens directly through the global values struct.
Swapping bewteen structs now also includes copying the necessary global configs
that cannot be changed nor saved in per-game settings. General and System config
menus now update based on whether it is viewing the global or per-game settings.
* settings: restore old values struct
No longer needed with the Settings::Setting class template.
* configuration: implement hierarchical game properties dialog
This sets the apropriate global or local data in each setting.
* clang format
* clang format take 2
can the docker container save this?
* address comments and style issues
* config: read and write settings with global awareness
Adds new functions to read and write settings while keeping the global state in
focus. Files now generated per-game are much smaller since often they only need
address the global state.
* settings: restore global state when necessary
Upon closing a game or the game properties dialog, we need to restore all global
settings to the original global state so that we can properly open the
configuration dialog or boot a different game.
* configuration: guard setting values incorrectly
This disables setting values while a game is running if the setting is
overwritten by a per game setting.
* config: don't write local settings in the global config
Simple guards to prevent writing the wrong settings in the wrong files.
* configuration: add comments, assume less, and clang format
No longer assumes that a disabled UI element means the global state is turned
off, instead opting to directly answer that question. Still however assumes a
game is running if it is in that state.
* configuration: fix a logic error
Should not be negated
* restore settings' global state regardless of accept/cancel
Fixes loading a properties dialog and causing the global config dialog to show
local settings.
* fix more logic errors
Fixed the frame limit would set the global setting from the game properties
dialog. Also strengthened the Settings::Setting member variables and simplified
the logic in config reading (ReadSettingGlobal).
* fix another logic error
In my efforts to guard RestoreGlobalState, I accidentally negated the IsPowered
condition.
* configure_audio: set toggle_stretched_audio to tristate
* fixed custom rtc and rng seed overwriting the global value
* clang format
* rebased
* clang format take 4
* address my own review
Basically revert unintended changes
* settings: literal instead of casting
"No need to cast, use 1U instead"
Thanks, Morph!
Co-authored-by: Morph <39850852+Morph1984@users.noreply.github.com>
* Revert "settings: literal instead of casting
"
This reverts commit 95e992a87c898f3e882ffdb415bb0ef9f80f613f.
* main: fix status buttons reporting wrong settings after stop emulation
* settings: Log UseDockedMode in the Controls group
This should have happened when use_docked_mode was moved over to the controls group
internally. This just reflects this in the log.
* main: load settings if the file has a title id
In other words, don't exit if the loader has trouble getting a title id.
* use a zero
* settings: initalize resolution factor with constructor instead of casting
* Revert "settings: initalize resolution factor with constructor instead of casting"
This reverts commit 54c35ecb46a29953842614620f9b7de1aa9d5dc8.
* configure_graphics: guard device selector when Vulkan is global
Prevents the user from editing the device selector if Vulkan is the global
renderer backend. Also resets the vulkan_device variable when the users
switches back-and-forth between global and Vulkan.
* address reviewer concerns
Changes function variables to const wherever they don't need to be changed. Sets Settings::Setting to final as it should not be inherited from. Sets ConfigurationShared::use_global_text to static.
Co-Authored-By: VolcaEM <volcaem@users.noreply.github.com>
* main: load per-game settings after LoadROM
This prevents `Restart Emulation` from restoring the global settings *after* the per-game settings were applied. Thanks to BSoDGamingYT for finding this bug.
* Revert "main: load per-game settings after LoadROM"
This reverts commit 9d0d48c52d2dcf3bfb1806cc8fa7d5a271a8a804.
* main: only restore global settings when necessary
Loading the per-game settings cannot happen after the ROM is loaded, so we have to specify when to restore the global state. Again thanks to BSoD for finding the bug.
* configuration_shared: address reviewer concerns except operator overrides
Dropping operator override usage in next commit.
Co-Authored-By: LC <lioncash@users.noreply.github.com>
* settings: Drop operator overrides from Setting template
Requires using GetValue and SetValue explicitly. Also reverts a change that broke title ID formatting in the game properties dialog.
* complete rebase
* configuration_shared: translate "Use global configuration"
Uses ConfigurePerGame to do so, since its usage, at least as of now, corresponds with ConfigurationShared.
* configure_per_game: address reviewer concern
As far as I understand, it prevents the program from unnecessarily copying strings.
Co-Authored-By: LC <lioncash@users.noreply.github.com>
Co-authored-by: Morph <39850852+Morph1984@users.noreply.github.com>
Co-authored-by: VolcaEM <volcaem@users.noreply.github.com>
Co-authored-by: LC <lioncash@users.noreply.github.com>
|
|
Simplifies the cognitive load of procedures using locks and makes locks
safe against exceptions.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This commit: Implements CPU Interrupts, Replaces Cycle Timing for Host
Timing, Reworks the Kernel's Scheduler, Introduce Idle State and
Suspended State, Recreates the bootmanager, Initializes Multicore
system.
|
|
num_pages is an std::size_t. It will always be >= 0
|
|
Previously if applications would send faulty buffers(example homebrew) it would lead to us returning uninitalized data. Switching from ASSERT_MSG to ASSERT_OR_EXECUTE_MSG allows us to have a fail safe to prevent crashes but also continue execution without introducing undefined behavior
|
|
|
|
GetTotalPhysicalMemoryAvailableWithoutSystemResource & GetTotalPhysicalMemoryUsedWithoutSystemResource seem to subtract the resource size from the usage.
|
|
clogs logs quite a bit
|
|
Timeout is a u64, it will always be >= 0
|
|
This isn't necessary in a cpp file and will cause warnings on clang.
|
|
Prevents header churn and needing to recompile these files if these
headers are ever changed in the future.
|
|
Prevents unused variable warnings.
|
|
This allows tuning standard library implementations to enable or disable
range checks at runtime, which is nicer for debugging.
|
|
Prevents variable name clashing.
|
|
While èis generally representable in some language encodings, in some
it isn't and will result in compilation warnings occurring. To remain
friendly with other language's codepages on Windows, we normalize it to
an ASCII e.
|
|
We can just pass the required instances into the constructor of the
request, eliminating all usages of the global system accessor.
|
|
Resolves a -Wextra-semi warning.
While we're at it, we can invert the branch to form a guard clause,
unindenting all of the contained code.
|
|
|
|
As we currently match hardware and don't return a successful result, these should be marked as errors instead of warnings and as stubs.
|
|
We can also allow unicorn to be constructed in 32-bit mode or 64-bit
mode to satisfy the need for both interpreter instances.
Allows this code to compile successfully of non x86-64 architectures.
|
|
Amends the parameter to match the documentation reference.
Resolves a -Wdocumentation warning with clang.
|
|
These were lost in the re-implementation of the virtual memory manager.
|
|
Since the VMM refactor, this is no longer used or needed.
|
|
Any time the lambda function is called, the permission being used in the
capture would be passed in as an argument to the lambda, so the capture
is unnecessary.
|
|
* kernel: memory: Improve implementation of device shared memory.
* fixup! kernel: memory: Improve implementation of device shared memory.
* fixup! kernel: memory: Improve implementation of device shared memory.
|
|
|
|
Casting from void* with static_cast is permitted by the standard, so we
can just make use of that instead.
|
|
- Should be no functional changes.
|
|
|
|
|
|
|
|
- Includes removing some SVC impls. that are untested.
|
|
|
|
|
|
|
|
- More consistent with other system components.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- This will be used for TLS pages, among other things.
|
|
|
|
- helpful to disambiguate Kernel::Memory namespace.
|
|
|
|
|
|
|
|
|
|
These were added in the change that enabled -Wextra on linux builds so
as not to introduce interface changes in the same change as a
build-system flag addition.
Now that the flags are enabled, we can freely change the interface to
make these unnecessary.
|
|
Allows reporting more cases where logic errors may exist, such as
implicit fallthrough cases, etc.
We currently ignore unused parameters, since we currently have many
cases where this is intentional (virtual interfaces).
While we're at it, we can also tidy up any existing code that causes
warnings. This also uncovered a few bugs as well.
|
|
This can result in silent logic bugs within code, and given the amount
of times these kind of warnings are caused, they should be flagged at
compile-time so no new code is submitted with them.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Same behavior, but without the need to explicitly loop through
everything manually.
|
|
Simplifies the overall function and also allows for it to become a
const-qualified member function.
|
|
We can just use the kernel member variable directly instead of going
through the system to obtain the same thing.
|
|
|
|
|
|
|
|
|
|
- This was holdover from citra.
|
|
|
|
shared_ptr was used in 2d1984c20c75e03ec79eeb3806b12efa1679b977 due to a
misunderstanding of how the language generates move constructors and
move assignment operators.
If a destructor is user-provided, then the compiler won't generate the
move constructor and move assignment operators by default--they must be
explicitly opted into.
The reason for the compilation errors is due to the fact that the
language will fall back to attempting to use the copy constructor/copy
assignment operators if the respective move constructor or move
assignment operator is unavailable.
Given that we explicitly opt into them now, the the move constructor and
move assignment operators will be generated as expected.
|
|
This isn't used within the class, so it can be removed to simplify the
overall interface.
While we're in the same area, we can simplify a unique_ptr reset() call.
|
|
|
|
|
|
This commit instends on better naming the new purpose of this classes.
|
|
|
|
This commit moves ARM Interface and Scheduler handling into the kernel.
|
|
|
|
This allows us to create a fastmem arena within the memory.cpp helpers.
|
|
|
|
module._memory was already moved over to a new shared_ptr.
So code_memory_size was not increased at all.
This lowers the heap space and so saves a bit of memory, usually between 50 to 100 MB.
This fixes a regression of c0a01f3adc466d07fc27020048e82cca60988970
|
|
* Kernel: Correct behavior of Address Arbiter threads.
This corrects arbitration threads to behave just like in Horizon OS.
They are added into a container and released according to what priority
they had when added. Horizon OS does not reorder them if their priority
changes.
* Kernel: Address Feedback.
|
|
This function doesn't actually return a result code, so we can amend the
signature of it to match.
|
|
Over the course of the changes to the kernel code, a few includes are no
longer necessary, particularly with the change over to std::shared_ptr
from Boost's intrusive_ptr.
|
|
These are fairly trivial to implement, we can just do nothing. This also
provides a spot for us to potentially dump out any relevant info in the
future (e.g. for debugging purposes with homebrew, etc).
While we're at it, we can also correct the names of both of these
supervisor calls.
|
|
This commit corrects an error in which a Core could remain with an
exclusive state after running, leaving space for possible race
conditions between changing cores.
|
|
|
|
Now that literally every other API function is converted over to the
Memory class, we can just move the file-local page table into the Memory
implementation class, finally getting rid of global state within the
memory code.
|
|
The Write functions are used slightly less than the Read functions,
which make these a bit nicer to move over.
The only adjustments we really need to make here are to Dynarmic's
exclusive monitor instance. We need to keep a reference to the currently
active memory instance to perform exclusive read/write operations.
|
|
With all of the trivial parts of the memory interface moved over, we can
get right into moving over the bits that are used.
Note that this does require the use of GetInstance from the global
system instance to be used within hle_ipc.cpp and the gdbstub. This is
fine for the time being, as they both already rely on the global system
instance in other functions. These will be removed in a change directed
at both of these respectively.
For now, it's sufficient, as it still accomplishes the goal of
de-globalizing the memory code.
|
|
This only had one usage spot, so this is fairly straightforward to
convert over.
|
|
With all of the interfaces ready for migration, it's trivial to migrate
over GetPointer().
|
|
Amends a few interfaces to be able to handle the migration over to the
new Memory class by passing the class by reference as a function
parameter where necessary.
Notably, within the filesystem services, this eliminates two ReadBlock()
calls by using the helper functions of HLERequestContext to do that for
us.
|
|
A fairly straightforward migration. These member functions can just be
mostly moved verbatim with minor changes. We already have the necessary
plumbing in places that they're used.
IsKernelVirtualAddress() can remain a non-member function, since it
doesn't rely on class state in any form.
|
|
Migrates all of the direct mapping facilities over to the new memory
class. In the process, this also obsoletes the need for memory_setup.h,
so we can remove it entirely from the project.
|
|
* core_timing: Use better reference tracking for EventType.
- Moves ownership of the event to the caller, ensuring we don't fire events for destroyed objects.
- Removes need for unique names - we won't be using this for save states anyways.
|
|
- Fixes shutdown crash and crash in Pokemon SwSh.
|
|
* kernel: Replace usage of boost::intrusive_ptr with std::shared_ptr for kernel objects.
- See https://github.com/citra-emu/citra/pull/4710 for details.
|
|
|
|
|
|
|
|
When the target is 0, all threads must be processed.
|
|
This commit ensures cond var threads act exactly as they do in the real
console. The original implementation uses an RBTree and the behavior of
cond var threads is that at the same priority level they act like a
FIFO.
|
|
This commit corrects the behavior of cancel synchronization when the
thread is running/ready and ensures the next wait is cancelled as it's
suppose to.
|
|
Uncovered a bug within Thread's SetCoreAndAffinityMask() where an
unsigned variable (ideal_core) was being compared against "< 0", which
would always be a false condition.
We can also get rid of an unused function (GetNextProcessorId) which contained a sign
mismatch warning.
|
|
|
|
- This does not actually seem to exist in the real kernel - games reset these automatically.
# Conflicts:
# src/core/hle/service/am/applets/applets.cpp
# src/core/hle/service/filesystem/fsp_srv.cpp
|
|
|
|
This is only compared against, so it can be made const.
|
|
|
|
Reduces the overall amount of code.
|
|
Adjusts the formatting of a few of the comments an ensures they get
recognized as proper Doxygen comments.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
In case of redundant yields, the scheduler will now idle the core for
it's timeslice, in order to avoid continuously yielding the same thing
over and over.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This only encourages the use of the global system instance (which will
be phased out long-term). Instead, we use the direct system function
call directly to remove the appealing but discouraged short-hand.
|
|
Corrects the parameter names within the doxygen comments so that they
resolve properly.
|
|
Narrows the scope of variables down to where they're only necessary.
|
|
If an unmapping operation fails, we shouldn't be decrementing the amount
of memory mapped and returning that the operation was successful. We
should actually be returning the error code in this case.
|
|
Avoids potentially expensive (depending on the size of the memory block)
allocations by reserving the necessary memory before performing both
insertions. This avoids scenarios where the second insert may cause a
reallocation to occur.
|
|
Avoids an unnecessary atomic reference count increment and decrement.
|
|
Avoids needing to read the same long sequence of code in both code
paths. Also makes it slightly nicer to read and debug, as the locals
will be able to be shown in the debugger.
|
|
Same behavior, one less magic constant to read.
|
|
Assertions already log out the function name, so there's no need to
manually include the function name in the assertion strings.
|
|
|
|
This commit ensures that all backing memory allocated for the Guest CPU
is aligned to 256 bytes. This due to how gpu memory works and the heavy
constraints it has in the alignment of physical memory.
|
|
This messages were originally set as warnning since few games used these
svcs and it was needed for debugging. This is no longer the case.
|
|
|
|
This was initially necessary when AArch64 JIT emulation was in its
infancy and all memory-related instructions weren't implemented.
Given the JIT now has all of these facilities implemented, we can remove
these functions from the CPU interface.
|
|
Prior to PR, Yuzu did not restore memory to RW-
on unmap of mirrored memory or unloading of NRO.
(In fact, in the NRO case, the memory was unmapped
instead of reprotected to --- on Load, so it was
actually lost entirely...)
This PR addresses that, and restores memory to RW-
as it should.
This fixes a crash in Super Smash Bros when creating
a World of Light save for the first time, and possibly
other games/circumstances.
|
|
This sets the DeviceMapped attribute for GPU-mapped memory blocks,
and prevents merging device mapped blocks. This prevents memory
mapped from the gpu from having its backing address changed by
block coalesce.
|
|
|
|
|
|
|
|
|
|
This implements svcMapPhysicalMemory/svcUnmapPhysicalMemory for Yuzu,
which can be used to map memory at a desired address by games since
3.0.0.
It also properly parses SystemResourceSize from NPDM, and makes
information available via svcGetInfo.
This is needed for games like Super Smash Bros. and Diablo 3 -- this
PR's implementation does not run into the "ASCII reads" issue mentioned
in the comments of #2626, which was caused by the following bugs in
Yuzu's memory management that this PR also addresses:
* Yuzu's memory coalescing does not properly merge blocks. This results
in a polluted address space/svcQueryMemory results that would be
impossible to replicate on hardware, which can lead to game code making
the wrong assumptions about memory layout.
* This implements better merging for AllocatedMemoryBlocks.
* Yuzu's implementation of svcMirrorMemory unprotected the entire
virtual memory range containing the range being mirrored. This could
lead to games attempting to map data at that unprotected
range/attempting to access that range after yuzu improperly unmapped
it.
* This PR fixes it by simply calling ReprotectRange instead of
Reprotect.
|
|
Prior to execution within a process beginning, the process establishes
its own TLS region for uses (as far as I can tell) related to exception
handling.
Now that TLS creation was decoupled from threads themselves, we can add
this behavior to our Process class. This is also good, as it allows us
to remove a stub within svcGetInfo, namely querying the address of that
region.
|
|
Keeps this particular set of behavior isolated to its own function.
|
|
Provides a more accurate name for the memory region and also
disambiguates between the map and new map regions of memory, making it
easier to understand.
|
|
Handles the placement of the stack a little nicer compared to the
previous code, which was off in a few ways. e.g.
The stack (new map) region, shouldn't be the width of the entire address
space if the size of the region calculation ends up being zero. It
should be placed at the same location as the TLS IO region and also have
the same size.
In the event the TLS IO region contains a size of zero, we should also
be doing the same thing. This fixes our memory layout a little bit and
also resolves some cases where assertions can trigger due to the memory
layout being incorrect.
|
|
Ensures a Process instance is always created with a deterministic
initial state.
|
|
Extracts out all of the thread local storage management from thread
instances themselves and makes the owning process handle the management
of the memory. This brings the memory management slightly more in line
with how the kernel handles these allocations.
Furthermore, this also makes the TLS page management a little more
readable compared to the lingering implementation that was carried over
from Citra.
|
|
This will be necessary for making our TLS slot management slightly more
straightforward. This can also be utilized for other purposes in the
future.
We can implement the existing simpler overload in terms of this one
anyways, we just pass the beginning and end of the ASLR region as the
boundaries.
|
|
The old implementation had faulty Threadsafe methods where events could
be missing. This implementation unifies unsafe/safe methods and makes
core timing thread safe overall.
|
|
This is performing more work than would otherwise be necessary during
VMManager's destruction. All we actually want to occur in this scenario
is for any allocated memory to be freed, which will happen automatically
as the VMManager instance goes out of scope.
Anything else being done is simply unnecessary work.
|
|
This allows kernel internal type processes to be assigned IDs in the KIP range while userland processes are assigned in the user range.
|
|
Makes the interface more flexible in terms of how Create() may be
called, while still allowing the parameter itself to be moved into.
|
|
Given we don't currently implement the personal heap yet, the existing
memory querying functions are essentially doing what the memory querying
types introduced in 6.0.0 do.
So, we can build the necessary machinery over the top of those and just
use them as part of info types.
|
|
Disambiguates and makes the name a little more consistent with
TotalPhysicalMemoryUsed.
|
|
|
|
Boost headers typically include a lot of other headers, so removing this
can prevent a bit of unnecessary compiler churn when building.
|
|
Makes the interface more type-safe and consistent in terms of return
values.
|
|
|
|
Co-Authored-By: Mat M. <mathew1800@gmail.com>
|
|
These are only used from within this translation unit, so they don't
need to have external linkage. They were intended to be marked with this
anyways to be consistent with the other service functions.
|
|
Renames the members to more accurately indicate what they signify.
"OneShot" and "Sticky" are kind of ambiguous identifiers for the reset
types, and can be kind of misleading. Automatic and Manual communicate
the kind of reset type in a clearer manner. Either the event is
automatically reset, or it isn't and must be manually cleared.
The "OneShot" and "Sticky" terminology is just a hold-over from Citra
where the kernel had a third type of event reset type known as "Pulse".
Given the Switch kernel only has two forms of event reset types, we
don't need to keep the old terminology around anymore.
|
|
This reduces the boilerplate that services have to write out the current thread explicitly. Using current thread instead of client thread is also semantically incorrect, and will be a problem when we implement multicore (at which time there will be multiple current threads)
|
|
These are actually quite important indicators of thread lifetimes, so
they should be going into the debug log, rather than being treated as
misc info and delegated to the trace log.
|
|
Makes the code much nicer to follow in terms of behavior and control
flow. It also fixes a few bugs in the implementation.
Notably, the thread's owner process shouldn't be accessed in order to
retrieve the core mask or ideal core. This should be done through the
current running process. The only reason this bug wasn't encountered yet
is because we currently only support running one process, and thus every
owner process will be the current process.
We also weren't checking against the process' CPU core mask to see if an
allowed core is specified or not.
With this out of the way, it'll be less noisy to implement proper
handling of the affinity flags internally within the kernel thread
instances.
|
|
Adds the missing flags to the enum and documents them.
|
|
This call was added to the SVC handlers in the 8.0.0 kernel, so we can
finally give it a name.
|
|
This is a holdover from Citra, where the 3DS has both
WaitSynchronization1 and WaitSynchronizationN. The switch only has one
form of wait synchronizing (literally WaitSynchonization). This allows
us to throw out code that doesn't apply at all to the Switch kernel.
Because of this unnecessary dichotomy within the wait synchronization
utilities, we were also neglecting to properly handle waiting on
multiple objects.
While we're at it, we can also scrub out any lingering references to
WaitSynchronization1/WaitSynchronizationN in comments, and change them
to WaitSynchronization (or remove them if the mention no longer
applies).
|
|
The actual behavior of this function is slightly more complex than what
we're currently doing within the supervisor call. To avoid dumping most
of this behavior in the supervisor call itself, we can migrate this to
another function.
|
|
This doesn't actually modify internal state of a wait object, so it can
be const qualified.
|
|
Makes the dependency on the system instance explicit within VMManager's
interface.
|
|
Allows the handle to be seen alongside the entry point.
|
|
This is a holdover from Citra that currently remains unused, so it can
be removed from the Thread interface.
|
|
This member variable is entirely unused. It was only set but never
actually utilized. Given that, we can remove it to get rid of noise in
the thread interface.
|
|
Essentially performs the inverse of svcMapProcessCodeMemory. This unmaps
the aliasing region first, then restores the general traits of the
aliased memory.
What this entails, is:
- Restoring Read/Write permissions to the VMA.
- Restoring its memory state to reflect it as a general heap memory region.
- Clearing the memory attributes on the region.
|
|
This is utilized for mapping code modules into memory. Notably, the
ldr service would call this in order to map objects into memory.
|
|
This gives us significantly more control over where in the
initialization process we start execution of the main process.
Previously we were running the main process before the CPU or GPU
threads were initialized (not good). This amends execution to start
after all of our threads are properly set up.
|
|
Initially required due to the split codepath with how the initial main
process instance was initialized. We used to initialize the process
like:
Init() {
main_process = Process::Create(...);
kernel.MakeCurrentProcess(main_process.get());
}
Load() {
const auto load_result = loader.Load(*kernel.GetCurrentProcess());
if (load_result != Loader::ResultStatus::Success) {
// Handle error here.
}
...
}
which presented a problem.
Setting a created process as the main process would set the page table
for that process as the main page table. This is fine... until we get to
the part that the page table can have its size changed in the Load()
function via NPDM metadata, which can dictate either a 32-bit, 36-bit,
or 39-bit usable address space.
Now that we have full control over the process' creation in load, we can
simply set the initial process as the main process after all the loading
is done, reflecting the potential page table changes without any
special-casing behavior.
We can also remove the cache flushing within LoadModule(), as execution
wouldn't have even begun yet during all usages of this function, now
that we have the initialization order cleaned up.
|
|
Our initialization process is a little wonky than one would expect when
it comes to code flow. We initialize the CPU last, as opposed to
hardware, where the CPU obviously needs to be first, otherwise nothing
else would work, and we have code that adds checks to get around this.
For example, in the page table setting code, we check to see if the
system is turned on before we even notify the CPU instances of a page
table switch. This results in dead code (at the moment), because the
only time a page table switch will occur is when the system is *not*
running, preventing the emulated CPU instances from being notified of a
page table switch in a convenient manner (technically the code path
could be taken, but we don't emulate the process creation svc handlers
yet).
This moves the threads creation into its own member function of the core
manager and restores a little order (and predictability) to our
initialization process.
Previously, in the multi-threaded cases, we'd kick off several threads
before even the main kernel process was created and ready to execute (gross!).
Now the initialization process is like so:
Initialization:
1. Timers
2. CPU
3. Kernel
4. Filesystem stuff (kind of gross, but can be amended trivially)
5. Applet stuff (ditto in terms of being kind of gross)
6. Main process (will be moved into the loading step in a following
change)
7. Telemetry (this should be initialized last in the future).
8. Services (4 and 5 should ideally be alongside this).
9. GDB (gross. Uses namespace scope state. Needs to be refactored into a
class or booted altogether).
10. Renderer
11. GPU (will also have its threads created in a separate step in a
following change).
Which... isn't *ideal* per-se, however getting rid of the wonky
intertwining of CPU state initialization out of this mix gets rid of
most of the footguns when it comes to our initialization process.
|
|
Some objects declare their handle type as const, while others declare it
as constexpr. This makes the const ones constexpr for consistency, and
prevent unexpected compilation errors if these happen to be attempted to be
used within a constexpr context.
|
|
These are holdovers from Citra.
|
|
We need to ensure dynarmic gets a valid pointer if the page table is
resized (the relevant pointers would be invalidated in this scenario).
In this scenario, the page table can be resized depending on what kind
of address space is specified within the NPDM metadata (if it's
present).
|
|
Adjusts the interface of the wrappers to take a system reference, which
allows accessing a system instance without using the global accessors.
This also allows getting rid of all global accessors within the
supervisor call handling code. While this does make the wrappers
themselves slightly more noisy, this will be further cleaned up in a
follow-up. This eliminates the global system accessors in the current
code while preserving the existing interface.
|
|
Centralizes the page table switching to one spot, rather than making
calling code deal with it everywhere.
|
|
Keeps the return type consistent with the function name. While we're at
it, we can also reduce the amount of boilerplate involved with handling
these by using structured bindings.
|
|
Returns the same type that the function name describes.
|
|
We need to be checking whether or not the given address is within the
kernel address space or if the given address isn't word-aligned and bail
in these scenarios instead of trashing any kernel state.
|
|
Also amend erroneous use of size_t. We should be using u64 here.
|
|
Given server sessions can be given a name, we should allow retrieving
it instead of using the default implementation of GetName(), which would
just return "[UNKNOWN KERNEL OBJECT]".
|
|
The AddressArbiter type isn't actually used, given the arbiter itself
isn't a direct kernel object (or object that implements the wait object
facilities).
Given this, we can remove the enum entry entirely.
|
|
Similarly like svcGetProcessList, this retrieves the list of threads
from the current process. In the kernel itself, a process instance
maintains a list of threads, which are used within this function.
Threads are registered to a process' thread list at thread
initialization, and unregistered from the list upon thread destruction
(if said thread has a non-null owning process).
We assert on the debug event case, as we currently don't implement
kernel debug objects.
|
|
This service function simply copies out a specified number of kernel
process IDs, while simultaneously reporting the total number of
processes.
|
|
|
|
Now that ShouldWait() is a const qualified member function, this one can
be made const qualified as well, since it can handle passing a const
qualified this pointer to ShouldWait().
|
|
Given this is intended as a querying function, it doesn't make sense to
allow the implementer to modify the state of the given thread.
|
|
Previously this was performing a u64 + int sign conversion. When dealing
with addresses, we should generally be keeping the arithmetic in the
same signedness type.
This also gets rid of the static lifetime of the constant, as there's no
need to make a trivial type like this potentially live for the entire
duration of the program.
|
|
The pointed to member is never actually modified, so it can be made
const.
|
|
This doesn't really provide any benefit to the resource limit interface.
There's no way for callers to any of the service functions for resource
limits to provide a custom name, so all created instances of resource
limits other than the system resource limit would have a name of
"Unknown".
The system resource limit itself is already trivially identifiable from
its limit values, so there's no real need to take up space in the object to
identify one object meaningfully out of N total objects.
|
|
Since C++17, the introduction of deduction guides for locking facilities
means that we no longer need to hardcode the mutex type into the locks
themselves, making it easier to switch mutex types, should it ever be
necessary in the future.
|
|
This was made unused in b404fcdf1443b91ac9994c05ad1fe039fcd9675e, but
the parameter itself wasn't removed.
|
|
Since C++17, we no longer need to explicitly specify the type of the
mutex within the lock_guard. The type system can now deduce these with
deduction guides.
|
|
Nothing from this header is used, so we can remove this include, getting
rid of a dependency on it.
|
|
The kernel makes sure that the given size to unmap is always the same
size as the entire region managed by the shared memory instance,
otherwise it returns an error code signifying an invalid size.
This is similarly done for transfer memory (which we already check for).
|
|
Reports the (mostly) correct size through svcGetInfo now for queries to
total used physical memory. This still doesn't correctly handle memory
allocated via svcMapPhysicalMemory, however, we don't currently handle
that case anyways.
|
|
This will be necessary to properly report the used memory size in
svcGetInfo.
|
|
This will be necessary in order to properly report memory usage within
svcGetInfo.
|
|
This will make operating with the process-related SVC commands much
nicer in the future (the parameter representing the stack size in
svcStartProcess is a 64-bit value).
|
|
The kernel always makes sure that the given stack size is aligned to
page boundaries.
|
|
|
|
|
|
In some cases, our callbacks were using s64 as a parameter, and in other
cases, they were using an int, which is inconsistent.
To make all callbacks consistent, we can just use an s64 as the type for
late cycles, given it gets rid of the need to cast internally.
While we're at it, also resolve some signed/unsigned conversions that
were occurring related to the callback registration.
|
|
This is no longer necessary, as ResultVal isn't used anywhere in the
header.
|
|
Another leftover from citra that's now no longer necessary.
|
|
One behavior that we weren't handling properly in our heap allocation
process was the ability for the heap to be shrunk down in size if a
larger size was previously requested.
This adds the basic behavior to do so and also gets rid of HeapFree, as
it's no longer necessary now that we have allocations and deallocations
going through the same API function.
While we're at it, fully document the behavior that this function
performs.
|
|
Makes it more obvious that this function is intending to stand in for
the actual supervisor call itself, and not acting as a general heap
allocation function.
Also the following change will merge the freeing behavior of HeapFree
into this function, so leaving it as HeapAllocate would be misleading.
|
|
In cases where HeapAllocate is called with the same size of the current
heap, we can simply do nothing and return successfully.
This avoids doing work where we otherwise don't have to. This is also
what the kernel itself does in this scenario.
|
|
Over time these have fallen out of use due to refactoring, so these can
be removed.
|
|
This isn't required anymore, as all the kernel ever queries is the size
of the current heap, not the total usage of it.
|
|
Another holdover from citra that can be tossed out is the notion of the
heap needing to be allocated in different addresses. On the switch, the
base address of the heap will always be managed by the memory allocator
in the kernel, so this doesn't need to be specified in the function's
interface itself.
The heap on the switch is always allocated with read/write permissions,
so we don't need to add specifying the memory permissions as part of the
heap allocation itself either.
This also corrects the error code returned from within the function.
If the size of the heap is larger than the entire heap region, then the
kernel will report an out of memory condition.
|
|
The use of a shared_ptr is an implementation detail of the VMManager
itself when mapping memory. Because of that, we shouldn't require all
users of the CodeSet to have to allocate the shared_ptr ahead of time.
It's intended that CodeSet simply pass in the required direct data, and
that the memory manager takes care of it from that point on.
This means we just do the shared pointer allocation in a single place,
when loading modules, as opposed to in each loader.
|
|
Makes it more evident that one is for actual code and one is for actual
data. Mutable and static are less than ideal terms here, because
read-only data is technically not mutable, but we were mapping it with
that label.
|
|
This should actually be using the data flags, rather than the code
flags.
|
|
The segment itself isn't actually modified.
|
|
Given this is utilized by the loaders, this allows avoiding inclusion of
the kernel process definitions where avoidable.
This also keeps the loading format for all executable data separate from
the kernel objects.
|
|
|
|
|
|
|
|
|
|
|
|
This was intended to be removed in
51d7f6bffcc0498a47abc7de27bf0906fc523dae, but I guess I forgot to
actually save the file like a dingus.
|
|
Puts the operation on global state in the same places as the rest of the
svc calls.
|
|
Rather than make a global accessor for this sort of thing. We can make
it a part of the thread interface itself. This allows getting rid of a
hidden global accessor in the kernel code.
|
|
Aims to disambiguate why each priority instance exists a little bit.
While we're at it, also add an explanatory comment to UpdatePriority().
|
|
|
|
This condition was checking against the nominal thread priority, whereas
the kernel itself checks against the current priority instead. We were
also assigning the nominal priority, when we should be assigning
current_priority, which takes priority inheritance into account.
This can lead to the incorrect priority being assigned to a thread.
Given we recursively update the relevant threads, we don't need to go
through the whole mutex waiter list. This matches what the kernel does
as well (only accessing the first entry within the waiting list).
|
|
The kernel keeps the internal waiting list ordered by priority. This is
trivial to do with std::find_if followed by an insertion.
|
|
Removes the use of global system accessors, and instead uses the
explicit interface provided.
|
|
Makes it an instantiable class like it is in the actual kernel. This
will also allow removing reliance on global accessors in a following
change, now that we can encapsulate a reference to the system instance
in the class.
|
|
Similarly, like svcMapTransferMemory, we can also implement
svcUnmapTransferMemory fairly trivially as well.
|
|
Now that transfer memory handling is separated from shared memory, we
can implement svcMapTransferMemory pretty trivially.
|
|
Within the kernel, shared memory and transfer memory facilities exist as
completely different kernel objects. They also have different validity
checking as well. Therefore, we shouldn't be treating the two as the
same kind of memory.
They also differ in terms of their behavioral aspect as well. Shared
memory is intended for sharing memory between processes, while transfer
memory is intended to be for transferring memory to other processes.
This breaks out the handling for transfer memory into its own class and
treats it as its own kernel object. This is also important when we
consider resource limits as well. Particularly because transfer memory
is limited by the resource limit value set for it.
While we currently don't handle resource limit testing against objects
yet (but we do allow setting them), this will make implementing that
behavior much easier in the future, as we don't need to distinguish
between shared memory and transfer memory allocations in the same place.
|
|
Now that we pass in a reference to the system instance, we can utilize
it to eliminate the global accessors in Process-related code.
|
|
With this, all kernel objects finally have all of their data members
behind an interface, making it nicer to reason about interactions with
other code (as external code no longer has the freedom to totally alter
internals and potentially messing up invariants).
|
|
There's no real need to use a shared lifetime here, since we don't
actually expose them to anything else. This is also kind of an
unnecessary use of the heap given the objects themselves are so small;
small enough, in fact that changing over to optionals actually reduces
the overall size of the HLERequestContext struct (818 bytes to 808
bytes).
|
|
Now that we have the address arbiter extracted to its own class, we can
fix an innaccuracy with the kernel. Said inaccuracy being that there
isn't only one address arbiter. Each process instance contains its own
AddressArbiter instance in the actual kernel.
This fixes that and gets rid of another long-standing issue that could
arise when attempting to create more than one process.
|
|
Similar to how WaitForAddress was isolated to its own function, we can
also move the necessary conditional checking into the address arbiter
class itself, allowing us to hide the implementation details of it from
public use.
|
|
Rather than let the service call itself work out which function is the
proper one to call, we can make that a behavior of the arbiter itself,
so we don't need to directly expose those implementation details.
|
|
Makes it much nicer to locally reason about server session behavior, as
part of its functionality isn't placed around other classes.
|
|
These can be made private, as they aren't accessed in contexts that
require them to be public.
|
|
Allows getting rid of reliance on the global accessor functions and
instead operating on the provided system instance.
|
|
- Invert conditions into guard clases where applicable.
- Mark std::vector parameter of WakeThreads as const
|
|
Places all of the functions for address arbiter operation into a class.
This will be necessary for future deglobalizing efforts related to both
the memory and system itself.
|
|
|
|
This is a TODO carried over from Citra that doesn't apply here.
|
|
Removes a few inclusion dependencies from the headers or replaces
existing ones with ones that don't indirectly include the required
headers.
This allows removing an inclusion of core/memory.h, meaning that if the
memory header is ever changed in the future, it won't result in
rebuilding the entirety of the HLE services (as the IPC headers are used
quite ubiquitously throughout the HLE service implementations).
|
|
Used as root for one region of cheats, set by loader
|
|
Significantly tidies up two guard conditionals.
|
|
Makes the interface uniform when it comes to checking various memory
regions.
|
|
Avoids directly relying on the global system instance and instead makes
an arbitrary system instance an explicit dependency on construction.
This also allows removing dependencies on some global accessor functions
as well.
|
|
Given we already pass in a reference to the kernel that the shared
memory instance is created under, we can just use that to check the
current process, rather than using the global accessor functions.
This allows removing direct dependency on the system instance entirely.
|
|
Provides a bit of a more proper interface for these functions.
|
|
Makes immutable state explicit.
|
|
The kernel allows restricting the total size of the handle table through
the process capability descriptors. Until now, this functionality wasn't
hooked up. With this, the process handle tables become properly restricted.
In the case of metadata-less executables, the handle table will assume
the maximum size is requested, preserving the behavior that existed
before these changes.
|
|
Directly initializes members where applicable.
|
|
Avoids implicit truncation warnings from u32 -> u16 (the truncation is
desirable behavior here).
|
|
A fairly trivial change. Other sections of the codebase use nested
namespaces instead of separate namespaces here. This one must have just
been overlooked.
|
|
Gets rid of the largest set of mutable global state within the core.
This also paves a way for eliminating usages of GetInstance() on the
System class as a follow-up.
Note that no behavioral changes have been made, and this simply extracts
the functionality into a class. This also has the benefit of making
dependencies on the core timing functionality explicit within the
relevant interfaces.
|
|
Places all of the timing-related functionality under the existing Core
namespace to keep things consistent, rather than having the timing
utilities sitting in its own completely separate namespace.
|
|
A holdover from citra, the Horizon kernel on the switch has no
prominent kernel object that functions as a timer. At least not
to the degree of sophistication that this class provided.
As such, this can be removed entirely. This class also wasn't used at
all in any meaningful way within the core, so this was just code sitting
around doing nothing. This also allows removing a few things from the
main KernelCore class that allows it to use slightly less resources
overall (though very minor and not anything really noticeable).
|
|
No inheritors of the WaitObject class actually make use of their own
implementations of these functions, so they can be made non-virtual.
It's also kind of sketchy to allow overriding how the threads get added
to the list anyways, given the kernel itself on the actual hardware
doesn't seem to customize based off this.
|
|
This implementation just calls the base class variant of the function,
so this isn't necessary.
|
|
This just calls the base variant of the function, so it can be removed.
|
|
Looking into the implementation of the C++ standard facilities that seem
to be within all modules, it appears that they use 7 as a break reason
to indicate an uncaught C++ exception.
This was primarily found via the third last function called within
Horizon's equivalent of libcxxabi's demangling_terminate_handler(),
which passes the value 0x80000007 to svcBreak.
|
|
Pulse is considered a hack and nothing should be using it. We should completely remove it
|
|
Gets rid of a few unnecessary header dependencies in some source files.
|
|
This is a bounds check to ensure that the thread priority is within the
valid range of 0-64. If it exceeds 64, that doesn't necessarily mean
that an actual priority of 64 was expected (it actually means whoever
called the function screwed up their math).
Instead clarify the message to indicate the allowed range of thread
priorities.
|
|
Now that we handle the kernel capability descriptors we can correct
CreateThread to properly check against the core and priority masks
like the actual kernel does.
|
|
Makes them consistent with their kernel capability counterparts.
|
|
Rather than use a switch here, this can be collapsed into a simple range
check, which is a little easier on the eyes.
|
|
This matches kernel behavior in that processes are started using their
specified ideal core, rather than always starting on core 0.
|
|
This makes the naming more closely match its meaning. It's just a
preferred core, not a required default core. This also makes the usages
of this term consistent across the thread and process implementations.
|
|
This function isn't a general purpose function that should be exposed to
everything, given it's specific to initializing the main thread for a
Process instance.
Given that, it's a tad bit more sensible to place this within
process.cpp, which keeps it visible only to the code that actually needs
it.
|
|
In all cases that these functions are needed, the VMManager can just be
retrieved and used instead of providing the same functions in Process'
interface.
This also makes it a little nicer dependency-wise, since it gets rid of
cases where the VMManager interface was being used, and then switched
over to using the interface for a Process instance. Instead, it makes
all accesses uniform and uses the VMManager instance for all necessary
tasks.
All the basic memory mapping functions did was forward to the Process'
VMManager instance anyways.
|
|
Like the other members related to memory regions, the attributes need to
be reset back to their defaults as well.
|
|
While we're at it, we can also toss out the leftover capability parsing
from Citra.
|
|
|
|
This just specifies the handle table size. There's also a section of
reserved bits that are checked against.
|
|
|
|
|
|
Similar to the service capability flags, however, we currently don't
emulate the GIC, so this currently handles all interrupts as being valid
for the time being.
|
|
|
|
Handles the priority mask and core mask flags to allow building up the
masks to determine the usable thread priorities and cores for a kernel
process instance.
|
|
We've had the old kernel capability parser from Citra, however, this is
unused code and doesn't actually map to how the kernel on the Switch
does it. This introduces the basic functional skeleton for parsing
process capabilities.
|
|
If a thread handle is passed to svcGetProcessId, the kernel attempts to
access the process ID via the thread's instance's owning process.
Technically, this function should also be handling the kernel debug
objects as well, however we currently don't handle those kernel objects
yet, so I've left a note via a comment about it to remind myself when
implementing it in the future.
|
|
With all the basic backing functionality implemented, we can now unstub
svcSetMemoryAttribute.
|
|
This puts the backing functionality for svcSetMemoryAttribute in place,
which will be utilized in a following change.
|
|
|
|
Starts the process ID counter off at 81, which is what the kernel itself
checks against internally when creating processes. It's actually
supposed to panic if the PID is less than 81 for a userland process.
|
|
The service call uses a 64-bit value, just like svcGetProcessId. This
amends the function signature accordingly.
|
|
The kernel uses a 64-bit value for the thread ID, so we shouldn't be
using a 32-bit value.
|
|
svcGetProcessId's out parameter is a pointer to a 64-bit value, not a
32-bit one.
|
|
In the actual kernel, this is a 64-bit value, so we shouldn't be using a
32-bit type to handle it.
|
|
|
|
Functions which are suppose to crash on non canary builds usually don't return anything which lead to uninitialized memory being used.
|
|
|
|
This is shorter and more concise. This also removes the now-innaccurate
comment, as it's not returned wholesale to svcQueryMemory anymore.
|
|
Adds the barebones enumeration constants and functions in place to
handle memory attributes, while also essentially leaving the attribute
itself non-functional.
|
|
svcQueryProcessMemory is trivial to implement, given all the behavior
necessary for it is present, it just needs a handler for it.
|
|
In the previous change, the memory writing was moved into the service
function itself, however it still had a problem, in that the entire
MemoryInfo structure wasn't being written out, only the first 32 bytes
of it were being written out. We still need to write out the trailing
two reference count members and zero out the padding bits.
Not doing this can result in wrong behavior in userland code in the following
scenario:
MemoryInfo info; // Put on the stack, not quaranteed to be zeroed out.
svcQueryMemory(&info, ...);
if (info.device_refcount == ...) // Whoops, uninitialized read.
This can also cause the wrong thing to happen if the user code uses
std::memcmp to compare the struct, with another one (questionable, but
allowed), as the padding bits are not guaranteed to be a deterministic
value. Note that the kernel itself also fully zeroes out the structure
before writing it out including the padding bits.
|
|
Moves the memory writes directly into QueryProcessMemory instead of
letting the wrapper function do it. It would be inaccurate to allow the
handler to do it because there's cases where memory shouldn't even be
written to. For example, if the given process handle is invalid.
HOWEVER, if the memory writing is within the wrapper, then we have no
control over if these memory writes occur, meaning in an error case, 68
bytes of memory randomly get trashed with zeroes, 64 of those being
written to wherever the memory info address points to, and the remaining
4 being written wherever the page info address points to.
One solution in this case would be to just conditionally check within
the handler itself, but this is kind of smelly, given the handler
shouldn't be performing conditional behavior itself, it's a behavior of
the managed function. In other words, if you remove the handler from the
equation entirely, does the function still retain its proper behavior?
In this case, no.
Now, we don't potentially trash memory from this function if an invalid
query is performed.
|
|
These should be swapped.
|
|
This would result in svcSetMemoryAttribute getting the wrong value for
its third parameter. This is currently fine, given the service function
is stubbed, however this will be unstubbed in a future change, so this
needs to change.
|
|
The kernel returns a memory info instance with the base address set to
the end of the address space, and the size of said block as
0 - address_space_end, it doesn't set both of said members to zero.
|
|
Gets rid of the need to directly access the managed VMAs outside of the
memory manager itself just for querying memory.
|
|
Gets the two structures out of an unrelated header and places them with
the rest of the memory management code.
This also corrects the structures. PageInfo appears to only contain a
32-bit flags member, and the extra padding word in MemoryInfo isn't
necessary.
|
|
Amends the MemoryState enum to use the same values like the actual
kernel does. Also provides the necessary operators to operate on them.
This will be necessary in the future for implementing
svcSetMemoryAttribute, as memory block state is checked before applying
the attribute.
|
|
The Process object kept itself alive indefinitely because its handle_table
contains a SharedMemory object which owns a reference to the same Process object,
creating a circular ownership scenario.
Break that up by storing only a non-owning pointer in the SharedMemory object.
|
|
This was only ever public so that code could check whether or not a
handle was valid or not. Instead of exposing the object directly and
allowing external code to potentially mess with the map contents, we
just provide a member function that allows checking whether or not a
handle is valid.
This makes all member variables of the VMManager class private except
for the page table.
|
|
A very trivial change. If metadata is available, the process should use
it to retrieve the desired core for the process to run on.
|
|
|
|
While partially correct, this service call allows the retrieved event to
be null, as it also uses the same handle to check if it was referring to
a Process instance. The previous two changes put the necessary machinery
in place to allow for this, so we can simply call those member functions
here and be done with it.
|
|
Process instances can be waited upon for state changes. This is also
utilized by svcResetSignal, which will be modified in an upcoming
change. This simply puts all of the WaitObject related machinery in
place.
|
|
svcResetSignal relies on the event instance to have already been
signaled before attempting to reset it. If this isn't the case, then an
error code has to be returned.
|
|
|
|
This function simply does a handle table lookup for a writable event
instance identified by the given handle value. If a writable event
cannot be found for the given handle, then an invalid handle error is
returned. If a writable event is found, then it simply signals the
event, as one would expect.
|
|
svcCreateEvent operates by creating both a readable and writable event
and then attempts to add both to the current process' handle table.
If adding either of the events to the handle table fails, then the
relevant error from the handle table is returned.
If adding the readable event after the writable event to the table
fails, then the writable event is removed from the handle table and the
relevant error from the handle table is returned.
Note that since we do not currently test resource limits, we don't check
the resource limit table yet.
|
|
Two kernel object should absolutely never have the same handle ID type.
This can cause incorrect behavior when it comes to retrieving object
types from the handle table. In this case it allows converting a
WritableEvent into a ReadableEvent and vice-versa, which is undefined
behavior, since the object types are not the same.
This also corrects ClearEvent() to check both kernel types like the
kernel itself does.
|
|
Another hold-over from Citra.
|
|
Allows a process to register the resource limit as part of its handle
table.
|
|
|
|
|
|
This will automatically occur anyway when PrepareReschedule is called
|
|
|
|
Added to both dynarmic and unicorn
|
|
When we get an svcBreak we get a backtrace now
|
|
The kernel uses the handle table of the current process to retrieve the
process that should be used to retrieve certain information. To someone
not familiar with the kernel, this might raise the question of "Ok,
sounds nice, but doesn't this make it impossible to retrieve information
about the current process?".
No, it doesn't, because HandleTable instances in the kernel have the
notion of a "pseudo-handle", where certain values allow the kernel to
lookup objects outside of a given handle table. Currently, there's only
a pseudo-handle for the current process (0xFFFF8001) and a pseudo-handle
for the current thread (0xFFFF8000), so to retrieve the current process,
one would just pass 0xFFFF8001 into svcGetInfo.
The lookup itself in the handle table would be something like:
template <typename T>
T* Lookup(Handle handle) {
if (handle == PSEUDO_HANDLE_CURRENT_PROCESS) {
return CurrentProcess();
}
if (handle == PSUEDO_HANDLE_CURRENT_THREAD) {
return CurrentThread();
}
return static_cast<T*>(&objects[handle]);
}
which, as is shown, allows accessing the current process or current
thread, even if those two objects aren't actually within the HandleTable
instance.
|
|
Our implementation of svcGetInfo was slightly incorrect in that we
weren't doing proper error checking everywhere. Instead, reorganize it
to be similar to how the kernel seems to do it.
|
|
|
|
A non-existent parameter was left in some formatting calls (the logging
macro for which only does anything meaningful on debug builds)
|
|
|
|
|
|
|
|
|
|
Used to store ReadableEvents of all events on the system.
|
|
More hardware accurate. On the actual system, there is a differentiation between the signaler and signalee, they form a client/server relationship much like ServerPort and ClientPort.
|
|
|
|
The opposite of the getter functions, this function sets the limit value
for a particular ResourceLimit resource category, with the restriction
that the new limit value must be equal to or greater than the current
resource value. If this is violated, then ERR_INVALID_STATE is returned.
e.g.
Assume:
current[Events] = 10;
limit[Events] = 20;
a call to this service function lowering the limit value to 10 would be
fine, however, attempting to lower it to 9 in this case would cause an
invalid state error.
|
|
This kernel service function is essentially the exact same as
svcGetResourceLimitLimitValue(), with the only difference being that it
retrieves the current value for a given resource category using the
provided resource limit handle, rather than retrieving the limiting
value of that resource limit instance.
Given these are exactly the same and only differ on returned values, we
can extract the existing code for svcGetResourceLimitLimitValue() to
handle both values.
|
|
This kernel service function retrieves the maximum allowable value for
a provided resource category for a given resource limit instance. Given
we already have the functionality added to the resource limit instance
itself, it's sufficient to just hook it up.
The error scenarios for this are:
1. If an invalid resource category type is provided, then ERR_INVALID_ENUM is returned.
2. If an invalid handle is provided, then ERR_INVALID_HANDLE is returned (bad thing goes in, bad thing goes out, as one would expect).
If neither of the above error cases occur, then the out parameter is
provided with the maximum limit value for the given category and success
is returned.
|
|
This function simply creates a ResourceLimit instance and attempts to
create a handle for it within the current process' handle table. If the
kernal fails to either create the ResourceLimit instance or create a
handle for the ResourceLimit instance, it returns a failure code
(OUT_OF_RESOURCE, and HANDLE_TABLE_FULL respectively). Finally, it exits
by providing the output parameter with the handle value for the
ResourceLimit instance and returning that it was successful.
Note: We do not return OUT_OF_RESOURCE because, if yuzu runs out of
available memory, then new will currently throw. We *could* allocate the
kernel instance with std::nothrow, however this would be inconsistent
with how all other kernel objects are currently allocated.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
These don't depend on class state, and are effectively implementation
details, so they can go into the cpp file .
|
|
The previous handle table size is a holdover from Citra. The actual
handle table construct on Horizon only allows for a maximum of 1024
entries.
|
|
We don't need to potentially inline the teardown logic of all of the
handle instances.
|
|
<random> isn't necesary directly within the header and can be placed in
the cpp file where its needed. Avoids propagating random generation
utilities via a header file.
|
|
Cleans out the citra/3DS-specific implementation details that don't
apply to the Switch. Sets the stage for implementing ResourceLimit
instances properly.
While we're at it, remove the erroneous checks within CreateThread() and
SetThreadPriority(). While these are indeed checked in some capacity,
they are not checked via a ResourceLimit instance.
In the process of moving out Citra-specifics, this also replaces the
system ResourceLimit instance's values with ones from the Switch.
|
|
Both member functions assume the passed in target process will not be
null. Instead of making this assumption implicit, we can change the
functions to be references and enforce this at the type-system level.
|
|
Given this doesn't mutate instance state, we can provide a
const-qualified variant as well.
|
|
Keeps the interface consistent with the regular Create() function.
|
|
Makes the interface nicer to use in terms of 64-bit code, as it makes it
less likely for one to get truncation warnings (and also makes sense in
the context of the rest of the interface where 64-bit types are used for
sizes and offsets
|
|
Rather than allow unfettered access to the class internals, we hide all
members by default and create and API that other code can operate
against.
|
|
|
|
https://user-images.githubusercontent.com/20753089/48677874-b8e01c80-eb7b-11e8-8043-b99faa29022c.PNG
|
|
|
|
Seems to be used and created identically to SharedMemory, so just reuse that.
|
|
|
|
Similar to PR 1706, which cleans up the error codes for the filesystem
code, but done for the kernel error codes. This removes the ErrCodes
namespace and specifies the errors directly. This also fixes up any
straggling lines of code that weren't using the named error codes where
applicable.
|
|
Credits to Subv
|
|
The code in both places was the same verbatim, so we can extract it to a
function to deduplicate the logic.
|
|
Now that we've moved all of the heap-related stuff to the VMManager
class, we can unstub this function, as the necessary members are visible
now.
|
|
Avoids a breach of responsibilities in the interface and keeps the
direct code for memory management within the VMManager class.
|
|
|
|
|
|
* svcBreak now dumps information from the debug buffer passed
info1 and info2 seem to somtimes hold an address to a buffer, this is usually 4 bytes or the size of the int and contains an error code. There's other circumstances where it can be something different so we hexdump these to examine them at a later date.
* Addressed comments
|
|
|
|
|
|
Cleans up unused includes and trims off some dependencies on externals.
|
|
* get rid of boost::optional
* Remove optional references
* Use std::reference_wrapper for optional references
* Fix clang format
* Fix clang format part 2
* Adressed feedback
* Fix clang format and MacOS build
|
|
Gets rid of the need to call the getter and then check for null.
|
|
Nothing requires the shared owner ship here, so we can just return a
plain pointer.
|
|
|
|
Nothing from this enum is intended to be used outside of this function.
|
|
This retrieves:
if (curr_thread == handle_thread) {
result = total_thread_ticks + (hardware_tick_count - last_context_switch_ticks);
} else if (curr_thread == handle_thread && sub_id == current_core_index) {
result = hardware_tick_count - last_context_switch_ticks;
}
|
|
|
|
|
|
Now that we've gotten the innaccurate error codes out of the way, we can
finally toss away a bunch of these, trimming down the error codes to
ones that are actually used and knocking out two TODO comments.
|
|
This is more consistent with what the kernel does.
|
|
|
|
This is what the kernel does in this instance.
|
|
These are now entirely unused and can be removed.
|
|
Like with the previous change, the kernel doesn't return NOT_AUTHORIZED
here. It returns INVALID_THREAD_PRIORITY.
|
|
All priority checks are supposed to occur before checking the validity
of the thread handle, we're also not supposed to return
ERR_NOT_AUTHORIZED here.
|
|
The kernel appears to return 0xE601 for this situation. Particularly in
svcWaitSynchronization, svcReplyAndReceive, and svcGetThreadContext
|
|
The kernel appears to return 0xF601 for this case.
|
|
|
|
There seems to be more such as type 1, and 2. Unsure what these currently are but when a game hits them we can investigate and add the rest
|
|
In the kernel, there isn't a singular handle table that everything gets
tossed into or used, rather, each process gets its own handle table that
it uses. This currently isn't an issue for us, since we only execute one
process at the moment, but we may as well get this out of the way so
it's not a headache later on.
|
|
This should be comparing against the queried process' vma_map, not the
current process'. The only reason this hasn't become an issue yet is we
currently only handle one process being active at any time.
|
|
The kernel itself checks whether or not the provided addresses are word
aligned before continuing, so we should be doing the same.
|
|
Aligning on 4KB pages isn't a Switch-specific thing, so this can be
moved to common so it can be used with other things as well.
|
|
Now that the changes clarifying the address spaces has been merged, we
can wrap the checks that the kernel performs when mapping shared memory
(and other forms of memory) into its own helper function and then use
those within MapSharedMemory and UnmapSharedMemory to complete the
sanitizing checks that are supposed to be done.
|
|
|
|
So, one thing that's puzzled me is why the kernel seemed to *not* use
the direct code address ranges in some cases for some service functions.
For example, in svcMapMemory, the full address space width is compared
against for validity, but for svcMapSharedMemory, it compares against
0xFFE00000, 0xFF8000000, and 0x7FF8000000 as upper bounds, and uses
either 0x200000 or 0x8000000 as the lower-bounds as the beginning of the
compared range. Coincidentally, these exact same values are also used in
svcGetInfo, and also when initializing the user address space, so this
is actually retrieving the ASLR extents, not the extents of the address
space in general.
|
|
This should help diagnose crashes easier and prevent many users thinking that a game is still running when in fact it's just an audio thread still running(this is typically not killed when svcBreak is hit since the game expects us to do this)
|
|
A fairly basic service function, which only appears to currently support
retrieving the process state. This also alters the ProcessStatus enum to
contain all of the values that a kernel process seems to be able of
reporting with regards to state.
|
|
These only exist to ferry data into a Process instance and end up going
out of scope quite early. Because of this, we can just make it a plain
struct for holding things and just std::move it into the relevant
function. There's no need to make this inherit from the kernel's Object
type.
|
|
Regular value initialization is adequate here for zeroing out data. It
also has the benefit of not invoking undefined behavior if a non-trivial
type is ever added to the struct for whatever reason.
|
|
|
|
This adds the missing address range checking that the service functions
do before attempting to map or unmap memory. Given that both service
functions perform the same set of checks in the same order, we can wrap
these into a function and just call it from both functions, which
deduplicates a little bit of code.
|
|
There's no real need to use a shared pointer in these cases, and only
makes object management more fragile in terms of how easy it would be to
introduce cycles. Instead, just do the simple thing of using a regular
pointer. Much of this is just a hold-over from citra anyways.
It also doesn't make sense from a behavioral point of view for a
process' thread to prolong the lifetime of the process itself (the
process is supposed to own the thread, not the other way around).
|
|
|
|
signal_debugger seems like a more fitting name
|
|
svcBreak reason should be a u32, not a u64.
|
|
|
|
|
|
When loading NROs, svcBreak is called to signal to the debugger that a new "module" is loaded. As no debugger is technically attached we shouldn't be killing the programs execution.
|
|
|
|
This will allow us to easily remove the use of "NFC" in "System"
|
|
This was the result of a typo accidentally introduced in
e51d715700a35a8f14e5b804b6f7553c9a40888b. This restores the previous
correct behavior.
The behavior with the reference was incorrect and would cause some games
to fail to boot.
|
|
Conceptually, it doesn't make sense for a thread to be able to persist
the lifetime of a scheduler. A scheduler should be taking care of the
threads; the threads should not be taking care of the scheduler.
If the threads outlive the scheduler (or we simply don't actually
terminate/shutdown the threads), then it should be considered a bug
that we need to fix.
Attributing this to balika011, as they opened #1317 to attempt to fix
this in a similar way, but my refactoring of the kernel code caused
quite a few conflicts.
|
|
Many of the member variables of the thread class aren't even used
outside of the class itself, so there's no need to make those variables
public. This change follows in the steps of the previous changes that
made other kernel types' members private.
The main motivation behind this is that the Thread class will likely
change in the future as emulation becomes more accurate, and letting
random bits of the emulator access data members of the Thread class
directly makes it a pain to shuffle around and/or modify internals.
Having all data members public like this also makes it difficult to
reason about certain bits of behavior without first verifying what parts
of the core actually use them.
Everything being public also generally follows the tendency for changes
to be introduced in completely different translation units that would
otherwise be better introduced as an addition to the Thread class'
public interface.
|
|
Now that we have all of the rearranging and proper structure sizes in
place, it's fairly trivial to implement svcGetThreadContext(). In the
64-bit case we can more or less just write out the context as is, minus
some minor value sanitizing. In the 32-bit case we'll need to clear out
the registers that wouldn't normally be accessible from a 32-bit
AArch32 exectuable (or process).
|
|
This will be necessary for the implementation of svcGetThreadContext(),
as the kernel checks whether or not the process that owns the thread
that has it context being retrieved is a 64-bit or 32-bit process.
If the process is 32-bit, then the upper 15 general-purpose registers
and upper 16 vector registers are cleared to zero (as AArch32 only has
15 GPRs and 16 128-bit vector registers. not 31 general-purpose
registers and 32 128-bit vector registers like AArch64).
|
|
Makes the public interface consistent in terms of how accesses are done
on a process object. It also makes it slightly nicer to reason about the
logic of the process class, as we don't want to expose everything to
external code.
|
|
boost::static_pointer_cast for boost::intrusive_ptr (what SharedPtr is),
takes its parameter by const reference. Given that, it means that this
std::move doesn't actually do anything other than obscure what the
function's actual behavior is, so we can remove this. To clarify, this
would only do something if the parameter was either taking its argument
by value, by non-const ref, or by rvalue-reference.
|
|
It doesn't make sense to allow a scheduler to be constructed around a
null pointer.
|
|
The locations of these can actually vary depending on the address space
layout, so we shouldn't be using these when determining where to map
memory or be using them as offsets for calculations. This keeps all the
memory ranges flexible and malleable based off of the virtual memory
manager instance state.
|
|
Previously, these were reporting hardcoded values, but given the regions
can change depending on the requested address spaces, these need to
report the values that the memory manager contains.
|
|
Given games can also request a 32-bit or 39-bit address space, we
shouldn't be hardcoding the address space range as 36-bit.
|
|
Rather than hard-code the address range to be 36-bit, we can derive the
parameters from supplied NPDM metadata if the supplied exectuable
supports it. This is the bare minimum necessary for this to be possible.
The following commits will rework the memory code further to adjust to
this.
|
|
|
|
Reduces the use of Process class members externally and keeps most code
related to tearing down a process with the rest of the process code.
|
|
Allows making several members of the process class private, it also
avoids going through Core::CurrentProcess() just to retrieve the owning
process.
|
|
The owning process of a thread is required to exist before the thread,
so we can enforce this API-wise by using a reference. We can also avoid
the reliance on the system instance by using that parameter to access
the page table that needs to be set.
|
|
Avoids an unnecessary inclusion and also uncovers three places where
indirect inclusions were relied upon, which allows us to also resolve
those.
|
|
This can just be a regular function, getting rid of the need to also
explicitly undef the define at the end of the file. Given FuncReturn()
was already converted into a function, it's #undef can also be removed.
|
|
This modifies the CPU interface to more accurately match an
AArch64-supporting CPU as opposed to an ARM11 one. Two of the methods
don't even make sense to keep around for this interface, as Adv Simd is
used, rather than the VFP in the primary execution state. This is
essentially a modernization change that should have occurred from the
get-go.
|
|
We already have a ResultCode constant for the case of an invalid
address, so we can just use it instead of re-rolling that ResultCode
type.
|
|
The kernel does the equivalent of the following check before proceeding:
if (address + 0x8000000000 < 0x7FFFE00000) {
return ERR_INVALID_MEMORY_STATE;
}
which is essentially what our IsKernelVirtualAddress() function does. So
we should also be checking for this.
The kernel also checks if the given input addresses are 4-byte aligned,
however our Mutex::TryAcquire() and Mutex::Release() functions already
handle this, so we don't need to add code for this case.
|
|
|
|
|
|
The kernel caps the size limit of shared memory to 8589930496 bytes (or
(1GB - 512 bytes) * 8), so approximately 8GB, where every GB has a 512
byte sector taken off of it.
It also ensures the shared memory is created with either read or
read/write permissions for both permission types passed in, allowing the
remote permissions to also be set as "don't care".
|
|
Part of the checking done by the kernel is to check if the given
address and size are 4KB aligned, as well as checking if the size isn't
zero. It also only allows mapping shared memory as readable or
read/write, but nothing else, and so we shouldn't allow mapping as
anything else either.
|
|
The kernel checks if the addresses and given size is 4KB aligned before
continuing onwards to map the memory.
|
|
The kernel checks if the given size is a multiple of 2MB and <= to 4GB
before going ahead and attempting to allocate that much memory.
|
|
This is the value returned by the kernel for svcConnectToNamedPort() if
the named port cannot be found.
|
|
Previously, these were sitting outside of the Kernel namespace, which
doesn't really make sense, given they're related to the Thread class
which is within the Kernel namespace.
|
|
This is what the kernel does for an out-of-range processor ID.
|
|
|
|
While unlikely, it does avoid constructing a std::string and
unnecessarily calling into the memory code if a game or executable
decides to be really silly about their logging.
|
|
This should be a u64 to represent size.
|
|
Given we now have the kernel as a class, it doesn't make sense to keep
the current process pointer within the System class, as processes are
related to the kernel.
This also gets rid of a subtle case where memory wouldn't be freed on
core shutdown, as the current_process pointer would never be reset,
causing the pointed to contents to continue to live.
|
|
Now that we have a class representing the kernel in some capacity, we
now have a place to put the named port map, so we move it over and get
rid of another piece of global state within the core.
|
|
The follow-up to e2457418dae19b889b2ad85255bb95d4cd0e4bff, which
replaces most of the includes in the core header with forward declarations.
This makes it so that if any of the headers the core header was
previously including change, then no one will need to rebuild the bulk
of the core, due to core.h being quite a prevalent inclusion.
This should make turnaround for changes much faster for developers.
|
|
As means to pave the way for getting rid of global state within core,
This eliminates kernel global state by removing all globals. Instead
this introduces a KernelCore class which acts as a kernel instance. This
instance lives in the System class, which keeps its lifetime contained
to the lifetime of the System class.
This also forces the kernel types to actually interact with the main
kernel instance itself instead of having transient kernel state placed
all over several translation units, keeping everything together. It also
has a nice consequence of making dependencies much more explicit.
This also makes our initialization a tad bit more correct. Previously we
were creating a kernel process before the actual kernel was initialized,
which doesn't really make much sense.
The KernelCore class itself follows the PImpl idiom, which allows
keeping all the implementation details sealed away from everything else,
which forces the use of the exposed API and allows us to avoid any
unnecessary inclusions within the main kernel header.
|
|
We can make this error code an alias of the resource limit exceeded
error code, allowing us to get rid of the lingering 3DS error code of
the same type.
|
|
We can treat this as an alias of TooLarge for documentation purposes.
This also lets us get rid of another lingering 3DS-related error code.
|
|
This replaces the lingering 3DS constant with the proper one, and
utilizes it within HandleTable's Create() member function.
|
|
|
|
|
|
We already have the variable itself set up to perform this task, so we
can just return its value from the currently executing process instead
of always stubbing it to zero.
|
|
Gets all of these types and interfaces out of the global namespace.
|
|
Allows querying the inverse of IsDomain() to make things more readable.
This will likely also be usable in the event of implementing
ConvertDomainToSession().
|
|
Given if we hit here all is lost, we should probably be logging the
break reason code and associated information to distinguish between the
causes.
|
|
|
|
Despite being covered by a global mutex, we should still ensure that the
class handles its reference counts properly. This avoids potential
shenanigans when it comes to data races.
Given this is the root object that drives quite a bit of the kernel
object hierarchy, ensuring we always have the correct behavior (and no
races) is a good thing.
|
|
The current core may have nothing to do with the core where the new thread was scheduled to run. In case it's the same core, then the following PrepareReshedule call will take care of that.
|
|
Another thread might be in the middle of a reschedule, thus altering the state of the schedulers.
|
|
WakeAfterDelay might be called from any host thread, so err on the side of caution and use the thread-safe CoreTiming::ScheduleEventThreadsafe.
Note that CoreTiming is still far from thread-safe, there may be more things we have to work on for it to be up to par with what we want.
|
|
Exit from AddMutexWaiter early if the thread is already waiting for a mutex owned by the owner thread.
This accounts for the possibility of a thread that is waiting on a condition variable being awakened twice in a row.
Also added more validation asserts.
This should fix one of the random crashes in Breath Of The Wild.
|
|
This function doesn't modify instance state, so the const qualifier can
be added to it.
|
|
|
|
This function doesn't modify anything within the reference Thread
instance.
|
|
These members don't need to be entirely exposed, we can instead expose
an API to operate on them without directly needing to mutate them
We can also guard against overflow/API misuse this way as well, given
active_sessions is an unsigned value.
|
|
Instead we can simply provide accessors to the required data instead of
giving external read/write access to the variables directly.
|
|
In all cases the vector being supplied is empty, so we can just return
by value in these instances.
|
|
This amends cases where crashes can occur that were missed due to the
odd way the previous code was set up (using 3DS memory regions that
don't exist).
|
|
|
|
Using member variables for referencing the segments array increases the
size of the class in memory for little benefit. The same behavior can be
achieved through the use of accessors that just return the relevant
segment.
|
|
Removes leftover code from citra that isn't needed.
|
|
|
|
Makes our immutable state explicit.
|
|
These two variables correspond to address ranges.
|
|
Avoids using a u32 to compare against a range of size_t, which can be a
source of warnings. While we're at it, compress a std::tie into a
structured binding.
|
|
This function only reads the data being referenced, it doesn't modify
it, so we can turn the reference into a const reference.
|
|
This function isn't used outside of this translation unit, so we can
make it internally linked.
|
|
General moving to keep kernel object types separate from the direct
kernel code. Also essentially a preliminary cleanup before eliminating
global kernel state in the kernel code.
|
|
Given there's no implementation, we may as well remove the code
entirely.
|
|
These source files were entirely unused throughout the rest of the
codebase. This also has the benefit of getting rid of a global variable
as well.
|
|
Removes unnecessary direct dependencies in some headers and also gets
rid of indirect dependencies that were being relied on to be included.
|
|
Instead, we can just expose functions that return the queryable state
instead of letting anything modify it.
|
|
The loop's induction variable was signed, but we were comparing against
an unsigned variable.
|
|
Provides slightly more context than only logging out the address value.
|
|
|
|
The pointed to thread's members are simply observed in this case, so we
don't need to copy it here.
|
|
|
|
This is just an unused hold-over from citra, so we can get rid of this
to trim off an exposed global, among other things.
|
|
This is a holdover from citra that's essentially unused.
|
|
|
|
Note that there's currently a dynarmic bug preventing this register from being written.
|
|
Makes the thread status strongly typed, so implicit conversions can't
happen. It also makes it easier to catch mistakes at compile time.
|
|
This introduces a slightly more generic variant of WriteBuffer().
Notably, this variant doesn't constrain the arguments to only accepting
std::vector instances. It accepts whatever adheres to the
ContiguousContainer concept in the C++ standard library.
This essentially means, std::array, std::string, and std::vector can be
used directly with this interface. The interface no longer forces you to
solely use containers that dynamically allocate.
To ensure our overloads play nice with one another, we only enable the
container-based WriteBuffer if the argument is not a pointer, otherwise
we fall back to the pointer-based one.
|
|
The reason this would never be true is that ideal_processor is a u8 and
THREADPROCESSORID_DEFAULT is an s32. In this case, it boils down to how
arithmetic conversions are performed before performing the comparison.
If an unsigned value has a lesser conversion rank (aka smaller size)
than the signed type being compared, then the unsigned value is promoted
to the signed value (i.e. u8 -> s32 happens before the comparison). No
sign-extension occurs here either.
An alternative phrasing:
Say we have a variable named core and it's given a value of -2.
u8 core = -2;
This becomes 254 due to the lack of sign. During integral promotion to
the signed type, this still remains as 254, and therefore the condition
will always be true, because no matter what value the u8 is given it
will never be -2 in terms of 32 bits.
Now, if one type was a s32 and one was a u32, this would be entirely
different, since they have the same bit width (and the signed type would
be converted to unsigned instead of the other way around) but would
still have its representation preserved in terms of bits, allowing the
comparison to be false in some cases, as opposed to being true all the
time.
---
We also get rid of two signed/unsigned comparison warnings while we're
at it.
|
|
Previously, the buffer_index parameter was unused, causing all writes to
use the buffer index of zero, which is not necessarily what is wanted
all the time.
Thankfully, all current usages don't use a buffer index other than zero,
so this just prevents a bug before it has a chance to spring.
|
|
This was introduced within 4f81bc4e1bd12e4df7410c6790ba818d8dbba9c0, and
considering there's no comment indicating that this is intentional, this
is very likely a bug.
|
|
Without these, this would perform concatenation, which is definitely not
what we want here.
|
|
Avoids pointless copies
|
|
This would result in a lot of allocations and related object
construction, just to toss it all away immediately after the call.
These are definitely not intentional, and it was intended that all of
these should have been accessing the static function GetInstance()
through the name itself, not constructed instances.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
prevent yuzu crash, if games, like Axiom Verge, trying to read 0 bytes from file
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This situation may happen like so:
Thread 1 with low priority calls WaitProcessWideKey with timeout.
Thread 2 with high priority calls WaitProcessWideKey without timeout.
Thread 3 calls SignalProcessWideKey
- Thread 2 acquires the lock and awakens.
- Thread 1 can't acquire the lock and is put to sleep with the lock owner being Thread 2.
Thread 1's timeout expires, with the lock owner still being set to Thread 2.
|
|
|
|
Also added some proper error handling.
|
|
|
|
* add some InfoType
* correct OpenApplicationProxy cmd number
* add IDisplayController functions
* fix clang-format
* add more system languages
|
|
A thread may own multiple mutexes at the same time, and only release one of them while other threads are waiting for the other mutexes.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This makes the formatting expectations more obvious (e.g. any zero padding specified
is padding that's entirely dedicated to the value being printed, not any pretty-printing
that also gets tacked on).
|
|
- This can be used for domain objects as inputs to service functions.
|
|
* GetSharedFontInOrderOfPriority
* Update pl_u.cpp
* Ability to use ReadBuffer and WriteBuffer with different buffer indexes, fixed up GetSharedFontInOrderOfPriority
* switched to NGLOG
* Update pl_u.cpp
* Update pl_u.cpp
* language_code is actually language code and not index
* u32->u64
* final cleanups
|
|
All of these variables and functions are related to timings and should be within the namespace.
|
|
Given we utilize fmt, we don't need to provide our own functions for formatting anymore
|
|
|
|
|
|
Functions don't need to be terminated by semicolons.
|
|
|
|
Verified with a hwtest and implemented based on reverse engineering.
Thread A's priority will get bumped to the highest priority among all the threads that are waiting for a mutex that A holds.
Once A releases the mutex and ownership is transferred to B, A's priority will return to normal and B's priority will be bumped.
|
|
|
|
|
|
|
|
|
|
They work in tandem with guest code to provide synchronization primitives along with svcArbitrateLock/Unlock
|
|
Switch mutexes are no longer kernel objects, they are managed in userland and only use the kernel to handle the contention case.
Mutex addresses store a special flag value (0x40000000) to notify the guest code that there are still some threads waiting for the mutex to be released. This flag is updated when a thread calls ArbitrateUnlock.
TODO:
* Fix svcWaitProcessWideKey
* Fix svcSignalProcessWideKey
* Remove the Mutex class.
|
|
Prevents enum identifiers from leaking into the surrounding scope.
|
|
C++17 has non-member size() which we can just call where necessary.
|
|
* Updated ACC with more service names
* Updated SVC with more service names
* Updated set with more service names
* Updated sockets with more service names
* Updated SPL with more service names
* Updated time with more service names
* Updated vi with more service names
|
|
- Gets Binding of Isaac running.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
There may be many CodeSets per Process, so it's wasteful and overcomplicated to store the program id in each of them.
|
|
|
|
|
|
C++11 requires spaces on the Identifier
Add inttypes include
clang
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Ported from citra PR #3091
The delay specified here is from a Nintendo 3DS, and should be measured in a Nintendo Switch.
This change is enough to prevent Puyo Puyo Tetris's main thread starvation.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
* Added svcCreateSharedMemory
* Services which are not implemented now throw UNIMPLEMENTED()
* clang-format
* changed perms to u32
* removed camelcase
|
|
* Fixes some cast warnings, partially fixes citra #3064
* Converted casts to uint32_t to u32
* Ran clang-format
|
|
|
|
|
|
* Stub PopLaunchParameter and implement Buffer C Descriptors reading
* Address PR feedback
* Ensure we push a u64 not a size_t
* Fix formatting
|
|
Makes the codebase a little more consistent with regards to available documentation. Also amends the duplicate case where there was a similar entry at 0x72 named ConnectToPort.
|
|
Makes the table match SwitchBrew for these entries
|
|
|
|
|
|
|
|
# Conflicts:
# src/core/hle/kernel/svc.cpp
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Also properly keep track of data in guest memory, this fixes managing the semaphore from userland.
It was found that Semaphores are actually Condition Variables, with Release(1) and Release(-1) being equivalent to notify_one and notify_all. We should change the name of the class to reflect this.
|
|
|
|
|
|
* CoreTiming: New CoreTiming; Add Test for CoreTiming
|
|
|
|
|
|
Popping objects from the buffer is still not implemented.
|
|
Service code now doesn't have to deal with this.
|
|
Domain object ids are always stored immediately after the raw data.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This is kinda crufty, but we need it for now to update guest state variables.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Also reference the right offset into the backing block for the requested address.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This change makes for a clearer (less confusing) path of execution in the scheduler, now the code to execute when a thread awakes is closer to the code that puts the thread to sleep (WaitSynch1, WaitSynchN). It also allows us to implement the special wake up behavior of ReplyAndReceive without hacking up WaitObject::WakeupAllWaitingThreads.
If savestates are desired in the future, we can change this implementation to one similar to the CoreTiming event system, where we first register the callback functions at startup and assign their identifiers to the Thread callback variable instead of directly assigning a lambda to the wake up callback variable.
|
|
Don't automatically assume that Thread::Create will only be called when the parent process is currently scheduled. This assumption will be broken when applets or system modules are loaded.
|
|
Don't expose Memory::current_page_table as a global.
|
|
We were unnecessarily clearing the cache when going from Process A -> Idle -> Process A, this caused extreme performance regressions.
|
|
|
|
|
|
The loader is in charge of setting the newly created process's page table as the main one during the loading process.
|
|
This mutex is acquired in SVC::CallSVC, ie, as soon as the guest application enters the HLE kernel, and should be acquired by the aforementioned threads before modifying kernel structures.
|
|
This is necessary for loading multiple processes at the same time.
The main thread will be automatically scheduled when necessary once the scheduler runs.
|
|
|
|
|
|
|
|
|
|
|
|
And fix a few places in the code to take advantage of that.
|
|
Missed this in my first implementation. Thanks to @wwylele for pointing
out that this was missing.
|
|
Replace it with std::move(result_val).Unwrap(), or Foo().Unwrap() in
case you already have an rvalue.
|
|
|
|
|
|
|
|
Reduces the necessary allocation to max(in_handles, out_handles) rather
than (in_handles + out_handles).
|
|
|
|
|
|
Copy the IPC command buffer to/from the request context before/after the
handler is invoked. This is part of a move away from using global data
for handling IPC requests.
|
|
|
|
Fixes #2760
|
|
The old "Interface" class had a few problems such as using free
functions (Which didn't allow you to write the service handler as if it
were a regular class.) which weren't very extensible. (Only received one
parameter with a pointer to the Interface object.)
The new ServiceFramework aims to solve these problems by working with
member functions and passing a generic context struct as parameter. This
struct can be extended in the future without having to update all
existing service implementations.
|
|
|
|
This allows attaching a HLE handle to a ServerPort at any point after it
is created, allowing port/session creation to be generic between HLE and
regular services.
|
|
Most of the code that works with this is or will be in the kernel, so
it's a more appropriate place for it to be.
|
|
|
|
Now that HandleTable doesn't directly depend on WaitObject anymore, this
can be separated from the main kernel.h header.
|
|
This isn't necessary anymore since plain Get works correctly for
WaitObjects.
|
|
|
|
|
|
It is not meant to be used by anything other than CreateSessionPair.
|
|
|
|
Reduce the associated port's connection count when a ServerSession is destroyed.
|
|
This replaces the hardcoded VRAM/DSP mappings with ones made based on
the ExHeader ARM11 Kernel caps list. While this has no visible effect
for most applications (since they use a standard set of mappings) it
does improve support for system modules and n3DS exclusives.
|
|
Also move address space mapping out of video_core.
|
|
|
|
|
|
Corrects a few issues with regards to Doxygen documentation, for example:
- Incorrect parameter referencing.
- Missing @param tags.
- Typos in @param tags.
and a few minor other issues.
|
|
|
|
|
|
|
|
|
|
With this we avoid an useless temporary deschedule of the current thread.
|
|
|
|
After hwtesting and reverse engineering the kernel, it was found that the CTROS scheduler performs no priority boosting for threads like this, although some other forms of scheduling priority-starved threads might take place.
For example, it was found that hardware interrupts might cause low-priority threads to run if the CPU is preempted in the middle of an SVC handler that deschedules the current (high priority) thread before scheduling it again.
|
|
Closes #1904
|
|
The regression was caused by a missing check in #2260.
The new behavior is consistent with the real kernel.
|
|
|
|
This fixes a potential bug where threads would not get removed from said list if they awoke after waiting with WaitSynchronizationN with wait_all = false
|
|
|
|
This commit removes the overly general THREADSTATUS_WAIT_SYNCH and replaces it with two more granular statuses:
THREADSTATUS_WAIT_SYNCH_ANY when a thread waits on objects via WaitSynchronization1 or WaitSynchronizationN with wait_all = false.
THREADSTATUS_WAIT_SYNCH_ALL when a thread waits on objects via WaitSynchronizationN with wait_all = true.
|
|
|
|
|
|
The implementation is based on reverse engineering of the 3DS's kernel.
A mutex holder's priority will be temporarily boosted to the best priority among any threads that want to acquire any of its held mutexes.
When the holder releases the mutex, it's priority will be boosted to the best priority among the threads that want to acquire any of its remaining held mutexes.
|
|
This will be useful when implementing mutex priority inheritance.
|
|
Not all syscalls should cause reschedules, this commit attempts to remedy that, however, it still does not cover all cases.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Define a variable with the value of the sync timeout error code.
Use a boost::flat_map instead of an unordered_map to hold the equivalence of objects and wait indices in a WaitSynchN call.
|
|
Further implementation will happen in a future commit.
Fixes a regression.
|
|
|
|
|
|
|
|
The error code was taken from the 3DS kernel.
|
|
HandleSyncRequest now takes care of calling the command buffer translate function before actually invoking the command handler for HLE services.
|
|
|
|
|
|
|
|
Threads will now be awakened when the objects they're waiting on are signaled, instead of repeating the WaitSynchronization call every now and then.
The scheduler is now called once after every SVC call, and once after a thread is awakened from sleep by its timeout callback.
This new implementation is based off reverse-engineering of the real kernel.
See https://gist.github.com/Subv/02f29bd9f1e5deb7aceea1e8f019c8f4 for a more detailed description of how the real kernel handles rescheduling.
|
|
|
|
|
|
Sessions and Ports are now detached from each other.
HLE services are handled by means of a SessionRequestHandler class, Interface now inherits from this class.
The File and Directory classes are no longer kernel objects, but SessionRequestHandlers instead, bound to a ServerSession when requested.
File::OpenLinkFile now creates a new session pair and binds the File instance to it.
|
|
Pass the triggering ServerSession to the HLE command handler to differentiate which session caused the request.
|
|
Interface is now used by aggregation in ClientPort, to forward service commands to their HLE implementation if needed.
|
|
|
|
All handles obtained via srv::GetServiceHandle or svcConnectToPort are references to ClientSessions.
Service modules will wait on the counterpart of those ClientSessions (Called ServerSessions) using svcReplyAndReceive or svcWaitSynchronization[1|N], and will be awoken when a SyncRequest is performed.
HLE Interfaces are now ClientPorts which override the HandleSyncRequest virtual member function to perform command handling immediately.
|
|
3dsx and elf files default to system mode 2 (96MB allocated to the application).
This allows Home Menu to boot without modifications.
Closes #1849
|
|
Related to #1904
|
|
|
|
|
|
|
|
|
|
This makes clang-format useful on those.
Also add a bunch of forgotten transitive includes, which otherwise
prevented compilation.
|
|
|
|
|
|
|
|
|
|
|
|
This is part of an ongoing effort to implement support for multiple processes.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Reserve enough space in the vector that holds the linear heap memory to prevent relocations of the backing memory when growing too much.
Closes #1790
|
|
|
|
|
|
|
|
|
|
|
|
Applications can request the kernel to allocate a piece of the linear heap for them when creating a shared memory object.
Shared memory areas are now properly mapped into the target processes when calling svcMapMemoryBlock.
Removed the APT Shared Font hack as it is no longer needed.
|
|
R0 is used as the last parameter instead of R4.
|
|
We do not currently implement any cores other than the AppCore (Core 0).
|
|
Each thread gets a 0x200-byte area from the 0x1000-sized page, when all 8 thread slots in a single page are used up, the kernel allocates a new page to hold another 8 entries.
This is consistent with what the real kernel does.
|
|
|
|
|
|
This shouldn't be directly exposed if there's already a partial API that operates on it.
We can just provide the rest of that API.
|
|
|
|
|
|
|
|
This commit:
* Adds a new subproject, audio_core.
* Defines structures that exist in DSP shared memory.
* Hooks up various other parts of the emulator into audio core.
This sets the foundation for a later HLE DSP implementation.
|
|
|
|
|
|
This implementation will need to be (almost completely) changed when we implement multiprocess support.
|
|
Closes #1139
|
|
This was verified with hwtests that i plan to upload later on.
|
|
This makes smealum/ctrulib@b96dd51d3349961189d4ab1bc2a5c45deff21c09 work
with Citra.
|
|
|
|
|
|
|
|
Typo which sneaked in through review on #1025
|
|
|
|
Should fix invalid read loops in some games
|
|
|
|
This also adds some basic memory usage accounting. These two types are
used by Super Smash Bros. during startup.
|
|
This adds some structures necessary to support multiple memory regions
in the future. It also adds support for different system memory types
and the new linear heap mapping at 0x30000000.
|
|
|
|
These helpers aren't really part of the kernel, and mem_map.cpp/h is
going to be moved there next.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
They'll be reset if needed during the next svcWaitSynchronization call (if there's any pending)
|
|
This commit fixes several kernel object leaks. The most severe of them
was threads not being removed from the private handle table used for
CoreTiming events. This resulted in Threads never being released, which
in turn held references to Process, causing CodeSets to never be freed
when loading other applications.
|
|
|
|
|
|
The code now properly configures the process image to match the loaded
binary segments (code, rodata, data) instead of just blindly allocating
a large chunk of dummy memory.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This enables more dynamic management of the process address space,
compared to just directly configuring the page table for major areas.
This will serve as the foundation upon which the rest of the Kernel
memory management functions will be built.
|
|
|
|
|
|
Implemented svcs GetResourceLimit, GetResourceLimitCurrentValues and GetResourceLimitLimitValues.
Note that the resource limits do not currently keep track of used objects, since we have no way to distinguish between an object created by the application, and an object created by some HLE module once we're inside Kernel::T::Create.
|
|
memory.cpp/h contains definitions related to acessing memory and
configuring the address space
mem_map.cpp/h contains higher-level definitions related to configuring
the address space accoording to the kernel and allocating memory.
|
|
Sign mismatches and "forcing value to bool" warnings.
|
|
|
|
Instead just use nullptr to represent no thread is active.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
The TLS area for thread T with id Ti is located at TLS_AREA_VADDR + (Ti - 1) * 0x200.
This allows some games like Mario Kart 7 to continue further.
|
|
This works around crashes related to GSP/HID/etc. shared memory blocks
having garbage values. The proper fix requires proper management of
mapped memory blocks in the process.
|
|
|
|
When the macro was introduced in 326ec51261299e48de97592631c02523da9c8118
it wasn't noticed that it conflicted in name with a heavily used macro
inside of dyncom. This causes some compiler warnings. Since it's only
lightly used, it was opted to simply remove the new macro.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This has been obsoleted by the field in Process.
|
|
|
|
|
|
|
|
|
|
|
|
- CreateMutex/ReleaseMutex/ReleaseSemaphore/SetTimer/CancelTimer/ArbitrateAddress
|
|
|
|
SVC: Return correct error code on invalid CreateThread processor ID.
SVC: Assert when creating a thread with an invalid userland priority.
|
|
|
|
|
|
|
|
|
|
Involves making asserts use printf instead of the log functions (log functions are asynchronous and, as such, the log won't be printed in time)
As such, the log type argument was removed (printf obviously can't use it, and it's made obsolete by the file and line printing)
Also removed some GEKKO cruft.
|
|
* Simplifies scheduling logic, specifically regarding thread status. It should be much clearer which statuses are valid
for a thread at any given point in the system.
* Removes dead code from thread.cpp.
* Moves the implementation of resetting a ThreadContext to the corresponding core's implementation.
Other changes:
* Fixed comments in arm interfaces.
* Updated comments in thread.cpp
* Removed confusing, useless, functions like MakeReady() and ChangeStatus() from thread.cpp.
* Removed stack_size from Thread. In the CTR kernel, the thread's stack would be allocated before thread creation.
|
|
|
|
|
|
They're finally unnecessary, and will stop cluttering the application's
handle table.
|
|
During normal operation, a thread waiting on an WaitObject and the
object hold mutual references to each other for the duration of the
wait.
If a process is forcefully terminated (The CTR kernel has a SVC to do
this, TerminateProcess, though no equivalent exists for threads.) its
threads would also be stopped and destroyed, leaving dangling pointers
in the WaitObjects.
The solution is to simply have the Thread remove itself from WaitObjects
when it is stopped. The vector of Threads in WaitObject has also been
changed to hold SharedPtrs, just in case. (Better to have a reference
cycle than a crash.)
|
|
This should speed up compile times a bit, as well as enable more liberal
use of forward declarations. (Due to SharedPtr not trying to emit the
destructor anymore.)
|
|
|
|
|
|
|
|
|
|
This is to support the removal of GetHandle soon
|
|
|
|
|
|
Remove unnecessary/unused struct variables.
|
|
|
|
|
|
It was only being used in two places, where it was replaced by a local
constant.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- ReleaseNextThread->WakeupNextThread
- ReleaseAllWaitingThreads->WakeupAllWaitingThreads.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- Separate wait checking from waiting the current thread
- Resume thread when wait_all=true only if all objects are available at once
- Set output to correct wait object index when there are duplicate handles
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
If a thread was woken up by something, cancel the wakeup timeout.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
It will now properly wait the specified number of nanoseconds and then wake up the thread.
|
|
This thread will not actually execute instructions, it will only advance the timing/events and try to yield immediately to the next ready thread, if there aren't any ready threads then it will be rescheduled and start its job again.
|
|
Replace all the C-style complicated buffer management with a std::deque.
In addition to making the code easier to understand it also adds support
for non-POD IdTypes.
Also clean the rest of the code to follow our code style.
|
|
This will happen when the mutex is already owned by another thread. Should fix some issues with games being stuck due to waiting threads not being awoken.
|
|
(Thanks 3dmoo!)
|
|
This handle manager more closely mirrors the behaviour of the CTR-OS
one. In addition object ref-counts and support for DuplicateHandle have
been added.
Note that support for DuplicateHandle is still experimental, since parts
of the kernel still use Handles internally, which will likely cause
troubles if two different handles to the same object are used to e.g.
wait on a synchronization primitive.
|
|
|
|
|
|
|
|
- Removed unused VBLANK sleep mode
- Added error log for bad context switch
- Renamed VerifyWait to CheckWaitType to be more clear
|
|
|
|
This boots a few (mostly Nintendo 1st party) games further.
|
|
The savedata for each game is stored in /savedata/<ProgramID> for NCCH files. ELF files and 3DSX files use the folder 0 because they have no ID information
Got rid of the code duplication in File and Directory
Files that deal with the host machine's file system now live in DiskFile, similarly for directories and DiskDirectory and archives with DiskArchive.
FS_U: Use the correct error code when a file wasn't found
|
|
|
|
|
|
This is a first step at fixing the conceptual insanity that is our
handling of service and IPC calls. For now, interfaces still directly
derived from Session because we don't have the infrastructure to do it
properly. (That is, Processes and scheduling them.)
|
|
|
|
Same semantics, idea by @yuriks
|
|
|
|
|
|
|
|
|
|
This behavior was tested on hardware, however i'm still not sure what use the "initial_count" parameter has
|
|
ToDo: Implement svcReleaseSemaphore
* Some testing against hardware needed
|
|
|
|
|
|
|
|
This is in line with what the hardware itself does.
It does this by splitting the initial directory opening into Directory.Open(), which will return false if a stat fails.
Then, Archive::OpenDirectory will return nullptr, and archive.cpp will return an error code .
|
|
Moved Mutex::WaitSynchronization to the end of the file.
|
|
|
|
Also resume only the next immediate thread waiting for the mutex when it is released, instead of resuming them all.
|
|
Use the next_thread_id variable directly.
|
|
|
|
|
|
For now threads are using their Handle value as their Id, it should not really cause any problems because Handle values are unique in Citra, but it should be changed. I left a ToDo there because this is not correct behavior as per hardware.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
All service calls in the CTR OS return result codes indicating the
success or failure of the call. Previous to this commit, Citra's HLE
emulation of services and the kernel universally either ignored errors
or returned dummy -1 error codes.
This commit makes an initial effort to provide an infrastructure for
error reporting and propagation which can be use going forward to make
HLE calls accurately return errors as the original system. A few parts
of the code have been updated to use the new system where applicable.
One part of this effort is the definition of the `ResultCode` type,
which provides facilities for constructing and parsing error codes in
the structured format used by the CTR.
The `ResultVal` type builds on `ResultCode` by providing a container for
values returned by function that can report errors. It enforces that
correct error checking will be done on function returns by preventing
the use of the return value if the function returned an error code.
Currently this change is mostly internal since errors are still
suppressed on the ARM<->HLE border, as a temporary compatibility hack.
As functionality is implemented and tested this hack can be eventually
removed.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
added a todo to kernel archive
|
|
|
|
|
|
|
|
|
|
This was automated using `clang-modernize`.
|
|
Kernel: Return an invalid handle to OpenFile when it failed to open.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
These avoid relying on memset for clearing the arrays.
|
|
Most functions already operate on std::strings. This also removes the need to manually null terminate thread names.
|
|
|
|
|
|
|
|
|
|
AddressArbiter: Added documentation comment, fixed whitespace issue.
AddressArbiter: Fixed incorrect comment, reordered if-statement to be more clear.
SVC: Removed trailing whitespace.
|
|
Thread: Cleaned up arbitrate address functions.
Thread: Cleaned up ArbitrateAllThreads function.
|
|
- Also added some safety checks to MapSharedMemory.
|
|
SharedMemory: Added optional name field for tracking known objects.
|
|
|
|
Archive: Fixed brace ugliness for neobrain :)
FS: Commented out unused local variables to prevent warnings.
...But keeping them here for future use.
archive_romfs: Removed unused #include.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- SVC: Added ExitThread support
- SVC: Added SignalEvent support
- Thread: Added WAITTYPE_EVENT for waiting threads for event signals
- Thread: Added support for blocking on other threads to finish (e.g. Thread::Join)
- Thread: Added debug function for printing current threads ready for execution
- Thread: Removed hack/broken thread ready state code from Kernel::Reschedule
- Mutex: Moved WaitCurrentThread from SVC to Mutex::WaitSynchronization
- Event: Added support for blocking threads on event signalling
Kernel: Added missing algorithm #include for use of std::find on non-Windows platforms.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- cleaned up Kernel code a bit (moved stuff into namespace, fixed whitespace issues)
- added handle types for all different CTROS handles
|
|
|
|
- various cleanups
|
|
- added ResetType enum
|
|
|
|
- reorganized some kernel thread functions
- added placeholder __KernelWaitThread_Synchronization function
|
|
- added KERNEL_DEFAULT_STACK_SIZE definition (0x4000)
|
|
|
|
|
|
- added __KernelSwitchToThread for enabling a thread
- added __KernelRotateThreadReadyQueue
|
|
|
|
|
|
|
|
|
|
- fixed some logging
|
|
|