segunda-feira, 16 de janeiro de 2012


O novo FreeBSD


... ou quando segurança e liberdade andam de mão dadas

Realmente, se tua palavra de ordem for "segurança" o SO de escolha tem que ser um BSD. Net, Open ou Free? Depende da tua paranóia! O FreeBSD sempre foi a minha escolha para servidores, plataforma de testes, administração de rede ou computação de alto desempenho. E nunca me decepcionou.

Ok, existem reclamações sobre demora de instalação, configuração (muitas vezes manual e na base do "vi") mas o resultado supera estes problemas. Afinal, o FreeBSD é um sistema amigável... o único problema é que ele é quem escolhe os amigos.

Mas chega de mimimi... afinal, a instalação do 9.0 foi um tiro: 15 minutos! A instalação foi em uma máquina virtual (VirtualBox) com 1MB de RAM e 15 GB de disco, rodando sobre Gnome 3/Ubuntu 11.10 em um HP Pavilion.

Contando o boot inicial de 1 minuto e 22 segundos, a instalação de base, kernel, doc, games, ports e src levou exatos 9 minutos. O restante já pode ser considerado configuração inicial (rede, nntp, sshd e serviços) depois disto aparece um display oferecendo a possibilidade de uma configuração extra, manual e mais fina. Mas isto pode ser feito depois e aos poucos, não é?

A interface de instalação é tipo ncurses mas bem fácil e intuitiva. Sem muitas complicações para o newbie. E aí vem o primeiro boot + 3 "enters" (sabem como é né?)... POW! 42 segundos... fiquei ali olhando achando que não era o FreeBSD que eu conhecia.

A primeira instalação feita foi o vim (o vi improved) que levou quase 45 minutos via rede (pkg_add -rvv vim) porque tinha instalar mais libs de curses e se pôs a instalar ruby, python, perl, x11 e suas dependências... assustador! Mas o procedimento foi tranquilo. Apesar de ter baixado o DVD completo, achei melhor instalar via rede para testar o desempenho em uma rede doméstica. Aí dá para entender porque a instalação do sistema é rápida. Mas melhorou muito em relação às versões anteriores.

Em seguida, o bash porque não vem instalado. O default é o sh, nu e cru. A instalação foi em segundos. Mas espere até ter que gerar o INDEX-9 do ports... meia hora! Claro que ainda tem muito o que fazer, principalmente se pretendes usá-lo como desktop.

Pessoalmente recomendo o FreeBSD como desktop para quem o usa para computação científica, adminstração de sistemas, redes etc. Caso contrário tem que ser muito nerd mesmo para usá-lo como SO do dia-a-dia. Se este for teu caso, e quiseres deixar tudo "redondinho" prepare-se para 2 ou 3 dias de compilação do Xorg, gnome ou KDE e todas as "perfumarias" do desktop gráfico... boa sorte!

A sério, sério mesmo, o FreeBSD faz juz ao seu padrinho Dennis Ritchie... um "monstro" da computação! Por falar nele, o SO vem com o gcc 4.2.1 e muitas outras novidades. Yesss... tem a máquina virtual de baixo nível para nós que gostamos de escovar bits. O LLVM é uma infraestrutura de compilador com um conceito de complilação projetado para certas otimizações efetivas por meio de um conjunto de instruções virtuais.

Ainda, outras novidades estão presentes nesta versão do FreeBSD. Uma das melhores é o ssh com High Performance (OpenSSH 5.8 hpn13v11) e o NFS versão 4 (man 4 nfsv4). Esta versão do NFS usa um único RPC que concatena as operações do FS, equivalentes aos vários RPCs da versão anterior. Além disso a manutenção dos arquivos de backup se dá de maneira diferente (veja a página do manual).

Por fim, o ZFS versão 5 e aplicativos como zetaback... são nossa alegria e tranquilidade. Um sistema seguro como o FreeBSD tinha que ter um sistema de segurança de arquivos assim. Afinal, como servidor o FreeBSD é imbatível. A instalação não é complicada e é de fácil operação e manutenção.

Quer mais? Vai lá instale e descubra as novidades. Mas não espere a amabilidade de um Linux. Pelo contrário, pense forte e prepare-se para uma "atitude", o Free é mesmo pra macho! Mas é "bão" o danado!

sexta-feira, 13 de janeiro de 2012

