blob: 163443e6006420c18f8988aa79cf1ee7e398a32c [file] [log] [blame]
/*
* Copyright (c) 2022-2025, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#include <host_realm_rmi.h>
#include <lib/aarch64/arch_features.h>
#include <realm_helpers.h>
#include <realm_rsi.h>
#include <smccc.h>
/* This function return RSI_ABI_VERSION */
u_register_t rsi_get_version(u_register_t req_ver)
{
smc_ret_values res = {};
res = tftf_smc(&(smc_args)
{SMC_RSI_VERSION, req_ver, 0UL, 0UL, 0UL, 0UL, 0UL, 0UL});
if (res.ret0 == SMC_UNKNOWN) {
return SMC_UNKNOWN;
}
if (res.ret0 == RSI_ERROR_STATE) {
return RSI_ERROR_STATE;
}
/* Return lower version */
return res.ret1;
}
/* This function returns RSI feature register at 'feature_reg_index' */
u_register_t rsi_features(u_register_t feature_reg_index,
u_register_t *feature_reg_value_ret)
{
smc_ret_values res = {};
res = tftf_smc(&(smc_args) {SMC_RSI_FEATURES, feature_reg_index,
0UL, 0UL, 0UL, 0UL, 0UL, 0UL});
/* This command always returns RSI_SUCCESS */
if (res.ret0 == RSI_SUCCESS) {
*feature_reg_value_ret = res.ret1;
}
return res.ret0;
}
/* This function call Host and request to exit Realm with proper exit code */
u_register_t rsi_exit_to_host(enum host_call_cmd exit_code)
{
struct rsi_host_call host_cal __aligned(sizeof(struct rsi_host_call));
smc_ret_values res = {};
host_cal.imm = exit_code;
host_cal.gprs[0] = realm_get_my_plane_num();
host_cal.gprs[1] = read_mpidr_el1();
res = tftf_smc(&(smc_args) {SMC_RSI_HOST_CALL, (u_register_t)&host_cal,
0UL, 0UL, 0UL, 0UL, 0UL, 0UL});
return res.ret0;
}
/* This function will exit to the Host to request RIPAS CHANGE of IPA range */
u_register_t rsi_ipa_state_set(u_register_t base,
u_register_t top,
rsi_ripas_type ripas,
u_register_t flag,
u_register_t *new_base,
rsi_response_type *response)
{
smc_ret_values res = {};
res = tftf_smc(&(smc_args)
{SMC_RSI_IPA_STATE_SET, base, top, ripas, flag});
if (res.ret0 == RSI_SUCCESS) {
*new_base = res.ret1;
*response = res.ret2;
}
return res.ret0;
}
/* This function will return RIPAS of IPA range */
u_register_t rsi_ipa_state_get(u_register_t base,
u_register_t top,
u_register_t *out_top,
rsi_ripas_type *ripas)
{
smc_ret_values res = {};
res = tftf_smc(&(smc_args)
{SMC_RSI_IPA_STATE_GET, base, top});
if (res.ret0 == RSI_SUCCESS) {
*out_top = res.ret1;
*ripas = res.ret2;
}
return res.ret0;
}
/* This function will initialize the attestation context */
u_register_t rsi_attest_token_init(u_register_t challenge_0,
u_register_t challenge_1,
u_register_t challenge_2,
u_register_t challenge_3,
u_register_t challenge_4,
u_register_t challenge_5,
u_register_t challenge_6,
u_register_t challenge_7,
u_register_t *out_token_upper_bound)
{
smc_ret_values_ext res = {};
tftf_smc_no_retval_x8(&(smc_args_ext) {
SMC_RSI_ATTEST_TOKEN_INIT,
challenge_0,
challenge_1,
challenge_2,
challenge_3,
challenge_4,
challenge_5,
challenge_6,
challenge_7
},
&res);
if (res.ret0 == RSI_SUCCESS) {
*out_token_upper_bound = res.ret1;
}
return res.ret0;
}
/* This function will retrieve the (or part of) attestation token */
u_register_t rsi_attest_token_continue(u_register_t buffer_addr,
u_register_t offset,
u_register_t buffer_size,
u_register_t *bytes_copied)
{
smc_ret_values res = {};
res = tftf_smc(&(smc_args) {
SMC_RSI_ATTEST_TOKEN_CONTINUE,
buffer_addr,
offset,
buffer_size
});
if ((res.ret0 == RSI_SUCCESS) || (res.ret0 == RSI_INCOMPLETE)) {
*bytes_copied = res.ret1;
}
return res.ret0;
}
u_register_t rsi_realm_config(struct rsi_realm_config *s)
{
smc_ret_values res = {};
res = tftf_smc(&(smc_args)
{SMC_RSI_REALM_CONFIG, (u_register_t)s});
return res.ret0;
}
u_register_t rsi_mem_get_perm_value(u_register_t plane_index,
u_register_t perm_index,
u_register_t *perm)
{
smc_ret_values res = {};
res = tftf_smc(&(smc_args)
{SMC_RSI_MEM_GET_PERM_VALUE, plane_index, perm_index});
if (res.ret0 == RSI_SUCCESS) {
*perm = res.ret1;
}
return res.ret0;
}
u_register_t rsi_mem_set_perm_value(u_register_t plane_index,
u_register_t perm_index,
u_register_t perm)
{
smc_ret_values res = {};
res = tftf_smc(&(smc_args)
{SMC_RSI_MEM_SET_PERM_VALUE, plane_index, perm_index,
perm});
return res.ret0;
}
u_register_t rsi_mem_set_perm_index(u_register_t base,
u_register_t top,
u_register_t perm_index,
u_register_t cookie,
u_register_t *new_base,
u_register_t *response,
u_register_t *new_cookie)
{
smc_ret_values res = {};
res = tftf_smc(&(smc_args)
{SMC_RSI_MEM_SET_PERM_INDEX, base, top, perm_index,
cookie});
if (res.ret0 == RSI_SUCCESS) {
*new_base = res.ret1;
*response = res.ret2;
*new_cookie = res.ret3;
}
return res.ret0;
}
u_register_t rsi_plane_enter(u_register_t plane_index,
u_register_t plane_run)
{
smc_ret_values res = {};
res = tftf_smc(&(smc_args)
{SMC_RSI_PLANE_ENTER, plane_index, plane_run});
return res.ret0;
}
u_register_t rsi_plane_reg_read(u_register_t plane_index,
u_register_t register_encoding,
u_register_t *value)
{
smc_ret_values res = {};
res = tftf_smc(&(smc_args)
{SMC_RSI_PLANE_REG_READ, plane_index,
register_encoding});
if (res.ret0 == RSI_SUCCESS) {
*value = res.ret1;
}
return res.ret0;
}
u_register_t rsi_plane_reg_write(u_register_t plane_index,
u_register_t register_encoding,
u_register_t value)
{
smc_ret_values res = {};
res = tftf_smc(&(smc_args)
{SMC_RSI_PLANE_REG_WRITE, plane_index,
register_encoding, value});
return res.ret0;
}
/* This function return instance ID of Realm device */
u_register_t rsi_rdev_get_instance_id(u_register_t rdev_id,
u_register_t *rdev_inst_id)
{
smc_ret_values res = {};
res = tftf_smc(&(smc_args)
{SMC_RSI_RDEV_GET_INSTANCE_ID, rdev_id, 0UL, 0UL, 0UL, 0UL,
0UL, 0UL});
if (res.ret0 == RSI_SUCCESS) {
*rdev_inst_id = res.ret1;
}
return res.ret0;
}
/* This function return state of the Realm device */
u_register_t rsi_rdev_get_state(u_register_t rdev_id, u_register_t rdev_inst_id,
u_register_t *rdev_rsi_state)
{
smc_ret_values res = {};
res = tftf_smc(&(smc_args)
{SMC_RSI_RDEV_GET_STATE, rdev_id, rdev_inst_id, 0UL, 0UL, 0UL,
0UL, 0UL});
if (res.ret0 == RSI_SUCCESS) {
*rdev_rsi_state = res.ret1;
}
return res.ret0;
}
/* This function triggers RDEV interruptible operation to get_measurements */
u_register_t rsi_rdev_get_measurements(u_register_t rdev_id,
u_register_t rdev_inst_id,
u_register_t meas_params_ptr)
{
smc_ret_values res = {};
res = tftf_smc(&(smc_args)
{SMC_RSI_RDEV_GET_MEASUREMENTS, rdev_id, rdev_inst_id,
meas_params_ptr, 0UL, 0UL, 0UL, 0UL});
return res.ret0;
}
/* This function triggers RDEV interruptible operation to get_measurements */
u_register_t rsi_rdev_get_info(u_register_t rdev_id, u_register_t rdev_inst_id,
u_register_t rdev_info_ptr)
{
smc_ret_values res = {};
res = tftf_smc(&(smc_args)
{SMC_RSI_RDEV_GET_INFO, rdev_id, rdev_inst_id,
rdev_info_ptr, 0UL, 0UL, 0UL, 0UL});
return res.ret0;
}
/* This function triggers RDEV interruptible operation to lock */
u_register_t rsi_rdev_lock(u_register_t rdev_id, u_register_t rdev_inst_id)
{
smc_ret_values res = {};
res = tftf_smc(&(smc_args)
{SMC_RSI_RDEV_LOCK, rdev_id, rdev_inst_id,
0UL, 0UL, 0UL, 0UL, 0UL});
return res.ret0;
}
/* This function triggers RDEV interruptible operation to get interface report */
u_register_t rsi_rdev_get_interface_report(u_register_t rdev_id,
u_register_t rdev_inst_id,
u_register_t tdisp_version_max)
{
smc_ret_values res = {};
res = tftf_smc(&(smc_args)
{SMC_RSI_RDEV_GET_INTERFACE_REPORT, rdev_id, rdev_inst_id,
tdisp_version_max, 0UL, 0UL, 0UL, 0UL});
return res.ret0;
}
/* This function triggers RDEV interruptible operation to start */
u_register_t rsi_rdev_start(u_register_t rdev_id, u_register_t rdev_inst_id)
{
smc_ret_values res = {};
res = tftf_smc(&(smc_args)
{SMC_RSI_RDEV_START, rdev_id, rdev_inst_id,
0UL, 0UL, 0UL, 0UL, 0UL});
return res.ret0;
}
/* This function triggers RDEV interruptible operation to stop the TDI */
u_register_t rsi_rdev_stop(u_register_t rdev_id, u_register_t rdev_inst_id)
{
smc_ret_values res = {};
res = tftf_smc(&(smc_args)
{SMC_RSI_RDEV_STOP, rdev_id, rdev_inst_id,
0UL, 0UL, 0UL, 0UL, 0UL});
return res.ret0;
}
/* This function exits the REC to do vdev communicate */
u_register_t rsi_rdev_continue(u_register_t rdev_id, u_register_t rdev_inst_id)
{
smc_ret_values res = {};
res = tftf_smc(&(smc_args)
{SMC_RSI_RDEV_CONTINUE, rdev_id, rdev_inst_id, 0UL, 0UL,
0UL, 0UL, 0UL});
return res.ret0;
}