From: Gavin Shan <gshan@redhat.com>
To: Suzuki K Poulose <suzuki.poulose@arm.com>,
kvm@vger.kernel.org, kvmarm@lists.linux.dev
Cc: maz@kernel.org, will@kernel.org, catalin.marinas@arm.com,
linux-kernel@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, steven.price@arm.com,
aneesh.kumar@kernel.org, oupton@kernel.org, joey.gouly@arm.com,
tabba@google.com, yuzenghui@huawei.com,
linux-coco@lists.linux.dev, gankulkarni@os.amperecomputing.com,
sdonthineni@nvidia.com, alpergun@google.com,
fj0570is@fujitsu.com, WeiLin.Chang@arm.com,
lpieralisi@kernel.org, enju.kohei@fujitsu.com
Subject: Re: [PATCH v17 7/7] firmware: arm_rmm: Add wrappers for Realm related RMI commands
Date: Wed, 9 Sep 2026 17:15:56 +1000 [thread overview]
Message-ID: <de7e2d98-2faa-4e16-8164-d7247d31dbd5@redhat.com> (raw)
In-Reply-To: <20260907095942.1140734-8-suzuki.poulose@arm.com>
On 9/7/26 7:59 PM, Suzuki K Poulose wrote:
> From: Steven Price <steven.price@arm.com>
>
> Introduce wrappers for the RMI functions needed for creating and
> managing realm guests. This will be used by the KVM to manage the
> Realms
>
> Signed-off-by: Steven Price <steven.price@arm.com>
> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
> ---
> Changes since v16:
> * Split into a separate patch and move away from arch/arm64 to
> include/linux/.
> * Also moved into the firmware_rmm series from the KVM CCA support.
> This is done in a hope to reduce the merge conflicts and make
> the KVM CCA upstreaming in independent parallel chunks
> ---
> include/linux/arm-rmi-cmds.h | 453 +++++++++++++++++++++++++++++++++++
> 1 file changed, 453 insertions(+)
>
> diff --git a/include/linux/arm-rmi-cmds.h b/include/linux/arm-rmi-cmds.h
> index 79e2c1f165112..746257d77dd61 100644
> --- a/include/linux/arm-rmi-cmds.h
> +++ b/include/linux/arm-rmi-cmds.h
> @@ -222,4 +222,457 @@ static inline long rmi_granule_range_undelegate(unsigned long base,
> return ret;
> }
>
> +/**
> + * rmi_rtt_data_map_init() - Create a protected mapping with data contents
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
s/Create a protected mapping with data contents/Create a mappings in protected IPA with known contents
With this, it's consistently counterpart of the comments for rmi_rtt_data_map().
> + * @rd: PA of the RD
> + * @data: PA of the target granule
> + * @ipa: IPA at which the granule will be mapped in the guest
> + * @src: PA of the source granule
> + * @flags: RMI_MEASURE_CONTENT if the contents should be measured
> + *
> + * Create a mapping from Protected IPA space to conventional memory, copying
> + * contents from a Non-secure Granule provided by the caller.
> + *
> + * Return: 0 on success, positive RMI result code or negative Linux error code
> + */
> +static inline long rmi_rtt_data_map_init(unsigned long rd, unsigned long data,
> + unsigned long ipa, unsigned long src,
> + unsigned long flags)
> +{
> + struct arm_smccc_1_2_regs regs = {
> + SMC_RMI_RTT_DATA_MAP_INIT, rd, data, ipa, src, flags
> + };
> +
> + return rmi_sro_execute(®s);
> +}
> +
> +/**
> + * rmi_rtt_data_map() - Create mappings in protected IPA with unknown contents
> + * @rd: PA of the RD
> + * @base: Base of the target IPA range
> + * @top: Top of the target IPA range
> + * @flags: Flags
> + * @oaddr: Output address set descriptor
> + * @out_top: Top address of range which was processed.
> + *
> + * Return: 0 on success, positive RMI result code or negative Linux error code
> + */
> +static inline long rmi_rtt_data_map(unsigned long rd,
> + unsigned long base,
> + unsigned long top,
> + unsigned long flags,
> + unsigned long oaddr,
> + unsigned long *out_top)
> +{
> + struct arm_smccc_1_2_regs regs = {
> + SMC_RMI_RTT_DATA_MAP, rd, base, top, flags, oaddr
> + };
> + long ret;
> +
> + ret = rmi_sro_execute(®s);
> +
> + if (ret == RMI_SUCCESS && out_top)
> + *out_top = regs.a1;
> +
> + return ret;
> +}
> +
> +/**
> + * rmi_rtt_data_unmap() - Remove mappings to conventional memory
> + * @rd: PA of the RD for the target Realm
> + * @base: Base of the target IPA range
> + * @top: Top of the target IPA range
> + * @flags: Flags
> + * @oaddr: Output address set descriptor
> + * @out_top: Returns top IPA of range which has been unmapped
> + * @out_range: Output address range
> + * @out_count: Number of entries in output address list
> + *
> + * Removes mappings to convention memory with a target Protected IPA range.
> + *
> + * Return: 0 on success, positive RMI result code or negative Linux error code
> + */
It would be worthwhile to mention 'in protect IPA' where the mappings are
teared down. Besides, 'for the target Realm' can be dropped from the comments
for @rd.
/**
* rmi_rtt_data_unmap() - Remove mappings to conventional memory in protected IPA
* @rd: PA of the RD
* :
*/
> +static inline long rmi_rtt_data_unmap(unsigned long rd,
> + unsigned long base,
> + unsigned long top,
> + unsigned long flags,
> + unsigned long oaddr,
> + unsigned long *out_top,
> + unsigned long *out_range,
> + unsigned long *out_count)
> +{
> + struct arm_smccc_1_2_regs regs = {
> + SMC_RMI_RTT_DATA_UNMAP, rd, base, top, flags, oaddr
> + };
> + long ret;
> +
> + ret = rmi_sro_execute(®s);
> +
> + if (ret == RMI_SUCCESS) {
> + if (out_top)
> + *out_top = regs.a1;
> + if (out_range)
> + *out_range = regs.a2;
> + if (out_count)
> + *out_count = regs.a3;
> + }
> +
> + return ret;
> +}
The nested if statements can be avoided if we have:
if (ret != RMI_SUCCESS)
return ret;
if (out_top)
*out_top = regs.a1;
if (out_range)
*out_range = regs.a2;
if (out_count)
*out_count = regs.a3;
return RMI_SUCCESS;
> +
> +/**
> + * rmi_psci_complete() - Complete pending PSCI command
> + * @calling_rec: PA of the calling REC
> + * @status: Status of the PSCI request
> + *
> + * Completes a pending PSCI command.
> + *
> + * Return: RMI return code
> + */
> +static inline long rmi_psci_complete(unsigned long calling_rec,
> + unsigned long status)
> +{
> + struct arm_smccc_res res;
> +
> + arm_smccc_1_1_invoke(SMC_RMI_PSCI_COMPLETE, calling_rec, status, &res);
> +
> + return res.a0;
> +}
> +
> +/**
> + * rmi_realm_activate() - Active a realm
> + * @rd: PA of the RD
> + *
> + * Mark a realm as Active signalling that creation is complete and allowing
^^^^^^^^
s/complete/completed ?
> + * execution of the realm.
> + *
> + * Return: RMI return code
> + */
> +static inline long rmi_realm_activate(unsigned long rd)
> +{
> + struct arm_smccc_res res;
> +
> + arm_smccc_1_1_invoke(SMC_RMI_REALM_ACTIVATE, rd, &res);
> +
> + return res.a0;
> +}
> +
> +/**
> + * rmi_realm_create() - Create a realm
> + * @rd: PA of the RD
> + * @params: PA of realm parameters
> + * @sro: Preallocated SRO context to be used
We needn't to have 'to be used. This comment applies to other helpers
like rmi_realm_terminate(), rmi_realm_destroy(), rmi_rec_create(),
rmi_rec_destroy() where a preallocated SRO context is needed.
* @sro: Preallocated SRO context
> + *
> + * Create a new realm using the given parameters.
> + *
> + * Return: 0 on success, positive RMI result code or negative Linux error code
> + */
> +static inline long rmi_realm_create(unsigned long rd, unsigned long params,
> + struct rmi_sro_state *sro)
> +{
> + return rmi_sro_memxfer_cmd(sro, GFP_KERNEL,
> + SMC_RMI_REALM_CREATE, rd, params);
> +}
> +
> +/**
> + * rmi_realm_terminate() - Terminate a realm
> + * @rd: PA of the RD
> + * @sro: Preallocated SRO context to be used
> + *
> + * Terminates a realm, moving it into a ZOMBIE state
> + *
> + * Return: 0 on success, positive RMI result code or negative Linux error code
> + */
> +static inline long rmi_realm_terminate(unsigned long rd,
> + struct rmi_sro_state *sro)
> +{
> + return rmi_sro_memxfer_cmd(sro, GFP_KERNEL,
> + SMC_RMI_REALM_TERMINATE, rd);
> +}
> +
> +/**
> + * rmi_realm_destroy() - Destroy a realm
> + * @rd: PA of the RD
> + * @sro: Preallocated SRO context to be used
> + *
> + * Destroys a realm, all objects belonging to the realm must be destroyed first.
> + *
> + * Return: 0 on success, positive RMI result code or negative Linux error code
> + */
> +static inline long rmi_realm_destroy(unsigned long rd,
> + struct rmi_sro_state *sro)
> +{
> + return rmi_sro_memxfer_cmd(sro, GFP_KERNEL,
> + SMC_RMI_REALM_DESTROY, rd);
> +}
> +
> +/**
> + * rmi_rec_create() - Create a REC
> + * @rd: PA of the RD
> + * @rec: PA of the target REC
> + * @params: PA of REC parameters
> + * @sro: Allocated SRO context to be used
* @sro: Preallocated SRO context
> + *
> + * Create a REC using the parameters specified in the struct rec_params pointed
> + * to by @params.
> + *
> + * Return: 0 on success, positive RMI result code or negative Linux error code
> + */
> +static inline long rmi_rec_create(unsigned long rd,
> + unsigned long rec,
> + unsigned long params,
> + struct rmi_sro_state *sro)
> +{
> + long ret;
> +
> + *sro = (struct rmi_sro_state){.regs = {
> + SMC_RMI_REC_CREATE, rd, rec, params
> + }};
> + ret = rmi_sro_memxfer_execute(sro, GFP_KERNEL);
> + rmi_sro_free(sro);
> +
> + return ret;
> +}
> +
> +/**
> + * rmi_rec_destroy() - Destroy a REC
> + * @rec: PA of the target REC
> + * @sro: Allocated SRO context to be used
* @sro: Preallocated SRO context
> + *
> + * Destroys a REC. The REC must not be running.
> + *
> + * Return: 0 on success, positive RMI result code or negative Linux error code
> + */
> +static inline long rmi_rec_destroy(unsigned long rec,
> + struct rmi_sro_state *sro)
> +{
> + return rmi_sro_memxfer_cmd(sro, GFP_KERNEL, SMC_RMI_REC_DESTROY, rec);
> +}
> +
> +/**
> + * rmi_rec_enter() - Enter a REC
> + * @rec: PA of the target REC
> + * @run_ptr: PA of RecRun structure
> + *
> + * Starts (or continues) execution within a REC.
> + *
> + * Return: RMI return code
> + */
> +static inline long rmi_rec_enter(unsigned long rec, unsigned long run_ptr)
> +{
> + struct arm_smccc_res res;
> +
> + arm_smccc_1_1_invoke(SMC_RMI_REC_ENTER, rec, run_ptr, &res);
> +
> + return res.a0;
> +}
> +
> +/**
> + * rmi_rtt_create() - Creates an RTT
> + * @rd: PA of the RD
> + * @rtt: PA of the target RTT
> + * @ipa: Base of the IPA range described by the RTT
> + * @level: Depth of the RTT within the tree
> + *
> + * Creates an RTT (Realm Translation Table) at the specified level for the
> + * translation of the specified address within the realm.
> + *
> + * Return: 0 on success, positive RMI result code or negative Linux error code
> + */
> +static inline long rmi_rtt_create(unsigned long rd, unsigned long rtt,
> + unsigned long ipa, long level)
> +{
> + struct arm_smccc_1_2_regs regs = {
> + SMC_RMI_RTT_CREATE, rd, rtt, ipa, level
> + };
> +
> + return rmi_sro_execute(®s);
> +}
> +
> +/**
> + * rmi_rtt_destroy() - Destroy an RTT
> + * @rd: PA of the RD for the target realm
* @rd: PA of the RD
> + * @ipa: Base of the IPA range described by the RTT
> + * @level: RTT level
> + * @out_rtt: Pointer to write the PA of the RTT which was destroyed
> + * @out_top: Pointer to write the top IPA of non-live RTT entries, from entry
> + * at which the RTT walk terminated.
> + *
> + * Destroys an RTT. The RTT must be non-live, i.e. none of the entries in the
> + * table are in ASSIGNED or TABLE state.
> + *
> + * Return: 0 on success, positive RMI result code or negative Linux error code.
> + */
> +static inline long rmi_rtt_destroy(unsigned long rd,
> + unsigned long ipa,
> + long level,
> + unsigned long *out_rtt,
> + unsigned long *out_top)
> +{
> + struct arm_smccc_1_2_regs regs = {
> + SMC_RMI_RTT_DESTROY, rd, ipa, level
> + };
> + long ret = rmi_sro_execute(®s);
> +
> + if (ret == RMI_SUCCESS) {
> + if (out_rtt)
> + *out_rtt = regs.a1;
> + if (out_top)
> + *out_top = regs.a2;
> + }
> +
> + return ret;
> +}
> +
The nested if statements can be avoided if we have:
if (ret != RMI_SUCCESS)
return ret;
if (out_rtt)
*out_rtt = regs.a1;
if (out_top)
*out_top = regs.a2;
return RMI_SUCCESS;
> +/**
> + * rmi_rtt_fold() - Fold an RTT
> + * @rd: PA of the RD
> + * @ipa: Base of the IPA range described by the RTT
> + * @level: Depth of the RTT within the tree
> + * @out_rtt: Pointer to write the PA of the RTT which was destroyed
> + *
> + * Folds an RTT. If all entries with the RTT are 'homogeneous' the RTT can be
> + * folded into the parent and the RTT destroyed.
> + *
> + * Return: 0 on success, positive RMI result code or negative Linux error code
> + */
> +static inline long rmi_rtt_fold(unsigned long rd, unsigned long ipa,
> + long level, unsigned long *out_rtt)
> +{
> + struct arm_smccc_1_2_regs regs = {
> + SMC_RMI_RTT_FOLD, rd, ipa, level
> + };
> + long ret = rmi_sro_execute(®s);
> +
> + if (ret == RMI_SUCCESS && out_rtt)
> + *out_rtt = regs.a1;
> +
> + return ret;
> +}
> +
> +/**
> + * rmi_rtt_init_ripas() - Set RIPAS for new realm
> + * @rd: PA of the RD
> + * @base: Base of target IPA region
> + * @top: Top of target IPA region
> + * @out_top: Top IPA of range whose RIPAS was modified
> + *
> + * Sets the RIPAS of a target IPA range to RAM, for a realm in the NEW state.
> + *
> + * Return: 0 on success, positive RMI result code or negative Linux error code
> + */
> +static inline long rmi_rtt_init_ripas(unsigned long rd, unsigned long base,
> + unsigned long top, unsigned long *out_top)
> +{
> + struct arm_smccc_1_2_regs regs = {
> + SMC_RMI_RTT_INIT_RIPAS, rd, base, top
> + };
> + long ret = rmi_sro_execute(®s);
> +
> + if (ret == RMI_SUCCESS && out_top)
> + *out_top = regs.a1;
> +
> + return ret;
> +}
> +
> +/**
> + * rmi_rtt_unprot_map() - Map unprotected granules into a realm
> + * @rd: PA of the RD
> + * @base: Base IPA of the mapping
> + * @top: Top of the target IPA range
> + * @flags: Flags
> + * @oaddr: Output address set descriptor
> + * @out_top: Top IPA of range which has been mapped
> + *
> + * Create mappings to memory within a target unprotected IPA range.
> + *
> + * Return: 0 on success, positive RMI result code or negative Linux error code
> + */
> +static inline long rmi_rtt_unprot_map(unsigned long rd,
> + unsigned long base,
> + unsigned long top,
> + unsigned long flags,
> + unsigned long oaddr,
> + unsigned long *out_top)
> +{
> + struct arm_smccc_1_2_regs regs = {
> + SMC_RMI_RTT_UNPROT_MAP, rd, base, top, flags, oaddr
> + };
> + long ret = rmi_sro_execute(®s);
> +
> + if (ret == RMI_SUCCESS && out_top)
> + *out_top = regs.a1;
> +
> + return ret;
> +}
> +
> +/**
> + * rmi_rtt_set_ripas() - Set RIPAS for an running realm
> + * @rd: PA of the RD
> + * @rec: PA of the REC making the request
> + * @base: Base of target IPA region
> + * @top: Top of target IPA region
> + * @out_top: Pointer to write top IPA of range whose RIPAS was modified
> + *
> + * Completes a request made by the realm to change the RIPAS of a target IPA
> + * range.
> + *
> + * Return: 0 on success, positive RMI result code or negative Linux error code
> + */
> +static inline long rmi_rtt_set_ripas(unsigned long rd, unsigned long rec,
> + unsigned long base, unsigned long top,
> + unsigned long *out_top)
> +{
> + struct arm_smccc_1_2_regs regs = {
> + SMC_RMI_RTT_SET_RIPAS, rd, rec, base, top
> + };
> + long ret = rmi_sro_execute(®s);
> +
> + if (ret == RMI_SUCCESS && out_top)
> + *out_top = regs.a1;
> +
> + return ret;
> +}
> +
> +/**
> + * rmi_rtt_unprot_unmap() - Remove mappings within an unprotected IPA range
> + * @rd: PA of the RD
> + * @base: Base IPA of the mapping
> + * @top: Top of the target IPA range
> + * @flags: Flags
> + * @oaddr: Output address set descriptor
> + * @out_top: Top IPA which has been unmapped
> + * @out_range: Output address range
> + * @out_count: Number of entries in output address list
> + *
> + * Removes mappings to memory within a target unprotected IPA range.
> + *
> + * Return: 0 on success, positive RMI result code or negative Linux error code
> + */
> +static inline long rmi_rtt_unprot_unmap(unsigned long rd,
> + unsigned long base,
> + unsigned long top,
> + unsigned long flags,
> + unsigned long oaddr,
> + unsigned long *out_top,
> + unsigned long *out_range,
> + unsigned long *out_count)
> +{
> + struct arm_smccc_1_2_regs regs = {
> + SMC_RMI_RTT_UNPROT_UNMAP, rd, base, top, flags, oaddr
> + };
> + long ret = rmi_sro_execute(®s);
> +
> + if (ret == RMI_SUCCESS) {
> + if (out_top)
> + *out_top = regs.a1;
> + if (out_range)
> + *out_range = regs.a2;
> + if (out_count)
> + *out_count = regs.a3;
> + }
> +
> + return ret;
> +}
> +
The nested if statements can be avoided if we have:
if (ret != RMI_SUCCESS)
return ret;
if (out_top)
*out_top = regs.a1;
if (out_range)
*out_range = regs.a2;
if (out_count)
*out_count = regs.a3;
return RMI_SUCCESS;
> #endif
Thanks,
Gavin
next prev parent reply other threads:[~2026-09-09 7:16 UTC|newest]
Thread overview: 45+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-07 9:59 [PATCH v17 0/7] firmware: arm_rmm: Add RMM v2.0 base RMI support Suzuki K Poulose
2026-09-07 9:59 ` [PATCH v17 1/7] firmware: arm_rmm: Add SMC definitions for calling the RMM Suzuki K Poulose
2026-09-08 6:19 ` Gavin Shan
2026-09-08 10:37 ` Suzuki K Poulose
2026-09-08 22:41 ` Gavin Shan
2026-09-09 8:39 ` Suzuki K Poulose
2026-09-10 9:47 ` Gavin Shan
2026-09-10 9:54 ` Suzuki K Poulose
2026-09-07 9:59 ` [PATCH v17 2/7] firmware: arm_rmm: Check for RMI support at init Suzuki K Poulose
2026-09-08 6:46 ` Gavin Shan
2026-09-08 9:49 ` Suzuki K Poulose
2026-09-07 9:59 ` [PATCH v17 3/7] firmware: arm_rmm: Configure the RMM with the host's page size Suzuki K Poulose
2026-09-07 10:14 ` sashiko-bot
2026-09-07 12:02 ` Suzuki K Poulose
2026-09-07 22:40 ` Gavin Shan
2026-09-08 9:58 ` Suzuki K Poulose
2026-09-08 7:04 ` Gavin Shan
2026-09-08 8:00 ` Kohei Enju
2026-09-08 10:59 ` Gavin Shan
2026-09-09 2:01 ` Kohei Enju
2026-09-08 10:43 ` Suzuki K Poulose
2026-09-07 9:59 ` [PATCH v17 4/7] firmware: arm_rmm: Add support for SRO Suzuki K Poulose
2026-09-07 10:14 ` sashiko-bot
2026-09-08 22:10 ` Suzuki K Poulose
2026-09-09 4:10 ` Gavin Shan
2026-09-10 9:51 ` Suzuki K Poulose
2026-09-11 15:29 ` Suzuki K Poulose
2026-09-07 9:59 ` [PATCH v17 5/7] firmware: arm_rmm: Activate the RMM Suzuki K Poulose
2026-09-07 10:17 ` sashiko-bot
2026-09-07 16:16 ` Suzuki K Poulose
2026-09-09 4:29 ` Gavin Shan
2026-09-09 8:25 ` Suzuki K Poulose
2026-09-07 9:59 ` [PATCH v17 6/7] firmware: arm_rmm: Ensure the RMM has GPT entries for memory Suzuki K Poulose
2026-09-09 6:40 ` Gavin Shan
2026-09-09 8:33 ` Suzuki K Poulose
2026-09-07 9:59 ` [PATCH v17 7/7] firmware: arm_rmm: Add wrappers for Realm related RMI commands Suzuki K Poulose
2026-09-07 10:10 ` sashiko-bot
2026-09-07 12:20 ` Suzuki K Poulose
2026-09-09 7:15 ` Gavin Shan [this message]
2026-09-09 8:55 ` Suzuki K Poulose
2026-09-08 4:09 ` [PATCH v17 0/7] firmware: arm_rmm: Add RMM v2.0 base RMI support Kohei Enju
2026-09-08 5:46 ` Suzuki K Poulose
2026-09-08 7:30 ` Kohei Enju
2026-09-09 10:52 ` Gavin Shan
2026-09-10 4:51 ` Kohei Enju
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=de7e2d98-2faa-4e16-8164-d7247d31dbd5@redhat.com \
--to=gshan@redhat.com \
--cc=WeiLin.Chang@arm.com \
--cc=alpergun@google.com \
--cc=aneesh.kumar@kernel.org \
--cc=catalin.marinas@arm.com \
--cc=enju.kohei@fujitsu.com \
--cc=fj0570is@fujitsu.com \
--cc=gankulkarni@os.amperecomputing.com \
--cc=joey.gouly@arm.com \
--cc=kvm@vger.kernel.org \
--cc=kvmarm@lists.linux.dev \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-coco@lists.linux.dev \
--cc=linux-kernel@vger.kernel.org \
--cc=lpieralisi@kernel.org \
--cc=maz@kernel.org \
--cc=oupton@kernel.org \
--cc=sdonthineni@nvidia.com \
--cc=steven.price@arm.com \
--cc=suzuki.poulose@arm.com \
--cc=tabba@google.com \
--cc=will@kernel.org \
--cc=yuzenghui@huawei.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.