Interface: IntManager_i386 Arquivos: intmanager_i386.h Última atualização: 29/06/2003 Autor: Luiz Henrique Shigunov |
Descrição Estruturas |
Funções | |
0x00 - Catch - Registra que o módulo está interceptando uma interrupção 0x04 - CatchException - Registra que o módulo trata uma exceção 0x01 - Free - Retira do registro que o módulo está interceptando uma interrupção |
0x05 - FreeException - Retira do registro que o módulo trata uma exceção 0x02 - NoInt - Desabilita as interrupções de hardware 0x03 - RestoreInt - Restaura as interrupções de hardware |
Esta página descreve a interface IntManager_i386.
O administrador de interrupções é responsável por administrar as interrupções do sistema, as exceções (já que elas são interrupções) e fornecer informações sobre as interrupções usadas.
As funções que servem as interrupções são chamadas de FSI (função servidora de interrupção).
As FSIs de software executam com as interrupções habilitadas, ou seja, se ocorrer uma interrupção de hardware enquanto uma FSI de software estiver executando, a interrupção de hardware é servida.
Já as FSIs de hardware executam com as interrupções de hardware desabilitadas, sendo que devem retornar com as interrupções de hardware desabilitadas.
As interrupções que são exceções são tratadas como FSIs de software. Exceto a exceção de número 14 (Page Fault) que é tratada como FSI de hardware, ou seja, é chamada com as interrupções desabilitadas. Isso é feito porque essa exceção precisa utilizar dados de um registrador que não é salvo na troca de linha de execução.
As FSIs de hardware devem estar sempre carregadas na memória física e só podem usar dados que também estejam sempre na memória física.
Isso se justifica porque para implementar memória virtual é preciso utilizar o disco e para se utilizar o disco as interrupções de hardware são necessárias.
Por isso, as FSIs de hardware devem tomar muito cuidado ao chamar funções dos módulos, pois elas também devem seguir essas restrições.
A melhor alternativa é utilizar uma tarefa/linha de execução com prioridade alta para chamar as funções que não seguem essas restrições. Utilizando esta alternativa, tem-se que tomar cuidado com as interrupções de hardware seguidas. Se for preciso, deve-se desabilitar a interrupção de hardware específica.
Estas restrições não se aplicam as interrupções de software.
Várias FSIs podem estar servindo uma mesma interrupção de hardware. Quando do registro de uma FSI é indicado se a FSI deve ser colocada no início da lista ou no fim da lista de FSIs. Uma FSI que realmente serve a interrupção deve ser colocada no fim. Já uma função que coleta estatísticas deve ser colocada no início.
Quando ocorre uma interrupção de hardware, cada FSI é chamada com a estrutura IntManager_i386_Regs. Mudar algum valor da estrutura mudará o conteúdo do registrador quando a interrupção voltar.
Ao retornar a FSI de hardware indica qual ação tomar:
Retornar E_HANDLED_INT indica que as outras FSIs não devem ser chamadas, mas retornar E_UNHANDLED_INT indica para chamar.
E_INVOKE_SCHEDULER indica que a interrupção foi servida (as outras FSIs não serão chamadas) e é usada quando uma tarefa/linha de execução de alta prioridade é liberado pela FSI (a tarefa/linha de execução estava esperando num sincronizador, por exemplo). Neste caso, antes do escalonador ser chamado, o hardware de interrupções será informado que a interupção foi servida.
A sintaxe de uma FSI de hardware deve ser:
int nome_da_função(IntManager_i386_Regs *regs)
Interrupções de software devem salvar os registradores antes de usá-los e restaurar antes de retornar com iret.
Todas as interrupções que não estão em uso apontam para uma FSI padrão.
As exceções e interrupções de hardware têm descritor privilegiado. As interrupções de software podem escolher entre um privilegiado ou não.
Várias FSIs podem servir uma exceção e a FSI é escolhida baseado no endereço onde a exceção ocorreu.
Cada FSI que trata uma exceção é chamada com a estrutura IntManager_i386_ExRegs. Mudar algum valor da estrutura mudará o conteúdo do registrador quando a exceção voltar.
Ao retornar a FSI indica qual ação tomar:
Retornar E_HANDLED_INT indica que as outras FSIs não devem ser chamadas, mas retornar E_UNHANDLED_INT indica para chamar.
Então, a sintaxe de uma FSI que trata exceção deve ser:
int nome_da_função(IntManager_i386_ExRegs *regs);
As exceções geradas pelo processador podem ser de três tipos: falta (fault), armadilha (trap) ou aborto (abort).
Uma exceção tipo falta é aquela que normalmente permite que o erro seja corrigido e a instrução seja executada novamente. O endereço de retorna dessa exceção aponta para a instrução que causou a falta.
Uma exceção tipo armadilha é ativada depois que a instrução que causou a exceção terminou de executar. O endereço de retorna dessa exceção aponta para a próxima instrução depois da que causou a exceção.
Uma exceção tipo aborto é aquela que não indica com precisão onde o erro ocorreu e que, na maior parte das vezes, não é possível continuar. É causada por erros físicos (hardware) e erros nas tabelas do sistema.
As exceções mais comuns são:
typedef struct { unsigned int EBP; unsigned int ESI; unsigned int EDI; unsigned int EDX; unsigned int ECX; unsigned int EBX; unsigned int EAX; unsigned int ErrorCode; unsigned int EIP; unsigned int CS; unsigned int EFLAGS; unsigned int ESP; unsigned int SS; } IntManager_i386_ExRegs;
Quando uma exceção não tem código de error, ErrorCode da estrutura será indefinido.
ESP e SS só existem se o nível de privilégio do código que estava executando for diferente de 0. Por isso, cuidado ao passar essa estrutura para outras funções - o tamanho dela pode ser menor!
typedef struct { unsigned int EBP; unsigned int ESI; unsigned int EDI; unsigned int EDX; unsigned int ECX; unsigned int EBX; unsigned int EAX; unsigned int EIP; unsigned int CS; unsigned int EFLAGS; unsigned int ESP; unsigned int SS; } IntManager_i386_Regs;
ESP e SS só existem se o nível de privilégio do código que estava executando for diferente de 0. Por isso, cuidado ao passar essa estrutura para outras funções - o tamanho dela pode ser menor!
int IntManager_i386_Catch(SysModManager_Module *modID, unsigned int interrupt, int (*function)(IntManager_i386_Regs*), int prop);
Esta função registra que o módulo modID está usando a interrupção interrupt e associa a interrupção com a função function.
A linha de execução que executar function pode estar destrutível. Se isso for problema as funções Undestroyable e Destroyable da interface TaskManager devem ser usadas.
prop deve ser 0 ou:
O privilégio do descritor para as interrupções de software pode ser 0 ou 3. Se for 0 somente os módulos do sistema poderão chamá-las.
As as IRQs, se forem chamadas pelo processador, são sempre executadas independente do privilégio. Mas se forem chamadas dum código, através da instrução INT, o processador verifica o privilégio.
Se interrupt for uma IRQ, o módulo controlador de interrupções será chamado para habilitar a IRQ.
int IntManager_i386_CatchException(unsigned int exception, int (*function)(IntManager_i386_ExRegs*), void *start, void *end);
Esta função registra a função function para tratar a exceção exception quando essa ocorrer entre start-end, inclusive.
A linha de execução que executar function pode estar destrutível. Se isso for problema as funções Undestroyable e Destroyable da interface TaskManager devem ser usadas.
Interrupções com número menores a 32 são consideradas exceções.
int IntManager_i386_Free(SysModManager_Module *modID, unsigned int interrupt, int prop);
Esta função retira do registro que o módulo modID está usando a interrupção interrupt.
prop deve ser 0 ou:
Se for uma IRQ o módulo controlador de interrupções será chamado para desabilitar a IRQ.
int IntManager_i386_FreeException(unsigned int exception, int (*function)(IntManager_i386_ExRegs*), void *start);
Esta função retira do registro que function trata a exceção exception quando essa ocorre em start.
Interrupções com número menores a 32 são consideradas exceções.
int IntManager_i386_NoInt(void);
Esta função desabilita as interrupções.
Os flags do processador antes de desabilitar as interrupções.
void IntManager_i386_RestoreInt(int flags);
Esta função restaura os flags do processador para flags, possivelmente habilitando as interrupções.
Nada.