Blog Personal.

Conceptos Básicos

Master Class sobre direccionamiento y acceso a memoria.

MMU

Las primeras CPUs de 8 y 16 bits solo soportaban direccionamiento físico pero con el tiempo de empezó a ver que esto era un problema para entornos multitarea con varios procesos ejecutandose al mismo tiempo. El problema que lleva consigo este tipo de direccionamiento es que un programa puede manipular los datos de otro a l y esto hace necesario un tipo de protección de memoria donde un programa no invada el espacio de memoria del otro porque incluso podría llegar a perjudicar al sistema operativo. Para ello se opto por implementar el direccionamiento virtual, siendo su primera implementación en los x86 con el 80286 al incluir una MMU que direccionaba la memoria por segmentos pero no se hizo muy popular y no fue hasta la llegada del 80386 que la MMU mejoro para soportar segmentos y páginas para el direccionamiento que los Sistemas Operativos en PC dieron un avance importante en lo que a calidad se refiere.

A partir del 80386 en adelante, todos los sistemas x86 incluyendo los de 64 bits utilizan direccionamiento lógico que es convertido en direccionamiento físico por la MMU para que la memoria pueda entender que dato ha de ha de buscar. Canonicamente el direccionamiento es de 48 bits en los sistemas de 64 bits que son lo que ahora mismo hay en el mercado. Los 48 bits son debido a que del direccionamiento de 64 bits hay unos 16 bits que son especiales y nos indican como se ha de tratar esa parte de la memoria.

  • NX (No Execute): El bit NX cuando esta activo nos indica que en esa direccción de memoria no hay código ejecutable y por tanto no interpretará cierto bits como instrucciones para la CPU.
  • Unos 3 bits se reservan para el sistema operativo y por tanto pueden significar una cosa u otra dependiendo del sistema operativo que estemos utilizando en ese momento,
  • G (iGnored): Le dice a la CPU que ignore esa página de memoria y pase a la siguiente.
  • S (Size): Marca el tamaño de la página de memoria (4KB o 4MB), el concepto de página de memoria os lo comentaré más adelante, no os preocupéis.
  • El valor del siguiente bit es siempre 0
  • A (Available): Marca si el dato ha sido accedido por otro proceso en ese momento, este bit es gestionado por el sistema operativo.
  • D (Dirty): Es utilizado para marcar que la página de memoria no tiene que copiarse en la cache.
  • El valor del siguiente bit es siempre 0.
  • W (Write): marca si la página se puede modificar (escritura).
  • U (User): Marca si es página de la memoria es accesible por el Sistema Operativo (Supervisor) o por las aplicaciones (Usuario).
  • R (Read): Marca si la página de memoria puede ser leida. nos marca si podemos leer los datos de esa página.
  • P (Present): Este bit es marcado cuando queremos mover la página de memoria a un nivel inferior de la jerarquía de memoria.

Esto significa que los sistemas x86-64 pueden direccionar unos 48 bits, hay que tener en cuenta que el direccionamiento no es la memoria disponible en el sistema sino la forma en la que el procesador se comunica con la RAM. Toda CPU tiene dos tipos de pines:

  • Pins de Datos desde donde se trasmiten los datos.
  • Pins de Direccionamiento donde se le indica a la memoria donde se encuentra el dato.

El valor que transmiten los pins de direccionamiento es controlado por el contador de programa y van incrementando en 1 cada dirección de memoria a no ser que se cambie el valor del contador de programa con una instrucción de salto. ¿Y que indica para la RAM la dirección de memoria? Digamos que la memoria fisicamente se organiza en una tabla y cuando accedemos a un dato en concreto de forma directa, lo que hacemos es marcar en que fila y columna se encuentra, si por ejemplo nuestro direccionamiento es de 6 bits entonces la memoria podrá tener 64 elementos (26) de los cuales unos 3 bits me dirán la fila y otros 3 bits me dirán la columna de donde se encuentra el dato. Por lo que un direccionamiento de 48 bits de memoria nos da acceso a una tabla de 248 elementos donde cada elemento es un byte de memoria.

