Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
qemu
提交
e54b7f52
Q
qemu
项目概览
openeuler
/
qemu
通知
10
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
Q
qemu
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
e54b7f52
编写于
2月 01, 2011
作者:
A
Anthony Liguori
浏览文件
操作
浏览文件
下载
差异文件
Merge remote branch 'amit/for-anthony' into staging
上级
1cd20f8b
37f95bf3
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
139 addition
and
46 deletion
+139
-46
hw/virtio-console.c
hw/virtio-console.c
+17
-21
hw/virtio-serial-bus.c
hw/virtio-serial-bus.c
+101
-22
hw/virtio-serial.h
hw/virtio-serial.h
+21
-3
未找到文件。
hw/virtio-console.c
浏览文件 @
e54b7f52
...
@@ -20,11 +20,11 @@ typedef struct VirtConsole {
...
@@ -20,11 +20,11 @@ typedef struct VirtConsole {
/* Callback function that's called when the guest sends us data */
/* Callback function that's called when the guest sends us data */
static
void
flush_buf
(
VirtIOSerialPort
*
port
,
const
uint8_t
*
buf
,
size_t
len
)
static
ssize_t
flush_buf
(
VirtIOSerialPort
*
port
,
const
uint8_t
*
buf
,
size_t
len
)
{
{
VirtConsole
*
vcon
=
DO_UPCAST
(
VirtConsole
,
port
,
port
);
VirtConsole
*
vcon
=
DO_UPCAST
(
VirtConsole
,
port
,
port
);
qemu_chr_write
(
vcon
->
chr
,
buf
,
len
);
return
qemu_chr_write
(
vcon
->
chr
,
buf
,
len
);
}
}
/* Readiness of the guest to accept data on a port */
/* Readiness of the guest to accept data on a port */
...
@@ -48,34 +48,37 @@ static void chr_event(void *opaque, int event)
...
@@ -48,34 +48,37 @@ static void chr_event(void *opaque, int event)
VirtConsole
*
vcon
=
opaque
;
VirtConsole
*
vcon
=
opaque
;
switch
(
event
)
{
switch
(
event
)
{
case
CHR_EVENT_OPENED
:
{
case
CHR_EVENT_OPENED
:
virtio_serial_open
(
&
vcon
->
port
);
virtio_serial_open
(
&
vcon
->
port
);
break
;
break
;
}
case
CHR_EVENT_CLOSED
:
case
CHR_EVENT_CLOSED
:
virtio_serial_close
(
&
vcon
->
port
);
virtio_serial_close
(
&
vcon
->
port
);
break
;
break
;
}
}
}
}
/* Virtio Console Ports */
static
int
generic_port_init
(
VirtConsole
*
vcon
,
VirtIOSerialDevice
*
dev
)
static
int
virtconsole_initfn
(
VirtIOSerialDevice
*
dev
)
{
{
VirtIOSerialPort
*
port
=
DO_UPCAST
(
VirtIOSerialPort
,
dev
,
&
dev
->
qdev
);
vcon
->
port
.
info
=
dev
->
info
;
VirtConsole
*
vcon
=
DO_UPCAST
(
VirtConsole
,
port
,
port
);
port
->
info
=
dev
->
info
;
port
->
is_console
=
true
;
if
(
vcon
->
chr
)
{
if
(
vcon
->
chr
)
{
qemu_chr_add_handlers
(
vcon
->
chr
,
chr_can_read
,
chr_read
,
chr_event
,
qemu_chr_add_handlers
(
vcon
->
chr
,
chr_can_read
,
chr_read
,
chr_event
,
vcon
);
vcon
);
port
->
info
->
have_data
=
flush_buf
;
vcon
->
port
.
info
->
have_data
=
flush_buf
;
}
}
return
0
;
return
0
;
}
}
/* Virtio Console Ports */
static
int
virtconsole_initfn
(
VirtIOSerialDevice
*
dev
)
{
VirtIOSerialPort
*
port
=
DO_UPCAST
(
VirtIOSerialPort
,
dev
,
&
dev
->
qdev
);
VirtConsole
*
vcon
=
DO_UPCAST
(
VirtConsole
,
port
,
port
);
port
->
is_console
=
true
;
return
generic_port_init
(
vcon
,
dev
);
}
static
int
virtconsole_exitfn
(
VirtIOSerialDevice
*
dev
)
static
int
virtconsole_exitfn
(
VirtIOSerialDevice
*
dev
)
{
{
VirtIOSerialPort
*
port
=
DO_UPCAST
(
VirtIOSerialPort
,
dev
,
&
dev
->
qdev
);
VirtIOSerialPort
*
port
=
DO_UPCAST
(
VirtIOSerialPort
,
dev
,
&
dev
->
qdev
);
...
@@ -115,14 +118,7 @@ static int virtserialport_initfn(VirtIOSerialDevice *dev)
...
@@ -115,14 +118,7 @@ static int virtserialport_initfn(VirtIOSerialDevice *dev)
VirtIOSerialPort
*
port
=
DO_UPCAST
(
VirtIOSerialPort
,
dev
,
&
dev
->
qdev
);
VirtIOSerialPort
*
port
=
DO_UPCAST
(
VirtIOSerialPort
,
dev
,
&
dev
->
qdev
);
VirtConsole
*
vcon
=
DO_UPCAST
(
VirtConsole
,
port
,
port
);
VirtConsole
*
vcon
=
DO_UPCAST
(
VirtConsole
,
port
,
port
);
port
->
info
=
dev
->
info
;
return
generic_port_init
(
vcon
,
dev
);
if
(
vcon
->
chr
)
{
qemu_chr_add_handlers
(
vcon
->
chr
,
chr_can_read
,
chr_read
,
chr_event
,
vcon
);
port
->
info
->
have_data
=
flush_buf
;
}
return
0
;
}
}
static
VirtIOSerialPortInfo
virtserialport_info
=
{
static
VirtIOSerialPortInfo
virtserialport_info
=
{
...
...
hw/virtio-serial-bus.c
浏览文件 @
e54b7f52
...
@@ -113,39 +113,74 @@ static size_t write_to_port(VirtIOSerialPort *port,
...
@@ -113,39 +113,74 @@ static size_t write_to_port(VirtIOSerialPort *port,
return
offset
;
return
offset
;
}
}
static
void
do_flush_queued_data
(
VirtIOSerialPort
*
port
,
VirtQueue
*
vq
,
static
void
discard_vq_data
(
VirtQueue
*
vq
,
VirtIODevice
*
vdev
)
VirtIODevice
*
vdev
,
bool
discard
)
{
{
VirtQueueElement
elem
;
VirtQueueElement
elem
;
assert
(
port
||
discard
);
while
(
virtqueue_pop
(
vq
,
&
elem
))
{
virtqueue_push
(
vq
,
&
elem
,
0
);
}
virtio_notify
(
vdev
,
vq
);
}
static
void
do_flush_queued_data
(
VirtIOSerialPort
*
port
,
VirtQueue
*
vq
,
VirtIODevice
*
vdev
)
{
assert
(
port
);
assert
(
virtio_queue_ready
(
vq
));
assert
(
virtio_queue_ready
(
vq
));
while
((
discard
||
!
port
->
throttled
)
&&
virtqueue_pop
(
vq
,
&
elem
))
{
while
(
!
port
->
throttled
)
{
uint8_t
*
buf
;
unsigned
int
i
;
size_t
ret
,
buf_size
;
if
(
!
discard
)
{
/* Pop an elem only if we haven't left off a previous one mid-way */
buf_size
=
iov_size
(
elem
.
out_sg
,
elem
.
out_num
);
if
(
!
port
->
elem
.
out_num
)
{
buf
=
qemu_malloc
(
buf_size
);
if
(
!
virtqueue_pop
(
vq
,
&
port
->
elem
))
{
ret
=
iov_to_buf
(
elem
.
out_sg
,
elem
.
out_num
,
buf
,
0
,
buf_size
);
break
;
}
port
->
iov_idx
=
0
;
port
->
iov_offset
=
0
;
}
port
->
info
->
have_data
(
port
,
buf
,
ret
);
for
(
i
=
port
->
iov_idx
;
i
<
port
->
elem
.
out_num
;
i
++
)
{
qemu_free
(
buf
);
size_t
buf_size
;
ssize_t
ret
;
buf_size
=
port
->
elem
.
out_sg
[
i
].
iov_len
-
port
->
iov_offset
;
ret
=
port
->
info
->
have_data
(
port
,
port
->
elem
.
out_sg
[
i
].
iov_base
+
port
->
iov_offset
,
buf_size
);
if
(
ret
<
0
&&
ret
!=
-
EAGAIN
)
{
/* We don't handle any other type of errors here */
abort
();
}
if
(
ret
==
-
EAGAIN
||
(
ret
>=
0
&&
ret
<
buf_size
))
{
virtio_serial_throttle_port
(
port
,
true
);
port
->
iov_idx
=
i
;
if
(
ret
>
0
)
{
port
->
iov_offset
+=
ret
;
}
break
;
}
port
->
iov_offset
=
0
;
}
}
virtqueue_push
(
vq
,
&
elem
,
0
);
if
(
port
->
throttled
)
{
break
;
}
virtqueue_push
(
vq
,
&
port
->
elem
,
0
);
port
->
elem
.
out_num
=
0
;
}
}
virtio_notify
(
vdev
,
vq
);
virtio_notify
(
vdev
,
vq
);
}
}
static
void
flush_queued_data
(
VirtIOSerialPort
*
port
,
bool
discard
)
static
void
flush_queued_data
(
VirtIOSerialPort
*
port
)
{
{
assert
(
port
);
assert
(
port
);
if
(
!
virtio_queue_ready
(
port
->
ovq
))
{
if
(
!
virtio_queue_ready
(
port
->
ovq
))
{
return
;
return
;
}
}
do_flush_queued_data
(
port
,
port
->
ovq
,
&
port
->
vser
->
vdev
,
discard
);
do_flush_queued_data
(
port
,
port
->
ovq
,
&
port
->
vser
->
vdev
);
}
}
static
size_t
send_control_msg
(
VirtIOSerialPort
*
port
,
void
*
buf
,
size_t
len
)
static
size_t
send_control_msg
(
VirtIOSerialPort
*
port
,
void
*
buf
,
size_t
len
)
...
@@ -204,7 +239,7 @@ int virtio_serial_close(VirtIOSerialPort *port)
...
@@ -204,7 +239,7 @@ int virtio_serial_close(VirtIOSerialPort *port)
* consume, reset the throttling flag and discard the data.
* consume, reset the throttling flag and discard the data.
*/
*/
port
->
throttled
=
false
;
port
->
throttled
=
false
;
flush_queued_data
(
port
,
true
);
discard_vq_data
(
port
->
ovq
,
&
port
->
vser
->
vdev
);
send_control_event
(
port
,
VIRTIO_CONSOLE_PORT_OPEN
,
0
);
send_control_event
(
port
,
VIRTIO_CONSOLE_PORT_OPEN
,
0
);
...
@@ -258,7 +293,7 @@ void virtio_serial_throttle_port(VirtIOSerialPort *port, bool throttle)
...
@@ -258,7 +293,7 @@ void virtio_serial_throttle_port(VirtIOSerialPort *port, bool throttle)
return
;
return
;
}
}
flush_queued_data
(
port
,
false
);
flush_queued_data
(
port
);
}
}
/* Guest wants to notify us of some event */
/* Guest wants to notify us of some event */
...
@@ -414,11 +449,15 @@ static void handle_output(VirtIODevice *vdev, VirtQueue *vq)
...
@@ -414,11 +449,15 @@ static void handle_output(VirtIODevice *vdev, VirtQueue *vq)
discard
=
true
;
discard
=
true
;
}
}
if
(
!
discard
&&
port
->
throttled
)
{
if
(
discard
)
{
discard_vq_data
(
vq
,
vdev
);
return
;
}
if
(
port
->
throttled
)
{
return
;
return
;
}
}
do_flush_queued_data
(
port
,
vq
,
vdev
,
discard
);
do_flush_queued_data
(
port
,
vq
,
vdev
);
}
}
static
void
handle_input
(
VirtIODevice
*
vdev
,
VirtQueue
*
vq
)
static
void
handle_input
(
VirtIODevice
*
vdev
,
VirtQueue
*
vq
)
...
@@ -488,9 +527,24 @@ static void virtio_serial_save(QEMUFile *f, void *opaque)
...
@@ -488,9 +527,24 @@ static void virtio_serial_save(QEMUFile *f, void *opaque)
* Items in struct VirtIOSerialPort.
* Items in struct VirtIOSerialPort.
*/
*/
QTAILQ_FOREACH
(
port
,
&
s
->
ports
,
next
)
{
QTAILQ_FOREACH
(
port
,
&
s
->
ports
,
next
)
{
uint32_t
elem_popped
;
qemu_put_be32s
(
f
,
&
port
->
id
);
qemu_put_be32s
(
f
,
&
port
->
id
);
qemu_put_byte
(
f
,
port
->
guest_connected
);
qemu_put_byte
(
f
,
port
->
guest_connected
);
qemu_put_byte
(
f
,
port
->
host_connected
);
qemu_put_byte
(
f
,
port
->
host_connected
);
elem_popped
=
0
;
if
(
port
->
elem
.
out_num
)
{
elem_popped
=
1
;
}
qemu_put_be32s
(
f
,
&
elem_popped
);
if
(
elem_popped
)
{
qemu_put_be32s
(
f
,
&
port
->
iov_idx
);
qemu_put_be64s
(
f
,
&
port
->
iov_offset
);
qemu_put_buffer
(
f
,
(
unsigned
char
*
)
&
port
->
elem
,
sizeof
(
port
->
elem
));
}
}
}
}
}
...
@@ -501,7 +555,7 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
...
@@ -501,7 +555,7 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
uint32_t
max_nr_ports
,
nr_active_ports
,
ports_map
;
uint32_t
max_nr_ports
,
nr_active_ports
,
ports_map
;
unsigned
int
i
;
unsigned
int
i
;
if
(
version_id
>
2
)
{
if
(
version_id
>
3
)
{
return
-
EINVAL
;
return
-
EINVAL
;
}
}
...
@@ -554,6 +608,29 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
...
@@ -554,6 +608,29 @@ static int virtio_serial_load(QEMUFile *f, void *opaque, int version_id)
send_control_event
(
port
,
VIRTIO_CONSOLE_PORT_OPEN
,
send_control_event
(
port
,
VIRTIO_CONSOLE_PORT_OPEN
,
port
->
host_connected
);
port
->
host_connected
);
}
}
if
(
version_id
>
2
)
{
uint32_t
elem_popped
;
qemu_get_be32s
(
f
,
&
elem_popped
);
if
(
elem_popped
)
{
qemu_get_be32s
(
f
,
&
port
->
iov_idx
);
qemu_get_be64s
(
f
,
&
port
->
iov_offset
);
qemu_get_buffer
(
f
,
(
unsigned
char
*
)
&
port
->
elem
,
sizeof
(
port
->
elem
));
virtqueue_map_sg
(
port
->
elem
.
in_sg
,
port
->
elem
.
in_addr
,
port
->
elem
.
in_num
,
1
);
virtqueue_map_sg
(
port
->
elem
.
out_sg
,
port
->
elem
.
out_addr
,
port
->
elem
.
out_num
,
1
);
/*
* Port was throttled on source machine. Let's
* unthrottle it here so data starts flowing again.
*/
virtio_serial_throttle_port
(
port
,
false
);
}
}
}
}
return
0
;
return
0
;
}
}
...
@@ -634,7 +711,7 @@ static void remove_port(VirtIOSerial *vser, uint32_t port_id)
...
@@ -634,7 +711,7 @@ static void remove_port(VirtIOSerial *vser, uint32_t port_id)
port
=
find_port_by_id
(
vser
,
port_id
);
port
=
find_port_by_id
(
vser
,
port_id
);
/* Flush out any unconsumed buffers first */
/* Flush out any unconsumed buffers first */
flush_queued_data
(
port
,
true
);
discard_vq_data
(
port
->
ovq
,
&
port
->
vser
->
vdev
);
send_control_event
(
port
,
VIRTIO_CONSOLE_PORT_REMOVE
,
1
);
send_control_event
(
port
,
VIRTIO_CONSOLE_PORT_REMOVE
,
1
);
}
}
...
@@ -695,6 +772,8 @@ static int virtser_port_qdev_init(DeviceState *qdev, DeviceInfo *base)
...
@@ -695,6 +772,8 @@ static int virtser_port_qdev_init(DeviceState *qdev, DeviceInfo *base)
port
->
guest_connected
=
true
;
port
->
guest_connected
=
true
;
}
}
port
->
elem
.
out_num
=
0
;
QTAILQ_INSERT_TAIL
(
&
port
->
vser
->
ports
,
port
,
next
);
QTAILQ_INSERT_TAIL
(
&
port
->
vser
->
ports
,
port
,
next
);
port
->
ivq
=
port
->
vser
->
ivqs
[
port
->
id
];
port
->
ivq
=
port
->
vser
->
ivqs
[
port
->
id
];
port
->
ovq
=
port
->
vser
->
ovqs
[
port
->
id
];
port
->
ovq
=
port
->
vser
->
ovqs
[
port
->
id
];
...
@@ -806,7 +885,7 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports)
...
@@ -806,7 +885,7 @@ VirtIODevice *virtio_serial_init(DeviceState *dev, uint32_t max_nr_ports)
* Register for the savevm section with the virtio-console name
* Register for the savevm section with the virtio-console name
* to preserve backward compat
* to preserve backward compat
*/
*/
register_savevm
(
dev
,
"virtio-console"
,
-
1
,
2
,
virtio_serial_save
,
register_savevm
(
dev
,
"virtio-console"
,
-
1
,
3
,
virtio_serial_save
,
virtio_serial_load
,
vser
);
virtio_serial_load
,
vser
);
return
vdev
;
return
vdev
;
...
...
hw/virtio-serial.h
浏览文件 @
e54b7f52
...
@@ -102,6 +102,23 @@ struct VirtIOSerialPort {
...
@@ -102,6 +102,23 @@ struct VirtIOSerialPort {
*/
*/
uint32_t
id
;
uint32_t
id
;
/*
* This is the elem that we pop from the virtqueue. A slow
* backend that consumes guest data (e.g. the file backend for
* qemu chardevs) can cause the guest to block till all the output
* is flushed. This isn't desired, so we keep a note of the last
* element popped and continue consuming it once the backend
* becomes writable again.
*/
VirtQueueElement
elem
;
/*
* The index and the offset into the iov buffer that was popped in
* elem above.
*/
uint32_t
iov_idx
;
uint64_t
iov_offset
;
/* Identify if this is a port that binds with hvc in the guest */
/* Identify if this is a port that binds with hvc in the guest */
uint8_t
is_console
;
uint8_t
is_console
;
...
@@ -137,10 +154,11 @@ struct VirtIOSerialPortInfo {
...
@@ -137,10 +154,11 @@ struct VirtIOSerialPortInfo {
/*
/*
* Guest wrote some data to the port. This data is handed over to
* Guest wrote some data to the port. This data is handed over to
* the app via this callback. The app
is supposed to consume all
* the app via this callback. The app
can return a size less than
*
the data that is presented to i
t.
*
'len'. In this case, throttling will be enabled for this por
t.
*/
*/
void
(
*
have_data
)(
VirtIOSerialPort
*
port
,
const
uint8_t
*
buf
,
size_t
len
);
ssize_t
(
*
have_data
)(
VirtIOSerialPort
*
port
,
const
uint8_t
*
buf
,
size_t
len
);
};
};
/* Interface to the virtio-serial bus */
/* Interface to the virtio-serial bus */
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录