[BitVisor-devel:28] Re: BitVisorのシリアル入出力について
Hideki EIRAKU
hdk @ igel.co.jp
2011年 10月 25日 (火) 12:16:25 JST
イーゲル 榮樂です。
From: Shougo Matsushita <shougo @ softlab.cs.tsukuba.ac.jp>
Subject: [BitVisor-devel:27] BitVisorのシリアル入出力について
Date: Fri, 21 Oct 2011 17:57:26 +0900
> 筑波大学 ソフトウェア研究室の松下正吾です。
> BitVisor側はdbgsh経由で実行したBitVisor付属のcore/builtin/bin_serialtest,
> PC側はgtktermで通信をさせて実験をしました。
> BitVisorのシリアル入出力オプション(TTY_SERIAL)はコンパイル時に有効化しています。
>
> BitVisorからのシリアル出力はちゃんと送れているのですが、BitVisorのシリアル入力がおかしいです。
> どういう挙動をするかというと、bin_serialtest内のc = msgsendint (in, 0))で10秒〜20秒ほど固まることがあります。
> inはシリアル入力ポートです。
> 固まるまではリアルタイムにシリアル入力から受けとった文字がdbgshに出力されます。
> 固まる頻度は、連続して5, 6文字くらい入力すると固まります。
> 固まった後しばらく待ってから、またgtktermで出力すると
> 「固まっている間に表示できていなかった文字+gtktermで入力した文字」が画面に表示されます。
> データが取り零されていることはないようです。
BitVisor のシリアルポート入出力待ちは、割り込みを使わずポーリングで行っ
ています。出力はいいのですが、入力は、データが届くまでの間、ゲスト OS
の動作を止めてしまうので、dbgsh から試すと、固まるように見えることがあ
るかも知れません。
> printf ("serial in test\n");
> while ((c = msgsendint (in, 0)) != '.')
> printf ("%c", c);
ここからたどると core/serial.c の serial_recv() 関数のところにたどり着
きます。serial_recv() 関数は、もともと panic 後のデバッグ用途のみを想定
していたため、ビジーループでデータが届くまで待ちます。dbgsh が動作して
いるのは VM とは違うスレッドではあるものの、BitVisor のスレッドはプリエ
ンプティブではないため、この処理にきたところでかたまります。
少々強引ですが、こんな修正でも回避可能です。
------------------------------------------------------------
diff --git a/core/serial.c b/core/serial.c
--- a/core/serial.c
+++ b/core/serial.c
@@ -79,6 +79,7 @@
#define INIT_MODEMCTL 0x3 /* RTS | DTR */
static bool initialized;
+static bool schedule_ok = false;
static void
serial_init (unsigned int port)
@@ -98,9 +99,13 @@ serial_send (unsigned int port, unsigned
u8 status;
asm_outb (port + PORT_DATA, data);
- do
+ goto x;
+ do {
+ if (schedule_ok)
+ schedule ();
+ x:
asm_inb (port + PORT_LINESTATUS, &status);
- while (!(status & LINESTATUS_TX_BIT));
+ } while (!(status & LINESTATUS_TX_BIT));
}
static unsigned char
@@ -108,9 +113,13 @@ serial_recv (unsigned int port)
{
u8 status, data;
- do
+ goto x;
+ do {
+ if (schedule_ok)
+ schedule ();
+ x:
asm_inb (port + PORT_LINESTATUS, &status);
- while (!(status & LINESTATUS_RX_BIT));
+ } while (!(status & LINESTATUS_RX_BIT));
asm_inb (port + PORT_DATA, &data);
return data;
}
@@ -182,4 +191,11 @@ serial_init_msg (void)
msgregister ("serialout", serialout_msghandler);
}
+static void
+serial_init_bsp (void)
+{
+ schedule_ok = true;
+}
+
INITFUNC ("msg0", serial_init_msg);
+INITFUNC ("bsp0", serial_init_bsp);
------------------------------------------------------------
これは、ビジーループの時に schedule() を呼び出してスレッドを回すように
するものです。単純に schedule() だけ入れると、起動時の文字出力で落ちて
しまいますので、準備ができるまでは schedule() を呼ばないような仕掛けも
いれてあります。
--
Hideki EIRAKU <hdk @ igel.co.jp>
BitVisor-devel メーリングリストの案内