Pues bien, en ese PC hay 2Gb de RAM, algo escasos, y una gráfica nVidia GeForce 210 con 512Mb de vídeo, conectada por PCI-e.
Dándole vueltas al asunto, con tan poca RAM y tanta vRAM sin usar, ¿podría aprovechar esa vRAM? La respuesta, en Linux, es "evidentemente sí".
Así llegué a la tecnología MTD de Linux, y su posibilidad para crear un dispositivo de bloques con ella. Y en ese dispositivo crear una unidad Swap con máxima prioridad.
Se trata de crear un dispositivo de bloques en la memoria de vídeo sobrante de la tarjeta. Luego podemos usarlo como deseemos, en mi caso, como unidad swap.
1. Detectar el PCI ID de la tarjeta
Usamos el comando lspci para ver todos nuestros dispositivos PCI. En el listado buscamos la tarjeta que queremos usar y copiamos su ID:
Código: Seleccionar todo
root@NAS:/home/nas# lspci
00:00.0 Host bridge: Advanced Micro Devices, Inc. [AMD/ATI] RX780/RX790 Host Bridge
00:02.0 PCI bridge: Advanced Micro Devices, Inc. [AMD/ATI] RX780/RD790 PCI to PCI bridge (external gfx0 port A)
00:0a.0 PCI bridge: Advanced Micro Devices, Inc. [AMD/ATI] RD790 PCI to PCI bridge (PCI express gpp port F)
00:11.0 SATA controller: Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 SATA Controller [AHCI mode]
00:12.0 USB controller: Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 USB OHCI0 Controller
00:12.1 USB controller: Advanced Micro Devices, Inc. [AMD/ATI] SB7x0 USB OHCI1 Controller
00:12.2 USB controller: Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 USB EHCI Controller
00:13.0 USB controller: Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 USB OHCI0 Controller
00:13.1 USB controller: Advanced Micro Devices, Inc. [AMD/ATI] SB7x0 USB OHCI1 Controller
00:13.2 USB controller: Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 USB EHCI Controller
00:14.0 SMBus: Advanced Micro Devices, Inc. [AMD/ATI] SBx00 SMBus Controller (rev 3c)
00:14.1 IDE interface: Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 IDE Controller
00:14.2 Audio device: Advanced Micro Devices, Inc. [AMD/ATI] SBx00 Azalia (Intel HDA)
00:14.3 ISA bridge: Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 LPC host controller
00:14.4 PCI bridge: Advanced Micro Devices, Inc. [AMD/ATI] SBx00 PCI to PCI Bridge
00:14.5 USB controller: Advanced Micro Devices, Inc. [AMD/ATI] SB7x0/SB8x0/SB9x0 USB OHCI2 Controller
00:18.0 Host bridge: Advanced Micro Devices, Inc. [AMD] K8 [Athlon64/Opteron] HyperTransport Technology Configuration
00:18.1 Host bridge: Advanced Micro Devices, Inc. [AMD] K8 [Athlon64/Opteron] Address Map
00:18.2 Host bridge: Advanced Micro Devices, Inc. [AMD] K8 [Athlon64/Opteron] DRAM Controller
00:18.3 Host bridge: Advanced Micro Devices, Inc. [AMD] K8 [Athlon64/Opteron] Miscellaneous Control
01:00.0 VGA compatible controller: NVIDIA Corporation GT218 [GeForce 210] (rev a2)
01:00.1 Audio device: NVIDIA Corporation High Definition Audio Controller (rev a1)
02:00.0 Ethernet controller: Realtek Semiconductor Co., Ltd. RTL8111/8168/8411 PCI Express Gigabit Ethernet Controller (rev 03)
2. Tomamos nota de los bloques de memoria
Volvemos a usar lspci, con las opciones -v y -s y el PCI ID de la tarjeta de video para extraer los detalles de los bloques de VRAM accesibles. Aquí seguramente haya varios bloques y no aparezca toda la VRAM, es normal y desgraciadamente solo tendremos acceso a los que aparezcan. Nos interesan los bloques grandes marcados como "prefetchable".
Código: Seleccionar todo
root@NAS:/home/nas# lspci -v -s 01:00.0
01:00.0 VGA compatible controller: NVIDIA Corporation GT218 [GeForce 210] (rev a2) (prog-if 00 [VGA controller])
Subsystem: ASUSTeK Computer Inc. GT218 [GeForce 210]
Flags: bus master, fast devsel, latency 0, IRQ 18, NUMA node 0
Memory at fb000000 (32-bit, non-prefetchable) [size=16M]
Memory at c0000000 (64-bit, prefetchable) [size=256M]
Memory at de000000 (64-bit, prefetchable) [size=32M]
I/O ports at ef00 [size=128]
Expansion ROM at 000c0000 [virtual] [disabled] [size=128K]
Capabilities: [60] Power Management version 3
Capabilities: [68] MSI: Enable- Count=1/1 Maskable- 64bit+
Capabilities: [78] Express Endpoint, MSI 00
Capabilities: [b4] Vendor Specific Information: Len=14 <?>
Capabilities: [100] Virtual Channel
Capabilities: [128] Power Budgeting <?>
Capabilities: [600] Vendor Specific Information: ID=0001 Rev=1 Len=024 <?>
Kernel driver in use: nvidia
Kernel modules: nvidia
Código: Seleccionar todo
Memory at c0000000 (64-bit, prefetchable) [size=256M]
3. Configuramos el módulo phram
Usa los valores del punto anterior para configurar el módulo phram según tus necesidades.
Block Addres: es la dirección inicial del bloque de VRAM de la tarjeta. En el caso anterior es c0000000
Block size, in Mbytes: El tamaño del bloque en MBytes. En el caso anterior es 256
Reserved size, in Mbytes: Hay que dejar unos Mbytes para la memoria de vídeo, aunque sea para el modo texto. Como he dicho, dejaré 32Mbytes.
En la siguiente calculadora podéis extraer los valores para configurar el módulo. Los valores los guardaremos en un archivo nuevo que llamaremos /etc/modprobe.d/vram-swap.conf
Nos dará algo como:
Código: Seleccionar todo
options phram phram=swap,0xc2000000,224Mi
Si queréis añadir mas de un bloque podéis hacerlo repitiendo la calculadora y añadiendo el nuevo bloque detrás cambiando su nombre. Por ejemplo:
Código: Seleccionar todo
options phram phram=swap,0xc2000000,224Mi phram=swapB,0xff000000,64Mi
4. Configuramos las X
Especialmente importante si usamos las X, creamos el archivo /etc/X11/xorg.conf.d/vramswap.conf y añadimos la limitación de VRAM a la que hemos reservado en el punto anterior, en mi ejemplo, 32Mb:
Código: Seleccionar todo
Section "Device"
Driver "nvidia" # or whichever other driver you use
VideoRam 32768
EndSection
5. Probamos que todo funcione correctamente
Ahora cargaremos los módulos manualmente para probar que todo funcione correctamente:
Código: Seleccionar todo
root@NAS:/home/nas# modprobe phram
root@NAS:/home/nas# modprobe mtdblock
root@NAS:/home/nas# mkswap /dev/mtdblock0
root@NAS:/home/nas# swapon /dev/mtdblock0 -p 10
Ahora lo ideal sería estresar el sistema o usarlo a fondo durante un rato, para comprobar que sea estable.
Si hay inestabilidad podemos aumentar el margen de memoria reservada del punto 3.
6. Configuramos todo para el arranque del sistema
Editamos el archivo /etc/modules-load.d/vramswap.conf y añadimos los módulos para que se carguen automáticamente al arrancar el sistema:
Código: Seleccionar todo
phram
mtdblock
Luego creamos el servicio systemd para que inicie todo automáticamente:
Editamos el archivo /usr/lib/systemd/system/vramswap.service
Código: Seleccionar todo
[Unit]
Description=Swap on Video RAM
[Service]
Type=oneshot
ExecStart=/usr/sbin/mkswap /dev/mtdblock0
ExecStart=/usr/sbin/swapon /dev/mtdblock0 -p 10
ExecStop=/usr/sbin/swapoff /dev/mtdblock0
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
Código: Seleccionar todo
[Unit]
Description=Swap on Video RAM
[Service]
Type=oneshot
ExecStart=/usr/sbin/mkswap /dev/mtdblock0
ExecStart=/usr/sbin/swapon /dev/mtdblock0 -p 10
ExecStart=/usr/sbin/mkswap /dev/mtdblock1
ExecStart=/usr/sbin/swapon /dev/mtdblock1 -p 10
ExecStop=/usr/sbin/swapoff /dev/mtdblock0
ExecStop=/usr/sbin/swapoff /dev/mtdblock1
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
Y lo activamos en el arranque:
Código: Seleccionar todo
root@NAS:/home/nas# systemctl enable vramswap
Con ésto tendremos todo el sistema configurado para usar esa memoria de video sobrante como SWAP con cada reinicio.
Fuente: https://wiki.archlinux.org/title/Swap_on_video_RAM