1 // 2 // Copyright (c) 2010-2023 Antmicro 3 // 4 // This file is licensed under the MIT License. 5 // Full license text is available in 'licenses/MIT.txt'. 6 // 7 8 using System.Collections.Generic; 9 using Antmicro.Renode.Core; 10 using Antmicro.Renode.Peripherals.CPU; 11 using Antmicro.Renode.Peripherals.Memory; 12 13 namespace Antmicro.Renode.Peripherals.Miscellaneous 14 { 15 public class OpenTitan_ScrambledMemory 16 { OpenTitan_ScrambledMemory(IMachine machine, long size)17 public OpenTitan_ScrambledMemory(IMachine machine, long size) 18 { 19 if(size % PageSize != 0) 20 { 21 size += (PageSize - (size % PageSize)); 22 } 23 24 this.machine = machine; 25 underlyingMemory = new MappedMemory(machine, size); 26 writtenOffsets = new HashSet<long>(); 27 } 28 ReadDoubleWord(long offset)29 public uint ReadDoubleWord(long offset) 30 { 31 if(!CheckAccess(offset, 4)) 32 { 33 return 0; 34 } 35 return underlyingMemory.ReadDoubleWord(offset); 36 } 37 WriteDoubleWord(long offset, uint value)38 public void WriteDoubleWord(long offset, uint value) 39 { 40 MarkWritten(offset, 4); 41 underlyingMemory.WriteDoubleWord(offset, value); 42 } 43 WriteBytes(long offset, byte[] value)44 public void WriteBytes(long offset, byte[] value) 45 { 46 MarkWritten(offset, value.Length); 47 underlyingMemory.WriteBytes(offset, value); 48 } 49 ReadBytes(long offset, int count, byte[] destination, int startIndex)50 public void ReadBytes(long offset, int count, byte[] destination, int startIndex) 51 { 52 if(!CheckAccess(offset , count)) 53 { 54 return; 55 } 56 underlyingMemory.ReadBytes(offset, count, destination, startIndex); 57 } 58 ZeroAll()59 public void ZeroAll() 60 { 61 wasCleared = true; 62 writtenOffsets.Clear(); 63 underlyingMemory.ZeroAll(); 64 } 65 66 public long Size => underlyingMemory.Size; 67 68 public IEnumerable<IMappedSegment> MappedSegments => underlyingMemory.MappedSegments; 69 MarkWritten(long offset, int size = 1)70 private void MarkWritten(long offset, int size = 1) 71 { 72 for(var i = 0; i < size; i++) 73 { 74 writtenOffsets.Add(offset + i); 75 } 76 } 77 CheckAccess(long offset, int size = 1)78 private bool CheckAccess(long offset, int size = 1) 79 { 80 if(wasCleared && !writtenOffsets.Contains(offset)) 81 { 82 if(machine.SystemBus.TryGetCurrentCPU(out var cpu) && cpu is ICPUWithNMI ibexCPU) 83 { 84 // https://github.com/lowRISC/opentitan/blob/f243e6802143374741739d2c164c4f2f61697669/sw/device/lib/runtime/ibex.h#LL48C5-L48C5 85 ibexCPU.OnNMI(0, true, 0xffffffe0); // Load integrity error internal interrupt 86 } 87 return false; 88 } 89 return true; 90 } 91 92 private bool wasCleared; 93 94 private readonly IMachine machine; 95 private readonly MappedMemory underlyingMemory; 96 private readonly HashSet<long> writtenOffsets; 97 98 private const long PageSize = 0x1000; 99 } 100 } 101