Una de las cosas que hace tan poderoso a linux es la incapacidad de distinguir entre un dispositivo y un archivo. Con la cantidad de memoria de video que están incorporando en la placas de video actuales, ¿Por que no asignar una buena tajada a un archivo (un nodo en este caso) y usarlo como memoria SWAP?
Pequeña gran aclaración al margen: Los drivers binarios de las placas de video no permiten especificar la cantidad de memoria que se quiere usar del total disponible si no que se hacen con el control de la totalidad de memoria. No se puede usar el driver de nvidia o de ati y usar la vez la memoria de video como SWAP, por que estarás pisando memoria de video con datos y viceversa con la consecuente corrupción de datos. El único driver que conozco que permite especificar la cantidad de memoria de video a utilizar es XF86-video-vesa, con lo que se pierde aceleración 3D.
Choose your poison: ¿Direct rendering o memoria SWAP rapidísima?
Partiendo de esa premisa, robado copiado en su momento del gran Blog de Stolz –Fuera de servicio en este momento– y complementado un poco con el metodo prueba y error y otro tanto con la Wiki de Gentoo, me dejo para cuando lo necesite de nuevo y para la posteridad: Como usar la memoria de nuestra tarjeta de video como memoria SWAP.
1. Configuración del Kernel
Antes que nada, necesitamos darle soporte a nuestro kernel para que pueda mapear la memoria de video al espacio PCI. El encargado de esto será el driver MTD. La configuración para cualquier kernel 2.6 es:
Device Drivers —>
<M> Memory Technology Device (MTD) support —>
<M> Direct char device access to MTD devices
<M> Common interface to block layer for MTD ‘translation layers
<M> Caching block device access to MTD devices Self-contained MTD device drivers —>
<M> Physical system RAM
Todos marcados como módulos, para poder llamarlos con modprobe mas adelante. Doy por sentado que si estás leyendo esto, sabés como recompilar tu kernel con las opciones nuevas. De no ser así: Google al rescate!
2. Encontrando la placa de video y su rango de memoria
Teniendo el kernel listo con las opciones necesarias, lo siguiente es ubicar la placa de video, puntualmente el BUS ID de la misma. El comando lspci (parte del paquete pciutils) será el encargado de darnos toda la información necesaria:
~ # lspci | grep VGA 01:00.0 VGA compatible controller: ATI Technologies Inc R350 AH
Lo que interesa es el BUS en donde se asienta la tarjeta de video según el BIOS, en mi caso 01:00.0. Tomen nota de este valor para usarlo mas adelante. Teniendo ese parámetro, necesitamos mas información sobre el hardware conectado en dicho BUS, la opción -vvv sobre el número de BUS hace al comando lspci tres veces mas verborrágico:
~ # lspci -vvv -s 01:00.0 01:00.0
VGA compatible controller: ATI Technologies Inc R350 AH [Radeon 9800] (prog-if 00 [VGA controller]) Subsystem: ATI Technologies Inc Device 0002 Control: I/O+ Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping+ SERR- FastB2B- DisINTx- Status: Cap+ 66MHz+ UDF- FastB2B+ ParErr- DEVSEL=medium >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx- Latency: 32 (2000ns min), Cache Line Size: 32 bytes Interrupt: pin A routed to IRQ 16 Region 0: Memory at d0000000 (32-bit, prefetchable) [size=256M] Region 1: I/O ports at c000 [size=256] Region 2: Memory at e1000000 (32-bit, non-prefetchable) [size=64K] [virtual] Expansion ROM at e0000000 [disabled] [size=128K] Capabilities: [58] AGP version 3.0 Status: RQ=256 Iso- ArqSz=0 Cal=0 SBA+ ITACoh- GART64- HTrans- 64bit- FW+ AGP3+ Rate=x4,x8 Command: RQ=1 ArqSz=0 Cal=0 SBA+ AGP- GART64- 64bit- FW- Rate=<none> Capabilities: [50] Power Management version 2 Flags: PMEClk- DSI- D1+ D2+ AuxCurrent=0mA PME(D0-,D1-,D2-,D3hot-,D3cold-) Status: D0 PME-Enable- DSel=0 DScale=0 PME-
Lo que estamos buscando es la region 0 que es la que indica dónde empieza el rango de memoria de video para poder direccionarlo:
Region 0: Memory at d0000000 (32-bit, prefetchable) [size=256M]
Que en mi caso comienza en d0000000, que sería el equivalente en hexadecimal a OxdOOOOOOO y dispone de 256Mb en total. De estos 256Mb totales, 16 los está usando el driver VESA:
~ # grep Total /var/log/Xorg.0.log (II) VESA(0): VESA VBE Total Mem: 16384 kB
Lo cual me deja con un total de 240Mb de memoria de video disponible para meter dentro lo que se me ocurra (por que no necesariamente tiene que ser memoria SWAP).
Es importante tener en cuenta que:
- Los datos almacenados en la ram de video son volatiles. Se pierden al reiniciar –incluído el sistema de archivos que se le haya dado.
- La cantidad de memoria de video direccionable por el kernel se ve limitada por el valor del parámetro AGP Aperture Size que se haya especificado en el BIOS.
- La cantidad de memoria de video que utilizará el driver vesa se puede configurar en el archivo /etc/X11/xorg.conf.
- La memoria de video no tiene ningún sistema de ECC, si hay una memoria rota la información contenida dentro se corromperá irremediablemente.
3. Un poco de matemáticas:
Tenemos entonces memoria de video direccionable a partir de OxDOOOOOOO. como los primeros 16Mb los usa VESA, calculamos: 16 * 1024 * 1024 = 1677216 que usando la calculadora de google he convertido a hexadecimal: Ox1OOOOOO
Para saber cual es la primera dirección de memoria disponible, basta entonces con sumar la primera disponible + los 16Mb que usa el driver vesa: OxDOOOOOOO + Ox1OOOOOO = OxEOOOOOOO y de ahí en adelante hasta los 240Mb.
4. Crear el dispositivo de bloques:
Creamos entonces el dispositivo, cuyo nombre arbitrario será VRAM y tendrá una capacidad de 240Mb en total:
~ # modprobe phram phram=VRAM,OxEOOOOOOO,240Mi
Al hacer esto ya debería existir un nuevo dispositivo: /dev/mtd* (donde el * tomará el primer valor disponible incrementalmente).
~ # ls /dev/mtd*
/dev/mtd0 /dev/mtd0ro
También se puede corroborar en /proc:
~ # cat /proc/mtd
dev: size erasesize name
mtd0: 0f000000 00001000 «VRAM»
Si usas udev basta con hacer:
~ # modprobe mtdchar
~ # modprobe mtdblock
Para que se genere el nodo al dispositivo /dev/mtdblock0 que es el que contiene el espacio utilizable.
De no ser así, se pueden crear ambos nodos a los dispositivos a mano:
~ # mknod /dev/mtd0 c 90 0
~ # mknod /dev/mtdblock0 b 31 0
Y listo! Ya tenemos el dispositivo de bloques listo para utilizar. Lo formateamos como espacio swap:
~ # mkswap /dev/mtdblock0
Y le avisamos al kernel que lo use como memoria swap de alta prioridad:
~ # swapon /dev/mtdblock0 -p 1
Cuanto mayor es el número, mayor la tendencia a hacer swap dentro del dispositivo en cuestión. Se puede corroborar de esta forma:
~ # swapon -s
Filename Type Size Used Priority
/dev/mtdblock0 partition 245752 184 1
/dev/sda2 partition 1060280 50740 -1
Tengo a la memoria de video con prioridad 1 y la partición que contiene la memoria swap sobre el disco rígido con prioridad -1.
¿Complicado? Resumamos entonces:
Quizás todo junto parece complicado hasta que se hace por primera vez. Teniendo todo listo, simplemente agregando a alguno de los guiones de arranque o con un script por separado:
modprobe phram phram=VRAM,OxEOOOOOOO,240Mi
modprobe mtdchar
modprobe mtdblockmkswap /dev/mtdblock0
swapon /dev/mtdblock0 -p 1
Y listo, el cambio es permamente. 5 líneas de código.
No era tan complicado al fin y al cabo ¿no?
1 comentario