Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable resizable BAR support #3

Closed
wants to merge 3 commits into from

Conversation

sjkelly
Copy link

@sjkelly sjkelly commented May 11, 2022

Resizable BAR support is a PCIe extension that allows resizing a PCIe device's
mappable memory/register space (also referred to as BARs - after the Base
Address Register that sets up the region). An important use case are GPUs.
While data center GPUs, generally have BAR sizes that match the size of video
memory, consumer and workstation GPUs generally declare only have 256MiB worth
of BARs mapping GPU memory to maintain compatibility with 32bit operating
systems. However, for performance (particularly when using PCIe P2P), it is
desirable to be able to map the entirety of GPU memory, necessitating
resizable BARs.

However, while PCIe ReBAR has been a standard for more than 10 years,
it was ill used until a few years ago and thus support is lacking.
On very recent motherboards (generally after 2020), a BIOS update might
be available that causes the firmware to read and reserve space for a
ReBAR expansion (or even perform the BAR resize itself). However, older
motherbards do not have this support.

Fortunately for us, the Linux kernel has some support to do its own PCIe
enumeration without relying on the firmware to do everything. Linux even has
support for resizable BARs, though in practice there are a number of important
limitations:

@CLAassistant
Copy link

CLAassistant commented May 11, 2022

CLA assistant check
All committers have signed the CLA.

@aritger
Copy link
Collaborator

aritger commented May 11, 2022

Thanks for the contribution, sjkelly, and congratulations on the first pull request in this repository :) I need to catch up a bit on the history of resizable BAR support within NVIDIA, and either I or someone else from NVIDIA will get back to this change soon. Thanks again!

@TheRawMeatball
Copy link

The use of goto is concerning to me.

@ghost
Copy link

ghost commented May 11, 2022

You have to adapt your code to the current codebase. Rewriting such a thing is for a separate time not relevant to this PR.

@TheRawMeatball
Copy link

I am not advocating for a rewrite, but for not introducing more goto in new code.

@Alcaro
Copy link

Alcaro commented May 11, 2022

Yes, this patch adds 3 gotos.

There are 30 gotos in the file already, and Linus himself says gotos are good kernel coding style. I see no problem. https://web.archive.org/web/20130521051957/http:/kerneltrap.org/node/553/2131

@ghost
Copy link

ghost commented May 11, 2022

@TheRawMeatball Look at the current file. It's how the codebase was written. Removing the usage of goto is not relevant to this PR.

@Keno
Copy link

Keno commented May 11, 2022

One of the gotos is not required, since we dropped one of the error paths during rebase, so @sjkelly will remove that. But yes, other than that, gotos are fairly idiomatic in Linux. Much of the hate against gotos is based on the Dijkstra article, but there's some missing context there. Dijkstra was not really arguing against local gotos, but against global gotos that jump all over the place. Regardless, may I suggest not turning this PR into a discussion on the merits of gotos to allow the NVIDIA folks space for a proper review :)?

@RustyRaptor
Copy link

The worst part about using a GOTO is how other programmers will react to it.

@jackpot51
Copy link

I have a feeling there are firmware edgecases where an SMM handler or ACPI code could be holding on to the old BAR address. This kind of code is common for NVIDIA laptops and can vary between vendors or even models.

@Keno
Copy link

Keno commented May 12, 2022

I have a feeling there are firmware edgecases where an SMM handler or ACPI code could be holding on to the old BAR address. This kind of code is common for NVIDIA laptops and can vary between vendors or even models.

Yes, it's possible, though in that situation, the firmware is supposed to ask the kernel not to move the PCIe BARs: https://github.com/torvalds/linux/blob/f400bea2d44beec76f7e7f45e5372ef790336a4d/drivers/acpi/pci_root.c#L919-L927. This patch respects that setting. I'm also not sure whether there are currently any laptop GPUs that include ReBAR support, since that's quite a new feature.

@jackpot51
Copy link

