Linux KVM環境におけるシリアル増設カードの件

前回記事の、検証を実際にやってみた。

1)ゲストマシン環境下では実質、シリアルは最大4ポートが限界
QEMUが440BXをベースとしているせいかIRQが足りない(笑)。
IRQが15までしかないようで空き状況を考えると、4ポートが限界です。

※ゲストOSが対応しているPCIシリアルカードをPCIパススルーとかすれば、これはこれでできるかもしれない。
 今回はターゲットOSがMS-DOSだったため、これは難しかった。MCDPC.EXEが対応している必要があったので。

シリアルポートは、マッピングでQEMU側でも4ポートをサポートしている。
例えば、ホストマシンの/dev/ttyS4~S7をゲストマシンのCOM1~4に割り当てるためには、QEMUの起動オプションに、

-parallel none -serial /dev/ttyS4 -serial /dev/ttyS5 -serial /dev/ttyS6 -serial /dev/ttyS7

を追加する。IRQ消費を防ぐためにパラレルポートは削っておく。
すると、ゲストマシン環境下では、下記のようにI/OaddrとIRQが割り当てられる。

COM1 = 3F8, IRQ = 4 < ---- COM1
COM2 = 2F8, IRQ = 3 <---- COM2
COM3 = 3E8, IRQ = 4 <---- COM3
COM4 = 2E8, IRQ = 3 <---- COM4
しかしこの状況のゲストマシン環境下ではゲストOSにもよるのだが、上記の手法では、IRQの4と3が競合して問題が発生してしまった。 MS-DOSはもちろんWindowsXPでも競合問題が解決できなかった。 つまり、このままでは2ポートまでしか認識できない。ISAとして認識してるようである。 今回どうしたかというと、競合を回避するためにIRQを変更してみた。 変更方法としては、QEMUのオプションで変更方法がないようなので、QEMUをソースインストールしパッチを当てる。I/OaddrとIRQは、
COM1 = 3F8, IRQ = 4 < ---- COM1
COM2 = 2F8, IRQ = 3 <---- COM2
COM3 = 3E8, IRQ = 5 <---- COM3
COM4 = 2E8, IRQ = 7 <---- COM4
となるようにすることとする。最新版をダウンロード。
# tar zxvf qemu-kvm-0.14.0.tar.gz
# cd qemu-kvm-0.14.0

# vi hw/serial.c (下記部分を修正)
-----
static const int isa_serial_io[MAX_SERIAL_PORTS] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
static const int isa_serial_irq[MAX_SERIAL_PORTS] = { 4, 3, 4, 3 };
↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
static const int isa_serial_io[MAX_SERIAL_PORTS] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
static const int isa_serial_irq[MAX_SERIAL_PORTS] = { 4, 3, 5, 7 };
-----

# make clean
# ./configure \
--disable-spice \
--disable-sdl \
--disable-xen \
--enable-mixemu \
--enable-vnc-thread \
--enable-kvm

# make
# make install

とすることで、回避できた。

ちなみにMS-DOSだとCOM4がMCDPC.EXEは認識するのだが、WindowsXP環境のDOS窓環境でMCDPC.EXEを動かすとCOM4が認識しなかった(謎)。
ということで、MS-DOSを使うことになりました。

ちなみにゲストOSがCentOSの場合で、ゲスト側のIRQを変更する場合は、こうするとできそうだが未検証。

Linuxカーネルのソースを修正(下記部分を修正)

# vi linux/arch/x86/include/asm/serial.h
-----
#define SERIAL_PORT_DFNS                        \
        /* UART CLK   PORT IRQ     FLAGS        */                      \
        { 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS },      /* ttyS0 */     \
        { 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS },      /* ttyS1 */     \
        { 0, BASE_BAUD, 0x3E8, 4, STD_COM_FLAGS },      /* ttyS2 */     \
        { 0, BASE_BAUD, 0x2E8, 3, STD_COM4_FLAGS },     /* ttyS3 */

↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

#define SERIAL_PORT_DFNS                        \
        /* UART CLK   PORT IRQ     FLAGS        */                      \
        { 0, BASE_BAUD, 0x3F8, 4, STD_COM_FLAGS },      /* ttyS0 */     \
        { 0, BASE_BAUD, 0x2F8, 3, STD_COM_FLAGS },      /* ttyS1 */     \
        { 0, BASE_BAUD, 0x3E8, 5, STD_COM_FLAGS },      /* ttyS2 */     \
        { 0, BASE_BAUD, 0x2E8, 7, STD_COM4_FLAGS },     /* ttyS3 */
-----

2)MS-DOSのCPU1コア100%の件
ゲストマシンのOSがMS-DOSの場合、アイドル状態(コマンドプロンプトによる入力待ち等)になると、アプリケーションによってはCPUを占領されてしまう。何にもしない無限ループでCPUを占領(笑)。
VMwareで公開されていた、DOSIDLE.EXEを常駐させてみると、コマンドプロンプト等ではCPU負荷は下げられたが、アプリケーションによってはCPUが占領された(アプリの作り方によるもの。当時はこれが主流だった)。
これはもうどうしようもない(笑)。結局、MS-DOSにCPU1コア分を割当てるような状況になってます。^^;

とりあえず、仮想環境で5マシンをVM化してみた。相変わらず1コアだけが100%。(T_T)。

まぁ、これでしばらく使ってみたいと思います。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*