FreeBSD 9.0

O novo "Beastie" está na rua...

A equipe do FreeBSD anunciou, nesta semana, a versão 9.0 do FreeBSD. Dedicado a Dennis M. Ritchie — um dos "pais" do sistema UNIX e que faleceu recentemente — o FreeBSD apresenta uma nova versão que vem cheia de novidades. Dentre elas, por exemplo:

  1. uma versão mais rápida do sistema de arquivos com suporte a journaling
  2. uma nova versão do ZFS (ver meu post sobre ZFS)
  3. NFS versão 4
  4. SSH de alta performance: HPN-SSH
  5. Um compilador com otimização interprocedural, o LLVM compiler (veja llvm.org).

Além disso, o novo sistema operacional vem com suporte a arquiteturas amd64, i386, ia64, powerpc, powerpc64, e sparc64.

Muita novidade a ser testada e apresentada. Já estou "baixando" a imagem ISO e logo, logo volto com os "comments" aqui no blog.

Por enquanto aguardem ou vejam por si mesmos:

http://www.freebsd.org

domingo, 8 de janeiro de 2012



0-1 ou On/OFF

Desde que comecei esta "brincadeira" de escrever sobre sistemas operacionais — bem, uma brincadeira que está ficando cada vez mais séria — tenho recebido emails, mensagens da rede social me estimulando e perguntando algumas particularidades dos sistemas. Para mim, tem sido um desafio de atualização e mesmo de aprendizado pois os novos processadores estão há anos-luz daquele velho código do 8086 que aprendi na escola de engenharia.

O assunto, desta vez, é o on/off, para responder à uma pergunta que os alunos de sistemas fazem frequentemente: como o sistema operacional é carregado na memória do computador? Em que exato momento isto acontece e o que acontece em seguida? Este assunto também é uma continuidade do último artigo (Anatomia de um kernell).



Bem, primeiro, é preciso explicar que quando a corrente elétrica começa a percorrer os circuitos da placa-mãe e chega ao processador este se encontra no que chamamos de "real mode" (em contraposição ao "protected mode"). Neste estado, o processador tem acesso a 1MB de memória ROM e começa executando o código que se encontra no endereço final deste segmento ou 0xFFF0 (absoluto CS:IP F000:FFF0). Este código é o que chamamos de Sistema Básico de Entrada e Saída ou Basic Input Output System (BIOS).

Usando uma descrição simplista e resumida, este programa (BIOS) executa, então o self-test ou Power-On Self Test (POST) que verifica a integridade física do sistema e dos periféricos. Em seguida, o programa procura pela palavra 0xAA55 (assinatura de boot) no primeiro setor de um periférico do tipo disco (Floppy, HD, CD/DVD etc.) ou cartão de memória (pen drive, cartão SD etc.).

Clicando nesta imagens podes ver um exemplo do POST


Uma vez encontrado o setor de boot, normalmente chamado de Master Boot Record (MBR) o sistema carrega o código para o endereço 0x7C00 do segmento inicial da memória (CS:IP 0000:7C00) e passa a executar as instruções a partir daí.

Bem, a partir daí o kernel do sistema operacional é carregado na memória. No caso do Linux, o código binário do kernel é carregado em 0x07C0 (em modo real 0000:7C00 = 0x07C0 shifted left once + 0). O código Assembly do Loader pode ser encontrado em /usr/src/linux/arch/x86/boot/header.S (linux=linux-source-X.X.X para cada versão de kernel). O código do header.S substitui os antigos códigos do kernel bootsect.S/setup.S.

Master Boot Record [1]


O passo seguinte é a descompressão do kernel (zImage ou vmlinuz). O arquivo zImage (vmlinuz) não é apenas uma imagem comprimida mas tem o próprio gzip no início do arquivo (não se pode descomprimir o arquivo vmlinuz). Durante este processo, qualquer erro trava tudo pois o sistema não está operativo e a BIOS não tem o controle. Finalmente, a função start_kernel() que é descrita no arquivo /usr/src/linux/init/main.c entra em ação e nunca retorna. A partir deste ponto, todo o SO codificado em C entra em operação.

Hello World!

Referências:

[1] Fonte da imagem: Voronin, A. Data storage on hard discs (Part 1) May 22, 2001, http://www.engineersgarage.com/mygarage/how-computer-boots-up

terça-feira, 3 de janeiro de 2012



Anatomia de um kernel

… uma visão global.


O núcleo (kernel) de um sistema operacional é o responsável pela camada que faz a interface entre o hardware e os serviços principais do SO. No caso do Linux, ele tem uma estrutura derivada do MINIX do Tannenbaum [1], desenvolvido pelo Linus Torvalds ainda quando estudante. Torvalds tomou por base o microkernel MINIX e criou um kernel monolítico com cinco subsistemas [2]:

1. O Process scheduler (SCHED) que é responsável pelo controle de acesso dos processos à CPU. Ele cria as facilidades de interface entre hardware – CPU – processos. É o SCHED que controla os semáforos do sistema operacional Linux (veja o artigo sobre semáforos).

2. O Memory Manager (MM) que controla o uso da memória principal pelos processos de forma segura e eficiente. O MM suporta memórias virtuais que permite ao Linux rodar processos que usem mais memória do que disponível no sistema e, ainda, controla a paginação de segmentos de memória na área de SWAP.

3. O Virtual File System (VFS) que reune a diversidade de hardware em uma interface comum, criando uma abstração dos detalhes de cada tipo de dispositivo. O VFS também permite a utilização concomitante e simultânea de vários formatos de sistemas de arquivos (Mac, DOS, BSD etc.).

4. O Network Interface (NET) que disponibiliza e controla o acesso a dispositivos de rede, tais como placas de rede, MODEM, Bluetooth etc.

5. O Inter-Process Communication (IPC) é o subsistema que controla a interação entre os processos e prove a comunicação entre eles. É o IPC que é responsável pela preemptividade (ver meu artigo sobre preemptividade e multitarefa).

Figura 1 - Esquema de relações entre os subsistemas do kernel do Linux


Na figura 1 se observa que o subsistema principal ou centro do núcleo é o SCHED do qual dependem todos os outros processos pois ele é quem controla o tempo de execução de cada processo. O IPC depende do MM para alocar e compartilhar a memória pois isto permite que dois processos acessem a mesma área de memória comum. A relação entre o SCHED e o MM está ligada ao gerenciamento do mapa de memória do hardware para controle de acesso de cada processo em execução. Isto permite que os segmentos de memória sejam "paginados" e reconstituídos dependendo do processo em execução. O VFS usa o NET para suportar o dispositivo de ramdisk e o sistema de arquivo remoto (NFS) [3]

Além do subsistema MM depender do SCHED ele usa o subsistema VFS para suporte ao swap principalmente quando um processo precisa acessar um segmento que se encontra "paginado" (swapped).

A vantagem de um kernel monolítico está na performance. Embora um microkernel seja mais flexível, um kernel monolítico permite que o núcleo e todos os serviços rodem como um único processo, num espaço de endereçamento único possibilitando uma alta performance (serviços em um microkernel rodam e espaços de endereçamento separados).

Existem vantagens e desvantagens na comparação de um microkernel e um kernel monolítico. Por exemplo, em um microkernel a manutenção é mais simples porque qualquer modificação é feita em cada tarefa (task) do subsistema. Por outro lado, é necessário 2 vezes a chamada de TASK_SWITCH (uma para entrar no âmbito da tarefa e outro para retornar da função).

Os microkernels são bons exemplos didáticos de sistemas (e.g. Minix) mas não são otimizados. O kernel do Linux pode usar "threads" do kernel para implementar uma estrutura do tipo microkernel como, por exemplo, o daemon kswapd (kernel swap daemon) que é usado para recuperar as páginas de memória na área de swap e não tem problemas de performance pois a operação é lenta por natureza.


Referências:

[1] Tanenbaum, A. S. Modern Operating Systems, Prentice Hall, 1992

[2] Bovet, D. P. e Cesati, M. Understanding the Linux Kernel, O'Reilly, 2000

[3] Rubini, A. Linux Device Drivers, O'Reilly, 1998

segunda-feira, 2 de janeiro de 2012









 Windows 7


...Sete? Que sete? Sete o quê?


Quanta honra para ser o primeiro post de 2012. Mas é para mostrar que mentalidade tem que ser aberta... ABERTA, eu disse. Não sou fã do Windows da Microsoft, isto todo mundo sabe, mas a filosofia de portabilidade me obriga a conhecê-lo como SO se bem que, convenhamos... o sistema operacional do Windows 7 é o DOS ainda. Vou fazer alguns comentários sobre o SO para cumprir a missão deste blog (viu guri? Não sou tão xiita assim!).

