Browse Source

add atmosphere changes from 21.0.0 branch + correct prepo struct

pull/3004/head
Maufeat 3 months ago
committed by crueter
parent
commit
2c51651636
  1. 1
      src/core/hle/kernel/k_auto_object.cpp
  2. 10
      src/core/hle/kernel/k_auto_object.h
  3. 22
      src/core/hle/kernel/k_condition_variable.cpp
  4. 3
      src/core/hle/kernel/k_scheduler.cpp
  5. 24
      src/core/hle/kernel/k_thread.cpp
  6. 25
      src/core/hle/kernel/k_thread.h
  7. 37
      src/core/hle/service/filesystem/fsp/fsp_srv.cpp
  8. 21
      src/core/hle/service/prepo/prepo.cpp

1
src/core/hle/kernel/k_auto_object.cpp

@ -8,6 +8,7 @@ namespace Kernel {
KAutoObject* KAutoObject::Create(KAutoObject* obj) { KAutoObject* KAutoObject::Create(KAutoObject* obj) {
obj->m_ref_count = 1; obj->m_ref_count = 1;
obj->m_class_token = obj->GetTypeObj().GetClassToken();
return obj; return obj;
} }

10
src/core/hle/kernel/k_auto_object.h

@ -74,6 +74,10 @@ protected:
return (this->GetClassToken() | rhs.GetClassToken()) == this->GetClassToken(); return (this->GetClassToken() | rhs.GetClassToken()) == this->GetClassToken();
} }
static constexpr bool IsClassTokenDerivedFrom(ClassTokenType self, ClassTokenType base) {
return (self | base) == self;
}
private: private:
const char* m_name; const char* m_name;
ClassTokenType m_class_token; ClassTokenType m_class_token;
@ -84,6 +88,7 @@ private:
public: public:
explicit KAutoObject(KernelCore& kernel) : m_kernel(kernel) { explicit KAutoObject(KernelCore& kernel) : m_kernel(kernel) {
m_class_token = GetStaticTypeObj().GetClassToken();
RegisterWithKernel(); RegisterWithKernel();
} }
virtual ~KAutoObject() = default; virtual ~KAutoObject() = default;
@ -107,11 +112,11 @@ public:
} }
bool IsDerivedFrom(const TypeObj& rhs) const { bool IsDerivedFrom(const TypeObj& rhs) const {
return this->GetTypeObj().IsDerivedFrom(rhs);
return TypeObj::IsClassTokenDerivedFrom(m_class_token, rhs.GetClassToken());
} }
bool IsDerivedFrom(const KAutoObject& rhs) const { bool IsDerivedFrom(const KAutoObject& rhs) const {
return this->IsDerivedFrom(rhs.GetTypeObj());
return TypeObj::IsClassTokenDerivedFrom(m_class_token, rhs.m_class_token);
} }
template <typename Derived> template <typename Derived>
@ -180,6 +185,7 @@ protected:
private: private:
std::atomic<u32> m_ref_count{}; std::atomic<u32> m_ref_count{};
ClassTokenType m_class_token{}; // neu: gespeicherter Klassentoken zur Devitalisierung
}; };
class KAutoObjectWithListContainer; class KAutoObjectWithListContainer;

22
src/core/hle/kernel/k_condition_variable.cpp

