* SCSI max_transfer support for scsi-generic (Eric)
* x86 SMI broadcast (Laszlo) * Character device QOMification (Marc-André) * Record/replay improvements (Pavel) * iscsi fixes (Peter L.) * "info mtree -f" command (Peter Xu) * TSC clock rate reporting (Phil) * DEVICE_CATEGORY_CPU (Thomas) * Memory sign-extension fix (Ladi) -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQEcBAABAgAGBQJYi36jAAoJEL/70l94x66DNFMIAIMy/WjYQ1dtc0xjxJ3EG+cL IfmyVA2B7ZLrrN3hFvba8nKsE5/q443QmSjlIjfG7bvlqOszpPi8fnLHe2U0rGwU ctP0cw5jXHqiZYVtVDHlCvqPUh/DFydBvkmNUAgpLNVkzWEw2ZBcryKzoNJVIRDz hnwX0V/yqleqCEMUp2Ia4BLDg1lO9s6gIUjvDYmlZim5ehOuFvSWizzV0/aGfjTl 0QGCvehwkAYX056z0PwegijCoCPe9HyB9wfmy7eEVXJnv6NVP0qCmAZek7pF3tt5 zpKV74jFBjx/rbpl5yc2XOIM6yNbabkalENIzqIfPKYPsNuozOaHl0t82Q3J6OU= =/3Gk -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging * SCSI max_transfer support for scsi-generic (Eric) * x86 SMI broadcast (Laszlo) * Character device QOMification (Marc-André) * Record/replay improvements (Pavel) * iscsi fixes (Peter L.) * "info mtree -f" command (Peter Xu) * TSC clock rate reporting (Phil) * DEVICE_CATEGORY_CPU (Thomas) * Memory sign-extension fix (Ladi) # gpg: Signature made Fri 27 Jan 2017 17:08:51 GMT # gpg: using RSA key 0xBFFBD25F78C7AE83 # gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>" # gpg: aka "Paolo Bonzini <pbonzini@redhat.com>" # Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4 E2F7 7E15 100C CD36 69B1 # Subkey fingerprint: F133 3857 4B66 2389 866C 7682 BFFB D25F 78C7 AE83 * remotes/bonzini/tags/for-upstream: (41 commits) memory: don't sign-extend 32-bit writes chardev: qom-ify vc: use a common prefix for chr callbacks baum: use a common prefix for chr callbacks gtk: overwrite the console.c char driver char: use error_report() spice-char: improve error reporting char: rename TCPChardev and NetChardev char: rename CharDriverState Chardev bt: use qemu_chr_alloc() char: allocate CharDriverState as a single object char: use a feature bit for replay char: introduce generic qemu_chr_get_kind() char: fold single-user functions in caller char: move callbacks in CharDriver char: use a static array for backends char: use a const CharDriver doc: fix spelling char: add qemu_chr_fe_add_watch() Returns description qemu-options: stdio is available on win32 ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
a0def59428
@ -1642,6 +1642,7 @@ M: Peter Lieven <pl@kamp.de>
|
||||
L: qemu-block@nongnu.org
|
||||
S: Supported
|
||||
F: block/iscsi.c
|
||||
F: block/iscsi-opts.c
|
||||
|
||||
NFS
|
||||
M: Jeff Cody <jcody@redhat.com>
|
||||
|
106
backends/baum.c
106
backends/baum.c
@ -85,7 +85,7 @@
|
||||
#define BUF_SIZE 256
|
||||
|
||||
typedef struct {
|
||||
CharDriverState *chr;
|
||||
Chardev parent;
|
||||
|
||||
brlapi_handle_t *brlapi;
|
||||
int brlapi_fd;
|
||||
@ -98,7 +98,10 @@ typedef struct {
|
||||
uint8_t out_buf_used, out_buf_ptr;
|
||||
|
||||
QEMUTimer *cellCount_timer;
|
||||
} BaumDriverState;
|
||||
} BaumChardev;
|
||||
|
||||
#define TYPE_CHARDEV_BRAILLE "chardev-braille"
|
||||
#define BAUM_CHARDEV(obj) OBJECT_CHECK(BaumChardev, (obj), TYPE_CHARDEV_BRAILLE)
|
||||
|
||||
/* Let's assume NABCC by default */
|
||||
enum way {
|
||||
@ -223,7 +226,7 @@ static const uint8_t nabcc_translation[2][256] = {
|
||||
};
|
||||
|
||||
/* The guest OS has started discussing with us, finish initializing BrlAPI */
|
||||
static int baum_deferred_init(BaumDriverState *baum)
|
||||
static int baum_deferred_init(BaumChardev *baum)
|
||||
{
|
||||
int tty = BRLAPI_TTY_DEFAULT;
|
||||
QemuConsole *con;
|
||||
@ -253,9 +256,9 @@ static int baum_deferred_init(BaumDriverState *baum)
|
||||
}
|
||||
|
||||
/* The serial port can receive more of our data */
|
||||
static void baum_accept_input(struct CharDriverState *chr)
|
||||
static void baum_chr_accept_input(struct Chardev *chr)
|
||||
{
|
||||
BaumDriverState *baum = chr->opaque;
|
||||
BaumChardev *baum = BAUM_CHARDEV(chr);
|
||||
int room, first;
|
||||
|
||||
if (!baum->out_buf_used)
|
||||
@ -279,24 +282,25 @@ static void baum_accept_input(struct CharDriverState *chr)
|
||||
}
|
||||
|
||||
/* We want to send a packet */
|
||||
static void baum_write_packet(BaumDriverState *baum, const uint8_t *buf, int len)
|
||||
static void baum_write_packet(BaumChardev *baum, const uint8_t *buf, int len)
|
||||
{
|
||||
Chardev *chr = CHARDEV(baum);
|
||||
uint8_t io_buf[1 + 2 * len], *cur = io_buf;
|
||||
int room;
|
||||
*cur++ = ESC;
|
||||
while (len--)
|
||||
if ((*cur++ = *buf++) == ESC)
|
||||
*cur++ = ESC;
|
||||
room = qemu_chr_be_can_write(baum->chr);
|
||||
room = qemu_chr_be_can_write(chr);
|
||||
len = cur - io_buf;
|
||||
if (len <= room) {
|
||||
/* Fits */
|
||||
qemu_chr_be_write(baum->chr, io_buf, len);
|
||||
qemu_chr_be_write(chr, io_buf, len);
|
||||
} else {
|
||||
int first;
|
||||
uint8_t out;
|
||||
/* Can't fit all, send what can be, and store the rest. */
|
||||
qemu_chr_be_write(baum->chr, io_buf, room);
|
||||
qemu_chr_be_write(chr, io_buf, room);
|
||||
len -= room;
|
||||
cur = io_buf + room;
|
||||
if (len > BUF_SIZE - baum->out_buf_used) {
|
||||
@ -321,14 +325,14 @@ static void baum_write_packet(BaumDriverState *baum, const uint8_t *buf, int len
|
||||
/* Called when the other end seems to have a wrong idea of our display size */
|
||||
static void baum_cellCount_timer_cb(void *opaque)
|
||||
{
|
||||
BaumDriverState *baum = opaque;
|
||||
BaumChardev *baum = BAUM_CHARDEV(opaque);
|
||||
uint8_t cell_count[] = { BAUM_RSP_CellCount, baum->x * baum->y };
|
||||
DPRINTF("Timeout waiting for DisplayData, sending cell count\n");
|
||||
baum_write_packet(baum, cell_count, sizeof(cell_count));
|
||||
}
|
||||
|
||||
/* Try to interpret a whole incoming packet */
|
||||
static int baum_eat_packet(BaumDriverState *baum, const uint8_t *buf, int len)
|
||||
static int baum_eat_packet(BaumChardev *baum, const uint8_t *buf, int len)
|
||||
{
|
||||
const uint8_t *cur = buf;
|
||||
uint8_t req = 0;
|
||||
@ -469,9 +473,9 @@ static int baum_eat_packet(BaumDriverState *baum, const uint8_t *buf, int len)
|
||||
}
|
||||
|
||||
/* The other end is writing some data. Store it and try to interpret */
|
||||
static int baum_write(CharDriverState *chr, const uint8_t *buf, int len)
|
||||
static int baum_chr_write(Chardev *chr, const uint8_t *buf, int len)
|
||||
{
|
||||
BaumDriverState *baum = chr->opaque;
|
||||
BaumChardev *baum = BAUM_CHARDEV(chr);
|
||||
int tocopy, cur, eaten, orig_len = len;
|
||||
|
||||
if (!len)
|
||||
@ -510,14 +514,16 @@ static int baum_write(CharDriverState *chr, const uint8_t *buf, int len)
|
||||
}
|
||||
|
||||
/* Send the key code to the other end */
|
||||
static void baum_send_key(BaumDriverState *baum, uint8_t type, uint8_t value) {
|
||||
static void baum_send_key(BaumChardev *baum, uint8_t type, uint8_t value)
|
||||
{
|
||||
uint8_t packet[] = { type, value };
|
||||
DPRINTF("writing key %x %x\n", type, value);
|
||||
baum_write_packet(baum, packet, sizeof(packet));
|
||||
}
|
||||
|
||||
static void baum_send_key2(BaumDriverState *baum, uint8_t type, uint8_t value,
|
||||
uint8_t value2) {
|
||||
static void baum_send_key2(BaumChardev *baum, uint8_t type, uint8_t value,
|
||||
uint8_t value2)
|
||||
{
|
||||
uint8_t packet[] = { type, value, value2 };
|
||||
DPRINTF("writing key %x %x\n", type, value);
|
||||
baum_write_packet(baum, packet, sizeof(packet));
|
||||
@ -526,7 +532,7 @@ static void baum_send_key2(BaumDriverState *baum, uint8_t type, uint8_t value,
|
||||
/* We got some data on the BrlAPI socket */
|
||||
static void baum_chr_read(void *opaque)
|
||||
{
|
||||
BaumDriverState *baum = opaque;
|
||||
BaumChardev *baum = BAUM_CHARDEV(opaque);
|
||||
brlapi_keyCode_t code;
|
||||
int ret;
|
||||
if (!baum->brlapi)
|
||||
@ -610,41 +616,25 @@ static void baum_chr_read(void *opaque)
|
||||
}
|
||||
}
|
||||
|
||||
static void baum_free(struct CharDriverState *chr)
|
||||
static void baum_chr_free(Chardev *chr)
|
||||
{
|
||||
BaumDriverState *baum = chr->opaque;
|
||||
BaumChardev *baum = BAUM_CHARDEV(chr);
|
||||
|
||||
timer_free(baum->cellCount_timer);
|
||||
if (baum->brlapi) {
|
||||
brlapi__closeConnection(baum->brlapi);
|
||||
g_free(baum->brlapi);
|
||||
}
|
||||
g_free(baum);
|
||||
}
|
||||
|
||||
static CharDriverState *chr_baum_init(const char *id,
|
||||
ChardevBackend *backend,
|
||||
ChardevReturn *ret,
|
||||
bool *be_opened,
|
||||
Error **errp)
|
||||
static void baum_chr_open(Chardev *chr,
|
||||
ChardevBackend *backend,
|
||||
bool *be_opened,
|
||||
Error **errp)
|
||||
{
|
||||
ChardevCommon *common = backend->u.braille.data;
|
||||
BaumDriverState *baum;
|
||||
CharDriverState *chr;
|
||||
BaumChardev *baum = BAUM_CHARDEV(chr);
|
||||
brlapi_handle_t *handle;
|
||||
|
||||
chr = qemu_chr_alloc(common, errp);
|
||||
if (!chr) {
|
||||
return NULL;
|
||||
}
|
||||
baum = g_malloc0(sizeof(BaumDriverState));
|
||||
baum->chr = chr;
|
||||
|
||||
chr->opaque = baum;
|
||||
chr->chr_write = baum_write;
|
||||
chr->chr_accept_input = baum_accept_input;
|
||||
chr->chr_free = baum_free;
|
||||
|
||||
handle = g_malloc0(brlapi_getHandleSize());
|
||||
baum->brlapi = handle;
|
||||
|
||||
@ -652,27 +642,41 @@ static CharDriverState *chr_baum_init(const char *id,
|
||||
if (baum->brlapi_fd == -1) {
|
||||
error_setg(errp, "brlapi__openConnection: %s",
|
||||
brlapi_strerror(brlapi_error_location()));
|
||||
goto fail_handle;
|
||||
g_free(handle);
|
||||
return;
|
||||
}
|
||||
baum->deferred_init = 0;
|
||||
|
||||
baum->cellCount_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, baum_cellCount_timer_cb, baum);
|
||||
|
||||
qemu_set_fd_handler(baum->brlapi_fd, baum_chr_read, NULL, baum);
|
||||
|
||||
return chr;
|
||||
|
||||
fail_handle:
|
||||
g_free(handle);
|
||||
g_free(chr);
|
||||
g_free(baum);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void char_braille_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
ChardevClass *cc = CHARDEV_CLASS(oc);
|
||||
|
||||
cc->open = baum_chr_open;
|
||||
cc->chr_write = baum_chr_write;
|
||||
cc->chr_accept_input = baum_chr_accept_input;
|
||||
cc->chr_free = baum_chr_free;
|
||||
}
|
||||
|
||||
static const TypeInfo char_braille_type_info = {
|
||||
.name = TYPE_CHARDEV_BRAILLE,
|
||||
.parent = TYPE_CHARDEV,
|
||||
.instance_size = sizeof(BaumChardev),
|
||||
.class_init = char_braille_class_init,
|
||||
};
|
||||
|
||||
static void register_types(void)
|
||||
{
|
||||
register_char_driver("braille", CHARDEV_BACKEND_KIND_BRAILLE, NULL,
|
||||
chr_baum_init);
|
||||
static const CharDriver driver = {
|
||||
.kind = CHARDEV_BACKEND_KIND_BRAILLE,
|
||||
};
|
||||
|
||||
register_char_driver(&driver);
|
||||
type_register_static(&char_braille_type_info);
|
||||
}
|
||||
|
||||
type_init(register_types);
|
||||
|
@ -31,18 +31,23 @@
|
||||
#define MSMOUSE_HI2(n) (((n) & 0xc0) >> 6)
|
||||
|
||||
typedef struct {
|
||||
CharDriverState *chr;
|
||||
Chardev parent;
|
||||
|
||||
QemuInputHandlerState *hs;
|
||||
int axis[INPUT_AXIS__MAX];
|
||||
bool btns[INPUT_BUTTON__MAX];
|
||||
bool btnc[INPUT_BUTTON__MAX];
|
||||
uint8_t outbuf[32];
|
||||
int outlen;
|
||||
} MouseState;
|
||||
} MouseChardev;
|
||||
|
||||
static void msmouse_chr_accept_input(CharDriverState *chr)
|
||||
#define TYPE_CHARDEV_MSMOUSE "chardev-msmouse"
|
||||
#define MOUSE_CHARDEV(obj) \
|
||||
OBJECT_CHECK(MouseChardev, (obj), TYPE_CHARDEV_MSMOUSE)
|
||||
|
||||
static void msmouse_chr_accept_input(Chardev *chr)
|
||||
{
|
||||
MouseState *mouse = chr->opaque;
|
||||
MouseChardev *mouse = MOUSE_CHARDEV(chr);
|
||||
int len;
|
||||
|
||||
len = qemu_chr_be_can_write(chr);
|
||||
@ -60,7 +65,7 @@ static void msmouse_chr_accept_input(CharDriverState *chr)
|
||||
}
|
||||
}
|
||||
|
||||
static void msmouse_queue_event(MouseState *mouse)
|
||||
static void msmouse_queue_event(MouseChardev *mouse)
|
||||
{
|
||||
unsigned char bytes[4] = { 0x40, 0x00, 0x00, 0x00 };
|
||||
int dx, dy, count = 3;
|
||||
@ -97,7 +102,7 @@ static void msmouse_queue_event(MouseState *mouse)
|
||||
static void msmouse_input_event(DeviceState *dev, QemuConsole *src,
|
||||
InputEvent *evt)
|
||||
{
|
||||
MouseState *mouse = (MouseState *)dev;
|
||||
MouseChardev *mouse = MOUSE_CHARDEV(dev);
|
||||
InputMoveEvent *move;
|
||||
InputBtnEvent *btn;
|
||||
|
||||
@ -121,24 +126,24 @@ static void msmouse_input_event(DeviceState *dev, QemuConsole *src,
|
||||
|
||||
static void msmouse_input_sync(DeviceState *dev)
|
||||
{
|
||||
MouseState *mouse = (MouseState *)dev;
|
||||
MouseChardev *mouse = MOUSE_CHARDEV(dev);
|
||||
Chardev *chr = CHARDEV(dev);
|
||||
|
||||
msmouse_queue_event(mouse);
|
||||
msmouse_chr_accept_input(mouse->chr);
|
||||
msmouse_chr_accept_input(chr);
|
||||
}
|
||||
|
||||
static int msmouse_chr_write (struct CharDriverState *s, const uint8_t *buf, int len)
|
||||
static int msmouse_chr_write(struct Chardev *s, const uint8_t *buf, int len)
|
||||
{
|
||||
/* Ignore writes to mouse port */
|
||||
return len;
|
||||
}
|
||||
|
||||
static void msmouse_chr_free(struct CharDriverState *chr)
|
||||
static void msmouse_chr_free(struct Chardev *chr)
|
||||
{
|
||||
MouseState *mouse = chr->opaque;
|
||||
MouseChardev *mouse = MOUSE_CHARDEV(chr);
|
||||
|
||||
qemu_input_handler_unregister(mouse->hs);
|
||||
g_free(mouse);
|
||||
}
|
||||
|
||||
static QemuInputHandler msmouse_handler = {
|
||||
@ -148,39 +153,43 @@ static QemuInputHandler msmouse_handler = {
|
||||
.sync = msmouse_input_sync,
|
||||
};
|
||||
|
||||
static CharDriverState *qemu_chr_open_msmouse(const char *id,
|
||||
ChardevBackend *backend,
|
||||
ChardevReturn *ret,
|
||||
bool *be_opened,
|
||||
Error **errp)
|
||||
static void msmouse_chr_open(Chardev *chr,
|
||||
ChardevBackend *backend,
|
||||
bool *be_opened,
|
||||
Error **errp)
|
||||
{
|
||||
ChardevCommon *common = backend->u.msmouse.data;
|
||||
MouseState *mouse;
|
||||
CharDriverState *chr;
|
||||
MouseChardev *mouse = MOUSE_CHARDEV(chr);
|
||||
|
||||
chr = qemu_chr_alloc(common, errp);
|
||||
if (!chr) {
|
||||
return NULL;
|
||||
}
|
||||
chr->chr_write = msmouse_chr_write;
|
||||
chr->chr_free = msmouse_chr_free;
|
||||
chr->chr_accept_input = msmouse_chr_accept_input;
|
||||
*be_opened = false;
|
||||
|
||||
mouse = g_new0(MouseState, 1);
|
||||
mouse->hs = qemu_input_handler_register((DeviceState *)mouse,
|
||||
&msmouse_handler);
|
||||
|
||||
mouse->chr = chr;
|
||||
chr->opaque = mouse;
|
||||
|
||||
return chr;
|
||||
}
|
||||
|
||||
static void char_msmouse_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
ChardevClass *cc = CHARDEV_CLASS(oc);
|
||||
|
||||
cc->open = msmouse_chr_open;
|
||||
cc->chr_write = msmouse_chr_write;
|
||||
cc->chr_accept_input = msmouse_chr_accept_input;
|
||||
cc->chr_free = msmouse_chr_free;
|
||||
}
|
||||
|
||||
static const TypeInfo char_msmouse_type_info = {
|
||||
.name = TYPE_CHARDEV_MSMOUSE,
|
||||
.parent = TYPE_CHARDEV,
|
||||
.instance_size = sizeof(MouseChardev),
|
||||
.class_init = char_msmouse_class_init,
|
||||
};
|
||||
|
||||
static void register_types(void)
|
||||
{
|
||||
register_char_driver("msmouse", CHARDEV_BACKEND_KIND_MSMOUSE, NULL,
|
||||
qemu_chr_open_msmouse);
|
||||
static const CharDriver driver = {
|
||||
.kind = CHARDEV_BACKEND_KIND_MSMOUSE,
|
||||
};
|
||||
|
||||
register_char_driver(&driver);
|
||||
type_register_static(&char_msmouse_type_info);
|
||||
}
|
||||
|
||||
type_init(register_types);
|
||||
|
@ -86,7 +86,7 @@ static void rng_egd_chr_read(void *opaque, const uint8_t *buf, int size)
|
||||
static void rng_egd_opened(RngBackend *b, Error **errp)
|
||||
{
|
||||
RngEgd *s = RNG_EGD(b);
|
||||
CharDriverState *chr;
|
||||
Chardev *chr;
|
||||
|
||||
if (s->chr_name == NULL) {
|
||||
error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
|
||||
@ -125,7 +125,7 @@ static void rng_egd_set_chardev(Object *obj, const char *value, Error **errp)
|
||||
static char *rng_egd_get_chardev(Object *obj, Error **errp)
|
||||
{
|
||||
RngEgd *s = RNG_EGD(obj);
|
||||
CharDriverState *chr = qemu_chr_fe_get_driver(&s->chr);
|
||||
Chardev *chr = qemu_chr_fe_get_driver(&s->chr);
|
||||
|
||||
if (chr && chr->label) {
|
||||
return g_strdup(chr->label);
|
||||
|
@ -30,13 +30,18 @@
|
||||
#define BUF_SIZE 32
|
||||
|
||||
typedef struct {
|
||||
CharDriverState *chr;
|
||||
Chardev parent;
|
||||
|
||||
uint8_t in_buf[32];
|
||||
int in_buf_used;
|
||||
} TestdevCharState;
|
||||
} TestdevChardev;
|
||||
|
||||
#define TYPE_CHARDEV_TESTDEV "chardev-testdev"
|
||||
#define TESTDEV_CHARDEV(obj) \
|
||||
OBJECT_CHECK(TestdevChardev, (obj), TYPE_CHARDEV_TESTDEV)
|
||||
|
||||
/* Try to interpret a whole incoming packet */
|
||||
static int testdev_eat_packet(TestdevCharState *testdev)
|
||||
static int testdev_eat_packet(TestdevChardev *testdev)
|
||||
{
|
||||
const uint8_t *cur = testdev->in_buf;
|
||||
int len = testdev->in_buf_used;
|
||||
@ -77,9 +82,9 @@ static int testdev_eat_packet(TestdevCharState *testdev)
|
||||
}
|
||||
|
||||
/* The other end is writing some data. Store it and try to interpret */
|
||||
static int testdev_write(CharDriverState *chr, const uint8_t *buf, int len)
|
||||
static int testdev_chr_write(Chardev *chr, const uint8_t *buf, int len)
|
||||
{
|
||||
TestdevCharState *testdev = chr->opaque;
|
||||
TestdevChardev *testdev = TESTDEV_CHARDEV(chr);
|
||||
int tocopy, eaten, orig_len = len;
|
||||
|
||||
while (len) {
|
||||
@ -102,36 +107,28 @@ static int testdev_write(CharDriverState *chr, const uint8_t *buf, int len)
|
||||
return orig_len;
|
||||
}
|
||||
|
||||
static void testdev_free(struct CharDriverState *chr)
|
||||
static void char_testdev_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
TestdevCharState *testdev = chr->opaque;
|
||||
ChardevClass *cc = CHARDEV_CLASS(oc);
|
||||
|
||||
g_free(testdev);
|
||||
cc->chr_write = testdev_chr_write;
|
||||
}
|
||||
|
||||
static CharDriverState *chr_testdev_init(const char *id,
|
||||
ChardevBackend *backend,
|
||||
ChardevReturn *ret,
|
||||
bool *be_opened,
|
||||
Error **errp)
|
||||
{
|
||||
TestdevCharState *testdev;
|
||||
CharDriverState *chr;
|
||||
|
||||
testdev = g_new0(TestdevCharState, 1);
|
||||
testdev->chr = chr = g_new0(CharDriverState, 1);
|
||||
|
||||
chr->opaque = testdev;
|
||||
chr->chr_write = testdev_write;
|
||||
chr->chr_free = testdev_free;
|
||||
|
||||
return chr;
|
||||
}
|
||||
static const TypeInfo char_testdev_type_info = {
|
||||
.name = TYPE_CHARDEV_TESTDEV,
|
||||
.parent = TYPE_CHARDEV,
|
||||
.instance_size = sizeof(TestdevChardev),
|
||||
.class_init = char_testdev_class_init,
|
||||
};
|
||||
|
||||
static void register_types(void)
|
||||
{
|
||||
register_char_driver("testdev", CHARDEV_BACKEND_KIND_TESTDEV, NULL,
|
||||
chr_testdev_init);
|
||||
static const CharDriver driver = {
|
||||
.kind = CHARDEV_BACKEND_KIND_TESTDEV,
|
||||
};
|
||||
|
||||
register_char_driver(&driver);
|
||||
type_register_static(&char_testdev_type_info);
|
||||
}
|
||||
|
||||
type_init(register_types);
|
||||
|
@ -14,6 +14,7 @@ block-obj-y += throttle-groups.o
|
||||
|
||||
block-obj-y += nbd.o nbd-client.o sheepdog.o
|
||||
block-obj-$(CONFIG_LIBISCSI) += iscsi.o
|
||||
block-obj-$(if $(CONFIG_LIBISCSI),y,n) += iscsi-opts.o
|
||||
block-obj-$(CONFIG_LIBNFS) += nfs.o
|
||||
block-obj-$(CONFIG_CURL) += curl.o
|
||||
block-obj-$(CONFIG_RBD) += rbd.o
|
||||
|
@ -651,12 +651,15 @@ static void raw_reopen_abort(BDRVReopenState *state)
|
||||
state->opaque = NULL;
|
||||
}
|
||||
|
||||
static int hdev_get_max_transfer_length(int fd)
|
||||
static int hdev_get_max_transfer_length(BlockDriverState *bs, int fd)
|
||||
{
|
||||
#ifdef BLKSECTGET
|
||||
int max_sectors = 0;
|
||||
if (ioctl(fd, BLKSECTGET, &max_sectors) == 0) {
|
||||
return max_sectors;
|
||||
int max_bytes = 0;
|
||||
short max_sectors = 0;
|
||||
if (bs->sg && ioctl(fd, BLKSECTGET, &max_bytes) == 0) {
|
||||
return max_bytes;
|
||||
} else if (!bs->sg && ioctl(fd, BLKSECTGET, &max_sectors) == 0) {
|
||||
return max_sectors << BDRV_SECTOR_BITS;
|
||||
} else {
|
||||
return -errno;
|
||||
}
|
||||
@ -671,10 +674,10 @@ static void raw_refresh_limits(BlockDriverState *bs, Error **errp)
|
||||
struct stat st;
|
||||
|
||||
if (!fstat(s->fd, &st)) {
|
||||
if (S_ISBLK(st.st_mode)) {
|
||||
int ret = hdev_get_max_transfer_length(s->fd);
|
||||
if (ret > 0 && ret <= BDRV_REQUEST_MAX_SECTORS) {
|
||||
bs->bl.max_transfer = pow2floor(ret << BDRV_SECTOR_BITS);
|
||||
if (S_ISBLK(st.st_mode) || S_ISCHR(st.st_mode)) {
|
||||
int ret = hdev_get_max_transfer_length(bs, s->fd);
|
||||
if (ret > 0 && ret <= BDRV_REQUEST_MAX_BYTES) {
|
||||
bs->bl.max_transfer = pow2floor(ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
69
block/iscsi-opts.c
Normal file
69
block/iscsi-opts.c
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* QEMU Block driver for iSCSI images (static options)
|
||||
*
|
||||
* Copyright (c) 2017 Peter Lieven <pl@kamp.de>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/config-file.h"
|
||||
|
||||
static QemuOptsList qemu_iscsi_opts = {
|
||||
.name = "iscsi",
|
||||
.head = QTAILQ_HEAD_INITIALIZER(qemu_iscsi_opts.head),
|
||||
.desc = {
|
||||
{
|
||||
.name = "user",
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "username for CHAP authentication to target",
|
||||
},{
|
||||
.name = "password",
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "password for CHAP authentication to target",
|
||||
},{
|
||||
.name = "password-secret",
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "ID of the secret providing password for CHAP "
|
||||
"authentication to target",
|
||||
},{
|
||||
.name = "header-digest",
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "HeaderDigest setting. "
|
||||
"{CRC32C|CRC32C-NONE|NONE-CRC32C|NONE}",
|
||||
},{
|
||||
.name = "initiator-name",
|
||||
.type = QEMU_OPT_STRING,
|
||||
.help = "Initiator iqn name to use when connecting",
|
||||
},{
|
||||
.name = "timeout",
|
||||
.type = QEMU_OPT_NUMBER,
|
||||
.help = "Request timeout in seconds (default 0 = no timeout)",
|
||||
},
|
||||
{ /* end of list */ }
|
||||
},
|
||||
};
|
||||
|
||||
static void iscsi_block_opts_init(void)
|
||||
{
|
||||
qemu_add_opts(&qemu_iscsi_opts);
|
||||
}
|
||||
|
||||
block_init(iscsi_block_opts_init);
|
@ -499,14 +499,18 @@ iscsi_allocmap_update(IscsiLun *iscsilun, int64_t sector_num,
|
||||
if (allocated) {
|
||||
bitmap_set(iscsilun->allocmap, cl_num_expanded, nb_cls_expanded);
|
||||
} else {
|
||||
bitmap_clear(iscsilun->allocmap, cl_num_shrunk, nb_cls_shrunk);
|
||||
if (nb_cls_shrunk > 0) {
|
||||
bitmap_clear(iscsilun->allocmap, cl_num_shrunk, nb_cls_shrunk);
|
||||
}
|
||||
}
|
||||
|
||||
if (iscsilun->allocmap_valid == NULL) {
|
||||
return;
|
||||
}
|
||||
if (valid) {
|
||||
bitmap_set(iscsilun->allocmap_valid, cl_num_shrunk, nb_cls_shrunk);
|
||||
if (nb_cls_shrunk > 0) {
|
||||
bitmap_set(iscsilun->allocmap_valid, cl_num_shrunk, nb_cls_shrunk);
|
||||
}
|
||||
} else {
|
||||
bitmap_clear(iscsilun->allocmap_valid, cl_num_expanded,
|
||||
nb_cls_expanded);
|
||||
|
@ -508,8 +508,8 @@ static inline void cpu_handle_interrupt(CPUState *cpu,
|
||||
True when it is, and we should restart on a new TB,
|
||||
and via longjmp via cpu_loop_exit. */
|
||||
else {
|
||||
replay_interrupt();
|
||||
if (cc->cpu_exec_interrupt(cpu, interrupt_request)) {
|
||||
replay_interrupt();
|
||||
*last_tb = NULL;
|
||||
}
|
||||
/* The target hook may have updated the 'cpu->interrupt_request';
|
||||
|
@ -196,6 +196,22 @@ is recorded to the log. In replay phase the queue is matched with
|
||||
events read from the log. Therefore block devices requests are processed
|
||||
deterministically.
|
||||
|
||||
Snapshotting
|
||||
------------
|
||||
|
||||
New VM snapshots may be created in replay mode. They can be used later
|
||||
to recover the desired VM state. All VM states created in replay mode
|
||||
are associated with the moment of time in the replay scenario.
|
||||
After recovering the VM state replay will start from that position.
|
||||
|
||||
Default starting snapshot name may be specified with icount field
|
||||
rrsnapshot as follows:
|
||||
-icount shift=7,rr=record,rrfile=replay.bin,rrsnapshot=snapshot_name
|
||||
|
||||
This snapshot is created at start of recording and restored at start
|
||||
of replaying. It also can be loaded while replaying to roll back
|
||||
the execution.
|
||||
|
||||
Network devices
|
||||
---------------
|
||||
|
||||
|
2
exec.c
2
exec.c
@ -2630,7 +2630,7 @@ static MemTxResult address_space_write_continue(AddressSpace *as, hwaddr addr,
|
||||
break;
|
||||
case 4:
|
||||
/* 32 bit write access */
|
||||
val = ldl_p(buf);
|
||||
val = (uint32_t)ldl_p(buf);
|
||||
result |= memory_region_dispatch_write(mr, addr1, val, 4,
|
||||
attrs);
|
||||
break;
|
||||
|
45
gdbstub.c
45
gdbstub.c
@ -305,7 +305,7 @@ typedef struct GDBState {
|
||||
int running_state;
|
||||
#else
|
||||
CharBackend chr;
|
||||
CharDriverState *mon_chr;
|
||||
Chardev *mon_chr;
|
||||
#endif
|
||||
char syscall_buf[256];
|
||||
gdb_syscall_complete_cb current_syscall_cb;
|
||||
@ -1473,7 +1473,7 @@ void gdb_exit(CPUArchState *env, int code)
|
||||
GDBState *s;
|
||||
char buf[4];
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
CharDriverState *chr;
|
||||
Chardev *chr;
|
||||
#endif
|
||||
|
||||
s = gdbserver_state;
|
||||
@ -1698,7 +1698,7 @@ static void gdb_monitor_output(GDBState *s, const char *msg, int len)
|
||||
put_packet(s, buf);
|
||||
}
|
||||
|
||||
static int gdb_monitor_write(CharDriverState *chr, const uint8_t *buf, int len)
|
||||
static int gdb_monitor_write(Chardev *chr, const uint8_t *buf, int len)
|
||||
{
|
||||
const char *p = (const char *)buf;
|
||||
int max_sz;
|
||||
@ -1725,13 +1725,35 @@ static void gdb_sigterm_handler(int signal)
|
||||
}
|
||||
#endif
|
||||
|
||||
static void gdb_monitor_open(Chardev *chr, ChardevBackend *backend,
|
||||
bool *be_opened, Error **errp)
|
||||
{
|
||||
*be_opened = false;
|
||||
}
|
||||
|
||||
static void char_gdb_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
ChardevClass *cc = CHARDEV_CLASS(oc);
|
||||
|
||||
cc->internal = true;
|
||||
cc->open = gdb_monitor_open;
|
||||
cc->chr_write = gdb_monitor_write;
|
||||
}
|
||||
|
||||
#define TYPE_CHARDEV_GDB "chardev-gdb"
|
||||
|
||||
static const TypeInfo char_gdb_type_info = {
|
||||
.name = TYPE_CHARDEV_GDB,
|
||||
.parent = TYPE_CHARDEV,
|
||||
.class_init = char_gdb_class_init,
|
||||
};
|
||||
|
||||
int gdbserver_start(const char *device)
|
||||
{
|
||||
GDBState *s;
|
||||
char gdbstub_device_name[128];
|
||||
CharDriverState *chr = NULL;
|
||||
CharDriverState *mon_chr;
|
||||
ChardevCommon common = { 0 };
|
||||
Chardev *chr = NULL;
|
||||
Chardev *mon_chr;
|
||||
|
||||
if (!first_cpu) {
|
||||
error_report("gdbstub: meaningless to attach gdb to a "
|
||||
@ -1770,8 +1792,8 @@ int gdbserver_start(const char *device)
|
||||
qemu_add_vm_change_state_handler(gdb_vm_state_change, NULL);
|
||||
|
||||
/* Initialize a monitor terminal for gdb */
|
||||
mon_chr = qemu_chr_alloc(&common, &error_abort);
|
||||
mon_chr->chr_write = gdb_monitor_write;
|
||||
mon_chr = qemu_chardev_new(NULL, TYPE_CHARDEV_GDB,
|
||||
NULL, &error_abort);
|
||||
monitor_init(mon_chr, 0);
|
||||
} else {
|
||||
if (qemu_chr_fe_get_driver(&s->chr)) {
|
||||
@ -1794,4 +1816,11 @@ int gdbserver_start(const char *device)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void register_types(void)
|
||||
{
|
||||
type_register_static(&char_gdb_type_info);
|
||||
}
|
||||
|
||||
type_init(register_types);
|
||||
#endif
|
||||
|
@ -249,9 +249,9 @@ ETEXI
|
||||
|
||||
{
|
||||
.name = "mtree",
|
||||
.args_type = "",
|
||||
.params = "",
|
||||
.help = "show memory tree",
|
||||
.args_type = "flatview:-f",
|
||||
.params = "[-f]",
|
||||
.help = "show memory tree (-f: dump flat view for address spaces)",
|
||||
.cmd = hmp_info_mtree,
|
||||
},
|
||||
|
||||
|
@ -118,7 +118,7 @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp)
|
||||
};
|
||||
|
||||
if (i < MAX_SERIAL_PORTS) {
|
||||
CharDriverState *chr;
|
||||
Chardev *chr;
|
||||
|
||||
chr = serial_hds[i];
|
||||
|
||||
|
@ -107,7 +107,7 @@ static void fsl_imx31_realize(DeviceState *dev, Error **errp)
|
||||
};
|
||||
|
||||
if (i < MAX_SERIAL_PORTS) {
|
||||
CharDriverState *chr;
|
||||
Chardev *chr;
|
||||
|
||||
chr = serial_hds[i];
|
||||
|
||||
|
@ -187,7 +187,7 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
|
||||
};
|
||||
|
||||
if (i < MAX_SERIAL_PORTS) {
|
||||
CharDriverState *chr;
|
||||
Chardev *chr;
|
||||
|
||||
chr = serial_hds[i];
|
||||
|
||||
|
@ -786,7 +786,7 @@ static void n8x0_cbus_setup(struct n800_s *s)
|
||||
|
||||
static void n8x0_uart_setup(struct n800_s *s)
|
||||
{
|
||||
CharDriverState *radio = uart_hci_init();
|
||||
Chardev *radio = uart_hci_init();
|
||||
|
||||
qdev_connect_gpio_out(s->mpu->gpio, N8X0_BT_RESET_GPIO,
|
||||
csrhci_pins_get(radio)[csrhci_pin_reset]);
|
||||
|
@ -792,7 +792,7 @@ static const MemoryRegionOps omap_sti_fifo_ops = {
|
||||
static struct omap_sti_s *omap_sti_init(struct omap_target_agent_s *ta,
|
||||
MemoryRegion *sysmem,
|
||||
hwaddr channel_base, qemu_irq irq, omap_clk clk,
|
||||
CharDriverState *chr)
|
||||
Chardev *chr)
|
||||
{
|
||||
struct omap_sti_s *s = g_new0(struct omap_sti_s, 1);
|
||||
|
||||
|
@ -2024,7 +2024,7 @@ static PXA2xxFIrState *pxa2xx_fir_init(MemoryRegion *sysmem,
|
||||
hwaddr base,
|
||||
qemu_irq irq, qemu_irq rx_dma,
|
||||
qemu_irq tx_dma,
|
||||
CharDriverState *chr)
|
||||
Chardev *chr)
|
||||
{
|
||||
DeviceState *dev;
|
||||
SysBusDevice *sbd;
|
||||
|
@ -613,7 +613,7 @@ static void create_gic(VirtMachineState *vms, qemu_irq *pic)
|
||||
}
|
||||
|
||||
static void create_uart(const VirtMachineState *vms, qemu_irq *pic, int uart,
|
||||
MemoryRegion *mem, CharDriverState *chr)
|
||||
MemoryRegion *mem, Chardev *chr)
|
||||
{
|
||||
char *nodename;
|
||||
hwaddr base = vms->memmap[uart].base;
|
||||
|
@ -26,13 +26,14 @@
|
||||
#include "hw/irq.h"
|
||||
#include "sysemu/bt.h"
|
||||
#include "hw/bt.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
struct csrhci_s {
|
||||
Chardev parent;
|
||||
int enable;
|
||||
qemu_irq *pins;
|
||||
int pin_state;
|
||||
int modem_state;
|
||||
CharDriverState chr;
|
||||
#define FIFO_LEN 4096
|
||||
int out_start;
|
||||
int out_len;
|
||||
@ -54,6 +55,9 @@ struct csrhci_s {
|
||||
struct HCIInfo *hci;
|
||||
};
|
||||
|
||||
#define TYPE_CHARDEV_HCI "chardev-hci"
|
||||
#define HCI_CHARDEV(obj) OBJECT_CHECK(struct csrhci_s, (obj), TYPE_CHARDEV_HCI)
|
||||
|
||||
/* H4+ packet types */
|
||||
enum {
|
||||
H4_CMD_PKT = 1,
|
||||
@ -78,7 +82,8 @@ enum {
|
||||
|
||||
static inline void csrhci_fifo_wake(struct csrhci_s *s)
|
||||
{
|
||||
CharBackend *be = s->chr.be;
|
||||
Chardev *chr = (Chardev *)s;
|
||||
CharBackend *be = chr->be;
|
||||
|
||||
if (!s->enable || !s->out_len)
|
||||
return;
|
||||
@ -311,10 +316,10 @@ static void csrhci_ready_for_next_inpkt(struct csrhci_s *s)
|
||||
s->in_hdr = INT_MAX;
|
||||
}
|
||||
|
||||
static int csrhci_write(struct CharDriverState *chr,
|
||||
static int csrhci_write(struct Chardev *chr,
|
||||
const uint8_t *buf, int len)
|
||||
{
|
||||
struct csrhci_s *s = (struct csrhci_s *) chr->opaque;
|
||||
struct csrhci_s *s = (struct csrhci_s *)chr;
|
||||
int total = 0;
|
||||
|
||||
if (!s->enable)
|
||||
@ -384,10 +389,10 @@ static void csrhci_out_hci_packet_acl(void *opaque,
|
||||
csrhci_fifo_wake(s);
|
||||
}
|
||||
|
||||
static int csrhci_ioctl(struct CharDriverState *chr, int cmd, void *arg)
|
||||
static int csrhci_ioctl(struct Chardev *chr, int cmd, void *arg)
|
||||
{
|
||||
QEMUSerialSetParams *ssp;
|
||||
struct csrhci_s *s = (struct csrhci_s *) chr->opaque;
|
||||
struct csrhci_s *s = (struct csrhci_s *) chr;
|
||||
int prev_state = s->modem_state;
|
||||
|
||||
switch (cmd) {
|
||||
@ -453,21 +458,19 @@ static void csrhci_pins(void *opaque, int line, int level)
|
||||
}
|
||||
}
|
||||
|
||||
qemu_irq *csrhci_pins_get(CharDriverState *chr)
|
||||
qemu_irq *csrhci_pins_get(Chardev *chr)
|
||||
{
|
||||
struct csrhci_s *s = (struct csrhci_s *) chr->opaque;
|
||||
struct csrhci_s *s = (struct csrhci_s *) chr;
|
||||
|
||||
return s->pins;
|
||||
}
|
||||
|
||||
CharDriverState *uart_hci_init(void)
|
||||
static void csrhci_open(Chardev *chr,
|
||||
ChardevBackend *backend,
|
||||
bool *be_opened,
|
||||
Error **errp)
|
||||
{
|
||||
struct csrhci_s *s = (struct csrhci_s *)
|
||||
g_malloc0(sizeof(struct csrhci_s));
|
||||
|
||||
s->chr.opaque = s;
|
||||
s->chr.chr_write = csrhci_write;
|
||||
s->chr.chr_ioctl = csrhci_ioctl;
|
||||
struct csrhci_s *s = HCI_CHARDEV(chr);
|
||||
|
||||
s->hci = qemu_next_hci();
|
||||
s->hci->opaque = s;
|
||||
@ -477,6 +480,35 @@ CharDriverState *uart_hci_init(void)
|
||||
s->out_tm = timer_new_ns(QEMU_CLOCK_VIRTUAL, csrhci_out_tick, s);
|
||||
s->pins = qemu_allocate_irqs(csrhci_pins, s, __csrhci_pins);
|
||||
csrhci_reset(s);
|
||||
|
||||
return &s->chr;
|
||||
*be_opened = false;
|
||||
}
|
||||
|
||||
static void char_hci_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
ChardevClass *cc = CHARDEV_CLASS(oc);
|
||||
|
||||
cc->internal = true;
|
||||
cc->open = csrhci_open;
|
||||
cc->chr_write = csrhci_write;
|
||||
cc->chr_ioctl = csrhci_ioctl;
|
||||
}
|
||||
|
||||
static const TypeInfo char_hci_type_info = {
|
||||
.name = TYPE_CHARDEV_HCI,
|
||||
.parent = TYPE_CHARDEV,
|
||||
.instance_size = sizeof(struct csrhci_s),
|
||||
.class_init = char_hci_class_init,
|
||||
};
|
||||
|
||||
Chardev *uart_hci_init(void)
|
||||
{
|
||||
return qemu_chardev_new(NULL, TYPE_CHARDEV_HCI,
|
||||
NULL, &error_abort);
|
||||
}
|
||||
|
||||
static void register_types(void)
|
||||
{
|
||||
type_register_static(&char_hci_type_info);
|
||||
}
|
||||
|
||||
type_init(register_types);
|
||||
|
@ -689,7 +689,7 @@ static const VMStateDescription vmstate_escc = {
|
||||
};
|
||||
|
||||
MemoryRegion *escc_init(hwaddr base, qemu_irq irqA, qemu_irq irqB,
|
||||
CharDriverState *chrA, CharDriverState *chrB,
|
||||
Chardev *chrA, Chardev *chrB,
|
||||
int clock, int it_shift)
|
||||
{
|
||||
DeviceState *dev;
|
||||
|
@ -582,7 +582,7 @@ static const VMStateDescription vmstate_exynos4210_uart = {
|
||||
DeviceState *exynos4210_uart_create(hwaddr addr,
|
||||
int fifo_size,
|
||||
int channel,
|
||||
CharDriverState *chr,
|
||||
Chardev *chr,
|
||||
qemu_irq irq)
|
||||
{
|
||||
DeviceState *dev;
|
||||
|
@ -170,7 +170,7 @@ static void imx_serial_write(void *opaque, hwaddr offset,
|
||||
uint64_t value, unsigned size)
|
||||
{
|
||||
IMXSerialState *s = (IMXSerialState *)opaque;
|
||||
CharDriverState *chr = qemu_chr_fe_get_driver(&s->chr);
|
||||
Chardev *chr = qemu_chr_fe_get_driver(&s->chr);
|
||||
unsigned char ch;
|
||||
|
||||
DPRINTF("write(offset=0x%" HWADDR_PRIx ", value = 0x%x) to %s\n",
|
||||
|
@ -275,7 +275,7 @@ static void mcf_uart_receive(void *opaque, const uint8_t *buf, int size)
|
||||
mcf_uart_push_byte(s, buf[0]);
|
||||
}
|
||||
|
||||
void *mcf_uart_init(qemu_irq irq, CharDriverState *chr)
|
||||
void *mcf_uart_init(qemu_irq irq, Chardev *chr)
|
||||
{
|
||||
mcf_uart_state *s;
|
||||
|
||||
@ -300,7 +300,7 @@ static const MemoryRegionOps mcf_uart_ops = {
|
||||
void mcf_uart_mm_init(MemoryRegion *sysmem,
|
||||
hwaddr base,
|
||||
qemu_irq irq,
|
||||
CharDriverState *chr)
|
||||
Chardev *chr)
|
||||
{
|
||||
mcf_uart_state *s;
|
||||
|
||||
|
@ -54,7 +54,7 @@ void omap_uart_reset(struct omap_uart_s *s)
|
||||
struct omap_uart_s *omap_uart_init(hwaddr base,
|
||||
qemu_irq irq, omap_clk fclk, omap_clk iclk,
|
||||
qemu_irq txdma, qemu_irq rxdma,
|
||||
const char *label, CharDriverState *chr)
|
||||
const char *label, Chardev *chr)
|
||||
{
|
||||
struct omap_uart_s *s = g_new0(struct omap_uart_s, 1);
|
||||
|
||||
@ -163,7 +163,7 @@ struct omap_uart_s *omap2_uart_init(MemoryRegion *sysmem,
|
||||
struct omap_target_agent_s *ta,
|
||||
qemu_irq irq, omap_clk fclk, omap_clk iclk,
|
||||
qemu_irq txdma, qemu_irq rxdma,
|
||||
const char *label, CharDriverState *chr)
|
||||
const char *label, Chardev *chr)
|
||||
{
|
||||
hwaddr base = omap_l4_attach(ta, 0, NULL);
|
||||
struct omap_uart_s *s = omap_uart_init(base, irq,
|
||||
@ -178,7 +178,7 @@ struct omap_uart_s *omap2_uart_init(MemoryRegion *sysmem,
|
||||
return s;
|
||||
}
|
||||
|
||||
void omap_uart_attach(struct omap_uart_s *s, CharDriverState *chr)
|
||||
void omap_uart_attach(struct omap_uart_s *s, Chardev *chr)
|
||||
{
|
||||
/* TODO: Should reuse or destroy current s->serial */
|
||||
s->serial = serial_mm_init(get_system_memory(), s->base, 2, s->irq,
|
||||
|
@ -603,7 +603,7 @@ static const MemoryRegionOps parallel_mm_ops = {
|
||||
/* If fd is zero, it means that the parallel device uses the console */
|
||||
bool parallel_mm_init(MemoryRegion *address_space,
|
||||
hwaddr base, int it_shift, qemu_irq irq,
|
||||
CharDriverState *chr)
|
||||
Chardev *chr)
|
||||
{
|
||||
ParallelState *s;
|
||||
|
||||
|
@ -121,7 +121,7 @@ static void serial_register_types(void)
|
||||
|
||||
type_init(serial_register_types)
|
||||
|
||||
static void serial_isa_init(ISABus *bus, int index, CharDriverState *chr)
|
||||
static void serial_isa_init(ISABus *bus, int index, Chardev *chr)
|
||||
{
|
||||
DeviceState *dev;
|
||||
ISADevice *isadev;
|
||||
|
@ -937,7 +937,7 @@ const MemoryRegionOps serial_io_ops = {
|
||||
};
|
||||
|
||||
SerialState *serial_init(int base, qemu_irq irq, int baudbase,
|
||||
CharDriverState *chr, MemoryRegion *system_io)
|
||||
Chardev *chr, MemoryRegion *system_io)
|
||||
{
|
||||
SerialState *s;
|
||||
|
||||
@ -993,7 +993,7 @@ static const MemoryRegionOps serial_mm_ops[3] = {
|
||||
SerialState *serial_mm_init(MemoryRegion *address_space,
|
||||
hwaddr base, int it_shift,
|
||||
qemu_irq irq, int baudbase,
|
||||
CharDriverState *chr, enum device_endian end)
|
||||
Chardev *chr, enum device_endian end)
|
||||
{
|
||||
SerialState *s;
|
||||
|
||||
|
@ -356,7 +356,7 @@ static const MemoryRegionOps sh_serial_ops = {
|
||||
|
||||
void sh_serial_init(MemoryRegion *sysmem,
|
||||
hwaddr base, int feat,
|
||||
uint32_t freq, CharDriverState *chr,
|
||||
uint32_t freq, Chardev *chr,
|
||||
qemu_irq eri_source,
|
||||
qemu_irq rxi_source,
|
||||
qemu_irq txi_source,
|
||||
|
@ -141,7 +141,7 @@ static target_ulong h_get_term_char(PowerPCCPU *cpu, sPAPRMachineState *spapr,
|
||||
return H_SUCCESS;
|
||||
}
|
||||
|
||||
void spapr_vty_create(VIOsPAPRBus *bus, CharDriverState *chardev)
|
||||
void spapr_vty_create(VIOsPAPRBus *bus, Chardev *chardev)
|
||||
{
|
||||
DeviceState *dev;
|
||||
|
||||
|
@ -168,7 +168,7 @@ static void virtconsole_realize(DeviceState *dev, Error **errp)
|
||||
VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(dev);
|
||||
VirtConsole *vcon = VIRTIO_CONSOLE(dev);
|
||||
VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(dev);
|
||||
CharDriverState *chr = qemu_chr_fe_get_driver(&vcon->chr);
|
||||
Chardev *chr = qemu_chr_fe_get_driver(&vcon->chr);
|
||||
|
||||
if (port->id == 0 && !k->is_console) {
|
||||
error_setg(errp, "Port number 0 on virtio-serial devices reserved "
|
||||
|
@ -179,7 +179,7 @@ static void set_chr(Object *obj, Visitor *v, const char *name, void *opaque,
|
||||
Error *local_err = NULL;
|
||||
Property *prop = opaque;
|
||||
CharBackend *be = qdev_get_prop_ptr(dev, prop);
|
||||
CharDriverState *s;
|
||||
Chardev *s;
|
||||
char *str;
|
||||
|
||||
if (dev->realized) {
|
||||
@ -411,7 +411,7 @@ void qdev_prop_set_drive(DeviceState *dev, const char *name,
|
||||
}
|
||||
|
||||
void qdev_prop_set_chr(DeviceState *dev, const char *name,
|
||||
CharDriverState *value)
|
||||
Chardev *value)
|
||||
{
|
||||
assert(!value || value->label);
|
||||
object_property_set_str(OBJECT(dev),
|
||||
|
@ -72,10 +72,18 @@ static void cpu_core_instance_init(Object *obj)
|
||||
core->nr_threads = smp_threads;
|
||||
}
|
||||
|
||||
static void cpu_core_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
|
||||
set_bit(DEVICE_CATEGORY_CPU, dc->categories);
|
||||
}
|
||||
|
||||
static const TypeInfo cpu_core_type_info = {
|
||||
.name = TYPE_CPU_CORE,
|
||||
.parent = TYPE_DEVICE,
|
||||
.abstract = true,
|
||||
.class_init = cpu_core_class_init,
|
||||
.instance_size = sizeof(CPUCore),
|
||||
.instance_init = cpu_core_instance_init,
|
||||
};
|
||||
|
@ -85,7 +85,7 @@ struct MilkymistTMU2State {
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
MemoryRegion regs_region;
|
||||
CharDriverState *chr;
|
||||
Chardev *chr;
|
||||
qemu_irq irq;
|
||||
|
||||
uint32_t regs[R_MAX];
|
||||
|
@ -1392,7 +1392,7 @@ static const GraphicHwOps sm501_ops = {
|
||||
};
|
||||
|
||||
void sm501_init(MemoryRegion *address_space_mem, uint32_t base,
|
||||
uint32_t local_mem_bytes, qemu_irq irq, CharDriverState *chr)
|
||||
uint32_t local_mem_bytes, qemu_irq irq, Chardev *chr)
|
||||
{
|
||||
SM501State * s;
|
||||
DeviceState *dev;
|
||||
|
@ -413,6 +413,12 @@ static void patch_instruction(VAPICROMState *s, X86CPU *cpu, target_ulong ip)
|
||||
if (!kvm_enabled()) {
|
||||
cpu_get_tb_cpu_state(env, ¤t_pc, ¤t_cs_base,
|
||||
¤t_flags);
|
||||
/* Account this instruction, because we will exit the tb.
|
||||
This is the first instruction in the block. Therefore
|
||||
there is no need in restoring CPU state. */
|
||||
if (use_icount) {
|
||||
--cs->icount_decr.u16.low;
|
||||
}
|
||||
}
|
||||
|
||||
pause_all_vcpus();
|
||||
|
@ -385,6 +385,25 @@ static bool apic_common_sipi_needed(void *opaque)
|
||||
return s->wait_for_sipi != 0;
|
||||
}
|
||||
|
||||
static bool apic_irq_delivered_needed(void *opaque)
|
||||
{
|
||||
APICCommonState *s = APIC_COMMON(opaque);
|
||||
return s->cpu == X86_CPU(first_cpu) && apic_irq_delivered != 0;
|
||||
}
|
||||
|
||||
static void apic_irq_delivered_pre_save(void *opaque)
|
||||
{
|
||||
APICCommonState *s = APIC_COMMON(opaque);
|
||||
s->apic_irq_delivered = apic_irq_delivered;
|
||||
}
|
||||
|
||||
static int apic_irq_delivered_post_load(void *opaque, int version_id)
|
||||
{
|
||||
APICCommonState *s = APIC_COMMON(opaque);
|
||||
apic_irq_delivered = s->apic_irq_delivered;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_apic_common_sipi = {
|
||||
.name = "apic_sipi",
|
||||
.version_id = 1,
|
||||
@ -397,6 +416,19 @@ static const VMStateDescription vmstate_apic_common_sipi = {
|
||||
}
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_apic_irq_delivered = {
|
||||
.name = "apic_irq_delivered",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.needed = apic_irq_delivered_needed,
|
||||
.pre_save = apic_irq_delivered_pre_save,
|
||||
.post_load = apic_irq_delivered_post_load,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_INT32(apic_irq_delivered, APICCommonState),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_apic_common = {
|
||||
.name = "apic",
|
||||
.version_id = 3,
|
||||
@ -431,6 +463,7 @@ static const VMStateDescription vmstate_apic_common = {
|
||||
},
|
||||
.subsections = (const VMStateDescription*[]) {
|
||||
&vmstate_apic_common_sipi,
|
||||
&vmstate_apic_irq_delivered,
|
||||
NULL
|
||||
}
|
||||
};
|
||||
|
@ -288,7 +288,7 @@ MemoryRegion *isa_address_space_io(ISADevice *dev)
|
||||
|
||||
type_init(isabus_register_types)
|
||||
|
||||
static void parallel_init(ISABus *bus, int index, CharDriverState *chr)
|
||||
static void parallel_init(ISABus *bus, int index, Chardev *chr)
|
||||
{
|
||||
DeviceState *dev;
|
||||
ISADevice *isadev;
|
||||
|
@ -48,6 +48,8 @@
|
||||
#include "exec/address-spaces.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "qom/cpu.h"
|
||||
#include "hw/nvram/fw_cfg.h"
|
||||
#include "qemu/cutils.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
/* ICH9 LPC PCI to ISA bridge */
|
||||
@ -360,13 +362,62 @@ static void ich9_set_sci(void *opaque, int irq_num, int level)
|
||||
}
|
||||
}
|
||||
|
||||
static void smi_features_ok_callback(void *opaque)
|
||||
{
|
||||
ICH9LPCState *lpc = opaque;
|
||||
uint64_t guest_features;
|
||||
|
||||
if (lpc->smi_features_ok) {
|
||||
/* negotiation already complete, features locked */
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(&guest_features, lpc->smi_guest_features_le, sizeof guest_features);
|
||||
le64_to_cpus(&guest_features);
|
||||
if (guest_features & ~lpc->smi_host_features) {
|
||||
/* guest requests invalid features, leave @features_ok at zero */
|
||||
return;
|
||||
}
|
||||
|
||||
/* valid feature subset requested, lock it down, report success */
|
||||
lpc->smi_negotiated_features = guest_features;
|
||||
lpc->smi_features_ok = 1;
|
||||
}
|
||||
|
||||
void ich9_lpc_pm_init(PCIDevice *lpc_pci, bool smm_enabled)
|
||||
{
|
||||
ICH9LPCState *lpc = ICH9_LPC_DEVICE(lpc_pci);
|
||||
qemu_irq sci_irq;
|
||||
FWCfgState *fw_cfg = fw_cfg_find();
|
||||
|
||||
sci_irq = qemu_allocate_irq(ich9_set_sci, lpc, 0);
|
||||
ich9_pm_init(lpc_pci, &lpc->pm, smm_enabled, sci_irq);
|
||||
|
||||
if (lpc->smi_host_features && fw_cfg) {
|
||||
uint64_t host_features_le;
|
||||
|
||||
host_features_le = cpu_to_le64(lpc->smi_host_features);
|
||||
memcpy(lpc->smi_host_features_le, &host_features_le,
|
||||
sizeof host_features_le);
|
||||
fw_cfg_add_file(fw_cfg, "etc/smi/supported-features",
|
||||
lpc->smi_host_features_le,
|
||||
sizeof lpc->smi_host_features_le);
|
||||
|
||||
/* The other two guest-visible fields are cleared on device reset, we
|
||||
* just link them into fw_cfg here.
|
||||
*/
|
||||
fw_cfg_add_file_callback(fw_cfg, "etc/smi/requested-features",
|
||||
NULL, NULL,
|
||||
lpc->smi_guest_features_le,
|
||||
sizeof lpc->smi_guest_features_le,
|
||||
false);
|
||||
fw_cfg_add_file_callback(fw_cfg, "etc/smi/features-ok",
|
||||
smi_features_ok_callback, lpc,
|
||||
&lpc->smi_features_ok,
|
||||
sizeof lpc->smi_features_ok,
|
||||
true);
|
||||
}
|
||||
|
||||
ich9_lpc_reset(&lpc->d.qdev);
|
||||
}
|
||||
|
||||
@ -386,7 +437,15 @@ static void ich9_apm_ctrl_changed(uint32_t val, void *arg)
|
||||
|
||||
/* SMI_EN = PMBASE + 30. SMI control and enable register */
|
||||
if (lpc->pm.smi_en & ICH9_PMIO_SMI_EN_APMC_EN) {
|
||||
cpu_interrupt(current_cpu, CPU_INTERRUPT_SMI);
|
||||
if (lpc->smi_negotiated_features &
|
||||
(UINT64_C(1) << ICH9_LPC_SMI_F_BROADCAST_BIT)) {
|
||||
CPUState *cs;
|
||||
CPU_FOREACH(cs) {
|
||||
cpu_interrupt(cs, CPU_INTERRUPT_SMI);
|
||||
}
|
||||
} else {
|
||||
cpu_interrupt(current_cpu, CPU_INTERRUPT_SMI);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -507,6 +566,10 @@ static void ich9_lpc_reset(DeviceState *qdev)
|
||||
|
||||
lpc->sci_level = 0;
|
||||
lpc->rst_cnt = 0;
|
||||
|
||||
memset(lpc->smi_guest_features_le, 0, sizeof lpc->smi_guest_features_le);
|
||||
lpc->smi_features_ok = 0;
|
||||
lpc->smi_negotiated_features = 0;
|
||||
}
|
||||
|
||||
/* root complex register block is mapped into memory space */
|
||||
@ -668,6 +731,29 @@ static const VMStateDescription vmstate_ich9_rst_cnt = {
|
||||
}
|
||||
};
|
||||
|
||||
static bool ich9_smi_feat_needed(void *opaque)
|
||||
{
|
||||
ICH9LPCState *lpc = opaque;
|
||||
|
||||
return !buffer_is_zero(lpc->smi_guest_features_le,
|
||||
sizeof lpc->smi_guest_features_le) ||
|
||||
lpc->smi_features_ok;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_ich9_smi_feat = {
|
||||
.name = "ICH9LPC/smi_feat",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.needed = ich9_smi_feat_needed,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT8_ARRAY(smi_guest_features_le, ICH9LPCState,
|
||||
sizeof(uint64_t)),
|
||||
VMSTATE_UINT8(smi_features_ok, ICH9LPCState),
|
||||
VMSTATE_UINT64(smi_negotiated_features, ICH9LPCState),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_ich9_lpc = {
|
||||
.name = "ICH9LPC",
|
||||
.version_id = 1,
|
||||
@ -683,12 +769,15 @@ static const VMStateDescription vmstate_ich9_lpc = {
|
||||
},
|
||||
.subsections = (const VMStateDescription*[]) {
|
||||
&vmstate_ich9_rst_cnt,
|
||||
&vmstate_ich9_smi_feat,
|
||||
NULL
|
||||
}
|
||||
};
|
||||
|
||||
static Property ich9_lpc_properties[] = {
|
||||
DEFINE_PROP_BOOL("noreboot", ICH9LPCState, pin_strap.spkr_hi, true),
|
||||
DEFINE_PROP_BIT64("x-smi-broadcast", ICH9LPCState, smi_host_features,
|
||||
ICH9_LPC_SMI_F_BROADCAST_BIT, true),
|
||||
DEFINE_PROP_END_OF_LIST(),
|
||||
};
|
||||
|
||||
|
@ -268,7 +268,7 @@ static void pc87312_realize(DeviceState *dev, Error **errp)
|
||||
DeviceState *d;
|
||||
ISADevice *isa;
|
||||
ISABus *bus;
|
||||
CharDriverState *chr;
|
||||
Chardev *chr;
|
||||
DriveInfo *drive;
|
||||
char name[5];
|
||||
int i;
|
||||
|
@ -16,7 +16,7 @@ static inline DeviceState *lm32_pic_init(qemu_irq cpu_irq)
|
||||
return dev;
|
||||
}
|
||||
|
||||
static inline DeviceState *lm32_juart_init(CharDriverState *chr)
|
||||
static inline DeviceState *lm32_juart_init(Chardev *chr)
|
||||
{
|
||||
DeviceState *dev;
|
||||
|
||||
@ -29,7 +29,7 @@ static inline DeviceState *lm32_juart_init(CharDriverState *chr)
|
||||
|
||||
static inline DeviceState *lm32_uart_create(hwaddr addr,
|
||||
qemu_irq irq,
|
||||
CharDriverState *chr)
|
||||
Chardev *chr)
|
||||
{
|
||||
DeviceState *dev;
|
||||
SysBusDevice *s;
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
static inline DeviceState *milkymist_uart_create(hwaddr base,
|
||||
qemu_irq irq,
|
||||
CharDriverState *chr)
|
||||
Chardev *chr)
|
||||
{
|
||||
DeviceState *dev;
|
||||
|
||||
|
@ -551,10 +551,10 @@ static void malta_fgpa_display_event(void *opaque, int event)
|
||||
}
|
||||
|
||||
static MaltaFPGAState *malta_fpga_init(MemoryRegion *address_space,
|
||||
hwaddr base, qemu_irq uart_irq, CharDriverState *uart_chr)
|
||||
hwaddr base, qemu_irq uart_irq, Chardev *uart_chr)
|
||||
{
|
||||
MaltaFPGAState *s;
|
||||
CharDriverState *chr;
|
||||
Chardev *chr;
|
||||
|
||||
s = (MaltaFPGAState *)g_malloc0(sizeof(MaltaFPGAState));
|
||||
|
||||
|
@ -869,7 +869,7 @@ static void ivshmem_common_realize(PCIDevice *dev, Error **errp)
|
||||
s->ivshmem_bar2 = host_memory_backend_get_memory(s->hostmem,
|
||||
&error_abort);
|
||||
} else {
|
||||
CharDriverState *chr = qemu_chr_fe_get_driver(&s->server_chr);
|
||||
Chardev *chr = qemu_chr_fe_get_driver(&s->server_chr);
|
||||
assert(chr);
|
||||
|
||||
IVSHMEM_DPRINTF("using shared memory server (socket = %s)\n",
|
||||
|
@ -125,7 +125,7 @@ struct MilkymistPFPUState {
|
||||
SysBusDevice parent_obj;
|
||||
|
||||
MemoryRegion regs_region;
|
||||
CharDriverState *chr;
|
||||
Chardev *chr;
|
||||
qemu_irq irq;
|
||||
|
||||
uint32_t regs[R_MAX];
|
||||
|
@ -246,7 +246,7 @@ static void scsi_read_data(SCSIRequest *req)
|
||||
SCSIDevice *s = r->req.dev;
|
||||
int ret;
|
||||
|
||||
DPRINTF("scsi_read_data 0x%x\n", req->tag);
|
||||
DPRINTF("scsi_read_data tag=0x%x\n", req->tag);
|
||||
|
||||
/* The request is used as the AIO opaque value, so add a ref. */
|
||||
scsi_req_ref(&r->req);
|
||||
@ -294,7 +294,7 @@ static void scsi_write_data(SCSIRequest *req)
|
||||
SCSIDevice *s = r->req.dev;
|
||||
int ret;
|
||||
|
||||
DPRINTF("scsi_write_data 0x%x\n", req->tag);
|
||||
DPRINTF("scsi_write_data tag=0x%x\n", req->tag);
|
||||
if (r->len == 0) {
|
||||
r->len = r->buflen;
|
||||
scsi_req_data(&r->req, r->len);
|
||||
@ -329,6 +329,7 @@ static int32_t scsi_send_command(SCSIRequest *req, uint8_t *cmd)
|
||||
int ret;
|
||||
|
||||
#ifdef DEBUG_SCSI
|
||||
DPRINTF("Command: data=0x%02x", cmd[0]);
|
||||
{
|
||||
int i;
|
||||
for (i = 1; i < r->req.cmd.len; i++) {
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "hw/hw.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/replay.h"
|
||||
#include "hw/timer/mc146818rtc.h"
|
||||
#include "qapi/visitor.h"
|
||||
#include "qapi-event.h"
|
||||
@ -734,10 +735,16 @@ static int rtc_post_load(void *opaque, int version_id)
|
||||
check_update_timer(s);
|
||||
}
|
||||
|
||||
uint64_t now = qemu_clock_get_ns(rtc_clock);
|
||||
if (now < s->next_periodic_time ||
|
||||
now > (s->next_periodic_time + get_max_clock_jump())) {
|
||||
periodic_timer_update(s, qemu_clock_get_ns(rtc_clock));
|
||||
/* The periodic timer is deterministic in record/replay mode,
|
||||
* so there is no need to update it after loading the vmstate.
|
||||
* Reading RTC here would misalign record and replay.
|
||||
*/
|
||||
if (replay_mode == REPLAY_MODE_NONE) {
|
||||
uint64_t now = qemu_clock_get_ns(rtc_clock);
|
||||
if (now < s->next_periodic_time ||
|
||||
now > (s->next_periodic_time + get_max_clock_jump())) {
|
||||
periodic_timer_update(s, qemu_clock_get_ns(rtc_clock));
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TARGET_I386
|
||||
|
@ -264,7 +264,7 @@ static void ccid_card_vscard_handle_message(PassthruState *card,
|
||||
|
||||
static void ccid_card_vscard_drop_connection(PassthruState *card)
|
||||
{
|
||||
CharDriverState *chr = qemu_chr_fe_get_driver(&card->cs);
|
||||
Chardev *chr = qemu_chr_fe_get_driver(&card->cs);
|
||||
|
||||
qemu_chr_fe_deinit(&card->cs);
|
||||
qemu_chr_delete(chr);
|
||||
|
@ -483,7 +483,7 @@ static void usb_serial_realize(USBDevice *dev, Error **errp)
|
||||
{
|
||||
USBSerialState *s = USB_SERIAL_DEV(dev);
|
||||
Error *local_err = NULL;
|
||||
CharDriverState *chr = qemu_chr_fe_get_driver(&s->cs);
|
||||
Chardev *chr = qemu_chr_fe_get_driver(&s->cs);
|
||||
|
||||
usb_desc_create_serial(dev);
|
||||
usb_desc_init(dev);
|
||||
@ -512,7 +512,7 @@ static void usb_serial_realize(USBDevice *dev, Error **errp)
|
||||
static USBDevice *usb_serial_init(USBBus *bus, const char *filename)
|
||||
{
|
||||
USBDevice *dev;
|
||||
CharDriverState *cdrv;
|
||||
Chardev *cdrv;
|
||||
uint32_t vendorid = 0, productid = 0;
|
||||
char label[32];
|
||||
static int index;
|
||||
@ -564,7 +564,7 @@ static USBDevice *usb_serial_init(USBBus *bus, const char *filename)
|
||||
static USBDevice *usb_braille_init(USBBus *bus, const char *unused)
|
||||
{
|
||||
USBDevice *dev;
|
||||
CharDriverState *cdrv;
|
||||
Chardev *cdrv;
|
||||
|
||||
cdrv = qemu_chr_new("braille", "braille");
|
||||
if (!cdrv)
|
||||
|
@ -284,7 +284,7 @@ static gboolean usbredir_write_unblocked(GIOChannel *chan, GIOCondition cond,
|
||||
static int usbredir_write(void *priv, uint8_t *data, int count)
|
||||
{
|
||||
USBRedirDevice *dev = priv;
|
||||
CharDriverState *chr = qemu_chr_fe_get_driver(&dev->cs);
|
||||
Chardev *chr = qemu_chr_fe_get_driver(&dev->cs);
|
||||
int r;
|
||||
|
||||
if (!chr->be_open) {
|
||||
@ -1430,7 +1430,7 @@ static void usbredir_cleanup_device_queues(USBRedirDevice *dev)
|
||||
static void usbredir_handle_destroy(USBDevice *udev)
|
||||
{
|
||||
USBRedirDevice *dev = USB_REDIRECT(udev);
|
||||
CharDriverState *chr = qemu_chr_fe_get_driver(&dev->cs);
|
||||
Chardev *chr = qemu_chr_fe_get_driver(&dev->cs);
|
||||
|
||||
qemu_chr_fe_deinit(&dev->cs);
|
||||
qemu_chr_delete(chr);
|
||||
|
@ -116,6 +116,7 @@ typedef struct HDGeometry {
|
||||
|
||||
#define BDRV_REQUEST_MAX_SECTORS MIN(SIZE_MAX >> BDRV_SECTOR_BITS, \
|
||||
INT_MAX >> BDRV_SECTOR_BITS)
|
||||
#define BDRV_REQUEST_MAX_BYTES (BDRV_REQUEST_MAX_SECTORS << BDRV_SECTOR_BITS)
|
||||
|
||||
/*
|
||||
* Allocation status flags
|
||||
|
@ -1250,7 +1250,7 @@ void memory_global_dirty_log_start(void);
|
||||
*/
|
||||
void memory_global_dirty_log_stop(void);
|
||||
|
||||
void mtree_info(fprintf_function mon_printf, void *f);
|
||||
void mtree_info(fprintf_function mon_printf, void *f, bool flatview);
|
||||
|
||||
/**
|
||||
* memory_region_dispatch_read: perform a read directly to the specified
|
||||
|
@ -131,7 +131,7 @@ void exynos4210_combiner_get_gpioin(Exynos4210Irq *irqs, DeviceState *dev,
|
||||
DeviceState *exynos4210_uart_create(hwaddr addr,
|
||||
int fifo_size,
|
||||
int channel,
|
||||
CharDriverState *chr,
|
||||
Chardev *chr,
|
||||
qemu_irq irq);
|
||||
|
||||
#endif /* EXYNOS4210_H */
|
||||
|
@ -664,14 +664,14 @@ struct omap_uart_s;
|
||||
struct omap_uart_s *omap_uart_init(hwaddr base,
|
||||
qemu_irq irq, omap_clk fclk, omap_clk iclk,
|
||||
qemu_irq txdma, qemu_irq rxdma,
|
||||
const char *label, CharDriverState *chr);
|
||||
const char *label, Chardev *chr);
|
||||
struct omap_uart_s *omap2_uart_init(MemoryRegion *sysmem,
|
||||
struct omap_target_agent_s *ta,
|
||||
qemu_irq irq, omap_clk fclk, omap_clk iclk,
|
||||
qemu_irq txdma, qemu_irq rxdma,
|
||||
const char *label, CharDriverState *chr);
|
||||
const char *label, Chardev *chr);
|
||||
void omap_uart_reset(struct omap_uart_s *s);
|
||||
void omap_uart_attach(struct omap_uart_s *s, CharDriverState *chr);
|
||||
void omap_uart_attach(struct omap_uart_s *s, Chardev *chr);
|
||||
|
||||
struct omap_mpuio_s;
|
||||
qemu_irq *omap_mpuio_in_get(struct omap_mpuio_s *s);
|
||||
|
@ -127,8 +127,8 @@ enum {
|
||||
csrhci_pin_wakeup,
|
||||
__csrhci_pins,
|
||||
};
|
||||
qemu_irq *csrhci_pins_get(CharDriverState *chr);
|
||||
CharDriverState *uart_hci_init(void);
|
||||
qemu_irq *csrhci_pins_get(Chardev *chr);
|
||||
Chardev *uart_hci_init(void);
|
||||
|
||||
/* bt-l2cap.c */
|
||||
struct bt_l2cap_device_s;
|
||||
|
@ -51,7 +51,7 @@ typedef struct {
|
||||
|
||||
static inline DeviceState *cadence_uart_create(hwaddr addr,
|
||||
qemu_irq irq,
|
||||
CharDriverState *chr)
|
||||
Chardev *chr)
|
||||
{
|
||||
DeviceState *dev;
|
||||
SysBusDevice *s;
|
||||
|
@ -5,7 +5,7 @@
|
||||
#define TYPE_ESCC "escc"
|
||||
#define ESCC_SIZE 4
|
||||
MemoryRegion *escc_init(hwaddr base, qemu_irq irqA, qemu_irq irqB,
|
||||
CharDriverState *chrA, CharDriverState *chrB,
|
||||
Chardev *chrA, Chardev *chrB,
|
||||
int clock, int it_shift);
|
||||
|
||||
void slavio_serial_ms_kbd_init(hwaddr base, qemu_irq irq,
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
static inline DeviceState *pl011_create(hwaddr addr,
|
||||
qemu_irq irq,
|
||||
CharDriverState *chr)
|
||||
Chardev *chr)
|
||||
{
|
||||
DeviceState *dev;
|
||||
SysBusDevice *s;
|
||||
@ -34,7 +34,7 @@ static inline DeviceState *pl011_create(hwaddr addr,
|
||||
|
||||
static inline DeviceState *pl011_luminary_create(hwaddr addr,
|
||||
qemu_irq irq,
|
||||
CharDriverState *chr)
|
||||
Chardev *chr)
|
||||
{
|
||||
DeviceState *dev;
|
||||
SysBusDevice *s;
|
||||
|
@ -88,11 +88,11 @@ void serial_set_frequency(SerialState *s, uint32_t frequency);
|
||||
|
||||
/* legacy pre qom */
|
||||
SerialState *serial_init(int base, qemu_irq irq, int baudbase,
|
||||
CharDriverState *chr, MemoryRegion *system_io);
|
||||
Chardev *chr, MemoryRegion *system_io);
|
||||
SerialState *serial_mm_init(MemoryRegion *address_space,
|
||||
hwaddr base, int it_shift,
|
||||
qemu_irq irq, int baudbase,
|
||||
CharDriverState *chr, enum device_endian end);
|
||||
Chardev *chr, enum device_endian end);
|
||||
|
||||
/* serial-isa.c */
|
||||
#define TYPE_ISA_SERIAL "isa-serial"
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
static inline DeviceState *xilinx_uartlite_create(hwaddr addr,
|
||||
qemu_irq irq,
|
||||
CharDriverState *chr)
|
||||
Chardev *chr)
|
||||
{
|
||||
DeviceState *dev;
|
||||
SysBusDevice *s;
|
||||
|
@ -48,7 +48,7 @@ etraxfs_eth_init(NICInfo *nd, hwaddr base, int phyaddr,
|
||||
|
||||
static inline DeviceState *etraxfs_ser_create(hwaddr addr,
|
||||
qemu_irq irq,
|
||||
CharDriverState *chr)
|
||||
Chardev *chr)
|
||||
{
|
||||
DeviceState *dev;
|
||||
SysBusDevice *s;
|
||||
|
@ -65,6 +65,6 @@ qemu_irq tc6393xb_l3v_get(TC6393xbState *s);
|
||||
/* sm501.c */
|
||||
void sm501_init(struct MemoryRegion *address_space_mem, uint32_t base,
|
||||
uint32_t local_mem_bytes, qemu_irq irq,
|
||||
CharDriverState *chr);
|
||||
Chardev *chr);
|
||||
|
||||
#endif
|
||||
|
@ -189,6 +189,8 @@ struct APICCommonState {
|
||||
DeviceState *vapic;
|
||||
hwaddr vapic_paddr; /* note: persistence via kvmvapic */
|
||||
bool legacy_instance_id;
|
||||
|
||||
int apic_irq_delivered; /* for saving static variable */
|
||||
};
|
||||
|
||||
typedef struct VAPICState {
|
||||
|
@ -64,6 +64,16 @@ typedef struct ICH9LPCState {
|
||||
uint8_t rst_cnt;
|
||||
MemoryRegion rst_cnt_mem;
|
||||
|
||||
/* SMI feature negotiation via fw_cfg */
|
||||
uint64_t smi_host_features; /* guest-invisible, host endian */
|
||||
uint8_t smi_host_features_le[8]; /* guest-visible, read-only, little
|
||||
* endian uint64_t */
|
||||
uint8_t smi_guest_features_le[8]; /* guest-visible, read-write, little
|
||||
* endian uint64_t */
|
||||
uint8_t smi_features_ok; /* guest-visible, read-only; selecting it
|
||||
* triggers feature lockdown */
|
||||
uint64_t smi_negotiated_features; /* guest-invisible, host endian */
|
||||
|
||||
/* isa bus */
|
||||
ISABus *isa_bus;
|
||||
MemoryRegion rcrb_mem; /* root complex register block */
|
||||
@ -240,4 +250,7 @@ Object *ich9_lpc_find(void);
|
||||
#define ICH9_SMB_HST_D1 0x06
|
||||
#define ICH9_SMB_HOST_BLOCK_DB 0x07
|
||||
|
||||
/* bit positions used in fw_cfg SMI feature negotiation */
|
||||
#define ICH9_LPC_SMI_F_BROADCAST_BIT 0
|
||||
|
||||
#endif /* HW_ICH9_H */
|
||||
|
@ -181,7 +181,7 @@ void parallel_hds_isa_init(ISABus *bus, int n);
|
||||
|
||||
bool parallel_mm_init(MemoryRegion *address_space,
|
||||
hwaddr base, int it_shift, qemu_irq irq,
|
||||
CharDriverState *chr);
|
||||
Chardev *chr);
|
||||
|
||||
/* i8259.c */
|
||||
|
||||
@ -381,6 +381,16 @@ bool e820_get_entry(int, uint32_t, uint64_t *, uint64_t *);
|
||||
.property = "x-mach-use-reliable-get-clock",\
|
||||
.value = "off",\
|
||||
},\
|
||||
{\
|
||||
.driver = "ICH9-LPC",\
|
||||
.property = "x-smi-broadcast",\
|
||||
.value = "off",\
|
||||
},\
|
||||
{\
|
||||
.driver = TYPE_X86_CPU,\
|
||||
.property = "vmware-cpuid-freq",\
|
||||
.value = "off",\
|
||||
},
|
||||
|
||||
#define PC_COMPAT_2_7 \
|
||||
HW_COMPAT_2_7 \
|
||||
|
@ -11,10 +11,10 @@ uint64_t mcf_uart_read(void *opaque, hwaddr addr,
|
||||
unsigned size);
|
||||
void mcf_uart_write(void *opaque, hwaddr addr,
|
||||
uint64_t val, unsigned size);
|
||||
void *mcf_uart_init(qemu_irq irq, CharDriverState *chr);
|
||||
void *mcf_uart_init(qemu_irq irq, Chardev *chr);
|
||||
void mcf_uart_mm_init(struct MemoryRegion *sysmem,
|
||||
hwaddr base,
|
||||
qemu_irq irq, CharDriverState *chr);
|
||||
qemu_irq irq, Chardev *chr);
|
||||
|
||||
/* mcf_intc.c */
|
||||
qemu_irq *mcf_intc_init(struct MemoryRegion *sysmem,
|
||||
|
@ -127,7 +127,7 @@ int spapr_vio_send_crq(VIOsPAPRDevice *dev, uint8_t *crq);
|
||||
|
||||
VIOsPAPRDevice *vty_lookup(sPAPRMachineState *spapr, target_ulong reg);
|
||||
void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len);
|
||||
void spapr_vty_create(VIOsPAPRBus *bus, CharDriverState *chardev);
|
||||
void spapr_vty_create(VIOsPAPRBus *bus, Chardev *chardev);
|
||||
void spapr_vlan_create(VIOsPAPRBus *bus, NICInfo *nd);
|
||||
void spapr_vscsi_create(VIOsPAPRBus *bus);
|
||||
|
||||
|
@ -26,6 +26,7 @@ typedef enum DeviceCategory {
|
||||
DEVICE_CATEGORY_DISPLAY,
|
||||
DEVICE_CATEGORY_SOUND,
|
||||
DEVICE_CATEGORY_MISC,
|
||||
DEVICE_CATEGORY_CPU,
|
||||
DEVICE_CATEGORY_MAX
|
||||
} DeviceCategory;
|
||||
|
||||
|
@ -184,7 +184,7 @@ void qdev_prop_set_uint32(DeviceState *dev, const char *name, uint32_t value);
|
||||
void qdev_prop_set_int32(DeviceState *dev, const char *name, int32_t value);
|
||||
void qdev_prop_set_uint64(DeviceState *dev, const char *name, uint64_t value);
|
||||
void qdev_prop_set_string(DeviceState *dev, const char *name, const char *value);
|
||||
void qdev_prop_set_chr(DeviceState *dev, const char *name, CharDriverState *value);
|
||||
void qdev_prop_set_chr(DeviceState *dev, const char *name, Chardev *value);
|
||||
void qdev_prop_set_netdev(DeviceState *dev, const char *name, NetClientState *value);
|
||||
void qdev_prop_set_drive(DeviceState *dev, const char *name,
|
||||
BlockBackend *value, Error **errp);
|
||||
|
@ -42,7 +42,7 @@ void tmu012_init(struct MemoryRegion *sysmem, hwaddr base,
|
||||
#define SH_SERIAL_FEAT_SCIF (1 << 0)
|
||||
void sh_serial_init(MemoryRegion *sysmem,
|
||||
hwaddr base, int feat,
|
||||
uint32_t freq, CharDriverState *chr,
|
||||
uint32_t freq, Chardev *chr,
|
||||
qemu_irq eri_source,
|
||||
qemu_irq rxi_source,
|
||||
qemu_irq txi_source,
|
||||
|
@ -100,7 +100,7 @@ DeviceState *grlib_gptimer_create(hwaddr base,
|
||||
|
||||
static inline
|
||||
DeviceState *grlib_apbuart_create(hwaddr base,
|
||||
CharDriverState *serial,
|
||||
Chardev *serial,
|
||||
qemu_irq irq)
|
||||
{
|
||||
DeviceState *dev;
|
||||
|
@ -37,7 +37,7 @@ int xen_is_pirq_msi(uint32_t msi_data);
|
||||
|
||||
qemu_irq *xen_interrupt_controller_init(void);
|
||||
|
||||
void xenstore_store_pv_console_info(int i, struct CharDriverState *chr);
|
||||
void xenstore_store_pv_console_info(int i, struct Chardev *chr);
|
||||
|
||||
void xen_hvm_init(PCMachineState *pcms, MemoryRegion **ram_memory);
|
||||
|
||||
|
@ -16,7 +16,7 @@ extern Monitor *cur_mon;
|
||||
|
||||
bool monitor_cur_is_qmp(void);
|
||||
|
||||
void monitor_init(CharDriverState *chr, int flags);
|
||||
void monitor_init(Chardev *chr, int flags);
|
||||
void monitor_cleanup(void);
|
||||
|
||||
int monitor_suspend(Monitor *mon);
|
||||
|
@ -17,7 +17,7 @@ typedef struct BlockBackendRootState BlockBackendRootState;
|
||||
typedef struct BlockDriverState BlockDriverState;
|
||||
typedef struct BusClass BusClass;
|
||||
typedef struct BusState BusState;
|
||||
typedef struct CharDriverState CharDriverState;
|
||||
typedef struct Chardev Chardev;
|
||||
typedef struct CompatProperty CompatProperty;
|
||||
typedef struct CPUAddressSpace CPUAddressSpace;
|
||||
typedef struct CPUState CPUState;
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "qapi/qmp/qstring.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/bitmap.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
/* character device */
|
||||
|
||||
@ -69,14 +70,16 @@ typedef enum {
|
||||
/* Whether it is possible to send/recv file descriptors
|
||||
* over the data channel */
|
||||
QEMU_CHAR_FEATURE_FD_PASS,
|
||||
/* Whether replay or record mode is enabled */
|
||||
QEMU_CHAR_FEATURE_REPLAY,
|
||||
|
||||
QEMU_CHAR_FEATURE_LAST,
|
||||
} CharDriverFeature;
|
||||
|
||||
/* This is the backend as seen by frontend, the actual backend is
|
||||
* CharDriverState */
|
||||
* Chardev */
|
||||
typedef struct CharBackend {
|
||||
CharDriverState *chr;
|
||||
Chardev *chr;
|
||||
IOEventHandler *chr_event;
|
||||
IOCanReadHandler *chr_can_read;
|
||||
IOReadHandler *chr_read;
|
||||
@ -85,48 +88,22 @@ typedef struct CharBackend {
|
||||
int fe_open;
|
||||
} CharBackend;
|
||||
|
||||
struct CharDriverState {
|
||||
typedef struct CharDriver CharDriver;
|
||||
|
||||
struct Chardev {
|
||||
Object parent_obj;
|
||||
|
||||
QemuMutex chr_write_lock;
|
||||
int (*chr_write)(struct CharDriverState *s, const uint8_t *buf, int len);
|
||||
int (*chr_sync_read)(struct CharDriverState *s,
|
||||
const uint8_t *buf, int len);
|
||||
GSource *(*chr_add_watch)(struct CharDriverState *s, GIOCondition cond);
|
||||
void (*chr_update_read_handler)(struct CharDriverState *s,
|
||||
GMainContext *context);
|
||||
int (*chr_ioctl)(struct CharDriverState *s, int cmd, void *arg);
|
||||
int (*get_msgfds)(struct CharDriverState *s, int* fds, int num);
|
||||
int (*set_msgfds)(struct CharDriverState *s, int *fds, int num);
|
||||
int (*chr_add_client)(struct CharDriverState *chr, int fd);
|
||||
int (*chr_wait_connected)(struct CharDriverState *chr, Error **errp);
|
||||
void (*chr_free)(struct CharDriverState *chr);
|
||||
void (*chr_disconnect)(struct CharDriverState *chr);
|
||||
void (*chr_accept_input)(struct CharDriverState *chr);
|
||||
void (*chr_set_echo)(struct CharDriverState *chr, bool echo);
|
||||
void (*chr_set_fe_open)(struct CharDriverState *chr, int fe_open);
|
||||
CharBackend *be;
|
||||
void *opaque;
|
||||
char *label;
|
||||
char *filename;
|
||||
int logfd;
|
||||
int be_open;
|
||||
int is_mux;
|
||||
guint fd_in_tag;
|
||||
bool replay;
|
||||
DECLARE_BITMAP(features, QEMU_CHAR_FEATURE_LAST);
|
||||
QTAILQ_ENTRY(CharDriverState) next;
|
||||
QTAILQ_ENTRY(Chardev) next;
|
||||
};
|
||||
|
||||
/**
|
||||
* qemu_chr_alloc:
|
||||
* @backend: the common backend config
|
||||
* @errp: pointer to a NULL-initialized error object
|
||||
*
|
||||
* Allocate and initialize a new CharDriverState.
|
||||
*
|
||||
* Returns: a newly allocated CharDriverState, or NULL on error.
|
||||
*/
|
||||
CharDriverState *qemu_chr_alloc(ChardevCommon *backend, Error **errp);
|
||||
|
||||
/**
|
||||
* @qemu_chr_new_from_opts:
|
||||
*
|
||||
@ -136,8 +113,8 @@ CharDriverState *qemu_chr_alloc(ChardevCommon *backend, Error **errp);
|
||||
*
|
||||
* Returns: a new character backend
|
||||
*/
|
||||
CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts,
|
||||
Error **errp);
|
||||
Chardev *qemu_chr_new_from_opts(QemuOpts *opts,
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* @qemu_chr_parse_common:
|
||||
@ -159,7 +136,7 @@ void qemu_chr_parse_common(QemuOpts *opts, ChardevCommon *backend);
|
||||
*
|
||||
* Returns: a new character backend
|
||||
*/
|
||||
CharDriverState *qemu_chr_new(const char *label, const char *filename);
|
||||
Chardev *qemu_chr_new(const char *label, const char *filename);
|
||||
|
||||
|
||||
/**
|
||||
@ -197,7 +174,7 @@ int qemu_chr_fe_wait_connected(CharBackend *be, Error **errp);
|
||||
*
|
||||
* Returns: a new character backend
|
||||
*/
|
||||
CharDriverState *qemu_chr_new_noreplay(const char *label, const char *filename);
|
||||
Chardev *qemu_chr_new_noreplay(const char *label, const char *filename);
|
||||
|
||||
/**
|
||||
* @qemu_chr_delete:
|
||||
@ -205,14 +182,14 @@ CharDriverState *qemu_chr_new_noreplay(const char *label, const char *filename);
|
||||
* Destroy a character backend and remove it from the list of
|
||||
* identified character backends.
|
||||
*/
|
||||
void qemu_chr_delete(CharDriverState *chr);
|
||||
void qemu_chr_delete(Chardev *chr);
|
||||
|
||||
/**
|
||||
* @qemu_chr_free:
|
||||
*
|
||||
* Destroy a character backend.
|
||||
*/
|
||||
void qemu_chr_free(CharDriverState *chr);
|
||||
void qemu_chr_free(Chardev *chr);
|
||||
|
||||
/**
|
||||
* @qemu_chr_fe_set_echo:
|
||||
@ -258,6 +235,8 @@ void qemu_chr_fe_printf(CharBackend *be, const char *fmt, ...)
|
||||
* @cond the condition to poll for
|
||||
* @func the function to call when the condition happens
|
||||
* @user_data the opaque pointer to pass to @func
|
||||
*
|
||||
* Returns: the source tag
|
||||
*/
|
||||
guint qemu_chr_fe_add_watch(CharBackend *be, GIOCondition cond,
|
||||
GIOFunc func, void *user_data);
|
||||
@ -366,7 +345,7 @@ int qemu_chr_fe_set_msgfds(CharBackend *be, int *fds, int num);
|
||||
*
|
||||
* Returns: the number of bytes the front end can receive via @qemu_chr_be_write
|
||||
*/
|
||||
int qemu_chr_be_can_write(CharDriverState *s);
|
||||
int qemu_chr_be_can_write(Chardev *s);
|
||||
|
||||
/**
|
||||
* @qemu_chr_be_write:
|
||||
@ -378,7 +357,7 @@ int qemu_chr_be_can_write(CharDriverState *s);
|
||||
* @buf a buffer to receive data from the front end
|
||||
* @len the number of bytes to receive from the front end
|
||||
*/
|
||||
void qemu_chr_be_write(CharDriverState *s, uint8_t *buf, int len);
|
||||
void qemu_chr_be_write(Chardev *s, uint8_t *buf, int len);
|
||||
|
||||
/**
|
||||
* @qemu_chr_be_write_impl:
|
||||
@ -388,7 +367,7 @@ void qemu_chr_be_write(CharDriverState *s, uint8_t *buf, int len);
|
||||
* @buf a buffer to receive data from the front end
|
||||
* @len the number of bytes to receive from the front end
|
||||
*/
|
||||
void qemu_chr_be_write_impl(CharDriverState *s, uint8_t *buf, int len);
|
||||
void qemu_chr_be_write_impl(Chardev *s, uint8_t *buf, int len);
|
||||
|
||||
/**
|
||||
* @qemu_chr_be_event:
|
||||
@ -397,7 +376,7 @@ void qemu_chr_be_write_impl(CharDriverState *s, uint8_t *buf, int len);
|
||||
*
|
||||
* @event the event to send
|
||||
*/
|
||||
void qemu_chr_be_event(CharDriverState *s, int event);
|
||||
void qemu_chr_be_event(Chardev *s, int event);
|
||||
|
||||
/**
|
||||
* @qemu_chr_fe_init:
|
||||
@ -408,7 +387,7 @@ void qemu_chr_be_event(CharDriverState *s, int event);
|
||||
*
|
||||
* Returns: false on error.
|
||||
*/
|
||||
bool qemu_chr_fe_init(CharBackend *b, CharDriverState *s, Error **errp);
|
||||
bool qemu_chr_fe_init(CharBackend *b, Chardev *s, Error **errp);
|
||||
|
||||
/**
|
||||
* @qemu_chr_fe_get_driver:
|
||||
@ -416,7 +395,7 @@ bool qemu_chr_fe_init(CharBackend *b, CharDriverState *s, Error **errp);
|
||||
* Returns the driver associated with a CharBackend or NULL if no
|
||||
* associated CharDriver.
|
||||
*/
|
||||
CharDriverState *qemu_chr_fe_get_driver(CharBackend *be);
|
||||
Chardev *qemu_chr_fe_get_driver(CharBackend *be);
|
||||
|
||||
/**
|
||||
* @qemu_chr_fe_deinit:
|
||||
@ -461,33 +440,83 @@ void qemu_chr_fe_set_handlers(CharBackend *b,
|
||||
*/
|
||||
void qemu_chr_fe_take_focus(CharBackend *b);
|
||||
|
||||
void qemu_chr_be_generic_open(CharDriverState *s);
|
||||
void qemu_chr_be_generic_open(Chardev *s);
|
||||
void qemu_chr_fe_accept_input(CharBackend *be);
|
||||
int qemu_chr_add_client(CharDriverState *s, int fd);
|
||||
CharDriverState *qemu_chr_find(const char *name);
|
||||
bool chr_is_ringbuf(const CharDriverState *chr);
|
||||
int qemu_chr_add_client(Chardev *s, int fd);
|
||||
Chardev *qemu_chr_find(const char *name);
|
||||
|
||||
bool qemu_chr_has_feature(CharDriverState *chr,
|
||||
bool qemu_chr_has_feature(Chardev *chr,
|
||||
CharDriverFeature feature);
|
||||
void qemu_chr_set_feature(CharDriverState *chr,
|
||||
void qemu_chr_set_feature(Chardev *chr,
|
||||
CharDriverFeature feature);
|
||||
QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename);
|
||||
|
||||
typedef void CharDriverParse(QemuOpts *opts, ChardevBackend *backend,
|
||||
Error **errp);
|
||||
typedef CharDriverState *CharDriverCreate(const char *id,
|
||||
ChardevBackend *backend,
|
||||
ChardevReturn *ret, bool *be_opened,
|
||||
Error **errp);
|
||||
#define TYPE_CHARDEV "chardev"
|
||||
#define CHARDEV(obj) OBJECT_CHECK(Chardev, (obj), TYPE_CHARDEV)
|
||||
#define CHARDEV_CLASS(klass) \
|
||||
OBJECT_CLASS_CHECK(ChardevClass, (klass), TYPE_CHARDEV)
|
||||
#define CHARDEV_GET_CLASS(obj) \
|
||||
OBJECT_GET_CLASS(ChardevClass, (obj), TYPE_CHARDEV)
|
||||
|
||||
void register_char_driver(const char *name, ChardevBackendKind kind,
|
||||
CharDriverParse *parse, CharDriverCreate *create);
|
||||
#define TYPE_CHARDEV_NULL "chardev-null"
|
||||
#define TYPE_CHARDEV_MUX "chardev-mux"
|
||||
#define TYPE_CHARDEV_RINGBUF "chardev-ringbuf"
|
||||
#define TYPE_CHARDEV_PTY "chardev-pty"
|
||||
#define TYPE_CHARDEV_CONSOLE "chardev-console"
|
||||
#define TYPE_CHARDEV_STDIO "chardev-stdio"
|
||||
#define TYPE_CHARDEV_PIPE "chardev-pipe"
|
||||
#define TYPE_CHARDEV_MEMORY "chardev-memory"
|
||||
#define TYPE_CHARDEV_PARALLEL "chardev-parallel"
|
||||
#define TYPE_CHARDEV_FILE "chardev-file"
|
||||
#define TYPE_CHARDEV_SERIAL "chardev-serial"
|
||||
#define TYPE_CHARDEV_SOCKET "chardev-socket"
|
||||
#define TYPE_CHARDEV_UDP "chardev-udp"
|
||||
|
||||
#define CHARDEV_IS_MUX(chr) \
|
||||
object_dynamic_cast(OBJECT(chr), TYPE_CHARDEV_MUX)
|
||||
#define CHARDEV_IS_RINGBUF(chr) \
|
||||
object_dynamic_cast(OBJECT(chr), TYPE_CHARDEV_RINGBUF)
|
||||
#define CHARDEV_IS_PTY(chr) \
|
||||
object_dynamic_cast(OBJECT(chr), TYPE_CHARDEV_PTY)
|
||||
|
||||
typedef struct ChardevClass {
|
||||
ObjectClass parent_class;
|
||||
|
||||
bool internal; /* TODO: eventually use TYPE_USER_CREATABLE */
|
||||
|
||||
void (*open)(Chardev *chr, ChardevBackend *backend,
|
||||
bool *be_opened, Error **errp);
|
||||
|
||||
int (*chr_write)(Chardev *s, const uint8_t *buf, int len);
|
||||
int (*chr_sync_read)(Chardev *s, const uint8_t *buf, int len);
|
||||
GSource *(*chr_add_watch)(Chardev *s, GIOCondition cond);
|
||||
void (*chr_update_read_handler)(Chardev *s, GMainContext *context);
|
||||
int (*chr_ioctl)(Chardev *s, int cmd, void *arg);
|
||||
int (*get_msgfds)(Chardev *s, int* fds, int num);
|
||||
int (*set_msgfds)(Chardev *s, int *fds, int num);
|
||||
int (*chr_add_client)(Chardev *chr, int fd);
|
||||
int (*chr_wait_connected)(Chardev *chr, Error **errp);
|
||||
void (*chr_free)(Chardev *chr);
|
||||
void (*chr_disconnect)(Chardev *chr);
|
||||
void (*chr_accept_input)(Chardev *chr);
|
||||
void (*chr_set_echo)(Chardev *chr, bool echo);
|
||||
void (*chr_set_fe_open)(Chardev *chr, int fe_open);
|
||||
} ChardevClass;
|
||||
|
||||
struct CharDriver {
|
||||
ChardevBackendKind kind;
|
||||
const char *alias;
|
||||
void (*parse)(QemuOpts *opts, ChardevBackend *backend, Error **errp);
|
||||
};
|
||||
|
||||
Chardev *qemu_chardev_new(const char *id, const char *typename,
|
||||
ChardevBackend *backend, Error **errp);
|
||||
|
||||
void register_char_driver(const CharDriver *driver);
|
||||
|
||||
extern int term_escape_char;
|
||||
|
||||
|
||||
/* console.c */
|
||||
typedef CharDriverState *(VcHandler)(ChardevVC *vc, Error **errp);
|
||||
void register_vc_handler(VcHandler *handler);
|
||||
void qemu_chr_parse_vc(QemuOpts *opts, ChardevBackend *backend, Error **errp);
|
||||
|
||||
#endif
|
||||
|
@ -43,6 +43,9 @@ typedef struct ReplayNetState ReplayNetState;
|
||||
|
||||
extern ReplayMode replay_mode;
|
||||
|
||||
/* Name of the initial VM snapshot */
|
||||
extern char *replay_snapshot;
|
||||
|
||||
/* Replay process control functions */
|
||||
|
||||
/*! Enables recording or saving event log with specified parameters */
|
||||
@ -125,9 +128,9 @@ uint64_t blkreplay_next_id(void);
|
||||
/* Character device */
|
||||
|
||||
/*! Registers char driver to save it's events */
|
||||
void replay_register_char_driver(struct CharDriverState *chr);
|
||||
void replay_register_char_driver(struct Chardev *chr);
|
||||
/*! Saves write to char device event to the log */
|
||||
void replay_chr_be_write(struct CharDriverState *s, uint8_t *buf, int len);
|
||||
void replay_chr_be_write(struct Chardev *s, uint8_t *buf, int len);
|
||||
/*! Writes char write return value to the replay log. */
|
||||
void replay_char_write_event_save(int res, int offset);
|
||||
/*! Reads char write return value from the replay log. */
|
||||
@ -149,4 +152,10 @@ void replay_unregister_net(ReplayNetState *rns);
|
||||
void replay_net_packet_event(ReplayNetState *rns, unsigned flags,
|
||||
const struct iovec *iov, int iovcnt);
|
||||
|
||||
/* VM state operations */
|
||||
|
||||
/*! Called at the start of execution.
|
||||
Loads or saves initial vmstate depending on execution mode. */
|
||||
void replay_vmstate_init(void);
|
||||
|
||||
#endif
|
||||
|
@ -74,6 +74,7 @@ void qemu_add_machine_init_done_notifier(Notifier *notify);
|
||||
void qemu_remove_machine_init_done_notifier(Notifier *notify);
|
||||
|
||||
void hmp_savevm(Monitor *mon, const QDict *qdict);
|
||||
int save_vmstate(Monitor *mon, const char *name);
|
||||
int load_vmstate(const char *name);
|
||||
void hmp_delvm(Monitor *mon, const QDict *qdict);
|
||||
void hmp_info_snapshots(Monitor *mon, const QDict *qdict);
|
||||
@ -189,13 +190,13 @@ void hmp_pcie_aer_inject_error(Monitor *mon, const QDict *qdict);
|
||||
|
||||
#define MAX_SERIAL_PORTS 4
|
||||
|
||||
extern CharDriverState *serial_hds[MAX_SERIAL_PORTS];
|
||||
extern Chardev *serial_hds[MAX_SERIAL_PORTS];
|
||||
|
||||
/* parallel ports */
|
||||
|
||||
#define MAX_PARALLEL_PORTS 3
|
||||
|
||||
extern CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
|
||||
extern Chardev *parallel_hds[MAX_PARALLEL_PORTS];
|
||||
|
||||
void hmp_usb_add(Monitor *mon, const QDict *qdict);
|
||||
void hmp_usb_del(Monitor *mon, const QDict *qdict);
|
||||
|
@ -383,6 +383,8 @@ void graphic_hw_invalidate(QemuConsole *con);
|
||||
void graphic_hw_text_update(QemuConsole *con, console_ch_t *chardata);
|
||||
void graphic_hw_gl_block(QemuConsole *con, bool block);
|
||||
|
||||
void qemu_console_early_init(void);
|
||||
|
||||
QemuConsole *qemu_console_lookup_by_index(unsigned int index);
|
||||
QemuConsole *qemu_console_lookup_by_device(DeviceState *dev, uint32_t head);
|
||||
QemuConsole *qemu_console_lookup_by_device_name(const char *device_id,
|
||||
|
@ -64,7 +64,7 @@ typedef struct VirtualVteConsole {
|
||||
GtkWidget *box;
|
||||
GtkWidget *scrollbar;
|
||||
GtkWidget *terminal;
|
||||
CharDriverState *chr;
|
||||
Chardev *chr;
|
||||
bool echo;
|
||||
} VirtualVteConsole;
|
||||
#endif
|
||||
|
@ -51,7 +51,7 @@ int qemu_spice_migrate_info(const char *hostname, int port, int tls_port,
|
||||
#if SPICE_SERVER_VERSION >= 0x000c02
|
||||
void qemu_spice_register_ports(void);
|
||||
#else
|
||||
static inline CharDriverState *qemu_chr_open_spice_port(const char *name)
|
||||
static inline Chardev *qemu_chr_open_spice_port(const char *name)
|
||||
{ return NULL; }
|
||||
#endif
|
||||
|
||||
|
89
memory.c
89
memory.c
@ -2450,6 +2450,21 @@ void address_space_destroy(AddressSpace *as)
|
||||
call_rcu(as, do_address_space_destroy, rcu);
|
||||
}
|
||||
|
||||
static const char *memory_region_type(MemoryRegion *mr)
|
||||
{
|
||||
if (memory_region_is_ram_device(mr)) {
|
||||
return "ramd";
|
||||
} else if (memory_region_is_romd(mr)) {
|
||||
return "romd";
|
||||
} else if (memory_region_is_rom(mr)) {
|
||||
return "rom";
|
||||
} else if (memory_region_is_ram(mr)) {
|
||||
return "ram";
|
||||
} else {
|
||||
return "i/o";
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct MemoryRegionList MemoryRegionList;
|
||||
|
||||
struct MemoryRegionList {
|
||||
@ -2459,6 +2474,10 @@ struct MemoryRegionList {
|
||||
|
||||
typedef QTAILQ_HEAD(queue, MemoryRegionList) MemoryRegionListHead;
|
||||
|
||||
#define MR_SIZE(size) (int128_nz(size) ? (hwaddr)int128_get64( \
|
||||
int128_sub((size), int128_one())) : 0)
|
||||
#define MTREE_INDENT " "
|
||||
|
||||
static void mtree_print_mr(fprintf_function mon_printf, void *f,
|
||||
const MemoryRegion *mr, unsigned int level,
|
||||
hwaddr base,
|
||||
@ -2474,7 +2493,7 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f,
|
||||
}
|
||||
|
||||
for (i = 0; i < level; i++) {
|
||||
mon_printf(f, " ");
|
||||
mon_printf(f, MTREE_INDENT);
|
||||
}
|
||||
|
||||
if (mr->alias) {
|
||||
@ -2494,37 +2513,24 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f,
|
||||
QTAILQ_INSERT_TAIL(alias_print_queue, ml, queue);
|
||||
}
|
||||
mon_printf(f, TARGET_FMT_plx "-" TARGET_FMT_plx
|
||||
" (prio %d, %c%c): alias %s @%s " TARGET_FMT_plx
|
||||
" (prio %d, %s): alias %s @%s " TARGET_FMT_plx
|
||||
"-" TARGET_FMT_plx "%s\n",
|
||||
base + mr->addr,
|
||||
base + mr->addr
|
||||
+ (int128_nz(mr->size) ?
|
||||
(hwaddr)int128_get64(int128_sub(mr->size,
|
||||
int128_one())) : 0),
|
||||
base + mr->addr + MR_SIZE(mr->size),
|
||||
mr->priority,
|
||||
mr->romd_mode ? 'R' : '-',
|
||||
!mr->readonly && !(mr->rom_device && mr->romd_mode) ? 'W'
|
||||
: '-',
|
||||
memory_region_type((MemoryRegion *)mr),
|
||||
memory_region_name(mr),
|
||||
memory_region_name(mr->alias),
|
||||
mr->alias_offset,
|
||||
mr->alias_offset
|
||||
+ (int128_nz(mr->size) ?
|
||||
(hwaddr)int128_get64(int128_sub(mr->size,
|
||||
int128_one())) : 0),
|
||||
mr->alias_offset + MR_SIZE(mr->size),
|
||||
mr->enabled ? "" : " [disabled]");
|
||||
} else {
|
||||
mon_printf(f,
|
||||
TARGET_FMT_plx "-" TARGET_FMT_plx " (prio %d, %c%c): %s%s\n",
|
||||
TARGET_FMT_plx "-" TARGET_FMT_plx " (prio %d, %s): %s%s\n",
|
||||
base + mr->addr,
|
||||
base + mr->addr
|
||||
+ (int128_nz(mr->size) ?
|
||||
(hwaddr)int128_get64(int128_sub(mr->size,
|
||||
int128_one())) : 0),
|
||||
base + mr->addr + MR_SIZE(mr->size),
|
||||
mr->priority,
|
||||
mr->romd_mode ? 'R' : '-',
|
||||
!mr->readonly && !(mr->rom_device && mr->romd_mode) ? 'W'
|
||||
: '-',
|
||||
memory_region_type((MemoryRegion *)mr),
|
||||
memory_region_name(mr),
|
||||
mr->enabled ? "" : " [disabled]");
|
||||
}
|
||||
@ -2558,12 +2564,51 @@ static void mtree_print_mr(fprintf_function mon_printf, void *f,
|
||||
}
|
||||
}
|
||||
|
||||
void mtree_info(fprintf_function mon_printf, void *f)
|
||||
static void mtree_print_flatview(fprintf_function p, void *f,
|
||||
AddressSpace *as)
|
||||
{
|
||||
FlatView *view = address_space_get_flatview(as);
|
||||
FlatRange *range = &view->ranges[0];
|
||||
MemoryRegion *mr;
|
||||
int n = view->nr;
|
||||
|
||||
if (n <= 0) {
|
||||
p(f, MTREE_INDENT "No rendered FlatView for "
|
||||
"address space '%s'\n", as->name);
|
||||
flatview_unref(view);
|
||||
return;
|
||||
}
|
||||
|
||||
while (n--) {
|
||||
mr = range->mr;
|
||||
p(f, MTREE_INDENT TARGET_FMT_plx "-"
|
||||
TARGET_FMT_plx " (prio %d, %s): %s\n",
|
||||
int128_get64(range->addr.start),
|
||||
int128_get64(range->addr.start) + MR_SIZE(range->addr.size),
|
||||
mr->priority,
|
||||
memory_region_type(mr),
|
||||
memory_region_name(mr));
|
||||
range++;
|
||||
}
|
||||
|
||||
flatview_unref(view);
|
||||
}
|
||||
|
||||
void mtree_info(fprintf_function mon_printf, void *f, bool flatview)
|
||||
{
|
||||
MemoryRegionListHead ml_head;
|
||||
MemoryRegionList *ml, *ml2;
|
||||
AddressSpace *as;
|
||||
|
||||
if (flatview) {
|
||||
QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
|
||||
mon_printf(f, "address-space (flat view): %s\n", as->name);
|
||||
mtree_print_flatview(mon_printf, f, as);
|
||||
mon_printf(f, "\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
QTAILQ_INIT(&ml_head);
|
||||
|
||||
QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
|
||||
|
@ -2042,38 +2042,40 @@ int qemu_loadvm_state(QEMUFile *f)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void hmp_savevm(Monitor *mon, const QDict *qdict)
|
||||
int save_vmstate(Monitor *mon, const char *name)
|
||||
{
|
||||
BlockDriverState *bs, *bs1;
|
||||
QEMUSnapshotInfo sn1, *sn = &sn1, old_sn1, *old_sn = &old_sn1;
|
||||
int ret;
|
||||
int ret = -1;
|
||||
QEMUFile *f;
|
||||
int saved_vm_running;
|
||||
uint64_t vm_state_size;
|
||||
qemu_timeval tv;
|
||||
struct tm tm;
|
||||
const char *name = qdict_get_try_str(qdict, "name");
|
||||
Error *local_err = NULL;
|
||||
AioContext *aio_context;
|
||||
|
||||
if (!bdrv_all_can_snapshot(&bs)) {
|
||||
monitor_printf(mon, "Device '%s' is writable but does not "
|
||||
"support snapshots.\n", bdrv_get_device_name(bs));
|
||||
return;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Delete old snapshots of the same name */
|
||||
if (name && bdrv_all_delete_snapshot(name, &bs1, &local_err) < 0) {
|
||||
error_reportf_err(local_err,
|
||||
"Error while deleting snapshot on device '%s': ",
|
||||
bdrv_get_device_name(bs1));
|
||||
return;
|
||||
if (name) {
|
||||
ret = bdrv_all_delete_snapshot(name, &bs1, &local_err);
|
||||
if (ret < 0) {
|
||||
error_reportf_err(local_err,
|
||||
"Error while deleting snapshot on device '%s': ",
|
||||
bdrv_get_device_name(bs1));
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
bs = bdrv_all_find_vmstate_bs();
|
||||
if (bs == NULL) {
|
||||
monitor_printf(mon, "No block device can accept snapshots\n");
|
||||
return;
|
||||
return ret;
|
||||
}
|
||||
aio_context = bdrv_get_aio_context(bs);
|
||||
|
||||
@ -2082,7 +2084,7 @@ void hmp_savevm(Monitor *mon, const QDict *qdict)
|
||||
ret = global_state_store();
|
||||
if (ret) {
|
||||
monitor_printf(mon, "Error saving global state\n");
|
||||
return;
|
||||
return ret;
|
||||
}
|
||||
vm_stop(RUN_STATE_SAVE_VM);
|
||||
|
||||
@ -2128,13 +2130,22 @@ void hmp_savevm(Monitor *mon, const QDict *qdict)
|
||||
if (ret < 0) {
|
||||
monitor_printf(mon, "Error while creating snapshot on '%s'\n",
|
||||
bdrv_get_device_name(bs));
|
||||
goto the_end;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
the_end:
|
||||
aio_context_release(aio_context);
|
||||
if (saved_vm_running) {
|
||||
vm_start();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void hmp_savevm(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
save_vmstate(mon, qdict_get_try_str(qdict, "name"));
|
||||
}
|
||||
|
||||
void qmp_xen_save_devices_state(const char *filename, Error **errp)
|
||||
|
10
monitor.c
10
monitor.c
@ -1529,7 +1529,9 @@ static void hmp_boot_set(Monitor *mon, const QDict *qdict)
|
||||
|
||||
static void hmp_info_mtree(Monitor *mon, const QDict *qdict)
|
||||
{
|
||||
mtree_info((fprintf_function)monitor_printf, mon);
|
||||
bool flatview = qdict_get_try_bool(qdict, "flatview", false);
|
||||
|
||||
mtree_info((fprintf_function)monitor_printf, mon, flatview);
|
||||
}
|
||||
|
||||
static void hmp_info_numa(Monitor *mon, const QDict *qdict)
|
||||
@ -3193,8 +3195,8 @@ static void ringbuf_completion(ReadLineState *rs, const char *str)
|
||||
ChardevInfo *chr_info = list->value;
|
||||
|
||||
if (!strncmp(chr_info->label, str, len)) {
|
||||
CharDriverState *chr = qemu_chr_find(chr_info->label);
|
||||
if (chr && chr_is_ringbuf(chr)) {
|
||||
Chardev *chr = qemu_chr_find(chr_info->label);
|
||||
if (chr && CHARDEV_IS_RINGBUF(chr)) {
|
||||
readline_add_completion(rs, chr_info->label);
|
||||
}
|
||||
}
|
||||
@ -3983,7 +3985,7 @@ static void __attribute__((constructor)) monitor_lock_init(void)
|
||||
qemu_mutex_init(&monitor_lock);
|
||||
}
|
||||
|
||||
void monitor_init(CharDriverState *chr, int flags)
|
||||
void monitor_init(Chardev *chr, int flags)
|
||||
{
|
||||
static int is_first_init = 1;
|
||||
Monitor *mon;
|
||||
|
@ -564,7 +564,7 @@ static void compare_sec_rs_finalize(SocketReadState *sec_rs)
|
||||
* Return 0 is success.
|
||||
* Return 1 is failed.
|
||||
*/
|
||||
static int find_and_check_chardev(CharDriverState **chr,
|
||||
static int find_and_check_chardev(Chardev **chr,
|
||||
char *chr_name,
|
||||
Error **errp)
|
||||
{
|
||||
@ -611,7 +611,7 @@ static void check_old_packet_regular(void *opaque)
|
||||
static void colo_compare_complete(UserCreatable *uc, Error **errp)
|
||||
{
|
||||
CompareState *s = COLO_COMPARE(uc);
|
||||
CharDriverState *chr;
|
||||
Chardev *chr;
|
||||
char thread_name[64];
|
||||
static int compare_id;
|
||||
|
||||
|
@ -191,7 +191,7 @@ static void filter_redirector_cleanup(NetFilterState *nf)
|
||||
static void filter_mirror_setup(NetFilterState *nf, Error **errp)
|
||||
{
|
||||
MirrorState *s = FILTER_MIRROR(nf);
|
||||
CharDriverState *chr;
|
||||
Chardev *chr;
|
||||
|
||||
if (!s->outdev) {
|
||||
error_setg(errp, "filter mirror needs 'outdev' "
|
||||
@ -220,7 +220,7 @@ static void redirector_rs_finalize(SocketReadState *rs)
|
||||
static void filter_redirector_setup(NetFilterState *nf, Error **errp)
|
||||
{
|
||||
MirrorState *s = FILTER_REDIRECTOR(nf);
|
||||
CharDriverState *chr;
|
||||
Chardev *chr;
|
||||
|
||||
if (!s->indev && !s->outdev) {
|
||||
error_setg(errp, "filter redirector needs 'indev' or "
|
||||
|
@ -748,7 +748,7 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str,
|
||||
}
|
||||
} else {
|
||||
Error *err = NULL;
|
||||
CharDriverState *chr = qemu_chr_new(buf, p);
|
||||
Chardev *chr = qemu_chr_new(buf, p);
|
||||
|
||||
if (!chr) {
|
||||
error_report("could not open guest forwarding device '%s'", buf);
|
||||
|
@ -195,7 +195,7 @@ static void net_vhost_user_event(void *opaque, int event)
|
||||
const char *name = opaque;
|
||||
NetClientState *ncs[MAX_QUEUE_NUM];
|
||||
VhostUserState *s;
|
||||
CharDriverState *chr;
|
||||
Chardev *chr;
|
||||
Error *err = NULL;
|
||||
int queues;
|
||||
|
||||
@ -232,7 +232,7 @@ static void net_vhost_user_event(void *opaque, int event)
|
||||
}
|
||||
|
||||
static int net_vhost_user_init(NetClientState *peer, const char *device,
|
||||
const char *name, CharDriverState *chr,
|
||||
const char *name, Chardev *chr,
|
||||
int queues)
|
||||
{
|
||||
Error *err = NULL;
|
||||
@ -274,10 +274,10 @@ static int net_vhost_user_init(NetClientState *peer, const char *device,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static CharDriverState *net_vhost_claim_chardev(
|
||||
static Chardev *net_vhost_claim_chardev(
|
||||
const NetdevVhostUserOptions *opts, Error **errp)
|
||||
{
|
||||
CharDriverState *chr = qemu_chr_find(opts->chardev);
|
||||
Chardev *chr = qemu_chr_find(opts->chardev);
|
||||
|
||||
if (chr == NULL) {
|
||||
error_setg(errp, "chardev \"%s\" not found", opts->chardev);
|
||||
@ -324,7 +324,7 @@ int net_init_vhost_user(const Netdev *netdev, const char *name,
|
||||
{
|
||||
int queues;
|
||||
const NetdevVhostUserOptions *vhost_user_opts;
|
||||
CharDriverState *chr;
|
||||
Chardev *chr;
|
||||
|
||||
assert(netdev->type == NET_CLIENT_DRIVER_VHOST_USER);
|
||||
vhost_user_opts = &netdev->u.vhost_user;
|
||||
|
@ -137,6 +137,7 @@ static void qdev_print_devinfos(bool show_no_user)
|
||||
[DEVICE_CATEGORY_DISPLAY] = "Display",
|
||||
[DEVICE_CATEGORY_SOUND] = "Sound",
|
||||
[DEVICE_CATEGORY_MISC] = "Misc",
|
||||
[DEVICE_CATEGORY_CPU] = "CPU",
|
||||
[DEVICE_CATEGORY_MAX] = "Uncategorized",
|
||||
};
|
||||
GSList *list, *elt;
|
||||
|
1926
qemu-char.c
1926
qemu-char.c
File diff suppressed because it is too large
Load Diff
@ -2430,8 +2430,6 @@ Connect to standard input and standard output of the QEMU process.
|
||||
exiting QEMU with the key sequence @key{Control-c}. This option is enabled by
|
||||
default, use @option{signal=off} to disable it.
|
||||
|
||||
@option{stdio} is not available on Windows hosts.
|
||||
|
||||
@item -chardev braille ,id=@var{id}
|
||||
|
||||
Connect to a local BrlAPI server. @option{braille} does not take any options.
|
||||
@ -3017,7 +3015,7 @@ udp::4555@@:4556} to QEMU. Another approach is to use a patched
|
||||
version of netcat which can listen to a TCP port and send and receive
|
||||
characters via udp. If you have a patched version of netcat which
|
||||
activates telnet remote echo and single char transfer, then you can
|
||||
use the following options to step up a netcat redirector to allow
|
||||
use the following options to set up a netcat redirector to allow
|
||||
telnet on port 5555 to access the QEMU port.
|
||||
@table @code
|
||||
@item QEMU Options:
|
||||
@ -3400,12 +3398,12 @@ re-inject them.
|
||||
ETEXI
|
||||
|
||||
DEF("icount", HAS_ARG, QEMU_OPTION_icount, \
|
||||
"-icount [shift=N|auto][,align=on|off][,sleep=on|off,rr=record|replay,rrfile=<filename>]\n" \
|
||||
"-icount [shift=N|auto][,align=on|off][,sleep=on|off,rr=record|replay,rrfile=<filename>,rrsnapshot=<snapshot>]\n" \
|
||||
" enable virtual instruction counter with 2^N clock ticks per\n" \
|
||||
" instruction, enable aligning the host and virtual clocks\n" \
|
||||
" or disable real time cpu sleeping\n", QEMU_ARCH_ALL)
|
||||
STEXI
|
||||
@item -icount [shift=@var{N}|auto][,rr=record|replay,rrfile=@var{filename}]
|
||||
@item -icount [shift=@var{N}|auto][,rr=record|replay,rrfile=@var{filename},rrsnapshot=@var{snapshot}]
|
||||
@findex -icount
|
||||
Enable virtual instruction counter. The virtual cpu will execute one
|
||||
instruction every 2^@var{N} ns of virtual time. If @code{auto} is specified
|
||||
@ -3438,6 +3436,10 @@ when the shift value is high (how high depends on the host machine).
|
||||
When @option{rr} option is specified deterministic record/replay is enabled.
|
||||
Replay log is written into @var{filename} file in record mode and
|
||||
read from this file in replay mode.
|
||||
|
||||
Option rrsnapshot is used to create new vm snapshot named @var{snapshot}
|
||||
at the start of execution recording. In replay mode this option is used
|
||||
to load the initial VM state.
|
||||
ETEXI
|
||||
|
||||
DEF("watchdog", HAS_ARG, QEMU_OPTION_watchdog, \
|
||||
|
2
qmp.c
2
qmp.c
@ -616,7 +616,7 @@ void qmp_add_client(const char *protocol, const char *fdname,
|
||||
bool has_skipauth, bool skipauth, bool has_tls, bool tls,
|
||||
Error **errp)
|
||||
{
|
||||
CharDriverState *s;
|
||||
Chardev *s;
|
||||
int fd;
|
||||
|
||||
fd = monitor_get_fd(cur_mon, fdname, errp);
|
||||
|
@ -415,6 +415,7 @@ static void cpu_class_init(ObjectClass *klass, void *data)
|
||||
k->cpu_exec_enter = cpu_common_noop;
|
||||
k->cpu_exec_exit = cpu_common_noop;
|
||||
k->cpu_exec_interrupt = cpu_common_exec_interrupt;
|
||||
set_bit(DEVICE_CATEGORY_CPU, dc->categories);
|
||||
dc->realize = cpu_common_realizefn;
|
||||
dc->unrealize = cpu_common_unrealizefn;
|
||||
/*
|
||||
|
2
qtest.c
2
qtest.c
@ -670,7 +670,7 @@ static int qtest_init_accel(MachineState *ms)
|
||||
|
||||
void qtest_init(const char *qtest_chrdev, const char *qtest_log, Error **errp)
|
||||
{
|
||||
CharDriverState *chr;
|
||||
Chardev *chr;
|
||||
|
||||
chr = qemu_chr_new("qtest", qtest_chrdev);
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
/* Char drivers that generate qemu_chr_be_write events
|
||||
that should be saved into the log. */
|
||||
static CharDriverState **char_drivers;
|
||||
static Chardev **char_drivers;
|
||||
static int drivers_count;
|
||||
|
||||
/* Char event attributes. */
|
||||
@ -28,7 +28,7 @@ typedef struct CharEvent {
|
||||
size_t len;
|
||||
} CharEvent;
|
||||
|
||||
static int find_char_driver(CharDriverState *chr)
|
||||
static int find_char_driver(Chardev *chr)
|
||||
{
|
||||
int i = 0;
|
||||
for ( ; i < drivers_count ; ++i) {
|
||||
@ -39,7 +39,7 @@ static int find_char_driver(CharDriverState *chr)
|
||||
return -1;
|
||||
}
|
||||
|
||||
void replay_register_char_driver(CharDriverState *chr)
|
||||
void replay_register_char_driver(Chardev *chr)
|
||||
{
|
||||
if (replay_mode == REPLAY_MODE_NONE) {
|
||||
return;
|
||||
@ -49,7 +49,7 @@ void replay_register_char_driver(CharDriverState *chr)
|
||||
char_drivers[drivers_count++] = chr;
|
||||
}
|
||||
|
||||
void replay_chr_be_write(CharDriverState *s, uint8_t *buf, int len)
|
||||
void replay_chr_be_write(Chardev *s, uint8_t *buf, int len)
|
||||
{
|
||||
CharEvent *event = g_malloc0(sizeof(CharEvent));
|
||||
|
||||
|
@ -59,3 +59,20 @@ void replay_vmstate_register(void)
|
||||
{
|
||||
vmstate_register(NULL, 0, &vmstate_replay, &replay_state);
|
||||
}
|
||||
|
||||
void replay_vmstate_init(void)
|
||||
{
|
||||
if (replay_snapshot) {
|
||||
if (replay_mode == REPLAY_MODE_RECORD) {
|
||||
if (save_vmstate(cur_mon, replay_snapshot) != 0) {
|
||||
error_report("Could not create snapshot for icount record");
|
||||
exit(1);
|
||||
}
|
||||
} else if (replay_mode == REPLAY_MODE_PLAY) {
|
||||
if (load_vmstate(replay_snapshot) != 0) {
|
||||
error_report("Could not load snapshot for icount replay");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
#define HEADER_SIZE (sizeof(uint32_t) + sizeof(uint64_t))
|
||||
|
||||
ReplayMode replay_mode = REPLAY_MODE_NONE;
|
||||
char *replay_snapshot;
|
||||
|
||||
/* Name of replay file */
|
||||
static char *replay_filename;
|
||||
@ -292,6 +293,7 @@ void replay_configure(QemuOpts *opts)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
replay_snapshot = g_strdup(qemu_opt_get(opts, "rrsnapshot"));
|
||||
replay_vmstate_register();
|
||||
replay_enable(fname, mode);
|
||||
|
||||
@ -346,6 +348,9 @@ void replay_finish(void)
|
||||
replay_filename = NULL;
|
||||
}
|
||||
|
||||
g_free(replay_snapshot);
|
||||
replay_snapshot = NULL;
|
||||
|
||||
replay_finish_events();
|
||||
replay_mutex_destroy();
|
||||
}
|
||||
|
@ -2,42 +2,51 @@
|
||||
#include "trace.h"
|
||||
#include "ui/qemu-spice.h"
|
||||
#include "sysemu/char.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include <spice.h>
|
||||
#include <spice/protocol.h>
|
||||
|
||||
|
||||
typedef struct SpiceCharDriver {
|
||||
CharDriverState* chr;
|
||||
SpiceCharDeviceInstance sin;
|
||||
typedef struct SpiceChardev {
|
||||
Chardev parent;
|
||||
|
||||
SpiceCharDeviceInstance sin;
|
||||
bool active;
|
||||
bool blocked;
|
||||
const uint8_t *datapos;
|
||||
int datalen;
|
||||
QLIST_ENTRY(SpiceCharDriver) next;
|
||||
} SpiceCharDriver;
|
||||
QLIST_ENTRY(SpiceChardev) next;
|
||||
} SpiceChardev;
|
||||
|
||||
#define TYPE_CHARDEV_SPICE "chardev-spice"
|
||||
#define TYPE_CHARDEV_SPICEVMC "chardev-spicevmc"
|
||||
#define TYPE_CHARDEV_SPICEPORT "chardev-spiceport"
|
||||
|
||||
#define SPICE_CHARDEV(obj) OBJECT_CHECK(SpiceChardev, (obj), TYPE_CHARDEV_SPICE)
|
||||
|
||||
typedef struct SpiceCharSource {
|
||||
GSource source;
|
||||
SpiceCharDriver *scd;
|
||||
SpiceChardev *scd;
|
||||
} SpiceCharSource;
|
||||
|
||||
static QLIST_HEAD(, SpiceCharDriver) spice_chars =
|
||||
static QLIST_HEAD(, SpiceChardev) spice_chars =
|
||||
QLIST_HEAD_INITIALIZER(spice_chars);
|
||||
|
||||
static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
|
||||
{
|
||||
SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
|
||||
SpiceChardev *scd = container_of(sin, SpiceChardev, sin);
|
||||
Chardev *chr = CHARDEV(scd);
|
||||
ssize_t out = 0;
|
||||
ssize_t last_out;
|
||||
uint8_t* p = (uint8_t*)buf;
|
||||
|
||||
while (len > 0) {
|
||||
int can_write = qemu_chr_be_can_write(scd->chr);
|
||||
int can_write = qemu_chr_be_can_write(chr);
|
||||
last_out = MIN(len, can_write);
|
||||
if (last_out <= 0) {
|
||||
break;
|
||||
}
|
||||
qemu_chr_be_write(scd->chr, p, last_out);
|
||||
qemu_chr_be_write(chr, p, last_out);
|
||||
out += last_out;
|
||||
len -= last_out;
|
||||
p += last_out;
|
||||
@ -49,7 +58,7 @@ static int vmc_write(SpiceCharDeviceInstance *sin, const uint8_t *buf, int len)
|
||||
|
||||
static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
|
||||
{
|
||||
SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
|
||||
SpiceChardev *scd = container_of(sin, SpiceChardev, sin);
|
||||
int bytes = MIN(len, scd->datalen);
|
||||
|
||||
if (bytes > 0) {
|
||||
@ -69,7 +78,8 @@ static int vmc_read(SpiceCharDeviceInstance *sin, uint8_t *buf, int len)
|
||||
#if SPICE_SERVER_VERSION >= 0x000c02
|
||||
static void vmc_event(SpiceCharDeviceInstance *sin, uint8_t event)
|
||||
{
|
||||
SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
|
||||
SpiceChardev *scd = container_of(sin, SpiceChardev, sin);
|
||||
Chardev *chr = CHARDEV(scd);
|
||||
int chr_event;
|
||||
|
||||
switch (event) {
|
||||
@ -81,20 +91,21 @@ static void vmc_event(SpiceCharDeviceInstance *sin, uint8_t event)
|
||||
}
|
||||
|
||||
trace_spice_vmc_event(chr_event);
|
||||
qemu_chr_be_event(scd->chr, chr_event);
|
||||
qemu_chr_be_event(chr, chr_event);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void vmc_state(SpiceCharDeviceInstance *sin, int connected)
|
||||
{
|
||||
SpiceCharDriver *scd = container_of(sin, SpiceCharDriver, sin);
|
||||
SpiceChardev *scd = container_of(sin, SpiceChardev, sin);
|
||||
Chardev *chr = CHARDEV(scd);
|
||||
|
||||
if ((scd->chr->be_open && connected) ||
|
||||
(!scd->chr->be_open && !connected)) {
|
||||
if ((chr->be_open && connected) ||
|
||||
(!chr->be_open && !connected)) {
|
||||
return;
|
||||
}
|
||||
|
||||
qemu_chr_be_event(scd->chr,
|
||||
qemu_chr_be_event(chr,
|
||||
connected ? CHR_EVENT_OPENED : CHR_EVENT_CLOSED);
|
||||
}
|
||||
|
||||
@ -115,7 +126,7 @@ static SpiceCharDeviceInterface vmc_interface = {
|
||||
};
|
||||
|
||||
|
||||
static void vmc_register_interface(SpiceCharDriver *scd)
|
||||
static void vmc_register_interface(SpiceChardev *scd)
|
||||
{
|
||||
if (scd->active) {
|
||||
return;
|
||||
@ -126,7 +137,7 @@ static void vmc_register_interface(SpiceCharDriver *scd)
|
||||
trace_spice_vmc_register_interface(scd);
|
||||
}
|
||||
|
||||
static void vmc_unregister_interface(SpiceCharDriver *scd)
|
||||
static void vmc_unregister_interface(SpiceChardev *scd)
|
||||
{
|
||||
if (!scd->active) {
|
||||
return;
|
||||
@ -166,9 +177,9 @@ static GSourceFuncs SpiceCharSourceFuncs = {
|
||||
.dispatch = spice_char_source_dispatch,
|
||||
};
|
||||
|
||||
static GSource *spice_chr_add_watch(CharDriverState *chr, GIOCondition cond)
|
||||
static GSource *spice_chr_add_watch(Chardev *chr, GIOCondition cond)
|
||||
{
|
||||
SpiceCharDriver *scd = chr->opaque;
|
||||
SpiceChardev *scd = SPICE_CHARDEV(chr);
|
||||
SpiceCharSource *src;
|
||||
|
||||
assert(cond & G_IO_OUT);
|
||||
@ -180,9 +191,9 @@ static GSource *spice_chr_add_watch(CharDriverState *chr, GIOCondition cond)
|
||||
return (GSource *)src;
|
||||
}
|
||||
|
||||
static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
|
||||
static int spice_chr_write(Chardev *chr, const uint8_t *buf, int len)
|
||||
{
|
||||
SpiceCharDriver *s = chr->opaque;
|
||||
SpiceChardev *s = SPICE_CHARDEV(chr);
|
||||
int read_bytes;
|
||||
|
||||
assert(s->datalen == 0);
|
||||
@ -199,9 +210,9 @@ static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
|
||||
return read_bytes;
|
||||
}
|
||||
|
||||
static void spice_chr_free(struct CharDriverState *chr)
|
||||
static void spice_chr_free(struct Chardev *chr)
|
||||
{
|
||||
SpiceCharDriver *s = chr->opaque;
|
||||
SpiceChardev *s = SPICE_CHARDEV(chr);
|
||||
|
||||
vmc_unregister_interface(s);
|
||||
QLIST_REMOVE(s, next);
|
||||
@ -210,12 +221,11 @@ static void spice_chr_free(struct CharDriverState *chr)
|
||||
#if SPICE_SERVER_VERSION >= 0x000c02
|
||||
g_free((char *)s->sin.portname);
|
||||
#endif
|
||||
g_free(s);
|
||||
}
|
||||
|
||||
static void spice_vmc_set_fe_open(struct CharDriverState *chr, int fe_open)
|
||||
static void spice_vmc_set_fe_open(struct Chardev *chr, int fe_open)
|
||||
{
|
||||
SpiceCharDriver *s = chr->opaque;
|
||||
SpiceChardev *s = SPICE_CHARDEV(chr);
|
||||
if (fe_open) {
|
||||
vmc_register_interface(s);
|
||||
} else {
|
||||
@ -223,10 +233,10 @@ static void spice_vmc_set_fe_open(struct CharDriverState *chr, int fe_open)
|
||||
}
|
||||
}
|
||||
|
||||
static void spice_port_set_fe_open(struct CharDriverState *chr, int fe_open)
|
||||
static void spice_port_set_fe_open(struct Chardev *chr, int fe_open)
|
||||
{
|
||||
#if SPICE_SERVER_VERSION >= 0x000c02
|
||||
SpiceCharDriver *s = chr->opaque;
|
||||
SpiceChardev *s = SPICE_CHARDEV(chr);
|
||||
|
||||
if (fe_open) {
|
||||
spice_server_port_event(&s->sin, SPICE_PORT_EVENT_OPENED);
|
||||
@ -236,69 +246,31 @@ static void spice_port_set_fe_open(struct CharDriverState *chr, int fe_open)
|
||||
#endif
|
||||
}
|
||||
|
||||
static void print_allowed_subtypes(void)
|
||||
static void spice_chr_accept_input(struct Chardev *chr)
|
||||
{
|
||||
const char** psubtype;
|
||||
int i;
|
||||
|
||||
fprintf(stderr, "allowed names: ");
|
||||
for(i=0, psubtype = spice_server_char_device_recognized_subtypes();
|
||||
*psubtype != NULL; ++psubtype, ++i) {
|
||||
if (i == 0) {
|
||||
fprintf(stderr, "%s", *psubtype);
|
||||
} else {
|
||||
fprintf(stderr, ", %s", *psubtype);
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
static void spice_chr_accept_input(struct CharDriverState *chr)
|
||||
{
|
||||
SpiceCharDriver *s = chr->opaque;
|
||||
SpiceChardev *s = SPICE_CHARDEV(chr);
|
||||
|
||||
spice_server_char_device_wakeup(&s->sin);
|
||||
}
|
||||
|
||||
static CharDriverState *chr_open(const char *subtype,
|
||||
void (*set_fe_open)(struct CharDriverState *,
|
||||
int),
|
||||
ChardevCommon *backend,
|
||||
Error **errp)
|
||||
static void chr_open(Chardev *chr, const char *subtype)
|
||||
{
|
||||
CharDriverState *chr;
|
||||
SpiceCharDriver *s;
|
||||
SpiceChardev *s = SPICE_CHARDEV(chr);
|
||||
|
||||
chr = qemu_chr_alloc(backend, errp);
|
||||
if (!chr) {
|
||||
return NULL;
|
||||
}
|
||||
s = g_malloc0(sizeof(SpiceCharDriver));
|
||||
s->chr = chr;
|
||||
s->active = false;
|
||||
s->sin.subtype = g_strdup(subtype);
|
||||
chr->opaque = s;
|
||||
chr->chr_write = spice_chr_write;
|
||||
chr->chr_add_watch = spice_chr_add_watch;
|
||||
chr->chr_free = spice_chr_free;
|
||||
chr->chr_set_fe_open = set_fe_open;
|
||||
chr->chr_accept_input = spice_chr_accept_input;
|
||||
|
||||
QLIST_INSERT_HEAD(&spice_chars, s, next);
|
||||
|
||||
return chr;
|
||||
}
|
||||
|
||||
static CharDriverState *qemu_chr_open_spice_vmc(const char *id,
|
||||
ChardevBackend *backend,
|
||||
ChardevReturn *ret,
|
||||
bool *be_opened,
|
||||
Error **errp)
|
||||
static void qemu_chr_open_spice_vmc(Chardev *chr,
|
||||
ChardevBackend *backend,
|
||||
bool *be_opened,
|
||||
Error **errp)
|
||||
{
|
||||
ChardevSpiceChannel *spicevmc = backend->u.spicevmc.data;
|
||||
const char *type = spicevmc->type;
|
||||
const char **psubtype = spice_server_char_device_recognized_subtypes();
|
||||
ChardevCommon *common = qapi_ChardevSpiceChannel_base(spicevmc);
|
||||
|
||||
for (; *psubtype != NULL; ++psubtype) {
|
||||
if (strcmp(type, *psubtype) == 0) {
|
||||
@ -306,47 +278,46 @@ static CharDriverState *qemu_chr_open_spice_vmc(const char *id,
|
||||
}
|
||||
}
|
||||
if (*psubtype == NULL) {
|
||||
fprintf(stderr, "spice-qemu-char: unsupported type: %s\n", type);
|
||||
print_allowed_subtypes();
|
||||
return NULL;
|
||||
char *subtypes = g_strjoinv(", ",
|
||||
(gchar **)spice_server_char_device_recognized_subtypes());
|
||||
|
||||
error_setg(errp, "unsupported type name: %s", type);
|
||||
error_append_hint(errp, "allowed spice char type names: %s\n",
|
||||
subtypes);
|
||||
|
||||
g_free(subtypes);
|
||||
return;
|
||||
}
|
||||
|
||||
*be_opened = false;
|
||||
return chr_open(type, spice_vmc_set_fe_open, common, errp);
|
||||
chr_open(chr, type);
|
||||
}
|
||||
|
||||
#if SPICE_SERVER_VERSION >= 0x000c02
|
||||
static CharDriverState *qemu_chr_open_spice_port(const char *id,
|
||||
ChardevBackend *backend,
|
||||
ChardevReturn *ret,
|
||||
bool *be_opened,
|
||||
Error **errp)
|
||||
static void qemu_chr_open_spice_port(Chardev *chr,
|
||||
ChardevBackend *backend,
|
||||
bool *be_opened,
|
||||
Error **errp)
|
||||
{
|
||||
ChardevSpicePort *spiceport = backend->u.spiceport.data;
|
||||
const char *name = spiceport->fqdn;
|
||||
ChardevCommon *common = qapi_ChardevSpicePort_base(spiceport);
|
||||
CharDriverState *chr;
|
||||
SpiceCharDriver *s;
|
||||
SpiceChardev *s;
|
||||
|
||||
if (name == NULL) {
|
||||
fprintf(stderr, "spice-qemu-char: missing name parameter\n");
|
||||
return NULL;
|
||||
error_setg(errp, "missing name parameter");
|
||||
return;
|
||||
}
|
||||
|
||||
chr = chr_open("port", spice_port_set_fe_open, common, errp);
|
||||
if (!chr) {
|
||||
return NULL;
|
||||
}
|
||||
chr_open(chr, "port");
|
||||
|
||||
*be_opened = false;
|
||||
s = chr->opaque;
|
||||
s = SPICE_CHARDEV(chr);
|
||||
s->sin.portname = g_strdup(name);
|
||||
|
||||
return chr;
|
||||
}
|
||||
|
||||
void qemu_spice_register_ports(void)
|
||||
{
|
||||
SpiceCharDriver *s;
|
||||
SpiceChardev *s;
|
||||
|
||||
QLIST_FOREACH(s, &spice_chars, next) {
|
||||
if (s->sin.portname == NULL) {
|
||||
@ -387,12 +358,68 @@ static void qemu_chr_parse_spice_port(QemuOpts *opts, ChardevBackend *backend,
|
||||
spiceport->fqdn = g_strdup(name);
|
||||
}
|
||||
|
||||
static void char_spice_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
ChardevClass *cc = CHARDEV_CLASS(oc);
|
||||
|
||||
cc->chr_write = spice_chr_write;
|
||||
cc->chr_add_watch = spice_chr_add_watch;
|
||||
cc->chr_accept_input = spice_chr_accept_input;
|
||||
cc->chr_free = spice_chr_free;
|
||||
}
|
||||
|
||||
static const TypeInfo char_spice_type_info = {
|
||||
.name = TYPE_CHARDEV_SPICE,
|
||||
.parent = TYPE_CHARDEV,
|
||||
.instance_size = sizeof(SpiceChardev),
|
||||
.class_init = char_spice_class_init,
|
||||
.abstract = true,
|
||||
};
|
||||
|
||||
static void char_spicevmc_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
ChardevClass *cc = CHARDEV_CLASS(oc);
|
||||
|
||||
cc->open = qemu_chr_open_spice_vmc;
|
||||
cc->chr_set_fe_open = spice_vmc_set_fe_open;
|
||||
}
|
||||
|
||||
static const TypeInfo char_spicevmc_type_info = {
|
||||
.name = TYPE_CHARDEV_SPICEVMC,
|
||||
.parent = TYPE_CHARDEV_SPICE,
|
||||
.class_init = char_spicevmc_class_init,
|
||||
};
|
||||
|
||||
static void char_spiceport_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
ChardevClass *cc = CHARDEV_CLASS(oc);
|
||||
|
||||
cc->open = qemu_chr_open_spice_port;
|
||||
cc->chr_set_fe_open = spice_port_set_fe_open;
|
||||
}
|
||||
|
||||
static const TypeInfo char_spiceport_type_info = {
|
||||
.name = TYPE_CHARDEV_SPICEPORT,
|
||||
.parent = TYPE_CHARDEV_SPICE,
|
||||
.class_init = char_spiceport_class_init,
|
||||
};
|
||||
|
||||
static void register_types(void)
|
||||
{
|
||||
register_char_driver("spicevmc", CHARDEV_BACKEND_KIND_SPICEVMC,
|
||||
qemu_chr_parse_spice_vmc, qemu_chr_open_spice_vmc);
|
||||
register_char_driver("spiceport", CHARDEV_BACKEND_KIND_SPICEPORT,
|
||||
qemu_chr_parse_spice_port, qemu_chr_open_spice_port);
|
||||
static const CharDriver vmc_driver = {
|
||||
.kind = CHARDEV_BACKEND_KIND_SPICEVMC,
|
||||
.parse = qemu_chr_parse_spice_vmc,
|
||||
};
|
||||
static const CharDriver port_driver = {
|
||||
.kind = CHARDEV_BACKEND_KIND_SPICEPORT,
|
||||
.parse = qemu_chr_parse_spice_port,
|
||||
};
|
||||
register_char_driver(&vmc_driver);
|
||||
register_char_driver(&port_driver);
|
||||
|
||||
type_register_static(&char_spice_type_info);
|
||||
type_register_static(&char_spicevmc_type_info);
|
||||
type_register_static(&char_spiceport_type_info);
|
||||
}
|
||||
|
||||
type_init(register_types);
|
||||
|
@ -11,6 +11,6 @@ int monitor_get_fd(Monitor *mon, const char *name, Error **errp)
|
||||
return -1;
|
||||
}
|
||||
|
||||
void monitor_init(CharDriverState *chr, int flags)
|
||||
void monitor_init(Chardev *chr, int flags)
|
||||
{
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user