diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/common/ring_buffer.h | 21 | ||||
-rw-r--r-- | src/core/hle/kernel/k_address_arbiter.cpp | 84 | ||||
-rw-r--r-- | src/core/hle/kernel/svc.cpp | 247 | ||||
-rw-r--r-- | src/core/hle/service/lm/lm.cpp | 16 | ||||
-rw-r--r-- | src/core/hle/service/ns/pl_u.cpp | 9 | ||||
-rw-r--r-- | src/tests/common/ring_buffer.cpp | 10 | ||||
-rw-r--r-- | src/video_core/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/video_core/morton.cpp | 0 | ||||
-rw-r--r-- | src/video_core/morton.h | 0 | ||||
-rw-r--r-- | src/video_core/renderer_opengl/renderer_opengl.cpp | 2 | ||||
-rw-r--r-- | src/yuzu/bootmanager.cpp | 31 | ||||
-rw-r--r-- | src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp | 26 |
12 files changed, 266 insertions, 182 deletions
diff --git a/src/common/ring_buffer.h b/src/common/ring_buffer.h index 138fa01310..4a8d09806c 100644 --- a/src/common/ring_buffer.h +++ b/src/common/ring_buffer.h @@ -19,15 +19,14 @@ namespace Common { /// SPSC ring buffer /// @tparam T Element type /// @tparam capacity Number of slots in ring buffer -/// @tparam granularity Slot size in terms of number of elements -template <typename T, std::size_t capacity, std::size_t granularity = 1> +template <typename T, std::size_t capacity> class RingBuffer { - /// A "slot" is made of `granularity` elements of `T`. - static constexpr std::size_t slot_size = granularity * sizeof(T); + /// A "slot" is made of a single `T`. + static constexpr std::size_t slot_size = sizeof(T); // T must be safely memcpy-able and have a trivial default constructor. static_assert(std::is_trivial_v<T>); // Ensure capacity is sensible. - static_assert(capacity < std::numeric_limits<std::size_t>::max() / 2 / granularity); + static_assert(capacity < std::numeric_limits<std::size_t>::max() / 2); static_assert((capacity & (capacity - 1)) == 0, "capacity must be a power of two"); // Ensure lock-free. static_assert(std::atomic_size_t::is_always_lock_free); @@ -47,7 +46,7 @@ public: const std::size_t second_copy = push_count - first_copy; const char* in = static_cast<const char*>(new_slots); - std::memcpy(m_data.data() + pos * granularity, in, first_copy * slot_size); + std::memcpy(m_data.data() + pos, in, first_copy * slot_size); in += first_copy * slot_size; std::memcpy(m_data.data(), in, second_copy * slot_size); @@ -74,7 +73,7 @@ public: const std::size_t second_copy = pop_count - first_copy; char* out = static_cast<char*>(output); - std::memcpy(out, m_data.data() + pos * granularity, first_copy * slot_size); + std::memcpy(out, m_data.data() + pos, first_copy * slot_size); out += first_copy * slot_size; std::memcpy(out, m_data.data(), second_copy * slot_size); @@ -84,9 +83,9 @@ public: } std::vector<T> Pop(std::size_t max_slots = ~std::size_t(0)) { - std::vector<T> out(std::min(max_slots, capacity) * granularity); - const std::size_t count = Pop(out.data(), out.size() / granularity); - out.resize(count * granularity); + std::vector<T> out(std::min(max_slots, capacity)); + const std::size_t count = Pop(out.data(), out.size()); + out.resize(count); return out; } @@ -113,7 +112,7 @@ private: alignas(128) std::atomic_size_t m_write_index{0}; #endif - std::array<T, granularity * capacity> m_data; + std::array<T, capacity> m_data; }; } // namespace Common diff --git a/src/core/hle/kernel/k_address_arbiter.cpp b/src/core/hle/kernel/k_address_arbiter.cpp index f2f497dc4d..d0e90fd60e 100644 --- a/src/core/hle/kernel/k_address_arbiter.cpp +++ b/src/core/hle/kernel/k_address_arbiter.cpp @@ -118,9 +118,10 @@ ResultCode KAddressArbiter::SignalAndIncrementIfEqual(VAddr addr, s32 value, s32 // Check the userspace value. s32 user_value{}; - R_UNLESS(UpdateIfEqual(system, std::addressof(user_value), addr, value, value + 1), - Svc::ResultInvalidCurrentMemory); - + if (!UpdateIfEqual(system, &user_value, addr, value, value + 1)) { + LOG_ERROR(Kernel, "Invalid current memory!"); + return Svc::ResultInvalidCurrentMemory; + } if (user_value != value) { return Svc::ResultInvalidState; } @@ -146,61 +147,34 @@ ResultCode KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32 // Perform signaling. s32 num_waiters{}; { - KScopedSchedulerLock sl(kernel); + [[maybe_unused]] const KScopedSchedulerLock sl(kernel); auto it = thread_tree.nfind_light({addr, -1}); // Determine the updated value. s32 new_value{}; - if (/*GetTargetFirmware() >= TargetFirmware_7_0_0*/ true) { - if (count <= 0) { - if ((it != thread_tree.end()) && (it->GetAddressArbiterKey() == addr)) { - new_value = value - 2; - } else { - new_value = value + 1; - } + if (count <= 0) { + if (it != thread_tree.end() && it->GetAddressArbiterKey() == addr) { + new_value = value - 2; } else { - if ((it != thread_tree.end()) && (it->GetAddressArbiterKey() == addr)) { - auto tmp_it = it; - s32 tmp_num_waiters{}; - while ((++tmp_it != thread_tree.end()) && - (tmp_it->GetAddressArbiterKey() == addr)) { - if ((tmp_num_waiters++) >= count) { - break; - } - } - - if (tmp_num_waiters < count) { - new_value = value - 1; - } else { - new_value = value; - } - } else { - new_value = value + 1; - } + new_value = value + 1; } } else { - if (count <= 0) { - if ((it != thread_tree.end()) && (it->GetAddressArbiterKey() == addr)) { - new_value = value - 1; - } else { - new_value = value + 1; - } - } else { + if (it != thread_tree.end() && it->GetAddressArbiterKey() == addr) { auto tmp_it = it; s32 tmp_num_waiters{}; - while ((tmp_it != thread_tree.end()) && (tmp_it->GetAddressArbiterKey() == addr) && - (tmp_num_waiters < count + 1)) { - ++tmp_num_waiters; - ++tmp_it; + while (++tmp_it != thread_tree.end() && tmp_it->GetAddressArbiterKey() == addr) { + if (tmp_num_waiters++ >= count) { + break; + } } - if (tmp_num_waiters == 0) { - new_value = value + 1; - } else if (tmp_num_waiters <= count) { + if (tmp_num_waiters < count) { new_value = value - 1; } else { new_value = value; } + } else { + new_value = value + 1; } } @@ -208,13 +182,15 @@ ResultCode KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32 s32 user_value{}; bool succeeded{}; if (value != new_value) { - succeeded = UpdateIfEqual(system, std::addressof(user_value), addr, value, new_value); + succeeded = UpdateIfEqual(system, &user_value, addr, value, new_value); } else { - succeeded = ReadFromUser(system, std::addressof(user_value), addr); + succeeded = ReadFromUser(system, &user_value, addr); } - R_UNLESS(succeeded, Svc::ResultInvalidCurrentMemory); - + if (!succeeded) { + LOG_ERROR(Kernel, "Invalid current memory!"); + return Svc::ResultInvalidCurrentMemory; + } if (user_value != value) { return Svc::ResultInvalidState; } @@ -255,9 +231,9 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement s32 user_value{}; bool succeeded{}; if (decrement) { - succeeded = DecrementIfLessThan(system, std::addressof(user_value), addr, value); + succeeded = DecrementIfLessThan(system, &user_value, addr, value); } else { - succeeded = ReadFromUser(system, std::addressof(user_value), addr); + succeeded = ReadFromUser(system, &user_value, addr); } if (!succeeded) { @@ -278,7 +254,7 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement } // Set the arbiter. - cur_thread->SetAddressArbiter(std::addressof(thread_tree), addr); + cur_thread->SetAddressArbiter(&thread_tree, addr); thread_tree.insert(*cur_thread); cur_thread->SetState(ThreadState::Waiting); cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration); @@ -299,7 +275,7 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement // Get the result. KSynchronizationObject* dummy{}; - return cur_thread->GetWaitResult(std::addressof(dummy)); + return cur_thread->GetWaitResult(&dummy); } ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) { @@ -320,7 +296,7 @@ ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) { // Read the value from userspace. s32 user_value{}; - if (!ReadFromUser(system, std::addressof(user_value), addr)) { + if (!ReadFromUser(system, &user_value, addr)) { slp.CancelSleep(); return Svc::ResultInvalidCurrentMemory; } @@ -338,7 +314,7 @@ ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) { } // Set the arbiter. - cur_thread->SetAddressArbiter(std::addressof(thread_tree), addr); + cur_thread->SetAddressArbiter(&thread_tree, addr); thread_tree.insert(*cur_thread); cur_thread->SetState(ThreadState::Waiting); cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration); @@ -359,7 +335,7 @@ ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) { // Get the result. KSynchronizationObject* dummy{}; - return cur_thread->GetWaitResult(std::addressof(dummy)); + return cur_thread->GetWaitResult(&dummy); } } // namespace Kernel diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index edf208eff3..26650a5134 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -368,7 +368,10 @@ static ResultCode GetThreadId(Core::System& system, u64* out_thread_id, Handle t // Get the thread from its handle. const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); - R_UNLESS(thread, Svc::ResultInvalidHandle); + if (!thread) { + LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle); + return ResultInvalidHandle; + } // Get the thread's id. *out_thread_id = thread->GetThreadID(); @@ -478,7 +481,10 @@ static ResultCode CancelSynchronization(Core::System& system, Handle thread_hand // Get the thread from its handle. const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); - R_UNLESS(thread, Svc::ResultInvalidHandle); + if (!thread) { + LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle); + return ResultInvalidHandle; + } // Cancel the thread's wait. thread->WaitCancel(); @@ -496,8 +502,15 @@ static ResultCode ArbitrateLock(Core::System& system, Handle thread_handle, VAdd thread_handle, address, tag); // Validate the input address. - R_UNLESS(!Memory::IsKernelAddress(address), Svc::ResultInvalidCurrentMemory); - R_UNLESS(Common::IsAligned(address, sizeof(u32)), Svc::ResultInvalidAddress); + if (Memory::IsKernelAddress(address)) { + LOG_ERROR(Kernel_SVC, "Attempting to arbitrate a lock on a kernel address (address={:08X})", + address); + return ResultInvalidCurrentMemory; + } + if (!Common::IsAligned(address, sizeof(u32))) { + LOG_ERROR(Kernel_SVC, "Input address must be 4 byte aligned (address: {:08X})", address); + return ResultInvalidAddress; + } return system.Kernel().CurrentProcess()->WaitForAddress(thread_handle, address, tag); } @@ -512,8 +525,16 @@ static ResultCode ArbitrateUnlock(Core::System& system, VAddr address) { LOG_TRACE(Kernel_SVC, "called address=0x{:X}", address); // Validate the input address. - R_UNLESS(!Memory::IsKernelAddress(address), Svc::ResultInvalidCurrentMemory); - R_UNLESS(Common::IsAligned(address, sizeof(u32)), Svc::ResultInvalidAddress); + if (Memory::IsKernelAddress(address)) { + LOG_ERROR(Kernel_SVC, + "Attempting to arbitrate an unlock on a kernel address (address={:08X})", + address); + return ResultInvalidCurrentMemory; + } + if (!Common::IsAligned(address, sizeof(u32))) { + LOG_ERROR(Kernel_SVC, "Input address must be 4 byte aligned (address: {:08X})", address); + return ResultInvalidAddress; + } return system.Kernel().CurrentProcess()->SignalToAddress(address); } @@ -1025,37 +1046,47 @@ static ResultCode UnmapPhysicalMemory32(Core::System& system, u32 addr, u32 size return UnmapPhysicalMemory(system, addr, size); } -constexpr bool IsValidThreadActivity(Svc::ThreadActivity thread_activity) { - switch (thread_activity) { - case Svc::ThreadActivity::Runnable: - case Svc::ThreadActivity::Paused: - return true; - default: - return false; - } -} - /// Sets the thread activity static ResultCode SetThreadActivity(Core::System& system, Handle thread_handle, - Svc::ThreadActivity thread_activity) { + ThreadActivity thread_activity) { LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, activity=0x{:08X}", thread_handle, thread_activity); // Validate the activity. - R_UNLESS(IsValidThreadActivity(thread_activity), Svc::ResultInvalidEnumValue); + constexpr auto IsValidThreadActivity = [](ThreadActivity activity) { + return activity == ThreadActivity::Runnable || activity == ThreadActivity::Paused; + }; + if (!IsValidThreadActivity(thread_activity)) { + LOG_ERROR(Kernel_SVC, "Invalid thread activity value provided (activity={})", + thread_activity); + return ResultInvalidEnumValue; + } // Get the thread from its handle. auto& kernel = system.Kernel(); const auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); - R_UNLESS(thread, Svc::ResultInvalidHandle); + if (!thread) { + LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle); + return ResultInvalidHandle; + } // Check that the activity is being set on a non-current thread for the current process. - R_UNLESS(thread->GetOwnerProcess() == kernel.CurrentProcess(), Svc::ResultInvalidHandle); - R_UNLESS(thread.get() != GetCurrentThreadPointer(kernel), Svc::ResultBusy); + if (thread->GetOwnerProcess() != kernel.CurrentProcess()) { + LOG_ERROR(Kernel_SVC, "Invalid owning process for the created thread."); + return ResultInvalidHandle; + } + if (thread.get() == GetCurrentThreadPointer(kernel)) { + LOG_ERROR(Kernel_SVC, "Thread is busy"); + return ResultBusy; + } // Set the activity. - R_TRY(thread->SetActivity(thread_activity)); + const auto set_result = thread->SetActivity(thread_activity); + if (set_result.IsError()) { + LOG_ERROR(Kernel_SVC, "Failed to set thread activity."); + return set_result; + } return RESULT_SUCCESS; } @@ -1074,16 +1105,29 @@ static ResultCode GetThreadContext(Core::System& system, VAddr out_context, Hand const auto* current_process = system.Kernel().CurrentProcess(); const std::shared_ptr<KThread> thread = current_process->GetHandleTable().Get<KThread>(thread_handle); - R_UNLESS(thread, Svc::ResultInvalidHandle); + if (!thread) { + LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={})", thread_handle); + return ResultInvalidHandle; + } // Require the handle be to a non-current thread in the current process. - R_UNLESS(thread->GetOwnerProcess() == current_process, Svc::ResultInvalidHandle); - R_UNLESS(thread.get() != system.Kernel().CurrentScheduler()->GetCurrentThread(), - Svc::ResultBusy); + if (thread->GetOwnerProcess() != current_process) { + LOG_ERROR(Kernel_SVC, "Thread owning process is not the current process."); + return ResultInvalidHandle; + } + if (thread.get() == system.Kernel().CurrentScheduler()->GetCurrentThread()) { + LOG_ERROR(Kernel_SVC, "Current thread is busy."); + return ResultBusy; + } // Get the thread context. std::vector<u8> context; - R_TRY(thread->GetThreadContext3(context)); + const auto context_result = thread->GetThreadContext3(context); + if (context_result.IsError()) { + LOG_ERROR(Kernel_SVC, "Unable to successfully retrieve thread context (result: {})", + context_result.raw); + return context_result; + } // Copy the thread context to user space. system.Memory().WriteBlock(out_context, context.data(), context.size()); @@ -1102,7 +1146,10 @@ static ResultCode GetThreadPriority(Core::System& system, u32* out_priority, Han // Get the thread from its handle. const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(handle); - R_UNLESS(thread, Svc::ResultInvalidHandle); + if (!thread) { + LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", handle); + return ResultInvalidHandle; + } // Get the thread's priority. *out_priority = thread->GetPriority(); @@ -1118,13 +1165,18 @@ static ResultCode SetThreadPriority(Core::System& system, Handle handle, u32 pri LOG_TRACE(Kernel_SVC, "called"); // Validate the priority. - R_UNLESS(Svc::HighestThreadPriority <= priority && priority <= Svc::LowestThreadPriority, - Svc::ResultInvalidPriority); + if (HighestThreadPriority > priority || priority > LowestThreadPriority) { + LOG_ERROR(Kernel_SVC, "Invalid thread priority specified (priority={})", priority); + return ResultInvalidPriority; + } // Get the thread from its handle. const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(handle); - R_UNLESS(thread, Svc::ResultInvalidHandle); + if (!thread) { + LOG_ERROR(Kernel_SVC, "Invalid handle provided (handle={:08X})", handle); + return ResultInvalidHandle; + } // Set the thread priority. thread->SetBasePriority(priority); @@ -1440,17 +1492,28 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e // Adjust core id, if it's the default magic. auto& kernel = system.Kernel(); auto& process = *kernel.CurrentProcess(); - if (core_id == Svc::IdealCoreUseProcessValue) { + if (core_id == IdealCoreUseProcessValue) { core_id = process.GetIdealCoreId(); } // Validate arguments. - R_UNLESS(IsValidCoreId(core_id), Svc::ResultInvalidCoreId); - R_UNLESS(((1ULL << core_id) & process.GetCoreMask()) != 0, Svc::ResultInvalidCoreId); + if (!IsValidCoreId(core_id)) { + LOG_ERROR(Kernel_SVC, "Invalid Core ID specified (id={})", core_id); + return ResultInvalidCoreId; + } + if (((1ULL << core_id) & process.GetCoreMask()) == 0) { + LOG_ERROR(Kernel_SVC, "Core ID doesn't fall within allowable cores (id={})", core_id); + return ResultInvalidCoreId; + } - R_UNLESS(Svc::HighestThreadPriority <= priority && priority <= Svc::LowestThreadPriority, - Svc::ResultInvalidPriority); - R_UNLESS(process.CheckThreadPriority(priority), Svc::ResultInvalidPriority); + if (HighestThreadPriority > priority || priority > LowestThreadPriority) { + LOG_ERROR(Kernel_SVC, "Invalid priority specified (priority={})", priority); + return ResultInvalidPriority; + } + if (!process.CheckThreadPriority(priority)) { + LOG_ERROR(Kernel_SVC, "Invalid allowable thread priority (priority={})", priority); + return ResultInvalidPriority; + } ASSERT(process.GetResourceLimit()->Reserve( LimitableResource::Threads, 1, system.CoreTiming().GetGlobalTimeNs().count() + 100000000)); @@ -1489,10 +1552,19 @@ static ResultCode StartThread(Core::System& system, Handle thread_handle) { // Get the thread from its handle. const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); - R_UNLESS(thread, Svc::ResultInvalidHandle); + if (!thread) { + LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle); + return ResultInvalidHandle; + } // Try to start the thread. - R_TRY(thread->Run()); + const auto run_result = thread->Run(); + if (run_result.IsError()) { + LOG_ERROR(Kernel_SVC, + "Unable to successfuly start thread (thread handle={:08X}, result={})", + thread_handle, run_result.raw); + return run_result; + } return RESULT_SUCCESS; } @@ -1553,8 +1625,14 @@ static ResultCode WaitProcessWideKeyAtomic(Core::System& system, VAddr address, cv_key, tag, timeout_ns); // Validate input. - R_UNLESS(!Memory::IsKernelAddress(address), Svc::ResultInvalidCurrentMemory); - R_UNLESS(Common::IsAligned(address, sizeof(int32_t)), Svc::ResultInvalidAddress); + if (Memory::IsKernelAddress(address)) { + LOG_ERROR(Kernel_SVC, "Attempted to wait on kernel address (address={:08X})", address); + return ResultInvalidCurrentMemory; + } + if (!Common::IsAligned(address, sizeof(s32))) { + LOG_ERROR(Kernel_SVC, "Address must be 4 byte aligned (address={:08X})", address); + return ResultInvalidAddress; + } // Convert timeout from nanoseconds to ticks. s64 timeout{}; @@ -1629,9 +1707,18 @@ static ResultCode WaitForAddress(Core::System& system, VAddr address, Svc::Arbit address, arb_type, value, timeout_ns); // Validate input. - R_UNLESS(!Memory::IsKernelAddress(address), Svc::ResultInvalidCurrentMemory); - R_UNLESS(Common::IsAligned(address, sizeof(int32_t)), Svc::ResultInvalidAddress); - R_UNLESS(IsValidArbitrationType(arb_type), Svc::ResultInvalidEnumValue); + if (Memory::IsKernelAddress(address)) { + LOG_ERROR(Kernel_SVC, "Attempting to wait on kernel address (address={:08X})", address); + return ResultInvalidCurrentMemory; + } + if (!Common::IsAligned(address, sizeof(s32))) { + LOG_ERROR(Kernel_SVC, "Wait address must be 4 byte aligned (address={:08X})", address); + return ResultInvalidAddress; + } + if (!IsValidArbitrationType(arb_type)) { + LOG_ERROR(Kernel_SVC, "Invalid arbitration type specified (type={})", arb_type); + return ResultInvalidEnumValue; + } // Convert timeout from nanoseconds to ticks. s64 timeout{}; @@ -1665,9 +1752,18 @@ static ResultCode SignalToAddress(Core::System& system, VAddr address, Svc::Sign address, signal_type, value, count); // Validate input. - R_UNLESS(!Memory::IsKernelAddress(address), Svc::ResultInvalidCurrentMemory); - R_UNLESS(Common::IsAligned(address, sizeof(s32)), Svc::ResultInvalidAddress); - R_UNLESS(IsValidSignalType(signal_type), Svc::ResultInvalidEnumValue); + if (Memory::IsKernelAddress(address)) { + LOG_ERROR(Kernel_SVC, "Attempting to signal to a kernel address (address={:08X})", address); + return ResultInvalidCurrentMemory; + } + if (!Common::IsAligned(address, sizeof(s32))) { + LOG_ERROR(Kernel_SVC, "Signaled address must be 4 byte aligned (address={:08X})", address); + return ResultInvalidAddress; + } + if (!IsValidSignalType(signal_type)) { + LOG_ERROR(Kernel_SVC, "Invalid signal type specified (type={})", signal_type); + return ResultInvalidEnumValue; + } return system.Kernel().CurrentProcess()->SignalAddressArbiter(address, signal_type, value, count); @@ -1815,10 +1911,17 @@ static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, // Get the thread from its handle. const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); - R_UNLESS(thread, Svc::ResultInvalidHandle); + if (!thread) { + LOG_ERROR(Kernel_SVC, "Invalid thread handle specified (handle={:08X})", thread_handle); + return ResultInvalidHandle; + } // Get the core mask. - R_TRY(thread->GetCoreMask(out_core_id, out_affinity_mask)); + const auto result = thread->GetCoreMask(out_core_id, out_affinity_mask); + if (result.IsError()) { + LOG_ERROR(Kernel_SVC, "Unable to successfully retrieve core mask (result={})", result.raw); + return result; + } return RESULT_SUCCESS; } @@ -1846,26 +1949,46 @@ static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle, } else { // Validate the affinity mask. const u64 process_core_mask = current_process.GetCoreMask(); - R_UNLESS((affinity_mask | process_core_mask) == process_core_mask, - Svc::ResultInvalidCoreId); - R_UNLESS(affinity_mask != 0, Svc::ResultInvalidCombination); + if ((affinity_mask | process_core_mask) != process_core_mask) { + LOG_ERROR(Kernel_SVC, + "Affinity mask does match the process core mask (affinity mask={:016X}, core " + "mask={:016X})", + affinity_mask, process_core_mask); + return ResultInvalidCoreId; + } + if (affinity_mask == 0) { + LOG_ERROR(Kernel_SVC, "Affinity mask is zero."); + return ResultInvalidCombination; + } // Validate the core id. if (IsValidCoreId(core_id)) { - R_UNLESS(((1ULL << core_id) & affinity_mask) != 0, Svc::ResultInvalidCombination); + if (((1ULL << core_id) & affinity_mask) == 0) { + LOG_ERROR(Kernel_SVC, "Invalid core ID (ID={})", core_id); + return ResultInvalidCombination; + } } else { - R_UNLESS(core_id == Svc::IdealCoreNoUpdate || core_id == Svc::IdealCoreDontCare, - Svc::ResultInvalidCoreId); + if (core_id != IdealCoreNoUpdate && core_id != IdealCoreDontCare) { + LOG_ERROR(Kernel_SVC, "Invalid core ID (ID={})", core_id); + return ResultInvalidCoreId; + } } } // Get the thread from its handle. const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); - R_UNLESS(thread, Svc::ResultInvalidHandle); + if (!thread) { + LOG_ERROR(Kernel_SVC, "Invalid thread handle (handle={:08X})", thread_handle); + return ResultInvalidHandle; + } // Set the core mask. - R_TRY(thread->SetCoreMask(core_id, affinity_mask)); + const auto set_result = thread->SetCoreMask(core_id, affinity_mask); + if (set_result.IsError()) { + LOG_ERROR(Kernel_SVC, "Unable to successfully set core mask (result={})", set_result.raw); + return set_result; + } return RESULT_SUCCESS; } @@ -1884,7 +2007,10 @@ static ResultCode SignalEvent(Core::System& system, Handle event_handle) { // Get the writable event. auto writable_event = handle_table.Get<KWritableEvent>(event_handle); - R_UNLESS(writable_event, Svc::ResultInvalidHandle); + if (!writable_event) { + LOG_ERROR(Kernel_SVC, "Invalid event handle provided (handle={:08X})", event_handle); + return ResultInvalidHandle; + } return writable_event->Signal(); } @@ -1933,7 +2059,10 @@ static ResultCode CreateEvent(Core::System& system, Handle* out_write, Handle* o // Create a new event. const auto event = KEvent::Create(kernel, "CreateEvent"); - R_UNLESS(event != nullptr, Svc::ResultOutOfResource); + if (!event) { + LOG_ERROR(Kernel_SVC, "Unable to create new events. Event creation limit reached."); + return ResultOutOfResource; + } // Initialize the event. event->Initialize(); diff --git a/src/core/hle/service/lm/lm.cpp b/src/core/hle/service/lm/lm.cpp index 2a6d43d2a9..7d7542fc2e 100644 --- a/src/core/hle/service/lm/lm.cpp +++ b/src/core/hle/service/lm/lm.cpp @@ -143,17 +143,19 @@ private: rb.Push(RESULT_SUCCESS); } - u32 ReadLeb128(const std::vector<u8>& data, std::size_t& offset) { - u32 result{}; + u64 ReadLeb128(const std::vector<u8>& data, std::size_t& offset) { + u64 result{}; u32 shift{}; - do { - result |= (data[offset] & 0x7f) << shift; + + for (std::size_t i = 0; i < sizeof(u64); i++) { + const auto v = data[offset]; + result |= (static_cast<u64>(v & 0x7f) << shift); shift += 7; offset++; - if (offset >= data.size()) { + if (offset >= data.size() || ((v & 0x80) == 0)) { break; } - } while ((data[offset] & 0x80) != 0); + } return result; } @@ -262,7 +264,7 @@ private: switch (entry.severity) { case LogSeverity::Trace: - LOG_DEBUG(Service_LM, "LogManager DEBUG ({}):\n{}", DestinationToString(destination), + LOG_DEBUG(Service_LM, "LogManager TRACE ({}):\n{}", DestinationToString(destination), output_log); break; case LogSeverity::Info: diff --git a/src/core/hle/service/ns/pl_u.cpp b/src/core/hle/service/ns/pl_u.cpp index 71c7587dbd..b6ac0a81aa 100644 --- a/src/core/hle/service/ns/pl_u.cpp +++ b/src/core/hle/service/ns/pl_u.cpp @@ -65,13 +65,18 @@ static void DecryptSharedFont(const std::vector<u32>& input, Kernel::PhysicalMem void DecryptSharedFontToTTF(const std::vector<u32>& input, std::vector<u8>& output) { ASSERT_MSG(input[0] == EXPECTED_MAGIC, "Failed to derive key, unexpected magic number"); + if (input.size() < 2) { + LOG_ERROR(Service_NS, "Input font is empty"); + return; + } + const u32 KEY = input[0] ^ EXPECTED_RESULT; // Derive key using an inverse xor std::vector<u32> transformed_font(input.size()); // TODO(ogniK): Figure out a better way to do this std::transform(input.begin(), input.end(), transformed_font.begin(), [&KEY](u32 font_data) { return Common::swap32(font_data ^ KEY); }); - transformed_font[1] = Common::swap32(transformed_font[1]) ^ KEY; // "re-encrypt" the size - std::memcpy(output.data(), transformed_font.data() + 2, transformed_font.size() * sizeof(u32)); + std::memcpy(output.data(), transformed_font.data() + 2, + (transformed_font.size() - 2) * sizeof(u32)); } void EncryptSharedFont(const std::vector<u32>& input, std::vector<u8>& output, diff --git a/src/tests/common/ring_buffer.cpp b/src/tests/common/ring_buffer.cpp index 54def22da0..903626e4b5 100644 --- a/src/tests/common/ring_buffer.cpp +++ b/src/tests/common/ring_buffer.cpp @@ -14,7 +14,7 @@ namespace Common { TEST_CASE("RingBuffer: Basic Tests", "[common]") { - RingBuffer<char, 4, 1> buf; + RingBuffer<char, 4> buf; // Pushing values into a ring buffer with space should succeed. for (std::size_t i = 0; i < 4; i++) { @@ -77,7 +77,7 @@ TEST_CASE("RingBuffer: Basic Tests", "[common]") { } TEST_CASE("RingBuffer: Threaded Test", "[common]") { - RingBuffer<char, 4, 2> buf; + RingBuffer<char, 8> buf; const char seed = 42; const std::size_t count = 1000000; std::size_t full = 0; @@ -92,8 +92,8 @@ TEST_CASE("RingBuffer: Threaded Test", "[common]") { std::array<char, 2> value = {seed, seed}; std::size_t i = 0; while (i < count) { - if (const std::size_t c = buf.Push(&value[0], 1); c > 0) { - REQUIRE(c == 1U); + if (const std::size_t c = buf.Push(&value[0], 2); c > 0) { + REQUIRE(c == 2U); i++; next_value(value); } else { @@ -107,7 +107,7 @@ TEST_CASE("RingBuffer: Threaded Test", "[common]") { std::array<char, 2> value = {seed, seed}; std::size_t i = 0; while (i < count) { - if (const std::vector<char> v = buf.Pop(1); v.size() > 0) { + if (const std::vector<char> v = buf.Pop(2); v.size() > 0) { REQUIRE(v.size() == 2U); REQUIRE(v[0] == value[0]); REQUIRE(v[1] == value[1]); diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index bb1f8491fa..2cf95937e6 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -67,8 +67,6 @@ add_library(video_core STATIC guest_driver.h memory_manager.cpp memory_manager.h - morton.cpp - morton.h query_cache.h rasterizer_accelerated.cpp rasterizer_accelerated.h diff --git a/src/video_core/morton.cpp b/src/video_core/morton.cpp deleted file mode 100644 index e69de29bb2..0000000000 --- a/src/video_core/morton.cpp +++ /dev/null diff --git a/src/video_core/morton.h b/src/video_core/morton.h deleted file mode 100644 index e69de29bb2..0000000000 --- a/src/video_core/morton.h +++ /dev/null diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index dd77a543ce..21159e4981 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp @@ -506,7 +506,7 @@ bool RendererOpenGL::Init() { AddTelemetryFields(); - if (!GLAD_GL_VERSION_4_3) { + if (!GLAD_GL_VERSION_4_6) { return false; } diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index 4528eb1965..ffdf34a4a0 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -126,7 +126,7 @@ public: /// Create the original context that should be shared from explicit OpenGLSharedContext(QSurface* surface) : surface(surface) { QSurfaceFormat format; - format.setVersion(4, 3); + format.setVersion(4, 6); format.setProfile(QSurfaceFormat::CompatibilityProfile); format.setOption(QSurfaceFormat::FormatOption::DeprecatedFunctions); if (Settings::values.renderer_debug) { @@ -651,10 +651,10 @@ bool GRenderWindow::LoadOpenGL() { const QString renderer = QString::fromUtf8(reinterpret_cast<const char*>(glGetString(GL_RENDERER))); - if (!GLAD_GL_VERSION_4_3) { - LOG_ERROR(Frontend, "GPU does not support OpenGL 4.3: {}", renderer.toStdString()); - QMessageBox::warning(this, tr("Error while initializing OpenGL 4.3!"), - tr("Your GPU may not support OpenGL 4.3, or you do not have the " + if (!GLAD_GL_VERSION_4_6) { + LOG_ERROR(Frontend, "GPU does not support OpenGL 4.6: {}", renderer.toStdString()); + QMessageBox::warning(this, tr("Error while initializing OpenGL 4.6!"), + tr("Your GPU may not support OpenGL 4.6, or you do not have the " "latest graphics driver.<br><br>GL Renderer:<br>%1") .arg(renderer)); return false; @@ -677,26 +677,13 @@ bool GRenderWindow::LoadOpenGL() { QStringList GRenderWindow::GetUnsupportedGLExtensions() const { QStringList unsupported_ext; - if (!GLAD_GL_ARB_buffer_storage) - unsupported_ext.append(QStringLiteral("ARB_buffer_storage")); - if (!GLAD_GL_ARB_direct_state_access) - unsupported_ext.append(QStringLiteral("ARB_direct_state_access")); - if (!GLAD_GL_ARB_vertex_type_10f_11f_11f_rev) - unsupported_ext.append(QStringLiteral("ARB_vertex_type_10f_11f_11f_rev")); - if (!GLAD_GL_ARB_texture_mirror_clamp_to_edge) - unsupported_ext.append(QStringLiteral("ARB_texture_mirror_clamp_to_edge")); - if (!GLAD_GL_ARB_multi_bind) - unsupported_ext.append(QStringLiteral("ARB_multi_bind")); - if (!GLAD_GL_ARB_clip_control) - unsupported_ext.append(QStringLiteral("ARB_clip_control")); - // Extensions required to support some texture formats. - if (!GLAD_GL_EXT_texture_compression_s3tc) + if (!GLAD_GL_EXT_texture_compression_s3tc) { unsupported_ext.append(QStringLiteral("EXT_texture_compression_s3tc")); - if (!GLAD_GL_ARB_texture_compression_rgtc) + } + if (!GLAD_GL_ARB_texture_compression_rgtc) { unsupported_ext.append(QStringLiteral("ARB_texture_compression_rgtc")); - if (!GLAD_GL_ARB_depth_buffer_float) - unsupported_ext.append(QStringLiteral("ARB_depth_buffer_float")); + } if (!unsupported_ext.empty()) { LOG_ERROR(Frontend, "GPU does not support all required extensions: {}", diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp index a103b04bd3..deddea9ee8 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp @@ -59,29 +59,17 @@ private: bool EmuWindow_SDL2_GL::SupportsRequiredGLExtensions() { std::vector<std::string_view> unsupported_ext; - if (!GLAD_GL_ARB_buffer_storage) - unsupported_ext.push_back("ARB_buffer_storage"); - if (!GLAD_GL_ARB_direct_state_access) - unsupported_ext.push_back("ARB_direct_state_access"); - if (!GLAD_GL_ARB_vertex_type_10f_11f_11f_rev) - unsupported_ext.push_back("ARB_vertex_type_10f_11f_11f_rev"); - if (!GLAD_GL_ARB_texture_mirror_clamp_to_edge) - unsupported_ext.push_back("ARB_texture_mirror_clamp_to_edge"); - if (!GLAD_GL_ARB_multi_bind) - unsupported_ext.push_back("ARB_multi_bind"); - if (!GLAD_GL_ARB_clip_control) - unsupported_ext.push_back("ARB_clip_control"); - // Extensions required to support some texture formats. - if (!GLAD_GL_EXT_texture_compression_s3tc) + if (!GLAD_GL_EXT_texture_compression_s3tc) { unsupported_ext.push_back("EXT_texture_compression_s3tc"); - if (!GLAD_GL_ARB_texture_compression_rgtc) + } + if (!GLAD_GL_ARB_texture_compression_rgtc) { unsupported_ext.push_back("ARB_texture_compression_rgtc"); - if (!GLAD_GL_ARB_depth_buffer_float) - unsupported_ext.push_back("ARB_depth_buffer_float"); + } - for (const auto& extension : unsupported_ext) + for (const auto& extension : unsupported_ext) { LOG_CRITICAL(Frontend, "Unsupported GL extension: {}", extension); + } return unsupported_ext.empty(); } @@ -89,7 +77,7 @@ bool EmuWindow_SDL2_GL::SupportsRequiredGLExtensions() { EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsystem, bool fullscreen) : EmuWindow_SDL2{input_subsystem} { SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); + SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6); SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); |