On Wed, Aug 10, 2022 at 8:20 AM Peter Gonda <pgonda@xxxxxxxxxx> wrote: > ... > + > +static struct ucall *ucall_alloc(void) > +{ > + struct ucall *uc = NULL; > + int i; > + > + if (!use_ucall_pool) > + goto out; > + > + for (i = 0; i < KVM_MAX_VCPUS; ++i) { > + if (!atomic_test_and_set_bit(i, ucall_pool->in_use)) { > + uc = &ucall_pool->ucalls[i]; > + memset(uc->args, 0, sizeof(uc->args)); > + break; > + } > + } > +out: > + return uc; > +} > + > +static inline size_t uc_pool_idx(struct ucall *uc) > +{ > + return uc->hva - ucall_pool->ucalls; > +} > + > +static void ucall_free(struct ucall *uc) > +{ > + if (!use_ucall_pool) > + return; > + > + clear_bit(uc_pool_idx(uc), ucall_pool->in_use); > +} > > void ucall(uint64_t cmd, int nargs, ...) > { > - struct ucall uc = {}; > + struct ucall *uc; > + struct ucall tmp = {}; This steps seems to result in generating instructions that need SSE support on x86: struct ucall tmp = {}; movaps %xmm0,0x20(%rsp) movaps %xmm0,0x30(%rsp) movaps %xmm0,0x40(%rsp) movaps %xmm0,0x50(%rsp) This initialization will need proper compilation flags to generate instructions according to VM configuration. > va_list va; > int i; > > - WRITE_ONCE(uc.cmd, cmd); > + uc = ucall_alloc(); > + if (!uc) > + uc = &tmp; > + > + WRITE_ONCE(uc->cmd, cmd); > > nargs = min(nargs, UCALL_MAX_ARGS); > > va_start(va, nargs); > for (i = 0; i < nargs; ++i) > - WRITE_ONCE(uc.args[i], va_arg(va, uint64_t)); > + WRITE_ONCE(uc->args[i], va_arg(va, uint64_t)); > va_end(va); > > - ucall_arch_do_ucall((vm_vaddr_t)&uc); > ...