sencha: update for refactoring & profiling support - add support for instruction & memory profiling. - refactor Cheriot CPU classes - update copyright notices Bypass-Presubmit-Reason: no sencha CI tests NB: this requires an updated toolchain Change-Id: I81ee768c2bb39bf9970d2ee0d7373019db51c7dc
diff --git a/cheriot.resc b/cheriot.resc index bf46c98..1dce9fd 100644 --- a/cheriot.resc +++ b/cheriot.resc
@@ -16,9 +16,11 @@ mach create "cheriot" +include @sim/config/shodan_infrastructure/MpactCPU.cs +EnsureTypeIsLoaded "Antmicro.Renode.Peripherals.MpactCPU.MpactBaseCPU" +EnsureTypeIsLoaded "Antmicro.Renode.Peripherals.MpactCPU.MpactPeripheral" include @sim/config/shodan_infrastructure/MpactCheriotCPU.cs EnsureTypeIsLoaded "Antmicro.Renode.Peripherals.MpactCPU.MpactCheriotCPU" -EnsureTypeIsLoaded "Antmicro.Renode.Peripherals.MpactCPU.MpactCheriotPeripheral" $platformfile?=@sim/config/platforms/sail.repl
diff --git a/platforms/cheriot.repl b/platforms/cheriot.repl index 59c12ec..9e82f1a 100644 --- a/platforms/cheriot.repl +++ b/platforms/cheriot.repl
@@ -21,7 +21,7 @@ memorySize: 0x10000000 revocationMemoryBase: 0x83000000 -ram_smc : MpactCPU.MpactCheriotPeripheral @ sysbus 0x80000000 +ram_smc : MpactCPU.MpactPeripheral @ sysbus 0x80000000 size: 0x10000000 baseAddress: 0x80000000 mpactCpu: cpu1
diff --git a/sencha.resc b/sencha.resc index 3ba02e5..2a00994 100644 --- a/sencha.resc +++ b/sencha.resc
@@ -19,9 +19,11 @@ using sysbus mach create $name +include @sim/config/shodan_infrastructure/MpactCPU.cs +EnsureTypeIsLoaded "Antmicro.Renode.Peripherals.MpactCPU.MpactBaseCPU" +EnsureTypeIsLoaded "Antmicro.Renode.Peripherals.MpactCPU.MpactPeripheral" include @sim/config/shodan_infrastructure/MpactCheriotCPU.cs EnsureTypeIsLoaded "Antmicro.Renode.Peripherals.MpactCPU.MpactCheriotCPU" -EnsureTypeIsLoaded "Antmicro.Renode.Peripherals.MpactCPU.MpactCheriotPeripheral" EnsureTypeIsLoaded "Antmicro.Renode.Peripherals.CPU.RiscV32" include @sim/config/shodan_infrastructure/KelvinCPU.cs EnsureTypeIsLoaded "Antmicro.Renode.Peripherals.CPU.KelvinCPU"
diff --git a/shodan_infrastructure/MpactCPU.cs b/shodan_infrastructure/MpactCPU.cs new file mode 100644 index 0000000..01241ab --- /dev/null +++ b/shodan_infrastructure/MpactCPU.cs
@@ -0,0 +1,771 @@ +// +// Copyright (c) 2010-2024 Antmicro +// +// This file is licensed under the MIT License. +// Full license text is available in 'licenses/MIT.txt'. +// +// +// Copyright (c) 2024 Google LLC +// +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. +// + +// This file is derived from ReNode plugin sources, but has been modified +// so that it can be used as a plugin that interfaces with an mpact based +// simulator that implement the mpact_renode "C" linkage interface. + +using System; +using System.Linq; +using System.Runtime.InteropServices; +using System.Threading; +using System.Collections.Generic; +using System.Collections.Concurrent; +using Antmicro.Renode.Core; +using Antmicro.Renode.Debugging; +using Antmicro.Renode.Exceptions; +using Antmicro.Renode.Hooks; +using Antmicro.Renode.Logging; +using Antmicro.Renode.Peripherals; +using Antmicro.Renode.Peripherals.Bus; +using Antmicro.Renode.Peripherals.CPU; +using Antmicro.Renode.Peripherals.Timers; +using Antmicro.Renode.Peripherals.CPU.Disassembler; +using Antmicro.Renode.Peripherals.CPU.Registers; +using Antmicro.Renode.Utilities; +using Antmicro.Renode.Time; +using Antmicro.Renode.Utilities.Binding; +using ELFSharp.ELF; +using ELFSharp.UImage; + +namespace Antmicro.Renode.Peripherals.MpactCPU { + +// This interface is implemented by MpactCheriotCPU and used by +// MpactCheriotPeripheral to access memory in mpact_cheriot simulator +public interface IMpactPeripheral : IBytePeripheral, IWordPeripheral, + IDoubleWordPeripheral, + IQuadWordPeripheral, + IMultibyteWritePeripheral {} + + +// Struct containing info for loading binary image files. +public struct BinFileLoadInfo { + public string file_name; + public UInt64 load_address; + public UInt64 entry_point; +} + +// The MpactCPU class. This class derives from BaseCPU, which implements +// a CPU in ReNode. It is the base implemenation of the interface between +// ReNode and the mpact_sim based simulators. +public class MpactBaseCPU : BaseCPU, ICPUWithRegisters, + IGPIOReceiver, ITimeSink, + IDisposable, IMpactPeripheral { + + // Structure for ReNode register information that is obtained from the + // simulator. + [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi, Pack = 1)] + private struct RegInfo { + [FieldOffset(0)] + public Int32 index; + [FieldOffset(4)] + public Int32 width; + [FieldOffset(8)] + public bool isGeneral; + [FieldOffset(9)] + public bool isReadOnly; + } + + public MpactBaseCPU(uint id, UInt64 memoryBase, UInt64 memorySize, + string cpuType, IMachine machine, Endianess endianness, + CpuBitness bitness = CpuBitness.Bits32) + : base(id, cpuType, machine, endianness, bitness) { + this.memoryBase = memoryBase; + this.memorySize = memorySize; + // Allocate space for marshaling data to/from simulator. + error_ptr = Marshal.AllocHGlobal(4); + value_ptr = Marshal.AllocHGlobal(8); + reg_info_ptr = Marshal.AllocHGlobal(Marshal.SizeOf<RegInfo>()); + string_ptr = Marshal.AllocHGlobal(maxStringLen); + } + + ~MpactBaseCPU() { + Marshal.FreeHGlobal(error_ptr); + Marshal.FreeHGlobal(value_ptr); + Marshal.FreeHGlobal(reg_info_ptr); + Marshal.FreeHGlobal(string_ptr); + } + + + public override string Architecture { get { return "MpactSim";} } + + public virtual void SetMpactConfig(List<string> config_names, + List<string> config_values) { + config_names.Add("memoryBase"); + config_names.Add("memorySize"); + config_values.Add("0x" + memoryBase.ToString("X")); + config_values.Add("0x" + memorySize.ToString("X")); + if (cli_port != 0) { + config_names.Add("cliPort"); + config_values.Add("0x" + cli_port.ToString("X")); + config_names.Add("waitForCLI"); + config_values.Add("0x" + (wait_for_cli ? 1 : 0).ToString("X")); + } + } + + public override void Start() { + base.Start(); + + // Set up configuration array. + var config_names = new List<string>(); + var config_values = new List<string>(); + SetMpactConfig(config_names, config_values); + // Configure mpact sim. + Int32 cfg_res = set_config(mpact_id, config_names.ToArray(), + config_values.ToArray(), config_names.Count); + if (cfg_res < 0) { + LogAndThrowRE("Failed to set configuration information"); + } + // Load executable file, symbols only from executable file, or bin + // file if specified. Use symbols load if the executable is loaded + // by the system. + this.Log(LogLevel.Info, "symbol_file: '" + symbol_file + "'"); + if (!executable_file.Equals("")) { + var entry_point = load_elf(mpact_id, executable_file, + /*for_symbols_only=*/false, + error_ptr); + Int32 result = Marshal.ReadInt32(error_ptr); + if (result < 0) { + LogAndThrowRE("Failed to load executable"); + } + PC = entry_point; + } else if (!symbol_file.Equals("")) { + this.Log(LogLevel.Info, "loading symbol_file: '" + symbol_file + "'"); + load_elf(mpact_id, symbol_file, /*for_symbols_only=*/true, + error_ptr); + Int32 result = Marshal.ReadInt32(error_ptr); + if (result < 0) { + LogAndThrowRE("Failed to load symbols"); + } + } else if (!bin_file_info.file_name.Equals("")) { + Int32 res = load_image(mpact_id, bin_file_info.file_name, + bin_file_info.load_address); + if (res < 0) { + LogAndThrowRE("Failed to load binary image"); + } + PC = bin_file_info.entry_point; + } + } + + public override void Reset() { + base.Reset(); + instructionsExecutedThisRound = 0; + totalExecutedInstructions = 0; + // Call simulator to reset. + reset(mpact_id); + } + + public override void Dispose() { + base.Dispose(); + // Cleanup: simulator and any unmanaged resources. + this.Log(LogLevel.Info, "destruct mpact"); + destruct(mpact_id); + this.Log(LogLevel.Info, "done"); + } + + public string CpuLibraryPath { + get { + return cpu_library_path; + } + set { + this.Log(LogLevel.Info, "Lib: " + value); + if (String.IsNullOrWhiteSpace(value)) { + cpu_library_path = value; + return; + } + if (cpu_library_bound) { + LogAndThrowRE("CPU library already bound to: " + + cpu_library_path); + } + cpu_library_path = value; + try { + binder = new NativeBinder(this, cpu_library_path); + } + catch (System.Exception e) { + LogAndThrowRE("Failed to load CPU library: " + e.Message); + } + cpu_library_bound = true; + + // Instantiate the simulator, passing in callbacks to read and write + // from/to the system bus. + read_sysmem_delegate = + new FuncInt32UInt64IntPtrInt32(ReadSysMemory); + write_sysmem_delegate = + new FuncInt32UInt64IntPtrInt32(WriteSysMemory); + mpact_id = construct_with_sysbus(maxStringLen, + read_sysmem_delegate, + write_sysmem_delegate); + if (mpact_id < 0) { + LogAndThrowRE("Failed to create simulator instance"); + } + } + } + + public string ExecutableFile { + get => executable_file; + set => executable_file = value; + } + + public string SymbolFile { + get => symbol_file; + set => symbol_file = value; + } + + public BinFileLoadInfo BinFileInfo { + get => bin_file_info; + set => bin_file_info = value; + } + + public ushort CLIPort { get => cli_port; set => cli_port = value; } + + public bool WaitForCLI { + get => wait_for_cli; + set => wait_for_cli = value; + } + + public override ulong ExecutedInstructions => totalExecutedInstructions; + + public override ExecutionMode ExecutionMode { + get { return executionMode; } + set { + lock(singleStepSynchronizer.Guard) { + if (executionMode == value) return; + + executionMode = value; + + singleStepSynchronizer.Enabled = IsSingleStepMode; + UpdateHaltedState(); + } + } + } + + [Register] + public override RegisterValue PC { + get { + Int32 error = read_register(mpact_id, PC_ID, value_ptr); + if (error < 0) { + this.Log(LogLevel.Error, "Failed to read PC"); + } + Int64 value = Marshal.ReadInt64(value_ptr); + return Convert.ToUInt32(value); + } + + set { + Int32 error = write_register(mpact_id, PC_ID, value); + if (error < 0) { + this.Log(LogLevel.Error, "Failed to write PC"); + } + } + } + + public override ExecutionResult ExecuteInstructions( + ulong numberOfInstructionsToExecute, + out ulong numberOfExecutedInstructions) { + UInt64 instructionsExecutedThisRound = 0UL; + ExecutionResult result = ExecutionResult.Ok; + try { + // Invoke simulator for the number of instructions. + instructionsExecutedThisRound = + step(mpact_id, numberOfInstructionsToExecute, error_ptr); + // Parse the result. + Int32 step_result = Marshal.ReadInt32(error_ptr); + switch (step_result) { + case -1: + result = ExecutionResult.Aborted; + break; + case 0: + result = ExecutionResult.Ok; + break; + case 1: + result = ExecutionResult.Interrupted; + break; + case 2: + result = ExecutionResult.WaitingForInterrupt; + break; + case 3: + result = ExecutionResult.StoppedAtBreakpoint; + break; + case 4: + result = ExecutionResult.StoppedAtWatchpoint; + break; + case 5: + result = ExecutionResult.ExternalMmuFault; + break; + default: + LogAndThrowRE("Unknown return value from step - " + + step_result); + break; + } + } + catch (Exception) { + this.NoisyLog("CPU exception detected, halting."); + InvokeHalted(new HaltArguments(HaltReason.Abort, Id)); + return ExecutionResult.Aborted; + } + finally { + numberOfExecutedInstructions = instructionsExecutedThisRound; + totalExecutedInstructions += instructionsExecutedThisRound; + } + return result; + } + + // ICPUWithRegisters methods implementations. + public void SetRegisterUnsafe(int register, RegisterValue value) { + var status = write_register((Int32)mpact_id, (Int32)register, + (UInt64)value); + if (status < 0) { + LogAndThrowRE("Failed to write register " + register); + } + } + + public RegisterValue GetRegisterUnsafe(int register) { + var status = read_register(mpact_id, register, value_ptr); + if (status < 0) { + LogAndThrowRE("Failed to read register " + register); + } + Int64 value = Marshal.ReadInt64(value_ptr); + CPURegister cpu_register; + if (registerMap.TryGetValue(register, out cpu_register)) { + var width = cpu_register.Width; + switch (width) { + case 8: return (byte)value; + case 16: return (ushort)value; + case 32: return (uint)value; + case 64: return (ulong)value; + default: + LogAndThrowRE("Unexpected register width: {width}"); + break; + } + } else { + LogAndThrowRE("Unknown register id: {register}"); + } + return (ulong)0; + } + + protected void GetMpactRegisters() { + if (registerMap.Count != 0) return; + Int32 num_regs = get_reg_info_size(mpact_id); + for (Int32 i = 0; i < num_regs; i++) { + Int32 result = get_reg_info(mpact_id, i, string_ptr, reg_info_ptr); + if (result < 0) { + this.Log(LogLevel.Error, + "Failed to get register info for index " + i); + continue; + } + var reg_info = Marshal.PtrToStructure<RegInfo>(reg_info_ptr); + var cpu_reg = new CPURegister(reg_info.index, reg_info.width, + reg_info.isGeneral, + reg_info.isReadOnly); + var reg_name = Marshal.PtrToStringAuto(string_ptr); + registerMap.Add(reg_info.index, cpu_reg); + registerNamesMap.Add(reg_name, reg_info.index); + } + } + + public IEnumerable<CPURegister> GetRegisters() { + if (registerMap.Count == 0) { + GetMpactRegisters(); + } + return registerMap.Values.OrderBy(x => x.Index); + } + + public new string[,] GetRegistersValues() { + if (registerMap.Count == 0) { + GetMpactRegisters(); + } + var result = new Dictionary<string, ulong>(); + foreach (var reg in registerNamesMap) { + var status = read_register(mpact_id, reg.Value, value_ptr); + if (status < 0) continue; + Int64 value = Marshal.ReadInt64(value_ptr); + result.Add(reg.Key, Convert.ToUInt64(value)); + } + var table = new Table().AddRow("Name", "Value"); + table.AddRows(result, x=> x.Key, x=> "0x{0:X}".FormatWith(x.Value)); + return table.ToArray(); + } + + private void LogAndThrowRE(string info) { + this.Log(LogLevel.Error, info); + throw new RecoverableException(info); + } + + public Int32 LoadImageFile(String file_name, UInt64 address) { + return load_image(mpact_id, file_name, address); + } + + public void OnGPIO(int number, bool value) { + if (mpact_id < 0) { + this.Log(LogLevel.Noisy, + "OnGPIO: no simulator, discard gpio {0}:{1}", number, + value); + return; + } + Int32 status = set_irq_value(mpact_id, number, value); + if (status < 0) { + Console.Error.WriteLine("Failure in setting irq value"); + } + } + + public Int32 ReadSysMemory(UInt64 address, IntPtr buffer, Int32 length) { + // Read from System Bus. + switch (length) { + case 1: + var data8 = new byte[length]; + data8[0] = machine.SystemBus.ReadByte(address, this); + Marshal.Copy(data8, 0, buffer, length); + break; + case 2: + var data16 = new Int16[1]; + data16[0] = (Int16) machine.SystemBus.ReadWord(address, this); + Marshal.Copy(data16, 0, buffer, 1); + break; + case 4: + var data32 = new Int32[1]; + data32[0] = (Int32) machine.SystemBus.ReadDoubleWord(address, + this); + Marshal.Copy(data32, 0, buffer, 1); + break; + case 8: + var data64 = new Int64[1]; + data64[0] = (Int64) machine.SystemBus.ReadQuadWord(address, + this); + Marshal.Copy(data64, 0, buffer, 1); + break; + default: + var dataN = new byte[length]; + machine.SystemBus.ReadBytes(address, length, dataN, 0, false, + this); + Marshal.Copy(dataN, 0, buffer, length); + break; + } + return length; + } + + public Int32 WriteSysMemory(UInt64 address, IntPtr buffer, Int32 length) { + switch (length) { + case 1: + var data8 = new byte[1]; + Marshal.Copy(buffer, data8, 0, 1); + machine.SystemBus.WriteByte(address, data8[0], this); + break; + case 2: + var data16 = new Int16[1]; + Marshal.Copy(buffer, data16, 0, 1); + machine.SystemBus.WriteWord(address, (ushort)data16[0], this); + break; + case 4: + var data32 = new Int32[1]; + Marshal.Copy(buffer, data32, 0, 1); + machine.SystemBus.WriteDoubleWord(address, (uint)data32[0], + this); + break; + case 8: + var data64 = new Int64[1]; + Marshal.Copy(buffer, data64, 0, 1); + machine.SystemBus.WriteQuadWord(address, (ulong)data64[0], + this); + break; + default: + var dataN = new byte[length]; + Marshal.Copy(buffer, dataN, 0, length); + machine.SystemBus.WriteBytes(dataN, address); + break; + } + return length; + } + + // IMpactPeripheral methods. + public void WriteByte(long address, byte value) { + var data8 = new byte[1]; + data8[0] = (byte) value; + Marshal.Copy(data8, 0, value_ptr, 1); + write_memory(mpact_id, (UInt64) address, value_ptr, 1); + } + + public byte ReadByte(long address) { + var data8 = new byte[1]; + read_memory(mpact_id, (UInt64) address, value_ptr, 1); + Marshal.Copy(value_ptr, data8, 0, 1); + return (byte) data8[0]; + } + + public void WriteWord(long address, ushort value) { + var data16 = new Int16[1]; + data16[0] = (Int16) value; + Marshal.Copy(data16, 0, value_ptr, 1); + write_memory(mpact_id, (UInt64) address, value_ptr, 2); + } + + public ushort ReadWord(long address) { + var data16 = new Int16[1]; + read_memory(mpact_id, (UInt64) address, value_ptr, 2); + Marshal.Copy(value_ptr, data16, 0, 1); + return (ushort) data16[0]; + } + + public void WriteDoubleWord(long address, uint value) { + var data32 = new Int32[1]; + data32[0] = (Int32) value; + Marshal.Copy(data32, 0, value_ptr, 1); + write_memory(mpact_id, (UInt64) address, value_ptr, 4); + } + + public uint ReadDoubleWord(long address) { + var data32 = new Int32[1]; + read_memory(mpact_id, (UInt64) address, value_ptr, 4); + Marshal.Copy(value_ptr, data32, 0, 1); + return (uint) data32[0]; + } + + public void WriteQuadWord(long address, ulong value) { + var data64 = new Int64[1]; + data64[0] = (Int64) value; + Marshal.Copy(data64, 0, value_ptr, 1); + write_memory(mpact_id, (UInt64) address, value_ptr, 8); + } + + public ulong ReadQuadWord(long address) { + var data64 = new Int64[1]; + read_memory(mpact_id, (UInt64) address, value_ptr, 8); + Marshal.Copy(value_ptr, data64, 0, 1); + return (ulong) data64[0]; + } + + public byte[] ReadBytes(long offset, int count, ICPU context = null) { + var bytes = new byte[count]; + var byte_array_ptr = Marshal.AllocHGlobal(count); + read_memory(mpact_id, (UInt64) offset, byte_array_ptr, count); + Marshal.Copy(value_ptr, bytes, 0, count); + Marshal.FreeHGlobal(byte_array_ptr); + return bytes; + } + + public void WriteBytes(long offset, byte[] array, int startingIndex, + int count, ICPU context = null) { + var byte_array_ptr = Marshal.AllocHGlobal(count); + Marshal.Copy(array, startingIndex, byte_array_ptr, count); + write_memory(mpact_id, (UInt64) offset, byte_array_ptr, count); + Marshal.FreeHGlobal(byte_array_ptr); + } + + // End of IMpactPeripheral methods. + protected Dictionary<string, Int32> + registerNamesMap = new Dictionary<string, Int32>(); + + private ushort cli_port = 0; + private bool wait_for_cli = true; + private UInt64 size = 0; + private List<GDBFeatureDescriptor> + gdbFeatures = new List<GDBFeatureDescriptor>(); + private UInt64 memoryBase; + private UInt64 memorySize; + private Dictionary<Int32, CPURegister> + registerMap = new Dictionary<Int32, CPURegister>(); + private string executable_file = ""; + private string symbol_file = ""; + private BinFileLoadInfo + bin_file_info = new BinFileLoadInfo {file_name = "", + load_address = 0, + entry_point = 0}; + private string cpu_library_path = ""; + private bool cpu_library_bound = false; + private NativeBinder binder; + private readonly object nativeLock; + private readonly Int32 maxStringLen = 32; + + // Pointers used in marshaling data to/from the simulator library. + private IntPtr value_ptr {get; set;} + private IntPtr error_ptr {get; set;} + private IntPtr reg_info_ptr {get; set;} + private IntPtr string_ptr {get; set;} + + // Declare some additional function signatures. + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate Int32 ConnectWithSysbus(Int32 param0, Int32 param1, + FuncInt32UInt64IntPtrInt32 param2, + FuncInt32UInt64IntPtrInt32 param3); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate Int32 ConstructWithSysbus(Int32 param0, + FuncInt32UInt64IntPtrInt32 param1, + FuncInt32UInt64IntPtrInt32 param2); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate Int32 SetConfig(Int32 param0, string[] param1, + string[] param2, Int32 param3); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate Int32 SetIrqValue(Int32 param0, Int32 param1, bool param2); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate UInt64 LoadElf(Int32 param0, string param1, bool param2, + IntPtr param3); + + // Int32 read_sysmem_delegate(UInt64 address, IntPtr buffer, Int32 size) + private FuncInt32UInt64IntPtrInt32 read_sysmem_delegate; + // Int32 write_sysmem_delegate(UInt64 address, IntPtr buffer, Int32 size) + private FuncInt32UInt64IntPtrInt32 write_sysmem_delegate; + + // Functions that are imported from the mpact sim library. +#pragma warning disable 649 + [Import(UseExceptionWrapper = false)] + // Int32 construct_with_sysbus(Int32 id, + // Int32 read_callback(UInt64, IntPtr, Int32), + // Int32 write_callback(UInt64, IntPtr, Int32)); + private ConstructWithSysbus construct_with_sysbus; + + [Import(UseExceptionWrapper = false)] + // Int32 connect_with_sybsus(Int32 id, + // Int32 read_callback(UInt64, IntPtr, Int32), + // Int32 write_callback(UInt64, IntPtr, Int32)); + private ConnectWithSysbus connect_with_sysbus; + + [Import(UseExceptionWrapper = false)] + // void destruct(Int32 id); + private ActionInt32 destruct; + + [Import(UseExceptionWrapper = false)] + // void reset(Int32 id); + private ActionInt32 reset; + + [Import(UseExceptionWrapper = false)] + // Int32 get_reg_info_size(Int32 id) + private FuncInt32Int32 get_reg_info_size; + + [Import(UseExceptionWrapper = false)] + // Int32 get_reg_info(Int32 id, IntPtr *name, IntPtr *struct); + private FuncInt32Int32Int32IntPtrIntPtr get_reg_info; + + [Import(UseExceptionWrapper = false)] + // UInt64 load_elf(Int32 id, String file_name, + // bool for_symbols_only, Int32* error_ptr); + private LoadElf load_elf; + + [Import(UseExceptionWrapper = false)] + // Int32 load_image(Int32 id, String file_name, UInt64 address); + private FuncInt32Int32StringUInt64 load_image; + + [Import(UseExceptionWrapper = false)] + // UInt64 step(Int32 id, UInt64 step, IntPtr *error); + private FuncUInt64Int32UInt64IntPtr step; + + [Import(UseExceptionWrapper = false)] + // Int32 read_register(Int32 id, Int32 reg_id, IntPtr *value); + private FuncInt32Int32Int32IntPtr read_register; + + [Import(UseExceptionWrapper = false)] + // Int32 write_register(Int32 id, Int32 reg_id, UInt64 value); + private FuncInt32Int32Int32UInt64 write_register; + + [Import(UseExceptionWrapper = false)] + // Int32 read_memory(Int32 id, UInt64 address, IntPtr buffer, Int32 size); + private FuncInt32Int32UInt64IntPtrInt32 read_memory; + + [Import(UseExceptionWrapper = false)] + // Int32 write_memory(Int32 id, UInt64 address, IntPtr buffer, Int32 size); + private FuncInt32Int32UInt64IntPtrInt32 write_memory; + + [Import(UseExceptionWrapper = false)] + // Int32 set_config(Int32 id, string[] names string[] values, Int32 size); + private SetConfig set_config; + + [Import(UseExceptionWrapper = false)] + // Int32 set_irq_value(Int32 id, Int32 irq_no, bool value); + private SetIrqValue set_irq_value; + +#pragma warning restore 649 + + private Int32 mpact_id = -1; + private ulong instructionsExecutedThisRound {get; set;} + private ulong totalExecutedInstructions {get; set;} + private const int PC_ID = 0x07b1; +} // class MpactCheriotCPU + + +// Peripheral interface class. +public class MpactPeripheral : IKnownSize, IBytePeripheral, + IWordPeripheral, IDoubleWordPeripheral, + IQuadWordPeripheral, + IMultibyteWritePeripheral, IDisposable { + + public MpactPeripheral(IMachine machine, long baseAddress, + long size, IMpactPeripheral mpactCpu) { + if (size == 0) { + throw new ConstructionException("Memory size cannot be 0"); + } + this.machine = machine; + this.size = size; + this.base_address = baseAddress; + this.mpact_cpu = mpactCpu; + } + + public void Reset() {} + + public void Dispose() {} + + // All memory accesses are forwarded to the mpactCpu with the base_address + // added to the address field. + public void WriteByte(long address, byte value) { + mpact_cpu.WriteByte(address + base_address, value); + } + + public byte ReadByte(long address) { + return mpact_cpu.ReadByte(address + base_address); + } + + public void WriteWord(long address, ushort value) { + mpact_cpu.WriteWord(address + base_address, value); + } + + public ushort ReadWord(long address) { + return mpact_cpu.ReadWord(address + base_address); + } + + public void WriteDoubleWord(long address, uint value) { + mpact_cpu.WriteDoubleWord(address + base_address, value); + } + + public uint ReadDoubleWord(long address) { + return mpact_cpu.ReadDoubleWord(address + base_address); + } + + public void WriteQuadWord(long address, ulong value) { + mpact_cpu.WriteQuadWord(address + base_address, value); + } + + public ulong ReadQuadWord(long address) { + return mpact_cpu.ReadQuadWord(address + base_address); + } + + public byte[] ReadBytes(long offset, int count, ICPU context = null) { + return mpact_cpu.ReadBytes(offset + base_address, count, context); + } + + public void WriteBytes(long offset, byte[] array, int startingIndex, + int count, ICPU context = null) { + mpact_cpu.WriteBytes(offset + base_address, array, startingIndex, + count, context); + } + + public long Size { get { return size;} } + private IMpactPeripheral mpact_cpu; + private long size; + private long base_address = 0; + private IMachine machine; + +} // class MpactPeripheral + +} // namespace Antmicro.Renode.Peripherals.MpactCPU +
diff --git a/shodan_infrastructure/MpactCheriotCPU.cs b/shodan_infrastructure/MpactCheriotCPU.cs index 3c5960e..dbb7afb 100644 --- a/shodan_infrastructure/MpactCheriotCPU.cs +++ b/shodan_infrastructure/MpactCheriotCPU.cs
@@ -1,17 +1,19 @@ // +// Copyright (c) 2010-2024 Antmicro +// +// This file is licensed under the MIT License. +// Full license text is available in 'licenses/MIT.txt'. +// +// // Copyright (c) 2024 Google LLC // -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at +// Use of this source code is governed by an MIT-style +// license that can be found in the LICENSE file or at +// https://opensource.org/licenses/MIT. // -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. + +// This file specializes the MpactCPU class to add custom interfaces and +// properties required for the mpact_cheriot simulator. using System; using System.Linq; @@ -33,435 +35,54 @@ using Antmicro.Renode.Utilities; using Antmicro.Renode.Time; using Antmicro.Renode.Utilities.Binding; +using Antmicro.Renode.Peripherals.MpactCPU; using ELFSharp.ELF; using ELFSharp.UImage; namespace Antmicro.Renode.Peripherals.MpactCPU { -// This interface is implemented by MpactCheriotCPU and used by -// MpactCheriotPeripheral to access memory in mpact_cheriot simulator -public interface IMpactPeripheral : IBytePeripheral, IWordPeripheral, - IDoubleWordPeripheral, - IQuadWordPeripheral, - IMultibyteWritePeripheral {} - - -// Struct containing info for loading binary image files. -public struct BinFileLoadInfo { - public string file_name; - public UInt64 load_address; - public UInt64 entry_point; -} - // The MpactCheriotCPU class. This class derives from BaseCPU, which implements // a CPU in ReNode. It is the interface between ReNode and the mpact_cheriot // simulator library. -public class MpactCheriotCPU : BaseCPU, ICpuSupportingGdb, ICPUWithRegisters, - ICPUWithHooks, IGPIOReceiver, ITimeSink, - IDisposable, IMpactPeripheral { - - // Structure for ReNode register information that is obtained from the - // simulator. - [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Ansi, Pack = 1)] - private struct RegInfo { - [FieldOffset(0)] - public Int32 index; - [FieldOffset(4)] - public Int32 width; - [FieldOffset(8)] - public bool isGeneral; - [FieldOffset(9)] - public bool isReadOnly; - } +public class MpactCheriotCPU : MpactBaseCPU, ICpuSupportingGdb { public MpactCheriotCPU(uint id, UInt64 memoryBase, UInt64 memorySize, - UInt64 revocationMemoryBase, string cpuType, - IMachine machine, Endianess endianness, + UInt64 revocationMemoryBase, string cpuType, + IMachine machine, Endianess endianness, CpuBitness bitness = CpuBitness.Bits32) - : base(id, cpuType, machine, endianness, bitness) { - this.memoryBase = memoryBase; - this.memorySize = memorySize; + : base(id, memoryBase, memorySize, cpuType, machine, endianness, + bitness) { revocationMemBase = revocationMemoryBase; - // Allocate space for marshaling data to/from simulator. - error_ptr = Marshal.AllocHGlobal(4); - value_ptr = Marshal.AllocHGlobal(8); - reg_info_ptr = Marshal.AllocHGlobal(Marshal.SizeOf<RegInfo>()); - string_ptr = Marshal.AllocHGlobal(maxStringLen); } ~MpactCheriotCPU() { - Marshal.FreeHGlobal(error_ptr); - Marshal.FreeHGlobal(value_ptr); - Marshal.FreeHGlobal(reg_info_ptr); - Marshal.FreeHGlobal(string_ptr); } public override string Architecture { get { return "MpactCheriot";} } - public override void Start() { - base.Start(); - - // Set up configuration array. - var config_names = new List<string>(); - var config_values = new List<string>(); - config_names.Add("memoryBase"); - config_names.Add("memorySize"); - config_names.Add("revocationMemoryBase"); - config_values.Add("0x" + memoryBase.ToString("X")); - config_values.Add("0x" + memorySize.ToString("X")); - config_values.Add("0x" + revocationMemBase.ToString("X")); - if (cli_port != 0) { - config_names.Add("cliPort"); - config_values.Add("0x" + cli_port.ToString("X")); - config_names.Add("waitForCLI"); - config_values.Add("0x" + (wait_for_cli ? 1 : 0).ToString("X")); + public override void SetMpactConfig(List<string> config_names, + List<string> config_values) { + base.SetMpactConfig(config_names, config_values); + if (inst_profile) { + config_names.Add("instProfile"); + config_values.Add("0x1"); } - Int32 cfg_res = set_config(mpact_id, config_names.ToArray(), - config_values.ToArray(), config_names.Count); - if (cfg_res < 0) { - LogAndThrowRE("Failed to set configuration information"); - } - if (mpact_id < 0) { - LogAndThrowRE("Failed to create simulator instance"); - return; - } - // Load executable file or bin file if specified. Otherwise it is - // handled by the system. - this.Log(LogLevel.Info, "symbol_file: '" + symbol_file + "'"); - if (!executable_file.Equals("")) { - var entry_point = load_elf(mpact_id, executable_file, - /*for_symbols_only=*/false, - error_ptr); - Int32 result = Marshal.ReadInt32(error_ptr); - if (result < 0) { - LogAndThrowRE("Failed to load executable"); - } - PC = entry_point; - } else if (!symbol_file.Equals("")) { - this.Log(LogLevel.Info, "loading symbol_file: '" + symbol_file + "'"); - load_elf(mpact_id, symbol_file, /*for_symbols_only=*/true, - error_ptr); - Int32 result = Marshal.ReadInt32(error_ptr); - if (result < 0) { - LogAndThrowRE("Failed to load symbols"); - } - } else if (!bin_file_info.file_name.Equals("")) { - Int32 res = load_image(mpact_id, bin_file_info.file_name, - bin_file_info.load_address); - if (res < 0) { - LogAndThrowRE("Failed to load binary image"); - } - PC = bin_file_info.entry_point; + if (mem_profile) { + config_names.Add("memProfile"); + config_values.Add("0x1"); } } - public override void Reset() { - base.Reset(); - instructionsExecutedThisRound = 0; - totalExecutedInstructions = 0; - // Call simulator to reset. - reset(mpact_id); + public bool InstProfile { + get => inst_profile; + set => inst_profile = value; } - public override void Dispose() { - base.Dispose(); - // Cleanup: simulator and any unmanaged resources. - this.Log(LogLevel.Info, "destruct mpact"); - destruct(mpact_id); - this.Log(LogLevel.Info, "done"); - } - - public string CpuLibraryPath { - get { - return cpu_library_path; - } - set { - this.Log(LogLevel.Info, "Lib: " + value); - if (String.IsNullOrWhiteSpace(value)) { - cpu_library_path = value; - return; - } - if (cpu_library_bound) { - LogAndThrowRE("CPU library already bound to: " - + cpu_library_path); - } - cpu_library_path = value; - try { - binder = new NativeBinder(this, cpu_library_path); - } - catch (System.Exception e) { - LogAndThrowRE("Failed to load CPU library: " + e.Message); - } - cpu_library_bound = true; - - // Instantiate the simulator, passing in callbacks to read and write - // from/to the system bus. - read_sysmem_delegate = - new FuncInt32UInt64IntPtrInt32(ReadSysMemory); - write_sysmem_delegate = - new FuncInt32UInt64IntPtrInt32(WriteSysMemory); - mpact_id = construct_with_sysbus(maxStringLen, - read_sysmem_delegate, - write_sysmem_delegate); - } - } - - public string ExecutableFile { - get => executable_file; - set => executable_file = value; - } - - public string SymbolFile { - get => symbol_file; - set => symbol_file = value; - } - - public BinFileLoadInfo BinFileInfo { - get => bin_file_info; - set => bin_file_info = value; - } - - public ushort CLIPort { get => cli_port; set => cli_port = value; } - - public bool WaitForCLI { get => wait_for_cli; set => wait_for_cli = value; } - - public override ulong ExecutedInstructions => totalExecutedInstructions; - - public override ExecutionMode ExecutionMode { - get { return executionMode; } - set { - lock(singleStepSynchronizer.Guard) { - if (executionMode == value) return; - - executionMode = value; - - singleStepSynchronizer.Enabled = IsSingleStepMode; - UpdateHaltedState(); - } - } - } - - [Register] - public override RegisterValue PC { - get { - Int32 error = read_register(mpact_id, PC_ID, value_ptr); - if (error < 0) { - this.Log(LogLevel.Error, "Failed to read PC"); - } - Int64 value = Marshal.ReadInt64(value_ptr); - return Convert.ToUInt64(value); - } - - set { - Int32 error = write_register(mpact_id, PC_ID, value); - if (error < 0) { - this.Log(LogLevel.Error, "Failed to write PC"); - } - } - } - - public override ExecutionResult ExecuteInstructions( - ulong numberOfInstructionsToExecute, - out ulong numberOfExecutedInstructions) { - UInt64 instructionsExecutedThisRound = 0UL; - ExecutionResult result = ExecutionResult.Ok; - try { - // Invoke simulator for the number of instructions. - instructionsExecutedThisRound = - step(mpact_id, numberOfInstructionsToExecute, error_ptr); - // Parse the result. - Int32 step_result = Marshal.ReadInt32(error_ptr); - switch (step_result) { - case -1: - result = ExecutionResult.Aborted; - break; - case 0: - result = ExecutionResult.Ok; - break; - case 1: - result = ExecutionResult.Interrupted; - break; - case 2: - result = ExecutionResult.WaitingForInterrupt; - break; - case 3: - result = ExecutionResult.StoppedAtBreakpoint; - break; - case 4: - result = ExecutionResult.StoppedAtWatchpoint; - break; - case 5: - result = ExecutionResult.ExternalMmuFault; - break; - default: - LogAndThrowRE("Unknown return value from step - " - + step_result); - break; - } - } - catch (Exception) { - this.NoisyLog("CPU exception detected, halting."); - InvokeHalted(new HaltArguments(HaltReason.Abort, Id)); - return ExecutionResult.Aborted; - } - finally { - numberOfExecutedInstructions = instructionsExecutedThisRound; - totalExecutedInstructions += instructionsExecutedThisRound; - } - return result; - } - - // ICPUWithRegisters methods implementations. - public void SetRegisterUnsafe(int register, RegisterValue value) { - var status = write_register((Int32)mpact_id, (Int32)register, - (UInt64)value); - if (status < 0) { - LogAndThrowRE("Failed to write register " + register); - } - } - - public RegisterValue GetRegisterUnsafe(int register) { - var status = read_register(mpact_id, register, value_ptr); - if (status < 0) { - LogAndThrowRE("Failed to read register " + register); - } - Int64 value = Marshal.ReadInt64(value_ptr); - return (UInt32)value; - } - - private void GetMpactRegisters() { - if (registerMap.Count != 0) return; - Int32 num_regs = get_reg_info_size(mpact_id); - for (Int32 i = 0; i < num_regs; i++) { - Int32 result = get_reg_info(mpact_id, i, string_ptr, reg_info_ptr); - if (result < 0) { - this.Log(LogLevel.Error, - "Failed to get register info for index " + i); - continue; - } - var reg_info = Marshal.PtrToStructure<RegInfo>(reg_info_ptr); - var cpu_reg = new CPURegister(reg_info.index, reg_info.width, - reg_info.isGeneral, - reg_info.isReadOnly); - var reg_name = Marshal.PtrToStringAuto(string_ptr); - registerMap.Add(reg_info.index, cpu_reg); - registerNamesMap.Add(reg_name, reg_info.index); - } - } - - public IEnumerable<CPURegister> GetRegisters() { - if (registerMap.Count == 0) { - GetMpactRegisters(); - } - return registerMap.Values.OrderBy(x => x.Index); - } - - public new string[,] GetRegistersValues() { - if (registerMap.Count == 0) { - GetMpactRegisters(); - } - var result = new Dictionary<string, ulong>(); - foreach (var reg in registerNamesMap) { - var status = read_register(mpact_id, reg.Value, value_ptr); - if (status < 0) continue; - Int64 value = Marshal.ReadInt64(value_ptr); - result.Add(reg.Key, Convert.ToUInt64(value)); - } - var table = new Table().AddRow("Name", "Value"); - table.AddRows(result, x=> x.Key, x=> "0x{0:X}".FormatWith(x.Value)); - return table.ToArray(); - } - - private void LogAndThrowRE(string info) { - this.Log(LogLevel.Error, info); - throw new RecoverableException(info); - } - - public Int32 LoadImageFile(String file_name, UInt64 address) { - return load_image(mpact_id, file_name, address); - } - - public void OnGPIO(int number, bool value) { - if (mpact_id < 0) { - this.Log(LogLevel.Noisy, - "OnGPIO: no simulator, discard gpio {0}:{1}", number, - value); - return; - } - Int32 status = set_irq_value(mpact_id, number, value); - if (status < 0) { - Console.Error.WriteLine("Failure in setting irq value"); - } - } - - public Int32 ReadSysMemory(UInt64 address, IntPtr buffer, Int32 length) { - // Read from System Bus. - switch (length) { - case 1: - var data8 = new byte[length]; - data8[0] = machine.SystemBus.ReadByte(address, this); - Marshal.Copy(data8, 0, buffer, length); - break; - case 2: - var data16 = new Int16[1]; - data16[0] = (Int16) machine.SystemBus.ReadWord(address, this); - Marshal.Copy(data16, 0, buffer, 1); - break; - case 4: - var data32 = new Int32[1]; - data32[0] = (Int32) machine.SystemBus.ReadDoubleWord(address, - this); - Marshal.Copy(data32, 0, buffer, 1); - break; - case 8: - var data64 = new Int64[1]; - data64[0] = (Int64) machine.SystemBus.ReadQuadWord(address, - this); - Marshal.Copy(data64, 0, buffer, 1); - break; - default: - var dataN = new byte[length]; - machine.SystemBus.ReadBytes(address, length, dataN, 0, false, - this); - Marshal.Copy(dataN, 0, buffer, length); - break; - } - return length; - } - - public Int32 WriteSysMemory(UInt64 address, IntPtr buffer, Int32 length) { - switch (length) { - case 1: - var data8 = new byte[1]; - Marshal.Copy(buffer, data8, 0, 1); - machine.SystemBus.WriteByte(address, data8[0], this); - break; - case 2: - var data16 = new Int16[1]; - Marshal.Copy(buffer, data16, 0, 1); - machine.SystemBus.WriteWord(address, (ushort)data16[0], this); - break; - case 4: - var data32 = new Int32[1]; - Marshal.Copy(buffer, data32, 0, 1); - machine.SystemBus.WriteDoubleWord(address, (uint)data32[0], - this); - break; - case 8: - var data64 = new Int64[1]; - Marshal.Copy(buffer, data64, 0, 1); - machine.SystemBus.WriteQuadWord(address, (ulong)data64[0], - this); - break; - default: - var dataN = new byte[length]; - Marshal.Copy(buffer, dataN, 0, length); - machine.SystemBus.WriteBytes(dataN, address); - break; - } - return length; + public bool MemProfile { + get => mem_profile; + set => mem_profile = value; } // ICPUWithHooks methods. @@ -476,7 +97,7 @@ } public void AddHookAtWfiStateChange(Action<bool> hook) { throw new RecoverableException( - "Wfi state change hook not currently supported"); + "Wfi state change hook not currently supported"); } public void AddHook(ulong addr, Action<ICpuSupportingGdb, ulong> hook) { @@ -488,10 +109,10 @@ public void RemoveHooksAt(ulong addr) { /* empty */ } public void RemoveAllHooks() { /* empty */ } - // ICpuSuportingGdb methods. + // ICPUSupportingGdb methods. public void EnterSingleStepModeSafely(HaltArguments args, - bool? blocking = null) { + bool? blocking = null) { CheckCpuThreadId(); ChangeExecutionModeToSingleStep(blocking); UpdateHaltedState(); @@ -513,13 +134,13 @@ var c0_index = registerNamesMap["c0"]; for (var i = 0u; i < 16; ++i) { cpuGroup.Registers.Add( - new GDBRegisterDescriptor((uint)c0_index + i, 32u, - $"c{i}", intType, "general")); + new GDBRegisterDescriptor((uint)c0_index + i, 32u, + $"c{i}", intType, "general")); } var pcc_index = registerNamesMap["pcc"]; cpuGroup.Registers.Add( - new GDBRegisterDescriptor((uint)pcc_index, 32u, "pcc", - "code_ptr", "general")); + new GDBRegisterDescriptor((uint)pcc_index, 32u, "pcc", + "code_ptr", "general")); gdbFeatures.Add(cpuGroup); return gdbFeatures; @@ -528,290 +149,12 @@ // End of ICpuSupportingGdb methods. - // IMpactPeripheral methods. - public void WriteByte(long address, byte value) { - var data8 = new byte[1]; - data8[0] = (byte) value; - Marshal.Copy(data8, 0, value_ptr, 1); - write_memory(mpact_id, (UInt64) address + base_address, value_ptr, 1); - } - - public byte ReadByte(long address) { - var data8 = new byte[1]; - read_memory(mpact_id, (UInt64) address + base_address, value_ptr, 1); - Marshal.Copy(value_ptr, data8, 0, 1); - return (byte) data8[0]; - } - - public void WriteWord(long address, ushort value) { - var data16 = new Int16[1]; - data16[0] = (Int16) value; - Marshal.Copy(data16, 0, value_ptr, 1); - write_memory(mpact_id, (UInt64) address + base_address, value_ptr, 2); - } - - public ushort ReadWord(long address) { - var data16 = new Int16[1]; - read_memory(mpact_id, (UInt64) address + base_address, value_ptr, 2); - Marshal.Copy(value_ptr, data16, 0, 1); - return (ushort) data16[0]; - } - - public void WriteDoubleWord(long address, uint value) { - var data32 = new Int32[1]; - data32[0] = (Int32) value; - Marshal.Copy(data32, 0, value_ptr, 1); - write_memory(mpact_id, (UInt64) address + base_address, value_ptr, 4); - } - - public uint ReadDoubleWord(long address) { - var data32 = new Int32[1]; - read_memory(mpact_id, (UInt64) address + base_address, value_ptr, 4); - Marshal.Copy(value_ptr, data32, 0, 1); - return (uint) data32[0]; - } - - public void WriteQuadWord(long address, ulong value) { - var data64 = new Int64[1]; - data64[0] = (Int64) value; - Marshal.Copy(data64, 0, value_ptr, 1); - write_memory(mpact_id, (UInt64) address + base_address, value_ptr, 8); - } - - public ulong ReadQuadWord(long address) { - var data64 = new Int64[1]; - read_memory(mpact_id, (UInt64) address + base_address, value_ptr, 8); - Marshal.Copy(value_ptr, data64, 0, 1); - return (ulong) data64[0]; - } - - public byte[] ReadBytes(long offset, int count, ICPU context = null) { - var bytes = new byte[count]; - var byte_array_ptr = Marshal.AllocHGlobal(count); - read_memory(mpact_id, (UInt64) offset + base_address, byte_array_ptr, - count); - Marshal.Copy(value_ptr, bytes, 0, count); - Marshal.FreeHGlobal(byte_array_ptr); - return bytes; - } - - public void WriteBytes(long offset, byte[] array, int startingIndex, - int count, ICPU context = null) { - var byte_array_ptr = Marshal.AllocHGlobal(count); - Marshal.Copy(array, startingIndex, byte_array_ptr, count); - write_memory(mpact_id, (UInt64) offset + base_address, byte_array_ptr, - count); - Marshal.FreeHGlobal(byte_array_ptr); - } - - // End of IMpactPeripheral methods. - - private ushort cli_port = 0; - private bool wait_for_cli = true; - private UInt64 base_address = 0; - private UInt64 size = 0; - private List<GDBFeatureDescriptor> - gdbFeatures = new List<GDBFeatureDescriptor>(); - private UInt64 memoryBase; - private UInt64 memorySize; + private bool inst_profile = false; + private bool mem_profile = false; private UInt64 revocationMemBase; - private Dictionary<Int32, CPURegister> - registerMap = new Dictionary<Int32, CPURegister>(); - private Dictionary<string, Int32> - registerNamesMap = new Dictionary<string, Int32>(); - private string executable_file = ""; - private string symbol_file = ""; - private BinFileLoadInfo - bin_file_info = new BinFileLoadInfo {file_name = "", - load_address = 0, - entry_point = 0}; - private string cpu_library_path = ""; - private bool cpu_library_bound = false; - private NativeBinder binder; - private readonly object nativeLock; - private readonly Int32 maxStringLen = 32; - - // Pointers used in marshaling data to/from the simulator library. - private IntPtr value_ptr {get; set;} - private IntPtr error_ptr {get; set;} - private IntPtr reg_info_ptr {get; set;} - private IntPtr string_ptr {get; set;} - - // Declare some additional function signatures. - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate Int32 ConnectWithSysbus(Int32 param0, Int32 param1, - FuncInt32UInt64IntPtrInt32 param2, - FuncInt32UInt64IntPtrInt32 param3); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate Int32 ConstructWithSysbus(Int32 param0, - FuncInt32UInt64IntPtrInt32 param1, - FuncInt32UInt64IntPtrInt32 param2); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate Int32 SetConfig(Int32 param0, string[] param1, - string[] param2, Int32 param3); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate Int32 SetIrqValue(Int32 param0, Int32 param1, bool param2); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate UInt64 LoadElf(Int32 param0, string param1, bool param2, - IntPtr param3); - - // Int32 read_sysmem_delegate(UInt64 address, IntPtr buffer, Int32 size) - private FuncInt32UInt64IntPtrInt32 read_sysmem_delegate; - // Int32 write_sysmem_delegate(UInt64 address, IntPtr buffer, Int32 size) - private FuncInt32UInt64IntPtrInt32 write_sysmem_delegate; - - // Functions that are imported from the mpact sim library. -#pragma warning disable 649 - [Import(UseExceptionWrapper = false)] - // Int32 construct_with_sysbus(Int32 id, - // Int32 read_callback(UInt64, IntPtr, Int32), - // Int32 write_callback(UInt64, IntPtr, Int32)); - private ConstructWithSysbus construct_with_sysbus; - - [Import(UseExceptionWrapper = false)] - // Int32 connect_with_sybsus(Int32 id, - // Int32 read_callback(UInt64, IntPtr, Int32), - // Int32 write_callback(UInt64, IntPtr, Int32)); - private ConnectWithSysbus connect_with_sysbus; - - [Import(UseExceptionWrapper = false)] - // void destruct(Int32 id); - private ActionInt32 destruct; - - [Import(UseExceptionWrapper = false)] - // void reset(Int32 id); - private ActionInt32 reset; - - [Import(UseExceptionWrapper = false)] - // Int32 get_reg_info_size(Int32 id) - private FuncInt32Int32 get_reg_info_size; - - [Import(UseExceptionWrapper = false)] - // Int32 get_reg_info(Int32 id, IntPtr *name, IntPtr *struct); - private FuncInt32Int32Int32IntPtrIntPtr get_reg_info; - - [Import(UseExceptionWrapper = false)] - // UInt64 load_elf(Int32 id, String file_name, - // bool for_symbols_only, Int32* error_ptr); - private LoadElf load_elf; - - [Import(UseExceptionWrapper = false)] - // Int32 load_image(Int32 id, String file_name, UInt64 address); - private FuncInt32Int32StringUInt64 load_image; - - [Import(UseExceptionWrapper = false)] - // UInt64 step(Int32 id, UInt64 step, IntPtr *error); - private FuncUInt64Int32UInt64IntPtr step; - - [Import(UseExceptionWrapper = false)] - // Int32 read_register(Int32 id, Int32 reg_id, IntPtr *value); - private FuncInt32Int32Int32IntPtr read_register; - - [Import(UseExceptionWrapper = false)] - // Int32 write_register(Int32 id, Int32 reg_id, UInt64 value); - private FuncInt32Int32Int32UInt64 write_register; - - [Import(UseExceptionWrapper = false)] - // Int32 read_memory(Int32 id, UInt64 address, IntPtr buffer, Int32 size); - private FuncInt32Int32UInt64IntPtrInt32 read_memory; - - [Import(UseExceptionWrapper = false)] - // Int32 write_memory(Int32 id, UInt64 address, IntPtr buffer, Int32 size); - private FuncInt32Int32UInt64IntPtrInt32 write_memory; - - [Import(UseExceptionWrapper = false)] - // Int32 set_config(Int32 id, string[] names string[] values, Int32 size); - private SetConfig set_config; - - [Import(UseExceptionWrapper = false)] - // Int32 set_irq_value(Int32 id, Int32 irq_no, bool value); - private SetIrqValue set_irq_value; - -#pragma warning restore 649 - - private Int32 mpact_id = -1; - private ulong instructionsExecutedThisRound {get; set;} - private ulong totalExecutedInstructions {get; set;} - private const int PC_ID = 0x07b1; + private List<GDBFeatureDescriptor> + gdbFeatures = new List<GDBFeatureDescriptor>(); } // class MpactCheriotCPU - -// Peripheral interface class. -public class MpactCheriotPeripheral : IKnownSize, IBytePeripheral, - IWordPeripheral, IDoubleWordPeripheral, - IQuadWordPeripheral, - IMultibyteWritePeripheral, IDisposable { - - public MpactCheriotPeripheral(IMachine machine, long baseAddress, - long size, IMpactPeripheral mpactCpu) { - if (size == 0) { - throw new ConstructionException("Memory size cannot be 0"); - } - this.machine = machine; - this.size = size; - this.base_address = baseAddress; - this.mpact_cpu = mpactCpu; - } - - public void Reset() {} - - public void Dispose() {} - - // All memory accesses are forwarded to the mpactCpu with the base_address - // added to the address field. - public void WriteByte(long address, byte value) { - mpact_cpu.WriteByte(address + base_address, value); - } - - public byte ReadByte(long address) { - return mpact_cpu.ReadByte(address + base_address); - } - - public void WriteWord(long address, ushort value) { - mpact_cpu.WriteWord(address + base_address, value); - } - - public ushort ReadWord(long address) { - return mpact_cpu.ReadWord(address + base_address); - } - - public void WriteDoubleWord(long address, uint value) { - mpact_cpu.WriteDoubleWord(address + base_address, value); - } - - public uint ReadDoubleWord(long address) { - return mpact_cpu.ReadDoubleWord(address + base_address); - } - - public void WriteQuadWord(long address, ulong value) { - mpact_cpu.WriteQuadWord(address + base_address, value); - } - - public ulong ReadQuadWord(long address) { - return mpact_cpu.ReadQuadWord(address + base_address); - } - - public byte[] ReadBytes(long offset, int count, ICPU context = null) { - return mpact_cpu.ReadBytes(offset + base_address, count, context); - } - - public void WriteBytes(long offset, byte[] array, int startingIndex, - int count, ICPU context = null) { - mpact_cpu.WriteBytes(offset + base_address, array, startingIndex, - count, context); - } - - public long Size { get { return size;} } - private IMpactPeripheral mpact_cpu; - private long size; - private long base_address = 0; - private IMachine machine; - -} // class MpactCheriotPeripheral - } // namespace Antmicro.Renode.Peripherals.MpactCPU