summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-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
6 files changed, 232 insertions, 0 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
195 hle/kernel/k_condition_variable.cpp 195 hle/kernel/k_condition_variable.cpp
196 hle/kernel/k_condition_variable.h 196 hle/kernel/k_condition_variable.h
197 hle/kernel/k_debug.h 197 hle/kernel/k_debug.h
198 hle/kernel/k_device_address_space.cpp
199 hle/kernel/k_device_address_space.h
198 hle/kernel/k_dynamic_page_manager.h 200 hle/kernel/k_dynamic_page_manager.h
199 hle/kernel/k_dynamic_resource_manager.h 201 hle/kernel/k_dynamic_resource_manager.h
200 hle/kernel/k_dynamic_slab_heap.h 202 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 @@
11#include "core/hle/kernel/init/init_slab_setup.h" 11#include "core/hle/kernel/init/init_slab_setup.h"
12#include "core/hle/kernel/k_code_memory.h" 12#include "core/hle/kernel/k_code_memory.h"
13#include "core/hle/kernel/k_debug.h" 13#include "core/hle/kernel/k_debug.h"
14#include "core/hle/kernel/k_device_address_space.h"
14#include "core/hle/kernel/k_event.h" 15#include "core/hle/kernel/k_event.h"
15#include "core/hle/kernel/k_event_info.h" 16#include "core/hle/kernel/k_event_info.h"
16#include "core/hle/kernel/k_memory_layout.h" 17#include "core/hle/kernel/k_memory_layout.h"
@@ -43,6 +44,7 @@ namespace Kernel::Init {
43 HANDLER(KSharedMemoryInfo, (SLAB_COUNT(KSharedMemory) * 8), ##__VA_ARGS__) \ 44 HANDLER(KSharedMemoryInfo, (SLAB_COUNT(KSharedMemory) * 8), ##__VA_ARGS__) \
44 HANDLER(KTransferMemory, (SLAB_COUNT(KTransferMemory)), ##__VA_ARGS__) \ 45 HANDLER(KTransferMemory, (SLAB_COUNT(KTransferMemory)), ##__VA_ARGS__) \
45 HANDLER(KCodeMemory, (SLAB_COUNT(KCodeMemory)), ##__VA_ARGS__) \ 46 HANDLER(KCodeMemory, (SLAB_COUNT(KCodeMemory)), ##__VA_ARGS__) \
47 HANDLER(KDeviceAddressSpace, (SLAB_COUNT(KDeviceAddressSpace)), ##__VA_ARGS__) \
46 HANDLER(KSession, (SLAB_COUNT(KSession)), ##__VA_ARGS__) \ 48 HANDLER(KSession, (SLAB_COUNT(KSession)), ##__VA_ARGS__) \
47 HANDLER(KThreadLocalPage, \ 49 HANDLER(KThreadLocalPage, \
48 (SLAB_COUNT(KProcess) + (SLAB_COUNT(KProcess) + SLAB_COUNT(KThread)) / 8), \ 50 (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 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "common/assert.h"
5#include "core/core.h"
6#include "core/hle/kernel/k_device_address_space.h"
7#include "core/hle/kernel/kernel.h"
8#include "core/hle/kernel/svc_results.h"
9
10namespace Kernel {
11
12KDeviceAddressSpace::KDeviceAddressSpace(KernelCore& kernel_)
13 : KAutoObjectWithSlabHeapAndContainer(kernel_), m_lock(kernel_), m_is_initialized(false) {}
14KDeviceAddressSpace::~KDeviceAddressSpace() = default;
15
16void KDeviceAddressSpace::Initialize() {
17 // This just forwards to the device page table manager.
18 // KDevicePageTable::Initialize();
19}
20
21// Member functions.
22Result KDeviceAddressSpace::Initialize(u64 address, u64 size) {
23 // Initialize the device page table.
24 // R_TRY(m_table.Initialize(address, size));
25
26 // Set member variables.
27 m_space_address = address;
28 m_space_size = size;
29 m_is_initialized = true;
30
31 R_SUCCEED();
32}
33
34void KDeviceAddressSpace::Finalize() {
35 // Finalize the table.
36 // m_table.Finalize();
37}
38
39Result KDeviceAddressSpace::Attach(Svc::DeviceName device_name) {
40 // Lock the address space.
41 KScopedLightLock lk(m_lock);
42
43 // Attach.
44 // R_RETURN(m_table.Attach(device_name, m_space_address, m_space_size));
45 R_SUCCEED();
46}
47
48Result KDeviceAddressSpace::Detach(Svc::DeviceName device_name) {
49 // Lock the address space.
50 KScopedLightLock lk(m_lock);
51
52 // Detach.
53 // R_RETURN(m_table.Detach(device_name));
54 R_SUCCEED();
55}
56
57Result KDeviceAddressSpace::Map(KPageTable* page_table, VAddr process_address, size_t size,
58 u64 device_address, u32 option, bool is_aligned) {
59 // Check that the address falls within the space.
60 R_UNLESS((m_space_address <= device_address &&
61 device_address + size - 1 <= m_space_address + m_space_size - 1),
62 ResultInvalidCurrentMemory);
63
64 // Decode the option.
65 const Svc::MapDeviceAddressSpaceOption option_pack{option};
66 const auto device_perm = option_pack.permission.Value();
67 const auto flags = option_pack.flags.Value();
68 const auto reserved = option_pack.reserved.Value();
69
70 // Validate the option.
71 // TODO: It is likely that this check for flags == none is only on NX board.
72 R_UNLESS(flags == Svc::MapDeviceAddressSpaceFlag::None, ResultInvalidEnumValue);
73 R_UNLESS(reserved == 0, ResultInvalidEnumValue);
74
75 // Lock the address space.
76 KScopedLightLock lk(m_lock);
77
78 // Lock the page table to prevent concurrent device mapping operations.
79 // KScopedLightLock pt_lk = page_table->AcquireDeviceMapLock();
80
81 // Lock the pages.
82 bool is_io{};
83 R_TRY(page_table->LockForMapDeviceAddressSpace(std::addressof(is_io), process_address, size,
84 ConvertToKMemoryPermission(device_perm),
85 is_aligned, true));
86
87 // Ensure that if we fail, we don't keep unmapped pages locked.
88 ON_RESULT_FAILURE {
89 ASSERT(page_table->UnlockForDeviceAddressSpace(process_address, size) == ResultSuccess);
90 };
91
92 // Check that the io status is allowable.
93 if (is_io) {
94 R_UNLESS(static_cast<u32>(flags & Svc::MapDeviceAddressSpaceFlag::NotIoRegister) == 0,
95 ResultInvalidCombination);
96 }
97
98 // Map the pages.
99 {
100 // Perform the mapping.
101 // R_TRY(m_table.Map(page_table, process_address, size, device_address, device_perm,
102 // is_aligned, is_io));
103
104 // Ensure that we unmap the pages if we fail to update the protections.
105 // NOTE: Nintendo does not check the result of this unmap call.
106 // ON_RESULT_FAILURE { m_table.Unmap(device_address, size); };
107
108 // Update the protections in accordance with how much we mapped.
109 // R_TRY(page_table->UnlockForDeviceAddressSpacePartialMap(process_address, size));
110 }
111
112 // We succeeded.
113 R_SUCCEED();
114}
115
116Result KDeviceAddressSpace::Unmap(KPageTable* page_table, VAddr process_address, size_t size,
117 u64 device_address) {
118 // Check that the address falls within the space.
119 R_UNLESS((m_space_address <= device_address &&
120 device_address + size - 1 <= m_space_address + m_space_size - 1),
121 ResultInvalidCurrentMemory);
122
123 // Lock the address space.
124 KScopedLightLock lk(m_lock);
125
126 // Lock the page table to prevent concurrent device mapping operations.
127 // KScopedLightLock pt_lk = page_table->AcquireDeviceMapLock();
128
129 // Lock the pages.
130 R_TRY(page_table->LockForUnmapDeviceAddressSpace(process_address, size, true));
131
132 // Unmap the pages.
133 {
134 // If we fail to unmap, we want to do a partial unlock.
135 // ON_RESULT_FAILURE {
136 // ASSERT(page_table->UnlockForDeviceAddressSpacePartialMap(process_address, size) ==
137 // ResultSuccess);
138 // };
139
140 // Perform the unmap.
141 // R_TRY(m_table.Unmap(page_table, process_address, size, device_address));
142 }
143
144 // Unlock the pages.
145 ASSERT(page_table->UnlockForDeviceAddressSpace(process_address, size) == ResultSuccess);
146
147 R_SUCCEED();
148}
149
150} // 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 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <string>
7
8#include "common/common_types.h"
9#include "core/hle/kernel/k_page_table.h"
10#include "core/hle/kernel/slab_helpers.h"
11#include "core/hle/result.h"
12
13namespace Kernel {
14
15class KDeviceAddressSpace final
16 : public KAutoObjectWithSlabHeapAndContainer<KDeviceAddressSpace, KAutoObjectWithList> {
17 KERNEL_AUTOOBJECT_TRAITS(KDeviceAddressSpace, KAutoObject);
18
19public:
20 explicit KDeviceAddressSpace(KernelCore& kernel);
21 ~KDeviceAddressSpace();
22
23 Result Initialize(u64 address, u64 size);
24 void Finalize();
25
26 bool IsInitialized() const {
27 return m_is_initialized;
28 }
29 static void PostDestroy(uintptr_t arg) {}
30
31 Result Attach(Svc::DeviceName device_name);
32 Result Detach(Svc::DeviceName device_name);
33
34 Result MapByForce(KPageTable* page_table, VAddr process_address, size_t size,
35 u64 device_address, u32 option) {
36 R_RETURN(this->Map(page_table, process_address, size, device_address, option, false));
37 }
38
39 Result MapAligned(KPageTable* page_table, VAddr process_address, size_t size,
40 u64 device_address, u32 option) {
41 R_RETURN(this->Map(page_table, process_address, size, device_address, option, true));
42 }
43
44 Result Unmap(KPageTable* page_table, VAddr process_address, size_t size, u64 device_address);
45
46 static void Initialize();
47
48private:
49 Result Map(KPageTable* page_table, VAddr process_address, size_t size, u64 device_address,
50 u32 option, bool is_aligned);
51
52private:
53 KLightLock m_lock;
54 // KDevicePageTable m_table;
55 u64 m_space_address{};
56 u64 m_space_size{};
57 bool m_is_initialized{};
58};
59
60} // 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;
35class KAutoObjectWithListContainer; 35class KAutoObjectWithListContainer;
36class KClientSession; 36class KClientSession;
37class KDebug; 37class KDebug;
38class KDeviceAddressSpace;
38class KDynamicPageManager; 39class KDynamicPageManager;
39class KEvent; 40class KEvent;
40class KEventInfo; 41class KEventInfo;
@@ -359,6 +360,8 @@ public:
359 return slab_heap_container->transfer_memory; 360 return slab_heap_container->transfer_memory;
360 } else if constexpr (std::is_same_v<T, KCodeMemory>) { 361 } else if constexpr (std::is_same_v<T, KCodeMemory>) {
361 return slab_heap_container->code_memory; 362 return slab_heap_container->code_memory;
363 } else if constexpr (std::is_same_v<T, KDeviceAddressSpace>) {
364 return slab_heap_container->device_address_space;
362 } else if constexpr (std::is_same_v<T, KPageBuffer>) { 365 } else if constexpr (std::is_same_v<T, KPageBuffer>) {
363 return slab_heap_container->page_buffer; 366 return slab_heap_container->page_buffer;
364 } else if constexpr (std::is_same_v<T, KThreadLocalPage>) { 367 } else if constexpr (std::is_same_v<T, KThreadLocalPage>) {
@@ -431,6 +434,7 @@ private:
431 KSlabHeap<KThread> thread; 434 KSlabHeap<KThread> thread;
432 KSlabHeap<KTransferMemory> transfer_memory; 435 KSlabHeap<KTransferMemory> transfer_memory;
433 KSlabHeap<KCodeMemory> code_memory; 436 KSlabHeap<KCodeMemory> code_memory;
437 KSlabHeap<KDeviceAddressSpace> device_address_space;
434 KSlabHeap<KPageBuffer> page_buffer; 438 KSlabHeap<KPageBuffer> page_buffer;
435 KSlabHeap<KThreadLocalPage> thread_local_page; 439 KSlabHeap<KThreadLocalPage> thread_local_page;
436 KSlabHeap<KSessionRequest> session_request; 440 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 @@
5 5
6#include <bitset> 6#include <bitset>
7 7
8#include "common/bit_field.h"
8#include "common/common_funcs.h" 9#include "common/common_funcs.h"
9#include "common/common_types.h" 10#include "common/common_types.h"
10 11
@@ -498,6 +499,19 @@ enum class MemoryMapping : u32 {
498 Memory = 2, 499 Memory = 2,
499}; 500};
500 501
502enum class MapDeviceAddressSpaceFlag : u32 {
503 None = (0U << 0),
504 NotIoRegister = (1U << 0),
505};
506DECLARE_ENUM_FLAG_OPERATORS(MapDeviceAddressSpaceFlag);
507
508union MapDeviceAddressSpaceOption {
509 u32 raw;
510 BitField<0, 16, MemoryPermission> permission;
511 BitField<16, 1, MapDeviceAddressSpaceFlag> flags;
512 BitField<17, 15, u32> reserved;
513};
514
501enum class KernelDebugType : u32 { 515enum class KernelDebugType : u32 {
502 Thread = 0, 516 Thread = 0,
503 ThreadCallStack = 1, 517 ThreadCallStack = 1,