Pero el direccionamiento virtual no funciona apunta a direcciones de memoria de manera directa sino direcciones virtuales, las cuales se organizan por páginas de memoria.

El estándar a partir del 80386 era que cada página fuese de 4KB (212 bits del direccionamiento). A partir del Pentium Pro (P6) en adelante Intel añadió la capacidad de manejar páginas de 4MB de tamaño (222) pero hay que tener en cuenta que el kernel NT de Windows y el de Linux se crearon cuando esta opción no estaba disponible en los x86, por eso el tamaño estándar de las páginas esos sistemas operativos y de la mayoría es de 4KB ya que sus primeras versiones son Pre-Pentium Pro y por compatibilidad hacía atrás con las aplicaciones esto no ha cambiado y sus sistemas de archivo se siguen basando en páginas de 4KB que es lo que vamos a utilizar para entender el funcionamiento.

Imaginad la página como un documento escrito.

Dichos documentos/páginas se almacenan en la llamada Page Table, pensad en ello como una carpeta donde se guardan los documentos.

Pero existe un nivel más y la Page Table/Carpeta de Documentos es almacenada en el Page Directory que es como un armario fichero.

La dirección de memoria lógica empieza primero con los bits que indican el fichero, luego, luego la carpeta donde esta el fichero y más tarde el documento. La MMU no solo nos permite controlar el acceso a los documentos en concreto sino también podemos utilizar los mismos bits de control en el direccionamiento para controlar el acceso a nivel de la Page Table y la Page Directory, esto hace que la MMU como su nombre indica se encargue del manejo de la memoria, pero la MMU no lo hace inteligentemente sino que su gestión ha de ser llevada a cabo por el Sistema Operativo del sistema.

IOMMU y GPUMMU

¿Como interactuan los periféricos con la CPU? Pues utilizan la RAM como un punto en común para comunicarse entre ambas partes, el problema con ello es que estos al no compartir la MMU con la CPU pueden llegar a acceder a partes de la memoria RAM que pueden ser delicadas y es ahí donde entra la IOMMU que es lo mismo que la MMU pero para periféricos, siendo realmente la IOMMU en una unidad esclava de la MMU.

La IOMMU realmente esta comunicada con la MMU a través del Puente Norte/Northbridge del sistema y gracias a dicha comunicación la IOMMU sabe en que partes de la memoria RAM pueden acceder los periféricos y cuales no. Aparte que la da información a la CPU a que direcciones de memoria tiene que apuntar para comunicarse con los periféricos.

Antiguamente los sistemas no disponían de una IOMMU y se otorgaba con ellos un mapa de memoria donde se asignaban las direcciones de memoria que estaban pensadas para ciertas funciones de los periféricos y por tanto los programadores tenían muy claro que esas direcciones no se tenían que tocar. Pero con una IOMMU este problema desaparece ya que es esta la que se encarga junto a la MMU de que los periféricos no accedan a partes de la memoria del sistema que no deben sin que los programadores tengan que romperse la cabeza memorizando direcciones de memoria.

Mapa de Memoria del IBM PC original

Ahora bien, en un PC contemporáneo todos los periféricos independientemente de su naturaleza, ya sea el chip gráfico como un Disco Duro acceden a la memoria del sistema a través del IOMMU, el cual en el caso de los sistemas basados en arquitecturas Zen se encuentra en situado en el IO Hub que es donde se concentran todas las interfaces de E/S a la que van conectadas los periféricos, todo lo conectado interfaces como USB, PCI Express, SATA… Tiene que pasar por el IOMMU para acceder a memoria, esto incluye a las tarjetas gráficas que no son una excepción cuando estas necesitan acceder a la RAM del sistema, cosa que hacen por ejemplo para leer la lista o listas de comandos y por tanto de cosas a hacer.

Pero las GPUs en PC tienen su propia memoria local dado su formato en forma de tarjetas gráficas.

Pero el acceso a dicho memoria local y privada no es realizada a través de la IOMMU sino a través de una MMU propietaria de la GPU llamada GPUMMU, esto tiene lógica cuando tenemos dos espacios de memoria separados… ¿Pero que ocurre con la RAM unificada a nivel físico que es lo que ocurre en los SoC? Aquí la cosa es más complicada pero es importante explicarlo.

La GPUMMU en principio no sirve para acceder al mismo espacio de memoria/direccionamiento que la CPU sino a la memoria local que tenga asignada la GPU, ya sea con memoria propia a nivel físico y/o compartida.

En la relación entre la IOMMU y la MMU esta última marcará que páginas de memoria, directorios o ficheros son váidas para el acceso y como se puede acceder a ellas. Esta información es transmitida entre la IOMMU y la MMU para que el acceso a memoria sea coherente.Pero la GPUMMU no esta conectada al IOMMU ni tampoco a la MMU de otra manera, esto hace que no vea la memoria de la misma manera y tengan espacios de memoria distintos incluso con la misma memoria.

AMD en sus primeros SoC creo dos accesos hacía la memoria para la gPU. El Fusion Compute Link u Onion realizaba el acceso a través del IOMMU a la RAM mientras que el Radeon Memory Buso o Garlic lo hacía a través de la GPUMMU.

Este plantemiento fue llevado tal cual a Xbox One y PlayStation 4.

Como podéis ver la organización en los tres casos es la misma pero AMD en el mundo del PC empezó a. Esto hace que incluso aunque la RAM sea compartida a nivel físico esto hace a efectos prácticos no podamos acceder a la otra parcela de la memoria de manera directa, lo que lleva a tener que realizar movimientos de copia de datos de una parcela de memoria a otra.

AMD en PC decidió empezar a unificar el espacio de memoria tanto de la GPU con el de la CPU, pero esto supuso cambiar como funcionaba la GPUMMU y el acceso a memoria de la misma ya que la GPUMMU tenía su propia manera de ver la memoria que no es la misma que la de la MMU y la IOMMU, para empezar el contador de programa era de 40 bits (1TB de direccionamiento), debido a que la GPU no ejecuta un sistema operativo ni programas de la misma manera que una GPU los bits de control utilizados son distintos, por ejemplo la GPU para su propio manejo de memoria utilizaba algunos bits para control.

  • 1 bit si se marca nos sirve para copiar el dato en la Local Data Share de la Compute Unit.
  • 1 bit se se marca nos sirve para copiar el dato en la Global Data Share de la GPU.
  • 1 bit si se marca nos sirve para indicar que el dato va a ir a memoria a través de las unidades RBE(ROPS).
  • 1 bit si se marca nos sirve nos sirve para indicar que el dato NO va a ir a memoria a través de las unidades RBE(ROPS).

La GPUMMU además le da la capacidad de ver de manera virtual la memoria propia de la GPU por lo que también divide la memoria por páginas pero al contrario que en el estándar x86 donde las páginas son de 4KB o de 4MB en este caso son de 64KB (16 bits del direccionamiento) y esto es el motivo por el cual las texturas parcialmente residentes tienen este tamaño, porque la GPU cargaba hacía la cache páginas enteras de memoria de ese tamaño.

En PC a partir de Carrizo lo que hizo AMD fue añadir la Access Translation Cache o ATC en la jerarquía de memoria de la GPU.

La ATC traslada el direccionamiento al mismo direccionamiento que el del x86-64 y le permite ver la RAM de la misma manera que la CPU a la GPU por lo que pasa de tener un direccionamiento de 40 bits a uno de 48 bits.

La GPUMMU pasa a tener acceso al espacio de memoria de la CPU trayendo con ello tres ventajas asociadas:

  • No es necesario copiar los datos de una parcela a otra ya que ambos comparten la misma parcela, por lo que no es necesario utilizar mecanismos DMA para ello.
  • Permite operaciones GPGPU de apoyo a la CPU a con el máximo ancho de banda posible para la GPU
  • Se salta el acceso al direccionamiento común desde la IOMMU reduciendo la latencia.

Esto le permitió además AMD en los SoC de PC posteriores a Carrizo y los ya basados en Zen conectar la GPUMMU de manera directa el Northbridge/Data Fabric sin pasar por el IOMMU con tal de acceder al Northbridge.

Debido a que de esta manera la GPU tiene acceso al espacio de memoria del sistema también de manera indirecta se puede comunicar con los periféricos que utilizan ese espacio de memoria y por tanto esto le da acceso entre otra cosas al SSD del sistema en el caso de que haya uno, dado que la GPUMMU pasa a ser cliente del Northbridge/Data Fabric se puede comunicar con los otros clientes como el IOMMU.

Todo esto a simple vista elimina la necesidad del Fusion Compute Link para acceder a memoria, desde el mismo momento en que la visión es común con la GPUMMU entonces el FCL debería desaparecer por completo pero no es así, el FCL se sigue utilizando porque buena parte del código lo sigue utilizando aunque en los SoC de PC son una redundancia lo mismo ocurre con la unidad sDMA.

Esto es debido a que el código antiguo de la GPU sigue llamando a la unidad DMA y por tanto ha de estar con tal de evitar problemas. Además que la ATC para compatibilidad hacía atrás se puede desactivar por completo con un bit de control reservado, si ese bit esta activo entonces la ATC hará el traslado y la visión de memoria de la GPU será homogenea con la de la CPU, si no esta activo entonces será heterogénea.

Discos Duros, organización y acceso

En esta sección solo voy a tratar los Discos Duros mecánicos, se que las consolas de siguiente generación no los van a llevar pero para entender las ventajas del SSD hay que conocer la naturaleza de los discos duros convencionals.

Para empezar el Disco Duro al ser un medio circular rotatorio se organiza en una serie de circulos concentricos llamados «Pistas», en el que cada pista tiene una serie de «sectores» cuyo tamaño estándar es de 512 bytes, dependiendo del sistema de archivos utilizado en cada sistema se organizan las pistas en varios grupos de las mismas llamados clusters que es el tamaño mínimo que tiene un archivo dependiendo del sistema de archivos que utilice el sistema operativo, pero el tamaño de un archivo no puede ser menor que el de un cluster.

El problema con el Disco Duro es que dependiendo de la pista en la que se encuentre el dato la velocidad de acceso varia. Para las pistas más exteriores la velocidad de acceso a lo datos es más rápida pero es más lenta para las pistas que están más al interior debido a que el cabezal ha de cambiar de pista por lo que la latencia de acceso de los datos del Disco Duro depende de donde se encuentren estos. La controladora del Disco Duro cogerá la información que le hayan enviado y copiará en el búfer (un pequeño chip de RAM que tiene el Disco Duro) y enviará por el puerto los datos al Southbridge del sistema y de ahí los datos se enviarán a la RAM a través del IOMMU.

Debido a la lentitud del Disco Duro no se marcan como no-presentes por la MMU del sistema direcciones de memoria concretas sino páginas enteras que son copiadas en los clusters del disco duro y se crea una tabla que primero se almacena en la RAM del sistema y luego en el Disco Duroque indica en que pista y sector se encuentra la información por lo que si el dato no se encuentra en la RAM entonces tiene que consultar la tabla pasa saber que pedido le tiene que realizar al Disco Duro. La localización de dicha tabla la conoce solo el Sistema Operativo y dicha localización en memoria y en el disco dependerá del sistema operativo y el formato de la tabla dependerá del sistema de archivos del sistema operativo.

SSD y direccionamiento de memoria del mismo

Con la aparición del SSD las normas de almacenamiento masivo cambian por completo.

Los discos SSD utilizan RAM no volatil (NVRAM) o más conocida como memoria Flash, del tipo NAND. El hecho de que sea no-volatil significa que no se pierden los datos y el hecho de que sea RAM significa que al SSD se puede acceder a sus datos como si fuese memoria RAM y tratarla como una extensión de la misma de cara al direccionamiento y esto nos permite prescindir por completo de un sisema de archivos, al menos en teoría porque en PC no es así y los discos SSD se utilizan siguiendo la misma organización de direccionamiento que los Discos Duros pero sin la desventaja de estas como es la latencia variable según la posición de la pistas.

En PC, el SSD se encuentra conectado como todo periférico al IOMMU debido a que lo esta la interfaz SATA o PCIe que utilizamos. Esto hace que para los diferentes sistemas operativos en PC no sea más que un Disco Duro más rápido y aunque no sea necesario se siga utilizando el mismo direccionamiento que un Disco Duro y por tanto dividira la información en pistas, clusters y sectores.

Pero tanto en PlayStation 5 como en Xbox Series X es distinto, el controlador del SSD no esta conectado al IOMMU sino que esta conectado de manera directa el Northbridge/Data Fabric.

La ventaja de esto es que al contrario del Disco Duro que depende de un sistema de archivos que define el tamaño mínimo en un cluster aquí podemos enviar y recibir datos con el tamaño de una página de memoria dentro del direccionamiento virtual hacía el SSD, esto nos evita estar limitados al tamaño de un archivo/cluster para mover los datos y hace que no sea necesario un sistema de archivos para manejar la memoria, convirtiendo el manejo del espacio de memoria de cara a las aplicaciones en común con el SSD.

¿Pero significa esto que el SSD se utiliza como RAM? Pues NO.

Cuando una página conjunto de páginas no se encuentra disponible en la RAM y se necesita la lectura del mismo un co-procesador dedicado lo que hará será enviar la dirección de memoria de la página, page table o page directory que queramos y esta en la flash trasladará la dirección de memoria lógica. Esta traducción se ha de hacer porque pese a que el direccionamiento del sistema puede ser C donde este es la suma de A+B donde A es el espacio de la RAM y B el de la Nand Flash, en el caso del propio disco SSD su controlador solo ve B por lo que tiene que realizar el traslado del direccionamiento realizando una simple resta al direccionamiento para encontrar el dato, una vez encuentra el conjunto de datos lo envía haciendo el proceso del diagrama de más arriba hacía la izquierda. Para la escritura es distinta y el proceso se hace hacía la derecha del diagrama, los datos no se descomprimen sino que se comprimen.

Los juegos de la actual generación están pensados para un Disco Duro, esto implica dos escenarios posibles, el primero es que sea necesario un Disco Duro externo por el hecho que SSD no estará pensado para un sistema de archivos, el otro es simplemente que en modo de retrocompatibilidad la unidad DMA esta conectada al IOMMU y funcione como funcionan los discos SSD para PC, pero es algo que reduce enormemente las ventajas del SSD.

Esto es todo, tenéis el Discord y los comentarios de esta entrada para comentarla.

0 0 vote
Article Rating
3 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Set

Buen articulo, solo que es bastante confunso utilizar el termino ram par todo, ya que aveces se pierde a que memoria te estas refiriendo, si GPU o CPU, es importante dividir terminos Vram(Video Random Access Memory) y Ram Sistema. Sobre lo ultimo lo de utlizar el SSD como Ram, es en tema de uso de juegos y no de funcionamiento. Para ponernos en contexto la PS4 y One tienen memoria unificada Vram (GDDR5), en un juego hay datos primarios que se guardan Vram que es el acceso de memoria mas cercano de la GPU y de mas ancho de banda,… Read more »

Juan

Gracias x la entrada Urian!! De todo y bien explicado punto x punto! Cuánto trabajo q haces x todos nosotros! Te felicito x todo el esfuerzo q realizas

[…] en en la entrada Master Class sobre direccionamiento y acceso a memoria os comente como funciona el direccionamiento en los x86-64 y tenéis que tener en cuenta que un […]