
Aqueles que estão acompanhando nosso projeto podem ter notado que uma pasta e2k apareceu no diretório com arquiteturas, que contém suporte para processadores domésticos com
arquitetura Elbrus .
Uma série de artigos sobre como transportar a
Embox para plataformas domésticas não seria completa sem uma história sobre essa arquitetura.
Farei alguns comentários sobre o conteúdo do artigo. Primeiramente, o processo de dominar essa arquitetura por nós está no estágio inicial, conseguimos lançar o Embox nessa plataforma, mas ainda não implementamos muitas das partes necessárias, que serão discutidas em publicações futuras. Em segundo lugar, essa arquitetura é complexa e
uma descrição detalhada requer muito mais texto do que o formato permite
um artigo Portanto, sugerimos que este artigo seja uma introdução,
contendo um mínimo de informações técnicas sobre a própria arquitetura.
Vamos começar.
Objeto de pesquisa - Layout do sistema incorporado na Elbrus
Como estamos envolvidos na Embox (e se alguém não estiver ciente, é focado em sistemas embarcados), estávamos interessados principalmente na opção de posicionar o próprio MTsST, inclusive para sistemas embarcados. Voltando ao MCST, descobrimos que a empresa está interessada em usar seus processadores para sistemas embarcados. Uma das soluções mais recentes para esse segmento é
a placa E4C-COM . No processo de comunicação com o MCST, ficou claro que, para portar e dominar a arquitetura, você pode usar qualquer uma das máquinas disponíveis, e recebemos um computador chamado
Monocub para uso temporário. Em geral, um monocubo não é exatamente o que estamos acostumados em sistemas embarcados. Normalmente, os sistemas embarcados usam computadores de placa única, um chip - um sistema em um chip ou até mesmo um microcontrolador, mas o monocube é um computador completo, mas como foi testado em "clima e mecânica", ainda pode ser considerado um sistema embarcado.
Compilador, compilação, imagem de preenchimento
Depois de receber a unidade do sistema, surgiu naturalmente a questão - como preencher a imagem. O MCST usa seu próprio BIOS (carregador de inicialização do sistema de primeiro nível). Por padrão, o Elbrus OS está instalado (ou seja, Debian com modificações). Estamos interessados em lançar nossa própria imagem. Felizmente, o carregador MTST pode executar imagens na rede. Para fazer isso, use o
protocolo ATA sobre Ethernet .
Depois que fomos ajudados a montar um estande e lançar uma imagem externa pela rede, começamos a desenvolver nossa própria imagem. Para fazer isso, precisávamos de um compilador. Não encontramos o compilador no domínio público, mas desde que assinamos o NDA, recebemos binários para o Linux. O compilador acabou sendo bastante compatível com o gcc, e não tivemos que mudar nada, é claro, com exceção dos sinalizadores de compilação, que lançamos em um arquivo de configuração separado. O que é muito previsível, porque o Linux, embora com modificações, é montado por este compilador.
Algumas perguntas técnicas
Quem está envolvido em atividades específicas, como transportar o sistema operacional para uma plataforma, sabe que a primeira coisa a fazer é colocar corretamente o código do programa na memória. Ou seja, escreva um script vinculador (lds) e implemente o código inicial. Nós descobrimos rapidamente o script do vinculador, mas, ao implementar o código inicial, fomos confrontados com a primeira mágica, que não entendemos completamente. O fato é que Elbrus tem um modo de compatibilidade com x86 e, em 0x00FF0000, existe um código ao qual darei um
link , já que o emprestamos do exemplo do MCST. O script vinculador contém
.bootinfo : { _bootinfo_start = .; *(.x86_boot) . = _bootinfo_start + 0x10000; _bootinfo_end = .; } SECTION_REGION(bootinfo) .text : { _start = .; *(.e2k_entry);
O código inicial em si nem é escrito no assembler, mas simplesmente em
C. Ele é colocado na seção localizada em 0x01000000, que, a propósito, corresponde ao endereço inicial de máquinas x86 comuns - ali o cabeçalho de
inicialização múltipla ou outro cabeçalho fica nesse endereço.
Para garantir que o código e os endereços iniciais estejam corretos, você precisa obter alguma saída. Se você pode imprimir qualquer caractere, provavelmente não haverá problemas com a saída de strings. Usando esta saída, já será possível usar o familiar printf () para depuração. Além disso, a maioria das plataformas fornece a capacidade de gerar caracteres fazendo uma entrada simples em um registro específico (uma vez que o carregador de inicialização provavelmente configurou o UART conforme necessário).
Nosso computador usa o controlador de porta serial am85c30 (também conhecido como
z85c30 , descobrimos rapidamente como imprimir um caractere e isso é suficiente para o nosso printf funcionar. Imediatamente enfrentamos um problema estranho - alguns dos caracteres impressos pelo printf pareciam estar duplicados, mas às vezes confuso. Por exemplo, quando tentei produzir Olá, mundo! Ficou algo como Hhelellloo ,, woworrlldd. Agora parece óbvio que o assunto é multinúcleo, mas a princípio nós procurávamos no próprio driver. No monocub, há um Elbrus-2C de núcleo duplo + (1891VM7YA) ( quatro núcleos DSP não contam) e o carregador de inicialização ativa todos os núcleos do processador. Como resultado, para não mexer com SMP (multicore), todos os núcleos, exceto o primeiro, são enviados para um loop infinito. Para isso, introduzimos uma variável para o número do processador e o incrementamos usando adição atômica O núcleo zero continua a funcionar, enquanto outros kernels fazem loop.
cpuid = __e2k_atomic32_add(1, &last_cpuid); if (cpuid > 1) { while(1); } memcpy((void*)0, &_t_entry, 0x1800); kernel_start();
A chamada kernel_start () já é uma transferência de controle para o nosso código.
Também emprestamos adição atômica, para nós parece mágica. Mas, como você sabe, funciona - não toque!
#define WMB_AFTER_ATOMIC ".word 0x00008001\n" \ ".word 0x30000084\n" #define __e2k_atomic32_add(__val, __addr) \ ({ \ int __rval; \ asm volatile ("\n1:" \ "\n\tldw,0 %[addr], %[rval], mas=0x7" \ "\n\tadds %[rval], %[val], %[rval]" \ "\n\t{"\ "\n\tstw,2 %[addr], %[rval], mas=0x2" \ "\n\tibranch 1b ? %%MLOCK" \ "\n\t}" \ WMB_AFTER_ATOMIC \ : [rval] "=&r" (__rval), [addr] "+m" (*(__addr)) \ : [val] "ir" (__val) \ : "memory"); \ __rval; \ })
Outra mágica que precisei emprestar é um código necessário para todos os núcleos. Ou seja
static inline void e2k_wait_all(void) { _Pragma ("no_asm_inline") asm volatile ("wait \ttrap = %0, ma_c = %1, fl_c = %2, ld_c = %3, " "st_c = %4, all_e = %5, all_c = %6" : : "i" (0), "i" (1), "i" (1), "i" (0), "i" (0), "i" (1), "i" (1) : "memory"); }
Como resultado, depois de escrever o código de inicialização, não apenas recebemos as mensagens exibidas usando o printk, mas também começamos a carregar módulos, o que geralmente não é muito trivial para compiladores não muito comuns. Então, mais uma vez, observo que desta vez a compatibilidade com o gcc ficou muito satisfeita.
O próximo passo é geralmente iniciar o controlador de interrupção e o timer, mas, pensando que teremos que implementar não apenas suporte para esses dispositivos, mas também o código de arquitetura para os manipuladores de interrupção, decidimos que podemos começar pela periferia. O monocub possui um barramento PCIe, para os programadores parece um PCI comum. Estávamos interessados principalmente em dois dispositivos: um controlador de vídeo e um controlador de rede.
O monocube usa um controlador gráfico da série
sm750 . Este é um controlador gráfico para aplicativos incorporados, com suporte integrado para gráficos 2D. O chip é soldado diretamente na placa-mãe, como eu o entendo. As fontes do driver para Linux podem ser encontradas
aqui .
Depois que o driver foi encontrado, parecia que nossos problemas haviam acabado, restava apenas implementar o controlador para PCI. mais precisamente, operações de leitura / gravação do espaço de configuração do PCI para descobrir os parâmetros. A implementação dessas funções teve que ser emprestada novamente. Como resultado, a leitura de registros se resumia a macros como
#define _E2K_READ_MAS(addr, mas, type, size_letter, chan_letter) \ ({ \ register type res; \ asm volatile ("ld" #size_letter "," #chan_letter " \t0x0, [%1] %2, %0" \ : "=r" (res) \ : "r" ((__e2k_ptr_t) (addr)), \ "i" (mas)); \ res; \ }) #define _E2K_WRITE_MAS(addr, val, mas, type, size_letter, chan_letter) \ ({ \ asm volatile ("st" #size_letter "," #chan_letter " \t0x0, [%0] %2, %1" \ : \ : "r" ((__e2k_ptr_t) (addr)), \ "r" ((type) (val)), \ "i" (mas) \ : "memory"); \ })
Existe alguma compreensão do que está acontecendo. O Elbrus possui vários espaços de endereço alternativos, como, por exemplo, na
arquitetura SPARC . A identificação é feita usando o identificador do espaço de endereço. Ou seja, o mesmo comando ld chega a diferentes endereços internos, também gera operações de leitura de diferentes comprimentos (8, 16, 32, 64 bits). Se no SPARC este é um comando lda / sta separado, no Elbrus devido aos parâmetros, este é o comando ld. As
janelas do registro foram emprestadas da arquitetura SPARC. Adiarei uma história mais detalhada para os artigos subseqüentes.
Como resultado, tudo acabou com o PCI. Conseguimos obter todos os dados necessários, transferimos o driver gráfico para nós mesmos, mas depois enfrentamos o seguinte problema. Para desenhar uma imagem na memória de vídeo, você precisava escrever duas vezes. Tudo apontava para o cache. Para resolver esse problema, era necessário lidar com a MMU, e isso, como dizem, não pode ser resolvido com o condachka, pois, em princípio, muitos outros problemas que encontramos e que encontraremos mais de uma vez durante o desenvolvimento dessa arquitetura.
Avançamos em outras direções: interrupções e chamadas do sistema, mas também falaremos sobre isso nos próximos artigos desta sub-série. No final deste artigo, trarei a saída para o console (via porta serial).

Conclusões
Como disse na introdução, quero me concentrar principalmente nos detalhes técnicos, mas nos sentimentos gerais. Portanto, os sentimentos são contraditórios, embora certamente mais positivos. Por um lado, o processador existe e é muito interessante em termos de recursos arquiteturais. Com base neste processador, são produzidos sistemas de computador, existe um software de alta qualidade. Como eu disse, não houve reclamações sobre o compilador (até um certo ponto, que descreverei um pouco mais tarde), existe um Linux completo (SO "Elbrus"). Eu pessoalmente vi como, no próprio ICST, o desenvolvedor criou diretamente na área de trabalho com a arquitetura Elbrus.
Mas, por outro lado, não entendo por que, com tanta persistência, eles estão tentando fazer uma substituição banal do Intel x86 deste processador. De fato, em nenhum lugar do mundo eles usam processadores baseados na arquitetura
VLIW como computadores pessoais universais. O VLIW, devido às suas características arquitetônicas, é um excelente "triturador de números", eles fazem DSP nele, criaram servidores de itanium, criaram placas gráficas. Não, com uma escavadeira, é claro, você pode cavar um buraco para plantar uma árvore, mas vale a pena.
O principal problema que impede o desenvolvimento da arquitetura, na minha opinião, é a natureza fechada de todo o ecossistema. Sim, para obter uma descrição do sistema de comando, basta assinar o NDA, mas isso não é suficiente. A arquitetura é desconhecida e muito complexa. Sim, eu sempre pensei que algum software básico deveria ser desenvolvido diretamente do fabricante do processador, bem, ou em estreita cooperação com ele. De acordo com esse princípio, um PC no Elbrus possui um pacote de software com
o Elbrus OS . Mas ainda é ingênuo acreditar que uma empresa, mesmo uma grande, pode oferecer suporte de qualidade a todos os componentes: um processador, um compilador, ferramentas de desenvolvimento e depuração, software de sistema (vários sistemas operacionais), software de aplicativo, ... até a Intel não pode fazer isso. Há muito que o mundo caminha para a chamada colaboração ou desenvolvimento conjunto.
Deixe-me dar um exemplo de um problema do compilador que encontramos. O driver da porta serial em algum momento parou de exibir caracteres e, à primeira vista, nada mudou. Acabamos removendo a função de depuração não utilizada, que inserimos para entender através do desmontador como passar argumentos para a função no assembler. Ou seja, se a função estiver presente, tudo estará bem, se não, a saída desaparecerá. No início, eles pecaram por alinhamento, mas acabou que a função pode ser transferida para o final de C-Schnick, de modo que todos os personagens do motorista estavam nos mesmos lugares de antes, mas o problema foi reproduzido. Embora esse problema não tenha sido resolvido, continuamos investigando para mostrar aos desenvolvedores do compilador do MCST ou para entender onde cometemos um erro.
O problema acima, na minha opinião, poderia ter sido evitado se houvesse mais usuários de terceiros. No mínimo, o problema teria surgido mais cedo ou, seria possível pesquisar no Google o que fizemos de errado.
O ICST também está ciente do problema do fechamento, já que o processo de descoberta de coisas não classificadas já começou. Por exemplo, vi o Alt-Linux funcionar em vários PCs da Elbrus em várias conferências. Aqui estão fotos da tela de uma das conferências deste ano (desculpe-me por ver mal, estava escuro). Também nos conectamos com o desenvolvimento. Esperamos ser úteis para o ICST, porque, como se vê, alguns dos destaques da arquitetura Elbrus não podem ser suportados no Linux (ou os custos são muito grandes), por exemplo, memória marcada.


Outro ponto importante quando discutimos o problema do fechamento com os desenvolvedores do MCST, eles objetaram que, por exemplo, as fontes do kernel Linux estavam abertas por um longo tempo, mas apenas nós e os desenvolvedores do Dolomant fizemos perguntas e as usamos de alguma forma.
Além disso, de acordo com minhas informações, o MCST vai organizar um estande
acessível remotamente. No qual será possível montar e executar o software em um PC com arquitetura Elbrus. Se houver um interesse semelhante e você desejar usar o suporte, entre em contato, por exemplo, comigo: descreva como está planejado usá-lo, quanto tempo leva e assim por diante, porque para compartilhar com a alteração do software, é necessário organizar um cronograma. Transferirei os dados para o ICST ou conectarei aqueles que desejarem com os organizadores.
Links úteis:
O endereço para correspondência dos usuários é o usuário [at] mcst.ru
Uma breve descrição da arquitetura de ElbrusFontes EmboxPS Vamos mostrar a todos que querem o que recebemos no festival de TI do
TechTrain ,
de 2 a 2 de setembro.