Embora a maior parte do código no kernel do Linux seja escrita em C, ainda existem muitas partes desse código que são muito específicas da plataforma em que está sendo executada e precisam dar conta disso.
Um exemplo específico disso é a memória virtual, que funciona de maneira semelhante na maioria das arquiteturas (hierarquia de tabelas de páginas), mas possui detalhes específicos para cada arquitetura (como o número de níveis em cada arquitetura, e isso tem aumentado mesmo no x86 com introdução de novos chips maiores.) O código do kernel do Linux introduz macros para lidar com a travessia dessas hierarquias que podem ser elididas pelo compilador em arquiteturas que possuem menos níveis de tabelas de páginas (para que o código seja escrito em C, mas inclua detalhes da arquitetura em consideração.)
Muitas outras áreas são muito específicas para cada arquitetura e precisam ser tratadas com código específico do arco. A maioria deles envolve código em linguagem assembly. Exemplos são:
Troca de Contexto : A troca de contexto envolve salvar o valor de todos os registros para o processo que está sendo desativado e restaurar os registros do conjunto salvo do processo agendado na CPU. Até o número e o conjunto de registros são muito específicos para cada arquitetura. Esse código geralmente é implementado em assembly, para permitir acesso total aos registros e também para garantir que ele seja executado o mais rápido possível, pois o desempenho da alternância de contexto pode ser crítico para o sistema.
Chamadas do sistema : o mecanismo pelo qual o código do espaço do usuário pode acionar uma chamada do sistema geralmente é específico da arquitetura (e algumas vezes até do modelo de CPU específico, por exemplo, Intel e AMD introduziram instruções diferentes para isso, as CPUs mais antigas podem não ter essas instruções, portanto, detalhes para aqueles que ainda serão únicos.)
Manipuladores de interrupção : os detalhes de como lidar com interrupções (interrupções de hardware) geralmente são específicos da plataforma e geralmente requerem uma cola no nível do assembly para lidar com as convenções de chamada específicas em uso na plataforma. Além disso, as primitivas para ativar / desativar as interrupções geralmente são específicas da plataforma e também exigem código de montagem.
Inicialização : Os detalhes de como a inicialização deve ocorrer também geralmente incluem detalhes específicos da plataforma e geralmente exigem algum código de montagem para lidar com o ponto de entrada no kernel. Nas plataformas que possuem várias CPUs (SMP), os detalhes sobre como colocar outras CPUs online também costumam ser específicos da plataforma.
Primitivas de bloqueio : a implementação de primitivas de bloqueio (como spinlocks) geralmente também envolve detalhes específicos da plataforma, pois algumas arquiteturas fornecem (ou preferem) instruções diferentes da CPU para implementá-las com eficiência. Alguns implementarão operações atômicas, outros fornecerão um cmpxchg que pode testar / atualizar atomicamente (mas falhará se outro escritor entrar primeiro), outros incluirão um modificador de "bloqueio" nas instruções da CPU. Isso geralmente envolve escrever código de montagem também.
Provavelmente, existem outras áreas em que o código específico da plataforma ou arquitetura é necessário em um kernel (ou, especificamente, no kernel Linux). Observando a árvore de fontes do kernel, existem subárvores específicas da arquitetura, abaixo arch/
e abaixo, nas include/arch/
quais você pode encontrar mais exemplos disso.
Algumas são realmente surpreendentes, por exemplo, você verá que o número de chamadas de sistema disponíveis em cada arquitetura é distinto e que algumas chamadas de sistema existirão em algumas arquiteturas e não em outras. (Mesmo no x86, a lista de syscalls difere entre um kernel de 32 e 64 bits.)
Em resumo, há muitos casos em que um kernel precisa estar ciente de que é específico para uma plataforma. O kernel do Linux tenta abstrair a maioria deles, para que algoritmos de nível superior (como o gerenciamento e agendamento de memória funcionem) possam ser implementados em C e funcionem da mesma maneira (ou principalmente da mesma forma) em todas as arquiteturas.