1 // 2 // Copyright (c) 2010-2025 Antmicro 3 // Copyright (c) 2022-2025 Silicon Labs 4 // 5 // This file is licensed under the MIT License. 6 // Full license text is available in 'licenses/MIT.txt'. 7 // 8 9 using System; 10 using System.Collections.Generic; 11 using System.IO; 12 using Antmicro.Renode.Core; 13 using Antmicro.Renode.Core.Structure.Registers; 14 using Antmicro.Renode.Exceptions; 15 using Antmicro.Renode.Logging; 16 using Antmicro.Renode.Peripherals.Bus; 17 using Antmicro.Renode.Peripherals.Timers; 18 using Antmicro.Renode.Time; 19 20 namespace Antmicro.Renode.Peripherals.Miscellaneous.SiLabs 21 { 22 [AllowedTranslations(AllowedTranslation.ByteToDoubleWord | AllowedTranslation.WordToDoubleWord)] 23 public class EFR32xG2_SMU_1 : IBusPeripheral, IKnownSize 24 { EFR32xG2_SMU_1(Machine machine)25 public EFR32xG2_SMU_1(Machine machine) 26 { 27 this.machine = machine; 28 29 SecureIRQ = new GPIO(); 30 SecurePriviledgedIRQ = new GPIO(); 31 NonSecurePriviledgedIRQ = new GPIO(); 32 33 privilegedPeripheralAccess = new IFlagRegisterField[NumberOfPeripherals]; 34 nonSecurePrivilegedPeripheralAccess = new IFlagRegisterField[NumberOfPeripherals]; 35 securePeripheralAccess = new IFlagRegisterField[NumberOfPeripherals]; 36 disablePeripheralAccess = new IFlagRegisterField[NumberOfPeripherals]; 37 privilegedBusMusterAccess = new IFlagRegisterField[NumberOfBusMasters]; 38 secureBusMusterAccess = new IFlagRegisterField[NumberOfBusMasters]; 39 40 secureRegistersCollection = BuildSecureRegistersCollection(); 41 nonSecureRegistersCollection = BuildNonSecureRegistersCollection(); 42 } 43 Reset()44 public void Reset() 45 { 46 } 47 48 [ConnectionRegionAttribute("smu_s")] WriteDoubleWordSecure(long offset, uint value)49 public void WriteDoubleWordSecure(long offset, uint value) 50 { 51 Write<Registers>(secureRegistersCollection, "SmuSecure", offset, value); 52 } 53 54 [ConnectionRegionAttribute("smu_s")] ReadDoubleWordSecure(long offset)55 public uint ReadDoubleWordSecure(long offset) 56 { 57 return Read<Registers>(secureRegistersCollection, "SmuSecure", offset); 58 } 59 60 [ConnectionRegionAttribute("smu_ns")] WriteDoubleWordNonSecure(long offset, uint value)61 public void WriteDoubleWordNonSecure(long offset, uint value) 62 { 63 Write<Registers>(nonSecureRegistersCollection, "SmuNonSecure", offset, value); 64 } 65 66 [ConnectionRegionAttribute("smu_ns")] ReadDoubleWordNonSecure(long offset)67 public uint ReadDoubleWordNonSecure(long offset) 68 { 69 return Read<Registers>(nonSecureRegistersCollection, "SmuNonSecure", offset); 70 } 71 72 private uint Read<T>(DoubleWordRegisterCollection registersCollection, string regionName, long offset, bool internal_read = false) 73 where T : struct, IComparable, IFormattable 74 { 75 var result = 0U; 76 long internal_offset = offset; 77 78 // Set, Clear, Toggle registers should only be used for write operations. But just in case we convert here as well. 79 if (offset >= SetRegisterOffset && offset < ClearRegisterOffset) 80 { 81 // Set register 82 internal_offset = offset - SetRegisterOffset; 83 if(!internal_read) 84 { 85 this.Log(LogLevel.Noisy, "SET Operation on {0}, offset=0x{1:X}, internal_offset=0x{2:X}", Enum.Format(typeof(T), internal_offset, "G"), offset, internal_offset); 86 } 87 } else if (offset >= ClearRegisterOffset && offset < ToggleRegisterOffset) 88 { 89 // Clear register 90 internal_offset = offset - ClearRegisterOffset; 91 if(!internal_read) 92 { 93 this.Log(LogLevel.Noisy, "CLEAR Operation on {0}, offset=0x{1:X}, internal_offset=0x{2:X}", Enum.Format(typeof(T), internal_offset, "G"), offset, internal_offset); 94 } 95 } else if (offset >= ToggleRegisterOffset) 96 { 97 // Toggle register 98 internal_offset = offset - ToggleRegisterOffset; 99 if(!internal_read) 100 { 101 this.Log(LogLevel.Noisy, "TOGGLE Operation on {0}, offset=0x{1:X}, internal_offset=0x{2:X}", Enum.Format(typeof(T), internal_offset, "G"), offset, internal_offset); 102 } 103 } 104 105 if(!registersCollection.TryRead(internal_offset, out result)) 106 { 107 if(!internal_read) 108 { 109 this.Log(LogLevel.Noisy, "Unhandled read from {0} at offset 0x{1:X} ({2}).", regionName, internal_offset, Enum.Format(typeof(T), internal_offset, "G")); 110 } 111 } 112 else 113 { 114 if(!internal_read) 115 { 116 this.Log(LogLevel.Noisy, "{0}: Read from {1} at offset 0x{2:X} ({3}), returned 0x{4:X}", 117 this.GetTime(), regionName, internal_offset, Enum.Format(typeof(T), internal_offset, "G"), result); 118 } 119 } 120 121 return result; 122 } 123 124 private void Write<T>(DoubleWordRegisterCollection registersCollection, string regionName, long offset, uint value) 125 where T : struct, IComparable, IFormattable 126 { machine.ClockSource.ExecuteInLockAntmicro.Renode.Peripherals.Miscellaneous.SiLabs.EFR32xG2_SMU_1.IFormattable127 machine.ClockSource.ExecuteInLock(delegate { 128 long internal_offset = offset; 129 uint internal_value = value; 130 131 if (offset >= SetRegisterOffset && offset < ClearRegisterOffset) 132 { 133 // Set register 134 internal_offset = offset - SetRegisterOffset; 135 uint old_value = Read<T>(registersCollection, regionName, internal_offset, true); 136 internal_value = old_value | value; 137 this.Log(LogLevel.Noisy, "SET Operation on {0}, offset=0x{1:X}, internal_offset=0x{2:X}, SET_value=0x{3:X}, old_value=0x{4:X}, new_value=0x{5:X}", Enum.Format(typeof(T), internal_offset, "G"), offset, internal_offset, value, old_value, internal_value); 138 } else if (offset >= ClearRegisterOffset && offset < ToggleRegisterOffset) 139 { 140 // Clear register 141 internal_offset = offset - ClearRegisterOffset; 142 uint old_value = Read<T>(registersCollection, regionName, internal_offset, true); 143 internal_value = old_value & ~value; 144 this.Log(LogLevel.Noisy, "CLEAR Operation on {0}, offset=0x{1:X}, internal_offset=0x{2:X}, CLEAR_value=0x{3:X}, old_value=0x{4:X}, new_value=0x{5:X}", Enum.Format(typeof(T), internal_offset, "G"), offset, internal_offset, value, old_value, internal_value); 145 } else if (offset >= ToggleRegisterOffset) 146 { 147 // Toggle register 148 internal_offset = offset - ToggleRegisterOffset; 149 uint old_value = Read<T>(registersCollection, regionName, internal_offset, true); 150 internal_value = old_value ^ value; 151 this.Log(LogLevel.Noisy, "TOGGLE Operation on {0}, offset=0x{1:X}, internal_offset=0x{2:X}, TOGGLE_value=0x{3:X}, old_value=0x{4:X}, new_value=0x{5:X}", Enum.Format(typeof(T), internal_offset, "G"), offset, internal_offset, value, old_value, internal_value); 152 } 153 154 this.Log(LogLevel.Noisy, "{0}: Write to {1} at offset 0x{2:X} ({3}), value 0x{4:X}", 155 this.GetTime(), regionName, internal_offset, Enum.Format(typeof(T), internal_offset, "G"), internal_value); 156 157 if(!registersCollection.TryWrite(internal_offset, internal_value)) 158 { 159 this.Log(LogLevel.Debug, "Unhandled write to {0} at offset 0x{1:X} ({2}), value 0x{3:X}.", regionName, internal_offset, Enum.Format(typeof(T), internal_offset, "G"), internal_value); 160 return; 161 } 162 }); 163 } 164 BuildSecureRegistersCollection()165 private DoubleWordRegisterCollection BuildSecureRegistersCollection() 166 { 167 var registerDictionary = new Dictionary<long, DoubleWordRegister> 168 { 169 {(long)Registers.IpVersion, new DoubleWordRegister(this, 0x1) 170 .WithValueField(0, 32, FieldMode.Read, valueProviderCallback: _ => Version, name: "IPVERSION") 171 }, 172 {(long)Registers.Status, new DoubleWordRegister(this) 173 .WithFlag(0, out secureLock, FieldMode.Read, name: "SMULOCK") 174 .WithFlag(1, out secureProgrammingError, FieldMode.Read, name: "SMUPRGERR") 175 .WithReservedBits(2, 30) 176 }, 177 {(long)Registers.Lock, new DoubleWordRegister(this) 178 .WithValueField(0, 24, FieldMode.Write, writeCallback: (_, value) => 179 { 180 secureLock.Value = (value != UnlockKey); 181 }, name: "SMULOCKKEY") 182 .WithReservedBits(24, 8) 183 }, 184 {(long)Registers.InterruptFlags, new DoubleWordRegister(this) 185 .WithFlag(0, out PPU_PrivilegeInterrupt, name: "PPUPRIVIF") 186 .WithReservedBits(1, 1) 187 .WithFlag(2, out PPU_InstructionInterrupt, name: "PPUINSTIF") 188 .WithReservedBits(3, 13) 189 .WithFlag(16, out PPU_SecurityInterrupt, name: "PPUSECIF") 190 .WithFlag(17, out BMPU_SecurityInterrupt, name: "BMPUSECIF") 191 .WithReservedBits(18, 14) 192 .WithChangeCallback((_, __) => UpdateInterrupts()) 193 }, 194 {(long)Registers.InterruptEnable, new DoubleWordRegister(this) 195 .WithFlag(0, out PPU_PrivilegeInterruptEnable, name: "PPUPRIVIEN") 196 .WithReservedBits(1, 1) 197 .WithFlag(2, out PPU_InstructionInterruptEnable, name: "PPUINSTIEN") 198 .WithReservedBits(3, 13) 199 .WithFlag(16, out PPU_SecurityInterruptEnable, name: "PPUSECIEN") 200 .WithFlag(17, out BMPU_SecurityInterruptEnable, name: "BMPUSECIEN") 201 .WithReservedBits(18, 14) 202 .WithChangeCallback((_, __) => UpdateInterrupts()) 203 }, 204 {(long)Registers.M33Control, new DoubleWordRegister(this) 205 .WithFlag(0, out lockSAU, name: "LOCKSAU") 206 .WithFlag(1, out lockNonSecureMPU, name: "LOCKNSMPU") 207 .WithFlag(2, out lockSecureMPU, name: "LOCKSMPU") 208 .WithFlag(3, out lockNonSecureVTOR, name: "LOCKNSVTOR") 209 .WithFlag(4, out lockSecureVTAIRCR, name: "LOCKSVTAIRCR") 210 .WithReservedBits(5, 27) 211 }, 212 {(long)Registers.M33InitNsVector, new DoubleWordRegister(this) 213 .WithReservedBits(0, 7) 214 .WithTag("TBLOFF", 7, 25) 215 }, 216 {(long)Registers.M33InitSVector, new DoubleWordRegister(this) 217 .WithReservedBits(0, 7) 218 .WithTag("TBLOFF", 7, 25) 219 }, 220 {(long)Registers.PPU_PriviledgedAttribute0, new DoubleWordRegister(this, 0xFFFFFFFF) 221 .For((r, i) => r.WithFlag(i, out privilegedPeripheralAccess[i], name: $"PPUPATD{i}"), 0 , 32) 222 }, 223 {(long)Registers.PPU_PriviledgedAttribute1, new DoubleWordRegister(this, 0xFFFFFFFF) 224 .For((r, i) => r.WithFlag(i, out privilegedPeripheralAccess[i + 32], name: $"PPUPATD{i}"), 0 , 32) 225 }, 226 {(long)Registers.PPU_SecureAttribute0, new DoubleWordRegister(this, 0xFFFFFFFF) 227 .For((r, i) => r.WithFlag(i, out securePeripheralAccess[i], name: $"PPUSATD{i}"), 0 , 32) 228 }, 229 {(long)Registers.PPU_SecureAttribute1, new DoubleWordRegister(this, 0xFFFFFFFF) 230 .For((r, i) => r.WithFlag(i, out securePeripheralAccess[i + 32], name: $"PPUSATD{i}"), 0 , 32) 231 }, 232 {(long)Registers.PPU_Disable0, new DoubleWordRegister(this) 233 .For((r, i) => r.WithFlag(i, out disablePeripheralAccess[i], name: $"PPUDIS{i}"), 0 , 32) 234 }, 235 {(long)Registers.PPU_Disable1, new DoubleWordRegister(this) 236 .For((r, i) => r.WithFlag(i, out disablePeripheralAccess[i + 32], name: $"PPUDIS{i}"), 0 , 32) 237 }, 238 {(long)Registers.PPU_FaultStatus, new DoubleWordRegister(this) 239 .WithValueField(0, 8, out PPU_FaultStatus, FieldMode.Read, name: "PPUFSPERIPHID") 240 .WithReservedBits(8, 24) 241 }, 242 {(long)Registers.BMPU_PriviledgedAttribute0, new DoubleWordRegister(this, 0x1F) 243 .WithFlag(0, out privilegedBusMusterAccess[0], name: "BMPUPATD0") 244 .WithFlag(1, out privilegedBusMusterAccess[1], name: "BMPUPATD1") 245 .WithFlag(2, out privilegedBusMusterAccess[2], name: "BMPUPATD2") 246 .WithFlag(3, out privilegedBusMusterAccess[3], name: "BMPUPATD3") 247 .WithFlag(4, out privilegedBusMusterAccess[4], name: "BMPUPATD4") 248 .WithReservedBits(5, 27) 249 }, 250 {(long)Registers.BMPU_SecureAttribute0, new DoubleWordRegister(this, 0x1F) 251 .WithFlag(0, out secureBusMusterAccess[0], name: "BMPUSATD0") 252 .WithFlag(1, out secureBusMusterAccess[1], name: "BMPUSATD1") 253 .WithFlag(2, out secureBusMusterAccess[2], name: "BMPUSATD2") 254 .WithFlag(3, out secureBusMusterAccess[3], name: "BMPUSATD3") 255 .WithFlag(4, out secureBusMusterAccess[4], name: "BMPUSATD4") 256 .WithReservedBits(5, 27) 257 }, 258 {(long)Registers.BMPU_FaultStatus, new DoubleWordRegister(this) 259 .WithValueField(0, 8, out BMPU_FaultStatus, FieldMode.Read, name: "BMPUFSMASTERID") 260 .WithReservedBits(8, 24) 261 }, 262 {(long)Registers.BMPU_FaultStatusAddress, new DoubleWordRegister(this) 263 .WithValueField(0, 32, out BMPU_FaultStatusAddress, FieldMode.Read, name: "BMPUFSMASTERID") 264 }, 265 {(long)Registers.ESAU_RegionTypes0, new DoubleWordRegister(this) 266 .WithReservedBits(0, 12) 267 .WithFlag(12, out ESAU_Region3NonSecureType, name: "ESAUR3NS") 268 .WithReservedBits(13, 19) 269 }, 270 {(long)Registers.ESAU_RegionTypes1, new DoubleWordRegister(this) 271 .WithReservedBits(0, 12) 272 .WithFlag(12, out ESAU_Region11NonSecureType, name: "ESAUR11NS") 273 .WithReservedBits(13, 19) 274 }, 275 {(long)Registers.ESAU_MovableRegionBoundary0_1, new DoubleWordRegister(this, 0x02000000) 276 .WithReservedBits(0, 12) 277 .WithValueField(12, 16, out ESAU_MovableRegionBoundary0_1, name: "ESAUMRB01") 278 .WithReservedBits(28, 4) 279 .WithChangeCallback((_, __) => CheckMovableRegions()) 280 }, 281 {(long)Registers.ESAU_MovableRegionBoundary1_2, new DoubleWordRegister(this, 0x04000000) 282 .WithReservedBits(0, 12) 283 .WithValueField(12, 16, out ESAU_MovableRegionBoundary1_2, name: "ESAUMRB12") 284 .WithReservedBits(28, 4) 285 .WithChangeCallback((_, __) => CheckMovableRegions()) 286 }, 287 {(long)Registers.ESAU_MovableRegionBoundary4_5, new DoubleWordRegister(this, 0x02000000) 288 .WithReservedBits(0, 12) 289 .WithValueField(12, 16, out ESAU_MovableRegionBoundary4_5, name: "ESAUMRB45") 290 .WithReservedBits(28, 4) 291 .WithChangeCallback((_, __) => CheckMovableRegions()) 292 }, 293 {(long)Registers.ESAU_MovableRegionBoundary5_6, new DoubleWordRegister(this, 0x04000000) 294 .WithReservedBits(0, 12) 295 .WithValueField(12, 16, out ESAU_MovableRegionBoundary5_6, name: "ESAUMRB56") 296 .WithReservedBits(28, 4) 297 .WithChangeCallback((_, __) => CheckMovableRegions()) 298 }, 299 }; 300 return new DoubleWordRegisterCollection(this, registerDictionary); 301 } 302 BuildNonSecureRegistersCollection()303 private DoubleWordRegisterCollection BuildNonSecureRegistersCollection() 304 { 305 var registerDictionary = new Dictionary<long, DoubleWordRegister> 306 { 307 {(long)Registers.Status, new DoubleWordRegister(this) 308 .WithFlag(0, out nonSecureLock, FieldMode.Read, name: "SMULOCK") 309 .WithFlag(1, out nonSecureProgrammingError, FieldMode.Read, name: "SMUPRGERR") 310 .WithReservedBits(2, 30) 311 }, 312 {(long)Registers.Lock, new DoubleWordRegister(this) 313 .WithValueField(0, 24, FieldMode.Write, writeCallback: (_, value) => 314 { 315 nonSecureLock.Value = (value != UnlockKey); 316 }, name: "SMULOCKKEY") 317 .WithReservedBits(24, 8) 318 }, 319 {(long)Registers.InterruptFlags, new DoubleWordRegister(this) 320 .WithFlag(0, out PPUNS_PrivilegeInterrupt, name: "PPUNSPRIVIF") 321 .WithReservedBits(1, 1) 322 .WithFlag(2, out PPUNS_InstructionInterrupt, name: "PPUNSINSTIF") 323 .WithReservedBits(3, 29) 324 .WithChangeCallback((_, __) => UpdateInterrupts()) 325 }, 326 {(long)Registers.InterruptEnable, new DoubleWordRegister(this) 327 .WithFlag(0, out PPUNS_PrivilegeInterruptEnable, name: "PPUNSPRIVIEN") 328 .WithReservedBits(1, 1) 329 .WithFlag(2, out PPUNS_InstructionInterruptEnable, name: "PPUNSINSTIEN") 330 .WithReservedBits(3, 29) 331 .WithChangeCallback((_, __) => UpdateInterrupts()) 332 }, 333 {(long)Registers.PPU_PriviledgedAttribute0, new DoubleWordRegister(this, 0xFFFFFFFF) 334 .For((r, i) => r.WithFlag(i, out nonSecurePrivilegedPeripheralAccess[i], name: $"PPUPATD{i}"), 0 , 32) 335 }, 336 {(long)Registers.PPU_PriviledgedAttribute1, new DoubleWordRegister(this, 0xFFFFFFFF) 337 .For((r, i) => r.WithFlag(i, out nonSecurePrivilegedPeripheralAccess[i + 32], name: $"PPUPATD{i}"), 0 , 32) 338 }, 339 {(long)Registers.PPU_FaultStatus, new DoubleWordRegister(this) 340 .WithValueField(0, 8, out PPU_NonSecureFaultStatus, FieldMode.Read, name: "PPUFSPERIPHID") 341 .WithReservedBits(8, 24) 342 }, 343 }; 344 return new DoubleWordRegisterCollection(this, registerDictionary); 345 } 346 347 public long Size => 0x4000; 348 public GPIO SecureIRQ { get; } 349 public GPIO SecurePriviledgedIRQ { get; } 350 public GPIO NonSecurePriviledgedIRQ { get; } 351 private readonly Machine machine; 352 private readonly DoubleWordRegisterCollection secureRegistersCollection; 353 private readonly DoubleWordRegisterCollection nonSecureRegistersCollection; 354 private const uint SetRegisterOffset = 0x1000; 355 private const uint ClearRegisterOffset = 0x2000; 356 private const uint ToggleRegisterOffset = 0x3000; 357 private const uint Version = 1; 358 private const uint UnlockKey = 0xACCE55; 359 private const uint NumberOfPeripherals = 64; 360 private const uint NumberOfBusMasters = 5; 361 #region register fields 362 private readonly IFlagRegisterField[] privilegedPeripheralAccess; 363 private readonly IFlagRegisterField[] nonSecurePrivilegedPeripheralAccess; 364 private readonly IFlagRegisterField[] securePeripheralAccess; 365 private readonly IFlagRegisterField[] disablePeripheralAccess; 366 private readonly IFlagRegisterField[] privilegedBusMusterAccess; 367 private readonly IFlagRegisterField[] secureBusMusterAccess; 368 private IValueRegisterField ESAU_MovableRegionBoundary0_1; 369 private IValueRegisterField ESAU_MovableRegionBoundary1_2; 370 private IValueRegisterField ESAU_MovableRegionBoundary4_5; 371 private IValueRegisterField ESAU_MovableRegionBoundary5_6; 372 private IFlagRegisterField ESAU_Region3NonSecureType; 373 private IFlagRegisterField ESAU_Region11NonSecureType; 374 private IFlagRegisterField secureLock; 375 private IFlagRegisterField nonSecureLock; 376 private IFlagRegisterField secureProgrammingError; 377 private IFlagRegisterField nonSecureProgrammingError; 378 private IValueRegisterField PPU_FaultStatus; 379 private IValueRegisterField PPU_NonSecureFaultStatus; 380 private IValueRegisterField BMPU_FaultStatus; 381 private IValueRegisterField BMPU_FaultStatusAddress; 382 // TODO: SAU, MPUs, VTOR, VTAIRCR access must be filtered by SMU. 383 private IFlagRegisterField lockSAU; 384 private IFlagRegisterField lockNonSecureMPU; 385 private IFlagRegisterField lockSecureMPU; 386 private IFlagRegisterField lockNonSecureVTOR; 387 private IFlagRegisterField lockSecureVTAIRCR; 388 // Secure Interrupts 389 private IFlagRegisterField PPU_PrivilegeInterrupt; 390 private IFlagRegisterField PPU_InstructionInterrupt; 391 private IFlagRegisterField PPU_SecurityInterrupt; 392 private IFlagRegisterField BMPU_SecurityInterrupt; 393 private IFlagRegisterField PPU_PrivilegeInterruptEnable; 394 private IFlagRegisterField PPU_InstructionInterruptEnable; 395 private IFlagRegisterField PPU_SecurityInterruptEnable; 396 private IFlagRegisterField BMPU_SecurityInterruptEnable; 397 // Non-Secure Interrupts 398 private IFlagRegisterField PPUNS_PrivilegeInterrupt; 399 private IFlagRegisterField PPUNS_InstructionInterrupt; 400 private IFlagRegisterField PPUNS_PrivilegeInterruptEnable; 401 private IFlagRegisterField PPUNS_InstructionInterruptEnable; 402 #endregion 403 404 #region methods GetTime()405 private TimeInterval GetTime() => machine.LocalTimeSource.ElapsedVirtualTime; 406 UpdateInterrupts()407 private void UpdateInterrupts() 408 { 409 410 /* 411 The SMU contains three external interrupt lines, privileged, secure, and ns_privileged. 412 The privileged interrupt is asserted when the PPUINSTIF or the PPUPRIVIF is high and 413 the corresponding IEN bit is high. 414 The secure interrupt is asserted when the BMPUSECIF or the PPUSECIF is high and 415 the corresponding IEN bit is high. 416 The ns_privileged interrupt is asserted when the PPUNSPRIVIF or the PPUNSINSTIF is high and 417 the corresponding NSIEN bit is high. 418 */ 419 machine.ClockSource.ExecuteInLock(delegate { 420 var irq = ((BMPU_SecurityInterruptEnable.Value && BMPU_SecurityInterrupt.Value) 421 || PPU_SecurityInterruptEnable.Value && PPU_SecurityInterrupt.Value); 422 SecureIRQ.Set(irq); 423 424 irq = ((PPU_PrivilegeInterruptEnable.Value && PPU_PrivilegeInterrupt.Value) 425 || (PPU_InstructionInterruptEnable.Value && PPU_InstructionInterrupt.Value)); 426 SecurePriviledgedIRQ.Set(irq); 427 428 irq = ((PPUNS_PrivilegeInterruptEnable.Value && PPUNS_PrivilegeInterrupt.Value) 429 || (PPUNS_InstructionInterruptEnable.Value && PPUNS_InstructionInterrupt.Value)); 430 NonSecurePriviledgedIRQ.Set(irq); 431 }); 432 } 433 434 /* 435 ESAU Memory Regions 436 Region Num. | Base Address | Limit Address | Security Attribute 437 ------------+---------------------+----------------------+---------------------- 438 0 | 0x00000000 | 0x00000000|mrb01 | Secure 439 1 | 0x00000000|mrb01 | 0x00000000|mrb12 | Non-Secure-Callable 440 2 | 0x00000000|mrb12 | 0x0FE00000 | Non-Secure 441 3 | 0x0FE00000 | 0x10000000 | Secure or Non-Secure 442 4 | 0x20000000 | 0x20000000|mrb45 | Secure 443 5 | 0x20000000|mrb45 | 0x20000000|mrb56 | Non-Secure-Callable 444 6 | 0x20000000|mrb56 | 0x30000000 | Non-Secure 445 7 | 0x40000000 | 0x50000000 | Secure 446 8 | 0x50000000 | 0x60000000 | Non-Secure 447 9 | 0xA0000000 | 0xB0000000 | Secure 448 10 | 0xB0000000 | 0xC0000000 | Non-Secure 449 11 | 0xE0044000 | 0xE00FE000 | Secure or Non-Secure 450 12 | 0xE00FE000 | 0xE00FF000 | Exempt 451 */ GetMemoryAddressSecurityType(uint address)452 private SecurityType GetMemoryAddressSecurityType(uint address) 453 { 454 // Region 0 455 if (address < (((uint)ESAU_MovableRegionBoundary0_1.Value) << 12)) 456 { 457 return SecurityType.Secure; 458 } 459 // Region 1 460 else if ((((uint)ESAU_MovableRegionBoundary0_1.Value) << 12) <= address 461 && address < (((uint)ESAU_MovableRegionBoundary1_2.Value) << 12)) 462 { 463 return SecurityType.NonSecureCallable; 464 } 465 // Region 2 466 else if ((((uint)ESAU_MovableRegionBoundary1_2.Value) << 12) <= address 467 && address < 0x0FE00000) 468 { 469 return SecurityType.NonSecure; 470 } 471 // Region 3 472 else if (0x0FE00000 <= address && address < 0x10000000) 473 { 474 return (ESAU_Region3NonSecureType.Value) ? SecurityType.NonSecure : SecurityType.Secure; 475 } 476 // Region 4 477 else if (0x20000000 <= address 478 && address < (0x20000000 | (((uint)ESAU_MovableRegionBoundary4_5.Value) << 12))) 479 { 480 return SecurityType.Secure; 481 } 482 // Region 5 483 else if ((0x20000000 | (((uint)ESAU_MovableRegionBoundary4_5.Value) << 12)) <= address 484 && address < (0x20000000 | (((uint)ESAU_MovableRegionBoundary5_6.Value) << 12))) 485 { 486 return SecurityType.NonSecureCallable; 487 } 488 // Region 6 489 else if ((0x20000000 | (((uint)ESAU_MovableRegionBoundary5_6.Value) << 12)) <= address 490 && address < 0x30000000) 491 { 492 return SecurityType.NonSecure; 493 } 494 // Region 7 495 else if (0x40000000 <= address && address < 0x50000000) 496 { 497 return SecurityType.Secure; 498 } 499 // Region 8 500 else if (0x50000000 <= address && address < 0x60000000) 501 { 502 return SecurityType.NonSecure; 503 } 504 // Region 9 505 else if (0xA0000000 <= address && address < 0xB0000000) 506 { 507 return SecurityType.Secure; 508 } 509 // Region 10 510 else if (0xB0000000 <= address && address < 0xC0000000) 511 { 512 return SecurityType.NonSecure; 513 } 514 // Region 11 515 else if (0xE0044000 <= address && address < 0xE00FE000) 516 { 517 return (ESAU_Region11NonSecureType.Value) ? SecurityType.NonSecure : SecurityType.Secure; 518 } 519 // Region 12 520 else if (0xE00FE000 <= address && address < 0xE00FF000) 521 { 522 return SecurityType.Exempt; 523 } 524 525 this.Log(LogLevel.Error, "GetMemoryAddressSecurityType() invalid address"); 526 return SecurityType.None; 527 } 528 CheckMovableRegions()529 private void CheckMovableRegions() 530 { 531 if (ESAU_MovableRegionBoundary0_1.Value > ESAU_MovableRegionBoundary1_2.Value 532 || ESAU_MovableRegionBoundary1_2.Value > 0x0FE00000 533 || ESAU_MovableRegionBoundary4_5.Value > ESAU_MovableRegionBoundary5_6.Value 534 || ((0x20000000 | (((uint)ESAU_MovableRegionBoundary5_6.Value) << 12))) >= 0x30000000) 535 { 536 // TODO: do we need to fire an interrupt or trigger a fault? 537 secureProgrammingError.Value = true; 538 } 539 } 540 #endregion 541 542 #region enums 543 private enum SecurityType 544 { 545 None = 0, 546 Secure = 1, 547 NonSecure = 2, 548 NonSecureCallable = 3, 549 Exempt = 4, 550 } 551 552 private enum PeripheralIndex 553 { 554 Scratchpad = 0, 555 Emu = 1, 556 Cmu = 2, 557 Hfxo0 = 3, 558 Hfrco0 = 4, 559 Fsrco = 5, 560 Dpll0 = 6, 561 Lfxo = 7, 562 Lfrco = 8, 563 Ulfrco = 9, 564 Msc = 10, 565 Icache0 = 11, 566 Prs = 12, 567 Gpio = 13, 568 Ldma = 14, 569 LdmaXbar = 15, 570 Timer0 = 16, 571 Timer1 = 17, 572 Timer2 = 18, 573 Timer3 = 19, 574 Timer4 = 20, 575 Usart0 = 21, 576 Usart1 = 22, 577 Burtc = 23, 578 I2c1 = 24, 579 ChipTestCtrl = 25, 580 SyscfgCfgNs = 26, 581 Syscfg = 27, 582 Buram = 28, 583 IfadcDebug = 29, 584 Gpcrc = 30, 585 Dci = 31, 586 RootCfg = 32, 587 Dcdc = 33, 588 Pdm = 34, 589 RfSense = 35, 590 RadioAes = 36, 591 Smu = 37, 592 SmuCfgNs = 38, 593 Rtcc = 39, 594 LeTimer0 = 40, 595 Iadc0 = 41, 596 I2c0 = 42, 597 Wdog0 = 43, 598 Amuxcp0 = 44, 599 Euart0 = 45, 600 CryptoAcc = 46, 601 AhbRadio = 47, 602 } 603 604 private enum BusMasterIndex 605 { 606 RadioAes = 0, 607 CryptoAcc = 1, 608 RadioSubSystem = 2, 609 RadioFadcdDebug = 3, 610 Ldma = 4, 611 } 612 613 private enum Registers 614 { 615 IpVersion = 0x0000, 616 Status = 0x0004, 617 Lock = 0x0008, 618 InterruptFlags = 0x000C, 619 InterruptEnable = 0x0010, 620 M33Control = 0x0020, 621 M33InitNsVector = 0x0024, 622 M33InitSVector = 0x0028, 623 PPU_PriviledgedAttribute0 = 0x0040, 624 PPU_PriviledgedAttribute1 = 0x0044, 625 PPU_SecureAttribute0 = 0x0060, 626 PPU_SecureAttribute1 = 0x0064, 627 PPU_Disable0 = 0x0120, 628 PPU_Disable1 = 0x0124, 629 PPU_FaultStatus = 0x0140, 630 BMPU_PriviledgedAttribute0 = 0x0150, 631 BMPU_SecureAttribute0 = 0x0170, 632 BMPU_FaultStatus = 0x0250, 633 BMPU_FaultStatusAddress = 0x0254, 634 ESAU_RegionTypes0 = 0x0260, 635 ESAU_RegionTypes1 = 0x0264, 636 ESAU_MovableRegionBoundary0_1 = 0x0270, 637 ESAU_MovableRegionBoundary1_2 = 0x0274, 638 ESAU_MovableRegionBoundary4_5 = 0x0280, 639 ESAU_MovableRegionBoundary5_6 = 0x0284, 640 // Set registers 641 IpVersion_Set = 0x1000, 642 Status_Set = 0x1004, 643 Lock_Set = 0x1008, 644 InterruptFlags_Set = 0x100C, 645 InterruptEnable_Set = 0x1010, 646 M33Control_Set = 0x1020, 647 M33InitNsVector_Set = 0x1024, 648 M33InitSVector_Set = 0x1028, 649 PPU_PriviledgedAttribute0_Set = 0x1040, 650 PPU_PriviledgedAttribute1_Set = 0x1044, 651 PPU_SecureAttribute0_Set = 0x1060, 652 PPU_SecureAttribute1_Set = 0x1064, 653 PPU_Disable0_Set = 0x1120, 654 PPU_Disable1_Set = 0x1124, 655 PPU_FaultStatus_Set = 0x1140, 656 BMPU_PriviledgedAttribute0_Set = 0x1150, 657 BMPU_SecureAttribute0_Set = 0x1170, 658 BMPU_FaultStatus_Set = 0x1250, 659 BMPU_FaultStatusAddress_Set = 0x1254, 660 ESAU_RegionTypes0_Set = 0x1260, 661 ESAU_RegionTypes1_Set = 0x1264, 662 ESAU_MovableRegionBoundary0_1_Set = 0x1270, 663 ESAU_MovableRegionBoundary1_2_Set = 0x1274, 664 ESAU_MovableRegionBoundary4_5_Set = 0x1280, 665 ESAU_MovableRegionBoundary5_6_Set = 0x1284, 666 // Clear registers 667 IpVersion_Clr = 0x2000, 668 Status_Clr = 0x2004, 669 Lock_Clr = 0x2008, 670 InterruptFlags_Clr = 0x200C, 671 InterruptEnable_Clr = 0x2010, 672 M33Control_Clr = 0x2020, 673 M33InitNsVector_Clr = 0x2024, 674 M33InitSVector_Clr = 0x2028, 675 PPU_PriviledgedAttribute0_Clr = 0x2040, 676 PPU_PriviledgedAttribute1_Clr = 0x2044, 677 PPU_SecureAttribute0_Clr = 0x2060, 678 PPU_SecureAttribute1_Clr = 0x2064, 679 PPU_Disable0_Clr = 0x2120, 680 PPU_Disable1_Clr = 0x2124, 681 PPU_FaultStatus_Clr = 0x2140, 682 BMPU_PriviledgedAttribute0_Clr = 0x2150, 683 BMPU_SecureAttribute0_Clr = 0x2170, 684 BMPU_FaultStatus_Clr = 0x2250, 685 BMPU_FaultStatusAddress_Clr = 0x2254, 686 ESAU_RegionTypes0_Clr = 0x2260, 687 ESAU_RegionTypes1_Clr = 0x2264, 688 ESAU_MovableRegionBoundary0_1_Clr = 0x2270, 689 ESAU_MovableRegionBoundary1_2_Clr = 0x2274, 690 ESAU_MovableRegionBoundary4_5_Clr = 0x2280, 691 ESAU_MovableRegionBoundary5_6_Clr = 0x2284, 692 // Toggle registers 693 IpVersion_Tgl = 0x3000, 694 Status_Tgl = 0x3004, 695 Lock_Tgl = 0x3008, 696 InterruptFlags_Tgl = 0x300C, 697 InterruptEnable_Tgl = 0x3010, 698 M33Control_Tgl = 0x3020, 699 M33InitNsVector_Tgl = 0x3024, 700 M33InitSVector_Tgl = 0x3028, 701 PPU_PriviledgedAttribute0_Tgl = 0x3040, 702 PPU_PriviledgedAttribute1_Tgl = 0x3044, 703 PPU_SecureAttribute0_Tgl = 0x3060, 704 PPU_SecureAttribute1_Tgl = 0x3064, 705 PPU_Disable0_Tgl = 0x3120, 706 PPU_Disable1_Tgl = 0x3124, 707 PPU_FaultStatus_Tgl = 0x3140, 708 BMPU_PriviledgedAttribute0_Tgl = 0x3150, 709 BMPU_SecureAttribute0_Tgl = 0x3170, 710 BMPU_FaultStatus_Tgl = 0x3250, 711 BMPU_FaultStatusAddress_Tgl = 0x3254, 712 ESAU_RegionTypes0_Tgl = 0x3260, 713 ESAU_RegionTypes1_Tgl = 0x3264, 714 ESAU_MovableRegionBoundary0_1_Tgl = 0x3270, 715 ESAU_MovableRegionBoundary1_2_Tgl = 0x3274, 716 ESAU_MovableRegionBoundary4_5_Tgl = 0x3280, 717 ESAU_MovableRegionBoundary5_6_Tgl = 0x3284, 718 } 719 #endregion 720 } 721 }