xref: /kvm-unit-tests/riscv/sbi-asm.S (revision afd2cae50e8e9f2ee7dded9bab90b85a8aab94d7)
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#define __ASSEMBLY__
8#include <asm/asm.h>
9#include <asm/csr.h>
10
11#include "sbi-tests.h"
12
13.section .text
14
15/*
16 * sbi_hsm_check
17 *   a0 and a1 are set by SBI HSM start/suspend
18 *   s1 is the address of the results array
19 * Doesn't return.
20 *
21 * This function is only called from HSM start and on resumption
22 * from HSM suspend which means we can do whatever we like with
23 * all registers. So, to avoid complicated register agreements with
24 * other assembly functions called, we just always use the saved
25 * registers for anything that should be maintained across calls.
26 */
27#define HSM_RESULTS_ARRAY	s1
28#define HSM_RESULTS_MAP		s2
29#define HSM_CPU_INDEX		s3
30.balign 4
31sbi_hsm_check:
32	li	HSM_RESULTS_MAP, 0
33	REG_L	t0, ASMARR(a1, SBI_HSM_MAGIC_IDX)
34	li	t1, SBI_HSM_MAGIC
35	bne	t0, t1, 1f
36	ori	HSM_RESULTS_MAP, HSM_RESULTS_MAP, SBI_HSM_TEST_MAGIC_A1
371:	REG_L	t0, ASMARR(a1, SBI_HSM_HARTID_IDX)
38	bne	a0, t0, 2f
39	ori	HSM_RESULTS_MAP, HSM_RESULTS_MAP, SBI_HSM_TEST_HARTID_A0
402:	csrr	t0, CSR_SATP
41	bnez	t0, 3f
42	ori	HSM_RESULTS_MAP, HSM_RESULTS_MAP, SBI_HSM_TEST_SATP
433:	csrr	t0, CSR_SSTATUS
44	andi	t0, t0, SR_SIE
45	bnez	t0, 4f
46	ori	HSM_RESULTS_MAP, HSM_RESULTS_MAP, SBI_HSM_TEST_SIE
474:	call	hartid_to_cpu
48	mv	HSM_CPU_INDEX, a0
49	li	t0, -1
50	bne	HSM_CPU_INDEX, t0, 6f
515:	pause
52	j	5b
536:	ori	HSM_RESULTS_MAP, HSM_RESULTS_MAP, SBI_HSM_TEST_DONE
54	add	t0, HSM_RESULTS_ARRAY, HSM_CPU_INDEX
55	sb	HSM_RESULTS_MAP, 0(t0)
56	la	t1, sbi_hsm_stop_hart
57	add	t1, t1, HSM_CPU_INDEX
587:	lb	t0, 0(t1)
59	pause
60	beqz	t0, 7b
61	li	a7, 0x48534d	/* SBI_EXT_HSM */
62	li	a6, 1		/* SBI_EXT_HSM_HART_STOP */
63	ecall
648:	pause
65	j	8b
66
67.balign 4
68.global sbi_hsm_check_hart_start
69sbi_hsm_check_hart_start:
70	la	HSM_RESULTS_ARRAY, sbi_hsm_hart_start_checks
71	j	sbi_hsm_check
72
73.balign 4
74.global sbi_hsm_check_non_retentive_suspend
75sbi_hsm_check_non_retentive_suspend:
76	la	HSM_RESULTS_ARRAY, sbi_hsm_non_retentive_hart_suspend_checks
77	j	sbi_hsm_check
78
79.balign 4
80restore_csrs:
81	REG_L	a1, ASMARR(a0, SBI_CSR_SSTATUS_IDX)
82	csrw	CSR_SSTATUS, a1
83	REG_L	a1, ASMARR(a0, SBI_CSR_SIE_IDX)
84	csrw	CSR_SIE, a1
85	REG_L	a1, ASMARR(a0, SBI_CSR_STVEC_IDX)
86	csrw	CSR_STVEC, a1
87	REG_L	a1, ASMARR(a0, SBI_CSR_SSCRATCH_IDX)
88	csrw	CSR_SSCRATCH, a1
89	REG_L	a1, ASMARR(a0, SBI_CSR_SATP_IDX)
90	sfence.vma
91	csrw	CSR_SATP, a1
92	ret
93
94/*
95 * sbi_susp_resume
96 *
97 * State is as specified by "SUSP System Resume Register State" of the SBI spec
98 *   a0 is the hartid
99 *   a1 is the opaque parameter (here, it's the context array defined in check_susp())
100 * Doesn't return.
101 */
102#define SUSP_CTX		s1
103#define SUSP_RESULTS_MAP	s2
104.balign 4
105.global sbi_susp_resume
106sbi_susp_resume:
107	li	SUSP_RESULTS_MAP, 0
108	mv	SUSP_CTX, a1
109	REG_L	t0, ASMARR(SUSP_CTX, SBI_SUSP_MAGIC_IDX)
110	li	t1, SBI_SUSP_MAGIC
111	beq	t0, t1, 2f
1121:	pause
113	j	1b
1142:	csrr	t0, CSR_SATP
115	bnez	t0, 3f
116	ori	SUSP_RESULTS_MAP, SUSP_RESULTS_MAP, SBI_SUSP_TEST_SATP
1173:	csrr	t0, CSR_SSTATUS
118	andi	t0, t0, SR_SIE
119	bnez	t0, 4f
120	ori	SUSP_RESULTS_MAP, SUSP_RESULTS_MAP, SBI_SUSP_TEST_SIE
1214:	REG_L	t0, ASMARR(SUSP_CTX, SBI_SUSP_HARTID_IDX)
122	bne	t0, a0, 5f
123	ori	SUSP_RESULTS_MAP, SUSP_RESULTS_MAP, SBI_SUSP_TEST_HARTID
1245:	REG_S	SUSP_RESULTS_MAP, ASMARR(SUSP_CTX, SBI_SUSP_RESULTS_IDX)
125	REG_L	a0, ASMARR(SUSP_CTX, SBI_SUSP_CSRS_IDX)
126	call	restore_csrs
127	la	a0, sbi_susp_jmp
128	REG_L	a1, ASMARR(SUSP_CTX, SBI_SUSP_TESTNUM_IDX)
129	call	longjmp
1306:	pause	/* unreachable */
131	j	6b
132