[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH] vpci: Add resizable bar support
On Mon, Nov 18, 2024 at 06:06:03AM +0000, Chen, Jiqian wrote: > On 2024/11/15 19:42, Roger Pau Monné wrote: > > On Fri, Nov 15, 2024 at 03:04:22AM +0000, Chen, Jiqian wrote: > >> On 2024/11/15 01:36, Roger Pau Monné wrote: > >>> On Thu, Nov 14, 2024 at 04:52:18PM +0100, Roger Pau Monné wrote: > >>>> On Thu, Nov 14, 2024 at 06:11:46AM +0000, Chen, Jiqian wrote: > >>>>> On 2024/11/13 18:30, Roger Pau Monné wrote: > >>>>>> On Wed, Nov 13, 2024 at 10:00:33AM +0000, Chen, Jiqian wrote: > >>>>>>> On 2024/11/13 17:30, Roger Pau Monné wrote: > >>>>>>>> On Wed, Nov 13, 2024 at 04:00:27PM +0800, Jiqian Chen wrote: > >>>>>>>>> Some devices, like discrete GPU of amd, support resizable bar > >>>>>>>>> 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 support resizing has two > >>>>>>>>> registers, > >>>>>>>>> PCI_REBAR_CAP and PCI_REBAR_CTRL, so add these two registers and > >>>>>>>>> their > >>>>>>>>> corresponding handler into vpci. > >>>>>>>>> > >>>>>>>>> PCI_REBAR_CAP is RO, only provide reading. > >>>>>>>>> > >>>>>>>>> PCI_REBAR_CTRL only has bar size is RW, so add write function to > >>>>>>>>> support > >>>>>>>>> setting the new size. > >>>>>>>> > >>>>>>>> I think the logic to handle resizable BAR could be much simpler. > >>>>>>>> Some > >>>>>>>> time ago I've made a patch to add support for it, but due to lack of > >>>>>>>> hardware on my side to test it I've never submitted it. > >>>>>>>> > >>>>>>>> My approach would be to detect the presence of the > >>>>>>>> PCI_EXT_CAP_ID_REBAR capability in init_header(), and if the > >>>>>>>> capability is present force the sizing of BARs each time they are > >>>>>>>> mapped in modify_bars(). I don't think we need to trap accesses to > >>>>>>>> the capability itself, as resizing can only happen when memory > >>>>>>>> decoding is not enabled for the device. It's enough to fetch the > >>>>>>>> size > >>>>>>>> of the BARs ahead of each enabling of memory decoding. > >>>>>>>> > >>>>>>>> Note that memory decoding implies mapping the BARs into the p2m, > >>>>>>>> which > >>>>>>>> is already an expensive operation, the extra sizing is unlikely to > >>>>>>>> make much of a difference performance wise. > >>>>>>>> > >>>>>>>> I've found the following on my git tree and rebased on top of > >>>>>>>> staging: > >>>>>>> OK. > >>>>>>> Do you need me to validate your patch in my environment? > >>>>>> > >>>>>> Yes please, I have no way to test it. Let's see what others think > >>>>>> about the different approaches. > >>>>> There are some errors with your method. > >>>>> I attached the dmesg and xl dmesg logs. > >>>>> From the dmesg logs, it seems that 0000:03:00.0 has addresse overlap > >>>>> with 0000:03:00.1 > >>>> > >>>> Do you have the output of lspci with the BAR sizes/positions before > >>>> and after the resizing? > >>>> > >>>>> > >>>>> I think there is a place that needs to be modified regarding your > >>>>> method, > >>>>> although this modification does not help with the above-mentioned > >>>>> errors, > >>>>> it is that whether to support resizing is specific to which bar, rather > >>>>> than just determining whether there is a Rebar capability. > >>>> > >>>> Do we really need such fine-grained information? It should be > >>>> harmless (even if not strictly necessary) to size all BARs on the > >>>> device before enabling memory decoding, even if some of them do not > >>>> support resizing. > >>>> > >>>> I might have to provide a patch with additional messages to see what's > >>>> going on. > >>> > >>> One nit that I've noticed with the patch I gave you previously is that > >>> the check for a size change in modify_bars() should be done ahead of > >>> pci_check_bar(), otherwise the check is possibly using an outdated > >>> size. > >>> > >>> I've also added a debug message to notify when a BAR register is > >>> written and report the new address. This is done unconditionally, but > >>> if you think it's too chatty you can limit to only printing for the > >>> device that has the ReBAR capability. > >> Errors are the same. > >> Attached the dmesg, xl dmesg, patch and lspci output. > >> I will also continue to debug your method on my side to try to get some > >> findings. > > > > Hello, > > > > I've been looking at the output, and it all seems fine, except the > > 03:00.0 device that becomes broken at some point, note the lspci > > output lists [virtual] next to the resource sizes. This means reading > > for the registers returned 0, so the position and sizes are provided > > from the internal OS information. > > > > I'm assuming the patch you sent to the list doesn't lead to such errors, > Yes, the method of my patch doesn't lead to any errors. > I attached the dmesg, xl dmesg and lspci logs of my method. > > > in which case I can only guess that fetching the size of the > > BARs in modify_bars() causes issues with the device. > > > > To confirm this, can you try the following patch on top of your original > > change? > I tried below patch with my original patch, it didn't cause any errors. > And the lspci showed without the "[virtual]". > So, unfortunately, it is not related to the fetching size of Bars in > modify_bars(). I see, I'm at a loss as to what's wrong with my patch. Do you have any additional patches on Xen when testing your or my approach? I sadly don't have any box with a PCI device that exposes the resizable BAR capability, so I'm not able to test or debug this. I would like to understand why my approach doesn't work, as otherwise I feel like I'm missing how ReBAR is supposed to work. Anyway, if you can give a try to the diff below, it's the same patch, but with yet even more debug messages added. Thanks, and sorry for keeping you testing it. Regards, Roger. diff --git a/xen/drivers/vpci/header.c b/xen/drivers/vpci/header.c index ef6c965c081c..dda42ef0b7ff 100644 --- a/xen/drivers/vpci/header.c +++ b/xen/drivers/vpci/header.c @@ -316,6 +316,9 @@ static int modify_bars(const struct pci_dev *pdev, uint16_t cmd, bool rom_only) ASSERT(rw_is_write_locked(&pdev->domain->pci_lock)); + printk("%pp: modify bars cmd: %x rom_only: %d\n", + &pdev->sbdf, cmd, rom_only); + /* * Create a rangeset per BAR that represents the current device memory * region and compare it against all the currently active BAR memory @@ -346,6 +349,33 @@ static int modify_bars(const struct pci_dev *pdev, uint16_t cmd, bool rom_only) bar->enabled == !!(cmd & PCI_COMMAND_MEMORY) ) continue; + if ( bar->type != VPCI_BAR_ROM && header->bars_resizable && + (cmd & PCI_COMMAND_MEMORY) ) + { + uint64_t addr, size; + + pci_size_mem_bar(pdev->sbdf, PCI_BASE_ADDRESS_0 + i * 4, + &addr, &size, 0); + + printk("%pp: BAR%u ReBAR supported addr %#lx -> %#lx size %#lx -> %#lx\n", + &pdev->sbdf, i, bar->addr, addr, bar->size, size); + + if ( bar->addr != addr ) + printk(XENLOG_G_ERR + "%pp: BAR#%u address mismatch %#lx vs %#lx\n", + &pdev->sbdf, i, bar->addr, addr); + + if ( bar->size != size ) + { + printk(XENLOG_G_DEBUG + "%pp: detected BAR#%u size change (%#lx -> %#lx)\n", + &pdev->sbdf, i, bar->size, size); + bar->size = size; + end = PFN_DOWN(bar->addr + size - 1); + end_guest = PFN_DOWN(bar->guest_addr + size - 1); + } + } + if ( !pci_check_bar(pdev, _mfn(start), _mfn(end)) ) { printk(XENLOG_G_WARNING @@ -583,8 +613,6 @@ static void cf_check bar_write( */ if ( bar->enabled ) { - /* If the value written is the current one avoid printing a warning. */ - if ( val != (uint32_t)(bar->addr >> (hi ? 32 : 0)) ) gprintk(XENLOG_WARNING, "%pp: ignored BAR %zu write while mapped\n", &pdev->sbdf, bar - pdev->vpci->header.bars + hi); @@ -601,6 +629,10 @@ static void cf_check bar_write( /* Update guest address, so hardware domain BAR is identity mapped. */ bar->guest_addr = bar->addr; + printk("%pp: write BAR%zu val: %#x BAR%zu address: %#lx\n", + &pdev->sbdf, bar - pdev->vpci->header.bars, val, + bar - pdev->vpci->header.bars + hi, bar->addr); + /* Make sure Xen writes back the same value for the BAR RO bits. */ if ( !hi ) { @@ -870,6 +902,9 @@ static int cf_check init_header(struct pci_dev *pdev) if ( pdev->ignore_bars ) return 0; + header->bars_resizable = pci_find_ext_capability(pdev->sbdf, + PCI_EXT_CAP_ID_REBAR); + cmd = pci_conf_read16(pdev->sbdf, PCI_COMMAND); /* diff --git a/xen/include/xen/pci_regs.h b/xen/include/xen/pci_regs.h index 250ba106dbd3..c543a2b86778 100644 --- a/xen/include/xen/pci_regs.h +++ b/xen/include/xen/pci_regs.h @@ -459,6 +459,7 @@ #define PCI_EXT_CAP_ID_ARI 14 #define PCI_EXT_CAP_ID_ATS 15 #define PCI_EXT_CAP_ID_SRIOV 16 +#define PCI_EXT_CAP_ID_REBAR 21 /* Advanced Error Reporting */ #define PCI_ERR_UNCOR_STATUS 4 /* Uncorrectable Error Status */ diff --git a/xen/include/xen/vpci.h b/xen/include/xen/vpci.h index 41e7c3bc2791..45ebc1bb3356 100644 --- a/xen/include/xen/vpci.h +++ b/xen/include/xen/vpci.h @@ -129,6 +129,8 @@ struct vpci { * upon to know whether BARs are mapped into the guest p2m. */ bool bars_mapped : 1; + /* Device has the Resizable BARs capability. */ + bool bars_resizable : 1; /* FIXME: currently there's no support for SR-IOV. */ } header;
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |