Swap on video RAM
Article on utilizing video memory for system swap.
A graphics card with GDDR SDRAM or DDR SDRAM may be used as swap by using the MTD subsystem of the kernel. Systems with dedicated graphics memory of 256 MB or greater which also have limited amounts of system memory (DDR SDRAM) may benefit the most from this type of setup.
MTD is in the mainline kernel since version 2.6.23.
When you are running a kernel with MTD modules, you have to load the modules specifying the pci address ranges that correspond to the ram on your video card.
To find the available memory ranges run the following command and look for the VGA compatible controller section (see the example below).
$ lspci -vvv
01:00.0 VGA compatible controller: NVIDIA Corporation GK104 [GeForce GTX 670] (rev a1) (prog-if 00 [VGA controller]) Subsystem: ASUSTeK Computer Inc. Device 8405 Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR- FastB2B- DisINTx- Status: Cap+ 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx- Latency: 0 Interrupt: pin A routed to IRQ 57 Region 0: Memory at f5000000 (32-bit, non-prefetchable) [size=16M] Region 1: Memory at e8000000 (64-bit, prefetchable) [size=128M] Region 3: Memory at f0000000 (64-bit, prefetchable) [size=32M] Region 5: I/O ports at e000 [size=128] [virtual] Expansion ROM at f6000000 [disabled] [size=512K] Capabilities: <access denied> Kernel driver in use: nvidia Kernel modules: nouveau, nvidia
Of most potential benefit is a region that is prefetchable, 64-bit, and the largest in size.
A video card needs some of its memory to function, as such some calculations are needed. The offsets are easy to calculate as powers of 2. The card should use the beginning of the address range as a framebuffer for textures and such. However, if limited or as indicated in the beginning of this article, if two programs try to write to the same sectors, stability issues are likely to occur.
As an example: For a total of 256 MB of graphics memory, the forumla is 2^28 (two to the twenty-eighth power). Approximately 64 MB could be left for graphics memory and as such the start range for the swap usage of graphics memory would be calculated with the formula 2^26.
Using the numbers above, you can take the difference and determine a reseasonable range for usage as swap memory. leaving 2^24 (32M) for the normal function (less will work fine)
Configure the slram module:
options slram map=VRAM,0xStartRange,+0xUsedAmount
Load the modules on boot:
Create a systemd service:
[Unit] Description=Swap on Video RAM [Service] Type=oneshot ExecStart=/usr/bin/mkswap /dev/mtdblock0 ExecStart=/usr/bin/swapon /dev/mtdblock0 -p 10 ExecStop=/usr/bin/swapoff /dev/mtdblock0 RemainAfterExit=yes [Install] WantedBy=multi-user.target
Xorg driver config
To keep X stable, your video driver needs to be told to use less than the detected videoram.
Section "Device" Driver "radeon" # or whichever other driver you use VideoRam 32768 #other stuff EndSection
The above example specifies that you use 32 MB of graphics memory.
The following command may help you getting the used swap in the different spaces like disk partitions, flash disks and possibly this example of the swap on video ram
Now run the following commands as root to set up the vramfs and a swapfile.
vramfs /tmp/vram 256MB -f # Substitute 256M with your target vramfs size dd if=/dev/zero of=/tmp/vram/swapfile bs=1M count=200 # Substitute 200 with your target swapspace size in MB chmod 600 /tmp/vram/swapfile mkswap /tmp/vram/swapfile swapon /tmp/vram/swapfile
Your Swap should now be ready. Run
swapon to check.
See Swap#Swap file for more information.
/tmp/vramas temporary storage, much like a Tmpfs.
swapon: /tmp/vram/swapfile: skipping - it appears to have holes.
The swapfile created is not contiguous. A loop device can be set up to work around this issue.
cd /tmp/vram LOOPDEV=$(losetup -f) truncate -s 4G swapfile # replace 4G with target swapspace size, has to be smaller than the allocated vramfs losetup $LOOPDEV swapfile mkswap $LOOPDEV swapon $LOOPDEV