En este artículo, me gustaría considerar los mecanismos para entregar interrupciones desde dispositivos externos en el sistema x86 e intentar responder las preguntas:
- ¿Qué es PIC y para qué sirve?
- ¿Qué es APIC y para qué sirve? ¿Para qué sirven LAPIC y I / O APIC?
- ¿Cuáles son las diferencias entre APIC, xAPIC y x2APIC?
- ¿Qué es el MSI? ¿Cuáles son las diferencias entre MSI y MSI-X?
- ¿Cómo se relacionan las tablas $ PIR, MPtable, ACPI con esto?
Si está interesado en recibir una respuesta a cualquiera de estas preguntas o si solo desea familiarizarse con la evolución de los controladores de interrupción en el sistema x86, bienvenido a cat.
Introduccion
Todos sabemos lo que es la interrupción. Para aquellos que no lo son, cita de wikipedia:
Interrupción (interrupción en inglés): una señal del software o hardware que informa al procesador sobre la ocurrencia de cualquier evento que requiera atención inmediata. La interrupción notifica al procesador la ocurrencia de un evento de alta prioridad que requiere la interrupción del código actual ejecutado por el procesador. El procesador responde suspendiendo su actividad actual, manteniendo su estado y ejecutando una función llamada controlador de interrupción (o controlador de interrupción) que responde al evento y lo sirve, después de lo cual devuelve el control al código interrumpido.
Dependiendo de la fuente de la señal de interrupción, se dividen en:
- Eventos asíncronos o externos (hardware) que se originan en dispositivos de hardware externos (como dispositivos periféricos) y pueden ocurrir en cualquier momento arbitrario: una señal de un temporizador, una tarjeta de red o unidad de disco, pulsaciones de teclas, movimientos del mouse. El hecho de que tal interrupción ocurra en el sistema se interpreta como una solicitud de interrupción (IRQ): los dispositivos informan que requieren atención del sistema operativo;
- eventos síncronos o internos en el propio procesador como resultado de la violación de ciertas condiciones al ejecutar código de máquina: división por cero o desbordamiento de pila, acceso a direcciones de memoria no válidas o código de operación no válido;
En este artículo, me gustaría hablar sobre las interrupciones IRQ externas.
¿Por qué son necesarios? Supongamos que queremos realizar alguna acción con un paquete de entrada para una tarjeta de red cuando llegue. Para no preguntar a la tarjeta de red constantemente "¿tiene un nuevo paquete?" y no desperdicie recursos del procesador en esto; puede usar la interrupción IRQ. La línea de interrupción del dispositivo está conectada a la línea INTR del procesador, y cuando se recibe un paquete, la tarjeta de red "tira" de esta línea. El procesador comprende que hay información y lee el paquete.
Pero, ¿qué pasa si hay muchos dispositivos? No puede tener suficiente de todos los dispositivos externos de las patas del procesador.

Para resolver este problema, se les ocurrió un chip, un controlador de interrupción.
Pic
(
wiki /
osdev )
El primero fue un chip
PIC Intel 8259 . 8 líneas de entrada (IRQ0-7) y una salida que conecta el controlador con la línea INTR del procesador. Cuando ocurre una interrupción de un dispositivo, 8259 tira de la línea INTR, el procesador comprende que algún dispositivo está señalando una interrupción y sondea el PIC para comprender qué rama IRQx causó la interrupción. Hay un retraso adicional para esta encuesta, pero el número de líneas de interrupción aumenta a 8.

Sin embargo, 8 líneas rápidamente resultaron ser pequeñas, y para aumentar su número, se comenzaron a utilizar 2 8259 controladores (maestro y esclavo) conectados en cascada (Dual PIC).
Las IRQ 0 a 7 son procesadas por el primer Intel 8259 PIC (maestro), y las IRQ 8 a 15 son procesadas por el segundo 8259 PIC (esclavo). Solo un maestro señala la ocurrencia de una interrupción. Si se produce una interrupción en las líneas 8-15, el segundo PIC (esclavo) señala una interrupción al maestro a través de IRQ 2, y el maestro a su vez señala a la CPU. Esta interrupción en cascada toma una de las 16 líneas, pero al final ofrece 15 interrupciones disponibles para los dispositivos.

El circuito se ha establecido, y esto es lo que quieren decir cuando hablan sobre PIC (Programm Interrupt Controller) ahora. Posteriormente, los controladores 8259 recibieron algunas mejoras y se conocieron como 8259A, y este circuito se incluyó en el conjunto de chips. En un momento en que el bus principal para conectar dispositivos externos era el bus ISA, dicho sistema en su conjunto era suficiente. Solo era necesario asegurarse de que diferentes dispositivos no se conectaran a la misma línea IRQ para evitar conflictos, ya que las interrupciones ISA no se comparten.
Por lo general, el diseño de las interrupciones para dispositivos era más o menos estándar
Ejemplo (tomado
de aquí ):
IRQ 0 - temporizador del sistema
IRQ 1 - controlador de teclado
IRQ 2 - cascada (interrupción desde el controlador esclavo)
IRQ 3 - puerto serie COM2
IRQ 4 - puerto serie COM1
IRQ 5 - puerto paralelo 2 y 3 o tarjeta de sonido
IRQ 6 - controlador de disquete
IRQ 7 - puerto paralelo 1
IRQ 8 - Temporizador RTC
IRQ 9 - ACPI
IRQ 10 - abierto / SCSI / NIC
IRQ 11 - abierto / SCSI / NIC
IRQ 12 - controlador de mouse
IRQ 13 - coprocesador matemático
IRQ 14 - ATA canal 1
IRQ 15 - ATA canal 2
La configuración y el trabajo con 8259 microcircuitos se realiza a través de puertos de E / S:
→ La documentación para el 8259A se puede encontrar
aquí.El bus ISA fue reemplazado por el bus PCI. Y el número de dispositivos claramente comenzó a exceder el número 15, además, a diferencia del bus ISA estático, en este caso, los dispositivos se pueden agregar al sistema dinámicamente. Pero afortunadamente en este bus se pueden compartir interrupciones (es decir, se pueden conectar varios dispositivos a la misma línea IRQ). Como resultado, para resolver el problema de la falta de líneas IRQ, decidieron agrupar las interrupciones de todos los dispositivos PCI en líneas PIRQ (solicitud de interrupción programable).
Digamos que tenemos 4 líneas de interrupción libremente en el controlador PIC y 20 dispositivos PCI. Combinamos las interrupciones de 5 dispositivos por línea PIRQx y conectamos las líneas PIRQx al controlador. Si se produce una interrupción en la línea PIRQx, el procesador tendrá que interrogar a todos los dispositivos conectados a esta línea para comprender de quién proviene la interrupción, pero en general esto resuelve el problema. Un dispositivo que une líneas de interrupción PCI en una línea PIRQ a menudo se denomina enrutador PIR.
En este método, debe asegurarse de que las líneas PIRQx no estén conectadas a las líneas IRQx en las que ya se han iniciado las interrupciones ISA (ya que esto provocará conflictos), y que las líneas PIRQx estén equilibradas (porque cuantos más dispositivos conectamos a la misma línea PIRQ, más dispositivos necesitará interrogará al procesador para comprender cuál de estos dispositivos causó la interrupción).
Nota : el dispositivo PCI -> el mapeo PIR se muestra de forma abstracta en la imagen, porque de hecho es algo más complicado. En realidad, cada dispositivo PCI tiene 4 líneas de interrupción (INTA, INTB, INTC, INTD). Cada dispositivo PCI puede tener hasta 8 funciones, y ahora cada función tiene una interrupción INTx. La configuración del chipset determina qué INTx obtendrá cada función del dispositivo.
En esencia, las funciones son bloques lógicos separados. Por ejemplo, en un dispositivo PCI puede haber una función de controlador Smbus, una función de controlador SATA, una función de puente LPC. En el lado del sistema operativo, cada función es un dispositivo separado con su propio espacio de configuración PCI Config.
El BIOS pasó la información sobre el enrutamiento de interrupción en el PIC al BIOS usando la tabla $ PIR y completando los registros 3Ch (INT_LN Interrupt Line (R / W)) y 3Dh (INT_PN Interrupt Pin (RO)) del espacio de configuración PCI para cada función. La especificación para la tabla $ PIR estaba anteriormente
en el sitio web de Microsoft , pero ahora ya no está allí. El contenido de las filas de la tabla $ PIR puede entenderse a partir de la
especificación PCI BIOS [4.2.2. Obtenga opciones de enrutamiento de interrupción PCI] o lea
aquíApic
(
wiki ,
osdev )
El método anterior funcionó hasta que aparecieron los sistemas multiprocesador. El hecho es que en su dispositivo PIC puede transmitir interrupciones a un solo procesador principal. Pero me gustaría que la carga en los procesadores del manejo de interrupciones sea equilibrada. La solución a este problema fue la nueva interfaz APIC (Advanced PIC).
Para cada procesador, se agrega un controlador LAPIC especial (APIC local) y un controlador
APIC de E / S para enrutar las interrupciones de los dispositivos. Todos estos controladores se combinan en un bus común llamado APIC (los nuevos sistemas ahora están conectados a través de un bus de sistema estándar).
Cuando una interrupción de un dispositivo llega al pin I / O APIC, el controlador dirige la interrupción al LAPIC de uno de los procesadores. La presencia de I / O APIC le permite equilibrar la distribución de interrupciones de dispositivos externos entre procesadores.
El primer chip APIC fue
82489DX , era un chip separado que combina LAPIC y I / O APIC. Para crear un sistema de 2 procesadores, se necesitaban 3 microcircuitos de este tipo. 2 funcionaría como LAPIC y uno como I / O APIC. Más tarde, la funcionalidad LAPIC se incluyó directamente en los procesadores, y la funcionalidad I / O APIC se enmarcó en el chip 82093AA.
El I / O APIC
82093AA contenía 24 pines de entrada, y la arquitectura APIC podía soportar hasta 16 CPU. Para mantener la compatibilidad con sistemas más antiguos, se asignaron 0 ~ 15 interrupciones a las interrupciones ISA anteriores. Y las interrupciones de los dispositivos PCI comenzaron a mostrarse en la línea IRQ 16-23. Ahora era posible no pensar en conflictos de interrupción de dispositivos ISA y PCI. Además, gracias al mayor número de líneas de interrupción libre, también ha sido posible aumentar el número de líneas PIRQx.

