|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [RFC XEN PATCH v12 7/7] tools: Add new function to do PIRQ (un)map on PVH dom0
On 2024/7/8 22:57, Anthony PERARD wrote:
> On Mon, Jul 08, 2024 at 07:41:24PM +0800, Jiqian Chen wrote:
>> diff --git a/tools/libs/light/libxl_arm.c b/tools/libs/light/libxl_arm.c
>> index a4029e3ac810..d869bbec769e 100644
>> --- a/tools/libs/light/libxl_arm.c
>> +++ b/tools/libs/light/libxl_arm.c
>> @@ -1774,6 +1774,16 @@ void libxl__arch_update_domain_config(libxl__gc *gc,
>> {
>> }
>>
>> +int libxl__arch_hvm_map_gsi(libxl__gc *gc, uint32_t sbdf, uint32_t domid)
>> +{
>> + return -1;
>
> It's best to return an ERROR_* for libxl error code instead of -1.
> ERROR_NI seems to be the one, it probably means not-implemented. Or
> maybe ERROR_INVAL would do to.
Seems ERROR_INVAL is more suitable. Will change in next version.
>
>> +}
>> +
>> +int libxl__arch_hvm_unmap_gsi(libxl__gc *gc, uint32_t sbdf, uint32_t domid)
>> +{
>> + return -1;
>> +}
>> +
>> /*
>> * Local variables:
>> * mode: C
>> diff --git a/tools/libs/light/libxl_pci.c b/tools/libs/light/libxl_pci.c
>> index 96cb4da0794e..3d25997921cc 100644
>> --- a/tools/libs/light/libxl_pci.c
>> +++ b/tools/libs/light/libxl_pci.c
>> @@ -17,6 +17,7 @@
>> #include "libxl_osdeps.h" /* must come before any other headers */
>>
>> #include "libxl_internal.h"
>> +#include "libxl_arch.h"
>>
>> #define PCI_BDF "%04x:%02x:%02x.%01x"
>> #define PCI_BDF_SHORT "%02x:%02x.%01x"
>> @@ -1478,6 +1479,16 @@ static void pci_add_dm_done(libxl__egc *egc,
>> fclose(f);
>> if (!pci_supp_legacy_irq())
>> goto out_no_irq;
>> +
>> + /*
>> + * When dom0 is PVH and mapping a x86 gsi to pirq for domU,
>> + * should use gsi to grant irq permission.
>> + */
>> + if (!libxl__arch_hvm_map_gsi(gc, pci_encode_bdf(pci), domid))
>
> Could you store the result of libxl__arch_hvm_map_gsi() in `rc', then
> test that in the condition?
Will change in next version.
>
>> + goto pci_permissive;
>
> Why do you skip part of the function on success?
Because libxl__arch_hvm_map_gsi do the same thing for PVH dom0, and the
following part is for PV dom0.
If libxl__arch_hvm_map_gsi success, it should skip the following part.
> But also, please avoid the "goto" coding style, in libxl, it's tolerated
> for error handling when used to skip to the end of function to have a
> single path (or error path) out of a function.
Maybe I should split the part " xc_domain_getinfo_single(ctx->xch,
LIBXL_TOOLSTACK_DOMID, &info); " in libxl__arch_hvm_map_gsi to a single
function.
Then I can distinguish PVH and PV, and do different things for them.
>
>> + else
>> + LOGED(WARN, domid, "libxl__arch_hvm_map_gsi failed (err=%d)",
>> errno);
>
> No one reads logs unless there's a failure or something doesn't work. So
> here we just ignore failure returned by libxl__arch_hvm_map_gsi(), is it
> the right things to do? Usually, just ignoring error is wrong.
Will change in next version.
>
> FYI: LOGE* already logs errno.
>
>> +
>> sysfs_path = GCSPRINTF(SYSFS_PCI_DEV"/"PCI_BDF"/irq", pci->domain,
>> pci->bus, pci->dev, pci->func);
>> f = fopen(sysfs_path, "r");
>> @@ -1505,6 +1516,7 @@ static void pci_add_dm_done(libxl__egc *egc,
>> }
>> fclose(f);
>>
>> +pci_permissive:
>> /* Don't restrict writes to the PCI config space from this VM */
>> if (pci->permissive) {
>> if ( sysfs_write_bdf(gc, SYSFS_PCIBACK_DRIVER"/permissive",
>> @@ -2229,6 +2241,11 @@ skip_bar:
>> if (!pci_supp_legacy_irq())
>> goto skip_legacy_irq;
>>
>> + if (!libxl__arch_hvm_unmap_gsi(gc, pci_encode_bdf(pci), domid))
>> + goto skip_legacy_irq;
>> + else
>> + LOGED(WARN, domid, "libxl__arch_hvm_unmap_gsi failed (err=%d)",
>> errno);
>> +
>> sysfs_path = GCSPRINTF(SYSFS_PCI_DEV"/"PCI_BDF"/irq", pci->domain,
>> pci->bus, pci->dev, pci->func);
>>
>> diff --git a/tools/libs/light/libxl_x86.c b/tools/libs/light/libxl_x86.c
>> index 60643d6f5376..e7756d323cb6 100644
>> --- a/tools/libs/light/libxl_x86.c
>> +++ b/tools/libs/light/libxl_x86.c
>> @@ -879,6 +879,117 @@ void libxl__arch_update_domain_config(libxl__gc *gc,
>> libxl_defbool_val(src->b_info.u.hvm.pirq));
>> }
>>
>> +struct pcidev_map_pirq {
>> + uint32_t sbdf;
>> + uint32_t pirq;
>> + XEN_LIST_ENTRY(struct pcidev_map_pirq) entry;
>> +};
>> +
>> +static pthread_mutex_t pcidev_pirq_mutex = PTHREAD_MUTEX_INITIALIZER;
>> +static XEN_LIST_HEAD(, struct pcidev_map_pirq) pcidev_pirq_list =
>> + XEN_LIST_HEAD_INITIALIZER(pcidev_pirq_list);
>> +
>> +int libxl__arch_hvm_map_gsi(libxl__gc *gc, uint32_t sbdf, uint32_t domid)
>> +{
>> + int pirq = -1, gsi, r;
>> + xc_domaininfo_t info;
>> + struct pcidev_map_pirq *pcidev_pirq;
>> + libxl_ctx *ctx = libxl__gc_owner(gc);
>
> Instead of declaring "ctx", you can use the macro "CTX" when you need
> "ctx".
Will change in next version.
>
>> +
>> + r = xc_domain_getinfo_single(ctx->xch, LIBXL_TOOLSTACK_DOMID, &info);
>> + if (r < 0) {
>> + LOGED(ERROR, domid, "getdomaininfo failed (error=%d)", errno);
>> + return r;
>
> libxl_*() functions should return only libxl error code, that is return
> code from other libxl_* functions, useally store in 'rc', or one of ERROR_*.
OK, will change in next version.
>
>> + }
>> + if ((info.flags & XEN_DOMINF_hvm_guest) &&
>> + !(info.arch_config.emulation_flags & XEN_X86_EMU_USE_PIRQ)) {
>> + gsi = xc_physdev_gsi_from_pcidev(ctx->xch, sbdf);
>> + if (gsi < 0) {
>> + return ERROR_FAIL;
>> + }
>> + r = xc_physdev_map_pirq(ctx->xch, domid, gsi, &pirq);
>> + if (r < 0) {
>> + LOGED(ERROR, domid, "xc_physdev_map_pirq gsi=%d (error=%d)",
>> + gsi, errno);
>> + return r;
>> + }
>> + r = xc_domain_gsi_permission(ctx->xch, domid, gsi, 1);
>> + if (r < 0) {
>> + LOGED(ERROR, domid, "xc_domain_gsi_permission gsi=%d
>> (error=%d)",
>> + gsi, errno);
>> + return r;
>> + }
>> + } else {
>> + return ERROR_FAIL;
>
> Is it really an error?
>
> I few values can be returned here,
> * ERROR_INVAL meaing that the function was called on a dom0 that don't
> do "GSI",
I think this is more suitable. And then the following code of PV can be done in
pci_add_dm_done.
> * 0, that is success, because the function check if it need to do
> anything, and since there's nothing to do, we can return success.
>
>> + }
>> +
>> + /* Save the pirq for the usage of unmapping */
>> + pcidev_pirq = malloc(sizeof(struct pcidev_map_pirq));
>> + if (!pcidev_pirq) {
>> + LOGED(ERROR, domid, "no memory for saving pirq of pcidev info");
>> + return ERROR_NOMEM;
>> + }
>> + pcidev_pirq->sbdf = sbdf;
>> + pcidev_pirq->pirq = pirq;
>> +
>> + assert(!pthread_mutex_lock(&pcidev_pirq_mutex));
>> + XEN_LIST_INSERT_HEAD(&pcidev_pirq_list, pcidev_pirq, entry);
>
> I don't think that's going to work as you expect. libxl isn't a daemon
> (or sometime it is but used for several domains), so anything store in
> memory will be lost, or would be shared with other guest.
>
> Do you need this mappins sbdf<-> pirq ?
I need to store the pirq that assigned to the gsi. Because
libxl__arch_hvm_unmap_gsi need pirq to do xc_physdev_unmap_pirq
> Is there a way to query this information later from the environement?
What I can think of is before xc_physdev_unmap_pirq, use xc_physdev_map_pirq to
get the already mapped pirq, but I am not sure if it is suitable.
> If not, you will need to store the data somewhere else, probably in
> "libxl_domain_config *d_config" as
> libxl can retrive the data with libxl__get_domain_configuration().
However, pirq is dynamically mapped during starting domU, it may not be
suitable for saving in d_config.
> There's also the posibility to store that info in xenstore, but we
> should probably avoid that.
>
> Thanks,
>
--
Best regards,
Jiqian Chen.
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |