diff --git a/include/kernel/kernel.hpp b/include/kernel/kernel.hpp
index 2384c769..31a6b209 100644
--- a/include/kernel/kernel.hpp
+++ b/include/kernel/kernel.hpp
@@ -45,6 +45,7 @@ class Kernel {
 	Handle makePort(const char* name);
 	Handle makeSession(Handle port);
 	Handle makeThread(u32 entrypoint, u32 initialSP, u32 priority, s32 id, u32 arg,ThreadStatus status = ThreadStatus::Dormant);
+	Handle makeMemoryBlock(u32 addr, u32 size, u32 myPermission, u32 otherPermission);
 
 public:
 	Handle makeEvent(ResetType resetType); // Needs to be public to be accessible to the APT/HID services
diff --git a/include/kernel/kernel_types.hpp b/include/kernel/kernel_types.hpp
index 282d554a..3e4f510d 100644
--- a/include/kernel/kernel_types.hpp
+++ b/include/kernel/kernel_types.hpp
@@ -17,13 +17,17 @@ namespace SVCResult {
         BadHandle = 0xD8E007F7,
         BadHandleAlt = 0xD9001BF7,
 
+        InvalidCombination = 0xE0E01BEE, // Used for invalid memory permission combinations
+        UnalignedAddr = 0xE0E01BF1,
+        UnalignedSize = 0xE0E01BF2,
+
         BadThreadPriority = 0xE0E01BFD,
         PortNameTooLong = 0xE0E0181E,
 	};
 }
 
 enum class KernelObjectType : u8 {
-    AddressArbiter, Archive, File, Process, ResourceLimit, Session, Dummy,
+    AddressArbiter, Archive, File, MemoryBlock, Process, ResourceLimit, Session, Dummy,
     // Bundle waitable objects together in the enum to let the compiler optimize certain checks better
     Event, Mutex, Port, Semaphore, Timer, Thread
 };
