serial/chardevでQEMUのシリアル通信を見る

/ Linux QEMU

QEMUをSSH越しのCUIなどで使用する際に-serial mon:stdioを指定して仮想マシンのシリアル出力を別GUIではなくqemuのコマンドをたたいたその場所に出力させることがある。この際、QEMUそのものの出力と仮想マシンがシリアル通信ポート (PL011)に書き込んだことによる出力が混在してしまって解析が行いにくい時がある。

-serialオプションと-chardevオプションを組み合わせることでシリアル通信用のコンソールとQEMUを立ち上げたコンソールを別々に用意することができる。最新版であるQEMU 8.2.0を使ってこの方法を紹介していく。

chardev/serialのhelp表示

8.2.0におけるhelp表示の関係する部分を確認する。まずは-chardevに関する箇所は以下のようになっている。

Character device options:
-chardev help
-chardev null,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]
-chardev socket,id=id[,host=host],port=port[,to=to][,ipv4=on|off][,ipv6=on|off][,nodelay=on|off]
         [,server=on|off][,wait=on|off][,telnet=on|off][,websocket=on|off][,reconnect=seconds][,mux=on|off]
         [,logfile=PATH][,logappend=on|off][,tls-creds=ID][,tls-authz=ID] (tcp)
-chardev socket,id=id,path=path[,server=on|off][,wait=on|off][,telnet=on|off][,websocket=on|off][,reconnect=seconds]
         [,mux=on|off][,logfile=PATH][,logappend=on|off][,abstract=on|off][,tight=on|off] (unix)
-chardev udp,id=id[,host=host],port=port[,localaddr=localaddr]
         [,localport=localport][,ipv4=on|off][,ipv6=on|off][,mux=on|off]
         [,logfile=PATH][,logappend=on|off]
-chardev msmouse,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]
-chardev vc,id=id[[,width=width][,height=height]][[,cols=cols][,rows=rows]]
         [,mux=on|off][,logfile=PATH][,logappend=on|off]
-chardev ringbuf,id=id[,size=size][,logfile=PATH][,logappend=on|off]
-chardev file,id=id,path=path[,input-path=input-file][,mux=on|off][,logfile=PATH][,logappend=on|off]
-chardev pipe,id=id,path=path[,mux=on|off][,logfile=PATH][,logappend=on|off]
-chardev pty,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]
-chardev stdio,id=id[,mux=on|off][,signal=on|off][,logfile=PATH][,logappend=on|off]
-chardev braille,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]
-chardev serial,id=id,path=path[,mux=on|off][,logfile=PATH][,logappend=on|off]
-chardev parallel,id=id,path=path[,mux=on|off][,logfile=PATH][,logappend=on|off]

chardevに関しては-chardev helpで次のような表示が行えるとかかているので実行すると下記が出力された。

qemu-system-x86_64 -chardev help
Available chardev backend types:
  ringbuf
  mux
  pipe
  stdio
  pty
  null
  msmouse
  socket
  braille
  vc
  parallel
  dbus
  memory
  udp
  file
  wctablet
  serial
  testdev

次に-serialに関する場所をみると下記。

Debug/Expert options:
-compat [deprecated-input=accept|reject|crash][,deprecated-output=accept|hide]
                Policy for handling deprecated management interfaces
-compat [unstable-input=accept|reject|crash][,unstable-output=accept|hide]
                Policy for handling unstable management interfaces
-fw_cfg [name=]<name>,file=<file>
                add named fw_cfg entry with contents from file
-fw_cfg [name=]<name>,string=<str>
                add named fw_cfg entry with contents from string
-serial dev     redirect the serial port to char device 'dev'
-parallel dev   redirect the parallel port to char device 'dev'
-monitor dev    redirect the monitor to char device 'dev'
-qmp dev        like -monitor but opens in 'control' mode
-qmp-pretty dev like -qmp but uses pretty JSON formatting
-mon [chardev=]name[,mode=readline|control][,pretty[=on|off]]
-debugcon dev   redirect the debug console to char device 'dev'

こちらは断片的な情報しかなくこれだけ見てオプションを考えることは難しい(QEMUは他もそうだが)

serial chardev:の使用

この使用例は-serialのヘルプには書かれていないが下記のようにして使える。

qemu-system-x86_64 \
-chardev socket,id=uart,path=/tmp/qemu.socket,server=on \
-serial chardev:uart \
...

この引数でqemuを起動するとQEMUの出力はそのままのターミナルに流れながら別途で/tmp/qemu.socketにUNIXソケットが生えてくる。別ターミナルで

nc -U /tmp/qemu.socket

もしくは

socat UNIX-CONNECT:/tmp/qemu.socket STDIO

で接続することでこちらは仮想マシンのシリアル出力を確認することができる。

おまけ mon chardev:

下記のようにすると当該chardevはQEMUモニタ用のチャンネルになるらしい。

qemu-system-x86_64 \
-chardev socket,id=monitor,path=/tmp/qemu.socket,server=on \
-mon chardev:monitor \
...

モニタは接続すると次のようなインタラクティブシェルが現れる。

QEMU 8.2.0 monitor - type 'help' for more information
(qemu) x
unexpected end of expression
Try "help x" for more information
(qemu) quit

通常これはQEMU起動したターミナルでCtrl-A+Cで入れるものだがこちらも別ターミナルで操作できるようにしておくことで同じ理由で利便性や何かを自動化するうえでの実現性が増しそうである。このほか、"Debug/Expert options"ヘルプにあるようにgdbの接続なども別ターミナルで行える。