@ -23,8 +23,8 @@ bool ReadFromUser(KernelCore& kernel, u32* out, KProcessAddress address) {
return true; return true;
} }
bool WriteToUser(KernelCore& kernel, KProcessAddress address, const u32* p) {
GetCurrentMemory(kernel).Write32(GetInteger(address), *p);
bool WriteToUser(KernelCore& kernel, KProcessAddress address, u32 val) {
GetCurrentMemory(kernel).Write32(GetInteger(address), val);
return true; return true;
} }
@ -133,7 +133,7 @@ Result KConditionVariable::SignalToAddress(KernelCore& kernel, KProcessAddress a
// Write the value to userspace. // Write the value to userspace.
Result result{ResultSuccess}; Result result{ResultSuccess};
if (WriteToUser(kernel, addr, std::addressof(next_value))) [[likely]] {
if (WriteToUser(kernel, addr, next_value)) {
result = ResultSuccess; result = ResultSuccess;
} else { } else {
result = ResultInvalidCurrentMemory; result = ResultInvalidCurrentMemory;
@ -207,13 +207,13 @@ void KConditionVariable::SignalImpl(KThread* thread) {
// TODO(bunnei): We should call CanAccessAtomic(..) here. // TODO(bunnei): We should call CanAccessAtomic(..) here.
can_access = true; can_access = true;
if (can_access) [[likely]] {
if (can_access) {
UpdateLockAtomic(m_kernel, std::addressof(prev_tag), address, own_tag, UpdateLockAtomic(m_kernel, std::addressof(prev_tag), address, own_tag,
Svc::HandleWaitMask); Svc::HandleWaitMask);
} }
} }
if (can_access) [[likely]] {
if (can_access) {
if (prev_tag == Svc::InvalidHandle) { if (prev_tag == Svc::InvalidHandle) {
// If nobody held the lock previously, we're all good. // If nobody held the lock previously, we're all good.
thread->EndWait(ResultSuccess); thread->EndWait(ResultSuccess);
@ -225,7 +225,7 @@ void KConditionVariable::SignalImpl(KThread* thread) {
static_cast<Handle>(prev_tag & ~Svc::HandleWaitMask)) static_cast<Handle>(prev_tag & ~Svc::HandleWaitMask))
.ReleasePointerUnsafe(); .ReleasePointerUnsafe();
if (owner_thread) [[likely]] {
if (owner_thread) {
// Add the thread as a waiter on the owner. // Add the thread as a waiter on the owner.
owner_thread->AddWaiter(thread); owner_thread->AddWaiter(thread);
owner_thread->Close(); owner_thread->Close();
@ -261,8 +261,8 @@ void KConditionVariable::Signal(u64 cv_key, s32 count) {
// If we have no waiters, clear the has waiter flag. // If we have no waiters, clear the has waiter flag.
if (it == m_tree.end() || it->GetConditionVariableKey() != cv_key) { if (it == m_tree.end() || it->GetConditionVariableKey() != cv_key) {
const u32 has_waiter_flag{};
WriteToUser(m_kernel, cv_key, std::addressof(has_waiter_flag));
constexpr u32 HasNoWaiterFlag = 0;
WriteToUser(m_kernel, cv_key, HasNoWaiterFlag);
} }
} }
} }
@ -305,13 +305,13 @@ Result KConditionVariable::Wait(KProcessAddress addr, u64 key, u32 value, s64 ti
// Write to the cv key. // Write to the cv key.
{ {
const u32 has_waiter_flag = 1;
WriteToUser(m_kernel, key, std::addressof(has_waiter_flag));
constexpr u32 HasWaiterFlag = 1;
WriteToUser(m_kernel, key, HasWaiterFlag);
std::atomic_thread_fence(std::memory_order_seq_cst); std::atomic_thread_fence(std::memory_order_seq_cst);
} }
// Write the value to userspace. // Write the value to userspace.
if (!WriteToUser(m_kernel, addr, std::addressof(next_value))) {
if (!WriteToUser(m_kernel, addr, next_value)) {
slp.CancelSleep(); slp.CancelSleep();
R_THROW(ResultInvalidCurrentMemory); R_THROW(ResultInvalidCurrentMemory);
} }

3
src/core/hle/kernel/k_scheduler.cpp

@ -381,6 +381,9 @@ void KScheduler::SwitchThread(KThread* next_thread) {
// Set the new Thread Local region. // Set the new Thread Local region.
// cpu::SwitchThreadLocalRegion(GetInteger(next_thread->GetThreadLocalRegionAddress())); // cpu::SwitchThreadLocalRegion(GetInteger(next_thread->GetThreadLocalRegionAddress()));
// Update the thread's cpu time differential in TLS, if relevant.
next_thread->UpdateTlsThreadCpuTime(cur_tick);
} }
void KScheduler::ScheduleImpl() { void KScheduler::ScheduleImpl() {

24
src/core/hle/kernel/k_thread.cpp

@ -11,6 +11,7 @@
#include <mutex> #include <mutex>
#include <optional> #include <optional>
#include <vector> #include <vector>
#include <array>
#include "common/assert.h" #include "common/assert.h"
#include "common/bit_util.h" #include "common/bit_util.h"
@ -67,7 +68,6 @@ static void ResetThreadContext64(Kernel::Svc::ThreadContext& ctx, u64 stack_top,
} // namespace } // namespace
namespace Kernel { namespace Kernel {
namespace { namespace {
struct ThreadLocalRegion { struct ThreadLocalRegion {
@ -75,7 +75,13 @@ struct ThreadLocalRegion {
std::array<u32, MessageBufferSize / sizeof(u32)> message_buffer; std::array<u32, MessageBufferSize / sizeof(u32)> message_buffer;
std::atomic_uint16_t disable_count; std::atomic_uint16_t disable_count;
std::atomic_uint16_t interrupt_flag; std::atomic_uint16_t interrupt_flag;
std::atomic_uint8_t cache_maintenance_flag;
std::atomic_int64_t thread_cpu_time;
}; };
static_assert(offsetof(ThreadLocalRegion, disable_count) == 0x100);
static_assert(offsetof(ThreadLocalRegion, interrupt_flag) == 0x102);
static_assert(offsetof(ThreadLocalRegion, cache_maintenance_flag) == 0x104);
static_assert(offsetof(ThreadLocalRegion, thread_cpu_time) == 0x108);
class ThreadQueueImplForKThreadSleep final : public KThreadQueueWithoutEndWait { class ThreadQueueImplForKThreadSleep final : public KThreadQueueWithoutEndWait {
public: public:
@ -582,6 +588,19 @@ void KThread::ClearInterruptFlag() {
memory.Write16(m_tls_address + offsetof(ThreadLocalRegion, interrupt_flag), 0); memory.Write16(m_tls_address + offsetof(ThreadLocalRegion, interrupt_flag), 0);
} }
void KThread::UpdateTlsThreadCpuTime(s64 switch_tick) {
if (!this->IsUserThread()) {
return;
}
if (m_tls_address == 0) {
return;
}
const s64 value = this->GetCpuTime() - switch_tick;
auto& memory = this->GetOwnerProcess()->GetMemory();
memory.Write64(m_tls_address + offsetof(ThreadLocalRegion, thread_cpu_time), static_cast<u64>(value));
}
Result KThread::GetCoreMask(s32* out_ideal_core, u64* out_affinity_mask) { Result KThread::GetCoreMask(s32* out_ideal_core, u64* out_affinity_mask) {
KScopedSchedulerLock sl{m_kernel}; KScopedSchedulerLock sl{m_kernel};
@ -1447,5 +1466,4 @@ KScopedDisableDispatch::~KScopedDisableDispatch() {
GetCurrentThread(m_kernel).EnableDispatch(); GetCurrentThread(m_kernel).EnableDispatch();
} }
} }
} // namespace Kernel
}

25
src/core/hle/kernel/k_thread.h

@ -99,6 +99,12 @@ enum class DpcFlag : u32 {
Terminated = (1 << 1), Terminated = (1 << 1),
}; };
enum class ExceptionFlag : u8 {
IsCallingSvc = 1 << 0,
InExceptionHandler = 1 << 1,
};
DECLARE_ENUM_FLAG_OPERATORS(ExceptionFlag);
enum class ThreadWaitReasonForDebugging : u32 { enum class ThreadWaitReasonForDebugging : u32 {
None, ///< Thread is not waiting None, ///< Thread is not waiting
Sleep, ///< Thread is waiting due to a SleepThread SVC Sleep, ///< Thread is waiting due to a SleepThread SVC
@ -153,7 +159,7 @@ public:
/** /**
* Sets the thread's current priority. * Sets the thread's current priority.
* @param priority The new priority.
* @param value The new priority.
*/ */
void SetPriority(s32 value) { void SetPriority(s32 value) {
m_priority = value; m_priority = value;
@ -340,6 +346,8 @@ public:
void SetInterruptFlag(); void SetInterruptFlag();
void ClearInterruptFlag(); void ClearInterruptFlag();
void UpdateTlsThreadCpuTime(s64 switch_tick);
KThread* GetLockOwner() const; KThread* GetLockOwner() const;
const KAffinityMask& GetAffinityMask() const { const KAffinityMask& GetAffinityMask() const {
@ -446,6 +454,7 @@ public:
bool is_pinned; bool is_pinned;
s32 disable_count; s32 disable_count;
KThread* cur_thread; KThread* cur_thread;
std::atomic<u8> exception_flags{0};
}; };
StackParameters& GetStackParameters() { StackParameters& GetStackParameters() {
@ -456,6 +465,16 @@ public:
return m_stack_parameters; return m_stack_parameters;
} }
void SetExceptionFlag(ExceptionFlag flag) {
GetStackParameters().exception_flags.fetch_or(static_cast<u8>(flag), std::memory_order_relaxed);
}
void ClearExceptionFlag(ExceptionFlag flag) {
GetStackParameters().exception_flags.fetch_and(static_cast<u8>(~static_cast<u8>(flag)), std::memory_order_relaxed);
}
bool IsExceptionFlagSet(ExceptionFlag flag) const {
return (GetStackParameters().exception_flags.load(std::memory_order_relaxed) & static_cast<u8>(flag)) != 0;
}
class QueueEntry { class QueueEntry {
public: public:
constexpr QueueEntry() = default; constexpr QueueEntry() = default;
@ -511,10 +530,12 @@ public:
void SetInExceptionHandler() { void SetInExceptionHandler() {
this->GetStackParameters().is_in_exception_handler = true; this->GetStackParameters().is_in_exception_handler = true;
SetExceptionFlag(ExceptionFlag::InExceptionHandler);
} }
void ClearInExceptionHandler() { void ClearInExceptionHandler() {
this->GetStackParameters().is_in_exception_handler = false; this->GetStackParameters().is_in_exception_handler = false;
ClearExceptionFlag(ExceptionFlag::InExceptionHandler);
} }
bool IsInExceptionHandler() const { bool IsInExceptionHandler() const {
@ -523,10 +544,12 @@ public:
void SetIsCallingSvc() { void SetIsCallingSvc() {
this->GetStackParameters().is_calling_svc = true; this->GetStackParameters().is_calling_svc = true;
SetExceptionFlag(ExceptionFlag::IsCallingSvc);
} }
void ClearIsCallingSvc() { void ClearIsCallingSvc() {
this->GetStackParameters().is_calling_svc = false; this->GetStackParameters().is_calling_svc = false;
ClearExceptionFlag(ExceptionFlag::IsCallingSvc);
} }
bool IsCallingSvc() const { bool IsCallingSvc() const {

37
src/core/hle/service/filesystem/fsp/fsp_srv.cpp

@ -298,8 +298,41 @@ Result FSP_SRV::OpenSaveDataFileSystem(OutInterface<IFileSystem> out_interface,
Result FSP_SRV::OpenSaveDataFileSystemBySystemSaveDataId(OutInterface<IFileSystem> out_interface, Result FSP_SRV::OpenSaveDataFileSystemBySystemSaveDataId(OutInterface<IFileSystem> out_interface,
FileSys::SaveDataSpaceId space_id, FileSys::SaveDataSpaceId space_id,
FileSys::SaveDataAttribute attribute) { FileSys::SaveDataAttribute attribute) {
LOG_WARNING(Service_FS, "(STUBBED) called, delegating to 51 OpenSaveDataFilesystem");
R_RETURN(OpenSaveDataFileSystem(out_interface, space_id, attribute));
LOG_INFO(Service_FS, "called, space_id={}, {}",
space_id, attribute.DebugInfo());
R_UNLESS(attribute.system_save_data_id != FileSys::InvalidSystemSaveDataId,
FileSys::ResultInvalidArgument);
if (attribute.program_id == 0) {
attribute.program_id = program_id;
}
FileSys::VirtualDir dir{};
R_TRY(save_data_controller->OpenSaveData(&dir, space_id, attribute));
FileSys::StorageId id{};
switch (space_id) {
case FileSys::SaveDataSpaceId::User:
id = FileSys::StorageId::NandUser;
break;
case FileSys::SaveDataSpaceId::SdSystem:
case FileSys::SaveDataSpaceId::SdUser:
id = FileSys::StorageId::SdCard;
break;
case FileSys::SaveDataSpaceId::System:
id = FileSys::StorageId::NandSystem;
break;
case FileSys::SaveDataSpaceId::Temporary:
case FileSys::SaveDataSpaceId::ProperSystem:
case FileSys::SaveDataSpaceId::SafeMode:
ASSERT(false);
}
*out_interface =
std::make_shared<IFileSystem>(system, std::move(dir), SizeGetter::FromStorageId(fsc, id));
R_SUCCEED();
} }
Result FSP_SRV::OpenReadOnlySaveDataFileSystem(OutInterface<IFileSystem> out_interface, Result FSP_SRV::OpenReadOnlySaveDataFileSystem(OutInterface<IFileSystem> out_interface,

21
src/core/hle/service/prepo/prepo.cpp

@ -3,6 +3,9 @@
#include "common/hex_util.h" #include "common/hex_util.h"
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/uuid.h"
#include <cstring>
#include "core/core.h" #include "core/core.h"
#include "core/hle/service/acc/profile_manager.h" #include "core/hle/service/acc/profile_manager.h"
#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/ipc_helpers.h"
@ -145,10 +148,12 @@ private:
const auto data1 = ctx.ReadBufferA(0); const auto data1 = ctx.ReadBufferA(0);
const auto data2 = ctx.ReadBufferX(0); const auto data2 = ctx.ReadBufferX(0);
Common::UUID uuid{};
std::memcpy(uuid.uuid.data(), user_id.data(), sizeof(Common::UUID));
LOG_ERROR(Service_PREPO, LOG_ERROR(Service_PREPO,
"called, user_id={:016X}{:016X}, title_id={:016X}, data1_size={:016X}, "
"data2_size={:016X}",
user_id[1], user_id[0], title_id, data1.size(), data2.size());
"called, user_id={}, title_id={:016X}, data1_size={:016X}, data2_size={:016X}",
uuid.FormattedString(), title_id, data1.size(), data2.size());
const auto& reporter{system.GetReporter()}; const auto& reporter{system.GetReporter()};
reporter.SavePlayReport(Core::Reporter::PlayReportType::System, title_id, {data1, data2}, reporter.SavePlayReport(Core::Reporter::PlayReportType::System, title_id, {data1, data2},
@ -182,16 +187,20 @@ private:
void SaveSystemReportWithUser(HLERequestContext& ctx) { void SaveSystemReportWithUser(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
// 21.0.0+: field0 (u64), user_id (u128), title_id (u64)
const auto field0 = rp.PopRaw<u64>();
const auto user_id = rp.PopRaw<u128>(); const auto user_id = rp.PopRaw<u128>();
const auto title_id = rp.PopRaw<u64>(); const auto title_id = rp.PopRaw<u64>();
const auto reserved = rp.PopRaw<u64>();
const auto data_x = ctx.ReadBufferX(0); const auto data_x = ctx.ReadBufferX(0);
const auto data_a = ctx.ReadBufferA(0); const auto data_a = ctx.ReadBufferA(0);
Common::UUID uuid{};
std::memcpy(uuid.uuid.data(), user_id.data(), sizeof(Common::UUID));
LOG_ERROR(Service_PREPO, LOG_ERROR(Service_PREPO,
"called, user_id={:016X}{:016X}, title_id={:016X}, reserved={}, data_a_size={}, data_x_size={}",
user_id[1], user_id[0], title_id, reserved, data_a.size(), data_x.size());
"called, user_id={}, field0={:016X}, title_id={:016X}, data_a_size={}, data_x_size={}",
uuid.FormattedString(), field0, title_id, data_a.size(), data_x.size());
const auto& reporter{system.GetReporter()}; const auto& reporter{system.GetReporter()};
reporter.SavePlayReport(Core::Reporter::PlayReportType::System, title_id, {data_a, data_x}, reporter.SavePlayReport(Core::Reporter::PlayReportType::System, title_id, {data_a, data_x},

Loading…
Cancel
Save