QEMUのRaspberry Pi 3モデルでUSBホストエミュレーション

QEMUのqemu-develメーリングリストにRaspberry Pi のUSBホストのエミューレーションのコードが投稿されていたので動作を試してみました。

2020年4月時点ではV4のパッチが投稿されていますが、まだマージされてません。

* USBホストエミュレーションのパッチ
 * [[PATCH v4 0/7] dwc-hsotg (aka dwc2) USB host controller emulation](https://lore.kernel.org/qemu-devel/20200428022232.18875-1-pauldzim@gmail.com/)

動作状況は、作者の人が言うには「I have tested with USB network,
mass storage, mouse, keyboard, and tablet. I have tested with the dwc2
driver in the upstream Linux kernel, and with the dwc-otg driver in the
Raspbian kernel.」とのことです。

# QEMU 5.0にパッチを適用してビルド

QEMU 5.0にパッチを適用してビルドしてみた。

パッチのメールをraw形式でp1 ... p7 に保存して下記手順でpatchコマンドを使う。

```
$ cd qemu-5.0.0
$ patch  -p1 < ../files/p1
patching file hw/arm/bcm2835_peripherals.c
patching file hw/misc/Makefile.objs
patching file hw/misc/bcm2835_mphi.c
patching file include/hw/arm/bcm2835_peripherals.h
patching file include/hw/misc/bcm2835_mphi.h
$ patch  -p1 < ../files/p2
patching file include/hw/usb/dwc2-regs.h
$ patch  -p1 < ../files/p3
patching file hw/usb/hcd-dwc2.h
$ patch  -p1 < ../files/p4
patching file hw/usb/Kconfig
patching file hw/usb/Makefile.objs
patching file hw/usb/hcd-dwc2.c
patching file hw/usb/trace-events
$ patch  -p1 < ../files/p5
patching file hw/usb/dev-storage.c
$ patch  -p1 < ../files/p6
patching file hw/arm/bcm2835_peripherals.c
patching file include/hw/arm/bcm2835_peripherals.h
$ patch  -p1 < ../files/p7
patching file tests/acceptance/boot_linux_console.py
```

qemuをビルド

```
$ ./configure --prefix=`pwd`/build --target-list=arm-softmmu,aarch64-softmmu  --audio-drv-list=alsa --enable-trace-backend=log
$ make
$ make install
$  ./build/bin/qemu-system-aarch64 --version
QEMU emulator version 5.0.0
Copyright (c) 2003-2020 Fabrice Bellard and the QEMU Project developer

```

# QEMUモニタで確認

qemu に ```-device usb-kbd```のオプションを指定して適当なプログラムを実行してからモニタモードにする。
```info qtree```をすると、dwc2-usbが見つかり、その先にusb-busが生えて、Hubとkeyboardが繋がっていました。

```
$ qemu-system-aarch64 -M raspi3 -m 128 -serial null -serial mon:stdio -nographic -device usb-kbd  -kernel kernel.elf

Ctrl-A cでモニターモードへ移行

QEMU 4.2.0 monitor - type 'help' for more information
(qemu) info qtree 
...
  dev: dwc2-usb, id ""                                                                                                                                   
    gpio-out "sysbus-irq" 1                                                                                                                              
    mmio ffffffffffffffff/0000000000011000                                                                                                               
    bus: usb-bus.0                                                                                                                                       
      type usb-bus                                                                                                                                       
      dev: usb-hub, id ""                                                                                                                                
        ports = 8 (0x8)                                                                                                                                  
        port-power = false                                                                                                                               
        port = ""                                                                                                                                        
        serial = ""                                                                                                                                      
        full-path = true                                                                                                                                 
        msos-desc = true                                                                                                                                 
        addr 0.0, port 1, speed 12, name QEMU USB Hub, attached                                                                                          
      dev: usb-kbd, id ""                                                                                                                                
        usb_version = 2 (0x2)                                                                                                                            
        display = ""                                                                                                                                     
        port = ""                                                                                                                                        
        serial = ""                                                                                                                                      
        full-path = true                                                                                                                                 
        msos-desc = true                                                                                                                                 
        addr 0.0, port 1.1, speed 12, name QEMU USB Keyboard, attached  
...
```

# Linuxで確認

以前の記事「[QEMUのRaspberry Pi 3モデルでLinuxを起動](https://qiita.com/eggman/items/596df11cd7d0a90bd529)」の手順でDebianを起動してみました。

```
$ wget https://people.debian.org/~stapelberg/raspberrypi3/2018-01-08/2018-01-08-raspberry-pi-3-buster-PREVIEW.img.xz
$ xz -d 2018-01-08-raspberry-pi-3-buster-PREVIEW.img.xz
$ sudo virt-filesystems -a 2018-01-08-raspberry-pi-3-buster-PREVIEW.img
/dev/sda1
/dev/sda2

$ sudo guestfish --ro -a 2018-01-08-raspberry-pi-3-buster-PREVIEW.img -m /dev/sda1
...
><fs> copy-out /bcm2837-rpi-3-b.dtb .
><fs> copy-out /vmlinuz-4.14.0-3-arm64 .
><fs> copy-out /initrd.img-4.14.0-3-arm64 .
><fs> quit
```

という手順で必要なファイルを取り出し、-device usb-net を指定してQEMUを実行します。

```
qemu-system-aarch64 -M raspi3  -serial mon:stdio \
-kernel vmlinuz-4.14.0-3-arm64 \
-initrd initrd.img-4.14.0-3-arm64 \
-dtb bcm2837-rpi-3-b.dtb \
-append "rw earlycon=pl011,0x3f201000 console=ttyAMA0 loglevel=8 root=/dev/mmcblk0p2 fsck.repair=yes net.ifnames=0 rootwait memtest=1" \
-drive file=2018-01-08-raspberry-pi-3-buster-PREVIEW.img,format=raw,if=sd \
-device usb-net
```

起動時のメッセージを見るとUSBホストとUSBネットワークアダプタが認識されてました。

```
...
dwc2 3f980000.usb: 3f980000.usb supply vusb_d not found, using dummy regulator
dwc2 3f980000.usb: 3f980000.usb supply vusb_a not found, using dummy regulator
dwc2 3f980000.usb: dwc2_check_params: Invalid parameter max_packet_count=511
dwc2 3f980000.usb: dwc2_check_params: Invalid parameter max_transfer_size=65535
dwc2 3f980000.usb: DWC OTG Controller
dwc2 3f980000.usb: new USB bus registered, assigned bus number 1
dwc2 3f980000.usb: irq 41, io mem 0x3f980000
usb usb1: New USB device found, idVendor=1d6b, idProduct=0002
usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
usb usb1: Product: DWC OTG Controller
usb usb1: Manufacturer: Linux 4.14.0-3-arm64 dwc2_hsotg
usb usb1: SerialNumber: 3f980000.usb
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 1 port detected
usb 1-1: new full-speed USB device number 2 using dwc2
usb 1-1: New USB device found, idVendor=0409, idProduct=55aa
usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 1-1: Product: QEMU USB Hub
usb 1-1: Manufacturer: QEMU
usb 1-1: SerialNumber: 314159-1
hub 1-1:1.0: USB hub found
hub 1-1:1.0: 8 ports detected
usb 1-1.1: new full-speed USB device number 3 using dwc2
usb 1-1.1: New USB device found, idVendor=0525, idProduct=a4a2
usb 1-1.1: Product: RNDIS/QEMU USB Network Device
usb 1-1.1: Manufacturer: QEMU
usb 1-1.1: SerialNumber: 1-1.1
...
cdc_ether 1-1.1:1.0 eth0: register 'cdc_ether' at usb-3f980000.us
rnet Device, 40:54:00:12:34:58
usbcore: registered new interface driver cdc_ether
usbcore: registered new interface driver cdc_subset
...

```

起動後にinterfaceの確認

```
# ip addr show eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN group default qlen 1000
    link/ether 40:54:00:12:34:58 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::4254:ff:fe12:3458/64 scope link 
       valid_lft forever preferred_lft forever

```

ということで動いているっぽいです。