Share

O Qemu é um virtualizador e emulador de processadores capaz de emular várias arquiteturas tais como ARM, x86, MIPS, PowerPC. Nas versões mais recentes ele é capaz de emular processadores de 32 bits e de 64 bits também, como, por exemplo, ARM 32 bits e ARM 64 bits. Ele também emula diferentes profiles da arquitetura ARM tais como: ARM cortex-m3, ARM9 e ARM11, ARM cortex-A8 e cortex-A9, ARM cortex-A15. Para quem é fã de Arduino, existe suporte ao Netduino 2, que a propósito, usa um microcontrolador da família STM32F2.

Você ficaria impressionado ao descobrir a capacidade do Qemu de emular processadores e por conseguinte, o código que é executado, de tal forma que ele até mapea os mesmos endereços usados no programa! Isso pode ser verificado através do gdb, conectando uma instância ao hardware e outra instância ao Qemu. Obviamente que existem algumas limitações, pois nem todos os periféricos podem ser emulados, e alguns periféricos que são suportados não são emulados com todos os seus atributos. Por exemplo, quando um timer é emulado, geralmente existe suporte para modo de contagem, mas o suporte a PWM, que alguns timers possuem, é omitido no Qemu por ser complicado fazer esse tipo de emulação com precisão.

No momento em que esse texto é escrito, a versão mais recente do Qemu é a 2.8. Essa versão tem suporte a Raspberry PI 2, graças a um patch submetido por um funcionário da Microsoft, Andrew Baumann. Nem todos os periféricos são suportados, mas tem-se o suficiente para iniciar o mesmo kernel linux que roda na Raspberry PI 2! Pelo menos em kernels abaixo da versão 4.4.

Um dos periféricos para qual não existe suporte, pelo menos não no repositório oficial, é o Ethernet. Para quem não sabe, a interface Ethernet não provêm de um periférico interno ao Raspberry, mas sim de um chip Ethernet com interface USB da Microchip, o LAN9512. E como o controlador USB da Raspberry ainda não foi implementado no Qemu, não é possível também emular o LAN9512. Seria relativamente fácil emular o LAN9512, pois o Qemu já suporta um chip bem parecido, o LAN9118. Veja aqui: https://github.com/qemu/qemu/blob/master/hw/net/lan9118.c

Então vamos ao que interessa: a emulação! Comecemos por clonar o repositório do mantenedor da arquitetura ARM do Qemu:

 

Peter Maydell, é o mantenedor da arquitetura ARM no Qemu, e seu repositório contém os commits que serão aplicados ao Qemu oficial.

Mude para o branch target-arm.next:

Atualize o repositório:

 

Baixe as dependências necessárias (Debian 8) :

 

Para esse branch, é necessário a libdtc versão 1.4.2, mas no Debian 8 a última versão é 1.4.0. Então é necessário baixar a versão do próprio Qemu, por meio desse comando:

 

Agora, configure o Qemu para target ARM:

 

E finalmente, podemos compilá-lo:

 

Agora baixe o Raspbian do site da Raspberry foundation, no link: https://www.raspberrypi.org/downloads/raspbian/

Com o próximo comando, vamos descobrir o offset das partições na imagem do Raspbian:

 

A saída é algo como:

2017-01-11-raspbian-jessie-lite.img: DOS/MBR boot sector; partition 1 : ID=0xc, start-CHS (0x0,130,3), end-CHS (0x8,138,2), startsector 8192, 129024 sectors; partition 2 : ID=0x83, start-CHS (0x8,138,3), end-CHS (0xa9,10,33), startsector 137216, 2578432 sectors

Precisamos montar a partição do sistema arquivos, que é a partição 2 (partition 2), cujo startsector é 137216, como indicado acima. Substitua no comando abaixo, o valor que multiplica com 512, se a imagem que você baixou for diferente:

 

Edite o arquivo ld.so.preload e comenta a linha:

#/usr/lib/arm-linux-gnueabihf/libarmmem.so (este # é o indicador de comentário, e não o indicador de root)

Desmonte a partição:

 

Agora vamos montar a primeira partição, que inicia no setor 8192:

 

Precisamos copiar o kernel e o arquivo dtb, que serão usados na emulação da Raspberry no Qemu. Podemos copiar para a pasta /tmp, fora do sistema de arquivos que foi montado:

 

Agora volte para a pasta do código fonte do Qemu. E finalmente podemos iniciar o Qemu com o seguinte comando:

 

Veja abaixo a tela de boot e o login da Raspberry PI no Qemu:

E também informações sobre o hardware:

Debug do kernel usando o Qemu

Agora vejamos como fazer o debug diretamente no kernel do Linux por meio do Qemu. Isso pode ser útil para desenvolver device drivers, fazer o “Board Bring Up” de novas placas ou investigar algum problema no kernel. Será necessário baixar o kernel da Raspberry para que possamos compilá-lo e depurá-lo.

 

E para que possamos debugar o kernel é necessário adicionar os símbolos de debug por meio da opção CONFIG_DEBUG_INFO=y, que se encontra em Kernel hacking. Primeiro habilite Kernel debbuging, que também se encontra em Kernel hacking:

Entra na opção “Compile-time checks and compiler options —>” e marque a opção “Compile the kernel with debug info”.

Escolha a opção “Exit” até sair do menuconfig e salve. Infelizmente não é possível desabilitar a otimização do kernel Linux, e como consequência, às vezes durante o debug ele pula para linhas imprevisíveis.

Compile o kernel da Raspberry com esse comando:

 

Copie o novo kernel e dtb gerados para /tmp:

 

Em outro terminal, inicie o Qemu, mas dessa vez em modo debug, usando as opções -s -S:

 

E no terminal que está na raiz do código do kernel, inicie o debug usando a imagem descomprimida e conecte-se ao Qemu:

(gdb) target remote localhost:1234

Ainda no prompt do gdb, coloque um breakpoint em bcm2835_rng_read, que é a função responsável por gerar números aleatórios:

(gdb) break bcm2835_rng_read

(gdb) continue

E pronto, navegue pelo kernel como se estivesse na própria placa da Raspberry PI 2! Digite backtrace e veja por onde kernel passou. Defina um breakpoint em bcm2709_init, que é uma das primeiras funções chamadas pela CPU da Raspberry e veja o que acontece por lá! Veja abaixo uma figura ilustrando o debug do kernel Linux com gdb, ao que está conectado ao Qemu.

 

Referências:

  1. http://blog.3mdeb.com/2015/12/30/emulate-rapberry-pi-2-in-qemu/
  2. https://github.com/0xabu/qemu/wiki
  3. http://free-electrons.com/blog/uncompressed-linux-kernel-on-arm/
  4. https://github.com/raspberrypi/linux/blob/rpi-4.4.y/drivers/char/hw_random/bcm2835-rng.c#L34
Translate »