Claro que a instalação foi feita em uma máquina virtual Oracle VirtualBox, com 1,5 GB de memória, e uma configuração bem comum e econômica. Diga-se de passagem que o SO me surpreendeu, roda bem, sem nenhuma lentidão e tem uma interface mais limpa.

O processo de instalação em si, foi tranquilo, sem sustos e apenas a mensagem: "O computador será iniciado várias vezes durante a instalação" que não surpreendeu... afinal, o kernel  precisa ser recarregado depois das primeiras alterações de configuração (heranças do microkernel NT?). Alguns descuidos são perceptíveis. Primeiro, é horrorosa a primeira tela de "loading files... ". Acho que nem o Hurd consegue ser pior! Parecia um Atari antigão! Segundo, o gerundismo que impera e que "vai poder estar imperando" enquanto o sistema "vai poder estar sendo instalado" e que causa a literal verborragia informática típica do século (já) passado. Porque dizer "a instalação está sendo inicializada..." quando se pode dizer "inciando a instalação"? Pois é ... verborragia!

Depois do clássico "O Windows precisa ser reiniciado para continuar" vem mais letras sem antialiasing (descuido estético) informando: "Inciando os serviços". Depois vem o "concluindo a instalação... " e os três pontinhos piscando me lembrou o tempo dos terminais ASCII. Eu usava muito este recurso em meus programas em Assembly! Mas depois de novo reboot, apareceu o "Iniciando o Windows..." halas... sem aquele irritante "inicializando" que era de matar.

O que mais decepciona? É que o Windows 7 é "programa de índio", ou seja, vem pelado! Não tem editor de texto, nem de imagem e nem de apresentação. Não tem planilha nem compilador... C, então, nem pensar. Primeira coisa que um usuário Unix faz? Executar comando: cmd.exe e enter! O que se lê? Microsoft Windows [versão 6.1.7601]... Windows 7 porque? WTF!

Como pretendia explorar mais o SO, escolhi instalar um "commander" para verificar arquivos e diretórios. Instalei o FreeCommander e a grande decepção me desestimulou... lá está o velho DOS... com seus .bat e .sys. Talvez o mais longe do DOS que o Windows chegou foi na versão de 64 bits. Mas digo isso em relação àquele velho MS-DOS, porque o Windows continua sendo um sistema operado a disco, ou seja, um DOS. Uma olhadinha no velho command.com (16 bits), agora com o nome de cmd.exe (32 bits), e encontramos as interrupções 21H... no dump do arquivo:

pop     DS
mov     DX,000E
mov     AH,09
INT     21

Alguém se lembra disso? "Encontre o segmento de dados, carregue o endereço em DX, chame a interrupção 21H do DOS com o código 09." Não é preciso dizer mais nada... Nem tem sentido avaliar o SO chamado DOS (6.1 ???) sem novidades. Em suma, não mudou nada! O usuário, para variar, sempre pagando mais por nada menos que enfeites; ou pagando mais por maquilagem!

domingo, 25 de dezembro de 2011

FreeBSD

... oPtimizando o kernel.

O que queres? Um kernel mais leve, mais rápido, menor ou o quê? Em termos de opções de kernel, o FreeBSD é um dos melhores. Não... eu diria que ele é "O MÁXIMO". Mas tudo depende do que se quer fazer com ele. A maneira mais simples é copiar o GENERIC para um arquivo com o nome da tua máquina e começar a pensar no que mexer.

# cd /usr/src/sys/i386/conf
# cp GENERIC MEUKERNEL

Depois de alterado o arquivo MEUKERNEL, a compilação do MEUKERNEL é feita usando-se o parâmetro KERNCONF:

# cd /usr/src
# make buildkernel KERNCONF=MEUKERNEL

e instalar:

# make installkernel KERNCONF=MEUKERNEL


Supondo que saibas toda esta estória de 'make buildkernel', 'make installkernel', 'make buildworld' etc., os comentários deste artigo são mais específicos para a configuração do kernel a ser compilado. Se não sabes, melhor dar uma lida antes em: Building and Installing a Custom Kernel. [1]

