* KVM run_on_cpu fix (Alex)
* atomic usage fixes (Emilio, me) * hugetlbfs alignment fix (Haozhong) * CharBackend refactoring (Marc-André) * test-i386 fixes (me) * MemoryListener optimizations (me) * Miscellaneous bugfixes (me) * iSER support (Roy) * --version formatting (Thomas) -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQEcBAABAgAGBQJYDhCrAAoJEL/70l94x66DBbMH/iM6Z8Kp9tXImqdnVBLCIFW9 MhxeiaEJ5erILHpOajK8kHTg9Uuqj2Z3sY7n04IU0uvRhvOtwKd28m8AoC2El1j6 JAHLk2IAfoepfYPVl0s9quQJhxQXlGjMojdbVP4GD3GzIN27x9IrWUSv14gcjf11 sJr049KXoIphckXBq9JOCEXRSz9Bn9nAc4KzUAbLpH7p8P02Tiox5eW8W6Bn7E3F z1J+3XdFl29afjDFvtVLwU5lPM8KR6XC6qyZmD4PO7dzdYMmXxSSL0E/d746x9sp 4fVmLpoPSSMvmssMz45WZLiMNJQp0HB44rsYVaTjWdn1xprS8cj8JDfvNUQxwr0= =/2n2 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging * KVM run_on_cpu fix (Alex) * atomic usage fixes (Emilio, me) * hugetlbfs alignment fix (Haozhong) * CharBackend refactoring (Marc-André) * test-i386 fixes (me) * MemoryListener optimizations (me) * Miscellaneous bugfixes (me) * iSER support (Roy) * --version formatting (Thomas) # gpg: Signature made Mon 24 Oct 2016 14:46:19 BST # 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: (50 commits) exec.c: workaround regression caused by alignment change in d2f39ad char: remove explicit_be_open from CharDriverState char: use common error path in qmp_chardev_add char: replace avail_connections char: remove unused qemu_chr_fe_event char: use an enum for CHR_EVENT char: remove unused CHR_EVENT_FOCUS char: move fe_open in CharBackend char: remove explicit_fe_open, use a set_handlers argument char: rename chr_close/chr_free char: move front end handlers in CharBackend tests: start chardev unit tests char: make some qemu_chr_fe skip if no driver char: replace qemu_chr_claim/release with qemu_chr_fe_init/deinit vhost-user: only initialize queue 0 CharBackend char: fold qemu_chr_set_handlers in qemu_chr_fe_set_handlers char: use qemu_chr_fe* functions with CharBackend argument colo: claim in find_and_check_chardev char: rename some frontend functions char: remaining switch to CharBackend in frontend ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
		
						commit
						a3ae21ec3f
					
				@ -551,7 +551,7 @@ static void baum_chr_read(void *opaque)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void baum_close(struct CharDriverState *chr)
 | 
					static void baum_free(struct CharDriverState *chr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    BaumDriverState *baum = chr->opaque;
 | 
					    BaumDriverState *baum = chr->opaque;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -566,6 +566,7 @@ static void baum_close(struct CharDriverState *chr)
 | 
				
			|||||||
static CharDriverState *chr_baum_init(const char *id,
 | 
					static CharDriverState *chr_baum_init(const char *id,
 | 
				
			||||||
                                      ChardevBackend *backend,
 | 
					                                      ChardevBackend *backend,
 | 
				
			||||||
                                      ChardevReturn *ret,
 | 
					                                      ChardevReturn *ret,
 | 
				
			||||||
 | 
					                                      bool *be_opened,
 | 
				
			||||||
                                      Error **errp)
 | 
					                                      Error **errp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    ChardevCommon *common = backend->u.braille.data;
 | 
					    ChardevCommon *common = backend->u.braille.data;
 | 
				
			||||||
@ -589,7 +590,7 @@ static CharDriverState *chr_baum_init(const char *id,
 | 
				
			|||||||
    chr->opaque = baum;
 | 
					    chr->opaque = baum;
 | 
				
			||||||
    chr->chr_write = baum_write;
 | 
					    chr->chr_write = baum_write;
 | 
				
			||||||
    chr->chr_accept_input = baum_accept_input;
 | 
					    chr->chr_accept_input = baum_accept_input;
 | 
				
			||||||
    chr->chr_close = baum_close;
 | 
					    chr->chr_free = baum_free;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    handle = g_malloc0(brlapi_getHandleSize());
 | 
					    handle = g_malloc0(brlapi_getHandleSize());
 | 
				
			||||||
    baum->brlapi = handle;
 | 
					    baum->brlapi = handle;
 | 
				
			||||||
 | 
				
			|||||||
@ -133,7 +133,7 @@ static int msmouse_chr_write (struct CharDriverState *s, const uint8_t *buf, int
 | 
				
			|||||||
    return len;
 | 
					    return len;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void msmouse_chr_close (struct CharDriverState *chr)
 | 
					static void msmouse_chr_free(struct CharDriverState *chr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    MouseState *mouse = chr->opaque;
 | 
					    MouseState *mouse = chr->opaque;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -151,6 +151,7 @@ static QemuInputHandler msmouse_handler = {
 | 
				
			|||||||
static CharDriverState *qemu_chr_open_msmouse(const char *id,
 | 
					static CharDriverState *qemu_chr_open_msmouse(const char *id,
 | 
				
			||||||
                                              ChardevBackend *backend,
 | 
					                                              ChardevBackend *backend,
 | 
				
			||||||
                                              ChardevReturn *ret,
 | 
					                                              ChardevReturn *ret,
 | 
				
			||||||
 | 
					                                              bool *be_opened,
 | 
				
			||||||
                                              Error **errp)
 | 
					                                              Error **errp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    ChardevCommon *common = backend->u.msmouse.data;
 | 
					    ChardevCommon *common = backend->u.msmouse.data;
 | 
				
			||||||
@ -162,9 +163,9 @@ static CharDriverState *qemu_chr_open_msmouse(const char *id,
 | 
				
			|||||||
        return NULL;
 | 
					        return NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    chr->chr_write = msmouse_chr_write;
 | 
					    chr->chr_write = msmouse_chr_write;
 | 
				
			||||||
    chr->chr_close = msmouse_chr_close;
 | 
					    chr->chr_free = msmouse_chr_free;
 | 
				
			||||||
    chr->chr_accept_input = msmouse_chr_accept_input;
 | 
					    chr->chr_accept_input = msmouse_chr_accept_input;
 | 
				
			||||||
    chr->explicit_be_open = true;
 | 
					    *be_opened = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    mouse = g_new0(MouseState, 1);
 | 
					    mouse = g_new0(MouseState, 1);
 | 
				
			||||||
    mouse->hs = qemu_input_handler_register((DeviceState *)mouse,
 | 
					    mouse->hs = qemu_input_handler_register((DeviceState *)mouse,
 | 
				
			||||||
 | 
				
			|||||||
@ -15,7 +15,6 @@
 | 
				
			|||||||
#include "sysemu/char.h"
 | 
					#include "sysemu/char.h"
 | 
				
			||||||
#include "qapi/error.h"
 | 
					#include "qapi/error.h"
 | 
				
			||||||
#include "qapi/qmp/qerror.h"
 | 
					#include "qapi/qmp/qerror.h"
 | 
				
			||||||
#include "hw/qdev.h" /* just for DEFINE_PROP_CHR */
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define TYPE_RNG_EGD "rng-egd"
 | 
					#define TYPE_RNG_EGD "rng-egd"
 | 
				
			||||||
#define RNG_EGD(obj) OBJECT_CHECK(RngEgd, (obj), TYPE_RNG_EGD)
 | 
					#define RNG_EGD(obj) OBJECT_CHECK(RngEgd, (obj), TYPE_RNG_EGD)
 | 
				
			||||||
@ -24,7 +23,7 @@ typedef struct RngEgd
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    RngBackend parent;
 | 
					    RngBackend parent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    CharDriverState *chr;
 | 
					    CharBackend chr;
 | 
				
			||||||
    char *chr_name;
 | 
					    char *chr_name;
 | 
				
			||||||
} RngEgd;
 | 
					} RngEgd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -43,7 +42,7 @@ static void rng_egd_request_entropy(RngBackend *b, RngRequest *req)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        /* XXX this blocks entire thread. Rewrite to use
 | 
					        /* XXX this blocks entire thread. Rewrite to use
 | 
				
			||||||
         * qemu_chr_fe_write and background I/O callbacks */
 | 
					         * qemu_chr_fe_write and background I/O callbacks */
 | 
				
			||||||
        qemu_chr_fe_write_all(s->chr, header, sizeof(header));
 | 
					        qemu_chr_fe_write_all(&s->chr, header, sizeof(header));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        size -= len;
 | 
					        size -= len;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -87,6 +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)
 | 
					static void rng_egd_opened(RngBackend *b, Error **errp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    RngEgd *s = RNG_EGD(b);
 | 
					    RngEgd *s = RNG_EGD(b);
 | 
				
			||||||
 | 
					    CharDriverState *chr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (s->chr_name == NULL) {
 | 
					    if (s->chr_name == NULL) {
 | 
				
			||||||
        error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
 | 
					        error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
 | 
				
			||||||
@ -94,21 +94,19 @@ static void rng_egd_opened(RngBackend *b, Error **errp)
 | 
				
			|||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->chr = qemu_chr_find(s->chr_name);
 | 
					    chr = qemu_chr_find(s->chr_name);
 | 
				
			||||||
    if (s->chr == NULL) {
 | 
					    if (chr == NULL) {
 | 
				
			||||||
        error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
 | 
					        error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
 | 
				
			||||||
                  "Device '%s' not found", s->chr_name);
 | 
					                  "Device '%s' not found", s->chr_name);
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    if (!qemu_chr_fe_init(&s->chr, chr, errp)) {
 | 
				
			||||||
    if (qemu_chr_fe_claim(s->chr) != 0) {
 | 
					 | 
				
			||||||
        error_setg(errp, QERR_DEVICE_IN_USE, s->chr_name);
 | 
					 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* FIXME we should resubmit pending requests when the CDS reconnects. */
 | 
					    /* FIXME we should resubmit pending requests when the CDS reconnects. */
 | 
				
			||||||
    qemu_chr_add_handlers(s->chr, rng_egd_chr_can_read, rng_egd_chr_read,
 | 
					    qemu_chr_fe_set_handlers(&s->chr, rng_egd_chr_can_read,
 | 
				
			||||||
                          NULL, s);
 | 
					                             rng_egd_chr_read, NULL, s, NULL, true);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void rng_egd_set_chardev(Object *obj, const char *value, Error **errp)
 | 
					static void rng_egd_set_chardev(Object *obj, const char *value, Error **errp)
 | 
				
			||||||
@ -127,9 +125,10 @@ static void rng_egd_set_chardev(Object *obj, const char *value, Error **errp)
 | 
				
			|||||||
static char *rng_egd_get_chardev(Object *obj, Error **errp)
 | 
					static char *rng_egd_get_chardev(Object *obj, Error **errp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    RngEgd *s = RNG_EGD(obj);
 | 
					    RngEgd *s = RNG_EGD(obj);
 | 
				
			||||||
 | 
					    CharDriverState *chr = qemu_chr_fe_get_driver(&s->chr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (s->chr && s->chr->label) {
 | 
					    if (chr && chr->label) {
 | 
				
			||||||
        return g_strdup(s->chr->label);
 | 
					        return g_strdup(chr->label);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return NULL;
 | 
					    return NULL;
 | 
				
			||||||
@ -146,11 +145,7 @@ static void rng_egd_finalize(Object *obj)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    RngEgd *s = RNG_EGD(obj);
 | 
					    RngEgd *s = RNG_EGD(obj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (s->chr) {
 | 
					    qemu_chr_fe_deinit(&s->chr);
 | 
				
			||||||
        qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, NULL);
 | 
					 | 
				
			||||||
        qemu_chr_fe_release(s->chr);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    g_free(s->chr_name);
 | 
					    g_free(s->chr_name);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -102,7 +102,7 @@ static int testdev_write(CharDriverState *chr, const uint8_t *buf, int len)
 | 
				
			|||||||
    return orig_len;
 | 
					    return orig_len;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void testdev_close(struct CharDriverState *chr)
 | 
					static void testdev_free(struct CharDriverState *chr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    TestdevCharState *testdev = chr->opaque;
 | 
					    TestdevCharState *testdev = chr->opaque;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -112,6 +112,7 @@ static void testdev_close(struct CharDriverState *chr)
 | 
				
			|||||||
static CharDriverState *chr_testdev_init(const char *id,
 | 
					static CharDriverState *chr_testdev_init(const char *id,
 | 
				
			||||||
                                         ChardevBackend *backend,
 | 
					                                         ChardevBackend *backend,
 | 
				
			||||||
                                         ChardevReturn *ret,
 | 
					                                         ChardevReturn *ret,
 | 
				
			||||||
 | 
					                                         bool *be_opened,
 | 
				
			||||||
                                         Error **errp)
 | 
					                                         Error **errp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    TestdevCharState *testdev;
 | 
					    TestdevCharState *testdev;
 | 
				
			||||||
@ -122,7 +123,7 @@ static CharDriverState *chr_testdev_init(const char *id,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    chr->opaque = testdev;
 | 
					    chr->opaque = testdev;
 | 
				
			||||||
    chr->chr_write = testdev_write;
 | 
					    chr->chr_write = testdev_write;
 | 
				
			||||||
    chr->chr_close = testdev_close;
 | 
					    chr->chr_free = testdev_free;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return chr;
 | 
					    return chr;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -202,6 +202,10 @@ static inline unsigned exp_random(double mean)
 | 
				
			|||||||
#define SCSI_SENSE_ASCQ_PARAMETER_LIST_LENGTH_ERROR        0x1a00
 | 
					#define SCSI_SENSE_ASCQ_PARAMETER_LIST_LENGTH_ERROR        0x1a00
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef LIBISCSI_API_VERSION
 | 
				
			||||||
 | 
					#define LIBISCSI_API_VERSION 20130701
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int iscsi_translate_sense(struct scsi_sense *sense)
 | 
					static int iscsi_translate_sense(struct scsi_sense *sense)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int ret;
 | 
					    int ret;
 | 
				
			||||||
@ -592,6 +596,20 @@ iscsi_co_writev_flags(BlockDriverState *bs, int64_t sector_num, int nb_sectors,
 | 
				
			|||||||
    iscsi_co_init_iscsitask(iscsilun, &iTask);
 | 
					    iscsi_co_init_iscsitask(iscsilun, &iTask);
 | 
				
			||||||
retry:
 | 
					retry:
 | 
				
			||||||
    if (iscsilun->use_16_for_rw) {
 | 
					    if (iscsilun->use_16_for_rw) {
 | 
				
			||||||
 | 
					#if LIBISCSI_API_VERSION >= (20160603)
 | 
				
			||||||
 | 
					        iTask.task = iscsi_write16_iov_task(iscsilun->iscsi, iscsilun->lun, lba,
 | 
				
			||||||
 | 
					                                            NULL, num_sectors * iscsilun->block_size,
 | 
				
			||||||
 | 
					                                            iscsilun->block_size, 0, 0, fua, 0, 0,
 | 
				
			||||||
 | 
					                                            iscsi_co_generic_cb, &iTask,
 | 
				
			||||||
 | 
					                                            (struct scsi_iovec *)iov->iov, iov->niov);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        iTask.task = iscsi_write10_iov_task(iscsilun->iscsi, iscsilun->lun, lba,
 | 
				
			||||||
 | 
					                                            NULL, num_sectors * iscsilun->block_size,
 | 
				
			||||||
 | 
					                                            iscsilun->block_size, 0, 0, fua, 0, 0,
 | 
				
			||||||
 | 
					                                            iscsi_co_generic_cb, &iTask,
 | 
				
			||||||
 | 
					                                            (struct scsi_iovec *)iov->iov, iov->niov);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
        iTask.task = iscsi_write16_task(iscsilun->iscsi, iscsilun->lun, lba,
 | 
					        iTask.task = iscsi_write16_task(iscsilun->iscsi, iscsilun->lun, lba,
 | 
				
			||||||
                                        NULL, num_sectors * iscsilun->block_size,
 | 
					                                        NULL, num_sectors * iscsilun->block_size,
 | 
				
			||||||
                                        iscsilun->block_size, 0, 0, fua, 0, 0,
 | 
					                                        iscsilun->block_size, 0, 0, fua, 0, 0,
 | 
				
			||||||
@ -602,11 +620,14 @@ retry:
 | 
				
			|||||||
                                        iscsilun->block_size, 0, 0, fua, 0, 0,
 | 
					                                        iscsilun->block_size, 0, 0, fua, 0, 0,
 | 
				
			||||||
                                        iscsi_co_generic_cb, &iTask);
 | 
					                                        iscsi_co_generic_cb, &iTask);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
    if (iTask.task == NULL) {
 | 
					    if (iTask.task == NULL) {
 | 
				
			||||||
        return -ENOMEM;
 | 
					        return -ENOMEM;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					#if LIBISCSI_API_VERSION < (20160603)
 | 
				
			||||||
    scsi_task_set_iov_out(iTask.task, (struct scsi_iovec *) iov->iov,
 | 
					    scsi_task_set_iov_out(iTask.task, (struct scsi_iovec *) iov->iov,
 | 
				
			||||||
                          iov->niov);
 | 
					                          iov->niov);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
    while (!iTask.complete) {
 | 
					    while (!iTask.complete) {
 | 
				
			||||||
        iscsi_set_events(iscsilun);
 | 
					        iscsi_set_events(iscsilun);
 | 
				
			||||||
        qemu_coroutine_yield();
 | 
					        qemu_coroutine_yield();
 | 
				
			||||||
@ -789,6 +810,21 @@ static int coroutine_fn iscsi_co_readv(BlockDriverState *bs,
 | 
				
			|||||||
    iscsi_co_init_iscsitask(iscsilun, &iTask);
 | 
					    iscsi_co_init_iscsitask(iscsilun, &iTask);
 | 
				
			||||||
retry:
 | 
					retry:
 | 
				
			||||||
    if (iscsilun->use_16_for_rw) {
 | 
					    if (iscsilun->use_16_for_rw) {
 | 
				
			||||||
 | 
					#if LIBISCSI_API_VERSION >= (20160603)
 | 
				
			||||||
 | 
					        iTask.task = iscsi_read16_iov_task(iscsilun->iscsi, iscsilun->lun, lba,
 | 
				
			||||||
 | 
					                                           num_sectors * iscsilun->block_size,
 | 
				
			||||||
 | 
					                                           iscsilun->block_size, 0, 0, 0, 0, 0,
 | 
				
			||||||
 | 
					                                           iscsi_co_generic_cb, &iTask,
 | 
				
			||||||
 | 
					                                           (struct scsi_iovec *)iov->iov, iov->niov);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        iTask.task = iscsi_read10_iov_task(iscsilun->iscsi, iscsilun->lun, lba,
 | 
				
			||||||
 | 
					                                           num_sectors * iscsilun->block_size,
 | 
				
			||||||
 | 
					                                           iscsilun->block_size,
 | 
				
			||||||
 | 
					                                           0, 0, 0, 0, 0,
 | 
				
			||||||
 | 
					                                           iscsi_co_generic_cb, &iTask,
 | 
				
			||||||
 | 
					                                           (struct scsi_iovec *)iov->iov, iov->niov);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
        iTask.task = iscsi_read16_task(iscsilun->iscsi, iscsilun->lun, lba,
 | 
					        iTask.task = iscsi_read16_task(iscsilun->iscsi, iscsilun->lun, lba,
 | 
				
			||||||
                                       num_sectors * iscsilun->block_size,
 | 
					                                       num_sectors * iscsilun->block_size,
 | 
				
			||||||
                                       iscsilun->block_size, 0, 0, 0, 0, 0,
 | 
					                                       iscsilun->block_size, 0, 0, 0, 0, 0,
 | 
				
			||||||
@ -800,11 +836,13 @@ retry:
 | 
				
			|||||||
                                       0, 0, 0, 0, 0,
 | 
					                                       0, 0, 0, 0, 0,
 | 
				
			||||||
                                       iscsi_co_generic_cb, &iTask);
 | 
					                                       iscsi_co_generic_cb, &iTask);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
    if (iTask.task == NULL) {
 | 
					    if (iTask.task == NULL) {
 | 
				
			||||||
        return -ENOMEM;
 | 
					        return -ENOMEM;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					#if LIBISCSI_API_VERSION < (20160603)
 | 
				
			||||||
    scsi_task_set_iov_in(iTask.task, (struct scsi_iovec *) iov->iov, iov->niov);
 | 
					    scsi_task_set_iov_in(iTask.task, (struct scsi_iovec *) iov->iov, iov->niov);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
    while (!iTask.complete) {
 | 
					    while (!iTask.complete) {
 | 
				
			||||||
        iscsi_set_events(iscsilun);
 | 
					        iscsi_set_events(iscsilun);
 | 
				
			||||||
        qemu_coroutine_yield();
 | 
					        qemu_coroutine_yield();
 | 
				
			||||||
@ -1606,7 +1644,13 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
 | 
				
			|||||||
        ret = -ENOMEM;
 | 
					        ret = -ENOMEM;
 | 
				
			||||||
        goto out;
 | 
					        goto out;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					#if LIBISCSI_API_VERSION >= (20160603)
 | 
				
			||||||
 | 
					    if (iscsi_init_transport(iscsi, iscsi_url->transport)) {
 | 
				
			||||||
 | 
					        error_setg(errp, ("Error initializing transport."));
 | 
				
			||||||
 | 
					        ret = -EINVAL;
 | 
				
			||||||
 | 
					        goto out;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
    if (iscsi_set_targetname(iscsi, iscsi_url->target)) {
 | 
					    if (iscsi_set_targetname(iscsi, iscsi_url->target)) {
 | 
				
			||||||
        error_setg(errp, "iSCSI: Failed to set target name.");
 | 
					        error_setg(errp, "iSCSI: Failed to set target name.");
 | 
				
			||||||
        ret = -EINVAL;
 | 
					        ret = -EINVAL;
 | 
				
			||||||
@ -1649,7 +1693,7 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /* timeout handling is broken in libiscsi before 1.15.0 */
 | 
					    /* timeout handling is broken in libiscsi before 1.15.0 */
 | 
				
			||||||
    timeout = parse_timeout(iscsi_url->target);
 | 
					    timeout = parse_timeout(iscsi_url->target);
 | 
				
			||||||
#if defined(LIBISCSI_API_VERSION) && LIBISCSI_API_VERSION >= 20150621
 | 
					#if LIBISCSI_API_VERSION >= 20150621
 | 
				
			||||||
    iscsi_set_timeout(iscsi, timeout);
 | 
					    iscsi_set_timeout(iscsi, timeout);
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
    if (timeout) {
 | 
					    if (timeout) {
 | 
				
			||||||
@ -2010,9 +2054,48 @@ static BlockDriver bdrv_iscsi = {
 | 
				
			|||||||
    .bdrv_attach_aio_context = iscsi_attach_aio_context,
 | 
					    .bdrv_attach_aio_context = iscsi_attach_aio_context,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if LIBISCSI_API_VERSION >= (20160603)
 | 
				
			||||||
 | 
					static BlockDriver bdrv_iser = {
 | 
				
			||||||
 | 
					    .format_name     = "iser",
 | 
				
			||||||
 | 
					    .protocol_name   = "iser",
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .instance_size   = sizeof(IscsiLun),
 | 
				
			||||||
 | 
					    .bdrv_needs_filename = true,
 | 
				
			||||||
 | 
					    .bdrv_file_open  = iscsi_open,
 | 
				
			||||||
 | 
					    .bdrv_close      = iscsi_close,
 | 
				
			||||||
 | 
					    .bdrv_create     = iscsi_create,
 | 
				
			||||||
 | 
					    .create_opts     = &iscsi_create_opts,
 | 
				
			||||||
 | 
					    .bdrv_reopen_prepare   = iscsi_reopen_prepare,
 | 
				
			||||||
 | 
					    .bdrv_reopen_commit    = iscsi_reopen_commit,
 | 
				
			||||||
 | 
					    .bdrv_invalidate_cache = iscsi_invalidate_cache,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .bdrv_getlength  = iscsi_getlength,
 | 
				
			||||||
 | 
					    .bdrv_get_info   = iscsi_get_info,
 | 
				
			||||||
 | 
					    .bdrv_truncate   = iscsi_truncate,
 | 
				
			||||||
 | 
					    .bdrv_refresh_limits = iscsi_refresh_limits,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .bdrv_co_get_block_status = iscsi_co_get_block_status,
 | 
				
			||||||
 | 
					    .bdrv_co_pdiscard      = iscsi_co_pdiscard,
 | 
				
			||||||
 | 
					    .bdrv_co_pwrite_zeroes = iscsi_co_pwrite_zeroes,
 | 
				
			||||||
 | 
					    .bdrv_co_readv         = iscsi_co_readv,
 | 
				
			||||||
 | 
					    .bdrv_co_writev_flags  = iscsi_co_writev_flags,
 | 
				
			||||||
 | 
					    .bdrv_co_flush_to_disk = iscsi_co_flush,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef __linux__
 | 
				
			||||||
 | 
					    .bdrv_aio_ioctl   = iscsi_aio_ioctl,
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .bdrv_detach_aio_context = iscsi_detach_aio_context,
 | 
				
			||||||
 | 
					    .bdrv_attach_aio_context = iscsi_attach_aio_context,
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void iscsi_block_init(void)
 | 
					static void iscsi_block_init(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    bdrv_register(&bdrv_iscsi);
 | 
					    bdrv_register(&bdrv_iscsi);
 | 
				
			||||||
 | 
					#if LIBISCSI_API_VERSION >= (20160603)
 | 
				
			||||||
 | 
					    bdrv_register(&bdrv_iser);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
block_init(iscsi_block_init);
 | 
					block_init(iscsi_block_init);
 | 
				
			||||||
 | 
				
			|||||||
@ -733,7 +733,7 @@ static BlockAIOCB *qemu_rbd_aio_readv(BlockDriverState *bs,
 | 
				
			|||||||
                                      void *opaque)
 | 
					                                      void *opaque)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return rbd_start_aio(bs, sector_num << BDRV_SECTOR_BITS, qiov,
 | 
					    return rbd_start_aio(bs, sector_num << BDRV_SECTOR_BITS, qiov,
 | 
				
			||||||
                         nb_sectors << BDRV_SECTOR_BITS, cb, opaque,
 | 
					                         (int64_t) nb_sectors << BDRV_SECTOR_BITS, cb, opaque,
 | 
				
			||||||
                         RBD_AIO_READ);
 | 
					                         RBD_AIO_READ);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -745,7 +745,7 @@ static BlockAIOCB *qemu_rbd_aio_writev(BlockDriverState *bs,
 | 
				
			|||||||
                                       void *opaque)
 | 
					                                       void *opaque)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return rbd_start_aio(bs, sector_num << BDRV_SECTOR_BITS, qiov,
 | 
					    return rbd_start_aio(bs, sector_num << BDRV_SECTOR_BITS, qiov,
 | 
				
			||||||
                         nb_sectors << BDRV_SECTOR_BITS, cb, opaque,
 | 
					                         (int64_t) nb_sectors << BDRV_SECTOR_BITS, cb, opaque,
 | 
				
			||||||
                         RBD_AIO_WRITE);
 | 
					                         RBD_AIO_WRITE);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -651,7 +651,7 @@ void cpu_loop(CPUSPARCState *env)
 | 
				
			|||||||
static void usage(void)
 | 
					static void usage(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    printf("qemu-" TARGET_NAME " version " QEMU_VERSION QEMU_PKGVERSION
 | 
					    printf("qemu-" TARGET_NAME " version " QEMU_VERSION QEMU_PKGVERSION
 | 
				
			||||||
           ", " QEMU_COPYRIGHT "\n"
 | 
					           "\n" QEMU_COPYRIGHT "\n"
 | 
				
			||||||
           "usage: qemu-" TARGET_NAME " [options] program [arguments...]\n"
 | 
					           "usage: qemu-" TARGET_NAME " [options] program [arguments...]\n"
 | 
				
			||||||
           "BSD CPU emulator (compiled for %s emulation)\n"
 | 
					           "BSD CPU emulator (compiled for %s emulation)\n"
 | 
				
			||||||
           "\n"
 | 
					           "\n"
 | 
				
			||||||
 | 
				
			|||||||
@ -15,7 +15,8 @@ Macros defined by qemu/atomic.h fall in three camps:
 | 
				
			|||||||
- compiler barriers: barrier();
 | 
					- compiler barriers: barrier();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- weak atomic access and manual memory barriers: atomic_read(),
 | 
					- weak atomic access and manual memory barriers: atomic_read(),
 | 
				
			||||||
  atomic_set(), smp_rmb(), smp_wmb(), smp_mb(), smp_read_barrier_depends();
 | 
					  atomic_set(), smp_rmb(), smp_wmb(), smp_mb(), smp_mb_acquire(),
 | 
				
			||||||
 | 
					  smp_mb_release(), smp_read_barrier_depends();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- sequentially consistent atomic access: everything else.
 | 
					- sequentially consistent atomic access: everything else.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -111,8 +112,8 @@ consistent primitives.
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
When using this model, variables are accessed with atomic_read() and
 | 
					When using this model, variables are accessed with atomic_read() and
 | 
				
			||||||
atomic_set(), and restrictions to the ordering of accesses is enforced
 | 
					atomic_set(), and restrictions to the ordering of accesses is enforced
 | 
				
			||||||
using the smp_rmb(), smp_wmb(), smp_mb() and smp_read_barrier_depends()
 | 
					using the memory barrier macros: smp_rmb(), smp_wmb(), smp_mb(),
 | 
				
			||||||
memory barriers.
 | 
					smp_mb_acquire(), smp_mb_release(), smp_read_barrier_depends().
 | 
				
			||||||
 | 
					
 | 
				
			||||||
atomic_read() and atomic_set() prevents the compiler from using
 | 
					atomic_read() and atomic_set() prevents the compiler from using
 | 
				
			||||||
optimizations that might otherwise optimize accesses out of existence
 | 
					optimizations that might otherwise optimize accesses out of existence
 | 
				
			||||||
@ -124,7 +125,7 @@ other threads, and which are local to the current thread or protected
 | 
				
			|||||||
by other, more mundane means.
 | 
					by other, more mundane means.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Memory barriers control the order of references to shared memory.
 | 
					Memory barriers control the order of references to shared memory.
 | 
				
			||||||
They come in four kinds:
 | 
					They come in six kinds:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- smp_rmb() guarantees that all the LOAD operations specified before
 | 
					- smp_rmb() guarantees that all the LOAD operations specified before
 | 
				
			||||||
  the barrier will appear to happen before all the LOAD operations
 | 
					  the barrier will appear to happen before all the LOAD operations
 | 
				
			||||||
@ -142,6 +143,16 @@ They come in four kinds:
 | 
				
			|||||||
  In other words, smp_wmb() puts a partial ordering on stores, but is not
 | 
					  In other words, smp_wmb() puts a partial ordering on stores, but is not
 | 
				
			||||||
  required to have any effect on loads.
 | 
					  required to have any effect on loads.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- smp_mb_acquire() guarantees that all the LOAD operations specified before
 | 
				
			||||||
 | 
					  the barrier will appear to happen before all the LOAD or STORE operations
 | 
				
			||||||
 | 
					  specified after the barrier with respect to the other components of
 | 
				
			||||||
 | 
					  the system.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- smp_mb_release() guarantees that all the STORE operations specified *after*
 | 
				
			||||||
 | 
					  the barrier will appear to happen after all the LOAD or STORE operations
 | 
				
			||||||
 | 
					  specified *before* the barrier with respect to the other components of
 | 
				
			||||||
 | 
					  the system.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- smp_mb() guarantees that all the LOAD and STORE operations specified
 | 
					- smp_mb() guarantees that all the LOAD and STORE operations specified
 | 
				
			||||||
  before the barrier will appear to happen before all the LOAD and
 | 
					  before the barrier will appear to happen before all the LOAD and
 | 
				
			||||||
  STORE operations specified after the barrier with respect to the other
 | 
					  STORE operations specified after the barrier with respect to the other
 | 
				
			||||||
@ -149,8 +160,9 @@ They come in four kinds:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  smp_mb() puts a partial ordering on both loads and stores.  It is
 | 
					  smp_mb() puts a partial ordering on both loads and stores.  It is
 | 
				
			||||||
  stronger than both a read and a write memory barrier; it implies both
 | 
					  stronger than both a read and a write memory barrier; it implies both
 | 
				
			||||||
  smp_rmb() and smp_wmb(), but it also prevents STOREs coming before the
 | 
					  smp_mb_acquire() and smp_mb_release(), but it also prevents STOREs
 | 
				
			||||||
  barrier from overtaking LOADs coming after the barrier and vice versa.
 | 
					  coming before the barrier from overtaking LOADs coming after the
 | 
				
			||||||
 | 
					  barrier and vice versa.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- smp_read_barrier_depends() is a weaker kind of read barrier.  On
 | 
					- smp_read_barrier_depends() is a weaker kind of read barrier.  On
 | 
				
			||||||
  most processors, whenever two loads are performed such that the
 | 
					  most processors, whenever two loads are performed such that the
 | 
				
			||||||
@ -174,23 +186,20 @@ This is the set of barriers that is required *between* two atomic_read()
 | 
				
			|||||||
and atomic_set() operations to achieve sequential consistency:
 | 
					and atomic_set() operations to achieve sequential consistency:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    |               2nd operation                   |
 | 
					                    |               2nd operation                   |
 | 
				
			||||||
                    |-----------------------------------------|
 | 
					                    |-----------------------------------------------|
 | 
				
			||||||
     1st operation  | (after last)   | atomic_read | atomic_set     |
 | 
					     1st operation  | (after last)   | atomic_read | atomic_set     |
 | 
				
			||||||
     ---------------+--------------+-------------+------------|
 | 
					     ---------------+----------------+-------------+----------------|
 | 
				
			||||||
     (before first) |              | none        | smp_wmb()  |
 | 
					     (before first) |                | none        | smp_mb_release |
 | 
				
			||||||
     ---------------+--------------+-------------+------------|
 | 
					     ---------------+----------------+-------------+----------------|
 | 
				
			||||||
     atomic_read    | smp_rmb()    | smp_rmb()*  | **         |
 | 
					     atomic_read    | smp_mb_acquire | smp_rmb     | **             |
 | 
				
			||||||
     ---------------+--------------+-------------+------------|
 | 
					     ---------------+----------------+-------------+----------------|
 | 
				
			||||||
     atomic_set     | none           | smp_mb()*** | smp_wmb()      |
 | 
					     atomic_set     | none           | smp_mb()*** | smp_wmb()      |
 | 
				
			||||||
     ---------------+--------------+-------------+------------|
 | 
					     ---------------+----------------+-------------+----------------|
 | 
				
			||||||
 | 
					
 | 
				
			||||||
       * Or smp_read_barrier_depends().
 | 
					       * Or smp_read_barrier_depends().
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      ** This requires a load-store barrier.  How to achieve this varies
 | 
					      ** This requires a load-store barrier.  This is achieved by
 | 
				
			||||||
         depending on the machine, but in practice smp_rmb()+smp_wmb()
 | 
					         either smp_mb_acquire() or smp_mb_release().
 | 
				
			||||||
         should have the desired effect.  For example, on PowerPC the
 | 
					 | 
				
			||||||
         lwsync instruction is a combined load-load, load-store and
 | 
					 | 
				
			||||||
         store-store barrier.
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
     *** This requires a store-load barrier.  On most machines, the only
 | 
					     *** This requires a store-load barrier.  On most machines, the only
 | 
				
			||||||
         way to achieve this is a full barrier.
 | 
					         way to achieve this is a full barrier.
 | 
				
			||||||
@ -199,11 +208,11 @@ and atomic_set() operations to achieve sequential consistency:
 | 
				
			|||||||
You can see that the two possible definitions of atomic_mb_read()
 | 
					You can see that the two possible definitions of atomic_mb_read()
 | 
				
			||||||
and atomic_mb_set() are the following:
 | 
					and atomic_mb_set() are the following:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    1) atomic_mb_read(p)   = atomic_read(p); smp_rmb()
 | 
					    1) atomic_mb_read(p)   = atomic_read(p); smp_mb_acquire()
 | 
				
			||||||
       atomic_mb_set(p, v) = smp_wmb(); atomic_set(p, v); smp_mb()
 | 
					       atomic_mb_set(p, v) = smp_mb_release(); atomic_set(p, v); smp_mb()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    2) atomic_mb_read(p)   = smp_mb() atomic_read(p); smp_rmb()
 | 
					    2) atomic_mb_read(p)   = smp_mb() atomic_read(p); smp_mb_acquire()
 | 
				
			||||||
       atomic_mb_set(p, v) = smp_wmb(); atomic_set(p, v);
 | 
					       atomic_mb_set(p, v) = smp_mb_release(); atomic_set(p, v);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Usually the former is used, because smp_mb() is expensive and a program
 | 
					Usually the former is used, because smp_mb() is expensive and a program
 | 
				
			||||||
normally has more reads than writes.  Therefore it makes more sense to
 | 
					normally has more reads than writes.  Therefore it makes more sense to
 | 
				
			||||||
@ -222,7 +231,7 @@ place barriers instead:
 | 
				
			|||||||
     thread 1                                thread 1
 | 
					     thread 1                                thread 1
 | 
				
			||||||
     -------------------------               ------------------------
 | 
					     -------------------------               ------------------------
 | 
				
			||||||
     (other writes)
 | 
					     (other writes)
 | 
				
			||||||
                                             smp_wmb()
 | 
					                                             smp_mb_release()
 | 
				
			||||||
     atomic_mb_set(&a, x)                    atomic_set(&a, x)
 | 
					     atomic_mb_set(&a, x)                    atomic_set(&a, x)
 | 
				
			||||||
                                             smp_wmb()
 | 
					                                             smp_wmb()
 | 
				
			||||||
     atomic_mb_set(&b, y)                    atomic_set(&b, y)
 | 
					     atomic_mb_set(&b, y)                    atomic_set(&b, y)
 | 
				
			||||||
@ -233,7 +242,13 @@ place barriers instead:
 | 
				
			|||||||
     y = atomic_mb_read(&b)                  y = atomic_read(&b)
 | 
					     y = atomic_mb_read(&b)                  y = atomic_read(&b)
 | 
				
			||||||
                                             smp_rmb()
 | 
					                                             smp_rmb()
 | 
				
			||||||
     x = atomic_mb_read(&a)                  x = atomic_read(&a)
 | 
					     x = atomic_mb_read(&a)                  x = atomic_read(&a)
 | 
				
			||||||
                                             smp_rmb()
 | 
					                                             smp_mb_acquire()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Note that the barrier between the stores in thread 1, and between
 | 
				
			||||||
 | 
					  the loads in thread 2, has been optimized here to a write or a
 | 
				
			||||||
 | 
					  read memory barrier respectively.  On some architectures, notably
 | 
				
			||||||
 | 
					  ARMv7, smp_mb_acquire and smp_mb_release are just as expensive as
 | 
				
			||||||
 | 
					  smp_mb, but smp_rmb and/or smp_wmb are more efficient.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- sometimes, a thread is accessing many variables that are otherwise
 | 
					- sometimes, a thread is accessing many variables that are otherwise
 | 
				
			||||||
  unrelated to each other (for example because, apart from the current
 | 
					  unrelated to each other (for example because, apart from the current
 | 
				
			||||||
@ -246,12 +261,12 @@ place barriers instead:
 | 
				
			|||||||
     n = 0;                                  n = 0;
 | 
					     n = 0;                                  n = 0;
 | 
				
			||||||
     for (i = 0; i < 10; i++)          =>    for (i = 0; i < 10; i++)
 | 
					     for (i = 0; i < 10; i++)          =>    for (i = 0; i < 10; i++)
 | 
				
			||||||
       n += atomic_mb_read(&a[i]);             n += atomic_read(&a[i]);
 | 
					       n += atomic_mb_read(&a[i]);             n += atomic_read(&a[i]);
 | 
				
			||||||
                                             smp_rmb();
 | 
					                                             smp_mb_acquire();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  Similarly, atomic_mb_set() can be transformed as follows:
 | 
					  Similarly, atomic_mb_set() can be transformed as follows:
 | 
				
			||||||
  smp_mb():
 | 
					  smp_mb():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                             smp_wmb();
 | 
					                                             smp_mb_release();
 | 
				
			||||||
     for (i = 0; i < 10; i++)          =>    for (i = 0; i < 10; i++)
 | 
					     for (i = 0; i < 10; i++)          =>    for (i = 0; i < 10; i++)
 | 
				
			||||||
       atomic_mb_set(&a[i], false);            atomic_set(&a[i], false);
 | 
					       atomic_mb_set(&a[i], false);            atomic_set(&a[i], false);
 | 
				
			||||||
                                             smp_mb();
 | 
					                                             smp_mb();
 | 
				
			||||||
@ -261,7 +276,7 @@ The two tricks can be combined.  In this case, splitting a loop in
 | 
				
			|||||||
two lets you hoist the barriers out of the loops _and_ eliminate the
 | 
					two lets you hoist the barriers out of the loops _and_ eliminate the
 | 
				
			||||||
expensive smp_mb():
 | 
					expensive smp_mb():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                             smp_wmb();
 | 
					                                             smp_mb_release();
 | 
				
			||||||
     for (i = 0; i < 10; i++) {        =>    for (i = 0; i < 10; i++)
 | 
					     for (i = 0; i < 10; i++) {        =>    for (i = 0; i < 10; i++)
 | 
				
			||||||
       atomic_mb_set(&a[i], false);            atomic_set(&a[i], false);
 | 
					       atomic_mb_set(&a[i], false);            atomic_set(&a[i], false);
 | 
				
			||||||
       atomic_mb_set(&b[i], false);          smb_wmb();
 | 
					       atomic_mb_set(&b[i], false);          smb_wmb();
 | 
				
			||||||
@ -312,8 +327,8 @@ access and for data dependency barriers:
 | 
				
			|||||||
                             smp_read_barrier_depends();
 | 
					                             smp_read_barrier_depends();
 | 
				
			||||||
                             z = b[y];
 | 
					                             z = b[y];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
smp_wmb() also pairs with atomic_mb_read(), and smp_rmb() also pairs
 | 
					smp_wmb() also pairs with atomic_mb_read() and smp_mb_acquire().
 | 
				
			||||||
with atomic_mb_set().
 | 
					and smp_rmb() also pairs with atomic_mb_set() and smp_mb_release().
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
COMPARISON WITH LINUX KERNEL MEMORY BARRIERS
 | 
					COMPARISON WITH LINUX KERNEL MEMORY BARRIERS
 | 
				
			||||||
@ -359,8 +374,9 @@ and memory barriers, and the equivalents in QEMU:
 | 
				
			|||||||
  note that smp_store_mb() is a little weaker than atomic_mb_set().
 | 
					  note that smp_store_mb() is a little weaker than atomic_mb_set().
 | 
				
			||||||
  atomic_mb_read() compiles to the same instructions as Linux's
 | 
					  atomic_mb_read() compiles to the same instructions as Linux's
 | 
				
			||||||
  smp_load_acquire(), but this should be treated as an implementation
 | 
					  smp_load_acquire(), but this should be treated as an implementation
 | 
				
			||||||
  detail.  If required, QEMU might later add atomic_load_acquire() and
 | 
					  detail.  QEMU does have atomic_load_acquire() and atomic_store_release()
 | 
				
			||||||
  atomic_store_release() macros.
 | 
					  macros, but for now they are only used within atomic.h.  This may
 | 
				
			||||||
 | 
					  change in the future.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SOURCES
 | 
					SOURCES
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										7
									
								
								exec.c
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								exec.c
									
									
									
									
									
								
							@ -1254,7 +1254,12 @@ static void *file_ram_alloc(RAMBlock *block,
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    block->page_size = qemu_fd_getpagesize(fd);
 | 
					    block->page_size = qemu_fd_getpagesize(fd);
 | 
				
			||||||
    block->mr->align = MAX(block->page_size, QEMU_VMALLOC_ALIGN);
 | 
					    block->mr->align = block->page_size;
 | 
				
			||||||
 | 
					#if defined(__s390x__)
 | 
				
			||||||
 | 
					    if (kvm_enabled()) {
 | 
				
			||||||
 | 
					        block->mr->align = MAX(block->mr->align, QEMU_VMALLOC_ALIGN);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (memory < block->page_size) {
 | 
					    if (memory < block->page_size) {
 | 
				
			||||||
        error_setg(errp, "memory size 0x" RAM_ADDR_FMT " must be equal to "
 | 
					        error_setg(errp, "memory size 0x" RAM_ADDR_FMT " must be equal to "
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										31
									
								
								gdbstub.c
									
									
									
									
									
								
							
							
						
						
									
										31
									
								
								gdbstub.c
									
									
									
									
									
								
							@ -303,7 +303,7 @@ typedef struct GDBState {
 | 
				
			|||||||
    int fd;
 | 
					    int fd;
 | 
				
			||||||
    int running_state;
 | 
					    int running_state;
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
    CharDriverState *chr;
 | 
					    CharBackend chr;
 | 
				
			||||||
    CharDriverState *mon_chr;
 | 
					    CharDriverState *mon_chr;
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
    char syscall_buf[256];
 | 
					    char syscall_buf[256];
 | 
				
			||||||
@ -404,7 +404,7 @@ static void put_buffer(GDBState *s, const uint8_t *buf, int len)
 | 
				
			|||||||
#else
 | 
					#else
 | 
				
			||||||
    /* XXX this blocks entire thread. Rewrite to use
 | 
					    /* XXX this blocks entire thread. Rewrite to use
 | 
				
			||||||
     * qemu_chr_fe_write and background I/O callbacks */
 | 
					     * qemu_chr_fe_write and background I/O callbacks */
 | 
				
			||||||
    qemu_chr_fe_write_all(s->chr, buf, len);
 | 
					    qemu_chr_fe_write_all(&s->chr, buf, len);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1471,6 +1471,9 @@ void gdb_exit(CPUArchState *env, int code)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  GDBState *s;
 | 
					  GDBState *s;
 | 
				
			||||||
  char buf[4];
 | 
					  char buf[4];
 | 
				
			||||||
 | 
					#ifndef CONFIG_USER_ONLY
 | 
				
			||||||
 | 
					  CharDriverState *chr;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  s = gdbserver_state;
 | 
					  s = gdbserver_state;
 | 
				
			||||||
  if (!s) {
 | 
					  if (!s) {
 | 
				
			||||||
@ -1481,7 +1484,8 @@ void gdb_exit(CPUArchState *env, int code)
 | 
				
			|||||||
      return;
 | 
					      return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
  if (!s->chr) {
 | 
					  chr = qemu_chr_fe_get_driver(&s->chr);
 | 
				
			||||||
 | 
					  if (!chr) {
 | 
				
			||||||
      return;
 | 
					      return;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@ -1490,7 +1494,8 @@ void gdb_exit(CPUArchState *env, int code)
 | 
				
			|||||||
  put_packet(s, buf);
 | 
					  put_packet(s, buf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef CONFIG_USER_ONLY
 | 
					#ifndef CONFIG_USER_ONLY
 | 
				
			||||||
  qemu_chr_delete(s->chr);
 | 
					  qemu_chr_fe_deinit(&s->chr);
 | 
				
			||||||
 | 
					  qemu_chr_delete(chr);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1745,13 +1750,9 @@ int gdbserver_start(const char *device)
 | 
				
			|||||||
            sigaction(SIGINT, &act, NULL);
 | 
					            sigaction(SIGINT, &act, NULL);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
        chr = qemu_chr_new_noreplay("gdb", device, NULL);
 | 
					        chr = qemu_chr_new_noreplay("gdb", device);
 | 
				
			||||||
        if (!chr)
 | 
					        if (!chr)
 | 
				
			||||||
            return -1;
 | 
					            return -1;
 | 
				
			||||||
 | 
					 | 
				
			||||||
        qemu_chr_fe_claim_no_fail(chr);
 | 
					 | 
				
			||||||
        qemu_chr_add_handlers(chr, gdb_chr_can_receive, gdb_chr_receive,
 | 
					 | 
				
			||||||
                              gdb_chr_event, NULL);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s = gdbserver_state;
 | 
					    s = gdbserver_state;
 | 
				
			||||||
@ -1766,14 +1767,20 @@ int gdbserver_start(const char *device)
 | 
				
			|||||||
        mon_chr->chr_write = gdb_monitor_write;
 | 
					        mon_chr->chr_write = gdb_monitor_write;
 | 
				
			||||||
        monitor_init(mon_chr, 0);
 | 
					        monitor_init(mon_chr, 0);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        if (s->chr)
 | 
					        if (qemu_chr_fe_get_driver(&s->chr)) {
 | 
				
			||||||
            qemu_chr_delete(s->chr);
 | 
					            qemu_chr_delete(qemu_chr_fe_get_driver(&s->chr));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        mon_chr = s->mon_chr;
 | 
					        mon_chr = s->mon_chr;
 | 
				
			||||||
        memset(s, 0, sizeof(GDBState));
 | 
					        memset(s, 0, sizeof(GDBState));
 | 
				
			||||||
 | 
					        s->mon_chr = mon_chr;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    s->c_cpu = first_cpu;
 | 
					    s->c_cpu = first_cpu;
 | 
				
			||||||
    s->g_cpu = first_cpu;
 | 
					    s->g_cpu = first_cpu;
 | 
				
			||||||
    s->chr = chr;
 | 
					    if (chr) {
 | 
				
			||||||
 | 
					        qemu_chr_fe_init(&s->chr, chr, &error_abort);
 | 
				
			||||||
 | 
					        qemu_chr_fe_set_handlers(&s->chr, gdb_chr_can_receive, gdb_chr_receive,
 | 
				
			||||||
 | 
					                                 gdb_chr_event, NULL, NULL, true);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    s->state = chr ? RS_IDLE : RS_INACTIVE;
 | 
					    s->state = chr ? RS_IDLE : RS_INACTIVE;
 | 
				
			||||||
    s->mon_chr = mon_chr;
 | 
					    s->mon_chr = mon_chr;
 | 
				
			||||||
    s->current_syscall_cb = NULL;
 | 
					    s->current_syscall_cb = NULL;
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								hmp.c
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								hmp.c
									
									
									
									
									
								
							@ -2002,7 +2002,7 @@ void hmp_chardev_add(Monitor *mon, const QDict *qdict)
 | 
				
			|||||||
    if (opts == NULL) {
 | 
					    if (opts == NULL) {
 | 
				
			||||||
        error_setg(&err, "Parsing chardev args failed");
 | 
					        error_setg(&err, "Parsing chardev args failed");
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        qemu_chr_new_from_opts(opts, NULL, &err);
 | 
					        qemu_chr_new_from_opts(opts, &err);
 | 
				
			||||||
        qemu_opts_del(opts);
 | 
					        qemu_opts_del(opts);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    hmp_handle_error(mon, &err);
 | 
					    hmp_handle_error(mon, &err);
 | 
				
			||||||
 | 
				
			|||||||
@ -88,7 +88,7 @@ static void clipper_init(MachineState *machine)
 | 
				
			|||||||
    pci_vga_init(pci_bus);
 | 
					    pci_vga_init(pci_bus);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Serial code setup.  */
 | 
					    /* Serial code setup.  */
 | 
				
			||||||
    serial_hds_isa_init(isa_bus, MAX_SERIAL_PORTS);
 | 
					    serial_hds_isa_init(isa_bus, 0, MAX_SERIAL_PORTS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Network setup.  e1000 is good enough, failing Tulip support.  */
 | 
					    /* Network setup.  e1000 is good enough, failing Tulip support.  */
 | 
				
			||||||
    for (i = 0; i < nb_nics; i++) {
 | 
					    for (i = 0; i < nb_nics; i++) {
 | 
				
			||||||
 | 
				
			|||||||
@ -125,7 +125,7 @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp)
 | 
				
			|||||||
            if (!chr) {
 | 
					            if (!chr) {
 | 
				
			||||||
                char label[20];
 | 
					                char label[20];
 | 
				
			||||||
                snprintf(label, sizeof(label), "imx31.uart%d", i);
 | 
					                snprintf(label, sizeof(label), "imx31.uart%d", i);
 | 
				
			||||||
                chr = qemu_chr_new(label, "null", NULL);
 | 
					                chr = qemu_chr_new(label, "null");
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", chr);
 | 
					            qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", chr);
 | 
				
			||||||
 | 
				
			|||||||
@ -114,7 +114,7 @@ static void fsl_imx31_realize(DeviceState *dev, Error **errp)
 | 
				
			|||||||
            if (!chr) {
 | 
					            if (!chr) {
 | 
				
			||||||
                char label[20];
 | 
					                char label[20];
 | 
				
			||||||
                snprintf(label, sizeof(label), "imx31.uart%d", i);
 | 
					                snprintf(label, sizeof(label), "imx31.uart%d", i);
 | 
				
			||||||
                chr = qemu_chr_new(label, "null", NULL);
 | 
					                chr = qemu_chr_new(label, "null");
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", chr);
 | 
					            qdev_prop_set_chr(DEVICE(&s->uart[i]), "chardev", chr);
 | 
				
			||||||
 | 
				
			|||||||
@ -193,7 +193,7 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            if (!chr) {
 | 
					            if (!chr) {
 | 
				
			||||||
                char *label = g_strdup_printf("imx6.uart%d", i + 1);
 | 
					                char *label = g_strdup_printf("imx6.uart%d", i + 1);
 | 
				
			||||||
                chr = qemu_chr_new(label, "null", NULL);
 | 
					                chr = qemu_chr_new(label, "null");
 | 
				
			||||||
                g_free(label);
 | 
					                g_free(label);
 | 
				
			||||||
                serial_hds[i] = chr;
 | 
					                serial_hds[i] = chr;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
				
			|||||||
@ -621,7 +621,7 @@ struct omap_sti_s {
 | 
				
			|||||||
    qemu_irq irq;
 | 
					    qemu_irq irq;
 | 
				
			||||||
    MemoryRegion iomem;
 | 
					    MemoryRegion iomem;
 | 
				
			||||||
    MemoryRegion iomem_fifo;
 | 
					    MemoryRegion iomem_fifo;
 | 
				
			||||||
    CharDriverState *chr;
 | 
					    CharBackend chr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint32_t sysconfig;
 | 
					    uint32_t sysconfig;
 | 
				
			||||||
    uint32_t systest;
 | 
					    uint32_t systest;
 | 
				
			||||||
@ -771,14 +771,15 @@ static void omap_sti_fifo_write(void *opaque, hwaddr addr,
 | 
				
			|||||||
        /* Flush channel <i>value</i>.  */
 | 
					        /* Flush channel <i>value</i>.  */
 | 
				
			||||||
        /* XXX this blocks entire thread. Rewrite to use
 | 
					        /* XXX this blocks entire thread. Rewrite to use
 | 
				
			||||||
         * qemu_chr_fe_write and background I/O callbacks */
 | 
					         * qemu_chr_fe_write and background I/O callbacks */
 | 
				
			||||||
        qemu_chr_fe_write_all(s->chr, (const uint8_t *) "\r", 1);
 | 
					        qemu_chr_fe_write_all(&s->chr, (const uint8_t *) "\r", 1);
 | 
				
			||||||
    } else if (ch == STI_TRACE_CONSOLE_CHANNEL || 1) {
 | 
					    } else if (ch == STI_TRACE_CONSOLE_CHANNEL || 1) {
 | 
				
			||||||
        if (value == 0xc0 || value == 0xc3) {
 | 
					        if (value == 0xc0 || value == 0xc3) {
 | 
				
			||||||
            /* Open channel <i>ch</i>.  */
 | 
					            /* Open channel <i>ch</i>.  */
 | 
				
			||||||
        } else if (value == 0x00)
 | 
					        } else if (value == 0x00) {
 | 
				
			||||||
            qemu_chr_fe_write_all(s->chr, (const uint8_t *) "\n", 1);
 | 
					            qemu_chr_fe_write_all(&s->chr, (const uint8_t *) "\n", 1);
 | 
				
			||||||
        else
 | 
					        } else {
 | 
				
			||||||
            qemu_chr_fe_write_all(s->chr, &byte, 1);
 | 
					            qemu_chr_fe_write_all(&s->chr, &byte, 1);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -798,7 +799,8 @@ static struct omap_sti_s *omap_sti_init(struct omap_target_agent_s *ta,
 | 
				
			|||||||
    s->irq = irq;
 | 
					    s->irq = irq;
 | 
				
			||||||
    omap_sti_reset(s);
 | 
					    omap_sti_reset(s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->chr = chr ?: qemu_chr_new("null", "null", NULL);
 | 
					    qemu_chr_fe_init(&s->chr, chr ?: qemu_chr_new("null", "null"),
 | 
				
			||||||
 | 
					                     &error_abort);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    memory_region_init_io(&s->iomem, NULL, &omap_sti_ops, s, "omap.sti",
 | 
					    memory_region_init_io(&s->iomem, NULL, &omap_sti_ops, s, "omap.sti",
 | 
				
			||||||
                          omap_l4_region_size(ta, 0));
 | 
					                          omap_l4_region_size(ta, 0));
 | 
				
			||||||
 | 
				
			|||||||
@ -1764,7 +1764,7 @@ struct PXA2xxFIrState {
 | 
				
			|||||||
    qemu_irq rx_dma;
 | 
					    qemu_irq rx_dma;
 | 
				
			||||||
    qemu_irq tx_dma;
 | 
					    qemu_irq tx_dma;
 | 
				
			||||||
    uint32_t enable;
 | 
					    uint32_t enable;
 | 
				
			||||||
    CharDriverState *chr;
 | 
					    CharBackend chr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint8_t control[3];
 | 
					    uint8_t control[3];
 | 
				
			||||||
    uint8_t status[2];
 | 
					    uint8_t status[2];
 | 
				
			||||||
@ -1898,14 +1898,16 @@ static void pxa2xx_fir_write(void *opaque, hwaddr addr,
 | 
				
			|||||||
        pxa2xx_fir_update(s);
 | 
					        pxa2xx_fir_update(s);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case ICDR:
 | 
					    case ICDR:
 | 
				
			||||||
        if (s->control[2] & (1 << 2))			/* TXP */
 | 
					        if (s->control[2] & (1 << 2)) { /* TXP */
 | 
				
			||||||
            ch = value;
 | 
					            ch = value;
 | 
				
			||||||
        else
 | 
					        } else {
 | 
				
			||||||
            ch = ~value;
 | 
					            ch = ~value;
 | 
				
			||||||
        if (s->chr && s->enable && (s->control[0] & (1 << 3)))	/* TXE */
 | 
					        }
 | 
				
			||||||
 | 
					        if (s->enable && (s->control[0] & (1 << 3))) { /* TXE */
 | 
				
			||||||
            /* XXX this blocks entire thread. Rewrite to use
 | 
					            /* XXX this blocks entire thread. Rewrite to use
 | 
				
			||||||
             * qemu_chr_fe_write and background I/O callbacks */
 | 
					             * qemu_chr_fe_write and background I/O callbacks */
 | 
				
			||||||
            qemu_chr_fe_write_all(s->chr, &ch, 1);
 | 
					            qemu_chr_fe_write_all(&s->chr, &ch, 1);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case ICSR0:
 | 
					    case ICSR0:
 | 
				
			||||||
        s->status[0] &= ~(value & 0x66);
 | 
					        s->status[0] &= ~(value & 0x66);
 | 
				
			||||||
@ -1973,11 +1975,8 @@ static void pxa2xx_fir_realize(DeviceState *dev, Error **errp)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    PXA2xxFIrState *s = PXA2XX_FIR(dev);
 | 
					    PXA2xxFIrState *s = PXA2XX_FIR(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (s->chr) {
 | 
					    qemu_chr_fe_set_handlers(&s->chr, pxa2xx_fir_is_empty,
 | 
				
			||||||
        qemu_chr_fe_claim_no_fail(s->chr);
 | 
					                             pxa2xx_fir_rx, pxa2xx_fir_event, s, NULL, true);
 | 
				
			||||||
        qemu_chr_add_handlers(s->chr, pxa2xx_fir_is_empty,
 | 
					 | 
				
			||||||
                        pxa2xx_fir_rx, pxa2xx_fir_event, s);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool pxa2xx_fir_vmstate_validate(void *opaque, int version_id)
 | 
					static bool pxa2xx_fir_vmstate_validate(void *opaque, int version_id)
 | 
				
			||||||
 | 
				
			|||||||
@ -912,7 +912,7 @@ typedef struct StrongARMUARTState {
 | 
				
			|||||||
    SysBusDevice parent_obj;
 | 
					    SysBusDevice parent_obj;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    MemoryRegion iomem;
 | 
					    MemoryRegion iomem;
 | 
				
			||||||
    CharDriverState *chr;
 | 
					    CharBackend chr;
 | 
				
			||||||
    qemu_irq irq;
 | 
					    qemu_irq irq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint8_t utcr0;
 | 
					    uint8_t utcr0;
 | 
				
			||||||
@ -1020,9 +1020,7 @@ static void strongarm_uart_update_parameters(StrongARMUARTState *s)
 | 
				
			|||||||
    ssp.data_bits = data_bits;
 | 
					    ssp.data_bits = data_bits;
 | 
				
			||||||
    ssp.stop_bits = stop_bits;
 | 
					    ssp.stop_bits = stop_bits;
 | 
				
			||||||
    s->char_transmit_time =  (NANOSECONDS_PER_SECOND / speed) * frame_size;
 | 
					    s->char_transmit_time =  (NANOSECONDS_PER_SECOND / speed) * frame_size;
 | 
				
			||||||
    if (s->chr) {
 | 
					    qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
 | 
				
			||||||
        qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    DPRINTF(stderr, "%s speed=%d parity=%c data=%d stop=%d\n", s->chr->label,
 | 
					    DPRINTF(stderr, "%s speed=%d parity=%c data=%d stop=%d\n", s->chr->label,
 | 
				
			||||||
            speed, parity, data_bits, stop_bits);
 | 
					            speed, parity, data_bits, stop_bits);
 | 
				
			||||||
@ -1107,10 +1105,10 @@ static void strongarm_uart_tx(void *opaque)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if (s->utcr3 & UTCR3_LBM) /* loopback */ {
 | 
					    if (s->utcr3 & UTCR3_LBM) /* loopback */ {
 | 
				
			||||||
        strongarm_uart_receive(s, &s->tx_fifo[s->tx_start], 1);
 | 
					        strongarm_uart_receive(s, &s->tx_fifo[s->tx_start], 1);
 | 
				
			||||||
    } else if (s->chr) {
 | 
					    } else if (qemu_chr_fe_get_driver(&s->chr)) {
 | 
				
			||||||
        /* XXX this blocks entire thread. Rewrite to use
 | 
					        /* XXX this blocks entire thread. Rewrite to use
 | 
				
			||||||
         * qemu_chr_fe_write and background I/O callbacks */
 | 
					         * qemu_chr_fe_write and background I/O callbacks */
 | 
				
			||||||
        qemu_chr_fe_write_all(s->chr, &s->tx_fifo[s->tx_start], 1);
 | 
					        qemu_chr_fe_write_all(&s->chr, &s->tx_fifo[s->tx_start], 1);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->tx_start = (s->tx_start + 1) % 8;
 | 
					    s->tx_start = (s->tx_start + 1) % 8;
 | 
				
			||||||
@ -1239,13 +1237,11 @@ static void strongarm_uart_init(Object *obj)
 | 
				
			|||||||
    s->rx_timeout_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, strongarm_uart_rx_to, s);
 | 
					    s->rx_timeout_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, strongarm_uart_rx_to, s);
 | 
				
			||||||
    s->tx_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, strongarm_uart_tx, s);
 | 
					    s->tx_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, strongarm_uart_tx, s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (s->chr) {
 | 
					    qemu_chr_fe_set_handlers(&s->chr,
 | 
				
			||||||
        qemu_chr_add_handlers(s->chr,
 | 
					 | 
				
			||||||
                             strongarm_uart_can_receive,
 | 
					                             strongarm_uart_can_receive,
 | 
				
			||||||
                             strongarm_uart_receive,
 | 
					                             strongarm_uart_receive,
 | 
				
			||||||
                             strongarm_uart_event,
 | 
					                             strongarm_uart_event,
 | 
				
			||||||
                        s);
 | 
					                             s, NULL, true);
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void strongarm_uart_reset(DeviceState *dev)
 | 
					static void strongarm_uart_reset(DeviceState *dev)
 | 
				
			||||||
 | 
				
			|||||||
@ -78,13 +78,15 @@ enum {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static inline void csrhci_fifo_wake(struct csrhci_s *s)
 | 
					static inline void csrhci_fifo_wake(struct csrhci_s *s)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    CharBackend *be = s->chr.be;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!s->enable || !s->out_len)
 | 
					    if (!s->enable || !s->out_len)
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* XXX: Should wait for s->modem_state & CHR_TIOCM_RTS? */
 | 
					    /* XXX: Should wait for s->modem_state & CHR_TIOCM_RTS? */
 | 
				
			||||||
    if (s->chr.chr_can_read && s->chr.chr_can_read(s->chr.handler_opaque) &&
 | 
					    if (be && be->chr_can_read && be->chr_can_read(be->opaque) &&
 | 
				
			||||||
                    s->chr.chr_read) {
 | 
					        be->chr_read) {
 | 
				
			||||||
        s->chr.chr_read(s->chr.handler_opaque,
 | 
					        be->chr_read(be->opaque,
 | 
				
			||||||
                     s->outfifo + s->out_start++, 1);
 | 
					                     s->outfifo + s->out_start++, 1);
 | 
				
			||||||
        s->out_len--;
 | 
					        s->out_len--;
 | 
				
			||||||
        if (s->out_start >= s->out_size) {
 | 
					        if (s->out_start >= s->out_size) {
 | 
				
			||||||
@ -466,7 +468,6 @@ CharDriverState *uart_hci_init(void)
 | 
				
			|||||||
    s->chr.opaque = s;
 | 
					    s->chr.opaque = s;
 | 
				
			||||||
    s->chr.chr_write = csrhci_write;
 | 
					    s->chr.chr_write = csrhci_write;
 | 
				
			||||||
    s->chr.chr_ioctl = csrhci_ioctl;
 | 
					    s->chr.chr_ioctl = csrhci_ioctl;
 | 
				
			||||||
    s->chr.avail_connections = 1;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->hci = qemu_next_hci();
 | 
					    s->hci = qemu_next_hci();
 | 
				
			||||||
    s->hci->opaque = s;
 | 
					    s->hci->opaque = s;
 | 
				
			||||||
 | 
				
			|||||||
@ -79,9 +79,7 @@ static uint64_t bcm2835_aux_read(void *opaque, hwaddr offset, unsigned size)
 | 
				
			|||||||
                s->read_pos = 0;
 | 
					                s->read_pos = 0;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (s->chr) {
 | 
					        qemu_chr_fe_accept_input(&s->chr);
 | 
				
			||||||
            qemu_chr_accept_input(s->chr);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        bcm2835_aux_update(s);
 | 
					        bcm2835_aux_update(s);
 | 
				
			||||||
        return c;
 | 
					        return c;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -168,11 +166,9 @@ static void bcm2835_aux_write(void *opaque, hwaddr offset, uint64_t value,
 | 
				
			|||||||
    case AUX_MU_IO_REG:
 | 
					    case AUX_MU_IO_REG:
 | 
				
			||||||
        /* "DLAB bit set means access baudrate register" is NYI */
 | 
					        /* "DLAB bit set means access baudrate register" is NYI */
 | 
				
			||||||
        ch = value;
 | 
					        ch = value;
 | 
				
			||||||
        if (s->chr) {
 | 
					 | 
				
			||||||
        /* XXX this blocks entire thread. Rewrite to use
 | 
					        /* XXX this blocks entire thread. Rewrite to use
 | 
				
			||||||
         * qemu_chr_fe_write and background I/O callbacks */
 | 
					         * qemu_chr_fe_write and background I/O callbacks */
 | 
				
			||||||
            qemu_chr_fe_write_all(s->chr, &ch, 1);
 | 
					        qemu_chr_fe_write_all(&s->chr, &ch, 1);
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case AUX_MU_IER_REG:
 | 
					    case AUX_MU_IER_REG:
 | 
				
			||||||
@ -282,10 +278,8 @@ static void bcm2835_aux_realize(DeviceState *dev, Error **errp)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    BCM2835AuxState *s = BCM2835_AUX(dev);
 | 
					    BCM2835AuxState *s = BCM2835_AUX(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (s->chr) {
 | 
					    qemu_chr_fe_set_handlers(&s->chr, bcm2835_aux_can_receive,
 | 
				
			||||||
        qemu_chr_add_handlers(s->chr, bcm2835_aux_can_receive,
 | 
					                             bcm2835_aux_receive, NULL, s, NULL, true);
 | 
				
			||||||
                              bcm2835_aux_receive, NULL, s);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static Property bcm2835_aux_props[] = {
 | 
					static Property bcm2835_aux_props[] = {
 | 
				
			||||||
 | 
				
			|||||||
@ -142,9 +142,7 @@ static void uart_rx_reset(CadenceUARTState *s)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    s->rx_wpos = 0;
 | 
					    s->rx_wpos = 0;
 | 
				
			||||||
    s->rx_count = 0;
 | 
					    s->rx_count = 0;
 | 
				
			||||||
    if (s->chr) {
 | 
					    qemu_chr_fe_accept_input(&s->chr);
 | 
				
			||||||
        qemu_chr_accept_input(s->chr);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void uart_tx_reset(CadenceUARTState *s)
 | 
					static void uart_tx_reset(CadenceUARTState *s)
 | 
				
			||||||
@ -156,11 +154,9 @@ static void uart_send_breaks(CadenceUARTState *s)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    int break_enabled = 1;
 | 
					    int break_enabled = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (s->chr) {
 | 
					    qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_BREAK,
 | 
				
			||||||
        qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_BREAK,
 | 
					 | 
				
			||||||
                      &break_enabled);
 | 
					                      &break_enabled);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void uart_parameters_setup(CadenceUARTState *s)
 | 
					static void uart_parameters_setup(CadenceUARTState *s)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -210,9 +206,7 @@ static void uart_parameters_setup(CadenceUARTState *s)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    packet_size += ssp.data_bits + ssp.stop_bits;
 | 
					    packet_size += ssp.data_bits + ssp.stop_bits;
 | 
				
			||||||
    s->char_tx_time = (NANOSECONDS_PER_SECOND / ssp.speed) * packet_size;
 | 
					    s->char_tx_time = (NANOSECONDS_PER_SECOND / ssp.speed) * packet_size;
 | 
				
			||||||
    if (s->chr) {
 | 
					    qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
 | 
				
			||||||
        qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int uart_can_receive(void *opaque)
 | 
					static int uart_can_receive(void *opaque)
 | 
				
			||||||
@ -278,7 +272,7 @@ static gboolean cadence_uart_xmit(GIOChannel *chan, GIOCondition cond,
 | 
				
			|||||||
    int ret;
 | 
					    int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* instant drain the fifo when there's no back-end */
 | 
					    /* instant drain the fifo when there's no back-end */
 | 
				
			||||||
    if (!s->chr) {
 | 
					    if (!qemu_chr_fe_get_driver(&s->chr)) {
 | 
				
			||||||
        s->tx_count = 0;
 | 
					        s->tx_count = 0;
 | 
				
			||||||
        return FALSE;
 | 
					        return FALSE;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -287,7 +281,7 @@ static gboolean cadence_uart_xmit(GIOChannel *chan, GIOCondition cond,
 | 
				
			|||||||
        return FALSE;
 | 
					        return FALSE;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ret = qemu_chr_fe_write(s->chr, s->tx_fifo, s->tx_count);
 | 
					    ret = qemu_chr_fe_write(&s->chr, s->tx_fifo, s->tx_count);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (ret >= 0) {
 | 
					    if (ret >= 0) {
 | 
				
			||||||
        s->tx_count -= ret;
 | 
					        s->tx_count -= ret;
 | 
				
			||||||
@ -295,7 +289,7 @@ static gboolean cadence_uart_xmit(GIOChannel *chan, GIOCondition cond,
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (s->tx_count) {
 | 
					    if (s->tx_count) {
 | 
				
			||||||
        guint r = qemu_chr_fe_add_watch(s->chr, G_IO_OUT|G_IO_HUP,
 | 
					        guint r = qemu_chr_fe_add_watch(&s->chr, G_IO_OUT | G_IO_HUP,
 | 
				
			||||||
                                        cadence_uart_xmit, s);
 | 
					                                        cadence_uart_xmit, s);
 | 
				
			||||||
        if (!r) {
 | 
					        if (!r) {
 | 
				
			||||||
            s->tx_count = 0;
 | 
					            s->tx_count = 0;
 | 
				
			||||||
@ -368,9 +362,7 @@ static void uart_read_rx_fifo(CadenceUARTState *s, uint32_t *c)
 | 
				
			|||||||
        *c = s->rx_fifo[rx_rpos];
 | 
					        *c = s->rx_fifo[rx_rpos];
 | 
				
			||||||
        s->rx_count--;
 | 
					        s->rx_count--;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (s->chr) {
 | 
					        qemu_chr_fe_accept_input(&s->chr);
 | 
				
			||||||
            qemu_chr_accept_input(s->chr);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        *c = 0;
 | 
					        *c = 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -474,10 +466,8 @@ static void cadence_uart_realize(DeviceState *dev, Error **errp)
 | 
				
			|||||||
    s->fifo_trigger_handle = timer_new_ns(QEMU_CLOCK_VIRTUAL,
 | 
					    s->fifo_trigger_handle = timer_new_ns(QEMU_CLOCK_VIRTUAL,
 | 
				
			||||||
                                          fifo_trigger_update, s);
 | 
					                                          fifo_trigger_update, s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (s->chr) {
 | 
					    qemu_chr_fe_set_handlers(&s->chr, uart_can_receive, uart_receive,
 | 
				
			||||||
        qemu_chr_add_handlers(s->chr, uart_can_receive, uart_receive,
 | 
					                             uart_event, s, NULL, true);
 | 
				
			||||||
                              uart_event, s);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void cadence_uart_init(Object *obj)
 | 
					static void cadence_uart_init(Object *obj)
 | 
				
			||||||
 | 
				
			|||||||
@ -39,7 +39,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
typedef struct DebugconState {
 | 
					typedef struct DebugconState {
 | 
				
			||||||
    MemoryRegion io;
 | 
					    MemoryRegion io;
 | 
				
			||||||
    CharDriverState *chr;
 | 
					    CharBackend chr;
 | 
				
			||||||
    uint32_t readback;
 | 
					    uint32_t readback;
 | 
				
			||||||
} DebugconState;
 | 
					} DebugconState;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -62,7 +62,7 @@ static void debugcon_ioport_write(void *opaque, hwaddr addr, uint64_t val,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /* XXX this blocks entire thread. Rewrite to use
 | 
					    /* XXX this blocks entire thread. Rewrite to use
 | 
				
			||||||
     * qemu_chr_fe_write and background I/O callbacks */
 | 
					     * qemu_chr_fe_write and background I/O callbacks */
 | 
				
			||||||
    qemu_chr_fe_write_all(s->chr, &ch, 1);
 | 
					    qemu_chr_fe_write_all(&s->chr, &ch, 1);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -87,12 +87,12 @@ static const MemoryRegionOps debugcon_ops = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void debugcon_realize_core(DebugconState *s, Error **errp)
 | 
					static void debugcon_realize_core(DebugconState *s, Error **errp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (!s->chr) {
 | 
					    if (!qemu_chr_fe_get_driver(&s->chr)) {
 | 
				
			||||||
        error_setg(errp, "Can't create debugcon device, empty char device");
 | 
					        error_setg(errp, "Can't create debugcon device, empty char device");
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, s);
 | 
					    qemu_chr_fe_set_handlers(&s->chr, NULL, NULL, NULL, s, NULL, true);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void debugcon_isa_realizefn(DeviceState *dev, Error **errp)
 | 
					static void debugcon_isa_realizefn(DeviceState *dev, Error **errp)
 | 
				
			||||||
 | 
				
			|||||||
@ -76,11 +76,9 @@ static void digic_uart_write(void *opaque, hwaddr addr, uint64_t value,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    switch (addr) {
 | 
					    switch (addr) {
 | 
				
			||||||
    case R_TX:
 | 
					    case R_TX:
 | 
				
			||||||
        if (s->chr) {
 | 
					 | 
				
			||||||
        /* XXX this blocks entire thread. Rewrite to use
 | 
					        /* XXX this blocks entire thread. Rewrite to use
 | 
				
			||||||
         * qemu_chr_fe_write and background I/O callbacks */
 | 
					         * qemu_chr_fe_write and background I/O callbacks */
 | 
				
			||||||
            qemu_chr_fe_write_all(s->chr, &ch, 1);
 | 
					        qemu_chr_fe_write_all(&s->chr, &ch, 1);
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case R_ST:
 | 
					    case R_ST:
 | 
				
			||||||
@ -147,9 +145,8 @@ static void digic_uart_realize(DeviceState *dev, Error **errp)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    DigicUartState *s = DIGIC_UART(dev);
 | 
					    DigicUartState *s = DIGIC_UART(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (s->chr) {
 | 
					    qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx,
 | 
				
			||||||
        qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
 | 
					                             uart_event, s, NULL, true);
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void digic_uart_init(Object *obj)
 | 
					static void digic_uart_init(Object *obj)
 | 
				
			||||||
 | 
				
			|||||||
@ -88,7 +88,7 @@ typedef struct ChannelState {
 | 
				
			|||||||
    uint32_t reg;
 | 
					    uint32_t reg;
 | 
				
			||||||
    uint8_t wregs[SERIAL_REGS], rregs[SERIAL_REGS];
 | 
					    uint8_t wregs[SERIAL_REGS], rregs[SERIAL_REGS];
 | 
				
			||||||
    SERIOQueue queue;
 | 
					    SERIOQueue queue;
 | 
				
			||||||
    CharDriverState *chr;
 | 
					    CharBackend chr;
 | 
				
			||||||
    int e0_mode, led_mode, caps_lock_mode, num_lock_mode;
 | 
					    int e0_mode, led_mode, caps_lock_mode, num_lock_mode;
 | 
				
			||||||
    int disabled;
 | 
					    int disabled;
 | 
				
			||||||
    int clock;
 | 
					    int clock;
 | 
				
			||||||
@ -416,7 +416,7 @@ static void escc_update_parameters(ChannelState *s)
 | 
				
			|||||||
    int speed, parity, data_bits, stop_bits;
 | 
					    int speed, parity, data_bits, stop_bits;
 | 
				
			||||||
    QEMUSerialSetParams ssp;
 | 
					    QEMUSerialSetParams ssp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!s->chr || s->type != ser)
 | 
					    if (!qemu_chr_fe_get_driver(&s->chr) || s->type != ser)
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (s->wregs[W_TXCTRL1] & TXCTRL1_PAREN) {
 | 
					    if (s->wregs[W_TXCTRL1] & TXCTRL1_PAREN) {
 | 
				
			||||||
@ -466,7 +466,7 @@ static void escc_update_parameters(ChannelState *s)
 | 
				
			|||||||
    ssp.data_bits = data_bits;
 | 
					    ssp.data_bits = data_bits;
 | 
				
			||||||
    ssp.stop_bits = stop_bits;
 | 
					    ssp.stop_bits = stop_bits;
 | 
				
			||||||
    trace_escc_update_parameters(CHN_C(s), speed, parity, data_bits, stop_bits);
 | 
					    trace_escc_update_parameters(CHN_C(s), speed, parity, data_bits, stop_bits);
 | 
				
			||||||
    qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
 | 
					    qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void escc_mem_write(void *opaque, hwaddr addr,
 | 
					static void escc_mem_write(void *opaque, hwaddr addr,
 | 
				
			||||||
@ -556,11 +556,11 @@ static void escc_mem_write(void *opaque, hwaddr addr,
 | 
				
			|||||||
        trace_escc_mem_writeb_data(CHN_C(s), val);
 | 
					        trace_escc_mem_writeb_data(CHN_C(s), val);
 | 
				
			||||||
        s->tx = val;
 | 
					        s->tx = val;
 | 
				
			||||||
        if (s->wregs[W_TXCTRL2] & TXCTRL2_TXEN) { // tx enabled
 | 
					        if (s->wregs[W_TXCTRL2] & TXCTRL2_TXEN) { // tx enabled
 | 
				
			||||||
            if (s->chr)
 | 
					            if (qemu_chr_fe_get_driver(&s->chr)) {
 | 
				
			||||||
                /* XXX this blocks entire thread. Rewrite to use
 | 
					                /* XXX this blocks entire thread. Rewrite to use
 | 
				
			||||||
                 * qemu_chr_fe_write and background I/O callbacks */
 | 
					                 * qemu_chr_fe_write and background I/O callbacks */
 | 
				
			||||||
                qemu_chr_fe_write_all(s->chr, &s->tx, 1);
 | 
					                qemu_chr_fe_write_all(&s->chr, &s->tx, 1);
 | 
				
			||||||
            else if (s->type == kbd && !s->disabled) {
 | 
					            } else if (s->type == kbd && !s->disabled) {
 | 
				
			||||||
                handle_kbd_command(s, val);
 | 
					                handle_kbd_command(s, val);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -599,8 +599,7 @@ static uint64_t escc_mem_read(void *opaque, hwaddr addr,
 | 
				
			|||||||
        else
 | 
					        else
 | 
				
			||||||
            ret = s->rx;
 | 
					            ret = s->rx;
 | 
				
			||||||
        trace_escc_mem_readb_data(CHN_C(s), ret);
 | 
					        trace_escc_mem_readb_data(CHN_C(s), ret);
 | 
				
			||||||
        if (s->chr)
 | 
					        qemu_chr_fe_accept_input(&s->chr);
 | 
				
			||||||
            qemu_chr_accept_input(s->chr);
 | 
					 | 
				
			||||||
        return ret;
 | 
					        return ret;
 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
@ -1013,10 +1012,11 @@ static void escc_realize(DeviceState *dev, Error **errp)
 | 
				
			|||||||
                          ESCC_SIZE << s->it_shift);
 | 
					                          ESCC_SIZE << s->it_shift);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (i = 0; i < 2; i++) {
 | 
					    for (i = 0; i < 2; i++) {
 | 
				
			||||||
        if (s->chn[i].chr) {
 | 
					        if (qemu_chr_fe_get_driver(&s->chn[i].chr)) {
 | 
				
			||||||
            s->chn[i].clock = s->frequency / 2;
 | 
					            s->chn[i].clock = s->frequency / 2;
 | 
				
			||||||
            qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
 | 
					            qemu_chr_fe_set_handlers(&s->chn[i].chr, serial_can_receive,
 | 
				
			||||||
                                  serial_receive1, serial_event, &s->chn[i]);
 | 
					                                     serial_receive1, serial_event,
 | 
				
			||||||
 | 
					                                     &s->chn[i], NULL, true);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -53,7 +53,7 @@ typedef struct ETRAXSerial {
 | 
				
			|||||||
    SysBusDevice parent_obj;
 | 
					    SysBusDevice parent_obj;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    MemoryRegion mmio;
 | 
					    MemoryRegion mmio;
 | 
				
			||||||
    CharDriverState *chr;
 | 
					    CharBackend chr;
 | 
				
			||||||
    qemu_irq irq;
 | 
					    qemu_irq irq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    int pending_tx;
 | 
					    int pending_tx;
 | 
				
			||||||
@ -128,7 +128,7 @@ ser_write(void *opaque, hwaddr addr,
 | 
				
			|||||||
        case RW_DOUT:
 | 
					        case RW_DOUT:
 | 
				
			||||||
            /* XXX this blocks entire thread. Rewrite to use
 | 
					            /* XXX this blocks entire thread. Rewrite to use
 | 
				
			||||||
             * qemu_chr_fe_write and background I/O callbacks */
 | 
					             * qemu_chr_fe_write and background I/O callbacks */
 | 
				
			||||||
            qemu_chr_fe_write_all(s->chr, &ch, 1);
 | 
					            qemu_chr_fe_write_all(&s->chr, &ch, 1);
 | 
				
			||||||
            s->regs[R_INTR] |= 3;
 | 
					            s->regs[R_INTR] |= 3;
 | 
				
			||||||
            s->pending_tx = 1;
 | 
					            s->pending_tx = 1;
 | 
				
			||||||
            s->regs[addr] = value;
 | 
					            s->regs[addr] = value;
 | 
				
			||||||
@ -231,11 +231,9 @@ static void etraxfs_ser_realize(DeviceState *dev, Error **errp)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    ETRAXSerial *s = ETRAX_SERIAL(dev);
 | 
					    ETRAXSerial *s = ETRAX_SERIAL(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (s->chr) {
 | 
					    qemu_chr_fe_set_handlers(&s->chr,
 | 
				
			||||||
        qemu_chr_add_handlers(s->chr,
 | 
					 | 
				
			||||||
                             serial_can_receive, serial_receive,
 | 
					                             serial_can_receive, serial_receive,
 | 
				
			||||||
                              serial_event, s);
 | 
					                             serial_event, s, NULL, true);
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void etraxfs_ser_class_init(ObjectClass *klass, void *data)
 | 
					static void etraxfs_ser_class_init(ObjectClass *klass, void *data)
 | 
				
			||||||
 | 
				
			|||||||
@ -181,7 +181,7 @@ typedef struct Exynos4210UartState {
 | 
				
			|||||||
    Exynos4210UartFIFO   rx;
 | 
					    Exynos4210UartFIFO   rx;
 | 
				
			||||||
    Exynos4210UartFIFO   tx;
 | 
					    Exynos4210UartFIFO   tx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    CharDriverState  *chr;
 | 
					    CharBackend       chr;
 | 
				
			||||||
    qemu_irq          irq;
 | 
					    qemu_irq          irq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint32_t channel;
 | 
					    uint32_t channel;
 | 
				
			||||||
@ -346,7 +346,7 @@ static void exynos4210_uart_update_parameters(Exynos4210UartState *s)
 | 
				
			|||||||
    ssp.data_bits = data_bits;
 | 
					    ssp.data_bits = data_bits;
 | 
				
			||||||
    ssp.stop_bits = stop_bits;
 | 
					    ssp.stop_bits = stop_bits;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
 | 
					    qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    PRINT_DEBUG("UART%d: speed: %d, parity: %c, data: %d, stop: %d\n",
 | 
					    PRINT_DEBUG("UART%d: speed: %d, parity: %c, data: %d, stop: %d\n",
 | 
				
			||||||
                s->channel, speed, parity, data_bits, stop_bits);
 | 
					                s->channel, speed, parity, data_bits, stop_bits);
 | 
				
			||||||
@ -383,13 +383,13 @@ static void exynos4210_uart_write(void *opaque, hwaddr offset,
 | 
				
			|||||||
        break;
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case UTXH:
 | 
					    case UTXH:
 | 
				
			||||||
        if (s->chr) {
 | 
					        if (qemu_chr_fe_get_driver(&s->chr)) {
 | 
				
			||||||
            s->reg[I_(UTRSTAT)] &= ~(UTRSTAT_TRANSMITTER_EMPTY |
 | 
					            s->reg[I_(UTRSTAT)] &= ~(UTRSTAT_TRANSMITTER_EMPTY |
 | 
				
			||||||
                    UTRSTAT_Tx_BUFFER_EMPTY);
 | 
					                    UTRSTAT_Tx_BUFFER_EMPTY);
 | 
				
			||||||
            ch = (uint8_t)val;
 | 
					            ch = (uint8_t)val;
 | 
				
			||||||
            /* XXX this blocks entire thread. Rewrite to use
 | 
					            /* XXX this blocks entire thread. Rewrite to use
 | 
				
			||||||
             * qemu_chr_fe_write and background I/O callbacks */
 | 
					             * qemu_chr_fe_write and background I/O callbacks */
 | 
				
			||||||
            qemu_chr_fe_write_all(s->chr, &ch, 1);
 | 
					            qemu_chr_fe_write_all(&s->chr, &ch, 1);
 | 
				
			||||||
#if DEBUG_Tx_DATA
 | 
					#if DEBUG_Tx_DATA
 | 
				
			||||||
            fprintf(stderr, "%c", ch);
 | 
					            fprintf(stderr, "%c", ch);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
@ -606,7 +606,7 @@ DeviceState *exynos4210_uart_create(hwaddr addr,
 | 
				
			|||||||
        chr = serial_hds[channel];
 | 
					        chr = serial_hds[channel];
 | 
				
			||||||
        if (!chr) {
 | 
					        if (!chr) {
 | 
				
			||||||
            snprintf(label, ARRAY_SIZE(label), "%s%d", chr_name, channel);
 | 
					            snprintf(label, ARRAY_SIZE(label), "%s%d", chr_name, channel);
 | 
				
			||||||
            chr = qemu_chr_new(label, "null", NULL);
 | 
					            chr = qemu_chr_new(label, "null");
 | 
				
			||||||
            if (!(chr)) {
 | 
					            if (!(chr)) {
 | 
				
			||||||
                error_report("Can't assign serial port to UART%d", channel);
 | 
					                error_report("Can't assign serial port to UART%d", channel);
 | 
				
			||||||
                exit(1);
 | 
					                exit(1);
 | 
				
			||||||
@ -640,8 +640,9 @@ static int exynos4210_uart_init(SysBusDevice *dev)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    sysbus_init_irq(dev, &s->irq);
 | 
					    sysbus_init_irq(dev, &s->irq);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qemu_chr_add_handlers(s->chr, exynos4210_uart_can_receive,
 | 
					    qemu_chr_fe_set_handlers(&s->chr, exynos4210_uart_can_receive,
 | 
				
			||||||
                          exynos4210_uart_receive, exynos4210_uart_event, s);
 | 
					                             exynos4210_uart_receive, exynos4210_uart_event,
 | 
				
			||||||
 | 
					                             s, NULL, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -78,7 +78,7 @@ typedef struct UART {
 | 
				
			|||||||
    MemoryRegion iomem;
 | 
					    MemoryRegion iomem;
 | 
				
			||||||
    qemu_irq irq;
 | 
					    qemu_irq irq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    CharDriverState *chr;
 | 
					    CharBackend chr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* registers */
 | 
					    /* registers */
 | 
				
			||||||
    uint32_t status;
 | 
					    uint32_t status;
 | 
				
			||||||
@ -201,11 +201,12 @@ static void grlib_apbuart_write(void *opaque, hwaddr addr,
 | 
				
			|||||||
    case DATA_OFFSET:
 | 
					    case DATA_OFFSET:
 | 
				
			||||||
    case DATA_OFFSET + 3:       /* When only one byte write */
 | 
					    case DATA_OFFSET + 3:       /* When only one byte write */
 | 
				
			||||||
        /* Transmit when character device available and transmitter enabled */
 | 
					        /* Transmit when character device available and transmitter enabled */
 | 
				
			||||||
        if ((uart->chr) && (uart->control & UART_TRANSMIT_ENABLE)) {
 | 
					        if (qemu_chr_fe_get_driver(&uart->chr) &&
 | 
				
			||||||
 | 
					            (uart->control & UART_TRANSMIT_ENABLE)) {
 | 
				
			||||||
            c = value & 0xFF;
 | 
					            c = value & 0xFF;
 | 
				
			||||||
            /* XXX this blocks entire thread. Rewrite to use
 | 
					            /* XXX this blocks entire thread. Rewrite to use
 | 
				
			||||||
             * qemu_chr_fe_write and background I/O callbacks */
 | 
					             * qemu_chr_fe_write and background I/O callbacks */
 | 
				
			||||||
            qemu_chr_fe_write_all(uart->chr, &c, 1);
 | 
					            qemu_chr_fe_write_all(&uart->chr, &c, 1);
 | 
				
			||||||
            /* Generate interrupt */
 | 
					            /* Generate interrupt */
 | 
				
			||||||
            if (uart->control & UART_TRANSMIT_INTERRUPT) {
 | 
					            if (uart->control & UART_TRANSMIT_INTERRUPT) {
 | 
				
			||||||
                qemu_irq_pulse(uart->irq);
 | 
					                qemu_irq_pulse(uart->irq);
 | 
				
			||||||
@ -242,11 +243,11 @@ static int grlib_apbuart_init(SysBusDevice *dev)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    UART *uart = GRLIB_APB_UART(dev);
 | 
					    UART *uart = GRLIB_APB_UART(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qemu_chr_add_handlers(uart->chr,
 | 
					    qemu_chr_fe_set_handlers(&uart->chr,
 | 
				
			||||||
                             grlib_apbuart_can_receive,
 | 
					                             grlib_apbuart_can_receive,
 | 
				
			||||||
                             grlib_apbuart_receive,
 | 
					                             grlib_apbuart_receive,
 | 
				
			||||||
                             grlib_apbuart_event,
 | 
					                             grlib_apbuart_event,
 | 
				
			||||||
                          uart);
 | 
					                             uart, NULL, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sysbus_init_irq(dev, &uart->irq);
 | 
					    sysbus_init_irq(dev, &uart->irq);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -121,9 +121,7 @@ static uint64_t imx_serial_read(void *opaque, hwaddr offset,
 | 
				
			|||||||
            s->usr2 &= ~USR2_RDR;
 | 
					            s->usr2 &= ~USR2_RDR;
 | 
				
			||||||
            s->uts1 |= UTS1_RXEMPTY;
 | 
					            s->uts1 |= UTS1_RXEMPTY;
 | 
				
			||||||
            imx_update(s);
 | 
					            imx_update(s);
 | 
				
			||||||
            if (s->chr) {
 | 
					            qemu_chr_fe_accept_input(&s->chr);
 | 
				
			||||||
                qemu_chr_accept_input(s->chr);
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        return c;
 | 
					        return c;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -172,20 +170,19 @@ static void imx_serial_write(void *opaque, hwaddr offset,
 | 
				
			|||||||
                             uint64_t value, unsigned size)
 | 
					                             uint64_t value, unsigned size)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    IMXSerialState *s = (IMXSerialState *)opaque;
 | 
					    IMXSerialState *s = (IMXSerialState *)opaque;
 | 
				
			||||||
 | 
					    CharDriverState *chr = qemu_chr_fe_get_driver(&s->chr);
 | 
				
			||||||
    unsigned char ch;
 | 
					    unsigned char ch;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    DPRINTF("write(offset=0x%" HWADDR_PRIx ", value = 0x%x) to %s\n",
 | 
					    DPRINTF("write(offset=0x%" HWADDR_PRIx ", value = 0x%x) to %s\n",
 | 
				
			||||||
            offset, (unsigned int)value, s->chr ? s->chr->label : "NODEV");
 | 
					            offset, (unsigned int)value, chr ? chr->label : "NODEV");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    switch (offset >> 2) {
 | 
					    switch (offset >> 2) {
 | 
				
			||||||
    case 0x10: /* UTXD */
 | 
					    case 0x10: /* UTXD */
 | 
				
			||||||
        ch = value;
 | 
					        ch = value;
 | 
				
			||||||
        if (s->ucr2 & UCR2_TXEN) {
 | 
					        if (s->ucr2 & UCR2_TXEN) {
 | 
				
			||||||
            if (s->chr) {
 | 
					 | 
				
			||||||
            /* XXX this blocks entire thread. Rewrite to use
 | 
					            /* XXX this blocks entire thread. Rewrite to use
 | 
				
			||||||
             * qemu_chr_fe_write and background I/O callbacks */
 | 
					             * qemu_chr_fe_write and background I/O callbacks */
 | 
				
			||||||
                qemu_chr_fe_write_all(s->chr, &ch, 1);
 | 
					            qemu_chr_fe_write_all(&s->chr, &ch, 1);
 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            s->usr1 &= ~USR1_TRDY;
 | 
					            s->usr1 &= ~USR1_TRDY;
 | 
				
			||||||
            imx_update(s);
 | 
					            imx_update(s);
 | 
				
			||||||
            s->usr1 |= USR1_TRDY;
 | 
					            s->usr1 |= USR1_TRDY;
 | 
				
			||||||
@ -214,9 +211,7 @@ static void imx_serial_write(void *opaque, hwaddr offset,
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        if (value & UCR2_RXEN) {
 | 
					        if (value & UCR2_RXEN) {
 | 
				
			||||||
            if (!(s->ucr2 & UCR2_RXEN)) {
 | 
					            if (!(s->ucr2 & UCR2_RXEN)) {
 | 
				
			||||||
                if (s->chr) {
 | 
					                qemu_chr_fe_accept_input(&s->chr);
 | 
				
			||||||
                    qemu_chr_accept_input(s->chr);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        s->ucr2 = value & 0xffff;
 | 
					        s->ucr2 = value & 0xffff;
 | 
				
			||||||
@ -318,12 +313,10 @@ static void imx_serial_realize(DeviceState *dev, Error **errp)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    IMXSerialState *s = IMX_SERIAL(dev);
 | 
					    IMXSerialState *s = IMX_SERIAL(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (s->chr) {
 | 
					    DPRINTF("char dev for uart: %p\n", qemu_chr_fe_get_driver(&s->chr));
 | 
				
			||||||
        qemu_chr_add_handlers(s->chr, imx_can_receive, imx_receive,
 | 
					
 | 
				
			||||||
                              imx_event, s);
 | 
					    qemu_chr_fe_set_handlers(&s->chr, imx_can_receive, imx_receive,
 | 
				
			||||||
    } else {
 | 
					                             imx_event, s, NULL, true);
 | 
				
			||||||
        DPRINTF("No char dev for uart\n");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void imx_serial_init(Object *obj)
 | 
					static void imx_serial_init(Object *obj)
 | 
				
			||||||
 | 
				
			|||||||
@ -93,7 +93,7 @@ typedef struct SCC2698Block SCC2698Block;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
struct SCC2698Channel {
 | 
					struct SCC2698Channel {
 | 
				
			||||||
    IPOctalState *ipoctal;
 | 
					    IPOctalState *ipoctal;
 | 
				
			||||||
    CharDriverState *dev;
 | 
					    CharBackend dev;
 | 
				
			||||||
    bool rx_enabled;
 | 
					    bool rx_enabled;
 | 
				
			||||||
    uint8_t mr[2];
 | 
					    uint8_t mr[2];
 | 
				
			||||||
    uint8_t mr_idx;
 | 
					    uint8_t mr_idx;
 | 
				
			||||||
@ -288,9 +288,7 @@ static uint16_t io_read(IPackDevice *ip, uint8_t addr)
 | 
				
			|||||||
            if (ch->rx_pending == 0) {
 | 
					            if (ch->rx_pending == 0) {
 | 
				
			||||||
                ch->sr &= ~SR_RXRDY;
 | 
					                ch->sr &= ~SR_RXRDY;
 | 
				
			||||||
                blk->isr &= ~ISR_RXRDY(channel);
 | 
					                blk->isr &= ~ISR_RXRDY(channel);
 | 
				
			||||||
                if (ch->dev) {
 | 
					                qemu_chr_fe_accept_input(&ch->dev);
 | 
				
			||||||
                    qemu_chr_accept_input(ch->dev);
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                ch->rhr_idx = (ch->rhr_idx + 1) % RX_FIFO_SIZE;
 | 
					                ch->rhr_idx = (ch->rhr_idx + 1) % RX_FIFO_SIZE;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -357,13 +355,11 @@ static void io_write(IPackDevice *ip, uint8_t addr, uint16_t val)
 | 
				
			|||||||
    case REG_THRa:
 | 
					    case REG_THRa:
 | 
				
			||||||
    case REG_THRb:
 | 
					    case REG_THRb:
 | 
				
			||||||
        if (ch->sr & SR_TXRDY) {
 | 
					        if (ch->sr & SR_TXRDY) {
 | 
				
			||||||
            DPRINTF("Write THR%c (0x%x)\n", channel + 'a', reg);
 | 
					 | 
				
			||||||
            if (ch->dev) {
 | 
					 | 
				
			||||||
            uint8_t thr = reg;
 | 
					            uint8_t thr = reg;
 | 
				
			||||||
 | 
					            DPRINTF("Write THR%c (0x%x)\n", channel + 'a', reg);
 | 
				
			||||||
            /* XXX this blocks entire thread. Rewrite to use
 | 
					            /* XXX this blocks entire thread. Rewrite to use
 | 
				
			||||||
             * qemu_chr_fe_write and background I/O callbacks */
 | 
					             * qemu_chr_fe_write and background I/O callbacks */
 | 
				
			||||||
                qemu_chr_fe_write_all(ch->dev, &thr, 1);
 | 
					            qemu_chr_fe_write_all(&ch->dev, &thr, 1);
 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            DPRINTF("Write THR%c (0x%x), Tx disabled\n", channel + 'a', reg);
 | 
					            DPRINTF("Write THR%c (0x%x), Tx disabled\n", channel + 'a', reg);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -546,9 +542,10 @@ static void ipoctal_realize(DeviceState *dev, Error **errp)
 | 
				
			|||||||
        ch->ipoctal = s;
 | 
					        ch->ipoctal = s;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* Redirect IP-Octal channels to host character devices */
 | 
					        /* Redirect IP-Octal channels to host character devices */
 | 
				
			||||||
        if (ch->dev) {
 | 
					        if (qemu_chr_fe_get_driver(&ch->dev)) {
 | 
				
			||||||
            qemu_chr_add_handlers(ch->dev, hostdev_can_receive,
 | 
					            qemu_chr_fe_set_handlers(&ch->dev, hostdev_can_receive,
 | 
				
			||||||
                                  hostdev_receive, hostdev_event, ch);
 | 
					                                     hostdev_receive, hostdev_event,
 | 
				
			||||||
 | 
					                                     ch, NULL, true);
 | 
				
			||||||
            DPRINTF("Redirecting channel %u to %s\n", i, ch->dev->label);
 | 
					            DPRINTF("Redirecting channel %u to %s\n", i, ch->dev->label);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            DPRINTF("Could not redirect channel %u, no chardev set\n", i);
 | 
					            DPRINTF("Could not redirect channel %u, no chardev set\n", i);
 | 
				
			||||||
 | 
				
			|||||||
@ -44,7 +44,7 @@ enum {
 | 
				
			|||||||
struct LM32JuartState {
 | 
					struct LM32JuartState {
 | 
				
			||||||
    SysBusDevice parent_obj;
 | 
					    SysBusDevice parent_obj;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    CharDriverState *chr;
 | 
					    CharBackend chr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint32_t jtx;
 | 
					    uint32_t jtx;
 | 
				
			||||||
    uint32_t jrx;
 | 
					    uint32_t jrx;
 | 
				
			||||||
@ -75,11 +75,9 @@ void lm32_juart_set_jtx(DeviceState *d, uint32_t jtx)
 | 
				
			|||||||
    trace_lm32_juart_set_jtx(s->jtx);
 | 
					    trace_lm32_juart_set_jtx(s->jtx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->jtx = jtx;
 | 
					    s->jtx = jtx;
 | 
				
			||||||
    if (s->chr) {
 | 
					 | 
				
			||||||
    /* XXX this blocks entire thread. Rewrite to use
 | 
					    /* XXX this blocks entire thread. Rewrite to use
 | 
				
			||||||
     * qemu_chr_fe_write and background I/O callbacks */
 | 
					     * qemu_chr_fe_write and background I/O callbacks */
 | 
				
			||||||
        qemu_chr_fe_write_all(s->chr, &ch, 1);
 | 
					    qemu_chr_fe_write_all(&s->chr, &ch, 1);
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void lm32_juart_set_jrx(DeviceState *d, uint32_t jtx)
 | 
					void lm32_juart_set_jrx(DeviceState *d, uint32_t jtx)
 | 
				
			||||||
@ -120,9 +118,8 @@ static void lm32_juart_realize(DeviceState *dev, Error **errp)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    LM32JuartState *s = LM32_JUART(dev);
 | 
					    LM32JuartState *s = LM32_JUART(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (s->chr) {
 | 
					    qemu_chr_fe_set_handlers(&s->chr, juart_can_rx, juart_rx,
 | 
				
			||||||
        qemu_chr_add_handlers(s->chr, juart_can_rx, juart_rx, juart_event, s);
 | 
					                             juart_event, s, NULL, true);
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const VMStateDescription vmstate_lm32_juart = {
 | 
					static const VMStateDescription vmstate_lm32_juart = {
 | 
				
			||||||
 | 
				
			|||||||
@ -97,7 +97,7 @@ struct LM32UartState {
 | 
				
			|||||||
    SysBusDevice parent_obj;
 | 
					    SysBusDevice parent_obj;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    MemoryRegion iomem;
 | 
					    MemoryRegion iomem;
 | 
				
			||||||
    CharDriverState *chr;
 | 
					    CharBackend chr;
 | 
				
			||||||
    qemu_irq irq;
 | 
					    qemu_irq irq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint32_t regs[R_MAX];
 | 
					    uint32_t regs[R_MAX];
 | 
				
			||||||
@ -142,7 +142,7 @@ static uint64_t uart_read(void *opaque, hwaddr addr,
 | 
				
			|||||||
        r = s->regs[R_RXTX];
 | 
					        r = s->regs[R_RXTX];
 | 
				
			||||||
        s->regs[R_LSR] &= ~LSR_DR;
 | 
					        s->regs[R_LSR] &= ~LSR_DR;
 | 
				
			||||||
        uart_update_irq(s);
 | 
					        uart_update_irq(s);
 | 
				
			||||||
        qemu_chr_accept_input(s->chr);
 | 
					        qemu_chr_fe_accept_input(&s->chr);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case R_IIR:
 | 
					    case R_IIR:
 | 
				
			||||||
    case R_LSR:
 | 
					    case R_LSR:
 | 
				
			||||||
@ -177,11 +177,9 @@ static void uart_write(void *opaque, hwaddr addr,
 | 
				
			|||||||
    addr >>= 2;
 | 
					    addr >>= 2;
 | 
				
			||||||
    switch (addr) {
 | 
					    switch (addr) {
 | 
				
			||||||
    case R_RXTX:
 | 
					    case R_RXTX:
 | 
				
			||||||
        if (s->chr) {
 | 
					 | 
				
			||||||
        /* XXX this blocks entire thread. Rewrite to use
 | 
					        /* XXX this blocks entire thread. Rewrite to use
 | 
				
			||||||
         * qemu_chr_fe_write and background I/O callbacks */
 | 
					         * qemu_chr_fe_write and background I/O callbacks */
 | 
				
			||||||
            qemu_chr_fe_write_all(s->chr, &ch, 1);
 | 
					        qemu_chr_fe_write_all(&s->chr, &ch, 1);
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case R_IER:
 | 
					    case R_IER:
 | 
				
			||||||
    case R_LCR:
 | 
					    case R_LCR:
 | 
				
			||||||
@ -267,9 +265,8 @@ static void lm32_uart_realize(DeviceState *dev, Error **errp)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    LM32UartState *s = LM32_UART(dev);
 | 
					    LM32UartState *s = LM32_UART(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (s->chr) {
 | 
					    qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx,
 | 
				
			||||||
        qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
 | 
					                             uart_event, s, NULL, true);
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const VMStateDescription vmstate_lm32_uart = {
 | 
					static const VMStateDescription vmstate_lm32_uart = {
 | 
				
			||||||
 | 
				
			|||||||
@ -10,6 +10,7 @@
 | 
				
			|||||||
#include "hw/m68k/mcf.h"
 | 
					#include "hw/m68k/mcf.h"
 | 
				
			||||||
#include "sysemu/char.h"
 | 
					#include "sysemu/char.h"
 | 
				
			||||||
#include "exec/address-spaces.h"
 | 
					#include "exec/address-spaces.h"
 | 
				
			||||||
 | 
					#include "qapi/error.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
    MemoryRegion iomem;
 | 
					    MemoryRegion iomem;
 | 
				
			||||||
@ -26,7 +27,7 @@ typedef struct {
 | 
				
			|||||||
    int tx_enabled;
 | 
					    int tx_enabled;
 | 
				
			||||||
    int rx_enabled;
 | 
					    int rx_enabled;
 | 
				
			||||||
    qemu_irq irq;
 | 
					    qemu_irq irq;
 | 
				
			||||||
    CharDriverState *chr;
 | 
					    CharBackend chr;
 | 
				
			||||||
} mcf_uart_state;
 | 
					} mcf_uart_state;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* UART Status Register bits.  */
 | 
					/* UART Status Register bits.  */
 | 
				
			||||||
@ -92,7 +93,7 @@ uint64_t mcf_uart_read(void *opaque, hwaddr addr,
 | 
				
			|||||||
            if (s->fifo_len == 0)
 | 
					            if (s->fifo_len == 0)
 | 
				
			||||||
                s->sr &= ~MCF_UART_RxRDY;
 | 
					                s->sr &= ~MCF_UART_RxRDY;
 | 
				
			||||||
            mcf_uart_update(s);
 | 
					            mcf_uart_update(s);
 | 
				
			||||||
            qemu_chr_accept_input(s->chr);
 | 
					            qemu_chr_fe_accept_input(&s->chr);
 | 
				
			||||||
            return val;
 | 
					            return val;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    case 0x10:
 | 
					    case 0x10:
 | 
				
			||||||
@ -113,10 +114,9 @@ uint64_t mcf_uart_read(void *opaque, hwaddr addr,
 | 
				
			|||||||
static void mcf_uart_do_tx(mcf_uart_state *s)
 | 
					static void mcf_uart_do_tx(mcf_uart_state *s)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (s->tx_enabled && (s->sr & MCF_UART_TxEMP) == 0) {
 | 
					    if (s->tx_enabled && (s->sr & MCF_UART_TxEMP) == 0) {
 | 
				
			||||||
        if (s->chr)
 | 
					 | 
				
			||||||
        /* XXX this blocks entire thread. Rewrite to use
 | 
					        /* XXX this blocks entire thread. Rewrite to use
 | 
				
			||||||
         * qemu_chr_fe_write and background I/O callbacks */
 | 
					         * qemu_chr_fe_write and background I/O callbacks */
 | 
				
			||||||
            qemu_chr_fe_write_all(s->chr, (unsigned char *)&s->tb, 1);
 | 
					        qemu_chr_fe_write_all(&s->chr, (unsigned char *)&s->tb, 1);
 | 
				
			||||||
        s->sr |= MCF_UART_TxEMP;
 | 
					        s->sr |= MCF_UART_TxEMP;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (s->tx_enabled) {
 | 
					    if (s->tx_enabled) {
 | 
				
			||||||
@ -280,12 +280,12 @@ void *mcf_uart_init(qemu_irq irq, CharDriverState *chr)
 | 
				
			|||||||
    mcf_uart_state *s;
 | 
					    mcf_uart_state *s;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s = g_malloc0(sizeof(mcf_uart_state));
 | 
					    s = g_malloc0(sizeof(mcf_uart_state));
 | 
				
			||||||
    s->chr = chr;
 | 
					 | 
				
			||||||
    s->irq = irq;
 | 
					    s->irq = irq;
 | 
				
			||||||
    if (chr) {
 | 
					    if (chr) {
 | 
				
			||||||
        qemu_chr_fe_claim_no_fail(chr);
 | 
					        qemu_chr_fe_init(&s->chr, chr, &error_abort);
 | 
				
			||||||
        qemu_chr_add_handlers(chr, mcf_uart_can_receive, mcf_uart_receive,
 | 
					        qemu_chr_fe_set_handlers(&s->chr, mcf_uart_can_receive,
 | 
				
			||||||
                              mcf_uart_event, s);
 | 
					                                 mcf_uart_receive, mcf_uart_event,
 | 
				
			||||||
 | 
					                                 s, NULL, true);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    mcf_uart_reset(s);
 | 
					    mcf_uart_reset(s);
 | 
				
			||||||
    return s;
 | 
					    return s;
 | 
				
			||||||
 | 
				
			|||||||
@ -61,7 +61,7 @@ struct MilkymistUartState {
 | 
				
			|||||||
    SysBusDevice parent_obj;
 | 
					    SysBusDevice parent_obj;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    MemoryRegion regs_region;
 | 
					    MemoryRegion regs_region;
 | 
				
			||||||
    CharDriverState *chr;
 | 
					    CharBackend chr;
 | 
				
			||||||
    qemu_irq irq;
 | 
					    qemu_irq irq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint32_t regs[R_MAX];
 | 
					    uint32_t regs[R_MAX];
 | 
				
			||||||
@ -124,9 +124,7 @@ static void uart_write(void *opaque, hwaddr addr, uint64_t value,
 | 
				
			|||||||
    addr >>= 2;
 | 
					    addr >>= 2;
 | 
				
			||||||
    switch (addr) {
 | 
					    switch (addr) {
 | 
				
			||||||
    case R_RXTX:
 | 
					    case R_RXTX:
 | 
				
			||||||
        if (s->chr) {
 | 
					        qemu_chr_fe_write_all(&s->chr, &ch, 1);
 | 
				
			||||||
            qemu_chr_fe_write_all(s->chr, &ch, 1);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        s->regs[R_STAT] |= STAT_TX_EVT;
 | 
					        s->regs[R_STAT] |= STAT_TX_EVT;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case R_DIV:
 | 
					    case R_DIV:
 | 
				
			||||||
@ -138,7 +136,7 @@ static void uart_write(void *opaque, hwaddr addr, uint64_t value,
 | 
				
			|||||||
    case R_STAT:
 | 
					    case R_STAT:
 | 
				
			||||||
        /* write one to clear bits */
 | 
					        /* write one to clear bits */
 | 
				
			||||||
        s->regs[addr] &= ~(value & (STAT_RX_EVT | STAT_TX_EVT));
 | 
					        s->regs[addr] &= ~(value & (STAT_RX_EVT | STAT_TX_EVT));
 | 
				
			||||||
        qemu_chr_accept_input(s->chr);
 | 
					        qemu_chr_fe_accept_input(&s->chr);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
@ -200,9 +198,8 @@ static void milkymist_uart_realize(DeviceState *dev, Error **errp)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    MilkymistUartState *s = MILKYMIST_UART(dev);
 | 
					    MilkymistUartState *s = MILKYMIST_UART(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (s->chr) {
 | 
					    qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx,
 | 
				
			||||||
        qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
 | 
					                             uart_event, s, NULL, true);
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void milkymist_uart_init(Object *obj)
 | 
					static void milkymist_uart_init(Object *obj)
 | 
				
			||||||
 | 
				
			|||||||
@ -63,7 +63,7 @@ struct omap_uart_s *omap_uart_init(hwaddr base,
 | 
				
			|||||||
    s->irq = irq;
 | 
					    s->irq = irq;
 | 
				
			||||||
    s->serial = serial_mm_init(get_system_memory(), base, 2, irq,
 | 
					    s->serial = serial_mm_init(get_system_memory(), base, 2, irq,
 | 
				
			||||||
                               omap_clk_getrate(fclk)/16,
 | 
					                               omap_clk_getrate(fclk)/16,
 | 
				
			||||||
                               chr ?: qemu_chr_new(label, "null", NULL),
 | 
					                               chr ?: qemu_chr_new(label, "null"),
 | 
				
			||||||
                               DEVICE_NATIVE_ENDIAN);
 | 
					                               DEVICE_NATIVE_ENDIAN);
 | 
				
			||||||
    return s;
 | 
					    return s;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -183,6 +183,6 @@ void omap_uart_attach(struct omap_uart_s *s, CharDriverState *chr)
 | 
				
			|||||||
    /* TODO: Should reuse or destroy current s->serial */
 | 
					    /* TODO: Should reuse or destroy current s->serial */
 | 
				
			||||||
    s->serial = serial_mm_init(get_system_memory(), s->base, 2, s->irq,
 | 
					    s->serial = serial_mm_init(get_system_memory(), s->base, 2, s->irq,
 | 
				
			||||||
                               omap_clk_getrate(s->fclk) / 16,
 | 
					                               omap_clk_getrate(s->fclk) / 16,
 | 
				
			||||||
                               chr ?: qemu_chr_new("null", "null", NULL),
 | 
					                               chr ?: qemu_chr_new("null", "null"),
 | 
				
			||||||
                               DEVICE_NATIVE_ENDIAN);
 | 
					                               DEVICE_NATIVE_ENDIAN);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -74,7 +74,7 @@ typedef struct ParallelState {
 | 
				
			|||||||
    uint8_t control;
 | 
					    uint8_t control;
 | 
				
			||||||
    qemu_irq irq;
 | 
					    qemu_irq irq;
 | 
				
			||||||
    int irq_pending;
 | 
					    int irq_pending;
 | 
				
			||||||
    CharDriverState *chr;
 | 
					    CharBackend chr;
 | 
				
			||||||
    int hw_driver;
 | 
					    int hw_driver;
 | 
				
			||||||
    int epp_timeout;
 | 
					    int epp_timeout;
 | 
				
			||||||
    uint32_t last_read_offset; /* For debugging */
 | 
					    uint32_t last_read_offset; /* For debugging */
 | 
				
			||||||
@ -131,7 +131,7 @@ parallel_ioport_write_sw(void *opaque, uint32_t addr, uint32_t val)
 | 
				
			|||||||
                if ((s->control & PARA_CTR_STROBE) == 0)
 | 
					                if ((s->control & PARA_CTR_STROBE) == 0)
 | 
				
			||||||
                    /* XXX this blocks entire thread. Rewrite to use
 | 
					                    /* XXX this blocks entire thread. Rewrite to use
 | 
				
			||||||
                     * qemu_chr_fe_write and background I/O callbacks */
 | 
					                     * qemu_chr_fe_write and background I/O callbacks */
 | 
				
			||||||
                    qemu_chr_fe_write_all(s->chr, &s->dataw, 1);
 | 
					                    qemu_chr_fe_write_all(&s->chr, &s->dataw, 1);
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                if (s->control & PARA_CTR_INTEN) {
 | 
					                if (s->control & PARA_CTR_INTEN) {
 | 
				
			||||||
                    s->irq_pending = 1;
 | 
					                    s->irq_pending = 1;
 | 
				
			||||||
@ -161,7 +161,7 @@ static void parallel_ioport_write_hw(void *opaque, uint32_t addr, uint32_t val)
 | 
				
			|||||||
        if (s->dataw == val)
 | 
					        if (s->dataw == val)
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        pdebug("wd%02x\n", val);
 | 
					        pdebug("wd%02x\n", val);
 | 
				
			||||||
        qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_WRITE_DATA, &parm);
 | 
					        qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_PP_WRITE_DATA, &parm);
 | 
				
			||||||
        s->dataw = val;
 | 
					        s->dataw = val;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case PARA_REG_STS:
 | 
					    case PARA_REG_STS:
 | 
				
			||||||
@ -181,11 +181,11 @@ static void parallel_ioport_write_hw(void *opaque, uint32_t addr, uint32_t val)
 | 
				
			|||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                dir = 0;
 | 
					                dir = 0;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_DATA_DIR, &dir);
 | 
					            qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_PP_DATA_DIR, &dir);
 | 
				
			||||||
            parm &= ~PARA_CTR_DIR;
 | 
					            parm &= ~PARA_CTR_DIR;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_WRITE_CONTROL, &parm);
 | 
					        qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_PP_WRITE_CONTROL, &parm);
 | 
				
			||||||
        s->control = val;
 | 
					        s->control = val;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case PARA_REG_EPP_ADDR:
 | 
					    case PARA_REG_EPP_ADDR:
 | 
				
			||||||
@ -194,7 +194,8 @@ static void parallel_ioport_write_hw(void *opaque, uint32_t addr, uint32_t val)
 | 
				
			|||||||
            pdebug("wa%02x s\n", val);
 | 
					            pdebug("wa%02x s\n", val);
 | 
				
			||||||
        else {
 | 
					        else {
 | 
				
			||||||
            struct ParallelIOArg ioarg = { .buffer = &parm, .count = 1 };
 | 
					            struct ParallelIOArg ioarg = { .buffer = &parm, .count = 1 };
 | 
				
			||||||
            if (qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_EPP_WRITE_ADDR, &ioarg)) {
 | 
					            if (qemu_chr_fe_ioctl(&s->chr,
 | 
				
			||||||
 | 
					                                  CHR_IOCTL_PP_EPP_WRITE_ADDR, &ioarg)) {
 | 
				
			||||||
                s->epp_timeout = 1;
 | 
					                s->epp_timeout = 1;
 | 
				
			||||||
                pdebug("wa%02x t\n", val);
 | 
					                pdebug("wa%02x t\n", val);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -208,7 +209,7 @@ static void parallel_ioport_write_hw(void *opaque, uint32_t addr, uint32_t val)
 | 
				
			|||||||
            pdebug("we%02x s\n", val);
 | 
					            pdebug("we%02x s\n", val);
 | 
				
			||||||
        else {
 | 
					        else {
 | 
				
			||||||
            struct ParallelIOArg ioarg = { .buffer = &parm, .count = 1 };
 | 
					            struct ParallelIOArg ioarg = { .buffer = &parm, .count = 1 };
 | 
				
			||||||
            if (qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_EPP_WRITE, &ioarg)) {
 | 
					            if (qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_PP_EPP_WRITE, &ioarg)) {
 | 
				
			||||||
                s->epp_timeout = 1;
 | 
					                s->epp_timeout = 1;
 | 
				
			||||||
                pdebug("we%02x t\n", val);
 | 
					                pdebug("we%02x t\n", val);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -233,7 +234,7 @@ parallel_ioport_eppdata_write_hw2(void *opaque, uint32_t addr, uint32_t val)
 | 
				
			|||||||
        pdebug("we%04x s\n", val);
 | 
					        pdebug("we%04x s\n", val);
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    err = qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_EPP_WRITE, &ioarg);
 | 
					    err = qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_PP_EPP_WRITE, &ioarg);
 | 
				
			||||||
    if (err) {
 | 
					    if (err) {
 | 
				
			||||||
        s->epp_timeout = 1;
 | 
					        s->epp_timeout = 1;
 | 
				
			||||||
        pdebug("we%04x t\n", val);
 | 
					        pdebug("we%04x t\n", val);
 | 
				
			||||||
@ -256,7 +257,7 @@ parallel_ioport_eppdata_write_hw4(void *opaque, uint32_t addr, uint32_t val)
 | 
				
			|||||||
        pdebug("we%08x s\n", val);
 | 
					        pdebug("we%08x s\n", val);
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    err = qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_EPP_WRITE, &ioarg);
 | 
					    err = qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_PP_EPP_WRITE, &ioarg);
 | 
				
			||||||
    if (err) {
 | 
					    if (err) {
 | 
				
			||||||
        s->epp_timeout = 1;
 | 
					        s->epp_timeout = 1;
 | 
				
			||||||
        pdebug("we%08x t\n", val);
 | 
					        pdebug("we%08x t\n", val);
 | 
				
			||||||
@ -308,13 +309,13 @@ static uint32_t parallel_ioport_read_hw(void *opaque, uint32_t addr)
 | 
				
			|||||||
    addr &= 7;
 | 
					    addr &= 7;
 | 
				
			||||||
    switch(addr) {
 | 
					    switch(addr) {
 | 
				
			||||||
    case PARA_REG_DATA:
 | 
					    case PARA_REG_DATA:
 | 
				
			||||||
        qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_READ_DATA, &ret);
 | 
					        qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_PP_READ_DATA, &ret);
 | 
				
			||||||
        if (s->last_read_offset != addr || s->datar != ret)
 | 
					        if (s->last_read_offset != addr || s->datar != ret)
 | 
				
			||||||
            pdebug("rd%02x\n", ret);
 | 
					            pdebug("rd%02x\n", ret);
 | 
				
			||||||
        s->datar = ret;
 | 
					        s->datar = ret;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case PARA_REG_STS:
 | 
					    case PARA_REG_STS:
 | 
				
			||||||
        qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_READ_STATUS, &ret);
 | 
					        qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_PP_READ_STATUS, &ret);
 | 
				
			||||||
        ret &= ~PARA_STS_TMOUT;
 | 
					        ret &= ~PARA_STS_TMOUT;
 | 
				
			||||||
        if (s->epp_timeout)
 | 
					        if (s->epp_timeout)
 | 
				
			||||||
            ret |= PARA_STS_TMOUT;
 | 
					            ret |= PARA_STS_TMOUT;
 | 
				
			||||||
@ -326,7 +327,7 @@ static uint32_t parallel_ioport_read_hw(void *opaque, uint32_t addr)
 | 
				
			|||||||
        /* s->control has some bits fixed to 1. It is zero only when
 | 
					        /* s->control has some bits fixed to 1. It is zero only when
 | 
				
			||||||
           it has not been yet written to.  */
 | 
					           it has not been yet written to.  */
 | 
				
			||||||
        if (s->control == 0) {
 | 
					        if (s->control == 0) {
 | 
				
			||||||
            qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_READ_CONTROL, &ret);
 | 
					            qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_PP_READ_CONTROL, &ret);
 | 
				
			||||||
            if (s->last_read_offset != addr)
 | 
					            if (s->last_read_offset != addr)
 | 
				
			||||||
                pdebug("rc%02x\n", ret);
 | 
					                pdebug("rc%02x\n", ret);
 | 
				
			||||||
            s->control = ret;
 | 
					            s->control = ret;
 | 
				
			||||||
@ -338,12 +339,14 @@ static uint32_t parallel_ioport_read_hw(void *opaque, uint32_t addr)
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case PARA_REG_EPP_ADDR:
 | 
					    case PARA_REG_EPP_ADDR:
 | 
				
			||||||
        if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != (PARA_CTR_DIR|PARA_CTR_INIT))
 | 
					        if ((s->control & (PARA_CTR_DIR | PARA_CTR_SIGNAL)) !=
 | 
				
			||||||
 | 
					            (PARA_CTR_DIR | PARA_CTR_INIT))
 | 
				
			||||||
            /* Controls not correct for EPP addr cycle, so do nothing */
 | 
					            /* Controls not correct for EPP addr cycle, so do nothing */
 | 
				
			||||||
            pdebug("ra%02x s\n", ret);
 | 
					            pdebug("ra%02x s\n", ret);
 | 
				
			||||||
        else {
 | 
					        else {
 | 
				
			||||||
            struct ParallelIOArg ioarg = { .buffer = &ret, .count = 1 };
 | 
					            struct ParallelIOArg ioarg = { .buffer = &ret, .count = 1 };
 | 
				
			||||||
            if (qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_EPP_READ_ADDR, &ioarg)) {
 | 
					            if (qemu_chr_fe_ioctl(&s->chr,
 | 
				
			||||||
 | 
					                                  CHR_IOCTL_PP_EPP_READ_ADDR, &ioarg)) {
 | 
				
			||||||
                s->epp_timeout = 1;
 | 
					                s->epp_timeout = 1;
 | 
				
			||||||
                pdebug("ra%02x t\n", ret);
 | 
					                pdebug("ra%02x t\n", ret);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -352,12 +355,13 @@ static uint32_t parallel_ioport_read_hw(void *opaque, uint32_t addr)
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case PARA_REG_EPP_DATA:
 | 
					    case PARA_REG_EPP_DATA:
 | 
				
			||||||
        if ((s->control & (PARA_CTR_DIR|PARA_CTR_SIGNAL)) != (PARA_CTR_DIR|PARA_CTR_INIT))
 | 
					        if ((s->control & (PARA_CTR_DIR | PARA_CTR_SIGNAL)) !=
 | 
				
			||||||
 | 
					            (PARA_CTR_DIR | PARA_CTR_INIT))
 | 
				
			||||||
            /* Controls not correct for EPP data cycle, so do nothing */
 | 
					            /* Controls not correct for EPP data cycle, so do nothing */
 | 
				
			||||||
            pdebug("re%02x s\n", ret);
 | 
					            pdebug("re%02x s\n", ret);
 | 
				
			||||||
        else {
 | 
					        else {
 | 
				
			||||||
            struct ParallelIOArg ioarg = { .buffer = &ret, .count = 1 };
 | 
					            struct ParallelIOArg ioarg = { .buffer = &ret, .count = 1 };
 | 
				
			||||||
            if (qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_EPP_READ, &ioarg)) {
 | 
					            if (qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_PP_EPP_READ, &ioarg)) {
 | 
				
			||||||
                s->epp_timeout = 1;
 | 
					                s->epp_timeout = 1;
 | 
				
			||||||
                pdebug("re%02x t\n", ret);
 | 
					                pdebug("re%02x t\n", ret);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -385,7 +389,7 @@ parallel_ioport_eppdata_read_hw2(void *opaque, uint32_t addr)
 | 
				
			|||||||
        pdebug("re%04x s\n", eppdata);
 | 
					        pdebug("re%04x s\n", eppdata);
 | 
				
			||||||
        return eppdata;
 | 
					        return eppdata;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    err = qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_EPP_READ, &ioarg);
 | 
					    err = qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_PP_EPP_READ, &ioarg);
 | 
				
			||||||
    ret = le16_to_cpu(eppdata);
 | 
					    ret = le16_to_cpu(eppdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (err) {
 | 
					    if (err) {
 | 
				
			||||||
@ -412,7 +416,7 @@ parallel_ioport_eppdata_read_hw4(void *opaque, uint32_t addr)
 | 
				
			|||||||
        pdebug("re%08x s\n", eppdata);
 | 
					        pdebug("re%08x s\n", eppdata);
 | 
				
			||||||
        return eppdata;
 | 
					        return eppdata;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    err = qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_EPP_READ, &ioarg);
 | 
					    err = qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_PP_EPP_READ, &ioarg);
 | 
				
			||||||
    ret = le32_to_cpu(eppdata);
 | 
					    ret = le32_to_cpu(eppdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (err) {
 | 
					    if (err) {
 | 
				
			||||||
@ -508,7 +512,7 @@ static void parallel_isa_realizefn(DeviceState *dev, Error **errp)
 | 
				
			|||||||
    int base;
 | 
					    int base;
 | 
				
			||||||
    uint8_t dummy;
 | 
					    uint8_t dummy;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!s->chr) {
 | 
					    if (!qemu_chr_fe_get_driver(&s->chr)) {
 | 
				
			||||||
        error_setg(errp, "Can't create parallel device, empty char device");
 | 
					        error_setg(errp, "Can't create parallel device, empty char device");
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -530,7 +534,7 @@ static void parallel_isa_realizefn(DeviceState *dev, Error **errp)
 | 
				
			|||||||
    isa_init_irq(isadev, &s->irq, isa->isairq);
 | 
					    isa_init_irq(isadev, &s->irq, isa->isairq);
 | 
				
			||||||
    qemu_register_reset(parallel_reset, s);
 | 
					    qemu_register_reset(parallel_reset, s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_PP_READ_STATUS, &dummy) == 0) {
 | 
					    if (qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_PP_READ_STATUS, &dummy) == 0) {
 | 
				
			||||||
        s->hw_driver = 1;
 | 
					        s->hw_driver = 1;
 | 
				
			||||||
        s->status = dummy;
 | 
					        s->status = dummy;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -605,7 +609,7 @@ bool parallel_mm_init(MemoryRegion *address_space,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    s = g_malloc0(sizeof(ParallelState));
 | 
					    s = g_malloc0(sizeof(ParallelState));
 | 
				
			||||||
    s->irq = irq;
 | 
					    s->irq = irq;
 | 
				
			||||||
    s->chr = chr;
 | 
					    qemu_chr_fe_init(&s->chr, chr, &error_abort);
 | 
				
			||||||
    s->it_shift = it_shift;
 | 
					    s->it_shift = it_shift;
 | 
				
			||||||
    qemu_register_reset(parallel_reset, s);
 | 
					    qemu_register_reset(parallel_reset, s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -36,7 +36,7 @@ typedef struct PL011State {
 | 
				
			|||||||
    int read_pos;
 | 
					    int read_pos;
 | 
				
			||||||
    int read_count;
 | 
					    int read_count;
 | 
				
			||||||
    int read_trigger;
 | 
					    int read_trigger;
 | 
				
			||||||
    CharDriverState *chr;
 | 
					    CharBackend chr;
 | 
				
			||||||
    qemu_irq irq;
 | 
					    qemu_irq irq;
 | 
				
			||||||
    const unsigned char *id;
 | 
					    const unsigned char *id;
 | 
				
			||||||
} PL011State;
 | 
					} PL011State;
 | 
				
			||||||
@ -87,9 +87,7 @@ static uint64_t pl011_read(void *opaque, hwaddr offset,
 | 
				
			|||||||
        trace_pl011_read_fifo(s->read_count);
 | 
					        trace_pl011_read_fifo(s->read_count);
 | 
				
			||||||
        s->rsr = c >> 8;
 | 
					        s->rsr = c >> 8;
 | 
				
			||||||
        pl011_update(s);
 | 
					        pl011_update(s);
 | 
				
			||||||
        if (s->chr) {
 | 
					        qemu_chr_fe_accept_input(&s->chr);
 | 
				
			||||||
            qemu_chr_accept_input(s->chr);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        r = c;
 | 
					        r = c;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case 1: /* UARTRSR */
 | 
					    case 1: /* UARTRSR */
 | 
				
			||||||
@ -168,10 +166,9 @@ static void pl011_write(void *opaque, hwaddr offset,
 | 
				
			|||||||
    case 0: /* UARTDR */
 | 
					    case 0: /* UARTDR */
 | 
				
			||||||
        /* ??? Check if transmitter is enabled.  */
 | 
					        /* ??? Check if transmitter is enabled.  */
 | 
				
			||||||
        ch = value;
 | 
					        ch = value;
 | 
				
			||||||
        if (s->chr)
 | 
					 | 
				
			||||||
        /* XXX this blocks entire thread. Rewrite to use
 | 
					        /* XXX this blocks entire thread. Rewrite to use
 | 
				
			||||||
         * qemu_chr_fe_write and background I/O callbacks */
 | 
					         * qemu_chr_fe_write and background I/O callbacks */
 | 
				
			||||||
            qemu_chr_fe_write_all(s->chr, &ch, 1);
 | 
					        qemu_chr_fe_write_all(&s->chr, &ch, 1);
 | 
				
			||||||
        s->int_level |= PL011_INT_TX;
 | 
					        s->int_level |= PL011_INT_TX;
 | 
				
			||||||
        pl011_update(s);
 | 
					        pl011_update(s);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
@ -331,10 +328,8 @@ static void pl011_realize(DeviceState *dev, Error **errp)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    PL011State *s = PL011(dev);
 | 
					    PL011State *s = PL011(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (s->chr) {
 | 
					    qemu_chr_fe_set_handlers(&s->chr, pl011_can_receive, pl011_receive,
 | 
				
			||||||
        qemu_chr_add_handlers(s->chr, pl011_can_receive, pl011_receive,
 | 
					                             pl011_event, s, NULL, true);
 | 
				
			||||||
                              pl011_event, s);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void pl011_class_init(ObjectClass *oc, void *data)
 | 
					static void pl011_class_init(ObjectClass *oc, void *data)
 | 
				
			||||||
 | 
				
			|||||||
@ -37,7 +37,7 @@ typedef struct OprtnsCommand {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
typedef struct SCLPConsoleLM {
 | 
					typedef struct SCLPConsoleLM {
 | 
				
			||||||
    SCLPEvent event;
 | 
					    SCLPEvent event;
 | 
				
			||||||
    CharDriverState *chr;
 | 
					    CharBackend chr;
 | 
				
			||||||
    bool echo;                  /* immediate echo of input if true        */
 | 
					    bool echo;                  /* immediate echo of input if true        */
 | 
				
			||||||
    uint32_t write_errors;      /* errors writing to char layer           */
 | 
					    uint32_t write_errors;      /* errors writing to char layer           */
 | 
				
			||||||
    uint32_t length;            /* length of byte stream in buffer        */
 | 
					    uint32_t length;            /* length of byte stream in buffer        */
 | 
				
			||||||
@ -91,7 +91,7 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
 | 
				
			|||||||
    if (scon->echo) {
 | 
					    if (scon->echo) {
 | 
				
			||||||
        /* XXX this blocks entire thread. Rewrite to use
 | 
					        /* XXX this blocks entire thread. Rewrite to use
 | 
				
			||||||
         * qemu_chr_fe_write and background I/O callbacks */
 | 
					         * qemu_chr_fe_write and background I/O callbacks */
 | 
				
			||||||
        qemu_chr_fe_write_all(scon->chr, buf, size);
 | 
					        qemu_chr_fe_write_all(&scon->chr, buf, size);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -195,14 +195,14 @@ static int write_console_data(SCLPEvent *event, const uint8_t *buf, int len)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    SCLPConsoleLM *scon = SCLPLM_CONSOLE(event);
 | 
					    SCLPConsoleLM *scon = SCLPLM_CONSOLE(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!scon->chr) {
 | 
					    if (!qemu_chr_fe_get_driver(&scon->chr)) {
 | 
				
			||||||
        /* If there's no backend, we can just say we consumed all data. */
 | 
					        /* If there's no backend, we can just say we consumed all data. */
 | 
				
			||||||
        return len;
 | 
					        return len;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* XXX this blocks entire thread. Rewrite to use
 | 
					    /* XXX this blocks entire thread. Rewrite to use
 | 
				
			||||||
     * qemu_chr_fe_write and background I/O callbacks */
 | 
					     * qemu_chr_fe_write and background I/O callbacks */
 | 
				
			||||||
    return qemu_chr_fe_write_all(scon->chr, buf, len);
 | 
					    return qemu_chr_fe_write_all(&scon->chr, buf, len);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int process_mdb(SCLPEvent *event, MDBO *mdbo)
 | 
					static int process_mdb(SCLPEvent *event, MDBO *mdbo)
 | 
				
			||||||
@ -312,9 +312,8 @@ static int console_init(SCLPEvent *event)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    console_available = true;
 | 
					    console_available = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (scon->chr) {
 | 
					    qemu_chr_fe_set_handlers(&scon->chr, chr_can_read,
 | 
				
			||||||
        qemu_chr_add_handlers(scon->chr, chr_can_read, chr_read, NULL, scon);
 | 
					                             chr_read, NULL, scon, NULL, true);
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -31,7 +31,7 @@ typedef struct ASCIIConsoleData {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
typedef struct SCLPConsole {
 | 
					typedef struct SCLPConsole {
 | 
				
			||||||
    SCLPEvent event;
 | 
					    SCLPEvent event;
 | 
				
			||||||
    CharDriverState *chr;
 | 
					    CharBackend chr;
 | 
				
			||||||
    uint8_t iov[SIZE_BUFFER_VT220];
 | 
					    uint8_t iov[SIZE_BUFFER_VT220];
 | 
				
			||||||
    uint32_t iov_sclp;      /* offset in buf for SCLP read operation       */
 | 
					    uint32_t iov_sclp;      /* offset in buf for SCLP read operation       */
 | 
				
			||||||
    uint32_t iov_bs;        /* offset in buf for char layer read operation */
 | 
					    uint32_t iov_bs;        /* offset in buf for char layer read operation */
 | 
				
			||||||
@ -163,14 +163,14 @@ static ssize_t write_console_data(SCLPEvent *event, const uint8_t *buf,
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    SCLPConsole *scon = SCLP_CONSOLE(event);
 | 
					    SCLPConsole *scon = SCLP_CONSOLE(event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!scon->chr) {
 | 
					    if (!qemu_chr_fe_get_driver(&scon->chr)) {
 | 
				
			||||||
        /* If there's no backend, we can just say we consumed all data. */
 | 
					        /* If there's no backend, we can just say we consumed all data. */
 | 
				
			||||||
        return len;
 | 
					        return len;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* XXX this blocks entire thread. Rewrite to use
 | 
					    /* XXX this blocks entire thread. Rewrite to use
 | 
				
			||||||
     * qemu_chr_fe_write and background I/O callbacks */
 | 
					     * qemu_chr_fe_write and background I/O callbacks */
 | 
				
			||||||
    return qemu_chr_fe_write_all(scon->chr, buf, len);
 | 
					    return qemu_chr_fe_write_all(&scon->chr, buf, len);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int write_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr)
 | 
					static int write_event_data(SCLPEvent *event, EventBufferHeader *evt_buf_hdr)
 | 
				
			||||||
@ -227,10 +227,8 @@ static int console_init(SCLPEvent *event)
 | 
				
			|||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    console_available = true;
 | 
					    console_available = true;
 | 
				
			||||||
    if (scon->chr) {
 | 
					    qemu_chr_fe_set_handlers(&scon->chr, chr_can_read,
 | 
				
			||||||
        qemu_chr_add_handlers(scon->chr, chr_can_read,
 | 
					                             chr_read, NULL, scon, NULL, true);
 | 
				
			||||||
                              chr_read, NULL, scon);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -133,13 +133,14 @@ static void serial_isa_init(ISABus *bus, int index, CharDriverState *chr)
 | 
				
			|||||||
    qdev_init_nofail(dev);
 | 
					    qdev_init_nofail(dev);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void serial_hds_isa_init(ISABus *bus, int n)
 | 
					void serial_hds_isa_init(ISABus *bus, int from, int to)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int i;
 | 
					    int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert(n <= MAX_SERIAL_PORTS);
 | 
					    assert(from >= 0);
 | 
				
			||||||
 | 
					    assert(to <= MAX_SERIAL_PORTS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (i = 0; i < n; ++i) {
 | 
					    for (i = from; i < to; ++i) {
 | 
				
			||||||
        if (serial_hds[i]) {
 | 
					        if (serial_hds[i]) {
 | 
				
			||||||
            serial_isa_init(bus, i, serial_hds[i]);
 | 
					            serial_isa_init(bus, i, serial_hds[i]);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -153,8 +153,9 @@ static void serial_update_parameters(SerialState *s)
 | 
				
			|||||||
    int speed, parity, data_bits, stop_bits, frame_size;
 | 
					    int speed, parity, data_bits, stop_bits, frame_size;
 | 
				
			||||||
    QEMUSerialSetParams ssp;
 | 
					    QEMUSerialSetParams ssp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (s->divider == 0)
 | 
					    if (s->divider == 0 || s->divider > s->baudbase) {
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Start bit. */
 | 
					    /* Start bit. */
 | 
				
			||||||
    frame_size = 1;
 | 
					    frame_size = 1;
 | 
				
			||||||
@ -181,7 +182,7 @@ static void serial_update_parameters(SerialState *s)
 | 
				
			|||||||
    ssp.data_bits = data_bits;
 | 
					    ssp.data_bits = data_bits;
 | 
				
			||||||
    ssp.stop_bits = stop_bits;
 | 
					    ssp.stop_bits = stop_bits;
 | 
				
			||||||
    s->char_transmit_time =  (NANOSECONDS_PER_SECOND / speed) * frame_size;
 | 
					    s->char_transmit_time =  (NANOSECONDS_PER_SECOND / speed) * frame_size;
 | 
				
			||||||
    qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
 | 
					    qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    DPRINTF("speed=%d parity=%c data=%d stop=%d\n",
 | 
					    DPRINTF("speed=%d parity=%c data=%d stop=%d\n",
 | 
				
			||||||
           speed, parity, data_bits, stop_bits);
 | 
					           speed, parity, data_bits, stop_bits);
 | 
				
			||||||
@ -194,7 +195,8 @@ static void serial_update_msl(SerialState *s)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    timer_del(s->modem_status_poll);
 | 
					    timer_del(s->modem_status_poll);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (qemu_chr_fe_ioctl(s->chr,CHR_IOCTL_SERIAL_GET_TIOCM, &flags) == -ENOTSUP) {
 | 
					    if (qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_GET_TIOCM,
 | 
				
			||||||
 | 
					                          &flags) == -ENOTSUP) {
 | 
				
			||||||
        s->poll_msl = -1;
 | 
					        s->poll_msl = -1;
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -259,10 +261,11 @@ static void serial_xmit(SerialState *s)
 | 
				
			|||||||
        if (s->mcr & UART_MCR_LOOP) {
 | 
					        if (s->mcr & UART_MCR_LOOP) {
 | 
				
			||||||
            /* in loopback mode, say that we just received a char */
 | 
					            /* in loopback mode, say that we just received a char */
 | 
				
			||||||
            serial_receive1(s, &s->tsr, 1);
 | 
					            serial_receive1(s, &s->tsr, 1);
 | 
				
			||||||
        } else if (qemu_chr_fe_write(s->chr, &s->tsr, 1) != 1 &&
 | 
					        } else if (qemu_chr_fe_write(&s->chr, &s->tsr, 1) != 1 &&
 | 
				
			||||||
                   s->tsr_retry < MAX_XMIT_RETRY) {
 | 
					                   s->tsr_retry < MAX_XMIT_RETRY) {
 | 
				
			||||||
            assert(s->watch_tag == 0);
 | 
					            assert(s->watch_tag == 0);
 | 
				
			||||||
            s->watch_tag = qemu_chr_fe_add_watch(s->chr, G_IO_OUT|G_IO_HUP,
 | 
					            s->watch_tag =
 | 
				
			||||||
 | 
					                qemu_chr_fe_add_watch(&s->chr, G_IO_OUT | G_IO_HUP,
 | 
				
			||||||
                                      serial_watch_cb, s);
 | 
					                                      serial_watch_cb, s);
 | 
				
			||||||
            if (s->watch_tag > 0) {
 | 
					            if (s->watch_tag > 0) {
 | 
				
			||||||
                s->tsr_retry++;
 | 
					                s->tsr_retry++;
 | 
				
			||||||
@ -416,7 +419,7 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val,
 | 
				
			|||||||
            break_enable = (val >> 6) & 1;
 | 
					            break_enable = (val >> 6) & 1;
 | 
				
			||||||
            if (break_enable != s->last_break_enable) {
 | 
					            if (break_enable != s->last_break_enable) {
 | 
				
			||||||
                s->last_break_enable = break_enable;
 | 
					                s->last_break_enable = break_enable;
 | 
				
			||||||
                qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_BREAK,
 | 
					                qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_BREAK,
 | 
				
			||||||
                                  &break_enable);
 | 
					                                  &break_enable);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -431,7 +434,7 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            if (s->poll_msl >= 0 && old_mcr != s->mcr) {
 | 
					            if (s->poll_msl >= 0 && old_mcr != s->mcr) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                qemu_chr_fe_ioctl(s->chr,CHR_IOCTL_SERIAL_GET_TIOCM, &flags);
 | 
					                qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_GET_TIOCM, &flags);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                flags &= ~(CHR_TIOCM_RTS | CHR_TIOCM_DTR);
 | 
					                flags &= ~(CHR_TIOCM_RTS | CHR_TIOCM_DTR);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -440,7 +443,7 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val,
 | 
				
			|||||||
                if (val & UART_MCR_DTR)
 | 
					                if (val & UART_MCR_DTR)
 | 
				
			||||||
                    flags |= CHR_TIOCM_DTR;
 | 
					                    flags |= CHR_TIOCM_DTR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                qemu_chr_fe_ioctl(s->chr,CHR_IOCTL_SERIAL_SET_TIOCM, &flags);
 | 
					                qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_TIOCM, &flags);
 | 
				
			||||||
                /* Update the modem status after a one-character-send wait-time, since there may be a response
 | 
					                /* Update the modem status after a one-character-send wait-time, since there may be a response
 | 
				
			||||||
                   from the device/computer at the other end of the serial line */
 | 
					                   from the device/computer at the other end of the serial line */
 | 
				
			||||||
                timer_mod(s->modem_status_poll, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->char_transmit_time);
 | 
					                timer_mod(s->modem_status_poll, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->char_transmit_time);
 | 
				
			||||||
@ -485,7 +488,7 @@ static uint64_t serial_ioport_read(void *opaque, hwaddr addr, unsigned size)
 | 
				
			|||||||
            serial_update_irq(s);
 | 
					            serial_update_irq(s);
 | 
				
			||||||
            if (!(s->mcr & UART_MCR_LOOP)) {
 | 
					            if (!(s->mcr & UART_MCR_LOOP)) {
 | 
				
			||||||
                /* in loopback mode, don't receive any data */
 | 
					                /* in loopback mode, don't receive any data */
 | 
				
			||||||
                qemu_chr_accept_input(s->chr);
 | 
					                qemu_chr_fe_accept_input(&s->chr);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
@ -658,7 +661,7 @@ static int serial_post_load(void *opaque, int version_id)
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        assert(s->watch_tag == 0);
 | 
					        assert(s->watch_tag == 0);
 | 
				
			||||||
        s->watch_tag = qemu_chr_fe_add_watch(s->chr, G_IO_OUT|G_IO_HUP,
 | 
					        s->watch_tag = qemu_chr_fe_add_watch(&s->chr, G_IO_OUT | G_IO_HUP,
 | 
				
			||||||
                                             serial_watch_cb, s);
 | 
					                                             serial_watch_cb, s);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        /* tsr_retry == 0 implies LSR.TEMT = 1 (transmitter empty).  */
 | 
					        /* tsr_retry == 0 implies LSR.TEMT = 1 (transmitter empty).  */
 | 
				
			||||||
@ -883,7 +886,7 @@ static void serial_reset(void *opaque)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void serial_realize_core(SerialState *s, Error **errp)
 | 
					void serial_realize_core(SerialState *s, Error **errp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (!s->chr) {
 | 
					    if (!qemu_chr_fe_get_driver(&s->chr)) {
 | 
				
			||||||
        error_setg(errp, "Can't create serial device, empty char device");
 | 
					        error_setg(errp, "Can't create serial device, empty char device");
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -893,8 +896,8 @@ void serial_realize_core(SerialState *s, Error **errp)
 | 
				
			|||||||
    s->fifo_timeout_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, (QEMUTimerCB *) fifo_timeout_int, s);
 | 
					    s->fifo_timeout_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, (QEMUTimerCB *) fifo_timeout_int, s);
 | 
				
			||||||
    qemu_register_reset(serial_reset, s);
 | 
					    qemu_register_reset(serial_reset, s);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1,
 | 
					    qemu_chr_fe_set_handlers(&s->chr, serial_can_receive1, serial_receive1,
 | 
				
			||||||
                          serial_event, s);
 | 
					                             serial_event, s, NULL, true);
 | 
				
			||||||
    fifo8_create(&s->recv_fifo, UART_FIFO_LENGTH);
 | 
					    fifo8_create(&s->recv_fifo, UART_FIFO_LENGTH);
 | 
				
			||||||
    fifo8_create(&s->xmit_fifo, UART_FIFO_LENGTH);
 | 
					    fifo8_create(&s->xmit_fifo, UART_FIFO_LENGTH);
 | 
				
			||||||
    serial_reset(s);
 | 
					    serial_reset(s);
 | 
				
			||||||
@ -902,7 +905,7 @@ void serial_realize_core(SerialState *s, Error **errp)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void serial_exit_core(SerialState *s)
 | 
					void serial_exit_core(SerialState *s)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, NULL);
 | 
					    qemu_chr_fe_deinit(&s->chr);
 | 
				
			||||||
    qemu_unregister_reset(serial_reset, s);
 | 
					    qemu_unregister_reset(serial_reset, s);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -932,7 +935,7 @@ SerialState *serial_init(int base, qemu_irq irq, int baudbase,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    s->irq = irq;
 | 
					    s->irq = irq;
 | 
				
			||||||
    s->baudbase = baudbase;
 | 
					    s->baudbase = baudbase;
 | 
				
			||||||
    s->chr = chr;
 | 
					    qemu_chr_fe_init(&s->chr, chr, &error_abort);
 | 
				
			||||||
    serial_realize_core(s, &error_fatal);
 | 
					    serial_realize_core(s, &error_fatal);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    vmstate_register(NULL, base, &vmstate_serial, s);
 | 
					    vmstate_register(NULL, base, &vmstate_serial, s);
 | 
				
			||||||
@ -989,7 +992,7 @@ SerialState *serial_mm_init(MemoryRegion *address_space,
 | 
				
			|||||||
    s->it_shift = it_shift;
 | 
					    s->it_shift = it_shift;
 | 
				
			||||||
    s->irq = irq;
 | 
					    s->irq = irq;
 | 
				
			||||||
    s->baudbase = baudbase;
 | 
					    s->baudbase = baudbase;
 | 
				
			||||||
    s->chr = chr;
 | 
					    qemu_chr_fe_init(&s->chr, chr, &error_abort);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    serial_realize_core(s, &error_fatal);
 | 
					    serial_realize_core(s, &error_fatal);
 | 
				
			||||||
    vmstate_register(NULL, base, &vmstate_serial, s);
 | 
					    vmstate_register(NULL, base, &vmstate_serial, s);
 | 
				
			||||||
 | 
				
			|||||||
@ -29,6 +29,7 @@
 | 
				
			|||||||
#include "hw/sh4/sh.h"
 | 
					#include "hw/sh4/sh.h"
 | 
				
			||||||
#include "sysemu/char.h"
 | 
					#include "sysemu/char.h"
 | 
				
			||||||
#include "exec/address-spaces.h"
 | 
					#include "exec/address-spaces.h"
 | 
				
			||||||
 | 
					#include "qapi/error.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
//#define DEBUG_SERIAL
 | 
					//#define DEBUG_SERIAL
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -62,7 +63,7 @@ typedef struct {
 | 
				
			|||||||
    int flags;
 | 
					    int flags;
 | 
				
			||||||
    int rtrg;
 | 
					    int rtrg;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    CharDriverState *chr;
 | 
					    CharBackend chr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qemu_irq eri;
 | 
					    qemu_irq eri;
 | 
				
			||||||
    qemu_irq rxi;
 | 
					    qemu_irq rxi;
 | 
				
			||||||
@ -109,11 +110,11 @@ static void sh_serial_write(void *opaque, hwaddr offs,
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    case 0x0c: /* FTDR / TDR */
 | 
					    case 0x0c: /* FTDR / TDR */
 | 
				
			||||||
        if (s->chr) {
 | 
					        if (qemu_chr_fe_get_driver(&s->chr)) {
 | 
				
			||||||
            ch = val;
 | 
					            ch = val;
 | 
				
			||||||
            /* XXX this blocks entire thread. Rewrite to use
 | 
					            /* XXX this blocks entire thread. Rewrite to use
 | 
				
			||||||
             * qemu_chr_fe_write and background I/O callbacks */
 | 
					             * qemu_chr_fe_write and background I/O callbacks */
 | 
				
			||||||
            qemu_chr_fe_write_all(s->chr, &ch, 1);
 | 
					            qemu_chr_fe_write_all(&s->chr, &ch, 1);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	s->dr = val;
 | 
						s->dr = val;
 | 
				
			||||||
	s->flags &= ~SH_SERIAL_FLAG_TDE;
 | 
						s->flags &= ~SH_SERIAL_FLAG_TDE;
 | 
				
			||||||
@ -395,12 +396,11 @@ void sh_serial_init(MemoryRegion *sysmem,
 | 
				
			|||||||
                             0, 0x28);
 | 
					                             0, 0x28);
 | 
				
			||||||
    memory_region_add_subregion(sysmem, A7ADDR(base), &s->iomem_a7);
 | 
					    memory_region_add_subregion(sysmem, A7ADDR(base), &s->iomem_a7);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->chr = chr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (chr) {
 | 
					    if (chr) {
 | 
				
			||||||
        qemu_chr_fe_claim_no_fail(chr);
 | 
					        qemu_chr_fe_init(&s->chr, chr, &error_abort);
 | 
				
			||||||
        qemu_chr_add_handlers(chr, sh_serial_can_receive1, sh_serial_receive1,
 | 
					        qemu_chr_fe_set_handlers(&s->chr, sh_serial_can_receive1,
 | 
				
			||||||
			      sh_serial_event, s);
 | 
					                                 sh_serial_receive1,
 | 
				
			||||||
 | 
					                                 sh_serial_event, s, NULL, true);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->eri = eri_source;
 | 
					    s->eri = eri_source;
 | 
				
			||||||
 | 
				
			|||||||
@ -11,7 +11,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
typedef struct VIOsPAPRVTYDevice {
 | 
					typedef struct VIOsPAPRVTYDevice {
 | 
				
			||||||
    VIOsPAPRDevice sdev;
 | 
					    VIOsPAPRDevice sdev;
 | 
				
			||||||
    CharDriverState *chardev;
 | 
					    CharBackend chardev;
 | 
				
			||||||
    uint32_t in, out;
 | 
					    uint32_t in, out;
 | 
				
			||||||
    uint8_t buf[VTERM_BUFSIZE];
 | 
					    uint8_t buf[VTERM_BUFSIZE];
 | 
				
			||||||
} VIOsPAPRVTYDevice;
 | 
					} VIOsPAPRVTYDevice;
 | 
				
			||||||
@ -51,7 +51,7 @@ static int vty_getchars(VIOsPAPRDevice *sdev, uint8_t *buf, int max)
 | 
				
			|||||||
        buf[n++] = dev->buf[dev->out++ % VTERM_BUFSIZE];
 | 
					        buf[n++] = dev->buf[dev->out++ % VTERM_BUFSIZE];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qemu_chr_accept_input(dev->chardev);
 | 
					    qemu_chr_fe_accept_input(&dev->chardev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return n;
 | 
					    return n;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -62,20 +62,20 @@ void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /* XXX this blocks entire thread. Rewrite to use
 | 
					    /* XXX this blocks entire thread. Rewrite to use
 | 
				
			||||||
     * qemu_chr_fe_write and background I/O callbacks */
 | 
					     * qemu_chr_fe_write and background I/O callbacks */
 | 
				
			||||||
    qemu_chr_fe_write_all(dev->chardev, buf, len);
 | 
					    qemu_chr_fe_write_all(&dev->chardev, buf, len);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void spapr_vty_realize(VIOsPAPRDevice *sdev, Error **errp)
 | 
					static void spapr_vty_realize(VIOsPAPRDevice *sdev, Error **errp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(sdev);
 | 
					    VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(sdev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!dev->chardev) {
 | 
					    if (!qemu_chr_fe_get_driver(&dev->chardev)) {
 | 
				
			||||||
        error_setg(errp, "chardev property not set");
 | 
					        error_setg(errp, "chardev property not set");
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qemu_chr_add_handlers(dev->chardev, vty_can_receive,
 | 
					    qemu_chr_fe_set_handlers(&dev->chardev, vty_can_receive,
 | 
				
			||||||
                          vty_receive, NULL, dev);
 | 
					                             vty_receive, NULL, dev, NULL, true);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Forward declaration */
 | 
					/* Forward declaration */
 | 
				
			||||||
 | 
				
			|||||||
@ -97,17 +97,13 @@ static uint64_t stm32f2xx_usart_read(void *opaque, hwaddr addr,
 | 
				
			|||||||
    case USART_SR:
 | 
					    case USART_SR:
 | 
				
			||||||
        retvalue = s->usart_sr;
 | 
					        retvalue = s->usart_sr;
 | 
				
			||||||
        s->usart_sr &= ~USART_SR_TC;
 | 
					        s->usart_sr &= ~USART_SR_TC;
 | 
				
			||||||
        if (s->chr) {
 | 
					        qemu_chr_fe_accept_input(&s->chr);
 | 
				
			||||||
            qemu_chr_accept_input(s->chr);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        return retvalue;
 | 
					        return retvalue;
 | 
				
			||||||
    case USART_DR:
 | 
					    case USART_DR:
 | 
				
			||||||
        DB_PRINT("Value: 0x%" PRIx32 ", %c\n", s->usart_dr, (char) s->usart_dr);
 | 
					        DB_PRINT("Value: 0x%" PRIx32 ", %c\n", s->usart_dr, (char) s->usart_dr);
 | 
				
			||||||
        s->usart_sr |= USART_SR_TXE;
 | 
					        s->usart_sr |= USART_SR_TXE;
 | 
				
			||||||
        s->usart_sr &= ~USART_SR_RXNE;
 | 
					        s->usart_sr &= ~USART_SR_RXNE;
 | 
				
			||||||
        if (s->chr) {
 | 
					        qemu_chr_fe_accept_input(&s->chr);
 | 
				
			||||||
            qemu_chr_accept_input(s->chr);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        qemu_set_irq(s->irq, 0);
 | 
					        qemu_set_irq(s->irq, 0);
 | 
				
			||||||
        return s->usart_dr & 0x3FF;
 | 
					        return s->usart_dr & 0x3FF;
 | 
				
			||||||
    case USART_BRR:
 | 
					    case USART_BRR:
 | 
				
			||||||
@ -152,11 +148,9 @@ static void stm32f2xx_usart_write(void *opaque, hwaddr addr,
 | 
				
			|||||||
    case USART_DR:
 | 
					    case USART_DR:
 | 
				
			||||||
        if (value < 0xF000) {
 | 
					        if (value < 0xF000) {
 | 
				
			||||||
            ch = value;
 | 
					            ch = value;
 | 
				
			||||||
            if (s->chr) {
 | 
					 | 
				
			||||||
            /* XXX this blocks entire thread. Rewrite to use
 | 
					            /* XXX this blocks entire thread. Rewrite to use
 | 
				
			||||||
             * qemu_chr_fe_write and background I/O callbacks */
 | 
					             * qemu_chr_fe_write and background I/O callbacks */
 | 
				
			||||||
                qemu_chr_fe_write_all(s->chr, &ch, 1);
 | 
					            qemu_chr_fe_write_all(&s->chr, &ch, 1);
 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            s->usart_sr |= USART_SR_TC;
 | 
					            s->usart_sr |= USART_SR_TC;
 | 
				
			||||||
            s->usart_sr &= ~USART_SR_TXE;
 | 
					            s->usart_sr &= ~USART_SR_TXE;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -212,10 +206,8 @@ static void stm32f2xx_usart_realize(DeviceState *dev, Error **errp)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    STM32F2XXUsartState *s = STM32F2XX_USART(dev);
 | 
					    STM32F2XXUsartState *s = STM32F2XX_USART(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (s->chr) {
 | 
					    qemu_chr_fe_set_handlers(&s->chr, stm32f2xx_usart_can_receive,
 | 
				
			||||||
        qemu_chr_add_handlers(s->chr, stm32f2xx_usart_can_receive,
 | 
					                             stm32f2xx_usart_receive, NULL, s, NULL, true);
 | 
				
			||||||
                              stm32f2xx_usart_receive, NULL, s);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void stm32f2xx_usart_class_init(ObjectClass *klass, void *data)
 | 
					static void stm32f2xx_usart_class_init(ObjectClass *klass, void *data)
 | 
				
			||||||
 | 
				
			|||||||
@ -24,7 +24,7 @@
 | 
				
			|||||||
typedef struct VirtConsole {
 | 
					typedef struct VirtConsole {
 | 
				
			||||||
    VirtIOSerialPort parent_obj;
 | 
					    VirtIOSerialPort parent_obj;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    CharDriverState *chr;
 | 
					    CharBackend chr;
 | 
				
			||||||
    guint watch;
 | 
					    guint watch;
 | 
				
			||||||
} VirtConsole;
 | 
					} VirtConsole;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -49,12 +49,12 @@ static ssize_t flush_buf(VirtIOSerialPort *port,
 | 
				
			|||||||
    VirtConsole *vcon = VIRTIO_CONSOLE(port);
 | 
					    VirtConsole *vcon = VIRTIO_CONSOLE(port);
 | 
				
			||||||
    ssize_t ret;
 | 
					    ssize_t ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!vcon->chr) {
 | 
					    if (!qemu_chr_fe_get_driver(&vcon->chr)) {
 | 
				
			||||||
        /* If there's no backend, we can just say we consumed all data. */
 | 
					        /* If there's no backend, we can just say we consumed all data. */
 | 
				
			||||||
        return len;
 | 
					        return len;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ret = qemu_chr_fe_write(vcon->chr, buf, len);
 | 
					    ret = qemu_chr_fe_write(&vcon->chr, buf, len);
 | 
				
			||||||
    trace_virtio_console_flush_buf(port->id, len, ret);
 | 
					    trace_virtio_console_flush_buf(port->id, len, ret);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (ret < len) {
 | 
					    if (ret < len) {
 | 
				
			||||||
@ -92,7 +92,7 @@ static ssize_t flush_buf(VirtIOSerialPort *port,
 | 
				
			|||||||
        if (!k->is_console) {
 | 
					        if (!k->is_console) {
 | 
				
			||||||
            virtio_serial_throttle_port(port, true);
 | 
					            virtio_serial_throttle_port(port, true);
 | 
				
			||||||
            if (!vcon->watch) {
 | 
					            if (!vcon->watch) {
 | 
				
			||||||
                vcon->watch = qemu_chr_fe_add_watch(vcon->chr,
 | 
					                vcon->watch = qemu_chr_fe_add_watch(&vcon->chr,
 | 
				
			||||||
                                                    G_IO_OUT|G_IO_HUP,
 | 
					                                                    G_IO_OUT|G_IO_HUP,
 | 
				
			||||||
                                                    chr_write_unblocked, vcon);
 | 
					                                                    chr_write_unblocked, vcon);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -108,8 +108,8 @@ static void set_guest_connected(VirtIOSerialPort *port, int guest_connected)
 | 
				
			|||||||
    DeviceState *dev = DEVICE(port);
 | 
					    DeviceState *dev = DEVICE(port);
 | 
				
			||||||
    VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(port);
 | 
					    VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (vcon->chr && !k->is_console) {
 | 
					    if (!k->is_console) {
 | 
				
			||||||
        qemu_chr_fe_set_open(vcon->chr, guest_connected);
 | 
					        qemu_chr_fe_set_open(&vcon->chr, guest_connected);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (dev->id) {
 | 
					    if (dev->id) {
 | 
				
			||||||
@ -122,9 +122,7 @@ static void guest_writable(VirtIOSerialPort *port)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    VirtConsole *vcon = VIRTIO_CONSOLE(port);
 | 
					    VirtConsole *vcon = VIRTIO_CONSOLE(port);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (vcon->chr) {
 | 
					    qemu_chr_fe_accept_input(&vcon->chr);
 | 
				
			||||||
        qemu_chr_accept_input(vcon->chr);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Readiness of the guest to accept data on a port */
 | 
					/* Readiness of the guest to accept data on a port */
 | 
				
			||||||
@ -170,6 +168,7 @@ static void virtconsole_realize(DeviceState *dev, Error **errp)
 | 
				
			|||||||
    VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(dev);
 | 
					    VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(dev);
 | 
				
			||||||
    VirtConsole *vcon = VIRTIO_CONSOLE(dev);
 | 
					    VirtConsole *vcon = VIRTIO_CONSOLE(dev);
 | 
				
			||||||
    VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(dev);
 | 
					    VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(dev);
 | 
				
			||||||
 | 
					    CharDriverState *chr = qemu_chr_fe_get_driver(&vcon->chr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (port->id == 0 && !k->is_console) {
 | 
					    if (port->id == 0 && !k->is_console) {
 | 
				
			||||||
        error_setg(errp, "Port number 0 on virtio-serial devices reserved "
 | 
					        error_setg(errp, "Port number 0 on virtio-serial devices reserved "
 | 
				
			||||||
@ -177,7 +176,7 @@ static void virtconsole_realize(DeviceState *dev, Error **errp)
 | 
				
			|||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (vcon->chr) {
 | 
					    if (chr) {
 | 
				
			||||||
        /*
 | 
					        /*
 | 
				
			||||||
         * For consoles we don't block guest data transfer just
 | 
					         * For consoles we don't block guest data transfer just
 | 
				
			||||||
         * because nothing is connected - we'll just let it go
 | 
					         * because nothing is connected - we'll just let it go
 | 
				
			||||||
@ -188,14 +187,12 @@ static void virtconsole_realize(DeviceState *dev, Error **errp)
 | 
				
			|||||||
         * trigger open/close of the device
 | 
					         * trigger open/close of the device
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        if (k->is_console) {
 | 
					        if (k->is_console) {
 | 
				
			||||||
            vcon->chr->explicit_fe_open = 0;
 | 
					            qemu_chr_fe_set_handlers(&vcon->chr, chr_can_read, chr_read,
 | 
				
			||||||
            qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read,
 | 
					                                     NULL, vcon, NULL, true);
 | 
				
			||||||
                                  NULL, vcon);
 | 
					 | 
				
			||||||
            virtio_serial_open(port);
 | 
					            virtio_serial_open(port);
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            vcon->chr->explicit_fe_open = 1;
 | 
					            qemu_chr_fe_set_handlers(&vcon->chr, chr_can_read, chr_read,
 | 
				
			||||||
            qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read,
 | 
					                                     chr_event, vcon, NULL, false);
 | 
				
			||||||
                                  chr_event, vcon);
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -23,9 +23,11 @@
 | 
				
			|||||||
#include <sys/select.h>
 | 
					#include <sys/select.h>
 | 
				
			||||||
#include <termios.h>
 | 
					#include <termios.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "qapi/error.h"
 | 
				
			||||||
#include "hw/hw.h"
 | 
					#include "hw/hw.h"
 | 
				
			||||||
#include "sysemu/char.h"
 | 
					#include "sysemu/char.h"
 | 
				
			||||||
#include "hw/xen/xen_backend.h"
 | 
					#include "hw/xen/xen_backend.h"
 | 
				
			||||||
 | 
					#include "qapi/error.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <xen/io/console.h>
 | 
					#include <xen/io/console.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -43,7 +45,7 @@ struct XenConsole {
 | 
				
			|||||||
    char              console[XEN_BUFSIZE];
 | 
					    char              console[XEN_BUFSIZE];
 | 
				
			||||||
    int               ring_ref;
 | 
					    int               ring_ref;
 | 
				
			||||||
    void              *sring;
 | 
					    void              *sring;
 | 
				
			||||||
    CharDriverState   *chr;
 | 
					    CharBackend       chr;
 | 
				
			||||||
    int               backlog;
 | 
					    int               backlog;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -148,11 +150,13 @@ static void xencons_send(struct XenConsole *con)
 | 
				
			|||||||
    ssize_t len, size;
 | 
					    ssize_t len, size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    size = con->buffer.size - con->buffer.consumed;
 | 
					    size = con->buffer.size - con->buffer.consumed;
 | 
				
			||||||
    if (con->chr)
 | 
					    if (qemu_chr_fe_get_driver(&con->chr)) {
 | 
				
			||||||
        len = qemu_chr_fe_write(con->chr, con->buffer.data + con->buffer.consumed,
 | 
					        len = qemu_chr_fe_write(&con->chr,
 | 
				
			||||||
 | 
					                                con->buffer.data + con->buffer.consumed,
 | 
				
			||||||
                                size);
 | 
					                                size);
 | 
				
			||||||
    else
 | 
					    } else {
 | 
				
			||||||
        len = size;
 | 
					        len = size;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    if (len < 1) {
 | 
					    if (len < 1) {
 | 
				
			||||||
	if (!con->backlog) {
 | 
						if (!con->backlog) {
 | 
				
			||||||
	    con->backlog = 1;
 | 
						    con->backlog = 1;
 | 
				
			||||||
@ -196,13 +200,18 @@ static int con_init(struct XenDevice *xendev)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /* no Xen override, use qemu output device */
 | 
					    /* no Xen override, use qemu output device */
 | 
				
			||||||
    if (output == NULL) {
 | 
					    if (output == NULL) {
 | 
				
			||||||
        con->chr = serial_hds[con->xendev.dev];
 | 
					        if (con->xendev.dev) {
 | 
				
			||||||
 | 
					            qemu_chr_fe_init(&con->chr, serial_hds[con->xendev.dev],
 | 
				
			||||||
 | 
					                             &error_abort);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        snprintf(label, sizeof(label), "xencons%d", con->xendev.dev);
 | 
					        snprintf(label, sizeof(label), "xencons%d", con->xendev.dev);
 | 
				
			||||||
        con->chr = qemu_chr_new(label, output, NULL);
 | 
					        qemu_chr_fe_init(&con->chr,
 | 
				
			||||||
 | 
					                         qemu_chr_new(label, output), &error_abort);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    xenstore_store_pv_console_info(con->xendev.dev, con->chr);
 | 
					    xenstore_store_pv_console_info(con->xendev.dev,
 | 
				
			||||||
 | 
					                                   qemu_chr_fe_get_driver(&con->chr));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
out:
 | 
					out:
 | 
				
			||||||
    g_free(type);
 | 
					    g_free(type);
 | 
				
			||||||
@ -235,17 +244,8 @@ static int con_initialise(struct XenDevice *xendev)
 | 
				
			|||||||
	return -1;
 | 
						return -1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    xen_be_bind_evtchn(&con->xendev);
 | 
					    xen_be_bind_evtchn(&con->xendev);
 | 
				
			||||||
    if (con->chr) {
 | 
					    qemu_chr_fe_set_handlers(&con->chr, xencons_can_receive,
 | 
				
			||||||
        if (qemu_chr_fe_claim(con->chr) == 0) {
 | 
					                             xencons_receive, NULL, con, NULL, true);
 | 
				
			||||||
            qemu_chr_add_handlers(con->chr, xencons_can_receive,
 | 
					 | 
				
			||||||
                                  xencons_receive, NULL, con);
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            xen_be_printf(xendev, 0,
 | 
					 | 
				
			||||||
                          "xen_console_init error chardev %s already used\n",
 | 
					 | 
				
			||||||
                          con->chr->label);
 | 
					 | 
				
			||||||
            con->chr = NULL;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    xen_be_printf(xendev, 1, "ring mfn %d, remote port %d, local port %d, limit %zd\n",
 | 
					    xen_be_printf(xendev, 1, "ring mfn %d, remote port %d, local port %d, limit %zd\n",
 | 
				
			||||||
		  con->ring_ref,
 | 
							  con->ring_ref,
 | 
				
			||||||
@ -259,10 +259,7 @@ static void con_disconnect(struct XenDevice *xendev)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
 | 
					    struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (con->chr) {
 | 
					    qemu_chr_fe_deinit(&con->chr);
 | 
				
			||||||
        qemu_chr_add_handlers(con->chr, NULL, NULL, NULL, NULL);
 | 
					 | 
				
			||||||
        qemu_chr_fe_release(con->chr);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    xen_be_unbind_evtchn(&con->xendev);
 | 
					    xen_be_unbind_evtchn(&con->xendev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (con->sring) {
 | 
					    if (con->sring) {
 | 
				
			||||||
 | 
				
			|||||||
@ -55,7 +55,7 @@ typedef struct XilinxUARTLite {
 | 
				
			|||||||
    SysBusDevice parent_obj;
 | 
					    SysBusDevice parent_obj;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    MemoryRegion mmio;
 | 
					    MemoryRegion mmio;
 | 
				
			||||||
    CharDriverState *chr;
 | 
					    CharBackend chr;
 | 
				
			||||||
    qemu_irq irq;
 | 
					    qemu_irq irq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint8_t rx_fifo[8];
 | 
					    uint8_t rx_fifo[8];
 | 
				
			||||||
@ -107,7 +107,7 @@ uart_read(void *opaque, hwaddr addr, unsigned int size)
 | 
				
			|||||||
                s->rx_fifo_len--;
 | 
					                s->rx_fifo_len--;
 | 
				
			||||||
            uart_update_status(s);
 | 
					            uart_update_status(s);
 | 
				
			||||||
            uart_update_irq(s);
 | 
					            uart_update_irq(s);
 | 
				
			||||||
            qemu_chr_accept_input(s->chr);
 | 
					            qemu_chr_fe_accept_input(&s->chr);
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        default:
 | 
					        default:
 | 
				
			||||||
@ -143,11 +143,9 @@ uart_write(void *opaque, hwaddr addr,
 | 
				
			|||||||
            break;
 | 
					            break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        case R_TX:
 | 
					        case R_TX:
 | 
				
			||||||
            if (s->chr)
 | 
					 | 
				
			||||||
            /* XXX this blocks entire thread. Rewrite to use
 | 
					            /* XXX this blocks entire thread. Rewrite to use
 | 
				
			||||||
             * qemu_chr_fe_write and background I/O callbacks */
 | 
					             * qemu_chr_fe_write and background I/O callbacks */
 | 
				
			||||||
                qemu_chr_fe_write_all(s->chr, &ch, 1);
 | 
					            qemu_chr_fe_write_all(&s->chr, &ch, 1);
 | 
				
			||||||
 | 
					 | 
				
			||||||
            s->regs[addr] = value;
 | 
					            s->regs[addr] = value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            /* hax.  */
 | 
					            /* hax.  */
 | 
				
			||||||
@ -213,8 +211,8 @@ static void xilinx_uartlite_realize(DeviceState *dev, Error **errp)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    XilinxUARTLite *s = XILINX_UARTLITE(dev);
 | 
					    XilinxUARTLite *s = XILINX_UARTLITE(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (s->chr)
 | 
					    qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx,
 | 
				
			||||||
        qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
 | 
					                             uart_event, s, NULL, true);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void xilinx_uartlite_init(Object *obj)
 | 
					static void xilinx_uartlite_init(Object *obj)
 | 
				
			||||||
 | 
				
			|||||||
@ -160,55 +160,67 @@ PropertyInfo qdev_prop_drive = {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/* --- character device --- */
 | 
					/* --- character device --- */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void parse_chr(DeviceState *dev, const char *str, void **ptr,
 | 
					static void get_chr(Object *obj, Visitor *v, const char *name, void *opaque,
 | 
				
			||||||
                      const char *propname, Error **errp)
 | 
					                    Error **errp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    CharDriverState *chr = qemu_chr_find(str);
 | 
					    DeviceState *dev = DEVICE(obj);
 | 
				
			||||||
    if (chr == NULL) {
 | 
					    CharBackend *be = qdev_get_prop_ptr(dev, opaque);
 | 
				
			||||||
 | 
					    char *p;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    p = g_strdup(be->chr && be->chr->label ? be->chr->label : "");
 | 
				
			||||||
 | 
					    visit_type_str(v, name, &p, errp);
 | 
				
			||||||
 | 
					    g_free(p);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void set_chr(Object *obj, Visitor *v, const char *name, void *opaque,
 | 
				
			||||||
 | 
					                    Error **errp)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    DeviceState *dev = DEVICE(obj);
 | 
				
			||||||
 | 
					    Error *local_err = NULL;
 | 
				
			||||||
 | 
					    Property *prop = opaque;
 | 
				
			||||||
 | 
					    CharBackend *be = qdev_get_prop_ptr(dev, prop);
 | 
				
			||||||
 | 
					    CharDriverState *s;
 | 
				
			||||||
 | 
					    char *str;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (dev->realized) {
 | 
				
			||||||
 | 
					        qdev_prop_set_after_realize(dev, name, errp);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    visit_type_str(v, name, &str, &local_err);
 | 
				
			||||||
 | 
					    if (local_err) {
 | 
				
			||||||
 | 
					        error_propagate(errp, local_err);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!*str) {
 | 
				
			||||||
 | 
					        g_free(str);
 | 
				
			||||||
 | 
					        be->chr = NULL;
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    s = qemu_chr_find(str);
 | 
				
			||||||
 | 
					    g_free(str);
 | 
				
			||||||
 | 
					    if (s == NULL) {
 | 
				
			||||||
        error_setg(errp, "Property '%s.%s' can't find value '%s'",
 | 
					        error_setg(errp, "Property '%s.%s' can't find value '%s'",
 | 
				
			||||||
                   object_get_typename(OBJECT(dev)), propname, str);
 | 
					                   object_get_typename(obj), prop->name, str);
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (qemu_chr_fe_claim(chr) != 0) {
 | 
					
 | 
				
			||||||
        error_setg(errp, "Property '%s.%s' can't take value '%s', it's in use",
 | 
					    if (!qemu_chr_fe_init(be, s, errp)) {
 | 
				
			||||||
                  object_get_typename(OBJECT(dev)), propname, str);
 | 
					        error_prepend(errp, "Property '%s.%s' can't take value '%s': ",
 | 
				
			||||||
 | 
					                      object_get_typename(obj), prop->name, str);
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    *ptr = chr;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void release_chr(Object *obj, const char *name, void *opaque)
 | 
					static void release_chr(Object *obj, const char *name, void *opaque)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    DeviceState *dev = DEVICE(obj);
 | 
					    DeviceState *dev = DEVICE(obj);
 | 
				
			||||||
    Property *prop = opaque;
 | 
					    Property *prop = opaque;
 | 
				
			||||||
    CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
 | 
					    CharBackend *be = qdev_get_prop_ptr(dev, prop);
 | 
				
			||||||
    CharDriverState *chr = *ptr;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (chr) {
 | 
					    qemu_chr_fe_deinit(be);
 | 
				
			||||||
        qemu_chr_add_handlers(chr, NULL, NULL, NULL, NULL);
 | 
					 | 
				
			||||||
        qemu_chr_fe_release(chr);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static char *print_chr(void *ptr)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    CharDriverState *chr = ptr;
 | 
					 | 
				
			||||||
    const char *val = chr->label ? chr->label : "";
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return g_strdup(val);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void get_chr(Object *obj, Visitor *v, const char *name, void *opaque,
 | 
					 | 
				
			||||||
                    Error **errp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    get_pointer(obj, v, opaque, print_chr, name, errp);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void set_chr(Object *obj, Visitor *v, const char *name, void *opaque,
 | 
					 | 
				
			||||||
                    Error **errp)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    set_pointer(obj, v, opaque, parse_chr, name, errp);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PropertyInfo qdev_prop_chr = {
 | 
					PropertyInfo qdev_prop_chr = {
 | 
				
			||||||
 | 
				
			|||||||
@ -1589,7 +1589,7 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
 | 
				
			|||||||
        pcspk_init(isa_bus, pit);
 | 
					        pcspk_init(isa_bus, pit);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    serial_hds_isa_init(isa_bus, MAX_SERIAL_PORTS);
 | 
					    serial_hds_isa_init(isa_bus, 0, MAX_SERIAL_PORTS);
 | 
				
			||||||
    parallel_hds_isa_init(isa_bus, MAX_PARALLEL_PORTS);
 | 
					    parallel_hds_isa_init(isa_bus, MAX_PARALLEL_PORTS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    a20_line = qemu_allocate_irqs(handle_a20_line_change, first_cpu, 2);
 | 
					    a20_line = qemu_allocate_irqs(handle_a20_line_change, first_cpu, 2);
 | 
				
			||||||
 | 
				
			|||||||
@ -62,7 +62,7 @@
 | 
				
			|||||||
typedef struct IPMIBmcExtern {
 | 
					typedef struct IPMIBmcExtern {
 | 
				
			||||||
    IPMIBmc parent;
 | 
					    IPMIBmc parent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    CharDriverState *chr;
 | 
					    CharBackend chr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    bool connected;
 | 
					    bool connected;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -105,7 +105,7 @@ static void continue_send(IPMIBmcExtern *ibe)
 | 
				
			|||||||
        goto check_reset;
 | 
					        goto check_reset;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 send:
 | 
					 send:
 | 
				
			||||||
    ret = qemu_chr_fe_write(ibe->chr, ibe->outbuf + ibe->outpos,
 | 
					    ret = qemu_chr_fe_write(&ibe->chr, ibe->outbuf + ibe->outpos,
 | 
				
			||||||
                            ibe->outlen - ibe->outpos);
 | 
					                            ibe->outlen - ibe->outpos);
 | 
				
			||||||
    if (ret > 0) {
 | 
					    if (ret > 0) {
 | 
				
			||||||
        ibe->outpos += ret;
 | 
					        ibe->outpos += ret;
 | 
				
			||||||
@ -442,12 +442,13 @@ static void ipmi_bmc_extern_realize(DeviceState *dev, Error **errp)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    IPMIBmcExtern *ibe = IPMI_BMC_EXTERN(dev);
 | 
					    IPMIBmcExtern *ibe = IPMI_BMC_EXTERN(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!ibe->chr) {
 | 
					    if (!qemu_chr_fe_get_driver(&ibe->chr)) {
 | 
				
			||||||
        error_setg(errp, "IPMI external bmc requires chardev attribute");
 | 
					        error_setg(errp, "IPMI external bmc requires chardev attribute");
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qemu_chr_add_handlers(ibe->chr, can_receive, receive, chr_event, ibe);
 | 
					    qemu_chr_fe_set_handlers(&ibe->chr, can_receive, receive,
 | 
				
			||||||
 | 
					                             chr_event, ibe, NULL, true);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int ipmi_bmc_extern_post_migrate(void *opaque, int version_id)
 | 
					static int ipmi_bmc_extern_post_migrate(void *opaque, int version_id)
 | 
				
			||||||
 | 
				
			|||||||
@ -283,7 +283,7 @@ static void pc87312_realize(DeviceState *dev, Error **errp)
 | 
				
			|||||||
        /* FIXME use a qdev chardev prop instead of parallel_hds[] */
 | 
					        /* FIXME use a qdev chardev prop instead of parallel_hds[] */
 | 
				
			||||||
        chr = parallel_hds[0];
 | 
					        chr = parallel_hds[0];
 | 
				
			||||||
        if (chr == NULL) {
 | 
					        if (chr == NULL) {
 | 
				
			||||||
            chr = qemu_chr_new("par0", "null", NULL);
 | 
					            chr = qemu_chr_new("par0", "null");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        isa = isa_create(bus, "isa-parallel");
 | 
					        isa = isa_create(bus, "isa-parallel");
 | 
				
			||||||
        d = DEVICE(isa);
 | 
					        d = DEVICE(isa);
 | 
				
			||||||
@ -303,7 +303,7 @@ static void pc87312_realize(DeviceState *dev, Error **errp)
 | 
				
			|||||||
            chr = serial_hds[i];
 | 
					            chr = serial_hds[i];
 | 
				
			||||||
            if (chr == NULL) {
 | 
					            if (chr == NULL) {
 | 
				
			||||||
                snprintf(name, sizeof(name), "ser%d", i);
 | 
					                snprintf(name, sizeof(name), "ser%d", i);
 | 
				
			||||||
                chr = qemu_chr_new(name, "null", NULL);
 | 
					                chr = qemu_chr_new(name, "null");
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            isa = isa_create(bus, "isa-serial");
 | 
					            isa = isa_create(bus, "isa-serial");
 | 
				
			||||||
            d = DEVICE(isa);
 | 
					            d = DEVICE(isa);
 | 
				
			||||||
 | 
				
			|||||||
@ -374,7 +374,7 @@ static void mips_fulong2e_init(MachineState *machine)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    rtc_init(isa_bus, 2000, NULL);
 | 
					    rtc_init(isa_bus, 2000, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    serial_hds_isa_init(isa_bus, MAX_SERIAL_PORTS);
 | 
					    serial_hds_isa_init(isa_bus, 0, MAX_SERIAL_PORTS);
 | 
				
			||||||
    parallel_hds_isa_init(isa_bus, 1);
 | 
					    parallel_hds_isa_init(isa_bus, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Sound card */
 | 
					    /* Sound card */
 | 
				
			||||||
 | 
				
			|||||||
@ -85,9 +85,10 @@ typedef struct {
 | 
				
			|||||||
    uint32_t i2coe;
 | 
					    uint32_t i2coe;
 | 
				
			||||||
    uint32_t i2cout;
 | 
					    uint32_t i2cout;
 | 
				
			||||||
    uint32_t i2csel;
 | 
					    uint32_t i2csel;
 | 
				
			||||||
    CharDriverState *display;
 | 
					    CharBackend display;
 | 
				
			||||||
    char display_text[9];
 | 
					    char display_text[9];
 | 
				
			||||||
    SerialState *uart;
 | 
					    SerialState *uart;
 | 
				
			||||||
 | 
					    bool display_inited;
 | 
				
			||||||
} MaltaFPGAState;
 | 
					} MaltaFPGAState;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define TYPE_MIPS_MALTA "mips-malta"
 | 
					#define TYPE_MIPS_MALTA "mips-malta"
 | 
				
			||||||
@ -124,8 +125,10 @@ static void malta_fpga_update_display(void *opaque)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    leds_text[8] = '\0';
 | 
					    leds_text[8] = '\0';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qemu_chr_fe_printf(s->display, "\e[H\n\n|\e[32m%-8.8s\e[00m|\r\n", leds_text);
 | 
					    qemu_chr_fe_printf(&s->display, "\e[H\n\n|\e[32m%-8.8s\e[00m|\r\n",
 | 
				
			||||||
    qemu_chr_fe_printf(s->display, "\n\n\n\n|\e[31m%-8.8s\e[00m|", s->display_text);
 | 
					                       leds_text);
 | 
				
			||||||
 | 
					    qemu_chr_fe_printf(&s->display, "\n\n\n\n|\e[31m%-8.8s\e[00m|",
 | 
				
			||||||
 | 
					                       s->display_text);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
@ -530,23 +533,29 @@ static void malta_fpga_reset(void *opaque)
 | 
				
			|||||||
    snprintf(s->display_text, 9, "        ");
 | 
					    snprintf(s->display_text, 9, "        ");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void malta_fpga_led_init(CharDriverState *chr)
 | 
					static void malta_fgpa_display_event(void *opaque, int event)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    qemu_chr_fe_printf(chr, "\e[HMalta LEDBAR\r\n");
 | 
					    MaltaFPGAState *s = opaque;
 | 
				
			||||||
    qemu_chr_fe_printf(chr, "+--------+\r\n");
 | 
					
 | 
				
			||||||
    qemu_chr_fe_printf(chr, "+        +\r\n");
 | 
					    if (event == CHR_EVENT_OPENED && !s->display_inited) {
 | 
				
			||||||
    qemu_chr_fe_printf(chr, "+--------+\r\n");
 | 
					        qemu_chr_fe_printf(&s->display, "\e[HMalta LEDBAR\r\n");
 | 
				
			||||||
    qemu_chr_fe_printf(chr, "\n");
 | 
					        qemu_chr_fe_printf(&s->display, "+--------+\r\n");
 | 
				
			||||||
    qemu_chr_fe_printf(chr, "Malta ASCII\r\n");
 | 
					        qemu_chr_fe_printf(&s->display, "+        +\r\n");
 | 
				
			||||||
    qemu_chr_fe_printf(chr, "+--------+\r\n");
 | 
					        qemu_chr_fe_printf(&s->display, "+--------+\r\n");
 | 
				
			||||||
    qemu_chr_fe_printf(chr, "+        +\r\n");
 | 
					        qemu_chr_fe_printf(&s->display, "\n");
 | 
				
			||||||
    qemu_chr_fe_printf(chr, "+--------+\r\n");
 | 
					        qemu_chr_fe_printf(&s->display, "Malta ASCII\r\n");
 | 
				
			||||||
 | 
					        qemu_chr_fe_printf(&s->display, "+--------+\r\n");
 | 
				
			||||||
 | 
					        qemu_chr_fe_printf(&s->display, "+        +\r\n");
 | 
				
			||||||
 | 
					        qemu_chr_fe_printf(&s->display, "+--------+\r\n");
 | 
				
			||||||
 | 
					        s->display_inited = true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static MaltaFPGAState *malta_fpga_init(MemoryRegion *address_space,
 | 
					static MaltaFPGAState *malta_fpga_init(MemoryRegion *address_space,
 | 
				
			||||||
         hwaddr base, qemu_irq uart_irq, CharDriverState *uart_chr)
 | 
					         hwaddr base, qemu_irq uart_irq, CharDriverState *uart_chr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    MaltaFPGAState *s;
 | 
					    MaltaFPGAState *s;
 | 
				
			||||||
 | 
					    CharDriverState *chr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s = (MaltaFPGAState *)g_malloc0(sizeof(MaltaFPGAState));
 | 
					    s = (MaltaFPGAState *)g_malloc0(sizeof(MaltaFPGAState));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -560,7 +569,10 @@ static MaltaFPGAState *malta_fpga_init(MemoryRegion *address_space,
 | 
				
			|||||||
    memory_region_add_subregion(address_space, base, &s->iomem_lo);
 | 
					    memory_region_add_subregion(address_space, base, &s->iomem_lo);
 | 
				
			||||||
    memory_region_add_subregion(address_space, base + 0xa00, &s->iomem_hi);
 | 
					    memory_region_add_subregion(address_space, base + 0xa00, &s->iomem_hi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->display = qemu_chr_new("fpga", "vc:320x200", malta_fpga_led_init);
 | 
					    chr = qemu_chr_new("fpga", "vc:320x200");
 | 
				
			||||||
 | 
					    qemu_chr_fe_init(&s->display, chr, NULL);
 | 
				
			||||||
 | 
					    qemu_chr_fe_set_handlers(&s->display, NULL, NULL,
 | 
				
			||||||
 | 
					                             malta_fgpa_display_event, s, NULL, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->uart = serial_mm_init(address_space, base + 0x900, 3, uart_irq,
 | 
					    s->uart = serial_mm_init(address_space, base + 0x900, 3, uart_irq,
 | 
				
			||||||
                             230400, uart_chr, DEVICE_NATIVE_ENDIAN);
 | 
					                             230400, uart_chr, DEVICE_NATIVE_ENDIAN);
 | 
				
			||||||
@ -1025,7 +1037,7 @@ void mips_malta_init(MachineState *machine)
 | 
				
			|||||||
        if (!serial_hds[i]) {
 | 
					        if (!serial_hds[i]) {
 | 
				
			||||||
            char label[32];
 | 
					            char label[32];
 | 
				
			||||||
            snprintf(label, sizeof(label), "serial%d", i);
 | 
					            snprintf(label, sizeof(label), "serial%d", i);
 | 
				
			||||||
            serial_hds[i] = qemu_chr_new(label, "null", NULL);
 | 
					            serial_hds[i] = qemu_chr_new(label, "null");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -1215,7 +1227,7 @@ void mips_malta_init(MachineState *machine)
 | 
				
			|||||||
    isa_create_simple(isa_bus, "i8042");
 | 
					    isa_create_simple(isa_bus, "i8042");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    rtc_init(isa_bus, 2000, NULL);
 | 
					    rtc_init(isa_bus, 2000, NULL);
 | 
				
			||||||
    serial_hds_isa_init(isa_bus, 2);
 | 
					    serial_hds_isa_init(isa_bus, 0, 2);
 | 
				
			||||||
    parallel_hds_isa_init(isa_bus, 1);
 | 
					    parallel_hds_isa_init(isa_bus, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for(i = 0; i < MAX_FD; i++) {
 | 
					    for(i = 0; i < MAX_FD; i++) {
 | 
				
			||||||
 | 
				
			|||||||
@ -286,7 +286,7 @@ void mips_r4k_init(MachineState *machine)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    pit = pit_init(isa_bus, 0x40, 0, NULL);
 | 
					    pit = pit_init(isa_bus, 0x40, 0, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    serial_hds_isa_init(isa_bus, MAX_SERIAL_PORTS);
 | 
					    serial_hds_isa_init(isa_bus, 0, MAX_SERIAL_PORTS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    isa_vga_init(isa_bus);
 | 
					    isa_vga_init(isa_bus);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -88,7 +88,7 @@ typedef struct IVShmemState {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    /* exactly one of these two may be set */
 | 
					    /* exactly one of these two may be set */
 | 
				
			||||||
    HostMemoryBackend *hostmem; /* with interrupts */
 | 
					    HostMemoryBackend *hostmem; /* with interrupts */
 | 
				
			||||||
    CharDriverState *server_chr; /* without interrupts */
 | 
					    CharBackend server_chr; /* without interrupts */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* registers */
 | 
					    /* registers */
 | 
				
			||||||
    uint32_t intrmask;
 | 
					    uint32_t intrmask;
 | 
				
			||||||
@ -627,7 +627,7 @@ static void ivshmem_read(void *opaque, const uint8_t *buf, int size)
 | 
				
			|||||||
    msg = le64_to_cpu(s->msg_buf);
 | 
					    msg = le64_to_cpu(s->msg_buf);
 | 
				
			||||||
    s->msg_buffered_bytes = 0;
 | 
					    s->msg_buffered_bytes = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fd = qemu_chr_fe_get_msgfd(s->server_chr);
 | 
					    fd = qemu_chr_fe_get_msgfd(&s->server_chr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    process_msg(s, msg, fd, &err);
 | 
					    process_msg(s, msg, fd, &err);
 | 
				
			||||||
    if (err) {
 | 
					    if (err) {
 | 
				
			||||||
@ -642,7 +642,7 @@ static int64_t ivshmem_recv_msg(IVShmemState *s, int *pfd, Error **errp)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    n = 0;
 | 
					    n = 0;
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
        ret = qemu_chr_fe_read_all(s->server_chr, (uint8_t *)&msg + n,
 | 
					        ret = qemu_chr_fe_read_all(&s->server_chr, (uint8_t *)&msg + n,
 | 
				
			||||||
                                   sizeof(msg) - n);
 | 
					                                   sizeof(msg) - n);
 | 
				
			||||||
        if (ret < 0 && ret != -EINTR) {
 | 
					        if (ret < 0 && ret != -EINTR) {
 | 
				
			||||||
            error_setg_errno(errp, -ret, "read from server failed");
 | 
					            error_setg_errno(errp, -ret, "read from server failed");
 | 
				
			||||||
@ -651,7 +651,7 @@ static int64_t ivshmem_recv_msg(IVShmemState *s, int *pfd, Error **errp)
 | 
				
			|||||||
        n += ret;
 | 
					        n += ret;
 | 
				
			||||||
    } while (n < sizeof(msg));
 | 
					    } while (n < sizeof(msg));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    *pfd = qemu_chr_fe_get_msgfd(s->server_chr);
 | 
					    *pfd = qemu_chr_fe_get_msgfd(&s->server_chr);
 | 
				
			||||||
    return msg;
 | 
					    return msg;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -868,10 +868,11 @@ static void ivshmem_common_realize(PCIDevice *dev, Error **errp)
 | 
				
			|||||||
        s->ivshmem_bar2 = host_memory_backend_get_memory(s->hostmem,
 | 
					        s->ivshmem_bar2 = host_memory_backend_get_memory(s->hostmem,
 | 
				
			||||||
                                                         &error_abort);
 | 
					                                                         &error_abort);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        assert(s->server_chr);
 | 
					        CharDriverState *chr = qemu_chr_fe_get_driver(&s->server_chr);
 | 
				
			||||||
 | 
					        assert(chr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        IVSHMEM_DPRINTF("using shared memory server (socket = %s)\n",
 | 
					        IVSHMEM_DPRINTF("using shared memory server (socket = %s)\n",
 | 
				
			||||||
                        s->server_chr->filename);
 | 
					                        chr->filename);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* we allocate enough space for 16 peers and grow as needed */
 | 
					        /* we allocate enough space for 16 peers and grow as needed */
 | 
				
			||||||
        resize_peers(s, 16);
 | 
					        resize_peers(s, 16);
 | 
				
			||||||
@ -893,8 +894,8 @@ static void ivshmem_common_realize(PCIDevice *dev, Error **errp)
 | 
				
			|||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        qemu_chr_add_handlers(s->server_chr, ivshmem_can_receive,
 | 
					        qemu_chr_fe_set_handlers(&s->server_chr, ivshmem_can_receive,
 | 
				
			||||||
                              ivshmem_read, NULL, s);
 | 
					                                 ivshmem_read, NULL, s, NULL, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (ivshmem_setup_interrupts(s) < 0) {
 | 
					        if (ivshmem_setup_interrupts(s) < 0) {
 | 
				
			||||||
            error_setg(errp, "failed to initialize interrupts");
 | 
					            error_setg(errp, "failed to initialize interrupts");
 | 
				
			||||||
@ -1121,7 +1122,7 @@ static void ivshmem_doorbell_realize(PCIDevice *dev, Error **errp)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    IVShmemState *s = IVSHMEM_COMMON(dev);
 | 
					    IVShmemState *s = IVSHMEM_COMMON(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!s->server_chr) {
 | 
					    if (!qemu_chr_fe_get_driver(&s->server_chr)) {
 | 
				
			||||||
        error_setg(errp, "You must specify a 'chardev'");
 | 
					        error_setg(errp, "You must specify a 'chardev'");
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -1250,7 +1251,7 @@ static void ivshmem_realize(PCIDevice *dev, Error **errp)
 | 
				
			|||||||
                     " or ivshmem-doorbell instead");
 | 
					                     " or ivshmem-doorbell instead");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!!s->server_chr + !!s->shmobj != 1) {
 | 
					    if (!!qemu_chr_fe_get_driver(&s->server_chr) + !!s->shmobj != 1) {
 | 
				
			||||||
        error_setg(errp, "You must specify either 'shm' or 'chardev'");
 | 
					        error_setg(errp, "You must specify either 'shm' or 'chardev'");
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -824,7 +824,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
 | 
				
			|||||||
        i++;
 | 
					        i++;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    serial_hds_isa_init(isa_bus, MAX_SERIAL_PORTS);
 | 
					    serial_hds_isa_init(isa_bus, i, MAX_SERIAL_PORTS);
 | 
				
			||||||
    parallel_hds_isa_init(isa_bus, MAX_PARALLEL_PORTS);
 | 
					    parallel_hds_isa_init(isa_bus, MAX_PARALLEL_PORTS);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for(i = 0; i < nb_nics; i++)
 | 
					    for(i = 0; i < nb_nics; i++)
 | 
				
			||||||
 | 
				
			|||||||
@ -607,6 +607,7 @@ static void xilinx_spips_realize(DeviceState *dev, Error **errp)
 | 
				
			|||||||
    XilinxSPIPS *s = XILINX_SPIPS(dev);
 | 
					    XilinxSPIPS *s = XILINX_SPIPS(dev);
 | 
				
			||||||
    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
 | 
					    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
 | 
				
			||||||
    XilinxSPIPSClass *xsc = XILINX_SPIPS_GET_CLASS(s);
 | 
					    XilinxSPIPSClass *xsc = XILINX_SPIPS_GET_CLASS(s);
 | 
				
			||||||
 | 
					    qemu_irq *cs;
 | 
				
			||||||
    int i;
 | 
					    int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    DB_PRINT_L(0, "realized spips\n");
 | 
					    DB_PRINT_L(0, "realized spips\n");
 | 
				
			||||||
@ -619,8 +620,10 @@ static void xilinx_spips_realize(DeviceState *dev, Error **errp)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->cs_lines = g_new0(qemu_irq, s->num_cs * s->num_busses);
 | 
					    s->cs_lines = g_new0(qemu_irq, s->num_cs * s->num_busses);
 | 
				
			||||||
    ssi_auto_connect_slaves(DEVICE(s), s->cs_lines, s->spi[0]);
 | 
					    for (i = 0, cs = s->cs_lines; i < s->num_busses; ++i, cs += s->num_cs) {
 | 
				
			||||||
    ssi_auto_connect_slaves(DEVICE(s), s->cs_lines, s->spi[1]);
 | 
					        ssi_auto_connect_slaves(DEVICE(s), cs, s->spi[i]);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sysbus_init_irq(sbd, &s->irq);
 | 
					    sysbus_init_irq(sbd, &s->irq);
 | 
				
			||||||
    for (i = 0; i < s->num_cs * s->num_busses; ++i) {
 | 
					    for (i = 0; i < s->num_cs * s->num_busses; ++i) {
 | 
				
			||||||
        sysbus_init_irq(sbd, &s->cs_lines[i]);
 | 
					        sysbus_init_irq(sbd, &s->cs_lines[i]);
 | 
				
			||||||
 | 
				
			|||||||
@ -48,7 +48,7 @@ typedef struct PassthruState PassthruState;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
struct PassthruState {
 | 
					struct PassthruState {
 | 
				
			||||||
    CCIDCardState base;
 | 
					    CCIDCardState base;
 | 
				
			||||||
    CharDriverState *cs;
 | 
					    CharBackend cs;
 | 
				
			||||||
    uint8_t  vscard_in_data[VSCARD_IN_SIZE];
 | 
					    uint8_t  vscard_in_data[VSCARD_IN_SIZE];
 | 
				
			||||||
    uint32_t vscard_in_pos;
 | 
					    uint32_t vscard_in_pos;
 | 
				
			||||||
    uint32_t vscard_in_hdr;
 | 
					    uint32_t vscard_in_hdr;
 | 
				
			||||||
@ -77,9 +77,9 @@ static void ccid_card_vscard_send_msg(PassthruState *s,
 | 
				
			|||||||
    scr_msg_header.length = htonl(length);
 | 
					    scr_msg_header.length = htonl(length);
 | 
				
			||||||
    /* XXX this blocks entire thread. Rewrite to use
 | 
					    /* XXX this blocks entire thread. Rewrite to use
 | 
				
			||||||
     * qemu_chr_fe_write and background I/O callbacks */
 | 
					     * qemu_chr_fe_write and background I/O callbacks */
 | 
				
			||||||
    qemu_chr_fe_write_all(s->cs, (uint8_t *)&scr_msg_header,
 | 
					    qemu_chr_fe_write_all(&s->cs, (uint8_t *)&scr_msg_header,
 | 
				
			||||||
                          sizeof(VSCMsgHeader));
 | 
					                          sizeof(VSCMsgHeader));
 | 
				
			||||||
    qemu_chr_fe_write_all(s->cs, payload, length);
 | 
					    qemu_chr_fe_write_all(&s->cs, payload, length);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void ccid_card_vscard_send_apdu(PassthruState *s,
 | 
					static void ccid_card_vscard_send_apdu(PassthruState *s,
 | 
				
			||||||
@ -264,7 +264,10 @@ static void ccid_card_vscard_handle_message(PassthruState *card,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void ccid_card_vscard_drop_connection(PassthruState *card)
 | 
					static void ccid_card_vscard_drop_connection(PassthruState *card)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    qemu_chr_delete(card->cs);
 | 
					    CharDriverState *chr = qemu_chr_fe_get_driver(&card->cs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qemu_chr_fe_deinit(&card->cs);
 | 
				
			||||||
 | 
					    qemu_chr_delete(chr);
 | 
				
			||||||
    card->vscard_in_pos = card->vscard_in_hdr = 0;
 | 
					    card->vscard_in_pos = card->vscard_in_hdr = 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -309,8 +312,6 @@ static void ccid_card_vscard_event(void *opaque, int event)
 | 
				
			|||||||
    case CHR_EVENT_BREAK:
 | 
					    case CHR_EVENT_BREAK:
 | 
				
			||||||
        card->vscard_in_pos = card->vscard_in_hdr = 0;
 | 
					        card->vscard_in_pos = card->vscard_in_hdr = 0;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case CHR_EVENT_FOCUS:
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
    case CHR_EVENT_OPENED:
 | 
					    case CHR_EVENT_OPENED:
 | 
				
			||||||
        DPRINTF(card, D_INFO, "%s: CHR_EVENT_OPENED\n", __func__);
 | 
					        DPRINTF(card, D_INFO, "%s: CHR_EVENT_OPENED\n", __func__);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
@ -324,7 +325,7 @@ static void passthru_apdu_from_guest(
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    PassthruState *card = PASSTHRU_CCID_CARD(base);
 | 
					    PassthruState *card = PASSTHRU_CCID_CARD(base);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!card->cs) {
 | 
					    if (!qemu_chr_fe_get_driver(&card->cs)) {
 | 
				
			||||||
        printf("ccid-passthru: no chardev, discarding apdu length %d\n", len);
 | 
					        printf("ccid-passthru: no chardev, discarding apdu length %d\n", len);
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -345,12 +346,12 @@ static int passthru_initfn(CCIDCardState *base)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    card->vscard_in_pos = 0;
 | 
					    card->vscard_in_pos = 0;
 | 
				
			||||||
    card->vscard_in_hdr = 0;
 | 
					    card->vscard_in_hdr = 0;
 | 
				
			||||||
    if (card->cs) {
 | 
					    if (qemu_chr_fe_get_driver(&card->cs)) {
 | 
				
			||||||
        DPRINTF(card, D_INFO, "initing chardev\n");
 | 
					        DPRINTF(card, D_INFO, "initing chardev\n");
 | 
				
			||||||
        qemu_chr_add_handlers(card->cs,
 | 
					        qemu_chr_fe_set_handlers(&card->cs,
 | 
				
			||||||
            ccid_card_vscard_can_read,
 | 
					            ccid_card_vscard_can_read,
 | 
				
			||||||
            ccid_card_vscard_read,
 | 
					            ccid_card_vscard_read,
 | 
				
			||||||
            ccid_card_vscard_event, card);
 | 
					            ccid_card_vscard_event, card, NULL, true);
 | 
				
			||||||
        ccid_card_vscard_send_init(card);
 | 
					        ccid_card_vscard_send_init(card);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        error_report("missing chardev");
 | 
					        error_report("missing chardev");
 | 
				
			||||||
 | 
				
			|||||||
@ -103,7 +103,7 @@ typedef struct {
 | 
				
			|||||||
    uint8_t event_trigger;
 | 
					    uint8_t event_trigger;
 | 
				
			||||||
    QEMUSerialSetParams params;
 | 
					    QEMUSerialSetParams params;
 | 
				
			||||||
    int latency;        /* ms */
 | 
					    int latency;        /* ms */
 | 
				
			||||||
    CharDriverState *cs;
 | 
					    CharBackend cs;
 | 
				
			||||||
} USBSerialState;
 | 
					} USBSerialState;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define TYPE_USB_SERIAL "usb-serial-dev"
 | 
					#define TYPE_USB_SERIAL "usb-serial-dev"
 | 
				
			||||||
@ -209,8 +209,10 @@ static uint8_t usb_get_modem_lines(USBSerialState *s)
 | 
				
			|||||||
    int flags;
 | 
					    int flags;
 | 
				
			||||||
    uint8_t ret;
 | 
					    uint8_t ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (qemu_chr_fe_ioctl(s->cs, CHR_IOCTL_SERIAL_GET_TIOCM, &flags) == -ENOTSUP)
 | 
					    if (qemu_chr_fe_ioctl(&s->cs,
 | 
				
			||||||
 | 
					                          CHR_IOCTL_SERIAL_GET_TIOCM, &flags) == -ENOTSUP) {
 | 
				
			||||||
        return FTDI_CTS|FTDI_DSR|FTDI_RLSD;
 | 
					        return FTDI_CTS|FTDI_DSR|FTDI_RLSD;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ret = 0;
 | 
					    ret = 0;
 | 
				
			||||||
    if (flags & CHR_TIOCM_CTS)
 | 
					    if (flags & CHR_TIOCM_CTS)
 | 
				
			||||||
@ -260,7 +262,7 @@ static void usb_serial_handle_control(USBDevice *dev, USBPacket *p,
 | 
				
			|||||||
    case DeviceOutVendor | FTDI_SET_MDM_CTRL:
 | 
					    case DeviceOutVendor | FTDI_SET_MDM_CTRL:
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        static int flags;
 | 
					        static int flags;
 | 
				
			||||||
        qemu_chr_fe_ioctl(s->cs,CHR_IOCTL_SERIAL_GET_TIOCM, &flags);
 | 
					        qemu_chr_fe_ioctl(&s->cs, CHR_IOCTL_SERIAL_GET_TIOCM, &flags);
 | 
				
			||||||
        if (value & FTDI_SET_RTS) {
 | 
					        if (value & FTDI_SET_RTS) {
 | 
				
			||||||
            if (value & FTDI_RTS)
 | 
					            if (value & FTDI_RTS)
 | 
				
			||||||
                flags |= CHR_TIOCM_RTS;
 | 
					                flags |= CHR_TIOCM_RTS;
 | 
				
			||||||
@ -273,7 +275,7 @@ static void usb_serial_handle_control(USBDevice *dev, USBPacket *p,
 | 
				
			|||||||
            else
 | 
					            else
 | 
				
			||||||
                flags &= ~CHR_TIOCM_DTR;
 | 
					                flags &= ~CHR_TIOCM_DTR;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        qemu_chr_fe_ioctl(s->cs,CHR_IOCTL_SERIAL_SET_TIOCM, &flags);
 | 
					        qemu_chr_fe_ioctl(&s->cs, CHR_IOCTL_SERIAL_SET_TIOCM, &flags);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case DeviceOutVendor | FTDI_SET_FLOW_CTRL:
 | 
					    case DeviceOutVendor | FTDI_SET_FLOW_CTRL:
 | 
				
			||||||
@ -292,7 +294,7 @@ static void usb_serial_handle_control(USBDevice *dev, USBPacket *p,
 | 
				
			|||||||
            divisor = 1;
 | 
					            divisor = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        s->params.speed = (48000000 / 2) / (8 * divisor + subdivisor8);
 | 
					        s->params.speed = (48000000 / 2) / (8 * divisor + subdivisor8);
 | 
				
			||||||
        qemu_chr_fe_ioctl(s->cs, CHR_IOCTL_SERIAL_SET_PARAMS, &s->params);
 | 
					        qemu_chr_fe_ioctl(&s->cs, CHR_IOCTL_SERIAL_SET_PARAMS, &s->params);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    case DeviceOutVendor | FTDI_SET_DATA:
 | 
					    case DeviceOutVendor | FTDI_SET_DATA:
 | 
				
			||||||
@ -321,7 +323,7 @@ static void usb_serial_handle_control(USBDevice *dev, USBPacket *p,
 | 
				
			|||||||
                DPRINTF("unsupported stop bits %d\n", value & FTDI_STOP);
 | 
					                DPRINTF("unsupported stop bits %d\n", value & FTDI_STOP);
 | 
				
			||||||
                goto fail;
 | 
					                goto fail;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        qemu_chr_fe_ioctl(s->cs, CHR_IOCTL_SERIAL_SET_PARAMS, &s->params);
 | 
					        qemu_chr_fe_ioctl(&s->cs, CHR_IOCTL_SERIAL_SET_PARAMS, &s->params);
 | 
				
			||||||
        /* TODO: TX ON/OFF */
 | 
					        /* TODO: TX ON/OFF */
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case DeviceInVendor | FTDI_GET_MDM_ST:
 | 
					    case DeviceInVendor | FTDI_GET_MDM_ST:
 | 
				
			||||||
@ -368,7 +370,7 @@ static void usb_serial_handle_data(USBDevice *dev, USBPacket *p)
 | 
				
			|||||||
            iov = p->iov.iov + i;
 | 
					            iov = p->iov.iov + i;
 | 
				
			||||||
            /* XXX this blocks entire thread. Rewrite to use
 | 
					            /* XXX this blocks entire thread. Rewrite to use
 | 
				
			||||||
             * qemu_chr_fe_write and background I/O callbacks */
 | 
					             * qemu_chr_fe_write and background I/O callbacks */
 | 
				
			||||||
            qemu_chr_fe_write_all(s->cs, iov->iov_base, iov->iov_len);
 | 
					            qemu_chr_fe_write_all(&s->cs, iov->iov_base, iov->iov_len);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        p->actual_length = p->iov.size;
 | 
					        p->actual_length = p->iov.size;
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
@ -464,8 +466,6 @@ static void usb_serial_event(void *opaque, int event)
 | 
				
			|||||||
        case CHR_EVENT_BREAK:
 | 
					        case CHR_EVENT_BREAK:
 | 
				
			||||||
            s->event_trigger |= FTDI_BI;
 | 
					            s->event_trigger |= FTDI_BI;
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        case CHR_EVENT_FOCUS:
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        case CHR_EVENT_OPENED:
 | 
					        case CHR_EVENT_OPENED:
 | 
				
			||||||
            if (!s->dev.attached) {
 | 
					            if (!s->dev.attached) {
 | 
				
			||||||
                usb_device_attach(&s->dev, &error_abort);
 | 
					                usb_device_attach(&s->dev, &error_abort);
 | 
				
			||||||
@ -483,12 +483,13 @@ static void usb_serial_realize(USBDevice *dev, Error **errp)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    USBSerialState *s = USB_SERIAL_DEV(dev);
 | 
					    USBSerialState *s = USB_SERIAL_DEV(dev);
 | 
				
			||||||
    Error *local_err = NULL;
 | 
					    Error *local_err = NULL;
 | 
				
			||||||
 | 
					    CharDriverState *chr = qemu_chr_fe_get_driver(&s->cs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    usb_desc_create_serial(dev);
 | 
					    usb_desc_create_serial(dev);
 | 
				
			||||||
    usb_desc_init(dev);
 | 
					    usb_desc_init(dev);
 | 
				
			||||||
    dev->auto_attach = 0;
 | 
					    dev->auto_attach = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!s->cs) {
 | 
					    if (!chr) {
 | 
				
			||||||
        error_setg(errp, "Property chardev is required");
 | 
					        error_setg(errp, "Property chardev is required");
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -499,11 +500,11 @@ static void usb_serial_realize(USBDevice *dev, Error **errp)
 | 
				
			|||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qemu_chr_add_handlers(s->cs, usb_serial_can_read, usb_serial_read,
 | 
					    qemu_chr_fe_set_handlers(&s->cs, usb_serial_can_read, usb_serial_read,
 | 
				
			||||||
                          usb_serial_event, s);
 | 
					                             usb_serial_event, s, NULL, true);
 | 
				
			||||||
    usb_serial_handle_reset(dev);
 | 
					    usb_serial_handle_reset(dev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (s->cs->be_open && !dev->attached) {
 | 
					    if (chr->be_open && !dev->attached) {
 | 
				
			||||||
        usb_device_attach(dev, &error_abort);
 | 
					        usb_device_attach(dev, &error_abort);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -547,7 +548,7 @@ static USBDevice *usb_serial_init(USBBus *bus, const char *filename)
 | 
				
			|||||||
    filename++;
 | 
					    filename++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    snprintf(label, sizeof(label), "usbserial%d", index++);
 | 
					    snprintf(label, sizeof(label), "usbserial%d", index++);
 | 
				
			||||||
    cdrv = qemu_chr_new(label, filename, NULL);
 | 
					    cdrv = qemu_chr_new(label, filename);
 | 
				
			||||||
    if (!cdrv)
 | 
					    if (!cdrv)
 | 
				
			||||||
        return NULL;
 | 
					        return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -565,7 +566,7 @@ static USBDevice *usb_braille_init(USBBus *bus, const char *unused)
 | 
				
			|||||||
    USBDevice *dev;
 | 
					    USBDevice *dev;
 | 
				
			||||||
    CharDriverState *cdrv;
 | 
					    CharDriverState *cdrv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    cdrv = qemu_chr_new("braille", "braille", NULL);
 | 
					    cdrv = qemu_chr_new("braille", "braille");
 | 
				
			||||||
    if (!cdrv)
 | 
					    if (!cdrv)
 | 
				
			||||||
        return NULL;
 | 
					        return NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -105,7 +105,7 @@ struct PacketIdQueue {
 | 
				
			|||||||
struct USBRedirDevice {
 | 
					struct USBRedirDevice {
 | 
				
			||||||
    USBDevice dev;
 | 
					    USBDevice dev;
 | 
				
			||||||
    /* Properties */
 | 
					    /* Properties */
 | 
				
			||||||
    CharDriverState *cs;
 | 
					    CharBackend cs;
 | 
				
			||||||
    uint8_t debug;
 | 
					    uint8_t debug;
 | 
				
			||||||
    char *filter_str;
 | 
					    char *filter_str;
 | 
				
			||||||
    int32_t bootindex;
 | 
					    int32_t bootindex;
 | 
				
			||||||
@ -283,9 +283,10 @@ static gboolean usbredir_write_unblocked(GIOChannel *chan, GIOCondition cond,
 | 
				
			|||||||
static int usbredir_write(void *priv, uint8_t *data, int count)
 | 
					static int usbredir_write(void *priv, uint8_t *data, int count)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    USBRedirDevice *dev = priv;
 | 
					    USBRedirDevice *dev = priv;
 | 
				
			||||||
 | 
					    CharDriverState *chr = qemu_chr_fe_get_driver(&dev->cs);
 | 
				
			||||||
    int r;
 | 
					    int r;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!dev->cs->be_open) {
 | 
					    if (!chr->be_open) {
 | 
				
			||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -294,10 +295,10 @@ static int usbredir_write(void *priv, uint8_t *data, int count)
 | 
				
			|||||||
        return 0;
 | 
					        return 0;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    r = qemu_chr_fe_write(dev->cs, data, count);
 | 
					    r = qemu_chr_fe_write(&dev->cs, data, count);
 | 
				
			||||||
    if (r < count) {
 | 
					    if (r < count) {
 | 
				
			||||||
        if (!dev->watch) {
 | 
					        if (!dev->watch) {
 | 
				
			||||||
            dev->watch = qemu_chr_fe_add_watch(dev->cs, G_IO_OUT|G_IO_HUP,
 | 
					            dev->watch = qemu_chr_fe_add_watch(&dev->cs, G_IO_OUT | G_IO_HUP,
 | 
				
			||||||
                                               usbredir_write_unblocked, dev);
 | 
					                                               usbredir_write_unblocked, dev);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (r < 0) {
 | 
					        if (r < 0) {
 | 
				
			||||||
@ -1375,7 +1376,7 @@ static void usbredir_realize(USBDevice *udev, Error **errp)
 | 
				
			|||||||
    USBRedirDevice *dev = USB_REDIRECT(udev);
 | 
					    USBRedirDevice *dev = USB_REDIRECT(udev);
 | 
				
			||||||
    int i;
 | 
					    int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (dev->cs == NULL) {
 | 
					    if (!qemu_chr_fe_get_driver(&dev->cs)) {
 | 
				
			||||||
        error_setg(errp, QERR_MISSING_PARAMETER, "chardev");
 | 
					        error_setg(errp, QERR_MISSING_PARAMETER, "chardev");
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -1406,8 +1407,9 @@ static void usbredir_realize(USBDevice *udev, Error **errp)
 | 
				
			|||||||
    dev->compatible_speedmask = USB_SPEED_MASK_FULL | USB_SPEED_MASK_HIGH;
 | 
					    dev->compatible_speedmask = USB_SPEED_MASK_FULL | USB_SPEED_MASK_HIGH;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Let the backend know we are ready */
 | 
					    /* Let the backend know we are ready */
 | 
				
			||||||
    qemu_chr_add_handlers(dev->cs, usbredir_chardev_can_read,
 | 
					    qemu_chr_fe_set_handlers(&dev->cs, usbredir_chardev_can_read,
 | 
				
			||||||
                          usbredir_chardev_read, usbredir_chardev_event, dev);
 | 
					                             usbredir_chardev_read, usbredir_chardev_event,
 | 
				
			||||||
 | 
					                             dev, NULL, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qemu_add_vm_change_state_handler(usbredir_vm_state_change, dev);
 | 
					    qemu_add_vm_change_state_handler(usbredir_vm_state_change, dev);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -1426,9 +1428,11 @@ static void usbredir_cleanup_device_queues(USBRedirDevice *dev)
 | 
				
			|||||||
static void usbredir_handle_destroy(USBDevice *udev)
 | 
					static void usbredir_handle_destroy(USBDevice *udev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    USBRedirDevice *dev = USB_REDIRECT(udev);
 | 
					    USBRedirDevice *dev = USB_REDIRECT(udev);
 | 
				
			||||||
 | 
					    CharDriverState *chr = qemu_chr_fe_get_driver(&dev->cs);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qemu_chr_fe_deinit(&dev->cs);
 | 
				
			||||||
 | 
					    qemu_chr_delete(chr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qemu_chr_delete(dev->cs);
 | 
					 | 
				
			||||||
    dev->cs = NULL;
 | 
					 | 
				
			||||||
    /* Note must be done after qemu_chr_close, as that causes a close event */
 | 
					    /* Note must be done after qemu_chr_close, as that causes a close event */
 | 
				
			||||||
    qemu_bh_delete(dev->chardev_close_bh);
 | 
					    qemu_bh_delete(dev->chardev_close_bh);
 | 
				
			||||||
    qemu_bh_delete(dev->device_reject_bh);
 | 
					    qemu_bh_delete(dev->device_reject_bh);
 | 
				
			||||||
 | 
				
			|||||||
@ -116,7 +116,7 @@ static bool ioeventfd_enabled(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static int vhost_user_read(struct vhost_dev *dev, VhostUserMsg *msg)
 | 
					static int vhost_user_read(struct vhost_dev *dev, VhostUserMsg *msg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    CharDriverState *chr = dev->opaque;
 | 
					    CharBackend *chr = dev->opaque;
 | 
				
			||||||
    uint8_t *p = (uint8_t *) msg;
 | 
					    uint8_t *p = (uint8_t *) msg;
 | 
				
			||||||
    int r, size = VHOST_USER_HDR_SIZE;
 | 
					    int r, size = VHOST_USER_HDR_SIZE;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -196,7 +196,7 @@ static bool vhost_user_one_time_request(VhostUserRequest request)
 | 
				
			|||||||
static int vhost_user_write(struct vhost_dev *dev, VhostUserMsg *msg,
 | 
					static int vhost_user_write(struct vhost_dev *dev, VhostUserMsg *msg,
 | 
				
			||||||
                            int *fds, int fd_num)
 | 
					                            int *fds, int fd_num)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    CharDriverState *chr = dev->opaque;
 | 
					    CharBackend *chr = dev->opaque;
 | 
				
			||||||
    int ret, size = VHOST_USER_HDR_SIZE + msg->size;
 | 
					    int ret, size = VHOST_USER_HDR_SIZE + msg->size;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /*
 | 
					    /*
 | 
				
			||||||
 | 
				
			|||||||
@ -265,7 +265,7 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!serial_hds[0]) {
 | 
					    if (!serial_hds[0]) {
 | 
				
			||||||
        serial_hds[0] = qemu_chr_new("serial0", "null", NULL);
 | 
					        serial_hds[0] = qemu_chr_new("serial0", "null");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    serial_mm_init(system_io, 0x0d050020, 2, xtensa_get_extint(env, 0),
 | 
					    serial_mm_init(system_io, 0x0d050020, 2, xtensa_get_extint(env, 0),
 | 
				
			||||||
 | 
				
			|||||||
@ -255,8 +255,9 @@ struct MemoryListener {
 | 
				
			|||||||
                               hwaddr addr, hwaddr len);
 | 
					                               hwaddr addr, hwaddr len);
 | 
				
			||||||
    /* Lower = earlier (during add), later (during del) */
 | 
					    /* Lower = earlier (during add), later (during del) */
 | 
				
			||||||
    unsigned priority;
 | 
					    unsigned priority;
 | 
				
			||||||
    AddressSpace *address_space_filter;
 | 
					    AddressSpace *address_space;
 | 
				
			||||||
    QTAILQ_ENTRY(MemoryListener) link;
 | 
					    QTAILQ_ENTRY(MemoryListener) link;
 | 
				
			||||||
 | 
					    QTAILQ_ENTRY(MemoryListener) link_as;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -278,7 +279,7 @@ struct AddressSpace {
 | 
				
			|||||||
    struct AddressSpaceDispatch *dispatch;
 | 
					    struct AddressSpaceDispatch *dispatch;
 | 
				
			||||||
    struct AddressSpaceDispatch *next_dispatch;
 | 
					    struct AddressSpaceDispatch *next_dispatch;
 | 
				
			||||||
    MemoryListener dispatch_listener;
 | 
					    MemoryListener dispatch_listener;
 | 
				
			||||||
 | 
					    QTAILQ_HEAD(memory_listeners_as, MemoryListener) listeners;
 | 
				
			||||||
    QTAILQ_ENTRY(AddressSpace) address_spaces_link;
 | 
					    QTAILQ_ENTRY(AddressSpace) address_spaces_link;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -22,7 +22,7 @@ typedef struct {
 | 
				
			|||||||
    /*< public >*/
 | 
					    /*< public >*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    MemoryRegion iomem;
 | 
					    MemoryRegion iomem;
 | 
				
			||||||
    CharDriverState *chr;
 | 
					    CharBackend chr;
 | 
				
			||||||
    qemu_irq irq;
 | 
					    qemu_irq irq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint8_t read_fifo[BCM2835_AUX_RX_FIFO_LEN];
 | 
					    uint8_t read_fifo[BCM2835_AUX_RX_FIFO_LEN];
 | 
				
			||||||
 | 
				
			|||||||
@ -44,7 +44,7 @@ typedef struct {
 | 
				
			|||||||
    uint32_t rx_count;
 | 
					    uint32_t rx_count;
 | 
				
			||||||
    uint32_t tx_count;
 | 
					    uint32_t tx_count;
 | 
				
			||||||
    uint64_t char_tx_time;
 | 
					    uint64_t char_tx_time;
 | 
				
			||||||
    CharDriverState *chr;
 | 
					    CharBackend chr;
 | 
				
			||||||
    qemu_irq irq;
 | 
					    qemu_irq irq;
 | 
				
			||||||
    QEMUTimer *fifo_trigger_handle;
 | 
					    QEMUTimer *fifo_trigger_handle;
 | 
				
			||||||
} CadenceUARTState;
 | 
					} CadenceUARTState;
 | 
				
			||||||
 | 
				
			|||||||
@ -19,6 +19,7 @@
 | 
				
			|||||||
#define HW_CHAR_DIGIC_UART_H
 | 
					#define HW_CHAR_DIGIC_UART_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "hw/sysbus.h"
 | 
					#include "hw/sysbus.h"
 | 
				
			||||||
 | 
					#include "sysemu/char.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define TYPE_DIGIC_UART "digic-uart"
 | 
					#define TYPE_DIGIC_UART "digic-uart"
 | 
				
			||||||
#define DIGIC_UART(obj) \
 | 
					#define DIGIC_UART(obj) \
 | 
				
			||||||
@ -37,7 +38,7 @@ typedef struct DigicUartState {
 | 
				
			|||||||
    /*< public >*/
 | 
					    /*< public >*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    MemoryRegion regs_region;
 | 
					    MemoryRegion regs_region;
 | 
				
			||||||
    CharDriverState *chr;
 | 
					    CharBackend chr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint32_t reg_rx;
 | 
					    uint32_t reg_rx;
 | 
				
			||||||
    uint32_t reg_st;
 | 
					    uint32_t reg_st;
 | 
				
			||||||
 | 
				
			|||||||
@ -19,6 +19,7 @@
 | 
				
			|||||||
#define IMX_SERIAL_H
 | 
					#define IMX_SERIAL_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "hw/sysbus.h"
 | 
					#include "hw/sysbus.h"
 | 
				
			||||||
 | 
					#include "sysemu/char.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define TYPE_IMX_SERIAL "imx.serial"
 | 
					#define TYPE_IMX_SERIAL "imx.serial"
 | 
				
			||||||
#define IMX_SERIAL(obj) OBJECT_CHECK(IMXSerialState, (obj), TYPE_IMX_SERIAL)
 | 
					#define IMX_SERIAL(obj) OBJECT_CHECK(IMXSerialState, (obj), TYPE_IMX_SERIAL)
 | 
				
			||||||
@ -96,7 +97,7 @@ typedef struct IMXSerialState {
 | 
				
			|||||||
    uint32_t ucr3;
 | 
					    uint32_t ucr3;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qemu_irq irq;
 | 
					    qemu_irq irq;
 | 
				
			||||||
    CharDriverState *chr;
 | 
					    CharBackend chr;
 | 
				
			||||||
} IMXSerialState;
 | 
					} IMXSerialState;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -28,8 +28,10 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "hw/hw.h"
 | 
					#include "hw/hw.h"
 | 
				
			||||||
#include "sysemu/sysemu.h"
 | 
					#include "sysemu/sysemu.h"
 | 
				
			||||||
 | 
					#include "sysemu/char.h"
 | 
				
			||||||
#include "exec/memory.h"
 | 
					#include "exec/memory.h"
 | 
				
			||||||
#include "qemu/fifo8.h"
 | 
					#include "qemu/fifo8.h"
 | 
				
			||||||
 | 
					#include "sysemu/char.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define UART_FIFO_LENGTH    16      /* 16550A Fifo Length */
 | 
					#define UART_FIFO_LENGTH    16      /* 16550A Fifo Length */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -52,7 +54,7 @@ struct SerialState {
 | 
				
			|||||||
       it can be reset while reading iir */
 | 
					       it can be reset while reading iir */
 | 
				
			||||||
    int thr_ipending;
 | 
					    int thr_ipending;
 | 
				
			||||||
    qemu_irq irq;
 | 
					    qemu_irq irq;
 | 
				
			||||||
    CharDriverState *chr;
 | 
					    CharBackend chr;
 | 
				
			||||||
    int last_break_enable;
 | 
					    int last_break_enable;
 | 
				
			||||||
    int it_shift;
 | 
					    int it_shift;
 | 
				
			||||||
    int baudbase;
 | 
					    int baudbase;
 | 
				
			||||||
@ -94,6 +96,6 @@ SerialState *serial_mm_init(MemoryRegion *address_space,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/* serial-isa.c */
 | 
					/* serial-isa.c */
 | 
				
			||||||
#define TYPE_ISA_SERIAL "isa-serial"
 | 
					#define TYPE_ISA_SERIAL "isa-serial"
 | 
				
			||||||
void serial_hds_isa_init(ISABus *bus, int n);
 | 
					void serial_hds_isa_init(ISABus *bus, int from, int to);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
				
			|||||||
@ -67,7 +67,7 @@ typedef struct {
 | 
				
			|||||||
    uint32_t usart_cr3;
 | 
					    uint32_t usart_cr3;
 | 
				
			||||||
    uint32_t usart_gtpr;
 | 
					    uint32_t usart_gtpr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    CharDriverState *chr;
 | 
					    CharBackend chr;
 | 
				
			||||||
    qemu_irq irq;
 | 
					    qemu_irq irq;
 | 
				
			||||||
} STM32F2XXUsartState;
 | 
					} STM32F2XXUsartState;
 | 
				
			||||||
#endif /* HW_STM32F2XX_USART_H */
 | 
					#endif /* HW_STM32F2XX_USART_H */
 | 
				
			||||||
 | 
				
			|||||||
@ -146,7 +146,7 @@ extern PropertyInfo qdev_prop_arraylen;
 | 
				
			|||||||
    DEFINE_PROP(_n, _s, _f, qdev_prop_ptr, void*)
 | 
					    DEFINE_PROP(_n, _s, _f, qdev_prop_ptr, void*)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define DEFINE_PROP_CHR(_n, _s, _f)             \
 | 
					#define DEFINE_PROP_CHR(_n, _s, _f)             \
 | 
				
			||||||
    DEFINE_PROP(_n, _s, _f, qdev_prop_chr, CharDriverState*)
 | 
					    DEFINE_PROP(_n, _s, _f, qdev_prop_chr, CharBackend)
 | 
				
			||||||
#define DEFINE_PROP_STRING(_n, _s, _f)             \
 | 
					#define DEFINE_PROP_STRING(_n, _s, _f)             \
 | 
				
			||||||
    DEFINE_PROP(_n, _s, _f, qdev_prop_string, char*)
 | 
					    DEFINE_PROP(_n, _s, _f, qdev_prop_string, char*)
 | 
				
			||||||
#define DEFINE_PROP_NETDEV(_n, _s, _f)             \
 | 
					#define DEFINE_PROP_NETDEV(_n, _s, _f)             \
 | 
				
			||||||
 | 
				
			|||||||
@ -73,8 +73,8 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define smp_mb()                     ({ barrier(); __atomic_thread_fence(__ATOMIC_SEQ_CST); })
 | 
					#define smp_mb()                     ({ barrier(); __atomic_thread_fence(__ATOMIC_SEQ_CST); })
 | 
				
			||||||
#define smp_wmb()   ({ barrier(); __atomic_thread_fence(__ATOMIC_RELEASE); })
 | 
					#define smp_mb_release()             ({ barrier(); __atomic_thread_fence(__ATOMIC_RELEASE); })
 | 
				
			||||||
#define smp_rmb()   ({ barrier(); __atomic_thread_fence(__ATOMIC_ACQUIRE); })
 | 
					#define smp_mb_acquire()             ({ barrier(); __atomic_thread_fence(__ATOMIC_ACQUIRE); })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Most compilers currently treat consume and acquire the same, but really
 | 
					/* Most compilers currently treat consume and acquire the same, but really
 | 
				
			||||||
 * no processors except Alpha need a barrier here.  Leave it in if
 | 
					 * no processors except Alpha need a barrier here.  Leave it in if
 | 
				
			||||||
@ -135,44 +135,18 @@
 | 
				
			|||||||
    __atomic_store_n(ptr, i, __ATOMIC_RELEASE);       \
 | 
					    __atomic_store_n(ptr, i, __ATOMIC_RELEASE);       \
 | 
				
			||||||
} while(0)
 | 
					} while(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* atomic_mb_read/set semantics map Java volatile variables. They are
 | 
					#define atomic_load_acquire(ptr)                        \
 | 
				
			||||||
 * less expensive on some platforms (notably POWER & ARMv7) than fully
 | 
					 | 
				
			||||||
 * sequentially consistent operations.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * As long as they are used as paired operations they are safe to
 | 
					 | 
				
			||||||
 * use. See docs/atomic.txt for more discussion.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#if defined(_ARCH_PPC)
 | 
					 | 
				
			||||||
#define atomic_mb_read(ptr)                             \
 | 
					 | 
				
			||||||
    ({                                                  \
 | 
					    ({                                                  \
 | 
				
			||||||
    QEMU_BUILD_BUG_ON(sizeof(*ptr) > sizeof(void *));   \
 | 
					    QEMU_BUILD_BUG_ON(sizeof(*ptr) > sizeof(void *));   \
 | 
				
			||||||
    typeof_strip_qual(*ptr) _val;                       \
 | 
					    typeof_strip_qual(*ptr) _val;                       \
 | 
				
			||||||
     __atomic_load(ptr, &_val, __ATOMIC_RELAXED);       \
 | 
					    __atomic_load(ptr, &_val, __ATOMIC_ACQUIRE);        \
 | 
				
			||||||
     smp_rmb();                                         \
 | 
					 | 
				
			||||||
    _val;                                               \
 | 
					    _val;                                               \
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define atomic_mb_set(ptr, i)  do {                     \
 | 
					#define atomic_store_release(ptr, i)  do {              \
 | 
				
			||||||
    QEMU_BUILD_BUG_ON(sizeof(*ptr) > sizeof(void *));   \
 | 
					    QEMU_BUILD_BUG_ON(sizeof(*ptr) > sizeof(void *));   \
 | 
				
			||||||
    smp_wmb();                                          \
 | 
					    __atomic_store_n(ptr, i, __ATOMIC_RELEASE);         \
 | 
				
			||||||
    __atomic_store_n(ptr, i, __ATOMIC_RELAXED);         \
 | 
					 | 
				
			||||||
    smp_mb();                                           \
 | 
					 | 
				
			||||||
} while(0)
 | 
					} while(0)
 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
#define atomic_mb_read(ptr)                             \
 | 
					 | 
				
			||||||
    ({                                                  \
 | 
					 | 
				
			||||||
    QEMU_BUILD_BUG_ON(sizeof(*ptr) > sizeof(void *));   \
 | 
					 | 
				
			||||||
    typeof_strip_qual(*ptr) _val;                       \
 | 
					 | 
				
			||||||
    __atomic_load(ptr, &_val, __ATOMIC_SEQ_CST);        \
 | 
					 | 
				
			||||||
    _val;                                               \
 | 
					 | 
				
			||||||
    })
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define atomic_mb_set(ptr, i)  do {                     \
 | 
					 | 
				
			||||||
    QEMU_BUILD_BUG_ON(sizeof(*ptr) > sizeof(void *));   \
 | 
					 | 
				
			||||||
    __atomic_store_n(ptr, i, __ATOMIC_SEQ_CST);         \
 | 
					 | 
				
			||||||
} while(0)
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* All the remaining operations are fully sequentially consistent */
 | 
					/* All the remaining operations are fully sequentially consistent */
 | 
				
			||||||
@ -238,8 +212,8 @@
 | 
				
			|||||||
 * here (a compiler barrier only).  QEMU doesn't do accesses to write-combining
 | 
					 * here (a compiler barrier only).  QEMU doesn't do accesses to write-combining
 | 
				
			||||||
 * qemu memory or non-temporal load/stores from C code.
 | 
					 * qemu memory or non-temporal load/stores from C code.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
#define smp_wmb()   barrier()
 | 
					#define smp_mb_release()   barrier()
 | 
				
			||||||
#define smp_rmb()   barrier()
 | 
					#define smp_mb_acquire()   barrier()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * __sync_lock_test_and_set() is documented to be an acquire barrier only,
 | 
					 * __sync_lock_test_and_set() is documented to be an acquire barrier only,
 | 
				
			||||||
@ -248,11 +222,6 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
#define atomic_xchg(ptr, i)    (barrier(), __sync_lock_test_and_set(ptr, i))
 | 
					#define atomic_xchg(ptr, i)    (barrier(), __sync_lock_test_and_set(ptr, i))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Load/store with Java volatile semantics.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#define atomic_mb_set(ptr, i)  ((void)atomic_xchg(ptr, i))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#elif defined(_ARCH_PPC)
 | 
					#elif defined(_ARCH_PPC)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
@ -265,9 +234,11 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
#define smp_wmb()          ({ asm volatile("eieio" ::: "memory"); (void)0; })
 | 
					#define smp_wmb()          ({ asm volatile("eieio" ::: "memory"); (void)0; })
 | 
				
			||||||
#if defined(__powerpc64__)
 | 
					#if defined(__powerpc64__)
 | 
				
			||||||
#define smp_rmb()   ({ asm volatile("lwsync" ::: "memory"); (void)0; })
 | 
					#define smp_mb_release()   ({ asm volatile("lwsync" ::: "memory"); (void)0; })
 | 
				
			||||||
 | 
					#define smp_mb_acquire()   ({ asm volatile("lwsync" ::: "memory"); (void)0; })
 | 
				
			||||||
#else
 | 
					#else
 | 
				
			||||||
#define smp_rmb()   ({ asm volatile("sync" ::: "memory"); (void)0; })
 | 
					#define smp_mb_release()   ({ asm volatile("sync" ::: "memory"); (void)0; })
 | 
				
			||||||
 | 
					#define smp_mb_acquire()   ({ asm volatile("sync" ::: "memory"); (void)0; })
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
#define smp_mb()           ({ asm volatile("sync" ::: "memory"); (void)0; })
 | 
					#define smp_mb()           ({ asm volatile("sync" ::: "memory"); (void)0; })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -277,18 +248,18 @@
 | 
				
			|||||||
 * For (host) platforms we don't have explicit barrier definitions
 | 
					 * For (host) platforms we don't have explicit barrier definitions
 | 
				
			||||||
 * for, we use the gcc __sync_synchronize() primitive to generate a
 | 
					 * for, we use the gcc __sync_synchronize() primitive to generate a
 | 
				
			||||||
 * full barrier.  This should be safe on all platforms, though it may
 | 
					 * full barrier.  This should be safe on all platforms, though it may
 | 
				
			||||||
 * be overkill for smp_wmb() and smp_rmb().
 | 
					 * be overkill for smp_mb_acquire() and smp_mb_release().
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
#ifndef smp_mb
 | 
					#ifndef smp_mb
 | 
				
			||||||
#define smp_mb()           __sync_synchronize()
 | 
					#define smp_mb()           __sync_synchronize()
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef smp_wmb
 | 
					#ifndef smp_mb_acquire
 | 
				
			||||||
#define smp_wmb()   __sync_synchronize()
 | 
					#define smp_mb_acquire()   __sync_synchronize()
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef smp_rmb
 | 
					#ifndef smp_mb_release
 | 
				
			||||||
#define smp_rmb()   __sync_synchronize()
 | 
					#define smp_mb_release()   __sync_synchronize()
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef smp_read_barrier_depends
 | 
					#ifndef smp_read_barrier_depends
 | 
				
			||||||
@ -341,41 +312,16 @@
 | 
				
			|||||||
    atomic_set(ptr, i);                           \
 | 
					    atomic_set(ptr, i);                           \
 | 
				
			||||||
} while (0)
 | 
					} while (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* These have the same semantics as Java volatile variables.
 | 
					#define atomic_load_acquire(ptr)    ({      \
 | 
				
			||||||
 * See http://gee.cs.oswego.edu/dl/jmm/cookbook.html:
 | 
					 | 
				
			||||||
 * "1. Issue a StoreStore barrier (wmb) before each volatile store."
 | 
					 | 
				
			||||||
 *  2. Issue a StoreLoad barrier after each volatile store.
 | 
					 | 
				
			||||||
 *     Note that you could instead issue one before each volatile load, but
 | 
					 | 
				
			||||||
 *     this would be slower for typical programs using volatiles in which
 | 
					 | 
				
			||||||
 *     reads greatly outnumber writes. Alternatively, if available, you
 | 
					 | 
				
			||||||
 *     can implement volatile store as an atomic instruction (for example
 | 
					 | 
				
			||||||
 *     XCHG on x86) and omit the barrier. This may be more efficient if
 | 
					 | 
				
			||||||
 *     atomic instructions are cheaper than StoreLoad barriers.
 | 
					 | 
				
			||||||
 *  3. Issue LoadLoad and LoadStore barriers after each volatile load."
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * If you prefer to think in terms of "pairing" of memory barriers,
 | 
					 | 
				
			||||||
 * an atomic_mb_read pairs with an atomic_mb_set.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * And for the few ia64 lovers that exist, an atomic_mb_read is a ld.acq,
 | 
					 | 
				
			||||||
 * while an atomic_mb_set is a st.rel followed by a memory barrier.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * These are a bit weaker than __atomic_load/store with __ATOMIC_SEQ_CST
 | 
					 | 
				
			||||||
 * (see docs/atomics.txt), and I'm not sure that __ATOMIC_ACQ_REL is enough.
 | 
					 | 
				
			||||||
 * Just always use the barriers manually by the rules above.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#define atomic_mb_read(ptr)    ({           \
 | 
					 | 
				
			||||||
    typeof(*ptr) _val = atomic_read(ptr);   \
 | 
					    typeof(*ptr) _val = atomic_read(ptr);   \
 | 
				
			||||||
    smp_rmb();                              \
 | 
					    smp_mb_acquire();                       \
 | 
				
			||||||
    _val;                                   \
 | 
					    _val;                                   \
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef atomic_mb_set
 | 
					#define atomic_store_release(ptr, i)  do {  \
 | 
				
			||||||
#define atomic_mb_set(ptr, i)  do {         \
 | 
					    smp_mb_release();                       \
 | 
				
			||||||
    smp_wmb();                              \
 | 
					 | 
				
			||||||
    atomic_set(ptr, i);                     \
 | 
					    atomic_set(ptr, i);                     \
 | 
				
			||||||
    smp_mb();                               \
 | 
					 | 
				
			||||||
} while (0)
 | 
					} while (0)
 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifndef atomic_xchg
 | 
					#ifndef atomic_xchg
 | 
				
			||||||
#if defined(__clang__)
 | 
					#if defined(__clang__)
 | 
				
			||||||
@ -404,4 +350,39 @@
 | 
				
			|||||||
#define atomic_or(ptr, n)      ((void) __sync_fetch_and_or(ptr, n))
 | 
					#define atomic_or(ptr, n)      ((void) __sync_fetch_and_or(ptr, n))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* __ATOMIC_RELAXED */
 | 
					#endif /* __ATOMIC_RELAXED */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef smp_wmb
 | 
				
			||||||
 | 
					#define smp_wmb()   smp_mb_release()
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#ifndef smp_rmb
 | 
				
			||||||
 | 
					#define smp_rmb()   smp_mb_acquire()
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* This is more efficient than a store plus a fence.  */
 | 
				
			||||||
 | 
					#if !defined(__SANITIZE_THREAD__)
 | 
				
			||||||
 | 
					#if defined(__i386__) || defined(__x86_64__) || defined(__s390x__)
 | 
				
			||||||
 | 
					#define atomic_mb_set(ptr, i)  ((void)atomic_xchg(ptr, i))
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* atomic_mb_read/set semantics map Java volatile variables. They are
 | 
				
			||||||
 | 
					 * less expensive on some platforms (notably POWER) than fully
 | 
				
			||||||
 | 
					 * sequentially consistent operations.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * As long as they are used as paired operations they are safe to
 | 
				
			||||||
 | 
					 * use. See docs/atomic.txt for more discussion.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef atomic_mb_read
 | 
				
			||||||
 | 
					#define atomic_mb_read(ptr)                             \
 | 
				
			||||||
 | 
					    atomic_load_acquire(ptr)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef atomic_mb_set
 | 
				
			||||||
 | 
					#define atomic_mb_set(ptr, i)  do {                     \
 | 
				
			||||||
 | 
					    atomic_store_release(ptr, i);                       \
 | 
				
			||||||
 | 
					    smp_mb();                                           \
 | 
				
			||||||
 | 
					} while(0)
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#endif /* QEMU_ATOMIC_H */
 | 
					#endif /* QEMU_ATOMIC_H */
 | 
				
			||||||
 | 
				
			|||||||
@ -13,12 +13,13 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/* character device */
 | 
					/* character device */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CHR_EVENT_BREAK   0 /* serial break char */
 | 
					typedef enum {
 | 
				
			||||||
#define CHR_EVENT_FOCUS   1 /* focus to this terminal (modal input needed) */
 | 
					    CHR_EVENT_BREAK, /* serial break char */
 | 
				
			||||||
#define CHR_EVENT_OPENED  2 /* new connection established */
 | 
					    CHR_EVENT_OPENED, /* new connection established */
 | 
				
			||||||
#define CHR_EVENT_MUX_IN  3 /* mux-focus was set to this terminal */
 | 
					    CHR_EVENT_MUX_IN, /* mux-focus was set to this terminal */
 | 
				
			||||||
#define CHR_EVENT_MUX_OUT 4 /* mux-focus will move on */
 | 
					    CHR_EVENT_MUX_OUT, /* mux-focus will move on */
 | 
				
			||||||
#define CHR_EVENT_CLOSED  5 /* connection closed */
 | 
					    CHR_EVENT_CLOSED /* connection closed */
 | 
				
			||||||
 | 
					} QEMUChrEvent;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define CHR_IOCTL_SERIAL_SET_PARAMS   1
 | 
					#define CHR_IOCTL_SERIAL_SET_PARAMS   1
 | 
				
			||||||
@ -72,10 +73,20 @@ typedef enum {
 | 
				
			|||||||
    QEMU_CHAR_FEATURE_LAST,
 | 
					    QEMU_CHAR_FEATURE_LAST,
 | 
				
			||||||
} CharDriverFeature;
 | 
					} CharDriverFeature;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* This is the backend as seen by frontend, the actual backend is
 | 
				
			||||||
 | 
					 * CharDriverState */
 | 
				
			||||||
 | 
					typedef struct CharBackend {
 | 
				
			||||||
 | 
					    CharDriverState *chr;
 | 
				
			||||||
 | 
					    IOEventHandler *chr_event;
 | 
				
			||||||
 | 
					    IOCanReadHandler *chr_can_read;
 | 
				
			||||||
 | 
					    IOReadHandler *chr_read;
 | 
				
			||||||
 | 
					    void *opaque;
 | 
				
			||||||
 | 
					    int tag;
 | 
				
			||||||
 | 
					    int fe_open;
 | 
				
			||||||
 | 
					} CharBackend;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct CharDriverState {
 | 
					struct CharDriverState {
 | 
				
			||||||
    QemuMutex chr_write_lock;
 | 
					    QemuMutex chr_write_lock;
 | 
				
			||||||
    void (*init)(struct CharDriverState *s);
 | 
					 | 
				
			||||||
    int (*chr_write)(struct CharDriverState *s, const uint8_t *buf, int len);
 | 
					    int (*chr_write)(struct CharDriverState *s, const uint8_t *buf, int len);
 | 
				
			||||||
    int (*chr_sync_read)(struct CharDriverState *s,
 | 
					    int (*chr_sync_read)(struct CharDriverState *s,
 | 
				
			||||||
                         const uint8_t *buf, int len);
 | 
					                         const uint8_t *buf, int len);
 | 
				
			||||||
@ -87,25 +98,17 @@ struct CharDriverState {
 | 
				
			|||||||
    int (*set_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_add_client)(struct CharDriverState *chr, int fd);
 | 
				
			||||||
    int (*chr_wait_connected)(struct CharDriverState *chr, Error **errp);
 | 
					    int (*chr_wait_connected)(struct CharDriverState *chr, Error **errp);
 | 
				
			||||||
    IOEventHandler *chr_event;
 | 
					    void (*chr_free)(struct CharDriverState *chr);
 | 
				
			||||||
    IOCanReadHandler *chr_can_read;
 | 
					 | 
				
			||||||
    IOReadHandler *chr_read;
 | 
					 | 
				
			||||||
    void *handler_opaque;
 | 
					 | 
				
			||||||
    void (*chr_close)(struct CharDriverState *chr);
 | 
					 | 
				
			||||||
    void (*chr_disconnect)(struct CharDriverState *chr);
 | 
					    void (*chr_disconnect)(struct CharDriverState *chr);
 | 
				
			||||||
    void (*chr_accept_input)(struct CharDriverState *chr);
 | 
					    void (*chr_accept_input)(struct CharDriverState *chr);
 | 
				
			||||||
    void (*chr_set_echo)(struct CharDriverState *chr, bool echo);
 | 
					    void (*chr_set_echo)(struct CharDriverState *chr, bool echo);
 | 
				
			||||||
    void (*chr_set_fe_open)(struct CharDriverState *chr, int fe_open);
 | 
					    void (*chr_set_fe_open)(struct CharDriverState *chr, int fe_open);
 | 
				
			||||||
    void (*chr_fe_event)(struct CharDriverState *chr, int event);
 | 
					    CharBackend *be;
 | 
				
			||||||
    void *opaque;
 | 
					    void *opaque;
 | 
				
			||||||
    char *label;
 | 
					    char *label;
 | 
				
			||||||
    char *filename;
 | 
					    char *filename;
 | 
				
			||||||
    int logfd;
 | 
					    int logfd;
 | 
				
			||||||
    int be_open;
 | 
					    int be_open;
 | 
				
			||||||
    int fe_open;
 | 
					 | 
				
			||||||
    int explicit_fe_open;
 | 
					 | 
				
			||||||
    int explicit_be_open;
 | 
					 | 
				
			||||||
    int avail_connections;
 | 
					 | 
				
			||||||
    int is_mux;
 | 
					    int is_mux;
 | 
				
			||||||
    guint fd_in_tag;
 | 
					    guint fd_in_tag;
 | 
				
			||||||
    bool replay;
 | 
					    bool replay;
 | 
				
			||||||
@ -130,12 +133,10 @@ CharDriverState *qemu_chr_alloc(ChardevCommon *backend, Error **errp);
 | 
				
			|||||||
 * Create a new character backend from a QemuOpts list.
 | 
					 * Create a new character backend from a QemuOpts list.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @opts see qemu-config.c for a list of valid options
 | 
					 * @opts see qemu-config.c for a list of valid options
 | 
				
			||||||
 * @init not sure..
 | 
					 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Returns: a new character backend
 | 
					 * Returns: a new character backend
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts,
 | 
					CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts,
 | 
				
			||||||
                                    void (*init)(struct CharDriverState *s),
 | 
					 | 
				
			||||||
                                        Error **errp);
 | 
					                                        Error **errp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -155,18 +156,19 @@ void qemu_chr_parse_common(QemuOpts *opts, ChardevCommon *backend);
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 * @label the name of the backend
 | 
					 * @label the name of the backend
 | 
				
			||||||
 * @filename the URI
 | 
					 * @filename the URI
 | 
				
			||||||
 * @init not sure..
 | 
					 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Returns: a new character backend
 | 
					 * Returns: a new character backend
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
CharDriverState *qemu_chr_new(const char *label, const char *filename,
 | 
					CharDriverState *qemu_chr_new(const char *label, const char *filename);
 | 
				
			||||||
                              void (*init)(struct CharDriverState *s));
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @qemu_chr_disconnect:
 | 
					 * @qemu_chr_fe_disconnect:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Close a fd accpeted by character backend.
 | 
					 * Close a fd accpeted by character backend.
 | 
				
			||||||
 | 
					 * Without associated CharDriver, do nothing.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void qemu_chr_disconnect(CharDriverState *chr);
 | 
					void qemu_chr_fe_disconnect(CharBackend *be);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @qemu_chr_cleanup:
 | 
					 * @qemu_chr_cleanup:
 | 
				
			||||||
@ -176,11 +178,12 @@ void qemu_chr_disconnect(CharDriverState *chr);
 | 
				
			|||||||
void qemu_chr_cleanup(void);
 | 
					void qemu_chr_cleanup(void);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @qemu_chr_wait_connected:
 | 
					 * @qemu_chr_fe_wait_connected:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Wait for characted backend to be connected.
 | 
					 * Wait for characted backend to be connected, return < 0 on error or
 | 
				
			||||||
 | 
					 * if no assicated CharDriver.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int qemu_chr_wait_connected(CharDriverState *chr, Error **errp);
 | 
					int qemu_chr_fe_wait_connected(CharBackend *be, Error **errp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @qemu_chr_new_noreplay:
 | 
					 * @qemu_chr_new_noreplay:
 | 
				
			||||||
@ -191,12 +194,10 @@ int qemu_chr_wait_connected(CharDriverState *chr, Error **errp);
 | 
				
			|||||||
 *
 | 
					 *
 | 
				
			||||||
 * @label the name of the backend
 | 
					 * @label the name of the backend
 | 
				
			||||||
 * @filename the URI
 | 
					 * @filename the URI
 | 
				
			||||||
 * @init not sure..
 | 
					 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Returns: a new character backend
 | 
					 * Returns: a new character backend
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
CharDriverState *qemu_chr_new_noreplay(const char *label, const char *filename,
 | 
					CharDriverState *qemu_chr_new_noreplay(const char *label, const char *filename);
 | 
				
			||||||
                                       void (*init)(struct CharDriverState *s));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @qemu_chr_delete:
 | 
					 * @qemu_chr_delete:
 | 
				
			||||||
@ -219,37 +220,31 @@ void qemu_chr_free(CharDriverState *chr);
 | 
				
			|||||||
 * Ask the backend to override its normal echo setting.  This only really
 | 
					 * Ask the backend to override its normal echo setting.  This only really
 | 
				
			||||||
 * applies to the stdio backend and is used by the QMP server such that you
 | 
					 * applies to the stdio backend and is used by the QMP server such that you
 | 
				
			||||||
 * can see what you type if you try to type QMP commands.
 | 
					 * can see what you type if you try to type QMP commands.
 | 
				
			||||||
 | 
					 * Without associated CharDriver, do nothing.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @echo true to enable echo, false to disable echo
 | 
					 * @echo true to enable echo, false to disable echo
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void qemu_chr_fe_set_echo(struct CharDriverState *chr, bool echo);
 | 
					void qemu_chr_fe_set_echo(CharBackend *be, bool echo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @qemu_chr_fe_set_open:
 | 
					 * @qemu_chr_fe_set_open:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Set character frontend open status.  This is an indication that the
 | 
					 * Set character frontend open status.  This is an indication that the
 | 
				
			||||||
 * front end is ready (or not) to begin doing I/O.
 | 
					 * front end is ready (or not) to begin doing I/O.
 | 
				
			||||||
 | 
					 * Without associated CharDriver, do nothing.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void qemu_chr_fe_set_open(struct CharDriverState *chr, int fe_open);
 | 
					void qemu_chr_fe_set_open(CharBackend *be, int fe_open);
 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @qemu_chr_fe_event:
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Send an event from the front end to the back end.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * @event the event to send
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
void qemu_chr_fe_event(CharDriverState *s, int event);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @qemu_chr_fe_printf:
 | 
					 * @qemu_chr_fe_printf:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Write to a character backend using a printf style interface.
 | 
					 * Write to a character backend using a printf style interface.  This
 | 
				
			||||||
 * This function is thread-safe.
 | 
					 * function is thread-safe. It does nothing without associated
 | 
				
			||||||
 | 
					 * CharDriver.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @fmt see #printf
 | 
					 * @fmt see #printf
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
void qemu_chr_fe_printf(CharDriverState *s, const char *fmt, ...)
 | 
					void qemu_chr_fe_printf(CharBackend *be, const char *fmt, ...)
 | 
				
			||||||
    GCC_FMT_ATTR(2, 3);
 | 
					    GCC_FMT_ATTR(2, 3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -258,13 +253,13 @@ void qemu_chr_fe_printf(CharDriverState *s, const char *fmt, ...)
 | 
				
			|||||||
 * If the backend is connected, create and add a #GSource that fires
 | 
					 * If the backend is connected, create and add a #GSource that fires
 | 
				
			||||||
 * when the given condition (typically G_IO_OUT|G_IO_HUP or G_IO_HUP)
 | 
					 * when the given condition (typically G_IO_OUT|G_IO_HUP or G_IO_HUP)
 | 
				
			||||||
 * is active; return the #GSource's tag.  If it is disconnected,
 | 
					 * is active; return the #GSource's tag.  If it is disconnected,
 | 
				
			||||||
 * return 0.
 | 
					 * or without associated CharDriver, return 0.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * @cond the condition to poll for
 | 
					 * @cond the condition to poll for
 | 
				
			||||||
 * @func the function to call when the condition happens
 | 
					 * @func the function to call when the condition happens
 | 
				
			||||||
 * @user_data the opaque pointer to pass to @func
 | 
					 * @user_data the opaque pointer to pass to @func
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
guint qemu_chr_fe_add_watch(CharDriverState *s, GIOCondition cond,
 | 
					guint qemu_chr_fe_add_watch(CharBackend *be, GIOCondition cond,
 | 
				
			||||||
                            GIOFunc func, void *user_data);
 | 
					                            GIOFunc func, void *user_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
@ -277,9 +272,9 @@ guint qemu_chr_fe_add_watch(CharDriverState *s, GIOCondition cond,
 | 
				
			|||||||
 * @buf the data
 | 
					 * @buf the data
 | 
				
			||||||
 * @len the number of bytes to send
 | 
					 * @len the number of bytes to send
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Returns: the number of bytes consumed
 | 
					 * Returns: the number of bytes consumed (0 if no assicated CharDriver)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int qemu_chr_fe_write(CharDriverState *s, const uint8_t *buf, int len);
 | 
					int qemu_chr_fe_write(CharBackend *be, const uint8_t *buf, int len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @qemu_chr_fe_write_all:
 | 
					 * @qemu_chr_fe_write_all:
 | 
				
			||||||
@ -292,9 +287,9 @@ int qemu_chr_fe_write(CharDriverState *s, const uint8_t *buf, int len);
 | 
				
			|||||||
 * @buf the data
 | 
					 * @buf the data
 | 
				
			||||||
 * @len the number of bytes to send
 | 
					 * @len the number of bytes to send
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Returns: the number of bytes consumed
 | 
					 * Returns: the number of bytes consumed (0 if no assicated CharDriver)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int qemu_chr_fe_write_all(CharDriverState *s, const uint8_t *buf, int len);
 | 
					int qemu_chr_fe_write_all(CharBackend *be, const uint8_t *buf, int len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @qemu_chr_fe_read_all:
 | 
					 * @qemu_chr_fe_read_all:
 | 
				
			||||||
@ -304,9 +299,9 @@ int qemu_chr_fe_write_all(CharDriverState *s, const uint8_t *buf, int len);
 | 
				
			|||||||
 * @buf the data buffer
 | 
					 * @buf the data buffer
 | 
				
			||||||
 * @len the number of bytes to read
 | 
					 * @len the number of bytes to read
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Returns: the number of bytes read
 | 
					 * Returns: the number of bytes read (0 if no assicated CharDriver)
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int qemu_chr_fe_read_all(CharDriverState *s, uint8_t *buf, int len);
 | 
					int qemu_chr_fe_read_all(CharBackend *be, uint8_t *buf, int len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @qemu_chr_fe_ioctl:
 | 
					 * @qemu_chr_fe_ioctl:
 | 
				
			||||||
@ -316,10 +311,11 @@ int qemu_chr_fe_read_all(CharDriverState *s, uint8_t *buf, int len);
 | 
				
			|||||||
 * @cmd see CHR_IOCTL_*
 | 
					 * @cmd see CHR_IOCTL_*
 | 
				
			||||||
 * @arg the data associated with @cmd
 | 
					 * @arg the data associated with @cmd
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Returns: if @cmd is not supported by the backend, -ENOTSUP, otherwise the
 | 
					 * Returns: if @cmd is not supported by the backend or there is no
 | 
				
			||||||
 *          return value depends on the semantics of @cmd
 | 
					 *          associated CharDriver, -ENOTSUP, otherwise the return
 | 
				
			||||||
 | 
					 *          value depends on the semantics of @cmd
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int qemu_chr_fe_ioctl(CharDriverState *s, int cmd, void *arg);
 | 
					int qemu_chr_fe_ioctl(CharBackend *be, int cmd, void *arg);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @qemu_chr_fe_get_msgfd:
 | 
					 * @qemu_chr_fe_get_msgfd:
 | 
				
			||||||
@ -332,7 +328,7 @@ int qemu_chr_fe_ioctl(CharDriverState *s, int cmd, void *arg);
 | 
				
			|||||||
 *          this function will return -1 until a client sends a new file
 | 
					 *          this function will return -1 until a client sends a new file
 | 
				
			||||||
 *          descriptor.
 | 
					 *          descriptor.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int qemu_chr_fe_get_msgfd(CharDriverState *s);
 | 
					int qemu_chr_fe_get_msgfd(CharBackend *be);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @qemu_chr_fe_get_msgfds:
 | 
					 * @qemu_chr_fe_get_msgfds:
 | 
				
			||||||
@ -345,7 +341,7 @@ int qemu_chr_fe_get_msgfd(CharDriverState *s);
 | 
				
			|||||||
 *          this function will return -1 until a client sends a new set of file
 | 
					 *          this function will return -1 until a client sends a new set of file
 | 
				
			||||||
 *          descriptors.
 | 
					 *          descriptors.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int qemu_chr_fe_get_msgfds(CharDriverState *s, int *fds, int num);
 | 
					int qemu_chr_fe_get_msgfds(CharBackend *be, int *fds, int num);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @qemu_chr_fe_set_msgfds:
 | 
					 * @qemu_chr_fe_set_msgfds:
 | 
				
			||||||
@ -356,38 +352,9 @@ int qemu_chr_fe_get_msgfds(CharDriverState *s, int *fds, int num);
 | 
				
			|||||||
 * result in overwriting the fd array with the new value without being send.
 | 
					 * result in overwriting the fd array with the new value without being send.
 | 
				
			||||||
 * Upon writing the message the fd array is freed.
 | 
					 * Upon writing the message the fd array is freed.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Returns: -1 if fd passing isn't supported.
 | 
					 * Returns: -1 if fd passing isn't supported or no associated CharDriver.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
int qemu_chr_fe_set_msgfds(CharDriverState *s, int *fds, int num);
 | 
					int qemu_chr_fe_set_msgfds(CharBackend *be, int *fds, int num);
 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @qemu_chr_fe_claim:
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Claim a backend before using it, should be called before calling
 | 
					 | 
				
			||||||
 * qemu_chr_add_handlers(). 
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Returns: -1 if the backend is already in use by another frontend, 0 on
 | 
					 | 
				
			||||||
 *          success.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
int qemu_chr_fe_claim(CharDriverState *s);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @qemu_chr_fe_claim_no_fail:
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Like qemu_chr_fe_claim, but will exit qemu with an error when the
 | 
					 | 
				
			||||||
 * backend is already in use.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
void qemu_chr_fe_claim_no_fail(CharDriverState *s);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/**
 | 
					 | 
				
			||||||
 * @qemu_chr_fe_claim:
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Release a backend for use by another frontend.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * Returns: -1 if the backend is already in use by another frontend, 0 on
 | 
					 | 
				
			||||||
 *          success.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
void qemu_chr_fe_release(CharDriverState *s);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @qemu_chr_be_can_write:
 | 
					 * @qemu_chr_be_can_write:
 | 
				
			||||||
@ -432,22 +399,70 @@ void qemu_chr_be_write_impl(CharDriverState *s, uint8_t *buf, int len);
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
void qemu_chr_be_event(CharDriverState *s, int event);
 | 
					void qemu_chr_be_event(CharDriverState *s, int event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void qemu_chr_add_handlers(CharDriverState *s,
 | 
					/**
 | 
				
			||||||
                           IOCanReadHandler *fd_can_read,
 | 
					 * @qemu_chr_fe_init:
 | 
				
			||||||
                           IOReadHandler *fd_read,
 | 
					 *
 | 
				
			||||||
                           IOEventHandler *fd_event,
 | 
					 * Initializes a front end for the given CharBackend and
 | 
				
			||||||
                           void *opaque);
 | 
					 * CharDriver. Call qemu_chr_fe_deinit() to remove the association and
 | 
				
			||||||
 | 
					 * release the driver.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns: false on error.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					bool qemu_chr_fe_init(CharBackend *b, CharDriverState *s, Error **errp);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* This API can make handler run in the context what you pass to. */
 | 
					/**
 | 
				
			||||||
void qemu_chr_add_handlers_full(CharDriverState *s,
 | 
					 * @qemu_chr_fe_get_driver:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Returns the driver associated with a CharBackend or NULL if no
 | 
				
			||||||
 | 
					 * associated CharDriver.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					CharDriverState *qemu_chr_fe_get_driver(CharBackend *be);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @qemu_chr_fe_deinit:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Dissociate the CharBackend from the CharDriver.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Safe to call without associated CharDriver.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void qemu_chr_fe_deinit(CharBackend *b);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @qemu_chr_fe_set_handlers:
 | 
				
			||||||
 | 
					 * @b: a CharBackend
 | 
				
			||||||
 | 
					 * @fd_can_read: callback to get the amount of data the frontend may
 | 
				
			||||||
 | 
					 *               receive
 | 
				
			||||||
 | 
					 * @fd_read: callback to receive data from char
 | 
				
			||||||
 | 
					 * @fd_event: event callback
 | 
				
			||||||
 | 
					 * @opaque: an opaque pointer for the callbacks
 | 
				
			||||||
 | 
					 * @context: a main loop context or NULL for the default
 | 
				
			||||||
 | 
					 * @set_open: whether to call qemu_chr_fe_set_open() implicitely when
 | 
				
			||||||
 | 
					 * any of the handler is non-NULL
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Set the front end char handlers. The front end takes the focus if
 | 
				
			||||||
 | 
					 * any of the handler is non-NULL.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Without associated CharDriver, nothing is changed.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void qemu_chr_fe_set_handlers(CharBackend *b,
 | 
				
			||||||
                              IOCanReadHandler *fd_can_read,
 | 
					                              IOCanReadHandler *fd_can_read,
 | 
				
			||||||
                              IOReadHandler *fd_read,
 | 
					                              IOReadHandler *fd_read,
 | 
				
			||||||
                              IOEventHandler *fd_event,
 | 
					                              IOEventHandler *fd_event,
 | 
				
			||||||
                              void *opaque,
 | 
					                              void *opaque,
 | 
				
			||||||
                                GMainContext *context);
 | 
					                              GMainContext *context,
 | 
				
			||||||
 | 
					                              bool set_open);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * @qemu_chr_fe_take_focus:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Take the focus (if the front end is muxed).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Without associated CharDriver, nothing is changed.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					void qemu_chr_fe_take_focus(CharBackend *b);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void qemu_chr_be_generic_open(CharDriverState *s);
 | 
					void qemu_chr_be_generic_open(CharDriverState *s);
 | 
				
			||||||
void qemu_chr_accept_input(CharDriverState *s);
 | 
					void qemu_chr_fe_accept_input(CharBackend *be);
 | 
				
			||||||
int qemu_chr_add_client(CharDriverState *s, int fd);
 | 
					int qemu_chr_add_client(CharDriverState *s, int fd);
 | 
				
			||||||
CharDriverState *qemu_chr_find(const char *name);
 | 
					CharDriverState *qemu_chr_find(const char *name);
 | 
				
			||||||
bool chr_is_ringbuf(const CharDriverState *chr);
 | 
					bool chr_is_ringbuf(const CharDriverState *chr);
 | 
				
			||||||
@ -458,10 +473,15 @@ void qemu_chr_set_feature(CharDriverState *chr,
 | 
				
			|||||||
                          CharDriverFeature feature);
 | 
					                          CharDriverFeature feature);
 | 
				
			||||||
QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename);
 | 
					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);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void register_char_driver(const char *name, ChardevBackendKind kind,
 | 
					void register_char_driver(const char *name, ChardevBackendKind kind,
 | 
				
			||||||
        void (*parse)(QemuOpts *opts, ChardevBackend *backend, Error **errp),
 | 
					                          CharDriverParse *parse, CharDriverCreate *create);
 | 
				
			||||||
        CharDriverState *(*create)(const char *id, ChardevBackend *backend,
 | 
					 | 
				
			||||||
                                   ChardevReturn *ret, Error **errp));
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
extern int term_escape_char;
 | 
					extern int term_escape_char;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -2215,15 +2215,14 @@ int kvm_sw_breakpoints_active(CPUState *cpu)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
struct kvm_set_guest_debug_data {
 | 
					struct kvm_set_guest_debug_data {
 | 
				
			||||||
    struct kvm_guest_debug dbg;
 | 
					    struct kvm_guest_debug dbg;
 | 
				
			||||||
    CPUState *cpu;
 | 
					 | 
				
			||||||
    int err;
 | 
					    int err;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void kvm_invoke_set_guest_debug(CPUState *unused_cpu, void *data)
 | 
					static void kvm_invoke_set_guest_debug(CPUState *cpu, void *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    struct kvm_set_guest_debug_data *dbg_data = data;
 | 
					    struct kvm_set_guest_debug_data *dbg_data = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    dbg_data->err = kvm_vcpu_ioctl(dbg_data->cpu, KVM_SET_GUEST_DEBUG,
 | 
					    dbg_data->err = kvm_vcpu_ioctl(cpu, KVM_SET_GUEST_DEBUG,
 | 
				
			||||||
                                   &dbg_data->dbg);
 | 
					                                   &dbg_data->dbg);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -3956,7 +3956,7 @@ static void handle_arg_strace(const char *arg)
 | 
				
			|||||||
static void handle_arg_version(const char *arg)
 | 
					static void handle_arg_version(const char *arg)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    printf("qemu-" TARGET_NAME " version " QEMU_VERSION QEMU_PKGVERSION
 | 
					    printf("qemu-" TARGET_NAME " version " QEMU_VERSION QEMU_PKGVERSION
 | 
				
			||||||
           ", " QEMU_COPYRIGHT "\n");
 | 
					           "\n" QEMU_COPYRIGHT "\n");
 | 
				
			||||||
    exit(EXIT_SUCCESS);
 | 
					    exit(EXIT_SUCCESS);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										91
									
								
								memory.c
									
									
									
									
									
								
							
							
						
						
									
										91
									
								
								memory.c
									
									
									
									
									
								
							@ -97,13 +97,6 @@ static AddrRange addrrange_intersection(AddrRange r1, AddrRange r2)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
enum ListenerDirection { Forward, Reverse };
 | 
					enum ListenerDirection { Forward, Reverse };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static bool memory_listener_match(MemoryListener *listener,
 | 
					 | 
				
			||||||
                                  MemoryRegionSection *section)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    return !listener->address_space_filter
 | 
					 | 
				
			||||||
        || listener->address_space_filter == section->address_space;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#define MEMORY_LISTENER_CALL_GLOBAL(_callback, _direction, _args...)    \
 | 
					#define MEMORY_LISTENER_CALL_GLOBAL(_callback, _direction, _args...)    \
 | 
				
			||||||
    do {                                                                \
 | 
					    do {                                                                \
 | 
				
			||||||
        MemoryListener *_listener;                                      \
 | 
					        MemoryListener *_listener;                                      \
 | 
				
			||||||
@ -129,24 +122,23 @@ static bool memory_listener_match(MemoryListener *listener,
 | 
				
			|||||||
        }                                                               \
 | 
					        }                                                               \
 | 
				
			||||||
    } while (0)
 | 
					    } while (0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define MEMORY_LISTENER_CALL(_callback, _direction, _section, _args...) \
 | 
					#define MEMORY_LISTENER_CALL(_as, _callback, _direction, _section, _args...) \
 | 
				
			||||||
    do {                                                                \
 | 
					    do {                                                                \
 | 
				
			||||||
        MemoryListener *_listener;                                      \
 | 
					        MemoryListener *_listener;                                      \
 | 
				
			||||||
 | 
					        struct memory_listeners_as *list = &(_as)->listeners;           \
 | 
				
			||||||
                                                                        \
 | 
					                                                                        \
 | 
				
			||||||
        switch (_direction) {                                           \
 | 
					        switch (_direction) {                                           \
 | 
				
			||||||
        case Forward:                                                   \
 | 
					        case Forward:                                                   \
 | 
				
			||||||
            QTAILQ_FOREACH(_listener, &memory_listeners, link) {        \
 | 
					            QTAILQ_FOREACH(_listener, list, link_as) {                  \
 | 
				
			||||||
                if (_listener->_callback                                \
 | 
					                if (_listener->_callback) {                             \
 | 
				
			||||||
                    && memory_listener_match(_listener, _section)) {    \
 | 
					 | 
				
			||||||
                    _listener->_callback(_listener, _section, ##_args); \
 | 
					                    _listener->_callback(_listener, _section, ##_args); \
 | 
				
			||||||
                }                                                       \
 | 
					                }                                                       \
 | 
				
			||||||
            }                                                           \
 | 
					            }                                                           \
 | 
				
			||||||
            break;                                                      \
 | 
					            break;                                                      \
 | 
				
			||||||
        case Reverse:                                                   \
 | 
					        case Reverse:                                                   \
 | 
				
			||||||
            QTAILQ_FOREACH_REVERSE(_listener, &memory_listeners,        \
 | 
					            QTAILQ_FOREACH_REVERSE(_listener, list, memory_listeners_as, \
 | 
				
			||||||
                                   memory_listeners, link) {            \
 | 
					                                   link_as) {                           \
 | 
				
			||||||
                if (_listener->_callback                                \
 | 
					                if (_listener->_callback) {                             \
 | 
				
			||||||
                    && memory_listener_match(_listener, _section)) {    \
 | 
					 | 
				
			||||||
                    _listener->_callback(_listener, _section, ##_args); \
 | 
					                    _listener->_callback(_listener, _section, ##_args); \
 | 
				
			||||||
                }                                                       \
 | 
					                }                                                       \
 | 
				
			||||||
            }                                                           \
 | 
					            }                                                           \
 | 
				
			||||||
@ -160,7 +152,7 @@ static bool memory_listener_match(MemoryListener *listener,
 | 
				
			|||||||
#define MEMORY_LISTENER_UPDATE_REGION(fr, as, dir, callback, _args...)  \
 | 
					#define MEMORY_LISTENER_UPDATE_REGION(fr, as, dir, callback, _args...)  \
 | 
				
			||||||
    do {                                                                \
 | 
					    do {                                                                \
 | 
				
			||||||
        MemoryRegionSection mrs = section_from_flat_range(fr, as);      \
 | 
					        MemoryRegionSection mrs = section_from_flat_range(fr, as);      \
 | 
				
			||||||
        MEMORY_LISTENER_CALL(callback, dir, &mrs, ##_args);             \
 | 
					        MEMORY_LISTENER_CALL(as, callback, dir, &mrs, ##_args);         \
 | 
				
			||||||
    } while(0)
 | 
					    } while(0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct CoalescedMemoryRange {
 | 
					struct CoalescedMemoryRange {
 | 
				
			||||||
@ -749,7 +741,7 @@ static void address_space_add_del_ioeventfds(AddressSpace *as,
 | 
				
			|||||||
                .offset_within_address_space = int128_get64(fd->addr.start),
 | 
					                .offset_within_address_space = int128_get64(fd->addr.start),
 | 
				
			||||||
                .size = fd->addr.size,
 | 
					                .size = fd->addr.size,
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
            MEMORY_LISTENER_CALL(eventfd_del, Forward, §ion,
 | 
					            MEMORY_LISTENER_CALL(as, eventfd_del, Forward, §ion,
 | 
				
			||||||
                                 fd->match_data, fd->data, fd->e);
 | 
					                                 fd->match_data, fd->data, fd->e);
 | 
				
			||||||
            ++iold;
 | 
					            ++iold;
 | 
				
			||||||
        } else if (inew < fds_new_nb
 | 
					        } else if (inew < fds_new_nb
 | 
				
			||||||
@ -762,7 +754,7 @@ static void address_space_add_del_ioeventfds(AddressSpace *as,
 | 
				
			|||||||
                .offset_within_address_space = int128_get64(fd->addr.start),
 | 
					                .offset_within_address_space = int128_get64(fd->addr.start),
 | 
				
			||||||
                .size = fd->addr.size,
 | 
					                .size = fd->addr.size,
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
            MEMORY_LISTENER_CALL(eventfd_add, Reverse, §ion,
 | 
					            MEMORY_LISTENER_CALL(as, eventfd_add, Reverse, §ion,
 | 
				
			||||||
                                 fd->match_data, fd->data, fd->e);
 | 
					                                 fd->match_data, fd->data, fd->e);
 | 
				
			||||||
            ++inew;
 | 
					            ++inew;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
@ -1507,7 +1499,7 @@ bool memory_region_is_skip_dump(MemoryRegion *mr)
 | 
				
			|||||||
uint8_t memory_region_get_dirty_log_mask(MemoryRegion *mr)
 | 
					uint8_t memory_region_get_dirty_log_mask(MemoryRegion *mr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    uint8_t mask = mr->dirty_log_mask;
 | 
					    uint8_t mask = mr->dirty_log_mask;
 | 
				
			||||||
    if (global_dirty_log) {
 | 
					    if (global_dirty_log && mr->ram_block) {
 | 
				
			||||||
        mask |= (1 << DIRTY_MEMORY_MIGRATION);
 | 
					        mask |= (1 << DIRTY_MEMORY_MIGRATION);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return mask;
 | 
					    return mask;
 | 
				
			||||||
@ -1650,14 +1642,26 @@ bool memory_region_test_and_clear_dirty(MemoryRegion *mr, hwaddr addr,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void memory_region_sync_dirty_bitmap(MemoryRegion *mr)
 | 
					void memory_region_sync_dirty_bitmap(MemoryRegion *mr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    MemoryListener *listener;
 | 
				
			||||||
    AddressSpace *as;
 | 
					    AddressSpace *as;
 | 
				
			||||||
 | 
					    FlatView *view;
 | 
				
			||||||
    FlatRange *fr;
 | 
					    FlatRange *fr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
 | 
					    /* If the same address space has multiple log_sync listeners, we
 | 
				
			||||||
        FlatView *view = address_space_get_flatview(as);
 | 
					     * visit that address space's FlatView multiple times.  But because
 | 
				
			||||||
 | 
					     * log_sync listeners are rare, it's still cheaper than walking each
 | 
				
			||||||
 | 
					     * address space once.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    QTAILQ_FOREACH(listener, &memory_listeners, link) {
 | 
				
			||||||
 | 
					        if (!listener->log_sync) {
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        as = listener->address_space;
 | 
				
			||||||
 | 
					        view = address_space_get_flatview(as);
 | 
				
			||||||
        FOR_EACH_FLAT_RANGE(fr, view) {
 | 
					        FOR_EACH_FLAT_RANGE(fr, view) {
 | 
				
			||||||
            if (fr->mr == mr) {
 | 
					            if (fr->mr == mr) {
 | 
				
			||||||
                MEMORY_LISTENER_UPDATE_REGION(fr, as, Forward, log_sync);
 | 
					                MemoryRegionSection mrs = section_from_flat_range(fr, as);
 | 
				
			||||||
 | 
					                listener->log_sync(listener, &mrs);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        flatview_unref(view);
 | 
					        flatview_unref(view);
 | 
				
			||||||
@ -1774,7 +1778,7 @@ static void memory_region_update_coalesced_range_as(MemoryRegion *mr, AddressSpa
 | 
				
			|||||||
                .size = fr->addr.size,
 | 
					                .size = fr->addr.size,
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            MEMORY_LISTENER_CALL(coalesced_mmio_del, Reverse, §ion,
 | 
					            MEMORY_LISTENER_CALL(as, coalesced_mmio_del, Reverse, §ion,
 | 
				
			||||||
                                 int128_get64(fr->addr.start),
 | 
					                                 int128_get64(fr->addr.start),
 | 
				
			||||||
                                 int128_get64(fr->addr.size));
 | 
					                                 int128_get64(fr->addr.size));
 | 
				
			||||||
            QTAILQ_FOREACH(cmr, &mr->coalesced, link) {
 | 
					            QTAILQ_FOREACH(cmr, &mr->coalesced, link) {
 | 
				
			||||||
@ -1785,7 +1789,7 @@ static void memory_region_update_coalesced_range_as(MemoryRegion *mr, AddressSpa
 | 
				
			|||||||
                    continue;
 | 
					                    continue;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                tmp = addrrange_intersection(tmp, fr->addr);
 | 
					                tmp = addrrange_intersection(tmp, fr->addr);
 | 
				
			||||||
                MEMORY_LISTENER_CALL(coalesced_mmio_add, Forward, §ion,
 | 
					                MEMORY_LISTENER_CALL(as, coalesced_mmio_add, Forward, §ion,
 | 
				
			||||||
                                     int128_get64(tmp.start),
 | 
					                                     int128_get64(tmp.start),
 | 
				
			||||||
                                     int128_get64(tmp.size));
 | 
					                                     int128_get64(tmp.size));
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -2176,14 +2180,14 @@ void memory_global_dirty_log_sync(void)
 | 
				
			|||||||
        if (!listener->log_sync) {
 | 
					        if (!listener->log_sync) {
 | 
				
			||||||
            continue;
 | 
					            continue;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        /* Global listeners are being phased out.  */
 | 
					        as = listener->address_space;
 | 
				
			||||||
        assert(listener->address_space_filter);
 | 
					 | 
				
			||||||
        as = listener->address_space_filter;
 | 
					 | 
				
			||||||
        view = address_space_get_flatview(as);
 | 
					        view = address_space_get_flatview(as);
 | 
				
			||||||
        FOR_EACH_FLAT_RANGE(fr, view) {
 | 
					        FOR_EACH_FLAT_RANGE(fr, view) {
 | 
				
			||||||
 | 
					            if (fr->dirty_log_mask) {
 | 
				
			||||||
                MemoryRegionSection mrs = section_from_flat_range(fr, as);
 | 
					                MemoryRegionSection mrs = section_from_flat_range(fr, as);
 | 
				
			||||||
                listener->log_sync(listener, &mrs);
 | 
					                listener->log_sync(listener, &mrs);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        flatview_unref(view);
 | 
					        flatview_unref(view);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -2218,11 +2222,6 @@ static void listener_add_address_space(MemoryListener *listener,
 | 
				
			|||||||
    FlatView *view;
 | 
					    FlatView *view;
 | 
				
			||||||
    FlatRange *fr;
 | 
					    FlatRange *fr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (listener->address_space_filter
 | 
					 | 
				
			||||||
        && listener->address_space_filter != as) {
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (listener->begin) {
 | 
					    if (listener->begin) {
 | 
				
			||||||
        listener->begin(listener);
 | 
					        listener->begin(listener);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -2255,12 +2254,11 @@ static void listener_add_address_space(MemoryListener *listener,
 | 
				
			|||||||
    flatview_unref(view);
 | 
					    flatview_unref(view);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void memory_listener_register(MemoryListener *listener, AddressSpace *filter)
 | 
					void memory_listener_register(MemoryListener *listener, AddressSpace *as)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    MemoryListener *other = NULL;
 | 
					    MemoryListener *other = NULL;
 | 
				
			||||||
    AddressSpace *as;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    listener->address_space_filter = filter;
 | 
					    listener->address_space = as;
 | 
				
			||||||
    if (QTAILQ_EMPTY(&memory_listeners)
 | 
					    if (QTAILQ_EMPTY(&memory_listeners)
 | 
				
			||||||
        || listener->priority >= QTAILQ_LAST(&memory_listeners,
 | 
					        || listener->priority >= QTAILQ_LAST(&memory_listeners,
 | 
				
			||||||
                                             memory_listeners)->priority) {
 | 
					                                             memory_listeners)->priority) {
 | 
				
			||||||
@ -2274,14 +2272,26 @@ void memory_listener_register(MemoryListener *listener, AddressSpace *filter)
 | 
				
			|||||||
        QTAILQ_INSERT_BEFORE(other, listener, link);
 | 
					        QTAILQ_INSERT_BEFORE(other, listener, link);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
 | 
					    if (QTAILQ_EMPTY(&as->listeners)
 | 
				
			||||||
        listener_add_address_space(listener, as);
 | 
					        || listener->priority >= QTAILQ_LAST(&as->listeners,
 | 
				
			||||||
 | 
					                                             memory_listeners)->priority) {
 | 
				
			||||||
 | 
					        QTAILQ_INSERT_TAIL(&as->listeners, listener, link_as);
 | 
				
			||||||
 | 
					    } else {
 | 
				
			||||||
 | 
					        QTAILQ_FOREACH(other, &as->listeners, link_as) {
 | 
				
			||||||
 | 
					            if (listener->priority < other->priority) {
 | 
				
			||||||
 | 
					                break;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        QTAILQ_INSERT_BEFORE(other, listener, link_as);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    listener_add_address_space(listener, as);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void memory_listener_unregister(MemoryListener *listener)
 | 
					void memory_listener_unregister(MemoryListener *listener)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    QTAILQ_REMOVE(&memory_listeners, listener, link);
 | 
					    QTAILQ_REMOVE(&memory_listeners, listener, link);
 | 
				
			||||||
 | 
					    QTAILQ_REMOVE(&listener->address_space->listeners, listener, link_as);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name)
 | 
					void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name)
 | 
				
			||||||
@ -2295,6 +2305,7 @@ void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name)
 | 
				
			|||||||
    flatview_init(as->current_map);
 | 
					    flatview_init(as->current_map);
 | 
				
			||||||
    as->ioeventfd_nb = 0;
 | 
					    as->ioeventfd_nb = 0;
 | 
				
			||||||
    as->ioeventfds = NULL;
 | 
					    as->ioeventfds = NULL;
 | 
				
			||||||
 | 
					    QTAILQ_INIT(&as->listeners);
 | 
				
			||||||
    QTAILQ_INSERT_TAIL(&address_spaces, as, address_spaces_link);
 | 
					    QTAILQ_INSERT_TAIL(&address_spaces, as, address_spaces_link);
 | 
				
			||||||
    as->name = g_strdup(name ? name : "anonymous");
 | 
					    as->name = g_strdup(name ? name : "anonymous");
 | 
				
			||||||
    address_space_init_dispatch(as);
 | 
					    address_space_init_dispatch(as);
 | 
				
			||||||
@ -2304,14 +2315,10 @@ void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void do_address_space_destroy(AddressSpace *as)
 | 
					static void do_address_space_destroy(AddressSpace *as)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    MemoryListener *listener;
 | 
					 | 
				
			||||||
    bool do_free = as->malloced;
 | 
					    bool do_free = as->malloced;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    address_space_destroy_dispatch(as);
 | 
					    address_space_destroy_dispatch(as);
 | 
				
			||||||
 | 
					    assert(QTAILQ_EMPTY(&as->listeners));
 | 
				
			||||||
    QTAILQ_FOREACH(listener, &memory_listeners, link) {
 | 
					 | 
				
			||||||
        assert(listener->address_space_filter != as);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    flatview_unref(as->current_map);
 | 
					    flatview_unref(as->current_map);
 | 
				
			||||||
    g_free(as->name);
 | 
					    g_free(as->name);
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										27
									
								
								monitor.c
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								monitor.c
									
									
									
									
									
								
							@ -186,7 +186,7 @@ typedef struct {
 | 
				
			|||||||
} MonitorQAPIEventConf;
 | 
					} MonitorQAPIEventConf;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Monitor {
 | 
					struct Monitor {
 | 
				
			||||||
    CharDriverState *chr;
 | 
					    CharBackend chr;
 | 
				
			||||||
    int reset_seen;
 | 
					    int reset_seen;
 | 
				
			||||||
    int flags;
 | 
					    int flags;
 | 
				
			||||||
    int suspend_cnt;
 | 
					    int suspend_cnt;
 | 
				
			||||||
@ -297,7 +297,7 @@ static void monitor_flush_locked(Monitor *mon)
 | 
				
			|||||||
    len = qstring_get_length(mon->outbuf);
 | 
					    len = qstring_get_length(mon->outbuf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (len && !mon->mux_out) {
 | 
					    if (len && !mon->mux_out) {
 | 
				
			||||||
        rc = qemu_chr_fe_write(mon->chr, (const uint8_t *) buf, len);
 | 
					        rc = qemu_chr_fe_write(&mon->chr, (const uint8_t *) buf, len);
 | 
				
			||||||
        if ((rc < 0 && errno != EAGAIN) || (rc == len)) {
 | 
					        if ((rc < 0 && errno != EAGAIN) || (rc == len)) {
 | 
				
			||||||
            /* all flushed or error */
 | 
					            /* all flushed or error */
 | 
				
			||||||
            QDECREF(mon->outbuf);
 | 
					            QDECREF(mon->outbuf);
 | 
				
			||||||
@ -311,7 +311,8 @@ static void monitor_flush_locked(Monitor *mon)
 | 
				
			|||||||
            mon->outbuf = tmp;
 | 
					            mon->outbuf = tmp;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (mon->out_watch == 0) {
 | 
					        if (mon->out_watch == 0) {
 | 
				
			||||||
            mon->out_watch = qemu_chr_fe_add_watch(mon->chr, G_IO_OUT|G_IO_HUP,
 | 
					            mon->out_watch =
 | 
				
			||||||
 | 
					                qemu_chr_fe_add_watch(&mon->chr, G_IO_OUT | G_IO_HUP,
 | 
				
			||||||
                                      monitor_unblocked, mon);
 | 
					                                      monitor_unblocked, mon);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -581,9 +582,7 @@ static void monitor_data_init(Monitor *mon)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void monitor_data_destroy(Monitor *mon)
 | 
					static void monitor_data_destroy(Monitor *mon)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (mon->chr) {
 | 
					    qemu_chr_fe_deinit(&mon->chr);
 | 
				
			||||||
        qemu_chr_add_handlers(mon->chr, NULL, NULL, NULL, NULL);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (monitor_is_qmp(mon)) {
 | 
					    if (monitor_is_qmp(mon)) {
 | 
				
			||||||
        json_message_parser_destroy(&mon->qmp.parser);
 | 
					        json_message_parser_destroy(&mon->qmp.parser);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -1745,7 +1744,7 @@ void qmp_getfd(const char *fdname, Error **errp)
 | 
				
			|||||||
    mon_fd_t *monfd;
 | 
					    mon_fd_t *monfd;
 | 
				
			||||||
    int fd;
 | 
					    int fd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fd = qemu_chr_fe_get_msgfd(cur_mon->chr);
 | 
					    fd = qemu_chr_fe_get_msgfd(&cur_mon->chr);
 | 
				
			||||||
    if (fd == -1) {
 | 
					    if (fd == -1) {
 | 
				
			||||||
        error_setg(errp, QERR_FD_NOT_SUPPLIED);
 | 
					        error_setg(errp, QERR_FD_NOT_SUPPLIED);
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
@ -1870,7 +1869,7 @@ AddfdInfo *qmp_add_fd(bool has_fdset_id, int64_t fdset_id, bool has_opaque,
 | 
				
			|||||||
    Monitor *mon = cur_mon;
 | 
					    Monitor *mon = cur_mon;
 | 
				
			||||||
    AddfdInfo *fdinfo;
 | 
					    AddfdInfo *fdinfo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fd = qemu_chr_fe_get_msgfd(mon->chr);
 | 
					    fd = qemu_chr_fe_get_msgfd(&mon->chr);
 | 
				
			||||||
    if (fd == -1) {
 | 
					    if (fd == -1) {
 | 
				
			||||||
        error_setg(errp, QERR_FD_NOT_SUPPLIED);
 | 
					        error_setg(errp, QERR_FD_NOT_SUPPLIED);
 | 
				
			||||||
        goto error;
 | 
					        goto error;
 | 
				
			||||||
@ -3977,7 +3976,7 @@ void monitor_init(CharDriverState *chr, int flags)
 | 
				
			|||||||
    mon = g_malloc(sizeof(*mon));
 | 
					    mon = g_malloc(sizeof(*mon));
 | 
				
			||||||
    monitor_data_init(mon);
 | 
					    monitor_data_init(mon);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    mon->chr = chr;
 | 
					    qemu_chr_fe_init(&mon->chr, chr, &error_abort);
 | 
				
			||||||
    mon->flags = flags;
 | 
					    mon->flags = flags;
 | 
				
			||||||
    if (flags & MONITOR_USE_READLINE) {
 | 
					    if (flags & MONITOR_USE_READLINE) {
 | 
				
			||||||
        mon->rs = readline_init(monitor_readline_printf,
 | 
					        mon->rs = readline_init(monitor_readline_printf,
 | 
				
			||||||
@ -3988,13 +3987,13 @@ void monitor_init(CharDriverState *chr, int flags)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (monitor_is_qmp(mon)) {
 | 
					    if (monitor_is_qmp(mon)) {
 | 
				
			||||||
        qemu_chr_add_handlers(chr, monitor_can_read, monitor_qmp_read,
 | 
					        qemu_chr_fe_set_handlers(&mon->chr, monitor_can_read, monitor_qmp_read,
 | 
				
			||||||
                              monitor_qmp_event, mon);
 | 
					                                 monitor_qmp_event, mon, NULL, true);
 | 
				
			||||||
        qemu_chr_fe_set_echo(chr, true);
 | 
					        qemu_chr_fe_set_echo(&mon->chr, true);
 | 
				
			||||||
        json_message_parser_init(&mon->qmp.parser, handle_qmp_command);
 | 
					        json_message_parser_init(&mon->qmp.parser, handle_qmp_command);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        qemu_chr_add_handlers(chr, monitor_can_read, monitor_read,
 | 
					        qemu_chr_fe_set_handlers(&mon->chr, monitor_can_read, monitor_read,
 | 
				
			||||||
                              monitor_event, mon);
 | 
					                                 monitor_event, mon, NULL, true);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qemu_mutex_lock(&monitor_lock);
 | 
					    qemu_mutex_lock(&monitor_lock);
 | 
				
			||||||
 | 
				
			|||||||
@ -68,9 +68,9 @@ typedef struct CompareState {
 | 
				
			|||||||
    char *pri_indev;
 | 
					    char *pri_indev;
 | 
				
			||||||
    char *sec_indev;
 | 
					    char *sec_indev;
 | 
				
			||||||
    char *outdev;
 | 
					    char *outdev;
 | 
				
			||||||
    CharDriverState *chr_pri_in;
 | 
					    CharBackend chr_pri_in;
 | 
				
			||||||
    CharDriverState *chr_sec_in;
 | 
					    CharBackend chr_sec_in;
 | 
				
			||||||
    CharDriverState *chr_out;
 | 
					    CharBackend chr_out;
 | 
				
			||||||
    SocketReadState pri_rs;
 | 
					    SocketReadState pri_rs;
 | 
				
			||||||
    SocketReadState sec_rs;
 | 
					    SocketReadState sec_rs;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -101,7 +101,7 @@ enum {
 | 
				
			|||||||
    SECONDARY_IN,
 | 
					    SECONDARY_IN,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int compare_chr_send(CharDriverState *out,
 | 
					static int compare_chr_send(CharBackend *out,
 | 
				
			||||||
                            const uint8_t *buf,
 | 
					                            const uint8_t *buf,
 | 
				
			||||||
                            uint32_t size);
 | 
					                            uint32_t size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -385,7 +385,7 @@ static void colo_compare_connection(void *opaque, void *user_data)
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (result) {
 | 
					        if (result) {
 | 
				
			||||||
            ret = compare_chr_send(s->chr_out, pkt->data, pkt->size);
 | 
					            ret = compare_chr_send(&s->chr_out, pkt->data, pkt->size);
 | 
				
			||||||
            if (ret < 0) {
 | 
					            if (ret < 0) {
 | 
				
			||||||
                error_report("colo_send_primary_packet failed");
 | 
					                error_report("colo_send_primary_packet failed");
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -408,7 +408,7 @@ static void colo_compare_connection(void *opaque, void *user_data)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int compare_chr_send(CharDriverState *out,
 | 
					static int compare_chr_send(CharBackend *out,
 | 
				
			||||||
                            const uint8_t *buf,
 | 
					                            const uint8_t *buf,
 | 
				
			||||||
                            uint32_t size)
 | 
					                            uint32_t size)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -451,7 +451,8 @@ static void compare_pri_chr_in(void *opaque, const uint8_t *buf, int size)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    ret = net_fill_rstate(&s->pri_rs, buf, size);
 | 
					    ret = net_fill_rstate(&s->pri_rs, buf, size);
 | 
				
			||||||
    if (ret == -1) {
 | 
					    if (ret == -1) {
 | 
				
			||||||
        qemu_chr_add_handlers(s->chr_pri_in, NULL, NULL, NULL, NULL);
 | 
					        qemu_chr_fe_set_handlers(&s->chr_pri_in, NULL, NULL, NULL,
 | 
				
			||||||
 | 
					                                 NULL, NULL, true);
 | 
				
			||||||
        error_report("colo-compare primary_in error");
 | 
					        error_report("colo-compare primary_in error");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -467,7 +468,8 @@ static void compare_sec_chr_in(void *opaque, const uint8_t *buf, int size)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    ret = net_fill_rstate(&s->sec_rs, buf, size);
 | 
					    ret = net_fill_rstate(&s->sec_rs, buf, size);
 | 
				
			||||||
    if (ret == -1) {
 | 
					    if (ret == -1) {
 | 
				
			||||||
        qemu_chr_add_handlers(s->chr_sec_in, NULL, NULL, NULL, NULL);
 | 
					        qemu_chr_fe_set_handlers(&s->chr_sec_in, NULL, NULL, NULL,
 | 
				
			||||||
 | 
					                                 NULL, NULL, true);
 | 
				
			||||||
        error_report("colo-compare secondary_in error");
 | 
					        error_report("colo-compare secondary_in error");
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -480,10 +482,10 @@ static void *colo_compare_thread(void *opaque)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    worker_context = g_main_context_new();
 | 
					    worker_context = g_main_context_new();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qemu_chr_add_handlers_full(s->chr_pri_in, compare_chr_can_read,
 | 
					    qemu_chr_fe_set_handlers(&s->chr_pri_in, compare_chr_can_read,
 | 
				
			||||||
                          compare_pri_chr_in, NULL, s, worker_context);
 | 
					                             compare_pri_chr_in, NULL, s, worker_context, true);
 | 
				
			||||||
    qemu_chr_add_handlers_full(s->chr_sec_in, compare_chr_can_read,
 | 
					    qemu_chr_fe_set_handlers(&s->chr_sec_in, compare_chr_can_read,
 | 
				
			||||||
                          compare_sec_chr_in, NULL, s, worker_context);
 | 
					                             compare_sec_chr_in, NULL, s, worker_context, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    compare_loop = g_main_loop_new(worker_context, FALSE);
 | 
					    compare_loop = g_main_loop_new(worker_context, FALSE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -545,7 +547,7 @@ static void compare_pri_rs_finalize(SocketReadState *pri_rs)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    if (packet_enqueue(s, PRIMARY_IN)) {
 | 
					    if (packet_enqueue(s, PRIMARY_IN)) {
 | 
				
			||||||
        trace_colo_compare_main("primary: unsupported packet in");
 | 
					        trace_colo_compare_main("primary: unsupported packet in");
 | 
				
			||||||
        compare_chr_send(s->chr_out, pri_rs->buf, pri_rs->packet_len);
 | 
					        compare_chr_send(&s->chr_out, pri_rs->buf, pri_rs->packet_len);
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        /* compare connection */
 | 
					        /* compare connection */
 | 
				
			||||||
        g_queue_foreach(&s->conn_list, colo_compare_connection, s);
 | 
					        g_queue_foreach(&s->conn_list, colo_compare_connection, s);
 | 
				
			||||||
@ -589,6 +591,7 @@ static int find_and_check_chardev(CharDriverState **chr,
 | 
				
			|||||||
                   chr_name);
 | 
					                   chr_name);
 | 
				
			||||||
        return 1;
 | 
					        return 1;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -619,6 +622,7 @@ static void check_old_packet_regular(void *opaque)
 | 
				
			|||||||
static void colo_compare_complete(UserCreatable *uc, Error **errp)
 | 
					static void colo_compare_complete(UserCreatable *uc, Error **errp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    CompareState *s = COLO_COMPARE(uc);
 | 
					    CompareState *s = COLO_COMPARE(uc);
 | 
				
			||||||
 | 
					    CharDriverState *chr;
 | 
				
			||||||
    char thread_name[64];
 | 
					    char thread_name[64];
 | 
				
			||||||
    static int compare_id;
 | 
					    static int compare_id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -634,24 +638,21 @@ static void colo_compare_complete(UserCreatable *uc, Error **errp)
 | 
				
			|||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (find_and_check_chardev(&s->chr_pri_in, s->pri_indev, errp)) {
 | 
					    if (find_and_check_chardev(&chr, s->pri_indev, errp) ||
 | 
				
			||||||
 | 
					        !qemu_chr_fe_init(&s->chr_pri_in, chr, errp)) {
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (find_and_check_chardev(&s->chr_sec_in, s->sec_indev, errp)) {
 | 
					    if (find_and_check_chardev(&chr, s->sec_indev, errp) ||
 | 
				
			||||||
 | 
					        !qemu_chr_fe_init(&s->chr_sec_in, chr, errp)) {
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (find_and_check_chardev(&s->chr_out, s->outdev, errp)) {
 | 
					    if (find_and_check_chardev(&chr, s->outdev, errp) ||
 | 
				
			||||||
 | 
					        !qemu_chr_fe_init(&s->chr_out, chr, errp)) {
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qemu_chr_fe_claim_no_fail(s->chr_pri_in);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    qemu_chr_fe_claim_no_fail(s->chr_sec_in);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    qemu_chr_fe_claim_no_fail(s->chr_out);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    net_socket_rs_init(&s->pri_rs, compare_pri_rs_finalize);
 | 
					    net_socket_rs_init(&s->pri_rs, compare_pri_rs_finalize);
 | 
				
			||||||
    net_socket_rs_init(&s->sec_rs, compare_sec_rs_finalize);
 | 
					    net_socket_rs_init(&s->sec_rs, compare_sec_rs_finalize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -702,17 +703,9 @@ static void colo_compare_finalize(Object *obj)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    CompareState *s = COLO_COMPARE(obj);
 | 
					    CompareState *s = COLO_COMPARE(obj);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (s->chr_pri_in) {
 | 
					    qemu_chr_fe_deinit(&s->chr_pri_in);
 | 
				
			||||||
        qemu_chr_add_handlers(s->chr_pri_in, NULL, NULL, NULL, NULL);
 | 
					    qemu_chr_fe_deinit(&s->chr_sec_in);
 | 
				
			||||||
        qemu_chr_fe_release(s->chr_pri_in);
 | 
					    qemu_chr_fe_deinit(&s->chr_out);
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (s->chr_sec_in) {
 | 
					 | 
				
			||||||
        qemu_chr_add_handlers(s->chr_sec_in, NULL, NULL, NULL, NULL);
 | 
					 | 
				
			||||||
        qemu_chr_fe_release(s->chr_sec_in);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (s->chr_out) {
 | 
					 | 
				
			||||||
        qemu_chr_fe_release(s->chr_out);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    g_queue_free(&s->conn_list);
 | 
					    g_queue_free(&s->conn_list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -38,12 +38,12 @@ typedef struct MirrorState {
 | 
				
			|||||||
    NetFilterState parent_obj;
 | 
					    NetFilterState parent_obj;
 | 
				
			||||||
    char *indev;
 | 
					    char *indev;
 | 
				
			||||||
    char *outdev;
 | 
					    char *outdev;
 | 
				
			||||||
    CharDriverState *chr_in;
 | 
					    CharBackend chr_in;
 | 
				
			||||||
    CharDriverState *chr_out;
 | 
					    CharBackend chr_out;
 | 
				
			||||||
    SocketReadState rs;
 | 
					    SocketReadState rs;
 | 
				
			||||||
} MirrorState;
 | 
					} MirrorState;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int filter_mirror_send(CharDriverState *chr_out,
 | 
					static int filter_mirror_send(CharBackend *chr_out,
 | 
				
			||||||
                              const struct iovec *iov,
 | 
					                              const struct iovec *iov,
 | 
				
			||||||
                              int iovcnt)
 | 
					                              int iovcnt)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -110,7 +110,8 @@ static void redirector_chr_read(void *opaque, const uint8_t *buf, int size)
 | 
				
			|||||||
    ret = net_fill_rstate(&s->rs, buf, size);
 | 
					    ret = net_fill_rstate(&s->rs, buf, size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (ret == -1) {
 | 
					    if (ret == -1) {
 | 
				
			||||||
        qemu_chr_add_handlers(s->chr_in, NULL, NULL, NULL, NULL);
 | 
					        qemu_chr_fe_set_handlers(&s->chr_in, NULL, NULL, NULL,
 | 
				
			||||||
 | 
					                                 NULL, NULL, true);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -121,7 +122,8 @@ static void redirector_chr_event(void *opaque, int event)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    switch (event) {
 | 
					    switch (event) {
 | 
				
			||||||
    case CHR_EVENT_CLOSED:
 | 
					    case CHR_EVENT_CLOSED:
 | 
				
			||||||
        qemu_chr_add_handlers(s->chr_in, NULL, NULL, NULL, NULL);
 | 
					        qemu_chr_fe_set_handlers(&s->chr_in, NULL, NULL, NULL,
 | 
				
			||||||
 | 
					                                 NULL, NULL, true);
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    default:
 | 
					    default:
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
@ -138,7 +140,7 @@ static ssize_t filter_mirror_receive_iov(NetFilterState *nf,
 | 
				
			|||||||
    MirrorState *s = FILTER_MIRROR(nf);
 | 
					    MirrorState *s = FILTER_MIRROR(nf);
 | 
				
			||||||
    int ret;
 | 
					    int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    ret = filter_mirror_send(s->chr_out, iov, iovcnt);
 | 
					    ret = filter_mirror_send(&s->chr_out, iov, iovcnt);
 | 
				
			||||||
    if (ret) {
 | 
					    if (ret) {
 | 
				
			||||||
        error_report("filter_mirror_send failed(%s)", strerror(-ret));
 | 
					        error_report("filter_mirror_send failed(%s)", strerror(-ret));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -160,8 +162,8 @@ static ssize_t filter_redirector_receive_iov(NetFilterState *nf,
 | 
				
			|||||||
    MirrorState *s = FILTER_REDIRECTOR(nf);
 | 
					    MirrorState *s = FILTER_REDIRECTOR(nf);
 | 
				
			||||||
    int ret;
 | 
					    int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (s->chr_out) {
 | 
					    if (qemu_chr_fe_get_driver(&s->chr_out)) {
 | 
				
			||||||
        ret = filter_mirror_send(s->chr_out, iov, iovcnt);
 | 
					        ret = filter_mirror_send(&s->chr_out, iov, iovcnt);
 | 
				
			||||||
        if (ret) {
 | 
					        if (ret) {
 | 
				
			||||||
            error_report("filter_mirror_send failed(%s)", strerror(-ret));
 | 
					            error_report("filter_mirror_send failed(%s)", strerror(-ret));
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -175,27 +177,21 @@ static void filter_mirror_cleanup(NetFilterState *nf)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    MirrorState *s = FILTER_MIRROR(nf);
 | 
					    MirrorState *s = FILTER_MIRROR(nf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (s->chr_out) {
 | 
					    qemu_chr_fe_deinit(&s->chr_out);
 | 
				
			||||||
        qemu_chr_fe_release(s->chr_out);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void filter_redirector_cleanup(NetFilterState *nf)
 | 
					static void filter_redirector_cleanup(NetFilterState *nf)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    MirrorState *s = FILTER_REDIRECTOR(nf);
 | 
					    MirrorState *s = FILTER_REDIRECTOR(nf);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (s->chr_in) {
 | 
					    qemu_chr_fe_deinit(&s->chr_in);
 | 
				
			||||||
        qemu_chr_add_handlers(s->chr_in, NULL, NULL, NULL, NULL);
 | 
					    qemu_chr_fe_deinit(&s->chr_out);
 | 
				
			||||||
        qemu_chr_fe_release(s->chr_in);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if (s->chr_out) {
 | 
					 | 
				
			||||||
        qemu_chr_fe_release(s->chr_out);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void filter_mirror_setup(NetFilterState *nf, Error **errp)
 | 
					static void filter_mirror_setup(NetFilterState *nf, Error **errp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    MirrorState *s = FILTER_MIRROR(nf);
 | 
					    MirrorState *s = FILTER_MIRROR(nf);
 | 
				
			||||||
 | 
					    CharDriverState *chr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!s->outdev) {
 | 
					    if (!s->outdev) {
 | 
				
			||||||
        error_setg(errp, "filter mirror needs 'outdev' "
 | 
					        error_setg(errp, "filter mirror needs 'outdev' "
 | 
				
			||||||
@ -203,17 +199,14 @@ static void filter_mirror_setup(NetFilterState *nf, Error **errp)
 | 
				
			|||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s->chr_out = qemu_chr_find(s->outdev);
 | 
					    chr = qemu_chr_find(s->outdev);
 | 
				
			||||||
    if (s->chr_out == NULL) {
 | 
					    if (chr == NULL) {
 | 
				
			||||||
        error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
 | 
					        error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
 | 
				
			||||||
                  "Device '%s' not found", s->outdev);
 | 
					                  "Device '%s' not found", s->outdev);
 | 
				
			||||||
        return;
 | 
					        return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (qemu_chr_fe_claim(s->chr_out) != 0) {
 | 
					    qemu_chr_fe_init(&s->chr_out, chr, errp);
 | 
				
			||||||
        error_setg(errp, QERR_DEVICE_IN_USE, s->outdev);
 | 
					 | 
				
			||||||
        return;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void redirector_rs_finalize(SocketReadState *rs)
 | 
					static void redirector_rs_finalize(SocketReadState *rs)
 | 
				
			||||||
@ -227,6 +220,7 @@ static void redirector_rs_finalize(SocketReadState *rs)
 | 
				
			|||||||
static void filter_redirector_setup(NetFilterState *nf, Error **errp)
 | 
					static void filter_redirector_setup(NetFilterState *nf, Error **errp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    MirrorState *s = FILTER_REDIRECTOR(nf);
 | 
					    MirrorState *s = FILTER_REDIRECTOR(nf);
 | 
				
			||||||
 | 
					    CharDriverState *chr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!s->indev && !s->outdev) {
 | 
					    if (!s->indev && !s->outdev) {
 | 
				
			||||||
        error_setg(errp, "filter redirector needs 'indev' or "
 | 
					        error_setg(errp, "filter redirector needs 'indev' or "
 | 
				
			||||||
@ -243,26 +237,32 @@ static void filter_redirector_setup(NetFilterState *nf, Error **errp)
 | 
				
			|||||||
    net_socket_rs_init(&s->rs, redirector_rs_finalize);
 | 
					    net_socket_rs_init(&s->rs, redirector_rs_finalize);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (s->indev) {
 | 
					    if (s->indev) {
 | 
				
			||||||
        s->chr_in = qemu_chr_find(s->indev);
 | 
					        chr = qemu_chr_find(s->indev);
 | 
				
			||||||
        if (s->chr_in == NULL) {
 | 
					        if (chr == NULL) {
 | 
				
			||||||
            error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
 | 
					            error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
 | 
				
			||||||
                      "IN Device '%s' not found", s->indev);
 | 
					                      "IN Device '%s' not found", s->indev);
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        qemu_chr_fe_claim_no_fail(s->chr_in);
 | 
					        if (!qemu_chr_fe_init(&s->chr_in, chr, errp)) {
 | 
				
			||||||
        qemu_chr_add_handlers(s->chr_in, redirector_chr_can_read,
 | 
					            return;
 | 
				
			||||||
                              redirector_chr_read, redirector_chr_event, nf);
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        qemu_chr_fe_set_handlers(&s->chr_in, redirector_chr_can_read,
 | 
				
			||||||
 | 
					                                 redirector_chr_read, redirector_chr_event,
 | 
				
			||||||
 | 
					                                 nf, NULL, true);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (s->outdev) {
 | 
					    if (s->outdev) {
 | 
				
			||||||
        s->chr_out = qemu_chr_find(s->outdev);
 | 
					        chr = qemu_chr_find(s->outdev);
 | 
				
			||||||
        if (s->chr_out == NULL) {
 | 
					        if (chr == NULL) {
 | 
				
			||||||
            error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
 | 
					            error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
 | 
				
			||||||
                      "OUT Device '%s' not found", s->outdev);
 | 
					                      "OUT Device '%s' not found", s->outdev);
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        qemu_chr_fe_claim_no_fail(s->chr_out);
 | 
					        if (!qemu_chr_fe_init(&s->chr_out, chr, errp)) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										25
									
								
								net/slirp.c
									
									
									
									
									
								
							
							
						
						
									
										25
									
								
								net/slirp.c
									
									
									
									
									
								
							@ -40,6 +40,7 @@
 | 
				
			|||||||
#include "sysemu/char.h"
 | 
					#include "sysemu/char.h"
 | 
				
			||||||
#include "sysemu/sysemu.h"
 | 
					#include "sysemu/sysemu.h"
 | 
				
			||||||
#include "qemu/cutils.h"
 | 
					#include "qemu/cutils.h"
 | 
				
			||||||
 | 
					#include "qapi/error.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
 | 
					static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -682,7 +683,7 @@ int net_slirp_smb(const char *exported_dir)
 | 
				
			|||||||
#endif /* !defined(_WIN32) */
 | 
					#endif /* !defined(_WIN32) */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct GuestFwd {
 | 
					struct GuestFwd {
 | 
				
			||||||
    CharDriverState *hd;
 | 
					    CharBackend hd;
 | 
				
			||||||
    struct in_addr server;
 | 
					    struct in_addr server;
 | 
				
			||||||
    int port;
 | 
					    int port;
 | 
				
			||||||
    Slirp *slirp;
 | 
					    Slirp *slirp;
 | 
				
			||||||
@ -746,15 +747,24 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str,
 | 
				
			|||||||
            return -1;
 | 
					            return -1;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        fwd = g_new(struct GuestFwd, 1);
 | 
					        Error *err = NULL;
 | 
				
			||||||
        fwd->hd = qemu_chr_new(buf, p, NULL);
 | 
					        CharDriverState *chr = qemu_chr_new(buf, p);
 | 
				
			||||||
        if (!fwd->hd) {
 | 
					
 | 
				
			||||||
 | 
					        if (!chr) {
 | 
				
			||||||
            error_report("could not open guest forwarding device '%s'", buf);
 | 
					            error_report("could not open guest forwarding device '%s'", buf);
 | 
				
			||||||
 | 
					            return -1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        fwd = g_new(struct GuestFwd, 1);
 | 
				
			||||||
 | 
					        qemu_chr_fe_init(&fwd->hd, chr, &err);
 | 
				
			||||||
 | 
					        if (err) {
 | 
				
			||||||
 | 
					            error_report_err(err);
 | 
				
			||||||
            g_free(fwd);
 | 
					            g_free(fwd);
 | 
				
			||||||
            return -1;
 | 
					            return -1;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (slirp_add_exec(s->slirp, 3, fwd->hd, &server, port) < 0) {
 | 
					        if (slirp_add_exec(s->slirp, 3, qemu_chr_fe_get_driver(&fwd->hd),
 | 
				
			||||||
 | 
					                           &server, port) < 0) {
 | 
				
			||||||
            error_report("conflicting/invalid host:port in guest forwarding "
 | 
					            error_report("conflicting/invalid host:port in guest forwarding "
 | 
				
			||||||
                         "rule '%s'", config_str);
 | 
					                         "rule '%s'", config_str);
 | 
				
			||||||
            g_free(fwd);
 | 
					            g_free(fwd);
 | 
				
			||||||
@ -764,9 +774,8 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str,
 | 
				
			|||||||
        fwd->port = port;
 | 
					        fwd->port = port;
 | 
				
			||||||
        fwd->slirp = s->slirp;
 | 
					        fwd->slirp = s->slirp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        qemu_chr_fe_claim_no_fail(fwd->hd);
 | 
					        qemu_chr_fe_set_handlers(&fwd->hd, guestfwd_can_read, guestfwd_read,
 | 
				
			||||||
        qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read,
 | 
					                                 NULL, fwd, NULL, true);
 | 
				
			||||||
                              NULL, fwd);
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -20,7 +20,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
typedef struct VhostUserState {
 | 
					typedef struct VhostUserState {
 | 
				
			||||||
    NetClientState nc;
 | 
					    NetClientState nc;
 | 
				
			||||||
    CharDriverState *chr;
 | 
					    CharBackend chr; /* only queue index 0 */
 | 
				
			||||||
    VHostNetState *vhost_net;
 | 
					    VHostNetState *vhost_net;
 | 
				
			||||||
    guint watch;
 | 
					    guint watch;
 | 
				
			||||||
    uint64_t acked_features;
 | 
					    uint64_t acked_features;
 | 
				
			||||||
@ -62,7 +62,7 @@ static void vhost_user_stop(int queues, NetClientState *ncs[])
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int vhost_user_start(int queues, NetClientState *ncs[])
 | 
					static int vhost_user_start(int queues, NetClientState *ncs[], CharBackend *be)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    VhostNetOptions options;
 | 
					    VhostNetOptions options;
 | 
				
			||||||
    struct vhost_net *net = NULL;
 | 
					    struct vhost_net *net = NULL;
 | 
				
			||||||
@ -78,7 +78,7 @@ static int vhost_user_start(int queues, NetClientState *ncs[])
 | 
				
			|||||||
        s = DO_UPCAST(VhostUserState, nc, ncs[i]);
 | 
					        s = DO_UPCAST(VhostUserState, nc, ncs[i]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        options.net_backend = ncs[i];
 | 
					        options.net_backend = ncs[i];
 | 
				
			||||||
        options.opaque      = s->chr;
 | 
					        options.opaque      = be;
 | 
				
			||||||
        options.busyloop_timeout = 0;
 | 
					        options.busyloop_timeout = 0;
 | 
				
			||||||
        net = vhost_net_init(&options);
 | 
					        net = vhost_net_init(&options);
 | 
				
			||||||
        if (!net) {
 | 
					        if (!net) {
 | 
				
			||||||
@ -150,10 +150,8 @@ static void vhost_user_cleanup(NetClientState *nc)
 | 
				
			|||||||
        g_free(s->vhost_net);
 | 
					        g_free(s->vhost_net);
 | 
				
			||||||
        s->vhost_net = NULL;
 | 
					        s->vhost_net = NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if (s->chr) {
 | 
					    if (nc->queue_index == 0) {
 | 
				
			||||||
        qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, NULL);
 | 
					        qemu_chr_fe_deinit(&s->chr);
 | 
				
			||||||
        qemu_chr_fe_release(s->chr);
 | 
					 | 
				
			||||||
        s->chr = NULL;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qemu_purge_queued_packets(nc);
 | 
					    qemu_purge_queued_packets(nc);
 | 
				
			||||||
@ -187,7 +185,7 @@ static gboolean net_vhost_user_watch(GIOChannel *chan, GIOCondition cond,
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    VhostUserState *s = opaque;
 | 
					    VhostUserState *s = opaque;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qemu_chr_disconnect(s->chr);
 | 
					    qemu_chr_fe_disconnect(&s->chr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return FALSE;
 | 
					    return FALSE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -197,6 +195,7 @@ static void net_vhost_user_event(void *opaque, int event)
 | 
				
			|||||||
    const char *name = opaque;
 | 
					    const char *name = opaque;
 | 
				
			||||||
    NetClientState *ncs[MAX_QUEUE_NUM];
 | 
					    NetClientState *ncs[MAX_QUEUE_NUM];
 | 
				
			||||||
    VhostUserState *s;
 | 
					    VhostUserState *s;
 | 
				
			||||||
 | 
					    CharDriverState *chr;
 | 
				
			||||||
    Error *err = NULL;
 | 
					    Error *err = NULL;
 | 
				
			||||||
    int queues;
 | 
					    int queues;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -206,13 +205,14 @@ static void net_vhost_user_event(void *opaque, int event)
 | 
				
			|||||||
    assert(queues < MAX_QUEUE_NUM);
 | 
					    assert(queues < MAX_QUEUE_NUM);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s = DO_UPCAST(VhostUserState, nc, ncs[0]);
 | 
					    s = DO_UPCAST(VhostUserState, nc, ncs[0]);
 | 
				
			||||||
    trace_vhost_user_event(s->chr->label, event);
 | 
					    chr = qemu_chr_fe_get_driver(&s->chr);
 | 
				
			||||||
 | 
					    trace_vhost_user_event(chr->label, event);
 | 
				
			||||||
    switch (event) {
 | 
					    switch (event) {
 | 
				
			||||||
    case CHR_EVENT_OPENED:
 | 
					    case CHR_EVENT_OPENED:
 | 
				
			||||||
        s->watch = qemu_chr_fe_add_watch(s->chr, G_IO_HUP,
 | 
					        s->watch = qemu_chr_fe_add_watch(&s->chr, G_IO_HUP,
 | 
				
			||||||
                                         net_vhost_user_watch, s);
 | 
					                                         net_vhost_user_watch, s);
 | 
				
			||||||
        if (vhost_user_start(queues, ncs) < 0) {
 | 
					        if (vhost_user_start(queues, ncs, &s->chr) < 0) {
 | 
				
			||||||
            qemu_chr_disconnect(s->chr);
 | 
					            qemu_chr_fe_disconnect(&s->chr);
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        qmp_set_link(name, true, &err);
 | 
					        qmp_set_link(name, true, &err);
 | 
				
			||||||
@ -235,6 +235,7 @@ static int net_vhost_user_init(NetClientState *peer, const char *device,
 | 
				
			|||||||
                               const char *name, CharDriverState *chr,
 | 
					                               const char *name, CharDriverState *chr,
 | 
				
			||||||
                               int queues)
 | 
					                               int queues)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    Error *err = NULL;
 | 
				
			||||||
    NetClientState *nc, *nc0 = NULL;
 | 
					    NetClientState *nc, *nc0 = NULL;
 | 
				
			||||||
    VhostUserState *s;
 | 
					    VhostUserState *s;
 | 
				
			||||||
    int i;
 | 
					    int i;
 | 
				
			||||||
@ -244,28 +245,28 @@ static int net_vhost_user_init(NetClientState *peer, const char *device,
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    for (i = 0; i < queues; i++) {
 | 
					    for (i = 0; i < queues; i++) {
 | 
				
			||||||
        nc = qemu_new_net_client(&net_vhost_user_info, peer, device, name);
 | 
					        nc = qemu_new_net_client(&net_vhost_user_info, peer, device, name);
 | 
				
			||||||
        if (!nc0) {
 | 
					 | 
				
			||||||
            nc0 = nc;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user%d to %s",
 | 
					        snprintf(nc->info_str, sizeof(nc->info_str), "vhost-user%d to %s",
 | 
				
			||||||
                 i, chr->label);
 | 
					                 i, chr->label);
 | 
				
			||||||
 | 
					 | 
				
			||||||
        nc->queue_index = i;
 | 
					        nc->queue_index = i;
 | 
				
			||||||
 | 
					        if (!nc0) {
 | 
				
			||||||
 | 
					            nc0 = nc;
 | 
				
			||||||
            s = DO_UPCAST(VhostUserState, nc, nc);
 | 
					            s = DO_UPCAST(VhostUserState, nc, nc);
 | 
				
			||||||
        s->chr = chr;
 | 
					            if (!qemu_chr_fe_init(&s->chr, chr, &err)) {
 | 
				
			||||||
 | 
					                error_report_err(err);
 | 
				
			||||||
 | 
					                return -1;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    s = DO_UPCAST(VhostUserState, nc, nc0);
 | 
					    s = DO_UPCAST(VhostUserState, nc, nc0);
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
        Error *err = NULL;
 | 
					        if (qemu_chr_fe_wait_connected(&s->chr, &err) < 0) {
 | 
				
			||||||
        if (qemu_chr_wait_connected(chr, &err) < 0) {
 | 
					 | 
				
			||||||
            error_report_err(err);
 | 
					            error_report_err(err);
 | 
				
			||||||
            return -1;
 | 
					            return -1;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        qemu_chr_add_handlers(chr, NULL, NULL,
 | 
					        qemu_chr_fe_set_handlers(&s->chr, NULL, NULL,
 | 
				
			||||||
                              net_vhost_user_event, nc0->name);
 | 
					                                 net_vhost_user_event, nc0->name, NULL, true);
 | 
				
			||||||
    } while (!s->started);
 | 
					    } while (!s->started);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert(s->vhost_net);
 | 
					    assert(s->vhost_net);
 | 
				
			||||||
@ -294,8 +295,6 @@ static CharDriverState *net_vhost_claim_chardev(
 | 
				
			|||||||
        return NULL;
 | 
					        return NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qemu_chr_fe_claim_no_fail(chr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return chr;
 | 
					    return chr;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										608
									
								
								qemu-char.c
									
									
									
									
									
								
							
							
						
						
									
										608
									
								
								qemu-char.c
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@ -44,7 +44,7 @@
 | 
				
			|||||||
#include <getopt.h>
 | 
					#include <getopt.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define QEMU_IMG_VERSION "qemu-img version " QEMU_VERSION QEMU_PKGVERSION \
 | 
					#define QEMU_IMG_VERSION "qemu-img version " QEMU_VERSION QEMU_PKGVERSION \
 | 
				
			||||||
                          ", " QEMU_COPYRIGHT "\n"
 | 
					                          "\n" QEMU_COPYRIGHT "\n"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct img_cmd_t {
 | 
					typedef struct img_cmd_t {
 | 
				
			||||||
    const char *name;
 | 
					    const char *name;
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										29
									
								
								qtest.c
									
									
									
									
									
								
							
							
						
						
									
										29
									
								
								qtest.c
									
									
									
									
									
								
							@ -38,7 +38,7 @@ bool qtest_allowed;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static DeviceState *irq_intercept_dev;
 | 
					static DeviceState *irq_intercept_dev;
 | 
				
			||||||
static FILE *qtest_log_fp;
 | 
					static FILE *qtest_log_fp;
 | 
				
			||||||
static CharDriverState *qtest_chr;
 | 
					static CharBackend qtest_chr;
 | 
				
			||||||
static GString *inbuf;
 | 
					static GString *inbuf;
 | 
				
			||||||
static int irq_levels[MAX_IRQ];
 | 
					static int irq_levels[MAX_IRQ];
 | 
				
			||||||
static qemu_timeval start_time;
 | 
					static qemu_timeval start_time;
 | 
				
			||||||
@ -190,7 +190,7 @@ static void qtest_get_time(qemu_timeval *tv)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void qtest_send_prefix(CharDriverState *chr)
 | 
					static void qtest_send_prefix(CharBackend *chr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    qemu_timeval tv;
 | 
					    qemu_timeval tv;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -218,7 +218,7 @@ static void GCC_FMT_ATTR(1, 2) qtest_log_send(const char *fmt, ...)
 | 
				
			|||||||
    va_end(ap);
 | 
					    va_end(ap);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void do_qtest_send(CharDriverState *chr, const char *str, size_t len)
 | 
					static void do_qtest_send(CharBackend *chr, const char *str, size_t len)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    qemu_chr_fe_write_all(chr, (uint8_t *)str, len);
 | 
					    qemu_chr_fe_write_all(chr, (uint8_t *)str, len);
 | 
				
			||||||
    if (qtest_log_fp && qtest_opened) {
 | 
					    if (qtest_log_fp && qtest_opened) {
 | 
				
			||||||
@ -226,12 +226,12 @@ static void do_qtest_send(CharDriverState *chr, const char *str, size_t len)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void qtest_send(CharDriverState *chr, const char *str)
 | 
					static void qtest_send(CharBackend *chr, const char *str)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    do_qtest_send(chr, str, strlen(str));
 | 
					    do_qtest_send(chr, str, strlen(str));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void GCC_FMT_ATTR(2, 3) qtest_sendf(CharDriverState *chr,
 | 
					static void GCC_FMT_ATTR(2, 3) qtest_sendf(CharBackend *chr,
 | 
				
			||||||
                                           const char *fmt, ...)
 | 
					                                           const char *fmt, ...)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    va_list ap;
 | 
					    va_list ap;
 | 
				
			||||||
@ -249,7 +249,7 @@ static void qtest_irq_handler(void *opaque, int n, int level)
 | 
				
			|||||||
    qemu_set_irq(old_irq, level);
 | 
					    qemu_set_irq(old_irq, level);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (irq_levels[n] != level) {
 | 
					    if (irq_levels[n] != level) {
 | 
				
			||||||
        CharDriverState *chr = qtest_chr;
 | 
					        CharBackend *chr = &qtest_chr;
 | 
				
			||||||
        irq_levels[n] = level;
 | 
					        irq_levels[n] = level;
 | 
				
			||||||
        qtest_send_prefix(chr);
 | 
					        qtest_send_prefix(chr);
 | 
				
			||||||
        qtest_sendf(chr, "IRQ %s %d\n",
 | 
					        qtest_sendf(chr, "IRQ %s %d\n",
 | 
				
			||||||
@ -257,7 +257,7 @@ static void qtest_irq_handler(void *opaque, int n, int level)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void qtest_process_command(CharDriverState *chr, gchar **words)
 | 
					static void qtest_process_command(CharBackend *chr, gchar **words)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const gchar *command;
 | 
					    const gchar *command;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -585,7 +585,7 @@ static void qtest_process_command(CharDriverState *chr, gchar **words)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void qtest_process_inbuf(CharDriverState *chr, GString *inbuf)
 | 
					static void qtest_process_inbuf(CharBackend *chr, GString *inbuf)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    char *end;
 | 
					    char *end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -609,7 +609,7 @@ static void qtest_process_inbuf(CharDriverState *chr, GString *inbuf)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void qtest_read(void *opaque, const uint8_t *buf, int size)
 | 
					static void qtest_read(void *opaque, const uint8_t *buf, int size)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    CharDriverState *chr = opaque;
 | 
					    CharBackend *chr = opaque;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    g_string_append_len(inbuf, (const gchar *)buf, size);
 | 
					    g_string_append_len(inbuf, (const gchar *)buf, size);
 | 
				
			||||||
    qtest_process_inbuf(chr, inbuf);
 | 
					    qtest_process_inbuf(chr, inbuf);
 | 
				
			||||||
@ -670,7 +670,7 @@ void qtest_init(const char *qtest_chrdev, const char *qtest_log, Error **errp)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    CharDriverState *chr;
 | 
					    CharDriverState *chr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    chr = qemu_chr_new("qtest", qtest_chrdev, NULL);
 | 
					    chr = qemu_chr_new("qtest", qtest_chrdev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (chr == NULL) {
 | 
					    if (chr == NULL) {
 | 
				
			||||||
        error_setg(errp, "Failed to initialize device for qtest: \"%s\"",
 | 
					        error_setg(errp, "Failed to initialize device for qtest: \"%s\"",
 | 
				
			||||||
@ -686,16 +686,17 @@ void qtest_init(const char *qtest_chrdev, const char *qtest_log, Error **errp)
 | 
				
			|||||||
        qtest_log_fp = stderr;
 | 
					        qtest_log_fp = stderr;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qemu_chr_add_handlers(chr, qtest_can_read, qtest_read, qtest_event, chr);
 | 
					    qemu_chr_fe_init(&qtest_chr, chr, errp);
 | 
				
			||||||
    qemu_chr_fe_set_echo(chr, true);
 | 
					    qemu_chr_fe_set_handlers(&qtest_chr, qtest_can_read, qtest_read,
 | 
				
			||||||
 | 
					                             qtest_event, &qtest_chr, NULL, true);
 | 
				
			||||||
 | 
					    qemu_chr_fe_set_echo(&qtest_chr, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    inbuf = g_string_new("");
 | 
					    inbuf = g_string_new("");
 | 
				
			||||||
    qtest_chr = chr;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool qtest_driver(void)
 | 
					bool qtest_driver(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return qtest_chr;
 | 
					    return qtest_chr.chr != NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void qtest_accel_class_init(ObjectClass *oc, void *data)
 | 
					static void qtest_accel_class_init(ObjectClass *oc, void *data)
 | 
				
			||||||
 | 
				
			|||||||
@ -199,7 +199,7 @@ static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
 | 
				
			|||||||
    return read_bytes;
 | 
					    return read_bytes;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void spice_chr_close(struct CharDriverState *chr)
 | 
					static void spice_chr_free(struct CharDriverState *chr)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    SpiceCharDriver *s = chr->opaque;
 | 
					    SpiceCharDriver *s = chr->opaque;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -236,15 +236,6 @@ static void spice_port_set_fe_open(struct CharDriverState *chr, int fe_open)
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void spice_chr_fe_event(struct CharDriverState *chr, int event)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
#if SPICE_SERVER_VERSION >= 0x000c02
 | 
					 | 
				
			||||||
    SpiceCharDriver *s = chr->opaque;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    spice_server_port_event(&s->sin, event);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void print_allowed_subtypes(void)
 | 
					static void print_allowed_subtypes(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    const char** psubtype;
 | 
					    const char** psubtype;
 | 
				
			||||||
@ -289,10 +280,8 @@ static CharDriverState *chr_open(const char *subtype,
 | 
				
			|||||||
    chr->opaque = s;
 | 
					    chr->opaque = s;
 | 
				
			||||||
    chr->chr_write = spice_chr_write;
 | 
					    chr->chr_write = spice_chr_write;
 | 
				
			||||||
    chr->chr_add_watch = spice_chr_add_watch;
 | 
					    chr->chr_add_watch = spice_chr_add_watch;
 | 
				
			||||||
    chr->chr_close = spice_chr_close;
 | 
					    chr->chr_free = spice_chr_free;
 | 
				
			||||||
    chr->chr_set_fe_open = set_fe_open;
 | 
					    chr->chr_set_fe_open = set_fe_open;
 | 
				
			||||||
    chr->explicit_be_open = true;
 | 
					 | 
				
			||||||
    chr->chr_fe_event = spice_chr_fe_event;
 | 
					 | 
				
			||||||
    chr->chr_accept_input = spice_chr_accept_input;
 | 
					    chr->chr_accept_input = spice_chr_accept_input;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    QLIST_INSERT_HEAD(&spice_chars, s, next);
 | 
					    QLIST_INSERT_HEAD(&spice_chars, s, next);
 | 
				
			||||||
@ -303,6 +292,7 @@ static CharDriverState *chr_open(const char *subtype,
 | 
				
			|||||||
static CharDriverState *qemu_chr_open_spice_vmc(const char *id,
 | 
					static CharDriverState *qemu_chr_open_spice_vmc(const char *id,
 | 
				
			||||||
                                                ChardevBackend *backend,
 | 
					                                                ChardevBackend *backend,
 | 
				
			||||||
                                                ChardevReturn *ret,
 | 
					                                                ChardevReturn *ret,
 | 
				
			||||||
 | 
					                                                bool *be_opened,
 | 
				
			||||||
                                                Error **errp)
 | 
					                                                Error **errp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    ChardevSpiceChannel *spicevmc = backend->u.spicevmc.data;
 | 
					    ChardevSpiceChannel *spicevmc = backend->u.spicevmc.data;
 | 
				
			||||||
@ -321,6 +311,7 @@ static CharDriverState *qemu_chr_open_spice_vmc(const char *id,
 | 
				
			|||||||
        return NULL;
 | 
					        return NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    *be_opened = false;
 | 
				
			||||||
    return chr_open(type, spice_vmc_set_fe_open, common, errp);
 | 
					    return chr_open(type, spice_vmc_set_fe_open, common, errp);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -328,6 +319,7 @@ static CharDriverState *qemu_chr_open_spice_vmc(const char *id,
 | 
				
			|||||||
static CharDriverState *qemu_chr_open_spice_port(const char *id,
 | 
					static CharDriverState *qemu_chr_open_spice_port(const char *id,
 | 
				
			||||||
                                                 ChardevBackend *backend,
 | 
					                                                 ChardevBackend *backend,
 | 
				
			||||||
                                                 ChardevReturn *ret,
 | 
					                                                 ChardevReturn *ret,
 | 
				
			||||||
 | 
					                                                 bool *be_opened,
 | 
				
			||||||
                                                 Error **errp)
 | 
					                                                 Error **errp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    ChardevSpicePort *spiceport = backend->u.spiceport.data;
 | 
					    ChardevSpicePort *spiceport = backend->u.spiceport.data;
 | 
				
			||||||
@ -345,6 +337,7 @@ static CharDriverState *qemu_chr_open_spice_port(const char *id,
 | 
				
			|||||||
    if (!chr) {
 | 
					    if (!chr) {
 | 
				
			||||||
        return NULL;
 | 
					        return NULL;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    *be_opened = false;
 | 
				
			||||||
    s = chr->opaque;
 | 
					    s = chr->opaque;
 | 
				
			||||||
    s->sin.portname = g_strdup(name);
 | 
					    s->sin.portname = g_strdup(name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -457,14 +457,13 @@ static void gen_lea_v_seg(DisasContext *s, TCGMemOp aflag, TCGv a0,
 | 
				
			|||||||
#endif
 | 
					#endif
 | 
				
			||||||
    case MO_32:
 | 
					    case MO_32:
 | 
				
			||||||
        /* 32 bit address */
 | 
					        /* 32 bit address */
 | 
				
			||||||
        if (ovr_seg < 0) {
 | 
					        if (ovr_seg < 0 && s->addseg) {
 | 
				
			||||||
            if (s->addseg) {
 | 
					 | 
				
			||||||
            ovr_seg = def_seg;
 | 
					            ovr_seg = def_seg;
 | 
				
			||||||
            } else {
 | 
					        }
 | 
				
			||||||
 | 
					        if (ovr_seg < 0) {
 | 
				
			||||||
            tcg_gen_ext32u_tl(cpu_A0, a0);
 | 
					            tcg_gen_ext32u_tl(cpu_A0, a0);
 | 
				
			||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
    case MO_16:
 | 
					    case MO_16:
 | 
				
			||||||
        /* 16 bit address */
 | 
					        /* 16 bit address */
 | 
				
			||||||
@ -5372,7 +5371,8 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
 | 
				
			|||||||
        {
 | 
					        {
 | 
				
			||||||
            AddressParts a = gen_lea_modrm_0(env, s, modrm);
 | 
					            AddressParts a = gen_lea_modrm_0(env, s, modrm);
 | 
				
			||||||
            TCGv ea = gen_lea_modrm_1(a);
 | 
					            TCGv ea = gen_lea_modrm_1(a);
 | 
				
			||||||
            gen_op_mov_reg_v(dflag, reg, ea);
 | 
					            gen_lea_v_seg(s, s->aflag, ea, -1, -1);
 | 
				
			||||||
 | 
					            gen_op_mov_reg_v(dflag, reg, cpu_A0);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										56
									
								
								tcg/tcg.c
									
									
									
									
									
								
							
							
						
						
									
										56
									
								
								tcg/tcg.c
									
									
									
									
									
								
							@ -2097,15 +2097,9 @@ static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
 | 
				
			|||||||
    save_globals(s, allocated_regs);
 | 
					    save_globals(s, allocated_regs);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args,
 | 
					static void tcg_reg_alloc_do_movi(TCGContext *s, TCGTemp *ots,
 | 
				
			||||||
                               TCGLifeData arg_life)
 | 
					                                  tcg_target_ulong val, TCGLifeData arg_life)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    TCGTemp *ots;
 | 
					 | 
				
			||||||
    tcg_target_ulong val;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    ots = &s->temps[args[0]];
 | 
					 | 
				
			||||||
    val = args[1];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (ots->fixed_reg) {
 | 
					    if (ots->fixed_reg) {
 | 
				
			||||||
        /* For fixed registers, we do not do any constant propagation.  */
 | 
					        /* For fixed registers, we do not do any constant propagation.  */
 | 
				
			||||||
        tcg_out_movi(s, ots->type, ots->reg, val);
 | 
					        tcg_out_movi(s, ots->type, ots->reg, val);
 | 
				
			||||||
@ -2126,6 +2120,15 @@ static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args,
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args,
 | 
				
			||||||
 | 
					                               TCGLifeData arg_life)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    TCGTemp *ots = &s->temps[args[0]];
 | 
				
			||||||
 | 
					    tcg_target_ulong val = args[1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tcg_reg_alloc_do_movi(s, ots, val, arg_life);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
 | 
					static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
 | 
				
			||||||
                              const TCGArg *args, TCGLifeData arg_life)
 | 
					                              const TCGArg *args, TCGLifeData arg_life)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@ -2141,21 +2144,29 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
 | 
				
			|||||||
    otype = ots->type;
 | 
					    otype = ots->type;
 | 
				
			||||||
    itype = ts->type;
 | 
					    itype = ts->type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* If the source value is not in a register, and we're going to be
 | 
					    if (ts->val_type == TEMP_VAL_CONST) {
 | 
				
			||||||
       forced to have it in a register in order to perform the copy,
 | 
					        /* propagate constant or generate sti */
 | 
				
			||||||
       then copy the SOURCE value into its own register first.  That way
 | 
					        tcg_target_ulong val = ts->val;
 | 
				
			||||||
       we don't have to reload SOURCE the next time it is used. */
 | 
					        if (IS_DEAD_ARG(1)) {
 | 
				
			||||||
    if (((NEED_SYNC_ARG(0) || ots->fixed_reg) && ts->val_type != TEMP_VAL_REG)
 | 
					            temp_dead(s, ts);
 | 
				
			||||||
        || ts->val_type == TEMP_VAL_MEM) {
 | 
					        }
 | 
				
			||||||
 | 
					        tcg_reg_alloc_do_movi(s, ots, val, arg_life);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* If the source value is in memory we're going to be forced
 | 
				
			||||||
 | 
					       to have it in a register in order to perform the copy.  Copy
 | 
				
			||||||
 | 
					       the SOURCE value into its own register first, that way we
 | 
				
			||||||
 | 
					       don't have to reload SOURCE the next time it is used. */
 | 
				
			||||||
 | 
					    if (ts->val_type == TEMP_VAL_MEM) {
 | 
				
			||||||
        temp_load(s, ts, tcg_target_available_regs[itype], allocated_regs);
 | 
					        temp_load(s, ts, tcg_target_available_regs[itype], allocated_regs);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    tcg_debug_assert(ts->val_type == TEMP_VAL_REG);
 | 
				
			||||||
    if (IS_DEAD_ARG(0) && !ots->fixed_reg) {
 | 
					    if (IS_DEAD_ARG(0) && !ots->fixed_reg) {
 | 
				
			||||||
        /* mov to a non-saved dead register makes no sense (even with
 | 
					        /* mov to a non-saved dead register makes no sense (even with
 | 
				
			||||||
           liveness analysis disabled). */
 | 
					           liveness analysis disabled). */
 | 
				
			||||||
        tcg_debug_assert(NEED_SYNC_ARG(0));
 | 
					        tcg_debug_assert(NEED_SYNC_ARG(0));
 | 
				
			||||||
        /* The code above should have moved the temp to a register. */
 | 
					 | 
				
			||||||
        tcg_debug_assert(ts->val_type == TEMP_VAL_REG);
 | 
					 | 
				
			||||||
        if (!ots->mem_allocated) {
 | 
					        if (!ots->mem_allocated) {
 | 
				
			||||||
            temp_allocate_frame(s, args[0]);
 | 
					            temp_allocate_frame(s, args[0]);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -2164,20 +2175,7 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
 | 
				
			|||||||
            temp_dead(s, ts);
 | 
					            temp_dead(s, ts);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        temp_dead(s, ots);
 | 
					        temp_dead(s, ots);
 | 
				
			||||||
    } else if (ts->val_type == TEMP_VAL_CONST) {
 | 
					 | 
				
			||||||
        /* propagate constant */
 | 
					 | 
				
			||||||
        if (ots->val_type == TEMP_VAL_REG) {
 | 
					 | 
				
			||||||
            s->reg_to_temp[ots->reg] = NULL;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        ots->val_type = TEMP_VAL_CONST;
 | 
					 | 
				
			||||||
        ots->val = ts->val;
 | 
					 | 
				
			||||||
        if (IS_DEAD_ARG(1)) {
 | 
					 | 
				
			||||||
            temp_dead(s, ts);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        /* The code in the first if block should have moved the
 | 
					 | 
				
			||||||
           temp to a register. */
 | 
					 | 
				
			||||||
        tcg_debug_assert(ts->val_type == TEMP_VAL_REG);
 | 
					 | 
				
			||||||
        if (IS_DEAD_ARG(1) && !ts->fixed_reg && !ots->fixed_reg) {
 | 
					        if (IS_DEAD_ARG(1) && !ts->fixed_reg && !ots->fixed_reg) {
 | 
				
			||||||
            /* the mov can be suppressed */
 | 
					            /* the mov can be suppressed */
 | 
				
			||||||
            if (ots->val_type == TEMP_VAL_REG) {
 | 
					            if (ots->val_type == TEMP_VAL_REG) {
 | 
				
			||||||
 | 
				
			|||||||
@ -8,6 +8,8 @@ SYSEMU_TARGET_LIST := $(subst -softmmu.mak,,$(notdir \
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
check-unit-y = tests/check-qdict$(EXESUF)
 | 
					check-unit-y = tests/check-qdict$(EXESUF)
 | 
				
			||||||
gcov-files-check-qdict-y = qobject/qdict.c
 | 
					gcov-files-check-qdict-y = qobject/qdict.c
 | 
				
			||||||
 | 
					check-unit-y = tests/test-char$(EXESUF)
 | 
				
			||||||
 | 
					gcov-files-check-qdict-y = qemu-char.c
 | 
				
			||||||
check-unit-y += tests/check-qfloat$(EXESUF)
 | 
					check-unit-y += tests/check-qfloat$(EXESUF)
 | 
				
			||||||
gcov-files-check-qfloat-y = qobject/qfloat.c
 | 
					gcov-files-check-qfloat-y = qobject/qfloat.c
 | 
				
			||||||
check-unit-y += tests/check-qint$(EXESUF)
 | 
					check-unit-y += tests/check-qint$(EXESUF)
 | 
				
			||||||
@ -481,6 +483,8 @@ tests/check-qnull$(EXESUF): tests/check-qnull.o $(test-util-obj-y)
 | 
				
			|||||||
tests/check-qjson$(EXESUF): tests/check-qjson.o $(test-util-obj-y)
 | 
					tests/check-qjson$(EXESUF): tests/check-qjson.o $(test-util-obj-y)
 | 
				
			||||||
tests/check-qom-interface$(EXESUF): tests/check-qom-interface.o $(test-qom-obj-y)
 | 
					tests/check-qom-interface$(EXESUF): tests/check-qom-interface.o $(test-qom-obj-y)
 | 
				
			||||||
tests/check-qom-proplist$(EXESUF): tests/check-qom-proplist.o $(test-qom-obj-y)
 | 
					tests/check-qom-proplist$(EXESUF): tests/check-qom-proplist.o $(test-qom-obj-y)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					tests/test-char$(EXESUF): tests/test-char.o qemu-char.o qemu-timer.o $(test-util-obj-y) $(qtest-obj-y) $(test-io-obj-y)
 | 
				
			||||||
tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(test-block-obj-y)
 | 
					tests/test-coroutine$(EXESUF): tests/test-coroutine.o $(test-block-obj-y)
 | 
				
			||||||
tests/test-aio$(EXESUF): tests/test-aio.o $(test-block-obj-y)
 | 
					tests/test-aio$(EXESUF): tests/test-aio.o $(test-block-obj-y)
 | 
				
			||||||
tests/test-rfifolock$(EXESUF): tests/test-rfifolock.o $(test-util-obj-y)
 | 
					tests/test-rfifolock$(EXESUF): tests/test-rfifolock.o $(test-util-obj-y)
 | 
				
			||||||
 | 
				
			|||||||
@ -193,7 +193,7 @@ static void *thread_func(void *p)
 | 
				
			|||||||
    rcu_register_thread();
 | 
					    rcu_register_thread();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    atomic_inc(&n_ready_threads);
 | 
					    atomic_inc(&n_ready_threads);
 | 
				
			||||||
    while (!atomic_mb_read(&test_start)) {
 | 
					    while (!atomic_read(&test_start)) {
 | 
				
			||||||
        cpu_relax();
 | 
					        cpu_relax();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -393,11 +393,11 @@ static void run_test(void)
 | 
				
			|||||||
    while (atomic_read(&n_ready_threads) != n_rw_threads + n_rz_threads) {
 | 
					    while (atomic_read(&n_ready_threads) != n_rw_threads + n_rz_threads) {
 | 
				
			||||||
        cpu_relax();
 | 
					        cpu_relax();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    atomic_mb_set(&test_start, true);
 | 
					    atomic_set(&test_start, true);
 | 
				
			||||||
    do {
 | 
					    do {
 | 
				
			||||||
        remaining = sleep(duration);
 | 
					        remaining = sleep(duration);
 | 
				
			||||||
    } while (remaining);
 | 
					    } while (remaining);
 | 
				
			||||||
    atomic_mb_set(&test_stop, true);
 | 
					    atomic_set(&test_stop, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (i = 0; i < n_rw_threads; i++) {
 | 
					    for (i = 0; i < n_rw_threads; i++) {
 | 
				
			||||||
        qemu_thread_join(&rw_threads[i]);
 | 
					        qemu_thread_join(&rw_threads[i]);
 | 
				
			||||||
 | 
				
			|||||||
@ -2250,14 +2250,14 @@ SSE_OP(a ## sd);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#define SSE_COMI(op, field)\
 | 
					#define SSE_COMI(op, field)\
 | 
				
			||||||
{\
 | 
					{\
 | 
				
			||||||
    unsigned int eflags;\
 | 
					    unsigned long eflags;\
 | 
				
			||||||
    XMMReg a, b;\
 | 
					    XMMReg a, b;\
 | 
				
			||||||
    a.field[0] = a1;\
 | 
					    a.field[0] = a1;\
 | 
				
			||||||
    b.field[0] = b1;\
 | 
					    b.field[0] = b1;\
 | 
				
			||||||
    asm volatile (#op " %2, %1\n"\
 | 
					    asm volatile (#op " %2, %1\n"\
 | 
				
			||||||
        "pushf\n"\
 | 
					        "pushf\n"\
 | 
				
			||||||
        "pop %0\n"\
 | 
					        "pop %0\n"\
 | 
				
			||||||
        : "=m" (eflags)\
 | 
					        : "=rm" (eflags)\
 | 
				
			||||||
        : "x" (a.dq), "x" (b.dq));\
 | 
					        : "x" (a.dq), "x" (b.dq));\
 | 
				
			||||||
    printf("%-9s: a=%f b=%f cc=%04x\n",\
 | 
					    printf("%-9s: a=%f b=%f cc=%04x\n",\
 | 
				
			||||||
           #op, a1, b1,\
 | 
					           #op, a1, b1,\
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										253
									
								
								tests/test-char.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										253
									
								
								tests/test-char.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,253 @@
 | 
				
			|||||||
 | 
					#include "qemu/osdep.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "qemu-common.h"
 | 
				
			||||||
 | 
					#include "qemu/config-file.h"
 | 
				
			||||||
 | 
					#include "sysemu/char.h"
 | 
				
			||||||
 | 
					#include "sysemu/sysemu.h"
 | 
				
			||||||
 | 
					#include "qapi/error.h"
 | 
				
			||||||
 | 
					#include "qmp-commands.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typedef struct FeHandler {
 | 
				
			||||||
 | 
					    int read_count;
 | 
				
			||||||
 | 
					    int last_event;
 | 
				
			||||||
 | 
					    char read_buf[128];
 | 
				
			||||||
 | 
					} FeHandler;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int fe_can_read(void *opaque)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    FeHandler *h = opaque;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return sizeof(h->read_buf) - h->read_count;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void fe_read(void *opaque, const uint8_t *buf, int size)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    FeHandler *h = opaque;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g_assert_cmpint(size, <=, fe_can_read(opaque));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    memcpy(h->read_buf + h->read_count, buf, size);
 | 
				
			||||||
 | 
					    h->read_count += size;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void fe_event(void *opaque, int event)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    FeHandler *h = opaque;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    h->last_event = event;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifdef CONFIG_HAS_GLIB_SUBPROCESS_TESTS
 | 
				
			||||||
 | 
					static void char_stdio_test_subprocess(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    CharDriverState *chr;
 | 
				
			||||||
 | 
					    CharBackend be;
 | 
				
			||||||
 | 
					    int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    chr = qemu_chr_new("label", "stdio");
 | 
				
			||||||
 | 
					    g_assert_nonnull(chr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qemu_chr_fe_init(&be, chr, &error_abort);
 | 
				
			||||||
 | 
					    qemu_chr_fe_set_open(&be, true);
 | 
				
			||||||
 | 
					    ret = qemu_chr_fe_write(&be, (void *)"buf", 4);
 | 
				
			||||||
 | 
					    g_assert_cmpint(ret, ==, 4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qemu_chr_fe_deinit(&be);
 | 
				
			||||||
 | 
					    qemu_chr_delete(chr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void char_stdio_test(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    g_test_trap_subprocess("/char/stdio/subprocess", 0, 0);
 | 
				
			||||||
 | 
					    g_test_trap_assert_passed();
 | 
				
			||||||
 | 
					    g_test_trap_assert_stdout("buf");
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void char_ringbuf_test(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    QemuOpts *opts;
 | 
				
			||||||
 | 
					    CharDriverState *chr;
 | 
				
			||||||
 | 
					    CharBackend be;
 | 
				
			||||||
 | 
					    char *data;
 | 
				
			||||||
 | 
					    int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    opts = qemu_opts_create(qemu_find_opts("chardev"), "ringbuf-label",
 | 
				
			||||||
 | 
					                            1, &error_abort);
 | 
				
			||||||
 | 
					    qemu_opt_set(opts, "backend", "ringbuf", &error_abort);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qemu_opt_set(opts, "size", "5", &error_abort);
 | 
				
			||||||
 | 
					    chr = qemu_chr_new_from_opts(opts, NULL);
 | 
				
			||||||
 | 
					    g_assert_null(chr);
 | 
				
			||||||
 | 
					    qemu_opts_del(opts);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    opts = qemu_opts_create(qemu_find_opts("chardev"), "ringbuf-label",
 | 
				
			||||||
 | 
					                            1, &error_abort);
 | 
				
			||||||
 | 
					    qemu_opt_set(opts, "backend", "ringbuf", &error_abort);
 | 
				
			||||||
 | 
					    qemu_opt_set(opts, "size", "2", &error_abort);
 | 
				
			||||||
 | 
					    chr = qemu_chr_new_from_opts(opts, &error_abort);
 | 
				
			||||||
 | 
					    g_assert_nonnull(chr);
 | 
				
			||||||
 | 
					    qemu_opts_del(opts);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qemu_chr_fe_init(&be, chr, &error_abort);
 | 
				
			||||||
 | 
					    ret = qemu_chr_fe_write(&be, (void *)"buff", 4);
 | 
				
			||||||
 | 
					    g_assert_cmpint(ret, ==, 4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    data = qmp_ringbuf_read("ringbuf-label", 4, false, 0, &error_abort);
 | 
				
			||||||
 | 
					    g_assert_cmpstr(data, ==, "ff");
 | 
				
			||||||
 | 
					    g_free(data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    data = qmp_ringbuf_read("ringbuf-label", 4, false, 0, &error_abort);
 | 
				
			||||||
 | 
					    g_assert_cmpstr(data, ==, "");
 | 
				
			||||||
 | 
					    g_free(data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qemu_chr_fe_deinit(&be);
 | 
				
			||||||
 | 
					    qemu_chr_delete(chr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void char_mux_test(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    QemuOpts *opts;
 | 
				
			||||||
 | 
					    CharDriverState *chr, *base;
 | 
				
			||||||
 | 
					    char *data;
 | 
				
			||||||
 | 
					    FeHandler h1 = { 0, }, h2 = { 0, };
 | 
				
			||||||
 | 
					    CharBackend chr_be1, chr_be2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    opts = qemu_opts_create(qemu_find_opts("chardev"), "mux-label",
 | 
				
			||||||
 | 
					                            1, &error_abort);
 | 
				
			||||||
 | 
					    qemu_opt_set(opts, "backend", "ringbuf", &error_abort);
 | 
				
			||||||
 | 
					    qemu_opt_set(opts, "size", "128", &error_abort);
 | 
				
			||||||
 | 
					    qemu_opt_set(opts, "mux", "on", &error_abort);
 | 
				
			||||||
 | 
					    chr = qemu_chr_new_from_opts(opts, &error_abort);
 | 
				
			||||||
 | 
					    g_assert_nonnull(chr);
 | 
				
			||||||
 | 
					    qemu_opts_del(opts);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qemu_chr_fe_init(&chr_be1, chr, &error_abort);
 | 
				
			||||||
 | 
					    qemu_chr_fe_set_handlers(&chr_be1,
 | 
				
			||||||
 | 
					                             fe_can_read,
 | 
				
			||||||
 | 
					                             fe_read,
 | 
				
			||||||
 | 
					                             fe_event,
 | 
				
			||||||
 | 
					                             &h1,
 | 
				
			||||||
 | 
					                             NULL, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qemu_chr_fe_init(&chr_be2, chr, &error_abort);
 | 
				
			||||||
 | 
					    qemu_chr_fe_set_handlers(&chr_be2,
 | 
				
			||||||
 | 
					                             fe_can_read,
 | 
				
			||||||
 | 
					                             fe_read,
 | 
				
			||||||
 | 
					                             fe_event,
 | 
				
			||||||
 | 
					                             &h2,
 | 
				
			||||||
 | 
					                             NULL, true);
 | 
				
			||||||
 | 
					    qemu_chr_fe_take_focus(&chr_be2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    base = qemu_chr_find("mux-label-base");
 | 
				
			||||||
 | 
					    g_assert_cmpint(qemu_chr_be_can_write(base), !=, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qemu_chr_be_write(base, (void *)"hello", 6);
 | 
				
			||||||
 | 
					    g_assert_cmpint(h1.read_count, ==, 0);
 | 
				
			||||||
 | 
					    g_assert_cmpint(h2.read_count, ==, 6);
 | 
				
			||||||
 | 
					    g_assert_cmpstr(h2.read_buf, ==, "hello");
 | 
				
			||||||
 | 
					    h2.read_count = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* switch focus */
 | 
				
			||||||
 | 
					    qemu_chr_be_write(base, (void *)"\1c", 2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qemu_chr_be_write(base, (void *)"hello", 6);
 | 
				
			||||||
 | 
					    g_assert_cmpint(h2.read_count, ==, 0);
 | 
				
			||||||
 | 
					    g_assert_cmpint(h1.read_count, ==, 6);
 | 
				
			||||||
 | 
					    g_assert_cmpstr(h1.read_buf, ==, "hello");
 | 
				
			||||||
 | 
					    h1.read_count = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* remove first handler */
 | 
				
			||||||
 | 
					    qemu_chr_fe_set_handlers(&chr_be1, NULL, NULL, NULL, NULL, NULL, true);
 | 
				
			||||||
 | 
					    qemu_chr_be_write(base, (void *)"hello", 6);
 | 
				
			||||||
 | 
					    g_assert_cmpint(h1.read_count, ==, 0);
 | 
				
			||||||
 | 
					    g_assert_cmpint(h2.read_count, ==, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qemu_chr_be_write(base, (void *)"\1c", 2);
 | 
				
			||||||
 | 
					    qemu_chr_be_write(base, (void *)"hello", 6);
 | 
				
			||||||
 | 
					    g_assert_cmpint(h1.read_count, ==, 0);
 | 
				
			||||||
 | 
					    g_assert_cmpint(h2.read_count, ==, 6);
 | 
				
			||||||
 | 
					    g_assert_cmpstr(h2.read_buf, ==, "hello");
 | 
				
			||||||
 | 
					    h2.read_count = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* print help */
 | 
				
			||||||
 | 
					    qemu_chr_be_write(base, (void *)"\1?", 2);
 | 
				
			||||||
 | 
					    data = qmp_ringbuf_read("mux-label-base", 128, false, 0, &error_abort);
 | 
				
			||||||
 | 
					    g_assert_cmpint(strlen(data), !=, 0);
 | 
				
			||||||
 | 
					    g_free(data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qemu_chr_fe_deinit(&chr_be1);
 | 
				
			||||||
 | 
					    qemu_chr_fe_deinit(&chr_be2);
 | 
				
			||||||
 | 
					    qemu_chr_delete(chr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void char_null_test(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    Error *err = NULL;
 | 
				
			||||||
 | 
					    CharDriverState *chr;
 | 
				
			||||||
 | 
					    CharBackend be;
 | 
				
			||||||
 | 
					    int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    chr = qemu_chr_find("label-null");
 | 
				
			||||||
 | 
					    g_assert_null(chr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    chr = qemu_chr_new("label-null", "null");
 | 
				
			||||||
 | 
					    chr = qemu_chr_find("label-null");
 | 
				
			||||||
 | 
					    g_assert_nonnull(chr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g_assert(qemu_chr_has_feature(chr,
 | 
				
			||||||
 | 
					                 QEMU_CHAR_FEATURE_FD_PASS) == false);
 | 
				
			||||||
 | 
					    g_assert(qemu_chr_has_feature(chr,
 | 
				
			||||||
 | 
					                 QEMU_CHAR_FEATURE_RECONNECTABLE) == false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* check max avail */
 | 
				
			||||||
 | 
					    qemu_chr_fe_init(&be, chr, &error_abort);
 | 
				
			||||||
 | 
					    qemu_chr_fe_init(&be, chr, &err);
 | 
				
			||||||
 | 
					    error_free_or_abort(&err);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* deinit & reinit */
 | 
				
			||||||
 | 
					    qemu_chr_fe_deinit(&be);
 | 
				
			||||||
 | 
					    qemu_chr_fe_init(&be, chr, &error_abort);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qemu_chr_fe_set_open(&be, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qemu_chr_fe_set_handlers(&be,
 | 
				
			||||||
 | 
					                             fe_can_read,
 | 
				
			||||||
 | 
					                             fe_read,
 | 
				
			||||||
 | 
					                             fe_event,
 | 
				
			||||||
 | 
					                             NULL, NULL, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ret = qemu_chr_fe_write(&be, (void *)"buf", 4);
 | 
				
			||||||
 | 
					    g_assert_cmpint(ret, ==, 4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    qemu_chr_fe_deinit(&be);
 | 
				
			||||||
 | 
					    qemu_chr_delete(chr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void char_invalid_test(void)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    CharDriverState *chr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    chr = qemu_chr_new("label-invalid", "invalid");
 | 
				
			||||||
 | 
					    g_assert_null(chr);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main(int argc, char **argv)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    g_test_init(&argc, &argv, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    module_call_init(MODULE_INIT_QOM);
 | 
				
			||||||
 | 
					    qemu_add_opts(&qemu_chardev_opts);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    g_test_add_func("/char/null", char_null_test);
 | 
				
			||||||
 | 
					    g_test_add_func("/char/invalid", char_invalid_test);
 | 
				
			||||||
 | 
					    g_test_add_func("/char/ringbuf", char_ringbuf_test);
 | 
				
			||||||
 | 
					    g_test_add_func("/char/mux", char_mux_test);
 | 
				
			||||||
 | 
					#ifdef CONFIG_HAS_GLIB_SUBPROCESS_TESTS
 | 
				
			||||||
 | 
					    g_test_add_func("/char/stdio/subprocess", char_stdio_test_subprocess);
 | 
				
			||||||
 | 
					    g_test_add_func("/char/stdio", char_stdio_test);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return g_test_run();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -11,6 +11,7 @@
 | 
				
			|||||||
#include "qemu/osdep.h"
 | 
					#include "qemu/osdep.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "libqtest.h"
 | 
					#include "libqtest.h"
 | 
				
			||||||
 | 
					#include "qapi/error.h"
 | 
				
			||||||
#include "qemu/option.h"
 | 
					#include "qemu/option.h"
 | 
				
			||||||
#include "qemu/range.h"
 | 
					#include "qemu/range.h"
 | 
				
			||||||
#include "qemu/sockets.h"
 | 
					#include "qemu/sockets.h"
 | 
				
			||||||
@ -19,6 +20,7 @@
 | 
				
			|||||||
#include "libqos/libqos.h"
 | 
					#include "libqos/libqos.h"
 | 
				
			||||||
#include "libqos/pci-pc.h"
 | 
					#include "libqos/pci-pc.h"
 | 
				
			||||||
#include "libqos/virtio-pci.h"
 | 
					#include "libqos/virtio-pci.h"
 | 
				
			||||||
 | 
					#include "qapi/error.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "libqos/pci-pc.h"
 | 
					#include "libqos/pci-pc.h"
 | 
				
			||||||
#include "libqos/virtio-pci.h"
 | 
					#include "libqos/virtio-pci.h"
 | 
				
			||||||
@ -141,7 +143,7 @@ typedef struct TestServer {
 | 
				
			|||||||
    gchar *socket_path;
 | 
					    gchar *socket_path;
 | 
				
			||||||
    gchar *mig_path;
 | 
					    gchar *mig_path;
 | 
				
			||||||
    gchar *chr_name;
 | 
					    gchar *chr_name;
 | 
				
			||||||
    CharDriverState *chr;
 | 
					    CharBackend chr;
 | 
				
			||||||
    int fds_num;
 | 
					    int fds_num;
 | 
				
			||||||
    int fds[VHOST_MEMORY_MAX_NREGIONS];
 | 
					    int fds[VHOST_MEMORY_MAX_NREGIONS];
 | 
				
			||||||
    VhostUserMemory memory;
 | 
					    VhostUserMemory memory;
 | 
				
			||||||
@ -261,13 +263,13 @@ static int chr_can_read(void *opaque)
 | 
				
			|||||||
static void chr_read(void *opaque, const uint8_t *buf, int size)
 | 
					static void chr_read(void *opaque, const uint8_t *buf, int size)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    TestServer *s = opaque;
 | 
					    TestServer *s = opaque;
 | 
				
			||||||
    CharDriverState *chr = s->chr;
 | 
					    CharBackend *chr = &s->chr;
 | 
				
			||||||
    VhostUserMsg msg;
 | 
					    VhostUserMsg msg;
 | 
				
			||||||
    uint8_t *p = (uint8_t *) &msg;
 | 
					    uint8_t *p = (uint8_t *) &msg;
 | 
				
			||||||
    int fd;
 | 
					    int fd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (s->test_fail) {
 | 
					    if (s->test_fail) {
 | 
				
			||||||
        qemu_chr_disconnect(chr);
 | 
					        qemu_chr_fe_disconnect(chr);
 | 
				
			||||||
        /* now switch to non-failure */
 | 
					        /* now switch to non-failure */
 | 
				
			||||||
        s->test_fail = false;
 | 
					        s->test_fail = false;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -312,7 +314,7 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
 | 
				
			|||||||
	g_assert_cmpint(msg.payload.u64 & (0x1ULL << VHOST_USER_F_PROTOCOL_FEATURES),
 | 
						g_assert_cmpint(msg.payload.u64 & (0x1ULL << VHOST_USER_F_PROTOCOL_FEATURES),
 | 
				
			||||||
			!=, 0ULL);
 | 
								!=, 0ULL);
 | 
				
			||||||
        if (s->test_flags == TEST_FLAGS_DISCONNECT) {
 | 
					        if (s->test_flags == TEST_FLAGS_DISCONNECT) {
 | 
				
			||||||
            qemu_chr_disconnect(chr);
 | 
					            qemu_chr_fe_disconnect(chr);
 | 
				
			||||||
            s->test_flags = TEST_FLAGS_BAD;
 | 
					            s->test_flags = TEST_FLAGS_BAD;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        break;
 | 
					        break;
 | 
				
			||||||
@ -344,7 +346,8 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
 | 
				
			|||||||
    case VHOST_USER_SET_MEM_TABLE:
 | 
					    case VHOST_USER_SET_MEM_TABLE:
 | 
				
			||||||
        /* received the mem table */
 | 
					        /* received the mem table */
 | 
				
			||||||
        memcpy(&s->memory, &msg.payload.memory, sizeof(msg.payload.memory));
 | 
					        memcpy(&s->memory, &msg.payload.memory, sizeof(msg.payload.memory));
 | 
				
			||||||
        s->fds_num = qemu_chr_fe_get_msgfds(chr, s->fds, G_N_ELEMENTS(s->fds));
 | 
					        s->fds_num = qemu_chr_fe_get_msgfds(chr, s->fds,
 | 
				
			||||||
 | 
					                                            G_N_ELEMENTS(s->fds));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* signal the test that it can continue */
 | 
					        /* signal the test that it can continue */
 | 
				
			||||||
        g_cond_signal(&s->data_cond);
 | 
					        g_cond_signal(&s->data_cond);
 | 
				
			||||||
@ -453,13 +456,15 @@ static void chr_event(void *opaque, int event)
 | 
				
			|||||||
static void test_server_create_chr(TestServer *server, const gchar *opt)
 | 
					static void test_server_create_chr(TestServer *server, const gchar *opt)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    gchar *chr_path;
 | 
					    gchar *chr_path;
 | 
				
			||||||
 | 
					    CharDriverState *chr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    chr_path = g_strdup_printf("unix:%s%s", server->socket_path, opt);
 | 
					    chr_path = g_strdup_printf("unix:%s%s", server->socket_path, opt);
 | 
				
			||||||
    server->chr = qemu_chr_new(server->chr_name, chr_path, NULL);
 | 
					    chr = qemu_chr_new(server->chr_name, chr_path);
 | 
				
			||||||
    g_free(chr_path);
 | 
					    g_free(chr_path);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qemu_chr_add_handlers(server->chr, chr_can_read, chr_read,
 | 
					    qemu_chr_fe_init(&server->chr, chr, &error_abort);
 | 
				
			||||||
                          chr_event, server);
 | 
					    qemu_chr_fe_set_handlers(&server->chr, chr_can_read, chr_read,
 | 
				
			||||||
 | 
					                             chr_event, server, NULL, true);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void test_server_listen(TestServer *server)
 | 
					static void test_server_listen(TestServer *server)
 | 
				
			||||||
@ -483,8 +488,10 @@ static inline void test_server_connect(TestServer *server)
 | 
				
			|||||||
static gboolean _test_server_free(TestServer *server)
 | 
					static gboolean _test_server_free(TestServer *server)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    int i;
 | 
					    int i;
 | 
				
			||||||
 | 
					    CharDriverState *chr = qemu_chr_fe_get_driver(&server->chr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qemu_chr_delete(server->chr);
 | 
					    qemu_chr_fe_deinit(&server->chr);
 | 
				
			||||||
 | 
					    qemu_chr_delete(chr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (i = 0; i < server->fds_num; i++) {
 | 
					    for (i = 0; i < server->fds_num; i++) {
 | 
				
			||||||
        close(server->fds[i]);
 | 
					        close(server->fds[i]);
 | 
				
			||||||
@ -721,7 +728,7 @@ reconnect_cb(gpointer user_data)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    TestServer *s = user_data;
 | 
					    TestServer *s = user_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qemu_chr_disconnect(s->chr);
 | 
					    qemu_chr_fe_disconnect(&s->chr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return FALSE;
 | 
					    return FALSE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										17
									
								
								ui/console.c
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								ui/console.c
									
									
									
									
									
								
							@ -1083,6 +1083,7 @@ static void kbd_send_chars(void *opaque)
 | 
				
			|||||||
void kbd_put_keysym_console(QemuConsole *s, int keysym)
 | 
					void kbd_put_keysym_console(QemuConsole *s, int keysym)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    uint8_t buf[16], *q;
 | 
					    uint8_t buf[16], *q;
 | 
				
			||||||
 | 
					    CharBackend *be;
 | 
				
			||||||
    int c;
 | 
					    int c;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!s || (s->console_type == GRAPHIC_CONSOLE))
 | 
					    if (!s || (s->console_type == GRAPHIC_CONSOLE))
 | 
				
			||||||
@ -1125,7 +1126,8 @@ void kbd_put_keysym_console(QemuConsole *s, int keysym)
 | 
				
			|||||||
        if (s->echo) {
 | 
					        if (s->echo) {
 | 
				
			||||||
            console_puts(s->chr, buf, q - buf);
 | 
					            console_puts(s->chr, buf, q - buf);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        if (s->chr->chr_read) {
 | 
					        be = s->chr->be;
 | 
				
			||||||
 | 
					        if (be && be->chr_read) {
 | 
				
			||||||
            qemu_fifo_write(&s->out_fifo, buf, q - buf);
 | 
					            qemu_fifo_write(&s->out_fifo, buf, q - buf);
 | 
				
			||||||
            kbd_send_chars(s);
 | 
					            kbd_send_chars(s);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -2033,8 +2035,6 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qemu_chr_be_generic_open(chr);
 | 
					    qemu_chr_be_generic_open(chr);
 | 
				
			||||||
    if (chr->init)
 | 
					 | 
				
			||||||
        chr->init(chr);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static CharDriverState *text_console_init(ChardevVC *vc, Error **errp)
 | 
					static CharDriverState *text_console_init(ChardevVC *vc, Error **errp)
 | 
				
			||||||
@ -2079,10 +2079,6 @@ static CharDriverState *text_console_init(ChardevVC *vc, Error **errp)
 | 
				
			|||||||
    s->chr = chr;
 | 
					    s->chr = chr;
 | 
				
			||||||
    chr->opaque = s;
 | 
					    chr->opaque = s;
 | 
				
			||||||
    chr->chr_set_echo = text_console_set_echo;
 | 
					    chr->chr_set_echo = text_console_set_echo;
 | 
				
			||||||
    /* console/chardev init sometimes completes elsewhere in a 2nd
 | 
					 | 
				
			||||||
     * stage, so defer OPENED events until they are fully initialized
 | 
					 | 
				
			||||||
     */
 | 
					 | 
				
			||||||
    chr->explicit_be_open = true;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (display_state) {
 | 
					    if (display_state) {
 | 
				
			||||||
        text_console_do_init(chr, display_state);
 | 
					        text_console_do_init(chr, display_state);
 | 
				
			||||||
@ -2093,8 +2089,13 @@ static CharDriverState *text_console_init(ChardevVC *vc, Error **errp)
 | 
				
			|||||||
static VcHandler *vc_handler = text_console_init;
 | 
					static VcHandler *vc_handler = text_console_init;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static CharDriverState *vc_init(const char *id, ChardevBackend *backend,
 | 
					static CharDriverState *vc_init(const char *id, ChardevBackend *backend,
 | 
				
			||||||
                                ChardevReturn *ret, Error **errp)
 | 
					                                ChardevReturn *ret, bool *be_opened,
 | 
				
			||||||
 | 
					                                Error **errp)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
 | 
					    /* console/chardev init sometimes completes elsewhere in a 2nd
 | 
				
			||||||
 | 
					     * stage, so defer OPENED events until they are fully initialized
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    *be_opened = false;
 | 
				
			||||||
    return vc_handler(backend->u.vc.data, errp);
 | 
					    return vc_handler(backend->u.vc.data, errp);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										6
									
								
								ui/gtk.c
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								ui/gtk.c
									
									
									
									
									
								
							@ -1685,9 +1685,6 @@ static CharDriverState *gd_vc_handler(ChardevVC *vc, Error **errp)
 | 
				
			|||||||
    /* Temporary, until gd_vc_vte_init runs.  */
 | 
					    /* Temporary, until gd_vc_vte_init runs.  */
 | 
				
			||||||
    chr->opaque = g_new0(VirtualConsole, 1);
 | 
					    chr->opaque = g_new0(VirtualConsole, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* defer OPENED events until our vc is fully initialized */
 | 
					 | 
				
			||||||
    chr->explicit_be_open = true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    vcs[nb_vcs++] = chr;
 | 
					    vcs[nb_vcs++] = chr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return chr;
 | 
					    return chr;
 | 
				
			||||||
@ -1789,9 +1786,6 @@ static GSList *gd_vc_vte_init(GtkDisplayState *s, VirtualConsole *vc,
 | 
				
			|||||||
                             gtk_label_new(vc->label));
 | 
					                             gtk_label_new(vc->label));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qemu_chr_be_generic_open(vc->vte.chr);
 | 
					    qemu_chr_be_generic_open(vc->vte.chr);
 | 
				
			||||||
    if (vc->vte.chr->init) {
 | 
					 | 
				
			||||||
        vc->vte.chr->init(vc->vte.chr);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return group;
 | 
					    return group;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -360,7 +360,11 @@ void qemu_event_destroy(QemuEvent *ev)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void qemu_event_set(QemuEvent *ev)
 | 
					void qemu_event_set(QemuEvent *ev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (atomic_mb_read(&ev->value) != EV_SET) {
 | 
					    /* qemu_event_set has release semantics, but because it *loads*
 | 
				
			||||||
 | 
					     * ev->value we need a full memory barrier here.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    smp_mb();
 | 
				
			||||||
 | 
					    if (atomic_read(&ev->value) != EV_SET) {
 | 
				
			||||||
        if (atomic_xchg(&ev->value, EV_SET) == EV_BUSY) {
 | 
					        if (atomic_xchg(&ev->value, EV_SET) == EV_BUSY) {
 | 
				
			||||||
            /* There were waiters, wake them up.  */
 | 
					            /* There were waiters, wake them up.  */
 | 
				
			||||||
            futex_wake(ev, INT_MAX);
 | 
					            futex_wake(ev, INT_MAX);
 | 
				
			||||||
@ -370,7 +374,11 @@ void qemu_event_set(QemuEvent *ev)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void qemu_event_reset(QemuEvent *ev)
 | 
					void qemu_event_reset(QemuEvent *ev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (atomic_mb_read(&ev->value) == EV_SET) {
 | 
					    unsigned value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    value = atomic_read(&ev->value);
 | 
				
			||||||
 | 
					    smp_mb_acquire();
 | 
				
			||||||
 | 
					    if (value == EV_SET) {
 | 
				
			||||||
        /*
 | 
					        /*
 | 
				
			||||||
         * If there was a concurrent reset (or even reset+wait),
 | 
					         * If there was a concurrent reset (or even reset+wait),
 | 
				
			||||||
         * do nothing.  Otherwise change EV_SET->EV_FREE.
 | 
					         * do nothing.  Otherwise change EV_SET->EV_FREE.
 | 
				
			||||||
@ -383,7 +391,8 @@ void qemu_event_wait(QemuEvent *ev)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    unsigned value;
 | 
					    unsigned value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    value = atomic_mb_read(&ev->value);
 | 
					    value = atomic_read(&ev->value);
 | 
				
			||||||
 | 
					    smp_mb_acquire();
 | 
				
			||||||
    if (value != EV_SET) {
 | 
					    if (value != EV_SET) {
 | 
				
			||||||
        if (value == EV_FREE) {
 | 
					        if (value == EV_FREE) {
 | 
				
			||||||
            /*
 | 
					            /*
 | 
				
			||||||
 | 
				
			|||||||
@ -274,7 +274,11 @@ void qemu_event_destroy(QemuEvent *ev)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void qemu_event_set(QemuEvent *ev)
 | 
					void qemu_event_set(QemuEvent *ev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (atomic_mb_read(&ev->value) != EV_SET) {
 | 
					    /* qemu_event_set has release semantics, but because it *loads*
 | 
				
			||||||
 | 
					     * ev->value we need a full memory barrier here.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    smp_mb();
 | 
				
			||||||
 | 
					    if (atomic_read(&ev->value) != EV_SET) {
 | 
				
			||||||
        if (atomic_xchg(&ev->value, EV_SET) == EV_BUSY) {
 | 
					        if (atomic_xchg(&ev->value, EV_SET) == EV_BUSY) {
 | 
				
			||||||
            /* There were waiters, wake them up.  */
 | 
					            /* There were waiters, wake them up.  */
 | 
				
			||||||
            SetEvent(ev->event);
 | 
					            SetEvent(ev->event);
 | 
				
			||||||
@ -284,7 +288,11 @@ void qemu_event_set(QemuEvent *ev)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void qemu_event_reset(QemuEvent *ev)
 | 
					void qemu_event_reset(QemuEvent *ev)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if (atomic_mb_read(&ev->value) == EV_SET) {
 | 
					    unsigned value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    value = atomic_read(&ev->value);
 | 
				
			||||||
 | 
					    smp_mb_acquire();
 | 
				
			||||||
 | 
					    if (value == EV_SET) {
 | 
				
			||||||
        /* If there was a concurrent reset (or even reset+wait),
 | 
					        /* If there was a concurrent reset (or even reset+wait),
 | 
				
			||||||
         * do nothing.  Otherwise change EV_SET->EV_FREE.
 | 
					         * do nothing.  Otherwise change EV_SET->EV_FREE.
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
@ -296,7 +304,8 @@ void qemu_event_wait(QemuEvent *ev)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    unsigned value;
 | 
					    unsigned value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    value = atomic_mb_read(&ev->value);
 | 
					    value = atomic_read(&ev->value);
 | 
				
			||||||
 | 
					    smp_mb_acquire();
 | 
				
			||||||
    if (value != EV_SET) {
 | 
					    if (value != EV_SET) {
 | 
				
			||||||
        if (value == EV_FREE) {
 | 
					        if (value == EV_FREE) {
 | 
				
			||||||
            /* qemu_event_set is not yet going to call SetEvent, but we are
 | 
					            /* qemu_event_set is not yet going to call SetEvent, but we are
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										11
									
								
								util/rcu.c
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								util/rcu.c
									
									
									
									
									
								
							@ -82,14 +82,16 @@ static void wait_for_readers(void)
 | 
				
			|||||||
        /* Instead of using atomic_mb_set for index->waiting, and
 | 
					        /* Instead of using atomic_mb_set for index->waiting, and
 | 
				
			||||||
         * atomic_mb_read for index->ctr, memory barriers are placed
 | 
					         * atomic_mb_read for index->ctr, memory barriers are placed
 | 
				
			||||||
         * manually since writes to different threads are independent.
 | 
					         * manually since writes to different threads are independent.
 | 
				
			||||||
         * atomic_mb_set has a smp_wmb before...
 | 
					         * qemu_event_reset has acquire semantics, so no memory barrier
 | 
				
			||||||
 | 
					         * is needed here.
 | 
				
			||||||
         */
 | 
					         */
 | 
				
			||||||
        smp_wmb();
 | 
					 | 
				
			||||||
        QLIST_FOREACH(index, ®istry, node) {
 | 
					        QLIST_FOREACH(index, ®istry, node) {
 | 
				
			||||||
            atomic_set(&index->waiting, true);
 | 
					            atomic_set(&index->waiting, true);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* ... and a smp_mb after.  */
 | 
					        /* Here, order the stores to index->waiting before the
 | 
				
			||||||
 | 
					         * loads of index->ctr.
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
        smp_mb();
 | 
					        smp_mb();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        QLIST_FOREACH_SAFE(index, ®istry, node, tmp) {
 | 
					        QLIST_FOREACH_SAFE(index, ®istry, node, tmp) {
 | 
				
			||||||
@ -104,9 +106,6 @@ static void wait_for_readers(void)
 | 
				
			|||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /* atomic_mb_read has smp_rmb after.  */
 | 
					 | 
				
			||||||
        smp_rmb();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (QLIST_EMPTY(®istry)) {
 | 
					        if (QLIST_EMPTY(®istry)) {
 | 
				
			||||||
            break;
 | 
					            break;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										15
									
								
								vl.c
									
									
									
									
									
								
							
							
						
						
									
										15
									
								
								vl.c
									
									
									
									
									
								
							@ -1958,7 +1958,7 @@ static void main_loop(void)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
static void version(void)
 | 
					static void version(void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    printf("QEMU emulator version " QEMU_VERSION QEMU_PKGVERSION ", "
 | 
					    printf("QEMU emulator version " QEMU_VERSION QEMU_PKGVERSION "\n"
 | 
				
			||||||
           QEMU_COPYRIGHT "\n");
 | 
					           QEMU_COPYRIGHT "\n");
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -2369,7 +2369,7 @@ static int chardev_init_func(void *opaque, QemuOpts *opts, Error **errp)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    Error *local_err = NULL;
 | 
					    Error *local_err = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qemu_chr_new_from_opts(opts, NULL, &local_err);
 | 
					    qemu_chr_new_from_opts(opts, &local_err);
 | 
				
			||||||
    if (local_err) {
 | 
					    if (local_err) {
 | 
				
			||||||
        error_report_err(local_err);
 | 
					        error_report_err(local_err);
 | 
				
			||||||
        return -1;
 | 
					        return -1;
 | 
				
			||||||
@ -2417,7 +2417,6 @@ static int mon_init_func(void *opaque, QemuOpts *opts, Error **errp)
 | 
				
			|||||||
        exit(1);
 | 
					        exit(1);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    qemu_chr_fe_claim_no_fail(chr);
 | 
					 | 
				
			||||||
    monitor_init(chr, flags);
 | 
					    monitor_init(chr, flags);
 | 
				
			||||||
    return 0;
 | 
					    return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -2514,7 +2513,7 @@ static int serial_parse(const char *devname)
 | 
				
			|||||||
        exit(1);
 | 
					        exit(1);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    snprintf(label, sizeof(label), "serial%d", index);
 | 
					    snprintf(label, sizeof(label), "serial%d", index);
 | 
				
			||||||
    serial_hds[index] = qemu_chr_new(label, devname, NULL);
 | 
					    serial_hds[index] = qemu_chr_new(label, devname);
 | 
				
			||||||
    if (!serial_hds[index]) {
 | 
					    if (!serial_hds[index]) {
 | 
				
			||||||
        error_report("could not connect serial device"
 | 
					        error_report("could not connect serial device"
 | 
				
			||||||
                     " to character backend '%s'", devname);
 | 
					                     " to character backend '%s'", devname);
 | 
				
			||||||
@ -2536,7 +2535,7 @@ static int parallel_parse(const char *devname)
 | 
				
			|||||||
        exit(1);
 | 
					        exit(1);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    snprintf(label, sizeof(label), "parallel%d", index);
 | 
					    snprintf(label, sizeof(label), "parallel%d", index);
 | 
				
			||||||
    parallel_hds[index] = qemu_chr_new(label, devname, NULL);
 | 
					    parallel_hds[index] = qemu_chr_new(label, devname);
 | 
				
			||||||
    if (!parallel_hds[index]) {
 | 
					    if (!parallel_hds[index]) {
 | 
				
			||||||
        error_report("could not connect parallel device"
 | 
					        error_report("could not connect parallel device"
 | 
				
			||||||
                     " to character backend '%s'", devname);
 | 
					                     " to character backend '%s'", devname);
 | 
				
			||||||
@ -2567,7 +2566,7 @@ static int virtcon_parse(const char *devname)
 | 
				
			|||||||
    qemu_opt_set(dev_opts, "driver", "virtconsole", &error_abort);
 | 
					    qemu_opt_set(dev_opts, "driver", "virtconsole", &error_abort);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    snprintf(label, sizeof(label), "virtcon%d", index);
 | 
					    snprintf(label, sizeof(label), "virtcon%d", index);
 | 
				
			||||||
    virtcon_hds[index] = qemu_chr_new(label, devname, NULL);
 | 
					    virtcon_hds[index] = qemu_chr_new(label, devname);
 | 
				
			||||||
    if (!virtcon_hds[index]) {
 | 
					    if (!virtcon_hds[index]) {
 | 
				
			||||||
        error_report("could not connect virtio console"
 | 
					        error_report("could not connect virtio console"
 | 
				
			||||||
                     " to character backend '%s'", devname);
 | 
					                     " to character backend '%s'", devname);
 | 
				
			||||||
@ -2600,7 +2599,7 @@ static int sclp_parse(const char *devname)
 | 
				
			|||||||
    qemu_opt_set(dev_opts, "driver", "sclpconsole", &error_abort);
 | 
					    qemu_opt_set(dev_opts, "driver", "sclpconsole", &error_abort);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    snprintf(label, sizeof(label), "sclpcon%d", index);
 | 
					    snprintf(label, sizeof(label), "sclpcon%d", index);
 | 
				
			||||||
    sclp_hds[index] = qemu_chr_new(label, devname, NULL);
 | 
					    sclp_hds[index] = qemu_chr_new(label, devname);
 | 
				
			||||||
    if (!sclp_hds[index]) {
 | 
					    if (!sclp_hds[index]) {
 | 
				
			||||||
        error_report("could not connect sclp console"
 | 
					        error_report("could not connect sclp console"
 | 
				
			||||||
                     " to character backend '%s'", devname);
 | 
					                     " to character backend '%s'", devname);
 | 
				
			||||||
@ -2616,7 +2615,7 @@ static int debugcon_parse(const char *devname)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    QemuOpts *opts;
 | 
					    QemuOpts *opts;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!qemu_chr_new("debugcon", devname, NULL)) {
 | 
					    if (!qemu_chr_new("debugcon", devname)) {
 | 
				
			||||||
        exit(1);
 | 
					        exit(1);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    opts = qemu_opts_create(qemu_find_opts("device"), "debugcon", 1, NULL);
 | 
					    opts = qemu_opts_create(qemu_find_opts("device"), "debugcon", 1, NULL);
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user