diff --git a/Ryujinx.HLE/HOS/Kernel/Memory/KPageTable.cs b/Ryujinx.HLE/HOS/Kernel/Memory/KPageTable.cs
index 20a13f576..d7ee04e32 100644
--- a/Ryujinx.HLE/HOS/Kernel/Memory/KPageTable.cs
+++ b/Ryujinx.HLE/HOS/Kernel/Memory/KPageTable.cs
@@ -86,7 +86,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
}
///
- protected override KernelResult MapPages(ulong dstVa, ulong pagesCount, ulong srcPa, KMemoryPermission permission)
+ protected override KernelResult MapPages(ulong dstVa, ulong pagesCount, ulong srcPa, KMemoryPermission permission, bool shouldFillPages, byte fillValue)
{
ulong size = pagesCount * PageSize;
@@ -99,11 +99,16 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
Context.MemoryManager.IncrementPagesReferenceCount(srcPa, pagesCount);
}
+ if (shouldFillPages)
+ {
+ _cpuMemory.Fill(dstVa, size, fillValue);
+ }
+
return KernelResult.Success;
}
///
- protected override KernelResult MapPages(ulong address, KPageList pageList, KMemoryPermission permission)
+ protected override KernelResult MapPages(ulong address, KPageList pageList, KMemoryPermission permission, bool shouldFillPages, byte fillValue)
{
using var scopedPageList = new KScopedPageList(Context.MemoryManager, pageList);
@@ -118,6 +123,11 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
_cpuMemory.Map(currentVa, Context.Memory.GetPointer(addr, size), size);
+ if (shouldFillPages)
+ {
+ _cpuMemory.Fill(currentVa, size, fillValue);
+ }
+
currentVa += size;
}
diff --git a/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs b/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs
index 965e03d9e..ff87ecb79 100644
--- a/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs
+++ b/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableBase.cs
@@ -75,6 +75,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
public abstract bool SupportsMemoryAliasing { get; }
+ private MemoryFillValue _heapFillValue;
+ private MemoryFillValue _ipcFillValue;
+
public KPageTableBase(KernelContext context)
{
Context = context;
@@ -82,6 +85,9 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
_blockManager = new KMemoryBlockManager();
_isKernel = false;
+
+ _heapFillValue = MemoryFillValue.Zero;
+ _ipcFillValue = MemoryFillValue.Zero;
}
private static readonly int[] AddrSpaceSizes = new int[] { 32, 36, 32, 39 };
@@ -299,6 +305,8 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
TlsIoRegionStart = tlsIoRegion.Start;
TlsIoRegionEnd = tlsIoRegion.End;
+ // TODO: Check kernel configuration via secure monitor call when implemented to set memory fill values.
+
_currentHeapAddr = HeapRegionStart;
_heapCapacity = 0;
PhysicalMemoryUsage = 0;
@@ -738,7 +746,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
return KernelResult.InvalidMemState;
}
- result = MapPages(_currentHeapAddr, pageList, KMemoryPermission.ReadAndWrite);
+ result = MapPages(_currentHeapAddr, pageList, KMemoryPermission.ReadAndWrite, true, (byte)_heapFillValue);
if (result != KernelResult.Success)
{
@@ -1783,7 +1791,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
{
ulong unusedSizeBefore = address - addressTruncated;
- Context.Memory.ZeroFill(GetDramAddressFromPa(dstFirstPagePa), unusedSizeBefore);
+ Context.Memory.Fill(GetDramAddressFromPa(dstFirstPagePa), unusedSizeBefore, (byte)_ipcFillValue);
ulong copySize = addressRounded <= endAddr ? addressRounded - address : size;
var data = srcPageTable.GetSpan(addressTruncated + unusedSizeBefore, (int)copySize);
@@ -1801,7 +1809,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
if (unusedSizeAfter != 0)
{
- Context.Memory.ZeroFill(GetDramAddressFromPa(firstPageFillAddress), unusedSizeAfter);
+ Context.Memory.Fill(GetDramAddressFromPa(firstPageFillAddress), unusedSizeAfter, (byte)_ipcFillValue);
}
KernelResult result = MapPages(currentVa, 1, dstFirstPagePa, permission);
@@ -1853,7 +1861,7 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
unusedSizeAfter = PageSize;
}
- Context.Memory.ZeroFill(GetDramAddressFromPa(lastPageFillAddr), unusedSizeAfter);
+ Context.Memory.Fill(GetDramAddressFromPa(lastPageFillAddr), unusedSizeAfter, (byte)_ipcFillValue);
KernelResult result = MapPages(currentVa, 1, dstLastPagePa, permission);
@@ -2779,8 +2787,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
/// Number of pages to map
/// Physical address where the pages should be mapped. May be ignored if aliasing is not supported
/// Permission of the region to be mapped
+ /// Indicate if the pages should be filled with the value
+ /// The value used to fill pages when is set to true
/// Result of the mapping operation
- protected abstract KernelResult MapPages(ulong dstVa, ulong pagesCount, ulong srcPa, KMemoryPermission permission);
+ protected abstract KernelResult MapPages(ulong dstVa, ulong pagesCount, ulong srcPa, KMemoryPermission permission, bool shouldFillPages = false, byte fillValue = 0);
///
/// Maps a region of memory into the specified physical memory region.
@@ -2788,8 +2798,10 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
/// Destination virtual address that should be mapped
/// List of physical memory pages where the pages should be mapped. May be ignored if aliasing is not supported
/// Permission of the region to be mapped
+ /// Indicate if the pages should be filled with the value
+ /// The value used to fill pages when is set to true
/// Result of the mapping operation
- protected abstract KernelResult MapPages(ulong address, KPageList pageList, KMemoryPermission permission);
+ protected abstract KernelResult MapPages(ulong address, KPageList pageList, KMemoryPermission permission, bool shouldFillPages = false, byte fillValue = 0);
///
/// Maps a region of memory into the specified host memory ranges.
diff --git a/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableHostMapped.cs b/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableHostMapped.cs
index cd51bab7c..29a7b2ed6 100644
--- a/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableHostMapped.cs
+++ b/Ryujinx.HLE/HOS/Kernel/Memory/KPageTableHostMapped.cs
@@ -70,16 +70,30 @@ namespace Ryujinx.HLE.HOS.Kernel.Memory
}
///
- protected override KernelResult MapPages(ulong dstVa, ulong pagesCount, ulong srcPa, KMemoryPermission permission)
+ protected override KernelResult MapPages(ulong dstVa, ulong pagesCount, ulong srcPa, KMemoryPermission permission, bool shouldFillPages, byte fillValue)
{
_cpuMemory.Map(dstVa, 0, pagesCount * PageSize);
+
+ if (shouldFillPages)
+ {
+ _cpuMemory.Fill(dstVa, pagesCount * PageSize, fillValue);
+ }
+
return KernelResult.Success;
}
///
- protected override KernelResult MapPages(ulong address, KPageList pageList, KMemoryPermission permission)
+ protected override KernelResult MapPages(ulong address, KPageList pageList, KMemoryPermission permission, bool shouldFillPages, byte fillValue)
{
- _cpuMemory.Map(address, 0, pageList.GetPagesCount() * PageSize);
+ ulong pagesCount = pageList.GetPagesCount();
+
+ _cpuMemory.Map(address, 0, pagesCount * PageSize);
+
+ if (shouldFillPages)
+ {
+ _cpuMemory.Fill(address, pagesCount * PageSize, fillValue);
+ }
+
return KernelResult.Success;
}
diff --git a/Ryujinx.HLE/HOS/Kernel/Memory/MemoryFillValue.cs b/Ryujinx.HLE/HOS/Kernel/Memory/MemoryFillValue.cs
new file mode 100644
index 000000000..cdc892fc5
--- /dev/null
+++ b/Ryujinx.HLE/HOS/Kernel/Memory/MemoryFillValue.cs
@@ -0,0 +1,10 @@
+namespace Ryujinx.HLE.HOS.Kernel.Memory
+{
+ enum MemoryFillValue : byte
+ {
+ Zero = 0,
+ Stack = 0x58,
+ Ipc = 0x59,
+ Heap = 0x5A,
+ }
+}
diff --git a/Ryujinx.Memory/MemoryBlock.cs b/Ryujinx.Memory/MemoryBlock.cs
index 25c66dfe3..3561b81a6 100644
--- a/Ryujinx.Memory/MemoryBlock.cs
+++ b/Ryujinx.Memory/MemoryBlock.cs
@@ -216,13 +216,14 @@ namespace Ryujinx.Memory
}
///
- /// Fills a region of memory with zeros.
+ /// Fills a region of memory with .
///
- /// Offset of the region to fill with zeros
+ /// Offset of the region to fill with
/// Size in bytes of the region to fill
+ /// Value to use for the fill
/// Throw when the memory block has already been disposed
/// Throw when either or are out of range
- public void ZeroFill(ulong offset, ulong size)
+ public void Fill(ulong offset, ulong size, byte value)
{
const int MaxChunkSize = 1 << 24;
@@ -230,7 +231,7 @@ namespace Ryujinx.Memory
{
int copySize = (int)Math.Min(MaxChunkSize, size - subOffset);
- GetSpan(offset + subOffset, copySize).Fill(0);
+ GetSpan(offset + subOffset, copySize).Fill(value);
}
}