Long Mode
Long mode é o modo de 64 bits que processadores x86-64 adicionam sobre tudo que o protected mode já fornece, estendendo registradores de propósito geral, endereços virtuais e codificação de instrução para 64 bits. Diferente de toda transição de modo anterior, entrar em long mode tem um pré-requisito que nenhuma das anteriores tinha: a paginação já precisa estar ativa, com PAE habilitado, antes que a CPU permita a transição; long mode não tem forma sem paginação para a qual recorrer.
O que muda
Seção intitulada “O que muda”Todo registrador de propósito geral cresce para 64 bits e ganha um nome prefixado com R (RAX a R15, incluindo oito registradores inteiramente novos sem equivalente na era de 32 bits, R8 a R15). Endereços virtuais também crescem para 64 bits, embora o hardware atual implemente por padrão apenas 48 bits utilizáveis desse espaço (57 com a extensão opcional LA57), exigindo que os bits superiores não usados sejam uma extensão de sinal do bit mais alto implementado (um endereço canônico), ou a CPU levanta uma falha em vez de truncar silenciosamente. A segmentação, central ao modelo de proteção do protected mode, torna-se em grande parte vestigial: base e limite de segmento são ignorados para a maioria dos segmentos sob long mode, com a CPU dependendo inteiramente da paginação para proteção de memória, embora seletores de segmento ainda sejam carregados e ainda carreguem a informação de nível de privilégio da qual uma transição de ring depende.
Pré-requisitos
Seção intitulada “Pré-requisitos”A própria disponibilidade do long mode nunca é presumida; ela é checada antecipadamente via a leaf estendida 0x80000001 do CPUID, cujo bit 29 de EDX (o bit LM) reporta se a CPU implementa o modo, antes que qualquer coisa da sequência abaixo seja tentada. Três condições precisam valer antes que a sequência de instruções de transição tenha sucesso: PAE (Physical Address Extension, bit 5 de CR4) precisa estar habilitado, já que o formato de tabela de página do long mode é o formato PAE estendido com um nível adicional de tabela, não uma estrutura não relacionada; um conjunto válido de tabelas de página já precisa estar carregado via CR3; e a própria paginação, bit PG de CR0, ainda não pode estar definida: é o último passo da sequência, não um pré-requisito satisfeito antes, já que defini-la é o que de fato completa a transição.
Entrando em long mode
Seção intitulada “Entrando em long mode”A sequência, executada a partir do protected mode, é uma ordem fixa de operações:
; 1. Habilitar PAEmov eax, cr4or eax, 1 << 5mov cr4, eax
; 2. Carregar CR3 com uma tabela PML4 já populada com pelo menos; entradas mapeadas por identidade cobrindo o código atualmente em execuçãomov eax, pml4_tablemov cr3, eax
; 3. Definir o bit de habilitação de long mode na MSR EFERmov ecx, 0xC0000080 ; IA32_EFERrdmsror eax, 1 << 8 ; LMEwrmsr
; 4. Habilitar paginação — isso de fato ativa o long modemov eax, cr0or eax, 1 << 31mov cr0, eax
; 5. Far jump para um segmento de código de 64 bits para completar a transiçãojmp CODE_SEG_64:long_mode_entryDefinir CR0.PG no passo 4 coloca a CPU em um estado transitório chamado compatibility mode, em vez de long mode completo de 64 bits diretamente: o far jump final no passo 5, para um descritor de código da GDT com seu bit de long mode definido, ainda é exigido para alcançar execução genuína de 64 bits, espelhando o mesmo padrão de “definir o bit de controle, depois far-jump para esvaziar o pipeline” que a transição de real para protected usa.
Compatibility mode
Seção intitulada “Compatibility mode”Além dessa breve janela transitória, o compatibility mode também persiste como um estado contínuo selecionável: um kernel em long mode pode rodar código de aplicação de 32 ou 16 bits essencialmente sem modificação, carregando um segmento de código de compatibility mode para ele, permitindo que binários existentes de user space de 32 bits rodem sob um kernel de 64 bits sem recompilação. O próprio kernel, no entanto, sempre executa como código genuíno de 64 bits uma vez completamente transicionado; o compatibility mode é uma acomodação voltada ao user space, não um modo em que o próprio código do kernel roda.
Notas de implementação
Seção intitulada “Notas de implementação”Como o long mode exige paginação ativa como pré-requisito, e o instruction pointer precisa permanecer válido durante toda a transição, as tabelas de página carregadas antes de definir CR0.PG precisam mapear por identidade (endereço virtual igual ao físico) qualquer código atualmente em execução: pular direto para a paginação com uma tabela que não cobre o próprio endereço do código em execução produz uma falha imediata na busca de instrução seguinte, antes que a CPU tenha qualquer infraestrutura utilizável de tratamento de interrupção para reportá-la de forma limpa. Muitos kernels lidam com isso mapeando por identidade os primeiros poucos megabytes de memória física temporariamente durante a transição, depois trocando para um conjunto de mapeamentos totalmente correto (incluindo um mapeamento de kernel na metade superior, se usado), uma vez seguramente em modo de 64 bits com tratamento adequado de exceções disponível.
Referências
Seção intitulada “Referências”- ^ AMD, AMD64 Architecture Programmer’s Manual, Volume 2, Capítulo 14: a especificação original da sequência de transição de long mode e seus pré-requisitos.
- ^ Intel, Intel 64 and IA-32 Architectures Software Developer’s Manual, Volume 3A, Capítulo 9: a descrição correspondente da entrada em modo IA-32e do lado Intel.
Ver também
Seção intitulada “Ver também”- Paging & Virtual Memory: o formato de tabela de página que o long mode exige como pré-requisito.
- Protected Mode: o modo do qual a sequência de transição do long mode parte.
- CPUID: a instrução e a leaf estendida que reporta se o long mode está disponível.
- Model-Specific Registers: o mecanismo RDMSR/WRMSR por trás do registrador EFER que esta transição escreve.