| ********************************** Variables ********************************** |
| |
| ${UART} sysbus.uart0 |
| ${URI} @https://dl.antmicro.com/projects/renode |
| |
| ### CPSR |
| |
| ${CPSR_N_MASK} ${{ 0x1 << 31 }} |
| ${CPSR_Z_MASK} ${{ 0x1 << 30 }} |
| ${CPSR_C_MASK} ${{ 0x1 << 29 }} |
| ${CPSR_V_MASK} ${{ 0x1 << 28 }} |
| ${CPSR_Q_MASK} ${{ 0x1 << 27 }} |
| ${CPSR_SSBS_MASK} ${{ 0x1 << 23 }} |
| ${CPSR_PAN_MASK} ${{ 0x1 << 22 }} |
| ${CPSR_IL_MASK} ${{ 0x1 << 20 }} |
| ${CPSR_GE_MASK} ${{ 0xF << 16 }} |
| ${CPSR_E_MASK} ${{ 0x1 << 9 }} |
| ${CPSR_A_MASK} ${{ 0x1 << 8 }} |
| ${CPSR_I_MASK} ${{ 0x1 << 7 }} |
| ${CPSR_F_MASK} ${{ 0x1 << 6 }} |
| ${CPSR_T_MASK} ${{ 0x1 << 5 }} |
| ${CPSR_MODE_MASK} ${{ 0x1F << 0 }} |
| |
| ${INITIAL_CPSR_T_VALUE} 0x0 |
| ${INITIAL_CPSR_E_VALUE} 0x0 |
| |
| ### SCTLR |
| |
| ${SCTLR_V_MASK} ${{ 1 << 13 }} |
| ${SCTLR_M_MASK} ${{ 1 << 0 }} |
| |
| ### Privilege Level |
| |
| @{AVAILABLE_PRIVILEGE_LEVELS} User |
| ... FIQ |
| ... IRQ |
| ... Supervisor |
| ... Abort |
| ... Hypervisor |
| ... Undefined |
| ... System |
| |
| @{UNAVAILABLE_PRIVILEGE_LEVELS} Monitor |
| ${HIGHEST_PRIVILEGE_LEVEL} Hypervisor |
| |
| ### Exceptions |
| |
| @{AVAILABLE_ASYNCHRONOUS_EXCEPTIONS} IRQ FIQ |
| @{AVAILABLE_SYNCHRONOUS_EXCEPTIONS} UNDEFINED_INSTRUCTION |
| |
| ### Hivecs |
| |
| ${HIVECS_BASE_ADDRESS} 0xFFFF0000 |
| ${HIVECS_DUMMY_MEMORY} SEPARATOR= |
| ... """ ${\n} |
| ... dummy_memory: Memory.MappedMemory @ sysbus ${HIVECS_BASE_ADDRESS} ${\n} |
| ... \ \ \ \ size: 0x1000 ${\n} |
| ... """ |
| |
| *********************************** Keywords ********************************** |
| |
| ### Stateless Keywords (do not depend on the current state of the simulation) |
| |
| Get Updated Register Value |
| [Arguments] ${reg_val} ${mask} ${new_val} |
| ${result}= Set Variable ${{ (${reg_val} & ~${mask}) | (${new_val} & ${mask}) }} |
| [Return] ${result} |
| |
| Get Register Field Value |
| [Arguments] ${reg_val} ${mask} |
| ${result}= Set Variable ${{ ${reg_val} & ${mask} }} |
| [Return] ${result} |
| |
| Get CPSR Field Value |
| [Arguments] ${cpsr} ${field} |
| IF "${field}" == "N" |
| ${result}= Get Register Field Value ${cpsr} ${CPSR_N_MASK} |
| ELSE IF "${field}" == "Z" |
| ${result}= Get Register Field Value ${cpsr} ${CPSR_Z_MASK} |
| ELSE IF "${field}" == "C" |
| ${result}= Get Register Field Value ${cpsr} ${CPSR_C_MASK} |
| ELSE IF "${field}" == "V" |
| ${result}= Get Register Field Value ${cpsr} ${CPSR_V_MASK} |
| ELSE IF "${field}" == "Q" |
| ${result}= Get Register Field Value ${cpsr} ${CPSR_Q_MASK} |
| ELSE IF "${field}" == "SSBS" |
| ${result}= Get Register Field Value ${cpsr} ${CPSR_SSBS_MASK} |
| ELSE IF "${field}" == "PAN" |
| ${result}= Get Register Field Value ${cpsr} ${CPSR_PAN_MASK} |
| ELSE IF "${field}" == "IL" |
| ${result}= Get Register Field Value ${cpsr} ${CPSR_IL_MASK} |
| ELSE IF "${field}" == "GE" |
| ${result}= Get Register Field Value ${cpsr} ${CPSR_GE_MASK} |
| ELSE IF "${field}" == "E" |
| ${result}= Get Register Field Value ${cpsr} ${CPSR_E_MASK} |
| ELSE IF "${field}" == "A" |
| ${result}= Get Register Field Value ${cpsr} ${CPSR_A_MASK} |
| ELSE IF "${field}" == "I" |
| ${result}= Get Register Field Value ${cpsr} ${CPSR_I_MASK} |
| ELSE IF "${field}" == "F" |
| ${result}= Get Register Field Value ${cpsr} ${CPSR_F_MASK} |
| ELSE IF "${field}" == "T" |
| ${result}= Get Register Field Value ${cpsr} ${CPSR_T_MASK} |
| ELSE IF "${field}" == "M" or "${field}" == "MODE" |
| ${result}= Get Register Field Value ${cpsr} ${CPSR_MODE_MASK} |
| ELSE |
| Fail Unexpected CPSR Field Name: "${field}" |
| END |
| [Return] ${result} |
| |
| Get CPSR Mode Value From Privilege Level Name |
| [Arguments] ${pl} |
| IF "${pl}" == "User" or "${pl}" == "USR" |
| ${result}= Convert To Integer 0b10000 |
| ELSE IF "${pl}" == "FIQ" |
| ${result}= Convert To Integer 0b10001 |
| ELSE IF "${pl}" == "IRQ" |
| ${result}= Convert To Integer 0b10010 |
| ELSE IF "${pl}" == "Supervisor" or "${pl}" == "SVC" |
| ${result}= Convert To Integer 0b10011 |
| ELSE IF "${pl}" == "Monitor" or "${pl}" == "MON" |
| ${result}= Convert To Integer 0b10110 |
| ELSE IF "${pl}" == "Abort" or "${pl}" == "ABT" |
| ${result}= Convert To Integer 0b10111 |
| ELSE IF "${pl}" == "Hypervisor" or "${pl}" == "HYP" |
| ${result}= Convert To Integer 0b11010 |
| ELSE IF "${pl}" == "Undefined" or "${pl}" == "UND" |
| ${result}= Convert To Integer 0b11011 |
| ELSE IF "${pl}" == "System" or "${pl}" == "SYS" |
| ${result}= Convert To Integer 0b11111 |
| ELSE |
| Fail Unexpected Privilege Level Name: "${pl}" |
| END |
| [Return] ${result} |
| |
| Get CPSR For Changed Privilege Level |
| [Arguments] ${pl} ${cpsr} |
| ${mode_val}= Get CPSR Mode Value From Privilege Level Name ${pl} |
| ${new_cpsr}= Get Updated Register Value ${cpsr} ${CPSR_MODE_MASK} ${mode_val} |
| [Return] ${new_cpsr} |
| |
| Get CPSR After Changing To Wrong Mode |
| [Arguments] ${old_cpsr} ${new_cpsr} |
| ${mask}= Set Variable ${{ ~${CPSR_MODE_MASK} }} |
| ${new_cpsr} Set Variable ${{ ${new_cpsr} | ${CPSR_IL_MASK} }} |
| ${result}= Get Updated Register Value ${old_cpsr} ${mask} ${new_cpsr} |
| [Return] ${result} |
| |
| Get Exception Handler Offset From Hypervisor Vector Table |
| [Arguments] ${exception_type} |
| IF "${exception_type}" == "UNDEFINED_INSTRUCTION" |
| ${offset}= Convert To Integer 0x4 |
| ELSE IF "${exception_type}" == "HYPERVISOR_CALL" |
| ${offset}= Convert To Integer 0x8 |
| ELSE IF "${exception_type}" == "PREFETCH_ABORT" |
| ${offset}= Convert To Integer 0xc |
| ELSE IF "${exception_type}" == "DATA_ABORT" |
| ${offset}= Convert To Integer 0x10 |
| ELSE IF "${exception_type}" == "HYP_TRAP" |
| ${offset}= Convert To Integer 0x14 |
| ELSE IF "${exception_type}" == "IRQ" |
| ${offset}= Convert To Integer 0x18 |
| ELSE IF "${exception_type}" == "FIQ" |
| ${offset}= Convert To Integer 0x1c |
| ELSE |
| Fail Unexpected Exception Type Name: "${exception_type}" |
| END |
| [Return] ${offset} |
| |
| Get Exception Handler Offset From Non-Secure Vector Table |
| [Arguments] ${exception_type} |
| IF "${exception_type}" == "UNDEFINED_INSTRUCTION" |
| ${offset}= Convert To Integer 0x4 |
| ELSE IF "${exception_type}" == "SUPERVISOR_CALL" |
| ${offset}= Convert To Integer 0x8 |
| ELSE IF "${exception_type}" == "PREFETCH_ABORT" |
| ${offset}= Convert To Integer 0xc |
| ELSE IF "${exception_type}" == "DATA_ABORT" |
| ${offset}= Convert To Integer 0x10 |
| ELSE IF "${exception_type}" == "IRQ" |
| ${offset}= Convert To Integer 0x18 |
| ELSE IF "${exception_type}" == "FIQ" |
| ${offset}= Convert To Integer 0x1c |
| ELSE |
| Fail Unexpected Exception Type Name: "${exception_type}" |
| END |
| [Return] ${offset} |
| |
| Get Exception Handler Offset |
| [Arguments] ${pl} ${excp_type} |
| IF "${pl}" == "Hypervisor" or "${pl}" == "HYP" |
| ${offset}= Get Exception Handler Offset From Hypervisor Vector Table ${excp_type} |
| ELSE |
| ${offset}= Get Exception Handler Offset From Non-Secure Vector Table ${excp_type} |
| END |
| [Return] ${offset} |
| |
| Convert Integer To Hex String |
| [Arguments] ${value} |
| ${result}= Convert To Hex ${value} prefix=0x |
| [Return] ${result} |
| |
| Contains Substring |
| [Arguments] ${str} ${substr} |
| ${result}= Run Keyword And Return Status Should Contain ${str} ${substr} |
| [Return] ${result} |
| |
| ### Stateful Keywords (they depend on the current state of the simulation) |
| |
| Get Current CPSR Value |
| ${cpsr}= Execute Command sysbus.cpu CPSR |
| ${cpsr}= Convert To Integer ${cpsr} |
| [Return] ${cpsr} |
| |
| Set Current CPSR Value |
| [Arguments] ${value} |
| ${value_str}= Convert Integer To Hex String ${value} |
| Execute Command sysbus.cpu CPSR ${value_str} |
| |
| Get Current Privilege Level Value |
| ${cpsr}= Get Current CPSR Value |
| ${mode}= Get Register Field Value ${cpsr} ${CPSR_MODE_MASK} |
| [Return] ${mode} |
| |
| Set Current Privilege Level Value |
| [Arguments] ${pl} |
| ${current_cpsr}= Get Current CPSR Value |
| ${new_cpsr}= Get CPSR For Changed Privilege Level ${pl} ${current_cpsr} |
| ${new_cpsr}= Convert Integer To Hex String ${new_cpsr} |
| Execute Command sysbus.cpu CPSR ${new_cpsr} |
| |
| Get Current PC Value |
| ${pc}= Execute Command sysbus.cpu PC |
| ${pc}= Convert To Integer ${pc} |
| [Return] ${pc} |
| |
| Set Current PC Value |
| [Arguments] ${value} |
| ${value_str}= Convert Integer To Hex String ${value} |
| Execute Command sysbus.cpu PC ${value_str} |
| |
| Get Current CPSR Field Value |
| [Arguments] ${field} |
| ${cpsr}= Get Current CPSR Value |
| ${result}= Get CPSR Field Value ${cpsr} ${field} |
| [Return] ${result} |
| |
| Get Current System Register Value |
| [Arguments] ${reg_name} |
| ${reg_value}= Execute Command sysbus.cpu GetSystemRegisterValue \"${reg_name}\" |
| ${result}= Convert To Integer ${reg_value} |
| Check For Register Errors In Last Log ${reg_name} |
| [Return] ${result} |
| |
| Set Current System Register Value |
| [Arguments] ${reg_name} ${value} |
| ${value_str}= Convert Integer To Hex String ${value} |
| Execute Command sysbus.cpu SetSystemRegisterValue \"${reg_name}\" ${value_str} |
| Check For Register Errors In Last Log ${reg_name} |
| |
| Set Asynchronous Exception |
| [Arguments] ${exception_type} |
| IF "${exception_type}" == "IRQ" |
| Execute Command sysbus.cpu OnGPIO 0 True |
| ELSE IF "${exception_type}" == "FIQ" |
| Execute Command sysbus.cpu OnGPIO 1 True |
| ELSE |
| Fail Unexpected Exception Type Name: "${exception_type}" |
| END |
| |
| Set Synchronous Exception |
| [Arguments] ${exception_type} |
| IF "${exception_type}" == "UNDEFINED_INSTRUCTION" |
| ${pc}= Get Current PC Value |
| Write Opcode To Address ${pc} 0xDEADBEEF |
| Execute Command sysbus.cpu Step |
| ELSE IF "${exception_type}" == "HYPERVISOR_CALL" |
| Fail Forcing "${exception_type}" is not supported |
| ELSE IF "${exception_type}" == "SUPERVISOR_CALL" |
| Fail Forcing "${exception_type}" is not supported |
| ELSE IF "${exception_type}" == "PREFETCH_ABORT" |
| Fail Forcing "${exception_type}" is not supported |
| ELSE IF "${exception_type}" == "DATA_ABORT" |
| Fail Forcing "${exception_type}" is not supported |
| ELSE |
| Fail Unexpected Exception Type Name: "${exception_type}" |
| END |
| |
| Set Exception Vector Base Address |
| [Arguments] ${pl} ${base_address} |
| IF "${pl}" == "Hypervisor" or "${pl}" == "HYP" |
| Set Current System Register Value HVBAR ${base_address} # exceptions taken to hypervisor mode |
| ELSE |
| Set Current System Register Value VBAR ${base_address} # exceptions taken to non-secure mode |
| END |
| |
| Reset CPU |
| Execute Command sysbus.cpu Reset |
| |
| Enable Hivecs |
| ${sctlr}= Get Current System Register Value SCTLR |
| ${sctlr}= Get Updated Register Value ${sctlr} ${SCTLR_V_MASK} ${SCTLR_V_MASK} |
| Set Current System Register Value SCTLR ${sctlr} |
| |
| Enable EL2 MPU |
| ${sctlr}= Get Current System Register Value HSCTLR |
| ${sctlr}= Get Updated Register Value ${sctlr} ${SCTLR_M_MASK} ${SCTLR_M_MASK} |
| Set Current System Register Value HSCTLR ${sctlr} |
| |
| Enable EL1 MPU |
| ${sctlr}= Get Current System Register Value SCTLR |
| ${sctlr}= Get Updated Register Value ${sctlr} ${SCTLR_M_MASK} ${SCTLR_M_MASK} |
| Set Current System Register Value SCTLR ${sctlr} |
| |
| Unmask Exception |
| [Arguments] ${excp_name} |
| ${mask} Set Variable 0x0 |
| IF "${excp_name}" == "A" or "${excp_name}" == "SERROR" |
| ${mask}= Set Variable ${{ ${mask} | ${CPSR_A_MASK} }} |
| END |
| IF "${excp_name}" == "I" or "${excp_name}" == "IRQ" |
| ${mask}= Set Variable ${{ ${mask} | ${CPSR_I_MASK} }} |
| END |
| IF "${excp_name}" == "F" or "${excp_name}" == "FIQ" |
| ${mask}= Set Variable ${{ ${mask} | ${CPSR_F_MASK} }} |
| END |
| ${cpsr}= Get Current CPSR Value |
| ${new_cpsr}= Get Updated Register Value ${cpsr} ${mask} 0 |
| Set Current CPSR Value ${new_cpsr} |
| |
| Check For Register Errors In Last Log |
| [Arguments] ${reg_name} |
| ${log}= Execute Command lastLog 1 |
| ${contains_reg_error} Contains Substring ${log} system register failure |
| ${contains_reg_name} Contains Substring ${log} ${reg_name} |
| IF ${contains_reg_error} and ${contains_reg_name} |
| Fail "${reg_name}" register does not exist! |
| END |
| |
| Write Opcode To Address |
| [Arguments] ${address} ${opcode} |
| Execute Command sysbus WriteDoubleWord ${address} ${opcode} |
| |
| Current Privilege Level Should Be |
| [Arguments] ${pl} |
| ${current_pl}= Get Current Privilege Level Value |
| ${expected_pl}= Get CPSR Mode Value From Privilege Level Name ${pl} |
| Should Be Equal As Integers ${current_pl} ${expected_pl} |
| |
| Current PC Should Be |
| [Arguments] ${expected_pc} |
| ${current_pc}= Get Current PC Value |
| Should Be Equal As Integers ${current_pc} ${expected_pc} |
| |
| Current CPSR Should Be |
| [Arguments] ${expected_cpsr} |
| ${cpsr}= Get Current CPSR Value |
| Should Be Equal As Integers ${cpsr} ${expected_cpsr} |
| |
| Current CPSR Field Should Be |
| [Arguments] ${field} ${expected_value} |
| ${val}= Get Current CPSR Field Value ${field} |
| Should Be Equal As Integers ${val} ${expected_value} |
| |
| Current CPSR Flag Should Be Set |
| [Arguments] ${flag} |
| ${val}= Get Current CPSR Field Value ${flag} |
| Should Be Equal As Integers ${val} 1 |
| |
| Current CPSR Flag Should Be Unset |
| [Arguments] ${flag} |
| ${val}= Get Current CPSR Field Value ${flag} |
| Should Be Equal As Integers ${val} 0 |
| |
| Current System Register Value Should Be |
| [Arguments] ${reg_name} ${expected_value} |
| ${reg_value}= Get Current System Register Value ${reg_name} |
| Should Be Equal As Integers ${reg_value} ${expected_value} |
| |
| ### Auxiliary Keywords (not general keywords used to simplify test cases) |
| |
| Initialize Emulation |
| [Arguments] ${exec_mode}=Continuous ${pl}=default ${pc}=default ${elf}=default |
| ... ${binary}=default ${create_uart_tester}=False ${map_memory}=False |
| |
| # Tests assume Renode prints HEX numbers. |
| Execute Command numbersMode Hexadecimal |
| |
| Execute Command mach create |
| Execute Command machine LoadPlatformDescription @platforms/cpus/cortex-r52.repl |
| Execute Command sysbus.cpu ExecutionMode ${exec_mode} |
| |
| # Map all addresses as read/write and executable for EL2, EL1, and EL0 |
| IF ${map_memory} |
| # Set Attr0 to Normal, Outer-Read and -Write |
| Set Current System Register Value MAIR0 0x70 |
| # Set base address to 0, Outer Shareable, and Read-Write at EL1 and EL0, and disable execute never |
| Set Current System Register Value PRBAR 0x12 |
| # Set limit address to 0xFFFFFFFF, select Attr0, and enable the region |
| Set Current System Register Value PRLAR 0xFFFFFFC1 |
| Enable EL1 MPU |
| |
| # Set Attr0 to Normal, Outer-Read and -Write |
| Set Current System Register Value HMAIR0 0x70 |
| # Set base address to 0, Outer Shareable, and Read-Write at EL2, EL1, and EL0, and disable execute never |
| Set Current System Register Value HPRBAR 0x12 |
| # Set limit address to 0xFFFFFFFF, select Attr0, and enable the region |
| Set Current System Register Value HPRLAR 0xFFFFFFC1 |
| Enable EL2 MPU |
| END |
| |
| IF "${elf}" != "default" |
| Execute Command sysbus LoadELF ${elf} |
| END |
| IF "${binary}" != "default" |
| Execute Command sysbus LoadBinary ${binary} |
| END |
| |
| IF "${pl}" != "default" |
| Set Current Privilege Level Value ${pl} |
| Current Privilege Level Should Be ${pl} |
| END |
| IF "${pc}" != "default" |
| Set Current PC Value ${pc} |
| Current PC Should Be ${pc} |
| END |
| |
| IF ${create_uart_tester} |
| Create Terminal Tester ${UART} defaultPauseEmulation=True |
| Execute Command showAnalyzer ${UART} |
| END |
| |
| Check If CPSR Contains Reset Values |
| Current CPSR Field Should Be A ${CPSR_A_MASK} |
| Current CPSR Field Should Be I ${CPSR_I_MASK} |
| Current CPSR Field Should Be F ${CPSR_F_MASK} |
| Current CPSR Field Should Be IL 0x0 |
| Current CPSR Field Should Be T ${INITIAL_CPSR_T_VALUE} |
| Current CPSR Field Should Be E ${INITIAL_CPSR_E_VALUE} |
| |
| Check If Current PC Equal To RVBAR |
| ${rvbar_value}= Get Current System Register Value RVBAR |
| Current PC Should Be ${rvbar_value} |
| |
| Add Dummy Memory At Hivecs Base Address |
| Execute Command machine LoadPlatformDescriptionFromString ${HIVECS_DUMMY_MEMORY} |
| |
| Check Protection Region Address Register Access Through Selector Register |
| [Arguments] ${direct_addr_reg} ${selected_addr_reg} ${selector_reg} ${region_num} ${reserved_mask} |
| ${WRITE_VALUE} Set Variable 0xFFFFFFFF |
| ${EXPECTED_REG_VALUE}= Evaluate 0xFFFFFFFF ^ ${reserved_mask} |
| Set Current System Register Value ${selector_reg} ${region_num} |
| Set Current System Register Value ${selected_addr_reg} ${WRITE_VALUE} |
| ${reg_value}= Get Current System Register Value ${direct_addr_reg} |
| Should Be Equal As Integers ${reg_value} ${EXPECTED_REG_VALUE} |
| |
| Check Protection Region Address Register Access Through Direct Register |
| [Arguments] ${direct_addr_reg} ${selected_addr_reg} ${region_selector_reg} ${region_num} ${reserved_mask} |
| ${WRITE_VALUE} Set Variable 0xFFFFFFFF |
| ${EXPECTED_REG_VALUE}= Evaluate 0xFFFFFFFF ^ ${reserved_mask} |
| Set Current System Register Value ${direct_addr_reg} ${WRITE_VALUE} |
| Set Current System Register Value ${region_selector_reg} ${region_num} |
| ${reg_value}= Get Current System Register Value ${selected_addr_reg} |
| Should Be Equal As Integers ${reg_value} ${EXPECTED_REG_VALUE} |
| |
| Check Debug Exceptions Template |
| [Arguments] ${instruction} ${handler_offset} ${DBGDSCRext} ${step} ${return_address} |
| ${HANDLER_ADDRESS}= Set Variable 0x8010 |
| |
| IF "${instruction}" == "BKPT" |
| ${opcode}= Set Variable 0xE1200070 |
| ELSE IF "${instruction}" == "SVC" |
| ${opcode}= Set Variable 0xEF000000 |
| ELSE IF "${instruction}" == "HVC" |
| ${opcode}= Set Variable 0xE1400070 |
| ELSE |
| Fail Unexpected instruction: "${instruction}" |
| END |
| |
| Initialize Emulation pc=0x8000 exec_mode=SingleStep |
| Write Opcode To Address 0x8000 0xE3080010 # mov r0, #0x8010 @ HANDLER_ADDRESS |
| Write Opcode To Address 0x8004 0xEE8C0F10 # mcr p15, 4, r0, c12, c0, 0 @ set HVBAR |
| Write Opcode To Address 0x8008 ${opcode} # instruction #0 |
| Write Opcode To Address 0x800C 0xEAFFFFFD # b 0x8008 |
| Write Opcode To Address 0x8010 0xE1A00000 # nop |
| Write Opcode To Address 0x8014 0xE1A00000 # nop |
| Write Opcode To Address 0x8018 0xE1A00000 # nop |
| Write Opcode To Address 0x801C 0xE160006E # eret |
| Start Emulation |
| |
| Execute Command sysbus.cpu Step 3 |
| Current PC Should Be ${{ ${HANDLER_ADDRESS} + ${handler_offset} }} |
| Current System Register Value Should Be DBGDSCRext ${DBGDSCRext} |
| Current CPSR Field Should Be A ${CPSR_A_MASK} |
| Current CPSR Field Should Be I ${CPSR_I_MASK} |
| Current CPSR Field Should Be F ${CPSR_F_MASK} |
| Execute Command sysbus.cpu Step ${step} |
| Current PC Should Be ${return_address} |
| |
| [Teardown] Reset Emulation |
| |
| Check Synchronous Exceptions Handling Template |
| [Arguments] ${pl} ${exception_type} |
| ${EXCEPTION_HANDLER_BASE_ADDRESS}= Set Variable 0x8000 |
| ${EXCEPTION_HANDLER_OFFSET}= Get Exception Handler Offset ${pl} ${exception_type} |
| ${EXPECTED_PC}= Set Variable ${{ ${EXCEPTION_HANDLER_BASE_ADDRESS} + ${EXCEPTION_HANDLER_OFFSET} }} |
| |
| Initialize Emulation pl=${pl} exec_mode=SingleStep map_memory=True |
| Unmask Exception ${exception_type} |
| Start Emulation |
| |
| Set Exception Vector Base Address ${pl} ${EXCEPTION_HANDLER_BASE_ADDRESS} |
| Set Synchronous Exception ${exception_type} |
| Current PC Should Be ${EXPECTED_PC} |
| |
| [Teardown] Reset Emulation |
| |
| Check Asynchronous Exceptions Handling Template |
| [Arguments] ${pl} ${exception_type} |
| ${EXCEPTION_HANDLER_BASE_ADDRESS}= Set Variable 0x8000 |
| ${EXCEPTION_HANDLER_OFFSET}= Get Exception Handler Offset ${pl} ${exception_type} |
| ${EXPECTED_PC}= Set Variable ${{ ${EXCEPTION_HANDLER_BASE_ADDRESS} + ${EXCEPTION_HANDLER_OFFSET} }} |
| |
| Initialize Emulation pl=${pl} exec_mode=SingleStep |
| Unmask Exception ${exception_type} |
| Start Emulation |
| |
| Set Exception Vector Base Address ${pl} ${EXCEPTION_HANDLER_BASE_ADDRESS} |
| Set Asynchronous Exception ${exception_type} |
| Execute Command sysbus.cpu Step |
| |
| # FIXME: An artificial 0x4 offset was added because Renode executes |
| # two instructions after entering exception handler with Step command |
| Current PC Should Be ${{ ${EXPECTED_PC} + 0x4 }} |
| |
| [Teardown] Reset Emulation |
| |
| ### Template Keywords (keywords used in test templates) |
| |
| Check Changing Privilege Level From Monitor Template |
| [Arguments] ${pl} |
| |
| Initialize Emulation pl=${pl} |
| |
| Check Value Of System Registers After Initialization Template |
| [Arguments] ${reg_name} ${value} |
| |
| Initialize Emulation |
| Current System Register Value Should Be ${reg_name} ${value} |
| |
| [Teardown] Reset Emulation |
| |
| Check Value Of System Registers After Reset Template |
| [Arguments] ${reg_name} ${value} ${access} |
| |
| Initialize Emulation |
| IF "${access}" == "RW" |
| Set Current System Register Value ${reg_name} 0xDEADBEEF |
| END |
| |
| Reset CPU |
| Current System Register Value Should Be ${reg_name} ${value} |
| |
| [Teardown] Reset Emulation |
| |
| Check Access To SPSR_hyp Register Template |
| [Arguments] ${pl} |
| |
| Initialize Emulation pl=${pl} pc=0x8000 exec_mode=SingleStep map_memory=True |
| Write Opcode To Address 0x8000 0xe16ef300 # msr SPSR_hyp, r0 |
| Start Emulation |
| |
| Execute Command sysbus.cpu Step |
| IF "${pl}" == "Hypervisor" or "${pl}" == "HYP" |
| # SPSR_hyp accesses from Hypervisor mode are UNPREDICTABLE. However, a common Cortex-R52 initialization procedure, |
| # that works correctly on hardware and in FVP, sets it so Renode also allows for such accesses. |
| Current Privilege Level Should Be Hypervisor |
| Current PC Should Be 0x8004 |
| ELSE |
| # SPSR_hyp access from other Privilege Levels causes |
| # Undefined Instruction Exception handled at Undefined Privilege Level |
| Current Privilege Level Should Be Undefined |
| Current PC Should Be 0x4 |
| END |
| |
| [Teardown] Reset Emulation |
| |
| Check Access To ELR_hyp Template |
| [Arguments] ${pl} ${expected_access_allowed} |
| |
| Initialize Emulation pl=${pl} pc=0x8000 exec_mode=SingleStep map_memory=True |
| Write Opcode To Address 0x8000 0xe30c0afe # movw r0, #51966 ; 0xcafe |
| Write Opcode To Address 0x8004 0xe12ef300 # msr ELR_hyp, r0 |
| Write Opcode To Address 0x8008 0xe10e1300 # mrs r1, ELR_hyp |
| Write Opcode To Address 0x800C 0xe1500001 # cmp r0, r1 |
| Start Emulation |
| |
| IF ${expected_access_allowed} == True |
| Execute Command sysbus.cpu Step 3 |
| Current CPSR Flag Should Be Unset C |
| Current Privilege Level Should Be ${pl} |
| ELSE |
| Execute Command sysbus.cpu Step 2 |
| Current PC Should Be 0x4 |
| Current Privilege Level Should Be Undefined |
| END |
| |
| [Teardown] Reset Emulation |
| |
| Check CPSR_c Instruction Changing Privilege Level To User Template |
| [Arguments] ${pl} ${expected_access_allowed} |
| ${TARGET_CPSR}= Set Variable 0x40000110 |
| ${EXPECTED_PC}= Set Variable 0x8004 |
| |
| Initialize Emulation pl=${pl} pc=0x8000 exec_mode=SingleStep map_memory=True |
| Write Opcode To Address 0x8000 0xe321f010 # msr CPSR_c, #16 |
| Start Emulation |
| |
| ${unmodified_cpsr}= Get Current CPSR Value |
| Execute Command sysbus.cpu Step |
| IF "${pl}" == "Hypervisor" or "${pl}" == "HYP" |
| ${expected_cpsr}= Get CPSR After Changing To Wrong Mode ${unmodified_cpsr} ${TARGET_CPSR} |
| ELSE |
| IF ${expected_access_allowed} == True |
| ${expected_cpsr}= Set Variable ${TARGET_CPSR} |
| ELSE |
| ${expected_cpsr}= Set Variable ${unmodified_cpsr} |
| END |
| END |
| Current PC Should Be ${EXPECTED_PC} |
| Current CPSR Should Be ${expected_cpsr} |
| |
| [Teardown] Reset Emulation |
| |
| Check VBAR Register Usage By IRQ Template |
| [Arguments] ${pl} |
| ${EXCEPTION_VECTOR_ADDRESS}= Set Variable 0x8000 |
| ${IRQ_HANDLER_OFFSET}= Set Variable 0x18 |
| ${EXPECTED_PC}= Set Variable ${{ ${EXCEPTION_VECTOR_ADDRESS} + ${IRQ_HANDLER_OFFSET} }} |
| |
| Initialize Emulation pl=${pl} exec_mode=SingleStep |
| Unmask Exception IRQ |
| Start Emulation |
| |
| Set Exception Vector Base Address ${pl} ${EXCEPTION_VECTOR_ADDRESS} |
| Set Asynchronous Exception IRQ |
| Execute Command sysbus.cpu Step |
| |
| # FIXME: An artificial 0x4 offset was added because Renode executes two instructions after entering IRQ handler with Step command |
| Current PC Should Be ${{ ${expected_pc} + 0x4 }} |
| |
| [Teardown] Reset Emulation |
| |
| Check High Exception Vectors Usage By IRQ Template |
| [Arguments] ${pl} |
| ${IRQ_HANDLER_BASE}= Set Variable 0xFFFF0000 |
| ${IRQ_HANDLER_OFFSET}= Set Variable 0x18 |
| ${EXPECTED_PC}= Set Variable ${{ ${IRQ_HANDLER_BASE} + ${IRQ_HANDLER_OFFSET} }} |
| |
| Initialize Emulation pl=${pl} exec_mode=SingleStep map_memory=True |
| Add Dummy Memory At Hivecs Base Address # Prevent CPU abort error when trying to execute code from hivecs addresses |
| Unmask Exception IRQ |
| Enable Hivecs |
| Start Emulation |
| |
| Set Asynchronous Exception IRQ |
| Execute Command sysbus.cpu Step |
| |
| # FIXME: An artificial 0x4 offset was added because Renode executes |
| # two instructions after entering exception handler with Step command |
| Current PC Should Be ${{ ${EXPECTED_PC} + 0x4 }} |
| |
| [Teardown] Reset Emulation |
| |
| Check Protection Region Address Register Access Template |
| [Arguments] ${pl} ${reg_type} ${region_num} |
| |
| Initialize Emulation pl=${pl} exec_mode=SingleStep |
| Start Emulation |
| |
| IF "${reg_type}" == "Base" or "${reg_type}" == "BAR" |
| ${direct_addr_reg}= Set Variable PRBAR |
| ${selector_reg}= Set Variable PRSELR |
| ${reserved_mask}= Set Variable 0x20 |
| ELSE IF "${reg_type}" == "Limit" or "${reg_type}" == "LAR" |
| ${direct_addr_reg}= Set Variable PRLAR |
| ${selector_reg}= Set Variable PRSELR |
| ${reserved_mask}= Set Variable 0x30 |
| ELSE |
| Fail "Incorrect Protection Region Type" |
| END |
| ${selected_addr_reg}= Catenate SEPARATOR= ${direct_addr_reg} ${region_num} |
| IF "${pl}" == "Hypervisor" or "${pl}" == "HYP" |
| ${direct_addr_reg}= Catenate SEPARATOR= H ${direct_addr_reg} |
| ${selected_addr_reg}= Catenate SEPARATOR= H ${selected_addr_reg} |
| ${selector_reg}= Catenate SEPARATOR= H ${selector_reg} |
| END |
| Check Protection Region Address Register Access Through Selector Register ${direct_addr_reg} ${selected_addr_reg} ${selector_reg} ${region_num} ${reserved_mask} |
| Check Protection Region Address Register Access Through Direct Register ${direct_addr_reg} ${selected_addr_reg} ${selector_reg} ${region_num} ${reserved_mask} |
| |
| [Teardown] Reset Emulation |
| |
| ********************************** Test Cases ********************************* |
| |
| ### Prerequisites |
| |
| Should Get Correct EL and SS on CPU Creation |
| # This platform uses `Cortex-R52` CPU - ARMv8R in AArch32 configuration |
| # We only check if EL and SS are reflected correctly on C# side, for their usage in peripherals |
| Initialize Emulation |
| |
| ${ss}= Execute Command sysbus.cpu SecurityState |
| ${el}= Execute Command sysbus.cpu ExceptionLevel |
| |
| Should Be Equal As Strings ${ss.split()[0].strip()} NonSecure |
| Should Be Equal As Strings ${el.split()[0].strip()} EL2_HypervisorMode |
| |
| Check Changing Privilege Level From Monitor |
| [Template] Check Changing Privilege Level From Monitor Template |
| [Tags] Prerequisite |
| |
| FOR ${pl} IN @{AVAILABLE_PRIVILEGE_LEVELS} |
| ${pl} |
| END |
| |
| Check Writing To System Registers From Monitor |
| [Tags] Prerequisite |
| |
| Initialize Emulation |
| Set Current System Register Value VBAR 0xCAFE0000 |
| Current System Register Value Should Be VBAR 0xCAFE0000 |
| |
| ### CPU Initialization |
| |
| Check Privilege Level After Initialization |
| [Tags] Initialization |
| |
| Initialize Emulation |
| Current Privilege Level Should Be ${HIGHEST_PRIVILEGE_LEVEL} |
| |
| Check CPSR Value After Initialization |
| [Tags] Initialization |
| |
| Initialize Emulation |
| Check If CPSR Contains Reset Values |
| |
| Check PC Value After Initialization |
| [Tags] Initialization |
| |
| Initialize Emulation |
| Check If Current PC Equal To RVBAR |
| |
| ### CPU Reset |
| |
| Check PC Value After Reset |
| [Tags] Reset |
| |
| Initialize Emulation |
| Reset CPU |
| Check If Current PC Equal To RVBAR |
| |
| ### Hypervisor |
| |
| Check Access To SPSR_hyp Register |
| [Template] Check Access To SPSR_hyp Register Template |
| [Tags] Hypervisor |
| |
| FOR ${pl} IN @{AVAILABLE_PRIVILEGE_LEVELS} |
| ${pl} |
| END |
| |
| Check Access To ELR_hyp Register |
| [Template] Check Access To ELR_hyp Template |
| [Tags] Hypervisor |
| |
| User False |
| FIQ False |
| IRQ False |
| Supervisor False |
| Abort False |
| Hypervisor True |
| Undefined False |
| System False |
| |
| ### Basic Operation |
| |
| Check CPSR_c Instruction Changing Privilege Level To User |
| [Template] Check CPSR_c Instruction Changing Privilege Level To User Template |
| [Tags] Basic Operation |
| |
| User False |
| FIQ True |
| IRQ True |
| Supervisor True |
| Hypervisor True |
| Abort True |
| Undefined True |
| System True |
| |
| ### Exceptions |
| |
| Check VBAR Register Usage By IRQ |
| [Template] Check VBAR Register Usage By IRQ Template |
| [Tags] Exceptions |
| |
| User |
| FIQ |
| IRQ |
| Supervisor |
| Hypervisor |
| Abort |
| Undefined |
| System |
| |
| Check High Exception Vectors Usage By IRQ |
| [Template] Check High Exception Vectors Usage By IRQ Template |
| [Tags] Exceptions |
| |
| User |
| FIQ |
| IRQ |
| Supervisor |
| Hypervisor |
| Abort |
| Undefined |
| System |
| |
| Check Debug Exceptions |
| [Template] Check Debug Exceptions Template |
| [Tags] Exceptions |
| |
| BKPT 0xC 0xC 1 0x8008 |
| SVC 0x8 0x0 2 0x800c |
| HVC 0x8 0x0 2 0x800c |
| |
| Check Asynchronous Exceptions Handling |
| [Template] Check Asynchronous Exceptions Handling Template |
| [Tags] Exceptions |
| |
| FOR ${pl} IN @{AVAILABLE_PRIVILEGE_LEVELS} |
| FOR ${exception_type} IN @{AVAILABLE_ASYNCHRONOUS_EXCEPTIONS} |
| ${pl} ${exception_type} |
| END |
| END |
| |
| Check Synchronous Exceptions Handling |
| [Template] Check Synchronous Exceptions Handling Template |
| [Tags] Exceptions |
| |
| FOR ${pl} IN @{AVAILABLE_PRIVILEGE_LEVELS} |
| FOR ${exception_type} IN @{AVAILABLE_SYNCHRONOUS_EXCEPTIONS} |
| ${pl} ${exception_type} |
| END |
| END |
| |
| ### Address Translation Registers |
| |
| Check Protection Region Address Register Access |
| [Template] Check Protection Region Address Register Access Template |
| [Tags] MPU |
| |
| FOR ${region_num} IN 0 7 15 |
| User Base ${region_num} |
| User Limit ${region_num} |
| Hypervisor Base ${region_num} |
| Hypervisor Limit ${region_num} |
| END |
| |
| ### Demos |
| |
| Run Zephyr Hello World Sample |
| [Tags] Demos |
| |
| Initialize Emulation elf=${URI}/aemv8r_aarch32--zephyr-hello_world.elf-s_390996-d824c18d2044d741b7761f7ab27d3b49fae9a9e4 |
| ... create_uart_tester=True |
| |
| Wait For Line On Uart *** Booting Zephyr OS build ${SPACE}*** |
| Wait For Line On Uart Hello World! fvp_baser_aemv8r_aarch32 |
| |
| Run Zephyr Synchronization Sample |
| [Tags] Demos |
| |
| Initialize Emulation elf=${URI}/fvp_baser_aemv8r_aarch32--zephyr-synchronization.elf-s_402972-0cd785e0ec32a0c9106dec5369ad36e4b4fb386f |
| ... create_uart_tester=True |
| |
| Wait For Line On Uart Booting Zephyr OS build |
| Wait For Line On Uart thread_a: Hello World from cpu 0 on fvp_baser_aemv8r_aarch32! |
| Wait For Line On Uart thread_b: Hello World from cpu 0 on fvp_baser_aemv8r_aarch32! |
| Wait For Line On Uart thread_a: Hello World from cpu 0 on fvp_baser_aemv8r_aarch32! |
| Wait For Line On Uart thread_b: Hello World from cpu 0 on fvp_baser_aemv8r_aarch32! |
| |
| Run Zephyr Philosophers Sample |
| [Tags] Demos |
| |
| Initialize Emulation elf=${URI}/fvp_baser_aemv8r_aarch32--zephyr-philosophers.elf-s_500280-b9bbb31c64dec3f3273535be657b8e4d7ca182f9 |
| ... create_uart_tester=True |
| |
| Wait For Line On Uart Philosopher 0.*THINKING treatAsRegex=true |
| Wait For Line On Uart Philosopher 0.*HOLDING treatAsRegex=true |
| Wait For Line On Uart Philosopher 0.*EATING treatAsRegex=true |
| Wait For Line On Uart Philosopher 1.*THINKING treatAsRegex=true |
| Wait For Line On Uart Philosopher 1.*HOLDING treatAsRegex=true |
| Wait For Line On Uart Philosopher 1.*EATING treatAsRegex=true |
| Wait For Line On Uart Philosopher 2.*THINKING treatAsRegex=true |
| Wait For Line On Uart Philosopher 2.*HOLDING treatAsRegex=true |
| Wait For Line On Uart Philosopher 2.*EATING treatAsRegex=true |
| Wait For Line On Uart Philosopher 3.*THINKING treatAsRegex=true |
| Wait For Line On Uart Philosopher 3.*HOLDING treatAsRegex=true |
| Wait For Line On Uart Philosopher 3.*EATING treatAsRegex=true |
| Wait For Line On Uart Philosopher 4.*THINKING treatAsRegex=true |
| Wait For Line On Uart Philosopher 4.*HOLDING treatAsRegex=true |
| Wait For Line On Uart Philosopher 4.*EATING treatAsRegex=true |
| Wait For Line On Uart Philosopher 5.*THINKING treatAsRegex=true |
| Wait For Line On Uart Philosopher 5.*HOLDING treatAsRegex=true |
| Wait For Line On Uart Philosopher 5.*EATING treatAsRegex=true |
| |
| Run Zephyr User Space Hello World Sample |
| [Tags] Demos |
| |
| Initialize Emulation elf=${URI}/fvp_baser_aemv8r_aarch32--zephyr-userspace_hello_world_user.elf-s_1039836-cbc30725dd16eeb46c01b921f0c96e6a927c3669 |
| ... create_uart_tester=True |
| |
| Wait For Line On Uart Booting Zephyr OS build |
| Wait For Line On Uart Hello World from UserSpace! (fvp_baser_aemv8r_aarch32) |
| |
| Run Zephyr User Space Prod Consumer Sample |
| [Tags] Demos |
| |
| Initialize Emulation elf=${URI}/fvp_baser_aemv8r_aarch32--zephyr-userspace_prod_consumer.elf-s_1291928-637dbadb671ac5811ed6390b6be09447e586bf82 |
| ... create_uart_tester=True |
| |
| Wait For Line On Uart Booting Zephyr OS build |
| Provides zephyr-userspace_prod_consumer-after-booting |
| Wait For Line On Uart I: SUCCESS |
| |
| Test Resuming Zephyr User Space Prod Consumer After Deserialization |
| Requires zephyr-userspace_prod_consumer-after-booting |
| Execute Command showAnalyzer ${UART} |
| Wait For Line On Uart I: SUCCESS |
| |
| Run Zephyr User Space Shared Mem Sample |
| [Tags] Demos |
| |
| Initialize Emulation elf=${URI}/fvp_baser_aemv8r_aarch32--zephyr-userspace_shared_mem.elf-s_1096936-6da5eb0f22c62b0a23f66f68a4ba51b9ece6deff |
| ... create_uart_tester=True |
| |
| Wait For Line On Uart Booting Zephyr OS build |
| Wait For Line On Uart PT Sending Message 1 |
| Wait For Line On Uart ENC Thread Received Data |
| Wait For Line On Uart ENC PT MSG: PT: message to encrypt |
| Wait For Line On Uart CT Thread Received Message |
| Wait For Line On Uart CT MSG: ofttbhfspgmeqzos |
| Wait For Line On Uart PT Sending Message 1' |
| Wait For Line On Uart ENC Thread Received Data |
| Wait For Line On Uart ENC PT MSG: ofttbhfspgmeqzos |
| Wait For Line On Uart CT Thread Received Message |
| Wait For Line On Uart CT MSG: messagetoencrypt |
| |
| Run Zephyr Basic Sys Heap Sample |
| [Tags] Demos |
| |
| Initialize Emulation elf=${URI}/fvp_baser_aemv8r_aarch32--zephyr-basic_sys_heap.elf-s_433924-f490ec4c563a8f553702b7203956bf961242d91b |
| ... create_uart_tester=True |
| |
| Wait For Line On Uart Booting Zephyr OS build |
| Wait For Line On Uart allocated 0, free 196, max allocated 0, heap size 256 |
| Wait For Line On Uart allocated 156, free 36, max allocated 156, heap size 256 |
| Wait For Line On Uart allocated 100, free 92, max allocated 156, heap size 256 |
| Wait For Line On Uart allocated 0, free 196, max allocated 156, heap size 256 |
| |
| Run Zephyr Compression LZ4 Sample |
| [Tags] Demos |
| |
| Initialize Emulation elf=${URI}/fvp_baser_aemv8r_aarch32--zephyr-compression_lz4.elf-s_840288-1558c5d70a6fa74ffebf6fe8a31398d29af0d087 |
| ... create_uart_tester=True |
| |
| Wait For Line On Uart Booting Zephyr OS build |
| Wait For Line On Uart Successfully decompressed some data |
| Wait For Line On Uart Validation done. The string we ended up with is: |
| |
| Run Zephyr Cpp Synchronization Sample |
| [Tags] Demos |
| |
| Initialize Emulation elf=${URI}/fvp_baser_aemv8r_aarch32--zephyr-cpp_cpp_synchronization.elf-s_488868-3ac689f04acc81aaf0e10b7979f12a8d66ba73d7 |
| ... create_uart_tester=True |
| |
| Wait For Line On Uart Booting Zephyr OS build |
| Wait For Line On Uart Create semaphore 0x4e04 |
| Wait For Line On Uart Create semaphore 0x4df0 |
| Wait For Line On Uart main: Hello World! |
| Wait For Line On Uart coop_thread_entry: Hello World! |
| Wait For Line On Uart main: Hello World! |
| Wait For Line On Uart coop_thread_entry: Hello World! |
| |
| Run Zephyr Kernel Condition Variables Sample |
| [Tags] Demos |
| |
| Initialize Emulation elf=${URI}/fvp_baser_aemv8r_aarch32--zephyr-kernel_condition_variables_condvar.elf-s_478952-6ef5d598b47ef8dd8a624ffb85e4cb60fc2c6736 |
| ... create_uart_tester=True |
| |
| Wait For Line On Uart Booting Zephyr OS build |
| Wait For Line On Uart Main(): Waited and joined with 3 threads. Final value of count = 145. Done. |
| |
| Run Zephyr Kernel Condition Variables Simple Sample |
| [Tags] Demos |
| |
| Initialize Emulation elf=${URI}/fvp_baser_aemv8r_aarch32--zephyr-kernel_condition_variables_simple.elf-s_476108-e8c6ccae3076acc95f23fc3c726b4bcb8e20fff1 |
| ... create_uart_tester=True |
| |
| Wait For Line On Uart Booting Zephyr OS build |
| Wait For Line On Uart [thread main] done == 20 so everyone is done |
| |
| Test Reading From Overlapping MPU Regions |
| [Tags] Exceptions |
| |
| Initialize Emulation elf=${URI}/zephyr_pmsav8-overlapping-regions-test_fvp_baser_aemv8r_aarch32.elf-s_573792-14ad334a607d98b602f0f72522c8c22ba986b5da |
| ... create_uart_tester=True |
| |
| # The app will try to load from 0xCAFEBEE0 in main. It was built with an additional region in |
| # MPU <0xCAFEB000,0xCAFEBFFF> that overlaps a default DEVICE region <0x80000000,0xFFFFFFFF>. |
| Execute Command sysbus Tag <0xCAFEBEE0,0xCAFEBEE3> "MPU_TEST" 0xDEADCAFE |
| |
| Wait For Line On Uart *** Booting Zephyr OS build |
| Wait For Line On Uart Reading value from an address with overlapping MPU regions... |
| |
| # 4 is a fault code for the Translation Fault. It doesn't have a nice log in Zephyr. |
| # See dump_fault in arch/arm/core/aarch32/cortex_a_r/fault.c. |
| Wait For Line On Uart DATA ABORT |
| Wait For Line On Uart Unknown (4) |