Esta fue una gran curva de aprendizaje que aparentemente me ayudó a fomentar ideas más teóricas y conceptuales que rodean las teorías/leyes sobre los misterios subyacentes de los sistemas operativos y los núcleos. Suponía que tenía una buena idea sobre cómo funcionaba Oss. Sin embargo, crear mi propio sistema operativo fue absolutamente más definitivo en comparación con solo leer. En mi propia opinión honesta. Esta era una forma de comprender mejor el software con el que me gustaría meterme en el modo kernel y el modo de usuario.
Antes de comenzar, a pesar de que el núcleo y el sistema operativo son de 32 bits. Explicaré conceptos en 64 bits también, evidentemente, uno de ellos es el modo largo.
Modos
Interrupciones
Descriptores
Paginación
Lea más sobre el modo protegido en Intel® 64 e IA-32 Architectures Software Developer's Manual Volume 3A: Guía de programación del sistema, Parte 1; Capítulo 3 *
¿Qué son las interrupciones?
Puede pensar que las interrupciones son una señal o datos que están siendo enviados por un dispositivo como teclado, unidad de estado sólido, controlador duro o mouse y software que le dice a la CPU que ocurrió un evento y que necesita detener de inmediato lo que está haciendo actualmente, para proceder a lo que le envió la interrupción.
Por ejemplo, cuando se mueve/haga clic en un mouse, el controlador del mouse enviará una interrupción al controlador de interrupción para la CPU, la atención de la CPU irá inmediatamente a la interrupción del mouse y procederá a ejecutar una rutina (movimiento o clic del mouse). Después de que la interrupción del mouse, la CPU continuará haciendo lo que sea antes de la interrupción o gestione otra interrupción si ha sido señal.
+------------------------+ +------------+
| TYPES OF INTERRUPTS |------------| Exceptions |
+------------------------+ +------------+
/
/
/
+------------+ +------------+
| HARDWARE | | SOFTWARE |
| INTERRUPTS | | INTERRUPTS |
+------------+ +------------+
Líneas IRQ, o IRQ basados en PIN: estas generalmente se enrutan estáticamente en el chipset. Los cables o líneas se ejecutan desde los dispositivos en el chipset hasta un controlador IRQ que es importante las solicitudes de interrupción enviadas por los dispositivos, enviándolos a la CPU uno por uno para evitar carreras. En muchos casos, un controlador IRQ enviará múltiples IRQ a la CPU a la vez, en función de la prioridad del dispositivo. Un ejemplo de un controlador IRQ muy conocido es la cadena del controlador Intel 8259, que está presente en todos los chips de IBM-PC compatibles, encadenando dos controladores juntos, cada uno proporcionando 8 pines de entrada para un total de 16 pines de señalización IRQ utilizables en el Legacy IBM-PC.
Interrupciones basadas en mensajes: se señalan escribiendo un valor en una ubicación de memoria reservada para obtener información sobre el dispositivo de interrupción, la interrupción en sí y la información de vectorización. Al dispositivo se le asigna una ubicación a la que escribe por firmware o por el software del kernel. Luego, el dispositivo genera un IRQ utilizando un protocolo de arbitraje específico para el bus del dispositivo. Un ejemplo de un bus que proporciona la funcionalidad de interrupción basada en mensajes es el bus PCI. Por wiki.osdev - https://wiki.osdev.org/interrupts
Entrada: la entrada define una región en la memoria donde comenzar, junto con el límite de la región y los privilegios de acceso asociados con la entrada. Acceda al privilegio como al decir el procesador si el sistema operativo se ejecuta en el sistema (anillo 0) o la aplicación (anillo 3). Evita que las aplicaciones o USERMODE tengan acceso a ciertos registros/operandos y mnemónicos. Como los registros de CR y la CLI/ITS respectivamente.
Límite: el tamaño del descriptor del segmento
Selector de segmentos: son registros que contienen el índice de los descriptores
Para ser más explícito, un índice no es un selector
Cosas que tiene un registro de segmento:
Acceda a la tabla Descriptor también tiene privilegde, esto se llama RPL (nivel de privilegio de solicitud) para cada registro, pero para el cs se llama CPL (nivel de privilegio actual). Ambos están sirviendo propósitos diferentes, que puedes encontrar en los manuales Intel o AMD.
La tabla para usar para mirar. Una mesa es la GDT, la otra es la LDT.
Una regla informal para imaginar conceptualmente el uso del selector: por lo que la regla informal es:
selector = index + table_to_use + privilege table_to_use + index = descriptor = toda la información sobre el segmento de memoria que se utilizará
donde el signo más no es una operación aritmética
Campo de bits del registro del selector de segmento:
15 3 2 0
+--------------------------------------------------+----+--------+
| Index | TI | RPL |
+--------------------------------------------------+----+--------+
TI = Table Indicator: 0 = GDT, 1 = LDT
The TI specify if the Descriptor were dealing with is a GDT or LDT
IF(TI == 0) THEN
... THE DESCRIPTOR IS A GDT
ELSEIF(TI == 1) THEN
... THE DESCRIPTOR IS A LDT
GDT es 1: 1 con dirección lógica, un ejemplo del GDT que funciona con el selector:
<---- Selector ----> +----- Segment Selector Register
+-------+----+-----+ v
| Index | TI | RPL | = DS
+-------+----+-----+ GDT LDT
| | +---------------------+ +---------------------+
| +------------>| Null Descriptor | | Null Descriptor |
| +---------------------+ +---------------------+
| | Descriptor 1 | | Descriptor 1 |
| +---------------------+ +---------------------+
| | | | |
| ... ... ... ... ... ... ... ...
| | |
| +---------------------+
+------------------->| Descriptor K |
+---------------------+
| |
... ... ... ...
RPL (Request Privilege Level) describes the privilege for accessing the descriptor
Almacenamos toda la base GDT (dirección) y límite (tamaño de nuestro GDT) en el GDTR. El GDTR apunta a todas nuestras entradas GDT en la memoria, comenzando desde la base. Después de eso, se carga con el lgdt Mnemonic:
typedef union _gdt_descriptor
{
struct
{
uint64_t limit_low : 16 ;
uint64_t base_low : 16 ;
uint64_t base_middle : 8 ;
uint64_t access : 8 ;
uint64_t granularity : 8 ;
uint64_t base_high : 8 ;
};
} __attribute__((packed)) gdt_entry_t ;
gdt_entry_t gdt_entrys[ 256 ];
/* The GDTR (GDT Register) */
struct gdtr
{
uint16_t limit;
uint32_t base;
} __attribute__((packed)) gdtr;
...
gdtr.base = &gdt_entrys;
gdtr.limit = ( sizeof (gdt_descr) * 256 ) - 1 )
Lea más sobre él en el Manual del Programador de Arquitectura AMD64, Volumen 2, Sección 4.7 (pág. 84 - 90 {+})
referencia a esto y adelante en adelante. https://notes.shichao.io/utlk/ch2/#paging-in-hardware Este fue, con mucho, el más divertido que tuve, estaba extremadamente emocionado una vez que lo entendí.
X86 OS Legacy-Paging Virtual Dirección con páginas de 4KB:
X86 OS CR4.Pae Paging Dirección virtual con página de 4KB:
X86_64 (IA-32E) OS CR4.LME/CR4.Pae Paging Virtual Dirección con página de 4KB:
• Los indicadores WP y PG en el registro de control CR0 (bit 16 y bit 31, respectivamente).
• El PSE, PAE, PGE, PCIDE, SMEP, SMAP y PKE en el registro de control CR4 (bit 4, bit 5, bit 7, bit 17, bit 20, bit 21 y bit 22, respectivamente).
• Los indicadores LME y NXE en el IA32_Efer MSR (bit 8 y bit 11, respectivamente). • El indicador de CA en el registro de efflags (bit 18). Por el Capítulo 4 de Intel® 64 e IA-32 Architectures Software Developer's Manual del volumen 3A: Guía de programación del sistema, Parte 1; Capítulo 4
• Los indicadores LME y NXE en el IA32_Efer MSR (bit 8 y bit 11, respectivamente). • El indicador de CA en el registro de efflags (bit 18). Capítulo 4 de Intel® 64 e IA-32 Architectures Software Developer's Manual del desarrollador Volumen 3A: Guía de programación del sistema, Parte 1; Capítulo 4
Si CR4.Pae y/o CR4.LME se establece en 1, entonces PSE no tiene en cuenta.
No se agregó terminal
cd smkrnl; make run
Para la chispa de la inspiración/apoyo en mi continuo esfuerzo en este proyecto y para ayudarme a comprender ciertos conceptos dentro del desarrollo del núcleo/sistema operativo. =)