La programación I / O APIC y LAPIC se realiza a través de MMIO. Los registros LAPIC generalmente se encuentran en 0xFEE00000, los registros I / O APIC en 0xFE00000. Aunque, en principio, todas estas direcciones pueden reconfigurarse.
Como en el caso de PIC, inicialmente, los chips individuales luego se convirtieron en parte del conjunto de chips.
Posteriormente, la arquitectura APIC recibió modernización y la nueva versión se llamó xAPIC (x - extendida). Compatibilidad retenida con la versión anterior. El número de CPU posibles en el sistema aumentó a 256.
La siguiente ronda de desarrollo de arquitectura se llamó
x2APIC . El número de CPU posibles en el sistema aumentó a 2 ^ 32. Los controladores pueden funcionar en modo de compatibilidad xAPIC, o en el nuevo modo x2APIC, donde la programación LAPIC se lleva a cabo no a través de MMIO, sino a través de registros MSR (que es mucho más rápido). A juzgar
por este enlace, se requiere soporte de IOMMU para que este modo funcione.
Cabe señalar que el sistema puede tener varios controladores I / O APIC. Por ejemplo, uno por 24 interrupciones en el puente sur, el otro por 32 en el norte. En el contexto de las E / S, las interrupciones APIC a menudo se denominan GSI (Interrupción del sistema global). Entonces, en dicho sistema será GSI 0-55.
¿Existe un LAPIC incorporado en la CPU y qué arquitectura puede ser entendida por los indicadores de bit en la CPUID?
Para que el sistema detecte LAPIC y I / O APIC, el BIOS debe proporcionar información sobre ellos al sistema a través de MPtable (el método anterior) o de la tabla ACPI (MADT en este caso). Además de la información general, tanto MPtable como ACPI (esta vez en la tabla DSDT) deben contener información sobre las interrupciones de enrutamiento, es decir, información sobre qué dispositivo está en qué línea de interrupciones (análogo de la tabla $ PIR).
La tabla MPTable se puede encontrar en la
especificación oficial. Anteriormente, la especificación estaba en el sitio web de Intel, pero ahora solo se puede encontrar en el archivo. La especificación ACPI ahora se encuentra en el sitio web de UEFI (versión actual
6.2 ). Cabe señalar que con ACPI puede especificar el enrutamiento de interrupción para sistemas sin APIC (en lugar de usar la tabla $ PIR).
Msi
(
wiki )
La versión anterior con APIC es buena, pero no sin fallas. Todas estas líneas de interrupción del dispositivo complican los circuitos y aumentan la probabilidad de errores. El bus PCI fue reemplazado por PCI express, en el que simplemente se decidió eliminar las líneas de interrupción. Para mantener la compatibilidad, ciertos tipos de mensajes emulan las señales de interrupción (INTx #). En este esquema, la adición lógica de líneas de interrupción, que solía hacerse mediante la conexión física de los cables, recaía sobre los hombros de los puentes PCI. Sin embargo, el soporte de interrupción INTx heredado es solo soporte para la compatibilidad con el bus PCI. De hecho, PCI express ha propuesto un nuevo método para entregar mensajes de interrupción: MSI (interrupciones señalizadas por mensaje). En este método, para señalar una interrupción, el dispositivo simplemente escribe en el área MMIO asignada para el procesador LAPIC.

Anteriormente, solo se asignaban 4 interrupciones a un dispositivo PCI (es decir, a todas sus funciones), pero ahora es posible abordar hasta 32 interrupciones.
En el caso de MSI, no se comparten las líneas, cada interrupción corresponde a su dispositivo.
Las interrupciones de MSI también resuelven otro problema. Supongamos que un dispositivo realiza una transacción de escritura de memoria y desea informar su finalización a través de una interrupción. Pero una transacción de escritura puede retrasarse en el bus durante el proceso de transferencia (que el dispositivo desconoce en absoluto), y la señal de interrupción llegará antes que el procesador. Por lo tanto, la CPU seguirá leyendo datos no válidos. Si se usa MSI, se transmite información sobre MSI, así como datos, y simplemente no podrá llegar antes.
Cabe señalar que las interrupciones de MSI no pueden funcionar sin LAPIC, pero el uso de MSI puede reemplazarnos con I / O APIC (simplificación de diseño).
Posteriormente, este método recibió la extensión MSI-X. Ahora cada dispositivo puede tener hasta 2048 interrupciones. Y se hizo posible indicar individualmente a cada interrupción en qué procesador debería ejecutarse. Esto puede ser muy útil para dispositivos con mucha carga, como tarjetas de red.
No se requieren tablas de BIOS adicionales para el soporte de MSI. Pero el dispositivo debe informar el soporte de MSI en una de las capacidades en su configuración PCI, y el controlador del dispositivo debe admitir trabajar con MSI.
Conclusión
En este artículo, examinamos la evolución de los controladores de interrupción y recibimos información teórica general sobre la entrega de interrupciones desde dispositivos externos en un sistema x86.
En la
siguiente parte, veremos cómo usar en Linux cada uno de los controladores descritos en la práctica.
Referencias