[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v7] vpci: Add resizable bar support
On 2025/2/7 01:17, Roger Pau Monné wrote: > On Thu, Feb 06, 2025 at 05:39:00PM +0800, Jiqian Chen wrote: >> Some devices, like discrete GPU of amd, support resizable bar > ^ AMD? > >> capability, but vpci of Xen doesn't support this feature, so >> they fail to resize bars and then cause probing failure. >> >> According to PCIe spec, each bar that supports resizing has >> two registers, PCI_REBAR_CAP and PCI_REBAR_CTRL. So, add >> handlers for them to support resizing the size of BARs. > > You need to update the commit message to note Xen will only trap > PCI_REBAR_CTRL, as PCI_REBAR_CAP is read-only and the hardware domain > will already get access to it without needing any setup. Thanks, I will add this sentence to the commit message. > >> >> Signed-off-by: Jiqian Chen <Jiqian.Chen@xxxxxxx> > > Just one comment about you not needing to introduce vpci_hw_write32() > anymore. The rest are nits to comments, which I'm not even sure are > better than your proposed text. > >> --- >> Hi all, >> v6->v7 changes: >> * Deleted codes that add register for PCI_REBAR_CAP, and added comments to >> explain why. >> * Added comments to explain why use "continue" when fail to add register for >> PCI_REBAR_CTRL. >> >> Best regards, >> Jiqian Chen. >> >> v5->v6 changes: >> * Changed "1UL" to "1ULL" in PCI_REBAR_CTRL_SIZE idefinition for 32 bit >> architecture. >> * In rebar_ctrl_write used "bar - pdev->vpci->header.bars" to get index >> instead of reading >> from register. >> * Added the index of BAR to error messages. >> * Changed to "continue" instead of "return an error" when vpci_add_register >> failed. >> >> v4->v5 changes: >> * Called pci_size_mem_bar in rebar_ctrl_write to get addr and size of BAR >> instead of setting >> their values directly after writing new size to hardware. >> * Changed from "return" to "continue" when index/type of BAR are not correct >> during initializing >> BAR. >> * Corrected the value of PCI_REBAR_CTRL_BAR_SIZE from "0x00001F00" to >> "0x00003F00". >> * Renamed PCI_REBAR_SIZE_BIAS to PCI_REBAR_CTRL_SIZE_BIAS. >> * Re-defined "PCI_REBAR_CAP_SHIFT 4" to "PCI_REBAR_CAP_SIZES_MASK >> 0xFFFFFFF0U". >> >> v3->v4 changes: >> * Removed PCI_REBAR_CAP_SIZES since it was not needed, and added >> PCI_REBAR_CAP_SHIFT and PCI_REBAR_CTRL_SIZES. >> * Added parameter resizable_sizes to struct vpci_bar to cache the support >> resizable sizes and >> added the logic in init_rebar(). >> * Changed PCI_REBAR_CAP to PCI_REBAR_CAP(n) (4+8*(n)), changed >> PCI_REBAR_CTRL to >> PCI_REBAR_CTRL(n) (8+8*(n)). >> * Added domain info of pci_dev to printings of init_rebar(). >> >> v2->v3 changes: >> * Used "bar->enabled" to replace "pci_conf_read16(pdev->sbdf, PCI_COMMAND) & >> PCI_COMMAND_MEMORY", >> and added comments why it needs this check. >> * Added "!is_hardware_domain(pdev->domain)" check in init_rebar() to return >> EOPNOTSUPP for domUs. >> * Moved BAR type and index check into init_rebar(), then only need to check >> once. >> * Added 'U' suffix for macro PCI_REBAR_CAP_SIZES. >> * Added macro PCI_REBAR_SIZE_BIAS to represent 20. >> TODO: need to hide ReBar capability from hardware domain when init_rebar() >> fails. >> >> v1->v2 changes: >> * In rebar_ctrl_write, to check if memory decoding is enabled, and added >> some checks for the type of Bar. >> * Added vpci_hw_write32 to handle PCI_REBAR_CAP's write, since there is >> no write limitation of dom0. >> * And has many other minor modifications as well. >> --- >> xen/drivers/vpci/Makefile | 2 +- >> xen/drivers/vpci/rebar.c | 136 +++++++++++++++++++++++++++++++++++++ >> xen/drivers/vpci/vpci.c | 6 ++ >> xen/include/xen/pci_regs.h | 15 ++++ >> xen/include/xen/vpci.h | 3 + >> 5 files changed, 161 insertions(+), 1 deletion(-) >> create mode 100644 xen/drivers/vpci/rebar.c >> >> diff --git a/xen/drivers/vpci/Makefile b/xen/drivers/vpci/Makefile >> index 1a1413b93e76..a7c8a30a8956 100644 >> --- a/xen/drivers/vpci/Makefile >> +++ b/xen/drivers/vpci/Makefile >> @@ -1,2 +1,2 @@ >> -obj-y += vpci.o header.o >> +obj-y += vpci.o header.o rebar.o >> obj-$(CONFIG_HAS_PCI_MSI) += msi.o msix.o >> diff --git a/xen/drivers/vpci/rebar.c b/xen/drivers/vpci/rebar.c >> new file mode 100644 >> index 000000000000..64b56a9567fa >> --- /dev/null >> +++ b/xen/drivers/vpci/rebar.c >> @@ -0,0 +1,136 @@ >> +/* SPDX-License-Identifier: GPL-2.0-only */ >> +/* >> + * Copyright (C) 2025 Advanced Micro Devices, Inc. All Rights Reserved. >> + * >> + * Author: Jiqian Chen <Jiqian.Chen@xxxxxxx> >> + */ >> + >> +#include <xen/sched.h> >> +#include <xen/vpci.h> >> + >> +static void cf_check rebar_ctrl_write(const struct pci_dev *pdev, >> + unsigned int reg, >> + uint32_t val, >> + void *data) >> +{ >> + struct vpci_bar *bar = data; >> + const unsigned int index = bar - pdev->vpci->header.bars; >> + uint64_t size = PCI_REBAR_CTRL_SIZE(val); >> + >> + if ( bar->enabled ) >> + { >> + /* >> + * Refuse to resize a BAR while memory decoding is enabled, as >> + * otherwise the size of the mapped region in the p2m would become >> + * stale with the newly set BAR size, and the position of the BAR >> + * would be reset to undefined. Note the PCIe specification also >> + * forbids resizing a BAR with memory decoding enabled. >> + */ >> + if ( size != bar->size ) >> + gprintk(XENLOG_ERR, >> + "%pp: refuse to resize BAR#%u with memory decoding >> enabled\n", >> + &pdev->sbdf, index); >> + return; >> + } >> + >> + if ( !((size >> PCI_REBAR_CTRL_SIZE_BIAS) & bar->resizable_sizes) ) >> + gprintk(XENLOG_WARNING, >> + "%pp: new BAR#%u size %#lx is not supported by hardware\n", >> + &pdev->sbdf, index, size); >> + >> + pci_conf_write32(pdev->sbdf, reg, val); >> + >> + pci_size_mem_bar(pdev->sbdf, >> + PCI_BASE_ADDRESS_0 + index * 4, >> + &bar->addr, >> + &bar->size, >> + (index == PCI_HEADER_NORMAL_NR_BARS - 1) ? >> + PCI_BAR_LAST : 0); >> + bar->guest_addr = bar->addr; >> +} >> + >> +static int cf_check init_rebar(struct pci_dev *pdev) >> +{ >> + uint32_t ctrl; >> + unsigned int nbars; >> + unsigned int rebar_offset = pci_find_ext_capability(pdev->sbdf, >> + >> PCI_EXT_CAP_ID_REBAR); >> + >> + if ( !rebar_offset ) >> + return 0; >> + >> + if ( !is_hardware_domain(pdev->domain) ) >> + { >> + printk(XENLOG_ERR "%pp: resizable BARs unsupported for unpriv >> %pd\n", >> + &pdev->sbdf, pdev->domain); >> + return -EOPNOTSUPP; >> + } >> + >> + ctrl = pci_conf_read32(pdev->sbdf, rebar_offset + PCI_REBAR_CTRL(0)); >> + nbars = MASK_EXTR(ctrl, PCI_REBAR_CTRL_NBAR_MASK); >> + for ( unsigned int i = 0; i < nbars; i++ ) >> + { >> + int rc; >> + struct vpci_bar *bar; >> + unsigned int index; >> + >> + ctrl = pci_conf_read32(pdev->sbdf, rebar_offset + >> PCI_REBAR_CTRL(i)); >> + index = ctrl & PCI_REBAR_CTRL_BAR_IDX; >> + if ( index >= PCI_HEADER_NORMAL_NR_BARS ) >> + { >> + printk(XENLOG_ERR "%pd %pp: too big BAR number %u in >> REBAR_CTRL\n", >> + pdev->domain, &pdev->sbdf, index); >> + continue; >> + } >> + >> + bar = &pdev->vpci->header.bars[index]; >> + if ( bar->type != VPCI_BAR_MEM64_LO && bar->type != VPCI_BAR_MEM32 ) >> + { >> + printk(XENLOG_ERR "%pd %pp: BAR%u is not in memory space\n", >> + pdev->domain, &pdev->sbdf, index); >> + continue; >> + } >> + >> + /* >> + * Here not to add register for PCI_REBAR_CAP since it is read-only > > "Here not to add" doesn't read right to me (but I'm not a native > speaker), I would rather use: > > "Don't add a handler for PCI_REBAR_CAP since it is read-only ..." > > TBH I would even drop the comment from here, at the end we allow the > hardware domain unmediated access to a lot of read-only devices, and > there's no comment for each of them. Got it, will drop this comment in next version. > >> + * register without other specific operations, and hardware domain >> + * has no limitation of read/write access to all PCI config space. >> + */ >> + rc = vpci_add_register(pdev->vpci, vpci_hw_read32, rebar_ctrl_write, >> + rebar_offset + PCI_REBAR_CTRL(i), 4, bar); >> + if ( rc ) >> + { >> + printk(XENLOG_ERR "%pd %pp: BAR%u fail to add reg of REBAR_CTRL >> rc=%d\n", >> + pdev->domain, &pdev->sbdf, index, rc); >> + /* >> + * Ideally we would hide the ReBar capability here, but code >> + * for doing so still needs to be written. And using continue >> + * can keep any possible hooks working, instead, returning >> + * failure would cause all vPCI hooks down and hardware domain >> + * has entirely unmediated access to the device, which is worse. >> + */ > > "Ideally we would hide the ReBar capability on error, but code for > doing so still needs to be written. Use continue instead to keep any > already setup register hooks, as returning an error will cause > the hardware domain to get unmediated access to all device registers." > > Seems slightly easier to parse IMO (again I'm not a native speaker, so > your proposed comment might be better). That's fine, I am not, too. So, I will change to your version. > >> + continue; >> + } >> + >> + bar->resizable_sizes = >> + MASK_EXTR(pci_conf_read32(pdev->sbdf, >> + rebar_offset + PCI_REBAR_CAP(i)), >> + PCI_REBAR_CAP_SIZES_MASK); >> + bar->resizable_sizes |= >> + (((uint64_t)MASK_EXTR(ctrl, PCI_REBAR_CTRL_SIZES_MASK) << 32) / >> + ISOLATE_LSB(PCI_REBAR_CAP_SIZES_MASK)); >> + } >> + >> + return 0; >> +} >> +REGISTER_VPCI_INIT(init_rebar, VPCI_PRIORITY_LOW); >> + >> +/* >> + * Local variables: >> + * mode: C >> + * c-file-style: "BSD" >> + * c-basic-offset: 4 >> + * tab-width: 4 >> + * indent-tabs-mode: nil >> + * End: >> + */ >> diff --git a/xen/drivers/vpci/vpci.c b/xen/drivers/vpci/vpci.c >> index 1e6aa5d799b9..3349b98389b8 100644 >> --- a/xen/drivers/vpci/vpci.c >> +++ b/xen/drivers/vpci/vpci.c >> @@ -232,6 +232,12 @@ void cf_check vpci_hw_write16( >> pci_conf_write16(pdev->sbdf, reg, val); >> } >> >> +void cf_check vpci_hw_write32( >> + const struct pci_dev *pdev, unsigned int reg, uint32_t val, void *data) >> +{ >> + pci_conf_write32(pdev->sbdf, reg, val); >> +} > > I think you now longer need to introduce vpci_hw_write32() since it's > not used anywhere in this patch. > > Thanks, Roger. -- Best regards, Jiqian Chen.
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |