As outras duas respostas (no momento da redação deste documento) falam sobre interrupções e o IDT. Isso está correto, no entanto, em uma CPU moderna de estilo Intel, existem pelo menos três maneiras de acessar um kernel.
Método # 1: interrompe.
Isso é explicado acima. Você configura uma entrada na tabela de descritores de interrupção / vetor de interrupção e executa uma interrupção de software para entrar no kernel.
A principal vantagem desse método é que um kernel típico precisa ser capaz de lidar com interrupções de qualquer maneira e funciona em hardware arcaico.
Método 2: Ligue para portões.
Um portão de chamada é um tipo especial de seletor de segmentos. O destino da chamada precisa ser carregado na tabela de descritores de segmento global ou local (GDT e LDT, respectivamente). Se você executar uma instrução de chamada remota usando o portão de chamada como o segmento (o deslocamento da chamada é ignorado), isso permitirá que você chame um código mais privilegiado. Os portões de chamada são extremamente flexíveis; a arquitetura IA-32 possui quatro níveis de privilégio, e os portões de chamada permitem que você ligue para qualquer nível.
Não acredito que o Linux já tenha usado portões de chamada, mas o Windows 95 o fez. Os serviços do kernel do Win95 ( krnl386.exe
e kernel.dll
) realmente foram executados no modo de usuário (anel 3). O nível de privilégio mais alto (anel 0) foi usado apenas para drivers e um microkernel que executava apenas a alternância de processos. A chamada para os motoristas foi feita usando portões de chamada. Isso permitiu que o código legado de 16 bits (dos quais havia muito!) Usasse drivers Win95 usando apenas uma ligação remota padrão, como sempre.
A proteção inadequada da tabela de descritores globais foi a causa de várias explorações do Windows 95, que conseguiram instalar seus próprios portões de chamada escrevendo sobre a memória.
Método # 3: SYSCALL / SYSRET e SYSENTER / SYSEXIT
Estes são dois conjuntos de instruções, inventados independentemente pela AMD e Intel, mas eles essencialmente fazem a mesma coisa. O SYSCALL / SYSRET ficou em primeiro lugar e era apenas AMD, SYSENTER / SYSEXIT era Intel, mas a AMD o implementa agora. Então, eu vou descrever SYSENTER / SYSEXIT.
Ao contrário dos portões de chamada, o SYSENTER pode ser usado apenas para transferir para o toque 0 e apenas para um local. No entanto, tem a vantagem de ter latência extremamente baixa porque, diferentemente de uma chamada ou interrupção, ela não toca na pilha.
O local da transferência é configurado usando três registradores específicos do modelo: um para as informações do segmento e um para o ponteiro de instruções e o ponteiro de pilha do código do kernel. Como nada é "empurrado" para a pilha, o código do modo de usuário é responsável por informar ao kernel para onde retornar, passando o ponteiro da instrução de retorno e o ponteiro da pilha nos registros. O kernel é responsável por restaurar o ponteiro da pilha e a instrução SYSEXIT restaura o ponteiro da instrução.
Mais informações sobre as instruções SYSENTER e SYSEXIT.