summaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
Diffstat (limited to 'src/core')
-rw-r--r--src/core/arm/arm_interface.h7
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic.cpp10
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic.h2
-rw-r--r--src/core/arm/unicorn/arm_unicorn.cpp14
-rw-r--r--src/core/arm/unicorn/arm_unicorn.h2
-rw-r--r--src/core/file_sys/errors.h16
-rw-r--r--src/core/file_sys/partition_filesystem.cpp12
-rw-r--r--src/core/file_sys/vfs.cpp2
-rw-r--r--src/core/file_sys/vfs.h27
-rw-r--r--src/core/file_sys/vfs_offset.cpp5
-rw-r--r--src/core/file_sys/vfs_offset.h2
-rw-r--r--src/core/file_sys/vfs_real.cpp16
-rw-r--r--src/core/hle/ipc_helpers.h19
-rw-r--r--src/core/hle/kernel/scheduler.cpp3
-rw-r--r--src/core/hle/kernel/thread.cpp1
-rw-r--r--src/core/hle/kernel/thread.h9
-rw-r--r--src/core/hle/service/apm/interface.cpp17
-rw-r--r--src/core/hle/service/filesystem/filesystem.cpp4
-rw-r--r--src/core/hle/service/ns/pl_u.cpp2
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp30
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_gpu.h8
-rw-r--r--src/core/hle/service/nvdrv/interface.cpp2
-rw-r--r--src/core/loader/deconstructed_rom_directory.cpp7
-rw-r--r--src/core/telemetry_session.cpp6
24 files changed, 160 insertions, 63 deletions
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h
index 8416e73b0..b0d7ced7f 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -20,9 +20,6 @@ public:
u64 cpsr;
std::array<u128, 32> fpu_registers;
u64 fpscr;
-
- // TODO(bunnei): Fix once we have proper support for tpidrro_el0, etc. in the JIT
- VAddr tls_address;
};
/// Runs the CPU until an event happens
@@ -104,6 +101,10 @@ public:
virtual void SetTlsAddress(VAddr address) = 0;
+ virtual u64 GetTPIDR_EL0() const = 0;
+
+ virtual void SetTPIDR_EL0(u64 value) = 0;
+
/**
* Saves the current CPU context
* @param ctx Thread context to save
diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp
index 3572ee7b9..5d7efc9b6 100644
--- a/src/core/arm/dynarmic/arm_dynarmic.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic.cpp
@@ -196,6 +196,14 @@ void ARM_Dynarmic::SetTlsAddress(u64 address) {
cb->tpidrro_el0 = address;
}
+u64 ARM_Dynarmic::GetTPIDR_EL0() const {
+ return cb->tpidr_el0;
+}
+
+void ARM_Dynarmic::SetTPIDR_EL0(u64 value) {
+ cb->tpidr_el0 = value;
+}
+
void ARM_Dynarmic::SaveContext(ARM_Interface::ThreadContext& ctx) {
ctx.cpu_registers = jit->GetRegisters();
ctx.sp = jit->GetSP();
@@ -203,7 +211,6 @@ void ARM_Dynarmic::SaveContext(ARM_Interface::ThreadContext& ctx) {
ctx.cpsr = jit->GetPstate();
ctx.fpu_registers = jit->GetVectors();
ctx.fpscr = jit->GetFpcr();
- ctx.tls_address = cb->tpidrro_el0;
}
void ARM_Dynarmic::LoadContext(const ARM_Interface::ThreadContext& ctx) {
@@ -213,7 +220,6 @@ void ARM_Dynarmic::LoadContext(const ARM_Interface::ThreadContext& ctx) {
jit->SetPstate(static_cast<u32>(ctx.cpsr));
jit->SetVectors(ctx.fpu_registers);
jit->SetFpcr(static_cast<u32>(ctx.fpscr));
- cb->tpidrro_el0 = ctx.tls_address;
}
void ARM_Dynarmic::PrepareReschedule() {
diff --git a/src/core/arm/dynarmic/arm_dynarmic.h b/src/core/arm/dynarmic/arm_dynarmic.h
index ed724c3f1..a9891ac4f 100644
--- a/src/core/arm/dynarmic/arm_dynarmic.h
+++ b/src/core/arm/dynarmic/arm_dynarmic.h
@@ -34,6 +34,8 @@ public:
void SetCPSR(u32 cpsr) override;
VAddr GetTlsAddress() const override;
void SetTlsAddress(VAddr address) override;
+ void SetTPIDR_EL0(u64 value) override;
+ u64 GetTPIDR_EL0() const override;
void SaveContext(ThreadContext& ctx) override;
void LoadContext(const ThreadContext& ctx) override;
diff --git a/src/core/arm/unicorn/arm_unicorn.cpp b/src/core/arm/unicorn/arm_unicorn.cpp
index d2d699e9b..4c11f35a4 100644
--- a/src/core/arm/unicorn/arm_unicorn.cpp
+++ b/src/core/arm/unicorn/arm_unicorn.cpp
@@ -169,6 +169,16 @@ void ARM_Unicorn::SetTlsAddress(VAddr base) {
CHECKED(uc_reg_write(uc, UC_ARM64_REG_TPIDRRO_EL0, &base));
}
+u64 ARM_Unicorn::GetTPIDR_EL0() const {
+ u64 value{};
+ CHECKED(uc_reg_read(uc, UC_ARM64_REG_TPIDR_EL0, &value));
+ return value;
+}
+
+void ARM_Unicorn::SetTPIDR_EL0(u64 value) {
+ CHECKED(uc_reg_write(uc, UC_ARM64_REG_TPIDR_EL0, &value));
+}
+
void ARM_Unicorn::Run() {
if (GDBStub::IsServerEnabled()) {
ExecuteInstructions(std::max(4000000, 0));
@@ -220,8 +230,6 @@ void ARM_Unicorn::SaveContext(ARM_Interface::ThreadContext& ctx) {
CHECKED(uc_reg_read_batch(uc, uregs, tregs, 31));
- ctx.tls_address = GetTlsAddress();
-
for (int i = 0; i < 32; ++i) {
uregs[i] = UC_ARM64_REG_Q0 + i;
tregs[i] = &ctx.fpu_registers[i];
@@ -249,8 +257,6 @@ void ARM_Unicorn::LoadContext(const ARM_Interface::ThreadContext& ctx) {
CHECKED(uc_reg_write_batch(uc, uregs, tregs, 31));
- SetTlsAddress(ctx.tls_address);
-
for (auto i = 0; i < 32; ++i) {
uregs[i] = UC_ARM64_REG_Q0 + i;
tregs[i] = (void*)&ctx.fpu_registers[i];
diff --git a/src/core/arm/unicorn/arm_unicorn.h b/src/core/arm/unicorn/arm_unicorn.h
index a78a0acf2..af7943352 100644
--- a/src/core/arm/unicorn/arm_unicorn.h
+++ b/src/core/arm/unicorn/arm_unicorn.h
@@ -28,6 +28,8 @@ public:
void SetCPSR(u32 cpsr) override;
VAddr GetTlsAddress() const override;
void SetTlsAddress(VAddr address) override;
+ void SetTPIDR_EL0(u64 value) override;
+ u64 GetTPIDR_EL0() const override;
void SaveContext(ThreadContext& ctx) override;
void LoadContext(const ThreadContext& ctx) override;
void PrepareReschedule() override;
diff --git a/src/core/file_sys/errors.h b/src/core/file_sys/errors.h
index a152dbd33..fea0593c7 100644
--- a/src/core/file_sys/errors.h
+++ b/src/core/file_sys/errors.h
@@ -20,13 +20,13 @@ enum {
constexpr ResultCode ERROR_PATH_NOT_FOUND(ErrorModule::FS, ErrCodes::NotFound);
// TODO(bunnei): Replace these with correct errors for Switch OS
-constexpr ResultCode ERROR_INVALID_PATH(ResultCode(-1));
-constexpr ResultCode ERROR_UNSUPPORTED_OPEN_FLAGS(ResultCode(-1));
-constexpr ResultCode ERROR_INVALID_OPEN_FLAGS(ResultCode(-1));
-constexpr ResultCode ERROR_FILE_NOT_FOUND(ResultCode(-1));
-constexpr ResultCode ERROR_UNEXPECTED_FILE_OR_DIRECTORY(ResultCode(-1));
-constexpr ResultCode ERROR_DIRECTORY_ALREADY_EXISTS(ResultCode(-1));
-constexpr ResultCode ERROR_FILE_ALREADY_EXISTS(ResultCode(-1));
-constexpr ResultCode ERROR_DIRECTORY_NOT_EMPTY(ResultCode(-1));
+constexpr ResultCode ERROR_INVALID_PATH(-1);
+constexpr ResultCode ERROR_UNSUPPORTED_OPEN_FLAGS(-1);
+constexpr ResultCode ERROR_INVALID_OPEN_FLAGS(-1);
+constexpr ResultCode ERROR_FILE_NOT_FOUND(-1);
+constexpr ResultCode ERROR_UNEXPECTED_FILE_OR_DIRECTORY(-1);
+constexpr ResultCode ERROR_DIRECTORY_ALREADY_EXISTS(-1);
+constexpr ResultCode ERROR_FILE_ALREADY_EXISTS(-1);
+constexpr ResultCode ERROR_DIRECTORY_NOT_EMPTY(-1);
} // namespace FileSys
diff --git a/src/core/file_sys/partition_filesystem.cpp b/src/core/file_sys/partition_filesystem.cpp
index 7ccca1089..8d2bd9f6b 100644
--- a/src/core/file_sys/partition_filesystem.cpp
+++ b/src/core/file_sys/partition_filesystem.cpp
@@ -2,7 +2,12 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <algorithm>
+#include <cstddef>
+#include <cstring>
+#include <iterator>
#include <utility>
+
#include "common/file_util.h"
#include "common/logging/log.h"
#include "core/file_sys/partition_filesystem.h"
@@ -99,14 +104,15 @@ void PartitionFilesystem::PrintDebugInfo() const {
}
bool PartitionFilesystem::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) {
- auto iter = std::find(pfs_files.begin(), pfs_files.end(), file);
+ const auto iter = std::find(pfs_files.begin(), pfs_files.end(), file);
if (iter == pfs_files.end())
return false;
- pfs_files[iter - pfs_files.begin()] = pfs_files.back();
+ const std::ptrdiff_t offset = std::distance(pfs_files.begin(), iter);
+ pfs_files[offset] = pfs_files.back();
pfs_files.pop_back();
- pfs_dirs.emplace_back(dir);
+ pfs_dirs.emplace_back(std::move(dir));
return true;
}
diff --git a/src/core/file_sys/vfs.cpp b/src/core/file_sys/vfs.cpp
index 16c8ad90b..3f690f12a 100644
--- a/src/core/file_sys/vfs.cpp
+++ b/src/core/file_sys/vfs.cpp
@@ -42,7 +42,7 @@ bool VfsFile::WriteByte(u8 data, size_t offset) {
return Write(&data, 1, offset) == 1;
}
-size_t VfsFile::WriteBytes(std::vector<u8> data, size_t offset) {
+size_t VfsFile::WriteBytes(const std::vector<u8>& data, size_t offset) {
return Write(data.data(), data.size(), offset);
}
diff --git a/src/core/file_sys/vfs.h b/src/core/file_sys/vfs.h
index a5213e0cc..db3c77eac 100644
--- a/src/core/file_sys/vfs.h
+++ b/src/core/file_sys/vfs.h
@@ -59,8 +59,7 @@ struct VfsFile : NonCopyable {
// Returns the number of bytes (sizeof(T)*number_elements) read successfully.
template <typename T>
size_t ReadArray(T* data, size_t number_elements, size_t offset = 0) const {
- static_assert(std::is_trivially_copyable<T>::value,
- "Data type must be trivially copyable.");
+ static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
return Read(reinterpret_cast<u8*>(data), number_elements * sizeof(T), offset);
}
@@ -69,8 +68,7 @@ struct VfsFile : NonCopyable {
// Returns the number of bytes read successfully.
template <typename T>
size_t ReadBytes(T* data, size_t size, size_t offset = 0) const {
- static_assert(std::is_trivially_copyable<T>::value,
- "Data type must be trivially copyable.");
+ static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
return Read(reinterpret_cast<u8*>(data), size, offset);
}
@@ -78,8 +76,7 @@ struct VfsFile : NonCopyable {
// Returns the number of bytes read successfully (sizeof(T)).
template <typename T>
size_t ReadObject(T* data, size_t offset = 0) const {
- static_assert(std::is_trivially_copyable<T>::value,
- "Data type must be trivially copyable.");
+ static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
return Read(reinterpret_cast<u8*>(data), sizeof(T), offset);
}
@@ -88,33 +85,29 @@ struct VfsFile : NonCopyable {
virtual bool WriteByte(u8 data, size_t offset = 0);
// Writes a vector of bytes to offset in file and returns the number of bytes successfully
// written.
- virtual size_t WriteBytes(std::vector<u8> data, size_t offset = 0);
+ virtual size_t WriteBytes(const std::vector<u8>& data, size_t offset = 0);
// Writes an array of type T, size number_elements to offset in file.
// Returns the number of bytes (sizeof(T)*number_elements) written successfully.
template <typename T>
- size_t WriteArray(T* data, size_t number_elements, size_t offset = 0) {
- static_assert(std::is_trivially_copyable<T>::value,
- "Data type must be trivially copyable.");
-
+ size_t WriteArray(const T* data, size_t number_elements, size_t offset = 0) {
+ static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
return Write(data, number_elements * sizeof(T), offset);
}
// Writes size bytes starting at memory location data to offset in file.
// Returns the number of bytes written successfully.
template <typename T>
- size_t WriteBytes(T* data, size_t size, size_t offset = 0) {
- static_assert(std::is_trivially_copyable<T>::value,
- "Data type must be trivially copyable.");
- return Write(reinterpret_cast<u8*>(data), size, offset);
+ size_t WriteBytes(const T* data, size_t size, size_t offset = 0) {
+ static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
+ return Write(reinterpret_cast<const u8*>(data), size, offset);
}
// Writes one object of type T to offset in file.
// Returns the number of bytes written successfully (sizeof(T)).
template <typename T>
size_t WriteObject(const T& data, size_t offset = 0) {
- static_assert(std::is_trivially_copyable<T>::value,
- "Data type must be trivially copyable.");
+ static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
return Write(&data, sizeof(T), offset);
}
diff --git a/src/core/file_sys/vfs_offset.cpp b/src/core/file_sys/vfs_offset.cpp
index 31fdd9aa1..217e02235 100644
--- a/src/core/file_sys/vfs_offset.cpp
+++ b/src/core/file_sys/vfs_offset.cpp
@@ -2,6 +2,7 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <algorithm>
#include <utility>
#include "core/file_sys/vfs_offset.h"
@@ -75,7 +76,7 @@ bool OffsetVfsFile::WriteByte(u8 data, size_t r_offset) {
return false;
}
-size_t OffsetVfsFile::WriteBytes(std::vector<u8> data, size_t r_offset) {
+size_t OffsetVfsFile::WriteBytes(const std::vector<u8>& data, size_t r_offset) {
return file->Write(data.data(), TrimToFit(data.size(), r_offset), offset + r_offset);
}
@@ -88,7 +89,7 @@ size_t OffsetVfsFile::GetOffset() const {
}
size_t OffsetVfsFile::TrimToFit(size_t r_size, size_t r_offset) const {
- return std::max<size_t>(std::min<size_t>(size - r_offset, r_size), 0);
+ return std::clamp(r_size, size_t{0}, size - r_offset);
}
} // namespace FileSys
diff --git a/src/core/file_sys/vfs_offset.h b/src/core/file_sys/vfs_offset.h
index 2e16e47eb..ded4827f5 100644
--- a/src/core/file_sys/vfs_offset.h
+++ b/src/core/file_sys/vfs_offset.h
@@ -28,7 +28,7 @@ struct OffsetVfsFile : public VfsFile {
std::vector<u8> ReadBytes(size_t size, size_t offset) const override;
std::vector<u8> ReadAllBytes() const override;
bool WriteByte(u8 data, size_t offset) override;
- size_t WriteBytes(std::vector<u8> data, size_t offset) override;
+ size_t WriteBytes(const std::vector<u8>& data, size_t offset) override;
bool Rename(const std::string& name) override;
diff --git a/src/core/file_sys/vfs_real.cpp b/src/core/file_sys/vfs_real.cpp
index 22c858e0d..f27fb1f2a 100644
--- a/src/core/file_sys/vfs_real.cpp
+++ b/src/core/file_sys/vfs_real.cpp
@@ -2,6 +2,11 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <algorithm>
+#include <cstddef>
+#include <iterator>
+#include <utility>
+
#include "common/common_paths.h"
#include "common/logging/log.h"
#include "core/file_sys/vfs_real.h"
@@ -104,11 +109,11 @@ RealVfsDirectory::RealVfsDirectory(const std::string& path_, Mode perms_)
}
std::vector<std::shared_ptr<VfsFile>> RealVfsDirectory::GetFiles() const {
- return std::vector<std::shared_ptr<VfsFile>>(files);
+ return files;
}
std::vector<std::shared_ptr<VfsDirectory>> RealVfsDirectory::GetSubdirectories() const {
- return std::vector<std::shared_ptr<VfsDirectory>>(subdirectories);
+ return subdirectories;
}
bool RealVfsDirectory::IsWritable() const {
@@ -163,14 +168,15 @@ bool RealVfsDirectory::Rename(const std::string& name) {
}
bool RealVfsDirectory::ReplaceFileWithSubdirectory(VirtualFile file, VirtualDir dir) {
- auto iter = std::find(files.begin(), files.end(), file);
+ const auto iter = std::find(files.begin(), files.end(), file);
if (iter == files.end())
return false;
- files[iter - files.begin()] = files.back();
+ const std::ptrdiff_t offset = std::distance(files.begin(), iter);
+ files[offset] = files.back();
files.pop_back();
- subdirectories.emplace_back(dir);
+ subdirectories.emplace_back(std::move(dir));
return true;
}
diff --git a/src/core/hle/ipc_helpers.h b/src/core/hle/ipc_helpers.h
index 24605a273..8b5b06f31 100644
--- a/src/core/hle/ipc_helpers.h
+++ b/src/core/hle/ipc_helpers.h
@@ -175,6 +175,25 @@ public:
void Push(const First& first_value, const Other&... other_values);
/**
+ * Helper function for pushing strongly-typed enumeration values.
+ *
+ * @tparam Enum The enumeration type to be pushed
+ *
+ * @param value The value to push.
+ *
+ * @note The underlying size of the enumeration type is the size of the
+ * data that gets pushed. e.g. "enum class SomeEnum : u16" will
+ * push a u16-sized amount of data.
+ */
+ template <typename Enum>
+ void PushEnum(Enum value) {
+ static_assert(std::is_enum_v<Enum>, "T must be an enum type within a PushEnum call.");
+ static_assert(!std::is_convertible_v<Enum, int>,
+ "enum type in PushEnum must be a strongly typed enum.");
+ Push(static_cast<std::underlying_type_t<Enum>>(value));
+ }
+
+ /**
* @brief Copies the content of the given trivially copyable class to the buffer as a normal
* param
* @note: The input class must be correctly packed/padded to fit hardware layout.
diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp
index f7e25cbf5..e307eec98 100644
--- a/src/core/hle/kernel/scheduler.cpp
+++ b/src/core/hle/kernel/scheduler.cpp
@@ -56,6 +56,8 @@ void Scheduler::SwitchContext(Thread* new_thread) {
if (previous_thread) {
previous_thread->last_running_ticks = CoreTiming::GetTicks();
cpu_core->SaveContext(previous_thread->context);
+ // Save the TPIDR_EL0 system register in case it was modified.
+ previous_thread->tpidr_el0 = cpu_core->GetTPIDR_EL0();
if (previous_thread->status == ThreadStatus::Running) {
// This is only the case when a reschedule is triggered without the current thread
@@ -87,6 +89,7 @@ void Scheduler::SwitchContext(Thread* new_thread) {
cpu_core->LoadContext(new_thread->context);
cpu_core->SetTlsAddress(new_thread->GetTLSAddress());
+ cpu_core->SetTPIDR_EL0(new_thread->GetTPIDR_EL0());
cpu_core->ClearExclusiveState();
} else {
current_thread = nullptr;
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 53f2e861e..cd85c4b7c 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -312,6 +312,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
thread->status = ThreadStatus::Dormant;
thread->entry_point = entry_point;
thread->stack_top = stack_top;
+ thread->tpidr_el0 = 0;
thread->nominal_priority = thread->current_priority = priority;
thread->last_running_ticks = CoreTiming::GetTicks();
thread->processor_id = processor_id;
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 47881ec20..6218960d2 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -183,6 +183,14 @@ public:
}
/*
+ * Returns the value of the TPIDR_EL0 Read/Write system register for this thread.
+ * @returns The value of the TPIDR_EL0 register.
+ */
+ u64 GetTPIDR_EL0() const {
+ return tpidr_el0;
+ }
+
+ /*
* Returns the address of the current thread's command buffer, located in the TLS.
* @returns VAddr of the thread's command buffer.
*/
@@ -213,6 +221,7 @@ public:
s32 processor_id;
VAddr tls_address; ///< Virtual address of the Thread Local Storage of the thread
+ u64 tpidr_el0; ///< TPIDR_EL0 read/write system register.
SharedPtr<Process> owner_process; ///< Process that owns this thread
diff --git a/src/core/hle/service/apm/interface.cpp b/src/core/hle/service/apm/interface.cpp
index 751d73f8d..ce943d829 100644
--- a/src/core/hle/service/apm/interface.cpp
+++ b/src/core/hle/service/apm/interface.cpp
@@ -20,6 +20,21 @@ public:
}
private:
+ enum class PerformanceConfiguration : u32 {
+ Config1 = 0x00010000,
+ Config2 = 0x00010001,
+ Config3 = 0x00010002,
+ Config4 = 0x00020000,
+ Config5 = 0x00020001,
+ Config6 = 0x00020002,
+ Config7 = 0x00020003,
+ Config8 = 0x00020004,
+ Config9 = 0x00020005,
+ Config10 = 0x00020006,
+ Config11 = 0x92220007,
+ Config12 = 0x92220008,
+ };
+
void SetPerformanceConfiguration(Kernel::HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
@@ -40,7 +55,7 @@ private:
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(RESULT_SUCCESS);
- rb.Push<u32>(0); // Performance configuration
+ rb.Push<u32>(static_cast<u32>(PerformanceConfiguration::Config1));
LOG_WARNING(Service_APM, "(STUBBED) called mode={}", static_cast<u32>(mode));
}
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp
index dffcdfbaf..671e0b8d0 100644
--- a/src/core/hle/service/filesystem/filesystem.cpp
+++ b/src/core/hle/service/filesystem/filesystem.cpp
@@ -272,9 +272,9 @@ void RegisterFileSystems() {
sdmc_factory = nullptr;
auto nand_directory = std::make_shared<FileSys::RealVfsDirectory>(
- FileUtil::GetUserPath(D_NAND_IDX), FileSys::Mode::Write);
+ FileUtil::GetUserPath(FileUtil::UserPath::NANDDir), FileSys::Mode::Write);
auto sd_directory = std::make_shared<FileSys::RealVfsDirectory>(
- FileUtil::GetUserPath(D_SDMC_IDX), FileSys::Mode::Write);
+ FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir), FileSys::Mode::Write);
auto savedata = std::make_unique<FileSys::SaveDataFactory>(std::move(nand_directory));
save_data_factory = std::move(savedata);
diff --git a/src/core/hle/service/ns/pl_u.cpp b/src/core/hle/service/ns/pl_u.cpp
index 691b1d106..bad27894a 100644
--- a/src/core/hle/service/ns/pl_u.cpp
+++ b/src/core/hle/service/ns/pl_u.cpp
@@ -42,7 +42,7 @@ PL_U::PL_U() : ServiceFramework("pl:u") {
RegisterHandlers(functions);
// Attempt to load shared font data from disk
- const std::string filepath{FileUtil::GetUserPath(D_SYSDATA_IDX) + SHARED_FONT};
+ const std::string filepath{FileUtil::GetUserPath(FileUtil::UserPath::SysDataDir) + SHARED_FONT};
FileUtil::CreateFullPath(filepath); // Create path if not already created
FileUtil::IOFile file(filepath, "rb");
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
index 8de870596..126782573 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.cpp
@@ -42,6 +42,9 @@ u32 nvhost_gpu::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u
if (command.cmd == NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO) {
return SubmitGPFIFO(input, output);
}
+ if (command.cmd == NVGPU_IOCTL_CHANNEL_KICKOFF_PB) {
+ return KickoffPB(input, output);
+ }
}
UNIMPLEMENTED_MSG("Unimplemented ioctl");
@@ -127,14 +130,37 @@ u32 nvhost_gpu::SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& outp
IoctlSubmitGpfifo params{};
std::memcpy(&params, input.data(), sizeof(IoctlSubmitGpfifo));
LOG_WARNING(Service_NVDRV, "(STUBBED) called, gpfifo={:X}, num_entries={:X}, flags={:X}",
- params.gpfifo, params.num_entries, params.flags);
+ params.address, params.num_entries, params.flags);
auto entries = std::vector<IoctlGpfifoEntry>();
entries.resize(params.num_entries);
std::memcpy(&entries[0], &input.data()[sizeof(IoctlSubmitGpfifo)],
params.num_entries * sizeof(IoctlGpfifoEntry));
for (auto entry : entries) {
- VAddr va_addr = entry.Address();
+ Tegra::GPUVAddr va_addr = entry.Address();
+ Core::System::GetInstance().GPU().ProcessCommandList(va_addr, entry.sz);
+ }
+ params.fence_out.id = 0;
+ params.fence_out.value = 0;
+ std::memcpy(output.data(), &params, output.size());
+ return 0;
+}
+
+u32 nvhost_gpu::KickoffPB(const std::vector<u8>& input, std::vector<u8>& output) {
+ if (input.size() < sizeof(IoctlSubmitGpfifo)) {
+ UNIMPLEMENTED();
+ }
+ IoctlSubmitGpfifo params{};
+ std::memcpy(&params, input.data(), sizeof(IoctlSubmitGpfifo));
+ LOG_WARNING(Service_NVDRV, "(STUBBED) called, gpfifo={:X}, num_entries={:X}, flags={:X}",
+ params.address, params.num_entries, params.flags);
+
+ std::vector<IoctlGpfifoEntry> entries(params.num_entries);
+ Memory::ReadBlock(params.address, entries.data(),
+ params.num_entries * sizeof(IoctlGpfifoEntry));
+
+ for (auto entry : entries) {
+ Tegra::GPUVAddr va_addr = entry.Address();
Core::System::GetInstance().GPU().ProcessCommandList(va_addr, entry.sz);
}
params.fence_out.id = 0;
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
index c9f6b9b6a..aa8df2e6e 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
+++ b/src/core/hle/service/nvdrv/devices/nvhost_gpu.h
@@ -15,6 +15,7 @@ namespace Service::Nvidia::Devices {
class nvmap;
constexpr u32 NVGPU_IOCTL_MAGIC('H');
constexpr u32 NVGPU_IOCTL_CHANNEL_SUBMIT_GPFIFO(0x8);
+constexpr u32 NVGPU_IOCTL_CHANNEL_KICKOFF_PB(0x1b);
class nvhost_gpu final : public nvdevice {
public:
@@ -158,14 +159,14 @@ private:
BitField<31, 1, u32_le> unk2;
};
- VAddr Address() const {
- return (static_cast<VAddr>(gpu_va_hi) << 32) | entry0;
+ Tegra::GPUVAddr Address() const {
+ return (static_cast<Tegra::GPUVAddr>(gpu_va_hi) << 32) | entry0;
}
};
static_assert(sizeof(IoctlGpfifoEntry) == 8, "IoctlGpfifoEntry is incorrect size");
struct IoctlSubmitGpfifo {
- u64_le gpfifo; // (ignored) pointer to gpfifo fence structs
+ u64_le address; // pointer to gpfifo entry structs
u32_le num_entries; // number of fence objects being submitted
u32_le flags;
IoctlFence fence_out; // returned new fence object for others to wait on
@@ -193,6 +194,7 @@ private:
u32 AllocGPFIFOEx2(const std::vector<u8>& input, std::vector<u8>& output);
u32 AllocateObjectContext(const std::vector<u8>& input, std::vector<u8>& output);
u32 SubmitGPFIFO(const std::vector<u8>& input, std::vector<u8>& output);
+ u32 KickoffPB(const std::vector<u8>& input, std::vector<u8>& output);
u32 GetWaitbase(const std::vector<u8>& input, std::vector<u8>& output);
u32 ChannelSetTimeout(const std::vector<u8>& input, std::vector<u8>& output);
diff --git a/src/core/hle/service/nvdrv/interface.cpp b/src/core/hle/service/nvdrv/interface.cpp
index b10efd5c9..1b497b814 100644
--- a/src/core/hle/service/nvdrv/interface.cpp
+++ b/src/core/hle/service/nvdrv/interface.cpp
@@ -101,7 +101,7 @@ NVDRV::NVDRV(std::shared_ptr<Module> nvdrv, const char* name)
{8, &NVDRV::SetClientPID, "SetClientPID"},
{9, nullptr, "DumpGraphicsMemoryInfo"},
{10, nullptr, "InitializeDevtools"},
- {11, nullptr, "Ioctl2"},
+ {11, &NVDRV::Ioctl, "Ioctl2"},
{12, nullptr, "Ioctl3"},
{13, &NVDRV::FinishInitialize, "FinishInitialize"},
};
diff --git a/src/core/loader/deconstructed_rom_directory.cpp b/src/core/loader/deconstructed_rom_directory.cpp
index 19b8667ba..394963a69 100644
--- a/src/core/loader/deconstructed_rom_directory.cpp
+++ b/src/core/loader/deconstructed_rom_directory.cpp
@@ -83,16 +83,13 @@ ResultStatus AppLoader_DeconstructedRomDirectory::Load(
VAddr next_load_addr{Memory::PROCESS_IMAGE_VADDR};
for (const auto& module : {"rtld", "main", "subsdk0", "subsdk1", "subsdk2", "subsdk3",
"subsdk4", "subsdk5", "subsdk6", "subsdk7", "sdk"}) {
- const VAddr load_addr = next_load_addr;
const FileSys::VirtualFile module_file = dir->GetFile(module);
- if (module_file != nullptr)
+ if (module_file != nullptr) {
+ const VAddr load_addr = next_load_addr;
next_load_addr = AppLoader_NSO::LoadModule(module_file, load_addr);
- if (next_load_addr) {
LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", module, load_addr);
// Register module with GDBStub
GDBStub::RegisterModule(module, load_addr, next_load_addr - 1, false);
- } else {
- next_load_addr = load_addr;
}
}
diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp
index b9a603df3..69aa7a7be 100644
--- a/src/core/telemetry_session.cpp
+++ b/src/core/telemetry_session.cpp
@@ -37,7 +37,8 @@ static u64 GenerateTelemetryId() {
u64 GetTelemetryId() {
u64 telemetry_id{};
- static const std::string& filename{FileUtil::GetUserPath(D_CONFIG_IDX) + "telemetry_id"};
+ static const std::string& filename{FileUtil::GetUserPath(FileUtil::UserPath::ConfigDir) +
+ "telemetry_id"};
if (FileUtil::Exists(filename)) {
FileUtil::IOFile file(filename, "rb");
@@ -61,7 +62,8 @@ u64 GetTelemetryId() {
u64 RegenerateTelemetryId() {
const u64 new_telemetry_id{GenerateTelemetryId()};
- static const std::string& filename{FileUtil::GetUserPath(D_CONFIG_IDX) + "telemetry_id"};
+ static const std::string& filename{FileUtil::GetUserPath(FileUtil::UserPath::ConfigDir) +
+ "telemetry_id"};
FileUtil::IOFile file(filename, "wb");
if (!file.IsOpen()) {