blob: 38a6446c32c2918810b29e1d505ed755736b409c [file] [log] [blame]
/*
* SPDX-License-Identifier: BSD-3-Clause
* SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
*/
#include <granule.h>
#include <realm.h>
#include <rsi-config.h>
#include <rsi-walk.h>
#include <smc-rsi.h>
struct rsi_config_result handle_rsi_realm_config(struct rec *rec)
{
struct rsi_config_result res = { 0 };
unsigned long ipa = rec->regs[1];
struct rd *rd;
enum s2_walk_status walk_status;
struct s2_walk_result walk_res;
struct granule *gr;
struct rsi_realm_config *config;
if (!GRANULE_ALIGNED(ipa) || !addr_in_rec_par(rec, ipa)) {
res.smc_res.x[0] = RSI_ERROR_INPUT;
return res;
}
rd = granule_map(rec->realm_info.g_rd, SLOT_RD);
walk_status = realm_ipa_to_pa(rd, ipa, &walk_res);
if (walk_status == WALK_FAIL) {
if (s2_walk_result_match_ripas(&walk_res, RMI_EMPTY)) {
res.smc_res.x[0] = RSI_ERROR_INPUT;
} else {
/* Exit to Host */
res.walk_result.abort = true;
res.walk_result.rtt_level = walk_res.rtt_level;
}
goto out_unmap_rd;
}
if (walk_status == WALK_INVALID_PARAMS) {
/* Return error to Realm */
res.smc_res.x[0] = RSI_ERROR_INPUT;
goto out_unmap_rd;
}
/* Map Realm data granule to RMM address space */
gr = find_granule(walk_res.pa);
config = (struct rsi_realm_config *)granule_map(gr, SLOT_RSI_CALL);
/* Populate config structure */
config->ipa_width = rec->realm_info.ipa_bits;
/* Unmap Realm data granule */
buffer_unmap(config);
/* Unlock last level RTT */
granule_unlock(walk_res.llt);
/* Write output values */
res.smc_res.x[0] = RSI_SUCCESS;
out_unmap_rd:
buffer_unmap(rd);
return res;
}