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 System.Collections.Generic; 9 using System.Linq; 10 using Antmicro.Renode.Utilities; 11 12 namespace Antmicro.Renode.Peripherals.CPU 13 { 14 public interface IARMSingleSecurityStateCPU : ICPU 15 { 16 ExceptionLevel ExceptionLevel { get; } 17 18 Affinity Affinity { get; } 19 // This kind of CPU is always in a specific Security State and it can't be changed 20 SecurityState SecurityState { get; } 21 22 bool FIQMaskOverride { get; } 23 bool IRQMaskOverride { get; } 24 } 25 26 public interface IARMTwoSecurityStatesCPU : IARMSingleSecurityStateCPU 27 { GetAtomicExceptionLevelAndSecurityState(out ExceptionLevel exceptionLevel, out SecurityState securityState)28 void GetAtomicExceptionLevelAndSecurityState(out ExceptionLevel exceptionLevel, out SecurityState securityState); 29 30 // This property should return false if CPU doesn't support EL3 31 bool IsEL3UsingAArch32State { get; } 32 33 // The CPU may support two security states, but be in configuration that allows only one 34 bool HasSingleSecurityState { get; } 35 36 event Action<ExceptionLevel, SecurityState> ExecutionModeChanged; 37 } 38 39 public interface IARMCPUsConnectionsProvider 40 { AttachCPU(IARMSingleSecurityStateCPU cpu)41 void AttachCPU(IARMSingleSecurityStateCPU cpu); 42 // AttachedCPUs and CPUAttached provide information for GPIO handling purposes. 43 // Depending on the declaration order in repl file, some CPUs can be attached before or after peripheral's creation. 44 IEnumerable<IARMSingleSecurityStateCPU> AttachedCPUs { get; } 45 event Action<IARMSingleSecurityStateCPU> CPUAttached; 46 } 47 48 public enum ExceptionLevel : uint 49 { 50 EL0_UserMode = 0, 51 EL1_SystemMode = 1, 52 EL2_HypervisorMode = 2, 53 EL3_MonitorMode = 3 54 } 55 56 public enum ExecutionState 57 { 58 AArch32, 59 AArch64 60 } 61 62 // GIC should use GPIO#0 of an ARM CPU to signal IRQ and GPIO#1 to signal FIQ 63 // An ARM CPU should be connected to a GIC following the convention `[<N*4>-<N*4+3>] -> cpuN@[0-3]`"; 64 public enum InterruptSignalType 65 { 66 IRQ = 0, 67 FIQ = 1, 68 vIRQ = 2, 69 vFIQ = 3, 70 } 71 72 public enum SecurityState 73 { 74 Secure, 75 NonSecure 76 } 77 78 public class Affinity 79 { Affinity(byte level0, byte level1 = 0, byte level2 = 0, byte level3 = 0)80 public Affinity(byte level0, byte level1 = 0, byte level2 = 0, byte level3 = 0) 81 { 82 levels[0] = level0; 83 levels[1] = level1; 84 levels[2] = level2; 85 levels[3] = level3; 86 UpdateLevels(); 87 } 88 Affinity(uint allLevels)89 public Affinity(uint allLevels) 90 { 91 BitHelper.GetBytesFromValue(levels, 0, allLevels, levels.Length, reverse: true); 92 UpdateLevels(); 93 } 94 GetLevel(int levelIndex)95 public byte GetLevel(int levelIndex) 96 { 97 return levels[levelIndex]; 98 } 99 100 public uint AllLevels => allLevels; 101 ToString()102 public override string ToString() 103 { 104 return String.Join(".", levels); 105 } 106 107 // NOTE: UpdateLevels needs to be called whenever any value inside of `levels` is updated. UpdateLevels()108 protected void UpdateLevels() 109 { 110 allLevels = BitHelper.ToUInt32(levels, 0, levels.Length, reverse: true); 111 } 112 113 protected readonly byte[] levels = new byte[LevelsCount]; 114 protected const int LevelsCount = 4; 115 116 private uint allLevels; 117 } 118 119 public class MutableAffinity : Affinity 120 { MutableAffinity()121 public MutableAffinity() : base(0) { } 122 SetLevel(int levelIndex, byte levelValue)123 public void SetLevel(int levelIndex, byte levelValue) 124 { 125 levels[levelIndex] = levelValue; 126 UpdateLevels(); 127 } 128 } 129 } 130