1*** Variables *** 2${a0} 0xa 3${a1} 0xb 4${a2} 0xc 5${PRIV_ALL} 7 6${PRIV_READWRITE} 3 7${PRIV_WRITE_ONLY} 2 8${PRIV_EXEC_ONLY} 4 9${PRIV_NONE} 0 10${START_PC} 0x0 11${-1u64} 0xFFFFFFFFFFFFFFFF 12 13*** Keywords *** 14Create Platform 15 Execute Command using sysbus 16 Execute Command mach create "risc-v" 17 18 Execute Command machine LoadPlatformDescriptionFromString "clint: IRQControllers.CoreLevelInterruptor @ sysbus 0x44000000 { frequency: 66000000 }" 19 Execute Command machine LoadPlatformDescriptionFromString "cpu: CPU.RiscV32 @ sysbus { timeProvider: clint; cpuType: \\"rv32gc\\" }" 20 Execute Command machine LoadPlatformDescriptionFromString "mem: Memory.MappedMemory @ sysbus 0x0 { size: 0x100000 }" 21 22 Execute Command cpu PC ${START_PC} 23 24Expect Value Read From Address 25 [Arguments] ${address} ${value} 26 Execute Command cpu PC ${START_PC} 27 Execute Command cpu SetRegister ${a0} ${address} 28 Execute Command sysbus WriteDoubleWord ${START_PC} 0x52583 # lw a1, 0(a0) 29 30 Execute Command cpu Step 31 32 ${val}= Execute Command cpu GetRegister ${a1} 33 Should Be Equal As Integers ${val} ${value} 34 35Write Range With Doublewords 36 [Arguments] ${start_addr} ${length} ${value} 37 ${end_addr}= Evaluate ${start_addr}+${length} 38 ${bytesPerDoubleword}= Evaluate 4 39 FOR ${addr} IN RANGE ${start_addr} ${end_addr} ${bytesPerDoubleWord} 40 Execute Command sysbus WriteDoubleWord ${addr} ${value} 41 END 42 43Define Window Using CPU API 44 [Arguments] ${start_addr} ${end_addr} ${addend} ${priv} 45 Execute Command cpu EnableExternalWindowMmu true 46 ${window_index}= Execute Command cpu AcquireExternalMmuWindow ${PRIV_ALL} 47 Execute Command cpu SetMmuWindowStart ${window_index} ${start_addr} 48 Execute Command cpu SetMmuWindowEnd ${window_index} ${end_addr} 49 Execute Command cpu SetMmuWindowAddend ${window_index} ${addend} 50 Execute Command cpu SetMmuWindowPrivileges ${window_index} ${priv} 51 Return From Keyword ${window_index} 52 53Define Typed Window Using CPU API 54 [Arguments] ${start_addr} ${end_addr} ${addend} ${priv} ${type} 55 Execute Command cpu EnableExternalWindowMmu true 56 ${window_index}= Execute Command cpu AcquireExternalMmuWindow ${type} 57 Execute Command cpu SetMmuWindowStart ${window_index} ${start_addr} 58 Execute Command cpu SetMmuWindowEnd ${window_index} ${end_addr} 59 Execute Command cpu SetMmuWindowAddend ${window_index} ${addend} 60 Execute Command cpu SetMmuWindowPrivileges ${window_index} ${priv} 61 Return From Keyword ${window_index} 62 63Define Window In Peripheral 64 [Arguments] ${periph} ${window_index} ${start_addr} ${end_addr} ${addend} ${priv} 65 ${offset}= Evaluate 4 * ${window_index} 66 ${start_register}= Evaluate 0x0 + ${offset} 67 ${end_register}= Evaluate 0x400 + ${offset} 68 ${addend_register}= Evaluate 0x800 + ${offset} 69 ${priv_register}= Evaluate 0xC00 + ${offset} 70 Execute Command ${periph} WriteDoubleWord ${start_register} ${start_addr} 71 Execute Command ${periph} WriteDoubleWord ${end_register} ${end_addr} 72 Execute Command ${periph} WriteDoubleWord ${addend_register} ${addend} 73 Execute Command ${periph} WriteDoubleWord ${priv_register} ${priv} 74 75*** Test Cases *** 76Setting MMU Window Parameters Before Enabling Throws 77 Create Platform 78 Run Keyword And Expect Error KeywordException: *There was an error executing command 'cpu SetMmuWindowAddend 0 256'External MMU not enabled* 79 ... Execute Command cpu SetMmuWindowAddend 0 0x100 80 81Using Too High MMU Window Index Throws 82 Create Platform 83 Execute Command cpu EnableExternalWindowMmu true 84 Run Keyword And Expect Error KeywordException: *There was an error executing command 'cpu SetMmuWindowAddend 256 256'Window index to high, maximum number: 255, got 256* 85 ... Execute Command cpu SetMmuWindowAddend 256 0x100 86 87Read/Write From Address Outside The Defined MMU Windows Throws 88 Create Platform 89 Execute Command cpu EnableExternalWindowMmu true 90 Create Log Tester 0 91 Execute Command sysbus WriteWord 0x2000 0x1234 92 Expect Value Read From Address 0x10000 0x0 93 Wait For Log Entry MMU fault - the address 0x0 is not specified in any of the existing ranges 94 95Window Can Handle Only One Type Of Access 96 Create Platform 97 Execute Command cpu EnableExternalWindowMmu true 98 Create Log Tester 0 99 Define Typed Window Using CPU API 0x0000 0x1000 0x0 ${PRIV_EXEC_ONLY} ${PRIV_EXEC_ONLY} 100 Define Typed Window Using CPU API 0x0000 0x1000 0x1000 ${PRIV_READWRITE} ${PRIV_READWRITE} 101 Execute Command sysbus WriteWord 0x1000 0x0124 102 Expect Value Read From Address 0x0 0x0124 103 104Is Able To Retrive The Properties 105 Create Platform 106 107 ${window}= Define Window Using CPU API 0x1000 0x2000 0x100 ${PRIV_ALL} 108 ${range_start}= Execute Command cpu GetMmuWindowStart ${window} 109 ${range_end}= Execute Command cpu GetMmuWindowEnd ${window} 110 ${addend}= Execute Command cpu GetMmuWindowAddend ${window} 111 ${priv}= Execute Command cpu GetMmuWindowPrivileges ${window} 112 Should Be Equal As Integers 0x1000 ${range_start} 113 Should Be Equal As Integers 0x2000 ${range_end} 114 Should Be Equal As Integers 0x100 ${addend} 115 Should Be Equal As Integers ${PRIV_ALL} ${priv} 116 117Can Reset The Windows 118 Create Platform 119 120 ${window1}= Define Window Using CPU API 0x1000 0x2000 0x100 ${PRIV_ALL} 121 ${window2}= Define Window Using CPU API 0x2000 0x3000 0x100 ${PRIV_ALL} 122 ${window3}= Define Window Using CPU API 0x3000 0x4000 0x100 ${PRIV_ALL} 123 Execute Command cpu ResetMmuWindow ${window2} 124 125 # Removed window 126 ${range_start}= Execute Command cpu GetMmuWindowStart ${window2} 127 ${range_end}= Execute Command cpu GetMmuWindowEnd ${window2} 128 ${addend}= Execute Command cpu GetMmuWindowAddend ${window2} 129 ${priv}= Execute Command cpu GetMmuWindowPrivileges ${window2} 130 Should Be Equal As Integers 0 ${range_start} "Range start incorrect" 131 Should Be Equal As Integers 0 ${range_end} "Range end incorrect" 132 Should Be Equal As Integers 0 ${addend} "Range adden incorrect" 133 Should Be Equal As Integers 0 ${priv} "Range privileges incorrect" 134 135 # Surrounding windows should remain untouched 136 ${range_start}= Execute Command cpu GetMmuWindowStart ${window1} 137 ${range_end}= Execute Command cpu GetMmuWindowEnd ${window1} 138 ${addend}= Execute Command cpu GetMmuWindowAddend ${window1} 139 ${priv}= Execute Command cpu GetMmuWindowPrivileges ${window1} 140 Should Be Equal As Integers 0x1000 ${range_start} 141 Should Be Equal As Integers 0x2000 ${range_end} 142 Should Be Equal As Integers 0x100 ${addend} 143 Should Be Equal As Integers ${PRIV_ALL} ${priv} 144 145 ${range_start}= Execute Command cpu GetMmuWindowStart ${window3} 146 ${range_end}= Execute Command cpu GetMmuWindowEnd ${window3} 147 ${addend}= Execute Command cpu GetMmuWindowAddend ${window3} 148 ${priv}= Execute Command cpu GetMmuWindowPrivileges ${window3} 149 Should Be Equal As Integers 0x3000 ${range_start} 150 Should Be Equal As Integers 0x4000 ${range_end} 151 Should Be Equal As Integers 0x100 ${addend} 152 Should Be Equal As Integers ${PRIV_ALL} ${priv} 153 154Read/Write Uses The Proper Addend 155 Create Platform 156 Define Window Using CPU API 0x0000 0x1000 0x0 ${PRIV_ALL} 157 Define Window Using CPU API 0x10000 0x11000 0x1000 ${PRIV_ALL} 158 Execute Command sysbus WriteWord 0x10000 0xFFFF 159 Execute Command sysbus WriteWord 0x11000 0x0124 160 Expect Value Read From Address 0x10000 0x0124 161 162Throws On Ranges Unaligned To The Page Size 163 Create Platform 164 Run Keyword And Expect Error CpuAbortException: MMU ranges must be aligned to the page size (0x1000), the address 0x100 is not* 165 ... Define Window Using CPU API 0x100 0x1100 0x1000 ${PRIV_ALL} 166 167Permissions Are Respected 168 Create Platform 169 Create Log Tester 0 170 Execute Command logLevel -1 171 Define Window Using CPU API 0x0000 0x1000 0x0 ${PRIV_ALL} 172 Define Window Using CPU API 0x1000 0x2000 0x100 ${PRIV_EXEC_ONLY} 173 Write Range With Doublewords 0x1000 0x1FF 0xFFFFFFFF 174 Expect Value Read From Address 0x1100 0x0 175 Wait For Log Entry External MMU fault at 0x1100 176 177Fault Callback Works Only When Enabled 178 Create Platform 179 Create Log Tester 0.0001 180 Execute Command logLevel 0 cpu 181 Expect Value Read From Address 0x1100 0x0 182 Should Not Be In Log External MMU fault at 0x1100 183 184Peripheral Can Be Attached To The Sysbus 185 Create Platform 186 Execute Command machine LoadPlatformDescriptionFromString "mmu1: Miscellaneous.ExternalWindowMMU @ sysbus 0x47000000 {cpu: cpu; startAddress: 0x0; windowSize: 0x1000; numberOfWindows: 4}" 187 Define Window In Peripheral mmu1 0 0x0 0x1000 0x0 ${PRIV_EXEC_ONLY} 188 Provides SingleMMU 189 190Peripheral Can Be Configured Using The Registers Inteface 191 Requires SingleMMU 192 Define Window In Peripheral mmu1 1 0x10000 0x11000 0x1000 ${PRIV_ALL} 193 Execute Command sysbus WriteWord 0x10000 0xFFFF 194 Execute Command sysbus WriteWord 0x11000 0x0124 195 Expect Value Read From Address 0x10000 0x0124 196 197CPU Can Have Two MMUs 198 Create Platform 199 Execute Command machine LoadPlatformDescriptionFromString "mmu1: Miscellaneous.ExternalWindowMMU @ sysbus 0x47000000 {cpu: cpu; startAddress: 0x0; windowSize: 0x1000; numberOfWindows: 2}" 200 Execute Command machine LoadPlatformDescriptionFromString "mmu2: Miscellaneous.ExternalWindowMMU @ sysbus 0x47001000 {cpu: cpu; startAddress: 0x1000; windowSize: 0x1000; numberOfWindows: 2}" 201 Define Window In Peripheral mmu1 0 0x0 0x1000 0x0 ${PRIV_EXEC_ONLY} 202 Define Window In Peripheral mmu2 0 0x0 0x1000 0x0 ${PRIV_EXEC_ONLY} 203 Provides TwoMmus 204 205Peripheral Throws Fault On Illegal Data Access 206 Requires SingleMMU 207 Create Log Tester 0 208 Define Window In Peripheral mmu1 1 0x0000 0x1000 0x0000 ${PRIV_ALL} 209 Define Window In Peripheral mmu1 2 0x1000 0x2000 0x0000 ${PRIV_NONE} 210 Execute Command logLevel 0 mmu1 211 212 Expect Value Read From Address 0x1100 0x0 213 Wait For Log Entry mmu1: MMU fault occured 214 215Peripheral Does Not Throw When no_page_fault Is Set 216 Requires SingleMMU 217 Create Log Tester 0 218 Define Window In Peripheral mmu1 1 0x0000 0x1000 0x0000 ${PRIV_ALL} 219 Define Window In Peripheral mmu1 2 0x1000 0x2000 0x0000 ${PRIV_NONE} 220 Execute Command logLevel 0 mmu1 221 222 # cpu TranslateAddress uses the cpu_handle_mmu_fault with no_page_fault set to 1 223 ${returned value}= Execute Command cpu TranslateAddress 0x1100 Read 224 Should Be Equal As Integers ${returned value} ${-1u64} 225 Should Not Be In Log mmu1: MMU fault occured 226 227Peripheal Throws On Illegal Instruction Fetch 228 Create Platform 229 Create Log Tester 0 230 Execute Command machine LoadPlatformDescriptionFromString "mmu1: Miscellaneous.ExternalWindowMMU @ sysbus 0x47000000 {cpu: cpu; startAddress: 0x0; windowSize: 0x1000; numberOfWindows: 4}" 231 Define Window In Peripheral mmu1 1 0x0000 0x1000 0x0000 ${PRIV_WRITE_ONLY} 232 Execute Command logLevel 0 mmu1 233 234 Expect Value Read From Address 0x2000 0x0 235 Wait For Log Entry mmu1: MMU fault occured 236 237First MMU Throws On Fault In Its Window 238 Requires TwoMmus 239 Create Log Tester 0 240 241 Execute Command logLevel 0 mmu1 242 Execute Command logLevel 0 mmu2 243 244 Define Window In Peripheral mmu1 1 0x1000 0x2000 0x0000 ${PRIV_NONE} 245 Execute Command sysbus WriteWord 0x1000 0x0124 246 Expect Value Read From Address 0x1000 0x0 247 248 Wait For Log Entry mmu1: MMU fault occured 249 Should Not Be In Log mmu2: MMU fault occured 250 251Second MMU Throws On Fault In Its Window 252 Requires TwoMmus 253 Create Log Tester 0 254 255 Execute Command logLevel 0 mmu1 256 Execute Command logLevel 0 mmu2 257 258 Define Window In Peripheral mmu2 1 0x2000 0x3000 0x1000 ${PRIV_WRITE_ONLY} 259 Execute Command sysbus WriteWord 0x2000 0x0124 260 Expect Value Read From Address 0x2000 0x0 261 262 Wait For Log Entry mmu2: MMU fault occured 263 Should Not Be In Log mmu1: MMU fault occured 264 265Execution Stops On Fault 266 Requires SingleMMU 267 Write Range With Doublewords 0x0 0x1000 0x13 # Nop sled on whole page 268 Execute Command cpu SetRegister ${a0} 0x1C 269 Execute Command sysbus WriteDoubleWord 0x1C 0x52583 # lw a1, 0(a0) 270 Execute Command sysbus WriteDoubleWord 0x20 0xd02503 # lw a2, 0(zero) 271 Start Emulation 272 Sleep 0.1 273 274 # Assert we are halted on the faulting insn 275 ${pc}= Execute Command cpu PC 276 Should Be Equal As integers ${pc} 0x1C 277 # Assert that the second insn was not executed 278 ${val}= Execute Command cpu GetRegister ${a2} 279 Should Be Equal As Integers ${val} 0x0 280 281Throws When Window Is Out Of Range 282 Requires SingleMMU 283 Run Keyword And Expect Error *Address is outside of the possible range.* 284 ... Define Typed Window Using CPU API 0x0 0x100001000 0x0 ${PRIV_ALL} ${PRIV_ALL} 285 286Works With The Last Page Of Memory 287 Requires SingleMMU 288 Define Typed Window Using CPU API 0x0 0x100000000 0x0 ${PRIV_EXEC_ONLY} ${PRIV_EXEC_ONLY} 289 Execute Command sysbus ReadWord 0xFFFFFFFF 290