early-access version 1452
This commit is contained in:
parent
1e55ebc500
commit
0ea8f5d070
39 changed files with 399 additions and 329 deletions
|
@ -1,7 +1,7 @@
|
||||||
yuzu emulator early access
|
yuzu emulator early access
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is the source code for early-access 1444.
|
This is the source code for early-access 1452.
|
||||||
|
|
||||||
## Legal Notice
|
## Legal Notice
|
||||||
|
|
||||||
|
|
|
@ -147,7 +147,7 @@ add_library(core STATIC
|
||||||
hle/kernel/client_session.h
|
hle/kernel/client_session.h
|
||||||
hle/kernel/code_set.cpp
|
hle/kernel/code_set.cpp
|
||||||
hle/kernel/code_set.h
|
hle/kernel/code_set.h
|
||||||
hle/kernel/errors.h
|
hle/kernel/svc_results.h
|
||||||
hle/kernel/global_scheduler_context.cpp
|
hle/kernel/global_scheduler_context.cpp
|
||||||
hle/kernel/global_scheduler_context.h
|
hle/kernel/global_scheduler_context.h
|
||||||
hle/kernel/handle_table.cpp
|
hle/kernel/handle_table.cpp
|
||||||
|
@ -223,7 +223,6 @@ add_library(core STATIC
|
||||||
hle/kernel/svc.cpp
|
hle/kernel/svc.cpp
|
||||||
hle/kernel/svc.h
|
hle/kernel/svc.h
|
||||||
hle/kernel/svc_common.h
|
hle/kernel/svc_common.h
|
||||||
hle/kernel/svc_results.h
|
|
||||||
hle/kernel/svc_types.h
|
hle/kernel/svc_types.h
|
||||||
hle/kernel/svc_wrap.h
|
hle/kernel/svc_wrap.h
|
||||||
hle/kernel/time_manager.cpp
|
hle/kernel/time_manager.cpp
|
||||||
|
|
|
@ -4,11 +4,11 @@
|
||||||
|
|
||||||
#include "core/hle/kernel/client_port.h"
|
#include "core/hle/kernel/client_port.h"
|
||||||
#include "core/hle/kernel/client_session.h"
|
#include "core/hle/kernel/client_session.h"
|
||||||
#include "core/hle/kernel/errors.h"
|
|
||||||
#include "core/hle/kernel/hle_ipc.h"
|
#include "core/hle/kernel/hle_ipc.h"
|
||||||
#include "core/hle/kernel/object.h"
|
#include "core/hle/kernel/object.h"
|
||||||
#include "core/hle/kernel/server_port.h"
|
#include "core/hle/kernel/server_port.h"
|
||||||
#include "core/hle/kernel/session.h"
|
#include "core/hle/kernel/session.h"
|
||||||
|
#include "core/hle/kernel/svc_results.h"
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ std::shared_ptr<ServerPort> ClientPort::GetServerPort() const {
|
||||||
|
|
||||||
ResultVal<std::shared_ptr<ClientSession>> ClientPort::Connect() {
|
ResultVal<std::shared_ptr<ClientSession>> ClientPort::Connect() {
|
||||||
if (active_sessions >= max_sessions) {
|
if (active_sessions >= max_sessions) {
|
||||||
return ERR_MAX_CONNECTIONS_REACHED;
|
return ResultMaxConnectionsReached;
|
||||||
}
|
}
|
||||||
active_sessions++;
|
active_sessions++;
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,11 @@
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include "core/hle/kernel/client_session.h"
|
#include "core/hle/kernel/client_session.h"
|
||||||
#include "core/hle/kernel/errors.h"
|
|
||||||
#include "core/hle/kernel/hle_ipc.h"
|
#include "core/hle/kernel/hle_ipc.h"
|
||||||
#include "core/hle/kernel/k_thread.h"
|
#include "core/hle/kernel/k_thread.h"
|
||||||
#include "core/hle/kernel/server_session.h"
|
#include "core/hle/kernel/server_session.h"
|
||||||
#include "core/hle/kernel/session.h"
|
#include "core/hle/kernel/session.h"
|
||||||
|
#include "core/hle/kernel/svc_results.h"
|
||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
@ -43,7 +43,7 @@ ResultCode ClientSession::SendSyncRequest(std::shared_ptr<KThread> thread,
|
||||||
Core::Timing::CoreTiming& core_timing) {
|
Core::Timing::CoreTiming& core_timing) {
|
||||||
// Keep ServerSession alive until we're done working with it.
|
// Keep ServerSession alive until we're done working with it.
|
||||||
if (!parent->Server()) {
|
if (!parent->Server()) {
|
||||||
return ERR_SESSION_CLOSED_BY_REMOTE;
|
return ResultSessionClosedByRemote;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Signal the server session that new data is available
|
// Signal the server session that new data is available
|
||||||
|
|
|
@ -6,12 +6,12 @@
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/hle/kernel/errors.h"
|
|
||||||
#include "core/hle/kernel/handle_table.h"
|
#include "core/hle/kernel/handle_table.h"
|
||||||
#include "core/hle/kernel/k_scheduler.h"
|
#include "core/hle/kernel/k_scheduler.h"
|
||||||
#include "core/hle/kernel/k_thread.h"
|
#include "core/hle/kernel/k_thread.h"
|
||||||
#include "core/hle/kernel/kernel.h"
|
#include "core/hle/kernel/kernel.h"
|
||||||
#include "core/hle/kernel/process.h"
|
#include "core/hle/kernel/process.h"
|
||||||
|
#include "core/hle/kernel/svc_results.h"
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -33,7 +33,7 @@ HandleTable::~HandleTable() = default;
|
||||||
ResultCode HandleTable::SetSize(s32 handle_table_size) {
|
ResultCode HandleTable::SetSize(s32 handle_table_size) {
|
||||||
if (static_cast<u32>(handle_table_size) > MAX_COUNT) {
|
if (static_cast<u32>(handle_table_size) > MAX_COUNT) {
|
||||||
LOG_ERROR(Kernel, "Handle table size {} is greater than {}", handle_table_size, MAX_COUNT);
|
LOG_ERROR(Kernel, "Handle table size {} is greater than {}", handle_table_size, MAX_COUNT);
|
||||||
return ERR_OUT_OF_MEMORY;
|
return ResultOutOfMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Values less than or equal to zero indicate to use the maximum allowable
|
// Values less than or equal to zero indicate to use the maximum allowable
|
||||||
|
@ -53,7 +53,7 @@ ResultVal<Handle> HandleTable::Create(std::shared_ptr<Object> obj) {
|
||||||
const u16 slot = next_free_slot;
|
const u16 slot = next_free_slot;
|
||||||
if (slot >= table_size) {
|
if (slot >= table_size) {
|
||||||
LOG_ERROR(Kernel, "Unable to allocate Handle, too many slots in use.");
|
LOG_ERROR(Kernel, "Unable to allocate Handle, too many slots in use.");
|
||||||
return ERR_HANDLE_TABLE_FULL;
|
return ResultHandleTableFull;
|
||||||
}
|
}
|
||||||
next_free_slot = generations[slot];
|
next_free_slot = generations[slot];
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ ResultVal<Handle> HandleTable::Duplicate(Handle handle) {
|
||||||
std::shared_ptr<Object> object = GetGeneric(handle);
|
std::shared_ptr<Object> object = GetGeneric(handle);
|
||||||
if (object == nullptr) {
|
if (object == nullptr) {
|
||||||
LOG_ERROR(Kernel, "Tried to duplicate invalid handle: {:08X}", handle);
|
LOG_ERROR(Kernel, "Tried to duplicate invalid handle: {:08X}", handle);
|
||||||
return ERR_INVALID_HANDLE;
|
return ResultInvalidHandle;
|
||||||
}
|
}
|
||||||
return Create(std::move(object));
|
return Create(std::move(object));
|
||||||
}
|
}
|
||||||
|
@ -84,7 +84,7 @@ ResultVal<Handle> HandleTable::Duplicate(Handle handle) {
|
||||||
ResultCode HandleTable::Close(Handle handle) {
|
ResultCode HandleTable::Close(Handle handle) {
|
||||||
if (!IsValid(handle)) {
|
if (!IsValid(handle)) {
|
||||||
LOG_ERROR(Kernel, "Handle is not valid! handle={:08X}", handle);
|
LOG_ERROR(Kernel, "Handle is not valid! handle={:08X}", handle);
|
||||||
return ERR_INVALID_HANDLE;
|
return ResultInvalidHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u16 slot = GetSlot(handle);
|
const u16 slot = GetSlot(handle);
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "core/hle/ipc_helpers.h"
|
#include "core/hle/ipc_helpers.h"
|
||||||
#include "core/hle/kernel/errors.h"
|
|
||||||
#include "core/hle/kernel/handle_table.h"
|
#include "core/hle/kernel/handle_table.h"
|
||||||
#include "core/hle/kernel/hle_ipc.h"
|
#include "core/hle/kernel/hle_ipc.h"
|
||||||
#include "core/hle/kernel/k_readable_event.h"
|
#include "core/hle/kernel/k_readable_event.h"
|
||||||
|
@ -26,6 +25,7 @@
|
||||||
#include "core/hle/kernel/object.h"
|
#include "core/hle/kernel/object.h"
|
||||||
#include "core/hle/kernel/process.h"
|
#include "core/hle/kernel/process.h"
|
||||||
#include "core/hle/kernel/server_session.h"
|
#include "core/hle/kernel/server_session.h"
|
||||||
|
#include "core/hle/kernel/svc_results.h"
|
||||||
#include "core/hle/kernel/time_manager.h"
|
#include "core/hle/kernel/time_manager.h"
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
|
|
||||||
|
|
|
@ -120,10 +120,10 @@ ResultCode KAddressArbiter::SignalAndIncrementIfEqual(VAddr addr, s32 value, s32
|
||||||
s32 user_value{};
|
s32 user_value{};
|
||||||
if (!UpdateIfEqual(system, &user_value, addr, value, value + 1)) {
|
if (!UpdateIfEqual(system, &user_value, addr, value, value + 1)) {
|
||||||
LOG_ERROR(Kernel, "Invalid current memory!");
|
LOG_ERROR(Kernel, "Invalid current memory!");
|
||||||
return Svc::ResultInvalidCurrentMemory;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
if (user_value != value) {
|
if (user_value != value) {
|
||||||
return Svc::ResultInvalidState;
|
return ResultInvalidState;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto it = thread_tree.nfind_light({addr, -1});
|
auto it = thread_tree.nfind_light({addr, -1});
|
||||||
|
@ -189,10 +189,10 @@ ResultCode KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32
|
||||||
|
|
||||||
if (!succeeded) {
|
if (!succeeded) {
|
||||||
LOG_ERROR(Kernel, "Invalid current memory!");
|
LOG_ERROR(Kernel, "Invalid current memory!");
|
||||||
return Svc::ResultInvalidCurrentMemory;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
if (user_value != value) {
|
if (user_value != value) {
|
||||||
return Svc::ResultInvalidState;
|
return ResultInvalidState;
|
||||||
}
|
}
|
||||||
|
|
||||||
while ((it != thread_tree.end()) && (count <= 0 || num_waiters < count) &&
|
while ((it != thread_tree.end()) && (count <= 0 || num_waiters < count) &&
|
||||||
|
@ -221,11 +221,11 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement
|
||||||
// Check that the thread isn't terminating.
|
// Check that the thread isn't terminating.
|
||||||
if (cur_thread->IsTerminationRequested()) {
|
if (cur_thread->IsTerminationRequested()) {
|
||||||
slp.CancelSleep();
|
slp.CancelSleep();
|
||||||
return Svc::ResultTerminationRequested;
|
return ResultTerminationRequested;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the synced object.
|
// Set the synced object.
|
||||||
cur_thread->SetSyncedObject(nullptr, Svc::ResultTimedOut);
|
cur_thread->SetSyncedObject(nullptr, ResultTimedOut);
|
||||||
|
|
||||||
// Read the value from userspace.
|
// Read the value from userspace.
|
||||||
s32 user_value{};
|
s32 user_value{};
|
||||||
|
@ -238,19 +238,19 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement
|
||||||
|
|
||||||
if (!succeeded) {
|
if (!succeeded) {
|
||||||
slp.CancelSleep();
|
slp.CancelSleep();
|
||||||
return Svc::ResultInvalidCurrentMemory;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that the value is less than the specified one.
|
// Check that the value is less than the specified one.
|
||||||
if (user_value >= value) {
|
if (user_value >= value) {
|
||||||
slp.CancelSleep();
|
slp.CancelSleep();
|
||||||
return Svc::ResultInvalidState;
|
return ResultInvalidState;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that the timeout is non-zero.
|
// Check that the timeout is non-zero.
|
||||||
if (timeout == 0) {
|
if (timeout == 0) {
|
||||||
slp.CancelSleep();
|
slp.CancelSleep();
|
||||||
return Svc::ResultTimedOut;
|
return ResultTimedOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the arbiter.
|
// Set the arbiter.
|
||||||
|
@ -288,29 +288,29 @@ ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) {
|
||||||
// Check that the thread isn't terminating.
|
// Check that the thread isn't terminating.
|
||||||
if (cur_thread->IsTerminationRequested()) {
|
if (cur_thread->IsTerminationRequested()) {
|
||||||
slp.CancelSleep();
|
slp.CancelSleep();
|
||||||
return Svc::ResultTerminationRequested;
|
return ResultTerminationRequested;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the synced object.
|
// Set the synced object.
|
||||||
cur_thread->SetSyncedObject(nullptr, Svc::ResultTimedOut);
|
cur_thread->SetSyncedObject(nullptr, ResultTimedOut);
|
||||||
|
|
||||||
// Read the value from userspace.
|
// Read the value from userspace.
|
||||||
s32 user_value{};
|
s32 user_value{};
|
||||||
if (!ReadFromUser(system, &user_value, addr)) {
|
if (!ReadFromUser(system, &user_value, addr)) {
|
||||||
slp.CancelSleep();
|
slp.CancelSleep();
|
||||||
return Svc::ResultInvalidCurrentMemory;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that the value is equal.
|
// Check that the value is equal.
|
||||||
if (value != user_value) {
|
if (value != user_value) {
|
||||||
slp.CancelSleep();
|
slp.CancelSleep();
|
||||||
return Svc::ResultInvalidState;
|
return ResultInvalidState;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that the timeout is non-zero.
|
// Check that the timeout is non-zero.
|
||||||
if (timeout == 0) {
|
if (timeout == 0) {
|
||||||
slp.CancelSleep();
|
slp.CancelSleep();
|
||||||
return Svc::ResultTimedOut;
|
return ResultTimedOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the arbiter.
|
// Set the arbiter.
|
||||||
|
|
|
@ -92,10 +92,10 @@ ResultCode KConditionVariable::SignalToAddress(VAddr addr) {
|
||||||
// Write the value to userspace.
|
// Write the value to userspace.
|
||||||
if (!WriteToUser(system, addr, std::addressof(next_value))) {
|
if (!WriteToUser(system, addr, std::addressof(next_value))) {
|
||||||
if (next_owner_thread) {
|
if (next_owner_thread) {
|
||||||
next_owner_thread->SetSyncedObject(nullptr, Svc::ResultInvalidCurrentMemory);
|
next_owner_thread->SetSyncedObject(nullptr, ResultInvalidCurrentMemory);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Svc::ResultInvalidCurrentMemory;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,20 +114,20 @@ ResultCode KConditionVariable::WaitForAddress(Handle handle, VAddr addr, u32 val
|
||||||
cur_thread->SetSyncedObject(nullptr, RESULT_SUCCESS);
|
cur_thread->SetSyncedObject(nullptr, RESULT_SUCCESS);
|
||||||
|
|
||||||
// Check if the thread should terminate.
|
// Check if the thread should terminate.
|
||||||
R_UNLESS(!cur_thread->IsTerminationRequested(), Svc::ResultTerminationRequested);
|
R_UNLESS(!cur_thread->IsTerminationRequested(), ResultTerminationRequested);
|
||||||
|
|
||||||
{
|
{
|
||||||
// Read the tag from userspace.
|
// Read the tag from userspace.
|
||||||
u32 test_tag{};
|
u32 test_tag{};
|
||||||
R_UNLESS(ReadFromUser(system, std::addressof(test_tag), addr),
|
R_UNLESS(ReadFromUser(system, std::addressof(test_tag), addr),
|
||||||
Svc::ResultInvalidCurrentMemory);
|
ResultInvalidCurrentMemory);
|
||||||
|
|
||||||
// If the tag isn't the handle (with wait mask), we're done.
|
// If the tag isn't the handle (with wait mask), we're done.
|
||||||
R_UNLESS(test_tag == (handle | Svc::HandleWaitMask), RESULT_SUCCESS);
|
R_UNLESS(test_tag == (handle | Svc::HandleWaitMask), RESULT_SUCCESS);
|
||||||
|
|
||||||
// Get the lock owner thread.
|
// Get the lock owner thread.
|
||||||
owner_thread = kernel.CurrentProcess()->GetHandleTable().Get<KThread>(handle);
|
owner_thread = kernel.CurrentProcess()->GetHandleTable().Get<KThread>(handle);
|
||||||
R_UNLESS(owner_thread, Svc::ResultInvalidHandle);
|
R_UNLESS(owner_thread, ResultInvalidHandle);
|
||||||
|
|
||||||
// Update the lock.
|
// Update the lock.
|
||||||
cur_thread->SetAddressKey(addr, value);
|
cur_thread->SetAddressKey(addr, value);
|
||||||
|
@ -191,13 +191,13 @@ KThread* KConditionVariable::SignalImpl(KThread* thread) {
|
||||||
thread_to_close = owner_thread.get();
|
thread_to_close = owner_thread.get();
|
||||||
} else {
|
} else {
|
||||||
// The lock was tagged with a thread that doesn't exist.
|
// The lock was tagged with a thread that doesn't exist.
|
||||||
thread->SetSyncedObject(nullptr, Svc::ResultInvalidState);
|
thread->SetSyncedObject(nullptr, ResultInvalidState);
|
||||||
thread->Wakeup();
|
thread->Wakeup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// If the address wasn't accessible, note so.
|
// If the address wasn't accessible, note so.
|
||||||
thread->SetSyncedObject(nullptr, Svc::ResultInvalidCurrentMemory);
|
thread->SetSyncedObject(nullptr, ResultInvalidCurrentMemory);
|
||||||
thread->Wakeup();
|
thread->Wakeup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,12 +263,12 @@ ResultCode KConditionVariable::Wait(VAddr addr, u64 key, u32 value, s64 timeout)
|
||||||
KScopedSchedulerLockAndSleep slp{kernel, cur_thread, timeout};
|
KScopedSchedulerLockAndSleep slp{kernel, cur_thread, timeout};
|
||||||
|
|
||||||
// Set the synced object.
|
// Set the synced object.
|
||||||
cur_thread->SetSyncedObject(nullptr, Svc::ResultTimedOut);
|
cur_thread->SetSyncedObject(nullptr, ResultTimedOut);
|
||||||
|
|
||||||
// Check that the thread isn't terminating.
|
// Check that the thread isn't terminating.
|
||||||
if (cur_thread->IsTerminationRequested()) {
|
if (cur_thread->IsTerminationRequested()) {
|
||||||
slp.CancelSleep();
|
slp.CancelSleep();
|
||||||
return Svc::ResultTerminationRequested;
|
return ResultTerminationRequested;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the value and process for the next owner.
|
// Update the value and process for the next owner.
|
||||||
|
@ -302,7 +302,7 @@ ResultCode KConditionVariable::Wait(VAddr addr, u64 key, u32 value, s64 timeout)
|
||||||
// Write the value to userspace.
|
// Write the value to userspace.
|
||||||
if (!WriteToUser(system, addr, std::addressof(next_value))) {
|
if (!WriteToUser(system, addr, std::addressof(next_value))) {
|
||||||
slp.CancelSleep();
|
slp.CancelSleep();
|
||||||
return Svc::ResultInvalidCurrentMemory;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/common_funcs.h"
|
#include "common/common_funcs.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "core/hle/kernel/errors.h"
|
|
||||||
#include "core/hle/kernel/k_readable_event.h"
|
#include "core/hle/kernel/k_readable_event.h"
|
||||||
#include "core/hle/kernel/k_scheduler.h"
|
#include "core/hle/kernel/k_scheduler.h"
|
||||||
#include "core/hle/kernel/k_thread.h"
|
#include "core/hle/kernel/k_thread.h"
|
||||||
|
@ -47,7 +46,7 @@ ResultCode KReadableEvent::Reset() {
|
||||||
KScopedSchedulerLock lk{kernel};
|
KScopedSchedulerLock lk{kernel};
|
||||||
|
|
||||||
if (!is_signaled) {
|
if (!is_signaled) {
|
||||||
return Svc::ResultInvalidState;
|
return ResultInvalidState;
|
||||||
}
|
}
|
||||||
|
|
||||||
is_signaled = false;
|
is_signaled = false;
|
||||||
|
|
|
@ -75,7 +75,7 @@ s64 KResourceLimit::GetFreeValue(LimitableResource which) const {
|
||||||
ResultCode KResourceLimit::SetLimitValue(LimitableResource which, s64 value) {
|
ResultCode KResourceLimit::SetLimitValue(LimitableResource which, s64 value) {
|
||||||
const auto index = static_cast<std::size_t>(which);
|
const auto index = static_cast<std::size_t>(which);
|
||||||
KScopedLightLock lk(lock);
|
KScopedLightLock lk(lock);
|
||||||
R_UNLESS(current_values[index] <= value, Svc::ResultInvalidState);
|
R_UNLESS(current_values[index] <= value, ResultInvalidState);
|
||||||
|
|
||||||
limit_values[index] = value;
|
limit_values[index] = value;
|
||||||
|
|
||||||
|
|
|
@ -40,20 +40,20 @@ ResultCode KSynchronizationObject::Wait(KernelCore& kernel, s32* out_index,
|
||||||
// Check if the timeout is zero.
|
// Check if the timeout is zero.
|
||||||
if (timeout == 0) {
|
if (timeout == 0) {
|
||||||
slp.CancelSleep();
|
slp.CancelSleep();
|
||||||
return Svc::ResultTimedOut;
|
return ResultTimedOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if the thread should terminate.
|
// Check if the thread should terminate.
|
||||||
if (thread->IsTerminationRequested()) {
|
if (thread->IsTerminationRequested()) {
|
||||||
slp.CancelSleep();
|
slp.CancelSleep();
|
||||||
return Svc::ResultTerminationRequested;
|
return ResultTerminationRequested;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if waiting was canceled.
|
// Check if waiting was canceled.
|
||||||
if (thread->IsWaitCancelled()) {
|
if (thread->IsWaitCancelled()) {
|
||||||
slp.CancelSleep();
|
slp.CancelSleep();
|
||||||
thread->ClearWaitCancelled();
|
thread->ClearWaitCancelled();
|
||||||
return Svc::ResultCancelled;
|
return ResultCancelled;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the waiters.
|
// Add the waiters.
|
||||||
|
@ -75,7 +75,7 @@ ResultCode KSynchronizationObject::Wait(KernelCore& kernel, s32* out_index,
|
||||||
|
|
||||||
// Mark the thread as waiting.
|
// Mark the thread as waiting.
|
||||||
thread->SetCancellable();
|
thread->SetCancellable();
|
||||||
thread->SetSyncedObject(nullptr, Svc::ResultTimedOut);
|
thread->SetSyncedObject(nullptr, ResultTimedOut);
|
||||||
thread->SetState(ThreadState::Waiting);
|
thread->SetState(ThreadState::Waiting);
|
||||||
thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Synchronization);
|
thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Synchronization);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/cpu_manager.h"
|
#include "core/cpu_manager.h"
|
||||||
#include "core/hardware_properties.h"
|
#include "core/hardware_properties.h"
|
||||||
#include "core/hle/kernel/errors.h"
|
|
||||||
#include "core/hle/kernel/handle_table.h"
|
#include "core/hle/kernel/handle_table.h"
|
||||||
#include "core/hle/kernel/k_condition_variable.h"
|
#include "core/hle/kernel/k_condition_variable.h"
|
||||||
#include "core/hle/kernel/k_resource_limit.h"
|
#include "core/hle/kernel/k_resource_limit.h"
|
||||||
|
@ -127,7 +126,7 @@ ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_s
|
||||||
|
|
||||||
// Set core ID and wait result.
|
// Set core ID and wait result.
|
||||||
core_id = phys_core;
|
core_id = phys_core;
|
||||||
wait_result = Svc::ResultNoSynchronizationObject;
|
wait_result = ResultNoSynchronizationObject;
|
||||||
|
|
||||||
// Set priorities.
|
// Set priorities.
|
||||||
priority = prio;
|
priority = prio;
|
||||||
|
@ -238,7 +237,7 @@ void KThread::Finalize() {
|
||||||
while (it != waiter_list.end()) {
|
while (it != waiter_list.end()) {
|
||||||
// The thread shouldn't be a kernel waiter.
|
// The thread shouldn't be a kernel waiter.
|
||||||
it->SetLockOwner(nullptr);
|
it->SetLockOwner(nullptr);
|
||||||
it->SetSyncedObject(nullptr, Svc::ResultInvalidState);
|
it->SetSyncedObject(nullptr, ResultInvalidState);
|
||||||
it->Wakeup();
|
it->Wakeup();
|
||||||
it = waiter_list.erase(it);
|
it = waiter_list.erase(it);
|
||||||
}
|
}
|
||||||
|
@ -447,7 +446,7 @@ ResultCode KThread::SetCoreMask(s32 core_id, u64 v_affinity_mask) {
|
||||||
// If the core id is no-update magic, preserve the ideal core id.
|
// If the core id is no-update magic, preserve the ideal core id.
|
||||||
if (core_id == Svc::IdealCoreNoUpdate) {
|
if (core_id == Svc::IdealCoreNoUpdate) {
|
||||||
core_id = virtual_ideal_core_id;
|
core_id = virtual_ideal_core_id;
|
||||||
R_UNLESS(((1ULL << core_id) & v_affinity_mask) != 0, Svc::ResultInvalidCombination);
|
R_UNLESS(((1ULL << core_id) & v_affinity_mask) != 0, ResultInvalidCombination);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the virtual core/affinity mask.
|
// Set the virtual core/affinity mask.
|
||||||
|
@ -526,7 +525,7 @@ ResultCode KThread::SetCoreMask(s32 core_id, u64 v_affinity_mask) {
|
||||||
if (GetStackParameters().is_pinned) {
|
if (GetStackParameters().is_pinned) {
|
||||||
// Verify that the current thread isn't terminating.
|
// Verify that the current thread isn't terminating.
|
||||||
R_UNLESS(!GetCurrentThread(kernel).IsTerminationRequested(),
|
R_UNLESS(!GetCurrentThread(kernel).IsTerminationRequested(),
|
||||||
Svc::ResultTerminationRequested);
|
ResultTerminationRequested);
|
||||||
|
|
||||||
// Note that the thread was pinned.
|
// Note that the thread was pinned.
|
||||||
thread_is_pinned = true;
|
thread_is_pinned = true;
|
||||||
|
@ -604,7 +603,7 @@ void KThread::WaitCancel() {
|
||||||
sleeping_queue->WakeupThread(this);
|
sleeping_queue->WakeupThread(this);
|
||||||
wait_cancelled = true;
|
wait_cancelled = true;
|
||||||
} else {
|
} else {
|
||||||
SetSyncedObject(nullptr, Svc::ResultCancelled);
|
SetSyncedObject(nullptr, ResultCancelled);
|
||||||
SetState(ThreadState::Runnable);
|
SetState(ThreadState::Runnable);
|
||||||
wait_cancelled = false;
|
wait_cancelled = false;
|
||||||
}
|
}
|
||||||
|
@ -663,12 +662,12 @@ ResultCode KThread::SetActivity(Svc::ThreadActivity activity) {
|
||||||
// Verify our state.
|
// Verify our state.
|
||||||
const auto cur_state = GetState();
|
const auto cur_state = GetState();
|
||||||
R_UNLESS((cur_state == ThreadState::Waiting || cur_state == ThreadState::Runnable),
|
R_UNLESS((cur_state == ThreadState::Waiting || cur_state == ThreadState::Runnable),
|
||||||
Svc::ResultInvalidState);
|
ResultInvalidState);
|
||||||
|
|
||||||
// Either pause or resume.
|
// Either pause or resume.
|
||||||
if (activity == Svc::ThreadActivity::Paused) {
|
if (activity == Svc::ThreadActivity::Paused) {
|
||||||
// Verify that we're not suspended.
|
// Verify that we're not suspended.
|
||||||
R_UNLESS(!IsSuspendRequested(SuspendType::Thread), Svc::ResultInvalidState);
|
R_UNLESS(!IsSuspendRequested(SuspendType::Thread), ResultInvalidState);
|
||||||
|
|
||||||
// Suspend.
|
// Suspend.
|
||||||
RequestSuspend(SuspendType::Thread);
|
RequestSuspend(SuspendType::Thread);
|
||||||
|
@ -676,7 +675,7 @@ ResultCode KThread::SetActivity(Svc::ThreadActivity activity) {
|
||||||
ASSERT(activity == Svc::ThreadActivity::Runnable);
|
ASSERT(activity == Svc::ThreadActivity::Runnable);
|
||||||
|
|
||||||
// Verify that we're suspended.
|
// Verify that we're suspended.
|
||||||
R_UNLESS(IsSuspendRequested(SuspendType::Thread), Svc::ResultInvalidState);
|
R_UNLESS(IsSuspendRequested(SuspendType::Thread), ResultInvalidState);
|
||||||
|
|
||||||
// Resume.
|
// Resume.
|
||||||
Resume(SuspendType::Thread);
|
Resume(SuspendType::Thread);
|
||||||
|
@ -698,7 +697,7 @@ ResultCode KThread::SetActivity(Svc::ThreadActivity activity) {
|
||||||
if (GetStackParameters().is_pinned) {
|
if (GetStackParameters().is_pinned) {
|
||||||
// Verify that the current thread isn't terminating.
|
// Verify that the current thread isn't terminating.
|
||||||
R_UNLESS(!GetCurrentThread(kernel).IsTerminationRequested(),
|
R_UNLESS(!GetCurrentThread(kernel).IsTerminationRequested(),
|
||||||
Svc::ResultTerminationRequested);
|
ResultTerminationRequested);
|
||||||
|
|
||||||
// Note that the thread was pinned and not current.
|
// Note that the thread was pinned and not current.
|
||||||
thread_is_pinned = true;
|
thread_is_pinned = true;
|
||||||
|
@ -745,7 +744,7 @@ ResultCode KThread::GetThreadContext3(std::vector<u8>& out) {
|
||||||
KScopedSchedulerLock sl{kernel};
|
KScopedSchedulerLock sl{kernel};
|
||||||
|
|
||||||
// Verify that we're suspended.
|
// Verify that we're suspended.
|
||||||
R_UNLESS(IsSuspendRequested(SuspendType::Thread), Svc::ResultInvalidState);
|
R_UNLESS(IsSuspendRequested(SuspendType::Thread), ResultInvalidState);
|
||||||
|
|
||||||
// If we're not terminating, get the thread's user context.
|
// If we're not terminating, get the thread's user context.
|
||||||
if (!IsTerminationRequested()) {
|
if (!IsTerminationRequested()) {
|
||||||
|
@ -905,12 +904,11 @@ ResultCode KThread::Run() {
|
||||||
KScopedSchedulerLock lk{kernel};
|
KScopedSchedulerLock lk{kernel};
|
||||||
|
|
||||||
// If either this thread or the current thread are requesting termination, note it.
|
// If either this thread or the current thread are requesting termination, note it.
|
||||||
R_UNLESS(!IsTerminationRequested(), Svc::ResultTerminationRequested);
|
R_UNLESS(!IsTerminationRequested(), ResultTerminationRequested);
|
||||||
R_UNLESS(!GetCurrentThread(kernel).IsTerminationRequested(),
|
R_UNLESS(!GetCurrentThread(kernel).IsTerminationRequested(), ResultTerminationRequested);
|
||||||
Svc::ResultTerminationRequested);
|
|
||||||
|
|
||||||
// Ensure our thread state is correct.
|
// Ensure our thread state is correct.
|
||||||
R_UNLESS(GetState() == ThreadState::Initialized, Svc::ResultInvalidState);
|
R_UNLESS(GetState() == ThreadState::Initialized, ResultInvalidState);
|
||||||
|
|
||||||
// If the current thread has been asked to suspend, suspend it and retry.
|
// If the current thread has been asked to suspend, suspend it and retry.
|
||||||
if (GetCurrentThread(kernel).IsSuspended()) {
|
if (GetCurrentThread(kernel).IsSuspended()) {
|
||||||
|
@ -962,7 +960,7 @@ ResultCode KThread::Sleep(s64 timeout) {
|
||||||
// Check if the thread should terminate.
|
// Check if the thread should terminate.
|
||||||
if (IsTerminationRequested()) {
|
if (IsTerminationRequested()) {
|
||||||
slp.CancelSleep();
|
slp.CancelSleep();
|
||||||
return Svc::ResultTerminationRequested;
|
return ResultTerminationRequested;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark the thread as waiting.
|
// Mark the thread as waiting.
|
||||||
|
|
|
@ -26,7 +26,6 @@
|
||||||
#include "core/device_memory.h"
|
#include "core/device_memory.h"
|
||||||
#include "core/hardware_properties.h"
|
#include "core/hardware_properties.h"
|
||||||
#include "core/hle/kernel/client_port.h"
|
#include "core/hle/kernel/client_port.h"
|
||||||
#include "core/hle/kernel/errors.h"
|
|
||||||
#include "core/hle/kernel/handle_table.h"
|
#include "core/hle/kernel/handle_table.h"
|
||||||
#include "core/hle/kernel/k_resource_limit.h"
|
#include "core/hle/kernel/k_resource_limit.h"
|
||||||
#include "core/hle/kernel/k_scheduler.h"
|
#include "core/hle/kernel/k_scheduler.h"
|
||||||
|
@ -39,6 +38,7 @@
|
||||||
#include "core/hle/kernel/process.h"
|
#include "core/hle/kernel/process.h"
|
||||||
#include "core/hle/kernel/service_thread.h"
|
#include "core/hle/kernel/service_thread.h"
|
||||||
#include "core/hle/kernel/shared_memory.h"
|
#include "core/hle/kernel/shared_memory.h"
|
||||||
|
#include "core/hle/kernel/svc_results.h"
|
||||||
#include "core/hle/kernel/time_manager.h"
|
#include "core/hle/kernel/time_manager.h"
|
||||||
#include "core/hle/lock.h"
|
#include "core/hle/lock.h"
|
||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
|
|
|
@ -8,9 +8,9 @@
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "common/scope_exit.h"
|
#include "common/scope_exit.h"
|
||||||
#include "core/hle/kernel/errors.h"
|
|
||||||
#include "core/hle/kernel/memory/memory_manager.h"
|
#include "core/hle/kernel/memory/memory_manager.h"
|
||||||
#include "core/hle/kernel/memory/page_linked_list.h"
|
#include "core/hle/kernel/memory/page_linked_list.h"
|
||||||
|
#include "core/hle/kernel/svc_results.h"
|
||||||
|
|
||||||
namespace Kernel::Memory {
|
namespace Kernel::Memory {
|
||||||
|
|
||||||
|
@ -95,7 +95,7 @@ ResultCode MemoryManager::Allocate(PageLinkedList& page_list, std::size_t num_pa
|
||||||
// Choose a heap based on our page size request
|
// Choose a heap based on our page size request
|
||||||
const s32 heap_index{PageHeap::GetBlockIndex(num_pages)};
|
const s32 heap_index{PageHeap::GetBlockIndex(num_pages)};
|
||||||
if (heap_index < 0) {
|
if (heap_index < 0) {
|
||||||
return ERR_OUT_OF_MEMORY;
|
return ResultOutOfMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO (bunnei): Support multiple managers
|
// TODO (bunnei): Support multiple managers
|
||||||
|
@ -140,7 +140,7 @@ ResultCode MemoryManager::Allocate(PageLinkedList& page_list, std::size_t num_pa
|
||||||
|
|
||||||
// Only succeed if we allocated as many pages as we wanted
|
// Only succeed if we allocated as many pages as we wanted
|
||||||
if (num_pages) {
|
if (num_pages) {
|
||||||
return ERR_OUT_OF_MEMORY;
|
return ResultOutOfMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We succeeded!
|
// We succeeded!
|
||||||
|
|
|
@ -6,7 +6,6 @@
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/scope_exit.h"
|
#include "common/scope_exit.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/hle/kernel/errors.h"
|
|
||||||
#include "core/hle/kernel/k_scoped_resource_reservation.h"
|
#include "core/hle/kernel/k_scoped_resource_reservation.h"
|
||||||
#include "core/hle/kernel/kernel.h"
|
#include "core/hle/kernel/kernel.h"
|
||||||
#include "core/hle/kernel/memory/address_space_info.h"
|
#include "core/hle/kernel/memory/address_space_info.h"
|
||||||
|
@ -16,6 +15,7 @@
|
||||||
#include "core/hle/kernel/memory/page_table.h"
|
#include "core/hle/kernel/memory/page_table.h"
|
||||||
#include "core/hle/kernel/memory/system_control.h"
|
#include "core/hle/kernel/memory/system_control.h"
|
||||||
#include "core/hle/kernel/process.h"
|
#include "core/hle/kernel/process.h"
|
||||||
|
#include "core/hle/kernel/svc_results.h"
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
|
|
||||||
namespace Kernel::Memory {
|
namespace Kernel::Memory {
|
||||||
|
@ -141,7 +141,7 @@ ResultCode PageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_t
|
||||||
(alias_region_size + heap_region_size + stack_region_size + kernel_map_region_size)};
|
(alias_region_size + heap_region_size + stack_region_size + kernel_map_region_size)};
|
||||||
if (alloc_size < needed_size) {
|
if (alloc_size < needed_size) {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
return ERR_OUT_OF_MEMORY;
|
return ResultOutOfMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::size_t remaining_size{alloc_size - needed_size};
|
const std::size_t remaining_size{alloc_size - needed_size};
|
||||||
|
@ -277,11 +277,11 @@ ResultCode PageTable::MapProcessCode(VAddr addr, std::size_t num_pages, MemorySt
|
||||||
const u64 size{num_pages * PageSize};
|
const u64 size{num_pages * PageSize};
|
||||||
|
|
||||||
if (!CanContain(addr, size, state)) {
|
if (!CanContain(addr, size, state)) {
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsRegionMapped(addr, size)) {
|
if (IsRegionMapped(addr, size)) {
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
PageLinkedList page_linked_list;
|
PageLinkedList page_linked_list;
|
||||||
|
@ -307,7 +307,7 @@ ResultCode PageTable::MapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std::
|
||||||
MemoryAttribute::None, MemoryAttribute::IpcAndDeviceMapped));
|
MemoryAttribute::None, MemoryAttribute::IpcAndDeviceMapped));
|
||||||
|
|
||||||
if (IsRegionMapped(dst_addr, size)) {
|
if (IsRegionMapped(dst_addr, size)) {
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
PageLinkedList page_linked_list;
|
PageLinkedList page_linked_list;
|
||||||
|
@ -418,7 +418,7 @@ ResultCode PageTable::MapPhysicalMemory(VAddr addr, std::size_t size) {
|
||||||
remaining_size);
|
remaining_size);
|
||||||
if (!memory_reservation.Succeeded()) {
|
if (!memory_reservation.Succeeded()) {
|
||||||
LOG_ERROR(Kernel, "Could not reserve remaining {:X} bytes", remaining_size);
|
LOG_ERROR(Kernel, "Could not reserve remaining {:X} bytes", remaining_size);
|
||||||
return ERR_RESOURCE_LIMIT_EXCEEDED;
|
return ResultResourceLimitedExceeded;
|
||||||
}
|
}
|
||||||
|
|
||||||
PageLinkedList page_linked_list;
|
PageLinkedList page_linked_list;
|
||||||
|
@ -452,12 +452,12 @@ ResultCode PageTable::UnmapPhysicalMemory(VAddr addr, std::size_t size) {
|
||||||
block_manager->IterateForRange(addr, end_addr, [&](const MemoryInfo& info) {
|
block_manager->IterateForRange(addr, end_addr, [&](const MemoryInfo& info) {
|
||||||
if (info.state == MemoryState::Normal) {
|
if (info.state == MemoryState::Normal) {
|
||||||
if (info.attribute != MemoryAttribute::None) {
|
if (info.attribute != MemoryAttribute::None) {
|
||||||
result = ERR_INVALID_ADDRESS_STATE;
|
result = ResultInvalidCurrentMemory;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mapped_size += GetSizeInRange(info, addr, end_addr);
|
mapped_size += GetSizeInRange(info, addr, end_addr);
|
||||||
} else if (info.state != MemoryState::Free) {
|
} else if (info.state != MemoryState::Free) {
|
||||||
result = ERR_INVALID_ADDRESS_STATE;
|
result = ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -524,7 +524,7 @@ ResultCode PageTable::Map(VAddr dst_addr, VAddr src_addr, std::size_t size) {
|
||||||
MemoryAttribute::Mask, MemoryAttribute::None, MemoryAttribute::IpcAndDeviceMapped));
|
MemoryAttribute::Mask, MemoryAttribute::None, MemoryAttribute::IpcAndDeviceMapped));
|
||||||
|
|
||||||
if (IsRegionMapped(dst_addr, size)) {
|
if (IsRegionMapped(dst_addr, size)) {
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
PageLinkedList page_linked_list;
|
PageLinkedList page_linked_list;
|
||||||
|
@ -575,7 +575,7 @@ ResultCode PageTable::Unmap(VAddr dst_addr, VAddr src_addr, std::size_t size) {
|
||||||
AddRegionToPages(dst_addr, num_pages, dst_pages);
|
AddRegionToPages(dst_addr, num_pages, dst_pages);
|
||||||
|
|
||||||
if (!dst_pages.IsEqual(src_pages)) {
|
if (!dst_pages.IsEqual(src_pages)) {
|
||||||
return ERR_INVALID_MEMORY_RANGE;
|
return ResultInvalidMemoryRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -624,11 +624,11 @@ ResultCode PageTable::MapPages(VAddr addr, PageLinkedList& page_linked_list, Mem
|
||||||
const std::size_t size{num_pages * PageSize};
|
const std::size_t size{num_pages * PageSize};
|
||||||
|
|
||||||
if (!CanContain(addr, size, state)) {
|
if (!CanContain(addr, size, state)) {
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsRegionMapped(addr, num_pages * PageSize)) {
|
if (IsRegionMapped(addr, num_pages * PageSize)) {
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
CASCADE_CODE(MapPages(addr, page_linked_list, perm));
|
CASCADE_CODE(MapPages(addr, page_linked_list, perm));
|
||||||
|
@ -766,7 +766,7 @@ ResultCode PageTable::SetHeapCapacity(std::size_t new_heap_capacity) {
|
||||||
ResultVal<VAddr> PageTable::SetHeapSize(std::size_t size) {
|
ResultVal<VAddr> PageTable::SetHeapSize(std::size_t size) {
|
||||||
|
|
||||||
if (size > heap_region_end - heap_region_start) {
|
if (size > heap_region_end - heap_region_start) {
|
||||||
return ERR_OUT_OF_MEMORY;
|
return ResultOutOfMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u64 previous_heap_size{GetHeapSize()};
|
const u64 previous_heap_size{GetHeapSize()};
|
||||||
|
@ -786,7 +786,7 @@ ResultVal<VAddr> PageTable::SetHeapSize(std::size_t size) {
|
||||||
|
|
||||||
if (!memory_reservation.Succeeded()) {
|
if (!memory_reservation.Succeeded()) {
|
||||||
LOG_ERROR(Kernel, "Could not reserve heap extension of size {:X} bytes", delta);
|
LOG_ERROR(Kernel, "Could not reserve heap extension of size {:X} bytes", delta);
|
||||||
return ERR_RESOURCE_LIMIT_EXCEEDED;
|
return ResultResourceLimitedExceeded;
|
||||||
}
|
}
|
||||||
|
|
||||||
PageLinkedList page_linked_list;
|
PageLinkedList page_linked_list;
|
||||||
|
@ -796,7 +796,7 @@ ResultVal<VAddr> PageTable::SetHeapSize(std::size_t size) {
|
||||||
system.Kernel().MemoryManager().Allocate(page_linked_list, num_pages, memory_pool));
|
system.Kernel().MemoryManager().Allocate(page_linked_list, num_pages, memory_pool));
|
||||||
|
|
||||||
if (IsRegionMapped(current_heap_addr, delta)) {
|
if (IsRegionMapped(current_heap_addr, delta)) {
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
CASCADE_CODE(
|
CASCADE_CODE(
|
||||||
|
@ -821,17 +821,17 @@ ResultVal<VAddr> PageTable::AllocateAndMapMemory(std::size_t needed_num_pages, s
|
||||||
std::lock_guard lock{page_table_lock};
|
std::lock_guard lock{page_table_lock};
|
||||||
|
|
||||||
if (!CanContain(region_start, region_num_pages * PageSize, state)) {
|
if (!CanContain(region_start, region_num_pages * PageSize, state)) {
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (region_num_pages <= needed_num_pages) {
|
if (region_num_pages <= needed_num_pages) {
|
||||||
return ERR_OUT_OF_MEMORY;
|
return ResultOutOfMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
const VAddr addr{
|
const VAddr addr{
|
||||||
AllocateVirtualMemory(region_start, region_num_pages, needed_num_pages, align)};
|
AllocateVirtualMemory(region_start, region_num_pages, needed_num_pages, align)};
|
||||||
if (!addr) {
|
if (!addr) {
|
||||||
return ERR_OUT_OF_MEMORY;
|
return ResultOutOfMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_map_only) {
|
if (is_map_only) {
|
||||||
|
@ -1110,13 +1110,13 @@ constexpr ResultCode PageTable::CheckMemoryState(const MemoryInfo& info, MemoryS
|
||||||
MemoryAttribute attr) const {
|
MemoryAttribute attr) const {
|
||||||
// Validate the states match expectation
|
// Validate the states match expectation
|
||||||
if ((info.state & state_mask) != state) {
|
if ((info.state & state_mask) != state) {
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
if ((info.perm & perm_mask) != perm) {
|
if ((info.perm & perm_mask) != perm) {
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
if ((info.attribute & attr_mask) != attr) {
|
if ((info.attribute & attr_mask) != attr) {
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
|
@ -1143,14 +1143,14 @@ ResultCode PageTable::CheckMemoryState(MemoryState* out_state, MemoryPermission*
|
||||||
while (true) {
|
while (true) {
|
||||||
// Validate the current block
|
// Validate the current block
|
||||||
if (!(info.state == first_state)) {
|
if (!(info.state == first_state)) {
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
if (!(info.perm == first_perm)) {
|
if (!(info.perm == first_perm)) {
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
if (!((info.attribute | static_cast<MemoryAttribute>(ignore_attr)) ==
|
if (!((info.attribute | static_cast<MemoryAttribute>(ignore_attr)) ==
|
||||||
(first_attr | static_cast<MemoryAttribute>(ignore_attr)))) {
|
(first_attr | static_cast<MemoryAttribute>(ignore_attr)))) {
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate against the provided masks
|
// Validate against the provided masks
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
#include "core/device_memory.h"
|
#include "core/device_memory.h"
|
||||||
#include "core/file_sys/program_metadata.h"
|
#include "core/file_sys/program_metadata.h"
|
||||||
#include "core/hle/kernel/code_set.h"
|
#include "core/hle/kernel/code_set.h"
|
||||||
#include "core/hle/kernel/errors.h"
|
|
||||||
#include "core/hle/kernel/k_resource_limit.h"
|
#include "core/hle/kernel/k_resource_limit.h"
|
||||||
#include "core/hle/kernel/k_scheduler.h"
|
#include "core/hle/kernel/k_scheduler.h"
|
||||||
#include "core/hle/kernel/k_scoped_resource_reservation.h"
|
#include "core/hle/kernel/k_scoped_resource_reservation.h"
|
||||||
|
@ -256,8 +255,8 @@ ResultCode Process::Reset() {
|
||||||
KScopedSchedulerLock sl{kernel};
|
KScopedSchedulerLock sl{kernel};
|
||||||
|
|
||||||
// Validate that we're in a state that we can reset.
|
// Validate that we're in a state that we can reset.
|
||||||
R_UNLESS(status != ProcessStatus::Exited, Svc::ResultInvalidState);
|
R_UNLESS(status != ProcessStatus::Exited, ResultInvalidState);
|
||||||
R_UNLESS(is_signaled, Svc::ResultInvalidState);
|
R_UNLESS(is_signaled, ResultInvalidState);
|
||||||
|
|
||||||
// Clear signaled.
|
// Clear signaled.
|
||||||
is_signaled = false;
|
is_signaled = false;
|
||||||
|
@ -281,7 +280,7 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata,
|
||||||
if (!memory_reservation.Succeeded()) {
|
if (!memory_reservation.Succeeded()) {
|
||||||
LOG_ERROR(Kernel, "Could not reserve process memory requirements of size {:X} bytes",
|
LOG_ERROR(Kernel, "Could not reserve process memory requirements of size {:X} bytes",
|
||||||
code_size + system_resource_size);
|
code_size + system_resource_size);
|
||||||
return ERR_RESOURCE_LIMIT_EXCEEDED;
|
return ResultResourceLimitedExceeded;
|
||||||
}
|
}
|
||||||
// Initialize proces address space
|
// Initialize proces address space
|
||||||
if (const ResultCode result{
|
if (const ResultCode result{
|
||||||
|
|
|
@ -6,10 +6,10 @@
|
||||||
|
|
||||||
#include "common/bit_util.h"
|
#include "common/bit_util.h"
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "core/hle/kernel/errors.h"
|
|
||||||
#include "core/hle/kernel/handle_table.h"
|
#include "core/hle/kernel/handle_table.h"
|
||||||
#include "core/hle/kernel/memory/page_table.h"
|
#include "core/hle/kernel/memory/page_table.h"
|
||||||
#include "core/hle/kernel/process_capability.h"
|
#include "core/hle/kernel/process_capability.h"
|
||||||
|
#include "core/hle/kernel/svc_results.h"
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -123,13 +123,13 @@ ResultCode ProcessCapabilities::ParseCapabilities(const u32* capabilities,
|
||||||
// If there's only one, then there's a problem.
|
// If there's only one, then there's a problem.
|
||||||
if (i >= num_capabilities) {
|
if (i >= num_capabilities) {
|
||||||
LOG_ERROR(Kernel, "Invalid combination! i={}", i);
|
LOG_ERROR(Kernel, "Invalid combination! i={}", i);
|
||||||
return ERR_INVALID_COMBINATION;
|
return ResultInvalidCombination;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto size_flags = capabilities[i];
|
const auto size_flags = capabilities[i];
|
||||||
if (GetCapabilityType(size_flags) != CapabilityType::MapPhysical) {
|
if (GetCapabilityType(size_flags) != CapabilityType::MapPhysical) {
|
||||||
LOG_ERROR(Kernel, "Invalid capability type! size_flags={}", size_flags);
|
LOG_ERROR(Kernel, "Invalid capability type! size_flags={}", size_flags);
|
||||||
return ERR_INVALID_COMBINATION;
|
return ResultInvalidCombination;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto result = HandleMapPhysicalFlags(descriptor, size_flags, page_table);
|
const auto result = HandleMapPhysicalFlags(descriptor, size_flags, page_table);
|
||||||
|
@ -159,7 +159,7 @@ ResultCode ProcessCapabilities::ParseSingleFlagCapability(u32& set_flags, u32& s
|
||||||
const auto type = GetCapabilityType(flag);
|
const auto type = GetCapabilityType(flag);
|
||||||
|
|
||||||
if (type == CapabilityType::Unset) {
|
if (type == CapabilityType::Unset) {
|
||||||
return ERR_INVALID_CAPABILITY_DESCRIPTOR;
|
return ResultInvalidCapabilityDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Bail early on ignorable entries, as one would expect,
|
// Bail early on ignorable entries, as one would expect,
|
||||||
|
@ -176,7 +176,7 @@ ResultCode ProcessCapabilities::ParseSingleFlagCapability(u32& set_flags, u32& s
|
||||||
LOG_ERROR(Kernel,
|
LOG_ERROR(Kernel,
|
||||||
"Attempted to initialize flags that may only be initialized once. set_flags={}",
|
"Attempted to initialize flags that may only be initialized once. set_flags={}",
|
||||||
set_flags);
|
set_flags);
|
||||||
return ERR_INVALID_COMBINATION;
|
return ResultInvalidCombination;
|
||||||
}
|
}
|
||||||
set_flags |= set_flag;
|
set_flags |= set_flag;
|
||||||
|
|
||||||
|
@ -202,7 +202,7 @@ ResultCode ProcessCapabilities::ParseSingleFlagCapability(u32& set_flags, u32& s
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_ERROR(Kernel, "Invalid capability type! type={}", type);
|
LOG_ERROR(Kernel, "Invalid capability type! type={}", type);
|
||||||
return ERR_INVALID_CAPABILITY_DESCRIPTOR;
|
return ResultInvalidCapabilityDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessCapabilities::Clear() {
|
void ProcessCapabilities::Clear() {
|
||||||
|
@ -225,7 +225,7 @@ ResultCode ProcessCapabilities::HandlePriorityCoreNumFlags(u32 flags) {
|
||||||
if (priority_mask != 0 || core_mask != 0) {
|
if (priority_mask != 0 || core_mask != 0) {
|
||||||
LOG_ERROR(Kernel, "Core or priority mask are not zero! priority_mask={}, core_mask={}",
|
LOG_ERROR(Kernel, "Core or priority mask are not zero! priority_mask={}, core_mask={}",
|
||||||
priority_mask, core_mask);
|
priority_mask, core_mask);
|
||||||
return ERR_INVALID_CAPABILITY_DESCRIPTOR;
|
return ResultInvalidCapabilityDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 core_num_min = (flags >> 16) & 0xFF;
|
const u32 core_num_min = (flags >> 16) & 0xFF;
|
||||||
|
@ -233,7 +233,7 @@ ResultCode ProcessCapabilities::HandlePriorityCoreNumFlags(u32 flags) {
|
||||||
if (core_num_min > core_num_max) {
|
if (core_num_min > core_num_max) {
|
||||||
LOG_ERROR(Kernel, "Core min is greater than core max! core_num_min={}, core_num_max={}",
|
LOG_ERROR(Kernel, "Core min is greater than core max! core_num_min={}, core_num_max={}",
|
||||||
core_num_min, core_num_max);
|
core_num_min, core_num_max);
|
||||||
return ERR_INVALID_COMBINATION;
|
return ResultInvalidCombination;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 priority_min = (flags >> 10) & 0x3F;
|
const u32 priority_min = (flags >> 10) & 0x3F;
|
||||||
|
@ -242,13 +242,13 @@ ResultCode ProcessCapabilities::HandlePriorityCoreNumFlags(u32 flags) {
|
||||||
LOG_ERROR(Kernel,
|
LOG_ERROR(Kernel,
|
||||||
"Priority min is greater than priority max! priority_min={}, priority_max={}",
|
"Priority min is greater than priority max! priority_min={}, priority_max={}",
|
||||||
core_num_min, priority_max);
|
core_num_min, priority_max);
|
||||||
return ERR_INVALID_COMBINATION;
|
return ResultInvalidCombination;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The switch only has 4 usable cores.
|
// The switch only has 4 usable cores.
|
||||||
if (core_num_max >= 4) {
|
if (core_num_max >= 4) {
|
||||||
LOG_ERROR(Kernel, "Invalid max cores specified! core_num_max={}", core_num_max);
|
LOG_ERROR(Kernel, "Invalid max cores specified! core_num_max={}", core_num_max);
|
||||||
return ERR_INVALID_PROCESSOR_ID;
|
return ResultInvalidCoreId;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto make_mask = [](u64 min, u64 max) {
|
const auto make_mask = [](u64 min, u64 max) {
|
||||||
|
@ -269,7 +269,7 @@ ResultCode ProcessCapabilities::HandleSyscallFlags(u32& set_svc_bits, u32 flags)
|
||||||
|
|
||||||
// If we've already set this svc before, bail.
|
// If we've already set this svc before, bail.
|
||||||
if ((set_svc_bits & svc_bit) != 0) {
|
if ((set_svc_bits & svc_bit) != 0) {
|
||||||
return ERR_INVALID_COMBINATION;
|
return ResultInvalidCombination;
|
||||||
}
|
}
|
||||||
set_svc_bits |= svc_bit;
|
set_svc_bits |= svc_bit;
|
||||||
|
|
||||||
|
@ -283,7 +283,7 @@ ResultCode ProcessCapabilities::HandleSyscallFlags(u32& set_svc_bits, u32 flags)
|
||||||
|
|
||||||
if (svc_number >= svc_capabilities.size()) {
|
if (svc_number >= svc_capabilities.size()) {
|
||||||
LOG_ERROR(Kernel, "Process svc capability is out of range! svc_number={}", svc_number);
|
LOG_ERROR(Kernel, "Process svc capability is out of range! svc_number={}", svc_number);
|
||||||
return ERR_OUT_OF_RANGE;
|
return ResultOutOfRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
svc_capabilities[svc_number] = true;
|
svc_capabilities[svc_number] = true;
|
||||||
|
@ -321,7 +321,7 @@ ResultCode ProcessCapabilities::HandleInterruptFlags(u32 flags) {
|
||||||
if (interrupt >= interrupt_capabilities.size()) {
|
if (interrupt >= interrupt_capabilities.size()) {
|
||||||
LOG_ERROR(Kernel, "Process interrupt capability is out of range! svc_number={}",
|
LOG_ERROR(Kernel, "Process interrupt capability is out of range! svc_number={}",
|
||||||
interrupt);
|
interrupt);
|
||||||
return ERR_OUT_OF_RANGE;
|
return ResultOutOfRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
interrupt_capabilities[interrupt] = true;
|
interrupt_capabilities[interrupt] = true;
|
||||||
|
@ -334,7 +334,7 @@ ResultCode ProcessCapabilities::HandleProgramTypeFlags(u32 flags) {
|
||||||
const u32 reserved = flags >> 17;
|
const u32 reserved = flags >> 17;
|
||||||
if (reserved != 0) {
|
if (reserved != 0) {
|
||||||
LOG_ERROR(Kernel, "Reserved value is non-zero! reserved={}", reserved);
|
LOG_ERROR(Kernel, "Reserved value is non-zero! reserved={}", reserved);
|
||||||
return ERR_RESERVED_VALUE;
|
return ResultReservedValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
program_type = static_cast<ProgramType>((flags >> 14) & 0b111);
|
program_type = static_cast<ProgramType>((flags >> 14) & 0b111);
|
||||||
|
@ -354,7 +354,7 @@ ResultCode ProcessCapabilities::HandleKernelVersionFlags(u32 flags) {
|
||||||
LOG_ERROR(Kernel,
|
LOG_ERROR(Kernel,
|
||||||
"Kernel version is non zero or flags are too small! major_version={}, flags={}",
|
"Kernel version is non zero or flags are too small! major_version={}, flags={}",
|
||||||
major_version, flags);
|
major_version, flags);
|
||||||
return ERR_INVALID_CAPABILITY_DESCRIPTOR;
|
return ResultInvalidCapabilityDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
kernel_version = flags;
|
kernel_version = flags;
|
||||||
|
@ -365,7 +365,7 @@ ResultCode ProcessCapabilities::HandleHandleTableFlags(u32 flags) {
|
||||||
const u32 reserved = flags >> 26;
|
const u32 reserved = flags >> 26;
|
||||||
if (reserved != 0) {
|
if (reserved != 0) {
|
||||||
LOG_ERROR(Kernel, "Reserved value is non-zero! reserved={}", reserved);
|
LOG_ERROR(Kernel, "Reserved value is non-zero! reserved={}", reserved);
|
||||||
return ERR_RESERVED_VALUE;
|
return ResultReservedValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
handle_table_size = static_cast<s32>((flags >> 16) & 0x3FF);
|
handle_table_size = static_cast<s32>((flags >> 16) & 0x3FF);
|
||||||
|
@ -376,7 +376,7 @@ ResultCode ProcessCapabilities::HandleDebugFlags(u32 flags) {
|
||||||
const u32 reserved = flags >> 19;
|
const u32 reserved = flags >> 19;
|
||||||
if (reserved != 0) {
|
if (reserved != 0) {
|
||||||
LOG_ERROR(Kernel, "Reserved value is non-zero! reserved={}", reserved);
|
LOG_ERROR(Kernel, "Reserved value is non-zero! reserved={}", reserved);
|
||||||
return ERR_RESERVED_VALUE;
|
return ResultReservedValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
is_debuggable = (flags & 0x20000) != 0;
|
is_debuggable = (flags & 0x20000) != 0;
|
||||||
|
|
|
@ -5,11 +5,11 @@
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "core/hle/kernel/client_port.h"
|
#include "core/hle/kernel/client_port.h"
|
||||||
#include "core/hle/kernel/errors.h"
|
|
||||||
#include "core/hle/kernel/k_thread.h"
|
#include "core/hle/kernel/k_thread.h"
|
||||||
#include "core/hle/kernel/object.h"
|
#include "core/hle/kernel/object.h"
|
||||||
#include "core/hle/kernel/server_port.h"
|
#include "core/hle/kernel/server_port.h"
|
||||||
#include "core/hle/kernel/server_session.h"
|
#include "core/hle/kernel/server_session.h"
|
||||||
|
#include "core/hle/kernel/svc_results.h"
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ ServerPort::~ServerPort() = default;
|
||||||
|
|
||||||
ResultVal<std::shared_ptr<ServerSession>> ServerPort::Accept() {
|
ResultVal<std::shared_ptr<ServerSession>> ServerPort::Accept() {
|
||||||
if (pending_sessions.empty()) {
|
if (pending_sessions.empty()) {
|
||||||
return ERR_NOT_FOUND;
|
return ResultNotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto session = std::move(pending_sessions.back());
|
auto session = std::move(pending_sessions.back());
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
#include "core/cpu_manager.h"
|
#include "core/cpu_manager.h"
|
||||||
#include "core/hle/kernel/client_port.h"
|
#include "core/hle/kernel/client_port.h"
|
||||||
#include "core/hle/kernel/client_session.h"
|
#include "core/hle/kernel/client_session.h"
|
||||||
#include "core/hle/kernel/errors.h"
|
|
||||||
#include "core/hle/kernel/handle_table.h"
|
#include "core/hle/kernel/handle_table.h"
|
||||||
#include "core/hle/kernel/k_address_arbiter.h"
|
#include "core/hle/kernel/k_address_arbiter.h"
|
||||||
#include "core/hle/kernel/k_condition_variable.h"
|
#include "core/hle/kernel/k_condition_variable.h"
|
||||||
|
@ -72,49 +71,49 @@ ResultCode MapUnmapMemorySanityChecks(const Memory::PageTable& manager, VAddr ds
|
||||||
VAddr src_addr, u64 size) {
|
VAddr src_addr, u64 size) {
|
||||||
if (!Common::Is4KBAligned(dst_addr)) {
|
if (!Common::Is4KBAligned(dst_addr)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Destination address is not aligned to 4KB, 0x{:016X}", dst_addr);
|
LOG_ERROR(Kernel_SVC, "Destination address is not aligned to 4KB, 0x{:016X}", dst_addr);
|
||||||
return ERR_INVALID_ADDRESS;
|
return ResultInvalidAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Common::Is4KBAligned(src_addr)) {
|
if (!Common::Is4KBAligned(src_addr)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Source address is not aligned to 4KB, 0x{:016X}", src_addr);
|
LOG_ERROR(Kernel_SVC, "Source address is not aligned to 4KB, 0x{:016X}", src_addr);
|
||||||
return ERR_INVALID_SIZE;
|
return ResultInvalidSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
LOG_ERROR(Kernel_SVC, "Size is 0");
|
LOG_ERROR(Kernel_SVC, "Size is 0");
|
||||||
return ERR_INVALID_SIZE;
|
return ResultInvalidSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Common::Is4KBAligned(size)) {
|
if (!Common::Is4KBAligned(size)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Size is not aligned to 4KB, 0x{:016X}", size);
|
LOG_ERROR(Kernel_SVC, "Size is not aligned to 4KB, 0x{:016X}", size);
|
||||||
return ERR_INVALID_SIZE;
|
return ResultInvalidSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsValidAddressRange(dst_addr, size)) {
|
if (!IsValidAddressRange(dst_addr, size)) {
|
||||||
LOG_ERROR(Kernel_SVC,
|
LOG_ERROR(Kernel_SVC,
|
||||||
"Destination is not a valid address range, addr=0x{:016X}, size=0x{:016X}",
|
"Destination is not a valid address range, addr=0x{:016X}, size=0x{:016X}",
|
||||||
dst_addr, size);
|
dst_addr, size);
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsValidAddressRange(src_addr, size)) {
|
if (!IsValidAddressRange(src_addr, size)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Source is not a valid address range, addr=0x{:016X}, size=0x{:016X}",
|
LOG_ERROR(Kernel_SVC, "Source is not a valid address range, addr=0x{:016X}, size=0x{:016X}",
|
||||||
src_addr, size);
|
src_addr, size);
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!manager.IsInsideAddressSpace(src_addr, size)) {
|
if (!manager.IsInsideAddressSpace(src_addr, size)) {
|
||||||
LOG_ERROR(Kernel_SVC,
|
LOG_ERROR(Kernel_SVC,
|
||||||
"Source is not within the address space, addr=0x{:016X}, size=0x{:016X}",
|
"Source is not within the address space, addr=0x{:016X}, size=0x{:016X}",
|
||||||
src_addr, size);
|
src_addr, size);
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (manager.IsOutsideStackRegion(dst_addr, size)) {
|
if (manager.IsOutsideStackRegion(dst_addr, size)) {
|
||||||
LOG_ERROR(Kernel_SVC,
|
LOG_ERROR(Kernel_SVC,
|
||||||
"Destination is not within the stack region, addr=0x{:016X}, size=0x{:016X}",
|
"Destination is not within the stack region, addr=0x{:016X}, size=0x{:016X}",
|
||||||
dst_addr, size);
|
dst_addr, size);
|
||||||
return ERR_INVALID_MEMORY_RANGE;
|
return ResultInvalidMemoryRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (manager.IsInsideHeapRegion(dst_addr, size)) {
|
if (manager.IsInsideHeapRegion(dst_addr, size)) {
|
||||||
|
@ -122,7 +121,7 @@ ResultCode MapUnmapMemorySanityChecks(const Memory::PageTable& manager, VAddr ds
|
||||||
"Destination does not fit within the heap region, addr=0x{:016X}, "
|
"Destination does not fit within the heap region, addr=0x{:016X}, "
|
||||||
"size=0x{:016X}",
|
"size=0x{:016X}",
|
||||||
dst_addr, size);
|
dst_addr, size);
|
||||||
return ERR_INVALID_MEMORY_RANGE;
|
return ResultInvalidMemoryRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (manager.IsInsideAliasRegion(dst_addr, size)) {
|
if (manager.IsInsideAliasRegion(dst_addr, size)) {
|
||||||
|
@ -130,7 +129,7 @@ ResultCode MapUnmapMemorySanityChecks(const Memory::PageTable& manager, VAddr ds
|
||||||
"Destination does not fit within the map region, addr=0x{:016X}, "
|
"Destination does not fit within the map region, addr=0x{:016X}, "
|
||||||
"size=0x{:016X}",
|
"size=0x{:016X}",
|
||||||
dst_addr, size);
|
dst_addr, size);
|
||||||
return ERR_INVALID_MEMORY_RANGE;
|
return ResultInvalidMemoryRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
|
@ -148,7 +147,7 @@ ResultVal<s64> RetrieveResourceLimitValue(Core::System& system, Handle resource_
|
||||||
const auto type = static_cast<LimitableResource>(resource_type);
|
const auto type = static_cast<LimitableResource>(resource_type);
|
||||||
if (!IsValidResourceType(type)) {
|
if (!IsValidResourceType(type)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Invalid resource limit type: '{}'", resource_type);
|
LOG_ERROR(Kernel_SVC, "Invalid resource limit type: '{}'", resource_type);
|
||||||
return ERR_INVALID_ENUM_VALUE;
|
return ResultInvalidEnumValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto* const current_process = system.Kernel().CurrentProcess();
|
const auto* const current_process = system.Kernel().CurrentProcess();
|
||||||
|
@ -159,7 +158,7 @@ ResultVal<s64> RetrieveResourceLimitValue(Core::System& system, Handle resource_
|
||||||
if (!resource_limit_object) {
|
if (!resource_limit_object) {
|
||||||
LOG_ERROR(Kernel_SVC, "Handle to non-existent resource limit instance used. Handle={:08X}",
|
LOG_ERROR(Kernel_SVC, "Handle to non-existent resource limit instance used. Handle={:08X}",
|
||||||
resource_limit);
|
resource_limit);
|
||||||
return ERR_INVALID_HANDLE;
|
return ResultInvalidHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (value_type) {
|
switch (value_type) {
|
||||||
|
@ -171,7 +170,7 @@ ResultVal<s64> RetrieveResourceLimitValue(Core::System& system, Handle resource_
|
||||||
return MakeResult(resource_limit_object->GetPeakValue(type));
|
return MakeResult(resource_limit_object->GetPeakValue(type));
|
||||||
default:
|
default:
|
||||||
LOG_ERROR(Kernel_SVC, "Invalid resource value_type: '{}'", value_type);
|
LOG_ERROR(Kernel_SVC, "Invalid resource value_type: '{}'", value_type);
|
||||||
return ERR_INVALID_ENUM_VALUE;
|
return ResultInvalidEnumValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
@ -185,12 +184,12 @@ static ResultCode SetHeapSize(Core::System& system, VAddr* heap_addr, u64 heap_s
|
||||||
if ((heap_size % 0x200000) != 0) {
|
if ((heap_size % 0x200000) != 0) {
|
||||||
LOG_ERROR(Kernel_SVC, "The heap size is not a multiple of 2MB, heap_size=0x{:016X}",
|
LOG_ERROR(Kernel_SVC, "The heap size is not a multiple of 2MB, heap_size=0x{:016X}",
|
||||||
heap_size);
|
heap_size);
|
||||||
return ERR_INVALID_SIZE;
|
return ResultInvalidSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (heap_size >= 0x200000000) {
|
if (heap_size >= 0x200000000) {
|
||||||
LOG_ERROR(Kernel_SVC, "The heap size is not less than 8GB, heap_size=0x{:016X}", heap_size);
|
LOG_ERROR(Kernel_SVC, "The heap size is not less than 8GB, heap_size=0x{:016X}", heap_size);
|
||||||
return ERR_INVALID_SIZE;
|
return ResultInvalidSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& page_table{system.Kernel().CurrentProcess()->PageTable()};
|
auto& page_table{system.Kernel().CurrentProcess()->PageTable()};
|
||||||
|
@ -216,19 +215,19 @@ static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 si
|
||||||
|
|
||||||
if (!Common::Is4KBAligned(address)) {
|
if (!Common::Is4KBAligned(address)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Address not page aligned (0x{:016X})", address);
|
LOG_ERROR(Kernel_SVC, "Address not page aligned (0x{:016X})", address);
|
||||||
return ERR_INVALID_ADDRESS;
|
return ResultInvalidAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size == 0 || !Common::Is4KBAligned(size)) {
|
if (size == 0 || !Common::Is4KBAligned(size)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Invalid size (0x{:X}). Size must be non-zero and page aligned.",
|
LOG_ERROR(Kernel_SVC, "Invalid size (0x{:X}). Size must be non-zero and page aligned.",
|
||||||
size);
|
size);
|
||||||
return ERR_INVALID_ADDRESS;
|
return ResultInvalidAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsValidAddressRange(address, size)) {
|
if (!IsValidAddressRange(address, size)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Address range overflowed (Address: 0x{:016X}, Size: 0x{:016X})",
|
LOG_ERROR(Kernel_SVC, "Address range overflowed (Address: 0x{:016X}, Size: 0x{:016X})",
|
||||||
address, size);
|
address, size);
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto attributes{static_cast<Memory::MemoryAttribute>(mask | attribute)};
|
const auto attributes{static_cast<Memory::MemoryAttribute>(mask | attribute)};
|
||||||
|
@ -237,7 +236,7 @@ static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 si
|
||||||
LOG_ERROR(Kernel_SVC,
|
LOG_ERROR(Kernel_SVC,
|
||||||
"Memory attribute doesn't match the given mask (Attribute: 0x{:X}, Mask: {:X}",
|
"Memory attribute doesn't match the given mask (Attribute: 0x{:X}, Mask: {:X}",
|
||||||
attribute, mask);
|
attribute, mask);
|
||||||
return ERR_INVALID_COMBINATION;
|
return ResultInvalidCombination;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& page_table{system.Kernel().CurrentProcess()->PageTable()};
|
auto& page_table{system.Kernel().CurrentProcess()->PageTable()};
|
||||||
|
@ -301,7 +300,7 @@ static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle,
|
||||||
LOG_ERROR(Kernel_SVC,
|
LOG_ERROR(Kernel_SVC,
|
||||||
"Port Name Address is not a valid virtual address, port_name_address=0x{:016X}",
|
"Port Name Address is not a valid virtual address, port_name_address=0x{:016X}",
|
||||||
port_name_address);
|
port_name_address);
|
||||||
return ERR_NOT_FOUND;
|
return ResultNotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr std::size_t PortNameMaxLength = 11;
|
static constexpr std::size_t PortNameMaxLength = 11;
|
||||||
|
@ -310,7 +309,7 @@ static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle,
|
||||||
if (port_name.size() > PortNameMaxLength) {
|
if (port_name.size() > PortNameMaxLength) {
|
||||||
LOG_ERROR(Kernel_SVC, "Port name is too long, expected {} but got {}", PortNameMaxLength,
|
LOG_ERROR(Kernel_SVC, "Port name is too long, expected {} but got {}", PortNameMaxLength,
|
||||||
port_name.size());
|
port_name.size());
|
||||||
return ERR_OUT_OF_RANGE;
|
return ResultOutOfRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_TRACE(Kernel_SVC, "called port_name={}", port_name);
|
LOG_TRACE(Kernel_SVC, "called port_name={}", port_name);
|
||||||
|
@ -319,7 +318,7 @@ static ResultCode ConnectToNamedPort(Core::System& system, Handle* out_handle,
|
||||||
const auto it = kernel.FindNamedPort(port_name);
|
const auto it = kernel.FindNamedPort(port_name);
|
||||||
if (!kernel.IsValidNamedPort(it)) {
|
if (!kernel.IsValidNamedPort(it)) {
|
||||||
LOG_WARNING(Kernel_SVC, "tried to connect to unknown port: {}", port_name);
|
LOG_WARNING(Kernel_SVC, "tried to connect to unknown port: {}", port_name);
|
||||||
return ERR_NOT_FOUND;
|
return ResultNotFound;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto client_port = it->second;
|
auto client_port = it->second;
|
||||||
|
@ -346,7 +345,7 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) {
|
||||||
std::shared_ptr<ClientSession> session = handle_table.Get<ClientSession>(handle);
|
std::shared_ptr<ClientSession> session = handle_table.Get<ClientSession>(handle);
|
||||||
if (!session) {
|
if (!session) {
|
||||||
LOG_ERROR(Kernel_SVC, "called with invalid handle=0x{:08X}", handle);
|
LOG_ERROR(Kernel_SVC, "called with invalid handle=0x{:08X}", handle);
|
||||||
return ERR_INVALID_HANDLE;
|
return ResultInvalidHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName());
|
LOG_TRACE(Kernel_SVC, "called handle=0x{:08X}({})", handle, session->GetName());
|
||||||
|
@ -411,7 +410,7 @@ static ResultCode GetProcessId(Core::System& system, u64* process_id, Handle han
|
||||||
const Process* const owner_process = thread->GetOwnerProcess();
|
const Process* const owner_process = thread->GetOwnerProcess();
|
||||||
if (!owner_process) {
|
if (!owner_process) {
|
||||||
LOG_ERROR(Kernel_SVC, "Non-existent owning process encountered.");
|
LOG_ERROR(Kernel_SVC, "Non-existent owning process encountered.");
|
||||||
return ERR_INVALID_HANDLE;
|
return ResultInvalidHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
*process_id = owner_process->GetProcessID();
|
*process_id = owner_process->GetProcessID();
|
||||||
|
@ -421,7 +420,7 @@ static ResultCode GetProcessId(Core::System& system, u64* process_id, Handle han
|
||||||
// NOTE: This should also handle debug objects before returning.
|
// NOTE: This should also handle debug objects before returning.
|
||||||
|
|
||||||
LOG_ERROR(Kernel_SVC, "Handle does not exist, handle=0x{:08X}", handle);
|
LOG_ERROR(Kernel_SVC, "Handle does not exist, handle=0x{:08X}", handle);
|
||||||
return ERR_INVALID_HANDLE;
|
return ResultInvalidHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ResultCode GetProcessId32(Core::System& system, u32* process_id_low, u32* process_id_high,
|
static ResultCode GetProcessId32(Core::System& system, u32* process_id_low, u32* process_id_high,
|
||||||
|
@ -444,7 +443,7 @@ static ResultCode WaitSynchronization(Core::System& system, s32* index, VAddr ha
|
||||||
LOG_ERROR(Kernel_SVC,
|
LOG_ERROR(Kernel_SVC,
|
||||||
"Handle address is not a valid virtual address, handle_address=0x{:016X}",
|
"Handle address is not a valid virtual address, handle_address=0x{:016X}",
|
||||||
handles_address);
|
handles_address);
|
||||||
return ERR_INVALID_POINTER;
|
return ResultInvalidPointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr u64 MaxHandles = 0x40;
|
static constexpr u64 MaxHandles = 0x40;
|
||||||
|
@ -452,7 +451,7 @@ static ResultCode WaitSynchronization(Core::System& system, s32* index, VAddr ha
|
||||||
if (handle_count > MaxHandles) {
|
if (handle_count > MaxHandles) {
|
||||||
LOG_ERROR(Kernel_SVC, "Handle count specified is too large, expected {} but got {}",
|
LOG_ERROR(Kernel_SVC, "Handle count specified is too large, expected {} but got {}",
|
||||||
MaxHandles, handle_count);
|
MaxHandles, handle_count);
|
||||||
return ERR_OUT_OF_RANGE;
|
return ResultOutOfRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& kernel = system.Kernel();
|
auto& kernel = system.Kernel();
|
||||||
|
@ -465,7 +464,7 @@ static ResultCode WaitSynchronization(Core::System& system, s32* index, VAddr ha
|
||||||
|
|
||||||
if (object == nullptr) {
|
if (object == nullptr) {
|
||||||
LOG_ERROR(Kernel_SVC, "Object is a nullptr");
|
LOG_ERROR(Kernel_SVC, "Object is a nullptr");
|
||||||
return ERR_INVALID_HANDLE;
|
return ResultInvalidHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
objects[i] = object.get();
|
objects[i] = object.get();
|
||||||
|
@ -487,6 +486,7 @@ static ResultCode CancelSynchronization(Core::System& system, Handle thread_hand
|
||||||
// Get the thread from its handle.
|
// Get the thread from its handle.
|
||||||
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
|
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
|
||||||
std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
|
std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
|
||||||
|
|
||||||
if (!thread) {
|
if (!thread) {
|
||||||
LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle);
|
LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle);
|
||||||
return ResultInvalidHandle;
|
return ResultInvalidHandle;
|
||||||
|
@ -531,6 +531,7 @@ static ResultCode ArbitrateUnlock(Core::System& system, VAddr address) {
|
||||||
LOG_TRACE(Kernel_SVC, "called address=0x{:X}", address);
|
LOG_TRACE(Kernel_SVC, "called address=0x{:X}", address);
|
||||||
|
|
||||||
// Validate the input address.
|
// Validate the input address.
|
||||||
|
|
||||||
if (Memory::IsKernelAddress(address)) {
|
if (Memory::IsKernelAddress(address)) {
|
||||||
LOG_ERROR(Kernel_SVC,
|
LOG_ERROR(Kernel_SVC,
|
||||||
"Attempting to arbitrate an unlock on a kernel address (address={:08X})",
|
"Attempting to arbitrate an unlock on a kernel address (address={:08X})",
|
||||||
|
@ -741,7 +742,7 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha
|
||||||
if (info_sub_id != 0) {
|
if (info_sub_id != 0) {
|
||||||
LOG_ERROR(Kernel_SVC, "Info sub id is non zero! info_id={}, info_sub_id={}", info_id,
|
LOG_ERROR(Kernel_SVC, "Info sub id is non zero! info_id={}, info_sub_id={}", info_id,
|
||||||
info_sub_id);
|
info_sub_id);
|
||||||
return ERR_INVALID_ENUM_VALUE;
|
return ResultInvalidEnumValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& current_process_handle_table =
|
const auto& current_process_handle_table =
|
||||||
|
@ -750,7 +751,7 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha
|
||||||
if (!process) {
|
if (!process) {
|
||||||
LOG_ERROR(Kernel_SVC, "Process is not valid! info_id={}, info_sub_id={}, handle={:08X}",
|
LOG_ERROR(Kernel_SVC, "Process is not valid! info_id={}, info_sub_id={}, handle={:08X}",
|
||||||
info_id, info_sub_id, handle);
|
info_id, info_sub_id, handle);
|
||||||
return ERR_INVALID_HANDLE;
|
return ResultInvalidHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (info_id_type) {
|
switch (info_id_type) {
|
||||||
|
@ -832,7 +833,7 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_ERROR(Kernel_SVC, "Unimplemented svcGetInfo id=0x{:016X}", info_id);
|
LOG_ERROR(Kernel_SVC, "Unimplemented svcGetInfo id=0x{:016X}", info_id);
|
||||||
return ERR_INVALID_ENUM_VALUE;
|
return ResultInvalidEnumValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
case GetInfoType::IsCurrentProcessBeingDebugged:
|
case GetInfoType::IsCurrentProcessBeingDebugged:
|
||||||
|
@ -842,13 +843,13 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha
|
||||||
case GetInfoType::RegisterResourceLimit: {
|
case GetInfoType::RegisterResourceLimit: {
|
||||||
if (handle != 0) {
|
if (handle != 0) {
|
||||||
LOG_ERROR(Kernel, "Handle is non zero! handle={:08X}", handle);
|
LOG_ERROR(Kernel, "Handle is non zero! handle={:08X}", handle);
|
||||||
return ERR_INVALID_HANDLE;
|
return ResultInvalidHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info_sub_id != 0) {
|
if (info_sub_id != 0) {
|
||||||
LOG_ERROR(Kernel, "Info sub id is non zero! info_id={}, info_sub_id={}", info_id,
|
LOG_ERROR(Kernel, "Info sub id is non zero! info_id={}, info_sub_id={}", info_id,
|
||||||
info_sub_id);
|
info_sub_id);
|
||||||
return ERR_INVALID_COMBINATION;
|
return ResultInvalidCombination;
|
||||||
}
|
}
|
||||||
|
|
||||||
Process* const current_process = system.Kernel().CurrentProcess();
|
Process* const current_process = system.Kernel().CurrentProcess();
|
||||||
|
@ -873,13 +874,13 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha
|
||||||
if (handle != 0) {
|
if (handle != 0) {
|
||||||
LOG_ERROR(Kernel_SVC, "Process Handle is non zero, expected 0 result but got {:016X}",
|
LOG_ERROR(Kernel_SVC, "Process Handle is non zero, expected 0 result but got {:016X}",
|
||||||
handle);
|
handle);
|
||||||
return ERR_INVALID_HANDLE;
|
return ResultInvalidHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (info_sub_id >= Process::RANDOM_ENTROPY_SIZE) {
|
if (info_sub_id >= Process::RANDOM_ENTROPY_SIZE) {
|
||||||
LOG_ERROR(Kernel_SVC, "Entropy size is out of range, expected {} but got {}",
|
LOG_ERROR(Kernel_SVC, "Entropy size is out of range, expected {} but got {}",
|
||||||
Process::RANDOM_ENTROPY_SIZE, info_sub_id);
|
Process::RANDOM_ENTROPY_SIZE, info_sub_id);
|
||||||
return ERR_INVALID_COMBINATION;
|
return ResultInvalidCombination;
|
||||||
}
|
}
|
||||||
|
|
||||||
*result = system.Kernel().CurrentProcess()->GetRandomEntropy(info_sub_id);
|
*result = system.Kernel().CurrentProcess()->GetRandomEntropy(info_sub_id);
|
||||||
|
@ -896,7 +897,7 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha
|
||||||
if (info_sub_id != 0xFFFFFFFFFFFFFFFF && info_sub_id >= num_cpus) {
|
if (info_sub_id != 0xFFFFFFFFFFFFFFFF && info_sub_id >= num_cpus) {
|
||||||
LOG_ERROR(Kernel_SVC, "Core count is out of range, expected {} but got {}", num_cpus,
|
LOG_ERROR(Kernel_SVC, "Core count is out of range, expected {} but got {}", num_cpus,
|
||||||
info_sub_id);
|
info_sub_id);
|
||||||
return ERR_INVALID_COMBINATION;
|
return ResultInvalidCombination;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto thread = system.Kernel().CurrentProcess()->GetHandleTable().Get<KThread>(
|
const auto thread = system.Kernel().CurrentProcess()->GetHandleTable().Get<KThread>(
|
||||||
|
@ -904,7 +905,7 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha
|
||||||
if (!thread) {
|
if (!thread) {
|
||||||
LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}",
|
LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}",
|
||||||
static_cast<Handle>(handle));
|
static_cast<Handle>(handle));
|
||||||
return ERR_INVALID_HANDLE;
|
return ResultInvalidHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& core_timing = system.CoreTiming();
|
const auto& core_timing = system.CoreTiming();
|
||||||
|
@ -928,7 +929,7 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha
|
||||||
|
|
||||||
default:
|
default:
|
||||||
LOG_ERROR(Kernel_SVC, "Unimplemented svcGetInfo id=0x{:016X}", info_id);
|
LOG_ERROR(Kernel_SVC, "Unimplemented svcGetInfo id=0x{:016X}", info_id);
|
||||||
return ERR_INVALID_ENUM_VALUE;
|
return ResultInvalidEnumValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -951,22 +952,22 @@ static ResultCode MapPhysicalMemory(Core::System& system, VAddr addr, u64 size)
|
||||||
|
|
||||||
if (!Common::Is4KBAligned(addr)) {
|
if (!Common::Is4KBAligned(addr)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Address is not aligned to 4KB, 0x{:016X}", addr);
|
LOG_ERROR(Kernel_SVC, "Address is not aligned to 4KB, 0x{:016X}", addr);
|
||||||
return ERR_INVALID_ADDRESS;
|
return ResultInvalidAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Common::Is4KBAligned(size)) {
|
if (!Common::Is4KBAligned(size)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Size is not aligned to 4KB, 0x{:X}", size);
|
LOG_ERROR(Kernel_SVC, "Size is not aligned to 4KB, 0x{:X}", size);
|
||||||
return ERR_INVALID_SIZE;
|
return ResultInvalidSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
LOG_ERROR(Kernel_SVC, "Size is zero");
|
LOG_ERROR(Kernel_SVC, "Size is zero");
|
||||||
return ERR_INVALID_SIZE;
|
return ResultInvalidSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(addr < addr + size)) {
|
if (!(addr < addr + size)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Size causes 64-bit overflow of address");
|
LOG_ERROR(Kernel_SVC, "Size causes 64-bit overflow of address");
|
||||||
return ERR_INVALID_MEMORY_RANGE;
|
return ResultInvalidMemoryRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
Process* const current_process{system.Kernel().CurrentProcess()};
|
Process* const current_process{system.Kernel().CurrentProcess()};
|
||||||
|
@ -974,21 +975,21 @@ static ResultCode MapPhysicalMemory(Core::System& system, VAddr addr, u64 size)
|
||||||
|
|
||||||
if (current_process->GetSystemResourceSize() == 0) {
|
if (current_process->GetSystemResourceSize() == 0) {
|
||||||
LOG_ERROR(Kernel_SVC, "System Resource Size is zero");
|
LOG_ERROR(Kernel_SVC, "System Resource Size is zero");
|
||||||
return ERR_INVALID_STATE;
|
return ResultInvalidState;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!page_table.IsInsideAddressSpace(addr, size)) {
|
if (!page_table.IsInsideAddressSpace(addr, size)) {
|
||||||
LOG_ERROR(Kernel_SVC,
|
LOG_ERROR(Kernel_SVC,
|
||||||
"Address is not within the address space, addr=0x{:016X}, size=0x{:016X}", addr,
|
"Address is not within the address space, addr=0x{:016X}, size=0x{:016X}", addr,
|
||||||
size);
|
size);
|
||||||
return ERR_INVALID_MEMORY_RANGE;
|
return ResultInvalidMemoryRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (page_table.IsOutsideAliasRegion(addr, size)) {
|
if (page_table.IsOutsideAliasRegion(addr, size)) {
|
||||||
LOG_ERROR(Kernel_SVC,
|
LOG_ERROR(Kernel_SVC,
|
||||||
"Address is not within the alias region, addr=0x{:016X}, size=0x{:016X}", addr,
|
"Address is not within the alias region, addr=0x{:016X}, size=0x{:016X}", addr,
|
||||||
size);
|
size);
|
||||||
return ERR_INVALID_MEMORY_RANGE;
|
return ResultInvalidMemoryRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
return page_table.MapPhysicalMemory(addr, size);
|
return page_table.MapPhysicalMemory(addr, size);
|
||||||
|
@ -1005,22 +1006,22 @@ static ResultCode UnmapPhysicalMemory(Core::System& system, VAddr addr, u64 size
|
||||||
|
|
||||||
if (!Common::Is4KBAligned(addr)) {
|
if (!Common::Is4KBAligned(addr)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Address is not aligned to 4KB, 0x{:016X}", addr);
|
LOG_ERROR(Kernel_SVC, "Address is not aligned to 4KB, 0x{:016X}", addr);
|
||||||
return ERR_INVALID_ADDRESS;
|
return ResultInvalidAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Common::Is4KBAligned(size)) {
|
if (!Common::Is4KBAligned(size)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Size is not aligned to 4KB, 0x{:X}", size);
|
LOG_ERROR(Kernel_SVC, "Size is not aligned to 4KB, 0x{:X}", size);
|
||||||
return ERR_INVALID_SIZE;
|
return ResultInvalidSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
LOG_ERROR(Kernel_SVC, "Size is zero");
|
LOG_ERROR(Kernel_SVC, "Size is zero");
|
||||||
return ERR_INVALID_SIZE;
|
return ResultInvalidSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(addr < addr + size)) {
|
if (!(addr < addr + size)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Size causes 64-bit overflow of address");
|
LOG_ERROR(Kernel_SVC, "Size causes 64-bit overflow of address");
|
||||||
return ERR_INVALID_MEMORY_RANGE;
|
return ResultInvalidMemoryRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
Process* const current_process{system.Kernel().CurrentProcess()};
|
Process* const current_process{system.Kernel().CurrentProcess()};
|
||||||
|
@ -1028,21 +1029,21 @@ static ResultCode UnmapPhysicalMemory(Core::System& system, VAddr addr, u64 size
|
||||||
|
|
||||||
if (current_process->GetSystemResourceSize() == 0) {
|
if (current_process->GetSystemResourceSize() == 0) {
|
||||||
LOG_ERROR(Kernel_SVC, "System Resource Size is zero");
|
LOG_ERROR(Kernel_SVC, "System Resource Size is zero");
|
||||||
return ERR_INVALID_STATE;
|
return ResultInvalidState;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!page_table.IsInsideAddressSpace(addr, size)) {
|
if (!page_table.IsInsideAddressSpace(addr, size)) {
|
||||||
LOG_ERROR(Kernel_SVC,
|
LOG_ERROR(Kernel_SVC,
|
||||||
"Address is not within the address space, addr=0x{:016X}, size=0x{:016X}", addr,
|
"Address is not within the address space, addr=0x{:016X}, size=0x{:016X}", addr,
|
||||||
size);
|
size);
|
||||||
return ERR_INVALID_MEMORY_RANGE;
|
return ResultInvalidMemoryRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (page_table.IsOutsideAliasRegion(addr, size)) {
|
if (page_table.IsOutsideAliasRegion(addr, size)) {
|
||||||
LOG_ERROR(Kernel_SVC,
|
LOG_ERROR(Kernel_SVC,
|
||||||
"Address is not within the alias region, addr=0x{:016X}, size=0x{:016X}", addr,
|
"Address is not within the alias region, addr=0x{:016X}, size=0x{:016X}", addr,
|
||||||
size);
|
size);
|
||||||
return ERR_INVALID_MEMORY_RANGE;
|
return ResultInvalidMemoryRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
return page_table.UnmapPhysicalMemory(addr, size);
|
return page_table.UnmapPhysicalMemory(addr, size);
|
||||||
|
@ -1212,23 +1213,23 @@ static ResultCode MapSharedMemory(Core::System& system, Handle shared_memory_han
|
||||||
|
|
||||||
if (!Common::Is4KBAligned(addr)) {
|
if (!Common::Is4KBAligned(addr)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Address is not aligned to 4KB, addr=0x{:016X}", addr);
|
LOG_ERROR(Kernel_SVC, "Address is not aligned to 4KB, addr=0x{:016X}", addr);
|
||||||
return ERR_INVALID_ADDRESS;
|
return ResultInvalidAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
LOG_ERROR(Kernel_SVC, "Size is 0");
|
LOG_ERROR(Kernel_SVC, "Size is 0");
|
||||||
return ERR_INVALID_SIZE;
|
return ResultInvalidSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Common::Is4KBAligned(size)) {
|
if (!Common::Is4KBAligned(size)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Size is not aligned to 4KB, size=0x{:016X}", size);
|
LOG_ERROR(Kernel_SVC, "Size is not aligned to 4KB, size=0x{:016X}", size);
|
||||||
return ERR_INVALID_SIZE;
|
return ResultInvalidSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsValidAddressRange(addr, size)) {
|
if (!IsValidAddressRange(addr, size)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Region is not a valid address range, addr=0x{:016X}, size=0x{:016X}",
|
LOG_ERROR(Kernel_SVC, "Region is not a valid address range, addr=0x{:016X}, size=0x{:016X}",
|
||||||
addr, size);
|
addr, size);
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto permission_type = static_cast<Memory::MemoryPermission>(permissions);
|
const auto permission_type = static_cast<Memory::MemoryPermission>(permissions);
|
||||||
|
@ -1236,7 +1237,7 @@ static ResultCode MapSharedMemory(Core::System& system, Handle shared_memory_han
|
||||||
Memory::MemoryPermission::ReadAndWrite) {
|
Memory::MemoryPermission::ReadAndWrite) {
|
||||||
LOG_ERROR(Kernel_SVC, "Expected Read or ReadWrite permission but got permissions=0x{:08X}",
|
LOG_ERROR(Kernel_SVC, "Expected Read or ReadWrite permission but got permissions=0x{:08X}",
|
||||||
permissions);
|
permissions);
|
||||||
return ERR_INVALID_MEMORY_PERMISSIONS;
|
return ResultInvalidMemoryPermissions;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* const current_process{system.Kernel().CurrentProcess()};
|
auto* const current_process{system.Kernel().CurrentProcess()};
|
||||||
|
@ -1247,7 +1248,7 @@ static ResultCode MapSharedMemory(Core::System& system, Handle shared_memory_han
|
||||||
"Addr does not fit within the valid region, addr=0x{:016X}, "
|
"Addr does not fit within the valid region, addr=0x{:016X}, "
|
||||||
"size=0x{:016X}",
|
"size=0x{:016X}",
|
||||||
addr, size);
|
addr, size);
|
||||||
return ERR_INVALID_MEMORY_RANGE;
|
return ResultInvalidMemoryRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (page_table.IsInsideHeapRegion(addr, size)) {
|
if (page_table.IsInsideHeapRegion(addr, size)) {
|
||||||
|
@ -1255,7 +1256,7 @@ static ResultCode MapSharedMemory(Core::System& system, Handle shared_memory_han
|
||||||
"Addr does not fit within the heap region, addr=0x{:016X}, "
|
"Addr does not fit within the heap region, addr=0x{:016X}, "
|
||||||
"size=0x{:016X}",
|
"size=0x{:016X}",
|
||||||
addr, size);
|
addr, size);
|
||||||
return ERR_INVALID_MEMORY_RANGE;
|
return ResultInvalidMemoryRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (page_table.IsInsideAliasRegion(addr, size)) {
|
if (page_table.IsInsideAliasRegion(addr, size)) {
|
||||||
|
@ -1263,14 +1264,14 @@ static ResultCode MapSharedMemory(Core::System& system, Handle shared_memory_han
|
||||||
"Address does not fit within the map region, addr=0x{:016X}, "
|
"Address does not fit within the map region, addr=0x{:016X}, "
|
||||||
"size=0x{:016X}",
|
"size=0x{:016X}",
|
||||||
addr, size);
|
addr, size);
|
||||||
return ERR_INVALID_MEMORY_RANGE;
|
return ResultInvalidMemoryRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto shared_memory{current_process->GetHandleTable().Get<SharedMemory>(shared_memory_handle)};
|
auto shared_memory{current_process->GetHandleTable().Get<SharedMemory>(shared_memory_handle)};
|
||||||
if (!shared_memory) {
|
if (!shared_memory) {
|
||||||
LOG_ERROR(Kernel_SVC, "Shared memory does not exist, shared_memory_handle=0x{:08X}",
|
LOG_ERROR(Kernel_SVC, "Shared memory does not exist, shared_memory_handle=0x{:08X}",
|
||||||
shared_memory_handle);
|
shared_memory_handle);
|
||||||
return ERR_INVALID_HANDLE;
|
return ResultInvalidHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
return shared_memory->Map(*current_process, addr, size, permission_type);
|
return shared_memory->Map(*current_process, addr, size, permission_type);
|
||||||
|
@ -1291,7 +1292,7 @@ static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_add
|
||||||
if (!process) {
|
if (!process) {
|
||||||
LOG_ERROR(Kernel_SVC, "Process handle does not exist, process_handle=0x{:08X}",
|
LOG_ERROR(Kernel_SVC, "Process handle does not exist, process_handle=0x{:08X}",
|
||||||
process_handle);
|
process_handle);
|
||||||
return ERR_INVALID_HANDLE;
|
return ResultInvalidHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& memory{system.Memory()};
|
auto& memory{system.Memory()};
|
||||||
|
@ -1338,18 +1339,18 @@ static ResultCode MapProcessCodeMemory(Core::System& system, Handle process_hand
|
||||||
if (!Common::Is4KBAligned(src_address)) {
|
if (!Common::Is4KBAligned(src_address)) {
|
||||||
LOG_ERROR(Kernel_SVC, "src_address is not page-aligned (src_address=0x{:016X}).",
|
LOG_ERROR(Kernel_SVC, "src_address is not page-aligned (src_address=0x{:016X}).",
|
||||||
src_address);
|
src_address);
|
||||||
return ERR_INVALID_ADDRESS;
|
return ResultInvalidAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Common::Is4KBAligned(dst_address)) {
|
if (!Common::Is4KBAligned(dst_address)) {
|
||||||
LOG_ERROR(Kernel_SVC, "dst_address is not page-aligned (dst_address=0x{:016X}).",
|
LOG_ERROR(Kernel_SVC, "dst_address is not page-aligned (dst_address=0x{:016X}).",
|
||||||
dst_address);
|
dst_address);
|
||||||
return ERR_INVALID_ADDRESS;
|
return ResultInvalidAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size == 0 || !Common::Is4KBAligned(size)) {
|
if (size == 0 || !Common::Is4KBAligned(size)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Size is zero or not page-aligned (size=0x{:016X})", size);
|
LOG_ERROR(Kernel_SVC, "Size is zero or not page-aligned (size=0x{:016X})", size);
|
||||||
return ERR_INVALID_SIZE;
|
return ResultInvalidSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsValidAddressRange(dst_address, size)) {
|
if (!IsValidAddressRange(dst_address, size)) {
|
||||||
|
@ -1357,7 +1358,7 @@ static ResultCode MapProcessCodeMemory(Core::System& system, Handle process_hand
|
||||||
"Destination address range overflows the address space (dst_address=0x{:016X}, "
|
"Destination address range overflows the address space (dst_address=0x{:016X}, "
|
||||||
"size=0x{:016X}).",
|
"size=0x{:016X}).",
|
||||||
dst_address, size);
|
dst_address, size);
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsValidAddressRange(src_address, size)) {
|
if (!IsValidAddressRange(src_address, size)) {
|
||||||
|
@ -1365,7 +1366,7 @@ static ResultCode MapProcessCodeMemory(Core::System& system, Handle process_hand
|
||||||
"Source address range overflows the address space (src_address=0x{:016X}, "
|
"Source address range overflows the address space (src_address=0x{:016X}, "
|
||||||
"size=0x{:016X}).",
|
"size=0x{:016X}).",
|
||||||
src_address, size);
|
src_address, size);
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
|
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
|
||||||
|
@ -1373,7 +1374,7 @@ static ResultCode MapProcessCodeMemory(Core::System& system, Handle process_hand
|
||||||
if (!process) {
|
if (!process) {
|
||||||
LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).",
|
LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).",
|
||||||
process_handle);
|
process_handle);
|
||||||
return ERR_INVALID_HANDLE;
|
return ResultInvalidHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& page_table = process->PageTable();
|
auto& page_table = process->PageTable();
|
||||||
|
@ -1382,7 +1383,7 @@ static ResultCode MapProcessCodeMemory(Core::System& system, Handle process_hand
|
||||||
"Source address range is not within the address space (src_address=0x{:016X}, "
|
"Source address range is not within the address space (src_address=0x{:016X}, "
|
||||||
"size=0x{:016X}).",
|
"size=0x{:016X}).",
|
||||||
src_address, size);
|
src_address, size);
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!page_table.IsInsideASLRRegion(dst_address, size)) {
|
if (!page_table.IsInsideASLRRegion(dst_address, size)) {
|
||||||
|
@ -1390,7 +1391,7 @@ static ResultCode MapProcessCodeMemory(Core::System& system, Handle process_hand
|
||||||
"Destination address range is not within the ASLR region (dst_address=0x{:016X}, "
|
"Destination address range is not within the ASLR region (dst_address=0x{:016X}, "
|
||||||
"size=0x{:016X}).",
|
"size=0x{:016X}).",
|
||||||
dst_address, size);
|
dst_address, size);
|
||||||
return ERR_INVALID_MEMORY_RANGE;
|
return ResultInvalidMemoryRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
return page_table.MapProcessCodeMemory(dst_address, src_address, size);
|
return page_table.MapProcessCodeMemory(dst_address, src_address, size);
|
||||||
|
@ -1406,18 +1407,18 @@ static ResultCode UnmapProcessCodeMemory(Core::System& system, Handle process_ha
|
||||||
if (!Common::Is4KBAligned(dst_address)) {
|
if (!Common::Is4KBAligned(dst_address)) {
|
||||||
LOG_ERROR(Kernel_SVC, "dst_address is not page-aligned (dst_address=0x{:016X}).",
|
LOG_ERROR(Kernel_SVC, "dst_address is not page-aligned (dst_address=0x{:016X}).",
|
||||||
dst_address);
|
dst_address);
|
||||||
return ERR_INVALID_ADDRESS;
|
return ResultInvalidAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Common::Is4KBAligned(src_address)) {
|
if (!Common::Is4KBAligned(src_address)) {
|
||||||
LOG_ERROR(Kernel_SVC, "src_address is not page-aligned (src_address=0x{:016X}).",
|
LOG_ERROR(Kernel_SVC, "src_address is not page-aligned (src_address=0x{:016X}).",
|
||||||
src_address);
|
src_address);
|
||||||
return ERR_INVALID_ADDRESS;
|
return ResultInvalidAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size == 0 || Common::Is4KBAligned(size)) {
|
if (size == 0 || Common::Is4KBAligned(size)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Size is zero or not page-aligned (size=0x{:016X}).", size);
|
LOG_ERROR(Kernel_SVC, "Size is zero or not page-aligned (size=0x{:016X}).", size);
|
||||||
return ERR_INVALID_SIZE;
|
return ResultInvalidSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsValidAddressRange(dst_address, size)) {
|
if (!IsValidAddressRange(dst_address, size)) {
|
||||||
|
@ -1425,7 +1426,7 @@ static ResultCode UnmapProcessCodeMemory(Core::System& system, Handle process_ha
|
||||||
"Destination address range overflows the address space (dst_address=0x{:016X}, "
|
"Destination address range overflows the address space (dst_address=0x{:016X}, "
|
||||||
"size=0x{:016X}).",
|
"size=0x{:016X}).",
|
||||||
dst_address, size);
|
dst_address, size);
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsValidAddressRange(src_address, size)) {
|
if (!IsValidAddressRange(src_address, size)) {
|
||||||
|
@ -1433,7 +1434,7 @@ static ResultCode UnmapProcessCodeMemory(Core::System& system, Handle process_ha
|
||||||
"Source address range overflows the address space (src_address=0x{:016X}, "
|
"Source address range overflows the address space (src_address=0x{:016X}, "
|
||||||
"size=0x{:016X}).",
|
"size=0x{:016X}).",
|
||||||
src_address, size);
|
src_address, size);
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
|
const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
|
||||||
|
@ -1441,7 +1442,7 @@ static ResultCode UnmapProcessCodeMemory(Core::System& system, Handle process_ha
|
||||||
if (!process) {
|
if (!process) {
|
||||||
LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).",
|
LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).",
|
||||||
process_handle);
|
process_handle);
|
||||||
return ERR_INVALID_HANDLE;
|
return ResultInvalidHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& page_table = process->PageTable();
|
auto& page_table = process->PageTable();
|
||||||
|
@ -1450,7 +1451,7 @@ static ResultCode UnmapProcessCodeMemory(Core::System& system, Handle process_ha
|
||||||
"Source address range is not within the address space (src_address=0x{:016X}, "
|
"Source address range is not within the address space (src_address=0x{:016X}, "
|
||||||
"size=0x{:016X}).",
|
"size=0x{:016X}).",
|
||||||
src_address, size);
|
src_address, size);
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!page_table.IsInsideASLRRegion(dst_address, size)) {
|
if (!page_table.IsInsideASLRRegion(dst_address, size)) {
|
||||||
|
@ -1458,7 +1459,7 @@ static ResultCode UnmapProcessCodeMemory(Core::System& system, Handle process_ha
|
||||||
"Destination address range is not within the ASLR region (dst_address=0x{:016X}, "
|
"Destination address range is not within the ASLR region (dst_address=0x{:016X}, "
|
||||||
"size=0x{:016X}).",
|
"size=0x{:016X}).",
|
||||||
dst_address, size);
|
dst_address, size);
|
||||||
return ERR_INVALID_MEMORY_RANGE;
|
return ResultInvalidMemoryRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
return page_table.UnmapProcessCodeMemory(dst_address, src_address, size);
|
return page_table.UnmapProcessCodeMemory(dst_address, src_address, size);
|
||||||
|
@ -1526,7 +1527,7 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e
|
||||||
system.CoreTiming().GetGlobalTimeNs().count() + 100000000);
|
system.CoreTiming().GetGlobalTimeNs().count() + 100000000);
|
||||||
if (!thread_reservation.Succeeded()) {
|
if (!thread_reservation.Succeeded()) {
|
||||||
LOG_ERROR(Kernel_SVC, "Could not reserve a new thread");
|
LOG_ERROR(Kernel_SVC, "Could not reserve a new thread");
|
||||||
return ERR_RESOURCE_LIMIT_EXCEEDED;
|
return ResultResourceLimitedExceeded;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<KThread> thread;
|
std::shared_ptr<KThread> thread;
|
||||||
|
@ -1856,7 +1857,7 @@ static ResultCode ResetSignal(Core::System& system, Handle handle) {
|
||||||
|
|
||||||
LOG_ERROR(Kernel_SVC, "invalid handle (0x{:08X})", handle);
|
LOG_ERROR(Kernel_SVC, "invalid handle (0x{:08X})", handle);
|
||||||
|
|
||||||
return Svc::ResultInvalidHandle;
|
return ResultInvalidHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ResultCode ResetSignal32(Core::System& system, Handle handle) {
|
static ResultCode ResetSignal32(Core::System& system, Handle handle) {
|
||||||
|
@ -1872,18 +1873,18 @@ static ResultCode CreateTransferMemory(Core::System& system, Handle* handle, VAd
|
||||||
|
|
||||||
if (!Common::Is4KBAligned(addr)) {
|
if (!Common::Is4KBAligned(addr)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Address ({:016X}) is not page aligned!", addr);
|
LOG_ERROR(Kernel_SVC, "Address ({:016X}) is not page aligned!", addr);
|
||||||
return ERR_INVALID_ADDRESS;
|
return ResultInvalidAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Common::Is4KBAligned(size) || size == 0) {
|
if (!Common::Is4KBAligned(size) || size == 0) {
|
||||||
LOG_ERROR(Kernel_SVC, "Size ({:016X}) is not page aligned or equal to zero!", size);
|
LOG_ERROR(Kernel_SVC, "Size ({:016X}) is not page aligned or equal to zero!", size);
|
||||||
return ERR_INVALID_ADDRESS;
|
return ResultInvalidAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsValidAddressRange(addr, size)) {
|
if (!IsValidAddressRange(addr, size)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Address and size cause overflow! (address={:016X}, size={:016X})",
|
LOG_ERROR(Kernel_SVC, "Address and size cause overflow! (address={:016X}, size={:016X})",
|
||||||
addr, size);
|
addr, size);
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto perms{static_cast<Memory::MemoryPermission>(permissions)};
|
const auto perms{static_cast<Memory::MemoryPermission>(permissions)};
|
||||||
|
@ -1891,7 +1892,7 @@ static ResultCode CreateTransferMemory(Core::System& system, Handle* handle, VAd
|
||||||
perms == Memory::MemoryPermission::Write) {
|
perms == Memory::MemoryPermission::Write) {
|
||||||
LOG_ERROR(Kernel_SVC, "Invalid memory permissions for transfer memory! (perms={:08X})",
|
LOG_ERROR(Kernel_SVC, "Invalid memory permissions for transfer memory! (perms={:08X})",
|
||||||
permissions);
|
permissions);
|
||||||
return ERR_INVALID_MEMORY_PERMISSIONS;
|
return ResultInvalidMemoryPermissions;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& kernel = system.Kernel();
|
auto& kernel = system.Kernel();
|
||||||
|
@ -1900,7 +1901,7 @@ static ResultCode CreateTransferMemory(Core::System& system, Handle* handle, VAd
|
||||||
LimitableResource::TransferMemory);
|
LimitableResource::TransferMemory);
|
||||||
if (!trmem_reservation.Succeeded()) {
|
if (!trmem_reservation.Succeeded()) {
|
||||||
LOG_ERROR(Kernel_SVC, "Could not reserve a new transfer memory");
|
LOG_ERROR(Kernel_SVC, "Could not reserve a new transfer memory");
|
||||||
return ERR_RESOURCE_LIMIT_EXCEEDED;
|
return ResultResourceLimitedExceeded;
|
||||||
}
|
}
|
||||||
auto transfer_mem_handle = TransferMemory::Create(kernel, system.Memory(), addr, size, perms);
|
auto transfer_mem_handle = TransferMemory::Create(kernel, system.Memory(), addr, size, perms);
|
||||||
|
|
||||||
|
@ -2009,7 +2010,6 @@ static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle,
|
||||||
LOG_ERROR(Kernel_SVC, "Unable to successfully set core mask (result={})", set_result.raw);
|
LOG_ERROR(Kernel_SVC, "Unable to successfully set core mask (result={})", set_result.raw);
|
||||||
return set_result;
|
return set_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2031,7 +2031,7 @@ static ResultCode SignalEvent(Core::System& system, Handle event_handle) {
|
||||||
LimitableResource::Events);
|
LimitableResource::Events);
|
||||||
if (!event_reservation.Succeeded()) {
|
if (!event_reservation.Succeeded()) {
|
||||||
LOG_ERROR(Kernel, "Could not reserve a new event");
|
LOG_ERROR(Kernel, "Could not reserve a new event");
|
||||||
return ERR_RESOURCE_LIMIT_EXCEEDED;
|
return ResultResourceLimitedExceeded;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the writable event.
|
// Get the writable event.
|
||||||
|
@ -2075,7 +2075,7 @@ static ResultCode ClearEvent(Core::System& system, Handle event_handle) {
|
||||||
|
|
||||||
LOG_ERROR(Kernel_SVC, "Event handle does not exist, event_handle=0x{:08X}", event_handle);
|
LOG_ERROR(Kernel_SVC, "Event handle does not exist, event_handle=0x{:08X}", event_handle);
|
||||||
|
|
||||||
return Svc::ResultInvalidHandle;
|
return ResultInvalidHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ResultCode ClearEvent32(Core::System& system, Handle event_handle) {
|
static ResultCode ClearEvent32(Core::System& system, Handle event_handle) {
|
||||||
|
@ -2138,13 +2138,13 @@ static ResultCode GetProcessInfo(Core::System& system, u64* out, Handle process_
|
||||||
if (!process) {
|
if (!process) {
|
||||||
LOG_ERROR(Kernel_SVC, "Process handle does not exist, process_handle=0x{:08X}",
|
LOG_ERROR(Kernel_SVC, "Process handle does not exist, process_handle=0x{:08X}",
|
||||||
process_handle);
|
process_handle);
|
||||||
return ERR_INVALID_HANDLE;
|
return ResultInvalidHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto info_type = static_cast<InfoType>(type);
|
const auto info_type = static_cast<InfoType>(type);
|
||||||
if (info_type != InfoType::Status) {
|
if (info_type != InfoType::Status) {
|
||||||
LOG_ERROR(Kernel_SVC, "Expected info_type to be Status but got {} instead", type);
|
LOG_ERROR(Kernel_SVC, "Expected info_type to be Status but got {} instead", type);
|
||||||
return ERR_INVALID_ENUM_VALUE;
|
return ResultInvalidEnumValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
*out = static_cast<u64>(process->GetStatus());
|
*out = static_cast<u64>(process->GetStatus());
|
||||||
|
@ -2206,7 +2206,7 @@ static ResultCode SetResourceLimitLimitValue(Core::System& system, Handle resour
|
||||||
const auto type = static_cast<LimitableResource>(resource_type);
|
const auto type = static_cast<LimitableResource>(resource_type);
|
||||||
if (!IsValidResourceType(type)) {
|
if (!IsValidResourceType(type)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Invalid resource limit type: '{}'", resource_type);
|
LOG_ERROR(Kernel_SVC, "Invalid resource limit type: '{}'", resource_type);
|
||||||
return ERR_INVALID_ENUM_VALUE;
|
return ResultInvalidEnumValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* const current_process = system.Kernel().CurrentProcess();
|
auto* const current_process = system.Kernel().CurrentProcess();
|
||||||
|
@ -2217,14 +2217,14 @@ static ResultCode SetResourceLimitLimitValue(Core::System& system, Handle resour
|
||||||
if (!resource_limit_object) {
|
if (!resource_limit_object) {
|
||||||
LOG_ERROR(Kernel_SVC, "Handle to non-existent resource limit instance used. Handle={:08X}",
|
LOG_ERROR(Kernel_SVC, "Handle to non-existent resource limit instance used. Handle={:08X}",
|
||||||
resource_limit);
|
resource_limit);
|
||||||
return ERR_INVALID_HANDLE;
|
return ResultInvalidHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto set_result = resource_limit_object->SetLimitValue(type, static_cast<s64>(value));
|
const auto set_result = resource_limit_object->SetLimitValue(type, static_cast<s64>(value));
|
||||||
if (set_result.IsError()) {
|
if (set_result.IsError()) {
|
||||||
LOG_ERROR(
|
LOG_ERROR(Kernel_SVC,
|
||||||
Kernel_SVC,
|
"Attempted to lower resource limit ({}) for category '{}' below its current "
|
||||||
"Attempted to lower resource limit ({}) for category '{}' below its current value ({})",
|
"value ({})",
|
||||||
resource_limit_object->GetLimitValue(type), resource_type,
|
resource_limit_object->GetLimitValue(type), resource_type,
|
||||||
resource_limit_object->GetCurrentValue(type));
|
resource_limit_object->GetCurrentValue(type));
|
||||||
return set_result;
|
return set_result;
|
||||||
|
@ -2243,7 +2243,7 @@ static ResultCode GetProcessList(Core::System& system, u32* out_num_processes,
|
||||||
LOG_ERROR(Kernel_SVC,
|
LOG_ERROR(Kernel_SVC,
|
||||||
"Supplied size outside [0, 0x0FFFFFFF] range. out_process_ids_size={}",
|
"Supplied size outside [0, 0x0FFFFFFF] range. out_process_ids_size={}",
|
||||||
out_process_ids_size);
|
out_process_ids_size);
|
||||||
return ERR_OUT_OF_RANGE;
|
return ResultOutOfRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& kernel = system.Kernel();
|
const auto& kernel = system.Kernel();
|
||||||
|
@ -2253,7 +2253,7 @@ static ResultCode GetProcessList(Core::System& system, u32* out_num_processes,
|
||||||
out_process_ids, total_copy_size)) {
|
out_process_ids, total_copy_size)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Address range outside address space. begin=0x{:016X}, end=0x{:016X}",
|
LOG_ERROR(Kernel_SVC, "Address range outside address space. begin=0x{:016X}, end=0x{:016X}",
|
||||||
out_process_ids, out_process_ids + total_copy_size);
|
out_process_ids, out_process_ids + total_copy_size);
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& memory = system.Memory();
|
auto& memory = system.Memory();
|
||||||
|
@ -2282,7 +2282,7 @@ static ResultCode GetThreadList(Core::System& system, u32* out_num_threads, VAdd
|
||||||
if ((out_thread_ids_size & 0xF0000000) != 0) {
|
if ((out_thread_ids_size & 0xF0000000) != 0) {
|
||||||
LOG_ERROR(Kernel_SVC, "Supplied size outside [0, 0x0FFFFFFF] range. size={}",
|
LOG_ERROR(Kernel_SVC, "Supplied size outside [0, 0x0FFFFFFF] range. size={}",
|
||||||
out_thread_ids_size);
|
out_thread_ids_size);
|
||||||
return ERR_OUT_OF_RANGE;
|
return ResultOutOfRange;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto* const current_process = system.Kernel().CurrentProcess();
|
const auto* const current_process = system.Kernel().CurrentProcess();
|
||||||
|
@ -2292,7 +2292,7 @@ static ResultCode GetThreadList(Core::System& system, u32* out_num_threads, VAdd
|
||||||
!current_process->PageTable().IsInsideAddressSpace(out_thread_ids, total_copy_size)) {
|
!current_process->PageTable().IsInsideAddressSpace(out_thread_ids, total_copy_size)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Address range outside address space. begin=0x{:016X}, end=0x{:016X}",
|
LOG_ERROR(Kernel_SVC, "Address range outside address space. begin=0x{:016X}, end=0x{:016X}",
|
||||||
out_thread_ids, out_thread_ids + total_copy_size);
|
out_thread_ids, out_thread_ids + total_copy_size);
|
||||||
return ERR_INVALID_ADDRESS_STATE;
|
return ResultInvalidCurrentMemory;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& memory = system.Memory();
|
auto& memory = system.Memory();
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Copyright 2020 yuzu emulator team
|
// Copyright 2018 yuzu emulator team
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
@ -6,21 +6,36 @@
|
||||||
|
|
||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
|
|
||||||
namespace Kernel::Svc {
|
namespace Kernel {
|
||||||
|
|
||||||
|
// Confirmed Switch kernel error codes
|
||||||
|
|
||||||
|
constexpr ResultCode ResultMaxConnectionsReached{ErrorModule::Kernel, 7};
|
||||||
|
constexpr ResultCode ResultInvalidCapabilityDescriptor{ErrorModule::Kernel, 14};
|
||||||
constexpr ResultCode ResultNoSynchronizationObject{ErrorModule::Kernel, 57};
|
constexpr ResultCode ResultNoSynchronizationObject{ErrorModule::Kernel, 57};
|
||||||
constexpr ResultCode ResultTerminationRequested{ErrorModule::Kernel, 59};
|
constexpr ResultCode ResultTerminationRequested{ErrorModule::Kernel, 59};
|
||||||
|
constexpr ResultCode ResultInvalidSize{ErrorModule::Kernel, 101};
|
||||||
constexpr ResultCode ResultInvalidAddress{ErrorModule::Kernel, 102};
|
constexpr ResultCode ResultInvalidAddress{ErrorModule::Kernel, 102};
|
||||||
constexpr ResultCode ResultOutOfResource{ErrorModule::Kernel, 103};
|
constexpr ResultCode ResultOutOfResource{ErrorModule::Kernel, 103};
|
||||||
|
constexpr ResultCode ResultOutOfMemory{ErrorModule::Kernel, 104};
|
||||||
|
constexpr ResultCode ResultHandleTableFull{ErrorModule::Kernel, 105};
|
||||||
constexpr ResultCode ResultInvalidCurrentMemory{ErrorModule::Kernel, 106};
|
constexpr ResultCode ResultInvalidCurrentMemory{ErrorModule::Kernel, 106};
|
||||||
|
constexpr ResultCode ResultInvalidMemoryPermissions{ErrorModule::Kernel, 108};
|
||||||
|
constexpr ResultCode ResultInvalidMemoryRange{ErrorModule::Kernel, 110};
|
||||||
constexpr ResultCode ResultInvalidPriority{ErrorModule::Kernel, 112};
|
constexpr ResultCode ResultInvalidPriority{ErrorModule::Kernel, 112};
|
||||||
constexpr ResultCode ResultInvalidCoreId{ErrorModule::Kernel, 113};
|
constexpr ResultCode ResultInvalidCoreId{ErrorModule::Kernel, 113};
|
||||||
constexpr ResultCode ResultInvalidHandle{ErrorModule::Kernel, 114};
|
constexpr ResultCode ResultInvalidHandle{ErrorModule::Kernel, 114};
|
||||||
|
constexpr ResultCode ResultInvalidPointer{ErrorModule::Kernel, 115};
|
||||||
constexpr ResultCode ResultInvalidCombination{ErrorModule::Kernel, 116};
|
constexpr ResultCode ResultInvalidCombination{ErrorModule::Kernel, 116};
|
||||||
constexpr ResultCode ResultTimedOut{ErrorModule::Kernel, 117};
|
constexpr ResultCode ResultTimedOut{ErrorModule::Kernel, 117};
|
||||||
constexpr ResultCode ResultCancelled{ErrorModule::Kernel, 118};
|
constexpr ResultCode ResultCancelled{ErrorModule::Kernel, 118};
|
||||||
|
constexpr ResultCode ResultOutOfRange{ErrorModule::Kernel, 119};
|
||||||
constexpr ResultCode ResultInvalidEnumValue{ErrorModule::Kernel, 120};
|
constexpr ResultCode ResultInvalidEnumValue{ErrorModule::Kernel, 120};
|
||||||
|
constexpr ResultCode ResultNotFound{ErrorModule::Kernel, 121};
|
||||||
constexpr ResultCode ResultBusy{ErrorModule::Kernel, 122};
|
constexpr ResultCode ResultBusy{ErrorModule::Kernel, 122};
|
||||||
|
constexpr ResultCode ResultSessionClosedByRemote{ErrorModule::Kernel, 123};
|
||||||
constexpr ResultCode ResultInvalidState{ErrorModule::Kernel, 125};
|
constexpr ResultCode ResultInvalidState{ErrorModule::Kernel, 125};
|
||||||
|
constexpr ResultCode ResultReservedValue{ErrorModule::Kernel, 126};
|
||||||
|
constexpr ResultCode ResultResourceLimitedExceeded{ErrorModule::Kernel, 132};
|
||||||
|
|
||||||
} // namespace Kernel::Svc
|
} // namespace Kernel
|
||||||
|
|
|
@ -11,10 +11,10 @@
|
||||||
#include "common/scope_exit.h"
|
#include "common/scope_exit.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/hle/ipc_helpers.h"
|
#include "core/hle/ipc_helpers.h"
|
||||||
#include "core/hle/kernel/errors.h"
|
|
||||||
#include "core/hle/kernel/memory/page_table.h"
|
#include "core/hle/kernel/memory/page_table.h"
|
||||||
#include "core/hle/kernel/memory/system_control.h"
|
#include "core/hle/kernel/memory/system_control.h"
|
||||||
#include "core/hle/kernel/process.h"
|
#include "core/hle/kernel/process.h"
|
||||||
|
#include "core/hle/kernel/svc_results.h"
|
||||||
#include "core/hle/service/ldr/ldr.h"
|
#include "core/hle/service/ldr/ldr.h"
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/service.h"
|
||||||
#include "core/loader/nro.h"
|
#include "core/loader/nro.h"
|
||||||
|
@ -330,7 +330,7 @@ public:
|
||||||
const VAddr addr{GetRandomMapRegion(page_table, size)};
|
const VAddr addr{GetRandomMapRegion(page_table, size)};
|
||||||
const ResultCode result{page_table.MapProcessCodeMemory(addr, baseAddress, size)};
|
const ResultCode result{page_table.MapProcessCodeMemory(addr, baseAddress, size)};
|
||||||
|
|
||||||
if (result == Kernel::ERR_INVALID_ADDRESS_STATE) {
|
if (result == Kernel::ResultInvalidCurrentMemory) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -361,7 +361,7 @@ public:
|
||||||
const ResultCode result{
|
const ResultCode result{
|
||||||
page_table.MapProcessCodeMemory(addr + nro_size, bss_addr, bss_size)};
|
page_table.MapProcessCodeMemory(addr + nro_size, bss_addr, bss_size)};
|
||||||
|
|
||||||
if (result == Kernel::ERR_INVALID_ADDRESS_STATE) {
|
if (result == Kernel::ResultInvalidCurrentMemory) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,9 +43,8 @@ constexpr std::array VIEW_CLASS_32_BITS{
|
||||||
PixelFormat::A2B10G10R10_UNORM, PixelFormat::R16G16_UINT, PixelFormat::R32_UINT,
|
PixelFormat::A2B10G10R10_UNORM, PixelFormat::R16G16_UINT, PixelFormat::R32_UINT,
|
||||||
PixelFormat::R16G16_SINT, PixelFormat::R32_SINT, PixelFormat::A8B8G8R8_UNORM,
|
PixelFormat::R16G16_SINT, PixelFormat::R32_SINT, PixelFormat::A8B8G8R8_UNORM,
|
||||||
PixelFormat::R16G16_UNORM, PixelFormat::A8B8G8R8_SNORM, PixelFormat::R16G16_SNORM,
|
PixelFormat::R16G16_UNORM, PixelFormat::A8B8G8R8_SNORM, PixelFormat::R16G16_SNORM,
|
||||||
PixelFormat::A8B8G8R8_SRGB, PixelFormat::E5B9G9R9_FLOAT, PixelFormat::B8G8R8A8_UNORM,
|
PixelFormat::A8B8G8R8_SRGB, PixelFormat::E5B9G9R9_FLOAT, PixelFormat::A8B8G8R8_UINT,
|
||||||
PixelFormat::B8G8R8A8_SRGB, PixelFormat::A8B8G8R8_UINT, PixelFormat::A8B8G8R8_SINT,
|
PixelFormat::A8B8G8R8_SINT, PixelFormat::A2B10G10R10_UINT,
|
||||||
PixelFormat::A2B10G10R10_UINT,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: How should we handle 24 bits?
|
// TODO: How should we handle 24 bits?
|
||||||
|
|
|
@ -5,6 +5,8 @@ set(SHADER_FILES
|
||||||
convert_float_to_depth.frag
|
convert_float_to_depth.frag
|
||||||
full_screen_triangle.vert
|
full_screen_triangle.vert
|
||||||
opengl_copy_bc4.comp
|
opengl_copy_bc4.comp
|
||||||
|
opengl_copy_bgr16.comp
|
||||||
|
opengl_copy_bgra.comp
|
||||||
opengl_present.frag
|
opengl_present.frag
|
||||||
opengl_present.vert
|
opengl_present.vert
|
||||||
pitch_unswizzle.comp
|
pitch_unswizzle.comp
|
||||||
|
|
14
src/video_core/host_shaders/opengl_copy_bgr16.comp
Executable file
14
src/video_core/host_shaders/opengl_copy_bgr16.comp
Executable file
|
@ -0,0 +1,14 @@
|
||||||
|
// Copyright 2021 yuzu Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#version 430 core
|
||||||
|
|
||||||
|
layout (local_size_x = 4, local_size_y = 4) in;
|
||||||
|
|
||||||
|
layout(binding = 0, r16ui) readonly uniform uimage2D bgr_input;
|
||||||
|
layout(binding = 1, r16ui) writeonly uniform uimage2D bgr_output;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
imageStore(bgr_output, ivec2(gl_GlobalInvocationID.xy), imageLoad(bgr_input, ivec2(gl_GlobalInvocationID.xy)));
|
||||||
|
}
|
15
src/video_core/host_shaders/opengl_copy_bgra.comp
Executable file
15
src/video_core/host_shaders/opengl_copy_bgra.comp
Executable file
|
@ -0,0 +1,15 @@
|
||||||
|
// Copyright 2021 yuzu Emulator Project
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#version 430 core
|
||||||
|
|
||||||
|
layout (local_size_x = 4, local_size_y = 4) in;
|
||||||
|
|
||||||
|
layout(binding = 0, rgba8) readonly uniform image2D bgr_input;
|
||||||
|
layout(binding = 1, rgba8) writeonly uniform image2D bgr_output;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec4 color = imageLoad(bgr_input, ivec2(gl_GlobalInvocationID.xy));
|
||||||
|
imageStore(bgr_output, ivec2(gl_GlobalInvocationID.xy), color.bgra);
|
||||||
|
}
|
|
@ -162,10 +162,11 @@ private:
|
||||||
VideoCore::RasterizerInterface* rasterizer = nullptr;
|
VideoCore::RasterizerInterface* rasterizer = nullptr;
|
||||||
|
|
||||||
std::vector<PageEntry> page_table;
|
std::vector<PageEntry> page_table;
|
||||||
std::vector<std::pair<VAddr, std::size_t>> cache_invalidate_queue;
|
|
||||||
|
|
||||||
using MapRange = std::pair<GPUVAddr, size_t>;
|
using MapRange = std::pair<GPUVAddr, size_t>;
|
||||||
std::vector<MapRange> map_ranges;
|
std::vector<MapRange> map_ranges;
|
||||||
|
|
||||||
|
std::vector<std::pair<VAddr, std::size_t>> cache_invalidate_queue;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Tegra
|
} // namespace Tegra
|
||||||
|
|
|
@ -198,8 +198,8 @@ bool IsASTCSupported() {
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
Device::Device() {
|
Device::Device() {
|
||||||
if (!GLAD_GL_VERSION_4_3) {
|
if (!GLAD_GL_VERSION_4_6) {
|
||||||
LOG_ERROR(Render_OpenGL, "OpenGL 4.3 is not available");
|
LOG_ERROR(Render_OpenGL, "OpenGL 4.6 is not available");
|
||||||
throw std::runtime_error{"Insufficient version"};
|
throw std::runtime_error{"Insufficient version"};
|
||||||
}
|
}
|
||||||
const std::string_view vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
|
const std::string_view vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
namespace OpenGL {
|
namespace OpenGL {
|
||||||
|
|
||||||
using Maxwell = Tegra::Engines::Maxwell3D::Regs;
|
using Maxwell = Tegra::Engines::Maxwell3D::Regs;
|
||||||
|
using GLvec4 = std::array<GLfloat, 4>;
|
||||||
|
|
||||||
using Tegra::Engines::ShaderType;
|
using Tegra::Engines::ShaderType;
|
||||||
using VideoCore::Surface::PixelFormat;
|
using VideoCore::Surface::PixelFormat;
|
||||||
|
@ -51,14 +52,7 @@ MICROPROFILE_DEFINE(OpenGL_CacheManagement, "OpenGL", "Cache Management", MP_RGB
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
constexpr size_t NUM_CONST_BUFFERS_PER_STAGE = 18;
|
|
||||||
constexpr size_t NUM_CONST_BUFFERS_BYTES_PER_STAGE =
|
|
||||||
NUM_CONST_BUFFERS_PER_STAGE * Maxwell::MaxConstBufferSize;
|
|
||||||
constexpr size_t TOTAL_CONST_BUFFER_BYTES =
|
|
||||||
NUM_CONST_BUFFERS_BYTES_PER_STAGE * Maxwell::MaxShaderStage;
|
|
||||||
|
|
||||||
constexpr size_t NUM_SUPPORTED_VERTEX_ATTRIBUTES = 16;
|
constexpr size_t NUM_SUPPORTED_VERTEX_ATTRIBUTES = 16;
|
||||||
constexpr size_t NUM_SUPPORTED_VERTEX_BINDINGS = 16;
|
|
||||||
|
|
||||||
struct TextureHandle {
|
struct TextureHandle {
|
||||||
constexpr TextureHandle(u32 data, bool via_header_index) {
|
constexpr TextureHandle(u32 data, bool via_header_index) {
|
||||||
|
|
|
@ -398,7 +398,9 @@ void AttachTexture(GLuint fbo, GLenum attachment, const ImageView* image_view) {
|
||||||
|
|
||||||
[[nodiscard]] bool IsPixelFormatBGR(PixelFormat format) {
|
[[nodiscard]] bool IsPixelFormatBGR(PixelFormat format) {
|
||||||
switch (format) {
|
switch (format) {
|
||||||
case PixelFormat::B5G6R5_UNORM:
|
// TODO: B5G6R5 is currently not rendering after the compute copy.
|
||||||
|
// uncomment when this is resolved.
|
||||||
|
// case PixelFormat::B5G6R5_UNORM:
|
||||||
case PixelFormat::B8G8R8A8_UNORM:
|
case PixelFormat::B8G8R8A8_UNORM:
|
||||||
case PixelFormat::B8G8R8A8_SRGB:
|
case PixelFormat::B8G8R8A8_SRGB:
|
||||||
return true;
|
return true;
|
||||||
|
@ -407,6 +409,16 @@ void AttachTexture(GLuint fbo, GLenum attachment, const ImageView* image_view) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[[nodiscard]] GLenum GetStorageInternalFormat(PixelFormat format) {
|
||||||
|
switch (format) {
|
||||||
|
case PixelFormat::R5G6B5_UNORM:
|
||||||
|
case PixelFormat::B5G6R5_UNORM:
|
||||||
|
return GL_RGB565;
|
||||||
|
default:
|
||||||
|
return GL_RGBA8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
ImageBufferMap::~ImageBufferMap() {
|
ImageBufferMap::~ImageBufferMap() {
|
||||||
|
@ -523,6 +535,9 @@ bool TextureCacheRuntime::CanImageBeCopied(const Image& dst, const Image& src) {
|
||||||
if (dst.info.type == ImageType::e3D && dst.info.format == PixelFormat::BC4_UNORM) {
|
if (dst.info.type == ImageType::e3D && dst.info.format == PixelFormat::BC4_UNORM) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (IsPixelFormatBGR(dst.info.format) || IsPixelFormatBGR(src.info.format)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -531,6 +546,8 @@ void TextureCacheRuntime::EmulateCopyImage(Image& dst, Image& src,
|
||||||
if (dst.info.type == ImageType::e3D && dst.info.format == PixelFormat::BC4_UNORM) {
|
if (dst.info.type == ImageType::e3D && dst.info.format == PixelFormat::BC4_UNORM) {
|
||||||
ASSERT(src.info.type == ImageType::e3D);
|
ASSERT(src.info.type == ImageType::e3D);
|
||||||
util_shaders.CopyBC4(dst, src, copies);
|
util_shaders.CopyBC4(dst, src, copies);
|
||||||
|
} else if (IsPixelFormatBGR(dst.info.format) || IsPixelFormatBGR(src.info.format)) {
|
||||||
|
util_shaders.CopyBGR(dst, src, copies);
|
||||||
} else {
|
} else {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
@ -774,6 +791,39 @@ void Image::DownloadMemory(ImageBufferMap& map,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLuint Image::StorageHandle() noexcept {
|
||||||
|
switch (info.format) {
|
||||||
|
case PixelFormat::A8B8G8R8_SRGB:
|
||||||
|
case PixelFormat::B8G8R8A8_SRGB:
|
||||||
|
case PixelFormat::R5G6B5_UNORM:
|
||||||
|
case PixelFormat::B5G6R5_UNORM:
|
||||||
|
case PixelFormat::BC1_RGBA_SRGB:
|
||||||
|
case PixelFormat::BC2_SRGB:
|
||||||
|
case PixelFormat::BC3_SRGB:
|
||||||
|
case PixelFormat::BC7_SRGB:
|
||||||
|
case PixelFormat::ASTC_2D_4X4_SRGB:
|
||||||
|
case PixelFormat::ASTC_2D_8X8_SRGB:
|
||||||
|
case PixelFormat::ASTC_2D_8X5_SRGB:
|
||||||
|
case PixelFormat::ASTC_2D_5X4_SRGB:
|
||||||
|
case PixelFormat::ASTC_2D_5X5_SRGB:
|
||||||
|
case PixelFormat::ASTC_2D_10X8_SRGB:
|
||||||
|
case PixelFormat::ASTC_2D_6X6_SRGB:
|
||||||
|
case PixelFormat::ASTC_2D_10X10_SRGB:
|
||||||
|
case PixelFormat::ASTC_2D_12X12_SRGB:
|
||||||
|
case PixelFormat::ASTC_2D_8X6_SRGB:
|
||||||
|
case PixelFormat::ASTC_2D_6X5_SRGB:
|
||||||
|
if (store_view.handle != 0) {
|
||||||
|
return store_view.handle;
|
||||||
|
}
|
||||||
|
store_view.Create();
|
||||||
|
glTextureView(store_view.handle, ImageTarget(info), texture.handle,
|
||||||
|
GetStorageInternalFormat(info.format), 0, info.resources.levels, 0,
|
||||||
|
info.resources.layers);
|
||||||
|
return store_view.handle;
|
||||||
|
default:
|
||||||
|
return texture.handle;
|
||||||
|
}
|
||||||
|
}
|
||||||
void Image::CopyBufferToImage(const VideoCommon::BufferImageCopy& copy, size_t buffer_offset) {
|
void Image::CopyBufferToImage(const VideoCommon::BufferImageCopy& copy, size_t buffer_offset) {
|
||||||
// Compressed formats don't have a pixel format or type
|
// Compressed formats don't have a pixel format or type
|
||||||
const bool is_compressed = gl_format == GL_NONE;
|
const bool is_compressed = gl_format == GL_NONE;
|
||||||
|
@ -955,13 +1005,7 @@ void ImageView::SetupView(const Device& device, Image& image, ImageViewType view
|
||||||
glTextureView(handle, target, parent, internal_format, view_range.base.level,
|
glTextureView(handle, target, parent, internal_format, view_range.base.level,
|
||||||
view_range.extent.levels, view_range.base.layer, view_range.extent.layers);
|
view_range.extent.levels, view_range.base.layer, view_range.extent.layers);
|
||||||
if (!info.IsRenderTarget()) {
|
if (!info.IsRenderTarget()) {
|
||||||
auto swizzle = info.Swizzle();
|
ApplySwizzle(handle, format, info.Swizzle());
|
||||||
if (IsPixelFormatBGR(image.info.format) || IsPixelFormatBGR(info.format)) {
|
|
||||||
// Explicitly swap the R and B channels of the swizzle.
|
|
||||||
swizzle[0] = SwizzleSource::R;
|
|
||||||
swizzle[2] = SwizzleSource::B;
|
|
||||||
}
|
|
||||||
ApplySwizzle(handle, format, swizzle);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (device.HasDebuggingToolAttached()) {
|
if (device.HasDebuggingToolAttached()) {
|
||||||
|
|
|
@ -145,6 +145,8 @@ public:
|
||||||
|
|
||||||
void DownloadMemory(ImageBufferMap& map, std::span<const VideoCommon::BufferImageCopy> copies);
|
void DownloadMemory(ImageBufferMap& map, std::span<const VideoCommon::BufferImageCopy> copies);
|
||||||
|
|
||||||
|
GLuint StorageHandle() noexcept;
|
||||||
|
|
||||||
GLuint Handle() const noexcept {
|
GLuint Handle() const noexcept {
|
||||||
return texture.handle;
|
return texture.handle;
|
||||||
}
|
}
|
||||||
|
@ -155,8 +157,8 @@ private:
|
||||||
void CopyImageToBuffer(const VideoCommon::BufferImageCopy& copy, size_t buffer_offset);
|
void CopyImageToBuffer(const VideoCommon::BufferImageCopy& copy, size_t buffer_offset);
|
||||||
|
|
||||||
OGLTexture texture;
|
OGLTexture texture;
|
||||||
OGLTextureView store_view;
|
|
||||||
OGLBuffer buffer;
|
OGLBuffer buffer;
|
||||||
|
OGLTextureView store_view;
|
||||||
GLenum gl_internal_format = GL_NONE;
|
GLenum gl_internal_format = GL_NONE;
|
||||||
GLenum gl_format = GL_NONE;
|
GLenum gl_format = GL_NONE;
|
||||||
GLenum gl_type = GL_NONE;
|
GLenum gl_type = GL_NONE;
|
||||||
|
|
|
@ -4,23 +4,10 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array>
|
|
||||||
#include <glad/glad.h>
|
#include <glad/glad.h>
|
||||||
#include "common/common_types.h"
|
|
||||||
#include "common/logging/log.h"
|
|
||||||
#include "video_core/engines/maxwell_3d.h"
|
#include "video_core/engines/maxwell_3d.h"
|
||||||
|
|
||||||
namespace OpenGL {
|
namespace OpenGL::MaxwellToGL {
|
||||||
|
|
||||||
using GLvec2 = std::array<GLfloat, 2>;
|
|
||||||
using GLvec3 = std::array<GLfloat, 3>;
|
|
||||||
using GLvec4 = std::array<GLfloat, 4>;
|
|
||||||
|
|
||||||
using GLuvec2 = std::array<GLuint, 2>;
|
|
||||||
using GLuvec3 = std::array<GLuint, 3>;
|
|
||||||
using GLuvec4 = std::array<GLuint, 4>;
|
|
||||||
|
|
||||||
namespace MaxwellToGL {
|
|
||||||
|
|
||||||
using Maxwell = Tegra::Engines::Maxwell3D::Regs;
|
using Maxwell = Tegra::Engines::Maxwell3D::Regs;
|
||||||
|
|
||||||
|
@ -317,26 +304,6 @@ inline GLenum BlendFunc(Maxwell::Blend::Factor factor) {
|
||||||
return GL_ZERO;
|
return GL_ZERO;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline GLenum SwizzleSource(Tegra::Texture::SwizzleSource source) {
|
|
||||||
switch (source) {
|
|
||||||
case Tegra::Texture::SwizzleSource::Zero:
|
|
||||||
return GL_ZERO;
|
|
||||||
case Tegra::Texture::SwizzleSource::R:
|
|
||||||
return GL_RED;
|
|
||||||
case Tegra::Texture::SwizzleSource::G:
|
|
||||||
return GL_GREEN;
|
|
||||||
case Tegra::Texture::SwizzleSource::B:
|
|
||||||
return GL_BLUE;
|
|
||||||
case Tegra::Texture::SwizzleSource::A:
|
|
||||||
return GL_ALPHA;
|
|
||||||
case Tegra::Texture::SwizzleSource::OneInt:
|
|
||||||
case Tegra::Texture::SwizzleSource::OneFloat:
|
|
||||||
return GL_ONE;
|
|
||||||
}
|
|
||||||
UNIMPLEMENTED_MSG("Unimplemented swizzle source={}", source);
|
|
||||||
return GL_ZERO;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline GLenum ComparisonOp(Maxwell::ComparisonOp comparison) {
|
inline GLenum ComparisonOp(Maxwell::ComparisonOp comparison) {
|
||||||
switch (comparison) {
|
switch (comparison) {
|
||||||
case Maxwell::ComparisonOp::Never:
|
case Maxwell::ComparisonOp::Never:
|
||||||
|
@ -493,5 +460,4 @@ inline GLenum ViewportSwizzle(Maxwell::ViewportSwizzle swizzle) {
|
||||||
return GL_VIEWPORT_SWIZZLE_POSITIVE_X_NV + static_cast<GLenum>(swizzle);
|
return GL_VIEWPORT_SWIZZLE_POSITIVE_X_NV + static_cast<GLenum>(swizzle);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace MaxwellToGL
|
} // namespace OpenGL::MaxwellToGL
|
||||||
} // namespace OpenGL
|
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
#include "video_core/host_shaders/block_linear_unswizzle_2d_comp.h"
|
#include "video_core/host_shaders/block_linear_unswizzle_2d_comp.h"
|
||||||
#include "video_core/host_shaders/block_linear_unswizzle_3d_comp.h"
|
#include "video_core/host_shaders/block_linear_unswizzle_3d_comp.h"
|
||||||
#include "video_core/host_shaders/opengl_copy_bc4_comp.h"
|
#include "video_core/host_shaders/opengl_copy_bc4_comp.h"
|
||||||
|
#include "video_core/host_shaders/opengl_copy_bgr16_comp.h"
|
||||||
|
#include "video_core/host_shaders/opengl_copy_bgra_comp.h"
|
||||||
#include "video_core/host_shaders/pitch_unswizzle_comp.h"
|
#include "video_core/host_shaders/pitch_unswizzle_comp.h"
|
||||||
#include "video_core/renderer_opengl/gl_resource_manager.h"
|
#include "video_core/renderer_opengl/gl_resource_manager.h"
|
||||||
#include "video_core/renderer_opengl/gl_shader_manager.h"
|
#include "video_core/renderer_opengl/gl_shader_manager.h"
|
||||||
|
@ -36,6 +38,7 @@ using VideoCommon::SwizzleParameters;
|
||||||
using VideoCommon::Accelerated::MakeBlockLinearSwizzle2DParams;
|
using VideoCommon::Accelerated::MakeBlockLinearSwizzle2DParams;
|
||||||
using VideoCommon::Accelerated::MakeBlockLinearSwizzle3DParams;
|
using VideoCommon::Accelerated::MakeBlockLinearSwizzle3DParams;
|
||||||
using VideoCore::Surface::BytesPerBlock;
|
using VideoCore::Surface::BytesPerBlock;
|
||||||
|
using VideoCore::Surface::PixelFormat;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -55,7 +58,9 @@ UtilShaders::UtilShaders(ProgramManager& program_manager_)
|
||||||
block_linear_unswizzle_2d_program(MakeProgram(BLOCK_LINEAR_UNSWIZZLE_2D_COMP)),
|
block_linear_unswizzle_2d_program(MakeProgram(BLOCK_LINEAR_UNSWIZZLE_2D_COMP)),
|
||||||
block_linear_unswizzle_3d_program(MakeProgram(BLOCK_LINEAR_UNSWIZZLE_3D_COMP)),
|
block_linear_unswizzle_3d_program(MakeProgram(BLOCK_LINEAR_UNSWIZZLE_3D_COMP)),
|
||||||
pitch_unswizzle_program(MakeProgram(PITCH_UNSWIZZLE_COMP)),
|
pitch_unswizzle_program(MakeProgram(PITCH_UNSWIZZLE_COMP)),
|
||||||
copy_bc4_program(MakeProgram(OPENGL_COPY_BC4_COMP)) {
|
copy_bc4_program(MakeProgram(OPENGL_COPY_BC4_COMP)),
|
||||||
|
copy_bgr16_program(MakeProgram(OPENGL_COPY_BGR16_COMP)),
|
||||||
|
copy_bgra_program(MakeProgram(OPENGL_COPY_BGRA_COMP)) {
|
||||||
const auto swizzle_table = Tegra::Texture::MakeSwizzleTable();
|
const auto swizzle_table = Tegra::Texture::MakeSwizzleTable();
|
||||||
swizzle_table_buffer.Create();
|
swizzle_table_buffer.Create();
|
||||||
glNamedBufferStorage(swizzle_table_buffer.handle, sizeof(swizzle_table), &swizzle_table, 0);
|
glNamedBufferStorage(swizzle_table_buffer.handle, sizeof(swizzle_table), &swizzle_table, 0);
|
||||||
|
@ -93,7 +98,7 @@ void UtilShaders::BlockLinearUpload2D(Image& image, const ImageBufferMap& map,
|
||||||
glUniform1ui(7, params.block_height_mask);
|
glUniform1ui(7, params.block_height_mask);
|
||||||
glBindBufferRange(GL_SHADER_STORAGE_BUFFER, BINDING_INPUT_BUFFER, map.buffer, input_offset,
|
glBindBufferRange(GL_SHADER_STORAGE_BUFFER, BINDING_INPUT_BUFFER, map.buffer, input_offset,
|
||||||
image.guest_size_bytes - swizzle.buffer_offset);
|
image.guest_size_bytes - swizzle.buffer_offset);
|
||||||
glBindImageTexture(BINDING_OUTPUT_IMAGE, image.Handle(), swizzle.level, GL_TRUE, 0,
|
glBindImageTexture(BINDING_OUTPUT_IMAGE, image.StorageHandle(), swizzle.level, GL_TRUE, 0,
|
||||||
GL_WRITE_ONLY, store_format);
|
GL_WRITE_ONLY, store_format);
|
||||||
glDispatchCompute(num_dispatches_x, num_dispatches_y, image.info.resources.layers);
|
glDispatchCompute(num_dispatches_x, num_dispatches_y, image.info.resources.layers);
|
||||||
}
|
}
|
||||||
|
@ -134,7 +139,7 @@ void UtilShaders::BlockLinearUpload3D(Image& image, const ImageBufferMap& map,
|
||||||
glUniform1ui(9, params.block_depth_mask);
|
glUniform1ui(9, params.block_depth_mask);
|
||||||
glBindBufferRange(GL_SHADER_STORAGE_BUFFER, BINDING_INPUT_BUFFER, map.buffer, input_offset,
|
glBindBufferRange(GL_SHADER_STORAGE_BUFFER, BINDING_INPUT_BUFFER, map.buffer, input_offset,
|
||||||
image.guest_size_bytes - swizzle.buffer_offset);
|
image.guest_size_bytes - swizzle.buffer_offset);
|
||||||
glBindImageTexture(BINDING_OUTPUT_IMAGE, image.Handle(), swizzle.level, GL_TRUE, 0,
|
glBindImageTexture(BINDING_OUTPUT_IMAGE, image.StorageHandle(), swizzle.level, GL_TRUE, 0,
|
||||||
GL_WRITE_ONLY, store_format);
|
GL_WRITE_ONLY, store_format);
|
||||||
glDispatchCompute(num_dispatches_x, num_dispatches_y, num_dispatches_z);
|
glDispatchCompute(num_dispatches_x, num_dispatches_y, num_dispatches_z);
|
||||||
}
|
}
|
||||||
|
@ -164,7 +169,8 @@ void UtilShaders::PitchUpload(Image& image, const ImageBufferMap& map,
|
||||||
glUniform2i(LOC_DESTINATION, 0, 0);
|
glUniform2i(LOC_DESTINATION, 0, 0);
|
||||||
glUniform1ui(LOC_BYTES_PER_BLOCK, bytes_per_block);
|
glUniform1ui(LOC_BYTES_PER_BLOCK, bytes_per_block);
|
||||||
glUniform1ui(LOC_PITCH, pitch);
|
glUniform1ui(LOC_PITCH, pitch);
|
||||||
glBindImageTexture(BINDING_OUTPUT_IMAGE, image.Handle(), 0, GL_FALSE, 0, GL_WRITE_ONLY, format);
|
glBindImageTexture(BINDING_OUTPUT_IMAGE, image.StorageHandle(), 0, GL_FALSE, 0, GL_WRITE_ONLY,
|
||||||
|
format);
|
||||||
for (const SwizzleParameters& swizzle : swizzles) {
|
for (const SwizzleParameters& swizzle : swizzles) {
|
||||||
const Extent3D num_tiles = swizzle.num_tiles;
|
const Extent3D num_tiles = swizzle.num_tiles;
|
||||||
const size_t input_offset = swizzle.buffer_offset + map.offset;
|
const size_t input_offset = swizzle.buffer_offset + map.offset;
|
||||||
|
@ -195,15 +201,41 @@ void UtilShaders::CopyBC4(Image& dst_image, Image& src_image, std::span<const Im
|
||||||
|
|
||||||
glUniform3ui(LOC_SRC_OFFSET, copy.src_offset.x, copy.src_offset.y, copy.src_offset.z);
|
glUniform3ui(LOC_SRC_OFFSET, copy.src_offset.x, copy.src_offset.y, copy.src_offset.z);
|
||||||
glUniform3ui(LOC_DST_OFFSET, copy.dst_offset.x, copy.dst_offset.y, copy.dst_offset.z);
|
glUniform3ui(LOC_DST_OFFSET, copy.dst_offset.x, copy.dst_offset.y, copy.dst_offset.z);
|
||||||
glBindImageTexture(BINDING_INPUT_IMAGE, src_image.Handle(), copy.src_subresource.base_level,
|
glBindImageTexture(BINDING_INPUT_IMAGE, src_image.StorageHandle(),
|
||||||
GL_FALSE, 0, GL_READ_ONLY, GL_RG32UI);
|
copy.src_subresource.base_level, GL_FALSE, 0, GL_READ_ONLY, GL_RG32UI);
|
||||||
glBindImageTexture(BINDING_OUTPUT_IMAGE, dst_image.Handle(),
|
glBindImageTexture(BINDING_OUTPUT_IMAGE, dst_image.StorageHandle(),
|
||||||
copy.dst_subresource.base_level, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8UI);
|
copy.dst_subresource.base_level, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA8UI);
|
||||||
glDispatchCompute(copy.extent.width, copy.extent.height, copy.extent.depth);
|
glDispatchCompute(copy.extent.width, copy.extent.height, copy.extent.depth);
|
||||||
}
|
}
|
||||||
program_manager.RestoreGuestCompute();
|
program_manager.RestoreGuestCompute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UtilShaders::CopyBGR(Image& dst_image, Image& src_image,
|
||||||
|
std::span<const VideoCommon::ImageCopy> copies) {
|
||||||
|
static constexpr GLuint BINDING_INPUT_IMAGE = 0;
|
||||||
|
static constexpr GLuint BINDING_OUTPUT_IMAGE = 1;
|
||||||
|
|
||||||
|
GLenum format{};
|
||||||
|
const u32 bytes_per_block = BytesPerBlock(dst_image.info.format);
|
||||||
|
if (bytes_per_block == 2) {
|
||||||
|
// BGR565 Copy
|
||||||
|
program_manager.BindHostCompute(copy_bgr16_program.handle);
|
||||||
|
format = GL_R16UI;
|
||||||
|
} else if (bytes_per_block == 4) {
|
||||||
|
// BGRA8 Copy
|
||||||
|
program_manager.BindHostCompute(copy_bgra_program.handle);
|
||||||
|
format = GL_RGBA8;
|
||||||
|
}
|
||||||
|
for (const ImageCopy& copy : copies) {
|
||||||
|
glBindImageTexture(BINDING_INPUT_IMAGE, src_image.StorageHandle(),
|
||||||
|
copy.src_subresource.base_level, GL_FALSE, 0, GL_READ_ONLY, format);
|
||||||
|
glBindImageTexture(BINDING_OUTPUT_IMAGE, dst_image.StorageHandle(),
|
||||||
|
copy.dst_subresource.base_level, GL_FALSE, 0, GL_WRITE_ONLY, format);
|
||||||
|
glDispatchCompute(copy.extent.width, copy.extent.height, copy.extent.depth);
|
||||||
|
}
|
||||||
|
program_manager.RestoreGuestCompute();
|
||||||
|
}
|
||||||
|
|
||||||
GLenum StoreFormat(u32 bytes_per_block) {
|
GLenum StoreFormat(u32 bytes_per_block) {
|
||||||
switch (bytes_per_block) {
|
switch (bytes_per_block) {
|
||||||
case 1:
|
case 1:
|
||||||
|
|
|
@ -36,6 +36,9 @@ public:
|
||||||
void CopyBC4(Image& dst_image, Image& src_image,
|
void CopyBC4(Image& dst_image, Image& src_image,
|
||||||
std::span<const VideoCommon::ImageCopy> copies);
|
std::span<const VideoCommon::ImageCopy> copies);
|
||||||
|
|
||||||
|
void CopyBGR(Image& dst_image, Image& src_image,
|
||||||
|
std::span<const VideoCommon::ImageCopy> copies);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ProgramManager& program_manager;
|
ProgramManager& program_manager;
|
||||||
|
|
||||||
|
@ -45,6 +48,8 @@ private:
|
||||||
OGLProgram block_linear_unswizzle_3d_program;
|
OGLProgram block_linear_unswizzle_3d_program;
|
||||||
OGLProgram pitch_unswizzle_program;
|
OGLProgram pitch_unswizzle_program;
|
||||||
OGLProgram copy_bc4_program;
|
OGLProgram copy_bc4_program;
|
||||||
|
OGLProgram copy_bgr16_program;
|
||||||
|
OGLProgram copy_bgra_program;
|
||||||
};
|
};
|
||||||
|
|
||||||
GLenum StoreFormat(u32 bytes_per_block);
|
GLenum StoreFormat(u32 bytes_per_block);
|
||||||
|
|
|
@ -3161,7 +3161,11 @@ ShaderEntries GenerateShaderEntries(const VideoCommon::Shader::ShaderIR& ir) {
|
||||||
entries.const_buffers.emplace_back(cbuf.second, cbuf.first);
|
entries.const_buffers.emplace_back(cbuf.second, cbuf.first);
|
||||||
}
|
}
|
||||||
for (const auto& [base, usage] : ir.GetGlobalMemory()) {
|
for (const auto& [base, usage] : ir.GetGlobalMemory()) {
|
||||||
entries.global_buffers.emplace_back(base.cbuf_index, base.cbuf_offset, usage.is_written);
|
entries.global_buffers.emplace_back(GlobalBufferEntry{
|
||||||
|
.cbuf_index = base.cbuf_index,
|
||||||
|
.cbuf_offset = base.cbuf_offset,
|
||||||
|
.is_written = usage.is_written,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
for (const auto& sampler : ir.GetSamplers()) {
|
for (const auto& sampler : ir.GetSamplers()) {
|
||||||
if (sampler.is_buffer) {
|
if (sampler.is_buffer) {
|
||||||
|
|
|
@ -46,6 +46,7 @@ constexpr std::array REQUIRED_EXTENSIONS{
|
||||||
VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME,
|
VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME,
|
||||||
VK_EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME,
|
VK_EXT_SHADER_SUBGROUP_BALLOT_EXTENSION_NAME,
|
||||||
VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME,
|
VK_EXT_SHADER_SUBGROUP_VOTE_EXTENSION_NAME,
|
||||||
|
VK_EXT_ROBUSTNESS_2_EXTENSION_NAME,
|
||||||
VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME,
|
VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME,
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME,
|
VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME,
|
||||||
|
@ -379,20 +380,6 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
|
||||||
LOG_INFO(Render_Vulkan, "Device doesn't support extended dynamic state");
|
LOG_INFO(Render_Vulkan, "Device doesn't support extended dynamic state");
|
||||||
}
|
}
|
||||||
|
|
||||||
VkPhysicalDeviceRobustness2FeaturesEXT robustness2;
|
|
||||||
if (ext_robustness2) {
|
|
||||||
robustness2 = {
|
|
||||||
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT,
|
|
||||||
.pNext = nullptr,
|
|
||||||
.robustBufferAccess2 = true,
|
|
||||||
.robustImageAccess2 = true,
|
|
||||||
.nullDescriptor = true,
|
|
||||||
};
|
|
||||||
SetNext(next, robustness2);
|
|
||||||
} else {
|
|
||||||
LOG_INFO(Render_Vulkan, "Device doesn't support robustness2");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ext_depth_range_unrestricted) {
|
if (!ext_depth_range_unrestricted) {
|
||||||
LOG_INFO(Render_Vulkan, "Device doesn't support depth range unrestricted");
|
LOG_INFO(Render_Vulkan, "Device doesn't support depth range unrestricted");
|
||||||
}
|
}
|
||||||
|
@ -579,7 +566,16 @@ void Device::CheckSuitability(bool requires_swapchain) const {
|
||||||
throw vk::Exception(VK_ERROR_FEATURE_NOT_PRESENT);
|
throw vk::Exception(VK_ERROR_FEATURE_NOT_PRESENT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const VkPhysicalDeviceFeatures features{physical.GetFeatures()};
|
VkPhysicalDeviceRobustness2FeaturesEXT robustness2{};
|
||||||
|
robustness2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT;
|
||||||
|
|
||||||
|
VkPhysicalDeviceFeatures2 features2{};
|
||||||
|
features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
|
||||||
|
features2.pNext = &robustness2;
|
||||||
|
|
||||||
|
physical.GetFeatures2KHR(features2);
|
||||||
|
|
||||||
|
const VkPhysicalDeviceFeatures& features{features2.features};
|
||||||
const std::array feature_report{
|
const std::array feature_report{
|
||||||
std::make_pair(features.robustBufferAccess, "robustBufferAccess"),
|
std::make_pair(features.robustBufferAccess, "robustBufferAccess"),
|
||||||
std::make_pair(features.vertexPipelineStoresAndAtomics, "vertexPipelineStoresAndAtomics"),
|
std::make_pair(features.vertexPipelineStoresAndAtomics, "vertexPipelineStoresAndAtomics"),
|
||||||
|
@ -598,6 +594,9 @@ void Device::CheckSuitability(bool requires_swapchain) const {
|
||||||
std::make_pair(features.shaderImageGatherExtended, "shaderImageGatherExtended"),
|
std::make_pair(features.shaderImageGatherExtended, "shaderImageGatherExtended"),
|
||||||
std::make_pair(features.shaderStorageImageWriteWithoutFormat,
|
std::make_pair(features.shaderStorageImageWriteWithoutFormat,
|
||||||
"shaderStorageImageWriteWithoutFormat"),
|
"shaderStorageImageWriteWithoutFormat"),
|
||||||
|
std::make_pair(robustness2.robustBufferAccess2, "robustBufferAccess2"),
|
||||||
|
std::make_pair(robustness2.robustImageAccess2, "robustImageAccess2"),
|
||||||
|
std::make_pair(robustness2.nullDescriptor, "nullDescriptor"),
|
||||||
};
|
};
|
||||||
for (const auto& [is_supported, name] : feature_report) {
|
for (const auto& [is_supported, name] : feature_report) {
|
||||||
if (is_supported) {
|
if (is_supported) {
|
||||||
|
@ -621,7 +620,6 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) {
|
||||||
bool has_ext_transform_feedback{};
|
bool has_ext_transform_feedback{};
|
||||||
bool has_ext_custom_border_color{};
|
bool has_ext_custom_border_color{};
|
||||||
bool has_ext_extended_dynamic_state{};
|
bool has_ext_extended_dynamic_state{};
|
||||||
bool has_ext_robustness2{};
|
|
||||||
for (const VkExtensionProperties& extension : physical.EnumerateDeviceExtensionProperties()) {
|
for (const VkExtensionProperties& extension : physical.EnumerateDeviceExtensionProperties()) {
|
||||||
const auto test = [&](std::optional<std::reference_wrapper<bool>> status, const char* name,
|
const auto test = [&](std::optional<std::reference_wrapper<bool>> status, const char* name,
|
||||||
bool push) {
|
bool push) {
|
||||||
|
@ -649,14 +647,12 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) {
|
||||||
test(has_ext_transform_feedback, VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME, false);
|
test(has_ext_transform_feedback, VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME, false);
|
||||||
test(has_ext_custom_border_color, VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME, false);
|
test(has_ext_custom_border_color, VK_EXT_CUSTOM_BORDER_COLOR_EXTENSION_NAME, false);
|
||||||
test(has_ext_extended_dynamic_state, VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME, false);
|
test(has_ext_extended_dynamic_state, VK_EXT_EXTENDED_DYNAMIC_STATE_EXTENSION_NAME, false);
|
||||||
test(has_ext_robustness2, VK_EXT_ROBUSTNESS_2_EXTENSION_NAME, false);
|
|
||||||
test(has_ext_subgroup_size_control, VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME, false);
|
test(has_ext_subgroup_size_control, VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME, false);
|
||||||
if (Settings::values.renderer_debug) {
|
if (Settings::values.renderer_debug) {
|
||||||
test(nv_device_diagnostics_config, VK_NV_DEVICE_DIAGNOSTICS_CONFIG_EXTENSION_NAME,
|
test(nv_device_diagnostics_config, VK_NV_DEVICE_DIAGNOSTICS_CONFIG_EXTENSION_NAME,
|
||||||
true);
|
true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VkPhysicalDeviceFeatures2KHR features;
|
VkPhysicalDeviceFeatures2KHR features;
|
||||||
features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR;
|
features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR;
|
||||||
|
|
||||||
|
@ -673,7 +669,6 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) {
|
||||||
is_float16_supported = float16_int8_features.shaderFloat16;
|
is_float16_supported = float16_int8_features.shaderFloat16;
|
||||||
extensions.push_back(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME);
|
extensions.push_back(VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_ext_subgroup_size_control) {
|
if (has_ext_subgroup_size_control) {
|
||||||
VkPhysicalDeviceSubgroupSizeControlFeaturesEXT subgroup_features;
|
VkPhysicalDeviceSubgroupSizeControlFeaturesEXT subgroup_features;
|
||||||
subgroup_features.sType =
|
subgroup_features.sType =
|
||||||
|
@ -700,7 +695,6 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) {
|
||||||
} else {
|
} else {
|
||||||
is_warp_potentially_bigger = true;
|
is_warp_potentially_bigger = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_ext_transform_feedback) {
|
if (has_ext_transform_feedback) {
|
||||||
VkPhysicalDeviceTransformFeedbackFeaturesEXT tfb_features;
|
VkPhysicalDeviceTransformFeedbackFeaturesEXT tfb_features;
|
||||||
tfb_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT;
|
tfb_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT;
|
||||||
|
@ -722,7 +716,6 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) {
|
||||||
ext_transform_feedback = true;
|
ext_transform_feedback = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_ext_custom_border_color) {
|
if (has_ext_custom_border_color) {
|
||||||
VkPhysicalDeviceCustomBorderColorFeaturesEXT border_features;
|
VkPhysicalDeviceCustomBorderColorFeaturesEXT border_features;
|
||||||
border_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT;
|
border_features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_FEATURES_EXT;
|
||||||
|
@ -735,7 +728,6 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) {
|
||||||
ext_custom_border_color = true;
|
ext_custom_border_color = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_ext_extended_dynamic_state) {
|
if (has_ext_extended_dynamic_state) {
|
||||||
VkPhysicalDeviceExtendedDynamicStateFeaturesEXT dynamic_state;
|
VkPhysicalDeviceExtendedDynamicStateFeaturesEXT dynamic_state;
|
||||||
dynamic_state.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT;
|
dynamic_state.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_FEATURES_EXT;
|
||||||
|
@ -748,20 +740,6 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) {
|
||||||
ext_extended_dynamic_state = true;
|
ext_extended_dynamic_state = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_ext_robustness2) {
|
|
||||||
VkPhysicalDeviceRobustness2FeaturesEXT robustness2;
|
|
||||||
robustness2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT;
|
|
||||||
robustness2.pNext = nullptr;
|
|
||||||
features.pNext = &robustness2;
|
|
||||||
physical.GetFeatures2KHR(features);
|
|
||||||
if (robustness2.nullDescriptor && robustness2.robustBufferAccess2 &&
|
|
||||||
robustness2.robustImageAccess2) {
|
|
||||||
extensions.push_back(VK_EXT_ROBUSTNESS_2_EXTENSION_NAME);
|
|
||||||
ext_robustness2 = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return extensions;
|
return extensions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -285,7 +285,6 @@ private:
|
||||||
bool ext_transform_feedback{}; ///< Support for VK_EXT_transform_feedback.
|
bool ext_transform_feedback{}; ///< Support for VK_EXT_transform_feedback.
|
||||||
bool ext_custom_border_color{}; ///< Support for VK_EXT_custom_border_color.
|
bool ext_custom_border_color{}; ///< Support for VK_EXT_custom_border_color.
|
||||||
bool ext_extended_dynamic_state{}; ///< Support for VK_EXT_extended_dynamic_state.
|
bool ext_extended_dynamic_state{}; ///< Support for VK_EXT_extended_dynamic_state.
|
||||||
bool ext_robustness2{}; ///< Support for VK_EXT_robustness2.
|
|
||||||
bool ext_shader_stencil_export{}; ///< Support for VK_EXT_shader_stencil_export.
|
bool ext_shader_stencil_export{}; ///< Support for VK_EXT_shader_stencil_export.
|
||||||
bool nv_device_diagnostics_config{}; ///< Support for VK_NV_device_diagnostics_config.
|
bool nv_device_diagnostics_config{}; ///< Support for VK_NV_device_diagnostics_config.
|
||||||
bool has_renderdoc{}; ///< Has RenderDoc attached
|
bool has_renderdoc{}; ///< Has RenderDoc attached
|
||||||
|
|
|
@ -782,7 +782,7 @@ void Config::ReadRendererValues() {
|
||||||
ReadSettingGlobal(Settings::values.frame_limit, QStringLiteral("frame_limit"), 100);
|
ReadSettingGlobal(Settings::values.frame_limit, QStringLiteral("frame_limit"), 100);
|
||||||
ReadSettingGlobal(Settings::values.use_disk_shader_cache,
|
ReadSettingGlobal(Settings::values.use_disk_shader_cache,
|
||||||
QStringLiteral("use_disk_shader_cache"), true);
|
QStringLiteral("use_disk_shader_cache"), true);
|
||||||
ReadSettingGlobal(Settings::values.gpu_accuracy, QStringLiteral("gpu_accuracy"), 0);
|
ReadSettingGlobal(Settings::values.gpu_accuracy, QStringLiteral("gpu_accuracy"), 1);
|
||||||
ReadSettingGlobal(Settings::values.use_asynchronous_gpu_emulation,
|
ReadSettingGlobal(Settings::values.use_asynchronous_gpu_emulation,
|
||||||
QStringLiteral("use_asynchronous_gpu_emulation"), true);
|
QStringLiteral("use_asynchronous_gpu_emulation"), true);
|
||||||
ReadSettingGlobal(Settings::values.use_nvdec_emulation, QStringLiteral("use_nvdec_emulation"),
|
ReadSettingGlobal(Settings::values.use_nvdec_emulation, QStringLiteral("use_nvdec_emulation"),
|
||||||
|
@ -1351,7 +1351,7 @@ void Config::SaveRendererValues() {
|
||||||
Settings::values.use_disk_shader_cache, true);
|
Settings::values.use_disk_shader_cache, true);
|
||||||
WriteSettingGlobal(QStringLiteral("gpu_accuracy"),
|
WriteSettingGlobal(QStringLiteral("gpu_accuracy"),
|
||||||
static_cast<int>(Settings::values.gpu_accuracy.GetValue(global)),
|
static_cast<int>(Settings::values.gpu_accuracy.GetValue(global)),
|
||||||
Settings::values.gpu_accuracy.UsingGlobal(), 0);
|
Settings::values.gpu_accuracy.UsingGlobal(), 1);
|
||||||
WriteSettingGlobal(QStringLiteral("use_asynchronous_gpu_emulation"),
|
WriteSettingGlobal(QStringLiteral("use_asynchronous_gpu_emulation"),
|
||||||
Settings::values.use_asynchronous_gpu_emulation, true);
|
Settings::values.use_asynchronous_gpu_emulation, true);
|
||||||
WriteSettingGlobal(QStringLiteral("use_nvdec_emulation"), Settings::values.use_nvdec_emulation,
|
WriteSettingGlobal(QStringLiteral("use_nvdec_emulation"), Settings::values.use_nvdec_emulation,
|
||||||
|
|
|
@ -2490,6 +2490,11 @@ void GMainWindow::OnCaptureScreenshot() {
|
||||||
.arg(title_id, 16, 16, QLatin1Char{'0'})
|
.arg(title_id, 16, 16, QLatin1Char{'0'})
|
||||||
.arg(date);
|
.arg(date);
|
||||||
|
|
||||||
|
if (!Common::FS::CreateDir(screenshot_path.toStdString())) {
|
||||||
|
OnStartGame();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (UISettings::values.enable_screenshot_save_as) {
|
if (UISettings::values.enable_screenshot_save_as) {
|
||||||
filename = QFileDialog::getSaveFileName(this, tr("Capture Screenshot"), filename,
|
filename = QFileDialog::getSaveFileName(this, tr("Capture Screenshot"), filename,
|
||||||
|
|
|
@ -388,7 +388,7 @@ void Config::ReadValues() {
|
||||||
static_cast<u16>(sdl2_config->GetInteger("Renderer", "frame_limit", 100)));
|
static_cast<u16>(sdl2_config->GetInteger("Renderer", "frame_limit", 100)));
|
||||||
Settings::values.use_disk_shader_cache.SetValue(
|
Settings::values.use_disk_shader_cache.SetValue(
|
||||||
sdl2_config->GetBoolean("Renderer", "use_disk_shader_cache", false));
|
sdl2_config->GetBoolean("Renderer", "use_disk_shader_cache", false));
|
||||||
const int gpu_accuracy_level = sdl2_config->GetInteger("Renderer", "gpu_accuracy", 0);
|
const int gpu_accuracy_level = sdl2_config->GetInteger("Renderer", "gpu_accuracy", 1);
|
||||||
Settings::values.gpu_accuracy.SetValue(static_cast<Settings::GPUAccuracy>(gpu_accuracy_level));
|
Settings::values.gpu_accuracy.SetValue(static_cast<Settings::GPUAccuracy>(gpu_accuracy_level));
|
||||||
Settings::values.use_asynchronous_gpu_emulation.SetValue(
|
Settings::values.use_asynchronous_gpu_emulation.SetValue(
|
||||||
sdl2_config->GetBoolean("Renderer", "use_asynchronous_gpu_emulation", true));
|
sdl2_config->GetBoolean("Renderer", "use_asynchronous_gpu_emulation", true));
|
||||||
|
|
Loading…
Reference in a new issue