I have a feeling there are firmware edgecases where an SMM handler or ACPI code could be holding on to the old BAR address. This kind of code is common for NVIDIA laptops and can vary between vendors or even models.

Yes, it's possible, though in that situation, the firmware is supposed to ask the kernel not to move the PCIe BARs: https://github.com/torvalds/linux/blob/f400bea2d44beec76f7e7f45e5372ef790336a4d/drivers/acpi/pci_root.c#L919-L927. This patch respects that setting. I'm also not sure whether there are currently any laptop GPUs that include ReBAR support, since that's quite a new feature.

It is good there is a way for firmaare to communicate this case. Yes, there are laptops that support resizeable bar, it became standard with RTX 3000 I believe.

@needlesslygrim
Copy link

I have a feeling there are firmware edgecases where an SMM handler or ACPI code could be holding on to the old BAR address. This kind of code is common for NVIDIA laptops and can vary between vendors or even models.

Yes, it's possible, though in that situation, the firmware is supposed to ask the kernel not to move the PCIe BARs: https://github.com/torvalds/linux/blob/f400bea2d44beec76f7e7f45e5372ef790336a4d/drivers/acpi/pci_root.c#L919-L927. This patch respects that setting. I'm also not sure whether there are currently any laptop GPUs that include ReBAR support, since that's quite a new feature.

Most 30 series laptops support resizeable BAR as far as I'm aware, I know that the Omen 15 supports it but usually I don't think it's visible in the UEFI like on desktop UEFIs.

@divinity76
Copy link

divinity76 commented May 14, 2022

could easily replace the gotos with a for(;;){...continue;...break;} , BUT that might arguably result in uglier code than the goto. I'm with RustyRaptor.

@dmitriyc-nv
Copy link

Hi @sjkelly, if I understand the limitation of this patch correctly, it will only resize BAR1 if there is already enough address space available to do so. In other words, we cannot change the address space window that is already allocated to the GPU and can only operate within it. Can you please share a system configuration where these conditions exist and the patch successfully resizes BAR1?

@Keno
Copy link

Keno commented May 19, 2022

Hi @sjkelly, if I understand the limitation of this patch correctly, it will only resize BAR1 if there is already enough address space available to do so.

Yes, this is correct.

In other words, we cannot change the address space window that is already allocated to the GPU and can only operate within it.

No, this is not. The resources allocated to the GPU (BAR1 and BAR3) are released. The restriction is that address space needs to be available within the PCIe bridge that's upstream of the GPU. If there are no other devices in this PCIe bridge or the upstream PCIe bridge is the root complex this is not an issue, because the kernel will resize it (well, there's an issue about the size of the root complex window on AMD CPUs, but Linux already has code to open an additional huge window on boot to support rebar on AMD GPUs).

The mentioned restriction comes up when the PCIe topology includes a switch between the root complex and the GPU (pretty common on motherboards) and there is another PCIe device attached to the same switch. In that case, Linux currently does not have the ability to move the other device's PCIe BARs in order to resize the bridge window, which will likely cause the resize of the GPU BAR to fail.

Can you please share a system configuration where these conditions exist and the patch successfully resizes BAR1?

We have successfully tested this on a number of systems. The one that @sjkelly has locally is a SuperMicro MBD-C9Z390-CG-O motherboard with an RTX A5000 plugged into the closest PCIe slot, with the other PCIe slot on the same PCIe switch left empty.

@dmitriyc-nv
Copy link

Thanks Keno, I'm currently testing this patch internally.

kernel-open/nvidia/nv-pci.c Show resolved Hide resolved
kernel-open/nvidia/nv-pci.c Show resolved Hide resolved
kernel-open/nvidia/nv-pci.c Show resolved Hide resolved
kernel-open/nvidia/nv-pci.c Show resolved Hide resolved

if ((pci_resource_flags(pci_dev, NV_GPU_BAR1) & IORESOURCE_UNSET) ||
(pci_resource_flags(pci_dev, NV_GPU_BAR3) & IORESOURCE_UNSET)) {
if (requested_size != old_size) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it make sense to step through the available sizes down to the original size here?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think so.

@@ -434,6 +506,12 @@ nv_pci_probe
goto failed;
}

if (nv_resize_pcie_bars(pci_dev)) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this path runs every time .probe is called, we should add this feature behind a regkey module param at first (see nvrm_registry.h). Once we have good test coverage and feel confident that the feature is robust, we can enable this feature by default.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean nv-reg.h? Those expose kernel module options?

@PAR2020 PAR2020 added enhancement New feature or request NV-Triaged An NVBug has been created for dev to investigate labels Jun 27, 2022
@PAR2020
Copy link
Contributor

PAR2020 commented Jul 8, 2022

Tracking internally via bug 3642641

@PAR2020 PAR2020 added the Implemented Fixed, in test prior to release integration label Jul 8, 2022
@dmitriyc-nv
Copy link

There has been no activity on this PR for over a month. @Keno, @sjkelly - do you intend to continue working on this patch?

@sjkelly
Copy link
Author

sjkelly commented Jul 15, 2022

Yes I intend to address the comments unless someone is willing to expedite it internally.

Keno and others added 3 commits July 26, 2022 21:10
Resizable BAR support is a PCIe extension that allows resizing a PCIe device's
mappable memory/register space (also referred to as BARs - after the Base
Address Register that sets up the region). An important use case are GPUs.
While data center GPUs, generally have BAR sizes that match the size of video
memory, consumer and workstation GPUs generally declare only have 256MiB worth
of BARs mapping GPU memory to maintain compatibility with 32bit operating
systems. However, for performance (particularly when using PCIe P2P), it is
desirable to be able to map the entirety of GPU memory, necessitating
resizable BARs.

However, while PCIe ReBAR has been a standard for more than 10 years,
it was ill used until a few years ago and thus support is lacking.
On very recent motherboards (generally after 2020), a BIOS update might
be available that causes the firmware to read and reserve space for a
ReBAR expansion (or even perform the BAR resize itself). However, older
motherbards do not have this support.

Fortunately for us, the Linux kernel has some support to do its own PCIe
enumeration without relying on the firmware to do everything. Linux even has
support for resizable BARs, though in practice there are a number of important
limitations:

* There is currently no support for movable BARs in Linux. This means that if
  there are adjacent address space allocations, it is quite possible for BAR
  resizing to fail. There was a WIP patch series to resolve this issue at
  https://patchwork.ozlabs.org/project/linux-pci/cover/20201218174011.340514-1-s.miroshnichenko@yadro.com/
  but it appears to have faded out.
- check for `pci_rebar_get_possible_sizes`
- check for `pci_get_host_bridge`
- print info on EOPNOTSUPP when attempting rebar_resize
- short circuit return when requesting resize equal to current size
@PAR2020 PAR2020 removed the Implemented Fixed, in test prior to release integration label Aug 22, 2022
@Keno
Copy link

Keno commented Oct 24, 2022

@dmitriyc-nv Sorry, I lost track of this. I see @sjkelly did do the rebase, but it grew conflicts again. I can do another round of rebasing here if you would like.

@dmitriyc-nv
Copy link

No worries, I've continued working on the patch internally and it is going through review.

@Keno
Copy link

Keno commented Oct 25, 2022

Excellent, thank you. Looking forward to it.

@dmitriyc-nv
Copy link

A version of this patch has been merged in 530.30.02. Resizing can be enabled with the following module parameter:

NVreg_EnableResizableBar=1

@Keno
Copy link

Keno commented Mar 21, 2023

Awesome, thanks for pushing this through!

@sjkelly sjkelly closed this Mar 21, 2023
@dmitriyc-nv dmitriyc-nv added the Implemented Fixed, in test prior to release integration label Mar 22, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request Implemented Fixed, in test prior to release integration NV-Triaged An NVBug has been created for dev to investigate
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet