summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/arm/arm_interface.h3
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.cpp55
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.h13
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.cpp57
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.h9
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_cp15.h2
-rw-r--r--src/core/arm/dynarmic/arm_exclusive_monitor.h2
-rw-r--r--src/core/hle/kernel/k_class_token.cpp79
-rw-r--r--src/core/hle/kernel/k_client_port.h6
-rw-r--r--src/core/hle/kernel/k_client_session.h4
-rw-r--r--src/core/hle/kernel/k_event.h14
-rw-r--r--src/core/hle/kernel/k_port.h3
-rw-r--r--src/core/hle/kernel/k_process.h8
-rw-r--r--src/core/hle/kernel/k_readable_event.h4
-rw-r--r--src/core/hle/kernel/k_resource_limit.h4
-rw-r--r--src/core/hle/kernel/k_scheduler.cpp1
-rw-r--r--src/core/hle/kernel/k_server_port.h12
-rw-r--r--src/core/hle/kernel/k_server_session.h6
-rw-r--r--src/core/hle/kernel/k_session.h10
-rw-r--r--src/core/hle/kernel/k_shared_memory.h4
-rw-r--r--src/core/hle/kernel/k_slab_heap.h199
-rw-r--r--src/core/hle/kernel/k_synchronization_object.h4
-rw-r--r--src/core/hle/kernel/k_thread.cpp10
-rw-r--r--src/core/hle/kernel/k_thread.h10
-rw-r--r--src/core/hle/kernel/k_transfer_memory.h10
-rw-r--r--src/core/hle/kernel/k_writable_event.h2
-rw-r--r--src/core/hle/kernel/kernel.cpp5
-rw-r--r--src/core/hle/service/am/applets/software_keyboard.cpp25
-rw-r--r--src/core/hle/service/hid/controllers/gesture.h36
-rw-r--r--src/core/hle/service/hid/controllers/touchscreen.cpp13
-rw-r--r--src/core/hle/service/hid/controllers/touchscreen.h7
-rw-r--r--src/core/hle/service/hid/hid.cpp11
-rw-r--r--src/core/hle/service/ldn/ldn.cpp141
-rw-r--r--src/core/memory.cpp43
34 files changed, 587 insertions, 225 deletions
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h
index 77094b48f..689e3ceb5 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -65,9 +65,6 @@ public:
/// Step CPU by one instruction
virtual void Step() = 0;
- /// Exits execution from a callback, the callback must rewind the stack
- virtual void ExceptionalExit() = 0;
-
/// Clear all instruction cache
virtual void ClearInstructionCache() = 0;
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
index e401fa825..cea7f0fb1 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
@@ -4,9 +4,9 @@
#include <cinttypes>
#include <memory>
-#include <dynarmic/A32/a32.h>
-#include <dynarmic/A32/config.h>
-#include <dynarmic/A32/context.h>
+#include <dynarmic/interface/A32/a32.h>
+#include <dynarmic/interface/A32/config.h>
+#include <dynarmic/interface/A32/context.h>
#include "common/assert.h"
#include "common/logging/log.h"
#include "common/page_table.h"
@@ -24,45 +24,46 @@ namespace Core {
class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks {
public:
- explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent_) : parent{parent_} {}
+ explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent_)
+ : parent{parent_}, memory(parent.system.Memory()) {}
u8 MemoryRead8(u32 vaddr) override {
- return parent.system.Memory().Read8(vaddr);
+ return memory.Read8(vaddr);
}
u16 MemoryRead16(u32 vaddr) override {
- return parent.system.Memory().Read16(vaddr);
+ return memory.Read16(vaddr);
}
u32 MemoryRead32(u32 vaddr) override {
- return parent.system.Memory().Read32(vaddr);
+ return memory.Read32(vaddr);
}
u64 MemoryRead64(u32 vaddr) override {
- return parent.system.Memory().Read64(vaddr);
+ return memory.Read64(vaddr);
}
void MemoryWrite8(u32 vaddr, u8 value) override {
- parent.system.Memory().Write8(vaddr, value);
+ memory.Write8(vaddr, value);
}
void MemoryWrite16(u32 vaddr, u16 value) override {
- parent.system.Memory().Write16(vaddr, value);
+ memory.Write16(vaddr, value);
}
void MemoryWrite32(u32 vaddr, u32 value) override {
- parent.system.Memory().Write32(vaddr, value);
+ memory.Write32(vaddr, value);
}
void MemoryWrite64(u32 vaddr, u64 value) override {
- parent.system.Memory().Write64(vaddr, value);
+ memory.Write64(vaddr, value);
}
bool MemoryWriteExclusive8(u32 vaddr, u8 value, u8 expected) override {
- return parent.system.Memory().WriteExclusive8(vaddr, value, expected);
+ return memory.WriteExclusive8(vaddr, value, expected);
}
bool MemoryWriteExclusive16(u32 vaddr, u16 value, u16 expected) override {
- return parent.system.Memory().WriteExclusive16(vaddr, value, expected);
+ return memory.WriteExclusive16(vaddr, value, expected);
}
bool MemoryWriteExclusive32(u32 vaddr, u32 value, u32 expected) override {
- return parent.system.Memory().WriteExclusive32(vaddr, value, expected);
+ return memory.WriteExclusive32(vaddr, value, expected);
}
bool MemoryWriteExclusive64(u32 vaddr, u64 value, u64 expected) override {
- return parent.system.Memory().WriteExclusive64(vaddr, value, expected);
+ return memory.WriteExclusive64(vaddr, value, expected);
}
void InterpreterFallback(u32 pc, std::size_t num_instructions) override {
@@ -78,7 +79,9 @@ public:
}
void CallSVC(u32 swi) override {
- Kernel::Svc::Call(parent.system, swi);
+ parent.svc_called = true;
+ parent.svc_swi = swi;
+ parent.jit->HaltExecution();
}
void AddTicks(u64 ticks) override {
@@ -110,6 +113,7 @@ public:
}
ARM_Dynarmic_32& parent;
+ Core::Memory::Memory& memory;
std::size_t num_interpreted_instructions{};
static constexpr u64 minimum_run_cycles = 1000U;
};
@@ -187,11 +191,17 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*
}
void ARM_Dynarmic_32::Run() {
- jit->Run();
-}
-
-void ARM_Dynarmic_32::ExceptionalExit() {
- jit->ExceptionalExit();
+ while (true) {
+ jit->Run();
+ if (!svc_called) {
+ break;
+ }
+ svc_called = false;
+ Kernel::Svc::Call(system, svc_swi);
+ if (shutdown) {
+ break;
+ }
+ }
}
void ARM_Dynarmic_32::Step() {
@@ -275,6 +285,7 @@ void ARM_Dynarmic_32::LoadContext(const ThreadContext32& ctx) {
void ARM_Dynarmic_32::PrepareReschedule() {
jit->HaltExecution();
+ shutdown = true;
}
void ARM_Dynarmic_32::ClearInstructionCache() {
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.h b/src/core/arm/dynarmic/arm_dynarmic_32.h
index b882b0c59..063605b46 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.h
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.h
@@ -7,9 +7,9 @@
#include <memory>
#include <unordered_map>
-#include <dynarmic/A32/a32.h>
-#include <dynarmic/A64/a64.h>
-#include <dynarmic/exclusive_monitor.h>
+#include <dynarmic/interface/A32/a32.h>
+#include <dynarmic/interface/A64/a64.h>
+#include <dynarmic/interface/exclusive_monitor.h>
#include "common/common_types.h"
#include "common/hash.h"
#include "core/arm/arm_interface.h"
@@ -42,7 +42,6 @@ public:
u32 GetPSTATE() const override;
void SetPSTATE(u32 pstate) override;
void Run() override;
- void ExceptionalExit() override;
void Step() override;
VAddr GetTlsAddress() const override;
void SetTlsAddress(VAddr address) override;
@@ -82,6 +81,12 @@ private:
std::size_t core_index;
DynarmicExclusiveMonitor& exclusive_monitor;
std::shared_ptr<Dynarmic::A32::Jit> jit;
+
+ // SVC callback
+ u32 svc_swi{};
+ bool svc_called{};
+
+ bool shutdown{};
};
} // namespace Core
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
index 157051d69..63193dcb1 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
@@ -4,8 +4,8 @@
#include <cinttypes>
#include <memory>
-#include <dynarmic/A64/a64.h>
-#include <dynarmic/A64/config.h>
+#include <dynarmic/interface/A64/a64.h>
+#include <dynarmic/interface/A64/config.h>
#include "common/assert.h"
#include "common/logging/log.h"
#include "common/page_table.h"
@@ -27,57 +27,56 @@ using Vector = Dynarmic::A64::Vector;
class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks {
public:
- explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent_) : parent{parent_} {}
+ explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent_)
+ : parent{parent_}, memory(parent.system.Memory()) {}
u8 MemoryRead8(u64 vaddr) override {
- return parent.system.Memory().Read8(vaddr);
+ return memory.Read8(vaddr);
}
u16 MemoryRead16(u64 vaddr) override {
- return parent.system.Memory().Read16(vaddr);
+ return memory.Read16(vaddr);
}
u32 MemoryRead32(u64 vaddr) override {
- return parent.system.Memory().Read32(vaddr);
+ return memory.Read32(vaddr);
}
u64 MemoryRead64(u64 vaddr) override {
- return parent.system.Memory().Read64(vaddr);
+ return memory.Read64(vaddr);
}
Vector MemoryRead128(u64 vaddr) override {
- auto& memory = parent.system.Memory();
return {memory.Read64(vaddr), memory.Read64(vaddr + 8)};
}
void MemoryWrite8(u64 vaddr, u8 value) override {
- parent.system.Memory().Write8(vaddr, value);
+ memory.Write8(vaddr, value);
}
void MemoryWrite16(u64 vaddr, u16 value) override {
- parent.system.Memory().Write16(vaddr, value);
+ memory.Write16(vaddr, value);
}
void MemoryWrite32(u64 vaddr, u32 value) override {
- parent.system.Memory().Write32(vaddr, value);
+ memory.Write32(vaddr, value);
}
void MemoryWrite64(u64 vaddr, u64 value) override {
- parent.system.Memory().Write64(vaddr, value);
+ memory.Write64(vaddr, value);
}
void MemoryWrite128(u64 vaddr, Vector value) override {
- auto& memory = parent.system.Memory();
memory.Write64(vaddr, value[0]);
memory.Write64(vaddr + 8, value[1]);
}
bool MemoryWriteExclusive8(u64 vaddr, std::uint8_t value, std::uint8_t expected) override {
- return parent.system.Memory().WriteExclusive8(vaddr, value, expected);
+ return memory.WriteExclusive8(vaddr, value, expected);
}
bool MemoryWriteExclusive16(u64 vaddr, std::uint16_t value, std::uint16_t expected) override {
- return parent.system.Memory().WriteExclusive16(vaddr, value, expected);
+ return memory.WriteExclusive16(vaddr, value, expected);
}
bool MemoryWriteExclusive32(u64 vaddr, std::uint32_t value, std::uint32_t expected) override {
- return parent.system.Memory().WriteExclusive32(vaddr, value, expected);
+ return memory.WriteExclusive32(vaddr, value, expected);
}
bool MemoryWriteExclusive64(u64 vaddr, std::uint64_t value, std::uint64_t expected) override {
- return parent.system.Memory().WriteExclusive64(vaddr, value, expected);
+ return memory.WriteExclusive64(vaddr, value, expected);
}
bool MemoryWriteExclusive128(u64 vaddr, Vector value, Vector expected) override {
- return parent.system.Memory().WriteExclusive128(vaddr, value, expected);
+ return memory.WriteExclusive128(vaddr, value, expected);
}
void InterpreterFallback(u64 pc, std::size_t num_instructions) override {
@@ -102,7 +101,9 @@ public:
}
void CallSVC(u32 swi) override {
- Kernel::Svc::Call(parent.system, swi);
+ parent.svc_called = true;
+ parent.svc_swi = swi;
+ parent.jit->HaltExecution();
}
void AddTicks(u64 ticks) override {
@@ -137,6 +138,7 @@ public:
}
ARM_Dynarmic_64& parent;
+ Core::Memory::Memory& memory;
u64 tpidrro_el0 = 0;
u64 tpidr_el0 = 0;
static constexpr u64 minimum_run_cycles = 1000U;
@@ -227,11 +229,17 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable*
}
void ARM_Dynarmic_64::Run() {
- jit->Run();
-}
-
-void ARM_Dynarmic_64::ExceptionalExit() {
- jit->ExceptionalExit();
+ while (true) {
+ jit->Run();
+ if (!svc_called) {
+ break;
+ }
+ svc_called = false;
+ Kernel::Svc::Call(system, svc_swi);
+ if (shutdown) {
+ break;
+ }
+ }
}
void ARM_Dynarmic_64::Step() {
@@ -320,6 +328,7 @@ void ARM_Dynarmic_64::LoadContext(const ThreadContext64& ctx) {
void ARM_Dynarmic_64::PrepareReschedule() {
jit->HaltExecution();
+ shutdown = true;
}
void ARM_Dynarmic_64::ClearInstructionCache() {
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.h b/src/core/arm/dynarmic/arm_dynarmic_64.h
index 92f715f19..0c4e46c64 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.h
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.h
@@ -7,7 +7,7 @@
#include <memory>
#include <unordered_map>
-#include <dynarmic/A64/a64.h>
+#include <dynarmic/interface/A64/a64.h>
#include "common/common_types.h"
#include "common/hash.h"
#include "core/arm/arm_interface.h"
@@ -40,7 +40,6 @@ public:
void SetPSTATE(u32 pstate) override;
void Run() override;
void Step() override;
- void ExceptionalExit() override;
VAddr GetTlsAddress() const override;
void SetTlsAddress(VAddr address) override;
void SetTPIDR_EL0(u64 value) override;
@@ -75,6 +74,12 @@ private:
DynarmicExclusiveMonitor& exclusive_monitor;
std::shared_ptr<Dynarmic::A64::Jit> jit;
+
+ // SVC callback
+ u32 svc_swi{};
+ bool svc_called{};
+
+ bool shutdown{};
};
} // namespace Core
diff --git a/src/core/arm/dynarmic/arm_dynarmic_cp15.h b/src/core/arm/dynarmic/arm_dynarmic_cp15.h
index 8597beddf..7c7ede79e 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_cp15.h
+++ b/src/core/arm/dynarmic/arm_dynarmic_cp15.h
@@ -7,7 +7,7 @@
#include <memory>
#include <optional>
-#include <dynarmic/A32/coprocessor.h>
+#include <dynarmic/interface/A32/coprocessor.h>
#include "common/common_types.h"
namespace Core {
diff --git a/src/core/arm/dynarmic/arm_exclusive_monitor.h b/src/core/arm/dynarmic/arm_exclusive_monitor.h
index f9f056a59..73d41f223 100644
--- a/src/core/arm/dynarmic/arm_exclusive_monitor.h
+++ b/src/core/arm/dynarmic/arm_exclusive_monitor.h
@@ -7,7 +7,7 @@
#include <memory>
#include <unordered_map>
-#include <dynarmic/exclusive_monitor.h>
+#include <dynarmic/interface/exclusive_monitor.h>
#include "common/common_types.h"
#include "core/arm/dynarmic/arm_dynarmic_32.h"
diff --git a/src/core/hle/kernel/k_class_token.cpp b/src/core/hle/kernel/k_class_token.cpp
index beb8a2a05..0be0027be 100644
--- a/src/core/hle/kernel/k_class_token.cpp
+++ b/src/core/hle/kernel/k_class_token.cpp
@@ -84,50 +84,43 @@ static_assert(ClassToken<KTransferMemory> == ((0b10010001 << 8) | ClassToken<KAu
// Ensure that the token hierarchy reflects the class hierarchy.
// Base classes.
-static_assert(!std::is_final<KSynchronizationObject>::value &&
- std::is_base_of<KAutoObject, KSynchronizationObject>::value);
-static_assert(!std::is_final<KReadableEvent>::value &&
- std::is_base_of<KSynchronizationObject, KReadableEvent>::value);
+static_assert(!std::is_final_v<KSynchronizationObject> &&
+ std::is_base_of_v<KAutoObject, KSynchronizationObject>);
+static_assert(!std::is_final_v<KReadableEvent> &&
+ std::is_base_of_v<KSynchronizationObject, KReadableEvent>);
// Final classes
-// static_assert(std::is_final<KInterruptEvent>::value &&
-// std::is_base_of<KReadableEvent, KInterruptEvent>::value);
-// static_assert(std::is_final<KDebug>::value &&
-// std::is_base_of<KSynchronizationObject, KDebug>::value);
-static_assert(std::is_final<KThread>::value &&
- std::is_base_of<KSynchronizationObject, KThread>::value);
-static_assert(std::is_final<KServerPort>::value &&
- std::is_base_of<KSynchronizationObject, KServerPort>::value);
-static_assert(std::is_final<KServerSession>::value &&
- std::is_base_of<KSynchronizationObject, KServerSession>::value);
-static_assert(std::is_final<KClientPort>::value &&
- std::is_base_of<KSynchronizationObject, KClientPort>::value);
-static_assert(std::is_final<KClientSession>::value &&
- std::is_base_of<KAutoObject, KClientSession>::value);
-static_assert(std::is_final<KProcess>::value &&
- std::is_base_of<KSynchronizationObject, KProcess>::value);
-static_assert(std::is_final<KResourceLimit>::value &&
- std::is_base_of<KAutoObject, KResourceLimit>::value);
-// static_assert(std::is_final<KLightSession>::value &&
-// std::is_base_of<KAutoObject, KLightSession>::value);
-static_assert(std::is_final<KPort>::value && std::is_base_of<KAutoObject, KPort>::value);
-static_assert(std::is_final<KSession>::value && std::is_base_of<KAutoObject, KSession>::value);
-static_assert(std::is_final<KSharedMemory>::value &&
- std::is_base_of<KAutoObject, KSharedMemory>::value);
-static_assert(std::is_final<KEvent>::value && std::is_base_of<KAutoObject, KEvent>::value);
-static_assert(std::is_final<KWritableEvent>::value &&
- std::is_base_of<KAutoObject, KWritableEvent>::value);
-// static_assert(std::is_final<KLightClientSession>::value &&
-// std::is_base_of<KAutoObject, KLightClientSession>::value);
-// static_assert(std::is_final<KLightServerSession>::value &&
-// std::is_base_of<KAutoObject, KLightServerSession>::value);
-static_assert(std::is_final<KTransferMemory>::value &&
- std::is_base_of<KAutoObject, KTransferMemory>::value);
-// static_assert(std::is_final<KDeviceAddressSpace>::value &&
-// std::is_base_of<KAutoObject, KDeviceAddressSpace>::value);
-// static_assert(std::is_final<KSessionRequest>::value &&
-// std::is_base_of<KAutoObject, KSessionRequest>::value);
-// static_assert(std::is_final<KCodeMemory>::value &&
-// std::is_base_of<KAutoObject, KCodeMemory>::value);
+// static_assert(std::is_final_v<KInterruptEvent> &&
+// std::is_base_of_v<KReadableEvent, KInterruptEvent>);
+// static_assert(std::is_final_v<KDebug> &&
+// std::is_base_of_v<KSynchronizationObject, KDebug>);
+static_assert(std::is_final_v<KThread> && std::is_base_of_v<KSynchronizationObject, KThread>);
+static_assert(std::is_final_v<KServerPort> &&
+ std::is_base_of_v<KSynchronizationObject, KServerPort>);
+static_assert(std::is_final_v<KServerSession> &&
+ std::is_base_of_v<KSynchronizationObject, KServerSession>);
+static_assert(std::is_final_v<KClientPort> &&
+ std::is_base_of_v<KSynchronizationObject, KClientPort>);
+static_assert(std::is_final_v<KClientSession> && std::is_base_of_v<KAutoObject, KClientSession>);
+static_assert(std::is_final_v<KProcess> && std::is_base_of_v<KSynchronizationObject, KProcess>);
+static_assert(std::is_final_v<KResourceLimit> && std::is_base_of_v<KAutoObject, KResourceLimit>);
+// static_assert(std::is_final_v<KLightSession> &&
+// std::is_base_of_v<KAutoObject, KLightSession>);
+static_assert(std::is_final_v<KPort> && std::is_base_of_v<KAutoObject, KPort>);
+static_assert(std::is_final_v<KSession> && std::is_base_of_v<KAutoObject, KSession>);
+static_assert(std::is_final_v<KSharedMemory> && std::is_base_of_v<KAutoObject, KSharedMemory>);
+static_assert(std::is_final_v<KEvent> && std::is_base_of_v<KAutoObject, KEvent>);
+static_assert(std::is_final_v<KWritableEvent> && std::is_base_of_v<KAutoObject, KWritableEvent>);
+// static_assert(std::is_final_v<KLightClientSession> &&
+// std::is_base_of_v<KAutoObject, KLightClientSession>);
+// static_assert(std::is_final_v<KLightServerSession> &&
+// std::is_base_of_v<KAutoObject, KLightServerSession>);
+static_assert(std::is_final_v<KTransferMemory> && std::is_base_of_v<KAutoObject, KTransferMemory>);
+// static_assert(std::is_final_v<KDeviceAddressSpace> &&
+// std::is_base_of_v<KAutoObject, KDeviceAddressSpace>);
+// static_assert(std::is_final_v<KSessionRequest> &&
+// std::is_base_of_v<KAutoObject, KSessionRequest>);
+// static_assert(std::is_final_v<KCodeMemory> &&
+// std::is_base_of_v<KAutoObject, KCodeMemory>);
} // namespace Kernel
diff --git a/src/core/hle/kernel/k_client_port.h b/src/core/hle/kernel/k_client_port.h
index 8501156e8..f2fff3b01 100644
--- a/src/core/hle/kernel/k_client_port.h
+++ b/src/core/hle/kernel/k_client_port.h
@@ -22,7 +22,7 @@ class KClientPort final : public KSynchronizationObject {
public:
explicit KClientPort(KernelCore& kernel_);
- virtual ~KClientPort() override;
+ ~KClientPort() override;
void Initialize(KPort* parent_, s32 max_sessions_, std::string&& name_);
void OnSessionFinalized();
@@ -49,8 +49,8 @@ public:
bool IsServerClosed() const;
// Overridden virtual functions.
- virtual void Destroy() override;
- virtual bool IsSignaled() const override;
+ void Destroy() override;
+ bool IsSignaled() const override;
ResultCode CreateSession(KClientSession** out);
diff --git a/src/core/hle/kernel/k_client_session.h b/src/core/hle/kernel/k_client_session.h
index 720a8c243..b11d5b4e3 100644
--- a/src/core/hle/kernel/k_client_session.h
+++ b/src/core/hle/kernel/k_client_session.h
@@ -34,7 +34,7 @@ class KClientSession final
public:
explicit KClientSession(KernelCore& kernel_);
- virtual ~KClientSession();
+ ~KClientSession() override;
void Initialize(KSession* parent_, std::string&& name_) {
// Set member variables.
@@ -42,7 +42,7 @@ public:
name = std::move(name_);
}
- virtual void Destroy() override;
+ void Destroy() override;
static void PostDestroy([[maybe_unused]] uintptr_t arg) {}
KSession* GetParent() const {
diff --git a/src/core/hle/kernel/k_event.h b/src/core/hle/kernel/k_event.h
index 9a59ffb70..3d3ec99e2 100644
--- a/src/core/hle/kernel/k_event.h
+++ b/src/core/hle/kernel/k_event.h
@@ -20,23 +20,21 @@ class KEvent final : public KAutoObjectWithSlabHeapAndContainer<KEvent, KAutoObj
public:
explicit KEvent(KernelCore& kernel_);
- virtual ~KEvent();
+ ~KEvent() override;
void Initialize(std::string&& name);
- virtual void Finalize() override;
+ void Finalize() override;
- virtual bool IsInitialized() const override {
+ bool IsInitialized() const override {
return initialized;
}
- virtual uintptr_t GetPostDestroyArgument() const override {
+ uintptr_t GetPostDestroyArgument() const override {
return reinterpret_cast<uintptr_t>(owner);
}
- static void PostDestroy(uintptr_t arg);
-
- virtual KProcess* GetOwner() const override {
+ KProcess* GetOwner() const override {
return owner;
}
@@ -48,6 +46,8 @@ public:
return writable_event;
}
+ static void PostDestroy(uintptr_t arg);
+
private:
KReadableEvent readable_event;
KWritableEvent writable_event;
diff --git a/src/core/hle/kernel/k_port.h b/src/core/hle/kernel/k_port.h
index 960f1f3a3..4018ea2df 100644
--- a/src/core/hle/kernel/k_port.h
+++ b/src/core/hle/kernel/k_port.h
@@ -22,7 +22,7 @@ class KPort final : public KAutoObjectWithSlabHeapAndContainer<KPort, KAutoObjec
public:
explicit KPort(KernelCore& kernel_);
- virtual ~KPort();
+ ~KPort() override;
static void PostDestroy([[maybe_unused]] uintptr_t arg) {}
@@ -59,7 +59,6 @@ private:
ServerClosed = 3,
};
-private:
KServerPort server;
KClientPort client;
State state{State::Invalid};
diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h
index 123d71cd3..c0656b9af 100644
--- a/src/core/hle/kernel/k_process.h
+++ b/src/core/hle/kernel/k_process.h
@@ -331,19 +331,19 @@ public:
void LoadModule(CodeSet code_set, VAddr base_addr);
- virtual bool IsInitialized() const override {
+ bool IsInitialized() const override {
return is_initialized;
}
static void PostDestroy([[maybe_unused]] uintptr_t arg) {}
- virtual void Finalize();
+ void Finalize() override;
- virtual u64 GetId() const override final {
+ u64 GetId() const override {
return GetProcessID();
}
- virtual bool IsSignaled() const override;
+ bool IsSignaled() const override;
void PinCurrentThread();
void UnpinCurrentThread();
diff --git a/src/core/hle/kernel/k_readable_event.h b/src/core/hle/kernel/k_readable_event.h
index 33cd1dd3e..b2850ac7b 100644
--- a/src/core/hle/kernel/k_readable_event.h
+++ b/src/core/hle/kernel/k_readable_event.h
@@ -31,8 +31,8 @@ public:
return parent;
}
- virtual bool IsSignaled() const override;
- virtual void Destroy() override;
+ bool IsSignaled() const override;
+ void Destroy() override;
ResultCode Signal();
ResultCode Clear();
diff --git a/src/core/hle/kernel/k_resource_limit.h b/src/core/hle/kernel/k_resource_limit.h
index 0debbbb51..fab6005ff 100644
--- a/src/core/hle/kernel/k_resource_limit.h
+++ b/src/core/hle/kernel/k_resource_limit.h
@@ -37,10 +37,10 @@ class KResourceLimit final
public:
explicit KResourceLimit(KernelCore& kernel_);
- virtual ~KResourceLimit();
+ ~KResourceLimit() override;
void Initialize(const Core::Timing::CoreTiming* core_timing_);
- virtual void Finalize() override;
+ void Finalize() override;
s64 GetLimitValue(LimitableResource which) const;
s64 GetCurrentValue(LimitableResource which) const;
diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp
index 2f82fbcd6..6a7d80d03 100644
--- a/src/core/hle/kernel/k_scheduler.cpp
+++ b/src/core/hle/kernel/k_scheduler.cpp
@@ -659,7 +659,6 @@ void KScheduler::Unload(KThread* thread) {
if (thread) {
if (thread->IsCallingSvc()) {
- system.ArmInterface(core_id).ExceptionalExit();
thread->ClearIsCallingSvc();
}
if (!thread->IsTerminationRequested()) {
diff --git a/src/core/hle/kernel/k_server_port.h b/src/core/hle/kernel/k_server_port.h
index d1a757ec3..55481d63f 100644
--- a/src/core/hle/kernel/k_server_port.h
+++ b/src/core/hle/kernel/k_server_port.h
@@ -25,12 +25,9 @@ class SessionRequestHandler;
class KServerPort final : public KSynchronizationObject {
KERNEL_AUTOOBJECT_TRAITS(KServerPort, KSynchronizationObject);
-private:
- using SessionList = boost::intrusive::list<KServerSession>;
-
public:
explicit KServerPort(KernelCore& kernel_);
- virtual ~KServerPort() override;
+ ~KServerPort() override;
void Initialize(KPort* parent_, std::string&& name_);
@@ -63,13 +60,14 @@ public:
bool IsLight() const;
// Overridden virtual functions.
- virtual void Destroy() override;
- virtual bool IsSignaled() const override;
+ void Destroy() override;
+ bool IsSignaled() const override;
private:
+ using SessionList = boost::intrusive::list<KServerSession>;
+
void CleanupSessions();
-private:
SessionList session_list;
SessionRequestHandlerPtr session_handler;
KPort* parent{};
diff --git a/src/core/hle/kernel/k_server_session.h b/src/core/hle/kernel/k_server_session.h
index dd4de2904..27b757ad2 100644
--- a/src/core/hle/kernel/k_server_session.h
+++ b/src/core/hle/kernel/k_server_session.h
@@ -42,9 +42,9 @@ class KServerSession final : public KSynchronizationObject,
public:
explicit KServerSession(KernelCore& kernel_);
- virtual ~KServerSession() override;
+ ~KServerSession() override;
- virtual void Destroy() override;
+ void Destroy() override;
void Initialize(KSession* parent_, std::string&& name_);
@@ -56,7 +56,7 @@ public:
return parent;
}
- virtual bool IsSignaled() const override;
+ bool IsSignaled() const override;
void OnClientClosed();
diff --git a/src/core/hle/kernel/k_session.h b/src/core/hle/kernel/k_session.h
index a981fd1f6..4ddd080d2 100644
--- a/src/core/hle/kernel/k_session.h
+++ b/src/core/hle/kernel/k_session.h
@@ -18,17 +18,17 @@ class KSession final : public KAutoObjectWithSlabHeapAndContainer<KSession, KAut
public:
explicit KSession(KernelCore& kernel_);
- virtual ~KSession() override;
+ ~KSession() override;
void Initialize(KClientPort* port_, const std::string& name_);
- virtual void Finalize() override;
+ void Finalize() override;
- virtual bool IsInitialized() const override {
+ bool IsInitialized() const override {
return initialized;
}
- virtual uintptr_t GetPostDestroyArgument() const override {
+ uintptr_t GetPostDestroyArgument() const override {
return reinterpret_cast<uintptr_t>(process);
}
@@ -78,7 +78,6 @@ private:
ServerClosed = 3,
};
-private:
void SetState(State state) {
atomic_state = static_cast<u8>(state);
}
@@ -87,7 +86,6 @@ private:
return static_cast<State>(atomic_state.load(std::memory_order_relaxed));
}
-private:
KServerSession server;
KClientSession client;
std::atomic<std::underlying_type_t<State>> atomic_state{
diff --git a/src/core/hle/kernel/k_shared_memory.h b/src/core/hle/kernel/k_shared_memory.h
index 553a56327..e9815f90b 100644
--- a/src/core/hle/kernel/k_shared_memory.h
+++ b/src/core/hle/kernel/k_shared_memory.h
@@ -68,9 +68,9 @@ public:
return device_memory->GetPointer(physical_address + offset);
}
- virtual void Finalize() override;
+ void Finalize() override;
- virtual bool IsInitialized() const override {
+ bool IsInitialized() const override {
return is_initialized;
}
static void PostDestroy([[maybe_unused]] uintptr_t arg) {}
diff --git a/src/core/hle/kernel/k_slab_heap.h b/src/core/hle/kernel/k_slab_heap.h
index 81d472a3e..0ad74b0a0 100644
--- a/src/core/hle/kernel/k_slab_heap.h
+++ b/src/core/hle/kernel/k_slab_heap.h
@@ -4,34 +4,213 @@
#pragma once
+#include <atomic>
+
+#include "common/assert.h"
+#include "common/common_types.h"
+
namespace Kernel {
class KernelCore;
-/// This is a placeholder class to manage slab heaps for kernel objects. For now, we just allocate
-/// these with new/delete, but this can be re-implemented later to allocate these in emulated
-/// memory.
+namespace impl {
+
+class KSlabHeapImpl final : NonCopyable {
+public:
+ struct Node {
+ Node* next{};
+ };
+
+ constexpr KSlabHeapImpl() = default;
+
+ void Initialize(std::size_t size) {
+ ASSERT(head == nullptr);
+ obj_size = size;
+ }
+
+ constexpr std::size_t GetObjectSize() const {
+ return obj_size;
+ }
+
+ Node* GetHead() const {
+ return head;
+ }
+
+ void* Allocate() {
+ Node* ret = head.load();
+
+ do {
+ if (ret == nullptr) {
+ break;
+ }
+ } while (!head.compare_exchange_weak(ret, ret->next));
+
+ return ret;
+ }
+
+ void Free(void* obj) {
+ Node* node = static_cast<Node*>(obj);
+
+ Node* cur_head = head.load();
+ do {
+ node->next = cur_head;
+ } while (!head.compare_exchange_weak(cur_head, node));
+ }
+
+private:
+ std::atomic<Node*> head{};
+ std::size_t obj_size{};
+};
+
+} // namespace impl
+
+class KSlabHeapBase : NonCopyable {
+public:
+ constexpr KSlabHeapBase() = default;
+
+ constexpr bool Contains(uintptr_t addr) const {
+ return start <= addr && addr < end;
+ }
+
+ constexpr std::size_t GetSlabHeapSize() const {
+ return (end - start) / GetObjectSize();
+ }
+
+ constexpr std::size_t GetObjectSize() const {
+ return impl.GetObjectSize();
+ }
+
+ constexpr uintptr_t GetSlabHeapAddress() const {
+ return start;
+ }
+
+ std::size_t GetObjectIndexImpl(const void* obj) const {
+ return (reinterpret_cast<uintptr_t>(obj) - start) / GetObjectSize();
+ }
+
+ std::size_t GetPeakIndex() const {
+ return GetObjectIndexImpl(reinterpret_cast<const void*>(peak));
+ }
+
+ void* AllocateImpl() {
+ return impl.Allocate();
+ }
+
+ void FreeImpl(void* obj) {
+ // Don't allow freeing an object that wasn't allocated from this heap
+ ASSERT(Contains(reinterpret_cast<uintptr_t>(obj)));
+
+ impl.Free(obj);
+ }
+
+ void InitializeImpl(std::size_t obj_size, void* memory, std::size_t memory_size) {
+ // Ensure we don't initialize a slab using null memory
+ ASSERT(memory != nullptr);
+
+ // Initialize the base allocator
+ impl.Initialize(obj_size);
+
+ // Set our tracking variables
+ const std::size_t num_obj = (memory_size / obj_size);
+ start = reinterpret_cast<uintptr_t>(memory);
+ end = start + num_obj * obj_size;
+ peak = start;
+
+ // Free the objects
+ u8* cur = reinterpret_cast<u8*>(end);
+
+ for (std::size_t i{}; i < num_obj; i++) {
+ cur -= obj_size;
+ impl.Free(cur);
+ }
+ }
+
+private:
+ using Impl = impl::KSlabHeapImpl;
+
+ Impl impl;
+ uintptr_t peak{};
+ uintptr_t start{};
+ uintptr_t end{};
+};
template <typename T>
-class KSlabHeap final : NonCopyable {
+class KSlabHeap final : public KSlabHeapBase {
public:
- KSlabHeap() = default;
+ enum class AllocationType {
+ Host,
+ Guest,
+ };
- void Initialize([[maybe_unused]] void* memory, [[maybe_unused]] std::size_t memory_size) {
- // Placeholder that should initialize the backing slab heap implementation.
+ explicit constexpr KSlabHeap(AllocationType allocation_type_ = AllocationType::Host)
+ : KSlabHeapBase(), allocation_type{allocation_type_} {}
+
+ void Initialize(void* memory, std::size_t memory_size) {
+ if (allocation_type == AllocationType::Guest) {
+ InitializeImpl(sizeof(T), memory, memory_size);
+ }
}
T* Allocate() {
- return new T();
+ switch (allocation_type) {
+ case AllocationType::Host:
+ // Fallback for cases where we do not yet support allocating guest memory from the slab
+ // heap, such as for kernel memory regions.
+ return new T;
+
+ case AllocationType::Guest:
+ T* obj = static_cast<T*>(AllocateImpl());
+ if (obj != nullptr) {
+ new (obj) T();
+ }
+ return obj;
+ }
+
+ UNREACHABLE_MSG("Invalid AllocationType {}", allocation_type);
+ return nullptr;
}
T* AllocateWithKernel(KernelCore& kernel) {
- return new T(kernel);
+ switch (allocation_type) {
+ case AllocationType::Host:
+ // Fallback for cases where we do not yet support allocating guest memory from the slab
+ // heap, such as for kernel memory regions.
+ return new T(kernel);
+
+ case AllocationType::Guest:
+ T* obj = static_cast<T*>(AllocateImpl());
+ if (obj != nullptr) {
+ new (obj) T(kernel);
+ }
+ return obj;
+ }
+
+ UNREACHABLE_MSG("Invalid AllocationType {}", allocation_type);
+ return nullptr;
}
void Free(T* obj) {
- delete obj;
+ switch (allocation_type) {
+ case AllocationType::Host:
+ // Fallback for cases where we do not yet support allocating guest memory from the slab
+ // heap, such as for kernel memory regions.
+ delete obj;
+ return;
+
+ case AllocationType::Guest:
+ FreeImpl(obj);
+ return;
+ }
+
+ UNREACHABLE_MSG("Invalid AllocationType {}", allocation_type);
}
+
+ constexpr std::size_t GetObjectIndex(const T* obj) const {
+ return GetObjectIndexImpl(obj);
+ }
+
+private:
+ const AllocationType allocation_type;
};
} // namespace Kernel
diff --git a/src/core/hle/kernel/k_synchronization_object.h b/src/core/hle/kernel/k_synchronization_object.h
index a41dd1220..3d4ce1fbc 100644
--- a/src/core/hle/kernel/k_synchronization_object.h
+++ b/src/core/hle/kernel/k_synchronization_object.h
@@ -29,7 +29,7 @@ public:
KSynchronizationObject** objects, const s32 num_objects,
s64 timeout);
- virtual void Finalize() override;
+ void Finalize() override;
[[nodiscard]] virtual bool IsSignaled() const = 0;
@@ -37,7 +37,7 @@ public:
protected:
explicit KSynchronizationObject(KernelCore& kernel);
- virtual ~KSynchronizationObject();
+ ~KSynchronizationObject() override;
virtual void OnFinalizeSynchronizationObject() {}
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp
index e3f08f256..3cf43d290 100644
--- a/src/core/hle/kernel/k_thread.cpp
+++ b/src/core/hle/kernel/k_thread.cpp
@@ -168,13 +168,13 @@ ResultCode KThread::Initialize(KThreadFunction func, uintptr_t arg, VAddr user_s
std::memset(static_cast<void*>(std::addressof(GetStackParameters())), 0,
sizeof(StackParameters));
- // Setup the TLS, if needed.
- if (type == ThreadType::User) {
- tls_address = owner->CreateTLSRegion();
- }
-
// Set parent, if relevant.
if (owner != nullptr) {
+ // Setup the TLS, if needed.
+ if (type == ThreadType::User) {
+ tls_address = owner->CreateTLSRegion();
+ }
+
parent = owner;
parent->Open();
parent->IncrementThreadCount();
diff --git a/src/core/hle/kernel/k_thread.h b/src/core/hle/kernel/k_thread.h
index 4abfc2b49..01eebb165 100644
--- a/src/core/hle/kernel/k_thread.h
+++ b/src/core/hle/kernel/k_thread.h
@@ -358,21 +358,21 @@ public:
return termination_requested || GetRawState() == ThreadState::Terminated;
}
- [[nodiscard]] virtual u64 GetId() const override final {
+ [[nodiscard]] u64 GetId() const override {
return this->GetThreadID();
}
- [[nodiscard]] virtual bool IsInitialized() const override {
+ [[nodiscard]] bool IsInitialized() const override {
return initialized;
}
- [[nodiscard]] virtual uintptr_t GetPostDestroyArgument() const override {
+ [[nodiscard]] uintptr_t GetPostDestroyArgument() const override {
return reinterpret_cast<uintptr_t>(parent) | (resource_limit_release_hint ? 1 : 0);
}
- virtual void Finalize() override;
+ void Finalize() override;
- [[nodiscard]] virtual bool IsSignaled() const override;
+ [[nodiscard]] bool IsSignaled() const override;
static void PostDestroy(uintptr_t arg);
diff --git a/src/core/hle/kernel/k_transfer_memory.h b/src/core/hle/kernel/k_transfer_memory.h
index c2d0f1eaf..31029a5c2 100644
--- a/src/core/hle/kernel/k_transfer_memory.h
+++ b/src/core/hle/kernel/k_transfer_memory.h
@@ -27,23 +27,23 @@ class KTransferMemory final
public:
explicit KTransferMemory(KernelCore& kernel_);
- virtual ~KTransferMemory() override;
+ ~KTransferMemory() override;
ResultCode Initialize(VAddr address_, std::size_t size_, Svc::MemoryPermission owner_perm_);
- virtual void Finalize() override;
+ void Finalize() override;
- virtual bool IsInitialized() const override {
+ bool IsInitialized() const override {
return is_initialized;
}
- virtual uintptr_t GetPostDestroyArgument() const override {
+ uintptr_t GetPostDestroyArgument() const override {
return reinterpret_cast<uintptr_t>(owner);
}
static void PostDestroy(uintptr_t arg);
- KProcess* GetOwner() const {
+ KProcess* GetOwner() const override {
return owner;
}
diff --git a/src/core/hle/kernel/k_writable_event.h b/src/core/hle/kernel/k_writable_event.h
index 607b0eadb..858d982c4 100644
--- a/src/core/hle/kernel/k_writable_event.h
+++ b/src/core/hle/kernel/k_writable_event.h
@@ -21,7 +21,7 @@ public:
explicit KWritableEvent(KernelCore& kernel_);
~KWritableEvent() override;
- virtual void Destroy() override;
+ void Destroy() override;
static void PostDestroy([[maybe_unused]] uintptr_t arg) {}
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 8b55df82e..0ffb78d51 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -258,7 +258,7 @@ struct KernelCore::Impl {
KAutoObject::Create(thread.get());
ASSERT(KThread::InitializeDummyThread(thread.get()).IsSuccess());
thread->SetName(fmt::format("DummyThread:{}", GetHostThreadId()));
- return std::move(thread);
+ return thread;
};
thread_local auto thread = make_thread();
@@ -620,7 +620,8 @@ struct KernelCore::Impl {
void InitializePageSlab() {
// Allocate slab heaps
- user_slab_heap_pages = std::make_unique<KSlabHeap<Page>>();
+ user_slab_heap_pages =
+ std::make_unique<KSlabHeap<Page>>(KSlabHeap<Page>::AllocationType::Guest);
// TODO(ameerj): This should be derived, not hardcoded within the kernel
constexpr u64 user_slab_heap_size{0x3de000};
diff --git a/src/core/hle/service/am/applets/software_keyboard.cpp b/src/core/hle/service/am/applets/software_keyboard.cpp
index b05a5da04..b1a81810b 100644
--- a/src/core/hle/service/am/applets/software_keyboard.cpp
+++ b/src/core/hle/service/am/applets/software_keyboard.cpp
@@ -273,8 +273,13 @@ void SoftwareKeyboard::ProcessTextCheck() {
std::memcpy(&swkbd_text_check, text_check_data.data(), sizeof(SwkbdTextCheck));
- std::u16string text_check_message = Common::UTF16StringFromFixedZeroTerminatedBuffer(
- swkbd_text_check.text_check_message.data(), swkbd_text_check.text_check_message.size());
+ std::u16string text_check_message =
+ swkbd_text_check.text_check_result == SwkbdTextCheckResult::Failure ||
+ swkbd_text_check.text_check_result == SwkbdTextCheckResult::Confirm
+ ? Common::UTF16StringFromFixedZeroTerminatedBuffer(
+ swkbd_text_check.text_check_message.data(),
+ swkbd_text_check.text_check_message.size())
+ : u"";
LOG_INFO(Service_AM, "\nTextCheckResult: {}\nTextCheckMessage: {}",
GetTextCheckResultName(swkbd_text_check.text_check_result),
@@ -285,10 +290,10 @@ void SoftwareKeyboard::ProcessTextCheck() {
SubmitNormalOutputAndExit(SwkbdResult::Ok, current_text);
break;
case SwkbdTextCheckResult::Failure:
- ShowTextCheckDialog(SwkbdTextCheckResult::Failure, text_check_message);
+ ShowTextCheckDialog(SwkbdTextCheckResult::Failure, std::move(text_check_message));
break;
case SwkbdTextCheckResult::Confirm:
- ShowTextCheckDialog(SwkbdTextCheckResult::Confirm, text_check_message);
+ ShowTextCheckDialog(SwkbdTextCheckResult::Confirm, std::move(text_check_message));
break;
case SwkbdTextCheckResult::Silent:
default:
@@ -482,7 +487,7 @@ void SoftwareKeyboard::InitializeFrontendKeyboard() {
max_text_length <= 32 ? SwkbdTextDrawType::Line : SwkbdTextDrawType::Box;
Core::Frontend::KeyboardInitializeParameters initialize_parameters{
- .ok_text{ok_text},
+ .ok_text{std::move(ok_text)},
.header_text{},
.sub_text{},
.guide_text{},
@@ -558,10 +563,10 @@ void SoftwareKeyboard::InitializeFrontendKeyboard() {
: false;
Core::Frontend::KeyboardInitializeParameters initialize_parameters{
- .ok_text{ok_text},
- .header_text{header_text},
- .sub_text{sub_text},
- .guide_text{guide_text},
+ .ok_text{std::move(ok_text)},
+ .header_text{std::move(header_text)},
+ .sub_text{std::move(sub_text)},
+ .guide_text{std::move(guide_text)},
.initial_text{initial_text},
.max_text_length{max_text_length},
.min_text_length{min_text_length},
@@ -590,7 +595,7 @@ void SoftwareKeyboard::ShowNormalKeyboard() {
void SoftwareKeyboard::ShowTextCheckDialog(SwkbdTextCheckResult text_check_result,
std::u16string text_check_message) {
- frontend.ShowTextCheckDialog(text_check_result, text_check_message);
+ frontend.ShowTextCheckDialog(text_check_result, std::move(text_check_message));
}
void SoftwareKeyboard::ShowInlineKeyboard() {
diff --git a/src/core/hle/service/hid/controllers/gesture.h b/src/core/hle/service/hid/controllers/gesture.h
index eecfeaad5..7e7ae6625 100644
--- a/src/core/hle/service/hid/controllers/gesture.h
+++ b/src/core/hle/service/hid/controllers/gesture.h
@@ -7,6 +7,7 @@
#include <array>
#include "common/bit_field.h"
#include "common/common_types.h"
+#include "common/point.h"
#include "core/frontend/input.h"
#include "core/hle/service/hid/controllers/controller_base.h"
@@ -63,44 +64,21 @@ private:
};
static_assert(sizeof(Attribute) == 4, "Attribute is an invalid size");
- template <typename T>
- struct Point {
- T x{};
- T y{};
-
- friend Point operator+(const Point& lhs, const Point& rhs) {
- return {
- .x = lhs.x + rhs.x,
- .y = lhs.y + rhs.y,
- };
- }
-
- friend Point operator-(const Point& lhs, const Point& rhs) {
- return {
- .x = lhs.x - rhs.x,
- .y = lhs.y - rhs.y,
- };
- }
-
- friend bool operator==(const Point&, const Point&) = default;
- };
- static_assert(sizeof(Point<s32_le>) == 8, "Point is an invalid size");
-
struct GestureState {
s64_le sampling_number;
s64_le sampling_number2;
s64_le detection_count;
TouchType type;
Direction direction;
- Point<s32_le> pos;
- Point<s32_le> delta;
+ Common::Point<s32_le> pos;
+ Common::Point<s32_le> delta;
f32 vel_x;
f32 vel_y;
Attribute attributes;
f32 scale;
f32 rotation_angle;
s32_le point_count;
- std::array<Point<s32_le>, 4> points;
+ std::array<Common::Point<s32_le>, 4> points;
};
static_assert(sizeof(GestureState) == 0x68, "GestureState is an invalid size");
@@ -111,14 +89,14 @@ private:
static_assert(sizeof(SharedMemory) == 0x708, "SharedMemory is an invalid size");
struct Finger {
- Point<f32> pos{};
+ Common::Point<f32> pos{};
bool pressed{};
};
struct GestureProperties {
- std::array<Point<s32_le>, MAX_POINTS> points{};
+ std::array<Common::Point<s32_le>, MAX_POINTS> points{};
std::size_t active_points{};
- Point<s32_le> mid_point{};
+ Common::Point<s32_le> mid_point{};
s64_le detection_count{};
u64_le delta_time{};
f32 average_distance{};
diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp
index ac9112c40..6ef17acc5 100644
--- a/src/core/hle/service/hid/controllers/touchscreen.cpp
+++ b/src/core/hle/service/hid/controllers/touchscreen.cpp
@@ -74,8 +74,11 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin
for (std::size_t id = 0; id < MAX_FINGERS; ++id) {
auto& touch_entry = cur_entry.states[id];
if (id < active_fingers_count) {
- touch_entry.x = static_cast<u16>(active_fingers[id].x * Layout::ScreenUndocked::Width);
- touch_entry.y = static_cast<u16>(active_fingers[id].y * Layout::ScreenUndocked::Height);
+ const auto& [active_x, active_y] = active_fingers[id].position;
+ touch_entry.position = {
+ .x = static_cast<u16>(active_x * Layout::ScreenUndocked::Width),
+ .y = static_cast<u16>(active_y * Layout::ScreenUndocked::Height),
+ };
touch_entry.diameter_x = Settings::values.touchscreen.diameter_x;
touch_entry.diameter_y = Settings::values.touchscreen.diameter_y;
touch_entry.rotation_angle = Settings::values.touchscreen.rotation_angle;
@@ -86,8 +89,7 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin
} else {
// Clear touch entry
touch_entry.attribute.raw = 0;
- touch_entry.x = 0;
- touch_entry.y = 0;
+ touch_entry.position = {};
touch_entry.diameter_x = 0;
touch_entry.diameter_y = 0;
touch_entry.rotation_angle = 0;
@@ -140,8 +142,7 @@ std::size_t Controller_Touchscreen::UpdateTouchInputEvent(
fingers[finger_id].id = static_cast<u32_le>(finger_id);
attribute.start_touch.Assign(1);
}
- fingers[finger_id].x = x;
- fingers[finger_id].y = y;
+ fingers[finger_id].position = {x, y};
fingers[finger_id].attribute = attribute;
return finger_id;
}
diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h
index 2869d0cfd..ef2becefd 100644
--- a/src/core/hle/service/hid/controllers/touchscreen.h
+++ b/src/core/hle/service/hid/controllers/touchscreen.h
@@ -7,6 +7,7 @@
#include "common/bit_field.h"
#include "common/common_funcs.h"
#include "common/common_types.h"
+#include "common/point.h"
#include "common/swap.h"
#include "core/frontend/input.h"
#include "core/hle/service/hid/controllers/controller_base.h"
@@ -55,8 +56,7 @@ private:
u64_le delta_time;
Attributes attribute;
u32_le finger;
- u32_le x;
- u32_le y;
+ Common::Point<u32_le> position;
u32_le diameter_x;
u32_le diameter_y;
u32_le rotation_angle;
@@ -81,8 +81,7 @@ private:
struct Finger {
u64_le last_touch{};
- float x{};
- float y{};
+ Common::Point<float> position;
u32_le id{};
bool pressed{};
Attributes attribute;
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 49c17fd14..df0fe1c8e 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -1770,7 +1770,7 @@ public:
{232, nullptr, "GetIrSensorState"},
{233, nullptr, "GetXcdHandleForNpadWithIrSensor"},
{301, nullptr, "ActivateNpadSystem"},
- {303, nullptr, "ApplyNpadSystemCommonPolicy"},
+ {303, &HidSys::ApplyNpadSystemCommonPolicy, "ApplyNpadSystemCommonPolicy"},
{304, nullptr, "EnableAssigningSingleOnSlSrPress"},
{305, nullptr, "DisableAssigningSingleOnSlSrPress"},
{306, nullptr, "GetLastActiveNpad"},
@@ -1949,6 +1949,15 @@ public:
RegisterHandlers(functions);
}
+
+private:
+ void ApplyNpadSystemCommonPolicy(Kernel::HLERequestContext& ctx) {
+ // We already do this for homebrew so we can just stub it out
+ LOG_WARNING(Service_HID, "called");
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(RESULT_SUCCESS);
+ }
};
class HidTmp final : public ServiceFramework<HidTmp> {
diff --git a/src/core/hle/service/ldn/ldn.cpp b/src/core/hle/service/ldn/ldn.cpp
index d160ffe87..c709a8028 100644
--- a/src/core/hle/service/ldn/ldn.cpp
+++ b/src/core/hle/service/ldn/ldn.cpp
@@ -215,10 +215,151 @@ public:
}
};
+class INetworkService final : public ServiceFramework<INetworkService> {
+public:
+ explicit INetworkService(Core::System& system_) : ServiceFramework{system_, "INetworkService"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, nullptr, "Initialize"},
+ {256, nullptr, "AttachNetworkInterfaceStateChangeEvent"},
+ {264, nullptr, "GetNetworkInterfaceLastError"},
+ {272, nullptr, "GetRole"},
+ {280, nullptr, "GetAdvertiseData"},
+ {288, nullptr, "GetGroupInfo"},
+ {296, nullptr, "GetGroupInfo2"},
+ {304, nullptr, "GetGroupOwner"},
+ {312, nullptr, "GetIpConfig"},
+ {320, nullptr, "GetLinkLevel"},
+ {512, nullptr, "Scan"},
+ {768, nullptr, "CreateGroup"},
+ {776, nullptr, "DestroyGroup"},
+ {784, nullptr, "SetAdvertiseData"},
+ {1536, nullptr, "SendToOtherGroup"},
+ {1544, nullptr, "RecvFromOtherGroup"},
+ {1552, nullptr, "AddAcceptableGroupId"},
+ {1560, nullptr, "ClearAcceptableGroupId"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+};
+
+class INetworkServiceMonitor final : public ServiceFramework<INetworkServiceMonitor> {
+public:
+ explicit INetworkServiceMonitor(Core::System& system_)
+ : ServiceFramework{system_, "INetworkServiceMonitor"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, &INetworkServiceMonitor::Initialize, "Initialize"},
+ {256, nullptr, "AttachNetworkInterfaceStateChangeEvent"},
+ {264, nullptr, "GetNetworkInterfaceLastError"},
+ {272, nullptr, "GetRole"},
+ {280, nullptr, "GetAdvertiseData"},
+ {281, nullptr, "GetAdvertiseData2"},
+ {288, nullptr, "GetGroupInfo"},
+ {296, nullptr, "GetGroupInfo2"},
+ {304, nullptr, "GetGroupOwner"},
+ {312, nullptr, "GetIpConfig"},
+ {320, nullptr, "GetLinkLevel"},
+ {328, nullptr, "AttachJoinEvent"},
+ {336, nullptr, "GetMembers"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+
+ void Initialize(Kernel::HLERequestContext& ctx) {
+ LOG_WARNING(Service_LDN, "(STUBBED) called");
+
+ IPC::ResponseBuilder rb{ctx, 2};
+ rb.Push(ERROR_DISABLED);
+ }
+};
+
+class LP2PAPP final : public ServiceFramework<LP2PAPP> {
+public:
+ explicit LP2PAPP(Core::System& system_) : ServiceFramework{system_, "lp2p:app"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, &LP2PAPP::CreateMonitorService, "CreateNetworkService"},
+ {8, &LP2PAPP::CreateMonitorService, "CreateNetworkServiceMonitor"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+
+ void CreateNetworkervice(Kernel::HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const u64 reserved_input = rp.Pop<u64>();
+ const u32 input = rp.Pop<u32>();
+
+ LOG_WARNING(Service_LDN, "(STUBBED) called reserved_input={} input={}", reserved_input,
+ input);
+
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<INetworkService>(system);
+ }
+
+ void CreateMonitorService(Kernel::HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const u64 reserved_input = rp.Pop<u64>();
+
+ LOG_WARNING(Service_LDN, "(STUBBED) called reserved_input={}", reserved_input);
+
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<INetworkServiceMonitor>(system);
+ }
+};
+
+class LP2PSYS final : public ServiceFramework<LP2PSYS> {
+public:
+ explicit LP2PSYS(Core::System& system_) : ServiceFramework{system_, "lp2p:sys"} {
+ // clang-format off
+ static const FunctionInfo functions[] = {
+ {0, &LP2PSYS::CreateMonitorService, "CreateNetworkService"},
+ {8, &LP2PSYS::CreateMonitorService, "CreateNetworkServiceMonitor"},
+ };
+ // clang-format on
+
+ RegisterHandlers(functions);
+ }
+
+ void CreateNetworkervice(Kernel::HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const u64 reserved_input = rp.Pop<u64>();
+ const u32 input = rp.Pop<u32>();
+
+ LOG_WARNING(Service_LDN, "(STUBBED) called reserved_input={} input={}", reserved_input,
+ input);
+
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<INetworkService>(system);
+ }
+
+ void CreateMonitorService(Kernel::HLERequestContext& ctx) {
+ IPC::RequestParser rp{ctx};
+ const u64 reserved_input = rp.Pop<u64>();
+
+ LOG_WARNING(Service_LDN, "(STUBBED) called reserved_input={}", reserved_input);
+
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(RESULT_SUCCESS);
+ rb.PushIpcInterface<INetworkServiceMonitor>(system);
+ }
+};
+
void InstallInterfaces(SM::ServiceManager& sm, Core::System& system) {
std::make_shared<LDNM>(system)->InstallAsService(sm);
std::make_shared<LDNS>(system)->InstallAsService(sm);
std::make_shared<LDNU>(system)->InstallAsService(sm);
+ std::make_shared<LP2PAPP>(system)->InstallAsService(sm);
+ std::make_shared<LP2PSYS>(system)->InstallAsService(sm);
}
} // namespace Service::LDN
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index bf2ef7816..9857278f6 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -591,7 +591,15 @@ struct Memory::Impl {
* @returns The instance of T read from the specified virtual address.
*/
template <typename T>
- T Read(const VAddr vaddr) {
+ T Read(VAddr vaddr) {
+ // AARCH64 masks the upper 16 bit of all memory accesses
+ vaddr &= 0xffffffffffffLL;
+
+ if (vaddr >= 1uLL << current_page_table->GetAddressSpaceBits()) {
+ LOG_ERROR(HW_Memory, "Unmapped Read{} @ 0x{:08X}", sizeof(T) * 8, vaddr);
+ return 0;
+ }
+
// Avoid adding any extra logic to this fast-path block
const uintptr_t raw_pointer = current_page_table->pointers[vaddr >> PAGE_BITS].Raw();
if (const u8* const pointer = Common::PageTable::PageInfo::ExtractPointer(raw_pointer)) {
@@ -629,7 +637,16 @@ struct Memory::Impl {
* is undefined.
*/
template <typename T>
- void Write(const VAddr vaddr, const T data) {
+ void Write(VAddr vaddr, const T data) {
+ // AARCH64 masks the upper 16 bit of all memory accesses
+ vaddr &= 0xffffffffffffLL;
+
+ if (vaddr >= 1uLL << current_page_table->GetAddressSpaceBits()) {
+ LOG_ERROR(HW_Memory, "Unmapped Write{} 0x{:08X} @ 0x{:016X}", sizeof(data) * 8,
+ static_cast<u32>(data), vaddr);
+ return;
+ }
+
// Avoid adding any extra logic to this fast-path block
const uintptr_t raw_pointer = current_page_table->pointers[vaddr >> PAGE_BITS].Raw();
if (u8* const pointer = Common::PageTable::PageInfo::ExtractPointer(raw_pointer)) {
@@ -656,7 +673,16 @@ struct Memory::Impl {
}
template <typename T>
- bool WriteExclusive(const VAddr vaddr, const T data, const T expected) {
+ bool WriteExclusive(VAddr vaddr, const T data, const T expected) {
+ // AARCH64 masks the upper 16 bit of all memory accesses
+ vaddr &= 0xffffffffffffLL;
+
+ if (vaddr >= 1uLL << current_page_table->GetAddressSpaceBits()) {
+ LOG_ERROR(HW_Memory, "Unmapped Write{} 0x{:08X} @ 0x{:016X}", sizeof(data) * 8,
+ static_cast<u32>(data), vaddr);
+ return true;
+ }
+
const uintptr_t raw_pointer = current_page_table->pointers[vaddr >> PAGE_BITS].Raw();
if (u8* const pointer = Common::PageTable::PageInfo::ExtractPointer(raw_pointer)) {
// NOTE: Avoid adding any extra logic to this fast-path block
@@ -683,7 +709,16 @@ struct Memory::Impl {
return true;
}
- bool WriteExclusive128(const VAddr vaddr, const u128 data, const u128 expected) {
+ bool WriteExclusive128(VAddr vaddr, const u128 data, const u128 expected) {
+ // AARCH64 masks the upper 16 bit of all memory accesses
+ vaddr &= 0xffffffffffffLL;
+
+ if (vaddr >= 1uLL << current_page_table->GetAddressSpaceBits()) {
+ LOG_ERROR(HW_Memory, "Unmapped Write{} 0x{:08X} @ 0x{:016X}", sizeof(data) * 8,
+ static_cast<u32>(data[0]), vaddr);
+ return true;
+ }
+
const uintptr_t raw_pointer = current_page_table->pointers[vaddr >> PAGE_BITS].Raw();
if (u8* const pointer = Common::PageTable::PageInfo::ExtractPointer(raw_pointer)) {
// NOTE: Avoid adding any extra logic to this fast-path block