1 // 2 // Copyright (c) 2010-2024 Antmicro 3 // 4 // This file is licensed under the MIT License. 5 // Full license text is available in 'licenses/MIT.txt'. 6 // 7 using System; 8 using Antmicro.Renode.Core; 9 using Antmicro.Renode.Core.Structure; 10 using Antmicro.Renode.Peripherals.IRQControllers; 11 using Antmicro.Renode.Peripherals.Timers; 12 using Antmicro.Renode.Exceptions; 13 using Antmicro.Renode.Logging; 14 using Endianess = ELFSharp.ELF.Endianess; 15 16 namespace Antmicro.Renode.Peripherals.CPU 17 { 18 public class ARMv7A : Arm, IARMSingleSecurityStateCPU, IPeripheralRegister<ARM_GenericTimer, NullRegistrationPoint> 19 { ARMv7A(IMachine machine, string cpuType, uint cpuId = 0, ARM_GenericInterruptController genericInterruptController = null, Endianess endianness = Endianess.LittleEndian)20 public ARMv7A(IMachine machine, string cpuType, uint cpuId = 0, ARM_GenericInterruptController genericInterruptController = null, Endianess endianness = Endianess.LittleEndian) 21 : base(cpuType, machine, cpuId, endianness) 22 { 23 Affinity = new Affinity(cpuId); 24 try 25 { 26 genericInterruptController?.AttachCPU(this); 27 } 28 catch(Exception e) 29 { 30 throw new ConstructionException($"Failed to attach CPU to Generic Interrupt Controller: {e.Message}", e); 31 } 32 } 33 Register(ARM_GenericTimer peripheral, NullRegistrationPoint registrationPoint)34 public void Register(ARM_GenericTimer peripheral, NullRegistrationPoint registrationPoint) 35 { 36 if(genericTimer != null) 37 { 38 throw new RegistrationException("A generic timer is already registered."); 39 } 40 genericTimer = peripheral; 41 machine.RegisterAsAChildOf(this, peripheral, registrationPoint); 42 } 43 Unregister(ARM_GenericTimer peripheral)44 public void Unregister(ARM_GenericTimer peripheral) 45 { 46 genericTimer = null; 47 machine.UnregisterAsAChildOf(this, peripheral); 48 } 49 50 public override MemorySystemArchitectureType MemorySystemArchitecture => MemorySystemArchitectureType.Virtual_VMSA; 51 52 // Currently unsupported 53 public bool FIQMaskOverride => false; 54 public bool IRQMaskOverride => false; 55 56 public Affinity Affinity { get; } 57 public SecurityState SecurityState => SecurityState.Secure; 58 public ExceptionLevel ExceptionLevel => ExceptionLevel.EL1_SystemMode; 59 Write32CP15Inner(Coprocessor32BitMoveInstruction instruction, uint value)60 protected override void Write32CP15Inner(Coprocessor32BitMoveInstruction instruction, uint value) 61 { 62 if(instruction.CRn == GenericTimerCoprocessorRegister) 63 { 64 if(genericTimer != null) 65 { 66 genericTimer.WriteDoubleWordRegisterAArch32(instruction.FieldsOnly, value); 67 return; 68 } 69 this.Log(LogLevel.Error, "Trying to write the register of a generic timer, by the CP15 32-bit write instruction ({0}), but a timer was not found.", instruction); 70 return; 71 } 72 base.Write32CP15Inner(instruction, value); 73 } 74 Read32CP15Inner(Coprocessor32BitMoveInstruction instruction)75 protected override uint Read32CP15Inner(Coprocessor32BitMoveInstruction instruction) 76 { 77 if(instruction.CRn == GenericTimerCoprocessorRegister) 78 { 79 if(genericTimer != null) 80 { 81 return genericTimer.ReadDoubleWordRegisterAArch32(instruction.FieldsOnly); 82 } 83 this.Log(LogLevel.Error, "Trying to read the register of a generic timer, by the CP15 32-bit read instruction ({0}), but a timer was not found - returning 0x0.", instruction); 84 return 0; 85 } 86 return base.Read32CP15Inner(instruction); 87 } 88 Write64CP15Inner(Coprocessor64BitMoveInstruction instruction, ulong value)89 protected override void Write64CP15Inner(Coprocessor64BitMoveInstruction instruction, ulong value) 90 { 91 if(instruction.CRm == GenericTimerCoprocessorRegister) 92 { 93 if(genericTimer != null) 94 { 95 genericTimer.WriteQuadWordRegisterAArch32(instruction.FieldsOnly, value); 96 return; 97 } 98 this.Log(LogLevel.Error, "Trying to write the register of a generic timer, by the CP15 64-bit write instruction ({0}), but a timer was not found.", instruction); 99 return; 100 } 101 base.Write64CP15Inner(instruction, value); 102 } 103 Read64CP15Inner(Coprocessor64BitMoveInstruction instruction)104 protected override ulong Read64CP15Inner(Coprocessor64BitMoveInstruction instruction) 105 { 106 if(instruction.CRm == GenericTimerCoprocessorRegister) 107 { 108 if(genericTimer != null) 109 { 110 return genericTimer.ReadQuadWordRegisterAArch32(instruction.FieldsOnly); 111 } 112 this.Log(LogLevel.Error, "Trying to read the register of a generic timer, by the CP15 64-bit read instruction ({0}), but a timer was not found - returning 0x0.", instruction); 113 return 0; 114 } 115 return base.Read64CP15Inner(instruction); 116 } 117 118 protected ARM_GenericTimer genericTimer; 119 120 private const uint GenericTimerCoprocessorRegister = 14; 121 } 122 } 123