Resumo e Explicação da Funcionalidade de tohost
e fromhost
no Spike e em Ambientes RISC-V
A comunicação entre o simulador Spike e o programa em execução é realizada por meio de dois registradores especiais: tohost
e fromhost
. Esses registradores não fazem parte de um padrão oficial do RISC-V, mas são uma convenção adotada pela equipe da UC Berkeley para permitir a interação entre o host (sistema que executa o simulador) e o target (código RISC-V em execução no simulador).
Definição e Função
-
tohost
: Este registrador é utilizado para enviar comandos e dados do target para o host. A escrita de valores específicos emtohost
pode disparar a realização de uma chamada de sistema (syscall) ou a terminação do programa em execução.- Se o bit menos significativo (LSB) for 0, os bits superiores representam um ponteiro para uma estrutura que descreve a chamada de sistema.
- Se o LSB for 1, os bits superiores contêm o código de saída do programa, onde o valor 0 indica sucesso e qualquer outro valor indica falha.
-
fromhost
: Este registrador é usado pelo host para enviar respostas ou comandos ao target. O target deve verificar periodicamente o valor defromhost
para identificar novos comandos recebidos.
Definição de tohost
e fromhost
Para se comunicar com o simulador uma região da memória precisa ter o simbolo associado a estas duas localidades. Há duas formas de se fazer isso. A primeira é através do linker script:
OUTPUT_ARCH("riscv")
ENTRY(_start)
EXTERN(_vectors)
SECTIONS
{
. = 0x80000000;
.tohost : ALIGN(0x1000)
{
*(.tohost)
}
.fromhost : ALIGN(0x1000)
{
*(.fromhost)
}
.text : ALIGN(0x1000) {DEFINIÇÕES DA SEÇÃO .text}
}
E no código em C associamos uma variável a essas seções:
volatile unsigned long tohost __attribute__((section(".tohost")));
volatile unsigned long fromhost __attribute__((section(".fromhost")));
Então basta escrever/ler nessas variáveis que o simulador estará monitorando.
A segunda forma é através de código em assembly:
.section .text
.globl exit
# Função void exit(long) RV64
.globl exit
exit:
slli a0, a0, 1
ori a0, a0, 1
la t0, tohost
sd a0, 0(t0)
1: j 1b
.globl putchar
putchar:
li t1, 0x0101000000000000
or a0, t1, a0
la t0, tohost
sd a0, 0(t0) # Cuidado não é sb!! sb grava bytes.
ret
.section .tohost, "aw", @progbits
.align 6
.globl tohost
tohost: .dword 0
.align 6
.globl fromhost
fromhost: .dword 0
Onde se ve as definições de fromhost
e tohost
bem como um exemplo de aplicação definindo a função void exit(long)
e void putchar(int)
.
Exemplo de Uso
Suponha que temos um programa bare-metal que precisa realizar uma chamada de sistema para imprimir um caractere no console. O processo seria semelhante ao seguinte:
- O programa escreve um valor especial em
tohost
, indicando que deseja realizar uma operação de saída de caractere. - O Spike detecta a escrita em
tohost
e interpreta o comando. - O Spike executa a ação correspondente (por exemplo, imprime o caractere no console).
- Se necessário, o Spike pode responder ao programa por meio de
fromhost
.
Estrutura do Registro tohost
- Bits 63:56: Indicam o dispositivo. Existem dois dispositivos principais:
- Dispositivo 0: Usado para chamadas de sistema (syscalls).
- Dispositivo 1: Dispositivo de caractere bloqueante (para leitura/escrita de caracteres).
- Bits 55:48: Indicam o comando:
- Comando 0: Leitura de caractere (somente dispositivo 1).
- Comando 1: Escrita de caractere (somente dispositivo 1).
- Bits 47:0: Contêm o payload, que pode ser um ponteiro para uma estrutura de chamada de sistema ou um caractere a ser escrito.
Considerações para RV32
Embora tohost
e fromhost
tenham um formato de 64 bits, em sistemas RV32 esses registradores são acessados como duas palavras de 32 bits. Isso pode causar problemas de concorrência ao escrever valores de 64 bits em sistemas RV32, pois a escrita ocorre em duas etapas. No entanto, devido ao fato de o Spike processar blocos de instruções (geralmente em lotes de 5000), esse problema raramente se manifesta.
Exemplo de Implementação no FreeRTOS
Em uma demonstração do FreeRTOS executando no Spike, tohost
e fromhost
são utilizados para permitir que o sistema operacional emule chamadas de sistema Unix-like, possibilitando a saída de informações para o console e a interação com o host.
Limitações e Alternativas
Embora tohost
e fromhost
sejam mecanismos útis, eles apresentam algumas limitações:
- A falta de suporte completo para dispositivos em RV32.
- O uso de “magic numbers” (valores mágicos) que não são bem documentados.
Como alternativa, recomenda-se o uso de chamadas de sistema por proxy (proxy syscalls), que oferecem uma interface mais padronizada e flexível para a comunicação entre o target e o host.
Conclusão
A funcionalidade de tohost
e fromhost
é essencial para a execução e interação de programas bare-metal e sistemas operacionais no simulador Spike. Embora seja um mecanismo eficiente, a falta de documentação adequada torna seu uso complexo para novos desenvolvedores. Alternativas como proxy syscalls podem ser mais apropriadas em aplicações modernas.
Referências
- Código-fonte do Spike e exemplos de uso de
tohost
efromhost
. - Documentação do OpenSBI e do FreeRTOS para RISC-V.
- Discussões em repositórios de projetos relacionados ao ecossistema RISC-V.