kernel: Implement SetMemoryPermission syscall (#2772)
* kernel: Implement SetMemoryPermission syscall This commit implement the SetMemoryPermission syscall accurately. This also fix KMemoryPermission not being an unsigned 32 bits type and add the "DontCare" bit (used by shared memory, currently unused in Ryujinx) * Update MemoryPermission mask * Address gdkchan's comments * Fix a nit * Address gdkchan's comment
This commit is contained in:
parent
e7e65ccbc9
commit
c94d47cc40
6 changed files with 102 additions and 5 deletions
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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) },
|
||||
|
|
Reference in a new issue