aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs46
-rw-r--r--Ryujinx.HLE/HOS/Kernel/Memory/MemoryPermission.cs11
-rw-r--r--Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs32
-rw-r--r--Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall32.cs8
-rw-r--r--Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall64.cs8
-rw-r--r--Ryujinx.HLE/HOS/Kernel/SupervisorCall/SyscallTable.cs2
6 files changed, 102 insertions, 5 deletions
diff --git a/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs b/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs
index e1ab0b93..965e03d9 100644
--- a/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs
+++ b/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs
@@ -799,6 +799,52 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
return KernelResult.Success;
}
+ public KernelResult SetMemoryPermission(ulong address, ulong size, KMemoryPermission permission)
+ {
+ lock (_blockManager)
+ {
+ if (CheckRange(
+ address,
+ size,
+ MemoryState.PermissionChangeAllowed,
+ MemoryState.PermissionChangeAllowed,
+ KMemoryPermission.None,
+ KMemoryPermission.None,
+ MemoryAttribute.Mask,
+ MemoryAttribute.None,
+ MemoryAttribute.IpcAndDeviceMapped,
+ out MemoryState oldState,
+ out KMemoryPermission oldPermission,
+ out _))
+ {
+ if (permission != oldPermission)
+ {
+ if (!_slabManager.CanAllocate(MaxBlocksNeededForInsertion))
+ {
+ return KernelResult.OutOfResource;
+ }
+
+ ulong pagesCount = size / PageSize;
+
+ KernelResult result = Reprotect(address, pagesCount, permission);
+
+ if (result != KernelResult.Success)
+ {
+ return result;
+ }
+
+ _blockManager.InsertBlock(address, pagesCount, oldState, permission);
+ }
+
+ return KernelResult.Success;
+ }
+ else
+ {
+ return KernelResult.InvalidMemState;
+ }
+ }
+ }
+
public ulong GetTotalHeapSize()
{
lock (_blockManager)
diff --git a/Ryujinx.HLE/HOS/Kernel/Memory/MemoryPermission.cs b/Ryujinx.HLE/HOS/Kernel/Memory/MemoryPermission.cs
index 8bfd8d94..12300e4f 100644
--- a/Ryujinx.HLE/HOS/Kernel/Memory/MemoryPermission.cs
+++ b/Ryujinx.HLE/HOS/Kernel/Memory/MemoryPermission.cs
@@ -3,14 +3,15 @@ using System;
namespace Ryujinx.HLE.HOS.Kernel.Memory
{
[Flags]
- enum KMemoryPermission : byte
+ enum KMemoryPermission : uint
{
None = 0,
- Mask = 0xff,
+ Mask = uint.MaxValue,
- Read = 1 << 0,
- Write = 1 << 1,
- Execute = 1 << 2,
+ Read = 1 << 0,
+ Write = 1 << 1,
+ Execute = 1 << 2,
+ DontCare = 1 << 28,
ReadAndWrite = Read | Write,
ReadAndExecute = Read | Execute
diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs
index 4718d412..237c1a54 100644
--- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs
+++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall.cs
@@ -819,6 +819,38 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return process.MemoryManager.SetHeapSize(size, out position);
}
+ public KernelResult SetMemoryPermission(ulong address, ulong size, KMemoryPermission permission)
+ {
+ if (!PageAligned(address))
+ {
+ return KernelResult.InvalidAddress;
+ }
+
+ if (!PageAligned(size) || size == 0)
+ {
+ return KernelResult.InvalidSize;
+ }
+
+ if (address + size <= address)
+ {
+ return KernelResult.InvalidMemState;
+ }
+
+ if (permission == KMemoryPermission.None || (permission | KMemoryPermission.Write) != KMemoryPermission.ReadAndWrite)
+ {
+ return KernelResult.InvalidPermission;
+ }
+
+ KProcess currentProcess = KernelStatic.GetCurrentProcess();
+
+ if (!currentProcess.MemoryManager.InsideAddrSpace(address, size))
+ {
+ return KernelResult.InvalidMemState;
+ }
+
+ return currentProcess.MemoryManager.SetMemoryPermission(address, size, permission);
+ }
+
public KernelResult SetMemoryAttribute(
ulong position,
ulong size,
diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall32.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall32.cs
index 1875facb..d9a14502 100644
--- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall32.cs
+++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall32.cs
@@ -88,6 +88,14 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return result;
}
+ public KernelResult SetMemoryPermission32(
+ [R(0)] ulong position,
+ [R(1)] ulong size,
+ [R(2)] KMemoryPermission permission)
+ {
+ return _syscall.SetMemoryPermission(position, size, permission);
+ }
+
public KernelResult SetMemoryAttribute32(
[R(0)] uint position,
[R(1)] uint size,
diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall64.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall64.cs
index c22397cf..00dbb1e4 100644
--- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall64.cs
+++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/Syscall64.cs
@@ -109,6 +109,14 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
return _syscall.SetHeapSize(size, out position);
}
+ public KernelResult SetMemoryPermission64(
+ [R(0)] ulong position,
+ [R(1)] ulong size,
+ [R(2)] KMemoryPermission permission)
+ {
+ return _syscall.SetMemoryPermission(position, size, permission);
+ }
+
public KernelResult SetMemoryAttribute64(
[R(0)] ulong position,
[R(1)] ulong size,
diff --git a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SyscallTable.cs b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SyscallTable.cs
index 790a3179..bf263d7b 100644
--- a/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SyscallTable.cs
+++ b/Ryujinx.HLE/HOS/Kernel/SupervisorCall/SyscallTable.cs
@@ -25,6 +25,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
Dictionary<int, string> svcFuncs64 = new Dictionary<int, string>
{
{ 0x01, nameof(Syscall64.SetHeapSize64) },
+ { 0x02, nameof(Syscall64.SetMemoryPermission64) },
{ 0x03, nameof(Syscall64.SetMemoryAttribute64) },
{ 0x04, nameof(Syscall64.MapMemory64) },
{ 0x05, nameof(Syscall64.UnmapMemory64) },
@@ -94,6 +95,7 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
Dictionary<int, string> svcFuncs32 = new Dictionary<int, string>
{
{ 0x01, nameof(Syscall32.SetHeapSize32) },
+ { 0x02, nameof(Syscall32.SetMemoryPermission32) },
{ 0x03, nameof(Syscall32.SetMemoryAttribute32) },
{ 0x04, nameof(Syscall32.MapMemory32) },
{ 0x05, nameof(Syscall32.UnmapMemory32) },