summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r--src/core/hle/kernel/k_address_space_info.cpp4
-rw-r--r--src/core/hle/kernel/k_address_space_info.h2
-rw-r--r--src/core/hle/kernel/k_device_address_space.h4
-rw-r--r--src/core/hle/kernel/k_process.h4
-rw-r--r--src/core/hle/kernel/k_resource_limit.cpp3
-rw-r--r--src/core/hle/kernel/k_thread.cpp24
-rw-r--r--src/core/hle/kernel/k_thread.h2
-rw-r--r--src/core/hle/kernel/svc/svc_synchronization.cpp45
-rw-r--r--src/core/hle/kernel/svc/svc_thread.cpp3
9 files changed, 66 insertions, 25 deletions
diff --git a/src/core/hle/kernel/k_address_space_info.cpp b/src/core/hle/kernel/k_address_space_info.cpp
index 97972ebae..c36eb5dc4 100644
--- a/src/core/hle/kernel/k_address_space_info.cpp
+++ b/src/core/hle/kernel/k_address_space_info.cpp
@@ -44,11 +44,11 @@ const KAddressSpaceInfo& GetAddressSpaceInfo(size_t width, KAddressSpaceInfo::Ty
} // namespace
-uintptr_t KAddressSpaceInfo::GetAddressSpaceStart(size_t width, KAddressSpaceInfo::Type type) {
+std::size_t KAddressSpaceInfo::GetAddressSpaceStart(size_t width, KAddressSpaceInfo::Type type) {
return GetAddressSpaceInfo(width, type).address;
}
-size_t KAddressSpaceInfo::GetAddressSpaceSize(size_t width, KAddressSpaceInfo::Type type) {
+std::size_t KAddressSpaceInfo::GetAddressSpaceSize(size_t width, KAddressSpaceInfo::Type type) {
return GetAddressSpaceInfo(width, type).size;
}
diff --git a/src/core/hle/kernel/k_address_space_info.h b/src/core/hle/kernel/k_address_space_info.h
index 69e9d77f2..9a26f6b90 100644
--- a/src/core/hle/kernel/k_address_space_info.h
+++ b/src/core/hle/kernel/k_address_space_info.h
@@ -18,7 +18,7 @@ struct KAddressSpaceInfo final {
Count,
};
- static u64 GetAddressSpaceStart(std::size_t width, Type type);
+ static std::size_t GetAddressSpaceStart(std::size_t width, Type type);
static std::size_t GetAddressSpaceSize(std::size_t width, Type type);
const std::size_t bit_width{};
diff --git a/src/core/hle/kernel/k_device_address_space.h b/src/core/hle/kernel/k_device_address_space.h
index 4709df995..b4a014c38 100644
--- a/src/core/hle/kernel/k_device_address_space.h
+++ b/src/core/hle/kernel/k_device_address_space.h
@@ -21,9 +21,9 @@ public:
~KDeviceAddressSpace();
Result Initialize(u64 address, u64 size);
- void Finalize();
+ void Finalize() override;
- bool IsInitialized() const {
+ bool IsInitialized() const override {
return m_is_initialized;
}
static void PostDestroy(uintptr_t arg) {}
diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h
index 09bf2f1d0..549809000 100644
--- a/src/core/hle/kernel/k_process.h
+++ b/src/core/hle/kernel/k_process.h
@@ -310,10 +310,10 @@ public:
/// Clears the signaled state of the process if and only if it's signaled.
///
/// @pre The process must not be already terminated. If this is called on a
- /// terminated process, then ERR_INVALID_STATE will be returned.
+ /// terminated process, then ResultInvalidState will be returned.
///
/// @pre The process must be in a signaled state. If this is called on a
- /// process instance that is not signaled, ERR_INVALID_STATE will be
+ /// process instance that is not signaled, ResultInvalidState will be
/// returned.
Result Reset();
diff --git a/src/core/hle/kernel/k_resource_limit.cpp b/src/core/hle/kernel/k_resource_limit.cpp
index b9d22b414..626517619 100644
--- a/src/core/hle/kernel/k_resource_limit.cpp
+++ b/src/core/hle/kernel/k_resource_limit.cpp
@@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/assert.h"
+#include "common/overflow.h"
#include "core/core.h"
#include "core/core_timing.h"
#include "core/hle/kernel/k_resource_limit.h"
@@ -104,7 +105,7 @@ bool KResourceLimit::Reserve(LimitableResource which, s64 value, s64 timeout) {
ASSERT(current_hints[index] <= current_values[index]);
// If we would overflow, don't allow to succeed.
- if (current_values[index] + value <= current_values[index]) {
+ if (Common::WrappingAdd(current_values[index], value) <= current_values[index]) {
break;
}
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp
index 8c403f5fd..15ae652f9 100644
--- a/src/core/hle/kernel/k_thread.cpp
+++ b/src/core/hle/kernel/k_thread.cpp
@@ -49,6 +49,7 @@ static void ResetThreadContext32(Core::ARM_Interface::ThreadContext32& context,
context.cpu_registers[0] = arg;
context.cpu_registers[15] = entry_point;
context.cpu_registers[13] = stack_top;
+ context.fpscr = 0;
}
static void ResetThreadContext64(Core::ARM_Interface::ThreadContext64& context, VAddr stack_top,
@@ -58,8 +59,8 @@ static void ResetThreadContext64(Core::ARM_Interface::ThreadContext64& context,
context.cpu_registers[18] = Kernel::KSystemControl::GenerateRandomU64() | 1;
context.pc = entry_point;
context.sp = stack_top;
- // TODO(merry): Perform a hardware test to determine the below value.
context.fpcr = 0;
+ context.fpsr = 0;
}
} // namespace
@@ -815,6 +816,27 @@ void KThread::Continue() {
KScheduler::OnThreadStateChanged(kernel, this, old_state);
}
+void KThread::CloneFpuStatus() {
+ // We shouldn't reach here when starting kernel threads.
+ ASSERT(this->GetOwnerProcess() != nullptr);
+ ASSERT(this->GetOwnerProcess() == GetCurrentProcessPointer(kernel));
+
+ if (this->GetOwnerProcess()->Is64BitProcess()) {
+ // Clone FPSR and FPCR.
+ ThreadContext64 cur_ctx{};
+ kernel.System().CurrentArmInterface().SaveContext(cur_ctx);
+
+ this->GetContext64().fpcr = cur_ctx.fpcr;
+ this->GetContext64().fpsr = cur_ctx.fpsr;
+ } else {
+ // Clone FPSCR.
+ ThreadContext32 cur_ctx{};
+ kernel.System().CurrentArmInterface().SaveContext(cur_ctx);
+
+ this->GetContext32().fpscr = cur_ctx.fpscr;
+ }
+}
+
Result KThread::SetActivity(Svc::ThreadActivity activity) {
// Lock ourselves.
KScopedLightLock lk(activity_pause_lock);
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h
index bd125f5f1..9423f08ca 100644
--- a/src/core/hle/kernel/k_thread.h
+++ b/src/core/hle/kernel/k_thread.h
@@ -254,6 +254,8 @@ public:
thread_context_32.tpidr = static_cast<u32>(value);
}
+ void CloneFpuStatus();
+
[[nodiscard]] ThreadContext32& GetContext32() {
return thread_context_32;
}
diff --git a/src/core/hle/kernel/svc/svc_synchronization.cpp b/src/core/hle/kernel/svc/svc_synchronization.cpp
index 1a8f7e191..9e7bf9530 100644
--- a/src/core/hle/kernel/svc/svc_synchronization.cpp
+++ b/src/core/hle/kernel/svc/svc_synchronization.cpp
@@ -48,19 +48,15 @@ Result ResetSignal(Core::System& system, Handle handle) {
return ResultInvalidHandle;
}
-/// Wait for the given handles to synchronize, timeout after the specified nanoseconds
-Result WaitSynchronization(Core::System& system, s32* index, VAddr handles_address, s32 num_handles,
- s64 nano_seconds) {
- LOG_TRACE(Kernel_SVC, "called handles_address=0x{:X}, num_handles={}, nano_seconds={}",
- handles_address, num_handles, nano_seconds);
-
+static Result WaitSynchronization(Core::System& system, int32_t* out_index, const Handle* handles,
+ int32_t num_handles, int64_t timeout_ns) {
// Ensure number of handles is valid.
- R_UNLESS(0 <= num_handles && num_handles <= ArgumentHandleCountMax, ResultOutOfRange);
+ R_UNLESS(0 <= num_handles && num_handles <= Svc::ArgumentHandleCountMax, ResultOutOfRange);
+ // Get the synchronization context.
auto& kernel = system.Kernel();
+ auto& handle_table = GetCurrentProcess(kernel).GetHandleTable();
std::vector<KSynchronizationObject*> objs(num_handles);
- const auto& handle_table = GetCurrentProcess(kernel).GetHandleTable();
- Handle* handles = system.Memory().GetPointer<Handle>(handles_address);
// Copy user handles.
if (num_handles > 0) {
@@ -68,21 +64,38 @@ Result WaitSynchronization(Core::System& system, s32* index, VAddr handles_addre
R_UNLESS(handle_table.GetMultipleObjects<KSynchronizationObject>(objs.data(), handles,
num_handles),
ResultInvalidHandle);
- for (const auto& obj : objs) {
- kernel.RegisterInUseObject(obj);
- }
}
// Ensure handles are closed when we're done.
SCOPE_EXIT({
- for (s32 i = 0; i < num_handles; ++i) {
- kernel.UnregisterInUseObject(objs[i]);
+ for (auto i = 0; i < num_handles; ++i) {
objs[i]->Close();
}
});
- return KSynchronizationObject::Wait(kernel, index, objs.data(), static_cast<s32>(objs.size()),
- nano_seconds);
+ // Wait on the objects.
+ Result res = KSynchronizationObject::Wait(kernel, out_index, objs.data(),
+ static_cast<s32>(objs.size()), timeout_ns);
+
+ R_SUCCEED_IF(res == ResultSessionClosed);
+ R_RETURN(res);
+}
+
+/// Wait for the given handles to synchronize, timeout after the specified nanoseconds
+Result WaitSynchronization(Core::System& system, int32_t* out_index, VAddr user_handles,
+ int32_t num_handles, int64_t timeout_ns) {
+ LOG_TRACE(Kernel_SVC, "called user_handles={:#x}, num_handles={}, timeout_ns={}", user_handles,
+ num_handles, timeout_ns);
+
+ // Ensure number of handles is valid.
+ R_UNLESS(0 <= num_handles && num_handles <= Svc::ArgumentHandleCountMax, ResultOutOfRange);
+
+ std::vector<Handle> handles(num_handles);
+ if (num_handles > 0) {
+ system.Memory().ReadBlock(user_handles, handles.data(), num_handles * sizeof(Handle));
+ }
+
+ R_RETURN(WaitSynchronization(system, out_index, handles.data(), num_handles, timeout_ns));
}
/// Resumes a thread waiting on WaitSynchronization
diff --git a/src/core/hle/kernel/svc/svc_thread.cpp b/src/core/hle/kernel/svc/svc_thread.cpp
index b39807841..9bc1ebe74 100644
--- a/src/core/hle/kernel/svc/svc_thread.cpp
+++ b/src/core/hle/kernel/svc/svc_thread.cpp
@@ -82,6 +82,9 @@ Result CreateThread(Core::System& system, Handle* out_handle, VAddr entry_point,
// Commit the thread reservation.
thread_reservation.Commit();
+ // Clone the current fpu status to the new thread.
+ thread->CloneFpuStatus();
+
// Register the new thread.
KThread::Register(kernel, thread);