[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [RFC XEN PATCH] xen/arm: ffa: reclaim shared memory on guest destroy
Hi, On Tue, Dec 5, 2023 at 9:14 AM Bertrand Marquis <Bertrand.Marquis@xxxxxxx> wrote: > > Hi Julien, > > Thanks a lot for your review and comment, this is very helpful. > > > On 4 Dec 2023, at 20:24, Julien Grall <julien@xxxxxxx> wrote: > > > > Hi Jens, > > > > On 04/12/2023 07:55, Jens Wiklander wrote: > >> When an FF-A enabled guest is destroyed it may leave behind memory > >> shared with SPs. This memory must be reclaimed before it's reused or an > >> SP may make changes to memory used by a new unrelated guest. So when the > >> domain is teared down add FF-A requests to reclaim all remaining shared > >> memory. > >> SPs in the secure world are notified using VM_DESTROYED that a guest has > >> been destroyed. An SP is supposed to relinquish all shared memory to allow > >> reclaiming the memory. The relinquish operation may need to be delayed if > >> the shared memory is for instance part of a DMA operation. > >> If the FF-A memory reclaim request fails, return -ERESTART to retry > >> again. This will effectively block the destruction of the guest until > >> all memory has been reclaimed. > >> Signed-off-by: Jens Wiklander <jens.wiklander@xxxxxxxxxx> > >> --- > >> Hi, > >> This patch is a bit crude, but gets the job done. In a well designed > >> system this might even be good enough since the SP or the secure world > >> will let the memory be reclaimed and we can move on. But, if for some > >> reason reclaiming the memory is refused it must not be possible to reuse > >> the memory. > > > > IIUC, we are trying to harden against a buggy SP. Is that correct? > > This is not hardening as this is a possible scenario with a correctly > implemented SP. > This is valid for the SP to not be able to relinquish the memory directly so > we have > to take this possibility into account and retry. > > What is not expected if for the SP to never release the memory hence the > possible > "todo" at the end of the code where i think we might have to implement a > counter > to bound the possible number of loops but as always the question is how > many... > > In this case the only solution would be to park the memory as suggested after > but we are not completely sure where hence the RFC. > > > > >> These shared memory ranges are typically quite small compared to the > >> total memory usage of a guest so it would be an improvement if only > >> refused shared memory ranges where set aside from future reuse while the > >> guest was destroyed and other resources made available for reuse. This > >> could be done by for instance assign the refused shared memory ranges > >> to a dummy VM like DOMID_IO. > > > > I like the idea to use a dummy VM, but I don't think DOMID_IO is right. > > Once teardown has completed, the domain will stay around until the last > > reference on all pages are dropped. At this point, the amount of memory > > left-over is minimum (this is mostly bookeeping in Xen). > > > > From the userland PoV, the domain will still show-up in the list but tools > > like "xl list" will show "(null)". They are called zombie domains. > > > > So I would consider to keep the same domain around. The advantage is you > > can call "xl destroy" again to retry the operation. > > In this scenario the "restart" implementation here is right but how could we > park the VM as "zombie" instead of busy looping in > the "kill" loop of userland ? > > Also we need to release all the memory of the VM but the one shared with the > SP. > > I will let Jens answer the more implementation questions here after and try > to help on the more "system" ones. > > > > >> Thanks, > >> Jens > >> --- > >> xen/arch/arm/tee/ffa.c | 36 ++++++++++++++++++++++++++++++++++++ > >> 1 file changed, 36 insertions(+) > >> diff --git a/xen/arch/arm/tee/ffa.c b/xen/arch/arm/tee/ffa.c > >> index 183528d13388..9c596462a8a2 100644 > >> --- a/xen/arch/arm/tee/ffa.c > >> +++ b/xen/arch/arm/tee/ffa.c > >> @@ -1539,6 +1539,7 @@ static bool is_in_subscr_list(const uint16_t > >> *subscr, uint16_t start, > >> static int ffa_domain_teardown(struct domain *d) > >> { > >> struct ffa_ctx *ctx = d->arch.tee; > >> + struct ffa_shm_mem *shm, *tmp; > >> unsigned int n; > >> int32_t res; > >> @@ -1564,10 +1565,45 @@ static int ffa_domain_teardown(struct domain *d) > >> printk(XENLOG_ERR "ffa: Failed to report destruction of vm_id > >> %u to %u: res %d\n", > >> get_vm_id(d), subscr_vm_destroyed[n], res); > >> } > >> + /* > >> + * If this function is called again due to -ERESTART below, make sure > >> + * not to send the FFA_MSG_SEND_VM_DESTROYED's. > >> + */ > >> + subscr_vm_destroyed_count = 0; > > > > AFAICT, this variable is global. So wouldn't you effectively break other > > domain if let say the unmapping error is temporary? > > > >> if ( ctx->rx ) > >> rxtx_unmap(ctx); > >> + > >> + list_for_each_entry_safe(shm, tmp, &ctx->shm_list, list) > >> + { > >> + register_t handle_hi; > >> + register_t handle_lo; > >> + > >> + uint64_to_regpair(&handle_hi, &handle_lo, shm->handle); > >> + res = ffa_mem_reclaim(handle_lo, handle_hi, 0); > > > > Is this call expensive? If so, we may need to handle continuation here. > > This call should not be expensive in the normal case as memory is reclaimable > so there is no processing required in the SP and all is done in the SPMC which > should basically just return a yes or no depending on a state for the handle. I agree, this should only be a thing between the hypervisor and the SPMC in the secure world. > > So I think this is the best trade. > > @Jens: One thing to consider is that a Destroy might get a retry or busy > answer and we > will have to issue it again and this is not considered in the current > implementation. You're right, we'll need to keep track of which SPs we've been able to send a VM_DESTROY message to. > > After discussing the subject internally we could in fact consider that if an > SP cannot release > some memory shared with the VM destroyed, it should tell it by returning > "retry" to the message. > Here that could simplify things by doing a strategy where: > - we retry on the VM_DESTROY message if required We should keep a record of which SPs remain to be signaled with VM_DESTROY. An SP may have other reasons to return an error so this call can be retried later. > - if some memory is not reclaimable we check if we could park it and make the > VM a zombie. > What do you think ? The zombie option sounds like a good fallback when automatic reclaim (reasonable timeouts have expired etc) has failed. Thanks, Jens > > > > > >> + if ( res ) > >> + { > >> + printk(XENLOG_INFO, "ffa: Failed to reclaim handle %#lx : > >> %d\n", > >> + shm->handle, res); > > > > I think you want to use XENLOG_G_INFO to use the guest ratelimit. Also, I > > would suggest to print the domain ID in the logs (see '%pd'). > > > > > >> + } > >> + else > >> + { > >> + printk(XENLOG_DEBUG, "ffa: Reclaimed handle %#lx\n", > >> shm->handle); > > > > Same here. You want to use XENLOG_G_DEBUG and print the domain ID. > > > >> + ctx->shm_count--; > >> + list_del(&shm->list); > >> + } > >> + } > > > > NIT: New line here please for clarity. > > > >> + if ( !list_empty(&ctx->shm_list) ) > >> + { > >> + printk(XENLOG_INFO, "ffa: Remaining unclaimed handles, > >> retrying\n"); > > > > Same as the other printks. > > > >> + /* > >> + * TODO: add a timeout where we either panic or let the guest be > >> + * fully destroyed. > >> + */ > > Timeout with proper handling would be a solution. I am not sure about > > panic-ing. Do you think the TEE would be in a bad state if we can't release > > memory? > > > >> + return -ERESTART; > >> + } > >> + > >> XFREE(d->arch.tee); > >> return 0; > > > > Cheers, > > > > Cheers > Bertrand > > > -- > > Julien Grall > >
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |