La E/S mapeada en memoria ( MMIO ) y la E/S mapeada en puerto ( PMIO ) son dos métodos complementarios para realizar entrada/salida (E/S) entre la unidad central de procesamiento (CPU) y los dispositivos periféricos en una computadora (a menudo mediando el acceso a través del chipset ). Un enfoque alternativo es usar procesadores de E/S dedicados, comúnmente conocidos como canales en las computadoras mainframe , que ejecutan sus propias instrucciones .
La E/S mapeada en memoria utiliza el mismo espacio de direcciones para direccionar tanto la memoria principal [a] como los dispositivos de E/S . [1] La memoria y los registros de los dispositivos de E/S se mapean a (asocian con) valores de dirección, por lo que una dirección de memoria puede hacer referencia a una parte de la RAM física o a la memoria y los registros del dispositivo de E/S. Por lo tanto, las instrucciones de la CPU utilizadas para acceder a la memoria (por ejemplo, MOV ...
) también se pueden utilizar para acceder a los dispositivos. Cada dispositivo de E/S supervisa el bus de direcciones de la CPU y responde a cualquier acceso de la CPU a una dirección asignada a ese dispositivo, conectando el bus del sistema al registro de hardware del dispositivo deseado , o utiliza un bus dedicado.
Para acomodar los dispositivos de E/S, algunas áreas del bus de direcciones utilizadas por la CPU deben reservarse para E/S y no deben estar disponibles para la memoria física normal; el rango de direcciones utilizadas para los dispositivos de E/S está determinado por el hardware. La reserva puede ser permanente o temporal (como se logra mediante la conmutación de bancos ). Un ejemplo de esto último se encuentra en el Commodore 64 , que utiliza una forma de mapeo de memoria para hacer que la RAM o el hardware de E/S aparezcan en el 0xD000-0xDFFF
rango.
La E/S mapeada por puerto suele utilizar una clase especial de instrucciones de CPU diseñadas específicamente para realizar E/S, como las instrucciones in
y out
que se encuentran en los microprocesadores basados en la arquitectura x86 . Diferentes formas de estas dos instrucciones pueden copiar uno, dos o cuatro bytes ( outb
, outw
y outl
, respectivamente) entre el registro EAX o una de las subdivisiones de ese registro en la CPU y una dirección de puerto de E/S especificada que se asigna a un dispositivo de E/S. Los dispositivos de E/S tienen un espacio de direcciones separado de la memoria general, ya sea mediante un pin de "E/S" adicional en la interfaz física de la CPU o un bus completo dedicado a E/S. Debido a que el espacio de direcciones para E/S está aislado del de la memoria principal, a esto a veces se lo denomina E/S aislada. [2] En la arquitectura x86, el par índice/datos se utiliza a menudo para la E/S mapeada por puerto. [3]
Los diferentes métodos de comunicación de CPU a dispositivo, como el mapeo de memoria, no afectan el acceso directo a la memoria (DMA) de un dispositivo, porque, por definición, DMA es un método de comunicación de memoria a dispositivo que pasa por alto la CPU.
Las interrupciones de hardware son otro método de comunicación entre la CPU y los dispositivos periféricos, sin embargo, por diversas razones, las interrupciones siempre se tratan por separado. Una interrupción es iniciada por el dispositivo, a diferencia de los métodos mencionados anteriormente, que son iniciados por la CPU. También es unidireccional, ya que la información fluye solo del dispositivo a la CPU. Por último, cada línea de interrupción lleva solo un bit de información con un significado fijo, a saber, "se ha producido un evento que requiere atención en un dispositivo en esta línea de interrupción".
Las operaciones de E/S pueden ralentizar el acceso a la memoria si se comparten los buses de dirección y datos. Esto se debe a que el dispositivo periférico suele ser mucho más lento que la memoria principal. En algunas arquitecturas, la E/S asignada a puertos funciona a través de un bus de E/S dedicado, lo que alivia el problema.
Una ventaja de la E/S mapeada en memoria es que, al descartar la complejidad adicional que trae la E/S de puerto, una CPU requiere menos lógica interna y, por lo tanto, es más barata, más rápida, más fácil de construir, consume menos energía y puede ser físicamente más pequeña; esto sigue los principios básicos de la computación con conjunto de instrucciones reducido y también es ventajoso en sistemas integrados . La otra ventaja es que, debido a que las instrucciones de memoria regulares se utilizan para direccionar dispositivos, todos los modos de direccionamiento de la CPU están disponibles para la E/S así como para la memoria, y las instrucciones que realizan una operación ALU directamente en un operando de memoria (cargar un operando desde una ubicación de memoria, almacenar el resultado en una ubicación de memoria o ambos) también se pueden usar con registros de dispositivos de E/S. Por el contrario, las instrucciones de E/S asignadas a puertos suelen ser muy limitadas y a menudo solo permiten operaciones simples de carga y almacenamiento entre registros de CPU y puertos de E/S, de modo que, por ejemplo, para agregar una constante a un registro de dispositivo asignado a un puerto se requerirían tres instrucciones: leer el puerto en un registro de CPU, agregar la constante al registro de CPU y escribir el resultado nuevamente en el puerto.
Como los procesadores de 16 bits se han vuelto obsoletos y se han reemplazado por procesadores de 32 y 64 bits en uso general, reservar rangos de espacio de direcciones de memoria para E/S es un problema menor, ya que el espacio de direcciones de memoria del procesador suele ser mucho mayor que el espacio requerido para todos los dispositivos de memoria y E/S en un sistema. Por lo tanto, se ha vuelto más práctico aprovechar los beneficios de la E/S mapeada en memoria. Sin embargo, incluso aunque el espacio de direcciones ya no sea una preocupación importante, ninguno de los métodos de mapeo de E/S es universalmente superior al otro, y habrá casos en los que el uso de E/S mapeadas en puertos aún sea preferible.
La E/S mapeada en memoria es la preferida en arquitecturas basadas en IA-32 y x86-64 porque las instrucciones que realizan la E/S basada en puerto están limitadas a un registro: EAX, AX y AL son los únicos registros a los que se pueden mover o sacar datos, y un valor inmediato del tamaño de un byte en la instrucción o un valor en el registro DX determina qué puerto es el puerto de origen o destino de la transferencia. [4] [5] Dado que cualquier registro de propósito general puede enviar o recibir datos hacia o desde la memoria y los dispositivos de E/S mapeados en memoria, la E/S mapeada en memoria utiliza menos instrucciones y puede ejecutarse más rápido que la E/S de puerto. AMD no extendió las instrucciones de E/S de puerto al definir la arquitectura x86-64 para soportar puertos de 64 bits, por lo que no se pueden realizar transferencias de 64 bits utilizando la E/S de puerto. [6]
En las plataformas Intel más nuevas a partir de la serie 5 de 2008 , los dispositivos de E/S del chipset se comunican directamente a través de un bus de interfaz de medios directos (DMI) dedicado. [b] [7]
Dado que las cachés median los accesos a las direcciones de memoria, los datos escritos en diferentes direcciones pueden llegar a la memoria o los registros de los periféricos fuera del orden del programa, es decir, si el software escribe datos en una dirección y luego escribe datos en otra dirección, el búfer de escritura de la caché no garantiza que los datos llegarán a los periféricos en ese orden. [8] Cualquier programa que no incluya instrucciones de vaciado de caché después de cada escritura en la secuencia puede ver efectos de E/S no deseados si un sistema de caché optimiza el orden de escritura. Las escrituras en la memoria a menudo se pueden reordenar para reducir la redundancia o para hacer un mejor uso de los ciclos de acceso a la memoria sin cambiar el estado final de lo que se almacenó; mientras que las mismas optimizaciones pueden cambiar por completo el significado y el efecto de las escrituras en las regiones de E/S asignadas a la memoria.
La falta de previsión en la elección de las regiones de E/S asignadas a la memoria condujo a muchas de las barreras de capacidad de RAM en generaciones anteriores de computadoras. Los diseñadores rara vez esperaban que las máquinas crecieran para hacer un uso completo de la capacidad de RAM teórica de una arquitectura y, por lo tanto, a menudo usaban algunos de los bits de orden superior del espacio de direcciones como selectores para funciones de E/S asignadas a la memoria. Por ejemplo, la barrera de 640 KB en el IBM PC y derivados se debe a la reserva de la región entre 640 y 1024 KB (segmentos de 64k del 10 al 16) para el Área de memoria superior . Esta elección inicialmente tuvo poco impacto, pero eventualmente limitó la cantidad total de RAM disponible dentro del espacio de direcciones disponible de 20 bits. La barrera de 3 GB y el agujero PCI son manifestaciones similares de esto con espacios de direcciones de 32 bits, exacerbados por detalles del proceso de arranque x86 y el diseño de MMU . Las arquitecturas de 64 bits a menudo tienen problemas técnicos similares, pero estos solo rara vez tienen consecuencias prácticas.
Un sistema simple construido alrededor de un microprocesador de 8 bits podría proporcionar líneas de dirección de 16 bits, lo que le permitiría direccionar hasta 64 kibibytes (KiB) de memoria. En un sistema de este tipo, los primeros 32 KiB de espacio de dirección pueden asignarse a la memoria de acceso aleatorio (RAM), otros 16 KiB a la memoria de solo lectura (ROM) y el resto a una variedad de otros dispositivos, como temporizadores, contadores, chips de visualización de video, dispositivos generadores de sonido, etc.
El hardware del sistema está organizado de tal manera que los dispositivos en el bus de direcciones solo responderán a direcciones específicas que están destinadas a ellos, mientras que todas las demás direcciones se ignorarán. Esta es la tarea del circuito de decodificación de direcciones , y es la que establece el mapa de memoria del sistema. Como resultado, el mapa de memoria del sistema puede verse como en la tabla de la derecha. Este mapa de memoria contiene espacios vacíos, lo que también es bastante común en las arquitecturas de sistemas actuales.
Suponiendo que el cuarto registro del controlador de video establece el color de fondo de la pantalla, la CPU puede establecer este color escribiendo un valor en la ubicación de memoria A003 utilizando su instrucción de escritura de memoria estándar. Utilizando el mismo método, los gráficos se pueden mostrar en una pantalla escribiendo valores de caracteres en un área especial de RAM dentro del controlador de video. Antes de la RAM barata que permitía pantallas de mapa de bits , este método de celda de caracteres era una técnica popular para las pantallas de video de computadora (consulte Interfaz de usuario de texto ).
Los tipos de decodificación de direcciones, en los que un dispositivo puede decodificar direcciones de forma completa o incompleta, incluyen los siguientes:
En computadoras basadas en Windows, también se puede acceder a la memoria a través de controladores específicos como DOLLx8KD que brinda acceso de E/S en 8, 16 y 32 bits en la mayoría de las plataformas Windows desde Windows 95 hasta Windows 7. La instalación de controladores de puerto de E/S garantizará el acceso a la memoria activando los controladores con simples llamadas DLL que permiten la E/S del puerto y, cuando no es necesario, el controlador se puede cerrar para evitar el acceso no autorizado a los puertos de E/S.
Linux ofrece la utilidad pcimem para permitir la lectura y escritura en direcciones MMIO. El núcleo de Linux también permite rastrear el acceso a MMIO desde módulos del núcleo (controladores) mediante la función de depuración mmiotrace del núcleo . Para habilitar esto, el núcleo de Linux debe compilarse con la opción correspondiente habilitada. mmiotrace se utiliza para depurar controladores de dispositivos de código cerrado.