75 lines
2.3 KiB
C#
75 lines
2.3 KiB
C#
using System;
|
|
|
|
namespace VMdemo.Simulation
|
|
{
|
|
public readonly struct MemoryAccessResult
|
|
{
|
|
public MemoryAccessResult(ulong pfn, bool pageTableHit, bool pageFault, EvictionInfo eviction)
|
|
{
|
|
Pfn = pfn;
|
|
PageTableHit = pageTableHit;
|
|
PageFault = pageFault;
|
|
Eviction = eviction;
|
|
}
|
|
|
|
public ulong Pfn { get; }
|
|
public bool PageTableHit { get; }
|
|
public bool PageFault { get; }
|
|
public EvictionInfo Eviction { get; }
|
|
}
|
|
|
|
public static class MemoryAccessResolver
|
|
{
|
|
public static MemoryAccessResult Resolve(
|
|
ulong vpn,
|
|
ulong l1Index,
|
|
ulong l2Index,
|
|
TwoLevelPageTable pageTable,
|
|
PhysicalMemoryManager physicalMemoryManager,
|
|
TlbCache tlbCache)
|
|
{
|
|
if (pageTable == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(pageTable));
|
|
}
|
|
|
|
if (physicalMemoryManager == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(physicalMemoryManager));
|
|
}
|
|
|
|
if (tlbCache == null)
|
|
{
|
|
throw new ArgumentNullException(nameof(tlbCache));
|
|
}
|
|
|
|
if (pageTable.TryGetPresentPfn(l1Index, l2Index, out var pfn))
|
|
{
|
|
tlbCache.InsertOrUpdate(vpn, pfn);
|
|
return new MemoryAccessResult(pfn, true, false, EvictionInfo.None);
|
|
}
|
|
|
|
var allocation = physicalMemoryManager.AllocateForVpn(vpn);
|
|
if (allocation.Eviction.HasEvicted)
|
|
{
|
|
pageTable.GetIndicesFromVpn(
|
|
allocation.Eviction.EvictedVpn,
|
|
out var evictedL1Index,
|
|
out var evictedL2Index);
|
|
|
|
pageTable.MarkNotPresent(evictedL1Index, evictedL2Index);
|
|
tlbCache.Remove(allocation.Eviction.EvictedVpn);
|
|
}
|
|
|
|
pageTable.SetPresent(l1Index, l2Index, allocation.AssignedPfn);
|
|
tlbCache.InsertOrUpdate(vpn, allocation.AssignedPfn);
|
|
|
|
return new MemoryAccessResult(
|
|
allocation.AssignedPfn,
|
|
pageTableHit: false,
|
|
pageFault: true,
|
|
allocation.Eviction);
|
|
}
|
|
}
|
|
}
|