FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

RISC-V版xv6のコンソールデバッグ

RISC-Vに移植したxv6のデバッグを引き続き行っているのだが、どうやら表示系の調子がおかしい。

cpu-4096,33554432: init start

コア数が多すぎる(笑)。

デバッグしているのだが、ついでなのでxv6の表示系はどのように構成されているのか見ていく。

xv6のUARTの仕組み

xv6では、printfなどを実行するとUART経由でコンソールに表示されるようになっている。これにはx86の機能を使っているようだ。

#define COM1    0x3f8

static int uart;    // is there a uart?

void
uartinit(void)
{
  char *p;

  // Turn off the FIFO
  outb(COM1+2, 0);

  // 9600 baud, 8 data bits, 1 stop bit, parity off.
  outb(COM1+3, 0x80);    // Unlock divisor
  outb(COM1+0, 115200/9600);
  outb(COM1+1, 0);
  outb(COM1+3, 0x03);    // Lock divisor, 8 data bits.
  outb(COM1+4, 0);
  outb(COM1+1, 0x01);    // Enable receive interrupts.

別のアーキテクチャに移植するときは、メモリマップを改造して、UARTの置かれているメモリ領域にデータを出力すればよい。

void
uartputc(int c)
{
  int i;

  if(!uart)
    return;
  for(i = 0; i < 128 && !(inb(COM1+5) & 0x20); i++)
    microdelay(10);
  outb(COM1+0, c);
}

xv6のcprintfの仕組み

cprintfでは、可変引数の機能を使っている。

// Print to the console. only understands %d, %x, %p, %s.
void
cprintf(char *fmt, ...)
{
  int i, c, locking;
  uint *argp;
  char *s;

  locking = cons.locking;
  if(locking)
    acquire(&cons.lock);

  if (fmt == 0)
    panic("null fmt");

  argp = (uint*)(void*)(&fmt + 1);
  for(i = 0; (c = fmt[i] & 0xff) != 0; i++){
    if(c != '%'){

ソースコードを見る限り、%d, %x, %p, %s, %%が利用可能なようだ。

%d, %x, %pのときは、値を文字列に変換する処理に入る。

    switch(c){
    case 'd':
      printint(*argp++, 10, 1);
      break;
...

static void
printint(int xx, int base, int sign)

RISC-VのGCCコンパイルしたcprintf

ところが、どうやら可変長引数の処理のところにバグがありそうで、うまく表示ができていない。

80100600 <cprintf>:
80100600:   fa010113            addi    sp,sp,-96
80100604:   02112e23            sw  ra,60(sp)
80100608:   02812c23            sw  s0,56(sp)
8010060c:   04010413            addi    s0,sp,64
80100610:   fca42623            sw  a0,-52(s0)
80100614:   00b42223            sw  a1,4(s0)
80100618:   00c42423            sw  a2,8(s0)
8010061c:   00d42623            sw  a3,12(s0)
80100620:   00e42823            sw  a4,16(s0)
80100624:   00f42a23            sw  a5,20(s0)
80100628:   01042c23            sw  a6,24(s0)
8010062c:   01142e23            sw  a7,28(s0)

最初に引数を格納するのだが、なぜa0だけオフセットが違う?a1以降とメモリ場所がずれており、引数が上手く取り扱えていない気がする。

とりあえず、このあたりも継続してデバッグしていく。