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