summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/hle/kernel/init/init_slab_setup.cpp2
-rw-r--r--src/core/hle/kernel/k_device_address_space.cpp150
-rw-r--r--src/core/hle/kernel/k_device_address_space.h60
-rw-r--r--src/core/hle/kernel/kernel.h4
-rw-r--r--src/core/hle/kernel/svc_types.h14
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.cpp2
-rw-r--r--src/yuzu/multiplayer/lobby.cpp16
-rw-r--r--src/yuzu/multiplayer/lobby.h2
-rw-r--r--src/yuzu/multiplayer/lobby.ui7
10 files changed, 258 insertions, 1 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 3eee1cfbe..112c61b80 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -195,6 +195,8 @@ add_library(core STATIC
hle/kernel/k_condition_variable.cpp
hle/kernel/k_condition_variable.h
hle/kernel/k_debug.h
+ hle/kernel/k_device_address_space.cpp
+ hle/kernel/k_device_address_space.h
hle/kernel/k_dynamic_page_manager.h
hle/kernel/k_dynamic_resource_manager.h
hle/kernel/k_dynamic_slab_heap.h
diff --git a/src/core/hle/kernel/init/init_slab_setup.cpp b/src/core/hle/kernel/init/init_slab_setup.cpp
index 7b363eb1e..571acf4b2 100644
--- a/src/core/hle/kernel/init/init_slab_setup.cpp
+++ b/src/core/hle/kernel/init/init_slab_setup.cpp
@@ -11,6 +11,7 @@
#include "core/hle/kernel/init/init_slab_setup.h"
#include "core/hle/kernel/k_code_memory.h"
#include "core/hle/kernel/k_debug.h"
+#include "core/hle/kernel/k_device_address_space.h"
#include "core/hle/kernel/k_event.h"
#include "core/hle/kernel/k_event_info.h"
#include "core/hle/kernel/k_memory_layout.h"
@@ -43,6 +44,7 @@ namespace Kernel::Init {
HANDLER(KSharedMemoryInfo, (SLAB_COUNT(KSharedMemory) * 8), ##__VA_ARGS__) \
HANDLER(KTransferMemory, (SLAB_COUNT(KTransferMemory)), ##__VA_ARGS__) \
HANDLER(KCodeMemory, (SLAB_COUNT(KCodeMemory)), ##__VA_ARGS__) \
+ HANDLER(KDeviceAddressSpace, (SLAB_COUNT(KDeviceAddressSpace)), ##__VA_ARGS__) \
HANDLER(KSession, (SLAB_COUNT(KSession)), ##__VA_ARGS__) \
HANDLER(KThreadLocalPage, \
(SLAB_COUNT(KProcess) + (SLAB_COUNT(KProcess) + SLAB_COUNT(KThread)) / 8), \
diff --git a/src/core/hle/kernel/k_device_address_space.cpp b/src/core/hle/kernel/k_device_address_space.cpp
new file mode 100644
index 000000000..27659ea3b
--- /dev/null
+++ b/src/core/hle/kernel/k_device_address_space.cpp
@@ -0,0 +1,150 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "common/assert.h"
+#include "core/core.h"
+#include "core/hle/kernel/k_device_address_space.h"
+#include "core/hle/kernel/kernel.h"
+#include "core/hle/kernel/svc_results.h"
+
+namespace Kernel {
+
+KDeviceAddressSpace::KDeviceAddressSpace(KernelCore& kernel_)
+ : KAutoObjectWithSlabHeapAndContainer(kernel_), m_lock(kernel_), m_is_initialized(false) {}
+KDeviceAddressSpace::~KDeviceAddressSpace() = default;
+
+void KDeviceAddressSpace::Initialize() {
+ // This just forwards to the device page table manager.
+ // KDevicePageTable::Initialize();
+}
+
+// Member functions.
+Result KDeviceAddressSpace::Initialize(u64 address, u64 size) {
+ // Initialize the device page table.
+ // R_TRY(m_table.Initialize(address, size));
+
+ // Set member variables.
+ m_space_address = address;
+ m_space_size = size;
+ m_is_initialized = true;
+
+ R_SUCCEED();
+}
+
+void KDeviceAddressSpace::Finalize() {
+ // Finalize the table.
+ // m_table.Finalize();
+}
+
+Result KDeviceAddressSpace::Attach(Svc::DeviceName device_name) {
+ // Lock the address space.
+ KScopedLightLock lk(m_lock);
+
+ // Attach.
+ // R_RETURN(m_table.Attach(device_name, m_space_address, m_space_size));
+ R_SUCCEED();
+}
+
+Result KDeviceAddressSpace::Detach(Svc::DeviceName device_name) {
+ // Lock the address space.
+ KScopedLightLock lk(m_lock);
+
+ // Detach.
+ // R_RETURN(m_table.Detach(device_name));
+ R_SUCCEED();
+}
+
+Result KDeviceAddressSpace::Map(KPageTable* page_table, VAddr process_address, size_t size,
+ u64 device_address, u32 option, bool is_aligned) {
+ // Check that the address falls within the space.
+ R_UNLESS((m_space_address <= device_address &&
+ device_address + size - 1 <= m_space_address + m_space_size - 1),
+ ResultInvalidCurrentMemory);
+
+ // Decode the option.
+ const Svc::MapDeviceAddressSpaceOption option_pack{option};
+ const auto device_perm = option_pack.permission.Value();
+ const auto flags = option_pack.flags.Value();
+ const auto reserved = option_pack.reserved.Value();
+
+ // Validate the option.
+ // TODO: It is likely that this check for flags == none is only on NX board.
+ R_UNLESS(flags == Svc::MapDeviceAddressSpaceFlag::None, ResultInvalidEnumValue);
+ R_UNLESS(reserved == 0, ResultInvalidEnumValue);
+
+ // Lock the address space.
+ KScopedLightLock lk(m_lock);
+
+ // Lock the page table to prevent concurrent device mapping operations.
+ // KScopedLightLock pt_lk = page_table->AcquireDeviceMapLock();
+
+ // Lock the pages.
+ bool is_io{};
+ R_TRY(page_table->LockForMapDeviceAddressSpace(std::addressof(is_io), process_address, size,
+ ConvertToKMemoryPermission(device_perm),
+ is_aligned, true));
+
+ // Ensure that if we fail, we don't keep unmapped pages locked.
+ ON_RESULT_FAILURE {
+ ASSERT(page_table->UnlockForDeviceAddressSpace(process_address, size) == ResultSuccess);
+ };
+
+ // Check that the io status is allowable.
+ if (is_io) {
+ R_UNLESS(static_cast<u32>(flags & Svc::MapDeviceAddressSpaceFlag::NotIoRegister) == 0,
+ ResultInvalidCombination);
+ }
+
+ // Map the pages.
+ {
+ // Perform the mapping.
+ // R_TRY(m_table.Map(page_table, process_address, size, device_address, device_perm,
+ // is_aligned, is_io));
+
+ // Ensure that we unmap the pages if we fail to update the protections.
+ // NOTE: Nintendo does not check the result of this unmap call.
+ // ON_RESULT_FAILURE { m_table.Unmap(device_address, size); };
+
+ // Update the protections in accordance with how much we mapped.
+ // R_TRY(page_table->UnlockForDeviceAddressSpacePartialMap(process_address, size));
+ }
+
+ // We succeeded.
+ R_SUCCEED();
+}
+
+Result KDeviceAddressSpace::Unmap(KPageTable* page_table, VAddr process_address, size_t size,
+ u64 device_address) {
+ // Check that the address falls within the space.
+ R_UNLESS((m_space_address <= device_address &&
+ device_address + size - 1 <= m_space_address + m_space_size - 1),
+ ResultInvalidCurrentMemory);
+
+ // Lock the address space.
+ KScopedLightLock lk(m_lock);
+
+ // Lock the page table to prevent concurrent device mapping operations.
+ // KScopedLightLock pt_lk = page_table->AcquireDeviceMapLock();
+
+ // Lock the pages.
+ R_TRY(page_table->LockForUnmapDeviceAddressSpace(process_address, size, true));
+
+ // Unmap the pages.
+ {
+ // If we fail to unmap, we want to do a partial unlock.
+ // ON_RESULT_FAILURE {
+ // ASSERT(page_table->UnlockForDeviceAddressSpacePartialMap(process_address, size) ==
+ // ResultSuccess);
+ // };
+
+ // Perform the unmap.
+ // R_TRY(m_table.Unmap(page_table, process_address, size, device_address));
+ }
+
+ // Unlock the pages.
+ ASSERT(page_table->UnlockForDeviceAddressSpace(process_address, size) == ResultSuccess);
+
+ R_SUCCEED();
+}
+
+} // namespace Kernel
diff --git a/src/core/hle/kernel/k_device_address_space.h b/src/core/hle/kernel/k_device_address_space.h
new file mode 100644
index 000000000..4709df995
--- /dev/null
+++ b/src/core/hle/kernel/k_device_address_space.h
@@ -0,0 +1,60 @@
+// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <string>
+
+#include "common/common_types.h"
+#include "core/hle/kernel/k_page_table.h"
+#include "core/hle/kernel/slab_helpers.h"
+#include "core/hle/result.h"
+
+namespace Kernel {
+
+class KDeviceAddressSpace final
+ : public KAutoObjectWithSlabHeapAndContainer<KDeviceAddressSpace, KAutoObjectWithList> {
+ KERNEL_AUTOOBJECT_TRAITS(KDeviceAddressSpace, KAutoObject);
+
+public:
+ explicit KDeviceAddressSpace(KernelCore& kernel);
+ ~KDeviceAddressSpace();
+
+ Result Initialize(u64 address, u64 size);
+ void Finalize();
+
+ bool IsInitialized() const {
+ return m_is_initialized;
+ }
+ static void PostDestroy(uintptr_t arg) {}
+
+ Result Attach(Svc::DeviceName device_name);
+ Result Detach(Svc::DeviceName device_name);
+
+ Result MapByForce(KPageTable* page_table, VAddr process_address, size_t size,
+ u64 device_address, u32 option) {
+ R_RETURN(this->Map(page_table, process_address, size, device_address, option, false));
+ }
+
+ Result MapAligned(KPageTable* page_table, VAddr process_address, size_t size,
+ u64 device_address, u32 option) {
+ R_RETURN(this->Map(page_table, process_address, size, device_address, option, true));
+ }
+
+ Result Unmap(KPageTable* page_table, VAddr process_address, size_t size, u64 device_address);
+
+ static void Initialize();
+
+private:
+ Result Map(KPageTable* page_table, VAddr process_address, size_t size, u64 device_address,
+ u32 option, bool is_aligned);
+
+private:
+ KLightLock m_lock;
+ // KDevicePageTable m_table;
+ u64 m_space_address{};
+ u64 m_space_size{};
+ bool m_is_initialized{};
+};
+
+} // namespace Kernel
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 8d22f8d2c..5f52e1e95 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -35,6 +35,7 @@ class GlobalSchedulerContext;
class KAutoObjectWithListContainer;
class KClientSession;
class KDebug;
+class KDeviceAddressSpace;
class KDynamicPageManager;
class KEvent;
class KEventInfo;
@@ -359,6 +360,8 @@ public:
return slab_heap_container->transfer_memory;
} else if constexpr (std::is_same_v<T, KCodeMemory>) {
return slab_heap_container->code_memory;
+ } else if constexpr (std::is_same_v<T, KDeviceAddressSpace>) {
+ return slab_heap_container->device_address_space;
} else if constexpr (std::is_same_v<T, KPageBuffer>) {
return slab_heap_container->page_buffer;
} else if constexpr (std::is_same_v<T, KThreadLocalPage>) {
@@ -431,6 +434,7 @@ private:
KSlabHeap<KThread> thread;
KSlabHeap<KTransferMemory> transfer_memory;
KSlabHeap<KCodeMemory> code_memory;
+ KSlabHeap<KDeviceAddressSpace> device_address_space;
KSlabHeap<KPageBuffer> page_buffer;
KSlabHeap<KThreadLocalPage> thread_local_page;
KSlabHeap<KSessionRequest> session_request;
diff --git a/src/core/hle/kernel/svc_types.h b/src/core/hle/kernel/svc_types.h
index 9c2f9998a..e90c35601 100644
--- a/src/core/hle/kernel/svc_types.h
+++ b/src/core/hle/kernel/svc_types.h
@@ -5,6 +5,7 @@
#include <bitset>
+#include "common/bit_field.h"
#include "common/common_funcs.h"
#include "common/common_types.h"
@@ -498,6 +499,19 @@ enum class MemoryMapping : u32 {
Memory = 2,
};
+enum class MapDeviceAddressSpaceFlag : u32 {
+ None = (0U << 0),
+ NotIoRegister = (1U << 0),
+};
+DECLARE_ENUM_FLAG_OPERATORS(MapDeviceAddressSpaceFlag);
+
+union MapDeviceAddressSpaceOption {
+ u32 raw;
+ BitField<0, 16, MemoryPermission> permission;
+ BitField<16, 1, MapDeviceAddressSpaceFlag> flags;
+ BitField<17, 15, u32> reserved;
+};
+
enum class KernelDebugType : u32 {
Thread = 0,
ThreadCallStack = 1,
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp
index cab44bf9c..447d624e1 100644
--- a/src/core/hle/service/filesystem/fsp_srv.cpp
+++ b/src/core/hle/service/filesystem/fsp_srv.cpp
@@ -1083,7 +1083,7 @@ void FSP_SRV::GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx) {
}
void FSP_SRV::OutputAccessLogToSdCard(Kernel::HLERequestContext& ctx) {
- const auto raw = ctx.ReadBuffer();
+ const auto raw = ctx.ReadBufferCopy();
auto log = Common::StringFromFixedZeroTerminatedBuffer(
reinterpret_cast<const char*>(raw.data()), raw.size());
diff --git a/src/yuzu/multiplayer/lobby.cpp b/src/yuzu/multiplayer/lobby.cpp
index 08c275696..6c93e3511 100644
--- a/src/yuzu/multiplayer/lobby.cpp
+++ b/src/yuzu/multiplayer/lobby.cpp
@@ -77,6 +77,7 @@ Lobby::Lobby(QWidget* parent, QStandardItemModel* list,
// UI Buttons
connect(ui->refresh_list, &QPushButton::clicked, this, &Lobby::RefreshLobby);
connect(ui->games_owned, &QCheckBox::toggled, proxy, &LobbyFilterProxyModel::SetFilterOwned);
+ connect(ui->hide_empty, &QCheckBox::toggled, proxy, &LobbyFilterProxyModel::SetFilterEmpty);
connect(ui->hide_full, &QCheckBox::toggled, proxy, &LobbyFilterProxyModel::SetFilterFull);
connect(ui->search, &QLineEdit::textChanged, proxy, &LobbyFilterProxyModel::SetFilterSearch);
connect(ui->room_list, &QTreeView::doubleClicked, this, &Lobby::OnJoinRoom);
@@ -329,6 +330,16 @@ bool LobbyFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex& s
return true;
}
+ // filter by empty rooms
+ if (filter_empty) {
+ QModelIndex member_list = sourceModel()->index(sourceRow, Column::MEMBER, sourceParent);
+ int player_count =
+ sourceModel()->data(member_list, LobbyItemMemberList::MemberListRole).toList().size();
+ if (player_count == 0) {
+ return false;
+ }
+ }
+
// filter by filled rooms
if (filter_full) {
QModelIndex member_list = sourceModel()->index(sourceRow, Column::MEMBER, sourceParent);
@@ -399,6 +410,11 @@ void LobbyFilterProxyModel::SetFilterOwned(bool filter) {
invalidate();
}
+void LobbyFilterProxyModel::SetFilterEmpty(bool filter) {
+ filter_empty = filter;
+ invalidate();
+}
+
void LobbyFilterProxyModel::SetFilterFull(bool filter) {
filter_full = filter;
invalidate();
diff --git a/src/yuzu/multiplayer/lobby.h b/src/yuzu/multiplayer/lobby.h
index 300dad13e..2674ae7c3 100644
--- a/src/yuzu/multiplayer/lobby.h
+++ b/src/yuzu/multiplayer/lobby.h
@@ -130,12 +130,14 @@ public:
public slots:
void SetFilterOwned(bool);
+ void SetFilterEmpty(bool);
void SetFilterFull(bool);
void SetFilterSearch(const QString&);
private:
QStandardItemModel* game_list;
bool filter_owned = false;
+ bool filter_empty = false;
bool filter_full = false;
QString filter_search;
};
diff --git a/src/yuzu/multiplayer/lobby.ui b/src/yuzu/multiplayer/lobby.ui
index 4c9901c9a..0ef0ef762 100644
--- a/src/yuzu/multiplayer/lobby.ui
+++ b/src/yuzu/multiplayer/lobby.ui
@@ -78,6 +78,13 @@
</widget>
</item>
<item>
+ <widget class="QCheckBox" name="hide_empty">
+ <property name="text">
+ <string>Hide Empty Rooms</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<widget class="QCheckBox" name="hide_full">
<property name="text">
<string>Hide Full Rooms</string>