Tamanho do Kernel

O tamanho do kernel depende do que ele carrega para a memória em termos de módulos. Hoje o FreeBSD é bem mais modulado mas, mesmo assim, alguns módulos acabam levando muito código inútil para o kernel, aumentando a memória utilizada (memory footprint). Em servidores, por exemplo, pode-se eliminar todos os módulos de rede wireless se eles forem todos cabeados.

# Wireless NIC cards
device          wlan            # 802.11 support
device          wlan_wep        # 802.11 WEP support
device          wlan_ccmp       # 802.11 CCMP support

etc...

Omitir a opção de sistemas de arquivo MSDOS (options  MSDOSFS) aumenta a liberação de memória, bem como eliminar os símbolos de DEBUG (makeoptions  DEBUG=-g). Só isto pode liberar cerca de 60% a 70% da memória utilizada pelo kernel.

Sim, estás pronto para compilar o kernel... mas, espere... "se voce fizer agora voce ainda leva mais uma máquina de lavar..." oops, não! Isto é marketing... nós ainda precisamos de making não de marketing.

O make usa um arquivo /etc/make.conf que, se nunca o editastes, provavelmente, ele não existe ainda. Mas tem um arquivo de configuração no /usr/local/etc/default/make.conf que pode servir de base para criares o teu. Ele serve para as opções do make e pode ser usado para otimizar o compilador para determinado tipo de CPU [2] e escolher opções (flags) de compilação.

Tipo de CPU

Permite o controle do código que é gerado especificamente para uma determinada CPU. Isto pode tornar o Kernel mais rápido e adaptado para teu tipo de arquitetura e pode ser feito usando-se a variável CPUTYPE.

CPUTYPE=<tipo>

Onde <tipo> pode ser uma CPU x86 tipo AMD (opteron, athlon-mp, athlon-xp, athlon-4, athlon-tbird, athlon, k8, k7, k6-3, k6-2 ou k5), tipo Intel (core2, core,nocona, pentium4m, pentium4, prescott, pentium3m, pentium3, pentium-m, pentium-2, pentiumpro, pentium-mmx, pentium, i486 e i386), tipo Via (c3 e c3-2), Alpha/AXP (ev67, ev6, pca56, ev56, ev5, ev45 e ev4), tipo AMD64 (opteron, athlon64, nocona, prescott, core2) e Intel64 (itanium2, itanium).

Flags de compilação:

Existem flags de compilação para a compilação de programas e aplicativos (CFLAGS) e para a compilação do kernel (COPTFALGS). Normalmente pode-se usar nível 3 (-O3) em CFLAGS e nível 2 (-O2) em COPTFLAGS. A compilação do kernel nunca deve ser feita com -O3 porque tende a produzir efeitos colaterais indesejáveis no kernel resultando em kernel panic. Normalmente, o -O3 produz um código mais veloz em detrimento do tamanho do binário gerado.

CFLAGS= -O3 -pipe -funroll-loops -ffast-math
COPTFLAGS= -O2 -pipe -funroll-loops -ffast-math

A opção -pipe permite que a passagem de códigos entre processos se de por pipe ao invés de arquivos temporários. A opção -funroll-loops desdobra os loops de número conhecido de iteratividade, permitindo maior velocidade de execução. Finalmente, a opção -ffast-math elimina as regras estritas de operações matemáticas descritas nas normas IEEE/ANSI. Esta opção deve ser evitada no caso de implementações estritas destas normas como, por exemplo, na compilação do Scilab, Octave ou das bibliotecas ATLAS e BLAS, bem como no desenvolvimento de programas que usem código GSL (Gnu Scientific Library).

Caso não queira alterar as opções do make, pode-se usar o arquivo de configuração do kernel e na linha abaixo da declaração 'machine', adicionar:

makeoptions    COPTFLAGS="-O2 -pipe -funroll-loops -ffast-math"

Outros truques (tricks):

Uma outra maneira de se limitar a memória usada pelo kernel é desabilitar o código relativo ao serviço de NFS. Se tu estás configurando uma estação ou servidor e sabes que não vais usar sistemas de arquivo remotos via NFS, podes usar a opção:

options        NFS_NOSERVER

