From ba25ae7eba19906c6ad84d0fcca415d97d4eb4f9 Mon Sep 17 00:00:00 2001
From: PSI-Rockin <PSI-Rockin@users.noreply.github.com>
Date: Thu, 9 May 2024 20:05:19 -0400
Subject: [PATCH] Memory: Implement Unmap in ControlMemory

Also do a sanity check to make sure the memory region is free for linear allocations
---
 src/core/kernel/memory_management.cpp | 7 +++++++
 src/core/memory.cpp                   | 3 +++
 2 files changed, 10 insertions(+)

diff --git a/src/core/kernel/memory_management.cpp b/src/core/kernel/memory_management.cpp
index cc8b9313..24943c3a 100644
--- a/src/core/kernel/memory_management.cpp
+++ b/src/core/kernel/memory_management.cpp
@@ -89,10 +89,17 @@ void Kernel::controlMemory() {
 		}
 
 		case Operation::Map:
+			// Official kernel only allows Private regions to be mapped to Free regions. An Alias or Aliased region cannot be mapped again
 			if (!mem.mapVirtualMemory(addr0, addr1, pages, r, w, false, MemoryState::Free, MemoryState::Private,
 				MemoryState::Alias, MemoryState::Aliased)) Helpers::panic("ControlMemory: Failed to map memory");
 			break;
 
+		case Operation::Unmap:
+			// The same as a Map operation, except in reverse
+			if (!mem.mapVirtualMemory(addr0, addr1, pages, false, false, false, MemoryState::Alias, MemoryState::Aliased,
+				MemoryState::Free, MemoryState::Private)) Helpers::panic("ControlMemory: Failed to unmap memory");
+			break;
+
 		case Operation::Protect:
 			// Official kernel has an internal state bit to indicate that the region's permissions may be changed
 			// But this should account for all cases
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index 991c5437..80c2c531 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -426,6 +426,9 @@ bool Memory::allocMemoryLinear(u32& outVaddr, u32 inVaddr, s32 pages, FcramRegio
 
 	u32 paddr = memList.begin()->paddr;
 	u32 vaddr = getLinearHeapVaddr() + paddr;
+	auto res = testMemoryState(vaddr, pages, MemoryState::Free);
+	if (res.isFailure()) Helpers::panic("Unable to map linear allocation (vaddr:%08X pages:%08X)", vaddr, pages);
+
 	Operation op{ .newState = MemoryState::Continuous, .r = r, .w = w, .x = x, .changeState = true, .changePerms = true };
 	changeMemoryState(vaddr, pages, op);
 	mapPhysicalMemory(vaddr, paddr, pages, r, w, x);