Compare commits

..

85 Commits

Author SHA1 Message Date
Narr the Reg
ff11fdb07e Revert "yuzu: config: Remove player 8 and 9 from config file" 2023-02-26 14:39:13 -06:00
liamwhite
26c1edf2f0 Merge pull request #9849 from ameerj/async-astc
texture_cache: Add asynchronous ASTC texture decoding
2023-02-26 09:20:12 -05:00
liamwhite
c50a930bbb Merge pull request #9824 from german77/burning-profiles
yuzu: config: Remove player 8 and 9 from config file
2023-02-26 09:20:02 -05:00
Narr the Reg
60688bf0d5 yuzu: config: Remove player 8 and 9 from config file 2023-02-25 22:20:32 -06:00
liamwhite
833afb7ce3 Merge pull request #9848 from german77/metroid_motion
input_common: Implement dedicated motion from mouse
2023-02-25 12:44:13 -05:00
liamwhite
290ec3eb2f Merge pull request #9857 from german77/fwupdate
core: Update service function tables to 16.0.0+
2023-02-25 12:44:06 -05:00
liamwhite
d5bfc36e90 Merge pull request #9861 from german77/bustype
core: hidbus: Fix BusType size
2023-02-25 12:44:00 -05:00
liamwhite
5eeadde3c8 Merge pull request #9863 from german77/max-clock
config: Fix per game Force max clock
2023-02-25 12:43:53 -05:00
german77
cfd69e2e58 config: Fix per game Force max clock 2023-02-25 10:12:07 -06:00
Narr the Reg
5e4ea04a64 core: hidbus: Fix BusType size 2023-02-24 21:22:27 -06:00
Narr the Reg
39ca7b2928 core: Update service function tables to 16.0.0+ 2023-02-24 18:17:36 -06:00
liamwhite
ca8a804a3c Merge pull request #9842 from german77/proper_real_mouse
core: hid: Fix native mouse mapping
2023-02-22 22:08:35 -05:00
ameerj
b5bcd8c71b configuration: Add async ASTC decode setting 2023-02-22 18:21:09 -05:00
ameerj
090bc588e5 texture_cache: Add async texture decoding 2023-02-22 00:26:07 -05:00
Narr the Reg
739a81055f core: hid: Restore motion state on refresh and clamp motion values 2023-02-21 21:55:23 -06:00
Narr the Reg
673accd630 input_common: Implement dedicated motion from mouse 2023-02-21 21:55:22 -06:00
Narr the Reg
db2785082b settings: Add more input settings to the log 2023-02-21 19:48:38 -06:00
Narr the Reg
9477181d09 core: hid: Fix native mouse mappings 2023-02-21 19:48:38 -06:00
liamwhite
8f3e2a1b48 Merge pull request #9847 from german77/timeout
yuzu: Set a lower timeout for discord presence
2023-02-21 20:39:19 -05:00
Narr the Reg
d482ec32a4 yuzu: Set a lower timeout for discord presence 2023-02-21 18:23:58 -06:00
liamwhite
11f6bb1532 Merge pull request #9846 from merryhime/type-const
svc: Fix type consistency (exposed on macOS)
2023-02-21 18:58:04 -05:00
liamwhite
ba05301e1b Merge pull request #9841 from abouvier/httplib-update
externals: Update cpp-httplib to latest
2023-02-21 18:57:55 -05:00
liamwhite
5a657488e1 Merge pull request #9843 from MonsterDruide1/network-connreset
net: translate ECONNRESET network error
2023-02-21 18:57:37 -05:00
Merry
c9678bda24 svc: Fix type consistency (exposed on macOS) 2023-02-21 21:39:17 +00:00
Alexandre Bouvier
83afc12475 externals: Update cpp-httplib to latest 2023-02-21 20:55:37 +01:00
MonsterDruide1
d746cfc018 net: translate ECONNRESET network error 2023-02-21 20:47:59 +01:00
liamwhite
89221ca7d5 Merge pull request #9834 from german77/reverted
Qt: Reintroduce scaling for touch input
2023-02-20 09:05:49 -05:00
german77
165ebbb63c Qt: Reintroduce scaling for touch input 2023-02-19 17:52:44 -06:00
liamwhite
898c5d35a5 Merge pull request #9771 from ameerj/host-thread-id
kernel: Refactor thread_local variable usage
2023-02-19 13:12:43 -05:00
liamwhite
a4d0663158 Merge pull request #9588 from liamwhite/bylaws-reverts
Revert "shader_recompiler: Align SSBO offsets to meet host requirements"
2023-02-19 13:11:57 -05:00
liamwhite
e531d1fae9 Merge pull request #9815 from german77/qt-mouse
Qt: Fix mouse scalling
2023-02-18 16:25:48 -05:00
Morph
41183b622f Merge pull request #9825 from liamwhite/object-name
kernel: add KObjectName
2023-02-18 16:22:50 -05:00
bunnei
e91ff9b7bd Merge pull request #9810 from Kelebek1/nvdec_threads
Allow >1 cpu threads on video decoding, disable multi-frame decoding
2023-02-17 09:44:38 -08:00
Liam
1773a1039f kernel: add KObjectName 2023-02-17 09:16:05 -05:00
Mai
61b1772e51 Merge pull request #9817 from german77/save
yuzu: Write to config file on important config changes
2023-02-16 22:58:29 -05:00
Narr the Reg
0a88c7dbbe yuzu: Shutdown game on restart to reload per game config 2023-02-16 21:17:30 -06:00
Narr the Reg
df9c8bdfd9 yuzu: Write to config file on important config changes 2023-02-16 21:17:01 -06:00
bunnei
889bfce447 Merge pull request #9802 from Kelebek1/wait_data_cache
Re-add the invalidate_texture_data_cache register
2023-02-16 12:27:24 -08:00
bunnei
744434de38 Merge pull request #9769 from Kelebek1/audio_oob
[audio_core] Fix depop prepare
2023-02-16 12:26:23 -08:00
Narr the Reg
17207939e5 input_common: Split mouse input into individual devices 2023-02-16 14:22:13 -06:00
german77
57aaf00a0c Qt: Fix mouse scalling 2023-02-15 20:57:45 -06:00
liamwhite
6d77de96da Merge pull request #9796 from liamwhite/current
general: rename CurrentProcess to ApplicationProcess
2023-02-15 17:42:45 -05:00
liamwhite
04d2d2ef5f Merge pull request #9782 from arades79/fix-consexpr-value-declaration-usage
Fix consexpr value declaration usage
2023-02-15 17:42:38 -05:00
bunnei
0eb40117af Merge pull request #9809 from liamwhite/unused-service
service: remove deleted services
2023-02-15 12:33:59 -08:00
bunnei
3599ef2077 Merge pull request #9811 from yuzu-emu/revert-9793-borderless-hidpi
Revert "main: Fix borderless fullscreen for high dpi scaled displays"
2023-02-14 18:27:21 -08:00
arades79
98631b45b6 remove constexpr from virtual function
Signed-off-by: arades79 <scravers@protonmail.com>
2023-02-14 19:14:29 -05:00
liamwhite
58a2c19982 Revert "main: Fix borderless fullscreen for high dpi scaled displays" 2023-02-14 16:29:35 -05:00
Kelebek1
3b50906f00 Reimplement the invalidate_texture_data_cache register 2023-02-14 19:34:10 +00:00
Kelebek1
139b645aa2 Allow >1 cpu threads on video decoding, disable multi-frame decoding 2023-02-14 18:55:46 +00:00
Liam
79fbdfca17 service: remove deleted services 2023-02-14 12:38:21 -05:00
arades79
880b6e9795 use a string view to skip allocation
Signed-off-by: arades79 <scravers@protonmail.com>
2023-02-14 12:35:40 -05:00
arades79
683019878f remove static from pointer sized or smaller types for aesthetics, change constexpr static to static constexpr for consistency
Signed-off-by: arades79 <scravers@protonmail.com>
2023-02-14 12:35:39 -05:00
arades79
26e44a3be4 apply clang-format
Signed-off-by: arades79 <scravers@protonmail.com>
2023-02-14 12:35:39 -05:00
arades79
392a029ef4 don't use static inside constexpr function
Signed-off-by: arades79 <scravers@protonmail.com>
2023-02-14 12:33:11 -05:00
arades79
45e13b03f3 add static lifetime to constexpr values to force compile time evaluation where possible
Signed-off-by: arades79 <scravers@protonmail.com>
2023-02-14 12:33:11 -05:00
liamwhite
5f5a6e4b2e Merge pull request #9795 from Kelebek1/biquad_fix
[audio_core] Use different state offset for each biquad filter channel
2023-02-14 09:11:26 -05:00
liamwhite
d87db919f9 Merge pull request #9793 from Morph1984/borderless-hidpi
main: Fix borderless fullscreen for high dpi scaled displays
2023-02-14 09:11:15 -05:00
Liam
ceda2d280e general: rename CurrentProcess to ApplicationProcess 2023-02-13 19:03:12 -05:00
Kelebek1
3a90ed99be Fix biquad filter command's state buffer offset 2023-02-13 16:21:29 +00:00
Liam
4363ca304a kernel: use GetCurrentProcess 2023-02-13 11:05:14 -05:00
bunnei
770a49616d Merge pull request #9784 from m-HD/master
settings: added missing graphical settings to RestoreGlobalState()
2023-02-12 21:49:45 -08:00
Morph
d6677b50f6 main: Fix borderless fullscreen for high dpi scaled displays
On Windows, a borderless window will be treated the same as exclusive fullscreen
when the window geometry matches the physical dimensions of the screen.
However, with High DPI scaling, when the devicePixelRatioF() is > 1, the borderless
window apparently is not treated as exclusive fullscreen and functions correctly.
One can verify and replicate this behavior by using a high resolution (4K) display,
and switching between 100% and 200% scaling in Windows' display settings.
At 100%, without the addition of 1, it is treated as exclusive fullscreen.
At 200%, with or without the addition of 1, it is treated as borderless windowed.
Therefore, we can use (read: abuse) this difference in behavior to fix this issue for
those with higher resolution displays when the Qt scaling ratio is > 1.
Should this behavior be changed in the future, please revisit this workaround.
2023-02-12 21:58:49 -05:00
bunnei
8b74047b1b Merge pull request #9757 from german77/gyro
core: hid: Use gyro thresholds modes set by the game
2023-02-12 00:19:22 -08:00
bunnei
f70fcdb873 Merge pull request #9746 from ameerj/ogl-msaa-texcache
texture_cache: OpenGL: Implement MSAA uploads and copies
2023-02-12 00:18:52 -08:00
m-HD
9df92bad2a Update settings.cpp
added missing graphical settings to RestoreGlobalState()
2023-02-12 02:58:39 +01:00
liamwhite
fbba6e10bc Merge pull request #9781 from ColinKinloch/info_id_typo
kernel/svc: Fix undefined info_id
2023-02-11 20:13:54 -05:00
ameerj
93cf2b3ca8 texture_cache: OpenGL: Implement MSAA uploads and copies 2023-02-11 15:43:07 -05:00
Colin Kinloch
868ab0d3b4 kernel/svc: Fix undefined info_id 2023-02-11 18:00:34 +00:00
liamwhite
c97b5c9ff9 Merge pull request #9777 from vonchenplus/speed_up_video_copy
video_core: Speed up video frame data copy
2023-02-11 12:35:16 -05:00
Kelebek1
2e02ed8bb5 Add fallback for memory read/write in case the address goes over a 4K page 2023-02-11 16:27:43 +00:00
liamwhite
709879cfc1 Merge pull request #9773 from bunnei/fix-process-resource
core: kernel: k_process: Use application system resource.
2023-02-11 10:28:50 -05:00
liamwhite
89c09d639a Merge pull request #9768 from merryhime/biquad-rounding
biquad_filter: Fix rounding in ApplyBiquadFilterInt
2023-02-11 10:28:42 -05:00
liamwhite
1040f1f503 Merge pull request #9744 from behunin/quick-release
gpu_thread: Remove OnCommandListEndCommand
2023-02-11 10:28:30 -05:00
FengChen
4adf39edf2 video_core: Speed up video frame data copy 2023-02-11 22:18:54 +08:00
Kelebek1
19e1ea6a02 Fix depop prepare receiving bad mix infos and writing out of bounds, and update aux a bit, may help 2023-02-11 10:21:25 +00:00
bunnei
abd826ba87 Merge pull request #9742 from liamwhite/svc-wrap-only
kernel/svc: switch to generated wrappers
2023-02-10 21:41:22 -08:00
bunnei
023ac943aa Merge pull request #9759 from german77/pro_controller
input_common: Reintroduce custom pro controller support
2023-02-10 21:14:40 -08:00
bunnei
e79270507b core: kernel: k_process: Use application system resource. 2023-02-10 21:03:39 -08:00
ameerj
5e746da981 kernel: Refactor thread_local variable usage
On MSVC at least, there seems to be a non-trivial overhead to calling GetHostThreadId().

This slightly reworks the host_thread_id variable to reduce some of the complexity around its usage, along with some small refactors around current_thread and dummy thread
2023-02-10 20:43:06 -05:00
Narr the Reg
acba9a6b76 input_common: Reintroduce custom pro controller support 2023-02-09 20:08:54 -06:00
Narr the Reg
5e9fa5def5 core: hid: Use gyro thresholds modes set by the game 2023-02-09 19:07:50 -06:00
Behunin
8551ac6008 Remove OnCommandListEndCommand
Call rasterizer->ReleaseFences() directly
2023-02-07 17:21:17 -07:00
Liam
2415d37ea2 kernel/svc: switch to generated wrappers 2023-02-06 23:57:44 -05:00
Liam
505923f0f3 Revert "shader_recompiler: Align SSBO offsets to meet host requirements"
This reverts commit 8804a4eb23.
2023-01-07 15:50:58 -05:00
Liam
57a4388e2d Revert "Vulkan, OpenGL: Hook up storage buffer alignment code"
This reverts commit 9e2997c4b6.
2023-01-07 15:48:50 -05:00
226 changed files with 9071 additions and 2851 deletions

View File

@@ -241,7 +241,7 @@ endif()
if (ENABLE_WEB_SERVICE)
find_package(cpp-jwt 1.4 CONFIG)
find_package(httplib 0.11 MODULE)
find_package(httplib 0.12 MODULE)
endif()
if (YUZU_TESTS)

View File

@@ -132,7 +132,7 @@ void AudioRenderer::CreateSinkStreams() {
}
void AudioRenderer::ThreadFunc() {
constexpr char name[]{"AudioRenderer"};
static constexpr char name[]{"AudioRenderer"};
MicroProfileOnThreadCreate(name);
Common::SetCurrentThreadName(name);
Common::SetCurrentThreadPriority(Common::ThreadPriority::Critical);

View File

@@ -251,8 +251,8 @@ void CommandBuffer::GenerateBiquadFilterCommand(const s32 node_id, EffectInfoBas
const auto& parameter{
*reinterpret_cast<BiquadFilterInfo::ParameterVersion1*>(effect_info.GetParameter())};
const auto state{
reinterpret_cast<VoiceState::BiquadFilterState*>(effect_info.GetStateBuffer())};
const auto state{reinterpret_cast<VoiceState::BiquadFilterState*>(
effect_info.GetStateBuffer() + channel * sizeof(VoiceState::BiquadFilterState))};
cmd.input = buffer_offset + parameter.inputs[channel];
cmd.output = buffer_offset + parameter.outputs[channel];

View File

@@ -46,7 +46,7 @@ void CommandGenerator::GenerateDataSourceCommand(VoiceInfo& voice_info,
while (destination != nullptr) {
if (destination->IsConfigured()) {
auto mix_id{destination->GetMixId()};
if (mix_id < mix_context.GetCount()) {
if (mix_id < mix_context.GetCount() && mix_id != UnusedSplitterId) {
auto mix_info{mix_context.GetInfo(mix_id)};
command_buffer.GenerateDepopPrepareCommand(
voice_info.node_id, voice_state, render_context.depop_buffer,

View File

@@ -4,6 +4,7 @@
#include "audio_core/renderer/adsp/command_list_processor.h"
#include "audio_core/renderer/command/effect/aux_.h"
#include "audio_core/renderer/effect/aux_.h"
#include "core/core.h"
#include "core/memory.h"
namespace AudioCore::AudioRenderer {
@@ -19,10 +20,24 @@ static void ResetAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr aux_in
return;
}
auto info{reinterpret_cast<AuxInfo::AuxInfoDsp*>(memory.GetPointer(aux_info))};
info->read_offset = 0;
info->write_offset = 0;
info->total_sample_count = 0;
AuxInfo::AuxInfoDsp info{};
auto info_ptr{&info};
bool host_safe{(aux_info & Core::Memory::YUZU_PAGEMASK) <=
(Core::Memory::YUZU_PAGESIZE - sizeof(AuxInfo::AuxInfoDsp))};
if (host_safe) [[likely]] {
info_ptr = memory.GetPointer<AuxInfo::AuxInfoDsp>(aux_info);
} else {
memory.ReadBlockUnsafe(aux_info, info_ptr, sizeof(AuxInfo::AuxInfoDsp));
}
info_ptr->read_offset = 0;
info_ptr->write_offset = 0;
info_ptr->total_sample_count = 0;
if (!host_safe) [[unlikely]] {
memory.WriteBlockUnsafe(aux_info, info_ptr, sizeof(AuxInfo::AuxInfoDsp));
}
}
/**
@@ -40,11 +55,10 @@ static void ResetAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr aux_in
* @param update_count - If non-zero, send_info_ will be updated.
* @return Number of samples written.
*/
static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr send_info_,
[[maybe_unused]] u32 sample_count, const CpuAddr send_buffer,
const u32 count_max, std::span<const s32> input,
const u32 write_count_, const u32 write_offset,
const u32 update_count) {
static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, CpuAddr send_info_,
[[maybe_unused]] u32 sample_count, CpuAddr send_buffer, u32 count_max,
std::span<const s32> input, u32 write_count_, u32 write_offset,
u32 update_count) {
if (write_count_ > count_max) {
LOG_ERROR(Service_Audio,
"write_count must be smaller than count_max! write_count {}, count_max {}",
@@ -52,6 +66,11 @@ static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr send_in
return 0;
}
if (send_info_ == 0) {
LOG_ERROR(Service_Audio, "send_info_ is 0!");
return 0;
}
if (input.empty()) {
LOG_ERROR(Service_Audio, "input buffer is empty!");
return 0;
@@ -67,33 +86,47 @@ static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr send_in
}
AuxInfo::AuxInfoDsp send_info{};
memory.ReadBlockUnsafe(send_info_, &send_info, sizeof(AuxInfo::AuxInfoDsp));
auto send_ptr = &send_info;
bool host_safe = (send_info_ & Core::Memory::YUZU_PAGEMASK) <=
(Core::Memory::YUZU_PAGESIZE - sizeof(AuxInfo::AuxInfoDsp));
u32 target_write_offset{send_info.write_offset + write_offset};
if (target_write_offset > count_max || write_count_ == 0) {
if (host_safe) [[likely]] {
send_ptr = memory.GetPointer<AuxInfo::AuxInfoDsp>(send_info_);
} else {
memory.ReadBlockUnsafe(send_info_, send_ptr, sizeof(AuxInfo::AuxInfoDsp));
}
u32 target_write_offset{send_ptr->write_offset + write_offset};
if (target_write_offset > count_max) {
return 0;
}
u32 write_count{write_count_};
u32 write_pos{0};
u32 read_pos{0};
while (write_count > 0) {
u32 to_write{std::min(count_max - target_write_offset, write_count)};
if (to_write > 0) {
const auto write_addr = send_buffer + target_write_offset * sizeof(s32);
bool write_safe{(write_addr & Core::Memory::YUZU_PAGEMASK) <=
(Core::Memory::YUZU_PAGESIZE - (write_addr + to_write * sizeof(s32)))};
if (write_safe) [[likely]] {
auto ptr = memory.GetPointer(write_addr);
std::memcpy(ptr, &input[read_pos], to_write * sizeof(s32));
} else {
memory.WriteBlockUnsafe(send_buffer + target_write_offset * sizeof(s32),
&input[write_pos], to_write * sizeof(s32));
&input[read_pos], to_write * sizeof(s32));
}
target_write_offset = (target_write_offset + to_write) % count_max;
write_count -= to_write;
write_pos += to_write;
read_pos += to_write;
}
if (update_count) {
send_info.write_offset = (send_info.write_offset + update_count) % count_max;
send_ptr->write_offset = (send_ptr->write_offset + update_count) % count_max;
}
memory.WriteBlockUnsafe(send_info_, &send_info, sizeof(AuxInfo::AuxInfoDsp));
if (!host_safe) [[unlikely]] {
memory.WriteBlockUnsafe(send_info_, send_ptr, sizeof(AuxInfo::AuxInfoDsp));
}
return write_count_;
}
@@ -102,7 +135,7 @@ static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr send_in
* Read the given memory at return_buffer into the output mix buffer, and update return_info_ if
* update_count is set, to notify the game that an update happened.
*
* @param memory - Core memory for writing.
* @param memory - Core memory for reading.
* @param return_info_ - Meta information for where to read the mix buffer.
* @param return_buffer - Memory address to read the samples from.
* @param count_max - Maximum number of samples in the receiving buffer.
@@ -112,16 +145,21 @@ static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr send_in
* @param update_count - If non-zero, send_info_ will be updated.
* @return Number of samples read.
*/
static u32 ReadAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr return_info_,
const CpuAddr return_buffer, const u32 count_max, std::span<s32> output,
const u32 count_, const u32 read_offset, const u32 update_count) {
static u32 ReadAuxBufferDsp(Core::Memory::Memory& memory, CpuAddr return_info_,
CpuAddr return_buffer, u32 count_max, std::span<s32> output,
u32 read_count_, u32 read_offset, u32 update_count) {
if (count_max == 0) {
return 0;
}
if (count_ > count_max) {
if (read_count_ > count_max) {
LOG_ERROR(Service_Audio, "count must be smaller than count_max! count {}, count_max {}",
count_, count_max);
read_count_, count_max);
return 0;
}
if (return_info_ == 0) {
LOG_ERROR(Service_Audio, "return_info_ is 0!");
return 0;
}
@@ -136,35 +174,49 @@ static u32 ReadAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr return_i
}
AuxInfo::AuxInfoDsp return_info{};
memory.ReadBlockUnsafe(return_info_, &return_info, sizeof(AuxInfo::AuxInfoDsp));
auto return_ptr = &return_info;
bool host_safe = (return_info_ & Core::Memory::YUZU_PAGEMASK) <=
(Core::Memory::YUZU_PAGESIZE - sizeof(AuxInfo::AuxInfoDsp));
u32 target_read_offset{return_info.read_offset + read_offset};
if (host_safe) [[likely]] {
return_ptr = memory.GetPointer<AuxInfo::AuxInfoDsp>(return_info_);
} else {
memory.ReadBlockUnsafe(return_info_, return_ptr, sizeof(AuxInfo::AuxInfoDsp));
}
u32 target_read_offset{return_ptr->read_offset + read_offset};
if (target_read_offset > count_max) {
return 0;
}
u32 read_count{count_};
u32 read_pos{0};
u32 read_count{read_count_};
u32 write_pos{0};
while (read_count > 0) {
u32 to_read{std::min(count_max - target_read_offset, read_count)};
if (to_read > 0) {
const auto read_addr = return_buffer + target_read_offset * sizeof(s32);
bool read_safe{(read_addr & Core::Memory::YUZU_PAGEMASK) <=
(Core::Memory::YUZU_PAGESIZE - (read_addr + to_read * sizeof(s32)))};
if (read_safe) [[likely]] {
auto ptr = memory.GetPointer(read_addr);
std::memcpy(&output[write_pos], ptr, to_read * sizeof(s32));
} else {
memory.ReadBlockUnsafe(return_buffer + target_read_offset * sizeof(s32),
&output[read_pos], to_read * sizeof(s32));
&output[write_pos], to_read * sizeof(s32));
}
target_read_offset = (target_read_offset + to_read) % count_max;
read_count -= to_read;
read_pos += to_read;
write_pos += to_read;
}
if (update_count) {
return_info.read_offset = (return_info.read_offset + update_count) % count_max;
return_ptr->read_offset = (return_ptr->read_offset + update_count) % count_max;
}
memory.WriteBlockUnsafe(return_info_, &return_info, sizeof(AuxInfo::AuxInfoDsp));
if (!host_safe) [[unlikely]] {
memory.WriteBlockUnsafe(return_info_, return_ptr, sizeof(AuxInfo::AuxInfoDsp));
}
return count_;
return read_count_;
}
void AuxCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& processor,
@@ -189,7 +241,7 @@ void AuxCommand::Process(const ADSP::CommandListProcessor& processor) {
update_count)};
if (read != processor.sample_count) {
std::memset(&output_buffer[read], 0, processor.sample_count - read);
std::memset(&output_buffer[read], 0, (processor.sample_count - read) * sizeof(s32));
}
} else {
ResetAuxBufferDsp(*processor.memory, send_buffer_info);

View File

@@ -244,16 +244,16 @@ template <size_t NumChannels>
static void ApplyI3dl2ReverbEffect(I3dl2ReverbInfo::State& state,
std::span<std::span<const s32>> inputs,
std::span<std::span<s32>> outputs, const u32 sample_count) {
constexpr std::array<u8, I3dl2ReverbInfo::MaxDelayTaps> OutTapIndexes1Ch{
static constexpr std::array<u8, I3dl2ReverbInfo::MaxDelayTaps> OutTapIndexes1Ch{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
constexpr std::array<u8, I3dl2ReverbInfo::MaxDelayTaps> OutTapIndexes2Ch{
static constexpr std::array<u8, I3dl2ReverbInfo::MaxDelayTaps> OutTapIndexes2Ch{
0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1,
};
constexpr std::array<u8, I3dl2ReverbInfo::MaxDelayTaps> OutTapIndexes4Ch{
static constexpr std::array<u8, I3dl2ReverbInfo::MaxDelayTaps> OutTapIndexes4Ch{
0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0, 3, 3, 3,
};
constexpr std::array<u8, I3dl2ReverbInfo::MaxDelayTaps> OutTapIndexes6Ch{
static constexpr std::array<u8, I3dl2ReverbInfo::MaxDelayTaps> OutTapIndexes6Ch{
2, 0, 0, 1, 1, 1, 1, 4, 4, 4, 1, 1, 1, 0, 0, 0, 0, 5, 5, 5,
};

View File

@@ -252,16 +252,16 @@ template <size_t NumChannels>
static void ApplyReverbEffect(const ReverbInfo::ParameterVersion2& params, ReverbInfo::State& state,
std::vector<std::span<const s32>>& inputs,
std::vector<std::span<s32>>& outputs, const u32 sample_count) {
constexpr std::array<u8, ReverbInfo::MaxDelayTaps> OutTapIndexes1Ch{
static constexpr std::array<u8, ReverbInfo::MaxDelayTaps> OutTapIndexes1Ch{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
};
constexpr std::array<u8, ReverbInfo::MaxDelayTaps> OutTapIndexes2Ch{
static constexpr std::array<u8, ReverbInfo::MaxDelayTaps> OutTapIndexes2Ch{
0, 0, 1, 1, 0, 1, 0, 0, 1, 1,
};
constexpr std::array<u8, ReverbInfo::MaxDelayTaps> OutTapIndexes4Ch{
static constexpr std::array<u8, ReverbInfo::MaxDelayTaps> OutTapIndexes4Ch{
0, 0, 1, 1, 0, 1, 2, 2, 3, 3,
};
constexpr std::array<u8, ReverbInfo::MaxDelayTaps> OutTapIndexes6Ch{
static constexpr std::array<u8, ReverbInfo::MaxDelayTaps> OutTapIndexes6Ch{
0, 0, 1, 1, 2, 2, 4, 4, 5, 5,
};

View File

@@ -19,24 +19,24 @@ namespace AudioCore::AudioRenderer {
static void SrcProcessFrame(std::span<s32> output, std::span<const s32> input,
const u32 target_sample_count, const u32 source_sample_count,
UpsamplerState* state) {
constexpr u32 WindowSize = 10;
constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc1{
static constexpr u32 WindowSize = 10;
static constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc1{
0.95376587f, -0.12872314f, 0.060028076f, -0.032470703f, 0.017669678f,
-0.009124756f, 0.004272461f, -0.001739502f, 0.000579834f, -0.000091552734f,
};
constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc2{
static constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc2{
0.8230896f, -0.19161987f, 0.093444824f, -0.05090332f, 0.027557373f,
-0.014038086f, 0.0064697266f, -0.002532959f, 0.00079345703f, -0.00012207031f,
};
constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc3{
static constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc3{
0.6298828f, -0.19274902f, 0.09725952f, -0.05319214f, 0.028625488f,
-0.014373779f, 0.006500244f, -0.0024719238f, 0.0007324219f, -0.000091552734f,
};
constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc4{
static constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc4{
0.4057312f, -0.1468811f, 0.07601929f, -0.041656494f, 0.022216797f,
-0.011016846f, 0.004852295f, -0.0017700195f, 0.00048828125f, -0.000030517578f,
};
constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc5{
static constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc5{
0.1854248f, -0.075164795f, 0.03967285f, -0.021728516f, 0.011474609f,
-0.005584717f, 0.0024108887f, -0.0008239746f, 0.00021362305f, 0.0f,
};

View File

@@ -127,7 +127,7 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
render_device = params.rendering_device;
execution_mode = params.execution_mode;
core.Memory().ZeroBlock(*core.Kernel().CurrentProcess(), transfer_memory->GetSourceAddress(),
core.Memory().ZeroBlock(*core.ApplicationProcess(), transfer_memory->GetSourceAddress(),
transfer_memory_size);
// Note: We're not actually using the transfer memory because it's a pain to code for.

View File

@@ -94,7 +94,7 @@ bool SystemManager::Remove(System& system_) {
}
void SystemManager::ThreadFunc() {
constexpr char name[]{"AudioRenderSystemManager"};
static constexpr char name[]{"AudioRenderSystemManager"};
MicroProfileOnThreadCreate(name);
Common::SetCurrentThreadName(name);
Common::SetCurrentThreadPriority(Common::ThreadPriority::High);

View File

@@ -35,7 +35,7 @@ void SinkStream::AppendBuffer(SinkBuffer& buffer, std::vector<s16>& samples) {
if (system_channels == 6 && device_channels == 2) {
// We're given 6 channels, but our device only outputs 2, so downmix.
constexpr std::array<f32, 4> down_mix_coeff{1.0f, 0.707f, 0.251f, 0.707f};
static constexpr std::array<f32, 4> down_mix_coeff{1.0f, 0.707f, 0.251f, 0.707f};
for (u32 read_index = 0, write_index = 0; read_index < samples.size();
read_index += system_channels, write_index += device_channels) {
@@ -202,7 +202,7 @@ void SinkStream::ProcessAudioOutAndRender(std::span<s16> output_buffer, std::siz
// If we're paused or going to shut down, we don't want to consume buffers as coretiming is
// paused and we'll desync, so just play silence.
if (system.IsPaused() || system.IsShuttingDown()) {
constexpr std::array<s16, 6> silence{};
static constexpr std::array<s16, 6> silence{};
for (size_t i = frames_written; i < num_frames; i++) {
std::memcpy(&output_buffer[i * frame_size], &silence[0], frame_size_bytes);
}
@@ -270,7 +270,7 @@ void SinkStream::Stall() {
if (stalled_lock) {
return;
}
stalled_lock = system.StallProcesses();
stalled_lock = system.StallApplication();
}
void SinkStream::Unstall() {
@@ -278,7 +278,7 @@ void SinkStream::Unstall() {
if (!stalled_lock) {
return;
}
system.UnstallProcesses();
system.UnstallApplication();
stalled_lock.unlock();
}

View File

@@ -23,6 +23,7 @@ public:
buffer{Common::make_unique_for_overwrite<T[]>(initial_capacity)} {}
~ScratchBuffer() = default;
ScratchBuffer(ScratchBuffer&&) = default;
/// This will only grow the buffer's capacity if size is greater than the current capacity.
/// The previously held data will remain intact.

View File

@@ -59,6 +59,7 @@ void LogSettings() {
values.use_asynchronous_gpu_emulation.GetValue());
log_setting("Renderer_NvdecEmulation", values.nvdec_emulation.GetValue());
log_setting("Renderer_AccelerateASTC", values.accelerate_astc.GetValue());
log_setting("Renderer_AsyncASTC", values.async_astc.GetValue());
log_setting("Renderer_UseVsync", values.use_vsync.GetValue());
log_setting("Renderer_ShaderBackend", values.shader_backend.GetValue());
log_setting("Renderer_UseAsynchronousShaders", values.use_asynchronous_shaders.GetValue());
@@ -76,6 +77,13 @@ void LogSettings() {
log_setting("Debugging_GDBStub", values.use_gdbstub.GetValue());
log_setting("Input_EnableMotion", values.motion_enabled.GetValue());
log_setting("Input_EnableVibration", values.vibration_enabled.GetValue());
log_setting("Input_EnableTouch", values.touchscreen.enabled);
log_setting("Input_EnableMouse", values.mouse_enabled.GetValue());
log_setting("Input_EnableKeyboard", values.keyboard_enabled.GetValue());
log_setting("Input_EnableRingController", values.enable_ring_controller.GetValue());
log_setting("Input_EnableIrSensor", values.enable_ir_sensor.GetValue());
log_setting("Input_EnableCustomJoycon", values.enable_joycon_driver.GetValue());
log_setting("Input_EnableCustomProController", values.enable_procon_driver.GetValue());
log_setting("Input_EnableRawInput", values.enable_raw_input.GetValue());
}
@@ -199,7 +207,11 @@ void RestoreGlobalState(bool is_powered_on) {
values.renderer_backend.SetGlobal(true);
values.renderer_force_max_clock.SetGlobal(true);
values.vulkan_device.SetGlobal(true);
values.fullscreen_mode.SetGlobal(true);
values.aspect_ratio.SetGlobal(true);
values.resolution_setup.SetGlobal(true);
values.scaling_filter.SetGlobal(true);
values.anti_aliasing.SetGlobal(true);
values.max_anisotropy.SetGlobal(true);
values.use_speed_limit.SetGlobal(true);
values.speed_limit.SetGlobal(true);
@@ -208,6 +220,7 @@ void RestoreGlobalState(bool is_powered_on) {
values.use_asynchronous_gpu_emulation.SetGlobal(true);
values.nvdec_emulation.SetGlobal(true);
values.accelerate_astc.SetGlobal(true);
values.async_astc.SetGlobal(true);
values.use_vsync.SetGlobal(true);
values.shader_backend.SetGlobal(true);
values.use_asynchronous_shaders.SetGlobal(true);

View File

@@ -453,6 +453,7 @@ struct Values {
SwitchableSetting<bool> use_asynchronous_gpu_emulation{true, "use_asynchronous_gpu_emulation"};
SwitchableSetting<NvdecEmulation> nvdec_emulation{NvdecEmulation::GPU, "nvdec_emulation"};
SwitchableSetting<bool> accelerate_astc{true, "accelerate_astc"};
SwitchableSetting<bool> async_astc{false, "async_astc"};
SwitchableSetting<bool> use_vsync{true, "use_vsync"};
SwitchableSetting<ShaderBackend, true> shader_backend{ShaderBackend::GLSL, ShaderBackend::GLSL,
ShaderBackend::SPIRV, "shader_backend"};
@@ -488,6 +489,7 @@ struct Values {
Setting<bool> enable_raw_input{false, "enable_raw_input"};
Setting<bool> controller_navigation{true, "controller_navigation"};
Setting<bool> enable_joycon_driver{true, "enable_joycon_driver"};
Setting<bool> enable_procon_driver{false, "enable_procon_driver"};
SwitchableSetting<bool> vibration_enabled{true, "vibration_enabled"};
SwitchableSetting<bool> enable_accurate_vibrations{false, "enable_accurate_vibrations"};

View File

@@ -225,6 +225,8 @@ add_library(core STATIC
hle/kernel/k_memory_manager.h
hle/kernel/k_memory_region.h
hle/kernel/k_memory_region_type.h
hle/kernel/k_object_name.cpp
hle/kernel/k_object_name.h
hle/kernel/k_page_bitmap.h
hle/kernel/k_page_buffer.cpp
hle/kernel/k_page_buffer.h
@@ -310,6 +312,7 @@ add_library(core STATIC
hle/kernel/svc/svc_event.cpp
hle/kernel/svc/svc_exception.cpp
hle/kernel/svc/svc_info.cpp
hle/kernel/svc/svc_insecure_memory.cpp
hle/kernel/svc/svc_interrupt_event.cpp
hle/kernel/svc/svc_io_pool.cpp
hle/kernel/svc/svc_ipc.cpp
@@ -383,8 +386,6 @@ add_library(core STATIC
hle/service/am/omm.h
hle/service/am/spsm.cpp
hle/service/am/spsm.h
hle/service/am/tcap.cpp
hle/service/am/tcap.h
hle/service/aoc/aoc_u.cpp
hle/service/aoc/aoc_u.h
hle/service/apm/apm.cpp
@@ -395,28 +396,18 @@ add_library(core STATIC
hle/service/apm/apm_interface.h
hle/service/audio/audctl.cpp
hle/service/audio/audctl.h
hle/service/audio/auddbg.cpp
hle/service/audio/auddbg.h
hle/service/audio/audin_a.cpp
hle/service/audio/audin_a.h
hle/service/audio/audin_u.cpp
hle/service/audio/audin_u.h
hle/service/audio/audio.cpp
hle/service/audio/audio.h
hle/service/audio/audout_a.cpp
hle/service/audio/audout_a.h
hle/service/audio/audout_u.cpp
hle/service/audio/audout_u.h
hle/service/audio/audrec_a.cpp
hle/service/audio/audrec_a.h
hle/service/audio/audrec_u.cpp
hle/service/audio/audrec_u.h
hle/service/audio/audren_a.cpp
hle/service/audio/audren_a.h
hle/service/audio/audren_u.cpp
hle/service/audio/audren_u.h
hle/service/audio/codecctl.cpp
hle/service/audio/codecctl.h
hle/service/audio/errors.h
hle/service/audio/hwopus.cpp
hle/service/audio/hwopus.h
@@ -711,8 +702,6 @@ add_library(core STATIC
hle/service/sm/sm_controller.h
hle/service/sockets/bsd.cpp
hle/service/sockets/bsd.h
hle/service/sockets/ethc.cpp
hle/service/sockets/ethc.h
hle/service/sockets/nsd.cpp
hle/service/sockets/nsd.h
hle/service/sockets/sfdnsres.cpp
@@ -779,8 +768,6 @@ add_library(core STATIC
hle/service/vi/vi_s.h
hle/service/vi/vi_u.cpp
hle/service/vi/vi_u.h
hle/service/wlan/wlan.cpp
hle/service/wlan/wlan.h
internal_network/network.cpp
internal_network/network.h
internal_network/network_interface.cpp

View File

@@ -43,9 +43,9 @@ void ARM_Interface::SymbolicateBacktrace(Core::System& system, std::vector<Backt
std::map<std::string, Symbols::Symbols> symbols;
for (const auto& module : modules) {
symbols.insert_or_assign(module.second,
Symbols::GetSymbols(module.first, system.Memory(),
system.CurrentProcess()->Is64BitProcess()));
symbols.insert_or_assign(
module.second, Symbols::GetSymbols(module.first, system.Memory(),
system.ApplicationProcess()->Is64BitProcess()));
}
for (auto& entry : out) {

View File

@@ -5,6 +5,7 @@
#include <array>
#include <span>
#include <string>
#include <vector>
#include <dynarmic/interface/halt_reason.h>

View File

@@ -186,7 +186,7 @@ struct System::Impl {
void Run() {
std::unique_lock<std::mutex> lk(suspend_guard);
kernel.Suspend(false);
kernel.SuspendApplication(false);
core_timing.SyncPause(false);
is_paused.store(false, std::memory_order_relaxed);
}
@@ -195,7 +195,7 @@ struct System::Impl {
std::unique_lock<std::mutex> lk(suspend_guard);
core_timing.SyncPause(true);
kernel.Suspend(true);
kernel.SuspendApplication(true);
is_paused.store(true, std::memory_order_relaxed);
}
@@ -203,17 +203,17 @@ struct System::Impl {
return is_paused.load(std::memory_order_relaxed);
}
std::unique_lock<std::mutex> StallProcesses() {
std::unique_lock<std::mutex> StallApplication() {
std::unique_lock<std::mutex> lk(suspend_guard);
kernel.Suspend(true);
kernel.SuspendApplication(true);
core_timing.SyncPause(true);
return lk;
}
void UnstallProcesses() {
void UnstallApplication() {
if (!IsPaused()) {
core_timing.SyncPause(false);
kernel.Suspend(false);
kernel.SuspendApplication(false);
}
}
@@ -221,7 +221,7 @@ struct System::Impl {
debugger = std::make_unique<Debugger>(system, port);
}
SystemResultStatus SetupForMainProcess(System& system, Frontend::EmuWindow& emu_window) {
SystemResultStatus SetupForApplicationProcess(System& system, Frontend::EmuWindow& emu_window) {
LOG_DEBUG(Core, "initialized OK");
// Setting changes may require a full system reinitialization (e.g., disabling multicore).
@@ -273,7 +273,7 @@ struct System::Impl {
return SystemResultStatus::ErrorGetLoader;
}
SystemResultStatus init_result{SetupForMainProcess(system, emu_window)};
SystemResultStatus init_result{SetupForApplicationProcess(system, emu_window)};
if (init_result != SystemResultStatus::Success) {
LOG_CRITICAL(Core, "Failed to initialize system (Error {})!",
static_cast<int>(init_result));
@@ -302,7 +302,7 @@ struct System::Impl {
static_cast<u32>(SystemResultStatus::ErrorLoader) + static_cast<u32>(load_result));
}
AddGlueRegistrationForProcess(*app_loader, *main_process);
kernel.MakeCurrentProcess(main_process);
kernel.MakeApplicationProcess(main_process);
kernel.InitializeCores();
// Initialize cheat engine
@@ -585,12 +585,12 @@ void System::DetachDebugger() {
}
}
std::unique_lock<std::mutex> System::StallProcesses() {
return impl->StallProcesses();
std::unique_lock<std::mutex> System::StallApplication() {
return impl->StallApplication();
}
void System::UnstallProcesses() {
impl->UnstallProcesses();
void System::UnstallApplication() {
impl->UnstallApplication();
}
void System::InitializeDebugger() {
@@ -648,8 +648,8 @@ const Kernel::GlobalSchedulerContext& System::GlobalSchedulerContext() const {
return impl->kernel.GlobalSchedulerContext();
}
Kernel::KProcess* System::CurrentProcess() {
return impl->kernel.CurrentProcess();
Kernel::KProcess* System::ApplicationProcess() {
return impl->kernel.ApplicationProcess();
}
Core::DeviceMemory& System::DeviceMemory() {
@@ -660,8 +660,8 @@ const Core::DeviceMemory& System::DeviceMemory() const {
return *impl->device_memory;
}
const Kernel::KProcess* System::CurrentProcess() const {
return impl->kernel.CurrentProcess();
const Kernel::KProcess* System::ApplicationProcess() const {
return impl->kernel.ApplicationProcess();
}
ARM_Interface& System::ArmInterface(std::size_t core_index) {
@@ -760,8 +760,8 @@ const Core::SpeedLimiter& System::SpeedLimiter() const {
return impl->speed_limiter;
}
u64 System::GetCurrentProcessProgramID() const {
return impl->kernel.CurrentProcess()->GetProgramID();
u64 System::GetApplicationProcessProgramID() const {
return impl->kernel.ApplicationProcess()->GetProgramID();
}
Loader::ResultStatus System::GetGameName(std::string& out) const {
@@ -880,11 +880,11 @@ bool System::GetExitLock() const {
return impl->exit_lock;
}
void System::SetCurrentProcessBuildID(const CurrentBuildProcessID& id) {
void System::SetApplicationProcessBuildID(const CurrentBuildProcessID& id) {
impl->build_id = id;
}
const System::CurrentBuildProcessID& System::GetCurrentProcessBuildID() const {
const System::CurrentBuildProcessID& System::GetApplicationProcessBuildID() const {
return impl->build_id;
}

View File

@@ -184,8 +184,8 @@ public:
/// Forcibly detach the debugger if it is running.
void DetachDebugger();
std::unique_lock<std::mutex> StallProcesses();
void UnstallProcesses();
std::unique_lock<std::mutex> StallApplication();
void UnstallApplication();
/**
* Initialize the debugger.
@@ -295,11 +295,11 @@ public:
/// Gets the manager for the guest device memory
[[nodiscard]] const Core::DeviceMemory& DeviceMemory() const;
/// Provides a pointer to the current process
[[nodiscard]] Kernel::KProcess* CurrentProcess();
/// Provides a pointer to the application process
[[nodiscard]] Kernel::KProcess* ApplicationProcess();
/// Provides a constant pointer to the current process.
[[nodiscard]] const Kernel::KProcess* CurrentProcess() const;
/// Provides a constant pointer to the application process.
[[nodiscard]] const Kernel::KProcess* ApplicationProcess() const;
/// Provides a reference to the core timing instance.
[[nodiscard]] Timing::CoreTiming& CoreTiming();
@@ -331,7 +331,7 @@ public:
/// Provides a constant reference to the speed limiter
[[nodiscard]] const Core::SpeedLimiter& SpeedLimiter() const;
[[nodiscard]] u64 GetCurrentProcessProgramID() const;
[[nodiscard]] u64 GetApplicationProcessProgramID() const;
/// Gets the name of the current game
[[nodiscard]] Loader::ResultStatus GetGameName(std::string& out) const;
@@ -396,8 +396,8 @@ public:
void SetExitLock(bool locked);
[[nodiscard]] bool GetExitLock() const;
void SetCurrentProcessBuildID(const CurrentBuildProcessID& id);
[[nodiscard]] const CurrentBuildProcessID& GetCurrentProcessBuildID() const;
void SetApplicationProcessBuildID(const CurrentBuildProcessID& id);
[[nodiscard]] const CurrentBuildProcessID& GetApplicationProcessBuildID() const;
/// Register a host thread as an emulated CPU Core.
void RegisterCoreThread(std::size_t id);

View File

@@ -45,7 +45,7 @@ CoreTiming::~CoreTiming() {
}
void CoreTiming::ThreadEntry(CoreTiming& instance) {
constexpr char name[] = "HostTiming";
static constexpr char name[] = "HostTiming";
MicroProfileOnThreadCreate(name);
Common::SetCurrentThreadName(name);
Common::SetCurrentThreadPriority(Common::ThreadPriority::Critical);

View File

@@ -96,7 +96,7 @@ static std::string EscapeXML(std::string_view data) {
GDBStub::GDBStub(DebuggerBackend& backend_, Core::System& system_)
: DebuggerFrontend(backend_), system{system_} {
if (system.CurrentProcess()->Is64BitProcess()) {
if (system.ApplicationProcess()->Is64BitProcess()) {
arch = std::make_unique<GDBStubA64>();
} else {
arch = std::make_unique<GDBStubA32>();
@@ -340,15 +340,15 @@ void GDBStub::HandleBreakpointInsert(std::string_view command) {
success = true;
break;
case BreakpointType::WriteWatch:
success = system.CurrentProcess()->InsertWatchpoint(system, addr, size,
Kernel::DebugWatchpointType::Write);
success = system.ApplicationProcess()->InsertWatchpoint(system, addr, size,
Kernel::DebugWatchpointType::Write);
break;
case BreakpointType::ReadWatch:
success = system.CurrentProcess()->InsertWatchpoint(system, addr, size,
Kernel::DebugWatchpointType::Read);
success = system.ApplicationProcess()->InsertWatchpoint(system, addr, size,
Kernel::DebugWatchpointType::Read);
break;
case BreakpointType::AccessWatch:
success = system.CurrentProcess()->InsertWatchpoint(
success = system.ApplicationProcess()->InsertWatchpoint(
system, addr, size, Kernel::DebugWatchpointType::ReadOrWrite);
break;
case BreakpointType::Hardware:
@@ -391,15 +391,15 @@ void GDBStub::HandleBreakpointRemove(std::string_view command) {
break;
}
case BreakpointType::WriteWatch:
success = system.CurrentProcess()->RemoveWatchpoint(system, addr, size,
Kernel::DebugWatchpointType::Write);
success = system.ApplicationProcess()->RemoveWatchpoint(system, addr, size,
Kernel::DebugWatchpointType::Write);
break;
case BreakpointType::ReadWatch:
success = system.CurrentProcess()->RemoveWatchpoint(system, addr, size,
Kernel::DebugWatchpointType::Read);
success = system.ApplicationProcess()->RemoveWatchpoint(system, addr, size,
Kernel::DebugWatchpointType::Read);
break;
case BreakpointType::AccessWatch:
success = system.CurrentProcess()->RemoveWatchpoint(
success = system.ApplicationProcess()->RemoveWatchpoint(
system, addr, size, Kernel::DebugWatchpointType::ReadOrWrite);
break;
case BreakpointType::Hardware:
@@ -482,7 +482,7 @@ static std::optional<std::string> GetNameFromThreadType64(Core::Memory::Memory&
static std::optional<std::string> GetThreadName(Core::System& system,
const Kernel::KThread* thread) {
if (system.CurrentProcess()->Is64BitProcess()) {
if (system.ApplicationProcess()->Is64BitProcess()) {
return GetNameFromThreadType64(system.Memory(), thread);
} else {
return GetNameFromThreadType32(system.Memory(), thread);
@@ -555,7 +555,7 @@ void GDBStub::HandleQuery(std::string_view command) {
SendReply(fmt::format("TextSeg={:x}", main->first));
} else {
SendReply(fmt::format("TextSeg={:x}",
system.CurrentProcess()->PageTable().GetCodeRegionStart()));
system.ApplicationProcess()->PageTable().GetCodeRegionStart()));
}
} else if (command.starts_with("Xfer:libraries:read::")) {
Loader::AppLoader::Modules modules;
@@ -729,7 +729,7 @@ void GDBStub::HandleRcmd(const std::vector<u8>& command) {
std::string_view command_str{reinterpret_cast<const char*>(&command[0]), command.size()};
std::string reply;
auto* process = system.CurrentProcess();
auto* process = system.ApplicationProcess();
auto& page_table = process->PageTable();
const char* commands = "Commands:\n"

View File

@@ -41,9 +41,8 @@ static void PutSIMDRegister(std::array<u32, 64>& simd_regs, size_t offset, const
// For sample XML files see the GDB source /gdb/features
// This XML defines what the registers are for this specific ARM device
std::string GDBStubA64::GetTargetXML() const {
constexpr const char* target_xml =
R"(<?xml version="1.0"?>
std::string_view GDBStubA64::GetTargetXML() const {
return R"(<?xml version="1.0"?>
<!DOCTYPE target SYSTEM "gdb-target.dtd">
<target version="1.0">
<architecture>aarch64</architecture>
@@ -178,8 +177,6 @@ std::string GDBStubA64::GetTargetXML() const {
<reg name="fpcr" bitsize="32"/>
</feature>
</target>)";
return target_xml;
}
std::string GDBStubA64::RegRead(const Kernel::KThread* thread, size_t id) const {
@@ -270,9 +267,8 @@ u32 GDBStubA64::BreakpointInstruction() const {
return 0xd4200000;
}
std::string GDBStubA32::GetTargetXML() const {
constexpr const char* target_xml =
R"(<?xml version="1.0"?>
std::string_view GDBStubA32::GetTargetXML() const {
return R"(<?xml version="1.0"?>
<!DOCTYPE target SYSTEM "gdb-target.dtd">
<target version="1.0">
<architecture>arm</architecture>
@@ -378,8 +374,6 @@ std::string GDBStubA32::GetTargetXML() const {
<reg name="fpscr" bitsize="32" type="int" group="float" regnum="80"/>
</feature>
</target>)";
return target_xml;
}
std::string GDBStubA32::RegRead(const Kernel::KThread* thread, size_t id) const {

View File

@@ -16,7 +16,7 @@ namespace Core {
class GDBStubArch {
public:
virtual ~GDBStubArch() = default;
virtual std::string GetTargetXML() const = 0;
virtual std::string_view GetTargetXML() const = 0;
virtual std::string RegRead(const Kernel::KThread* thread, size_t id) const = 0;
virtual void RegWrite(Kernel::KThread* thread, size_t id, std::string_view value) const = 0;
virtual std::string ReadRegisters(const Kernel::KThread* thread) const = 0;
@@ -27,7 +27,7 @@ public:
class GDBStubA64 final : public GDBStubArch {
public:
std::string GetTargetXML() const override;
std::string_view GetTargetXML() const override;
std::string RegRead(const Kernel::KThread* thread, size_t id) const override;
void RegWrite(Kernel::KThread* thread, size_t id, std::string_view value) const override;
std::string ReadRegisters(const Kernel::KThread* thread) const override;
@@ -47,7 +47,7 @@ private:
class GDBStubA32 final : public GDBStubArch {
public:
std::string GetTargetXML() const override;
std::string_view GetTargetXML() const override;
std::string RegRead(const Kernel::KThread* thread, size_t id) const override;
void RegWrite(Kernel::KThread* thread, size_t id, std::string_view value) const override;
std::string ReadRegisters(const Kernel::KThread* thread) const override;

View File

@@ -41,12 +41,12 @@ static IPSFileType IdentifyMagic(const std::vector<u8>& magic) {
return IPSFileType::Error;
}
constexpr std::array<u8, 5> patch_magic{{'P', 'A', 'T', 'C', 'H'}};
static constexpr std::array<u8, 5> patch_magic{{'P', 'A', 'T', 'C', 'H'}};
if (std::equal(magic.begin(), magic.end(), patch_magic.begin())) {
return IPSFileType::IPS;
}
constexpr std::array<u8, 5> ips32_magic{{'I', 'P', 'S', '3', '2'}};
static constexpr std::array<u8, 5> ips32_magic{{'I', 'P', 'S', '3', '2'}};
if (std::equal(magic.begin(), magic.end(), ips32_magic.begin())) {
return IPSFileType::IPS32;
}
@@ -55,12 +55,12 @@ static IPSFileType IdentifyMagic(const std::vector<u8>& magic) {
}
static bool IsEOF(IPSFileType type, const std::vector<u8>& data) {
constexpr std::array<u8, 3> eof{{'E', 'O', 'F'}};
static constexpr std::array<u8, 3> eof{{'E', 'O', 'F'}};
if (type == IPSFileType::IPS && std::equal(data.begin(), data.end(), eof.begin())) {
return true;
}
constexpr std::array<u8, 4> eeof{{'E', 'E', 'O', 'F'}};
static constexpr std::array<u8, 4> eeof{{'E', 'E', 'O', 'F'}};
return type == IPSFileType::IPS32 && std::equal(data.begin(), data.end(), eeof.begin());
}

View File

@@ -71,7 +71,7 @@ static std::string GetRelativePathFromNcaID(const std::array<u8, 16>& nca_id, bo
}
static std::string GetCNMTName(TitleType type, u64 title_id) {
constexpr std::array<const char*, 9> TITLE_TYPE_NAMES{
static constexpr std::array<const char*, 9> TITLE_TYPE_NAMES{
"SystemProgram",
"SystemData",
"SystemUpdate",

View File

@@ -172,7 +172,7 @@ std::string SaveDataFactory::GetFullPath(Core::System& system, VirtualDir dir,
// be interpreted as the title id of the current process.
if (type == SaveDataType::SaveData || type == SaveDataType::DeviceSaveData) {
if (title_id == 0) {
title_id = system.GetCurrentProcessProgramID();
title_id = system.GetApplicationProcessProgramID();
}
}

View File

@@ -23,7 +23,8 @@ void EmulatedConsole::SetTouchParams() {
// We can't use mouse as touch if native mouse is enabled
if (!Settings::values.mouse_enabled) {
touch_params[index++] = Common::ParamPackage{"engine:mouse,axis_x:10,axis_y:11,button:0"};
touch_params[index++] =
Common::ParamPackage{"engine:mouse,axis_x:0,axis_y:1,button:0,port:2"};
}
touch_params[index++] =

View File

@@ -363,7 +363,17 @@ void EmulatedController::ReloadInput() {
SetMotion(callback, index);
},
});
motion_devices[index]->ForceUpdate();
// Restore motion state
auto& emulated_motion = controller.motion_values[index].emulated;
auto& motion = controller.motion_state[index];
emulated_motion.ResetRotations();
emulated_motion.ResetQuaternion();
motion.accel = emulated_motion.GetAcceleration();
motion.gyro = emulated_motion.GetGyroscope();
motion.rotation = emulated_motion.GetRotations();
motion.orientation = emulated_motion.GetOrientation();
motion.is_at_rest = !emulated_motion.IsMoving(motion_sensitivity);
}
for (std::size_t index = 0; index < camera_devices.size(); ++index) {
@@ -957,7 +967,7 @@ void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback
raw_status.gyro.y.value,
raw_status.gyro.z.value,
});
emulated.SetGyroThreshold(raw_status.gyro.x.properties.threshold);
emulated.SetUserGyroThreshold(raw_status.gyro.x.properties.threshold);
emulated.UpdateRotation(raw_status.delta_timestamp);
emulated.UpdateOrientation(raw_status.delta_timestamp);
force_update_motion = raw_status.force_update;
@@ -1284,6 +1294,26 @@ void EmulatedController::SetLedPattern() {
}
}
void EmulatedController::SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode mode) {
for (auto& motion : controller.motion_values) {
switch (mode) {
case GyroscopeZeroDriftMode::Loose:
motion_sensitivity = motion.emulated.IsAtRestLoose;
motion.emulated.SetGyroThreshold(motion.emulated.ThresholdLoose);
break;
case GyroscopeZeroDriftMode::Tight:
motion_sensitivity = motion.emulated.IsAtRestThight;
motion.emulated.SetGyroThreshold(motion.emulated.ThresholdThight);
break;
case GyroscopeZeroDriftMode::Standard:
default:
motion_sensitivity = motion.emulated.IsAtRestStandard;
motion.emulated.SetGyroThreshold(motion.emulated.ThresholdStandard);
break;
}
}
}
void EmulatedController::SetSupportedNpadStyleTag(NpadStyleTag supported_styles) {
supported_style_tag = supported_styles;
if (!is_connected) {

View File

@@ -398,6 +398,9 @@ public:
/// Asks the output device to change the player led pattern
void SetLedPattern();
/// Changes sensitivity of the motion sensor
void SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode mode);
/**
* Adds a callback to the list of events
* @param update_callback A ConsoleUpdateCallback that will be triggered
@@ -523,7 +526,7 @@ private:
bool is_connected{false};
bool is_configuring{false};
bool system_buttons_enabled{true};
f32 motion_sensitivity{0.01f};
f32 motion_sensitivity{Core::HID::MotionInput::IsAtRestStandard};
bool force_update_motion{false};
u32 turbo_button_state{0};

View File

@@ -19,49 +19,53 @@ void EmulatedDevices::ReloadFromSettings() {
void EmulatedDevices::ReloadInput() {
// If you load any device here add the equivalent to the UnloadInput() function
// Native Mouse is mapped on port 1, pad 0
const Common::ParamPackage mouse_params{"engine:mouse,port:1,pad:0"};
// Keyboard keys is mapped on port 1, pad 0 for normal keys, pad 1 for moddifier keys
const Common::ParamPackage keyboard_params{"engine:keyboard,port:1"};
std::size_t key_index = 0;
for (auto& mouse_device : mouse_button_devices) {
Common::ParamPackage mouse_params;
mouse_params.Set("engine", "mouse");
mouse_params.Set("button", static_cast<int>(key_index));
mouse_device = Common::Input::CreateInputDevice(mouse_params);
Common::ParamPackage mouse_button_params = mouse_params;
mouse_button_params.Set("button", static_cast<int>(key_index));
mouse_device = Common::Input::CreateInputDevice(mouse_button_params);
key_index++;
}
mouse_stick_device =
Common::Input::CreateInputDeviceFromString("engine:mouse,axis_x:0,axis_y:1");
Common::ParamPackage mouse_position_params = mouse_params;
mouse_position_params.Set("axis_x", 0);
mouse_position_params.Set("axis_y", 1);
mouse_position_params.Set("deadzone", 0.0f);
mouse_position_params.Set("range", 1.0f);
mouse_position_params.Set("threshold", 0.0f);
mouse_stick_device = Common::Input::CreateInputDevice(mouse_position_params);
// First two axis are reserved for mouse position
key_index = 2;
for (auto& mouse_device : mouse_analog_devices) {
Common::ParamPackage mouse_params;
mouse_params.Set("engine", "mouse");
mouse_params.Set("axis", static_cast<int>(key_index));
mouse_device = Common::Input::CreateInputDevice(mouse_params);
for (auto& mouse_device : mouse_wheel_devices) {
Common::ParamPackage mouse_wheel_params = mouse_params;
mouse_wheel_params.Set("axis", static_cast<int>(key_index));
mouse_device = Common::Input::CreateInputDevice(mouse_wheel_params);
key_index++;
}
key_index = 0;
for (auto& keyboard_device : keyboard_devices) {
// Keyboard keys are only mapped on port 1, pad 0
Common::ParamPackage keyboard_params;
keyboard_params.Set("engine", "keyboard");
keyboard_params.Set("button", static_cast<int>(key_index));
keyboard_params.Set("port", 1);
keyboard_params.Set("pad", 0);
keyboard_device = Common::Input::CreateInputDevice(keyboard_params);
Common::ParamPackage keyboard_key_params = keyboard_params;
keyboard_key_params.Set("button", static_cast<int>(key_index));
keyboard_key_params.Set("pad", 0);
keyboard_device = Common::Input::CreateInputDevice(keyboard_key_params);
key_index++;
}
key_index = 0;
for (auto& keyboard_device : keyboard_modifier_devices) {
// Keyboard moddifiers are only mapped on port 1, pad 1
Common::ParamPackage keyboard_params;
keyboard_params.Set("engine", "keyboard");
keyboard_params.Set("button", static_cast<int>(key_index));
keyboard_params.Set("port", 1);
keyboard_params.Set("pad", 1);
keyboard_device = Common::Input::CreateInputDevice(keyboard_params);
Common::ParamPackage keyboard_moddifier_params = keyboard_params;
keyboard_moddifier_params.Set("button", static_cast<int>(key_index));
keyboard_moddifier_params.Set("pad", 1);
keyboard_device = Common::Input::CreateInputDevice(keyboard_moddifier_params);
key_index++;
}
@@ -77,14 +81,14 @@ void EmulatedDevices::ReloadInput() {
});
}
for (std::size_t index = 0; index < mouse_analog_devices.size(); ++index) {
if (!mouse_analog_devices[index]) {
for (std::size_t index = 0; index < mouse_wheel_devices.size(); ++index) {
if (!mouse_wheel_devices[index]) {
continue;
}
mouse_analog_devices[index]->SetCallback({
mouse_wheel_devices[index]->SetCallback({
.on_change =
[this, index](const Common::Input::CallbackStatus& callback) {
SetMouseAnalog(callback, index);
SetMouseWheel(callback, index);
},
});
}
@@ -92,7 +96,9 @@ void EmulatedDevices::ReloadInput() {
if (mouse_stick_device) {
mouse_stick_device->SetCallback({
.on_change =
[this](const Common::Input::CallbackStatus& callback) { SetMouseStick(callback); },
[this](const Common::Input::CallbackStatus& callback) {
SetMousePosition(callback);
},
});
}
@@ -125,7 +131,7 @@ void EmulatedDevices::UnloadInput() {
for (auto& button : mouse_button_devices) {
button.reset();
}
for (auto& analog : mouse_analog_devices) {
for (auto& analog : mouse_wheel_devices) {
analog.reset();
}
mouse_stick_device.reset();
@@ -359,18 +365,18 @@ void EmulatedDevices::SetMouseButton(const Common::Input::CallbackStatus& callba
TriggerOnChange(DeviceTriggerType::Mouse);
}
void EmulatedDevices::SetMouseAnalog(const Common::Input::CallbackStatus& callback,
std::size_t index) {
if (index >= device_status.mouse_analog_values.size()) {
void EmulatedDevices::SetMouseWheel(const Common::Input::CallbackStatus& callback,
std::size_t index) {
if (index >= device_status.mouse_wheel_values.size()) {
return;
}
std::unique_lock lock{mutex};
const auto analog_value = TransformToAnalog(callback);
device_status.mouse_analog_values[index] = analog_value;
device_status.mouse_wheel_values[index] = analog_value;
if (is_configuring) {
device_status.mouse_position_state = {};
device_status.mouse_wheel_state = {};
lock.unlock();
TriggerOnChange(DeviceTriggerType::Mouse);
return;
@@ -389,7 +395,7 @@ void EmulatedDevices::SetMouseAnalog(const Common::Input::CallbackStatus& callba
TriggerOnChange(DeviceTriggerType::Mouse);
}
void EmulatedDevices::SetMouseStick(const Common::Input::CallbackStatus& callback) {
void EmulatedDevices::SetMousePosition(const Common::Input::CallbackStatus& callback) {
std::unique_lock lock{mutex};
const auto touch_value = TransformToTouch(callback);

View File

@@ -23,8 +23,8 @@ using KeyboardModifierDevices = std::array<std::unique_ptr<Common::Input::InputD
Settings::NativeKeyboard::NumKeyboardMods>;
using MouseButtonDevices = std::array<std::unique_ptr<Common::Input::InputDevice>,
Settings::NativeMouseButton::NumMouseButtons>;
using MouseAnalogDevices = std::array<std::unique_ptr<Common::Input::InputDevice>,
Settings::NativeMouseWheel::NumMouseWheels>;
using MouseWheelDevices = std::array<std::unique_ptr<Common::Input::InputDevice>,
Settings::NativeMouseWheel::NumMouseWheels>;
using MouseStickDevice = std::unique_ptr<Common::Input::InputDevice>;
using MouseButtonParams =
@@ -36,7 +36,7 @@ using KeyboardModifierValues =
std::array<Common::Input::ButtonStatus, Settings::NativeKeyboard::NumKeyboardMods>;
using MouseButtonValues =
std::array<Common::Input::ButtonStatus, Settings::NativeMouseButton::NumMouseButtons>;
using MouseAnalogValues =
using MouseWheelValues =
std::array<Common::Input::AnalogStatus, Settings::NativeMouseWheel::NumMouseWheels>;
using MouseStickValue = Common::Input::TouchStatus;
@@ -50,7 +50,7 @@ struct DeviceStatus {
KeyboardValues keyboard_values{};
KeyboardModifierValues keyboard_moddifier_values{};
MouseButtonValues mouse_button_values{};
MouseAnalogValues mouse_analog_values{};
MouseWheelValues mouse_wheel_values{};
MouseStickValue mouse_stick_value{};
// Data for HID serices
@@ -111,15 +111,6 @@ public:
/// Reverts any mapped changes made that weren't saved
void RestoreConfig();
// Returns the current mapped ring device
Common::ParamPackage GetRingParam() const;
/**
* Updates the current mapped ring device
* @param param ParamPackage with ring sensor data to be mapped
*/
void SetRingParam(Common::ParamPackage param);
/// Returns the latest status of button input from the keyboard with parameters
KeyboardValues GetKeyboardValues() const;
@@ -187,19 +178,13 @@ private:
* @param callback A CallbackStatus containing the wheel status
* @param index wheel ID to be updated
*/
void SetMouseAnalog(const Common::Input::CallbackStatus& callback, std::size_t index);
void SetMouseWheel(const Common::Input::CallbackStatus& callback, std::size_t index);
/**
* Updates the mouse position status of the mouse device
* @param callback A CallbackStatus containing the position status
*/
void SetMouseStick(const Common::Input::CallbackStatus& callback);
/**
* Updates the ring analog sensor status of the ring controller
* @param callback A CallbackStatus containing the force status
*/
void SetRingAnalog(const Common::Input::CallbackStatus& callback);
void SetMousePosition(const Common::Input::CallbackStatus& callback);
/**
* Triggers a callback that something has changed on the device status
@@ -212,7 +197,7 @@ private:
KeyboardDevices keyboard_devices;
KeyboardModifierDevices keyboard_modifier_devices;
MouseButtonDevices mouse_button_devices;
MouseAnalogDevices mouse_analog_devices;
MouseWheelDevices mouse_wheel_devices;
MouseStickDevice mouse_stick_device;
mutable std::mutex mutex;

View File

@@ -282,6 +282,13 @@ enum class VibrationGcErmCommand : u64 {
StopHard = 2,
};
// This is nn::hid::GyroscopeZeroDriftMode
enum class GyroscopeZeroDriftMode : u32 {
Loose = 0,
Standard = 1,
Tight = 2,
};
// This is nn::hid::NpadStyleTag
struct NpadStyleTag {
union {

View File

@@ -9,7 +9,9 @@ namespace Core::HID {
MotionInput::MotionInput() {
// Initialize PID constants with default values
SetPID(0.3f, 0.005f, 0.0f);
SetGyroThreshold(0.007f);
SetGyroThreshold(ThresholdStandard);
ResetQuaternion();
ResetRotations();
}
void MotionInput::SetPID(f32 new_kp, f32 new_ki, f32 new_kd) {
@@ -20,17 +22,25 @@ void MotionInput::SetPID(f32 new_kp, f32 new_ki, f32 new_kd) {
void MotionInput::SetAcceleration(const Common::Vec3f& acceleration) {
accel = acceleration;
accel.x = std::clamp(accel.x, -AccelMaxValue, AccelMaxValue);
accel.y = std::clamp(accel.y, -AccelMaxValue, AccelMaxValue);
accel.z = std::clamp(accel.z, -AccelMaxValue, AccelMaxValue);
}
void MotionInput::SetGyroscope(const Common::Vec3f& gyroscope) {
gyro = gyroscope - gyro_bias;
gyro.x = std::clamp(gyro.x, -GyroMaxValue, GyroMaxValue);
gyro.y = std::clamp(gyro.y, -GyroMaxValue, GyroMaxValue);
gyro.z = std::clamp(gyro.z, -GyroMaxValue, GyroMaxValue);
// Auto adjust drift to minimize drift
if (!IsMoving(0.1f)) {
if (!IsMoving(IsAtRestRelaxed)) {
gyro_bias = (gyro_bias * 0.9999f) + (gyroscope * 0.0001f);
}
if (gyro.Length() < gyro_threshold) {
if (gyro.Length() < gyro_threshold * user_gyro_threshold) {
gyro = {};
} else {
only_accelerometer = false;
@@ -49,6 +59,10 @@ void MotionInput::SetGyroThreshold(f32 threshold) {
gyro_threshold = threshold;
}
void MotionInput::SetUserGyroThreshold(f32 threshold) {
user_gyro_threshold = threshold / ThresholdStandard;
}
void MotionInput::EnableReset(bool reset) {
reset_enabled = reset;
}
@@ -57,6 +71,10 @@ void MotionInput::ResetRotations() {
rotations = {};
}
void MotionInput::ResetQuaternion() {
quat = {{0.0f, 0.0f, -1.0f}, 0.0f};
}
bool MotionInput::IsMoving(f32 sensitivity) const {
return gyro.Length() >= sensitivity || accel.Length() <= 0.9f || accel.Length() >= 1.1f;
}
@@ -208,7 +226,7 @@ void MotionInput::ResetOrientation() {
if (!reset_enabled || only_accelerometer) {
return;
}
if (!IsMoving(0.5f) && accel.z <= -0.9f) {
if (!IsMoving(IsAtRestRelaxed) && accel.z <= -0.9f) {
++reset_counter;
if (reset_counter > 900) {
quat.w = 0;

View File

@@ -11,6 +11,18 @@ namespace Core::HID {
class MotionInput {
public:
static constexpr float ThresholdLoose = 0.01f;
static constexpr float ThresholdStandard = 0.007f;
static constexpr float ThresholdThight = 0.002f;
static constexpr float IsAtRestRelaxed = 0.05f;
static constexpr float IsAtRestLoose = 0.02f;
static constexpr float IsAtRestStandard = 0.01f;
static constexpr float IsAtRestThight = 0.005f;
static constexpr float GyroMaxValue = 5.0f;
static constexpr float AccelMaxValue = 7.0f;
explicit MotionInput();
MotionInput(const MotionInput&) = default;
@@ -26,8 +38,12 @@ public:
void SetGyroBias(const Common::Vec3f& bias);
void SetGyroThreshold(f32 threshold);
/// Applies a modifier on top of the normal gyro threshold
void SetUserGyroThreshold(f32 threshold);
void EnableReset(bool reset);
void ResetRotations();
void ResetQuaternion();
void UpdateRotation(u64 elapsed_time);
void UpdateOrientation(u64 elapsed_time);
@@ -57,7 +73,7 @@ private:
Common::Vec3f derivative_error;
// Quaternion containing the device orientation
Common::Quaternion<f32> quat{{0.0f, 0.0f, -1.0f}, 0.0f};
Common::Quaternion<f32> quat;
// Number of full rotations in each axis
Common::Vec3f rotations;
@@ -74,6 +90,9 @@ private:
// Minimum gyro amplitude to detect if the device is moving
f32 gyro_threshold = 0.0f;
// Multiplies gyro_threshold by this value
f32 user_gyro_threshold = 0.0f;
// Number of invalid sequential data
u32 reset_counter = 0;

View File

@@ -148,7 +148,7 @@ public:
if (context->GetManager()->IsDomain()) {
context->AddDomainObject(std::move(iface));
} else {
kernel.CurrentProcess()->GetResourceLimit()->Reserve(
kernel.ApplicationProcess()->GetResourceLimit()->Reserve(
Kernel::LimitableResource::SessionCountMax, 1);
auto* session = Kernel::KSession::Create(kernel);

View File

@@ -16,6 +16,7 @@
#include "core/hle/kernel/k_event_info.h"
#include "core/hle/kernel/k_memory_layout.h"
#include "core/hle/kernel/k_memory_manager.h"
#include "core/hle/kernel/k_object_name.h"
#include "core/hle/kernel/k_page_buffer.h"
#include "core/hle/kernel/k_port.h"
#include "core/hle/kernel/k_process.h"
@@ -49,6 +50,7 @@ namespace Kernel::Init {
HANDLER(KThreadLocalPage, \
(SLAB_COUNT(KProcess) + (SLAB_COUNT(KProcess) + SLAB_COUNT(KThread)) / 8), \
##__VA_ARGS__) \
HANDLER(KObjectName, (SLAB_COUNT(KObjectName)), ##__VA_ARGS__) \
HANDLER(KResourceLimit, (SLAB_COUNT(KResourceLimit)), ##__VA_ARGS__) \
HANDLER(KEventInfo, (SLAB_COUNT(KThread) + SLAB_COUNT(KDebug)), ##__VA_ARGS__) \
HANDLER(KDebug, (SLAB_COUNT(KDebug)), ##__VA_ARGS__) \

View File

@@ -60,7 +60,8 @@ bool KClientPort::IsSignaled() const {
Result KClientPort::CreateSession(KClientSession** out) {
// Reserve a new session from the resource limit.
KScopedResourceReservation session_reservation(kernel.CurrentProcess()->GetResourceLimit(),
//! FIXME: we are reserving this from the wrong resource limit!
KScopedResourceReservation session_reservation(kernel.ApplicationProcess()->GetResourceLimit(),
LimitableResource::SessionCountMax);
R_UNLESS(session_reservation.Succeeded(), ResultLimitReached);

View File

@@ -21,7 +21,7 @@ KCodeMemory::KCodeMemory(KernelCore& kernel_)
Result KCodeMemory::Initialize(Core::DeviceMemory& device_memory, VAddr addr, size_t size) {
// Set members.
m_owner = kernel.CurrentProcess();
m_owner = GetCurrentProcessPointer(kernel);
// Get the owner page table.
auto& page_table = m_owner->PageTable();
@@ -74,7 +74,7 @@ Result KCodeMemory::Map(VAddr address, size_t size) {
R_UNLESS(!m_is_mapped, ResultInvalidState);
// Map the memory.
R_TRY(kernel.CurrentProcess()->PageTable().MapPageGroup(
R_TRY(GetCurrentProcess(kernel).PageTable().MapPageGroup(
address, *m_page_group, KMemoryState::CodeOut, KMemoryPermission::UserReadWrite));
// Mark ourselves as mapped.
@@ -91,8 +91,8 @@ Result KCodeMemory::Unmap(VAddr address, size_t size) {
KScopedLightLock lk(m_lock);
// Unmap the memory.
R_TRY(kernel.CurrentProcess()->PageTable().UnmapPageGroup(address, *m_page_group,
KMemoryState::CodeOut));
R_TRY(GetCurrentProcess(kernel).PageTable().UnmapPageGroup(address, *m_page_group,
KMemoryState::CodeOut));
// Mark ourselves as unmapped.
m_is_mapped = false;

View File

@@ -164,8 +164,8 @@ Result KConditionVariable::WaitForAddress(Handle handle, VAddr addr, u32 value)
R_SUCCEED_IF(test_tag != (handle | Svc::HandleWaitMask));
// Get the lock owner thread.
owner_thread = kernel.CurrentProcess()
->GetHandleTable()
owner_thread = GetCurrentProcess(kernel)
.GetHandleTable()
.GetObjectWithoutPseudoHandle<KThread>(handle)
.ReleasePointerUnsafe();
R_UNLESS(owner_thread != nullptr, ResultInvalidHandle);
@@ -213,8 +213,8 @@ void KConditionVariable::SignalImpl(KThread* thread) {
thread->EndWait(ResultSuccess);
} else {
// Get the previous owner.
KThread* owner_thread = kernel.CurrentProcess()
->GetHandleTable()
KThread* owner_thread = GetCurrentProcess(kernel)
.GetHandleTable()
.GetObjectWithoutPseudoHandle<KThread>(
static_cast<Handle>(prev_tag & ~Svc::HandleWaitMask))
.ReleasePointerUnsafe();

View File

@@ -90,7 +90,8 @@ public:
// Handle pseudo-handles.
if constexpr (std::derived_from<KProcess, T>) {
if (handle == Svc::PseudoHandle::CurrentProcess) {
auto* const cur_process = m_kernel.CurrentProcess();
//! FIXME: this is the wrong process!
auto* const cur_process = m_kernel.ApplicationProcess();
ASSERT(cur_process != nullptr);
return cur_process;
}

View File

@@ -16,7 +16,7 @@ void HandleInterrupt(KernelCore& kernel, s32 core_id) {
auto& current_thread = GetCurrentThread(kernel);
if (auto* process = kernel.CurrentProcess(); process) {
if (auto* process = GetCurrentProcessPointer(kernel); process) {
// If the user disable count is set, we may need to pin the current thread.
if (current_thread.GetUserDisableCount() && !process->GetPinnedThread(core_id)) {
KScopedSchedulerLock sl{kernel};

View File

@@ -0,0 +1,102 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/kernel/k_object_name.h"
namespace Kernel {
KObjectNameGlobalData::KObjectNameGlobalData(KernelCore& kernel) : m_object_list_lock{kernel} {}
KObjectNameGlobalData::~KObjectNameGlobalData() = default;
void KObjectName::Initialize(KAutoObject* obj, const char* name) {
// Set member variables.
m_object = obj;
std::strncpy(m_name.data(), name, sizeof(m_name) - 1);
m_name[sizeof(m_name) - 1] = '\x00';
// Open a reference to the object we hold.
m_object->Open();
}
bool KObjectName::MatchesName(const char* name) const {
return std::strncmp(m_name.data(), name, sizeof(m_name)) == 0;
}
Result KObjectName::NewFromName(KernelCore& kernel, KAutoObject* obj, const char* name) {
// Create a new object name.
KObjectName* new_name = KObjectName::Allocate(kernel);
R_UNLESS(new_name != nullptr, ResultOutOfResource);
// Initialize the new name.
new_name->Initialize(obj, name);
// Check if there's an existing name.
{
// Get the global data.
KObjectNameGlobalData& gd{kernel.ObjectNameGlobalData()};
// Ensure we have exclusive access to the global list.
KScopedLightLock lk{gd.GetObjectListLock()};
// If the object doesn't exist, put it into the list.
KScopedAutoObject existing_object = FindImpl(kernel, name);
if (existing_object.IsNull()) {
gd.GetObjectList().push_back(*new_name);
R_SUCCEED();
}
}
// The object already exists, which is an error condition. Perform cleanup.
obj->Close();
KObjectName::Free(kernel, new_name);
R_THROW(ResultInvalidState);
}
Result KObjectName::Delete(KernelCore& kernel, KAutoObject* obj, const char* compare_name) {
// Get the global data.
KObjectNameGlobalData& gd{kernel.ObjectNameGlobalData()};
// Ensure we have exclusive access to the global list.
KScopedLightLock lk{gd.GetObjectListLock()};
// Find a matching entry in the list, and delete it.
for (auto& name : gd.GetObjectList()) {
if (name.MatchesName(compare_name) && obj == name.GetObject()) {
// We found a match, clean up its resources.
obj->Close();
gd.GetObjectList().erase(gd.GetObjectList().iterator_to(name));
KObjectName::Free(kernel, std::addressof(name));
R_SUCCEED();
}
}
// We didn't find the object in the list.
R_THROW(ResultNotFound);
}
KScopedAutoObject<KAutoObject> KObjectName::Find(KernelCore& kernel, const char* name) {
// Get the global data.
KObjectNameGlobalData& gd{kernel.ObjectNameGlobalData()};
// Ensure we have exclusive access to the global list.
KScopedLightLock lk{gd.GetObjectListLock()};
return FindImpl(kernel, name);
}
KScopedAutoObject<KAutoObject> KObjectName::FindImpl(KernelCore& kernel, const char* compare_name) {
// Get the global data.
KObjectNameGlobalData& gd{kernel.ObjectNameGlobalData()};
// Try to find a matching object in the global list.
for (const auto& name : gd.GetObjectList()) {
if (name.MatchesName(compare_name)) {
return name.GetObject();
}
}
// There's no matching entry in the list.
return nullptr;
}
} // namespace Kernel

View File

@@ -0,0 +1,86 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <array>
#include <memory>
#include <boost/intrusive/list.hpp>
#include "core/hle/kernel/k_light_lock.h"
#include "core/hle/kernel/slab_helpers.h"
#include "core/hle/kernel/svc_results.h"
namespace Kernel {
class KObjectNameGlobalData;
class KObjectName : public KSlabAllocated<KObjectName>, public boost::intrusive::list_base_hook<> {
public:
explicit KObjectName(KernelCore&) {}
virtual ~KObjectName() = default;
static constexpr size_t NameLengthMax = 12;
using List = boost::intrusive::list<KObjectName>;
static Result NewFromName(KernelCore& kernel, KAutoObject* obj, const char* name);
static Result Delete(KernelCore& kernel, KAutoObject* obj, const char* name);
static KScopedAutoObject<KAutoObject> Find(KernelCore& kernel, const char* name);
template <typename Derived>
static Result Delete(KernelCore& kernel, const char* name) {
// Find the object.
KScopedAutoObject obj = Find(kernel, name);
R_UNLESS(obj.IsNotNull(), ResultNotFound);
// Cast the object to the desired type.
Derived* derived = obj->DynamicCast<Derived*>();
R_UNLESS(derived != nullptr, ResultNotFound);
// Check that the object is closed.
R_UNLESS(derived->IsServerClosed(), ResultInvalidState);
return Delete(kernel, obj.GetPointerUnsafe(), name);
}
template <typename Derived>
requires(std::derived_from<Derived, KAutoObject>)
static KScopedAutoObject<Derived> Find(KernelCore& kernel, const char* name) {
return Find(kernel, name);
}
private:
static KScopedAutoObject<KAutoObject> FindImpl(KernelCore& kernel, const char* name);
void Initialize(KAutoObject* obj, const char* name);
bool MatchesName(const char* name) const;
KAutoObject* GetObject() const {
return m_object;
}
private:
std::array<char, NameLengthMax> m_name{};
KAutoObject* m_object{};
};
class KObjectNameGlobalData {
public:
explicit KObjectNameGlobalData(KernelCore& kernel);
~KObjectNameGlobalData();
KLightLock& GetObjectListLock() {
return m_object_list_lock;
}
KObjectName::List& GetObjectList() {
return m_object_list;
}
private:
KLightLock m_object_list_lock;
KObjectName::List m_object_list;
};
} // namespace Kernel

View File

@@ -370,7 +370,7 @@ Result KProcess::LoadFromMetadata(const FileSys::ProgramMetadata& metadata, std:
// Initialize proces address space
if (const Result result{page_table.InitializeForProcess(
metadata.GetAddressSpaceType(), false, false, false, KMemoryManager::Pool::Application,
0x8000000, code_size, &kernel.GetSystemSystemResource(), resource_limit)};
0x8000000, code_size, &kernel.GetAppSystemResource(), resource_limit)};
result.IsError()) {
R_RETURN(result);
}

View File

@@ -328,7 +328,7 @@ u64 KScheduler::UpdateHighestPriorityThreadsImpl(KernelCore& kernel) {
}
void KScheduler::SwitchThread(KThread* next_thread) {
KProcess* const cur_process = kernel.CurrentProcess();
KProcess* const cur_process = GetCurrentProcessPointer(kernel);
KThread* const cur_thread = GetCurrentThreadPointer(kernel);
// We never want to schedule a null thread, so use the idle thread if we don't have a next.
@@ -689,11 +689,11 @@ void KScheduler::RotateScheduledQueue(KernelCore& kernel, s32 core_id, s32 prior
void KScheduler::YieldWithoutCoreMigration(KernelCore& kernel) {
// Validate preconditions.
ASSERT(CanSchedule(kernel));
ASSERT(kernel.CurrentProcess() != nullptr);
ASSERT(GetCurrentProcessPointer(kernel) != nullptr);
// Get the current thread and process.
KThread& cur_thread = GetCurrentThread(kernel);
KProcess& cur_process = *kernel.CurrentProcess();
KProcess& cur_process = GetCurrentProcess(kernel);
// If the thread's yield count matches, there's nothing for us to do.
if (cur_thread.GetYieldScheduleCount() == cur_process.GetScheduledCount()) {
@@ -728,11 +728,11 @@ void KScheduler::YieldWithoutCoreMigration(KernelCore& kernel) {
void KScheduler::YieldWithCoreMigration(KernelCore& kernel) {
// Validate preconditions.
ASSERT(CanSchedule(kernel));
ASSERT(kernel.CurrentProcess() != nullptr);
ASSERT(GetCurrentProcessPointer(kernel) != nullptr);
// Get the current thread and process.
KThread& cur_thread = GetCurrentThread(kernel);
KProcess& cur_process = *kernel.CurrentProcess();
KProcess& cur_process = GetCurrentProcess(kernel);
// If the thread's yield count matches, there's nothing for us to do.
if (cur_thread.GetYieldScheduleCount() == cur_process.GetScheduledCount()) {
@@ -816,11 +816,11 @@ void KScheduler::YieldWithCoreMigration(KernelCore& kernel) {
void KScheduler::YieldToAnyThread(KernelCore& kernel) {
// Validate preconditions.
ASSERT(CanSchedule(kernel));
ASSERT(kernel.CurrentProcess() != nullptr);
ASSERT(GetCurrentProcessPointer(kernel) != nullptr);
// Get the current thread and process.
KThread& cur_thread = GetCurrentThread(kernel);
KProcess& cur_process = *kernel.CurrentProcess();
KProcess& cur_process = GetCurrentProcess(kernel);
// If the thread's yield count matches, there's nothing for us to do.
if (cur_thread.GetYieldScheduleCount() == cur_process.GetScheduledCount()) {

View File

@@ -33,7 +33,8 @@ void KSession::Initialize(KClientPort* port_, const std::string& name_) {
name = name_;
// Set our owner process.
process = kernel.CurrentProcess();
//! FIXME: this is the wrong process!
process = kernel.ApplicationProcess();
process->Open();
// Set our port.

View File

@@ -1266,6 +1266,14 @@ KThread& GetCurrentThread(KernelCore& kernel) {
return *GetCurrentThreadPointer(kernel);
}
KProcess* GetCurrentProcessPointer(KernelCore& kernel) {
return GetCurrentThread(kernel).GetOwnerProcess();
}
KProcess& GetCurrentProcess(KernelCore& kernel) {
return *GetCurrentProcessPointer(kernel);
}
s32 GetCurrentCoreId(KernelCore& kernel) {
return GetCurrentThread(kernel).GetCurrentCore();
}

View File

@@ -110,6 +110,8 @@ enum class StepState : u32 {
void SetCurrentThread(KernelCore& kernel, KThread* thread);
[[nodiscard]] KThread* GetCurrentThreadPointer(KernelCore& kernel);
[[nodiscard]] KThread& GetCurrentThread(KernelCore& kernel);
[[nodiscard]] KProcess* GetCurrentProcessPointer(KernelCore& kernel);
[[nodiscard]] KProcess& GetCurrentProcess(KernelCore& kernel);
[[nodiscard]] s32 GetCurrentCoreId(KernelCore& kernel);
class KThread final : public KAutoObjectWithSlabHeapAndContainer<KThread, KWorkerTask>,

View File

@@ -16,7 +16,7 @@ KTransferMemory::~KTransferMemory() = default;
Result KTransferMemory::Initialize(VAddr address_, std::size_t size_,
Svc::MemoryPermission owner_perm_) {
// Set members.
owner = kernel.CurrentProcess();
owner = GetCurrentProcessPointer(kernel);
// TODO(bunnei): Lock for transfer memory

View File

@@ -29,6 +29,7 @@
#include "core/hle/kernel/k_hardware_timer.h"
#include "core/hle/kernel/k_memory_layout.h"
#include "core/hle/kernel/k_memory_manager.h"
#include "core/hle/kernel/k_object_name.h"
#include "core/hle/kernel/k_page_buffer.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_resource_limit.h"
@@ -84,6 +85,7 @@ struct KernelCore::Impl {
InitializeShutdownThreads();
InitializePhysicalCores();
InitializePreemption(kernel);
InitializeGlobalData(kernel);
// Initialize the Dynamic Slab Heaps.
{
@@ -102,13 +104,13 @@ struct KernelCore::Impl {
void InitializeCores() {
for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) {
cores[core_id]->Initialize((*current_process).Is64BitProcess());
system.Memory().SetCurrentPageTable(*current_process, core_id);
cores[core_id]->Initialize((*application_process).Is64BitProcess());
system.Memory().SetCurrentPageTable(*application_process, core_id);
}
}
void CloseCurrentProcess() {
KProcess* old_process = current_process.exchange(nullptr);
void CloseApplicationProcess() {
KProcess* old_process = application_process.exchange(nullptr);
if (old_process == nullptr) {
return;
}
@@ -182,7 +184,7 @@ struct KernelCore::Impl {
}
}
CloseCurrentProcess();
CloseApplicationProcess();
// Track kernel objects that were not freed on shutdown
{
@@ -194,6 +196,8 @@ struct KernelCore::Impl {
}
}
object_name_global_data.reset();
// Ensure that the object list container is finalized and properly shutdown.
global_object_list_container->Finalize();
global_object_list_container.reset();
@@ -363,27 +367,29 @@ struct KernelCore::Impl {
}
}
void MakeCurrentProcess(KProcess* process) {
current_process = process;
void InitializeGlobalData(KernelCore& kernel) {
object_name_global_data = std::make_unique<KObjectNameGlobalData>(kernel);
}
static inline thread_local u32 host_thread_id = UINT32_MAX;
void MakeApplicationProcess(KProcess* process) {
application_process = process;
}
/// Gets the host thread ID for the caller, allocating a new one if this is the first time
u32 GetHostThreadId(std::size_t core_id) {
if (host_thread_id == UINT32_MAX) {
// The first four slots are reserved for CPU core threads
ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
host_thread_id = static_cast<u32>(core_id);
}
static inline thread_local u8 host_thread_id = UINT8_MAX;
/// Sets the host thread ID for the caller.
u32 SetHostThreadId(std::size_t core_id) {
// This should only be called during core init.
ASSERT(host_thread_id == UINT8_MAX);
// The first four slots are reserved for CPU core threads
ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
host_thread_id = static_cast<u8>(core_id);
return host_thread_id;
}
/// Gets the host thread ID for the caller, allocating a new one if this is the first time
u32 GetHostThreadId() {
if (host_thread_id == UINT32_MAX) {
host_thread_id = next_host_thread_id++;
}
/// Gets the host thread ID for the caller
u32 GetHostThreadId() const {
return host_thread_id;
}
@@ -391,23 +397,19 @@ struct KernelCore::Impl {
KThread* GetHostDummyThread(KThread* existing_thread) {
auto initialize = [this](KThread* thread) {
ASSERT(KThread::InitializeDummyThread(thread, nullptr).IsSuccess());
thread->SetName(fmt::format("DummyThread:{}", GetHostThreadId()));
thread->SetName(fmt::format("DummyThread:{}", next_host_thread_id++));
return thread;
};
thread_local KThread raw_thread{system.Kernel()};
thread_local KThread* thread = nullptr;
if (thread == nullptr) {
thread = (existing_thread == nullptr) ? initialize(&raw_thread) : existing_thread;
}
thread_local KThread* thread = existing_thread ? existing_thread : initialize(&raw_thread);
return thread;
}
/// Registers a CPU core thread by allocating a host thread ID for it
void RegisterCoreThread(std::size_t core_id) {
ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
const auto this_id = GetHostThreadId(core_id);
const auto this_id = SetHostThreadId(core_id);
if (!is_multicore) {
single_core_thread_id = this_id;
}
@@ -415,7 +417,6 @@ struct KernelCore::Impl {
/// Registers a new host thread by allocating a host thread ID for it
void RegisterHostThread(KThread* existing_thread) {
[[maybe_unused]] const auto this_id = GetHostThreadId();
[[maybe_unused]] const auto dummy_thread = GetHostDummyThread(existing_thread);
}
@@ -445,11 +446,9 @@ struct KernelCore::Impl {
static inline thread_local KThread* current_thread{nullptr};
KThread* GetCurrentEmuThread() {
const auto thread_id = GetCurrentHostThreadID();
if (thread_id >= Core::Hardware::NUM_CPU_CORES) {
return GetHostDummyThread(nullptr);
if (!current_thread) {
current_thread = GetHostDummyThread(nullptr);
}
return current_thread;
}
@@ -821,7 +820,7 @@ struct KernelCore::Impl {
// Lists all processes that exist in the current session.
std::vector<KProcess*> process_list;
std::atomic<KProcess*> current_process{};
std::atomic<KProcess*> application_process{};
std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context;
std::unique_ptr<Kernel::KHardwareTimer> hardware_timer;
@@ -838,6 +837,8 @@ struct KernelCore::Impl {
std::unique_ptr<KAutoObjectWithListContainer> global_object_list_container;
std::unique_ptr<KObjectNameGlobalData> object_name_global_data;
/// Map of named ports managed by the kernel, which can be retrieved using
/// the ConnectToPort SVC.
std::unordered_map<std::string, ServiceInterfaceFactory> service_interface_factory;
@@ -941,20 +942,20 @@ void KernelCore::AppendNewProcess(KProcess* process) {
impl->process_list.push_back(process);
}
void KernelCore::MakeCurrentProcess(KProcess* process) {
impl->MakeCurrentProcess(process);
void KernelCore::MakeApplicationProcess(KProcess* process) {
impl->MakeApplicationProcess(process);
}
KProcess* KernelCore::CurrentProcess() {
return impl->current_process;
KProcess* KernelCore::ApplicationProcess() {
return impl->application_process;
}
const KProcess* KernelCore::CurrentProcess() const {
return impl->current_process;
const KProcess* KernelCore::ApplicationProcess() const {
return impl->application_process;
}
void KernelCore::CloseCurrentProcess() {
impl->CloseCurrentProcess();
void KernelCore::CloseApplicationProcess() {
impl->CloseApplicationProcess();
}
const std::vector<KProcess*>& KernelCore::GetProcessList() const {
@@ -1002,7 +1003,7 @@ const Kernel::PhysicalCore& KernelCore::CurrentPhysicalCore() const {
}
Kernel::KScheduler* KernelCore::CurrentScheduler() {
u32 core_id = impl->GetCurrentHostThreadID();
const u32 core_id = impl->GetCurrentHostThreadID();
if (core_id >= Core::Hardware::NUM_CPU_CORES) {
// This is expected when called from not a guest thread
return {};
@@ -1138,6 +1139,10 @@ void KernelCore::SetCurrentEmuThread(KThread* thread) {
impl->SetCurrentEmuThread(thread);
}
KObjectNameGlobalData& KernelCore::ObjectNameGlobalData() {
return *impl->object_name_global_data;
}
KMemoryManager& KernelCore::MemoryManager() {
return *impl->memory_manager;
}
@@ -1146,6 +1151,14 @@ const KMemoryManager& KernelCore::MemoryManager() const {
return *impl->memory_manager;
}
KSystemResource& KernelCore::GetAppSystemResource() {
return *impl->app_system_resource;
}
const KSystemResource& KernelCore::GetAppSystemResource() const {
return *impl->app_system_resource;
}
KSystemResource& KernelCore::GetSystemSystemResource() {
return *impl->sys_system_resource;
}
@@ -1194,12 +1207,12 @@ const Kernel::KSharedMemory& KernelCore::GetHidBusSharedMem() const {
return *impl->hidbus_shared_mem;
}
void KernelCore::Suspend(bool suspended) {
void KernelCore::SuspendApplication(bool suspended) {
const bool should_suspend{exception_exited || suspended};
const auto activity = should_suspend ? ProcessActivity::Paused : ProcessActivity::Runnable;
//! This refers to the application process, not the current process.
KScopedAutoObject<KProcess> process = CurrentProcess();
// Get the application process.
KScopedAutoObject<KProcess> process = ApplicationProcess();
if (process.IsNull()) {
return;
}
@@ -1210,8 +1223,8 @@ void KernelCore::Suspend(bool suspended) {
// Wait for process execution to stop.
bool must_wait{should_suspend};
// KernelCore::Suspend must be called from locked context, or we
// could race another call to SetActivity, interfering with waiting.
// KernelCore::SuspendApplication must be called from locked context,
// or we could race another call to SetActivity, interfering with waiting.
while (must_wait) {
KScopedSchedulerLock sl{*this};
@@ -1245,9 +1258,9 @@ bool KernelCore::IsShuttingDown() const {
return impl->IsShuttingDown();
}
void KernelCore::ExceptionalExit() {
void KernelCore::ExceptionalExitApplication() {
exception_exited = true;
Suspend(true);
SuspendApplication(true);
}
void KernelCore::EnterSVCProfile() {

View File

@@ -44,6 +44,8 @@ class KHardwareTimer;
class KLinkedListNode;
class KMemoryLayout;
class KMemoryManager;
class KObjectName;
class KObjectNameGlobalData;
class KPageBuffer;
class KPageBufferSlabHeap;
class KPort;
@@ -131,17 +133,17 @@ public:
/// Adds the given shared pointer to an internal list of active processes.
void AppendNewProcess(KProcess* process);
/// Makes the given process the new current process.
void MakeCurrentProcess(KProcess* process);
/// Makes the given process the new application process.
void MakeApplicationProcess(KProcess* process);
/// Retrieves a pointer to the current process.
KProcess* CurrentProcess();
/// Retrieves a pointer to the application process.
KProcess* ApplicationProcess();
/// Retrieves a const pointer to the current process.
const KProcess* CurrentProcess() const;
/// Retrieves a const pointer to the application process.
const KProcess* ApplicationProcess() const;
/// Closes the current process.
void CloseCurrentProcess();
/// Closes the application process.
void CloseApplicationProcess();
/// Retrieves the list of processes.
const std::vector<KProcess*>& GetProcessList() const;
@@ -240,12 +242,21 @@ public:
/// Register the current thread as a non CPU core thread.
void RegisterHostThread(KThread* existing_thread = nullptr);
/// Gets global data for KObjectName.
KObjectNameGlobalData& ObjectNameGlobalData();
/// Gets the virtual memory manager for the kernel.
KMemoryManager& MemoryManager();
/// Gets the virtual memory manager for the kernel.
const KMemoryManager& MemoryManager() const;
/// Gets the application resource manager.
KSystemResource& GetAppSystemResource();
/// Gets the application resource manager.
const KSystemResource& GetAppSystemResource() const;
/// Gets the system resource manager.
KSystemResource& GetSystemSystemResource();
@@ -282,11 +293,11 @@ public:
/// Gets the shared memory object for HIDBus services.
const Kernel::KSharedMemory& GetHidBusSharedMem() const;
/// Suspend/unsuspend all processes.
void Suspend(bool suspend);
/// Suspend/unsuspend application process.
void SuspendApplication(bool suspend);
/// Exceptional exit all processes.
void ExceptionalExit();
/// Exceptional exit application process.
void ExceptionalExitApplication();
/// Notify emulated CPU cores to shut down.
void ShutdownCores();
@@ -366,6 +377,8 @@ public:
return slab_heap_container->page_buffer;
} else if constexpr (std::is_same_v<T, KThreadLocalPage>) {
return slab_heap_container->thread_local_page;
} else if constexpr (std::is_same_v<T, KObjectName>) {
return slab_heap_container->object_name;
} else if constexpr (std::is_same_v<T, KSessionRequest>) {
return slab_heap_container->session_request;
} else if constexpr (std::is_same_v<T, KSecureSystemResource>) {
@@ -437,6 +450,7 @@ private:
KSlabHeap<KDeviceAddressSpace> device_address_space;
KSlabHeap<KPageBuffer> page_buffer;
KSlabHeap<KThreadLocalPage> thread_local_page;
KSlabHeap<KObjectName> object_name;
KSlabHeap<KSessionRequest> session_request;
KSlabHeap<KSecureSystemResource> secure_system_resource;
KSlabHeap<KEventInfo> event_info;

File diff suppressed because it is too large Load Diff

View File

@@ -1,172 +1,536 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
// This file is automatically generated using svc_generator.py.
#include "common/common_types.h"
#include "core/hle/kernel/svc_types.h"
#include "core/hle/result.h"
#pragma once
namespace Core {
class System;
}
#include "common/common_types.h"
#include "core/hle/kernel/svc_types.h"
#include "core/hle/result.h"
namespace Kernel::Svc {
void Call(Core::System& system, u32 immediate);
Result SetHeapSize(Core::System& system, VAddr* out_address, u64 size);
Result SetMemoryPermission(Core::System& system, VAddr address, u64 size, MemoryPermission perm);
Result SetMemoryAttribute(Core::System& system, VAddr address, u64 size, u32 mask, u32 attr);
Result MapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size);
Result UnmapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size);
Result QueryMemory(Core::System& system, VAddr memory_info_address, VAddr page_info_address,
VAddr query_address);
// clang-format off
Result SetHeapSize(Core::System& system, uint64_t* out_address, uint64_t size);
Result SetMemoryPermission(Core::System& system, uint64_t address, uint64_t size, MemoryPermission perm);
Result SetMemoryAttribute(Core::System& system, uint64_t address, uint64_t size, uint32_t mask, uint32_t attr);
Result MapMemory(Core::System& system, uint64_t dst_address, uint64_t src_address, uint64_t size);
Result UnmapMemory(Core::System& system, uint64_t dst_address, uint64_t src_address, uint64_t size);
Result QueryMemory(Core::System& system, uint64_t out_memory_info, PageInfo* out_page_info, uint64_t address);
void ExitProcess(Core::System& system);
Result CreateThread(Core::System& system, Handle* out_handle, VAddr entry_point, u64 arg,
VAddr stack_bottom, u32 priority, s32 core_id);
Result CreateThread(Core::System& system, Handle* out_handle, uint64_t func, uint64_t arg, uint64_t stack_bottom, int32_t priority, int32_t core_id);
Result StartThread(Core::System& system, Handle thread_handle);
void ExitThread(Core::System& system);
void SleepThread(Core::System& system, s64 nanoseconds);
Result GetThreadPriority(Core::System& system, u32* out_priority, Handle handle);
Result SetThreadPriority(Core::System& system, Handle thread_handle, u32 priority);
Result GetThreadCoreMask(Core::System& system, Handle thread_handle, s32* out_core_id,
u64* out_affinity_mask);
Result SetThreadCoreMask(Core::System& system, Handle thread_handle, s32 core_id,
u64 affinity_mask);
u32 GetCurrentProcessorNumber(Core::System& system);
void SleepThread(Core::System& system, int64_t ns);
Result GetThreadPriority(Core::System& system, int32_t* out_priority, Handle thread_handle);
Result SetThreadPriority(Core::System& system, Handle thread_handle, int32_t priority);
Result GetThreadCoreMask(Core::System& system, int32_t* out_core_id, uint64_t* out_affinity_mask, Handle thread_handle);
Result SetThreadCoreMask(Core::System& system, Handle thread_handle, int32_t core_id, uint64_t affinity_mask);
int32_t GetCurrentProcessorNumber(Core::System& system);
Result SignalEvent(Core::System& system, Handle event_handle);
Result ClearEvent(Core::System& system, Handle event_handle);
Result MapSharedMemory(Core::System& system, Handle shmem_handle, VAddr address, u64 size,
MemoryPermission map_perm);
Result UnmapSharedMemory(Core::System& system, Handle shmem_handle, VAddr address, u64 size);
Result CreateTransferMemory(Core::System& system, Handle* out, VAddr address, u64 size,
MemoryPermission map_perm);
Result MapSharedMemory(Core::System& system, Handle shmem_handle, uint64_t address, uint64_t size, MemoryPermission map_perm);
Result UnmapSharedMemory(Core::System& system, Handle shmem_handle, uint64_t address, uint64_t size);
Result CreateTransferMemory(Core::System& system, Handle* out_handle, uint64_t address, uint64_t size, MemoryPermission map_perm);
Result CloseHandle(Core::System& system, Handle handle);
Result ResetSignal(Core::System& system, Handle handle);
Result WaitSynchronization(Core::System& system, s32* index, VAddr handles_address, s32 num_handles,
s64 nano_seconds);
Result WaitSynchronization(Core::System& system, int32_t* out_index, uint64_t handles, int32_t num_handles, int64_t timeout_ns);
Result CancelSynchronization(Core::System& system, Handle handle);
Result ArbitrateLock(Core::System& system, Handle thread_handle, VAddr address, u32 tag);
Result ArbitrateUnlock(Core::System& system, VAddr address);
Result WaitProcessWideKeyAtomic(Core::System& system, VAddr address, VAddr cv_key, u32 tag,
s64 timeout_ns);
void SignalProcessWideKey(Core::System& system, VAddr cv_key, s32 count);
u64 GetSystemTick(Core::System& system);
Result ConnectToNamedPort(Core::System& system, Handle* out, VAddr port_name_address);
Result SendSyncRequest(Core::System& system, Handle handle);
Result GetProcessId(Core::System& system, u64* out_process_id, Handle handle);
Result GetThreadId(Core::System& system, u64* out_thread_id, Handle thread_handle);
void Break(Core::System& system, u32 reason, u64 info1, u64 info2);
void OutputDebugString(Core::System& system, VAddr address, u64 len);
Result GetInfo(Core::System& system, u64* result, u64 info_id, Handle handle, u64 info_sub_id);
Result MapPhysicalMemory(Core::System& system, VAddr addr, u64 size);
Result UnmapPhysicalMemory(Core::System& system, VAddr addr, u64 size);
Result GetResourceLimitLimitValue(Core::System& system, u64* out_limit_value,
Handle resource_limit_handle, LimitableResource which);
Result GetResourceLimitCurrentValue(Core::System& system, u64* out_current_value,
Handle resource_limit_handle, LimitableResource which);
Result SetThreadActivity(Core::System& system, Handle thread_handle,
ThreadActivity thread_activity);
Result GetThreadContext(Core::System& system, VAddr out_context, Handle thread_handle);
Result WaitForAddress(Core::System& system, VAddr address, ArbitrationType arb_type, s32 value,
s64 timeout_ns);
Result SignalToAddress(Core::System& system, VAddr address, SignalType signal_type, s32 value,
s32 count);
Result ArbitrateLock(Core::System& system, Handle thread_handle, uint64_t address, uint32_t tag);
Result ArbitrateUnlock(Core::System& system, uint64_t address);
Result WaitProcessWideKeyAtomic(Core::System& system, uint64_t address, uint64_t cv_key, uint32_t tag, int64_t timeout_ns);
void SignalProcessWideKey(Core::System& system, uint64_t cv_key, int32_t count);
int64_t GetSystemTick(Core::System& system);
Result ConnectToNamedPort(Core::System& system, Handle* out_handle, uint64_t name);
Result SendSyncRequest(Core::System& system, Handle session_handle);
Result SendSyncRequestWithUserBuffer(Core::System& system, uint64_t message_buffer, uint64_t message_buffer_size, Handle session_handle);
Result SendAsyncRequestWithUserBuffer(Core::System& system, Handle* out_event_handle, uint64_t message_buffer, uint64_t message_buffer_size, Handle session_handle);
Result GetProcessId(Core::System& system, uint64_t* out_process_id, Handle process_handle);
Result GetThreadId(Core::System& system, uint64_t* out_thread_id, Handle thread_handle);
void Break(Core::System& system, BreakReason break_reason, uint64_t arg, uint64_t size);
Result OutputDebugString(Core::System& system, uint64_t debug_str, uint64_t len);
void ReturnFromException(Core::System& system, Result result);
Result GetInfo(Core::System& system, uint64_t* out, InfoType info_type, Handle handle, uint64_t info_subtype);
void FlushEntireDataCache(Core::System& system);
Result FlushDataCache(Core::System& system, uint64_t address, uint64_t size);
Result MapPhysicalMemory(Core::System& system, uint64_t address, uint64_t size);
Result UnmapPhysicalMemory(Core::System& system, uint64_t address, uint64_t size);
Result GetDebugFutureThreadInfo(Core::System& system, lp64::LastThreadContext* out_context, uint64_t* out_thread_id, Handle debug_handle, int64_t ns);
Result GetLastThreadInfo(Core::System& system, lp64::LastThreadContext* out_context, uint64_t* out_tls_address, uint32_t* out_flags);
Result GetResourceLimitLimitValue(Core::System& system, int64_t* out_limit_value, Handle resource_limit_handle, LimitableResource which);
Result GetResourceLimitCurrentValue(Core::System& system, int64_t* out_current_value, Handle resource_limit_handle, LimitableResource which);
Result SetThreadActivity(Core::System& system, Handle thread_handle, ThreadActivity thread_activity);
Result GetThreadContext3(Core::System& system, uint64_t out_context, Handle thread_handle);
Result WaitForAddress(Core::System& system, uint64_t address, ArbitrationType arb_type, int32_t value, int64_t timeout_ns);
Result SignalToAddress(Core::System& system, uint64_t address, SignalType signal_type, int32_t value, int32_t count);
void SynchronizePreemptionState(Core::System& system);
void KernelDebug(Core::System& system, u32 kernel_debug_type, u64 param1, u64 param2, u64 param3);
void ChangeKernelTraceState(Core::System& system, u32 trace_state);
Result CreateSession(Core::System& system, Handle* out_server, Handle* out_client, u32 is_light,
u64 name);
Result ReplyAndReceive(Core::System& system, s32* out_index, Handle* handles, s32 num_handles,
Handle reply_target, s64 timeout_ns);
Result CreateEvent(Core::System& system, Handle* out_write, Handle* out_read);
Result CreateCodeMemory(Core::System& system, Handle* out, VAddr address, size_t size);
Result ControlCodeMemory(Core::System& system, Handle code_memory_handle, u32 operation,
VAddr address, size_t size, MemoryPermission perm);
Result GetProcessList(Core::System& system, u32* out_num_processes, VAddr out_process_ids,
u32 out_process_ids_size);
Result GetThreadList(Core::System& system, u32* out_num_threads, VAddr out_thread_ids,
u32 out_thread_ids_size, Handle debug_handle);
Result SetProcessMemoryPermission(Core::System& system, Handle process_handle, VAddr address,
u64 size, MemoryPermission perm);
Result MapProcessMemory(Core::System& system, VAddr dst_address, Handle process_handle,
VAddr src_address, u64 size);
Result UnmapProcessMemory(Core::System& system, VAddr dst_address, Handle process_handle,
VAddr src_address, u64 size);
Result QueryProcessMemory(Core::System& system, VAddr memory_info_address, VAddr page_info_address,
Handle process_handle, VAddr address);
Result MapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst_address,
u64 src_address, u64 size);
Result UnmapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst_address,
u64 src_address, u64 size);
Result GetProcessInfo(Core::System& system, u64* out, Handle process_handle, u32 type);
Result GetResourceLimitPeakValue(Core::System& system, int64_t* out_peak_value, Handle resource_limit_handle, LimitableResource which);
Result CreateIoPool(Core::System& system, Handle* out_handle, IoPoolType which);
Result CreateIoRegion(Core::System& system, Handle* out_handle, Handle io_pool, uint64_t physical_address, uint64_t size, MemoryMapping mapping, MemoryPermission perm);
void KernelDebug(Core::System& system, KernelDebugType kern_debug_type, uint64_t arg0, uint64_t arg1, uint64_t arg2);
void ChangeKernelTraceState(Core::System& system, KernelTraceState kern_trace_state);
Result CreateSession(Core::System& system, Handle* out_server_session_handle, Handle* out_client_session_handle, bool is_light, uint64_t name);
Result AcceptSession(Core::System& system, Handle* out_handle, Handle port);
Result ReplyAndReceive(Core::System& system, int32_t* out_index, uint64_t handles, int32_t num_handles, Handle reply_target, int64_t timeout_ns);
Result ReplyAndReceiveWithUserBuffer(Core::System& system, int32_t* out_index, uint64_t message_buffer, uint64_t message_buffer_size, uint64_t handles, int32_t num_handles, Handle reply_target, int64_t timeout_ns);
Result CreateEvent(Core::System& system, Handle* out_write_handle, Handle* out_read_handle);
Result MapIoRegion(Core::System& system, Handle io_region, uint64_t address, uint64_t size, MemoryPermission perm);
Result UnmapIoRegion(Core::System& system, Handle io_region, uint64_t address, uint64_t size);
Result MapPhysicalMemoryUnsafe(Core::System& system, uint64_t address, uint64_t size);
Result UnmapPhysicalMemoryUnsafe(Core::System& system, uint64_t address, uint64_t size);
Result SetUnsafeLimit(Core::System& system, uint64_t limit);
Result CreateCodeMemory(Core::System& system, Handle* out_handle, uint64_t address, uint64_t size);
Result ControlCodeMemory(Core::System& system, Handle code_memory_handle, CodeMemoryOperation operation, uint64_t address, uint64_t size, MemoryPermission perm);
void SleepSystem(Core::System& system);
Result ReadWriteRegister(Core::System& system, uint32_t* out_value, uint64_t address, uint32_t mask, uint32_t value);
Result SetProcessActivity(Core::System& system, Handle process_handle, ProcessActivity process_activity);
Result CreateSharedMemory(Core::System& system, Handle* out_handle, uint64_t size, MemoryPermission owner_perm, MemoryPermission remote_perm);
Result MapTransferMemory(Core::System& system, Handle trmem_handle, uint64_t address, uint64_t size, MemoryPermission owner_perm);
Result UnmapTransferMemory(Core::System& system, Handle trmem_handle, uint64_t address, uint64_t size);
Result CreateInterruptEvent(Core::System& system, Handle* out_read_handle, int32_t interrupt_id, InterruptType interrupt_type);
Result QueryPhysicalAddress(Core::System& system, lp64::PhysicalMemoryInfo* out_info, uint64_t address);
Result QueryIoMapping(Core::System& system, uint64_t* out_address, uint64_t* out_size, uint64_t physical_address, uint64_t size);
Result CreateDeviceAddressSpace(Core::System& system, Handle* out_handle, uint64_t das_address, uint64_t das_size);
Result AttachDeviceAddressSpace(Core::System& system, DeviceName device_name, Handle das_handle);
Result DetachDeviceAddressSpace(Core::System& system, DeviceName device_name, Handle das_handle);
Result MapDeviceAddressSpaceByForce(Core::System& system, Handle das_handle, Handle process_handle, uint64_t process_address, uint64_t size, uint64_t device_address, uint32_t option);
Result MapDeviceAddressSpaceAligned(Core::System& system, Handle das_handle, Handle process_handle, uint64_t process_address, uint64_t size, uint64_t device_address, uint32_t option);
Result UnmapDeviceAddressSpace(Core::System& system, Handle das_handle, Handle process_handle, uint64_t process_address, uint64_t size, uint64_t device_address);
Result InvalidateProcessDataCache(Core::System& system, Handle process_handle, uint64_t address, uint64_t size);
Result StoreProcessDataCache(Core::System& system, Handle process_handle, uint64_t address, uint64_t size);
Result FlushProcessDataCache(Core::System& system, Handle process_handle, uint64_t address, uint64_t size);
Result DebugActiveProcess(Core::System& system, Handle* out_handle, uint64_t process_id);
Result BreakDebugProcess(Core::System& system, Handle debug_handle);
Result TerminateDebugProcess(Core::System& system, Handle debug_handle);
Result GetDebugEvent(Core::System& system, uint64_t out_info, Handle debug_handle);
Result ContinueDebugEvent(Core::System& system, Handle debug_handle, uint32_t flags, uint64_t thread_ids, int32_t num_thread_ids);
Result GetProcessList(Core::System& system, int32_t* out_num_processes, uint64_t out_process_ids, int32_t max_out_count);
Result GetThreadList(Core::System& system, int32_t* out_num_threads, uint64_t out_thread_ids, int32_t max_out_count, Handle debug_handle);
Result GetDebugThreadContext(Core::System& system, uint64_t out_context, Handle debug_handle, uint64_t thread_id, uint32_t context_flags);
Result SetDebugThreadContext(Core::System& system, Handle debug_handle, uint64_t thread_id, uint64_t context, uint32_t context_flags);
Result QueryDebugProcessMemory(Core::System& system, uint64_t out_memory_info, PageInfo* out_page_info, Handle process_handle, uint64_t address);
Result ReadDebugProcessMemory(Core::System& system, uint64_t buffer, Handle debug_handle, uint64_t address, uint64_t size);
Result WriteDebugProcessMemory(Core::System& system, Handle debug_handle, uint64_t buffer, uint64_t address, uint64_t size);
Result SetHardwareBreakPoint(Core::System& system, HardwareBreakPointRegisterName name, uint64_t flags, uint64_t value);
Result GetDebugThreadParam(Core::System& system, uint64_t* out_64, uint32_t* out_32, Handle debug_handle, uint64_t thread_id, DebugThreadParam param);
Result GetSystemInfo(Core::System& system, uint64_t* out, SystemInfoType info_type, Handle handle, uint64_t info_subtype);
Result CreatePort(Core::System& system, Handle* out_server_handle, Handle* out_client_handle, int32_t max_sessions, bool is_light, uint64_t name);
Result ManageNamedPort(Core::System& system, Handle* out_server_handle, uint64_t name, int32_t max_sessions);
Result ConnectToPort(Core::System& system, Handle* out_handle, Handle port);
Result SetProcessMemoryPermission(Core::System& system, Handle process_handle, uint64_t address, uint64_t size, MemoryPermission perm);
Result MapProcessMemory(Core::System& system, uint64_t dst_address, Handle process_handle, uint64_t src_address, uint64_t size);
Result UnmapProcessMemory(Core::System& system, uint64_t dst_address, Handle process_handle, uint64_t src_address, uint64_t size);
Result QueryProcessMemory(Core::System& system, uint64_t out_memory_info, PageInfo* out_page_info, Handle process_handle, uint64_t address);
Result MapProcessCodeMemory(Core::System& system, Handle process_handle, uint64_t dst_address, uint64_t src_address, uint64_t size);
Result UnmapProcessCodeMemory(Core::System& system, Handle process_handle, uint64_t dst_address, uint64_t src_address, uint64_t size);
Result CreateProcess(Core::System& system, Handle* out_handle, uint64_t parameters, uint64_t caps, int32_t num_caps);
Result StartProcess(Core::System& system, Handle process_handle, int32_t priority, int32_t core_id, uint64_t main_thread_stack_size);
Result TerminateProcess(Core::System& system, Handle process_handle);
Result GetProcessInfo(Core::System& system, int64_t* out_info, Handle process_handle, ProcessInfoType info_type);
Result CreateResourceLimit(Core::System& system, Handle* out_handle);
Result SetResourceLimitLimitValue(Core::System& system, Handle resource_limit_handle,
LimitableResource which, u64 limit_value);
Result SetResourceLimitLimitValue(Core::System& system, Handle resource_limit_handle, LimitableResource which, int64_t limit_value);
Result MapInsecureMemory(Core::System& system, uint64_t address, uint64_t size);
Result UnmapInsecureMemory(Core::System& system, uint64_t address, uint64_t size);
//
Result SetHeapSize64From32(Core::System& system, uint64_t* out_address, uint32_t size);
Result SetMemoryPermission64From32(Core::System& system, uint32_t address, uint32_t size, MemoryPermission perm);
Result SetMemoryAttribute64From32(Core::System& system, uint32_t address, uint32_t size, uint32_t mask, uint32_t attr);
Result MapMemory64From32(Core::System& system, uint32_t dst_address, uint32_t src_address, uint32_t size);
Result UnmapMemory64From32(Core::System& system, uint32_t dst_address, uint32_t src_address, uint32_t size);
Result QueryMemory64From32(Core::System& system, uint32_t out_memory_info, PageInfo* out_page_info, uint32_t address);
void ExitProcess64From32(Core::System& system);
Result CreateThread64From32(Core::System& system, Handle* out_handle, uint32_t func, uint32_t arg, uint32_t stack_bottom, int32_t priority, int32_t core_id);
Result StartThread64From32(Core::System& system, Handle thread_handle);
void ExitThread64From32(Core::System& system);
void SleepThread64From32(Core::System& system, int64_t ns);
Result GetThreadPriority64From32(Core::System& system, int32_t* out_priority, Handle thread_handle);
Result SetThreadPriority64From32(Core::System& system, Handle thread_handle, int32_t priority);
Result GetThreadCoreMask64From32(Core::System& system, int32_t* out_core_id, uint64_t* out_affinity_mask, Handle thread_handle);
Result SetThreadCoreMask64From32(Core::System& system, Handle thread_handle, int32_t core_id, uint64_t affinity_mask);
int32_t GetCurrentProcessorNumber64From32(Core::System& system);
Result SignalEvent64From32(Core::System& system, Handle event_handle);
Result ClearEvent64From32(Core::System& system, Handle event_handle);
Result MapSharedMemory64From32(Core::System& system, Handle shmem_handle, uint32_t address, uint32_t size, MemoryPermission map_perm);
Result UnmapSharedMemory64From32(Core::System& system, Handle shmem_handle, uint32_t address, uint32_t size);
Result CreateTransferMemory64From32(Core::System& system, Handle* out_handle, uint32_t address, uint32_t size, MemoryPermission map_perm);
Result CloseHandle64From32(Core::System& system, Handle handle);
Result ResetSignal64From32(Core::System& system, Handle handle);
Result WaitSynchronization64From32(Core::System& system, int32_t* out_index, uint32_t handles, int32_t num_handles, int64_t timeout_ns);
Result CancelSynchronization64From32(Core::System& system, Handle handle);
Result ArbitrateLock64From32(Core::System& system, Handle thread_handle, uint32_t address, uint32_t tag);
Result ArbitrateUnlock64From32(Core::System& system, uint32_t address);
Result WaitProcessWideKeyAtomic64From32(Core::System& system, uint32_t address, uint32_t cv_key, uint32_t tag, int64_t timeout_ns);
void SignalProcessWideKey64From32(Core::System& system, uint32_t cv_key, int32_t count);
int64_t GetSystemTick64From32(Core::System& system);
Result ConnectToNamedPort64From32(Core::System& system, Handle* out_handle, uint32_t name);
Result SendSyncRequest64From32(Core::System& system, Handle session_handle);
Result SendSyncRequestWithUserBuffer64From32(Core::System& system, uint32_t message_buffer, uint32_t message_buffer_size, Handle session_handle);
Result SendAsyncRequestWithUserBuffer64From32(Core::System& system, Handle* out_event_handle, uint32_t message_buffer, uint32_t message_buffer_size, Handle session_handle);
Result GetProcessId64From32(Core::System& system, uint64_t* out_process_id, Handle process_handle);
Result GetThreadId64From32(Core::System& system, uint64_t* out_thread_id, Handle thread_handle);
void Break64From32(Core::System& system, BreakReason break_reason, uint32_t arg, uint32_t size);
Result OutputDebugString64From32(Core::System& system, uint32_t debug_str, uint32_t len);
void ReturnFromException64From32(Core::System& system, Result result);
Result GetInfo64From32(Core::System& system, uint64_t* out, InfoType info_type, Handle handle, uint64_t info_subtype);
void FlushEntireDataCache64From32(Core::System& system);
Result FlushDataCache64From32(Core::System& system, uint32_t address, uint32_t size);
Result MapPhysicalMemory64From32(Core::System& system, uint32_t address, uint32_t size);
Result UnmapPhysicalMemory64From32(Core::System& system, uint32_t address, uint32_t size);
Result GetDebugFutureThreadInfo64From32(Core::System& system, ilp32::LastThreadContext* out_context, uint64_t* out_thread_id, Handle debug_handle, int64_t ns);
Result GetLastThreadInfo64From32(Core::System& system, ilp32::LastThreadContext* out_context, uint64_t* out_tls_address, uint32_t* out_flags);
Result GetResourceLimitLimitValue64From32(Core::System& system, int64_t* out_limit_value, Handle resource_limit_handle, LimitableResource which);
Result GetResourceLimitCurrentValue64From32(Core::System& system, int64_t* out_current_value, Handle resource_limit_handle, LimitableResource which);
Result SetThreadActivity64From32(Core::System& system, Handle thread_handle, ThreadActivity thread_activity);
Result GetThreadContext364From32(Core::System& system, uint32_t out_context, Handle thread_handle);
Result WaitForAddress64From32(Core::System& system, uint32_t address, ArbitrationType arb_type, int32_t value, int64_t timeout_ns);
Result SignalToAddress64From32(Core::System& system, uint32_t address, SignalType signal_type, int32_t value, int32_t count);
void SynchronizePreemptionState64From32(Core::System& system);
Result GetResourceLimitPeakValue64From32(Core::System& system, int64_t* out_peak_value, Handle resource_limit_handle, LimitableResource which);
Result CreateIoPool64From32(Core::System& system, Handle* out_handle, IoPoolType which);
Result CreateIoRegion64From32(Core::System& system, Handle* out_handle, Handle io_pool, uint64_t physical_address, uint32_t size, MemoryMapping mapping, MemoryPermission perm);
void KernelDebug64From32(Core::System& system, KernelDebugType kern_debug_type, uint64_t arg0, uint64_t arg1, uint64_t arg2);
void ChangeKernelTraceState64From32(Core::System& system, KernelTraceState kern_trace_state);
Result CreateSession64From32(Core::System& system, Handle* out_server_session_handle, Handle* out_client_session_handle, bool is_light, uint32_t name);
Result AcceptSession64From32(Core::System& system, Handle* out_handle, Handle port);
Result ReplyAndReceive64From32(Core::System& system, int32_t* out_index, uint32_t handles, int32_t num_handles, Handle reply_target, int64_t timeout_ns);
Result ReplyAndReceiveWithUserBuffer64From32(Core::System& system, int32_t* out_index, uint32_t message_buffer, uint32_t message_buffer_size, uint32_t handles, int32_t num_handles, Handle reply_target, int64_t timeout_ns);
Result CreateEvent64From32(Core::System& system, Handle* out_write_handle, Handle* out_read_handle);
Result MapIoRegion64From32(Core::System& system, Handle io_region, uint32_t address, uint32_t size, MemoryPermission perm);
Result UnmapIoRegion64From32(Core::System& system, Handle io_region, uint32_t address, uint32_t size);
Result MapPhysicalMemoryUnsafe64From32(Core::System& system, uint32_t address, uint32_t size);
Result UnmapPhysicalMemoryUnsafe64From32(Core::System& system, uint32_t address, uint32_t size);
Result SetUnsafeLimit64From32(Core::System& system, uint32_t limit);
Result CreateCodeMemory64From32(Core::System& system, Handle* out_handle, uint32_t address, uint32_t size);
Result ControlCodeMemory64From32(Core::System& system, Handle code_memory_handle, CodeMemoryOperation operation, uint64_t address, uint64_t size, MemoryPermission perm);
void SleepSystem64From32(Core::System& system);
Result ReadWriteRegister64From32(Core::System& system, uint32_t* out_value, uint64_t address, uint32_t mask, uint32_t value);
Result SetProcessActivity64From32(Core::System& system, Handle process_handle, ProcessActivity process_activity);
Result CreateSharedMemory64From32(Core::System& system, Handle* out_handle, uint32_t size, MemoryPermission owner_perm, MemoryPermission remote_perm);
Result MapTransferMemory64From32(Core::System& system, Handle trmem_handle, uint32_t address, uint32_t size, MemoryPermission owner_perm);
Result UnmapTransferMemory64From32(Core::System& system, Handle trmem_handle, uint32_t address, uint32_t size);
Result CreateInterruptEvent64From32(Core::System& system, Handle* out_read_handle, int32_t interrupt_id, InterruptType interrupt_type);
Result QueryPhysicalAddress64From32(Core::System& system, ilp32::PhysicalMemoryInfo* out_info, uint32_t address);
Result QueryIoMapping64From32(Core::System& system, uint64_t* out_address, uint64_t* out_size, uint64_t physical_address, uint32_t size);
Result CreateDeviceAddressSpace64From32(Core::System& system, Handle* out_handle, uint64_t das_address, uint64_t das_size);
Result AttachDeviceAddressSpace64From32(Core::System& system, DeviceName device_name, Handle das_handle);
Result DetachDeviceAddressSpace64From32(Core::System& system, DeviceName device_name, Handle das_handle);
Result MapDeviceAddressSpaceByForce64From32(Core::System& system, Handle das_handle, Handle process_handle, uint64_t process_address, uint32_t size, uint64_t device_address, uint32_t option);
Result MapDeviceAddressSpaceAligned64From32(Core::System& system, Handle das_handle, Handle process_handle, uint64_t process_address, uint32_t size, uint64_t device_address, uint32_t option);
Result UnmapDeviceAddressSpace64From32(Core::System& system, Handle das_handle, Handle process_handle, uint64_t process_address, uint32_t size, uint64_t device_address);
Result InvalidateProcessDataCache64From32(Core::System& system, Handle process_handle, uint64_t address, uint64_t size);
Result StoreProcessDataCache64From32(Core::System& system, Handle process_handle, uint64_t address, uint64_t size);
Result FlushProcessDataCache64From32(Core::System& system, Handle process_handle, uint64_t address, uint64_t size);
Result DebugActiveProcess64From32(Core::System& system, Handle* out_handle, uint64_t process_id);
Result BreakDebugProcess64From32(Core::System& system, Handle debug_handle);
Result TerminateDebugProcess64From32(Core::System& system, Handle debug_handle);
Result GetDebugEvent64From32(Core::System& system, uint32_t out_info, Handle debug_handle);
Result ContinueDebugEvent64From32(Core::System& system, Handle debug_handle, uint32_t flags, uint32_t thread_ids, int32_t num_thread_ids);
Result GetProcessList64From32(Core::System& system, int32_t* out_num_processes, uint32_t out_process_ids, int32_t max_out_count);
Result GetThreadList64From32(Core::System& system, int32_t* out_num_threads, uint32_t out_thread_ids, int32_t max_out_count, Handle debug_handle);
Result GetDebugThreadContext64From32(Core::System& system, uint32_t out_context, Handle debug_handle, uint64_t thread_id, uint32_t context_flags);
Result SetDebugThreadContext64From32(Core::System& system, Handle debug_handle, uint64_t thread_id, uint32_t context, uint32_t context_flags);
Result QueryDebugProcessMemory64From32(Core::System& system, uint32_t out_memory_info, PageInfo* out_page_info, Handle process_handle, uint32_t address);
Result ReadDebugProcessMemory64From32(Core::System& system, uint32_t buffer, Handle debug_handle, uint32_t address, uint32_t size);
Result WriteDebugProcessMemory64From32(Core::System& system, Handle debug_handle, uint32_t buffer, uint32_t address, uint32_t size);
Result SetHardwareBreakPoint64From32(Core::System& system, HardwareBreakPointRegisterName name, uint64_t flags, uint64_t value);
Result GetDebugThreadParam64From32(Core::System& system, uint64_t* out_64, uint32_t* out_32, Handle debug_handle, uint64_t thread_id, DebugThreadParam param);
Result GetSystemInfo64From32(Core::System& system, uint64_t* out, SystemInfoType info_type, Handle handle, uint64_t info_subtype);
Result CreatePort64From32(Core::System& system, Handle* out_server_handle, Handle* out_client_handle, int32_t max_sessions, bool is_light, uint32_t name);
Result ManageNamedPort64From32(Core::System& system, Handle* out_server_handle, uint32_t name, int32_t max_sessions);
Result ConnectToPort64From32(Core::System& system, Handle* out_handle, Handle port);
Result SetProcessMemoryPermission64From32(Core::System& system, Handle process_handle, uint64_t address, uint64_t size, MemoryPermission perm);
Result MapProcessMemory64From32(Core::System& system, uint32_t dst_address, Handle process_handle, uint64_t src_address, uint32_t size);
Result UnmapProcessMemory64From32(Core::System& system, uint32_t dst_address, Handle process_handle, uint64_t src_address, uint32_t size);
Result QueryProcessMemory64From32(Core::System& system, uint32_t out_memory_info, PageInfo* out_page_info, Handle process_handle, uint64_t address);
Result MapProcessCodeMemory64From32(Core::System& system, Handle process_handle, uint64_t dst_address, uint64_t src_address, uint64_t size);
Result UnmapProcessCodeMemory64From32(Core::System& system, Handle process_handle, uint64_t dst_address, uint64_t src_address, uint64_t size);
Result CreateProcess64From32(Core::System& system, Handle* out_handle, uint32_t parameters, uint32_t caps, int32_t num_caps);
Result StartProcess64From32(Core::System& system, Handle process_handle, int32_t priority, int32_t core_id, uint64_t main_thread_stack_size);
Result TerminateProcess64From32(Core::System& system, Handle process_handle);
Result GetProcessInfo64From32(Core::System& system, int64_t* out_info, Handle process_handle, ProcessInfoType info_type);
Result CreateResourceLimit64From32(Core::System& system, Handle* out_handle);
Result SetResourceLimitLimitValue64From32(Core::System& system, Handle resource_limit_handle, LimitableResource which, int64_t limit_value);
Result MapInsecureMemory64From32(Core::System& system, uint32_t address, uint32_t size);
Result UnmapInsecureMemory64From32(Core::System& system, uint32_t address, uint32_t size);
Result SetHeapSize32(Core::System& system, u32* heap_addr, u32 heap_size);
Result SetMemoryAttribute32(Core::System& system, u32 address, u32 size, u32 mask, u32 attr);
Result MapMemory32(Core::System& system, u32 dst_addr, u32 src_addr, u32 size);
Result UnmapMemory32(Core::System& system, u32 dst_addr, u32 src_addr, u32 size);
Result QueryMemory32(Core::System& system, u32 memory_info_address, u32 page_info_address,
u32 query_address);
void ExitProcess32(Core::System& system);
Result CreateThread32(Core::System& system, Handle* out_handle, u32 priority, u32 entry_point,
u32 arg, u32 stack_top, s32 processor_id);
Result StartThread32(Core::System& system, Handle thread_handle);
void ExitThread32(Core::System& system);
void SleepThread32(Core::System& system, u32 nanoseconds_low, u32 nanoseconds_high);
Result GetThreadPriority32(Core::System& system, u32* out_priority, Handle handle);
Result SetThreadPriority32(Core::System& system, Handle thread_handle, u32 priority);
Result GetThreadCoreMask32(Core::System& system, Handle thread_handle, s32* out_core_id,
u32* out_affinity_mask_low, u32* out_affinity_mask_high);
Result SetThreadCoreMask32(Core::System& system, Handle thread_handle, s32 core_id,
u32 affinity_mask_low, u32 affinity_mask_high);
u32 GetCurrentProcessorNumber32(Core::System& system);
Result SignalEvent32(Core::System& system, Handle event_handle);
Result ClearEvent32(Core::System& system, Handle event_handle);
Result MapSharedMemory32(Core::System& system, Handle shmem_handle, u32 address, u32 size,
MemoryPermission map_perm);
Result UnmapSharedMemory32(Core::System& system, Handle shmem_handle, u32 address, u32 size);
Result CreateTransferMemory32(Core::System& system, Handle* out, u32 address, u32 size,
MemoryPermission map_perm);
Result CloseHandle32(Core::System& system, Handle handle);
Result ResetSignal32(Core::System& system, Handle handle);
Result WaitSynchronization32(Core::System& system, u32 timeout_low, u32 handles_address,
s32 num_handles, u32 timeout_high, s32* index);
Result CancelSynchronization32(Core::System& system, Handle handle);
Result ArbitrateLock32(Core::System& system, Handle thread_handle, u32 address, u32 tag);
Result ArbitrateUnlock32(Core::System& system, u32 address);
Result WaitProcessWideKeyAtomic32(Core::System& system, u32 address, u32 cv_key, u32 tag,
u32 timeout_ns_low, u32 timeout_ns_high);
void SignalProcessWideKey32(Core::System& system, u32 cv_key, s32 count);
void GetSystemTick32(Core::System& system, u32* time_low, u32* time_high);
Result ConnectToNamedPort32(Core::System& system, Handle* out_handle, u32 port_name_address);
Result SendSyncRequest32(Core::System& system, Handle handle);
Result GetProcessId32(Core::System& system, u32* out_process_id_low, u32* out_process_id_high,
Handle handle);
Result GetThreadId32(Core::System& system, u32* out_thread_id_low, u32* out_thread_id_high,
Handle thread_handle);
void Break32(Core::System& system, u32 reason, u32 info1, u32 info2);
void OutputDebugString32(Core::System& system, u32 address, u32 len);
Result GetInfo32(Core::System& system, u32* result_low, u32* result_high, u32 sub_id_low,
u32 info_id, u32 handle, u32 sub_id_high);
Result MapPhysicalMemory32(Core::System& system, u32 addr, u32 size);
Result UnmapPhysicalMemory32(Core::System& system, u32 addr, u32 size);
Result SetThreadActivity32(Core::System& system, Handle thread_handle,
ThreadActivity thread_activity);
Result GetThreadContext32(Core::System& system, u32 out_context, Handle thread_handle);
Result WaitForAddress32(Core::System& system, u32 address, ArbitrationType arb_type, s32 value,
u32 timeout_ns_low, u32 timeout_ns_high);
Result SignalToAddress32(Core::System& system, u32 address, SignalType signal_type, s32 value,
s32 count);
Result CreateEvent32(Core::System& system, Handle* out_write, Handle* out_read);
Result CreateCodeMemory32(Core::System& system, Handle* out, u32 address, u32 size);
Result ControlCodeMemory32(Core::System& system, Handle code_memory_handle, u32 operation,
u64 address, u64 size, MemoryPermission perm);
Result FlushProcessDataCache32(Core::System& system, Handle process_handle, u64 address, u64 size);
Result SetHeapSize64(Core::System& system, uint64_t* out_address, uint64_t size);
Result SetMemoryPermission64(Core::System& system, uint64_t address, uint64_t size, MemoryPermission perm);
Result SetMemoryAttribute64(Core::System& system, uint64_t address, uint64_t size, uint32_t mask, uint32_t attr);
Result MapMemory64(Core::System& system, uint64_t dst_address, uint64_t src_address, uint64_t size);
Result UnmapMemory64(Core::System& system, uint64_t dst_address, uint64_t src_address, uint64_t size);
Result QueryMemory64(Core::System& system, uint64_t out_memory_info, PageInfo* out_page_info, uint64_t address);
void ExitProcess64(Core::System& system);
Result CreateThread64(Core::System& system, Handle* out_handle, uint64_t func, uint64_t arg, uint64_t stack_bottom, int32_t priority, int32_t core_id);
Result StartThread64(Core::System& system, Handle thread_handle);
void ExitThread64(Core::System& system);
void SleepThread64(Core::System& system, int64_t ns);
Result GetThreadPriority64(Core::System& system, int32_t* out_priority, Handle thread_handle);
Result SetThreadPriority64(Core::System& system, Handle thread_handle, int32_t priority);
Result GetThreadCoreMask64(Core::System& system, int32_t* out_core_id, uint64_t* out_affinity_mask, Handle thread_handle);
Result SetThreadCoreMask64(Core::System& system, Handle thread_handle, int32_t core_id, uint64_t affinity_mask);
int32_t GetCurrentProcessorNumber64(Core::System& system);
Result SignalEvent64(Core::System& system, Handle event_handle);
Result ClearEvent64(Core::System& system, Handle event_handle);
Result MapSharedMemory64(Core::System& system, Handle shmem_handle, uint64_t address, uint64_t size, MemoryPermission map_perm);
Result UnmapSharedMemory64(Core::System& system, Handle shmem_handle, uint64_t address, uint64_t size);
Result CreateTransferMemory64(Core::System& system, Handle* out_handle, uint64_t address, uint64_t size, MemoryPermission map_perm);
Result CloseHandle64(Core::System& system, Handle handle);
Result ResetSignal64(Core::System& system, Handle handle);
Result WaitSynchronization64(Core::System& system, int32_t* out_index, uint64_t handles, int32_t num_handles, int64_t timeout_ns);
Result CancelSynchronization64(Core::System& system, Handle handle);
Result ArbitrateLock64(Core::System& system, Handle thread_handle, uint64_t address, uint32_t tag);
Result ArbitrateUnlock64(Core::System& system, uint64_t address);
Result WaitProcessWideKeyAtomic64(Core::System& system, uint64_t address, uint64_t cv_key, uint32_t tag, int64_t timeout_ns);
void SignalProcessWideKey64(Core::System& system, uint64_t cv_key, int32_t count);
int64_t GetSystemTick64(Core::System& system);
Result ConnectToNamedPort64(Core::System& system, Handle* out_handle, uint64_t name);
Result SendSyncRequest64(Core::System& system, Handle session_handle);
Result SendSyncRequestWithUserBuffer64(Core::System& system, uint64_t message_buffer, uint64_t message_buffer_size, Handle session_handle);
Result SendAsyncRequestWithUserBuffer64(Core::System& system, Handle* out_event_handle, uint64_t message_buffer, uint64_t message_buffer_size, Handle session_handle);
Result GetProcessId64(Core::System& system, uint64_t* out_process_id, Handle process_handle);
Result GetThreadId64(Core::System& system, uint64_t* out_thread_id, Handle thread_handle);
void Break64(Core::System& system, BreakReason break_reason, uint64_t arg, uint64_t size);
Result OutputDebugString64(Core::System& system, uint64_t debug_str, uint64_t len);
void ReturnFromException64(Core::System& system, Result result);
Result GetInfo64(Core::System& system, uint64_t* out, InfoType info_type, Handle handle, uint64_t info_subtype);
void FlushEntireDataCache64(Core::System& system);
Result FlushDataCache64(Core::System& system, uint64_t address, uint64_t size);
Result MapPhysicalMemory64(Core::System& system, uint64_t address, uint64_t size);
Result UnmapPhysicalMemory64(Core::System& system, uint64_t address, uint64_t size);
Result GetDebugFutureThreadInfo64(Core::System& system, lp64::LastThreadContext* out_context, uint64_t* out_thread_id, Handle debug_handle, int64_t ns);
Result GetLastThreadInfo64(Core::System& system, lp64::LastThreadContext* out_context, uint64_t* out_tls_address, uint32_t* out_flags);
Result GetResourceLimitLimitValue64(Core::System& system, int64_t* out_limit_value, Handle resource_limit_handle, LimitableResource which);
Result GetResourceLimitCurrentValue64(Core::System& system, int64_t* out_current_value, Handle resource_limit_handle, LimitableResource which);
Result SetThreadActivity64(Core::System& system, Handle thread_handle, ThreadActivity thread_activity);
Result GetThreadContext364(Core::System& system, uint64_t out_context, Handle thread_handle);
Result WaitForAddress64(Core::System& system, uint64_t address, ArbitrationType arb_type, int32_t value, int64_t timeout_ns);
Result SignalToAddress64(Core::System& system, uint64_t address, SignalType signal_type, int32_t value, int32_t count);
void SynchronizePreemptionState64(Core::System& system);
Result GetResourceLimitPeakValue64(Core::System& system, int64_t* out_peak_value, Handle resource_limit_handle, LimitableResource which);
Result CreateIoPool64(Core::System& system, Handle* out_handle, IoPoolType which);
Result CreateIoRegion64(Core::System& system, Handle* out_handle, Handle io_pool, uint64_t physical_address, uint64_t size, MemoryMapping mapping, MemoryPermission perm);
void KernelDebug64(Core::System& system, KernelDebugType kern_debug_type, uint64_t arg0, uint64_t arg1, uint64_t arg2);
void ChangeKernelTraceState64(Core::System& system, KernelTraceState kern_trace_state);
Result CreateSession64(Core::System& system, Handle* out_server_session_handle, Handle* out_client_session_handle, bool is_light, uint64_t name);
Result AcceptSession64(Core::System& system, Handle* out_handle, Handle port);
Result ReplyAndReceive64(Core::System& system, int32_t* out_index, uint64_t handles, int32_t num_handles, Handle reply_target, int64_t timeout_ns);
Result ReplyAndReceiveWithUserBuffer64(Core::System& system, int32_t* out_index, uint64_t message_buffer, uint64_t message_buffer_size, uint64_t handles, int32_t num_handles, Handle reply_target, int64_t timeout_ns);
Result CreateEvent64(Core::System& system, Handle* out_write_handle, Handle* out_read_handle);
Result MapIoRegion64(Core::System& system, Handle io_region, uint64_t address, uint64_t size, MemoryPermission perm);
Result UnmapIoRegion64(Core::System& system, Handle io_region, uint64_t address, uint64_t size);
Result MapPhysicalMemoryUnsafe64(Core::System& system, uint64_t address, uint64_t size);
Result UnmapPhysicalMemoryUnsafe64(Core::System& system, uint64_t address, uint64_t size);
Result SetUnsafeLimit64(Core::System& system, uint64_t limit);
Result CreateCodeMemory64(Core::System& system, Handle* out_handle, uint64_t address, uint64_t size);
Result ControlCodeMemory64(Core::System& system, Handle code_memory_handle, CodeMemoryOperation operation, uint64_t address, uint64_t size, MemoryPermission perm);
void SleepSystem64(Core::System& system);
Result ReadWriteRegister64(Core::System& system, uint32_t* out_value, uint64_t address, uint32_t mask, uint32_t value);
Result SetProcessActivity64(Core::System& system, Handle process_handle, ProcessActivity process_activity);
Result CreateSharedMemory64(Core::System& system, Handle* out_handle, uint64_t size, MemoryPermission owner_perm, MemoryPermission remote_perm);
Result MapTransferMemory64(Core::System& system, Handle trmem_handle, uint64_t address, uint64_t size, MemoryPermission owner_perm);
Result UnmapTransferMemory64(Core::System& system, Handle trmem_handle, uint64_t address, uint64_t size);
Result CreateInterruptEvent64(Core::System& system, Handle* out_read_handle, int32_t interrupt_id, InterruptType interrupt_type);
Result QueryPhysicalAddress64(Core::System& system, lp64::PhysicalMemoryInfo* out_info, uint64_t address);
Result QueryIoMapping64(Core::System& system, uint64_t* out_address, uint64_t* out_size, uint64_t physical_address, uint64_t size);
Result CreateDeviceAddressSpace64(Core::System& system, Handle* out_handle, uint64_t das_address, uint64_t das_size);
Result AttachDeviceAddressSpace64(Core::System& system, DeviceName device_name, Handle das_handle);
Result DetachDeviceAddressSpace64(Core::System& system, DeviceName device_name, Handle das_handle);
Result MapDeviceAddressSpaceByForce64(Core::System& system, Handle das_handle, Handle process_handle, uint64_t process_address, uint64_t size, uint64_t device_address, uint32_t option);
Result MapDeviceAddressSpaceAligned64(Core::System& system, Handle das_handle, Handle process_handle, uint64_t process_address, uint64_t size, uint64_t device_address, uint32_t option);
Result UnmapDeviceAddressSpace64(Core::System& system, Handle das_handle, Handle process_handle, uint64_t process_address, uint64_t size, uint64_t device_address);
Result InvalidateProcessDataCache64(Core::System& system, Handle process_handle, uint64_t address, uint64_t size);
Result StoreProcessDataCache64(Core::System& system, Handle process_handle, uint64_t address, uint64_t size);
Result FlushProcessDataCache64(Core::System& system, Handle process_handle, uint64_t address, uint64_t size);
Result DebugActiveProcess64(Core::System& system, Handle* out_handle, uint64_t process_id);
Result BreakDebugProcess64(Core::System& system, Handle debug_handle);
Result TerminateDebugProcess64(Core::System& system, Handle debug_handle);
Result GetDebugEvent64(Core::System& system, uint64_t out_info, Handle debug_handle);
Result ContinueDebugEvent64(Core::System& system, Handle debug_handle, uint32_t flags, uint64_t thread_ids, int32_t num_thread_ids);
Result GetProcessList64(Core::System& system, int32_t* out_num_processes, uint64_t out_process_ids, int32_t max_out_count);
Result GetThreadList64(Core::System& system, int32_t* out_num_threads, uint64_t out_thread_ids, int32_t max_out_count, Handle debug_handle);
Result GetDebugThreadContext64(Core::System& system, uint64_t out_context, Handle debug_handle, uint64_t thread_id, uint32_t context_flags);
Result SetDebugThreadContext64(Core::System& system, Handle debug_handle, uint64_t thread_id, uint64_t context, uint32_t context_flags);
Result QueryDebugProcessMemory64(Core::System& system, uint64_t out_memory_info, PageInfo* out_page_info, Handle process_handle, uint64_t address);
Result ReadDebugProcessMemory64(Core::System& system, uint64_t buffer, Handle debug_handle, uint64_t address, uint64_t size);
Result WriteDebugProcessMemory64(Core::System& system, Handle debug_handle, uint64_t buffer, uint64_t address, uint64_t size);
Result SetHardwareBreakPoint64(Core::System& system, HardwareBreakPointRegisterName name, uint64_t flags, uint64_t value);
Result GetDebugThreadParam64(Core::System& system, uint64_t* out_64, uint32_t* out_32, Handle debug_handle, uint64_t thread_id, DebugThreadParam param);
Result GetSystemInfo64(Core::System& system, uint64_t* out, SystemInfoType info_type, Handle handle, uint64_t info_subtype);
Result CreatePort64(Core::System& system, Handle* out_server_handle, Handle* out_client_handle, int32_t max_sessions, bool is_light, uint64_t name);
Result ManageNamedPort64(Core::System& system, Handle* out_server_handle, uint64_t name, int32_t max_sessions);
Result ConnectToPort64(Core::System& system, Handle* out_handle, Handle port);
Result SetProcessMemoryPermission64(Core::System& system, Handle process_handle, uint64_t address, uint64_t size, MemoryPermission perm);
Result MapProcessMemory64(Core::System& system, uint64_t dst_address, Handle process_handle, uint64_t src_address, uint64_t size);
Result UnmapProcessMemory64(Core::System& system, uint64_t dst_address, Handle process_handle, uint64_t src_address, uint64_t size);
Result QueryProcessMemory64(Core::System& system, uint64_t out_memory_info, PageInfo* out_page_info, Handle process_handle, uint64_t address);
Result MapProcessCodeMemory64(Core::System& system, Handle process_handle, uint64_t dst_address, uint64_t src_address, uint64_t size);
Result UnmapProcessCodeMemory64(Core::System& system, Handle process_handle, uint64_t dst_address, uint64_t src_address, uint64_t size);
Result CreateProcess64(Core::System& system, Handle* out_handle, uint64_t parameters, uint64_t caps, int32_t num_caps);
Result StartProcess64(Core::System& system, Handle process_handle, int32_t priority, int32_t core_id, uint64_t main_thread_stack_size);
Result TerminateProcess64(Core::System& system, Handle process_handle);
Result GetProcessInfo64(Core::System& system, int64_t* out_info, Handle process_handle, ProcessInfoType info_type);
Result CreateResourceLimit64(Core::System& system, Handle* out_handle);
Result SetResourceLimitLimitValue64(Core::System& system, Handle resource_limit_handle, LimitableResource which, int64_t limit_value);
Result MapInsecureMemory64(Core::System& system, uint64_t address, uint64_t size);
Result UnmapInsecureMemory64(Core::System& system, uint64_t address, uint64_t size);
enum class SvcId : u32 {
SetHeapSize = 0x1,
SetMemoryPermission = 0x2,
SetMemoryAttribute = 0x3,
MapMemory = 0x4,
UnmapMemory = 0x5,
QueryMemory = 0x6,
ExitProcess = 0x7,
CreateThread = 0x8,
StartThread = 0x9,
ExitThread = 0xa,
SleepThread = 0xb,
GetThreadPriority = 0xc,
SetThreadPriority = 0xd,
GetThreadCoreMask = 0xe,
SetThreadCoreMask = 0xf,
GetCurrentProcessorNumber = 0x10,
SignalEvent = 0x11,
ClearEvent = 0x12,
MapSharedMemory = 0x13,
UnmapSharedMemory = 0x14,
CreateTransferMemory = 0x15,
CloseHandle = 0x16,
ResetSignal = 0x17,
WaitSynchronization = 0x18,
CancelSynchronization = 0x19,
ArbitrateLock = 0x1a,
ArbitrateUnlock = 0x1b,
WaitProcessWideKeyAtomic = 0x1c,
SignalProcessWideKey = 0x1d,
GetSystemTick = 0x1e,
ConnectToNamedPort = 0x1f,
SendSyncRequestLight = 0x20,
SendSyncRequest = 0x21,
SendSyncRequestWithUserBuffer = 0x22,
SendAsyncRequestWithUserBuffer = 0x23,
GetProcessId = 0x24,
GetThreadId = 0x25,
Break = 0x26,
OutputDebugString = 0x27,
ReturnFromException = 0x28,
GetInfo = 0x29,
FlushEntireDataCache = 0x2a,
FlushDataCache = 0x2b,
MapPhysicalMemory = 0x2c,
UnmapPhysicalMemory = 0x2d,
GetDebugFutureThreadInfo = 0x2e,
GetLastThreadInfo = 0x2f,
GetResourceLimitLimitValue = 0x30,
GetResourceLimitCurrentValue = 0x31,
SetThreadActivity = 0x32,
GetThreadContext3 = 0x33,
WaitForAddress = 0x34,
SignalToAddress = 0x35,
SynchronizePreemptionState = 0x36,
GetResourceLimitPeakValue = 0x37,
CreateIoPool = 0x39,
CreateIoRegion = 0x3a,
KernelDebug = 0x3c,
ChangeKernelTraceState = 0x3d,
CreateSession = 0x40,
AcceptSession = 0x41,
ReplyAndReceiveLight = 0x42,
ReplyAndReceive = 0x43,
ReplyAndReceiveWithUserBuffer = 0x44,
CreateEvent = 0x45,
MapIoRegion = 0x46,
UnmapIoRegion = 0x47,
MapPhysicalMemoryUnsafe = 0x48,
UnmapPhysicalMemoryUnsafe = 0x49,
SetUnsafeLimit = 0x4a,
CreateCodeMemory = 0x4b,
ControlCodeMemory = 0x4c,
SleepSystem = 0x4d,
ReadWriteRegister = 0x4e,
SetProcessActivity = 0x4f,
CreateSharedMemory = 0x50,
MapTransferMemory = 0x51,
UnmapTransferMemory = 0x52,
CreateInterruptEvent = 0x53,
QueryPhysicalAddress = 0x54,
QueryIoMapping = 0x55,
CreateDeviceAddressSpace = 0x56,
AttachDeviceAddressSpace = 0x57,
DetachDeviceAddressSpace = 0x58,
MapDeviceAddressSpaceByForce = 0x59,
MapDeviceAddressSpaceAligned = 0x5a,
UnmapDeviceAddressSpace = 0x5c,
InvalidateProcessDataCache = 0x5d,
StoreProcessDataCache = 0x5e,
FlushProcessDataCache = 0x5f,
DebugActiveProcess = 0x60,
BreakDebugProcess = 0x61,
TerminateDebugProcess = 0x62,
GetDebugEvent = 0x63,
ContinueDebugEvent = 0x64,
GetProcessList = 0x65,
GetThreadList = 0x66,
GetDebugThreadContext = 0x67,
SetDebugThreadContext = 0x68,
QueryDebugProcessMemory = 0x69,
ReadDebugProcessMemory = 0x6a,
WriteDebugProcessMemory = 0x6b,
SetHardwareBreakPoint = 0x6c,
GetDebugThreadParam = 0x6d,
GetSystemInfo = 0x6f,
CreatePort = 0x70,
ManageNamedPort = 0x71,
ConnectToPort = 0x72,
SetProcessMemoryPermission = 0x73,
MapProcessMemory = 0x74,
UnmapProcessMemory = 0x75,
QueryProcessMemory = 0x76,
MapProcessCodeMemory = 0x77,
UnmapProcessCodeMemory = 0x78,
CreateProcess = 0x79,
StartProcess = 0x7a,
TerminateProcess = 0x7b,
GetProcessInfo = 0x7c,
CreateResourceLimit = 0x7d,
SetResourceLimitLimitValue = 0x7e,
CallSecureMonitor = 0x7f,
MapInsecureMemory = 0x90,
UnmapInsecureMemory = 0x91,
};
// clang-format on
// Custom ABI.
Result ReplyAndReceiveLight(Core::System& system, Handle handle, uint32_t* args);
Result ReplyAndReceiveLight64From32(Core::System& system, Handle handle, uint32_t* args);
Result ReplyAndReceiveLight64(Core::System& system, Handle handle, uint32_t* args);
Result SendSyncRequestLight(Core::System& system, Handle session_handle, uint32_t* args);
Result SendSyncRequestLight64From32(Core::System& system, Handle session_handle, uint32_t* args);
Result SendSyncRequestLight64(Core::System& system, Handle session_handle, uint32_t* args);
void CallSecureMonitor(Core::System& system, lp64::SecureMonitorArguments* args);
void CallSecureMonitor64From32(Core::System& system, ilp32::SecureMonitorArguments* args);
void CallSecureMonitor64(Core::System& system, lp64::SecureMonitorArguments* args);
// Defined in svc_light_ipc.cpp.
void SvcWrap_ReplyAndReceiveLight64From32(Core::System& system);
void SvcWrap_ReplyAndReceiveLight64(Core::System& system);
void SvcWrap_SendSyncRequestLight64From32(Core::System& system);
void SvcWrap_SendSyncRequestLight64(Core::System& system);
// Defined in svc_secure_monitor_call.cpp.
void SvcWrap_CallSecureMonitor64From32(Core::System& system);
void SvcWrap_CallSecureMonitor64(Core::System& system);
// Perform a supervisor call by index.
void Call(Core::System& system, u32 imm);
} // namespace Kernel::Svc

View File

@@ -16,18 +16,19 @@ Result SetThreadActivity(Core::System& system, Handle thread_handle,
thread_activity);
// Validate the activity.
constexpr auto IsValidThreadActivity = [](ThreadActivity activity) {
static constexpr auto IsValidThreadActivity = [](ThreadActivity activity) {
return activity == ThreadActivity::Runnable || activity == ThreadActivity::Paused;
};
R_UNLESS(IsValidThreadActivity(thread_activity), ResultInvalidEnumValue);
// Get the thread from its handle.
KScopedAutoObject thread =
system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>(thread_handle);
GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KThread>(thread_handle);
R_UNLESS(thread.IsNotNull(), ResultInvalidHandle);
// Check that the activity is being set on a non-current thread for the current process.
R_UNLESS(thread->GetOwnerProcess() == system.Kernel().CurrentProcess(), ResultInvalidHandle);
R_UNLESS(thread->GetOwnerProcess() == GetCurrentProcessPointer(system.Kernel()),
ResultInvalidHandle);
R_UNLESS(thread.GetPointerUnsafe() != GetCurrentThreadPointer(system.Kernel()), ResultBusy);
// Set the activity.
@@ -36,9 +37,30 @@ Result SetThreadActivity(Core::System& system, Handle thread_handle,
return ResultSuccess;
}
Result SetThreadActivity32(Core::System& system, Handle thread_handle,
Result SetProcessActivity(Core::System& system, Handle process_handle,
ProcessActivity process_activity) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result SetThreadActivity64(Core::System& system, Handle thread_handle,
ThreadActivity thread_activity) {
return SetThreadActivity(system, thread_handle, thread_activity);
}
Result SetProcessActivity64(Core::System& system, Handle process_handle,
ProcessActivity process_activity) {
return SetProcessActivity(system, process_handle, process_activity);
}
Result SetThreadActivity64From32(Core::System& system, Handle thread_handle,
ThreadActivity thread_activity) {
return SetThreadActivity(system, thread_handle, thread_activity);
}
Result SetProcessActivity64From32(Core::System& system, Handle process_handle,
ProcessActivity process_activity) {
return SetProcessActivity(system, process_handle, process_activity);
}
} // namespace Kernel::Svc

View File

@@ -72,13 +72,7 @@ Result WaitForAddress(Core::System& system, VAddr address, ArbitrationType arb_t
timeout = timeout_ns;
}
return system.Kernel().CurrentProcess()->WaitAddressArbiter(address, arb_type, value, timeout);
}
Result WaitForAddress32(Core::System& system, u32 address, ArbitrationType arb_type, s32 value,
u32 timeout_ns_low, u32 timeout_ns_high) {
const auto timeout = static_cast<s64>(timeout_ns_low | (u64{timeout_ns_high} << 32));
return WaitForAddress(system, address, arb_type, value, timeout);
return GetCurrentProcess(system.Kernel()).WaitAddressArbiter(address, arb_type, value, timeout);
}
// Signals to an address (via Address Arbiter)
@@ -101,13 +95,28 @@ Result SignalToAddress(Core::System& system, VAddr address, SignalType signal_ty
return ResultInvalidEnumValue;
}
return system.Kernel().CurrentProcess()->SignalAddressArbiter(address, signal_type, value,
count);
return GetCurrentProcess(system.Kernel())
.SignalAddressArbiter(address, signal_type, value, count);
}
Result SignalToAddress32(Core::System& system, u32 address, SignalType signal_type, s32 value,
Result WaitForAddress64(Core::System& system, VAddr address, ArbitrationType arb_type, s32 value,
s64 timeout_ns) {
return WaitForAddress(system, address, arb_type, value, timeout_ns);
}
Result SignalToAddress64(Core::System& system, VAddr address, SignalType signal_type, s32 value,
s32 count) {
return SignalToAddress(system, address, signal_type, value, count);
}
Result WaitForAddress64From32(Core::System& system, u32 address, ArbitrationType arb_type,
s32 value, s64 timeout_ns) {
return WaitForAddress(system, address, arb_type, value, timeout_ns);
}
Result SignalToAddress64From32(Core::System& system, u32 address, SignalType signal_type, s32 value,
s32 count) {
return SignalToAddress(system, address, signal_type, value, count);
}
} // namespace Kernel::Svc

View File

@@ -2,5 +2,49 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/kernel/svc.h"
#include "core/hle/kernel/svc_results.h"
namespace Kernel::Svc {} // namespace Kernel::Svc
namespace Kernel::Svc {
Result QueryPhysicalAddress(Core::System& system, lp64::PhysicalMemoryInfo* out_info,
uint64_t address) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result QueryIoMapping(Core::System& system, uint64_t* out_address, uint64_t* out_size,
uint64_t physical_address, uint64_t size) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result QueryPhysicalAddress64(Core::System& system, lp64::PhysicalMemoryInfo* out_info,
uint64_t address) {
R_RETURN(QueryPhysicalAddress(system, out_info, address));
}
Result QueryIoMapping64(Core::System& system, uint64_t* out_address, uint64_t* out_size,
uint64_t physical_address, uint64_t size) {
R_RETURN(QueryIoMapping(system, out_address, out_size, physical_address, size));
}
Result QueryPhysicalAddress64From32(Core::System& system, ilp32::PhysicalMemoryInfo* out_info,
uint32_t address) {
lp64::PhysicalMemoryInfo info{};
R_TRY(QueryPhysicalAddress(system, std::addressof(info), address));
*out_info = {
.physical_address = info.physical_address,
.virtual_address = static_cast<u32>(info.virtual_address),
.size = static_cast<u32>(info.size),
};
R_SUCCEED();
}
Result QueryIoMapping64From32(Core::System& system, uint64_t* out_address, uint64_t* out_size,
uint64_t physical_address, uint32_t size) {
R_RETURN(QueryIoMapping(system, reinterpret_cast<uint64_t*>(out_address),
reinterpret_cast<uint64_t*>(out_size), physical_address, size));
}
} // namespace Kernel::Svc

View File

@@ -9,15 +9,36 @@
namespace Kernel::Svc {
Result FlushProcessDataCache32(Core::System& system, Handle process_handle, u64 address, u64 size) {
void FlushEntireDataCache(Core::System& system) {
UNIMPLEMENTED();
}
Result FlushDataCache(Core::System& system, uint64_t address, uint64_t size) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result InvalidateProcessDataCache(Core::System& system, Handle process_handle, uint64_t address,
uint64_t size) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result StoreProcessDataCache(Core::System& system, Handle process_handle, uint64_t address,
uint64_t size) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result FlushProcessDataCache(Core::System& system, Handle process_handle, u64 address, u64 size) {
// Validate address/size.
R_UNLESS(size > 0, ResultInvalidSize);
R_UNLESS(address == static_cast<uintptr_t>(address), ResultInvalidCurrentMemory);
R_UNLESS(size == static_cast<size_t>(size), ResultInvalidCurrentMemory);
R_UNLESS(address == static_cast<uint64_t>(address), ResultInvalidCurrentMemory);
R_UNLESS(size == static_cast<uint64_t>(size), ResultInvalidCurrentMemory);
// Get the process from its handle.
KScopedAutoObject process =
system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KProcess>(process_handle);
GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KProcess>(process_handle);
R_UNLESS(process.IsNotNull(), ResultInvalidHandle);
// Verify the region is within range.
@@ -28,4 +49,50 @@ Result FlushProcessDataCache32(Core::System& system, Handle process_handle, u64
R_RETURN(system.Memory().FlushDataCache(*process, address, size));
}
void FlushEntireDataCache64(Core::System& system) {
FlushEntireDataCache(system);
}
Result FlushDataCache64(Core::System& system, uint64_t address, uint64_t size) {
R_RETURN(FlushDataCache(system, address, size));
}
Result InvalidateProcessDataCache64(Core::System& system, Handle process_handle, uint64_t address,
uint64_t size) {
R_RETURN(InvalidateProcessDataCache(system, process_handle, address, size));
}
Result StoreProcessDataCache64(Core::System& system, Handle process_handle, uint64_t address,
uint64_t size) {
R_RETURN(StoreProcessDataCache(system, process_handle, address, size));
}
Result FlushProcessDataCache64(Core::System& system, Handle process_handle, uint64_t address,
uint64_t size) {
R_RETURN(FlushProcessDataCache(system, process_handle, address, size));
}
void FlushEntireDataCache64From32(Core::System& system) {
return FlushEntireDataCache(system);
}
Result FlushDataCache64From32(Core::System& system, uint32_t address, uint32_t size) {
R_RETURN(FlushDataCache(system, address, size));
}
Result InvalidateProcessDataCache64From32(Core::System& system, Handle process_handle,
uint64_t address, uint64_t size) {
R_RETURN(InvalidateProcessDataCache(system, process_handle, address, size));
}
Result StoreProcessDataCache64From32(Core::System& system, Handle process_handle, uint64_t address,
uint64_t size) {
R_RETURN(StoreProcessDataCache(system, process_handle, address, size));
}
Result FlushProcessDataCache64From32(Core::System& system, Handle process_handle, uint64_t address,
uint64_t size) {
R_RETURN(FlushProcessDataCache(system, process_handle, address, size));
}
} // namespace Kernel::Svc

View File

@@ -28,7 +28,7 @@ constexpr bool IsValidUnmapFromOwnerCodeMemoryPermission(MemoryPermission perm)
} // namespace
Result CreateCodeMemory(Core::System& system, Handle* out, VAddr address, size_t size) {
Result CreateCodeMemory(Core::System& system, Handle* out, VAddr address, uint64_t size) {
LOG_TRACE(Kernel_SVC, "called, address=0x{:X}, size=0x{:X}", address, size);
// Get kernel instance.
@@ -46,7 +46,7 @@ Result CreateCodeMemory(Core::System& system, Handle* out, VAddr address, size_t
R_UNLESS(code_mem != nullptr, ResultOutOfResource);
// Verify that the region is in range.
R_UNLESS(system.CurrentProcess()->PageTable().Contains(address, size),
R_UNLESS(GetCurrentProcess(system.Kernel()).PageTable().Contains(address, size),
ResultInvalidCurrentMemory);
// Initialize the code memory.
@@ -56,19 +56,16 @@ Result CreateCodeMemory(Core::System& system, Handle* out, VAddr address, size_t
KCodeMemory::Register(kernel, code_mem);
// Add the code memory to the handle table.
R_TRY(system.CurrentProcess()->GetHandleTable().Add(out, code_mem));
R_TRY(GetCurrentProcess(system.Kernel()).GetHandleTable().Add(out, code_mem));
code_mem->Close();
return ResultSuccess;
}
Result CreateCodeMemory32(Core::System& system, Handle* out, u32 address, u32 size) {
return CreateCodeMemory(system, out, address, size);
}
Result ControlCodeMemory(Core::System& system, Handle code_memory_handle, u32 operation,
VAddr address, size_t size, MemoryPermission perm) {
Result ControlCodeMemory(Core::System& system, Handle code_memory_handle,
CodeMemoryOperation operation, VAddr address, uint64_t size,
MemoryPermission perm) {
LOG_TRACE(Kernel_SVC,
"called, code_memory_handle=0x{:X}, operation=0x{:X}, address=0x{:X}, size=0x{:X}, "
@@ -82,20 +79,22 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle, u32 op
R_UNLESS((address < address + size), ResultInvalidCurrentMemory);
// Get the code memory from its handle.
KScopedAutoObject code_mem =
system.CurrentProcess()->GetHandleTable().GetObject<KCodeMemory>(code_memory_handle);
KScopedAutoObject code_mem = GetCurrentProcess(system.Kernel())
.GetHandleTable()
.GetObject<KCodeMemory>(code_memory_handle);
R_UNLESS(code_mem.IsNotNull(), ResultInvalidHandle);
// NOTE: Here, Atmosphere extends the SVC to allow code memory operations on one's own process.
// This enables homebrew usage of these SVCs for JIT.
// Perform the operation.
switch (static_cast<CodeMemoryOperation>(operation)) {
switch (operation) {
case CodeMemoryOperation::Map: {
// Check that the region is in range.
R_UNLESS(
system.CurrentProcess()->PageTable().CanContain(address, size, KMemoryState::CodeOut),
ResultInvalidMemoryRegion);
R_UNLESS(GetCurrentProcess(system.Kernel())
.PageTable()
.CanContain(address, size, KMemoryState::CodeOut),
ResultInvalidMemoryRegion);
// Check the memory permission.
R_UNLESS(IsValidMapCodeMemoryPermission(perm), ResultInvalidNewMemoryPermission);
@@ -105,9 +104,10 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle, u32 op
} break;
case CodeMemoryOperation::Unmap: {
// Check that the region is in range.
R_UNLESS(
system.CurrentProcess()->PageTable().CanContain(address, size, KMemoryState::CodeOut),
ResultInvalidMemoryRegion);
R_UNLESS(GetCurrentProcess(system.Kernel())
.PageTable()
.CanContain(address, size, KMemoryState::CodeOut),
ResultInvalidMemoryRegion);
// Check the memory permission.
R_UNLESS(IsValidUnmapCodeMemoryPermission(perm), ResultInvalidNewMemoryPermission);
@@ -146,9 +146,26 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle, u32 op
return ResultSuccess;
}
Result ControlCodeMemory32(Core::System& system, Handle code_memory_handle, u32 operation,
u64 address, u64 size, MemoryPermission perm) {
return ControlCodeMemory(system, code_memory_handle, operation, address, size, perm);
Result CreateCodeMemory64(Core::System& system, Handle* out_handle, uint64_t address,
uint64_t size) {
R_RETURN(CreateCodeMemory(system, out_handle, address, size));
}
Result ControlCodeMemory64(Core::System& system, Handle code_memory_handle,
CodeMemoryOperation operation, uint64_t address, uint64_t size,
MemoryPermission perm) {
R_RETURN(ControlCodeMemory(system, code_memory_handle, operation, address, size, perm));
}
Result CreateCodeMemory64From32(Core::System& system, Handle* out_handle, uint32_t address,
uint32_t size) {
R_RETURN(CreateCodeMemory(system, out_handle, address, size));
}
Result ControlCodeMemory64From32(Core::System& system, Handle code_memory_handle,
CodeMemoryOperation operation, uint64_t address, uint64_t size,
MemoryPermission perm) {
R_RETURN(ControlCodeMemory(system, code_memory_handle, operation, address, size, perm));
}
} // namespace Kernel::Svc

View File

@@ -43,14 +43,8 @@ Result WaitProcessWideKeyAtomic(Core::System& system, VAddr address, VAddr cv_ke
}
// Wait on the condition variable.
return system.Kernel().CurrentProcess()->WaitConditionVariable(
address, Common::AlignDown(cv_key, sizeof(u32)), tag, timeout);
}
Result WaitProcessWideKeyAtomic32(Core::System& system, u32 address, u32 cv_key, u32 tag,
u32 timeout_ns_low, u32 timeout_ns_high) {
const auto timeout_ns = static_cast<s64>(timeout_ns_low | (u64{timeout_ns_high} << 32));
return WaitProcessWideKeyAtomic(system, address, cv_key, tag, timeout_ns);
return GetCurrentProcess(system.Kernel())
.WaitConditionVariable(address, Common::AlignDown(cv_key, sizeof(u32)), tag, timeout);
}
/// Signal process wide key
@@ -58,11 +52,25 @@ void SignalProcessWideKey(Core::System& system, VAddr cv_key, s32 count) {
LOG_TRACE(Kernel_SVC, "called, cv_key=0x{:X}, count=0x{:08X}", cv_key, count);
// Signal the condition variable.
return system.Kernel().CurrentProcess()->SignalConditionVariable(
Common::AlignDown(cv_key, sizeof(u32)), count);
return GetCurrentProcess(system.Kernel())
.SignalConditionVariable(Common::AlignDown(cv_key, sizeof(u32)), count);
}
void SignalProcessWideKey32(Core::System& system, u32 cv_key, s32 count) {
Result WaitProcessWideKeyAtomic64(Core::System& system, uint64_t address, uint64_t cv_key,
uint32_t tag, int64_t timeout_ns) {
R_RETURN(WaitProcessWideKeyAtomic(system, address, cv_key, tag, timeout_ns));
}
void SignalProcessWideKey64(Core::System& system, uint64_t cv_key, int32_t count) {
SignalProcessWideKey(system, cv_key, count);
}
Result WaitProcessWideKeyAtomic64From32(Core::System& system, uint32_t address, uint32_t cv_key,
uint32_t tag, int64_t timeout_ns) {
R_RETURN(WaitProcessWideKeyAtomic(system, address, cv_key, tag, timeout_ns));
}
void SignalProcessWideKey64From32(Core::System& system, uint32_t cv_key, int32_t count) {
SignalProcessWideKey(system, cv_key, count);
}

View File

@@ -2,5 +2,193 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/kernel/svc.h"
#include "core/hle/kernel/svc_results.h"
namespace Kernel::Svc {} // namespace Kernel::Svc
namespace Kernel::Svc {
Result DebugActiveProcess(Core::System& system, Handle* out_handle, uint64_t process_id) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result BreakDebugProcess(Core::System& system, Handle debug_handle) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result TerminateDebugProcess(Core::System& system, Handle debug_handle) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result GetDebugEvent(Core::System& system, uint64_t out_info, Handle debug_handle) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result ContinueDebugEvent(Core::System& system, Handle debug_handle, uint32_t flags,
uint64_t user_thread_ids, int32_t num_thread_ids) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result GetDebugThreadContext(Core::System& system, uint64_t out_context, Handle debug_handle,
uint64_t thread_id, uint32_t context_flags) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result SetDebugThreadContext(Core::System& system, Handle debug_handle, uint64_t thread_id,
uint64_t user_context, uint32_t context_flags) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result QueryDebugProcessMemory(Core::System& system, uint64_t out_memory_info,
PageInfo* out_page_info, Handle process_handle, uint64_t address) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result ReadDebugProcessMemory(Core::System& system, uint64_t buffer, Handle debug_handle,
uint64_t address, uint64_t size) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result WriteDebugProcessMemory(Core::System& system, Handle debug_handle, uint64_t buffer,
uint64_t address, uint64_t size) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result SetHardwareBreakPoint(Core::System& system, HardwareBreakPointRegisterName name,
uint64_t flags, uint64_t value) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result GetDebugThreadParam(Core::System& system, uint64_t* out_64, uint32_t* out_32,
Handle debug_handle, uint64_t thread_id, DebugThreadParam param) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result DebugActiveProcess64(Core::System& system, Handle* out_handle, uint64_t process_id) {
R_RETURN(DebugActiveProcess(system, out_handle, process_id));
}
Result BreakDebugProcess64(Core::System& system, Handle debug_handle) {
R_RETURN(BreakDebugProcess(system, debug_handle));
}
Result TerminateDebugProcess64(Core::System& system, Handle debug_handle) {
R_RETURN(TerminateDebugProcess(system, debug_handle));
}
Result GetDebugEvent64(Core::System& system, uint64_t out_info, Handle debug_handle) {
R_RETURN(GetDebugEvent(system, out_info, debug_handle));
}
Result ContinueDebugEvent64(Core::System& system, Handle debug_handle, uint32_t flags,
uint64_t thread_ids, int32_t num_thread_ids) {
R_RETURN(ContinueDebugEvent(system, debug_handle, flags, thread_ids, num_thread_ids));
}
Result GetDebugThreadContext64(Core::System& system, uint64_t out_context, Handle debug_handle,
uint64_t thread_id, uint32_t context_flags) {
R_RETURN(GetDebugThreadContext(system, out_context, debug_handle, thread_id, context_flags));
}
Result SetDebugThreadContext64(Core::System& system, Handle debug_handle, uint64_t thread_id,
uint64_t context, uint32_t context_flags) {
R_RETURN(SetDebugThreadContext(system, debug_handle, thread_id, context, context_flags));
}
Result QueryDebugProcessMemory64(Core::System& system, uint64_t out_memory_info,
PageInfo* out_page_info, Handle debug_handle, uint64_t address) {
R_RETURN(
QueryDebugProcessMemory(system, out_memory_info, out_page_info, debug_handle, address));
}
Result ReadDebugProcessMemory64(Core::System& system, uint64_t buffer, Handle debug_handle,
uint64_t address, uint64_t size) {
R_RETURN(ReadDebugProcessMemory(system, buffer, debug_handle, address, size));
}
Result WriteDebugProcessMemory64(Core::System& system, Handle debug_handle, uint64_t buffer,
uint64_t address, uint64_t size) {
R_RETURN(WriteDebugProcessMemory(system, debug_handle, buffer, address, size));
}
Result SetHardwareBreakPoint64(Core::System& system, HardwareBreakPointRegisterName name,
uint64_t flags, uint64_t value) {
R_RETURN(SetHardwareBreakPoint(system, name, flags, value));
}
Result GetDebugThreadParam64(Core::System& system, uint64_t* out_64, uint32_t* out_32,
Handle debug_handle, uint64_t thread_id, DebugThreadParam param) {
R_RETURN(GetDebugThreadParam(system, out_64, out_32, debug_handle, thread_id, param));
}
Result DebugActiveProcess64From32(Core::System& system, Handle* out_handle, uint64_t process_id) {
R_RETURN(DebugActiveProcess(system, out_handle, process_id));
}
Result BreakDebugProcess64From32(Core::System& system, Handle debug_handle) {
R_RETURN(BreakDebugProcess(system, debug_handle));
}
Result TerminateDebugProcess64From32(Core::System& system, Handle debug_handle) {
R_RETURN(TerminateDebugProcess(system, debug_handle));
}
Result GetDebugEvent64From32(Core::System& system, uint32_t out_info, Handle debug_handle) {
R_RETURN(GetDebugEvent(system, out_info, debug_handle));
}
Result ContinueDebugEvent64From32(Core::System& system, Handle debug_handle, uint32_t flags,
uint32_t thread_ids, int32_t num_thread_ids) {
R_RETURN(ContinueDebugEvent(system, debug_handle, flags, thread_ids, num_thread_ids));
}
Result GetDebugThreadContext64From32(Core::System& system, uint32_t out_context,
Handle debug_handle, uint64_t thread_id,
uint32_t context_flags) {
R_RETURN(GetDebugThreadContext(system, out_context, debug_handle, thread_id, context_flags));
}
Result SetDebugThreadContext64From32(Core::System& system, Handle debug_handle, uint64_t thread_id,
uint32_t context, uint32_t context_flags) {
R_RETURN(SetDebugThreadContext(system, debug_handle, thread_id, context, context_flags));
}
Result QueryDebugProcessMemory64From32(Core::System& system, uint32_t out_memory_info,
PageInfo* out_page_info, Handle debug_handle,
uint32_t address) {
R_RETURN(
QueryDebugProcessMemory(system, out_memory_info, out_page_info, debug_handle, address));
}
Result ReadDebugProcessMemory64From32(Core::System& system, uint32_t buffer, Handle debug_handle,
uint32_t address, uint32_t size) {
R_RETURN(ReadDebugProcessMemory(system, buffer, debug_handle, address, size));
}
Result WriteDebugProcessMemory64From32(Core::System& system, Handle debug_handle, uint32_t buffer,
uint32_t address, uint32_t size) {
R_RETURN(WriteDebugProcessMemory(system, debug_handle, buffer, address, size));
}
Result SetHardwareBreakPoint64From32(Core::System& system, HardwareBreakPointRegisterName name,
uint64_t flags, uint64_t value) {
R_RETURN(SetHardwareBreakPoint(system, name, flags, value));
}
Result GetDebugThreadParam64From32(Core::System& system, uint64_t* out_64, uint32_t* out_32,
Handle debug_handle, uint64_t thread_id,
DebugThreadParam param) {
R_RETURN(GetDebugThreadParam(system, out_64, out_32, debug_handle, thread_id, param));
}
} // namespace Kernel::Svc

View File

@@ -8,18 +8,22 @@
namespace Kernel::Svc {
/// Used to output a message on a debug hardware unit - does nothing on a retail unit
void OutputDebugString(Core::System& system, VAddr address, u64 len) {
if (len == 0) {
return;
}
Result OutputDebugString(Core::System& system, VAddr address, u64 len) {
R_SUCCEED_IF(len == 0);
std::string str(len, '\0');
system.Memory().ReadBlock(address, str.data(), str.size());
LOG_DEBUG(Debug_Emulated, "{}", str);
R_SUCCEED();
}
void OutputDebugString32(Core::System& system, u32 address, u32 len) {
OutputDebugString(system, address, len);
Result OutputDebugString64(Core::System& system, uint64_t debug_str, uint64_t len) {
R_RETURN(OutputDebugString(system, debug_str, len));
}
Result OutputDebugString64From32(Core::System& system, uint32_t debug_str, uint32_t len) {
R_RETURN(OutputDebugString(system, debug_str, len));
}
} // namespace Kernel::Svc

View File

@@ -1,6 +1,258 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/alignment.h"
#include "common/scope_exit.h"
#include "core/core.h"
#include "core/hle/kernel/k_device_address_space.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/svc.h"
namespace Kernel::Svc {} // namespace Kernel::Svc
namespace Kernel::Svc {
constexpr inline u64 DeviceAddressSpaceAlignMask = (1ULL << 22) - 1;
constexpr bool IsProcessAndDeviceAligned(uint64_t process_address, uint64_t device_address) {
return (process_address & DeviceAddressSpaceAlignMask) ==
(device_address & DeviceAddressSpaceAlignMask);
}
Result CreateDeviceAddressSpace(Core::System& system, Handle* out, uint64_t das_address,
uint64_t das_size) {
// Validate input.
R_UNLESS(Common::IsAligned(das_address, PageSize), ResultInvalidMemoryRegion);
R_UNLESS(Common::IsAligned(das_size, PageSize), ResultInvalidMemoryRegion);
R_UNLESS(das_size > 0, ResultInvalidMemoryRegion);
R_UNLESS((das_address < das_address + das_size), ResultInvalidMemoryRegion);
// Create the device address space.
KDeviceAddressSpace* das = KDeviceAddressSpace::Create(system.Kernel());
R_UNLESS(das != nullptr, ResultOutOfResource);
SCOPE_EXIT({ das->Close(); });
// Initialize the device address space.
R_TRY(das->Initialize(das_address, das_size));
// Register the device address space.
KDeviceAddressSpace::Register(system.Kernel(), das);
// Add to the handle table.
R_TRY(GetCurrentProcess(system.Kernel()).GetHandleTable().Add(out, das));
R_SUCCEED();
}
Result AttachDeviceAddressSpace(Core::System& system, DeviceName device_name, Handle das_handle) {
// Get the device address space.
KScopedAutoObject das = GetCurrentProcess(system.Kernel())
.GetHandleTable()
.GetObject<KDeviceAddressSpace>(das_handle);
R_UNLESS(das.IsNotNull(), ResultInvalidHandle);
// Attach.
R_RETURN(das->Attach(device_name));
}
Result DetachDeviceAddressSpace(Core::System& system, DeviceName device_name, Handle das_handle) {
// Get the device address space.
KScopedAutoObject das = GetCurrentProcess(system.Kernel())
.GetHandleTable()
.GetObject<KDeviceAddressSpace>(das_handle);
R_UNLESS(das.IsNotNull(), ResultInvalidHandle);
// Detach.
R_RETURN(das->Detach(device_name));
}
constexpr bool IsValidDeviceMemoryPermission(MemoryPermission device_perm) {
switch (device_perm) {
case MemoryPermission::Read:
case MemoryPermission::Write:
case MemoryPermission::ReadWrite:
return true;
default:
return false;
}
}
Result MapDeviceAddressSpaceByForce(Core::System& system, Handle das_handle, Handle process_handle,
uint64_t process_address, uint64_t size,
uint64_t device_address, u32 option) {
// Decode the option.
const MapDeviceAddressSpaceOption option_pack{option};
const auto device_perm = option_pack.permission;
const auto reserved = option_pack.reserved;
// Validate input.
R_UNLESS(Common::IsAligned(process_address, PageSize), ResultInvalidAddress);
R_UNLESS(Common::IsAligned(device_address, PageSize), ResultInvalidAddress);
R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize);
R_UNLESS(size > 0, ResultInvalidSize);
R_UNLESS((process_address < process_address + size), ResultInvalidCurrentMemory);
R_UNLESS((device_address < device_address + size), ResultInvalidMemoryRegion);
R_UNLESS((process_address == static_cast<uint64_t>(process_address)),
ResultInvalidCurrentMemory);
R_UNLESS(IsValidDeviceMemoryPermission(device_perm), ResultInvalidNewMemoryPermission);
R_UNLESS(reserved == 0, ResultInvalidEnumValue);
// Get the device address space.
KScopedAutoObject das = GetCurrentProcess(system.Kernel())
.GetHandleTable()
.GetObject<KDeviceAddressSpace>(das_handle);
R_UNLESS(das.IsNotNull(), ResultInvalidHandle);
// Get the process.
KScopedAutoObject process =
GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KProcess>(process_handle);
R_UNLESS(process.IsNotNull(), ResultInvalidHandle);
// Validate that the process address is within range.
auto& page_table = process->PageTable();
R_UNLESS(page_table.Contains(process_address, size), ResultInvalidCurrentMemory);
// Map.
R_RETURN(
das->MapByForce(std::addressof(page_table), process_address, size, device_address, option));
}
Result MapDeviceAddressSpaceAligned(Core::System& system, Handle das_handle, Handle process_handle,
uint64_t process_address, uint64_t size,
uint64_t device_address, u32 option) {
// Decode the option.
const MapDeviceAddressSpaceOption option_pack{option};
const auto device_perm = option_pack.permission;
const auto reserved = option_pack.reserved;
// Validate input.
R_UNLESS(Common::IsAligned(process_address, PageSize), ResultInvalidAddress);
R_UNLESS(Common::IsAligned(device_address, PageSize), ResultInvalidAddress);
R_UNLESS(IsProcessAndDeviceAligned(process_address, device_address), ResultInvalidAddress);
R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize);
R_UNLESS(size > 0, ResultInvalidSize);
R_UNLESS((process_address < process_address + size), ResultInvalidCurrentMemory);
R_UNLESS((device_address < device_address + size), ResultInvalidMemoryRegion);
R_UNLESS((process_address == static_cast<uint64_t>(process_address)),
ResultInvalidCurrentMemory);
R_UNLESS(IsValidDeviceMemoryPermission(device_perm), ResultInvalidNewMemoryPermission);
R_UNLESS(reserved == 0, ResultInvalidEnumValue);
// Get the device address space.
KScopedAutoObject das = GetCurrentProcess(system.Kernel())
.GetHandleTable()
.GetObject<KDeviceAddressSpace>(das_handle);
R_UNLESS(das.IsNotNull(), ResultInvalidHandle);
// Get the process.
KScopedAutoObject process =
GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KProcess>(process_handle);
R_UNLESS(process.IsNotNull(), ResultInvalidHandle);
// Validate that the process address is within range.
auto& page_table = process->PageTable();
R_UNLESS(page_table.Contains(process_address, size), ResultInvalidCurrentMemory);
// Map.
R_RETURN(
das->MapAligned(std::addressof(page_table), process_address, size, device_address, option));
}
Result UnmapDeviceAddressSpace(Core::System& system, Handle das_handle, Handle process_handle,
uint64_t process_address, uint64_t size, uint64_t device_address) {
// Validate input.
R_UNLESS(Common::IsAligned(process_address, PageSize), ResultInvalidAddress);
R_UNLESS(Common::IsAligned(device_address, PageSize), ResultInvalidAddress);
R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize);
R_UNLESS(size > 0, ResultInvalidSize);
R_UNLESS((process_address < process_address + size), ResultInvalidCurrentMemory);
R_UNLESS((device_address < device_address + size), ResultInvalidMemoryRegion);
R_UNLESS((process_address == static_cast<uint64_t>(process_address)),
ResultInvalidCurrentMemory);
// Get the device address space.
KScopedAutoObject das = GetCurrentProcess(system.Kernel())
.GetHandleTable()
.GetObject<KDeviceAddressSpace>(das_handle);
R_UNLESS(das.IsNotNull(), ResultInvalidHandle);
// Get the process.
KScopedAutoObject process =
GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KProcess>(process_handle);
R_UNLESS(process.IsNotNull(), ResultInvalidHandle);
// Validate that the process address is within range.
auto& page_table = process->PageTable();
R_UNLESS(page_table.Contains(process_address, size), ResultInvalidCurrentMemory);
R_RETURN(das->Unmap(std::addressof(page_table), process_address, size, device_address));
}
Result CreateDeviceAddressSpace64(Core::System& system, Handle* out_handle, uint64_t das_address,
uint64_t das_size) {
R_RETURN(CreateDeviceAddressSpace(system, out_handle, das_address, das_size));
}
Result AttachDeviceAddressSpace64(Core::System& system, DeviceName device_name, Handle das_handle) {
R_RETURN(AttachDeviceAddressSpace(system, device_name, das_handle));
}
Result DetachDeviceAddressSpace64(Core::System& system, DeviceName device_name, Handle das_handle) {
R_RETURN(DetachDeviceAddressSpace(system, device_name, das_handle));
}
Result MapDeviceAddressSpaceByForce64(Core::System& system, Handle das_handle,
Handle process_handle, uint64_t process_address,
uint64_t size, uint64_t device_address, u32 option) {
R_RETURN(MapDeviceAddressSpaceByForce(system, das_handle, process_handle, process_address, size,
device_address, option));
}
Result MapDeviceAddressSpaceAligned64(Core::System& system, Handle das_handle,
Handle process_handle, uint64_t process_address,
uint64_t size, uint64_t device_address, u32 option) {
R_RETURN(MapDeviceAddressSpaceAligned(system, das_handle, process_handle, process_address, size,
device_address, option));
}
Result UnmapDeviceAddressSpace64(Core::System& system, Handle das_handle, Handle process_handle,
uint64_t process_address, uint64_t size, uint64_t device_address) {
R_RETURN(UnmapDeviceAddressSpace(system, das_handle, process_handle, process_address, size,
device_address));
}
Result CreateDeviceAddressSpace64From32(Core::System& system, Handle* out_handle,
uint64_t das_address, uint64_t das_size) {
R_RETURN(CreateDeviceAddressSpace(system, out_handle, das_address, das_size));
}
Result AttachDeviceAddressSpace64From32(Core::System& system, DeviceName device_name,
Handle das_handle) {
R_RETURN(AttachDeviceAddressSpace(system, device_name, das_handle));
}
Result DetachDeviceAddressSpace64From32(Core::System& system, DeviceName device_name,
Handle das_handle) {
R_RETURN(DetachDeviceAddressSpace(system, device_name, das_handle));
}
Result MapDeviceAddressSpaceByForce64From32(Core::System& system, Handle das_handle,
Handle process_handle, uint64_t process_address,
uint32_t size, uint64_t device_address, u32 option) {
R_RETURN(MapDeviceAddressSpaceByForce(system, das_handle, process_handle, process_address, size,
device_address, option));
}
Result MapDeviceAddressSpaceAligned64From32(Core::System& system, Handle das_handle,
Handle process_handle, uint64_t process_address,
uint32_t size, uint64_t device_address, u32 option) {
R_RETURN(MapDeviceAddressSpaceAligned(system, das_handle, process_handle, process_address, size,
device_address, option));
}
Result UnmapDeviceAddressSpace64From32(Core::System& system, Handle das_handle,
Handle process_handle, uint64_t process_address,
uint32_t size, uint64_t device_address) {
R_RETURN(UnmapDeviceAddressSpace(system, das_handle, process_handle, process_address, size,
device_address));
}
} // namespace Kernel::Svc

View File

@@ -15,7 +15,7 @@ Result SignalEvent(Core::System& system, Handle event_handle) {
LOG_DEBUG(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle);
// Get the current handle table.
const KHandleTable& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
const KHandleTable& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
// Get the event.
KScopedAutoObject event = handle_table.GetObject<KEvent>(event_handle);
@@ -24,15 +24,11 @@ Result SignalEvent(Core::System& system, Handle event_handle) {
return event->Signal();
}
Result SignalEvent32(Core::System& system, Handle event_handle) {
return SignalEvent(system, event_handle);
}
Result ClearEvent(Core::System& system, Handle event_handle) {
LOG_TRACE(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle);
// Get the current handle table.
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
// Try to clear the writable event.
{
@@ -55,19 +51,15 @@ Result ClearEvent(Core::System& system, Handle event_handle) {
return ResultInvalidHandle;
}
Result ClearEvent32(Core::System& system, Handle event_handle) {
return ClearEvent(system, event_handle);
}
Result CreateEvent(Core::System& system, Handle* out_write, Handle* out_read) {
LOG_DEBUG(Kernel_SVC, "called");
// Get the kernel reference and handle table.
auto& kernel = system.Kernel();
auto& handle_table = kernel.CurrentProcess()->GetHandleTable();
auto& handle_table = GetCurrentProcess(kernel).GetHandleTable();
// Reserve a new event from the process resource limit
KScopedResourceReservation event_reservation(kernel.CurrentProcess(),
KScopedResourceReservation event_reservation(GetCurrentProcessPointer(kernel),
LimitableResource::EventCountMax);
R_UNLESS(event_reservation.Succeeded(), ResultLimitReached);
@@ -76,7 +68,7 @@ Result CreateEvent(Core::System& system, Handle* out_write, Handle* out_read) {
R_UNLESS(event != nullptr, ResultOutOfResource);
// Initialize the event.
event->Initialize(kernel.CurrentProcess());
event->Initialize(GetCurrentProcessPointer(kernel));
// Commit the thread reservation.
event_reservation.Commit();
@@ -104,8 +96,29 @@ Result CreateEvent(Core::System& system, Handle* out_write, Handle* out_read) {
return ResultSuccess;
}
Result CreateEvent32(Core::System& system, Handle* out_write, Handle* out_read) {
return CreateEvent(system, out_write, out_read);
Result SignalEvent64(Core::System& system, Handle event_handle) {
R_RETURN(SignalEvent(system, event_handle));
}
Result ClearEvent64(Core::System& system, Handle event_handle) {
R_RETURN(ClearEvent(system, event_handle));
}
Result CreateEvent64(Core::System& system, Handle* out_write_handle, Handle* out_read_handle) {
R_RETURN(CreateEvent(system, out_write_handle, out_read_handle));
}
Result SignalEvent64From32(Core::System& system, Handle event_handle) {
R_RETURN(SignalEvent(system, event_handle));
}
Result ClearEvent64From32(Core::System& system, Handle event_handle) {
R_RETURN(ClearEvent(system, event_handle));
}
Result CreateEvent64From32(Core::System& system, Handle* out_write_handle,
Handle* out_read_handle) {
R_RETURN(CreateEvent(system, out_write_handle, out_read_handle));
}
} // namespace Kernel::Svc

View File

@@ -12,10 +12,10 @@
namespace Kernel::Svc {
/// Break program execution
void Break(Core::System& system, u32 reason, u64 info1, u64 info2) {
void Break(Core::System& system, BreakReason reason, u64 info1, u64 info2) {
BreakReason break_reason =
static_cast<BreakReason>(reason & ~static_cast<u32>(BreakReason::NotificationOnlyFlag));
bool notification_only = (reason & static_cast<u32>(BreakReason::NotificationOnlyFlag)) != 0;
reason & static_cast<BreakReason>(~BreakReason::NotificationOnlyFlag);
bool notification_only = True(reason & BreakReason::NotificationOnlyFlag);
bool has_dumped_buffer{};
std::vector<u8> debug_buffer;
@@ -90,9 +90,9 @@ void Break(Core::System& system, u32 reason, u64 info1, u64 info2) {
break;
}
system.GetReporter().SaveSvcBreakReport(reason, notification_only, info1, info2,
has_dumped_buffer ? std::make_optional(debug_buffer)
: std::nullopt);
system.GetReporter().SaveSvcBreakReport(
static_cast<u32>(reason), notification_only, info1, info2,
has_dumped_buffer ? std::make_optional(debug_buffer) : std::nullopt);
if (!notification_only) {
LOG_CRITICAL(
@@ -114,8 +114,24 @@ void Break(Core::System& system, u32 reason, u64 info1, u64 info2) {
}
}
void Break32(Core::System& system, u32 reason, u32 info1, u32 info2) {
Break(system, reason, info1, info2);
void ReturnFromException(Core::System& system, Result result) {
UNIMPLEMENTED();
}
void Break64(Core::System& system, BreakReason break_reason, uint64_t arg, uint64_t size) {
Break(system, break_reason, arg, size);
}
void Break64From32(Core::System& system, BreakReason break_reason, uint32_t arg, uint32_t size) {
Break(system, break_reason, arg, size);
}
void ReturnFromException64(Core::System& system, Result result) {
ReturnFromException(system, result);
}
void ReturnFromException64From32(Core::System& system, Result result) {
ReturnFromException(system, result);
}
} // namespace Kernel::Svc

View File

@@ -10,11 +10,12 @@
namespace Kernel::Svc {
/// Gets system/memory information for the current process
Result GetInfo(Core::System& system, u64* result, u64 info_id, Handle handle, u64 info_sub_id) {
LOG_TRACE(Kernel_SVC, "called info_id=0x{:X}, info_sub_id=0x{:X}, handle=0x{:08X}", info_id,
info_sub_id, handle);
Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle handle,
u64 info_sub_id) {
LOG_TRACE(Kernel_SVC, "called info_id=0x{:X}, info_sub_id=0x{:X}, handle=0x{:08X}",
info_id_type, info_sub_id, handle);
const auto info_id_type = static_cast<InfoType>(info_id);
u32 info_id = static_cast<u32>(info_id_type);
switch (info_id_type) {
case InfoType::CoreMask:
@@ -43,7 +44,7 @@ Result GetInfo(Core::System& system, u64* result, u64 info_id, Handle handle, u6
return ResultInvalidEnumValue;
}
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
KScopedAutoObject process = handle_table.GetObject<KProcess>(handle);
if (process.IsNull()) {
LOG_ERROR(Kernel_SVC, "Process is not valid! info_id={}, info_sub_id={}, handle={:08X}",
@@ -153,7 +154,7 @@ Result GetInfo(Core::System& system, u64* result, u64 info_id, Handle handle, u6
return ResultInvalidCombination;
}
KProcess* const current_process = system.Kernel().CurrentProcess();
KProcess* const current_process = GetCurrentProcessPointer(system.Kernel());
KHandleTable& handle_table = current_process->GetHandleTable();
const auto resource_limit = current_process->GetResourceLimit();
if (!resource_limit) {
@@ -182,7 +183,7 @@ Result GetInfo(Core::System& system, u64* result, u64 info_id, Handle handle, u6
return ResultInvalidCombination;
}
*result = system.Kernel().CurrentProcess()->GetRandomEntropy(info_sub_id);
*result = GetCurrentProcess(system.Kernel()).GetRandomEntropy(info_sub_id);
return ResultSuccess;
case InfoType::InitialProcessIdRange:
@@ -199,9 +200,9 @@ Result GetInfo(Core::System& system, u64* result, u64 info_id, Handle handle, u6
return ResultInvalidCombination;
}
KScopedAutoObject thread =
system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>(
static_cast<Handle>(handle));
KScopedAutoObject thread = GetCurrentProcess(system.Kernel())
.GetHandleTable()
.GetObject<KThread>(static_cast<Handle>(handle));
if (thread.IsNull()) {
LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}",
static_cast<Handle>(handle));
@@ -248,7 +249,7 @@ Result GetInfo(Core::System& system, u64* result, u64 info_id, Handle handle, u6
R_UNLESS(info_sub_id == 0, ResultInvalidCombination);
// Get the handle table.
KProcess* current_process = system.Kernel().CurrentProcess();
KProcess* current_process = GetCurrentProcessPointer(system.Kernel());
KHandleTable& handle_table = current_process->GetHandleTable();
// Get a new handle for the current process.
@@ -267,16 +268,30 @@ Result GetInfo(Core::System& system, u64* result, u64 info_id, Handle handle, u6
}
}
Result GetInfo32(Core::System& system, u32* result_low, u32* result_high, u32 sub_id_low,
u32 info_id, u32 handle, u32 sub_id_high) {
const u64 sub_id{u64{sub_id_low} | (u64{sub_id_high} << 32)};
u64 res_value{};
Result GetSystemInfo(Core::System& system, uint64_t* out, SystemInfoType info_type, Handle handle,
uint64_t info_subtype) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
const Result result{GetInfo(system, &res_value, info_id, handle, sub_id)};
*result_high = static_cast<u32>(res_value >> 32);
*result_low = static_cast<u32>(res_value & std::numeric_limits<u32>::max());
Result GetInfo64(Core::System& system, uint64_t* out, InfoType info_type, Handle handle,
uint64_t info_subtype) {
R_RETURN(GetInfo(system, out, info_type, handle, info_subtype));
}
return result;
Result GetSystemInfo64(Core::System& system, uint64_t* out, SystemInfoType info_type, Handle handle,
uint64_t info_subtype) {
R_RETURN(GetSystemInfo(system, out, info_type, handle, info_subtype));
}
Result GetInfo64From32(Core::System& system, uint64_t* out, InfoType info_type, Handle handle,
uint64_t info_subtype) {
R_RETURN(GetInfo(system, out, info_type, handle, info_subtype));
}
Result GetSystemInfo64From32(Core::System& system, uint64_t* out, SystemInfoType info_type,
Handle handle, uint64_t info_subtype) {
R_RETURN(GetSystemInfo(system, out, info_type, handle, info_subtype));
}
} // namespace Kernel::Svc

View File

@@ -0,0 +1,35 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/kernel/svc.h"
#include "core/hle/kernel/svc_results.h"
namespace Kernel::Svc {
Result MapInsecureMemory(Core::System& system, uint64_t address, uint64_t size) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result UnmapInsecureMemory(Core::System& system, uint64_t address, uint64_t size) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result MapInsecureMemory64(Core::System& system, uint64_t address, uint64_t size) {
R_RETURN(MapInsecureMemory(system, address, size));
}
Result UnmapInsecureMemory64(Core::System& system, uint64_t address, uint64_t size) {
R_RETURN(UnmapInsecureMemory(system, address, size));
}
Result MapInsecureMemory64From32(Core::System& system, uint32_t address, uint32_t size) {
R_RETURN(MapInsecureMemory(system, address, size));
}
Result UnmapInsecureMemory64From32(Core::System& system, uint32_t address, uint32_t size) {
R_RETURN(UnmapInsecureMemory(system, address, size));
}
} // namespace Kernel::Svc

View File

@@ -2,5 +2,24 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/kernel/svc.h"
#include "core/hle/kernel/svc_results.h"
namespace Kernel::Svc {} // namespace Kernel::Svc
namespace Kernel::Svc {
Result CreateInterruptEvent(Core::System& system, Handle* out, int32_t interrupt_id,
InterruptType type) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result CreateInterruptEvent64(Core::System& system, Handle* out_read_handle, int32_t interrupt_id,
InterruptType interrupt_type) {
R_RETURN(CreateInterruptEvent(system, out_read_handle, interrupt_id, interrupt_type));
}
Result CreateInterruptEvent64From32(Core::System& system, Handle* out_read_handle,
int32_t interrupt_id, InterruptType interrupt_type) {
R_RETURN(CreateInterruptEvent(system, out_read_handle, interrupt_id, interrupt_type));
}
} // namespace Kernel::Svc

View File

@@ -2,5 +2,70 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/kernel/svc.h"
#include "core/hle/kernel/svc_results.h"
namespace Kernel::Svc {} // namespace Kernel::Svc
namespace Kernel::Svc {
Result CreateIoPool(Core::System& system, Handle* out, IoPoolType pool_type) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result CreateIoRegion(Core::System& system, Handle* out, Handle io_pool_handle, uint64_t phys_addr,
uint64_t size, MemoryMapping mapping, MemoryPermission perm) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result MapIoRegion(Core::System& system, Handle io_region_handle, uint64_t address, uint64_t size,
MemoryPermission map_perm) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result UnmapIoRegion(Core::System& system, Handle io_region_handle, uint64_t address,
uint64_t size) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result CreateIoPool64(Core::System& system, Handle* out_handle, IoPoolType pool_type) {
R_RETURN(CreateIoPool(system, out_handle, pool_type));
}
Result CreateIoRegion64(Core::System& system, Handle* out_handle, Handle io_pool,
uint64_t physical_address, uint64_t size, MemoryMapping mapping,
MemoryPermission perm) {
R_RETURN(CreateIoRegion(system, out_handle, io_pool, physical_address, size, mapping, perm));
}
Result MapIoRegion64(Core::System& system, Handle io_region, uint64_t address, uint64_t size,
MemoryPermission perm) {
R_RETURN(MapIoRegion(system, io_region, address, size, perm));
}
Result UnmapIoRegion64(Core::System& system, Handle io_region, uint64_t address, uint64_t size) {
R_RETURN(UnmapIoRegion(system, io_region, address, size));
}
Result CreateIoPool64From32(Core::System& system, Handle* out_handle, IoPoolType pool_type) {
R_RETURN(CreateIoPool(system, out_handle, pool_type));
}
Result CreateIoRegion64From32(Core::System& system, Handle* out_handle, Handle io_pool,
uint64_t physical_address, uint32_t size, MemoryMapping mapping,
MemoryPermission perm) {
R_RETURN(CreateIoRegion(system, out_handle, io_pool, physical_address, size, mapping, perm));
}
Result MapIoRegion64From32(Core::System& system, Handle io_region, uint32_t address, uint32_t size,
MemoryPermission perm) {
R_RETURN(MapIoRegion(system, io_region, address, size, perm));
}
Result UnmapIoRegion64From32(Core::System& system, Handle io_region, uint32_t address,
uint32_t size) {
R_RETURN(UnmapIoRegion(system, io_region, address, size));
}
} // namespace Kernel::Svc

View File

@@ -12,11 +12,9 @@ namespace Kernel::Svc {
/// Makes a blocking IPC call to a service.
Result SendSyncRequest(Core::System& system, Handle handle) {
auto& kernel = system.Kernel();
// Get the client session from its handle.
KScopedAutoObject session =
kernel.CurrentProcess()->GetHandleTable().GetObject<KClientSession>(handle);
GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KClientSession>(handle);
R_UNLESS(session.IsNotNull(), ResultInvalidHandle);
LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName());
@@ -24,20 +22,37 @@ Result SendSyncRequest(Core::System& system, Handle handle) {
return session->SendSyncRequest();
}
Result SendSyncRequest32(Core::System& system, Handle handle) {
return SendSyncRequest(system, handle);
Result SendSyncRequestWithUserBuffer(Core::System& system, uint64_t message_buffer,
uint64_t message_buffer_size, Handle session_handle) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result ReplyAndReceive(Core::System& system, s32* out_index, Handle* handles, s32 num_handles,
Result SendAsyncRequestWithUserBuffer(Core::System& system, Handle* out_event_handle,
uint64_t message_buffer, uint64_t message_buffer_size,
Handle session_handle) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result ReplyAndReceive(Core::System& system, s32* out_index, uint64_t handles_addr, s32 num_handles,
Handle reply_target, s64 timeout_ns) {
auto& kernel = system.Kernel();
auto& handle_table = GetCurrentThread(kernel).GetOwnerProcess()->GetHandleTable();
auto& handle_table = GetCurrentProcess(kernel).GetHandleTable();
R_UNLESS(0 <= num_handles && num_handles <= ArgumentHandleCountMax, ResultOutOfRange);
R_UNLESS(system.Memory().IsValidVirtualAddressRange(
handles_addr, static_cast<u64>(sizeof(Handle) * num_handles)),
ResultInvalidPointer);
std::vector<Handle> handles(num_handles);
system.Memory().ReadBlock(handles_addr, handles.data(), sizeof(Handle) * num_handles);
// Convert handle list to object table.
std::vector<KSynchronizationObject*> objs(num_handles);
R_UNLESS(
handle_table.GetMultipleObjects<KSynchronizationObject>(objs.data(), handles, num_handles),
ResultInvalidHandle);
R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(objs.data(), handles.data(),
num_handles),
ResultInvalidHandle);
// Ensure handles are closed when we're done.
SCOPE_EXIT({
@@ -86,4 +101,72 @@ Result ReplyAndReceive(Core::System& system, s32* out_index, Handle* handles, s3
}
}
Result ReplyAndReceiveWithUserBuffer(Core::System& system, int32_t* out_index,
uint64_t message_buffer, uint64_t message_buffer_size,
uint64_t handles, int32_t num_handles, Handle reply_target,
int64_t timeout_ns) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result SendSyncRequest64(Core::System& system, Handle session_handle) {
R_RETURN(SendSyncRequest(system, session_handle));
}
Result SendSyncRequestWithUserBuffer64(Core::System& system, uint64_t message_buffer,
uint64_t message_buffer_size, Handle session_handle) {
R_RETURN(
SendSyncRequestWithUserBuffer(system, message_buffer, message_buffer_size, session_handle));
}
Result SendAsyncRequestWithUserBuffer64(Core::System& system, Handle* out_event_handle,
uint64_t message_buffer, uint64_t message_buffer_size,
Handle session_handle) {
R_RETURN(SendAsyncRequestWithUserBuffer(system, out_event_handle, message_buffer,
message_buffer_size, session_handle));
}
Result ReplyAndReceive64(Core::System& system, int32_t* out_index, uint64_t handles,
int32_t num_handles, Handle reply_target, int64_t timeout_ns) {
R_RETURN(ReplyAndReceive(system, out_index, handles, num_handles, reply_target, timeout_ns));
}
Result ReplyAndReceiveWithUserBuffer64(Core::System& system, int32_t* out_index,
uint64_t message_buffer, uint64_t message_buffer_size,
uint64_t handles, int32_t num_handles, Handle reply_target,
int64_t timeout_ns) {
R_RETURN(ReplyAndReceiveWithUserBuffer(system, out_index, message_buffer, message_buffer_size,
handles, num_handles, reply_target, timeout_ns));
}
Result SendSyncRequest64From32(Core::System& system, Handle session_handle) {
R_RETURN(SendSyncRequest(system, session_handle));
}
Result SendSyncRequestWithUserBuffer64From32(Core::System& system, uint32_t message_buffer,
uint32_t message_buffer_size, Handle session_handle) {
R_RETURN(
SendSyncRequestWithUserBuffer(system, message_buffer, message_buffer_size, session_handle));
}
Result SendAsyncRequestWithUserBuffer64From32(Core::System& system, Handle* out_event_handle,
uint32_t message_buffer, uint32_t message_buffer_size,
Handle session_handle) {
R_RETURN(SendAsyncRequestWithUserBuffer(system, out_event_handle, message_buffer,
message_buffer_size, session_handle));
}
Result ReplyAndReceive64From32(Core::System& system, int32_t* out_index, uint32_t handles,
int32_t num_handles, Handle reply_target, int64_t timeout_ns) {
R_RETURN(ReplyAndReceive(system, out_index, handles, num_handles, reply_target, timeout_ns));
}
Result ReplyAndReceiveWithUserBuffer64From32(Core::System& system, int32_t* out_index,
uint32_t message_buffer, uint32_t message_buffer_size,
uint32_t handles, int32_t num_handles,
Handle reply_target, int64_t timeout_ns) {
R_RETURN(ReplyAndReceiveWithUserBuffer(system, out_index, message_buffer, message_buffer_size,
handles, num_handles, reply_target, timeout_ns));
}
} // namespace Kernel::Svc

View File

@@ -5,15 +5,31 @@
namespace Kernel::Svc {
void KernelDebug([[maybe_unused]] Core::System& system, [[maybe_unused]] u32 kernel_debug_type,
[[maybe_unused]] u64 param1, [[maybe_unused]] u64 param2,
[[maybe_unused]] u64 param3) {
void KernelDebug(Core::System& system, KernelDebugType kernel_debug_type, u64 arg0, u64 arg1,
u64 arg2) {
// Intentionally do nothing, as this does nothing in released kernel binaries.
}
void ChangeKernelTraceState([[maybe_unused]] Core::System& system,
[[maybe_unused]] u32 trace_state) {
void ChangeKernelTraceState(Core::System& system, KernelTraceState trace_state) {
// Intentionally do nothing, as this does nothing in released kernel binaries.
}
void KernelDebug64(Core::System& system, KernelDebugType kern_debug_type, uint64_t arg0,
uint64_t arg1, uint64_t arg2) {
KernelDebug(system, kern_debug_type, arg0, arg1, arg2);
}
void ChangeKernelTraceState64(Core::System& system, KernelTraceState kern_trace_state) {
ChangeKernelTraceState(system, kern_trace_state);
}
void KernelDebug64From32(Core::System& system, KernelDebugType kern_debug_type, uint64_t arg0,
uint64_t arg1, uint64_t arg2) {
KernelDebug(system, kern_debug_type, arg0, arg1, arg2);
}
void ChangeKernelTraceState64From32(Core::System& system, KernelTraceState kern_trace_state) {
ChangeKernelTraceState(system, kern_trace_state);
}
} // namespace Kernel::Svc

View File

@@ -1,6 +1,73 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/arm/arm_interface.h"
#include "core/core.h"
#include "core/hle/kernel/svc.h"
#include "core/hle/kernel/svc_results.h"
namespace Kernel::Svc {} // namespace Kernel::Svc
namespace Kernel::Svc {
Result SendSyncRequestLight(Core::System& system, Handle session_handle, u32* args) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result ReplyAndReceiveLight(Core::System& system, Handle session_handle, u32* args) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result SendSyncRequestLight64(Core::System& system, Handle session_handle, u32* args) {
R_RETURN(SendSyncRequestLight(system, session_handle, args));
}
Result ReplyAndReceiveLight64(Core::System& system, Handle session_handle, u32* args) {
R_RETURN(ReplyAndReceiveLight(system, session_handle, args));
}
Result SendSyncRequestLight64From32(Core::System& system, Handle session_handle, u32* args) {
R_RETURN(SendSyncRequestLight(system, session_handle, args));
}
Result ReplyAndReceiveLight64From32(Core::System& system, Handle session_handle, u32* args) {
R_RETURN(ReplyAndReceiveLight(system, session_handle, args));
}
// Custom ABI implementation for light IPC.
template <typename F>
static void SvcWrap_LightIpc(Core::System& system, F&& cb) {
auto& core = system.CurrentArmInterface();
std::array<u32, 7> arguments{};
Handle session_handle = static_cast<Handle>(core.GetReg(0));
for (int i = 0; i < 7; i++) {
arguments[i] = static_cast<u32>(core.GetReg(i + 1));
}
Result ret = cb(system, session_handle, arguments.data());
core.SetReg(0, ret.raw);
for (int i = 0; i < 7; i++) {
core.SetReg(i + 1, arguments[i]);
}
}
void SvcWrap_SendSyncRequestLight64(Core::System& system) {
SvcWrap_LightIpc(system, SendSyncRequestLight64);
}
void SvcWrap_ReplyAndReceiveLight64(Core::System& system) {
SvcWrap_LightIpc(system, ReplyAndReceiveLight64);
}
void SvcWrap_SendSyncRequestLight64From32(Core::System& system) {
SvcWrap_LightIpc(system, SendSyncRequestLight64From32);
}
void SvcWrap_ReplyAndReceiveLight64From32(Core::System& system) {
SvcWrap_LightIpc(system, ReplyAndReceiveLight64From32);
}
} // namespace Kernel::Svc

View File

@@ -24,11 +24,7 @@ Result ArbitrateLock(Core::System& system, Handle thread_handle, VAddr address,
return ResultInvalidAddress;
}
return system.Kernel().CurrentProcess()->WaitForAddress(thread_handle, address, tag);
}
Result ArbitrateLock32(Core::System& system, Handle thread_handle, u32 address, u32 tag) {
return ArbitrateLock(system, thread_handle, address, tag);
return GetCurrentProcess(system.Kernel()).WaitForAddress(thread_handle, address, tag);
}
/// Unlock a mutex
@@ -47,11 +43,24 @@ Result ArbitrateUnlock(Core::System& system, VAddr address) {
return ResultInvalidAddress;
}
return system.Kernel().CurrentProcess()->SignalToAddress(address);
return GetCurrentProcess(system.Kernel()).SignalToAddress(address);
}
Result ArbitrateUnlock32(Core::System& system, u32 address) {
return ArbitrateUnlock(system, address);
Result ArbitrateLock64(Core::System& system, Handle thread_handle, uint64_t address, uint32_t tag) {
R_RETURN(ArbitrateLock(system, thread_handle, address, tag));
}
Result ArbitrateUnlock64(Core::System& system, uint64_t address) {
R_RETURN(ArbitrateUnlock(system, address));
}
Result ArbitrateLock64From32(Core::System& system, Handle thread_handle, uint32_t address,
uint32_t tag) {
R_RETURN(ArbitrateLock(system, thread_handle, address, tag));
}
Result ArbitrateUnlock64From32(Core::System& system, uint32_t address) {
R_RETURN(ArbitrateUnlock(system, address));
}
} // namespace Kernel::Svc

View File

@@ -113,7 +113,7 @@ Result SetMemoryPermission(Core::System& system, VAddr address, u64 size, Memory
R_UNLESS(IsValidSetMemoryPermission(perm), ResultInvalidNewMemoryPermission);
// Validate that the region is in range for the current process.
auto& page_table = system.Kernel().CurrentProcess()->PageTable();
auto& page_table = GetCurrentProcess(system.Kernel()).PageTable();
R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory);
// Set the memory attribute.
@@ -137,23 +137,19 @@ Result SetMemoryAttribute(Core::System& system, VAddr address, u64 size, u32 mas
R_UNLESS((mask | attr | SupportedMask) == SupportedMask, ResultInvalidCombination);
// Validate that the region is in range for the current process.
auto& page_table{system.Kernel().CurrentProcess()->PageTable()};
auto& page_table{GetCurrentProcess(system.Kernel()).PageTable()};
R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory);
// Set the memory attribute.
return page_table.SetMemoryAttribute(address, size, mask, attr);
}
Result SetMemoryAttribute32(Core::System& system, u32 address, u32 size, u32 mask, u32 attr) {
return SetMemoryAttribute(system, address, size, mask, attr);
}
/// Maps a memory range into a different range.
Result MapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size) {
LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
src_addr, size);
auto& page_table{system.Kernel().CurrentProcess()->PageTable()};
auto& page_table{GetCurrentProcess(system.Kernel()).PageTable()};
if (const Result result{MapUnmapMemorySanityChecks(page_table, dst_addr, src_addr, size)};
result.IsError()) {
@@ -163,16 +159,12 @@ Result MapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size)
return page_table.MapMemory(dst_addr, src_addr, size);
}
Result MapMemory32(Core::System& system, u32 dst_addr, u32 src_addr, u32 size) {
return MapMemory(system, dst_addr, src_addr, size);
}
/// Unmaps a region that was previously mapped with svcMapMemory
Result UnmapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size) {
LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
src_addr, size);
auto& page_table{system.Kernel().CurrentProcess()->PageTable()};
auto& page_table{GetCurrentProcess(system.Kernel()).PageTable()};
if (const Result result{MapUnmapMemorySanityChecks(page_table, dst_addr, src_addr, size)};
result.IsError()) {
@@ -182,8 +174,44 @@ Result UnmapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 siz
return page_table.UnmapMemory(dst_addr, src_addr, size);
}
Result UnmapMemory32(Core::System& system, u32 dst_addr, u32 src_addr, u32 size) {
return UnmapMemory(system, dst_addr, src_addr, size);
Result SetMemoryPermission64(Core::System& system, uint64_t address, uint64_t size,
MemoryPermission perm) {
R_RETURN(SetMemoryPermission(system, address, size, perm));
}
Result SetMemoryAttribute64(Core::System& system, uint64_t address, uint64_t size, uint32_t mask,
uint32_t attr) {
R_RETURN(SetMemoryAttribute(system, address, size, mask, attr));
}
Result MapMemory64(Core::System& system, uint64_t dst_address, uint64_t src_address,
uint64_t size) {
R_RETURN(MapMemory(system, dst_address, src_address, size));
}
Result UnmapMemory64(Core::System& system, uint64_t dst_address, uint64_t src_address,
uint64_t size) {
R_RETURN(UnmapMemory(system, dst_address, src_address, size));
}
Result SetMemoryPermission64From32(Core::System& system, uint32_t address, uint32_t size,
MemoryPermission perm) {
R_RETURN(SetMemoryPermission(system, address, size, perm));
}
Result SetMemoryAttribute64From32(Core::System& system, uint32_t address, uint32_t size,
uint32_t mask, uint32_t attr) {
R_RETURN(SetMemoryAttribute(system, address, size, mask, attr));
}
Result MapMemory64From32(Core::System& system, uint32_t dst_address, uint32_t src_address,
uint32_t size) {
R_RETURN(MapMemory(system, dst_address, src_address, size));
}
Result UnmapMemory64From32(Core::System& system, uint32_t dst_address, uint32_t src_address,
uint32_t size) {
R_RETURN(UnmapMemory(system, dst_address, src_address, size));
}
} // namespace Kernel::Svc

View File

@@ -16,18 +16,11 @@ Result SetHeapSize(Core::System& system, VAddr* out_address, u64 size) {
R_UNLESS(size < MainMemorySizeMax, ResultInvalidSize);
// Set the heap size.
R_TRY(system.Kernel().CurrentProcess()->PageTable().SetHeapSize(out_address, size));
R_TRY(GetCurrentProcess(system.Kernel()).PageTable().SetHeapSize(out_address, size));
return ResultSuccess;
}
Result SetHeapSize32(Core::System& system, u32* heap_addr, u32 heap_size) {
VAddr temp_heap_addr{};
const Result result{SetHeapSize(system, &temp_heap_addr, heap_size)};
*heap_addr = static_cast<u32>(temp_heap_addr);
return result;
}
/// Maps memory at a desired address
Result MapPhysicalMemory(Core::System& system, VAddr addr, u64 size) {
LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size);
@@ -52,7 +45,7 @@ Result MapPhysicalMemory(Core::System& system, VAddr addr, u64 size) {
return ResultInvalidMemoryRegion;
}
KProcess* const current_process{system.Kernel().CurrentProcess()};
KProcess* const current_process{GetCurrentProcessPointer(system.Kernel())};
auto& page_table{current_process->PageTable()};
if (current_process->GetSystemResourceSize() == 0) {
@@ -77,10 +70,6 @@ Result MapPhysicalMemory(Core::System& system, VAddr addr, u64 size) {
return page_table.MapPhysicalMemory(addr, size);
}
Result MapPhysicalMemory32(Core::System& system, u32 addr, u32 size) {
return MapPhysicalMemory(system, addr, size);
}
/// Unmaps memory previously mapped via MapPhysicalMemory
Result UnmapPhysicalMemory(Core::System& system, VAddr addr, u64 size) {
LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size);
@@ -105,7 +94,7 @@ Result UnmapPhysicalMemory(Core::System& system, VAddr addr, u64 size) {
return ResultInvalidMemoryRegion;
}
KProcess* const current_process{system.Kernel().CurrentProcess()};
KProcess* const current_process{GetCurrentProcessPointer(system.Kernel())};
auto& page_table{current_process->PageTable()};
if (current_process->GetSystemResourceSize() == 0) {
@@ -130,8 +119,67 @@ Result UnmapPhysicalMemory(Core::System& system, VAddr addr, u64 size) {
return page_table.UnmapPhysicalMemory(addr, size);
}
Result UnmapPhysicalMemory32(Core::System& system, u32 addr, u32 size) {
return UnmapPhysicalMemory(system, addr, size);
Result MapPhysicalMemoryUnsafe(Core::System& system, uint64_t address, uint64_t size) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result UnmapPhysicalMemoryUnsafe(Core::System& system, uint64_t address, uint64_t size) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result SetUnsafeLimit(Core::System& system, uint64_t limit) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result SetHeapSize64(Core::System& system, uint64_t* out_address, uint64_t size) {
R_RETURN(SetHeapSize(system, out_address, size));
}
Result MapPhysicalMemory64(Core::System& system, uint64_t address, uint64_t size) {
R_RETURN(MapPhysicalMemory(system, address, size));
}
Result UnmapPhysicalMemory64(Core::System& system, uint64_t address, uint64_t size) {
R_RETURN(UnmapPhysicalMemory(system, address, size));
}
Result MapPhysicalMemoryUnsafe64(Core::System& system, uint64_t address, uint64_t size) {
R_RETURN(MapPhysicalMemoryUnsafe(system, address, size));
}
Result UnmapPhysicalMemoryUnsafe64(Core::System& system, uint64_t address, uint64_t size) {
R_RETURN(UnmapPhysicalMemoryUnsafe(system, address, size));
}
Result SetUnsafeLimit64(Core::System& system, uint64_t limit) {
R_RETURN(SetUnsafeLimit(system, limit));
}
Result SetHeapSize64From32(Core::System& system, uint64_t* out_address, uint32_t size) {
R_RETURN(SetHeapSize(system, out_address, size));
}
Result MapPhysicalMemory64From32(Core::System& system, uint32_t address, uint32_t size) {
R_RETURN(MapPhysicalMemory(system, address, size));
}
Result UnmapPhysicalMemory64From32(Core::System& system, uint32_t address, uint32_t size) {
R_RETURN(UnmapPhysicalMemory(system, address, size));
}
Result MapPhysicalMemoryUnsafe64From32(Core::System& system, uint32_t address, uint32_t size) {
R_RETURN(MapPhysicalMemoryUnsafe(system, address, size));
}
Result UnmapPhysicalMemoryUnsafe64From32(Core::System& system, uint32_t address, uint32_t size) {
R_RETURN(UnmapPhysicalMemoryUnsafe(system, address, size));
}
Result SetUnsafeLimit64From32(Core::System& system, uint32_t limit) {
R_RETURN(SetUnsafeLimit(system, limit));
}
} // namespace Kernel::Svc

View File

@@ -5,6 +5,7 @@
#include "core/core.h"
#include "core/hle/kernel/k_client_port.h"
#include "core/hle/kernel/k_client_session.h"
#include "core/hle/kernel/k_object_name.h"
#include "core/hle/kernel/k_port.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/svc.h"
@@ -34,7 +35,7 @@ Result ConnectToNamedPort(Core::System& system, Handle* out, VAddr port_name_add
// Get the current handle table.
auto& kernel = system.Kernel();
auto& handle_table = kernel.CurrentProcess()->GetHandleTable();
auto& handle_table = GetCurrentProcess(kernel).GetHandleTable();
// Find the client port.
auto port = kernel.CreateNamedServicePort(port_name);
@@ -63,9 +64,107 @@ Result ConnectToNamedPort(Core::System& system, Handle* out, VAddr port_name_add
return ResultSuccess;
}
Result ConnectToNamedPort32(Core::System& system, Handle* out_handle, u32 port_name_address) {
Result CreatePort(Core::System& system, Handle* out_server, Handle* out_client,
int32_t max_sessions, bool is_light, uint64_t name) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
return ConnectToNamedPort(system, out_handle, port_name_address);
Result ConnectToPort(Core::System& system, Handle* out_handle, Handle port) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result ManageNamedPort(Core::System& system, Handle* out_server_handle, uint64_t user_name,
int32_t max_sessions) {
// Copy the provided name from user memory to kernel memory.
std::array<char, KObjectName::NameLengthMax> name{};
system.Memory().ReadBlock(user_name, name.data(), sizeof(name));
// Validate that sessions and name are valid.
R_UNLESS(max_sessions >= 0, ResultOutOfRange);
R_UNLESS(name[sizeof(name) - 1] == '\x00', ResultOutOfRange);
if (max_sessions > 0) {
// Get the current handle table.
auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
// Create a new port.
KPort* port = KPort::Create(system.Kernel());
R_UNLESS(port != nullptr, ResultOutOfResource);
// Initialize the new port.
port->Initialize(max_sessions, false, "");
// Register the port.
KPort::Register(system.Kernel(), port);
// Ensure that our only reference to the port is in the handle table when we're done.
SCOPE_EXIT({
port->GetClientPort().Close();
port->GetServerPort().Close();
});
// Register the handle in the table.
R_TRY(handle_table.Add(out_server_handle, std::addressof(port->GetServerPort())));
ON_RESULT_FAILURE {
handle_table.Remove(*out_server_handle);
};
// Create a new object name.
R_TRY(KObjectName::NewFromName(system.Kernel(), std::addressof(port->GetClientPort()),
name.data()));
} else /* if (max_sessions == 0) */ {
// Ensure that this else case is correct.
ASSERT(max_sessions == 0);
// If we're closing, there's no server handle.
*out_server_handle = InvalidHandle;
// Delete the object.
R_TRY(KObjectName::Delete<KClientPort>(system.Kernel(), name.data()));
}
R_SUCCEED();
}
Result ConnectToNamedPort64(Core::System& system, Handle* out_handle, uint64_t name) {
R_RETURN(ConnectToNamedPort(system, out_handle, name));
}
Result CreatePort64(Core::System& system, Handle* out_server_handle, Handle* out_client_handle,
int32_t max_sessions, bool is_light, uint64_t name) {
R_RETURN(
CreatePort(system, out_server_handle, out_client_handle, max_sessions, is_light, name));
}
Result ManageNamedPort64(Core::System& system, Handle* out_server_handle, uint64_t name,
int32_t max_sessions) {
R_RETURN(ManageNamedPort(system, out_server_handle, name, max_sessions));
}
Result ConnectToPort64(Core::System& system, Handle* out_handle, Handle port) {
R_RETURN(ConnectToPort(system, out_handle, port));
}
Result ConnectToNamedPort64From32(Core::System& system, Handle* out_handle, uint32_t name) {
R_RETURN(ConnectToNamedPort(system, out_handle, name));
}
Result CreatePort64From32(Core::System& system, Handle* out_server_handle,
Handle* out_client_handle, int32_t max_sessions, bool is_light,
uint32_t name) {
R_RETURN(
CreatePort(system, out_server_handle, out_client_handle, max_sessions, is_light, name));
}
Result ManageNamedPort64From32(Core::System& system, Handle* out_server_handle, uint32_t name,
int32_t max_sessions) {
R_RETURN(ManageNamedPort(system, out_server_handle, name, max_sessions));
}
Result ConnectToPort64From32(Core::System& system, Handle* out_handle, Handle port) {
R_RETURN(ConnectToPort(system, out_handle, port));
}
} // namespace Kernel::Svc

View File

@@ -2,5 +2,20 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/kernel/svc.h"
#include "core/hle/kernel/svc_results.h"
namespace Kernel::Svc {} // namespace Kernel::Svc
namespace Kernel::Svc {
void SleepSystem(Core::System& system) {
UNIMPLEMENTED();
}
void SleepSystem64(Core::System& system) {
return SleepSystem(system);
}
void SleepSystem64From32(Core::System& system) {
return SleepSystem(system);
}
} // namespace Kernel::Svc

View File

@@ -9,7 +9,7 @@ namespace Kernel::Svc {
/// Exits the current process
void ExitProcess(Core::System& system) {
auto* current_process = system.Kernel().CurrentProcess();
auto* current_process = GetCurrentProcessPointer(system.Kernel());
LOG_INFO(Kernel_SVC, "Process {} exiting", current_process->GetProcessID());
ASSERT_MSG(current_process->GetState() == KProcess::State::Running,
@@ -18,18 +18,14 @@ void ExitProcess(Core::System& system) {
system.Exit();
}
void ExitProcess32(Core::System& system) {
ExitProcess(system);
}
/// Gets the ID of the specified process or a specified thread's owning process.
Result GetProcessId(Core::System& system, u64* out_process_id, Handle handle) {
LOG_DEBUG(Kernel_SVC, "called handle=0x{:08X}", handle);
// Get the object from the handle table.
KScopedAutoObject obj =
system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KAutoObject>(
static_cast<Handle>(handle));
KScopedAutoObject obj = GetCurrentProcess(system.Kernel())
.GetHandleTable()
.GetObject<KAutoObject>(static_cast<Handle>(handle));
R_UNLESS(obj.IsNotNull(), ResultInvalidHandle);
// Get the process from the object.
@@ -54,17 +50,8 @@ Result GetProcessId(Core::System& system, u64* out_process_id, Handle handle) {
return ResultSuccess;
}
Result GetProcessId32(Core::System& system, u32* out_process_id_low, u32* out_process_id_high,
Handle handle) {
u64 out_process_id{};
const auto result = GetProcessId(system, &out_process_id, handle);
*out_process_id_low = static_cast<u32>(out_process_id);
*out_process_id_high = static_cast<u32>(out_process_id >> 32);
return result;
}
Result GetProcessList(Core::System& system, u32* out_num_processes, VAddr out_process_ids,
u32 out_process_ids_size) {
Result GetProcessList(Core::System& system, s32* out_num_processes, VAddr out_process_ids,
int32_t out_process_ids_size) {
LOG_DEBUG(Kernel_SVC, "called. out_process_ids=0x{:016X}, out_process_ids_size={}",
out_process_ids, out_process_ids_size);
@@ -76,10 +63,10 @@ Result GetProcessList(Core::System& system, u32* out_num_processes, VAddr out_pr
return ResultOutOfRange;
}
const auto& kernel = system.Kernel();
auto& kernel = system.Kernel();
const auto total_copy_size = out_process_ids_size * sizeof(u64);
if (out_process_ids_size > 0 && !kernel.CurrentProcess()->PageTable().IsInsideAddressSpace(
if (out_process_ids_size > 0 && !GetCurrentProcess(kernel).PageTable().IsInsideAddressSpace(
out_process_ids, total_copy_size)) {
LOG_ERROR(Kernel_SVC, "Address range outside address space. begin=0x{:016X}, end=0x{:016X}",
out_process_ids, out_process_ids + total_copy_size);
@@ -89,7 +76,8 @@ Result GetProcessList(Core::System& system, u32* out_num_processes, VAddr out_pr
auto& memory = system.Memory();
const auto& process_list = kernel.GetProcessList();
const auto num_processes = process_list.size();
const auto copy_amount = std::min(std::size_t{out_process_ids_size}, num_processes);
const auto copy_amount =
std::min(static_cast<std::size_t>(out_process_ids_size), num_processes);
for (std::size_t i = 0; i < copy_amount; ++i) {
memory.Write64(out_process_ids, process_list[i]->GetProcessID());
@@ -100,10 +88,11 @@ Result GetProcessList(Core::System& system, u32* out_num_processes, VAddr out_pr
return ResultSuccess;
}
Result GetProcessInfo(Core::System& system, u64* out, Handle process_handle, u32 type) {
LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, type=0x{:X}", process_handle, type);
Result GetProcessInfo(Core::System& system, s64* out, Handle process_handle,
ProcessInfoType info_type) {
LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, type=0x{:X}", process_handle, info_type);
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle);
if (process.IsNull()) {
LOG_ERROR(Kernel_SVC, "Process handle does not exist, process_handle=0x{:08X}",
@@ -111,14 +100,95 @@ Result GetProcessInfo(Core::System& system, u64* out, Handle process_handle, u32
return ResultInvalidHandle;
}
const auto info_type = static_cast<ProcessInfoType>(type);
if (info_type != ProcessInfoType::ProcessState) {
LOG_ERROR(Kernel_SVC, "Expected info_type to be ProcessState but got {} instead", type);
LOG_ERROR(Kernel_SVC, "Expected info_type to be ProcessState but got {} instead",
info_type);
return ResultInvalidEnumValue;
}
*out = static_cast<u64>(process->GetState());
*out = static_cast<s64>(process->GetState());
return ResultSuccess;
}
Result CreateProcess(Core::System& system, Handle* out_handle, uint64_t parameters, uint64_t caps,
int32_t num_caps) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result StartProcess(Core::System& system, Handle process_handle, int32_t priority, int32_t core_id,
uint64_t main_thread_stack_size) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result TerminateProcess(Core::System& system, Handle process_handle) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
void ExitProcess64(Core::System& system) {
ExitProcess(system);
}
Result GetProcessId64(Core::System& system, uint64_t* out_process_id, Handle process_handle) {
R_RETURN(GetProcessId(system, out_process_id, process_handle));
}
Result GetProcessList64(Core::System& system, int32_t* out_num_processes, uint64_t out_process_ids,
int32_t max_out_count) {
R_RETURN(GetProcessList(system, out_num_processes, out_process_ids, max_out_count));
}
Result CreateProcess64(Core::System& system, Handle* out_handle, uint64_t parameters, uint64_t caps,
int32_t num_caps) {
R_RETURN(CreateProcess(system, out_handle, parameters, caps, num_caps));
}
Result StartProcess64(Core::System& system, Handle process_handle, int32_t priority,
int32_t core_id, uint64_t main_thread_stack_size) {
R_RETURN(StartProcess(system, process_handle, priority, core_id, main_thread_stack_size));
}
Result TerminateProcess64(Core::System& system, Handle process_handle) {
R_RETURN(TerminateProcess(system, process_handle));
}
Result GetProcessInfo64(Core::System& system, int64_t* out_info, Handle process_handle,
ProcessInfoType info_type) {
R_RETURN(GetProcessInfo(system, out_info, process_handle, info_type));
}
void ExitProcess64From32(Core::System& system) {
ExitProcess(system);
}
Result GetProcessId64From32(Core::System& system, uint64_t* out_process_id, Handle process_handle) {
R_RETURN(GetProcessId(system, out_process_id, process_handle));
}
Result GetProcessList64From32(Core::System& system, int32_t* out_num_processes,
uint32_t out_process_ids, int32_t max_out_count) {
R_RETURN(GetProcessList(system, out_num_processes, out_process_ids, max_out_count));
}
Result CreateProcess64From32(Core::System& system, Handle* out_handle, uint32_t parameters,
uint32_t caps, int32_t num_caps) {
R_RETURN(CreateProcess(system, out_handle, parameters, caps, num_caps));
}
Result StartProcess64From32(Core::System& system, Handle process_handle, int32_t priority,
int32_t core_id, uint64_t main_thread_stack_size) {
R_RETURN(StartProcess(system, process_handle, priority, core_id, main_thread_stack_size));
}
Result TerminateProcess64From32(Core::System& system, Handle process_handle) {
R_RETURN(TerminateProcess(system, process_handle));
}
Result GetProcessInfo64From32(Core::System& system, int64_t* out_info, Handle process_handle,
ProcessInfoType info_type) {
R_RETURN(GetProcessInfo(system, out_info, process_handle, info_type));
}
} // namespace Kernel::Svc

View File

@@ -37,15 +37,15 @@ Result SetProcessMemoryPermission(Core::System& system, Handle process_handle, V
R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize);
R_UNLESS(size > 0, ResultInvalidSize);
R_UNLESS((address < address + size), ResultInvalidCurrentMemory);
R_UNLESS(address == static_cast<uintptr_t>(address), ResultInvalidCurrentMemory);
R_UNLESS(size == static_cast<size_t>(size), ResultInvalidCurrentMemory);
R_UNLESS(address == static_cast<uint64_t>(address), ResultInvalidCurrentMemory);
R_UNLESS(size == static_cast<uint64_t>(size), ResultInvalidCurrentMemory);
// Validate the memory permission.
R_UNLESS(IsValidProcessMemoryPermission(perm), ResultInvalidNewMemoryPermission);
// Get the process from its handle.
KScopedAutoObject process =
system.CurrentProcess()->GetHandleTable().GetObject<KProcess>(process_handle);
GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KProcess>(process_handle);
R_UNLESS(process.IsNotNull(), ResultInvalidHandle);
// Validate that the address is in range.
@@ -71,7 +71,7 @@ Result MapProcessMemory(Core::System& system, VAddr dst_address, Handle process_
R_UNLESS((src_address < src_address + size), ResultInvalidCurrentMemory);
// Get the processes.
KProcess* dst_process = system.CurrentProcess();
KProcess* dst_process = GetCurrentProcessPointer(system.Kernel());
KScopedAutoObject src_process =
dst_process->GetHandleTable().GetObjectWithoutPseudoHandle<KProcess>(process_handle);
R_UNLESS(src_process.IsNotNull(), ResultInvalidHandle);
@@ -114,7 +114,7 @@ Result UnmapProcessMemory(Core::System& system, VAddr dst_address, Handle proces
R_UNLESS((src_address < src_address + size), ResultInvalidCurrentMemory);
// Get the processes.
KProcess* dst_process = system.CurrentProcess();
KProcess* dst_process = GetCurrentProcessPointer(system.Kernel());
KScopedAutoObject src_process =
dst_process->GetHandleTable().GetObjectWithoutPseudoHandle<KProcess>(process_handle);
R_UNLESS(src_process.IsNotNull(), ResultInvalidHandle);
@@ -174,7 +174,7 @@ Result MapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst
return ResultInvalidCurrentMemory;
}
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle);
if (process.IsNull()) {
LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).",
@@ -242,7 +242,7 @@ Result UnmapProcessCodeMemory(Core::System& system, Handle process_handle, u64 d
return ResultInvalidCurrentMemory;
}
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle);
if (process.IsNull()) {
LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).",
@@ -271,4 +271,54 @@ Result UnmapProcessCodeMemory(Core::System& system, Handle process_handle, u64 d
KPageTable::ICacheInvalidationStrategy::InvalidateAll);
}
Result SetProcessMemoryPermission64(Core::System& system, Handle process_handle, uint64_t address,
uint64_t size, MemoryPermission perm) {
R_RETURN(SetProcessMemoryPermission(system, process_handle, address, size, perm));
}
Result MapProcessMemory64(Core::System& system, uint64_t dst_address, Handle process_handle,
uint64_t src_address, uint64_t size) {
R_RETURN(MapProcessMemory(system, dst_address, process_handle, src_address, size));
}
Result UnmapProcessMemory64(Core::System& system, uint64_t dst_address, Handle process_handle,
uint64_t src_address, uint64_t size) {
R_RETURN(UnmapProcessMemory(system, dst_address, process_handle, src_address, size));
}
Result MapProcessCodeMemory64(Core::System& system, Handle process_handle, uint64_t dst_address,
uint64_t src_address, uint64_t size) {
R_RETURN(MapProcessCodeMemory(system, process_handle, dst_address, src_address, size));
}
Result UnmapProcessCodeMemory64(Core::System& system, Handle process_handle, uint64_t dst_address,
uint64_t src_address, uint64_t size) {
R_RETURN(UnmapProcessCodeMemory(system, process_handle, dst_address, src_address, size));
}
Result SetProcessMemoryPermission64From32(Core::System& system, Handle process_handle,
uint64_t address, uint64_t size, MemoryPermission perm) {
R_RETURN(SetProcessMemoryPermission(system, process_handle, address, size, perm));
}
Result MapProcessMemory64From32(Core::System& system, uint32_t dst_address, Handle process_handle,
uint64_t src_address, uint32_t size) {
R_RETURN(MapProcessMemory(system, dst_address, process_handle, src_address, size));
}
Result UnmapProcessMemory64From32(Core::System& system, uint32_t dst_address, Handle process_handle,
uint64_t src_address, uint32_t size) {
R_RETURN(UnmapProcessMemory(system, dst_address, process_handle, src_address, size));
}
Result MapProcessCodeMemory64From32(Core::System& system, Handle process_handle,
uint64_t dst_address, uint64_t src_address, uint64_t size) {
R_RETURN(MapProcessCodeMemory(system, process_handle, dst_address, src_address, size));
}
Result UnmapProcessCodeMemory64From32(Core::System& system, Handle process_handle,
uint64_t dst_address, uint64_t src_address, uint64_t size) {
R_RETURN(UnmapProcessCodeMemory(system, process_handle, dst_address, src_address, size));
}
} // namespace Kernel::Svc

View File

@@ -9,12 +9,16 @@
namespace Kernel::Svc {
/// Get which CPU core is executing the current thread
u32 GetCurrentProcessorNumber(Core::System& system) {
int32_t GetCurrentProcessorNumber(Core::System& system) {
LOG_TRACE(Kernel_SVC, "called");
return static_cast<u32>(system.CurrentPhysicalCore().CoreIndex());
return static_cast<int32_t>(system.CurrentPhysicalCore().CoreIndex());
}
u32 GetCurrentProcessorNumber32(Core::System& system) {
int32_t GetCurrentProcessorNumber64(Core::System& system) {
return GetCurrentProcessorNumber(system);
}
int32_t GetCurrentProcessorNumber64From32(Core::System& system) {
return GetCurrentProcessorNumber(system);
}

View File

@@ -7,26 +7,22 @@
namespace Kernel::Svc {
Result QueryMemory(Core::System& system, VAddr memory_info_address, VAddr page_info_address,
Result QueryMemory(Core::System& system, uint64_t out_memory_info, PageInfo* out_page_info,
VAddr query_address) {
LOG_TRACE(Kernel_SVC,
"called, memory_info_address=0x{:016X}, page_info_address=0x{:016X}, "
"called, out_memory_info=0x{:016X}, "
"query_address=0x{:016X}",
memory_info_address, page_info_address, query_address);
out_memory_info, query_address);
return QueryProcessMemory(system, memory_info_address, page_info_address, CurrentProcess,
// Query memory is just QueryProcessMemory on the current process.
return QueryProcessMemory(system, out_memory_info, out_page_info, CurrentProcess,
query_address);
}
Result QueryMemory32(Core::System& system, u32 memory_info_address, u32 page_info_address,
u32 query_address) {
return QueryMemory(system, memory_info_address, page_info_address, query_address);
}
Result QueryProcessMemory(Core::System& system, VAddr memory_info_address, VAddr page_info_address,
Handle process_handle, VAddr address) {
Result QueryProcessMemory(Core::System& system, uint64_t out_memory_info, PageInfo* out_page_info,
Handle process_handle, uint64_t address) {
LOG_TRACE(Kernel_SVC, "called process=0x{:08X} address={:X}", process_handle, address);
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle);
if (process.IsNull()) {
LOG_ERROR(Kernel_SVC, "Process handle does not exist, process_handle=0x{:08X}",
@@ -37,19 +33,33 @@ Result QueryProcessMemory(Core::System& system, VAddr memory_info_address, VAddr
auto& memory{system.Memory()};
const auto memory_info{process->PageTable().QueryInfo(address).GetSvcMemoryInfo()};
memory.Write64(memory_info_address + 0x00, memory_info.base_address);
memory.Write64(memory_info_address + 0x08, memory_info.size);
memory.Write32(memory_info_address + 0x10, static_cast<u32>(memory_info.state) & 0xff);
memory.Write32(memory_info_address + 0x14, static_cast<u32>(memory_info.attribute));
memory.Write32(memory_info_address + 0x18, static_cast<u32>(memory_info.permission));
memory.Write32(memory_info_address + 0x1c, memory_info.ipc_count);
memory.Write32(memory_info_address + 0x20, memory_info.device_count);
memory.Write32(memory_info_address + 0x24, 0);
memory.WriteBlock(out_memory_info, &memory_info, sizeof(memory_info));
// Page info appears to be currently unused by the kernel and is always set to zero.
memory.Write32(page_info_address, 0);
//! This is supposed to be part of the QueryInfo call.
*out_page_info = {};
return ResultSuccess;
R_SUCCEED();
}
Result QueryMemory64(Core::System& system, uint64_t out_memory_info, PageInfo* out_page_info,
uint64_t address) {
R_RETURN(QueryMemory(system, out_memory_info, out_page_info, address));
}
Result QueryProcessMemory64(Core::System& system, uint64_t out_memory_info, PageInfo* out_page_info,
Handle process_handle, uint64_t address) {
R_RETURN(QueryProcessMemory(system, out_memory_info, out_page_info, process_handle, address));
}
Result QueryMemory64From32(Core::System& system, uint32_t out_memory_info, PageInfo* out_page_info,
uint32_t address) {
R_RETURN(QueryMemory(system, out_memory_info, out_page_info, address));
}
Result QueryProcessMemory64From32(Core::System& system, uint32_t out_memory_info,
PageInfo* out_page_info, Handle process_handle,
uint64_t address) {
R_RETURN(QueryProcessMemory(system, out_memory_info, out_page_info, process_handle, address));
}
} // namespace Kernel::Svc

View File

@@ -2,5 +2,26 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/kernel/svc.h"
#include "core/hle/kernel/svc_results.h"
namespace Kernel::Svc {} // namespace Kernel::Svc
namespace Kernel::Svc {
Result ReadWriteRegister(Core::System& system, uint32_t* out, uint64_t address, uint32_t mask,
uint32_t value) {
*out = 0;
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result ReadWriteRegister64(Core::System& system, uint32_t* out_value, uint64_t address,
uint32_t mask, uint32_t value) {
R_RETURN(ReadWriteRegister(system, out_value, address, mask, value));
}
Result ReadWriteRegister64From32(Core::System& system, uint32_t* out_value, uint64_t address,
uint32_t mask, uint32_t value) {
R_RETURN(ReadWriteRegister(system, out_value, address, mask, value));
}
} // namespace Kernel::Svc

View File

@@ -27,12 +27,12 @@ Result CreateResourceLimit(Core::System& system, Handle* out_handle) {
KResourceLimit::Register(kernel, resource_limit);
// Add the limit to the handle table.
R_TRY(kernel.CurrentProcess()->GetHandleTable().Add(out_handle, resource_limit));
R_TRY(GetCurrentProcess(kernel).GetHandleTable().Add(out_handle, resource_limit));
return ResultSuccess;
}
Result GetResourceLimitLimitValue(Core::System& system, u64* out_limit_value,
Result GetResourceLimitLimitValue(Core::System& system, s64* out_limit_value,
Handle resource_limit_handle, LimitableResource which) {
LOG_DEBUG(Kernel_SVC, "called, resource_limit_handle={:08X}, which={}", resource_limit_handle,
which);
@@ -41,9 +41,9 @@ Result GetResourceLimitLimitValue(Core::System& system, u64* out_limit_value,
R_UNLESS(IsValidResourceType(which), ResultInvalidEnumValue);
// Get the resource limit.
auto& kernel = system.Kernel();
KScopedAutoObject resource_limit =
kernel.CurrentProcess()->GetHandleTable().GetObject<KResourceLimit>(resource_limit_handle);
KScopedAutoObject resource_limit = GetCurrentProcess(system.Kernel())
.GetHandleTable()
.GetObject<KResourceLimit>(resource_limit_handle);
R_UNLESS(resource_limit.IsNotNull(), ResultInvalidHandle);
// Get the limit value.
@@ -52,7 +52,7 @@ Result GetResourceLimitLimitValue(Core::System& system, u64* out_limit_value,
return ResultSuccess;
}
Result GetResourceLimitCurrentValue(Core::System& system, u64* out_current_value,
Result GetResourceLimitCurrentValue(Core::System& system, s64* out_current_value,
Handle resource_limit_handle, LimitableResource which) {
LOG_DEBUG(Kernel_SVC, "called, resource_limit_handle={:08X}, which={}", resource_limit_handle,
which);
@@ -61,9 +61,9 @@ Result GetResourceLimitCurrentValue(Core::System& system, u64* out_current_value
R_UNLESS(IsValidResourceType(which), ResultInvalidEnumValue);
// Get the resource limit.
auto& kernel = system.Kernel();
KScopedAutoObject resource_limit =
kernel.CurrentProcess()->GetHandleTable().GetObject<KResourceLimit>(resource_limit_handle);
KScopedAutoObject resource_limit = GetCurrentProcess(system.Kernel())
.GetHandleTable()
.GetObject<KResourceLimit>(resource_limit_handle);
R_UNLESS(resource_limit.IsNotNull(), ResultInvalidHandle);
// Get the current value.
@@ -73,7 +73,7 @@ Result GetResourceLimitCurrentValue(Core::System& system, u64* out_current_value
}
Result SetResourceLimitLimitValue(Core::System& system, Handle resource_limit_handle,
LimitableResource which, u64 limit_value) {
LimitableResource which, s64 limit_value) {
LOG_DEBUG(Kernel_SVC, "called, resource_limit_handle={:08X}, which={}, limit_value={}",
resource_limit_handle, which, limit_value);
@@ -81,9 +81,9 @@ Result SetResourceLimitLimitValue(Core::System& system, Handle resource_limit_ha
R_UNLESS(IsValidResourceType(which), ResultInvalidEnumValue);
// Get the resource limit.
auto& kernel = system.Kernel();
KScopedAutoObject resource_limit =
kernel.CurrentProcess()->GetHandleTable().GetObject<KResourceLimit>(resource_limit_handle);
KScopedAutoObject resource_limit = GetCurrentProcess(system.Kernel())
.GetHandleTable()
.GetObject<KResourceLimit>(resource_limit_handle);
R_UNLESS(resource_limit.IsNotNull(), ResultInvalidHandle);
// Set the limit value.
@@ -92,4 +92,58 @@ Result SetResourceLimitLimitValue(Core::System& system, Handle resource_limit_ha
return ResultSuccess;
}
Result GetResourceLimitPeakValue(Core::System& system, int64_t* out_peak_value,
Handle resource_limit_handle, LimitableResource which) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result GetResourceLimitLimitValue64(Core::System& system, int64_t* out_limit_value,
Handle resource_limit_handle, LimitableResource which) {
R_RETURN(GetResourceLimitLimitValue(system, out_limit_value, resource_limit_handle, which));
}
Result GetResourceLimitCurrentValue64(Core::System& system, int64_t* out_current_value,
Handle resource_limit_handle, LimitableResource which) {
R_RETURN(GetResourceLimitCurrentValue(system, out_current_value, resource_limit_handle, which));
}
Result GetResourceLimitPeakValue64(Core::System& system, int64_t* out_peak_value,
Handle resource_limit_handle, LimitableResource which) {
R_RETURN(GetResourceLimitPeakValue(system, out_peak_value, resource_limit_handle, which));
}
Result CreateResourceLimit64(Core::System& system, Handle* out_handle) {
R_RETURN(CreateResourceLimit(system, out_handle));
}
Result SetResourceLimitLimitValue64(Core::System& system, Handle resource_limit_handle,
LimitableResource which, int64_t limit_value) {
R_RETURN(SetResourceLimitLimitValue(system, resource_limit_handle, which, limit_value));
}
Result GetResourceLimitLimitValue64From32(Core::System& system, int64_t* out_limit_value,
Handle resource_limit_handle, LimitableResource which) {
R_RETURN(GetResourceLimitLimitValue(system, out_limit_value, resource_limit_handle, which));
}
Result GetResourceLimitCurrentValue64From32(Core::System& system, int64_t* out_current_value,
Handle resource_limit_handle, LimitableResource which) {
R_RETURN(GetResourceLimitCurrentValue(system, out_current_value, resource_limit_handle, which));
}
Result GetResourceLimitPeakValue64From32(Core::System& system, int64_t* out_peak_value,
Handle resource_limit_handle, LimitableResource which) {
R_RETURN(GetResourceLimitPeakValue(system, out_peak_value, resource_limit_handle, which));
}
Result CreateResourceLimit64From32(Core::System& system, Handle* out_handle) {
R_RETURN(CreateResourceLimit(system, out_handle));
}
Result SetResourceLimitLimitValue64From32(Core::System& system, Handle resource_limit_handle,
LimitableResource which, int64_t limit_value) {
R_RETURN(SetResourceLimitLimitValue(system, resource_limit_handle, which, limit_value));
}
} // namespace Kernel::Svc

View File

@@ -1,6 +1,53 @@
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/core.h"
#include "core/hle/kernel/physical_core.h"
#include "core/hle/kernel/svc.h"
namespace Kernel::Svc {} // namespace Kernel::Svc
namespace Kernel::Svc {
void CallSecureMonitor(Core::System& system, lp64::SecureMonitorArguments* args) {
UNIMPLEMENTED();
}
void CallSecureMonitor64(Core::System& system, lp64::SecureMonitorArguments* args) {
CallSecureMonitor(system, args);
}
void CallSecureMonitor64From32(Core::System& system, ilp32::SecureMonitorArguments* args) {
// CallSecureMonitor64From32 is not supported.
UNIMPLEMENTED_MSG("CallSecureMonitor64From32");
}
// Custom ABI for CallSecureMonitor.
void SvcWrap_CallSecureMonitor64(Core::System& system) {
auto& core = system.CurrentPhysicalCore().ArmInterface();
lp64::SecureMonitorArguments args{};
for (int i = 0; i < 8; i++) {
args.r[i] = core.GetReg(i);
}
CallSecureMonitor64(system, &args);
for (int i = 0; i < 8; i++) {
core.SetReg(i, args.r[i]);
}
}
void SvcWrap_CallSecureMonitor64From32(Core::System& system) {
auto& core = system.CurrentPhysicalCore().ArmInterface();
ilp32::SecureMonitorArguments args{};
for (int i = 0; i < 8; i++) {
args.r[i] = static_cast<u32>(core.GetReg(i));
}
CallSecureMonitor64From32(system, &args);
for (int i = 0; i < 8; i++) {
core.SetReg(i, args.r[i]);
}
}
} // namespace Kernel::Svc

View File

@@ -13,7 +13,7 @@ namespace {
template <typename T>
Result CreateSession(Core::System& system, Handle* out_server, Handle* out_client, u64 name) {
auto& process = *system.CurrentProcess();
auto& process = GetCurrentProcess(system.Kernel());
auto& handle_table = process.GetHandleTable();
// Declare the session we're going to allocate.
@@ -90,14 +90,39 @@ Result CreateSession(Core::System& system, Handle* out_server, Handle* out_clien
} // namespace
Result CreateSession(Core::System& system, Handle* out_server, Handle* out_client, u32 is_light,
Result CreateSession(Core::System& system, Handle* out_server, Handle* out_client, bool is_light,
u64 name) {
if (is_light) {
// return CreateSession<KLightSession>(system, out_server, out_client, name);
return ResultUnknown;
return ResultNotImplemented;
} else {
return CreateSession<KSession>(system, out_server, out_client, name);
}
}
Result AcceptSession(Core::System& system, Handle* out_handle, Handle port_handle) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result CreateSession64(Core::System& system, Handle* out_server_session_handle,
Handle* out_client_session_handle, bool is_light, uint64_t name) {
R_RETURN(CreateSession(system, out_server_session_handle, out_client_session_handle, is_light,
name));
}
Result AcceptSession64(Core::System& system, Handle* out_handle, Handle port) {
R_RETURN(AcceptSession(system, out_handle, port));
}
Result CreateSession64From32(Core::System& system, Handle* out_server_session_handle,
Handle* out_client_session_handle, bool is_light, uint32_t name) {
R_RETURN(CreateSession(system, out_server_session_handle, out_client_session_handle, is_light,
name));
}
Result AcceptSession64From32(Core::System& system, Handle* out_handle, Handle port) {
R_RETURN(AcceptSession(system, out_handle, port));
}
} // namespace Kernel::Svc

View File

@@ -42,7 +42,7 @@ Result MapSharedMemory(Core::System& system, Handle shmem_handle, VAddr address,
R_UNLESS(IsValidSharedMemoryPermission(map_perm), ResultInvalidNewMemoryPermission);
// Get the current process.
auto& process = *system.Kernel().CurrentProcess();
auto& process = GetCurrentProcess(system.Kernel());
auto& page_table = process.PageTable();
// Get the shared memory.
@@ -67,11 +67,6 @@ Result MapSharedMemory(Core::System& system, Handle shmem_handle, VAddr address,
return ResultSuccess;
}
Result MapSharedMemory32(Core::System& system, Handle shmem_handle, u32 address, u32 size,
Svc::MemoryPermission map_perm) {
return MapSharedMemory(system, shmem_handle, address, size, map_perm);
}
Result UnmapSharedMemory(Core::System& system, Handle shmem_handle, VAddr address, u64 size) {
// Validate the address/size.
R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress);
@@ -80,7 +75,7 @@ Result UnmapSharedMemory(Core::System& system, Handle shmem_handle, VAddr addres
R_UNLESS((address < address + size), ResultInvalidCurrentMemory);
// Get the current process.
auto& process = *system.Kernel().CurrentProcess();
auto& process = GetCurrentProcess(system.Kernel());
auto& page_table = process.PageTable();
// Get the shared memory.
@@ -99,8 +94,40 @@ Result UnmapSharedMemory(Core::System& system, Handle shmem_handle, VAddr addres
return ResultSuccess;
}
Result UnmapSharedMemory32(Core::System& system, Handle shmem_handle, u32 address, u32 size) {
return UnmapSharedMemory(system, shmem_handle, address, size);
Result CreateSharedMemory(Core::System& system, Handle* out_handle, uint64_t size,
MemoryPermission owner_perm, MemoryPermission remote_perm) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result MapSharedMemory64(Core::System& system, Handle shmem_handle, uint64_t address, uint64_t size,
MemoryPermission map_perm) {
R_RETURN(MapSharedMemory(system, shmem_handle, address, size, map_perm));
}
Result UnmapSharedMemory64(Core::System& system, Handle shmem_handle, uint64_t address,
uint64_t size) {
R_RETURN(UnmapSharedMemory(system, shmem_handle, address, size));
}
Result CreateSharedMemory64(Core::System& system, Handle* out_handle, uint64_t size,
MemoryPermission owner_perm, MemoryPermission remote_perm) {
R_RETURN(CreateSharedMemory(system, out_handle, size, owner_perm, remote_perm));
}
Result MapSharedMemory64From32(Core::System& system, Handle shmem_handle, uint32_t address,
uint32_t size, MemoryPermission map_perm) {
R_RETURN(MapSharedMemory(system, shmem_handle, address, size, map_perm));
}
Result UnmapSharedMemory64From32(Core::System& system, Handle shmem_handle, uint32_t address,
uint32_t size) {
R_RETURN(UnmapSharedMemory(system, shmem_handle, address, size));
}
Result CreateSharedMemory64From32(Core::System& system, Handle* out_handle, uint32_t size,
MemoryPermission owner_perm, MemoryPermission remote_perm) {
R_RETURN(CreateSharedMemory(system, out_handle, size, owner_perm, remote_perm));
}
} // namespace Kernel::Svc

View File

@@ -14,22 +14,18 @@ Result CloseHandle(Core::System& system, Handle handle) {
LOG_TRACE(Kernel_SVC, "Closing handle 0x{:08X}", handle);
// Remove the handle.
R_UNLESS(system.Kernel().CurrentProcess()->GetHandleTable().Remove(handle),
R_UNLESS(GetCurrentProcess(system.Kernel()).GetHandleTable().Remove(handle),
ResultInvalidHandle);
return ResultSuccess;
}
Result CloseHandle32(Core::System& system, Handle handle) {
return CloseHandle(system, handle);
}
/// Clears the signaled state of an event or process.
Result ResetSignal(Core::System& system, Handle handle) {
LOG_DEBUG(Kernel_SVC, "called handle 0x{:08X}", handle);
// Get the current handle table.
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
// Try to reset as readable event.
{
@@ -52,10 +48,6 @@ Result ResetSignal(Core::System& system, Handle handle) {
return ResultInvalidHandle;
}
Result ResetSignal32(Core::System& system, Handle handle) {
return ResetSignal(system, handle);
}
/// Wait for the given handles to synchronize, timeout after the specified nanoseconds
Result WaitSynchronization(Core::System& system, s32* index, VAddr handles_address, s32 num_handles,
s64 nano_seconds) {
@@ -67,7 +59,7 @@ Result WaitSynchronization(Core::System& system, s32* index, VAddr handles_addre
auto& kernel = system.Kernel();
std::vector<KSynchronizationObject*> objs(num_handles);
const auto& handle_table = kernel.CurrentProcess()->GetHandleTable();
const auto& handle_table = GetCurrentProcess(kernel).GetHandleTable();
Handle* handles = system.Memory().GetPointer<Handle>(handles_address);
// Copy user handles.
@@ -93,19 +85,13 @@ Result WaitSynchronization(Core::System& system, s32* index, VAddr handles_addre
nano_seconds);
}
Result WaitSynchronization32(Core::System& system, u32 timeout_low, u32 handles_address,
s32 num_handles, u32 timeout_high, s32* index) {
const s64 nano_seconds{(static_cast<s64>(timeout_high) << 32) | static_cast<s64>(timeout_low)};
return WaitSynchronization(system, index, handles_address, num_handles, nano_seconds);
}
/// Resumes a thread waiting on WaitSynchronization
Result CancelSynchronization(Core::System& system, Handle handle) {
LOG_TRACE(Kernel_SVC, "called handle=0x{:X}", handle);
// Get the thread from its handle.
KScopedAutoObject thread =
system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>(handle);
GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KThread>(handle);
R_UNLESS(thread.IsNotNull(), ResultInvalidHandle);
// Cancel the thread's wait.
@@ -113,10 +99,6 @@ Result CancelSynchronization(Core::System& system, Handle handle) {
return ResultSuccess;
}
Result CancelSynchronization32(Core::System& system, Handle handle) {
return CancelSynchronization(system, handle);
}
void SynchronizePreemptionState(Core::System& system) {
auto& kernel = system.Kernel();
@@ -124,7 +106,7 @@ void SynchronizePreemptionState(Core::System& system) {
KScopedSchedulerLock sl{kernel};
// If the current thread is pinned, unpin it.
KProcess* cur_process = system.Kernel().CurrentProcess();
KProcess* cur_process = GetCurrentProcessPointer(kernel);
const auto core_id = GetCurrentCoreId(kernel);
if (cur_process->GetPinnedThread(core_id) == GetCurrentThreadPointer(kernel)) {
@@ -136,4 +118,46 @@ void SynchronizePreemptionState(Core::System& system) {
}
}
Result CloseHandle64(Core::System& system, Handle handle) {
R_RETURN(CloseHandle(system, handle));
}
Result ResetSignal64(Core::System& system, Handle handle) {
R_RETURN(ResetSignal(system, handle));
}
Result WaitSynchronization64(Core::System& system, int32_t* out_index, uint64_t handles,
int32_t num_handles, int64_t timeout_ns) {
R_RETURN(WaitSynchronization(system, out_index, handles, num_handles, timeout_ns));
}
Result CancelSynchronization64(Core::System& system, Handle handle) {
R_RETURN(CancelSynchronization(system, handle));
}
void SynchronizePreemptionState64(Core::System& system) {
SynchronizePreemptionState(system);
}
Result CloseHandle64From32(Core::System& system, Handle handle) {
R_RETURN(CloseHandle(system, handle));
}
Result ResetSignal64From32(Core::System& system, Handle handle) {
R_RETURN(ResetSignal(system, handle));
}
Result WaitSynchronization64From32(Core::System& system, int32_t* out_index, uint32_t handles,
int32_t num_handles, int64_t timeout_ns) {
R_RETURN(WaitSynchronization(system, out_index, handles, num_handles, timeout_ns));
}
Result CancelSynchronization64From32(Core::System& system, Handle handle) {
R_RETURN(CancelSynchronization(system, handle));
}
void SynchronizePreemptionState64From32(Core::System& system) {
SynchronizePreemptionState(system);
}
} // namespace Kernel::Svc

View File

@@ -20,7 +20,7 @@ constexpr bool IsValidVirtualCoreId(int32_t core_id) {
/// Creates a new thread
Result CreateThread(Core::System& system, Handle* out_handle, VAddr entry_point, u64 arg,
VAddr stack_bottom, u32 priority, s32 core_id) {
VAddr stack_bottom, s32 priority, s32 core_id) {
LOG_DEBUG(Kernel_SVC,
"called entry_point=0x{:08X}, arg=0x{:08X}, stack_bottom=0x{:08X}, "
"priority=0x{:08X}, core_id=0x{:08X}",
@@ -28,7 +28,7 @@ Result CreateThread(Core::System& system, Handle* out_handle, VAddr entry_point,
// Adjust core id, if it's the default magic.
auto& kernel = system.Kernel();
auto& process = *kernel.CurrentProcess();
auto& process = GetCurrentProcess(kernel);
if (core_id == IdealCoreUseProcessValue) {
core_id = process.GetIdealCoreId();
}
@@ -53,9 +53,9 @@ Result CreateThread(Core::System& system, Handle* out_handle, VAddr entry_point,
}
// Reserve a new thread from the process resource limit (waiting up to 100ms).
KScopedResourceReservation thread_reservation(
kernel.CurrentProcess(), LimitableResource::ThreadCountMax, 1,
system.CoreTiming().GetGlobalTimeNs().count() + 100000000);
KScopedResourceReservation thread_reservation(&process, LimitableResource::ThreadCountMax, 1,
system.CoreTiming().GetGlobalTimeNs().count() +
100000000);
if (!thread_reservation.Succeeded()) {
LOG_ERROR(Kernel_SVC, "Could not reserve a new thread");
return ResultLimitReached;
@@ -91,18 +91,13 @@ Result CreateThread(Core::System& system, Handle* out_handle, VAddr entry_point,
return ResultSuccess;
}
Result CreateThread32(Core::System& system, Handle* out_handle, u32 priority, u32 entry_point,
u32 arg, u32 stack_top, s32 processor_id) {
return CreateThread(system, out_handle, entry_point, arg, stack_top, priority, processor_id);
}
/// Starts the thread for the provided handle
Result StartThread(Core::System& system, Handle thread_handle) {
LOG_DEBUG(Kernel_SVC, "called thread=0x{:08X}", thread_handle);
// Get the thread from its handle.
KScopedAutoObject thread =
system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>(thread_handle);
GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KThread>(thread_handle);
R_UNLESS(thread.IsNotNull(), ResultInvalidHandle);
// Try to start the thread.
@@ -115,10 +110,6 @@ Result StartThread(Core::System& system, Handle thread_handle) {
return ResultSuccess;
}
Result StartThread32(Core::System& system, Handle thread_handle) {
return StartThread(system, thread_handle);
}
/// Called when a thread exits
void ExitThread(Core::System& system) {
LOG_DEBUG(Kernel_SVC, "called, pc=0x{:08X}", system.CurrentArmInterface().GetPC());
@@ -129,10 +120,6 @@ void ExitThread(Core::System& system) {
system.Kernel().UnregisterInUseObject(current_thread);
}
void ExitThread32(Core::System& system) {
ExitThread(system);
}
/// Sleep the current thread
void SleepThread(Core::System& system, s64 nanoseconds) {
auto& kernel = system.Kernel();
@@ -160,13 +147,8 @@ void SleepThread(Core::System& system, s64 nanoseconds) {
}
}
void SleepThread32(Core::System& system, u32 nanoseconds_low, u32 nanoseconds_high) {
const auto nanoseconds = static_cast<s64>(u64{nanoseconds_low} | (u64{nanoseconds_high} << 32));
SleepThread(system, nanoseconds);
}
/// Gets the thread context
Result GetThreadContext(Core::System& system, VAddr out_context, Handle thread_handle) {
Result GetThreadContext3(Core::System& system, VAddr out_context, Handle thread_handle) {
LOG_DEBUG(Kernel_SVC, "called, out_context=0x{:08X}, thread_handle=0x{:X}", out_context,
thread_handle);
@@ -174,11 +156,11 @@ Result GetThreadContext(Core::System& system, VAddr out_context, Handle thread_h
// Get the thread from its handle.
KScopedAutoObject thread =
kernel.CurrentProcess()->GetHandleTable().GetObject<KThread>(thread_handle);
GetCurrentProcess(kernel).GetHandleTable().GetObject<KThread>(thread_handle);
R_UNLESS(thread.IsNotNull(), ResultInvalidHandle);
// Require the handle be to a non-current thread in the current process.
const auto* current_process = kernel.CurrentProcess();
const auto* current_process = GetCurrentProcessPointer(kernel);
R_UNLESS(current_process == thread->GetOwnerProcess(), ResultInvalidId);
// Verify that the thread isn't terminated.
@@ -223,17 +205,13 @@ Result GetThreadContext(Core::System& system, VAddr out_context, Handle thread_h
return ResultSuccess;
}
Result GetThreadContext32(Core::System& system, u32 out_context, Handle thread_handle) {
return GetThreadContext(system, out_context, thread_handle);
}
/// Gets the priority for the specified thread
Result GetThreadPriority(Core::System& system, u32* out_priority, Handle handle) {
Result GetThreadPriority(Core::System& system, s32* out_priority, Handle handle) {
LOG_TRACE(Kernel_SVC, "called");
// Get the thread from its handle.
KScopedAutoObject thread =
system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>(handle);
GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KThread>(handle);
R_UNLESS(thread.IsNotNull(), ResultInvalidHandle);
// Get the thread's priority.
@@ -241,14 +219,10 @@ Result GetThreadPriority(Core::System& system, u32* out_priority, Handle handle)
return ResultSuccess;
}
Result GetThreadPriority32(Core::System& system, u32* out_priority, Handle handle) {
return GetThreadPriority(system, out_priority, handle);
}
/// Sets the priority for the specified thread
Result SetThreadPriority(Core::System& system, Handle thread_handle, u32 priority) {
Result SetThreadPriority(Core::System& system, Handle thread_handle, s32 priority) {
// Get the current process.
KProcess& process = *system.Kernel().CurrentProcess();
KProcess& process = GetCurrentProcess(system.Kernel());
// Validate the priority.
R_UNLESS(HighestThreadPriority <= priority && priority <= LowestThreadPriority,
@@ -264,12 +238,8 @@ Result SetThreadPriority(Core::System& system, Handle thread_handle, u32 priorit
return ResultSuccess;
}
Result SetThreadPriority32(Core::System& system, Handle thread_handle, u32 priority) {
return SetThreadPriority(system, thread_handle, priority);
}
Result GetThreadList(Core::System& system, u32* out_num_threads, VAddr out_thread_ids,
u32 out_thread_ids_size, Handle debug_handle) {
Result GetThreadList(Core::System& system, s32* out_num_threads, VAddr out_thread_ids,
s32 out_thread_ids_size, Handle debug_handle) {
// TODO: Handle this case when debug events are supported.
UNIMPLEMENTED_IF(debug_handle != InvalidHandle);
@@ -283,7 +253,7 @@ Result GetThreadList(Core::System& system, u32* out_num_threads, VAddr out_threa
return ResultOutOfRange;
}
auto* const current_process = system.Kernel().CurrentProcess();
auto* const current_process = GetCurrentProcessPointer(system.Kernel());
const auto total_copy_size = out_thread_ids_size * sizeof(u64);
if (out_thread_ids_size > 0 &&
@@ -296,7 +266,7 @@ Result GetThreadList(Core::System& system, u32* out_num_threads, VAddr out_threa
auto& memory = system.Memory();
const auto& thread_list = current_process->GetThreadList();
const auto num_threads = thread_list.size();
const auto copy_amount = std::min(std::size_t{out_thread_ids_size}, num_threads);
const auto copy_amount = std::min(static_cast<std::size_t>(out_thread_ids_size), num_threads);
auto list_iter = thread_list.cbegin();
for (std::size_t i = 0; i < copy_amount; ++i, ++list_iter) {
@@ -308,13 +278,13 @@ Result GetThreadList(Core::System& system, u32* out_num_threads, VAddr out_threa
return ResultSuccess;
}
Result GetThreadCoreMask(Core::System& system, Handle thread_handle, s32* out_core_id,
u64* out_affinity_mask) {
Result GetThreadCoreMask(Core::System& system, s32* out_core_id, u64* out_affinity_mask,
Handle thread_handle) {
LOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle);
// Get the thread from its handle.
KScopedAutoObject thread =
system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>(thread_handle);
GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KThread>(thread_handle);
R_UNLESS(thread.IsNotNull(), ResultInvalidHandle);
// Get the core mask.
@@ -323,24 +293,15 @@ Result GetThreadCoreMask(Core::System& system, Handle thread_handle, s32* out_co
return ResultSuccess;
}
Result GetThreadCoreMask32(Core::System& system, Handle thread_handle, s32* out_core_id,
u32* out_affinity_mask_low, u32* out_affinity_mask_high) {
u64 out_affinity_mask{};
const auto result = GetThreadCoreMask(system, thread_handle, out_core_id, &out_affinity_mask);
*out_affinity_mask_high = static_cast<u32>(out_affinity_mask >> 32);
*out_affinity_mask_low = static_cast<u32>(out_affinity_mask);
return result;
}
Result SetThreadCoreMask(Core::System& system, Handle thread_handle, s32 core_id,
u64 affinity_mask) {
// Determine the core id/affinity mask.
if (core_id == IdealCoreUseProcessValue) {
core_id = system.Kernel().CurrentProcess()->GetIdealCoreId();
core_id = GetCurrentProcess(system.Kernel()).GetIdealCoreId();
affinity_mask = (1ULL << core_id);
} else {
// Validate the affinity mask.
const u64 process_core_mask = system.Kernel().CurrentProcess()->GetCoreMask();
const u64 process_core_mask = GetCurrentProcess(system.Kernel()).GetCoreMask();
R_UNLESS((affinity_mask | process_core_mask) == process_core_mask, ResultInvalidCoreId);
R_UNLESS(affinity_mask != 0, ResultInvalidCombination);
@@ -355,7 +316,7 @@ Result SetThreadCoreMask(Core::System& system, Handle thread_handle, s32 core_id
// Get the thread from its handle.
KScopedAutoObject thread =
system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>(thread_handle);
GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KThread>(thread_handle);
R_UNLESS(thread.IsNotNull(), ResultInvalidHandle);
// Set the core mask.
@@ -364,17 +325,11 @@ Result SetThreadCoreMask(Core::System& system, Handle thread_handle, s32 core_id
return ResultSuccess;
}
Result SetThreadCoreMask32(Core::System& system, Handle thread_handle, s32 core_id,
u32 affinity_mask_low, u32 affinity_mask_high) {
const auto affinity_mask = u64{affinity_mask_low} | (u64{affinity_mask_high} << 32);
return SetThreadCoreMask(system, thread_handle, core_id, affinity_mask);
}
/// Get the ID for the specified thread.
Result GetThreadId(Core::System& system, u64* out_thread_id, Handle thread_handle) {
// Get the thread from its handle.
KScopedAutoObject thread =
system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>(thread_handle);
GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KThread>(thread_handle);
R_UNLESS(thread.IsNotNull(), ResultInvalidHandle);
// Get the thread's id.
@@ -382,15 +337,101 @@ Result GetThreadId(Core::System& system, u64* out_thread_id, Handle thread_handl
return ResultSuccess;
}
Result GetThreadId32(Core::System& system, u32* out_thread_id_low, u32* out_thread_id_high,
Handle thread_handle) {
u64 out_thread_id{};
const Result result{GetThreadId(system, &out_thread_id, thread_handle)};
Result CreateThread64(Core::System& system, Handle* out_handle, uint64_t func, uint64_t arg,
uint64_t stack_bottom, int32_t priority, int32_t core_id) {
R_RETURN(CreateThread(system, out_handle, func, arg, stack_bottom, priority, core_id));
}
*out_thread_id_low = static_cast<u32>(out_thread_id >> 32);
*out_thread_id_high = static_cast<u32>(out_thread_id & std::numeric_limits<u32>::max());
Result StartThread64(Core::System& system, Handle thread_handle) {
R_RETURN(StartThread(system, thread_handle));
}
return result;
void ExitThread64(Core::System& system) {
return ExitThread(system);
}
void SleepThread64(Core::System& system, int64_t ns) {
return SleepThread(system, ns);
}
Result GetThreadPriority64(Core::System& system, int32_t* out_priority, Handle thread_handle) {
R_RETURN(GetThreadPriority(system, out_priority, thread_handle));
}
Result SetThreadPriority64(Core::System& system, Handle thread_handle, int32_t priority) {
R_RETURN(SetThreadPriority(system, thread_handle, priority));
}
Result GetThreadCoreMask64(Core::System& system, int32_t* out_core_id, uint64_t* out_affinity_mask,
Handle thread_handle) {
R_RETURN(GetThreadCoreMask(system, out_core_id, out_affinity_mask, thread_handle));
}
Result SetThreadCoreMask64(Core::System& system, Handle thread_handle, int32_t core_id,
uint64_t affinity_mask) {
R_RETURN(SetThreadCoreMask(system, thread_handle, core_id, affinity_mask));
}
Result GetThreadId64(Core::System& system, uint64_t* out_thread_id, Handle thread_handle) {
R_RETURN(GetThreadId(system, out_thread_id, thread_handle));
}
Result GetThreadContext364(Core::System& system, uint64_t out_context, Handle thread_handle) {
R_RETURN(GetThreadContext3(system, out_context, thread_handle));
}
Result GetThreadList64(Core::System& system, int32_t* out_num_threads, uint64_t out_thread_ids,
int32_t max_out_count, Handle debug_handle) {
R_RETURN(GetThreadList(system, out_num_threads, out_thread_ids, max_out_count, debug_handle));
}
Result CreateThread64From32(Core::System& system, Handle* out_handle, uint32_t func, uint32_t arg,
uint32_t stack_bottom, int32_t priority, int32_t core_id) {
R_RETURN(CreateThread(system, out_handle, func, arg, stack_bottom, priority, core_id));
}
Result StartThread64From32(Core::System& system, Handle thread_handle) {
R_RETURN(StartThread(system, thread_handle));
}
void ExitThread64From32(Core::System& system) {
return ExitThread(system);
}
void SleepThread64From32(Core::System& system, int64_t ns) {
return SleepThread(system, ns);
}
Result GetThreadPriority64From32(Core::System& system, int32_t* out_priority,
Handle thread_handle) {
R_RETURN(GetThreadPriority(system, out_priority, thread_handle));
}
Result SetThreadPriority64From32(Core::System& system, Handle thread_handle, int32_t priority) {
R_RETURN(SetThreadPriority(system, thread_handle, priority));
}
Result GetThreadCoreMask64From32(Core::System& system, int32_t* out_core_id,
uint64_t* out_affinity_mask, Handle thread_handle) {
R_RETURN(GetThreadCoreMask(system, out_core_id, out_affinity_mask, thread_handle));
}
Result SetThreadCoreMask64From32(Core::System& system, Handle thread_handle, int32_t core_id,
uint64_t affinity_mask) {
R_RETURN(SetThreadCoreMask(system, thread_handle, core_id, affinity_mask));
}
Result GetThreadId64From32(Core::System& system, uint64_t* out_thread_id, Handle thread_handle) {
R_RETURN(GetThreadId(system, out_thread_id, thread_handle));
}
Result GetThreadContext364From32(Core::System& system, uint32_t out_context, Handle thread_handle) {
R_RETURN(GetThreadContext3(system, out_context, thread_handle));
}
Result GetThreadList64From32(Core::System& system, int32_t* out_num_threads,
uint32_t out_thread_ids, int32_t max_out_count, Handle debug_handle) {
R_RETURN(GetThreadList(system, out_num_threads, out_thread_ids, max_out_count, debug_handle));
}
} // namespace Kernel::Svc

View File

@@ -2,5 +2,59 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/kernel/svc.h"
#include "core/hle/kernel/svc_results.h"
namespace Kernel::Svc {} // namespace Kernel::Svc
namespace Kernel::Svc {
Result GetDebugFutureThreadInfo(Core::System& system, lp64::LastThreadContext* out_context,
uint64_t* out_thread_id, Handle debug_handle, int64_t ns) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result GetLastThreadInfo(Core::System& system, lp64::LastThreadContext* out_context,
uint64_t* out_tls_address, uint32_t* out_flags) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result GetDebugFutureThreadInfo64(Core::System& system, lp64::LastThreadContext* out_context,
uint64_t* out_thread_id, Handle debug_handle, int64_t ns) {
R_RETURN(GetDebugFutureThreadInfo(system, out_context, out_thread_id, debug_handle, ns));
}
Result GetLastThreadInfo64(Core::System& system, lp64::LastThreadContext* out_context,
uint64_t* out_tls_address, uint32_t* out_flags) {
R_RETURN(GetLastThreadInfo(system, out_context, out_tls_address, out_flags));
}
Result GetDebugFutureThreadInfo64From32(Core::System& system, ilp32::LastThreadContext* out_context,
uint64_t* out_thread_id, Handle debug_handle, int64_t ns) {
lp64::LastThreadContext context{};
R_TRY(
GetDebugFutureThreadInfo(system, std::addressof(context), out_thread_id, debug_handle, ns));
*out_context = {
.fp = static_cast<u32>(context.fp),
.sp = static_cast<u32>(context.sp),
.lr = static_cast<u32>(context.lr),
.pc = static_cast<u32>(context.pc),
};
R_SUCCEED();
}
Result GetLastThreadInfo64From32(Core::System& system, ilp32::LastThreadContext* out_context,
uint64_t* out_tls_address, uint32_t* out_flags) {
lp64::LastThreadContext context{};
R_TRY(GetLastThreadInfo(system, std::addressof(context), out_tls_address, out_flags));
*out_context = {
.fp = static_cast<u32>(context.fp),
.sp = static_cast<u32>(context.sp),
.lr = static_cast<u32>(context.lr),
.pc = static_cast<u32>(context.pc),
};
R_SUCCEED();
}
} // namespace Kernel::Svc

View File

@@ -9,7 +9,7 @@
namespace Kernel::Svc {
/// This returns the total CPU ticks elapsed since the CPU was powered-on
u64 GetSystemTick(Core::System& system) {
int64_t GetSystemTick(Core::System& system) {
LOG_TRACE(Kernel_SVC, "called");
auto& core_timing = system.CoreTiming();
@@ -21,13 +21,15 @@ u64 GetSystemTick(Core::System& system) {
core_timing.AddTicks(400U);
}
return result;
return static_cast<int64_t>(result);
}
void GetSystemTick32(Core::System& system, u32* time_low, u32* time_high) {
const auto time = GetSystemTick(system);
*time_low = static_cast<u32>(time);
*time_high = static_cast<u32>(time >> 32);
int64_t GetSystemTick64(Core::System& system) {
return GetSystemTick(system);
}
int64_t GetSystemTick64From32(Core::System& system) {
return GetSystemTick(system);
}
} // namespace Kernel::Svc

View File

@@ -39,11 +39,11 @@ Result CreateTransferMemory(Core::System& system, Handle* out, VAddr address, u6
R_UNLESS(IsValidTransferMemoryPermission(map_perm), ResultInvalidNewMemoryPermission);
// Get the current process and handle table.
auto& process = *kernel.CurrentProcess();
auto& process = GetCurrentProcess(kernel);
auto& handle_table = process.GetHandleTable();
// Reserve a new transfer memory from the process resource limit.
KScopedResourceReservation trmem_reservation(kernel.CurrentProcess(),
KScopedResourceReservation trmem_reservation(&process,
LimitableResource::TransferMemoryCountMax);
R_UNLESS(trmem_reservation.Succeeded(), ResultLimitReached);
@@ -72,8 +72,46 @@ Result CreateTransferMemory(Core::System& system, Handle* out, VAddr address, u6
return ResultSuccess;
}
Result CreateTransferMemory32(Core::System& system, Handle* out, u32 address, u32 size,
MemoryPermission map_perm) {
return CreateTransferMemory(system, out, address, size, map_perm);
Result MapTransferMemory(Core::System& system, Handle trmem_handle, uint64_t address, uint64_t size,
MemoryPermission owner_perm) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result UnmapTransferMemory(Core::System& system, Handle trmem_handle, uint64_t address,
uint64_t size) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
}
Result MapTransferMemory64(Core::System& system, Handle trmem_handle, uint64_t address,
uint64_t size, MemoryPermission owner_perm) {
R_RETURN(MapTransferMemory(system, trmem_handle, address, size, owner_perm));
}
Result UnmapTransferMemory64(Core::System& system, Handle trmem_handle, uint64_t address,
uint64_t size) {
R_RETURN(UnmapTransferMemory(system, trmem_handle, address, size));
}
Result CreateTransferMemory64(Core::System& system, Handle* out_handle, uint64_t address,
uint64_t size, MemoryPermission map_perm) {
R_RETURN(CreateTransferMemory(system, out_handle, address, size, map_perm));
}
Result MapTransferMemory64From32(Core::System& system, Handle trmem_handle, uint32_t address,
uint32_t size, MemoryPermission owner_perm) {
R_RETURN(MapTransferMemory(system, trmem_handle, address, size, owner_perm));
}
Result UnmapTransferMemory64From32(Core::System& system, Handle trmem_handle, uint32_t address,
uint32_t size) {
R_RETURN(UnmapTransferMemory(system, trmem_handle, address, size));
}
Result CreateTransferMemory64From32(Core::System& system, Handle* out_handle, uint32_t address,
uint32_t size, MemoryPermission map_perm) {
R_RETURN(CreateTransferMemory(system, out_handle, address, size, map_perm));
}
} // namespace Kernel::Svc

View File

@@ -0,0 +1,716 @@
# SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
# SPDX-License-Identifier: GPL-2.0-or-later
# Raw SVC definitions from the kernel.
#
# Avoid modifying the prototypes; see below for how to customize generation
# for a given typename.
SVCS = [
[0x01, "Result SetHeapSize(Address* out_address, Size size);"],
[0x02, "Result SetMemoryPermission(Address address, Size size, MemoryPermission perm);"],
[0x03, "Result SetMemoryAttribute(Address address, Size size, uint32_t mask, uint32_t attr);"],
[0x04, "Result MapMemory(Address dst_address, Address src_address, Size size);"],
[0x05, "Result UnmapMemory(Address dst_address, Address src_address, Size size);"],
[0x06, "Result QueryMemory(Address out_memory_info, PageInfo* out_page_info, Address address);"],
[0x07, "void ExitProcess();"],
[0x08, "Result CreateThread(Handle* out_handle, ThreadFunc func, Address arg, Address stack_bottom, int32_t priority, int32_t core_id);"],
[0x09, "Result StartThread(Handle thread_handle);"],
[0x0A, "void ExitThread();"],
[0x0B, "void SleepThread(int64_t ns);"],
[0x0C, "Result GetThreadPriority(int32_t* out_priority, Handle thread_handle);"],
[0x0D, "Result SetThreadPriority(Handle thread_handle, int32_t priority);"],
[0x0E, "Result GetThreadCoreMask(int32_t* out_core_id, uint64_t* out_affinity_mask, Handle thread_handle);"],
[0x0F, "Result SetThreadCoreMask(Handle thread_handle, int32_t core_id, uint64_t affinity_mask);"],
[0x10, "int32_t GetCurrentProcessorNumber();"],
[0x11, "Result SignalEvent(Handle event_handle);"],
[0x12, "Result ClearEvent(Handle event_handle);"],
[0x13, "Result MapSharedMemory(Handle shmem_handle, Address address, Size size, MemoryPermission map_perm);"],
[0x14, "Result UnmapSharedMemory(Handle shmem_handle, Address address, Size size);"],
[0x15, "Result CreateTransferMemory(Handle* out_handle, Address address, Size size, MemoryPermission map_perm);"],
[0x16, "Result CloseHandle(Handle handle);"],
[0x17, "Result ResetSignal(Handle handle);"],
[0x18, "Result WaitSynchronization(int32_t* out_index, Address handles, int32_t num_handles, int64_t timeout_ns);"],
[0x19, "Result CancelSynchronization(Handle handle);"],
[0x1A, "Result ArbitrateLock(Handle thread_handle, Address address, uint32_t tag);"],
[0x1B, "Result ArbitrateUnlock(Address address);"],
[0x1C, "Result WaitProcessWideKeyAtomic(Address address, Address cv_key, uint32_t tag, int64_t timeout_ns);"],
[0x1D, "void SignalProcessWideKey(Address cv_key, int32_t count);"],
[0x1E, "int64_t GetSystemTick();"],
[0x1F, "Result ConnectToNamedPort(Handle* out_handle, Address name);"],
[0x20, "Result SendSyncRequestLight(Handle session_handle);"],
[0x21, "Result SendSyncRequest(Handle session_handle);"],
[0x22, "Result SendSyncRequestWithUserBuffer(Address message_buffer, Size message_buffer_size, Handle session_handle);"],
[0x23, "Result SendAsyncRequestWithUserBuffer(Handle* out_event_handle, Address message_buffer, Size message_buffer_size, Handle session_handle);"],
[0x24, "Result GetProcessId(uint64_t* out_process_id, Handle process_handle);"],
[0x25, "Result GetThreadId(uint64_t* out_thread_id, Handle thread_handle);"],
[0x26, "void Break(BreakReason break_reason, Address arg, Size size);"],
[0x27, "Result OutputDebugString(Address debug_str, Size len);"],
[0x28, "void ReturnFromException(Result result);"],
[0x29, "Result GetInfo(uint64_t* out, InfoType info_type, Handle handle, uint64_t info_subtype);"],
[0x2A, "void FlushEntireDataCache();"],
[0x2B, "Result FlushDataCache(Address address, Size size);"],
[0x2C, "Result MapPhysicalMemory(Address address, Size size);"],
[0x2D, "Result UnmapPhysicalMemory(Address address, Size size);"],
[0x2E, "Result GetDebugFutureThreadInfo(LastThreadContext* out_context, uint64_t* out_thread_id, Handle debug_handle, int64_t ns);"],
[0x2F, "Result GetLastThreadInfo(LastThreadContext* out_context, Address* out_tls_address, uint32_t* out_flags);"],
[0x30, "Result GetResourceLimitLimitValue(int64_t* out_limit_value, Handle resource_limit_handle, LimitableResource which);"],
[0x31, "Result GetResourceLimitCurrentValue(int64_t* out_current_value, Handle resource_limit_handle, LimitableResource which);"],
[0x32, "Result SetThreadActivity(Handle thread_handle, ThreadActivity thread_activity);"],
[0x33, "Result GetThreadContext3(Address out_context, Handle thread_handle);"],
[0x34, "Result WaitForAddress(Address address, ArbitrationType arb_type, int32_t value, int64_t timeout_ns);"],
[0x35, "Result SignalToAddress(Address address, SignalType signal_type, int32_t value, int32_t count);"],
[0x36, "void SynchronizePreemptionState();"],
[0x37, "Result GetResourceLimitPeakValue(int64_t* out_peak_value, Handle resource_limit_handle, LimitableResource which);"],
[0x39, "Result CreateIoPool(Handle* out_handle, IoPoolType which);"],
[0x3A, "Result CreateIoRegion(Handle* out_handle, Handle io_pool, PhysicalAddress physical_address, Size size, MemoryMapping mapping, MemoryPermission perm);"],
[0x3C, "void KernelDebug(KernelDebugType kern_debug_type, uint64_t arg0, uint64_t arg1, uint64_t arg2);"],
[0x3D, "void ChangeKernelTraceState(KernelTraceState kern_trace_state);"],
[0x40, "Result CreateSession(Handle* out_server_session_handle, Handle* out_client_session_handle, bool is_light, Address name);"],
[0x41, "Result AcceptSession(Handle* out_handle, Handle port);"],
[0x42, "Result ReplyAndReceiveLight(Handle handle);"],
[0x43, "Result ReplyAndReceive(int32_t* out_index, Address handles, int32_t num_handles, Handle reply_target, int64_t timeout_ns);"],
[0x44, "Result ReplyAndReceiveWithUserBuffer(int32_t* out_index, Address message_buffer, Size message_buffer_size, Address handles, int32_t num_handles, Handle reply_target, int64_t timeout_ns);"],
[0x45, "Result CreateEvent(Handle* out_write_handle, Handle* out_read_handle);"],
[0x46, "Result MapIoRegion(Handle io_region, Address address, Size size, MemoryPermission perm);"],
[0x47, "Result UnmapIoRegion(Handle io_region, Address address, Size size);"],
[0x48, "Result MapPhysicalMemoryUnsafe(Address address, Size size);"],
[0x49, "Result UnmapPhysicalMemoryUnsafe(Address address, Size size);"],
[0x4A, "Result SetUnsafeLimit(Size limit);"],
[0x4B, "Result CreateCodeMemory(Handle* out_handle, Address address, Size size);"],
[0x4C, "Result ControlCodeMemory(Handle code_memory_handle, CodeMemoryOperation operation, uint64_t address, uint64_t size, MemoryPermission perm);"],
[0x4D, "void SleepSystem();"],
[0x4E, "Result ReadWriteRegister(uint32_t* out_value, PhysicalAddress address, uint32_t mask, uint32_t value);"],
[0x4F, "Result SetProcessActivity(Handle process_handle, ProcessActivity process_activity);"],
[0x50, "Result CreateSharedMemory(Handle* out_handle, Size size, MemoryPermission owner_perm, MemoryPermission remote_perm);"],
[0x51, "Result MapTransferMemory(Handle trmem_handle, Address address, Size size, MemoryPermission owner_perm);"],
[0x52, "Result UnmapTransferMemory(Handle trmem_handle, Address address, Size size);"],
[0x53, "Result CreateInterruptEvent(Handle* out_read_handle, int32_t interrupt_id, InterruptType interrupt_type);"],
[0x54, "Result QueryPhysicalAddress(PhysicalMemoryInfo* out_info, Address address);"],
[0x55, "Result QueryIoMapping(Address* out_address, Size* out_size, PhysicalAddress physical_address, Size size);"],
[0x56, "Result CreateDeviceAddressSpace(Handle* out_handle, uint64_t das_address, uint64_t das_size);"],
[0x57, "Result AttachDeviceAddressSpace(DeviceName device_name, Handle das_handle);"],
[0x58, "Result DetachDeviceAddressSpace(DeviceName device_name, Handle das_handle);"],
[0x59, "Result MapDeviceAddressSpaceByForce(Handle das_handle, Handle process_handle, uint64_t process_address, Size size, uint64_t device_address, uint32_t option);"],
[0x5A, "Result MapDeviceAddressSpaceAligned(Handle das_handle, Handle process_handle, uint64_t process_address, Size size, uint64_t device_address, uint32_t option);"],
[0x5C, "Result UnmapDeviceAddressSpace(Handle das_handle, Handle process_handle, uint64_t process_address, Size size, uint64_t device_address);"],
[0x5D, "Result InvalidateProcessDataCache(Handle process_handle, uint64_t address, uint64_t size);"],
[0x5E, "Result StoreProcessDataCache(Handle process_handle, uint64_t address, uint64_t size);"],
[0x5F, "Result FlushProcessDataCache(Handle process_handle, uint64_t address, uint64_t size);"],
[0x60, "Result DebugActiveProcess(Handle* out_handle, uint64_t process_id);"],
[0x61, "Result BreakDebugProcess(Handle debug_handle);"],
[0x62, "Result TerminateDebugProcess(Handle debug_handle);"],
[0x63, "Result GetDebugEvent(Address out_info, Handle debug_handle);"],
[0x64, "Result ContinueDebugEvent(Handle debug_handle, uint32_t flags, Address thread_ids, int32_t num_thread_ids);"],
[0x65, "Result GetProcessList(int32_t* out_num_processes, Address out_process_ids, int32_t max_out_count);"],
[0x66, "Result GetThreadList(int32_t* out_num_threads, Address out_thread_ids, int32_t max_out_count, Handle debug_handle);"],
[0x67, "Result GetDebugThreadContext(Address out_context, Handle debug_handle, uint64_t thread_id, uint32_t context_flags);"],
[0x68, "Result SetDebugThreadContext(Handle debug_handle, uint64_t thread_id, Address context, uint32_t context_flags);"],
[0x69, "Result QueryDebugProcessMemory(Address out_memory_info, PageInfo* out_page_info, Handle process_handle, Address address);"],
[0x6A, "Result ReadDebugProcessMemory(Address buffer, Handle debug_handle, Address address, Size size);"],
[0x6B, "Result WriteDebugProcessMemory(Handle debug_handle, Address buffer, Address address, Size size);"],
[0x6C, "Result SetHardwareBreakPoint(HardwareBreakPointRegisterName name, uint64_t flags, uint64_t value);"],
[0x6D, "Result GetDebugThreadParam(uint64_t* out_64, uint32_t* out_32, Handle debug_handle, uint64_t thread_id, DebugThreadParam param);"],
[0x6F, "Result GetSystemInfo(uint64_t* out, SystemInfoType info_type, Handle handle, uint64_t info_subtype);"],
[0x70, "Result CreatePort(Handle* out_server_handle, Handle* out_client_handle, int32_t max_sessions, bool is_light, Address name);"],
[0x71, "Result ManageNamedPort(Handle* out_server_handle, Address name, int32_t max_sessions);"],
[0x72, "Result ConnectToPort(Handle* out_handle, Handle port);"],
[0x73, "Result SetProcessMemoryPermission(Handle process_handle, uint64_t address, uint64_t size, MemoryPermission perm);"],
[0x74, "Result MapProcessMemory(Address dst_address, Handle process_handle, uint64_t src_address, Size size);"],
[0x75, "Result UnmapProcessMemory(Address dst_address, Handle process_handle, uint64_t src_address, Size size);"],
[0x76, "Result QueryProcessMemory(Address out_memory_info, PageInfo* out_page_info, Handle process_handle, uint64_t address);"],
[0x77, "Result MapProcessCodeMemory(Handle process_handle, uint64_t dst_address, uint64_t src_address, uint64_t size);"],
[0x78, "Result UnmapProcessCodeMemory(Handle process_handle, uint64_t dst_address, uint64_t src_address, uint64_t size);"],
[0x79, "Result CreateProcess(Handle* out_handle, Address parameters, Address caps, int32_t num_caps);"],
[0x7A, "Result StartProcess(Handle process_handle, int32_t priority, int32_t core_id, uint64_t main_thread_stack_size);"],
[0x7B, "Result TerminateProcess(Handle process_handle);"],
[0x7C, "Result GetProcessInfo(int64_t* out_info, Handle process_handle, ProcessInfoType info_type);"],
[0x7D, "Result CreateResourceLimit(Handle* out_handle);"],
[0x7E, "Result SetResourceLimitLimitValue(Handle resource_limit_handle, LimitableResource which, int64_t limit_value);"],
[0x7F, "void CallSecureMonitor(SecureMonitorArguments args);"],
[0x90, "Result MapInsecureMemory(Address address, Size size);"],
[0x91, "Result UnmapInsecureMemory(Address address, Size size);"],
]
# These use a custom ABI, and therefore require custom wrappers
SKIP_WRAPPERS = {
0x20: "SendSyncRequestLight",
0x42: "ReplyAndReceiveLight",
0x7F: "CallSecureMonitor",
}
BIT_32 = 0
BIT_64 = 1
REG_SIZES = [4, 8]
SUFFIX_NAMES = ["64From32", "64"]
TYPE_SIZES = {
# SVC types
"ArbitrationType": 4,
"BreakReason": 4,
"CodeMemoryOperation": 4,
"DebugThreadParam": 4,
"DeviceName": 4,
"HardwareBreakPointRegisterName": 4,
"Handle": 4,
"InfoType": 4,
"InterruptType": 4,
"IoPoolType": 4,
"KernelDebugType": 4,
"KernelTraceState": 4,
"LimitableResource": 4,
"MemoryMapping": 4,
"MemoryPermission": 4,
"PageInfo": 4,
"ProcessActivity": 4,
"ProcessInfoType": 4,
"Result": 4,
"SignalType": 4,
"SystemInfoType": 4,
"ThreadActivity": 4,
# Arch-specific types
"ilp32::LastThreadContext": 16,
"ilp32::PhysicalMemoryInfo": 16,
"ilp32::SecureMonitorArguments": 32,
"lp64::LastThreadContext": 32,
"lp64::PhysicalMemoryInfo": 24,
"lp64::SecureMonitorArguments": 64,
# Generic types
"bool": 1,
"int32_t": 4,
"int64_t": 8,
"uint32_t": 4,
"uint64_t": 8,
"void": 0,
}
TYPE_REPLACEMENTS = {
"Address": ["uint32_t", "uint64_t"],
"LastThreadContext": ["ilp32::LastThreadContext", "lp64::LastThreadContext"],
"PhysicalAddress": ["uint64_t", "uint64_t"],
"PhysicalMemoryInfo": ["ilp32::PhysicalMemoryInfo", "lp64::PhysicalMemoryInfo"],
"SecureMonitorArguments": ["ilp32::SecureMonitorArguments", "lp64::SecureMonitorArguments"],
"Size": ["uint32_t", "uint64_t"],
"ThreadFunc": ["uint32_t", "uint64_t"],
}
# Statically verify that the hardcoded sizes match the intended
# sizes in C++.
def emit_size_check():
lines = []
for type, size in TYPE_SIZES.items():
if type != "void":
lines.append(f"static_assert(sizeof({type}) == {size});")
return "\n".join(lines)
# Replaces a type with an arch-specific one, if it exists.
def substitute_type(name, bitness):
if name in TYPE_REPLACEMENTS:
return TYPE_REPLACEMENTS[name][bitness]
else:
return name
class Argument:
def __init__(self, type_name, var_name, is_output, is_outptr, is_address):
self.type_name = type_name
self.var_name = var_name
self.is_output = is_output
self.is_outptr = is_outptr
self.is_address = is_address
# Parses C-style string declarations for SVCs.
def parse_declaration(declaration, bitness):
return_type, rest = declaration.split(" ", 1)
func_name, rest = rest.split("(", 1)
arg_names, rest = rest.split(")", 1)
argument_types = []
return_type = substitute_type(return_type, bitness)
assert return_type in TYPE_SIZES, f"Unknown type '{return_type}'"
if arg_names:
for arg_name in arg_names.split(", "):
type_name, var_name = arg_name.replace("*", "").split(" ", 1)
# All outputs must contain out_ in the name.
is_output = var_name == "out" or var_name.find("out_") != -1
# User-pointer outputs are not written to registers.
is_outptr = is_output and arg_name.find("*") == -1
# Special handling is performed for output addresses to avoid awkwardness
# in conversion for the 32-bit equivalents.
is_address = is_output and not is_outptr and \
type_name in ["Address", "Size"]
type_name = substitute_type(type_name, bitness)
assert type_name in TYPE_SIZES, f"Unknown type '{type_name}'"
argument_types.append(
Argument(type_name, var_name, is_output, is_outptr, is_address))
return (return_type, func_name, argument_types)
class RegisterAllocator:
def __init__(self, num_regs, byte_size, parameter_count):
self.registers = {}
self.num_regs = num_regs
self.byte_size = byte_size
self.parameter_count = parameter_count
# Mark the given register as allocated, for use in layout
# calculation if the NGRN exceeds the ABI parameter count.
def allocate(self, i):
assert i not in self.registers, f"Register R{i} already allocated"
self.registers[i] = True
return i
# Calculate the next available location for a register;
# the NGRN has exceeded the ABI parameter count.
def allocate_first_free(self):
for i in range(0, self.num_regs):
if i in self.registers:
continue
self.allocate(i)
return i
assert False, "No registers available"
# Add a single register at the given NGRN.
# If the index exceeds the ABI parameter count, try to find a
# location to add it. Returns the output location and increment.
def add_single(self, ngrn):
if ngrn >= self.parameter_count:
return (self.allocate_first_free(), 0)
else:
return (self.allocate(ngrn), 1)
# Add registers at the given NGRN for a data type of
# the given size. Returns the output locations and increment.
def add(self, ngrn, data_size, align=True):
if data_size <= self.byte_size:
r, i = self.add_single(ngrn)
return ([r], i)
regs = []
inc = ngrn % 2 if align else 0
remaining_size = data_size
while remaining_size > 0:
r, i = self.add_single(ngrn + inc)
regs.append(r)
inc += i
remaining_size -= self.byte_size
return (regs, inc)
def reg_alloc(bitness):
if bitness == 0:
# aapcs32: 4 4-byte registers
return RegisterAllocator(8, 4, 4)
elif bitness == 1:
# aapcs64: 8 8-byte registers
return RegisterAllocator(8, 8, 8)
# Converts a parsed SVC declaration into register lists for
# the return value, outputs, and inputs.
def get_registers(parse_result, bitness):
output_alloc = reg_alloc(bitness)
input_alloc = reg_alloc(bitness)
return_type, _, arguments = parse_result
return_write = []
output_writes = []
input_reads = []
input_ngrn = 0
output_ngrn = 0
# Run the input calculation.
for arg in arguments:
if arg.is_output and not arg.is_outptr:
input_ngrn += 1
continue
regs, increment = input_alloc.add(
input_ngrn, TYPE_SIZES[arg.type_name], align=True)
input_reads.append([arg.type_name, arg.var_name, regs])
input_ngrn += increment
# Include the return value if this SVC returns a value.
if return_type != "void":
regs, increment = output_alloc.add(
output_ngrn, TYPE_SIZES[return_type], align=False)
return_write.append([return_type, regs])
output_ngrn += increment
# Run the output calculation.
for arg in arguments:
if not arg.is_output or arg.is_outptr:
continue
regs, increment = output_alloc.add(
output_ngrn, TYPE_SIZES[arg.type_name], align=False)
output_writes.append(
[arg.type_name, arg.var_name, regs, arg.is_address])
output_ngrn += increment
return (return_write, output_writes, input_reads)
# Collects possibly multiple source registers into the named C++ value.
def emit_gather(sources, name, type_name, reg_size):
get_fn = f"GetReg{reg_size*8}"
if len(sources) == 1:
s, = sources
line = f"{name} = Convert<{type_name}>({get_fn}(system, {s}));"
return [line]
var_type = f"std::array<uint{reg_size*8}_t, {len(sources)}>"
lines = [
f"{var_type} {name}_gather{{}};"
]
for i in range(0, len(sources)):
lines.append(
f"{name}_gather[{i}] = {get_fn}(system, {sources[i]});")
lines.append(f"{name} = Convert<{type_name}>({name}_gather);")
return lines
# Produces one or more statements which assign the named C++ value
# into possibly multiple registers.
def emit_scatter(destinations, name, reg_size):
set_fn = f"SetReg{reg_size*8}"
reg_type = f"uint{reg_size*8}_t"
if len(destinations) == 1:
d, = destinations
line = f"{set_fn}(system, {d}, Convert<{reg_type}>({name}));"
return [line]
var_type = f"std::array<{reg_type}, {len(destinations)}>"
lines = [
f"auto {name}_scatter = Convert<{var_type}>({name});"
]
for i in range(0, len(destinations)):
lines.append(
f"{set_fn}(system, {destinations[i]}, {name}_scatter[{i}]);")
return lines
def emit_lines(lines, indent=' '):
output_lines = []
first = True
for line in lines:
if line and not first:
output_lines.append(indent + line)
else:
output_lines.append(line)
first = False
return "\n".join(output_lines)
# Emit a C++ function to wrap a guest SVC.
def emit_wrapper(wrapped_fn, suffix, register_info, arguments, byte_size):
return_write, output_writes, input_reads = register_info
lines = [
f"static void SvcWrap_{wrapped_fn}{suffix}(Core::System& system) {{"
]
# Get everything ready.
for return_type, _ in return_write:
lines.append(f"{return_type} ret{{}};")
if return_write:
lines.append("")
for output_type, var_name, _, is_address in output_writes:
output_type = "uint64_t" if is_address else output_type
lines.append(f"{output_type} {var_name}{{}};")
for input_type, var_name, _ in input_reads:
lines.append(f"{input_type} {var_name}{{}};")
if output_writes or input_reads:
lines.append("")
for input_type, var_name, sources in input_reads:
lines += emit_gather(sources, var_name, input_type, byte_size)
if input_reads:
lines.append("")
# Build the call.
call_arguments = ["system"]
for arg in arguments:
if arg.is_output and not arg.is_outptr:
call_arguments.append(f"&{arg.var_name}")
else:
call_arguments.append(arg.var_name)
line = ""
if return_write:
line += "ret = "
line += f"{wrapped_fn}{suffix}({', '.join(call_arguments)});"
lines.append(line)
if return_write or output_writes:
lines.append("")
# Write back the return value and outputs.
for _, destinations in return_write:
lines += emit_scatter(destinations, "ret", byte_size)
for _, var_name, destinations, _ in output_writes:
lines += emit_scatter(destinations, var_name, byte_size)
# Finish.
return emit_lines(lines) + "\n}"
COPYRIGHT = """\
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
// This file is automatically generated using svc_generator.py.
"""
PROLOGUE_H = """
#pragma once
namespace Core {
class System;
}
#include "common/common_types.h"
#include "core/hle/kernel/svc_types.h"
#include "core/hle/result.h"
namespace Kernel::Svc {
// clang-format off
"""
EPILOGUE_H = """
// clang-format on
// Custom ABI.
Result ReplyAndReceiveLight(Core::System& system, Handle handle, uint32_t* args);
Result ReplyAndReceiveLight64From32(Core::System& system, Handle handle, uint32_t* args);
Result ReplyAndReceiveLight64(Core::System& system, Handle handle, uint32_t* args);
Result SendSyncRequestLight(Core::System& system, Handle session_handle, uint32_t* args);
Result SendSyncRequestLight64From32(Core::System& system, Handle session_handle, uint32_t* args);
Result SendSyncRequestLight64(Core::System& system, Handle session_handle, uint32_t* args);
void CallSecureMonitor(Core::System& system, lp64::SecureMonitorArguments* args);
void CallSecureMonitor64From32(Core::System& system, ilp32::SecureMonitorArguments* args);
void CallSecureMonitor64(Core::System& system, lp64::SecureMonitorArguments* args);
// Defined in svc_light_ipc.cpp.
void SvcWrap_ReplyAndReceiveLight64From32(Core::System& system);
void SvcWrap_ReplyAndReceiveLight64(Core::System& system);
void SvcWrap_SendSyncRequestLight64From32(Core::System& system);
void SvcWrap_SendSyncRequestLight64(Core::System& system);
// Defined in svc_secure_monitor_call.cpp.
void SvcWrap_CallSecureMonitor64From32(Core::System& system);
void SvcWrap_CallSecureMonitor64(Core::System& system);
// Perform a supervisor call by index.
void Call(Core::System& system, u32 imm);
} // namespace Kernel::Svc
"""
PROLOGUE_CPP = """
#include <type_traits>
#include "core/arm/arm_interface.h"
#include "core/core.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/svc.h"
namespace Kernel::Svc {
static uint32_t GetReg32(Core::System& system, int n) {
return static_cast<uint32_t>(system.CurrentArmInterface().GetReg(n));
}
static void SetReg32(Core::System& system, int n, uint32_t result) {
system.CurrentArmInterface().SetReg(n, static_cast<uint64_t>(result));
}
static uint64_t GetReg64(Core::System& system, int n) {
return system.CurrentArmInterface().GetReg(n);
}
static void SetReg64(Core::System& system, int n, uint64_t result) {
system.CurrentArmInterface().SetReg(n, result);
}
// Like bit_cast, but handles the case when the source and dest
// are differently-sized.
template <typename To, typename From>
requires(std::is_trivial_v<To> && std::is_trivially_copyable_v<From>)
static To Convert(const From& from) {
To to{};
if constexpr (sizeof(To) >= sizeof(From)) {
std::memcpy(&to, &from, sizeof(From));
} else {
std::memcpy(&to, &from, sizeof(To));
}
return to;
}
// clang-format off
"""
EPILOGUE_CPP = """
// clang-format on
void Call(Core::System& system, u32 imm) {
auto& kernel = system.Kernel();
kernel.EnterSVCProfile();
if (GetCurrentProcess(system.Kernel()).Is64BitProcess()) {
Call64(system, imm);
} else {
Call32(system, imm);
}
kernel.ExitSVCProfile();
}
} // namespace Kernel::Svc
"""
def emit_call(bitness, names, suffix):
bit_size = REG_SIZES[bitness]*8
indent = " "
lines = [
f"static void Call{bit_size}(Core::System& system, u32 imm) {{",
f"{indent}switch (static_cast<SvcId>(imm)) {{"
]
for _, name in names:
lines.append(f"{indent}case SvcId::{name}:")
lines.append(f"{indent*2}return SvcWrap_{name}{suffix}(system);")
lines.append(f"{indent}default:")
lines.append(
f"{indent*2}LOG_CRITICAL(Kernel_SVC, \"Unknown SVC {{:x}}!\", imm);")
lines.append(f"{indent*2}break;")
lines.append(f"{indent}}}")
lines.append("}")
return "\n".join(lines)
def build_fn_declaration(return_type, name, arguments):
arg_list = ["Core::System& system"]
for arg in arguments:
type_name = "uint64_t" if arg.is_address else arg.type_name
pointer = "*" if arg.is_output and not arg.is_outptr else ""
arg_list.append(f"{type_name}{pointer} {arg.var_name}")
return f"{return_type} {name}({', '.join(arg_list)});"
def build_enum_declarations():
lines = ["enum class SvcId : u32 {"]
indent = " "
for imm, decl in SVCS:
_, name, _ = parse_declaration(decl, BIT_64)
lines.append(f"{indent}{name} = {hex(imm)},")
lines.append("};")
return "\n".join(lines)
def main():
arch_fw_declarations = [[], []]
svc_fw_declarations = []
wrapper_fns = []
names = []
for imm, decl in SVCS:
return_type, name, arguments = parse_declaration(decl, BIT_64)
if imm not in SKIP_WRAPPERS:
svc_fw_declarations.append(
build_fn_declaration(return_type, name, arguments))
names.append([imm, name])
for bitness in range(2):
byte_size = REG_SIZES[bitness]
suffix = SUFFIX_NAMES[bitness]
for imm, decl in SVCS:
if imm in SKIP_WRAPPERS:
continue
parse_result = parse_declaration(decl, bitness)
return_type, name, arguments = parse_result
register_info = get_registers(parse_result, bitness)
wrapper_fns.append(
emit_wrapper(name, suffix, register_info, arguments, byte_size))
arch_fw_declarations[bitness].append(
build_fn_declaration(return_type, name + suffix, arguments))
call_32 = emit_call(BIT_32, names, SUFFIX_NAMES[BIT_32])
call_64 = emit_call(BIT_64, names, SUFFIX_NAMES[BIT_64])
enum_decls = build_enum_declarations()
with open("svc.h", "w") as f:
f.write(COPYRIGHT)
f.write(PROLOGUE_H)
f.write("\n".join(svc_fw_declarations))
f.write("\n\n")
f.write("\n".join(arch_fw_declarations[BIT_32]))
f.write("\n\n")
f.write("\n".join(arch_fw_declarations[BIT_64]))
f.write("\n\n")
f.write(enum_decls)
f.write(EPILOGUE_H)
with open("svc.cpp", "w") as f:
f.write(COPYRIGHT)
f.write(PROLOGUE_CPP)
f.write(emit_size_check())
f.write("\n\n")
f.write("\n\n".join(wrapper_fns))
f.write("\n\n")
f.write(call_32)
f.write("\n\n")
f.write(call_64)
f.write(EPILOGUE_CPP)
print(f"Done (emitted {len(names)} definitions)")
if __name__ == "__main__":
main()

View File

@@ -11,6 +11,7 @@ namespace Kernel {
constexpr Result ResultOutOfSessions{ErrorModule::Kernel, 7};
constexpr Result ResultInvalidArgument{ErrorModule::Kernel, 14};
constexpr Result ResultNotImplemented{ErrorModule::Kernel, 33};
constexpr Result ResultNoSynchronizationObject{ErrorModule::Kernel, 57};
constexpr Result ResultTerminationRequested{ErrorModule::Kernel, 59};
constexpr Result ResultInvalidSize{ErrorModule::Kernel, 101};

View File

@@ -168,6 +168,7 @@ enum class BreakReason : u32 {
NotificationOnlyFlag = 0x80000000,
};
DECLARE_ENUM_FLAG_OPERATORS(BreakReason);
enum class DebugEvent : u32 {
CreateProcess = 0,
@@ -596,6 +597,11 @@ enum class ProcessInfoType : u32 {
ProcessState = 0,
};
enum class ProcessActivity : u32 {
Runnable,
Paused,
};
struct CreateProcessParameter {
std::array<char, 12> name;
u32 version;
@@ -611,4 +617,9 @@ static_assert(sizeof(CreateProcessParameter) == 0x30);
constexpr size_t NumSupervisorCalls = 0xC0;
using SvcAccessFlagSet = std::bitset<NumSupervisorCalls>;
enum class InitialProcessIdRangeInfo : u64 {
Minimum = 0,
Maximum = 1,
};
} // namespace Kernel::Svc

View File

@@ -1,733 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/common_types.h"
#include "core/arm/arm_interface.h"
#include "core/core.h"
#include "core/hle/kernel/svc_types.h"
#include "core/hle/result.h"
#include "core/memory.h"
namespace Kernel {
static inline u64 Param(const Core::System& system, int n) {
return system.CurrentArmInterface().GetReg(n);
}
static inline u32 Param32(const Core::System& system, int n) {
return static_cast<u32>(system.CurrentArmInterface().GetReg(n));
}
/**
* HLE a function return from the current ARM userland process
* @param system System context
* @param result Result to return
*/
static inline void FuncReturn(Core::System& system, u64 result) {
system.CurrentArmInterface().SetReg(0, result);
}
static inline void FuncReturn32(Core::System& system, u32 result) {
system.CurrentArmInterface().SetReg(0, (u64)result);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// Function wrappers that return type Result
template <Result func(Core::System&, u64)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, Param(system, 0)).raw);
}
template <Result func(Core::System&, u64, u64)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, Param(system, 0), Param(system, 1)).raw);
}
template <Result func(Core::System&, u32)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, static_cast<u32>(Param(system, 0))).raw);
}
template <Result func(Core::System&, u32, u32)>
void SvcWrap64(Core::System& system) {
FuncReturn(
system,
func(system, static_cast<u32>(Param(system, 0)), static_cast<u32>(Param(system, 1))).raw);
}
// Used by SetThreadActivity
template <Result func(Core::System&, Handle, Svc::ThreadActivity)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)),
static_cast<Svc::ThreadActivity>(Param(system, 1)))
.raw);
}
template <Result func(Core::System&, u32, u64, u64, u64)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1),
Param(system, 2), Param(system, 3))
.raw);
}
// Used by MapProcessMemory and UnmapProcessMemory
template <Result func(Core::System&, u64, u32, u64, u64)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, Param(system, 0), static_cast<u32>(Param(system, 1)),
Param(system, 2), Param(system, 3))
.raw);
}
// Used by ControlCodeMemory
template <Result func(Core::System&, Handle, u32, VAddr, size_t, Svc::MemoryPermission)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, static_cast<Handle>(Param(system, 0)),
static_cast<u32>(Param(system, 1)), Param(system, 2), Param(system, 3),
static_cast<Svc::MemoryPermission>(Param(system, 4)))
.raw);
}
template <Result func(Core::System&, u32*)>
void SvcWrap64(Core::System& system) {
u32 param = 0;
const u32 retval = func(system, &param).raw;
system.CurrentArmInterface().SetReg(1, param);
FuncReturn(system, retval);
}
template <Result func(Core::System&, u32*, u32)>
void SvcWrap64(Core::System& system) {
u32 param_1 = 0;
const u32 retval = func(system, &param_1, static_cast<u32>(Param(system, 1))).raw;
system.CurrentArmInterface().SetReg(1, param_1);
FuncReturn(system, retval);
}
template <Result func(Core::System&, u32*, u32*)>
void SvcWrap64(Core::System& system) {
u32 param_1 = 0;
u32 param_2 = 0;
const u32 retval = func(system, &param_1, &param_2).raw;
auto& arm_interface = system.CurrentArmInterface();
arm_interface.SetReg(1, param_1);
arm_interface.SetReg(2, param_2);
FuncReturn(system, retval);
}
template <Result func(Core::System&, u32*, u64)>
void SvcWrap64(Core::System& system) {
u32 param_1 = 0;
const u32 retval = func(system, &param_1, Param(system, 1)).raw;
system.CurrentArmInterface().SetReg(1, param_1);
FuncReturn(system, retval);
}
template <Result func(Core::System&, u32*, u64, u32)>
void SvcWrap64(Core::System& system) {
u32 param_1 = 0;
const u32 retval =
func(system, &param_1, Param(system, 1), static_cast<u32>(Param(system, 2))).raw;
system.CurrentArmInterface().SetReg(1, param_1);
FuncReturn(system, retval);
}
template <Result func(Core::System&, u64*, u32)>
void SvcWrap64(Core::System& system) {
u64 param_1 = 0;
const u32 retval = func(system, &param_1, static_cast<u32>(Param(system, 1))).raw;
system.CurrentArmInterface().SetReg(1, param_1);
FuncReturn(system, retval);
}
template <Result func(Core::System&, u64, u32)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, Param(system, 0), static_cast<u32>(Param(system, 1))).raw);
}
template <Result func(Core::System&, u64*, u64)>
void SvcWrap64(Core::System& system) {
u64 param_1 = 0;
const u32 retval = func(system, &param_1, Param(system, 1)).raw;
system.CurrentArmInterface().SetReg(1, param_1);
FuncReturn(system, retval);
}
template <Result func(Core::System&, u64*, u32, u32)>
void SvcWrap64(Core::System& system) {
u64 param_1 = 0;
const u32 retval = func(system, &param_1, static_cast<u32>(Param(system, 1)),
static_cast<u32>(Param(system, 2)))
.raw;
system.CurrentArmInterface().SetReg(1, param_1);
FuncReturn(system, retval);
}
// Used by GetResourceLimitLimitValue.
template <Result func(Core::System&, u64*, Handle, Svc::LimitableResource)>
void SvcWrap64(Core::System& system) {
u64 param_1 = 0;
const u32 retval = func(system, &param_1, static_cast<Handle>(Param(system, 1)),
static_cast<Svc::LimitableResource>(Param(system, 2)))
.raw;
system.CurrentArmInterface().SetReg(1, param_1);
FuncReturn(system, retval);
}
template <Result func(Core::System&, u32, u64)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1)).raw);
}
// Used by SetResourceLimitLimitValue
template <Result func(Core::System&, Handle, Svc::LimitableResource, u64)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, static_cast<Handle>(Param(system, 0)),
static_cast<Svc::LimitableResource>(Param(system, 1)), Param(system, 2))
.raw);
}
// Used by SetThreadCoreMask
template <Result func(Core::System&, Handle, s32, u64)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)),
static_cast<s32>(Param(system, 1)), Param(system, 2))
.raw);
}
// Used by GetThreadCoreMask
template <Result func(Core::System&, Handle, s32*, u64*)>
void SvcWrap64(Core::System& system) {
s32 param_1 = 0;
u64 param_2 = 0;
const Result retval = func(system, static_cast<u32>(Param(system, 2)), &param_1, &param_2);
system.CurrentArmInterface().SetReg(1, param_1);
system.CurrentArmInterface().SetReg(2, param_2);
FuncReturn(system, retval.raw);
}
template <Result func(Core::System&, u64, u64, u32, u32)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, Param(system, 0), Param(system, 1),
static_cast<u32>(Param(system, 2)), static_cast<u32>(Param(system, 3)))
.raw);
}
template <Result func(Core::System&, u64, u64, u32, u64)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, Param(system, 0), Param(system, 1),
static_cast<u32>(Param(system, 2)), Param(system, 3))
.raw);
}
template <Result func(Core::System&, u32, u64, u32)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, static_cast<u32>(Param(system, 0)), Param(system, 1),
static_cast<u32>(Param(system, 2)))
.raw);
}
template <Result func(Core::System&, u64, u64, u64)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, Param(system, 0), Param(system, 1), Param(system, 2)).raw);
}
template <Result func(Core::System&, u64, u64, u32)>
void SvcWrap64(Core::System& system) {
FuncReturn(
system,
func(system, Param(system, 0), Param(system, 1), static_cast<u32>(Param(system, 2))).raw);
}
// Used by SetMemoryPermission
template <Result func(Core::System&, u64, u64, Svc::MemoryPermission)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, Param(system, 0), Param(system, 1),
static_cast<Svc::MemoryPermission>(Param(system, 2)))
.raw);
}
// Used by MapSharedMemory
template <Result func(Core::System&, Handle, u64, u64, Svc::MemoryPermission)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, static_cast<Handle>(Param(system, 0)), Param(system, 1),
Param(system, 2), static_cast<Svc::MemoryPermission>(Param(system, 3)))
.raw);
}
template <Result func(Core::System&, u32, u64, u64)>
void SvcWrap64(Core::System& system) {
FuncReturn(
system,
func(system, static_cast<u32>(Param(system, 0)), Param(system, 1), Param(system, 2)).raw);
}
// Used by WaitSynchronization
template <Result func(Core::System&, s32*, u64, s32, s64)>
void SvcWrap64(Core::System& system) {
s32 param_1 = 0;
const u32 retval = func(system, &param_1, Param(system, 1), static_cast<s32>(Param(system, 2)),
static_cast<s64>(Param(system, 3)))
.raw;
system.CurrentArmInterface().SetReg(1, param_1);
FuncReturn(system, retval);
}
template <Result func(Core::System&, u64, u64, u32, s64)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system, Param(system, 0), Param(system, 1),
static_cast<u32>(Param(system, 2)), static_cast<s64>(Param(system, 3)))
.raw);
}
// Used by GetInfo
template <Result func(Core::System&, u64*, u64, Handle, u64)>
void SvcWrap64(Core::System& system) {
u64 param_1 = 0;
const u32 retval = func(system, &param_1, Param(system, 1),
static_cast<Handle>(Param(system, 2)), Param(system, 3))
.raw;
system.CurrentArmInterface().SetReg(1, param_1);
FuncReturn(system, retval);
}
template <Result func(Core::System&, u32*, u64, u64, u64, u32, s32)>
void SvcWrap64(Core::System& system) {
u32 param_1 = 0;
const u32 retval = func(system, &param_1, Param(system, 1), Param(system, 2), Param(system, 3),
static_cast<u32>(Param(system, 4)), static_cast<s32>(Param(system, 5)))
.raw;
system.CurrentArmInterface().SetReg(1, param_1);
FuncReturn(system, retval);
}
// Used by CreateTransferMemory
template <Result func(Core::System&, Handle*, u64, u64, Svc::MemoryPermission)>
void SvcWrap64(Core::System& system) {
u32 param_1 = 0;
const u32 retval = func(system, &param_1, Param(system, 1), Param(system, 2),
static_cast<Svc::MemoryPermission>(Param(system, 3)))
.raw;
system.CurrentArmInterface().SetReg(1, param_1);
FuncReturn(system, retval);
}
// Used by CreateCodeMemory
template <Result func(Core::System&, Handle*, VAddr, size_t)>
void SvcWrap64(Core::System& system) {
u32 param_1 = 0;
const u32 retval = func(system, &param_1, Param(system, 1), Param(system, 2)).raw;
system.CurrentArmInterface().SetReg(1, param_1);
FuncReturn(system, retval);
}
template <Result func(Core::System&, Handle*, u64, u32, u32)>
void SvcWrap64(Core::System& system) {
u32 param_1 = 0;
const u32 retval = func(system, &param_1, Param(system, 1), static_cast<u32>(Param(system, 2)),
static_cast<u32>(Param(system, 3)))
.raw;
system.CurrentArmInterface().SetReg(1, param_1);
FuncReturn(system, retval);
}
// Used by CreateSession
template <Result func(Core::System&, Handle*, Handle*, u32, u64)>
void SvcWrap64(Core::System& system) {
Handle param_1 = 0;
Handle param_2 = 0;
const u32 retval = func(system, &param_1, &param_2, static_cast<u32>(Param(system, 2)),
static_cast<u32>(Param(system, 3)))
.raw;
system.CurrentArmInterface().SetReg(1, param_1);
system.CurrentArmInterface().SetReg(2, param_2);
FuncReturn(system, retval);
}
// Used by ReplyAndReceive
template <Result func(Core::System&, s32*, Handle*, s32, Handle, s64)>
void SvcWrap64(Core::System& system) {
s32 param_1 = 0;
s32 num_handles = static_cast<s32>(Param(system, 2));
std::vector<Handle> handles(num_handles);
system.Memory().ReadBlock(Param(system, 1), handles.data(), num_handles * sizeof(Handle));
const u32 retval = func(system, &param_1, handles.data(), num_handles,
static_cast<s32>(Param(system, 3)), static_cast<s64>(Param(system, 4)))
.raw;
system.CurrentArmInterface().SetReg(1, param_1);
FuncReturn(system, retval);
}
// Used by WaitForAddress
template <Result func(Core::System&, u64, Svc::ArbitrationType, s32, s64)>
void SvcWrap64(Core::System& system) {
FuncReturn(system,
func(system, Param(system, 0), static_cast<Svc::ArbitrationType>(Param(system, 1)),
static_cast<s32>(Param(system, 2)), static_cast<s64>(Param(system, 3)))
.raw);
}
// Used by SignalToAddress
template <Result func(Core::System&, u64, Svc::SignalType, s32, s32)>
void SvcWrap64(Core::System& system) {
FuncReturn(system,
func(system, Param(system, 0), static_cast<Svc::SignalType>(Param(system, 1)),
static_cast<s32>(Param(system, 2)), static_cast<s32>(Param(system, 3)))
.raw);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// Function wrappers that return type u32
template <u32 func(Core::System&)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
// Function wrappers that return type u64
template <u64 func(Core::System&)>
void SvcWrap64(Core::System& system) {
FuncReturn(system, func(system));
}
////////////////////////////////////////////////////////////////////////////////////////////////////
/// Function wrappers that return type void
template <void func(Core::System&)>
void SvcWrap64(Core::System& system) {
func(system);
}
template <void func(Core::System&, u32)>
void SvcWrap64(Core::System& system) {
func(system, static_cast<u32>(Param(system, 0)));
}
template <void func(Core::System&, u32, u64, u64, u64)>
void SvcWrap64(Core::System& system) {
func(system, static_cast<u32>(Param(system, 0)), Param(system, 1), Param(system, 2),
Param(system, 3));
}
template <void func(Core::System&, s64)>
void SvcWrap64(Core::System& system) {
func(system, static_cast<s64>(Param(system, 0)));
}
template <void func(Core::System&, u64, s32)>
void SvcWrap64(Core::System& system) {
func(system, Param(system, 0), static_cast<s32>(Param(system, 1)));
}
template <void func(Core::System&, u64, u64)>
void SvcWrap64(Core::System& system) {
func(system, Param(system, 0), Param(system, 1));
}
template <void func(Core::System&, u64, u64, u64)>
void SvcWrap64(Core::System& system) {
func(system, Param(system, 0), Param(system, 1), Param(system, 2));
}
template <void func(Core::System&, u32, u64, u64)>
void SvcWrap64(Core::System& system) {
func(system, static_cast<u32>(Param(system, 0)), Param(system, 1), Param(system, 2));
}
// Used by QueryMemory32, ArbitrateLock32
template <Result func(Core::System&, u32, u32, u32)>
void SvcWrap32(Core::System& system) {
FuncReturn32(system,
func(system, Param32(system, 0), Param32(system, 1), Param32(system, 2)).raw);
}
// Used by Break32
template <void func(Core::System&, u32, u32, u32)>
void SvcWrap32(Core::System& system) {
func(system, Param32(system, 0), Param32(system, 1), Param32(system, 2));
}
// Used by ExitProcess32, ExitThread32
template <void func(Core::System&)>
void SvcWrap32(Core::System& system) {
func(system);
}
// Used by GetCurrentProcessorNumber32
template <u32 func(Core::System&)>
void SvcWrap32(Core::System& system) {
FuncReturn32(system, func(system));
}
// Used by SleepThread32
template <void func(Core::System&, u32, u32)>
void SvcWrap32(Core::System& system) {
func(system, Param32(system, 0), Param32(system, 1));
}
// Used by CreateThread32
template <Result func(Core::System&, Handle*, u32, u32, u32, u32, s32)>
void SvcWrap32(Core::System& system) {
Handle param_1 = 0;
const u32 retval = func(system, &param_1, Param32(system, 0), Param32(system, 1),
Param32(system, 2), Param32(system, 3), Param32(system, 4))
.raw;
system.CurrentArmInterface().SetReg(1, param_1);
FuncReturn(system, retval);
}
// Used by GetInfo32
template <Result func(Core::System&, u32*, u32*, u32, u32, u32, u32)>
void SvcWrap32(Core::System& system) {
u32 param_1 = 0;
u32 param_2 = 0;
const u32 retval = func(system, &param_1, &param_2, Param32(system, 0), Param32(system, 1),
Param32(system, 2), Param32(system, 3))
.raw;
system.CurrentArmInterface().SetReg(1, param_1);
system.CurrentArmInterface().SetReg(2, param_2);
FuncReturn(system, retval);
}
// Used by GetThreadPriority32, ConnectToNamedPort32
template <Result func(Core::System&, u32*, u32)>
void SvcWrap32(Core::System& system) {
u32 param_1 = 0;
const u32 retval = func(system, &param_1, Param32(system, 1)).raw;
system.CurrentArmInterface().SetReg(1, param_1);
FuncReturn(system, retval);
}
// Used by GetThreadId32
template <Result func(Core::System&, u32*, u32*, u32)>
void SvcWrap32(Core::System& system) {
u32 param_1 = 0;
u32 param_2 = 0;
const u32 retval = func(system, &param_1, &param_2, Param32(system, 1)).raw;
system.CurrentArmInterface().SetReg(1, param_1);
system.CurrentArmInterface().SetReg(2, param_2);
FuncReturn(system, retval);
}
// Used by GetSystemTick32
template <void func(Core::System&, u32*, u32*)>
void SvcWrap32(Core::System& system) {
u32 param_1 = 0;
u32 param_2 = 0;
func(system, &param_1, &param_2);
system.CurrentArmInterface().SetReg(0, param_1);
system.CurrentArmInterface().SetReg(1, param_2);
}
// Used by CreateEvent32
template <Result func(Core::System&, Handle*, Handle*)>
void SvcWrap32(Core::System& system) {
Handle param_1 = 0;
Handle param_2 = 0;
const u32 retval = func(system, &param_1, &param_2).raw;
system.CurrentArmInterface().SetReg(1, param_1);
system.CurrentArmInterface().SetReg(2, param_2);
FuncReturn(system, retval);
}
// Used by GetThreadId32
template <Result func(Core::System&, Handle, u32*, u32*, u32*)>
void SvcWrap32(Core::System& system) {
u32 param_1 = 0;
u32 param_2 = 0;
u32 param_3 = 0;
const u32 retval = func(system, Param32(system, 2), &param_1, &param_2, &param_3).raw;
system.CurrentArmInterface().SetReg(1, param_1);
system.CurrentArmInterface().SetReg(2, param_2);
system.CurrentArmInterface().SetReg(3, param_3);
FuncReturn(system, retval);
}
// Used by GetThreadCoreMask32
template <Result func(Core::System&, Handle, s32*, u32*, u32*)>
void SvcWrap32(Core::System& system) {
s32 param_1 = 0;
u32 param_2 = 0;
u32 param_3 = 0;
const u32 retval = func(system, Param32(system, 2), &param_1, &param_2, &param_3).raw;
system.CurrentArmInterface().SetReg(1, param_1);
system.CurrentArmInterface().SetReg(2, param_2);
system.CurrentArmInterface().SetReg(3, param_3);
FuncReturn(system, retval);
}
// Used by SignalProcessWideKey32
template <void func(Core::System&, u32, s32)>
void SvcWrap32(Core::System& system) {
func(system, static_cast<u32>(Param(system, 0)), static_cast<s32>(Param(system, 1)));
}
// Used by SetThreadActivity32
template <Result func(Core::System&, Handle, Svc::ThreadActivity)>
void SvcWrap32(Core::System& system) {
const u32 retval = func(system, static_cast<Handle>(Param(system, 0)),
static_cast<Svc::ThreadActivity>(Param(system, 1)))
.raw;
FuncReturn(system, retval);
}
// Used by SetThreadPriority32
template <Result func(Core::System&, Handle, u32)>
void SvcWrap32(Core::System& system) {
const u32 retval =
func(system, static_cast<Handle>(Param(system, 0)), static_cast<u32>(Param(system, 1))).raw;
FuncReturn(system, retval);
}
// Used by SetMemoryAttribute32
template <Result func(Core::System&, Handle, u32, u32, u32)>
void SvcWrap32(Core::System& system) {
const u32 retval =
func(system, static_cast<Handle>(Param(system, 0)), static_cast<u32>(Param(system, 1)),
static_cast<u32>(Param(system, 2)), static_cast<u32>(Param(system, 3)))
.raw;
FuncReturn(system, retval);
}
// Used by MapSharedMemory32
template <Result func(Core::System&, Handle, u32, u32, Svc::MemoryPermission)>
void SvcWrap32(Core::System& system) {
const u32 retval = func(system, static_cast<Handle>(Param(system, 0)),
static_cast<u32>(Param(system, 1)), static_cast<u32>(Param(system, 2)),
static_cast<Svc::MemoryPermission>(Param(system, 3)))
.raw;
FuncReturn(system, retval);
}
// Used by SetThreadCoreMask32
template <Result func(Core::System&, Handle, s32, u32, u32)>
void SvcWrap32(Core::System& system) {
const u32 retval =
func(system, static_cast<Handle>(Param(system, 0)), static_cast<s32>(Param(system, 1)),
static_cast<u32>(Param(system, 2)), static_cast<u32>(Param(system, 3)))
.raw;
FuncReturn(system, retval);
}
// Used by WaitProcessWideKeyAtomic32
template <Result func(Core::System&, u32, u32, Handle, u32, u32)>
void SvcWrap32(Core::System& system) {
const u32 retval =
func(system, static_cast<u32>(Param(system, 0)), static_cast<u32>(Param(system, 1)),
static_cast<Handle>(Param(system, 2)), static_cast<u32>(Param(system, 3)),
static_cast<u32>(Param(system, 4)))
.raw;
FuncReturn(system, retval);
}
// Used by WaitForAddress32
template <Result func(Core::System&, u32, Svc::ArbitrationType, s32, u32, u32)>
void SvcWrap32(Core::System& system) {
const u32 retval = func(system, static_cast<u32>(Param(system, 0)),
static_cast<Svc::ArbitrationType>(Param(system, 1)),
static_cast<s32>(Param(system, 2)), static_cast<u32>(Param(system, 3)),
static_cast<u32>(Param(system, 4)))
.raw;
FuncReturn(system, retval);
}
// Used by SignalToAddress32
template <Result func(Core::System&, u32, Svc::SignalType, s32, s32)>
void SvcWrap32(Core::System& system) {
const u32 retval = func(system, static_cast<u32>(Param(system, 0)),
static_cast<Svc::SignalType>(Param(system, 1)),
static_cast<s32>(Param(system, 2)), static_cast<s32>(Param(system, 3)))
.raw;
FuncReturn(system, retval);
}
// Used by SendSyncRequest32, ArbitrateUnlock32
template <Result func(Core::System&, u32)>
void SvcWrap32(Core::System& system) {
FuncReturn(system, func(system, static_cast<u32>(Param(system, 0))).raw);
}
// Used by CreateTransferMemory32
template <Result func(Core::System&, Handle*, u32, u32, Svc::MemoryPermission)>
void SvcWrap32(Core::System& system) {
Handle handle = 0;
const u32 retval = func(system, &handle, Param32(system, 1), Param32(system, 2),
static_cast<Svc::MemoryPermission>(Param32(system, 3)))
.raw;
system.CurrentArmInterface().SetReg(1, handle);
FuncReturn(system, retval);
}
// Used by WaitSynchronization32
template <Result func(Core::System&, u32, u32, s32, u32, s32*)>
void SvcWrap32(Core::System& system) {
s32 param_1 = 0;
const u32 retval = func(system, Param32(system, 0), Param32(system, 1), Param32(system, 2),
Param32(system, 3), &param_1)
.raw;
system.CurrentArmInterface().SetReg(1, param_1);
FuncReturn(system, retval);
}
// Used by CreateCodeMemory32
template <Result func(Core::System&, Handle*, u32, u32)>
void SvcWrap32(Core::System& system) {
Handle handle = 0;
const u32 retval = func(system, &handle, Param32(system, 1), Param32(system, 2)).raw;
system.CurrentArmInterface().SetReg(1, handle);
FuncReturn(system, retval);
}
// Used by ControlCodeMemory32
template <Result func(Core::System&, Handle, u32, u64, u64, Svc::MemoryPermission)>
void SvcWrap32(Core::System& system) {
const u32 retval =
func(system, Param32(system, 0), Param32(system, 1), Param(system, 2), Param(system, 4),
static_cast<Svc::MemoryPermission>(Param32(system, 6)))
.raw;
FuncReturn(system, retval);
}
// Used by Invalidate/Store/FlushProcessDataCache32
template <Result func(Core::System&, Handle, u64, u64)>
void SvcWrap32(Core::System& system) {
const u64 address = (Param(system, 3) << 32) | Param(system, 2);
const u64 size = (Param(system, 4) << 32) | Param(system, 1);
FuncReturn32(system, func(system, Param32(system, 0), address, size).raw);
}
} // namespace Kernel

View File

@@ -76,6 +76,8 @@ public:
{141, nullptr, "RefreshNetworkServiceLicenseCacheAsync"}, // 5.0.0+
{142, nullptr, "RefreshNetworkServiceLicenseCacheAsyncIfSecondsElapsed"}, // 5.0.0+
{150, nullptr, "CreateAuthorizationRequest"},
{160, nullptr, "RequiresUpdateNetworkServiceAccountIdTokenCache"},
{161, nullptr, "RequireReauthenticationOfNetworkServiceAccount"},
};
// clang-format on
@@ -136,7 +138,10 @@ public:
{140, nullptr, "GetNetworkServiceLicenseCache"}, // 5.0.0+
{141, nullptr, "RefreshNetworkServiceLicenseCacheAsync"}, // 5.0.0+
{142, nullptr, "RefreshNetworkServiceLicenseCacheAsyncIfSecondsElapsed"}, // 5.0.0+
{143, nullptr, "GetNetworkServiceLicenseCacheEx"},
{150, nullptr, "CreateAuthorizationRequest"},
{160, nullptr, "RequiresUpdateNetworkServiceAccountIdTokenCache"},
{161, nullptr, "RequireReauthenticationOfNetworkServiceAccount"},
{200, nullptr, "IsRegistered"},
{201, nullptr, "RegisterAsync"},
{202, nullptr, "UnregisterAsync"},
@@ -242,6 +247,7 @@ public:
{100, nullptr, "GetRequestWithTheme"},
{101, nullptr, "IsNetworkServiceAccountReplaced"},
{199, nullptr, "GetUrlForIntroductionOfExtraMembership"}, // 2.0.0 - 5.1.0
{200, nullptr, "ApplyAsyncWithAuthorizedToken"},
};
// clang-format on
@@ -647,9 +653,11 @@ public:
{0, nullptr, "EnsureAuthenticationTokenCacheAsync"},
{1, nullptr, "LoadAuthenticationTokenCache"},
{2, nullptr, "InvalidateAuthenticationTokenCache"},
{3, nullptr, "IsDeviceAuthenticationTokenCacheAvailable"},
{10, nullptr, "EnsureEdgeTokenCacheAsync"},
{11, nullptr, "LoadEdgeTokenCache"},
{12, nullptr, "InvalidateEdgeTokenCache"},
{13, nullptr, "IsEdgeTokenCacheAvailable"},
{20, nullptr, "EnsureApplicationAuthenticationCacheAsync"},
{21, nullptr, "LoadApplicationAuthenticationTokenCache"},
{22, nullptr, "LoadApplicationNetworkServiceClientConfigCache"},
@@ -762,7 +770,7 @@ Result Module::Interface::InitializeApplicationInfoBase() {
// processes emulated. As we don't actually have pid support we should assume we're just using
// our own process
const auto launch_property =
system.GetARPManager().GetLaunchProperty(system.GetCurrentProcessProgramID());
system.GetARPManager().GetLaunchProperty(system.GetApplicationProcessProgramID());
if (launch_property.Failed()) {
LOG_ERROR(Service_ACC, "Failed to get launch property");
@@ -806,7 +814,7 @@ void Module::Interface::IsUserAccountSwitchLocked(Kernel::HLERequestContext& ctx
bool is_locked = false;
if (res != Loader::ResultStatus::Success) {
const FileSys::PatchManager pm{system.GetCurrentProcessProgramID(),
const FileSys::PatchManager pm{system.GetApplicationProcessProgramID(),
system.GetFileSystemController(),
system.GetContentProvider()};
const auto nacp_unique = pm.GetControlMetadata().first;

View File

@@ -55,6 +55,10 @@ ACC_SU::ACC_SU(std::shared_ptr<Module> module_, std::shared_ptr<ProfileManager>
{290, nullptr, "ProxyProcedureForGuestLoginWithNintendoAccount"},
{291, nullptr, "ProxyProcedureForFloatingRegistrationWithNintendoAccount"},
{299, nullptr, "SuspendBackgroundDaemon"},
{900, nullptr, "SetUserUnqualifiedForDebug"},
{901, nullptr, "UnsetUserUnqualifiedForDebug"},
{902, nullptr, "ListUsersUnqualifiedForDebug"},
{910, nullptr, "RefreshFirmwareSettingsForDebug"},
{997, nullptr, "DebugInvalidateTokenCacheForUser"},
{998, nullptr, "DebugSetUserStateClose"},
{999, nullptr, "DebugSetUserStateOpen"},

View File

@@ -24,7 +24,6 @@
#include "core/hle/service/am/idle.h"
#include "core/hle/service/am/omm.h"
#include "core/hle/service/am/spsm.h"
#include "core/hle/service/am/tcap.h"
#include "core/hle/service/apm/apm_controller.h"
#include "core/hle/service/apm/apm_interface.h"
#include "core/hle/service/bcat/backend/backend.h"
@@ -79,7 +78,7 @@ IWindowController::IWindowController(Core::System& system_)
IWindowController::~IWindowController() = default;
void IWindowController::GetAppletResourceUserId(Kernel::HLERequestContext& ctx) {
const u64 process_id = system.CurrentProcess()->GetProcessID();
const u64 process_id = system.ApplicationProcess()->GetProcessID();
LOG_DEBUG(Service_AM, "called. Process ID=0x{:016X}", process_id);
@@ -227,6 +226,8 @@ IDebugFunctions::IDebugFunctions(Core::System& system_)
{30, nullptr, "RequestLaunchApplicationWithUserAndArgumentForDebug"},
{31, nullptr, "RequestLaunchApplicationByApplicationLaunchInfoForDebug"},
{40, nullptr, "GetAppletResourceUsageInfo"},
{50, nullptr, "AddSystemProgramIdAndAppletIdForDebug"},
{51, nullptr, "AddOperationConfirmedLibraryAppletIdForDebug"},
{100, nullptr, "SetCpuBoostModeForApplet"},
{101, nullptr, "CancelCpuBoostModeForApplet"},
{110, nullptr, "PushToAppletBoundChannelForDebug"},
@@ -238,6 +239,8 @@ IDebugFunctions::IDebugFunctions(Core::System& system_)
{131, nullptr, "FriendInvitationClearApplicationParameter"},
{132, nullptr, "FriendInvitationPushApplicationParameter"},
{140, nullptr, "RestrictPowerOperationForSecureLaunchModeForDebug"},
{200, nullptr, "CreateFloatingLibraryAppletAccepterForDebug"},
{300, nullptr, "TerminateAllRunningApplicationsForDebug"},
{900, nullptr, "GetGrcProcessLaunchedSystemEvent"},
};
// clang-format on
@@ -1252,7 +1255,7 @@ void ILibraryAppletCreator::CreateTransferMemoryStorage(Kernel::HLERequestContex
}
auto transfer_mem =
system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(handle);
system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(handle);
if (transfer_mem.IsNull()) {
LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle);
@@ -1286,7 +1289,7 @@ void ILibraryAppletCreator::CreateHandleStorage(Kernel::HLERequestContext& ctx)
}
auto transfer_mem =
system.CurrentProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(handle);
system.ApplicationProcess()->GetHandleTable().GetObject<Kernel::KTransferMemory>(handle);
if (transfer_mem.IsNull()) {
LOG_ERROR(Service_AM, "transfer_mem is a nullptr for handle={:08X}", handle);
@@ -1465,11 +1468,12 @@ void IApplicationFunctions::PopLaunchParameter(Kernel::HLERequestContext& ctx) {
const auto backend = BCAT::CreateBackendFromSettings(system, [this](u64 tid) {
return system.GetFileSystemController().GetBCATDirectory(tid);
});
const auto build_id_full = system.GetCurrentProcessBuildID();
const auto build_id_full = system.GetApplicationProcessBuildID();
u64 build_id{};
std::memcpy(&build_id, build_id_full.data(), sizeof(u64));
auto data = backend->GetLaunchParameter({system.GetCurrentProcessProgramID(), build_id});
auto data =
backend->GetLaunchParameter({system.GetApplicationProcessProgramID(), build_id});
if (data.has_value()) {
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
rb.Push(ResultSuccess);
@@ -1521,7 +1525,7 @@ void IApplicationFunctions::EnsureSaveData(Kernel::HLERequestContext& ctx) {
LOG_DEBUG(Service_AM, "called, uid={:016X}{:016X}", user_id[1], user_id[0]);
FileSys::SaveDataAttribute attribute{};
attribute.title_id = system.GetCurrentProcessProgramID();
attribute.title_id = system.GetApplicationProcessProgramID();
attribute.user_id = user_id;
attribute.type = FileSys::SaveDataType::SaveData;
const auto res = system.GetFileSystemController().CreateSaveData(
@@ -1551,7 +1555,7 @@ void IApplicationFunctions::GetDisplayVersion(Kernel::HLERequestContext& ctx) {
std::array<u8, 0x10> version_string{};
const auto res = [this] {
const auto title_id = system.GetCurrentProcessProgramID();
const auto title_id = system.GetApplicationProcessProgramID();
const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
system.GetContentProvider()};
@@ -1570,7 +1574,7 @@ void IApplicationFunctions::GetDisplayVersion(Kernel::HLERequestContext& ctx) {
const auto& version = res.first->GetVersionString();
std::copy(version.begin(), version.end(), version_string.begin());
} else {
constexpr char default_version[]{"1.0.0"};
static constexpr char default_version[]{"1.0.0"};
std::memcpy(version_string.data(), default_version, sizeof(default_version));
}
@@ -1588,7 +1592,7 @@ void IApplicationFunctions::GetDesiredLanguage(Kernel::HLERequestContext& ctx) {
u32 supported_languages = 0;
const auto res = [this] {
const auto title_id = system.GetCurrentProcessProgramID();
const auto title_id = system.GetApplicationProcessProgramID();
const FileSys::PatchManager pm{title_id, system.GetFileSystemController(),
system.GetContentProvider()};
@@ -1696,7 +1700,8 @@ void IApplicationFunctions::ExtendSaveData(Kernel::HLERequestContext& ctx) {
static_cast<u8>(type), user_id[1], user_id[0], new_normal_size, new_journal_size);
system.GetFileSystemController().WriteSaveDataSize(
type, system.GetCurrentProcessProgramID(), user_id, {new_normal_size, new_journal_size});
type, system.GetApplicationProcessProgramID(), user_id,
{new_normal_size, new_journal_size});
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess);
@@ -1720,7 +1725,7 @@ void IApplicationFunctions::GetSaveDataSize(Kernel::HLERequestContext& ctx) {
user_id[0]);
const auto size = system.GetFileSystemController().ReadSaveDataSize(
type, system.GetCurrentProcessProgramID(), user_id);
type, system.GetApplicationProcessProgramID(), user_id);
IPC::ResponseBuilder rb{ctx, 6};
rb.Push(ResultSuccess);
@@ -1838,7 +1843,6 @@ void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger
std::make_shared<IdleSys>(system)->InstallAsService(service_manager);
std::make_shared<OMM>(system)->InstallAsService(service_manager);
std::make_shared<SPSM>(system)->InstallAsService(service_manager);
std::make_shared<TCAP>(system)->InstallAsService(service_manager);
}
IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_)
@@ -1855,6 +1859,8 @@ IHomeMenuFunctions::IHomeMenuFunctions(Core::System& system_)
{31, nullptr, "GetWriterLockAccessorEx"},
{40, nullptr, "IsSleepEnabled"},
{41, nullptr, "IsRebootEnabled"},
{50, nullptr, "LaunchSystemApplet"},
{51, nullptr, "LaunchStarter"},
{100, nullptr, "PopRequestLaunchApplicationForDebug"},
{110, nullptr, "IsForceTerminateApplicationDisabledForDebug"},
{200, nullptr, "LaunchDevMenu"},

View File

@@ -166,7 +166,7 @@ void Error::Execute() {
}
const auto callback = [this] { DisplayCompleted(); };
const auto title_id = system.GetCurrentProcessProgramID();
const auto title_id = system.GetApplicationProcessProgramID();
const auto& reporter{system.GetReporter()};
switch (mode) {

View File

@@ -186,7 +186,7 @@ void PhotoViewer::Execute() {
const auto callback = [this] { ViewFinished(); };
switch (mode) {
case PhotoViewerAppletMode::CurrentApp:
frontend.ShowPhotosForApplication(system.GetCurrentProcessProgramID(), callback);
frontend.ShowPhotosForApplication(system.GetApplicationProcessProgramID(), callback);
break;
case PhotoViewerAppletMode::AllApps:
frontend.ShowAllPhotos(callback);

Some files were not shown because too many files have changed in this diff Show More