@@ -142,6 +146,7 @@ static const char* kernelObjectTypeToString(KernelObjectType t) {
         case KernelObjectType::Archive: return "archive";
         case KernelObjectType::Event: return "event";
         case KernelObjectType::File: return "file";
+        case KernelObjectType::MemoryBlock: return "memory block";
         case KernelObjectType::Port: return "port";
         case KernelObjectType::Process: return "process";
         case KernelObjectType::ResourceLimit: return "resource limit";
@@ -168,6 +173,17 @@ struct Semaphore {
     Semaphore(u32 initialCount, u32 maximumCount) : initialCount(initialCount), maximumCount(maximumCount) {}
 };
 
+struct MemoryBlock {
+    u32 addr = 0;
+    u32 size = 0;
+    u32 myPermission = 0;
+    u32 otherPermission = 0;
+    bool mapped = false;
+
+    MemoryBlock(u32 addr, u32 size, u32 myPerm, u32 otherPerm) : addr(addr), size(size), myPermission(myPerm), otherPermission(otherPerm),
+        mapped(false) {}
+};
+
 // Generic kernel object class
 struct KernelObject {
     Handle handle = 0; // A u32 the OS will use to identify objects
diff --git a/include/services/mic.hpp b/include/services/mic.hpp
index a83eb5dc..a7af986d 100644
--- a/include/services/mic.hpp
+++ b/include/services/mic.hpp
@@ -10,6 +10,7 @@ class MICService {
 	MAKE_LOG_FUNCTION(log, micLogger)
 
 	// Service commands
+	void mapSharedMem(u32 messagePointer);
 
 public:
 	MICService(Memory& mem) : mem(mem) {}
diff --git a/src/core/kernel/memory_management.cpp b/src/core/kernel/memory_management.cpp
index a6e22c54..3c171231 100644
--- a/src/core/kernel/memory_management.cpp
+++ b/src/core/kernel/memory_management.cpp
@@ -16,6 +16,21 @@ namespace Operation {
 	};
 }
 
+namespace MemoryPermissions {
+	enum : u32 {
+		None = 0,             // ---
+		Read = 1,             // R--
+		Write = 2,            // -W-
+		ReadWrite = 3,        // RW-
+		Execute = 4,          // --X
+		ReadExecute = 5,      // R-X
+		WriteExecute = 6,     // -WX
+		ReadWriteExecute = 7, // RWX
+
+		DontCare = 0x10000000
+	};
+}
+
 // Returns whether "value" is aligned to a page boundary (Ie a boundary of 4096 bytes)
 static constexpr bool isAligned(u32 value) {
 	return (value & 0xFFF) == 0;
@@ -32,8 +47,8 @@ void Kernel::controlMemory() {
 	u32 size = regs[3];
 	u32 perms = regs[4];
 
-	if (perms == 0x10000000) {
-		perms = 3; // We make "don't care" equivalent to read-write
+	if (perms == MemoryPermissions::DontCare) {
+		perms = MemoryPermissions::ReadWrite; // We make "don't care" equivalent to read-write
 		Helpers::panic("Unimplemented allocation permission: DONTCARE");
 	}
 
@@ -126,13 +141,56 @@ void Kernel::mapMemoryBlock() {
 	regs[0] = SVCResult::Success;
 }
 
+Handle Kernel::makeMemoryBlock(u32 addr, u32 size, u32 myPermission, u32 otherPermission) {
+	Handle ret = makeObject(KernelObjectType::MemoryBlock);
+	objects[ret].data = new MemoryBlock(addr, size, myPermission, otherPermission);
+
+	return ret;
+}
+
 void Kernel::createMemoryBlock() {
 	const u32 addr = regs[1];
 	const u32 size = regs[2];
-	const u32 myPermission = regs[3];
-	const u32 otherPermission = regs[4];
+	u32 myPermission = regs[3];
+	u32 otherPermission = mem.read32(regs[13] + 4); // This is placed on the stack rather than r4
 	logSVC("CreateMemoryBlock (addr = %08X, size = %08X, myPermission = %d, otherPermission = %d)\n", addr, size, myPermission, otherPermission);
 
-	regs[0] = SVCResult::Success; regs[1] = 0x66666666;
-	//Helpers::panic("Kernel::CreateMemoryBlock");
+	// Returns whether a permission is valid
+	auto isPermValid = [](u32 permission) {
+		switch (permission) {
+			case MemoryPermissions::None:
+			case MemoryPermissions::Read:
+			case MemoryPermissions::Write:
+			case MemoryPermissions::ReadWrite:
+			case MemoryPermissions::DontCare:
+				return true;
+
+			default: // Permissions with the executable flag enabled or invalid permissions are not allowed
+				return false;
+		}
+	};
+
+	// Throw error if the size of the shared memory block is not aligned to page boundary
+	if (!isAligned(size)) {
+		regs[0] = SVCResult::UnalignedSize;
+		return;
+	}
+
+	// Throw error if one of the permissions is not valid
+	if (!isPermValid(myPermission) || !isPermValid(otherPermission)) {
+		regs[0] = SVCResult::InvalidCombination;
+		return;
+	}
+
+	// TODO: The address needs to be in a specific range otherwise it throws an invalid address error
+
+	if (addr == 0)
+		Helpers::panic("CreateMemoryBlock: Tried to use addr = 0");
+
+	// Implement "Don't care" permission as RW
+	if (myPermission == MemoryPermissions::DontCare) myPermission = MemoryPermissions::ReadWrite;
+	if (otherPermission == MemoryPermissions::DontCare) otherPermission = MemoryPermissions::ReadWrite;
+
+	regs[0] = SVCResult::Success; 
+	regs[1] = makeMemoryBlock(addr, size, myPermission, otherPermission);
 }
\ No newline at end of file
diff --git a/src/core/services/mic.cpp b/src/core/services/mic.cpp
index 4c4ef2c9..248b5ff5 100644
--- a/src/core/services/mic.cpp
+++ b/src/core/services/mic.cpp
@@ -2,6 +2,7 @@
 
 namespace MICCommands {
 	enum : u32 {
+		MapSharedMem = 0x00010042
 	};
 }
 
@@ -16,6 +17,15 @@ void MICService::reset() {}
 void MICService::handleSyncRequest(u32 messagePointer) {
 	const u32 command = mem.read32(messagePointer);
 	switch (command) {
+		case MICCommands::MapSharedMem: mapSharedMem(messagePointer); break;
 		default: Helpers::panic("MIC service requested. Command: %08X\n", command);
 	}
+}
+
+void MICService::mapSharedMem(u32 messagePointer) {
+	u32 size = mem.read32(messagePointer + 4);
+	u32 handle = mem.read32(messagePointer + 12);
+
+	log("MIC::MapSharedMem (size = %08X, handle = %X) (stubbed)\n", size, handle);
+	mem.write32(messagePointer + 4, Result::Success);
 }
\ No newline at end of file