1 /*
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
5  */
6 
7 #include <realm.h>
8 #include <ripas.h>
9 #include <rsi-memory.h>
10 #include <smc-rsi.h>
11 #include <status.h>
12 
handle_rsi_ipa_state_set(struct rec * rec,struct rmi_rec_exit * rec_exit)13 bool handle_rsi_ipa_state_set(struct rec *rec, struct rmi_rec_exit *rec_exit)
14 {
15 	unsigned long start = rec->regs[1];
16 	unsigned long size = rec->regs[2];
17 	unsigned long end = start + size;
18 	enum ripas ripas = (enum ripas)rec->regs[3];
19 
20 	if (ripas > RMI_RAM) {
21 		return true;
22 	}
23 
24 	if (!GRANULE_ALIGNED(start)) {
25 		return true;
26 	}
27 
28 	if (!GRANULE_ALIGNED(size)) {
29 		return true;
30 	}
31 
32 	if (end <= start) {
33 		/* Size is zero, or range overflows */
34 		return true;
35 	}
36 
37 	if (!region_in_rec_par(rec, start, end)) {
38 		return true;
39 	}
40 
41 	rec->set_ripas.start = start;
42 	rec->set_ripas.end = end;
43 	rec->set_ripas.addr = start;
44 	rec->set_ripas.ripas = ripas;
45 
46 	rec_exit->exit_reason = RMI_EXIT_RIPAS_CHANGE;
47 	rec_exit->ripas_base = start;
48 	rec_exit->ripas_size = size;
49 	rec_exit->ripas_value = (unsigned int)ripas;
50 
51 	return false;
52 }
53 
handle_rsi_ipa_state_get(struct rec * rec)54 struct rsi_walk_smc_result handle_rsi_ipa_state_get(struct rec *rec)
55 {
56 	struct rsi_walk_smc_result res = { 0 };
57 	enum s2_walk_status ws;
58 	unsigned long rtt_level, ipa;
59 	enum ripas ripas;
60 
61 	ipa = rec->regs[1];
62 
63 	/* Exit to realm */
64 	res.walk_result.abort = false;
65 
66 	if (!GRANULE_ALIGNED(ipa) || !addr_in_rec_par(rec, ipa)) {
67 		res.smc_res.x[0] = RSI_ERROR_INPUT;
68 		return res;
69 	}
70 
71 	ws = realm_ipa_get_ripas(rec, ipa, &ripas, &rtt_level);
72 	if (ws == WALK_SUCCESS) {
73 		res.smc_res.x[0] = RSI_SUCCESS;
74 		res.smc_res.x[1] = ripas;
75 	} else {
76 		/* Exit to Host */
77 		res.walk_result.abort = true;
78 		res.walk_result.rtt_level = rtt_level;
79 	}
80 
81 	return res;
82 }
83