Re: [PATCH v9 21/27] gunyah: vm_mgr: Add framework to add VM Functions

Srivatsa Vaddagiri
2023-02-03T09:38:01Z

* Elliot Berman <quic_eberman@quicinc.com> [2023-01-20 14:46:20]:

> +static struct gunyah_vm_function_driver *__find_function(const char name[GUNYAH_FUNCTION_NAME_SIZE])
> + __must_hold(functions_lock)
> +{
> + struct gunyah_vm_function_driver *iter, *drv = NULL;
> +
> + list_for_each_entry(iter, &functions, list) {
> + if (!strncmp(iter->name, name, GUNYAH_FUNCTION_NAME_SIZE)) {
> + drv = iter;
> + break;
> + }
> + }

Not sure how much of a hot path this is going to sit in. I can imagine VM boot
to be in fast path for some cases (VMs spawned on usecase boundaries - I think
some VMs like in Amazon firecracker boot in fraction of a second). This
indirection could cost that a bit (linear search + strcmp for the right
function). IMHO a direct interface (ex: ADD_IOEVENTFD) will be more efficient.

> +void gunyah_vm_function_unregister(struct gunyah_vm_function_driver *drv)
> +{
> + struct gunyah_vm_function *f, *iter;
> +
> + mutex_lock(&functions_lock);
> + list_for_each_entry_safe(f, iter, &drv->instances, drv_list)
> + gh_vm_remove_function(f);
> + list_del(&drv->list);
> + mutex_unlock(&functions_lock);

This seems to allow essential functions to be unregistered while there are still
active users. For example, it would allow ioeventfd or irqfd module to be
unloaded while there are VMs depending on it. I think it would be better if we
allow module unload (aka function_unregister) only after dependent VMs are stopped.

> +static long gh_vm_rm_function(struct gunyah_vm *ghvm, struct gh_vm_function *fn)
> +{
> + long r = 0;
> + struct gunyah_vm_function *f, *iter;
> +
> + r = mutex_lock_interruptible(&functions_lock);
> + if (r)
> + return r;
> +
> + list_for_each_entry_safe(f, iter, &ghvm->functions, vm_list) {
> + if (!memcmp(&f->fn, fn, sizeof(*fn)))
> + gh_vm_remove_function(f);
> + }
> +

I think we should return some error (for ioctl atleast) if given function was
not found.

> +struct gh_vm_function {
> + char name[GUNYAH_FUNCTION_NAME_SIZE];
> + union {
> + char data[GUNYAH_FUNCTION_MAX_ARG_SIZE];
> + };

Can you find a way to optimize this memory/time usage? For example, in case of
ioevents we strictly need 28 bytes, but end up consuming 1kB.
Also we end up comparing 1024 bytes during REMOVE_FUNCTION when strictly 28
bytes or fewer bytes comparison was required in case of ioeventfd.