Outra maneira de diminuir a memória usada pelo kernel é estabelecer o número máximo de dispositivos de swap. Normalmente o kernel precisa alocar uma quantidade fixa de memória para mapear a intercalação dos dispositivos de swap (operação chamada de interleave). Normalmente uso 1 para estações de trabalho e 2 para servidores.

options         NSWAPDEV=<number>

Referências:



[1] Manual do FreeBSD online: http://www.freebsd.org/doc/en/books/handbook/kernelconfig-building.html

[2] Kinsella, R. "Profiling and Debugging the FreeBSD* Kernel", Intel White Paper, Document Number: 321772-001, Intel Corp., 2009.

sexta-feira, 9 de dezembro de 2011

Virtualização

Xen, Qemu, VirtualBox, VMWare... o que usar?

Primeiramente, tudo depende do que o usuário necessita. Por exemplo, se é necessário criar máquinas virtuais para distribuição de serviços (http, smtp, ftp etc.) então o Xen é "o cara". Se for para testar a portabilidade entre diversas arquiteturas (x86, Sparc, PPC etc.) então a opção é o QEMU. Se for para testar performance em diversos SOs ou rodar outras distribuições em mesma arquitetura de processador, então o VirtualBox da Oracle pode ser a melhor opção.

Basicamente, podemos dizer que QEmu + KVM e VirtualBox são equivalentes, enquanto o Xen e VMWare ESXI têm uma outra abordagem de virtualização. O Xen é um virtualizador (hypervisor — a tradução é livre e minha) ou seja, uma camada de software que corre diretamente no hardware do computador, substituindo o sistema operacional propriamente dito.

A virtualização pode ser vista como um sistema "hospedeiro" e um sistema "cliente". O sistema hospedeiro pode disponibilizar recursos de hardware para que um virtualizador controle uma ou mais máquinas virtualizadas (Fig. 1).

Figura 1. Esquema de virtualização do VirtualBox


Os mais importantes virtualizadores de hoje são:


Xen

Usa um modelo denominado "thin hypervisor", com um executável de 2 MB; é atrelado aos service domains; e não usa drivers (os sistemas hospedeiros é que carregam módulos e drivers necessários). Em resumo é uma virtualização real do hardware.

VMware ESXI

Similar ao Xen mas contém os drivers de harware e mantém o gerenciamento de pilhas. O suporte do hardware depende dos drivers do VMware. [1]

QEMU+KVM

É diferente da virtualização do Xen ou do VMware. A virtualização é feita no kernel do sistema hospedeiro. A virtualização do hardware é feita pelo software e o processador virtualizado pode ser de qualquer arquitetura suportada (x86, PPC, ARM, MIPS, Sparc 32 e 64, Motorola M68k etc.) oferecendo maior portabilidade. O KVM é um acelerador da virtualização no kernel que permite a execução do código nativo enquanto emula o restante da máquina. O QEMU pode emular o multiprocessamento simétrico (SMP) mesmo em um hospedeiro com apenas uma CPU. [2]

VirtualBox

Desenvolvido inicialmente pela Sun MicroSystems e agora mantido pela Oracle, o VirtualBox é uma excelente escolha para a virtualização de sistemas operacionais sob uma mesma arquitetura. O modelo de virtualização é de compartilhamento do hardware do hospedeiro, rodando o software do sistema virtualizado direto na CPU. Entretanto o VirtualBox sempre monitora para evitar danos ao sistema hospedeiro. Os processadores Intel e AMD já suportam as tecnologias VT-x e AMD-v para a virtualização de hardware, permitindo ao VirtualBox a interceptação de operações potencialmente danosas.

Nota: em alguns sistemas é necessário habilitar a funcionalidade na BIOS.

VirtualBox [3], Xen [4] e KVM [5] são baseados no QEMU. O QEMU-SystemC [6] usa QEMU para simular um sistema onde os dispositivos de hardware são desenvolvidos em SystemC.

Referências:

[1] http://www.vmware.com/, The VMWare PC virtualizer.

[2] http://wiki.qemu.org/Main_Page, open source processor emulator.

[3] http://virtualbox.org/, The VirtualBox PC virtualizer.

[4] http://www.xen.org/, The Xen hypervisor.

[5] http://kvm.qumranet.com/kvmwiki/Front_Page, Kernel Based Virtual Machine (KVM).

[6] http://www.greensocs.com/projects/QEMUSystemC, QEMU-SystemC, a hardware co-simulator.