private TlbEntry WalkPageTables(uint address) { TlbEntry entry = default; var pageDirectoryIndex = address >> 22; var pageTableIndex = (address >> 12) & 1023; var pageDirectoryEntry = GetLongPhysical(_pageDirectory + pageDirectoryIndex * 4); if ((pageDirectoryEntry & PageTableFlags.Present) == 0) { throw new MemoryAccessException(MemoryAccessStatus.PageDirectoryEntryNotPresent); } // TODO use correct mask for pageDirectoryEntry var pageTableEntry = GetLongPhysical((pageDirectoryEntry & 0xFFFFFC00) + pageTableIndex * 4); if ((pageTableEntry & PageTableFlags.Present) == 0) { throw new MemoryAccessException(MemoryAccessStatus.PageNotPresent); } var pageTableEntryAddress = pageTableEntry & 0xFFFFFC00; if (pageTableEntryAddress >= Size) { throw new MemoryAccessException(MemoryAccessStatus.PhysicalAddressOutOfRange); } entry.entry = pageTableEntry; entry.tag = address >> 12; _tlb[TlbEntry.IndexFromTag(entry.tag)] = entry; return(entry); }
private unsafe byte *GetMemoryAtVirtual(uint address, bool write) { var tag = TlbEntry.TagFromAddress(address); var index = TlbEntry.IndexFromTag(tag); var offset = TlbEntry.OffsetFromAddress(address); var tlbEntry = _tlb[index]; if (tlbEntry.tag != tag) { tlbEntry = WalkPageTables(address); } if (write && !tlbEntry.Rw()) { ThrowPageReadOnlyException(); } return(NotCheckedGetMemoryAtPhysical(tlbEntry.PagePhysicalAddress() + offset)); }