[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v2 5/5] xen/arm: ffa: Enable VM to VM without firmware
Hi Jens, > On 21 Mar 2025, at 15:00, Jens Wiklander <jens.wiklander@xxxxxxxxxx> wrote: > > Hi Bertrand, > > On Fri, Mar 21, 2025 at 2:47 PM Bertrand Marquis > <Bertrand.Marquis@xxxxxxx> wrote: >> >> Hi Jens, >> >>> On 21 Mar 2025, at 11:09, Jens Wiklander <jens.wiklander@xxxxxxxxxx> wrote: >>> >>> Hi, >>> >>> On Fri, Mar 21, 2025 at 10:25 AM Bertrand Marquis >>> <Bertrand.Marquis@xxxxxxx> wrote: >>>> >>>> Hi Jens, >>>> >>>>> On 21 Mar 2025, at 09:55, Jens Wiklander <jens.wiklander@xxxxxxxxxx> >>>>> wrote: >>>>> >>>>> Hi Bertrand, >>>>> >>>>> On Mon, Mar 10, 2025 at 3:51 PM Bertrand Marquis >>>>> <bertrand.marquis@xxxxxxx> wrote: >>>>>> >>>>>> When VM to VM support is activated and there is no suitable FF-A support >>>>>> in the firmware, enable FF-A support for VMs to allow using it for VM to >>>>>> VM communications. >>>>>> If there is Optee running in the secure world and using the non FF-A >>>>> >>>>> It's spelled OP-TEE in text, and optee or OPTEE in identifiers. >>>> >>>> ack >>>> >>>>> >>>>>> communication system, having CONFIG_FFA_VM_TO_VM could be non functional >>>>>> (if optee is probed first) or Optee could be non functional (if FF-A is >>>>>> probed first) so it is not recommended to activate the configuration >>>>>> option for such systems. >>>>>> >>>>>> To make buffer full notification work between VMs when there is not >>>>> >>>>> s/not/no/ >>>> >>>> ack >>>> >>>>> >>>>>> firmware, rework the notification handling and modify the global flag to >>>>>> only be used as check for firmware notification support instead. >>>>>> >>>>>> Modify part_info_get to return the list of VMs when there is no firmware >>>>>> support. >>>>>> >>>>>> Signed-off-by: Bertrand Marquis <bertrand.marquis@xxxxxxx> >>>>>> --- >>>>>> Changes in v2: >>>>>> - replace ifdef with IS_ENABLED when possible >>>>>> --- >>>>>> xen/arch/arm/tee/ffa.c | 12 +++- >>>>>> xen/arch/arm/tee/ffa_notif.c | 114 ++++++++++++++++---------------- >>>>>> xen/arch/arm/tee/ffa_partinfo.c | 3 +- >>>>>> 3 files changed, 69 insertions(+), 60 deletions(-) >>>>>> >>>>>> diff --git a/xen/arch/arm/tee/ffa.c b/xen/arch/arm/tee/ffa.c >>>>>> index 3bbdd7168a6b..f6582d2e855a 100644 >>>>>> --- a/xen/arch/arm/tee/ffa.c >>>>>> +++ b/xen/arch/arm/tee/ffa.c >>>>>> @@ -324,8 +324,9 @@ static int ffa_domain_init(struct domain *d) >>>>>> struct ffa_ctx *ctx; >>>>>> int ret; >>>>>> >>>>>> - if ( !ffa_fw_version ) >>>>>> + if ( !IS_ENABLED(CONFIG_FFA_VM_TO_VM) && !ffa_fw_version ) >>>>>> return -ENODEV; >>>>>> + >>>>>> /* >>>>>> * We are using the domain_id + 1 as the FF-A ID for VMs as FF-A ID 0 >>>>>> is >>>>>> * reserved for the hypervisor and we only support secure endpoints >>>>>> using >>>>>> @@ -549,6 +550,15 @@ err_no_fw: >>>>>> bitmap_zero(ffa_fw_abi_supported, FFA_ABI_BITMAP_SIZE); >>>>>> printk(XENLOG_WARNING "ARM FF-A No firmware support\n"); >>>>>> >>>>>> + if ( IS_ENABLED(CONFIG_FFA_VM_TO_VM) ) >>>>>> + { >>>>>> + INIT_LIST_HEAD(&ffa_teardown_head); >>>>>> + init_timer(&ffa_teardown_timer, ffa_teardown_timer_callback, >>>>>> NULL, 0); >>>>>> + >>>>>> + printk(XENLOG_INFO "ARM FF-A only available between VMs\n"); >>>>>> + return true; >>>>>> + } >>>>>> + >>>>>> return false; >>>>>> } >>>>>> >>>>>> diff --git a/xen/arch/arm/tee/ffa_notif.c b/xen/arch/arm/tee/ffa_notif.c >>>>>> index d19aa5c5bef6..0673e53a9def 100644 >>>>>> --- a/xen/arch/arm/tee/ffa_notif.c >>>>>> +++ b/xen/arch/arm/tee/ffa_notif.c >>>>>> @@ -16,7 +16,7 @@ >>>>>> >>>>>> #include "ffa_private.h" >>>>>> >>>>>> -static bool __ro_after_init notif_enabled; >>>>>> +static bool __ro_after_init fw_notif_enabled; >>>>>> static unsigned int __ro_after_init notif_sri_irq; >>>>>> >>>>>> int ffa_handle_notification_bind(struct cpu_user_regs *regs) >>>>>> @@ -27,21 +27,17 @@ int ffa_handle_notification_bind(struct >>>>>> cpu_user_regs *regs) >>>>>> uint32_t bitmap_lo = get_user_reg(regs, 3); >>>>>> uint32_t bitmap_hi = get_user_reg(regs, 4); >>>>>> >>>>>> - if ( !notif_enabled ) >>>>>> - return FFA_RET_NOT_SUPPORTED; >>>>>> - >>>>>> if ( (src_dst & 0xFFFFU) != ffa_get_vm_id(d) ) >>>>>> return FFA_RET_INVALID_PARAMETERS; >>>>>> >>>>>> if ( flags ) /* Only global notifications are supported */ >>>>>> return FFA_RET_DENIED; >>>>>> >>>>>> - /* >>>>>> - * We only support notifications from SP so no need to check the >>>>>> sender >>>>>> - * endpoint ID, the SPMC will take care of that for us. >>>>>> - */ >>>>>> - return ffa_simple_call(FFA_NOTIFICATION_BIND, src_dst, flags, >>>>>> bitmap_lo, >>>>>> - bitmap_hi); >>>>>> + if ( FFA_ID_IS_SECURE(src_dst>>16) && fw_notif_enabled ) >>>>> >>>>> Please add space before and after '>>', here and in the function below >>>>> in this patch. >>>> >>>> ack >>>> >>>>> >>>>>> + return ffa_simple_call(FFA_NOTIFICATION_BIND, src_dst, flags, >>>>>> + bitmap_lo, bitmap_hi); >>>>>> + >>>>>> + return FFA_RET_NOT_SUPPORTED; >>>>>> } >>>>>> >>>>>> int ffa_handle_notification_unbind(struct cpu_user_regs *regs) >>>>>> @@ -51,32 +47,34 @@ int ffa_handle_notification_unbind(struct >>>>>> cpu_user_regs *regs) >>>>>> uint32_t bitmap_lo = get_user_reg(regs, 3); >>>>>> uint32_t bitmap_hi = get_user_reg(regs, 4); >>>>>> >>>>>> - if ( !notif_enabled ) >>>>>> - return FFA_RET_NOT_SUPPORTED; >>>>>> - >>>>>> if ( (src_dst & 0xFFFFU) != ffa_get_vm_id(d) ) >>>>>> return FFA_RET_INVALID_PARAMETERS; >>>>>> >>>>>> - /* >>>>>> - * We only support notifications from SP so no need to check the >>>>>> - * destination endpoint ID, the SPMC will take care of that for us. >>>>>> - */ >>>>>> - return ffa_simple_call(FFA_NOTIFICATION_UNBIND, src_dst, 0, >>>>>> bitmap_lo, >>>>>> - bitmap_hi); >>>>>> + if ( FFA_ID_IS_SECURE(src_dst>>16) && fw_notif_enabled ) >>>>>> + return ffa_simple_call(FFA_NOTIFICATION_UNBIND, src_dst, 0, >>>>>> bitmap_lo, >>>>>> + bitmap_hi); >>>>>> + >>>>>> + return FFA_RET_NOT_SUPPORTED; >>>>>> } >>>>>> >>>>>> void ffa_handle_notification_info_get(struct cpu_user_regs *regs) >>>>>> { >>>>>> struct domain *d = current->domain; >>>>>> struct ffa_ctx *ctx = d->arch.tee; >>>>>> + bool notif_pending = false; >>>>>> >>>>>> - if ( !notif_enabled ) >>>>>> + if ( !IS_ENABLED(CONFIG_FFA_VM_TO_VM) && !fw_notif_enabled ) >>>>>> { >>>>>> ffa_set_regs_error(regs, FFA_RET_NOT_SUPPORTED); >>>>>> return; >>>>>> } >>>>>> >>>>>> - if ( test_and_clear_bool(ctx->notif.secure_pending) ) >>>>>> + notif_pending = ctx->notif.secure_pending; >>>>>> +#ifdef CONFIG_FFA_VM_TO_VM >>>>>> + notif_pending |= ctx->notif.buff_full_pending; >>>>>> +#endif >>>>> >>>>> Shouldn't ctx->notif.secure_pending and ctx->notif.secure_pending be >>>>> cleared also, like: >>>>> notif_pending = test_and_clear_bool(ctx->notif.secure_pending) || >>>>> test_and_clear_bool(ctx->notif.buff_full_pending); >>>> >>>> Notification info get is returning who has pending notification but only >>>> notification get should erase pending notifications. >>> >>> FFA_NOTIFICATION_INFO_GET can return a "More pending notifications >>> flag" in w2/x2 to inform the caller that it should call >>> FFA_NOTIFICATION_INFO_GET again to get the remaining receiver >>> endpoints. How can the ABI know where to resume the next time if the >>> previous pending receivers aren't cleared? >> >> I just checked the specification and you are right. >> It is explicitly saying that "Information about pending notifications is >> returned only once". >> >>> >>> The more pending notifications flag will not be needed here as we're >>> dealing with a single endpoint at a time so it might be more of a >>> philosophical question. I don't think it causes problems for the guest >>> to keep secure_pending unchanged for FFA_NOTIFICATION_INFO_GET, but we >>> should mention the changed behaviour in the commit message. >>> >> >> I agree I should discard the secure_pending flag in the implementation but >> I need to find a solution for the buffer full notification as I still need >> to signal >> it in notification get even if notification info get was called. >> >> I will do the following: >> - change secure_pending into pending_notif. >> - set pending_notif when current secure_pending is set >> - set pending_notif and buff_full_pending on indirect message >> - clean pending_notif in notif_info_get >> - clean pending_notif and buff_full in notif_get >> >> Do you agree this is the right path ? > > Yes, this is the way. :-) Well in fact there is a mistake in this way and I had to do something a bit different. When we have a notification get, we can only clear secure_pending if FFA_NOTIF_FLAG_BITMAP_SP(M) are passed. So i think i have to do the following: - secure_pending: set and clean as they are now - vm_pending: set when raising buf full and clean in info_get or get with FFA_NOTIF_FLAG_BITMAP_HYP set - buff_full_pending only cleaned in get with FFA_NOTIF_FLAG_BITMAP_HYP set This way info_get would still return something if a get is done but with only flags to retrieve secure and there is a buff full notif pending or with only HYP and secure ones pending. Giving something like that: --- a/xen/arch/arm/tee/ffa_notif.c +++ b/xen/arch/arm/tee/ffa_notif.c @@ -69,6 +69,7 @@ void ffa_handle_notification_info_get(struct cpu_user_regs *regs) { struct domain *d = current->domain; struct ffa_ctx *ctx = d->arch.tee; + bool notif_pending; if ( !notif_enabled ) { @@ -76,7 +77,11 @@ void ffa_handle_notification_info_get(struct cpu_user_regs *regs) return; } - if ( test_and_clear_bool(ctx->notif.secure_pending) ) + notif_pending = test_and_clear_bool(ctx->notif.secure_pending); + if ( IS_ENABLED(CONFIG_FFA_VM_TO_VM) ) + notif_pending |= test_and_clear_bool(ctx->notif.vm_pending) + + if ( notif_pending ) { /* A pending global notification for the guest */ ffa_set_regs(regs, FFA_SUCCESS_64, 0, @@ -153,11 +158,13 @@ void ffa_handle_notification_get(struct cpu_user_regs *regs) w6 = resp.a6; } -#ifdef CONFIG_FFA_VM_TO_VM - if ( flags & FFA_NOTIF_FLAG_BITMAP_HYP && + if ( IS_ENABLED(CONFIG_FFA_VM_TO_VM) && + flags & FFA_NOTIF_FLAG_BITMAP_HYP && test_and_clear_bool(ctx->notif.buff_full_pending) ) + { + ACCESS_ONCE(ctx->notif.vm_pending) = false; w7 = FFA_NOTIF_RX_BUFFER_FULL; -#endif + } ffa_set_regs(regs, FFA_SUCCESS_32, 0, w2, w3, w4, w5, w6, w7); } @@ -189,7 +196,8 @@ void ffa_raise_rx_buffer_full(struct domain *d) if ( !ctx ) return; - if ( !test_and_set_bool(ctx->notif.buff_full_pending) ) + ACCESS_ONCE(ctx->notif.buff_full_pending) = true + if ( !test_and_set_bool(ctx->notif.vm_pending) ) vgic_inject_irq(d, d->vcpu[0], notif_sri_irq, true); } Cheers Bertrand
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |