* 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:
Peter Maydell 2017-01-30 10:23:20 +00:00
commit a0def59428
114 changed files with 2204 additions and 1460 deletions

View file

@ -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>

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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

View file

@ -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
View 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);

View file

@ -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);

View file

@ -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';

View file

@ -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
View file

@ -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;

View file

@ -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

View file

@ -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,
},

View file

@ -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];

View file

@ -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];

View file

@ -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];

View file

@ -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]);

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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",

View file

@ -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;

View file

@ -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,

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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,

View file

@ -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;

View file

@ -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 "

View file

@ -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),

View file

@ -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,
};

View file

@ -85,7 +85,7 @@ struct MilkymistTMU2State {
SysBusDevice parent_obj;
MemoryRegion regs_region;
CharDriverState *chr;
Chardev *chr;
qemu_irq irq;
uint32_t regs[R_MAX];

View file

@ -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;

View file

@ -413,6 +413,12 @@ static void patch_instruction(VAPICROMState *s, X86CPU *cpu, target_ulong ip)
if (!kvm_enabled()) {
cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
&current_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();

View file

@ -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
}
};

View file

@ -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;

View file

@ -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(),
};

View file

@ -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;

View file

@ -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;

View file

@ -6,7 +6,7 @@
static inline DeviceState *milkymist_uart_create(hwaddr base,
qemu_irq irq,
CharDriverState *chr)
Chardev *chr)
{
DeviceState *dev;

View file

@ -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));

View file

@ -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",

View file

@ -125,7 +125,7 @@ struct MilkymistPFPUState {
SysBusDevice parent_obj;
MemoryRegion regs_region;
CharDriverState *chr;
Chardev *chr;
qemu_irq irq;
uint32_t regs[R_MAX];

View file

@ -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++) {

View file

@ -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

View file

@ -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);

View file

@ -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)

View file

@ -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);

View file

@ -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

View file

@ -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

View file

@ -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 */

View file

@ -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);

View file

@ -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;

View file

@ -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;

View file

@ -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,

View file

@ -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;

View file

@ -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"

View file

@ -17,7 +17,7 @@
static inline DeviceState *xilinx_uartlite_create(hwaddr addr,
qemu_irq irq,
CharDriverState *chr)
Chardev *chr)
{
DeviceState *dev;
SysBusDevice *s;

View file

@ -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;

View file

@ -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

View file

@ -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 {

View file

@ -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 */

View file

@ -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 \

View file

@ -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,

View file

@ -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);

View file

@ -26,6 +26,7 @@ typedef enum DeviceCategory {
DEVICE_CATEGORY_DISPLAY,
DEVICE_CATEGORY_SOUND,
DEVICE_CATEGORY_MISC,
DEVICE_CATEGORY_CPU,
DEVICE_CATEGORY_MAX
} DeviceCategory;

View file

@ -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);

View file

@ -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,

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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);

View file

@ -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,

View file

@ -64,7 +64,7 @@ typedef struct VirtualVteConsole {
GtkWidget *box;
GtkWidget *scrollbar;
GtkWidget *terminal;
CharDriverState *chr;
Chardev *chr;
bool echo;
} VirtualVteConsole;
#endif

View file

@ -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

View file

@ -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) {

View file

@ -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)

View file

@ -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;

View file

@ -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;

View file

@ -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 "

View file

@ -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);

View file

@ -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;

View file

@ -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;

File diff suppressed because it is too large Load diff

View file

@ -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
View file

@ -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);

View file

@ -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;
/*

View file

@ -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);

View file

@ -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));

View file

@ -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);
}
}
}
}

View file

@ -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();
}

View file

@ -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);

View file

@ -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