mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-07-27 12:23:53 -06:00
Merge remote-tracking branch 'luiz/queue/qmp' into staging
# By Lei Li (3) and others # Via Luiz Capitulino * luiz/queue/qmp: QAPI: Introduce memchar-read QMP command QAPI: Introduce memchar-write QMP command qemu-char: Add new char backend CirMemCharDriver docs: document virtio-balloon stats balloon: re-enable balloon stats balloon: drop old stats code & API block: Monitor command commit neglects to report some errors
This commit is contained in:
commit
6cebf7afac
10 changed files with 689 additions and 89 deletions
203
qemu-char.c
203
qemu-char.c
|
@ -98,6 +98,7 @@
|
|||
#include "ui/qemu-spice.h"
|
||||
|
||||
#define READ_BUF_LEN 4096
|
||||
#define CBUFF_SIZE 65536
|
||||
|
||||
/***********************************************************/
|
||||
/* character device */
|
||||
|
@ -2643,6 +2644,199 @@ size_t qemu_chr_mem_osize(const CharDriverState *chr)
|
|||
return d->outbuf_size;
|
||||
}
|
||||
|
||||
/*********************************************************/
|
||||
/*CircularMemory chardev*/
|
||||
|
||||
typedef struct {
|
||||
size_t size;
|
||||
size_t prod;
|
||||
size_t cons;
|
||||
uint8_t *cbuf;
|
||||
} CirMemCharDriver;
|
||||
|
||||
static bool cirmem_chr_is_empty(const CharDriverState *chr)
|
||||
{
|
||||
const CirMemCharDriver *d = chr->opaque;
|
||||
|
||||
return d->cons == d->prod;
|
||||
}
|
||||
|
||||
static size_t qemu_chr_cirmem_count(const CharDriverState *chr)
|
||||
{
|
||||
const CirMemCharDriver *d = chr->opaque;
|
||||
|
||||
return (d->prod - d->cons);
|
||||
}
|
||||
|
||||
static int cirmem_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
|
||||
{
|
||||
CirMemCharDriver *d = chr->opaque;
|
||||
int i;
|
||||
|
||||
if (!buf || (len < 0)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < len; i++ ) {
|
||||
/* Avoid writing the IAC information to the queue. */
|
||||
if ((unsigned char)buf[i] == IAC) {
|
||||
continue;
|
||||
}
|
||||
|
||||
d->cbuf[d->prod++ % d->size] = buf[i];
|
||||
if ((d->prod - d->cons) > d->size) {
|
||||
d->cons = d->prod - d->size;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cirmem_chr_read(CharDriverState *chr, uint8_t *buf, int len)
|
||||
{
|
||||
CirMemCharDriver *d = chr->opaque;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len && !cirmem_chr_is_empty(chr); i++) {
|
||||
buf[i] = d->cbuf[d->cons++ % d->size];
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static void cirmem_chr_close(struct CharDriverState *chr)
|
||||
{
|
||||
CirMemCharDriver *d = chr->opaque;
|
||||
|
||||
g_free(d->cbuf);
|
||||
g_free(d);
|
||||
chr->opaque = NULL;
|
||||
}
|
||||
|
||||
static CharDriverState *qemu_chr_open_cirmemchr(QemuOpts *opts)
|
||||
{
|
||||
CharDriverState *chr;
|
||||
CirMemCharDriver *d;
|
||||
|
||||
chr = g_malloc0(sizeof(CharDriverState));
|
||||
d = g_malloc(sizeof(*d));
|
||||
|
||||
d->size = qemu_opt_get_number(opts, "maxcapacity", 0);
|
||||
if (d->size == 0) {
|
||||
d->size = CBUFF_SIZE;
|
||||
}
|
||||
|
||||
/* The size must be power of 2 */
|
||||
if (d->size & (d->size - 1)) {
|
||||
fprintf(stderr, "chardev: size of memory device must be power of 2\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
d->prod = 0;
|
||||
d->cons = 0;
|
||||
d->cbuf = g_malloc0(d->size);
|
||||
|
||||
chr->opaque = d;
|
||||
chr->chr_write = cirmem_chr_write;
|
||||
chr->chr_close = cirmem_chr_close;
|
||||
|
||||
return chr;
|
||||
|
||||
fail:
|
||||
g_free(d);
|
||||
g_free(chr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool qemu_is_chr(const CharDriverState *chr, const char *filename)
|
||||
{
|
||||
return strcmp(chr->filename, filename);
|
||||
}
|
||||
|
||||
void qmp_memchar_write(const char *device, int64_t size,
|
||||
const char *data, bool has_format,
|
||||
enum DataFormat format,
|
||||
Error **errp)
|
||||
{
|
||||
CharDriverState *chr;
|
||||
guchar *write_data;
|
||||
int ret;
|
||||
gsize write_count;
|
||||
|
||||
chr = qemu_chr_find(device);
|
||||
if (!chr) {
|
||||
error_set(errp, QERR_DEVICE_NOT_FOUND, device);
|
||||
return;
|
||||
}
|
||||
|
||||
if (qemu_is_chr(chr, "memory")) {
|
||||
error_setg(errp,"%s is not memory char device", device);
|
||||
return;
|
||||
}
|
||||
|
||||
write_count = (gsize)size;
|
||||
|
||||
if (has_format && (format == DATA_FORMAT_BASE64)) {
|
||||
write_data = g_base64_decode(data, &write_count);
|
||||
} else {
|
||||
write_data = (uint8_t *)data;
|
||||
}
|
||||
|
||||
ret = cirmem_chr_write(chr, write_data, write_count);
|
||||
|
||||
if (ret < 0) {
|
||||
error_setg(errp, "Failed to write to device %s", device);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
MemCharRead *qmp_memchar_read(const char *device, int64_t size,
|
||||
bool has_format, enum DataFormat format,
|
||||
Error **errp)
|
||||
{
|
||||
CharDriverState *chr;
|
||||
guchar *read_data;
|
||||
MemCharRead *meminfo;
|
||||
size_t count;
|
||||
|
||||
chr = qemu_chr_find(device);
|
||||
if (!chr) {
|
||||
error_set(errp, QERR_DEVICE_NOT_FOUND, device);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (qemu_is_chr(chr, "memory")) {
|
||||
error_setg(errp,"%s is not memory char device", device);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (size <= 0) {
|
||||
error_setg(errp, "size must be greater than zero");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
meminfo = g_malloc0(sizeof(MemCharRead));
|
||||
|
||||
count = qemu_chr_cirmem_count(chr);
|
||||
if (count == 0) {
|
||||
meminfo->data = g_strdup("");
|
||||
return meminfo;
|
||||
}
|
||||
|
||||
size = size > count ? count : size;
|
||||
read_data = g_malloc0(size + 1);
|
||||
|
||||
meminfo->count = cirmem_chr_read(chr, read_data, size);
|
||||
|
||||
if (has_format && (format == DATA_FORMAT_BASE64)) {
|
||||
meminfo->data = g_base64_encode(read_data, (size_t)meminfo->count);
|
||||
} else {
|
||||
meminfo->data = (char *)read_data;
|
||||
}
|
||||
|
||||
return meminfo;
|
||||
}
|
||||
|
||||
QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
|
||||
{
|
||||
char host[65], port[33], width[8], height[8];
|
||||
|
@ -2697,6 +2891,11 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
|
|||
qemu_opt_set(opts, "path", filename);
|
||||
return opts;
|
||||
}
|
||||
if (strstart(filename, "memory", &p)) {
|
||||
qemu_opt_set(opts, "backend", "memory");
|
||||
qemu_opt_set(opts, "maxcapacity", p);
|
||||
return opts;
|
||||
}
|
||||
if (strstart(filename, "file:", &p)) {
|
||||
qemu_opt_set(opts, "backend", "file");
|
||||
qemu_opt_set(opts, "path", p);
|
||||
|
@ -2796,6 +2995,7 @@ static const struct {
|
|||
{ .name = "udp", .open = qemu_chr_open_udp },
|
||||
{ .name = "msmouse", .open = qemu_chr_open_msmouse },
|
||||
{ .name = "vc", .open = text_console_init },
|
||||
{ .name = "memory", .open = qemu_chr_open_cirmemchr },
|
||||
#ifdef _WIN32
|
||||
{ .name = "file", .open = qemu_chr_open_win_file_out },
|
||||
{ .name = "pipe", .open = qemu_chr_open_win_pipe },
|
||||
|
@ -3055,6 +3255,9 @@ QemuOptsList qemu_chardev_opts = {
|
|||
},{
|
||||
.name = "debug",
|
||||
.type = QEMU_OPT_NUMBER,
|
||||
},{
|
||||
.name = "maxcapacity",
|
||||
.type = QEMU_OPT_NUMBER,
|
||||
},
|
||||
{ /* end of list */ }
|
||||
},
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue