├── 495.46-pcie-rebar.patch ├── 5.16-dkms.patch ├── LICENSE.md ├── Makefile └── README.md /495.46-pcie-rebar.patch: -------------------------------------------------------------------------------- 1 | --- nv-pci.c 2022-01-08 23:12:19.137095516 +0000 2 | +++ /usr/src/nvidia-495.46/nvidia/nv-pci.c 2022-01-09 02:49:25.500844951 +0000 3 | @@ -217,7 +217,83 @@ 4 | 5 | 6 | 7 | +#define NV_GPU_BAR1 1 8 | +#define NV_GPU_BAR3 3 9 | +static int nv_resize_pcie_bars(struct pci_dev *pci_dev) { 10 | + struct pci_host_bridge *host; 11 | + u16 cmd; 12 | + int r, old_size, requested_size; 13 | + int ret = 0; 14 | + 15 | + // Check if BAR1 has PCIe rebar capabilities 16 | + u32 sizes = pci_rebar_get_possible_sizes(pci_dev, NV_GPU_BAR1); 17 | + if (sizes == 0) { 18 | + /* ReBAR not available. Nothing to do. */ 19 | + return 0; 20 | + } 21 | 22 | + /* Try to resize the BAR to the largest supported size */ 23 | + requested_size = fls(sizes) - 1; 24 | + 25 | + /* If the kernel will refuse us, don't even try to resize, 26 | + but give an informative error */ 27 | + host = pci_find_host_bridge(pci_dev->bus); 28 | + if (host->preserve_config) { 29 | + nv_printf(NV_DBG_INFO, "NVRM: Not resizing BAR because the firmware forbids moving windows.\n"); 30 | + return 0; 31 | + } 32 | + 33 | + nv_printf(NV_DBG_INFO, "NVRM: %04x:%02x:%02x.%x: Attempting to resize BAR1.\n", 34 | + NV_PCI_DOMAIN_NUMBER(pci_dev), NV_PCI_BUS_NUMBER(pci_dev), 35 | + NV_PCI_SLOT_NUMBER(pci_dev), PCI_FUNC(pci_dev->devfn)); 36 | + 37 | + /* Disable memory decoding - required by the kernel APIs */ 38 | + pci_read_config_word(pci_dev, PCI_COMMAND, &cmd); 39 | + pci_write_config_word(pci_dev, PCI_COMMAND, cmd & ~PCI_COMMAND_MEMORY); 40 | + 41 | + /* Release BAR1 */ 42 | + pci_release_resource(pci_dev, NV_GPU_BAR1); 43 | + 44 | + /* Release BAR3 - we don't want to resize it, it's in the same bridge, so we'll want to move it */ 45 | + pci_release_resource(pci_dev, NV_GPU_BAR3); 46 | + 47 | + /* Save the current size, just in case things go wrong */ 48 | + old_size = pci_rebar_bytes_to_size(pci_resource_len(pci_dev, NV_GPU_BAR1)); 49 | + 50 | +resize: 51 | + /* Attempt to resize BAR1 to the largest supported size */ 52 | + r = pci_resize_resource(pci_dev, NV_GPU_BAR1, requested_size); 53 | + 54 | + if (r) { 55 | + if (r == -ENOSPC) 56 | + nv_printf(NV_DBG_ERRORS, "NVRM: No address space to allocate resized BAR1.\n"); 57 | + else if (r) 58 | + nv_printf(NV_DBG_ERRORS, "NVRM: BAR resizing failed with error `%d`.\n", r); 59 | + } 60 | + 61 | + /* Re-attempt assignment of PCIe resources */ 62 | + pci_assign_unassigned_bus_resources(pci_dev->bus); 63 | + 64 | + if ((pci_resource_flags(pci_dev, NV_GPU_BAR1) & IORESOURCE_UNSET) || 65 | + (pci_resource_flags(pci_dev, NV_GPU_BAR3) & IORESOURCE_UNSET)) { 66 | + if (requested_size != old_size) { 67 | + /* Try to get the BAR back with the original size */ 68 | + requested_size = old_size; 69 | + goto resize; 70 | + } 71 | + /* Something went horribly wrong and the kernel didn't manage to re-allocate BAR1. 72 | + This is unlikely (because we had space before), but can happen. */ 73 | + nv_printf(NV_DBG_ERRORS, "NVRM: FATAL: Failed to re-allocate BAR1.\n"); 74 | + ret = -ENODEV; 75 | + goto done; 76 | + } 77 | + 78 | +done: 79 | + /* Re-enable memory decoding */ 80 | + pci_write_config_word(pci_dev, PCI_COMMAND, cmd); 81 | + 82 | + return ret; 83 | +} 84 | 85 | /* find nvidia devices and set initial state */ 86 | static int 87 | @@ -428,6 +504,12 @@ 88 | goto failed; 89 | } 90 | 91 | + if (nv_resize_pcie_bars(pci_dev)) { 92 | + nv_printf(NV_DBG_ERRORS, 93 | + "NVRM: Fatal Error while attempting to resize PCIe BARs.\n"); 94 | + goto failed; 95 | + } 96 | + 97 | NV_KMALLOC(nvl, sizeof(nv_linux_state_t)); 98 | if (nvl == NULL) 99 | { 100 | -------------------------------------------------------------------------------- /5.16-dkms.patch: -------------------------------------------------------------------------------- 1 | --- a/kernel/nvidia-uvm/uvm_migrate_pageable.c 2022-01-08 21:51:32.672454683 +0100 2 | +++ b/kernel/nvidia-uvm/uvm_migrate_pageable.c 2022-01-08 21:51:52.298644944 +0100 3 | @@ -406,7 +406,7 @@ 4 | uvm_push_set_flag(&push, UVM_PUSH_FLAG_CE_NEXT_MEMBAR_NONE); 5 | copying_gpu->parent->ce_hal->memset_8(&push, dst_address, 0, PAGE_SIZE); 6 | 7 | - dst[i] = migrate_pfn(page_to_pfn(dst_page)) | MIGRATE_PFN_LOCKED; 8 | + dst[i] = migrate_pfn(page_to_pfn(dst_page)); 9 | } 10 | 11 | if (copying_gpu) { 12 | @@ -490,7 +490,7 @@ 13 | uvm_push_set_flag(&push, UVM_PUSH_FLAG_CE_NEXT_MEMBAR_NONE); 14 | copying_gpu->parent->ce_hal->memcopy(&push, dst_address, src_address, PAGE_SIZE); 15 | 16 | - dst[i] = migrate_pfn(page_to_pfn(dst_page)) | MIGRATE_PFN_LOCKED; 17 | + dst[i] = migrate_pfn(page_to_pfn(dst_page)); 18 | } 19 | 20 | // TODO: Bug 1766424: If the destination is a GPU and the copy was done by 21 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022: Julia Computing Inc 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | sudo patch -N /usr/src/nvidia-495.46/nvidia-uvm/uvm_migrate_pageable.c 5.16-dkms.patch || echo "patch failed or already applied" 3 | sudo patch -N /usr/src/nvidia-495.46/nvidia/nv-pci.c 495.46-pcie-rebar.patch || echo "patch failed or already applied" 4 | sudo dkms uninstall -m nvidia -v 495.46 || echo "dkms uninstall failed, probably not yet installed" 5 | sudo dkms remove -m nvidia -v 495.46 || echo "dkms remove failed, probably not yet installed" 6 | sudo dkms add -m nvidia -v 495.46 || echo "dkms add failed, probably already added" 7 | sudo dkms build -m nvidia -v 495.46 8 | sudo dkms install -m nvidia -v 495.46 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PCIe ReBAR patch for the Linux NVIDIA kernel driver 2 | 3 | Resizable BAR support is a PCIe extension that allows resizing a PCIe device's 4 | mappable memory/register space (also referred to as BARs - after the Base 5 | Address Register that sets up the region). An important use case are GPUs. 6 | While data center GPUs, generally have BAR sizes that match the size of 7 | video memory, consumer and workstation GPUs generally declare only have 256MiB worth 8 | of BARs mapping GPU memory to maintain compatibility with 32bit operating systems. 9 | However, for performance (particularly when using PCIe P2P), it is desirable to be 10 | able to map the entirety of GPU memory, necessitating resizable BARs. 11 | 12 | However, while PCIe ReBAR has been a standard for more than 10 years, it was ill 13 | used until a few years ago and thus support is lacking. On very recent motherboards 14 | (generally after 2020), a BIOS update might be available that causes the firmware 15 | to read and reserve space for a ReBAR expansion (or even perform the BAR resize 16 | itself). However, older motherbards do not have this support. 17 | 18 | Fortunately for us, the Linux kernel has some support to do its own PCIe enumeration 19 | without relying on the firmware to do everything. Linux even has support for resizable 20 | BARs, though in practice there are a number of important limitations: 21 | 22 | - There is currently no support for movable BARs in Linux. This means that if there 23 | are adjacent address space allocations, it is quite possible for BAR resizing to fail. 24 | 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. 25 | 26 | - The resize must be explicitly requested by the driver, which the official NVidia linux 27 | kernel driver currently does not do. The patch in this repository address this part. 28 | 29 | ## Requirements 30 | 31 | This is tested with: 32 | - NVidia 495.46 Drivers 33 | - Linux 5.16 34 | 35 | --------------------------------------------------------------------------------