forked from emmauss/Ryujinx
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement code memory syscalls (#2958)
* Implement code memory syscalls * Remove owner process validation * Add 32-bit code memory syscalls * Remove unused field
- Loading branch information
Showing
7 changed files
with
632 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
using Ryujinx.Common; | ||
using Ryujinx.HLE.HOS.Kernel.Common; | ||
using Ryujinx.HLE.HOS.Kernel.Process; | ||
using System; | ||
using System.Diagnostics; | ||
|
||
namespace Ryujinx.HLE.HOS.Kernel.Memory | ||
{ | ||
class KCodeMemory : KAutoObject | ||
{ | ||
public KProcess Owner { get; private set; } | ||
private readonly KPageList _pageList; | ||
private readonly object _lock; | ||
private ulong _address; | ||
private bool _isOwnerMapped; | ||
private bool _isMapped; | ||
|
||
public KCodeMemory(KernelContext context) : base(context) | ||
{ | ||
_pageList = new KPageList(); | ||
_lock = new object(); | ||
} | ||
|
||
public KernelResult Initialize(ulong address, ulong size) | ||
{ | ||
Owner = KernelStatic.GetCurrentProcess(); | ||
|
||
KernelResult result = Owner.MemoryManager.BorrowCodeMemory(_pageList, address, size); | ||
|
||
if (result != KernelResult.Success) | ||
{ | ||
return result; | ||
} | ||
|
||
Owner.CpuMemory.Fill(address, size, 0xff); | ||
Owner.IncrementReferenceCount(); | ||
|
||
_address = address; | ||
_isMapped = false; | ||
_isOwnerMapped = false; | ||
|
||
return KernelResult.Success; | ||
} | ||
|
||
public KernelResult Map(ulong address, ulong size, KMemoryPermission perm) | ||
{ | ||
if (_pageList.GetPagesCount() != BitUtils.DivRoundUp(size, KPageTableBase.PageSize)) | ||
{ | ||
return KernelResult.InvalidSize; | ||
} | ||
|
||
lock (_lock) | ||
{ | ||
if (_isMapped) | ||
{ | ||
return KernelResult.InvalidState; | ||
} | ||
|
||
KProcess process = KernelStatic.GetCurrentProcess(); | ||
|
||
KernelResult result = process.MemoryManager.MapPages(address, _pageList, MemoryState.CodeWritable, KMemoryPermission.ReadAndWrite); | ||
|
||
if (result != KernelResult.Success) | ||
{ | ||
return result; | ||
} | ||
|
||
_isMapped = true; | ||
} | ||
|
||
return KernelResult.Success; | ||
} | ||
|
||
public KernelResult MapToOwner(ulong address, ulong size, KMemoryPermission permission) | ||
{ | ||
if (_pageList.GetPagesCount() != BitUtils.DivRoundUp(size, KPageTableBase.PageSize)) | ||
{ | ||
return KernelResult.InvalidSize; | ||
} | ||
|
||
lock (_lock) | ||
{ | ||
if (_isOwnerMapped) | ||
{ | ||
return KernelResult.InvalidState; | ||
} | ||
|
||
Debug.Assert(permission == KMemoryPermission.Read || permission == KMemoryPermission.ReadAndExecute); | ||
|
||
KernelResult result = Owner.MemoryManager.MapPages(address, _pageList, MemoryState.CodeReadOnly, permission); | ||
|
||
if (result != KernelResult.Success) | ||
{ | ||
return result; | ||
} | ||
|
||
_isOwnerMapped = true; | ||
} | ||
|
||
return KernelResult.Success; | ||
} | ||
|
||
public KernelResult Unmap(ulong address, ulong size) | ||
{ | ||
if (_pageList.GetPagesCount() != BitUtils.DivRoundUp(size, KPageTableBase.PageSize)) | ||
{ | ||
return KernelResult.InvalidSize; | ||
} | ||
|
||
lock (_lock) | ||
{ | ||
KProcess process = KernelStatic.GetCurrentProcess(); | ||
|
||
KernelResult result = process.MemoryManager.UnmapPages(address, _pageList, MemoryState.CodeWritable); | ||
|
||
if (result != KernelResult.Success) | ||
{ | ||
return result; | ||
} | ||
|
||
Debug.Assert(_isMapped); | ||
|
||
_isMapped = false; | ||
} | ||
|
||
return KernelResult.Success; | ||
} | ||
|
||
public KernelResult UnmapFromOwner(ulong address, ulong size) | ||
{ | ||
if (_pageList.GetPagesCount() != BitUtils.DivRoundUp(size, KPageTableBase.PageSize)) | ||
{ | ||
return KernelResult.InvalidSize; | ||
} | ||
|
||
lock (_lock) | ||
{ | ||
KernelResult result = Owner.MemoryManager.UnmapPages(address, _pageList, MemoryState.CodeReadOnly); | ||
|
||
if (result != KernelResult.Success) | ||
{ | ||
return result; | ||
} | ||
|
||
Debug.Assert(_isOwnerMapped); | ||
|
||
_isOwnerMapped = false; | ||
} | ||
|
||
return KernelResult.Success; | ||
} | ||
|
||
protected override void Destroy() | ||
{ | ||
if (!_isMapped && !_isOwnerMapped) | ||
{ | ||
ulong size = _pageList.GetPagesCount() * KPageTableBase.PageSize; | ||
|
||
if (Owner.MemoryManager.UnborrowCodeMemory(_address, size, _pageList) != KernelResult.Success) | ||
{ | ||
throw new InvalidOperationException("Unexpected failure restoring transfer memory attributes."); | ||
} | ||
} | ||
|
||
Owner.DecrementReferenceCount(); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
10 changes: 10 additions & 0 deletions
10
Ryujinx.HLE/HOS/Kernel/SupervisorCall/CodeMemoryOperation.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
namespace Ryujinx.HLE.HOS.Kernel.SupervisorCall | ||
{ | ||
enum CodeMemoryOperation : uint | ||
{ | ||
Map, | ||
MapToOwner, | ||
Unmap, | ||
UnmapFromOwner | ||
}; | ||
} |
Oops, something went wrong.