aboutsummaryrefslogtreecommitdiff
path: root/src/core/hle/service
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/service')
-rw-r--r--src/core/hle/service/audio/hwopus.cpp37
-rw-r--r--src/core/hle/service/filesystem/filesystem.cpp16
-rw-r--r--src/core/hle/service/filesystem/filesystem.h4
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp20
-rw-r--r--src/core/hle/service/nvdrv/devices/nvmap.cpp72
-rw-r--r--src/core/hle/service/service.cpp4
-rw-r--r--src/core/hle/service/service.h3
7 files changed, 121 insertions, 35 deletions
diff --git a/src/core/hle/service/audio/hwopus.cpp b/src/core/hle/service/audio/hwopus.cpp
index fc6067e59..7168c6a10 100644
--- a/src/core/hle/service/audio/hwopus.cpp
+++ b/src/core/hle/service/audio/hwopus.cpp
@@ -2,8 +2,10 @@
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
+#include <chrono>
#include <cstring>
#include <memory>
+#include <optional>
#include <vector>
#include <opus.h>
@@ -33,7 +35,8 @@ public:
{1, nullptr, "SetContext"},
{2, nullptr, "DecodeInterleavedForMultiStream"},
{3, nullptr, "SetContextForMultiStream"},
- {4, nullptr, "Unknown4"},
+ {4, &IHardwareOpusDecoderManager::DecodeInterleavedWithPerformance,
+ "DecodeInterleavedWithPerformance"},
{5, nullptr, "Unknown5"},
{6, nullptr, "Unknown6"},
{7, nullptr, "Unknown7"},
@@ -59,8 +62,31 @@ private:
ctx.WriteBuffer(samples.data(), samples.size() * sizeof(s16));
}
- bool Decoder_DecodeInterleaved(u32& consumed, u32& sample_count, const std::vector<u8>& input,
- std::vector<opus_int16>& output) {
+ void DecodeInterleavedWithPerformance(Kernel::HLERequestContext& ctx) {
+ u32 consumed = 0;
+ u32 sample_count = 0;
+ u64 performance = 0;
+ std::vector<opus_int16> samples(ctx.GetWriteBufferSize() / sizeof(opus_int16));
+ if (!Decoder_DecodeInterleaved(consumed, sample_count, ctx.ReadBuffer(), samples,
+ performance)) {
+ IPC::ResponseBuilder rb{ctx, 2};
+ // TODO(ogniK): Use correct error code
+ rb.Push(ResultCode(-1));
+ return;
+ }
+ IPC::ResponseBuilder rb{ctx, 6};
+ rb.Push(RESULT_SUCCESS);
+ rb.Push<u32>(consumed);
+ rb.Push<u64>(performance);
+ rb.Push<u32>(sample_count);
+ ctx.WriteBuffer(samples.data(), samples.size() * sizeof(s16));
+ }
+
+ bool Decoder_DecodeInterleaved(
+ u32& consumed, u32& sample_count, const std::vector<u8>& input,
+ std::vector<opus_int16>& output,
+ std::optional<std::reference_wrapper<u64>> performance_time = std::nullopt) {
+ const auto start_time = std::chrono::high_resolution_clock::now();
std::size_t raw_output_sz = output.size() * sizeof(opus_int16);
if (sizeof(OpusHeader) > input.size())
return false;
@@ -80,8 +106,13 @@ private:
(static_cast<int>(raw_output_sz / sizeof(s16) / channel_count)), 0);
if (out_sample_count < 0)
return false;
+ const auto end_time = std::chrono::high_resolution_clock::now() - start_time;
sample_count = out_sample_count;
consumed = static_cast<u32>(sizeof(OpusHeader) + hdr.sz);
+ if (performance_time.has_value()) {
+ performance_time->get() =
+ std::chrono::duration_cast<std::chrono::milliseconds>(end_time).count();
+ }
return true;
}
diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp
index 439e62d27..e06712603 100644
--- a/src/core/hle/service/filesystem/filesystem.cpp
+++ b/src/core/hle/service/filesystem/filesystem.cpp
@@ -361,19 +361,19 @@ FileSys::VirtualDir GetModificationLoadRoot(u64 title_id) {
return bis_factory->GetModificationLoadRoot(title_id);
}
-void CreateFactories(const FileSys::VirtualFilesystem& vfs, bool overwrite) {
+void CreateFactories(FileSys::VfsFilesystem& vfs, bool overwrite) {
if (overwrite) {
bis_factory = nullptr;
save_data_factory = nullptr;
sdmc_factory = nullptr;
}
- auto nand_directory = vfs->OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir),
- FileSys::Mode::ReadWrite);
- auto sd_directory = vfs->OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir),
- FileSys::Mode::ReadWrite);
- auto load_directory = vfs->OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::LoadDir),
- FileSys::Mode::ReadWrite);
+ auto nand_directory = vfs.OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::NANDDir),
+ FileSys::Mode::ReadWrite);
+ auto sd_directory = vfs.OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::SDMCDir),
+ FileSys::Mode::ReadWrite);
+ auto load_directory = vfs.OpenDirectory(FileUtil::GetUserPath(FileUtil::UserPath::LoadDir),
+ FileSys::Mode::ReadWrite);
if (bis_factory == nullptr)
bis_factory = std::make_unique<FileSys::BISFactory>(nand_directory, load_directory);
@@ -383,7 +383,7 @@ void CreateFactories(const FileSys::VirtualFilesystem& vfs, bool overwrite) {
sdmc_factory = std::make_unique<FileSys::SDMCFactory>(std::move(sd_directory));
}
-void InstallInterfaces(SM::ServiceManager& service_manager, const FileSys::VirtualFilesystem& vfs) {
+void InstallInterfaces(SM::ServiceManager& service_manager, FileSys::VfsFilesystem& vfs) {
romfs_factory = nullptr;
CreateFactories(vfs, false);
std::make_shared<FSP_LDR>()->InstallAsService(service_manager);
diff --git a/src/core/hle/service/filesystem/filesystem.h b/src/core/hle/service/filesystem/filesystem.h
index 53b01bb01..2df1faeb0 100644
--- a/src/core/hle/service/filesystem/filesystem.h
+++ b/src/core/hle/service/filesystem/filesystem.h
@@ -57,9 +57,9 @@ FileSys::VirtualDir GetModificationLoadRoot(u64 title_id);
// Creates the SaveData, SDMC, and BIS Factories. Should be called once and before any function
// above is called.
-void CreateFactories(const FileSys::VirtualFilesystem& vfs, bool overwrite = true);
+void CreateFactories(FileSys::VfsFilesystem& vfs, bool overwrite = true);
-void InstallInterfaces(SM::ServiceManager& service_manager, const FileSys::VirtualFilesystem& vfs);
+void InstallInterfaces(SM::ServiceManager& service_manager, FileSys::VfsFilesystem& vfs);
// A class that wraps a VfsDirectory with methods that return ResultVal and ResultCode instead of
// pointers and booleans. This makes using a VfsDirectory with switch services much easier and
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
index 7555bbe7d..c41ef7058 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
@@ -15,6 +15,11 @@
#include "video_core/renderer_base.h"
namespace Service::Nvidia::Devices {
+namespace NvErrCodes {
+enum {
+ InvalidNmapHandle = -22,
+};
+}
nvhost_as_gpu::nvhost_as_gpu(std::shared_ptr<nvmap> nvmap_dev) : nvmap_dev(std::move(nvmap_dev)) {}
nvhost_as_gpu::~nvhost_as_gpu() = default;
@@ -79,14 +84,16 @@ u32 nvhost_as_gpu::Remap(const std::vector<u8>& input, std::vector<u8>& output)
std::memcpy(entries.data(), input.data(), input.size());
auto& gpu = Core::System::GetInstance().GPU();
-
for (const auto& entry : entries) {
LOG_WARNING(Service_NVDRV, "remap entry, offset=0x{:X} handle=0x{:X} pages=0x{:X}",
entry.offset, entry.nvmap_handle, entry.pages);
Tegra::GPUVAddr offset = static_cast<Tegra::GPUVAddr>(entry.offset) << 0x10;
-
auto object = nvmap_dev->GetObject(entry.nvmap_handle);
- ASSERT(object);
+ if (!object) {
+ LOG_CRITICAL(Service_NVDRV, "nvmap {} is an invalid handle!", entry.nvmap_handle);
+ std::memcpy(output.data(), entries.data(), output.size());
+ return static_cast<u32>(NvErrCodes::InvalidNmapHandle);
+ }
ASSERT(object->status == nvmap::Object::Status::Allocated);
@@ -167,10 +174,11 @@ u32 nvhost_as_gpu::UnmapBuffer(const std::vector<u8>& input, std::vector<u8>& ou
auto& system_instance = Core::System::GetInstance();
// Remove this memory region from the rasterizer cache.
- system_instance.Renderer().Rasterizer().FlushAndInvalidateRegion(params.offset,
- itr->second.size);
-
auto& gpu = system_instance.GPU();
+ auto cpu_addr = gpu.MemoryManager().GpuToCpuAddress(params.offset);
+ ASSERT(cpu_addr);
+ system_instance.Renderer().Rasterizer().FlushAndInvalidateRegion(*cpu_addr, itr->second.size);
+
params.offset = gpu.MemoryManager().UnmapBuffer(params.offset, itr->second.size);
buffer_mappings.erase(itr->second.offset);
diff --git a/src/core/hle/service/nvdrv/devices/nvmap.cpp b/src/core/hle/service/nvdrv/devices/nvmap.cpp
index a2287cc1b..43651d8a6 100644
--- a/src/core/hle/service/nvdrv/devices/nvmap.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvmap.cpp
@@ -11,6 +11,13 @@
namespace Service::Nvidia::Devices {
+namespace NvErrCodes {
+enum {
+ OperationNotPermitted = -1,
+ InvalidValue = -22,
+};
+}
+
nvmap::nvmap() = default;
nvmap::~nvmap() = default;
@@ -44,7 +51,11 @@ u32 nvmap::ioctl(Ioctl command, const std::vector<u8>& input, std::vector<u8>& o
u32 nvmap::IocCreate(const std::vector<u8>& input, std::vector<u8>& output) {
IocCreateParams params;
std::memcpy(&params, input.data(), sizeof(params));
+ LOG_DEBUG(Service_NVDRV, "size=0x{:08X}", params.size);
+ if (!params.size) {
+ return static_cast<u32>(NvErrCodes::InvalidValue);
+ }
// Create a new nvmap object and obtain a handle to it.
auto object = std::make_shared<Object>();
object->id = next_id++;
@@ -55,8 +66,6 @@ u32 nvmap::IocCreate(const std::vector<u8>& input, std::vector<u8>& output) {
u32 handle = next_handle++;
handles[handle] = std::move(object);
- LOG_DEBUG(Service_NVDRV, "size=0x{:08X}", params.size);
-
params.handle = handle;
std::memcpy(output.data(), &params, sizeof(params));
@@ -66,9 +75,29 @@ u32 nvmap::IocCreate(const std::vector<u8>& input, std::vector<u8>& output) {
u32 nvmap::IocAlloc(const std::vector<u8>& input, std::vector<u8>& output) {
IocAllocParams params;
std::memcpy(&params, input.data(), sizeof(params));
+ LOG_DEBUG(Service_NVDRV, "called, addr={:X}", params.addr);
+
+ if (!params.handle) {
+ return static_cast<u32>(NvErrCodes::InvalidValue);
+ }
+
+ if ((params.align - 1) & params.align) {
+ return static_cast<u32>(NvErrCodes::InvalidValue);
+ }
+
+ const u32 min_alignment = 0x1000;
+ if (params.align < min_alignment) {
+ params.align = min_alignment;
+ }
auto object = GetObject(params.handle);
- ASSERT(object);
+ if (!object) {
+ return static_cast<u32>(NvErrCodes::InvalidValue);
+ }
+
+ if (object->status == Object::Status::Allocated) {
+ return static_cast<u32>(NvErrCodes::OperationNotPermitted);
+ }
object->flags = params.flags;
object->align = params.align;
@@ -76,8 +105,6 @@ u32 nvmap::IocAlloc(const std::vector<u8>& input, std::vector<u8>& output) {
object->addr = params.addr;
object->status = Object::Status::Allocated;
- LOG_DEBUG(Service_NVDRV, "called, addr={:X}", params.addr);
-
std::memcpy(output.data(), &params, sizeof(params));
return 0;
}
@@ -88,8 +115,14 @@ u32 nvmap::IocGetId(const std::vector<u8>& input, std::vector<u8>& output) {
LOG_WARNING(Service_NVDRV, "called");
+ if (!params.handle) {
+ return static_cast<u32>(NvErrCodes::InvalidValue);
+ }
+
auto object = GetObject(params.handle);
- ASSERT(object);
+ if (!object) {
+ return static_cast<u32>(NvErrCodes::OperationNotPermitted);
+ }
params.id = object->id;
@@ -105,7 +138,14 @@ u32 nvmap::IocFromId(const std::vector<u8>& input, std::vector<u8>& output) {
auto itr = std::find_if(handles.begin(), handles.end(),
[&](const auto& entry) { return entry.second->id == params.id; });
- ASSERT(itr != handles.end());
+ if (itr == handles.end()) {
+ return static_cast<u32>(NvErrCodes::InvalidValue);
+ }
+
+ auto& object = itr->second;
+ if (object->status != Object::Status::Allocated) {
+ return static_cast<u32>(NvErrCodes::InvalidValue);
+ }
itr->second->refcount++;
@@ -125,8 +165,13 @@ u32 nvmap::IocParam(const std::vector<u8>& input, std::vector<u8>& output) {
LOG_WARNING(Service_NVDRV, "(STUBBED) called type={}", params.param);
auto object = GetObject(params.handle);
- ASSERT(object);
- ASSERT(object->status == Object::Status::Allocated);
+ if (!object) {
+ return static_cast<u32>(NvErrCodes::InvalidValue);
+ }
+
+ if (object->status != Object::Status::Allocated) {
+ return static_cast<u32>(NvErrCodes::OperationNotPermitted);
+ }
switch (static_cast<ParamTypes>(params.param)) {
case ParamTypes::Size:
@@ -163,9 +208,12 @@ u32 nvmap::IocFree(const std::vector<u8>& input, std::vector<u8>& output) {
LOG_WARNING(Service_NVDRV, "(STUBBED) called");
auto itr = handles.find(params.handle);
- ASSERT(itr != handles.end());
-
- ASSERT(itr->second->refcount > 0);
+ if (itr == handles.end()) {
+ return static_cast<u32>(NvErrCodes::InvalidValue);
+ }
+ if (!itr->second->refcount) {
+ return static_cast<u32>(NvErrCodes::InvalidValue);
+ }
itr->second->refcount--;
diff --git a/src/core/hle/service/service.cpp b/src/core/hle/service/service.cpp
index 62f049660..a225cb4cb 100644
--- a/src/core/hle/service/service.cpp
+++ b/src/core/hle/service/service.cpp
@@ -197,7 +197,7 @@ ResultCode ServiceFrameworkBase::HandleSyncRequest(Kernel::HLERequestContext& co
// Module interface
/// Initialize ServiceManager
-void Init(std::shared_ptr<SM::ServiceManager>& sm, const FileSys::VirtualFilesystem& rfs) {
+void Init(std::shared_ptr<SM::ServiceManager>& sm, FileSys::VfsFilesystem& vfs) {
// NVFlinger needs to be accessed by several services like Vi and AppletOE so we instantiate it
// here and pass it into the respective InstallInterfaces functions.
auto nv_flinger = std::make_shared<NVFlinger::NVFlinger>();
@@ -220,7 +220,7 @@ void Init(std::shared_ptr<SM::ServiceManager>& sm, const FileSys::VirtualFilesys
EUPLD::InstallInterfaces(*sm);
Fatal::InstallInterfaces(*sm);
FGM::InstallInterfaces(*sm);
- FileSystem::InstallInterfaces(*sm, rfs);
+ FileSystem::InstallInterfaces(*sm, vfs);
Friend::InstallInterfaces(*sm);
GRC::InstallInterfaces(*sm);
HID::InstallInterfaces(*sm);
diff --git a/src/core/hle/service/service.h b/src/core/hle/service/service.h
index 2fc57a82e..98483ecf1 100644
--- a/src/core/hle/service/service.h
+++ b/src/core/hle/service/service.h
@@ -180,8 +180,7 @@ private:
};
/// Initialize ServiceManager
-void Init(std::shared_ptr<SM::ServiceManager>& sm,
- const std::shared_ptr<FileSys::VfsFilesystem>& vfs);
+void Init(std::shared_ptr<SM::ServiceManager>& sm, FileSys::VfsFilesystem& vfs);
/// Shutdown ServiceManager
void Shutdown();