blob: 923c2ceca5db819e2fd4b4a8ae1bf194228542e9 [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Helper assembly code routines for RISC-V SBI extension tests.
*
* Copyright (C) 2024, James Raphael Tiovalen <jamestiotio@gmail.com>
*/
#define __ASSEMBLY__
#include <asm/asm.h>
#include <asm/csr.h>
#include "sbi-tests.h"
.section .text
/*
* sbi_hsm_check
* a0 and a1 are set by SBI HSM start/suspend
* s1 is the address of the results array
* Doesn't return.
*
* This function is only called from HSM start and on resumption
* from HSM suspend which means we can do whatever we like with
* all registers. So, to avoid complicated register agreements with
* other assembly functions called, we just always use the saved
* registers for anything that should be maintained across calls.
*/
#define HSM_RESULTS_ARRAY s1
#define HSM_RESULTS_MAP s2
#define HSM_CPU_INDEX s3
.balign 4
sbi_hsm_check:
li HSM_RESULTS_MAP, 0
REG_L t0, ASMARR(a1, SBI_HSM_MAGIC_IDX)
li t1, SBI_HSM_MAGIC
bne t0, t1, 1f
ori HSM_RESULTS_MAP, HSM_RESULTS_MAP, SBI_HSM_TEST_MAGIC_A1
1: REG_L t0, ASMARR(a1, SBI_HSM_HARTID_IDX)
bne a0, t0, 2f
ori HSM_RESULTS_MAP, HSM_RESULTS_MAP, SBI_HSM_TEST_HARTID_A0
2: csrr t0, CSR_SATP
bnez t0, 3f
ori HSM_RESULTS_MAP, HSM_RESULTS_MAP, SBI_HSM_TEST_SATP
3: csrr t0, CSR_SSTATUS
andi t0, t0, SR_SIE
bnez t0, 4f
ori HSM_RESULTS_MAP, HSM_RESULTS_MAP, SBI_HSM_TEST_SIE
4: call hartid_to_cpu
mv HSM_CPU_INDEX, a0
li t0, -1
bne HSM_CPU_INDEX, t0, 6f
5: pause
j 5b
6: ori HSM_RESULTS_MAP, HSM_RESULTS_MAP, SBI_HSM_TEST_DONE
add t0, HSM_RESULTS_ARRAY, HSM_CPU_INDEX
sb HSM_RESULTS_MAP, 0(t0)
la t1, sbi_hsm_stop_hart
add t1, t1, HSM_CPU_INDEX
7: lb t0, 0(t1)
pause
beqz t0, 7b
li a7, 0x48534d /* SBI_EXT_HSM */
li a6, 1 /* SBI_EXT_HSM_HART_STOP */
ecall
8: pause
j 8b
.balign 4
.global sbi_hsm_check_hart_start
sbi_hsm_check_hart_start:
la HSM_RESULTS_ARRAY, sbi_hsm_hart_start_checks
j sbi_hsm_check
.balign 4
.global sbi_hsm_check_non_retentive_suspend
sbi_hsm_check_non_retentive_suspend:
la HSM_RESULTS_ARRAY, sbi_hsm_non_retentive_hart_suspend_checks
j sbi_hsm_check
.balign 4
restore_csrs:
REG_L a1, ASMARR(a0, SBI_CSR_SSTATUS_IDX)
csrw CSR_SSTATUS, a1
REG_L a1, ASMARR(a0, SBI_CSR_SIE_IDX)
csrw CSR_SIE, a1
REG_L a1, ASMARR(a0, SBI_CSR_STVEC_IDX)
csrw CSR_STVEC, a1
REG_L a1, ASMARR(a0, SBI_CSR_SSCRATCH_IDX)
csrw CSR_SSCRATCH, a1
REG_L a1, ASMARR(a0, SBI_CSR_SATP_IDX)
sfence.vma
csrw CSR_SATP, a1
ret
/*
* sbi_susp_resume
*
* State is as specified by "SUSP System Resume Register State" of the SBI spec
* a0 is the hartid
* a1 is the opaque parameter (here, it's the context array defined in check_susp())
* Doesn't return.
*/
#define SUSP_CTX s1
#define SUSP_RESULTS_MAP s2
.balign 4
.global sbi_susp_resume
sbi_susp_resume:
li SUSP_RESULTS_MAP, 0
mv SUSP_CTX, a1
REG_L t0, ASMARR(SUSP_CTX, SBI_SUSP_MAGIC_IDX)
li t1, SBI_SUSP_MAGIC
beq t0, t1, 2f
1: pause
j 1b
2: csrr t0, CSR_SATP
bnez t0, 3f
ori SUSP_RESULTS_MAP, SUSP_RESULTS_MAP, SBI_SUSP_TEST_SATP
3: csrr t0, CSR_SSTATUS
andi t0, t0, SR_SIE
bnez t0, 4f
ori SUSP_RESULTS_MAP, SUSP_RESULTS_MAP, SBI_SUSP_TEST_SIE
4: REG_L t0, ASMARR(SUSP_CTX, SBI_SUSP_HARTID_IDX)
bne t0, a0, 5f
ori SUSP_RESULTS_MAP, SUSP_RESULTS_MAP, SBI_SUSP_TEST_HARTID
5: REG_S SUSP_RESULTS_MAP, ASMARR(SUSP_CTX, SBI_SUSP_RESULTS_IDX)
REG_L a0, ASMARR(SUSP_CTX, SBI_SUSP_CSRS_IDX)
call restore_csrs
la a0, sbi_susp_jmp
REG_L a1, ASMARR(SUSP_CTX, SBI_SUSP_TESTNUM_IDX)
call longjmp
6: pause /* unreachable */
j 6b