Add support for PermissionLocked attribute added on firmware 17.0.0 (#6072)

* Update MemoryState enum and add new flags

* Add support for new PermissionLocked attribute added on firmware 17.0.0

* Format whitespace
This commit is contained in:
gdkchan 2024-01-03 20:05:14 -03:00 committed by GitHub
parent f11d663df7
commit 6f50b9bdb0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 172 additions and 35 deletions

View file

@ -675,7 +675,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
KMemoryPermission.None, KMemoryPermission.None,
MemoryAttribute.Mask, MemoryAttribute.Mask,
MemoryAttribute.None, MemoryAttribute.None,
MemoryAttribute.IpcAndDeviceMapped, MemoryAttribute.IpcAndDeviceMapped | MemoryAttribute.PermissionLocked,
out MemoryState state, out MemoryState state,
out _, out _,
out _); out _);
@ -687,7 +687,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
state, state,
KMemoryPermission.None, KMemoryPermission.None,
KMemoryPermission.None, KMemoryPermission.None,
MemoryAttribute.Mask, MemoryAttribute.Mask & ~MemoryAttribute.PermissionLocked,
MemoryAttribute.None); MemoryAttribute.None);
if (success) if (success)
@ -913,19 +913,27 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
return Result.Success; return Result.Success;
} }
public Result SetMemoryAttribute( public Result SetMemoryAttribute(ulong address, ulong size, MemoryAttribute attributeMask, MemoryAttribute attributeValue)
ulong address,
ulong size,
MemoryAttribute attributeMask,
MemoryAttribute attributeValue)
{ {
lock (_blockManager) lock (_blockManager)
{ {
MemoryState stateCheckMask = 0;
if (attributeMask.HasFlag(MemoryAttribute.Uncached))
{
stateCheckMask = MemoryState.AttributeChangeAllowed;
}
if (attributeMask.HasFlag(MemoryAttribute.PermissionLocked))
{
stateCheckMask |= MemoryState.PermissionLockAllowed;
}
if (CheckRange( if (CheckRange(
address, address,
size, size,
MemoryState.AttributeChangeAllowed, stateCheckMask,
MemoryState.AttributeChangeAllowed, stateCheckMask,
KMemoryPermission.None, KMemoryPermission.None,
KMemoryPermission.None, KMemoryPermission.None,
MemoryAttribute.BorrowedAndIpcMapped, MemoryAttribute.BorrowedAndIpcMapped,

View file

@ -12,11 +12,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
IpcMapped = 1 << 1, IpcMapped = 1 << 1,
DeviceMapped = 1 << 2, DeviceMapped = 1 << 2,
Uncached = 1 << 3, Uncached = 1 << 3,
PermissionLocked = 1 << 4,
IpcAndDeviceMapped = IpcMapped | DeviceMapped, IpcAndDeviceMapped = IpcMapped | DeviceMapped,
BorrowedAndIpcMapped = Borrowed | IpcMapped, BorrowedAndIpcMapped = Borrowed | IpcMapped,
DeviceMappedAndUncached = DeviceMapped | Uncached, DeviceMappedAndUncached = DeviceMapped | Uncached,
} }
} }

View file

@ -5,35 +5,155 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
[Flags] [Flags]
enum MemoryState : uint enum MemoryState : uint
{ {
Unmapped = 0x00000000, Unmapped = 0x0,
Io = 0x00002001, Io = Mapped | 0x1,
Normal = 0x00042002, Normal = Mapped | QueryPhysicalAddressAllowed | 0x2,
CodeStatic = 0x00DC7E03, CodeStatic = ForceReadWritableByDebugSyscalls |
CodeMutable = 0x03FEBD04, IpcSendAllowedType0 |
Heap = 0x037EBD05, IpcSendAllowedType3 |
SharedMemory = 0x00402006, IpcSendAllowedType1 |
ModCodeStatic = 0x00DD7E08, Mapped |
ModCodeMutable = 0x03FFBD09, ProcessPermissionChangeAllowed |
IpcBuffer0 = 0x005C3C0A, QueryPhysicalAddressAllowed |
Stack = 0x005C3C0B, MapDeviceAllowed |
ThreadLocal = 0x0040200C, MapDeviceAlignedAllowed |
TransferMemoryIsolated = 0x015C3C0D, IsPoolAllocated |
TransferMemory = 0x005C380E, MapProcessAllowed |
ProcessMemory = 0x0040380F, LinearMapped |
Reserved = 0x00000010, 0x3,
IpcBuffer1 = 0x005C3811, CodeMutable = PermissionChangeAllowed |
IpcBuffer3 = 0x004C2812, IpcSendAllowedType0 |
KernelStack = 0x00002013, IpcSendAllowedType3 |
CodeReadOnly = 0x00402214, IpcSendAllowedType1 |
CodeWritable = 0x00402015, Mapped |
UserMask = 0xff, MapAllowed |
Mask = 0xffffffff, TransferMemoryAllowed |
QueryPhysicalAddressAllowed |
MapDeviceAllowed |
MapDeviceAlignedAllowed |
IpcBufferAllowed |
IsPoolAllocated |
MapProcessAllowed |
AttributeChangeAllowed |
CodeMemoryAllowed |
LinearMapped |
PermissionLockAllowed |
0x4,
Heap = PermissionChangeAllowed |
IpcSendAllowedType0 |
IpcSendAllowedType3 |
IpcSendAllowedType1 |
Mapped |
MapAllowed |
TransferMemoryAllowed |
QueryPhysicalAddressAllowed |
MapDeviceAllowed |
MapDeviceAlignedAllowed |
IpcBufferAllowed |
IsPoolAllocated |
AttributeChangeAllowed |
CodeMemoryAllowed |
LinearMapped |
0x5,
SharedMemory = Mapped | IsPoolAllocated | LinearMapped | 0x6,
ModCodeStatic = ForceReadWritableByDebugSyscalls |
IpcSendAllowedType0 |
IpcSendAllowedType3 |
IpcSendAllowedType1 |
Mapped |
ProcessPermissionChangeAllowed |
UnmapProcessCodeMemoryAllowed |
QueryPhysicalAddressAllowed |
MapDeviceAllowed |
MapDeviceAlignedAllowed |
IsPoolAllocated |
MapProcessAllowed |
LinearMapped |
0x8,
ModCodeMutable = PermissionChangeAllowed |
IpcSendAllowedType0 |
IpcSendAllowedType3 |
IpcSendAllowedType1 |
Mapped |
MapAllowed |
UnmapProcessCodeMemoryAllowed |
TransferMemoryAllowed |
QueryPhysicalAddressAllowed |
MapDeviceAllowed |
MapDeviceAlignedAllowed |
IpcBufferAllowed |
IsPoolAllocated |
MapProcessAllowed |
AttributeChangeAllowed |
CodeMemoryAllowed |
LinearMapped |
PermissionLockAllowed |
0x9,
IpcBuffer0 = IpcSendAllowedType0 |
IpcSendAllowedType3 |
IpcSendAllowedType1 |
Mapped |
QueryPhysicalAddressAllowed |
MapDeviceAllowed |
MapDeviceAlignedAllowed |
IsPoolAllocated |
LinearMapped |
0xA,
Stack = IpcSendAllowedType0 |
IpcSendAllowedType3 |
IpcSendAllowedType1 |
Mapped |
QueryPhysicalAddressAllowed |
MapDeviceAllowed |
MapDeviceAlignedAllowed |
IsPoolAllocated |
LinearMapped |
0xB,
ThreadLocal = Mapped | IsPoolAllocated | LinearMapped | 0xC,
TransferMemoryIsolated = IpcSendAllowedType0 |
IpcSendAllowedType3 |
IpcSendAllowedType1 |
Mapped |
QueryPhysicalAddressAllowed |
MapDeviceAllowed |
MapDeviceAlignedAllowed |
IsPoolAllocated |
AttributeChangeAllowed |
LinearMapped |
0xD,
TransferMemory = IpcSendAllowedType3 |
IpcSendAllowedType1 |
Mapped |
QueryPhysicalAddressAllowed |
MapDeviceAllowed |
MapDeviceAlignedAllowed |
IsPoolAllocated |
LinearMapped |
0xE,
ProcessMemory = IpcSendAllowedType3 | IpcSendAllowedType1 | Mapped | IsPoolAllocated | LinearMapped | 0xF,
Reserved = 0x10,
IpcBuffer1 = IpcSendAllowedType3 |
IpcSendAllowedType1 |
Mapped |
QueryPhysicalAddressAllowed |
MapDeviceAllowed |
MapDeviceAlignedAllowed |
IsPoolAllocated |
LinearMapped |
0x11,
IpcBuffer3 = IpcSendAllowedType3 | Mapped | QueryPhysicalAddressAllowed | MapDeviceAllowed | IsPoolAllocated | LinearMapped | 0x12,
KernelStack = Mapped | 0x13,
CodeReadOnly = ForceReadWritableByDebugSyscalls | Mapped | IsPoolAllocated | LinearMapped | 0x14,
CodeWritable = Mapped | IsPoolAllocated | LinearMapped | 0x15,
UserMask = 0xFF,
Mask = 0xFFFFFFFF,
PermissionChangeAllowed = 1 << 8, PermissionChangeAllowed = 1 << 8,
ForceReadWritableByDebugSyscalls = 1 << 9, ForceReadWritableByDebugSyscalls = 1 << 9,
IpcSendAllowedType0 = 1 << 10, IpcSendAllowedType0 = 1 << 10,
IpcSendAllowedType3 = 1 << 11, IpcSendAllowedType3 = 1 << 11,
IpcSendAllowedType1 = 1 << 12, IpcSendAllowedType1 = 1 << 12,
Mapped = 1 << 13,
ProcessPermissionChangeAllowed = 1 << 14, ProcessPermissionChangeAllowed = 1 << 14,
MapAllowed = 1 << 15, MapAllowed = 1 << 15,
UnmapProcessCodeMemoryAllowed = 1 << 16, UnmapProcessCodeMemoryAllowed = 1 << 16,
@ -46,5 +166,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
MapProcessAllowed = 1 << 23, MapProcessAllowed = 1 << 23,
AttributeChangeAllowed = 1 << 24, AttributeChangeAllowed = 1 << 24,
CodeMemoryAllowed = 1 << 25, CodeMemoryAllowed = 1 << 25,
LinearMapped = 1 << 26,
PermissionLockAllowed = 1 << 27,
} }
} }

View file

@ -949,8 +949,16 @@ namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall
MemoryAttribute attributes = attributeMask | attributeValue; MemoryAttribute attributes = attributeMask | attributeValue;
const MemoryAttribute SupportedAttributes = MemoryAttribute.Uncached | MemoryAttribute.PermissionLocked;
if (attributes != attributeMask || if (attributes != attributeMask ||
(attributes | MemoryAttribute.Uncached) != MemoryAttribute.Uncached) (attributes | SupportedAttributes) != SupportedAttributes)
{
return KernelResult.InvalidCombination;
}
// The permission locked attribute can't be unset.
if ((attributeMask & MemoryAttribute.PermissionLocked) != (attributeValue & MemoryAttribute.PermissionLocked))
{ {
return KernelResult.InvalidCombination; return KernelResult.InvalidCombination;
} }