xref: /kvm-unit-tests/riscv/sbi.c (revision a3c0b550eda595bfc3dc6177225fe0f313c1a128)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * SBI verification
4  *
5  * Copyright (C) 2023, Ventana Micro Systems Inc., Andrew Jones <ajones@ventanamicro.com>
6  */
7 #include <libcflat.h>
8 #include <stdlib.h>
9 #include <asm/sbi.h>
10 
11 static void help(void)
12 {
13 	puts("Test SBI\n");
14 	puts("An environ must be provided where expected values are given.\n");
15 }
16 
17 static struct sbiret __base_sbi_ecall(int fid, unsigned long arg0)
18 {
19 	return sbi_ecall(SBI_EXT_BASE, fid, arg0, 0, 0, 0, 0, 0);
20 }
21 
22 static bool env_or_skip(const char *env)
23 {
24 	if (!getenv(env)) {
25 		report_skip("missing %s environment variable", env);
26 		return false;
27 	}
28 
29 	return true;
30 }
31 
32 static void gen_report(struct sbiret *ret,
33 		       long expected_error, long expected_value)
34 {
35 	bool check_error = ret->error == expected_error;
36 	bool check_value = ret->value == expected_value;
37 
38 	if (!check_error || !check_value)
39 		report_info("expected (error: %ld, value: %ld), received: (error: %ld, value %ld)",
40 			    expected_error, expected_value, ret->error, ret->value);
41 
42 	report(check_error, "expected sbi.error");
43 	report(check_value, "expected sbi.value");
44 }
45 
46 static void check_base(void)
47 {
48 	struct sbiret ret;
49 	long expected;
50 
51 	report_prefix_push("base");
52 
53 	ret = __base_sbi_ecall(SBI_EXT_BASE_GET_SPEC_VERSION, 0);
54 	if (ret.error || ret.value < 2) {
55 		report_skip("SBI spec version 0.2 or higher required");
56 		return;
57 	}
58 
59 	report_prefix_push("spec_version");
60 	if (env_or_skip("SPEC_VERSION")) {
61 		expected = strtol(getenv("SPEC_VERSION"), NULL, 0);
62 		gen_report(&ret, 0, expected);
63 	}
64 	report_prefix_pop();
65 
66 	report_prefix_push("impl_id");
67 	if (env_or_skip("IMPL_ID")) {
68 		expected = strtol(getenv("IMPL_ID"), NULL, 0);
69 		ret = __base_sbi_ecall(SBI_EXT_BASE_GET_IMP_ID, 0);
70 		gen_report(&ret, 0, expected);
71 	}
72 	report_prefix_pop();
73 
74 	report_prefix_push("impl_version");
75 	if (env_or_skip("IMPL_VERSION")) {
76 		expected = strtol(getenv("IMPL_VERSION"), NULL, 0);
77 		ret = __base_sbi_ecall(SBI_EXT_BASE_GET_IMP_VERSION, 0);
78 		gen_report(&ret, 0, expected);
79 	}
80 	report_prefix_pop();
81 
82 	report_prefix_push("probe_ext");
83 	expected = getenv("PROBE_EXT") ? strtol(getenv("PROBE_EXT"), NULL, 0) : 1;
84 	ret = __base_sbi_ecall(SBI_EXT_BASE_PROBE_EXT, SBI_EXT_BASE);
85 	gen_report(&ret, 0, expected);
86 	report_prefix_push("unavailable");
87 	ret = __base_sbi_ecall(SBI_EXT_BASE_PROBE_EXT, 0xb000000);
88 	gen_report(&ret, 0, 0);
89 	report_prefix_pop();
90 	report_prefix_pop();
91 
92 	report_prefix_push("mvendorid");
93 	if (env_or_skip("MVENDORID")) {
94 		expected = strtol(getenv("MVENDORID"), NULL, 0);
95 		ret = __base_sbi_ecall(SBI_EXT_BASE_GET_MVENDORID, 0);
96 		gen_report(&ret, 0, expected);
97 	}
98 	report_prefix_pop();
99 
100 	report_prefix_push("marchid");
101 	if (env_or_skip("MARCHID")) {
102 		expected = strtol(getenv("MARCHID"), NULL, 0);
103 		ret = __base_sbi_ecall(SBI_EXT_BASE_GET_MARCHID, 0);
104 		gen_report(&ret, 0, expected);
105 	}
106 	report_prefix_pop();
107 
108 	report_prefix_push("mimpid");
109 	if (env_or_skip("MIMPID")) {
110 		expected = strtol(getenv("MIMPID"), NULL, 0);
111 		ret = __base_sbi_ecall(SBI_EXT_BASE_GET_MIMPID, 0);
112 		gen_report(&ret, 0, expected);
113 	}
114 	report_prefix_pop();
115 
116 	report_prefix_pop();
117 }
118 
119 int main(int argc, char **argv)
120 {
121 
122 	if (argc > 1 && !strcmp(argv[1], "-h")) {
123 		help();
124 		exit(0);
125 	}
126 
127 	report_prefix_push("sbi");
128 	check_base();
129 
130 	return report_summary();
131 }
132