summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar bunnei2022-09-09 21:17:52 -0700
committerGravatar bunnei2022-10-18 19:13:34 -0700
commit58eb6953d1417d667af36461ac8391e005f49457 (patch)
tree3d21d4c4029e8d1e5087fbc11c8fe132f98d16db /src
parentcore: hle: kernel: k_memory_block_manager: Update. (diff)
downloadyuzu-58eb6953d1417d667af36461ac8391e005f49457.tar.gz
yuzu-58eb6953d1417d667af36461ac8391e005f49457.tar.xz
yuzu-58eb6953d1417d667af36461ac8391e005f49457.zip
core: hle: kernel: k_memory_block: Update.
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/kernel/k_memory_block.h506
-rw-r--r--src/core/hle/service/ldr/ldr.cpp4
2 files changed, 391 insertions, 119 deletions
diff --git a/src/core/hle/kernel/k_memory_block.h b/src/core/hle/kernel/k_memory_block.h
index 18df1f836..9444f6bd2 100644
--- a/src/core/hle/kernel/k_memory_block.h
+++ b/src/core/hle/kernel/k_memory_block.h
@@ -6,6 +6,7 @@
6#include "common/alignment.h" 6#include "common/alignment.h"
7#include "common/assert.h" 7#include "common/assert.h"
8#include "common/common_types.h" 8#include "common/common_types.h"
9#include "common/intrusive_red_black_tree.h"
9#include "core/hle/kernel/memory_types.h" 10#include "core/hle/kernel/memory_types.h"
10#include "core/hle/kernel/svc_types.h" 11#include "core/hle/kernel/svc_types.h"
11 12
@@ -168,9 +169,8 @@ constexpr KMemoryPermission ConvertToKMemoryPermission(Svc::MemoryPermission per
168 169
169enum class KMemoryAttribute : u8 { 170enum class KMemoryAttribute : u8 {
170 None = 0x00, 171 None = 0x00,
171 Mask = 0x7F, 172 All = 0xFF,
172 All = Mask, 173 UserMask = All,
173 DontCareMask = 0x80,
174 174
175 Locked = static_cast<u8>(Svc::MemoryAttribute::Locked), 175 Locked = static_cast<u8>(Svc::MemoryAttribute::Locked),
176 IpcLocked = static_cast<u8>(Svc::MemoryAttribute::IpcLocked), 176 IpcLocked = static_cast<u8>(Svc::MemoryAttribute::IpcLocked),
@@ -178,76 +178,112 @@ enum class KMemoryAttribute : u8 {
178 Uncached = static_cast<u8>(Svc::MemoryAttribute::Uncached), 178 Uncached = static_cast<u8>(Svc::MemoryAttribute::Uncached),
179 179
180 SetMask = Uncached, 180 SetMask = Uncached,
181
182 IpcAndDeviceMapped = IpcLocked | DeviceShared,
183 LockedAndIpcLocked = Locked | IpcLocked,
184 DeviceSharedAndUncached = DeviceShared | Uncached
185}; 181};
186DECLARE_ENUM_FLAG_OPERATORS(KMemoryAttribute); 182DECLARE_ENUM_FLAG_OPERATORS(KMemoryAttribute);
187 183
188static_assert((static_cast<u8>(KMemoryAttribute::Mask) & 184enum class KMemoryBlockDisableMergeAttribute : u8 {
189 static_cast<u8>(KMemoryAttribute::DontCareMask)) == 0); 185 None = 0,
186 Normal = (1u << 0),
187 DeviceLeft = (1u << 1),
188 IpcLeft = (1u << 2),
189 Locked = (1u << 3),
190 DeviceRight = (1u << 4),
191
192 AllLeft = Normal | DeviceLeft | IpcLeft | Locked,
193 AllRight = DeviceRight,
194};
195DECLARE_ENUM_FLAG_OPERATORS(KMemoryBlockDisableMergeAttribute);
190 196
191struct KMemoryInfo { 197struct KMemoryInfo {
192 VAddr addr{}; 198 uintptr_t m_address;
193 std::size_t size{}; 199 size_t m_size;
194 KMemoryState state{}; 200 KMemoryState m_state;
195 KMemoryPermission perm{}; 201 u16 m_device_disable_merge_left_count;
196 KMemoryAttribute attribute{}; 202 u16 m_device_disable_merge_right_count;
197 KMemoryPermission original_perm{}; 203 u16 m_ipc_lock_count;
198 u16 ipc_lock_count{}; 204 u16 m_device_use_count;
199 u16 device_use_count{}; 205 u16 m_ipc_disable_merge_count;
206 KMemoryPermission m_permission;
207 KMemoryAttribute m_attribute;
208 KMemoryPermission m_original_permission;
209 KMemoryBlockDisableMergeAttribute m_disable_merge_attribute;
200 210
201 constexpr Svc::MemoryInfo GetSvcMemoryInfo() const { 211 constexpr Svc::MemoryInfo GetSvcMemoryInfo() const {
202 return { 212 return {
203 addr, 213 .addr = m_address,
204 size, 214 .size = m_size,
205 static_cast<Svc::MemoryState>(state & KMemoryState::Mask), 215 .state = static_cast<Svc::MemoryState>(m_state & KMemoryState::Mask),
206 static_cast<Svc::MemoryAttribute>(attribute & KMemoryAttribute::Mask), 216 .attr = static_cast<Svc::MemoryAttribute>(m_attribute & KMemoryAttribute::UserMask),
207 static_cast<Svc::MemoryPermission>(perm & KMemoryPermission::UserMask), 217 .perm = static_cast<Svc::MemoryPermission>(m_permission & KMemoryPermission::UserMask),
208 ipc_lock_count, 218 .ipc_refcount = m_ipc_lock_count,
209 device_use_count, 219 .device_refcount = m_device_use_count,
220 .padding = {},
210 }; 221 };
211 } 222 }
212 223
213 constexpr VAddr GetAddress() const { 224 constexpr uintptr_t GetAddress() const {
214 return addr; 225 return m_address;
226 }
227
228 constexpr size_t GetSize() const {
229 return m_size;
215 } 230 }
216 constexpr std::size_t GetSize() const { 231
217 return size; 232 constexpr size_t GetNumPages() const {
233 return this->GetSize() / PageSize;
218 } 234 }
219 constexpr std::size_t GetNumPages() const { 235
220 return GetSize() / PageSize; 236 constexpr uintptr_t GetEndAddress() const {
237 return this->GetAddress() + this->GetSize();
221 } 238 }
222 constexpr VAddr GetEndAddress() const { 239
223 return GetAddress() + GetSize(); 240 constexpr uintptr_t GetLastAddress() const {
241 return this->GetEndAddress() - 1;
224 } 242 }
225 constexpr VAddr GetLastAddress() const { 243
226 return GetEndAddress() - 1; 244 constexpr u16 GetIpcLockCount() const {
245 return m_ipc_lock_count;
227 } 246 }
247
248 constexpr u16 GetIpcDisableMergeCount() const {
249 return m_ipc_disable_merge_count;
250 }
251
228 constexpr KMemoryState GetState() const { 252 constexpr KMemoryState GetState() const {
229 return state; 253 return m_state;
254 }
255
256 constexpr KMemoryPermission GetPermission() const {
257 return m_permission;
230 } 258 }
259
260 constexpr KMemoryPermission GetOriginalPermission() const {
261 return m_original_permission;
262 }
263
231 constexpr KMemoryAttribute GetAttribute() const { 264 constexpr KMemoryAttribute GetAttribute() const {
232 return attribute; 265 return m_attribute;
233 } 266 }
234 constexpr KMemoryPermission GetPermission() const { 267
235 return perm; 268 constexpr KMemoryBlockDisableMergeAttribute GetDisableMergeAttribute() const {
269 return m_disable_merge_attribute;
236 } 270 }
237}; 271};
238 272
239class KMemoryBlock final { 273class KMemoryBlock : public Common::IntrusiveRedBlackTreeBaseNode<KMemoryBlock> {
240 friend class KMemoryBlockManager;
241
242private: 274private:
243 VAddr addr{}; 275 u16 m_device_disable_merge_left_count;
244 std::size_t num_pages{}; 276 u16 m_device_disable_merge_right_count;
245 KMemoryState state{KMemoryState::None}; 277 VAddr m_address;
246 u16 ipc_lock_count{}; 278 size_t m_num_pages;
247 u16 device_use_count{}; 279 KMemoryState m_memory_state;
248 KMemoryPermission perm{KMemoryPermission::None}; 280 u16 m_ipc_lock_count;
249 KMemoryPermission original_perm{KMemoryPermission::None}; 281 u16 m_device_use_count;
250 KMemoryAttribute attribute{KMemoryAttribute::None}; 282 u16 m_ipc_disable_merge_count;
283 KMemoryPermission m_permission;
284 KMemoryPermission m_original_permission;
285 KMemoryAttribute m_attribute;
286 KMemoryBlockDisableMergeAttribute m_disable_merge_attribute;
251 287
252public: 288public:
253 static constexpr int Compare(const KMemoryBlock& lhs, const KMemoryBlock& rhs) { 289 static constexpr int Compare(const KMemoryBlock& lhs, const KMemoryBlock& rhs) {
@@ -261,113 +297,349 @@ public:
261 } 297 }
262 298
263public: 299public:
264 constexpr KMemoryBlock() = default;
265 constexpr KMemoryBlock(VAddr addr_, std::size_t num_pages_, KMemoryState state_,
266 KMemoryPermission perm_, KMemoryAttribute attribute_)
267 : addr{addr_}, num_pages(num_pages_), state{state_}, perm{perm_}, attribute{attribute_} {}
268
269 constexpr VAddr GetAddress() const { 300 constexpr VAddr GetAddress() const {
270 return addr; 301 return m_address;
271 } 302 }
272 303
273 constexpr std::size_t GetNumPages() const { 304 constexpr size_t GetNumPages() const {
274 return num_pages; 305 return m_num_pages;
275 } 306 }
276 307
277 constexpr std::size_t GetSize() const { 308 constexpr size_t GetSize() const {
278 return GetNumPages() * PageSize; 309 return this->GetNumPages() * PageSize;
279 } 310 }
280 311
281 constexpr VAddr GetEndAddress() const { 312 constexpr VAddr GetEndAddress() const {
282 return GetAddress() + GetSize(); 313 return this->GetAddress() + this->GetSize();
283 } 314 }
284 315
285 constexpr VAddr GetLastAddress() const { 316 constexpr VAddr GetLastAddress() const {
286 return GetEndAddress() - 1; 317 return this->GetEndAddress() - 1;
318 }
319
320 constexpr u16 GetIpcLockCount() const {
321 return m_ipc_lock_count;
322 }
323
324 constexpr u16 GetIpcDisableMergeCount() const {
325 return m_ipc_disable_merge_count;
326 }
327
328 constexpr KMemoryPermission GetPermission() const {
329 return m_permission;
330 }
331
332 constexpr KMemoryPermission GetOriginalPermission() const {
333 return m_original_permission;
334 }
335
336 constexpr KMemoryAttribute GetAttribute() const {
337 return m_attribute;
287 } 338 }
288 339
289 constexpr KMemoryInfo GetMemoryInfo() const { 340 constexpr KMemoryInfo GetMemoryInfo() const {
290 return { 341 return {
291 GetAddress(), GetSize(), state, perm, 342 .m_address = this->GetAddress(),
292 attribute, original_perm, ipc_lock_count, device_use_count, 343 .m_size = this->GetSize(),
344 .m_state = m_memory_state,
345 .m_device_disable_merge_left_count = m_device_disable_merge_left_count,
346 .m_device_disable_merge_right_count = m_device_disable_merge_right_count,
347 .m_ipc_lock_count = m_ipc_lock_count,
348 .m_device_use_count = m_device_use_count,
349 .m_ipc_disable_merge_count = m_ipc_disable_merge_count,
350 .m_permission = m_permission,
351 .m_attribute = m_attribute,
352 .m_original_permission = m_original_permission,
353 .m_disable_merge_attribute = m_disable_merge_attribute,
293 }; 354 };
294 } 355 }
295 356
296 void ShareToDevice(KMemoryPermission /*new_perm*/) { 357public:
297 ASSERT((attribute & KMemoryAttribute::DeviceShared) == KMemoryAttribute::DeviceShared || 358 explicit KMemoryBlock() = default;
298 device_use_count == 0); 359
299 attribute |= KMemoryAttribute::DeviceShared; 360 constexpr KMemoryBlock(VAddr addr, size_t np, KMemoryState ms, KMemoryPermission p,
300 const u16 new_use_count{++device_use_count}; 361 KMemoryAttribute attr)
301 ASSERT(new_use_count > 0); 362 : Common::IntrusiveRedBlackTreeBaseNode<KMemoryBlock>(),
363 m_device_disable_merge_left_count(), m_device_disable_merge_right_count(),
364 m_address(addr), m_num_pages(np), m_memory_state(ms), m_ipc_lock_count(0),
365 m_device_use_count(0), m_ipc_disable_merge_count(), m_permission(p),
366 m_original_permission(KMemoryPermission::None), m_attribute(attr),
367 m_disable_merge_attribute() {}
368
369 constexpr void Initialize(VAddr addr, size_t np, KMemoryState ms, KMemoryPermission p,
370 KMemoryAttribute attr) {
371 m_device_disable_merge_left_count = 0;
372 m_device_disable_merge_right_count = 0;
373 m_address = addr;
374 m_num_pages = np;
375 m_memory_state = ms;
376 m_ipc_lock_count = 0;
377 m_device_use_count = 0;
378 m_permission = p;
379 m_original_permission = KMemoryPermission::None;
380 m_attribute = attr;
381 m_disable_merge_attribute = KMemoryBlockDisableMergeAttribute::None;
382 }
383
384 constexpr bool HasProperties(KMemoryState s, KMemoryPermission p, KMemoryAttribute a) const {
385 constexpr auto AttributeIgnoreMask =
386 KMemoryAttribute::IpcLocked | KMemoryAttribute::DeviceShared;
387 return m_memory_state == s && m_permission == p &&
388 (m_attribute | AttributeIgnoreMask) == (a | AttributeIgnoreMask);
389 }
390
391 constexpr bool HasSameProperties(const KMemoryBlock& rhs) const {
392 return m_memory_state == rhs.m_memory_state && m_permission == rhs.m_permission &&
393 m_original_permission == rhs.m_original_permission &&
394 m_attribute == rhs.m_attribute && m_ipc_lock_count == rhs.m_ipc_lock_count &&
395 m_device_use_count == rhs.m_device_use_count;
396 }
397
398 constexpr bool CanMergeWith(const KMemoryBlock& rhs) const {
399 return this->HasSameProperties(rhs) &&
400 (m_disable_merge_attribute & KMemoryBlockDisableMergeAttribute::AllRight) ==
401 KMemoryBlockDisableMergeAttribute::None &&
402 (rhs.m_disable_merge_attribute & KMemoryBlockDisableMergeAttribute::AllLeft) ==
403 KMemoryBlockDisableMergeAttribute::None;
302 } 404 }
303 405
304 void UnshareToDevice(KMemoryPermission /*new_perm*/) { 406 constexpr bool Contains(VAddr addr) const {
305 ASSERT((attribute & KMemoryAttribute::DeviceShared) == KMemoryAttribute::DeviceShared); 407 return this->GetAddress() <= addr && addr <= this->GetEndAddress();
306 const u16 prev_use_count{device_use_count--}; 408 }
307 ASSERT(prev_use_count > 0); 409
308 if (prev_use_count == 1) { 410 constexpr void Add(const KMemoryBlock& added_block) {
309 attribute &= ~KMemoryAttribute::DeviceShared; 411 ASSERT(added_block.GetNumPages() > 0);
412 ASSERT(this->GetAddress() + added_block.GetSize() - 1 <
413 this->GetEndAddress() + added_block.GetSize() - 1);
414
415 m_num_pages += added_block.GetNumPages();
416 m_disable_merge_attribute = static_cast<KMemoryBlockDisableMergeAttribute>(
417 m_disable_merge_attribute | added_block.m_disable_merge_attribute);
418 m_device_disable_merge_right_count = added_block.m_device_disable_merge_right_count;
419 }
420
421 constexpr void Update(KMemoryState s, KMemoryPermission p, KMemoryAttribute a,
422 bool set_disable_merge_attr, u8 set_mask, u8 clear_mask) {
423 ASSERT(m_original_permission == KMemoryPermission::None);
424 ASSERT((m_attribute & KMemoryAttribute::IpcLocked) == KMemoryAttribute::None);
425
426 m_memory_state = s;
427 m_permission = p;
428 m_attribute = static_cast<KMemoryAttribute>(
429 a | (m_attribute & (KMemoryAttribute::IpcLocked | KMemoryAttribute::DeviceShared)));
430
431 if (set_disable_merge_attr && set_mask != 0) {
432 m_disable_merge_attribute = m_disable_merge_attribute |
433 static_cast<KMemoryBlockDisableMergeAttribute>(set_mask);
434 }
435 if (clear_mask != 0) {
436 m_disable_merge_attribute = m_disable_merge_attribute &
437 static_cast<KMemoryBlockDisableMergeAttribute>(~clear_mask);
310 } 438 }
311 } 439 }
312 440
313private: 441 constexpr void Split(KMemoryBlock* block, VAddr addr) {
314 constexpr bool HasProperties(KMemoryState s, KMemoryPermission p, KMemoryAttribute a) const { 442 ASSERT(this->GetAddress() < addr);
315 constexpr KMemoryAttribute AttributeIgnoreMask{KMemoryAttribute::DontCareMask | 443 ASSERT(this->Contains(addr));
316 KMemoryAttribute::IpcLocked | 444 ASSERT(Common::IsAligned(addr, PageSize));
317 KMemoryAttribute::DeviceShared}; 445
318 return state == s && perm == p && 446 block->m_address = m_address;
319 (attribute | AttributeIgnoreMask) == (a | AttributeIgnoreMask); 447 block->m_num_pages = (addr - this->GetAddress()) / PageSize;
448 block->m_memory_state = m_memory_state;
449 block->m_ipc_lock_count = m_ipc_lock_count;
450 block->m_device_use_count = m_device_use_count;
451 block->m_permission = m_permission;
452 block->m_original_permission = m_original_permission;
453 block->m_attribute = m_attribute;
454 block->m_disable_merge_attribute = static_cast<KMemoryBlockDisableMergeAttribute>(
455 m_disable_merge_attribute & KMemoryBlockDisableMergeAttribute::AllLeft);
456 block->m_ipc_disable_merge_count = m_ipc_disable_merge_count;
457 block->m_device_disable_merge_left_count = m_device_disable_merge_left_count;
458 block->m_device_disable_merge_right_count = 0;
459
460 m_address = addr;
461 m_num_pages -= block->m_num_pages;
462
463 m_ipc_disable_merge_count = 0;
464 m_device_disable_merge_left_count = 0;
465 m_disable_merge_attribute = static_cast<KMemoryBlockDisableMergeAttribute>(
466 m_disable_merge_attribute & KMemoryBlockDisableMergeAttribute::AllRight);
320 } 467 }
321 468
322 constexpr bool HasSameProperties(const KMemoryBlock& rhs) const { 469 constexpr void UpdateDeviceDisableMergeStateForShareLeft(
323 return state == rhs.state && perm == rhs.perm && original_perm == rhs.original_perm && 470 [[maybe_unused]] KMemoryPermission new_perm, bool left, [[maybe_unused]] bool right) {
324 attribute == rhs.attribute && ipc_lock_count == rhs.ipc_lock_count && 471 if (left) {
325 device_use_count == rhs.device_use_count; 472 m_disable_merge_attribute = static_cast<KMemoryBlockDisableMergeAttribute>(
473 m_disable_merge_attribute | KMemoryBlockDisableMergeAttribute::DeviceLeft);
474 const u16 new_device_disable_merge_left_count = ++m_device_disable_merge_left_count;
475 ASSERT(new_device_disable_merge_left_count > 0);
476 }
326 } 477 }
327 478
328 constexpr bool Contains(VAddr start) const { 479 constexpr void UpdateDeviceDisableMergeStateForShareRight(
329 return GetAddress() <= start && start <= GetEndAddress(); 480 [[maybe_unused]] KMemoryPermission new_perm, [[maybe_unused]] bool left, bool right) {
481 if (right) {
482 m_disable_merge_attribute = static_cast<KMemoryBlockDisableMergeAttribute>(
483 m_disable_merge_attribute | KMemoryBlockDisableMergeAttribute::DeviceRight);
484 const u16 new_device_disable_merge_right_count = ++m_device_disable_merge_right_count;
485 ASSERT(new_device_disable_merge_right_count > 0);
486 }
487 }
488
489 constexpr void UpdateDeviceDisableMergeStateForShare(KMemoryPermission new_perm, bool left,
490 bool right) {
491 this->UpdateDeviceDisableMergeStateForShareLeft(new_perm, left, right);
492 this->UpdateDeviceDisableMergeStateForShareRight(new_perm, left, right);
330 } 493 }
331 494
332 constexpr void Add(std::size_t count) { 495 constexpr void ShareToDevice([[maybe_unused]] KMemoryPermission new_perm, bool left,
333 ASSERT(count > 0); 496 bool right) {
334 ASSERT(GetAddress() + count * PageSize - 1 < GetEndAddress() + count * PageSize - 1); 497 // We must either be shared or have a zero lock count.
498 ASSERT((m_attribute & KMemoryAttribute::DeviceShared) == KMemoryAttribute::DeviceShared ||
499 m_device_use_count == 0);
335 500
336 num_pages += count; 501 // Share.
502 const u16 new_count = ++m_device_use_count;
503 ASSERT(new_count > 0);
504
505 m_attribute = static_cast<KMemoryAttribute>(m_attribute | KMemoryAttribute::DeviceShared);
506
507 this->UpdateDeviceDisableMergeStateForShare(new_perm, left, right);
337 } 508 }
338 509
339 constexpr void Update(KMemoryState new_state, KMemoryPermission new_perm, 510 constexpr void UpdateDeviceDisableMergeStateForUnshareLeft(
340 KMemoryAttribute new_attribute) { 511 [[maybe_unused]] KMemoryPermission new_perm, bool left, [[maybe_unused]] bool right) {
341 ASSERT(original_perm == KMemoryPermission::None);
342 ASSERT((attribute & KMemoryAttribute::IpcLocked) == KMemoryAttribute::None);
343 512
344 state = new_state; 513 if (left) {
345 perm = new_perm; 514 if (!m_device_disable_merge_left_count) {
515 return;
516 }
517 --m_device_disable_merge_left_count;
518 }
346 519
347 attribute = static_cast<KMemoryAttribute>( 520 m_device_disable_merge_left_count =
348 new_attribute | 521 std::min(m_device_disable_merge_left_count, m_device_use_count);
349 (attribute & (KMemoryAttribute::IpcLocked | KMemoryAttribute::DeviceShared))); 522
523 if (m_device_disable_merge_left_count == 0) {
524 m_disable_merge_attribute = static_cast<KMemoryBlockDisableMergeAttribute>(
525 m_disable_merge_attribute & ~KMemoryBlockDisableMergeAttribute::DeviceLeft);
526 }
350 } 527 }
351 528
352 constexpr KMemoryBlock Split(VAddr split_addr) { 529 constexpr void UpdateDeviceDisableMergeStateForUnshareRight(
353 ASSERT(GetAddress() < split_addr); 530 [[maybe_unused]] KMemoryPermission new_perm, [[maybe_unused]] bool left, bool right) {
354 ASSERT(Contains(split_addr)); 531 if (right) {
355 ASSERT(Common::IsAligned(split_addr, PageSize)); 532 const u16 old_device_disable_merge_right_count = m_device_disable_merge_right_count--;
533 ASSERT(old_device_disable_merge_right_count > 0);
534 if (old_device_disable_merge_right_count == 1) {
535 m_disable_merge_attribute = static_cast<KMemoryBlockDisableMergeAttribute>(
536 m_disable_merge_attribute & ~KMemoryBlockDisableMergeAttribute::DeviceRight);
537 }
538 }
539 }
356 540
357 KMemoryBlock block; 541 constexpr void UpdateDeviceDisableMergeStateForUnshare(KMemoryPermission new_perm, bool left,
358 block.addr = addr; 542 bool right) {
359 block.num_pages = (split_addr - GetAddress()) / PageSize; 543 this->UpdateDeviceDisableMergeStateForUnshareLeft(new_perm, left, right);
360 block.state = state; 544 this->UpdateDeviceDisableMergeStateForUnshareRight(new_perm, left, right);
361 block.ipc_lock_count = ipc_lock_count; 545 }
362 block.device_use_count = device_use_count;
363 block.perm = perm;
364 block.original_perm = original_perm;
365 block.attribute = attribute;
366 546
367 addr = split_addr; 547 constexpr void UnshareToDevice([[maybe_unused]] KMemoryPermission new_perm, bool left,
368 num_pages -= block.num_pages; 548 bool right) {
549 // We must be shared.
550 ASSERT((m_attribute & KMemoryAttribute::DeviceShared) == KMemoryAttribute::DeviceShared);
551
552 // Unhare.
553 const u16 old_count = m_device_use_count--;
554 ASSERT(old_count > 0);
555
556 if (old_count == 1) {
557 m_attribute =
558 static_cast<KMemoryAttribute>(m_attribute & ~KMemoryAttribute::DeviceShared);
559 }
560
561 this->UpdateDeviceDisableMergeStateForUnshare(new_perm, left, right);
562 }
563
564 constexpr void UnshareToDeviceRight([[maybe_unused]] KMemoryPermission new_perm, bool left,
565 bool right) {
566
567 // We must be shared.
568 ASSERT((m_attribute & KMemoryAttribute::DeviceShared) == KMemoryAttribute::DeviceShared);
569
570 // Unhare.
571 const u16 old_count = m_device_use_count--;
572 ASSERT(old_count > 0);
573
574 if (old_count == 1) {
575 m_attribute =
576 static_cast<KMemoryAttribute>(m_attribute & ~KMemoryAttribute::DeviceShared);
577 }
578
579 this->UpdateDeviceDisableMergeStateForUnshareRight(new_perm, left, right);
580 }
581
582 constexpr void LockForIpc(KMemoryPermission new_perm, bool left, [[maybe_unused]] bool right) {
583 // We must either be locked or have a zero lock count.
584 ASSERT((m_attribute & KMemoryAttribute::IpcLocked) == KMemoryAttribute::IpcLocked ||
585 m_ipc_lock_count == 0);
586
587 // Lock.
588 const u16 new_lock_count = ++m_ipc_lock_count;
589 ASSERT(new_lock_count > 0);
590
591 // If this is our first lock, update our permissions.
592 if (new_lock_count == 1) {
593 ASSERT(m_original_permission == KMemoryPermission::None);
594 ASSERT((m_permission | new_perm | KMemoryPermission::NotMapped) ==
595 (m_permission | KMemoryPermission::NotMapped));
596 ASSERT((m_permission & KMemoryPermission::UserExecute) !=
597 KMemoryPermission::UserExecute ||
598 (new_perm == KMemoryPermission::UserRead));
599 m_original_permission = m_permission;
600 m_permission = static_cast<KMemoryPermission>(
601 (new_perm & KMemoryPermission::IpcLockChangeMask) |
602 (m_original_permission & ~KMemoryPermission::IpcLockChangeMask));
603 }
604 m_attribute = static_cast<KMemoryAttribute>(m_attribute | KMemoryAttribute::IpcLocked);
605
606 if (left) {
607 m_disable_merge_attribute = static_cast<KMemoryBlockDisableMergeAttribute>(
608 m_disable_merge_attribute | KMemoryBlockDisableMergeAttribute::IpcLeft);
609 const u16 new_ipc_disable_merge_count = ++m_ipc_disable_merge_count;
610 ASSERT(new_ipc_disable_merge_count > 0);
611 }
612 }
613
614 constexpr void UnlockForIpc([[maybe_unused]] KMemoryPermission new_perm, bool left,
615 [[maybe_unused]] bool right) {
616 // We must be locked.
617 ASSERT((m_attribute & KMemoryAttribute::IpcLocked) == KMemoryAttribute::IpcLocked);
618
619 // Unlock.
620 const u16 old_lock_count = m_ipc_lock_count--;
621 ASSERT(old_lock_count > 0);
622
623 // If this is our last unlock, update our permissions.
624 if (old_lock_count == 1) {
625 ASSERT(m_original_permission != KMemoryPermission::None);
626 m_permission = m_original_permission;
627 m_original_permission = KMemoryPermission::None;
628 m_attribute = static_cast<KMemoryAttribute>(m_attribute & ~KMemoryAttribute::IpcLocked);
629 }
630
631 if (left) {
632 const u16 old_ipc_disable_merge_count = m_ipc_disable_merge_count--;
633 ASSERT(old_ipc_disable_merge_count > 0);
634 if (old_ipc_disable_merge_count == 1) {
635 m_disable_merge_attribute = static_cast<KMemoryBlockDisableMergeAttribute>(
636 m_disable_merge_attribute & ~KMemoryBlockDisableMergeAttribute::IpcLeft);
637 }
638 }
639 }
369 640
370 return block; 641 constexpr KMemoryBlockDisableMergeAttribute GetDisableMergeAttribute() const {
642 return m_disable_merge_attribute;
371 } 643 }
372}; 644};
373static_assert(std::is_trivially_destructible<KMemoryBlock>::value); 645static_assert(std::is_trivially_destructible<KMemoryBlock>::value);
diff --git a/src/core/hle/service/ldr/ldr.cpp b/src/core/hle/service/ldr/ldr.cpp
index becd6d1b9..652441bc2 100644
--- a/src/core/hle/service/ldr/ldr.cpp
+++ b/src/core/hle/service/ldr/ldr.cpp
@@ -290,7 +290,7 @@ public:
290 const std::size_t padding_size{page_table.GetNumGuardPages() * Kernel::PageSize}; 290 const std::size_t padding_size{page_table.GetNumGuardPages() * Kernel::PageSize};
291 const auto start_info{page_table.QueryInfo(start - 1)}; 291 const auto start_info{page_table.QueryInfo(start - 1)};
292 292
293 if (start_info.state != Kernel::KMemoryState::Free) { 293 if (start_info.GetState() != Kernel::KMemoryState::Free) {
294 return {}; 294 return {};
295 } 295 }
296 296
@@ -300,7 +300,7 @@ public:
300 300
301 const auto end_info{page_table.QueryInfo(start + size)}; 301 const auto end_info{page_table.QueryInfo(start + size)};
302 302
303 if (end_info.state != Kernel::KMemoryState::Free) { 303 if (end_info.GetState() != Kernel::KMemoryState::Free) {
304 return {}; 304 return {};
305 } 305 }
306 306