Re: [PATCH v9 15/43] arm64: RME: Allow VMM to set RIPAS
From: Steven Price
Date: Mon Jun 23 2025 - 10:50:06 EST
On 17/06/2025 13:56, zhuangyiwei wrote:
> Hi Steven
>
> On 2025/6/11 18:48, Steven Price wrote:
>> Each page within the protected region of the realm guest can be marked
>> as either RAM or EMPTY. Allow the VMM to control this before the guest
>> has started and provide the equivalent functions to change this (with
>> the guest's approval) at runtime.
>>
>> When transitioning from RIPAS RAM (1) to RIPAS EMPTY (0) the memory is
>> unmapped from the guest and undelegated allowing the memory to be reused
>> by the host. When transitioning to RIPAS RAM the actual population of
>> the leaf RTTs is done later on stage 2 fault, however it may be
>> necessary to allocate additional RTTs to allow the RMM track the RIPAS
>> for the requested range.
>>
>> When freeing a block mapping it is necessary to temporarily unfold the
>> RTT which requires delegating an extra page to the RMM, this page can
>> then be recovered once the contents of the block mapping have been
>> freed.
>>
>> Signed-off-by: Steven Price <steven.price@xxxxxxx>
>> ---
[...]
>> diff --git a/arch/arm64/kvm/rme.c b/arch/arm64/kvm/rme.c
>> index 25705da6f153..fe75c41d6ac3 100644
>> --- a/arch/arm64/kvm/rme.c
>> +++ b/arch/arm64/kvm/rme.c
[...]
>> @@ -126,6 +206,40 @@ static int realm_rtt_destroy(struct realm *realm,
>> unsigned long addr,
>> return ret;
>> }
>> +static int realm_create_rtt_levels(struct realm *realm,
>> + unsigned long ipa,
>> + int level,
>> + int max_level,
>> + struct kvm_mmu_memory_cache *mc)
>> +{
>> + if (level == max_level)
>> + return 0;
>> +
>> + while (level++ < max_level) {
>> + phys_addr_t rtt = alloc_rtt(mc);
>> + int ret;
>> +
>> + if (rtt == PHYS_ADDR_MAX)
>> + return -ENOMEM;
>> +
>> + ret = realm_rtt_create(realm, ipa, level, rtt);
>> +
>> + if (RMI_RETURN_STATUS(ret) == RMI_ERROR_RTT &&
>> + RMI_RETURN_INDEX(ret) == level - 1) {
>> + /* The RTT already exists, continue */
> Should rtt be freed and undelegated in this branch?
Indeed it should! There's a missing call to free_rtt(). Thanks for spotting.
>> + continue;
>> + }
>> + if (ret) {
>> + WARN(1, "Failed to create RTT at level %d: %d\n",
>> + level, ret);
>> + free_rtt(rtt);
>> + return -ENXIO;
>> + }
>> + }
>> +
>> + return 0;
>> +}
>> +
Thanks,
Steve