xref: /kvm-unit-tests/riscv/sbi-asm.S (revision 695740795adee59b48599e2f1a6bf19866a77779)
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * Helper assembly code routines for RISC-V SBI extension tests.
4 *
5 * Copyright (C) 2024, James Raphael Tiovalen <jamestiotio@gmail.com>
6 */
7#include <asm/asm.h>
8#include <asm/csr.h>
9#include <asm/asm-offsets.h>
10#include <generated/sbi-asm-offsets.h>
11
12#include "sbi-tests.h"
13
14.section .text
15
16/*
17 * sbi_hsm_check
18 *   a0 and a1 are set by SBI HSM start/suspend
19 *   s1 is the address of the results array
20 * Doesn't return.
21 *
22 * This function is only called from HSM start and on resumption
23 * from HSM suspend which means we can do whatever we like with
24 * all registers. So, to avoid complicated register agreements with
25 * other assembly functions called, we just always use the saved
26 * registers for anything that should be maintained across calls.
27 */
28#define HSM_RESULTS_ARRAY	s1
29#define HSM_RESULTS_MAP		s2
30#define HSM_CPU_INDEX		s3
31.balign 4
32sbi_hsm_check:
33	li	HSM_RESULTS_MAP, 0
34	REG_L	t0, ASMARR(a1, SBI_HSM_MAGIC_IDX)
35	li	t1, SBI_HSM_MAGIC
36	bne	t0, t1, 1f
37	ori	HSM_RESULTS_MAP, HSM_RESULTS_MAP, SBI_HSM_TEST_MAGIC_A1
381:	REG_L	t0, ASMARR(a1, SBI_HSM_HARTID_IDX)
39	bne	a0, t0, 2f
40	ori	HSM_RESULTS_MAP, HSM_RESULTS_MAP, SBI_HSM_TEST_HARTID_A0
412:	csrr	t0, CSR_SATP
42	bnez	t0, 3f
43	ori	HSM_RESULTS_MAP, HSM_RESULTS_MAP, SBI_HSM_TEST_SATP
443:	csrr	t0, CSR_SSTATUS
45	andi	t0, t0, SR_SIE
46	bnez	t0, 4f
47	ori	HSM_RESULTS_MAP, HSM_RESULTS_MAP, SBI_HSM_TEST_SIE
484:	call	hartid_to_cpu
49	mv	HSM_CPU_INDEX, a0
50	li	t0, -1
51	bne	HSM_CPU_INDEX, t0, 6f
525:	pause
53	j	5b
546:	ori	HSM_RESULTS_MAP, HSM_RESULTS_MAP, SBI_HSM_TEST_DONE
55	add	t0, HSM_RESULTS_ARRAY, HSM_CPU_INDEX
56	sb	HSM_RESULTS_MAP, 0(t0)
57	la	t1, sbi_hsm_stop_hart
58	add	t1, t1, HSM_CPU_INDEX
597:	lb	t0, 0(t1)
60	pause
61	beqz	t0, 7b
62	li	a7, ASM_SBI_EXT_HSM
63	li	a6, ASM_SBI_EXT_HSM_HART_STOP
64	ecall
658:	pause
66	j	8b
67
68.balign 4
69.global sbi_hsm_check_hart_start
70sbi_hsm_check_hart_start:
71	la	HSM_RESULTS_ARRAY, sbi_hsm_hart_start_checks
72	j	sbi_hsm_check
73
74.balign 4
75.global sbi_hsm_check_non_retentive_suspend
76sbi_hsm_check_non_retentive_suspend:
77	la	HSM_RESULTS_ARRAY, sbi_hsm_non_retentive_hart_suspend_checks
78	j	sbi_hsm_check
79
80.balign 4
81restore_csrs:
82	REG_L	a1, ASMARR(a0, SBI_CSR_SSTATUS_IDX)
83	csrw	CSR_SSTATUS, a1
84	REG_L	a1, ASMARR(a0, SBI_CSR_SIE_IDX)
85	csrw	CSR_SIE, a1
86	REG_L	a1, ASMARR(a0, SBI_CSR_STVEC_IDX)
87	csrw	CSR_STVEC, a1
88	REG_L	a1, ASMARR(a0, SBI_CSR_SSCRATCH_IDX)
89	csrw	CSR_SSCRATCH, a1
90	REG_L	a1, ASMARR(a0, SBI_CSR_SATP_IDX)
91	sfence.vma
92	csrw	CSR_SATP, a1
93	ret
94
95/*
96 * sbi_susp_resume
97 *
98 * State is as specified by "SUSP System Resume Register State" of the SBI spec
99 *   a0 is the hartid
100 *   a1 is the opaque parameter (here, it's the context array defined in check_susp())
101 * Doesn't return.
102 */
103#define SUSP_CTX		s1
104#define SUSP_RESULTS_MAP	s2
105.balign 4
106.global sbi_susp_resume
107sbi_susp_resume:
108	li	SUSP_RESULTS_MAP, 0
109	mv	SUSP_CTX, a1
110	REG_L	t0, ASMARR(SUSP_CTX, SBI_SUSP_MAGIC_IDX)
111	li	t1, SBI_SUSP_MAGIC
112	beq	t0, t1, 2f
1131:	pause
114	j	1b
1152:	csrr	t0, CSR_SATP
116	bnez	t0, 3f
117	ori	SUSP_RESULTS_MAP, SUSP_RESULTS_MAP, SBI_SUSP_TEST_SATP
1183:	csrr	t0, CSR_SSTATUS
119	andi	t0, t0, SR_SIE
120	bnez	t0, 4f
121	ori	SUSP_RESULTS_MAP, SUSP_RESULTS_MAP, SBI_SUSP_TEST_SIE
1224:	REG_L	t0, ASMARR(SUSP_CTX, SBI_SUSP_HARTID_IDX)
123	bne	t0, a0, 5f
124	ori	SUSP_RESULTS_MAP, SUSP_RESULTS_MAP, SBI_SUSP_TEST_HARTID
1255:	REG_S	SUSP_RESULTS_MAP, ASMARR(SUSP_CTX, SBI_SUSP_RESULTS_IDX)
126	REG_L	a0, ASMARR(SUSP_CTX, SBI_SUSP_CSRS_IDX)
127	call	restore_csrs
128	la	a0, sbi_susp_jmp
129	REG_L	a1, ASMARR(SUSP_CTX, SBI_SUSP_TESTNUM_IDX)
130	call	longjmp
1316:	pause	/* unreachable */
132	j	6b
133