* 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:
Peter Maydell 2016-10-24 15:03:09 +01:00
commit a3ae21ec3f
96 changed files with 1738 additions and 1229 deletions

View File

@ -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;
@ -566,6 +566,7 @@ static void baum_close(struct CharDriverState *chr)
static CharDriverState *chr_baum_init(const char *id,
ChardevBackend *backend,
ChardevReturn *ret,
bool *be_opened,
Error **errp)
{
ChardevCommon *common = backend->u.braille.data;
@ -589,7 +590,7 @@ static CharDriverState *chr_baum_init(const char *id,
chr->opaque = baum;
chr->chr_write = baum_write;
chr->chr_accept_input = baum_accept_input;
chr->chr_close = baum_close;
chr->chr_free = baum_free;
handle = g_malloc0(brlapi_getHandleSize());
baum->brlapi = handle;

View File

@ -133,7 +133,7 @@ static int msmouse_chr_write (struct CharDriverState *s, const uint8_t *buf, int
return len;
}
static void msmouse_chr_close (struct CharDriverState *chr)
static void msmouse_chr_free(struct CharDriverState *chr)
{
MouseState *mouse = chr->opaque;
@ -151,6 +151,7 @@ static QemuInputHandler msmouse_handler = {
static CharDriverState *qemu_chr_open_msmouse(const char *id,
ChardevBackend *backend,
ChardevReturn *ret,
bool *be_opened,
Error **errp)
{
ChardevCommon *common = backend->u.msmouse.data;
@ -162,9 +163,9 @@ static CharDriverState *qemu_chr_open_msmouse(const char *id,
return NULL;
}
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->explicit_be_open = true;
*be_opened = false;
mouse = g_new0(MouseState, 1);
mouse->hs = qemu_input_handler_register((DeviceState *)mouse,

View File

@ -15,7 +15,6 @@
#include "sysemu/char.h"
#include "qapi/error.h"
#include "qapi/qmp/qerror.h"
#include "hw/qdev.h" /* just for DEFINE_PROP_CHR */
#define TYPE_RNG_EGD "rng-egd"
#define RNG_EGD(obj) OBJECT_CHECK(RngEgd, (obj), TYPE_RNG_EGD)
@ -24,7 +23,7 @@ typedef struct RngEgd
{
RngBackend parent;
CharDriverState *chr;
CharBackend chr;
char *chr_name;
} RngEgd;
@ -43,7 +42,7 @@ static void rng_egd_request_entropy(RngBackend *b, RngRequest *req)
/* XXX this blocks entire thread. Rewrite to use
* 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;
}
@ -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)
{
RngEgd *s = RNG_EGD(b);
CharDriverState *chr;
if (s->chr_name == NULL) {
error_setg(errp, QERR_INVALID_PARAMETER_VALUE,
@ -94,21 +94,19 @@ static void rng_egd_opened(RngBackend *b, Error **errp)
return;
}
s->chr = qemu_chr_find(s->chr_name);
if (s->chr == NULL) {
chr = qemu_chr_find(s->chr_name);
if (chr == NULL) {
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
"Device '%s' not found", s->chr_name);
return;
}
if (qemu_chr_fe_claim(s->chr) != 0) {
error_setg(errp, QERR_DEVICE_IN_USE, s->chr_name);
if (!qemu_chr_fe_init(&s->chr, chr, errp)) {
return;
}
/* 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,
NULL, s);
qemu_chr_fe_set_handlers(&s->chr, rng_egd_chr_can_read,
rng_egd_chr_read, NULL, s, NULL, true);
}
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)
{
RngEgd *s = RNG_EGD(obj);
CharDriverState *chr = qemu_chr_fe_get_driver(&s->chr);
if (s->chr && s->chr->label) {
return g_strdup(s->chr->label);
if (chr && chr->label) {
return g_strdup(chr->label);
}
return NULL;
@ -146,11 +145,7 @@ static void rng_egd_finalize(Object *obj)
{
RngEgd *s = RNG_EGD(obj);
if (s->chr) {
qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, NULL);
qemu_chr_fe_release(s->chr);
}
qemu_chr_fe_deinit(&s->chr);
g_free(s->chr_name);
}

View File

@ -102,7 +102,7 @@ static int testdev_write(CharDriverState *chr, const uint8_t *buf, int len)
return orig_len;
}
static void testdev_close(struct CharDriverState *chr)
static void testdev_free(struct CharDriverState *chr)
{
TestdevCharState *testdev = chr->opaque;
@ -112,6 +112,7 @@ static void testdev_close(struct CharDriverState *chr)
static CharDriverState *chr_testdev_init(const char *id,
ChardevBackend *backend,
ChardevReturn *ret,
bool *be_opened,
Error **errp)
{
TestdevCharState *testdev;
@ -122,7 +123,7 @@ static CharDriverState *chr_testdev_init(const char *id,
chr->opaque = testdev;
chr->chr_write = testdev_write;
chr->chr_close = testdev_close;
chr->chr_free = testdev_free;
return chr;
}

View File

@ -202,6 +202,10 @@ static inline unsigned exp_random(double mean)
#define SCSI_SENSE_ASCQ_PARAMETER_LIST_LENGTH_ERROR 0x1a00
#endif
#ifndef LIBISCSI_API_VERSION
#define LIBISCSI_API_VERSION 20130701
#endif
static int iscsi_translate_sense(struct scsi_sense *sense)
{
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);
retry:
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,
NULL, num_sectors * iscsilun->block_size,
iscsilun->block_size, 0, 0, fua, 0, 0,
@ -602,11 +620,14 @@ retry:
iscsilun->block_size, 0, 0, fua, 0, 0,
iscsi_co_generic_cb, &iTask);
}
#endif
if (iTask.task == NULL) {
return -ENOMEM;
}
#if LIBISCSI_API_VERSION < (20160603)
scsi_task_set_iov_out(iTask.task, (struct scsi_iovec *) iov->iov,
iov->niov);
#endif
while (!iTask.complete) {
iscsi_set_events(iscsilun);
qemu_coroutine_yield();
@ -789,6 +810,21 @@ static int coroutine_fn iscsi_co_readv(BlockDriverState *bs,
iscsi_co_init_iscsitask(iscsilun, &iTask);
retry:
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,
num_sectors * iscsilun->block_size,
iscsilun->block_size, 0, 0, 0, 0, 0,
@ -800,11 +836,13 @@ retry:
0, 0, 0, 0, 0,
iscsi_co_generic_cb, &iTask);
}
#endif
if (iTask.task == NULL) {
return -ENOMEM;
}
#if LIBISCSI_API_VERSION < (20160603)
scsi_task_set_iov_in(iTask.task, (struct scsi_iovec *) iov->iov, iov->niov);
#endif
while (!iTask.complete) {
iscsi_set_events(iscsilun);
qemu_coroutine_yield();
@ -1606,7 +1644,13 @@ static int iscsi_open(BlockDriverState *bs, QDict *options, int flags,
ret = -ENOMEM;
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)) {
error_setg(errp, "iSCSI: Failed to set target name.");
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 = parse_timeout(iscsi_url->target);
#if defined(LIBISCSI_API_VERSION) && LIBISCSI_API_VERSION >= 20150621
#if LIBISCSI_API_VERSION >= 20150621
iscsi_set_timeout(iscsi, timeout);
#else
if (timeout) {
@ -2010,9 +2054,48 @@ static BlockDriver bdrv_iscsi = {
.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)
{
bdrv_register(&bdrv_iscsi);
#if LIBISCSI_API_VERSION >= (20160603)
bdrv_register(&bdrv_iser);
#endif
}
block_init(iscsi_block_init);

View File

@ -733,7 +733,7 @@ static BlockAIOCB *qemu_rbd_aio_readv(BlockDriverState *bs,
void *opaque)
{
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);
}
@ -745,7 +745,7 @@ static BlockAIOCB *qemu_rbd_aio_writev(BlockDriverState *bs,
void *opaque)
{
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);
}

View File

@ -651,7 +651,7 @@ void cpu_loop(CPUSPARCState *env)
static void usage(void)
{
printf("qemu-" TARGET_NAME " version " QEMU_VERSION QEMU_PKGVERSION
", " QEMU_COPYRIGHT "\n"
"\n" QEMU_COPYRIGHT "\n"
"usage: qemu-" TARGET_NAME " [options] program [arguments...]\n"
"BSD CPU emulator (compiled for %s emulation)\n"
"\n"

View File

@ -15,7 +15,8 @@ Macros defined by qemu/atomic.h fall in three camps:
- compiler barriers: barrier();
- 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.
@ -111,8 +112,8 @@ consistent primitives.
When using this model, variables are accessed with atomic_read() and
atomic_set(), and restrictions to the ordering of accesses is enforced
using the smp_rmb(), smp_wmb(), smp_mb() and smp_read_barrier_depends()
memory barriers.
using the memory barrier macros: smp_rmb(), smp_wmb(), smp_mb(),
smp_mb_acquire(), smp_mb_release(), smp_read_barrier_depends().
atomic_read() and atomic_set() prevents the compiler from using
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.
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
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
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
before the barrier will appear to happen before all the LOAD and
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
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
barrier from overtaking LOADs coming after the barrier and vice versa.
smp_mb_acquire() and smp_mb_release(), but it also prevents STOREs
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
most processors, whenever two loads are performed such that the
@ -173,24 +185,21 @@ They come in four kinds:
This is the set of barriers that is required *between* two atomic_read()
and atomic_set() operations to achieve sequential consistency:
| 2nd operation |
|-----------------------------------------|
1st operation | (after last) | atomic_read | atomic_set |
---------------+--------------+-------------+------------|
(before first) | | none | smp_wmb() |
---------------+--------------+-------------+------------|
atomic_read | smp_rmb() | smp_rmb()* | ** |
---------------+--------------+-------------+------------|
atomic_set | none | smp_mb()*** | smp_wmb() |
---------------+--------------+-------------+------------|
| 2nd operation |
|-----------------------------------------------|
1st operation | (after last) | atomic_read | atomic_set |
---------------+----------------+-------------+----------------|
(before first) | | none | smp_mb_release |
---------------+----------------+-------------+----------------|
atomic_read | smp_mb_acquire | smp_rmb | ** |
---------------+----------------+-------------+----------------|
atomic_set | none | smp_mb()*** | smp_wmb() |
---------------+----------------+-------------+----------------|
* Or smp_read_barrier_depends().
** This requires a load-store barrier. How to achieve this varies
depending on the machine, but in practice smp_rmb()+smp_wmb()
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 load-store barrier. This is achieved by
either smp_mb_acquire() or smp_mb_release().
*** This requires a store-load barrier. On most machines, the only
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()
and atomic_mb_set() are the following:
1) atomic_mb_read(p) = atomic_read(p); smp_rmb()
atomic_mb_set(p, v) = smp_wmb(); atomic_set(p, v); smp_mb()
1) atomic_mb_read(p) = atomic_read(p); smp_mb_acquire()
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()
atomic_mb_set(p, v) = smp_wmb(); atomic_set(p, v);
2) atomic_mb_read(p) = smp_mb() atomic_read(p); smp_mb_acquire()
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
normally has more reads than writes. Therefore it makes more sense to
@ -222,7 +231,7 @@ place barriers instead:
thread 1 thread 1
------------------------- ------------------------
(other writes)
smp_wmb()
smp_mb_release()
atomic_mb_set(&a, x) atomic_set(&a, x)
smp_wmb()
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)
smp_rmb()
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
unrelated to each other (for example because, apart from the current
@ -246,12 +261,12 @@ place barriers instead:
n = 0; n = 0;
for (i = 0; i < 10; i++) => for (i = 0; i < 10; 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:
smp_mb():
smp_wmb();
smp_mb_release();
for (i = 0; i < 10; i++) => for (i = 0; i < 10; i++)
atomic_mb_set(&a[i], false); atomic_set(&a[i], false);
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
expensive smp_mb():
smp_wmb();
smp_mb_release();
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(&b[i], false); smb_wmb();
@ -312,8 +327,8 @@ access and for data dependency barriers:
smp_read_barrier_depends();
z = b[y];
smp_wmb() also pairs with atomic_mb_read(), and smp_rmb() also pairs
with atomic_mb_set().
smp_wmb() also pairs with atomic_mb_read() and smp_mb_acquire().
and smp_rmb() also pairs with atomic_mb_set() and smp_mb_release().
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().
atomic_mb_read() compiles to the same instructions as Linux's
smp_load_acquire(), but this should be treated as an implementation
detail. If required, QEMU might later add atomic_load_acquire() and
atomic_store_release() macros.
detail. QEMU does have atomic_load_acquire() and atomic_store_release()
macros, but for now they are only used within atomic.h. This may
change in the future.
SOURCES

7
exec.c
View File

@ -1254,7 +1254,12 @@ static void *file_ram_alloc(RAMBlock *block,
}
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) {
error_setg(errp, "memory size 0x" RAM_ADDR_FMT " must be equal to "

View File

@ -303,7 +303,7 @@ typedef struct GDBState {
int fd;
int running_state;
#else
CharDriverState *chr;
CharBackend chr;
CharDriverState *mon_chr;
#endif
char syscall_buf[256];
@ -404,7 +404,7 @@ static void put_buffer(GDBState *s, const uint8_t *buf, int len)
#else
/* XXX this blocks entire thread. Rewrite to use
* 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
}
@ -1471,6 +1471,9 @@ void gdb_exit(CPUArchState *env, int code)
{
GDBState *s;
char buf[4];
#ifndef CONFIG_USER_ONLY
CharDriverState *chr;
#endif
s = gdbserver_state;
if (!s) {
@ -1481,7 +1484,8 @@ void gdb_exit(CPUArchState *env, int code)
return;
}
#else
if (!s->chr) {
chr = qemu_chr_fe_get_driver(&s->chr);
if (!chr) {
return;
}
#endif
@ -1490,7 +1494,8 @@ void gdb_exit(CPUArchState *env, int code)
put_packet(s, buf);
#ifndef CONFIG_USER_ONLY
qemu_chr_delete(s->chr);
qemu_chr_fe_deinit(&s->chr);
qemu_chr_delete(chr);
#endif
}
@ -1745,13 +1750,9 @@ int gdbserver_start(const char *device)
sigaction(SIGINT, &act, NULL);
}
#endif
chr = qemu_chr_new_noreplay("gdb", device, NULL);
chr = qemu_chr_new_noreplay("gdb", device);
if (!chr)
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;
@ -1766,14 +1767,20 @@ int gdbserver_start(const char *device)
mon_chr->chr_write = gdb_monitor_write;
monitor_init(mon_chr, 0);
} else {
if (s->chr)
qemu_chr_delete(s->chr);
if (qemu_chr_fe_get_driver(&s->chr)) {
qemu_chr_delete(qemu_chr_fe_get_driver(&s->chr));
}
mon_chr = s->mon_chr;
memset(s, 0, sizeof(GDBState));
s->mon_chr = mon_chr;
}
s->c_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->mon_chr = mon_chr;
s->current_syscall_cb = NULL;

2
hmp.c
View File

@ -2002,7 +2002,7 @@ void hmp_chardev_add(Monitor *mon, const QDict *qdict)
if (opts == NULL) {
error_setg(&err, "Parsing chardev args failed");
} else {
qemu_chr_new_from_opts(opts, NULL, &err);
qemu_chr_new_from_opts(opts, &err);
qemu_opts_del(opts);
}
hmp_handle_error(mon, &err);

View File

@ -88,7 +88,7 @@ static void clipper_init(MachineState *machine)
pci_vga_init(pci_bus);
/* 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. */
for (i = 0; i < nb_nics; i++) {

View File

@ -125,7 +125,7 @@ static void fsl_imx25_realize(DeviceState *dev, Error **errp)
if (!chr) {
char label[20];
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);

View File

@ -114,7 +114,7 @@ static void fsl_imx31_realize(DeviceState *dev, Error **errp)
if (!chr) {
char label[20];
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);

View File

@ -193,7 +193,7 @@ static void fsl_imx6_realize(DeviceState *dev, Error **errp)
if (!chr) {
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);
serial_hds[i] = chr;
}

View File

@ -621,7 +621,7 @@ struct omap_sti_s {
qemu_irq irq;
MemoryRegion iomem;
MemoryRegion iomem_fifo;
CharDriverState *chr;
CharBackend chr;
uint32_t sysconfig;
uint32_t systest;
@ -771,14 +771,15 @@ static void omap_sti_fifo_write(void *opaque, hwaddr addr,
/* Flush channel <i>value</i>. */
/* XXX this blocks entire thread. Rewrite to use
* 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) {
if (value == 0xc0 || value == 0xc3) {
/* Open channel <i>ch</i>. */
} else if (value == 0x00)
qemu_chr_fe_write_all(s->chr, (const uint8_t *) "\n", 1);
else
qemu_chr_fe_write_all(s->chr, &byte, 1);
} else if (value == 0x00) {
qemu_chr_fe_write_all(&s->chr, (const uint8_t *) "\n", 1);
} else {
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;
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",
omap_l4_region_size(ta, 0));

View File

@ -1764,7 +1764,7 @@ struct PXA2xxFIrState {
qemu_irq rx_dma;
qemu_irq tx_dma;
uint32_t enable;
CharDriverState *chr;
CharBackend chr;
uint8_t control[3];
uint8_t status[2];
@ -1898,14 +1898,16 @@ static void pxa2xx_fir_write(void *opaque, hwaddr addr,
pxa2xx_fir_update(s);
break;
case ICDR:
if (s->control[2] & (1 << 2)) /* TXP */
if (s->control[2] & (1 << 2)) { /* TXP */
ch = value;
else
} else {
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
* 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;
case ICSR0:
s->status[0] &= ~(value & 0x66);
@ -1973,11 +1975,8 @@ static void pxa2xx_fir_realize(DeviceState *dev, Error **errp)
{
PXA2xxFIrState *s = PXA2XX_FIR(dev);
if (s->chr) {
qemu_chr_fe_claim_no_fail(s->chr);
qemu_chr_add_handlers(s->chr, pxa2xx_fir_is_empty,
pxa2xx_fir_rx, pxa2xx_fir_event, s);
}
qemu_chr_fe_set_handlers(&s->chr, pxa2xx_fir_is_empty,
pxa2xx_fir_rx, pxa2xx_fir_event, s, NULL, true);
}
static bool pxa2xx_fir_vmstate_validate(void *opaque, int version_id)

View File

@ -912,7 +912,7 @@ typedef struct StrongARMUARTState {
SysBusDevice parent_obj;
MemoryRegion iomem;
CharDriverState *chr;
CharBackend chr;
qemu_irq irq;
uint8_t utcr0;
@ -1020,9 +1020,7 @@ static void strongarm_uart_update_parameters(StrongARMUARTState *s)
ssp.data_bits = data_bits;
ssp.stop_bits = stop_bits;
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,
speed, parity, data_bits, stop_bits);
@ -1107,10 +1105,10 @@ static void strongarm_uart_tx(void *opaque)
if (s->utcr3 & UTCR3_LBM) /* loopback */ {
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
* 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;
@ -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->tx_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, strongarm_uart_tx, s);
if (s->chr) {
qemu_chr_add_handlers(s->chr,
strongarm_uart_can_receive,
strongarm_uart_receive,
strongarm_uart_event,
s);
}
qemu_chr_fe_set_handlers(&s->chr,
strongarm_uart_can_receive,
strongarm_uart_receive,
strongarm_uart_event,
s, NULL, true);
}
static void strongarm_uart_reset(DeviceState *dev)

View File

@ -78,15 +78,17 @@ enum {
static inline void csrhci_fifo_wake(struct csrhci_s *s)
{
CharBackend *be = s->chr.be;
if (!s->enable || !s->out_len)
return;
/* 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) &&
s->chr.chr_read) {
s->chr.chr_read(s->chr.handler_opaque,
s->outfifo + s->out_start ++, 1);
s->out_len --;
if (be && be->chr_can_read && be->chr_can_read(be->opaque) &&
be->chr_read) {
be->chr_read(be->opaque,
s->outfifo + s->out_start++, 1);
s->out_len--;
if (s->out_start >= s->out_size) {
s->out_start = 0;
s->out_size = FIFO_LEN;
@ -466,7 +468,6 @@ CharDriverState *uart_hci_init(void)
s->chr.opaque = s;
s->chr.chr_write = csrhci_write;
s->chr.chr_ioctl = csrhci_ioctl;
s->chr.avail_connections = 1;
s->hci = qemu_next_hci();
s->hci->opaque = s;

View File

@ -79,9 +79,7 @@ static uint64_t bcm2835_aux_read(void *opaque, hwaddr offset, unsigned size)
s->read_pos = 0;
}
}
if (s->chr) {
qemu_chr_accept_input(s->chr);
}
qemu_chr_fe_accept_input(&s->chr);
bcm2835_aux_update(s);
return c;
@ -168,11 +166,9 @@ static void bcm2835_aux_write(void *opaque, hwaddr offset, uint64_t value,
case AUX_MU_IO_REG:
/* "DLAB bit set means access baudrate register" is NYI */
ch = value;
if (s->chr) {
/* XXX this blocks entire thread. Rewrite to use
* qemu_chr_fe_write and background I/O callbacks */
qemu_chr_fe_write_all(s->chr, &ch, 1);
}
/* XXX this blocks entire thread. Rewrite to use
* qemu_chr_fe_write and background I/O callbacks */
qemu_chr_fe_write_all(&s->chr, &ch, 1);
break;
case AUX_MU_IER_REG:
@ -282,10 +278,8 @@ static void bcm2835_aux_realize(DeviceState *dev, Error **errp)
{
BCM2835AuxState *s = BCM2835_AUX(dev);
if (s->chr) {
qemu_chr_add_handlers(s->chr, bcm2835_aux_can_receive,
bcm2835_aux_receive, NULL, s);
}
qemu_chr_fe_set_handlers(&s->chr, bcm2835_aux_can_receive,
bcm2835_aux_receive, NULL, s, NULL, true);
}
static Property bcm2835_aux_props[] = {

View File

@ -142,9 +142,7 @@ static void uart_rx_reset(CadenceUARTState *s)
{
s->rx_wpos = 0;
s->rx_count = 0;
if (s->chr) {
qemu_chr_accept_input(s->chr);
}
qemu_chr_fe_accept_input(&s->chr);
}
static void uart_tx_reset(CadenceUARTState *s)
@ -156,10 +154,8 @@ static void uart_send_breaks(CadenceUARTState *s)
{
int break_enabled = 1;
if (s->chr) {
qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_BREAK,
&break_enabled);
}
qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_BREAK,
&break_enabled);
}
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;
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)
@ -278,7 +272,7 @@ static gboolean cadence_uart_xmit(GIOChannel *chan, GIOCondition cond,
int ret;
/* 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;
return FALSE;
}
@ -287,7 +281,7 @@ static gboolean cadence_uart_xmit(GIOChannel *chan, GIOCondition cond,
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) {
s->tx_count -= ret;
@ -295,7 +289,7 @@ static gboolean cadence_uart_xmit(GIOChannel *chan, GIOCondition cond,
}
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);
if (!r) {
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];
s->rx_count--;
if (s->chr) {
qemu_chr_accept_input(s->chr);
}
qemu_chr_fe_accept_input(&s->chr);
} else {
*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,
fifo_trigger_update, s);
if (s->chr) {
qemu_chr_add_handlers(s->chr, uart_can_receive, uart_receive,
uart_event, s);
}
qemu_chr_fe_set_handlers(&s->chr, uart_can_receive, uart_receive,
uart_event, s, NULL, true);
}
static void cadence_uart_init(Object *obj)

View File

@ -39,7 +39,7 @@
typedef struct DebugconState {
MemoryRegion io;
CharDriverState *chr;
CharBackend chr;
uint32_t readback;
} 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
* 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)
{
if (!s->chr) {
if (!qemu_chr_fe_get_driver(&s->chr)) {
error_setg(errp, "Can't create debugcon device, empty char device");
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)

View File

@ -76,11 +76,9 @@ static void digic_uart_write(void *opaque, hwaddr addr, uint64_t value,
switch (addr) {
case R_TX:
if (s->chr) {
/* XXX this blocks entire thread. Rewrite to use
* qemu_chr_fe_write and background I/O callbacks */
qemu_chr_fe_write_all(s->chr, &ch, 1);
}
/* XXX this blocks entire thread. Rewrite to use
* qemu_chr_fe_write and background I/O callbacks */
qemu_chr_fe_write_all(&s->chr, &ch, 1);
break;
case R_ST:
@ -147,9 +145,8 @@ static void digic_uart_realize(DeviceState *dev, Error **errp)
{
DigicUartState *s = DIGIC_UART(dev);
if (s->chr) {
qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
}
qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx,
uart_event, s, NULL, true);
}
static void digic_uart_init(Object *obj)

View File

@ -88,7 +88,7 @@ typedef struct ChannelState {
uint32_t reg;
uint8_t wregs[SERIAL_REGS], rregs[SERIAL_REGS];
SERIOQueue queue;
CharDriverState *chr;
CharBackend chr;
int e0_mode, led_mode, caps_lock_mode, num_lock_mode;
int disabled;
int clock;
@ -416,7 +416,7 @@ static void escc_update_parameters(ChannelState *s)
int speed, parity, data_bits, stop_bits;
QEMUSerialSetParams ssp;
if (!s->chr || s->type != ser)
if (!qemu_chr_fe_get_driver(&s->chr) || s->type != ser)
return;
if (s->wregs[W_TXCTRL1] & TXCTRL1_PAREN) {
@ -466,7 +466,7 @@ static void escc_update_parameters(ChannelState *s)
ssp.data_bits = data_bits;
ssp.stop_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,
@ -556,11 +556,11 @@ static void escc_mem_write(void *opaque, hwaddr addr,
trace_escc_mem_writeb_data(CHN_C(s), val);
s->tx = val;
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
* qemu_chr_fe_write and background I/O callbacks */
qemu_chr_fe_write_all(s->chr, &s->tx, 1);
else if (s->type == kbd && !s->disabled) {
qemu_chr_fe_write_all(&s->chr, &s->tx, 1);
} else if (s->type == kbd && !s->disabled) {
handle_kbd_command(s, val);
}
}
@ -599,8 +599,7 @@ static uint64_t escc_mem_read(void *opaque, hwaddr addr,
else
ret = s->rx;
trace_escc_mem_readb_data(CHN_C(s), ret);
if (s->chr)
qemu_chr_accept_input(s->chr);
qemu_chr_fe_accept_input(&s->chr);
return ret;
default:
break;
@ -1013,10 +1012,11 @@ static void escc_realize(DeviceState *dev, Error **errp)
ESCC_SIZE << s->it_shift);
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;
qemu_chr_add_handlers(s->chn[i].chr, serial_can_receive,
serial_receive1, serial_event, &s->chn[i]);
qemu_chr_fe_set_handlers(&s->chn[i].chr, serial_can_receive,
serial_receive1, serial_event,
&s->chn[i], NULL, true);
}
}

View File

@ -53,7 +53,7 @@ typedef struct ETRAXSerial {
SysBusDevice parent_obj;
MemoryRegion mmio;
CharDriverState *chr;
CharBackend chr;
qemu_irq irq;
int pending_tx;
@ -128,7 +128,7 @@ ser_write(void *opaque, hwaddr addr,
case RW_DOUT:
/* XXX this blocks entire thread. Rewrite to use
* 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->pending_tx = 1;
s->regs[addr] = value;
@ -231,11 +231,9 @@ static void etraxfs_ser_realize(DeviceState *dev, Error **errp)
{
ETRAXSerial *s = ETRAX_SERIAL(dev);
if (s->chr) {
qemu_chr_add_handlers(s->chr,
serial_can_receive, serial_receive,
serial_event, s);
}
qemu_chr_fe_set_handlers(&s->chr,
serial_can_receive, serial_receive,
serial_event, s, NULL, true);
}
static void etraxfs_ser_class_init(ObjectClass *klass, void *data)

View File

@ -181,7 +181,7 @@ typedef struct Exynos4210UartState {
Exynos4210UartFIFO rx;
Exynos4210UartFIFO tx;
CharDriverState *chr;
CharBackend chr;
qemu_irq irq;
uint32_t channel;
@ -346,7 +346,7 @@ static void exynos4210_uart_update_parameters(Exynos4210UartState *s)
ssp.data_bits = data_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",
s->channel, speed, parity, data_bits, stop_bits);
@ -383,13 +383,13 @@ static void exynos4210_uart_write(void *opaque, hwaddr offset,
break;
case UTXH:
if (s->chr) {
if (qemu_chr_fe_get_driver(&s->chr)) {
s->reg[I_(UTRSTAT)] &= ~(UTRSTAT_TRANSMITTER_EMPTY |
UTRSTAT_Tx_BUFFER_EMPTY);
ch = (uint8_t)val;
/* XXX this blocks entire thread. Rewrite to use
* 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
fprintf(stderr, "%c", ch);
#endif
@ -606,7 +606,7 @@ DeviceState *exynos4210_uart_create(hwaddr addr,
chr = serial_hds[channel];
if (!chr) {
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)) {
error_report("Can't assign serial port to UART%d", channel);
exit(1);
@ -640,8 +640,9 @@ static int exynos4210_uart_init(SysBusDevice *dev)
sysbus_init_irq(dev, &s->irq);
qemu_chr_add_handlers(s->chr, exynos4210_uart_can_receive,
exynos4210_uart_receive, exynos4210_uart_event, s);
qemu_chr_fe_set_handlers(&s->chr, exynos4210_uart_can_receive,
exynos4210_uart_receive, exynos4210_uart_event,
s, NULL, true);
return 0;
}

View File

@ -78,7 +78,7 @@ typedef struct UART {
MemoryRegion iomem;
qemu_irq irq;
CharDriverState *chr;
CharBackend chr;
/* registers */
uint32_t status;
@ -201,11 +201,12 @@ static void grlib_apbuart_write(void *opaque, hwaddr addr,
case DATA_OFFSET:
case DATA_OFFSET + 3: /* When only one byte write */
/* 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;
/* XXX this blocks entire thread. Rewrite to use
* 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 */
if (uart->control & UART_TRANSMIT_INTERRUPT) {
qemu_irq_pulse(uart->irq);
@ -242,11 +243,11 @@ static int grlib_apbuart_init(SysBusDevice *dev)
{
UART *uart = GRLIB_APB_UART(dev);
qemu_chr_add_handlers(uart->chr,
grlib_apbuart_can_receive,
grlib_apbuart_receive,
grlib_apbuart_event,
uart);
qemu_chr_fe_set_handlers(&uart->chr,
grlib_apbuart_can_receive,
grlib_apbuart_receive,
grlib_apbuart_event,
uart, NULL, true);
sysbus_init_irq(dev, &uart->irq);

View File

@ -121,9 +121,7 @@ static uint64_t imx_serial_read(void *opaque, hwaddr offset,
s->usr2 &= ~USR2_RDR;
s->uts1 |= UTS1_RXEMPTY;
imx_update(s);
if (s->chr) {
qemu_chr_accept_input(s->chr);
}
qemu_chr_fe_accept_input(&s->chr);
}
return c;
@ -172,20 +170,19 @@ static void imx_serial_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size)
{
IMXSerialState *s = (IMXSerialState *)opaque;
CharDriverState *chr = qemu_chr_fe_get_driver(&s->chr);
unsigned char ch;
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) {
case 0x10: /* UTXD */
ch = value;
if (s->ucr2 & UCR2_TXEN) {
if (s->chr) {
/* XXX this blocks entire thread. Rewrite to use
* qemu_chr_fe_write and background I/O callbacks */
qemu_chr_fe_write_all(s->chr, &ch, 1);
}
/* XXX this blocks entire thread. Rewrite to use
* qemu_chr_fe_write and background I/O callbacks */
qemu_chr_fe_write_all(&s->chr, &ch, 1);
s->usr1 &= ~USR1_TRDY;
imx_update(s);
s->usr1 |= USR1_TRDY;
@ -214,9 +211,7 @@ static void imx_serial_write(void *opaque, hwaddr offset,
}
if (value & UCR2_RXEN) {
if (!(s->ucr2 & UCR2_RXEN)) {
if (s->chr) {
qemu_chr_accept_input(s->chr);
}
qemu_chr_fe_accept_input(&s->chr);
}
}
s->ucr2 = value & 0xffff;
@ -318,12 +313,10 @@ static void imx_serial_realize(DeviceState *dev, Error **errp)
{
IMXSerialState *s = IMX_SERIAL(dev);
if (s->chr) {
qemu_chr_add_handlers(s->chr, imx_can_receive, imx_receive,
imx_event, s);
} else {
DPRINTF("No char dev for uart\n");
}
DPRINTF("char dev for uart: %p\n", qemu_chr_fe_get_driver(&s->chr));
qemu_chr_fe_set_handlers(&s->chr, imx_can_receive, imx_receive,
imx_event, s, NULL, true);
}
static void imx_serial_init(Object *obj)

View File

@ -93,7 +93,7 @@ typedef struct SCC2698Block SCC2698Block;
struct SCC2698Channel {
IPOctalState *ipoctal;
CharDriverState *dev;
CharBackend dev;
bool rx_enabled;
uint8_t mr[2];
uint8_t mr_idx;
@ -288,9 +288,7 @@ static uint16_t io_read(IPackDevice *ip, uint8_t addr)
if (ch->rx_pending == 0) {
ch->sr &= ~SR_RXRDY;
blk->isr &= ~ISR_RXRDY(channel);
if (ch->dev) {
qemu_chr_accept_input(ch->dev);
}
qemu_chr_fe_accept_input(&ch->dev);
} else {
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_THRb:
if (ch->sr & SR_TXRDY) {
uint8_t thr = reg;
DPRINTF("Write THR%c (0x%x)\n", channel + 'a', reg);
if (ch->dev) {
uint8_t thr = reg;
/* XXX this blocks entire thread. Rewrite to use
* qemu_chr_fe_write and background I/O callbacks */
qemu_chr_fe_write_all(ch->dev, &thr, 1);
}
/* XXX this blocks entire thread. Rewrite to use
* qemu_chr_fe_write and background I/O callbacks */
qemu_chr_fe_write_all(&ch->dev, &thr, 1);
} else {
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;
/* Redirect IP-Octal channels to host character devices */
if (ch->dev) {
qemu_chr_add_handlers(ch->dev, hostdev_can_receive,
hostdev_receive, hostdev_event, ch);
if (qemu_chr_fe_get_driver(&ch->dev)) {
qemu_chr_fe_set_handlers(&ch->dev, hostdev_can_receive,
hostdev_receive, hostdev_event,
ch, NULL, true);
DPRINTF("Redirecting channel %u to %s\n", i, ch->dev->label);
} else {
DPRINTF("Could not redirect channel %u, no chardev set\n", i);

View File

@ -44,7 +44,7 @@ enum {
struct LM32JuartState {
SysBusDevice parent_obj;
CharDriverState *chr;
CharBackend chr;
uint32_t jtx;
uint32_t jrx;
@ -75,11 +75,9 @@ void lm32_juart_set_jtx(DeviceState *d, uint32_t jtx)
trace_lm32_juart_set_jtx(s->jtx);
s->jtx = jtx;
if (s->chr) {
/* XXX this blocks entire thread. Rewrite to use
* qemu_chr_fe_write and background I/O callbacks */
qemu_chr_fe_write_all(s->chr, &ch, 1);
}
/* XXX this blocks entire thread. Rewrite to use
* qemu_chr_fe_write and background I/O callbacks */
qemu_chr_fe_write_all(&s->chr, &ch, 1);
}
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);
if (s->chr) {
qemu_chr_add_handlers(s->chr, juart_can_rx, juart_rx, juart_event, s);
}
qemu_chr_fe_set_handlers(&s->chr, juart_can_rx, juart_rx,
juart_event, s, NULL, true);
}
static const VMStateDescription vmstate_lm32_juart = {

View File

@ -97,7 +97,7 @@ struct LM32UartState {
SysBusDevice parent_obj;
MemoryRegion iomem;
CharDriverState *chr;
CharBackend chr;
qemu_irq irq;
uint32_t regs[R_MAX];
@ -142,7 +142,7 @@ static uint64_t uart_read(void *opaque, hwaddr addr,
r = s->regs[R_RXTX];
s->regs[R_LSR] &= ~LSR_DR;
uart_update_irq(s);
qemu_chr_accept_input(s->chr);
qemu_chr_fe_accept_input(&s->chr);
break;
case R_IIR:
case R_LSR:
@ -177,11 +177,9 @@ static void uart_write(void *opaque, hwaddr addr,
addr >>= 2;
switch (addr) {
case R_RXTX:
if (s->chr) {
/* XXX this blocks entire thread. Rewrite to use
* qemu_chr_fe_write and background I/O callbacks */
qemu_chr_fe_write_all(s->chr, &ch, 1);
}
/* XXX this blocks entire thread. Rewrite to use
* qemu_chr_fe_write and background I/O callbacks */
qemu_chr_fe_write_all(&s->chr, &ch, 1);
break;
case R_IER:
case R_LCR:
@ -267,9 +265,8 @@ static void lm32_uart_realize(DeviceState *dev, Error **errp)
{
LM32UartState *s = LM32_UART(dev);
if (s->chr) {
qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
}
qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx,
uart_event, s, NULL, true);
}
static const VMStateDescription vmstate_lm32_uart = {

View File

@ -10,6 +10,7 @@
#include "hw/m68k/mcf.h"
#include "sysemu/char.h"
#include "exec/address-spaces.h"
#include "qapi/error.h"
typedef struct {
MemoryRegion iomem;
@ -26,7 +27,7 @@ typedef struct {
int tx_enabled;
int rx_enabled;
qemu_irq irq;
CharDriverState *chr;
CharBackend chr;
} mcf_uart_state;
/* UART Status Register bits. */
@ -92,7 +93,7 @@ uint64_t mcf_uart_read(void *opaque, hwaddr addr,
if (s->fifo_len == 0)
s->sr &= ~MCF_UART_RxRDY;
mcf_uart_update(s);
qemu_chr_accept_input(s->chr);
qemu_chr_fe_accept_input(&s->chr);
return val;
}
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)
{
if (s->tx_enabled && (s->sr & MCF_UART_TxEMP) == 0) {
if (s->chr)
/* XXX this blocks entire thread. Rewrite to use
* qemu_chr_fe_write and background I/O callbacks */
qemu_chr_fe_write_all(s->chr, (unsigned char *)&s->tb, 1);
/* XXX this blocks entire thread. Rewrite to use
* qemu_chr_fe_write and background I/O callbacks */
qemu_chr_fe_write_all(&s->chr, (unsigned char *)&s->tb, 1);
s->sr |= MCF_UART_TxEMP;
}
if (s->tx_enabled) {
@ -280,12 +280,12 @@ void *mcf_uart_init(qemu_irq irq, CharDriverState *chr)
mcf_uart_state *s;
s = g_malloc0(sizeof(mcf_uart_state));
s->chr = chr;
s->irq = irq;
if (chr) {
qemu_chr_fe_claim_no_fail(chr);
qemu_chr_add_handlers(chr, mcf_uart_can_receive, mcf_uart_receive,
mcf_uart_event, s);
qemu_chr_fe_init(&s->chr, chr, &error_abort);
qemu_chr_fe_set_handlers(&s->chr, mcf_uart_can_receive,
mcf_uart_receive, mcf_uart_event,
s, NULL, true);
}
mcf_uart_reset(s);
return s;

View File

@ -61,7 +61,7 @@ struct MilkymistUartState {
SysBusDevice parent_obj;
MemoryRegion regs_region;
CharDriverState *chr;
CharBackend chr;
qemu_irq irq;
uint32_t regs[R_MAX];
@ -124,9 +124,7 @@ static void uart_write(void *opaque, hwaddr addr, uint64_t value,
addr >>= 2;
switch (addr) {
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;
break;
case R_DIV:
@ -138,7 +136,7 @@ static void uart_write(void *opaque, hwaddr addr, uint64_t value,
case R_STAT:
/* write one to clear bits */
s->regs[addr] &= ~(value & (STAT_RX_EVT | STAT_TX_EVT));
qemu_chr_accept_input(s->chr);
qemu_chr_fe_accept_input(&s->chr);
break;
default:
@ -200,9 +198,8 @@ static void milkymist_uart_realize(DeviceState *dev, Error **errp)
{
MilkymistUartState *s = MILKYMIST_UART(dev);
if (s->chr) {
qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
}
qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx,
uart_event, s, NULL, true);
}
static void milkymist_uart_init(Object *obj)

View File

@ -63,7 +63,7 @@ struct omap_uart_s *omap_uart_init(hwaddr base,
s->irq = irq;
s->serial = serial_mm_init(get_system_memory(), base, 2, irq,
omap_clk_getrate(fclk)/16,
chr ?: qemu_chr_new(label, "null", NULL),
chr ?: qemu_chr_new(label, "null"),
DEVICE_NATIVE_ENDIAN);
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 */
s->serial = serial_mm_init(get_system_memory(), s->base, 2, s->irq,
omap_clk_getrate(s->fclk) / 16,
chr ?: qemu_chr_new("null", "null", NULL),
chr ?: qemu_chr_new("null", "null"),
DEVICE_NATIVE_ENDIAN);
}

View File

@ -74,7 +74,7 @@ typedef struct ParallelState {
uint8_t control;
qemu_irq irq;
int irq_pending;
CharDriverState *chr;
CharBackend chr;
int hw_driver;
int epp_timeout;
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)
/* XXX this blocks entire thread. Rewrite to use
* 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 {
if (s->control & PARA_CTR_INTEN) {
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)
return;
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;
break;
case PARA_REG_STS:
@ -181,11 +181,11 @@ static void parallel_ioport_write_hw(void *opaque, uint32_t addr, uint32_t val)
} else {
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;
}
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;
break;
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);
else {
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;
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);
else {
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;
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);
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) {
s->epp_timeout = 1;
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);
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) {
s->epp_timeout = 1;
pdebug("we%08x t\n", val);
@ -308,13 +309,13 @@ static uint32_t parallel_ioport_read_hw(void *opaque, uint32_t addr)
addr &= 7;
switch(addr) {
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)
pdebug("rd%02x\n", ret);
s->datar = ret;
break;
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;
if (s->epp_timeout)
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
it has not been yet written to. */
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)
pdebug("rc%02x\n", ret);
s->control = ret;
@ -338,12 +339,14 @@ static uint32_t parallel_ioport_read_hw(void *opaque, uint32_t addr)
}
break;
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 */
pdebug("ra%02x s\n", ret);
else {
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;
pdebug("ra%02x t\n", ret);
}
@ -352,12 +355,13 @@ static uint32_t parallel_ioport_read_hw(void *opaque, uint32_t addr)
}
break;
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 */
pdebug("re%02x s\n", ret);
else {
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;
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);
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);
if (err) {
@ -412,7 +416,7 @@ parallel_ioport_eppdata_read_hw4(void *opaque, uint32_t addr)
pdebug("re%08x s\n", 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);
if (err) {
@ -508,7 +512,7 @@ static void parallel_isa_realizefn(DeviceState *dev, Error **errp)
int base;
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");
return;
}
@ -530,7 +534,7 @@ static void parallel_isa_realizefn(DeviceState *dev, Error **errp)
isa_init_irq(isadev, &s->irq, isa->isairq);
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->status = dummy;
}
@ -605,7 +609,7 @@ bool parallel_mm_init(MemoryRegion *address_space,
s = g_malloc0(sizeof(ParallelState));
s->irq = irq;
s->chr = chr;
qemu_chr_fe_init(&s->chr, chr, &error_abort);
s->it_shift = it_shift;
qemu_register_reset(parallel_reset, s);

View File

@ -36,7 +36,7 @@ typedef struct PL011State {
int read_pos;
int read_count;
int read_trigger;
CharDriverState *chr;
CharBackend chr;
qemu_irq irq;
const unsigned char *id;
} PL011State;
@ -87,9 +87,7 @@ static uint64_t pl011_read(void *opaque, hwaddr offset,
trace_pl011_read_fifo(s->read_count);
s->rsr = c >> 8;
pl011_update(s);
if (s->chr) {
qemu_chr_accept_input(s->chr);
}
qemu_chr_fe_accept_input(&s->chr);
r = c;
break;
case 1: /* UARTRSR */
@ -168,10 +166,9 @@ static void pl011_write(void *opaque, hwaddr offset,
case 0: /* UARTDR */
/* ??? Check if transmitter is enabled. */
ch = value;
if (s->chr)
/* XXX this blocks entire thread. Rewrite to use
* qemu_chr_fe_write and background I/O callbacks */
qemu_chr_fe_write_all(s->chr, &ch, 1);
/* XXX this blocks entire thread. Rewrite to use
* qemu_chr_fe_write and background I/O callbacks */
qemu_chr_fe_write_all(&s->chr, &ch, 1);
s->int_level |= PL011_INT_TX;
pl011_update(s);
break;
@ -331,10 +328,8 @@ static void pl011_realize(DeviceState *dev, Error **errp)
{
PL011State *s = PL011(dev);
if (s->chr) {
qemu_chr_add_handlers(s->chr, pl011_can_receive, pl011_receive,
pl011_event, s);
}
qemu_chr_fe_set_handlers(&s->chr, pl011_can_receive, pl011_receive,
pl011_event, s, NULL, true);
}
static void pl011_class_init(ObjectClass *oc, void *data)

View File

@ -37,7 +37,7 @@ typedef struct OprtnsCommand {
typedef struct SCLPConsoleLM {
SCLPEvent event;
CharDriverState *chr;
CharBackend chr;
bool echo; /* immediate echo of input if true */
uint32_t write_errors; /* errors writing to char layer */
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) {
/* XXX this blocks entire thread. Rewrite to use
* 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);
if (!scon->chr) {
if (!qemu_chr_fe_get_driver(&scon->chr)) {
/* If there's no backend, we can just say we consumed all data. */
return len;
}
/* XXX this blocks entire thread. Rewrite to use
* 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)
@ -312,9 +312,8 @@ static int console_init(SCLPEvent *event)
}
console_available = true;
if (scon->chr) {
qemu_chr_add_handlers(scon->chr, chr_can_read, chr_read, NULL, scon);
}
qemu_chr_fe_set_handlers(&scon->chr, chr_can_read,
chr_read, NULL, scon, NULL, true);
return 0;
}

View File

@ -31,7 +31,7 @@ typedef struct ASCIIConsoleData {
typedef struct SCLPConsole {
SCLPEvent event;
CharDriverState *chr;
CharBackend chr;
uint8_t iov[SIZE_BUFFER_VT220];
uint32_t iov_sclp; /* offset in buf for SCLP 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);
if (!scon->chr) {
if (!qemu_chr_fe_get_driver(&scon->chr)) {
/* If there's no backend, we can just say we consumed all data. */
return len;
}
/* XXX this blocks entire thread. Rewrite to use
* 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)
@ -227,10 +227,8 @@ static int console_init(SCLPEvent *event)
return -1;
}
console_available = true;
if (scon->chr) {
qemu_chr_add_handlers(scon->chr, chr_can_read,
chr_read, NULL, scon);
}
qemu_chr_fe_set_handlers(&scon->chr, chr_can_read,
chr_read, NULL, scon, NULL, true);
return 0;
}

View File

@ -133,13 +133,14 @@ static void serial_isa_init(ISABus *bus, int index, CharDriverState *chr)
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;
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]) {
serial_isa_init(bus, i, serial_hds[i]);
}

View File

@ -153,8 +153,9 @@ static void serial_update_parameters(SerialState *s)
int speed, parity, data_bits, stop_bits, frame_size;
QEMUSerialSetParams ssp;
if (s->divider == 0)
if (s->divider == 0 || s->divider > s->baudbase) {
return;
}
/* Start bit. */
frame_size = 1;
@ -181,7 +182,7 @@ static void serial_update_parameters(SerialState *s)
ssp.data_bits = data_bits;
ssp.stop_bits = stop_bits;
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",
speed, parity, data_bits, stop_bits);
@ -194,7 +195,8 @@ static void serial_update_msl(SerialState *s)
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;
return;
}
@ -259,11 +261,12 @@ static void serial_xmit(SerialState *s)
if (s->mcr & UART_MCR_LOOP) {
/* in loopback mode, say that we just received a char */
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) {
assert(s->watch_tag == 0);
s->watch_tag = qemu_chr_fe_add_watch(s->chr, G_IO_OUT|G_IO_HUP,
serial_watch_cb, s);
s->watch_tag =
qemu_chr_fe_add_watch(&s->chr, G_IO_OUT | G_IO_HUP,
serial_watch_cb, s);
if (s->watch_tag > 0) {
s->tsr_retry++;
return;
@ -416,8 +419,8 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val,
break_enable = (val >> 6) & 1;
if (break_enable != s->last_break_enable) {
s->last_break_enable = break_enable;
qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_BREAK,
&break_enable);
qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_BREAK,
&break_enable);
}
}
break;
@ -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) {
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);
@ -440,7 +443,7 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val,
if (val & UART_MCR_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
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);
@ -485,7 +488,7 @@ static uint64_t serial_ioport_read(void *opaque, hwaddr addr, unsigned size)
serial_update_irq(s);
if (!(s->mcr & UART_MCR_LOOP)) {
/* in loopback mode, don't receive any data */
qemu_chr_accept_input(s->chr);
qemu_chr_fe_accept_input(&s->chr);
}
}
break;
@ -658,7 +661,7 @@ static int serial_post_load(void *opaque, int version_id)
}
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);
} else {
/* 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)
{
if (!s->chr) {
if (!qemu_chr_fe_get_driver(&s->chr)) {
error_setg(errp, "Can't create serial device, empty char device");
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);
qemu_register_reset(serial_reset, s);
qemu_chr_add_handlers(s->chr, serial_can_receive1, serial_receive1,
serial_event, s);
qemu_chr_fe_set_handlers(&s->chr, serial_can_receive1, serial_receive1,
serial_event, s, NULL, true);
fifo8_create(&s->recv_fifo, UART_FIFO_LENGTH);
fifo8_create(&s->xmit_fifo, UART_FIFO_LENGTH);
serial_reset(s);
@ -902,7 +905,7 @@ void serial_realize_core(SerialState *s, Error **errp)
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);
}
@ -932,7 +935,7 @@ SerialState *serial_init(int base, qemu_irq irq, int baudbase,
s->irq = irq;
s->baudbase = baudbase;
s->chr = chr;
qemu_chr_fe_init(&s->chr, chr, &error_abort);
serial_realize_core(s, &error_fatal);
vmstate_register(NULL, base, &vmstate_serial, s);
@ -989,7 +992,7 @@ SerialState *serial_mm_init(MemoryRegion *address_space,
s->it_shift = it_shift;
s->irq = irq;
s->baudbase = baudbase;
s->chr = chr;
qemu_chr_fe_init(&s->chr, chr, &error_abort);
serial_realize_core(s, &error_fatal);
vmstate_register(NULL, base, &vmstate_serial, s);

View File

@ -29,6 +29,7 @@
#include "hw/sh4/sh.h"
#include "sysemu/char.h"
#include "exec/address-spaces.h"
#include "qapi/error.h"
//#define DEBUG_SERIAL
@ -62,7 +63,7 @@ typedef struct {
int flags;
int rtrg;
CharDriverState *chr;
CharBackend chr;
qemu_irq eri;
qemu_irq rxi;
@ -109,11 +110,11 @@ static void sh_serial_write(void *opaque, hwaddr offs,
}
return;
case 0x0c: /* FTDR / TDR */
if (s->chr) {
if (qemu_chr_fe_get_driver(&s->chr)) {
ch = val;
/* XXX this blocks entire thread. Rewrite to use
* 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->flags &= ~SH_SERIAL_FLAG_TDE;
@ -395,12 +396,11 @@ void sh_serial_init(MemoryRegion *sysmem,
0, 0x28);
memory_region_add_subregion(sysmem, A7ADDR(base), &s->iomem_a7);
s->chr = chr;
if (chr) {
qemu_chr_fe_claim_no_fail(chr);
qemu_chr_add_handlers(chr, sh_serial_can_receive1, sh_serial_receive1,
sh_serial_event, s);
qemu_chr_fe_init(&s->chr, chr, &error_abort);
qemu_chr_fe_set_handlers(&s->chr, sh_serial_can_receive1,
sh_serial_receive1,
sh_serial_event, s, NULL, true);
}
s->eri = eri_source;

View File

@ -11,7 +11,7 @@
typedef struct VIOsPAPRVTYDevice {
VIOsPAPRDevice sdev;
CharDriverState *chardev;
CharBackend chardev;
uint32_t in, out;
uint8_t buf[VTERM_BUFSIZE];
} VIOsPAPRVTYDevice;
@ -51,7 +51,7 @@ static int vty_getchars(VIOsPAPRDevice *sdev, uint8_t *buf, int max)
buf[n++] = dev->buf[dev->out++ % VTERM_BUFSIZE];
}
qemu_chr_accept_input(dev->chardev);
qemu_chr_fe_accept_input(&dev->chardev);
return n;
}
@ -62,20 +62,20 @@ void vty_putchars(VIOsPAPRDevice *sdev, uint8_t *buf, int len)
/* XXX this blocks entire thread. Rewrite to use
* 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)
{
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");
return;
}
qemu_chr_add_handlers(dev->chardev, vty_can_receive,
vty_receive, NULL, dev);
qemu_chr_fe_set_handlers(&dev->chardev, vty_can_receive,
vty_receive, NULL, dev, NULL, true);
}
/* Forward declaration */

View File

@ -97,17 +97,13 @@ static uint64_t stm32f2xx_usart_read(void *opaque, hwaddr addr,
case USART_SR:
retvalue = s->usart_sr;
s->usart_sr &= ~USART_SR_TC;
if (s->chr) {
qemu_chr_accept_input(s->chr);
}
qemu_chr_fe_accept_input(&s->chr);
return retvalue;
case 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_RXNE;
if (s->chr) {
qemu_chr_accept_input(s->chr);
}
qemu_chr_fe_accept_input(&s->chr);
qemu_set_irq(s->irq, 0);
return s->usart_dr & 0x3FF;
case USART_BRR:
@ -152,11 +148,9 @@ static void stm32f2xx_usart_write(void *opaque, hwaddr addr,
case USART_DR:
if (value < 0xF000) {
ch = value;
if (s->chr) {
/* XXX this blocks entire thread. Rewrite to use
* qemu_chr_fe_write and background I/O callbacks */
qemu_chr_fe_write_all(s->chr, &ch, 1);
}
/* XXX this blocks entire thread. Rewrite to use
* qemu_chr_fe_write and background I/O callbacks */
qemu_chr_fe_write_all(&s->chr, &ch, 1);
s->usart_sr |= USART_SR_TC;
s->usart_sr &= ~USART_SR_TXE;
}
@ -212,10 +206,8 @@ static void stm32f2xx_usart_realize(DeviceState *dev, Error **errp)
{
STM32F2XXUsartState *s = STM32F2XX_USART(dev);
if (s->chr) {
qemu_chr_add_handlers(s->chr, stm32f2xx_usart_can_receive,
stm32f2xx_usart_receive, NULL, s);
}
qemu_chr_fe_set_handlers(&s->chr, stm32f2xx_usart_can_receive,
stm32f2xx_usart_receive, NULL, s, NULL, true);
}
static void stm32f2xx_usart_class_init(ObjectClass *klass, void *data)

View File

@ -24,7 +24,7 @@
typedef struct VirtConsole {
VirtIOSerialPort parent_obj;
CharDriverState *chr;
CharBackend chr;
guint watch;
} VirtConsole;
@ -49,12 +49,12 @@ static ssize_t flush_buf(VirtIOSerialPort *port,
VirtConsole *vcon = VIRTIO_CONSOLE(port);
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. */
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);
if (ret < len) {
@ -92,7 +92,7 @@ static ssize_t flush_buf(VirtIOSerialPort *port,
if (!k->is_console) {
virtio_serial_throttle_port(port, true);
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,
chr_write_unblocked, vcon);
}
@ -108,8 +108,8 @@ static void set_guest_connected(VirtIOSerialPort *port, int guest_connected)
DeviceState *dev = DEVICE(port);
VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(port);
if (vcon->chr && !k->is_console) {
qemu_chr_fe_set_open(vcon->chr, guest_connected);
if (!k->is_console) {
qemu_chr_fe_set_open(&vcon->chr, guest_connected);
}
if (dev->id) {
@ -122,9 +122,7 @@ static void guest_writable(VirtIOSerialPort *port)
{
VirtConsole *vcon = VIRTIO_CONSOLE(port);
if (vcon->chr) {
qemu_chr_accept_input(vcon->chr);
}
qemu_chr_fe_accept_input(&vcon->chr);
}
/* 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);
VirtConsole *vcon = VIRTIO_CONSOLE(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) {
error_setg(errp, "Port number 0 on virtio-serial devices reserved "
@ -177,7 +176,7 @@ static void virtconsole_realize(DeviceState *dev, Error **errp)
return;
}
if (vcon->chr) {
if (chr) {
/*
* For consoles we don't block guest data transfer just
* 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
*/
if (k->is_console) {
vcon->chr->explicit_fe_open = 0;
qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read,
NULL, vcon);
qemu_chr_fe_set_handlers(&vcon->chr, chr_can_read, chr_read,
NULL, vcon, NULL, true);
virtio_serial_open(port);
} else {
vcon->chr->explicit_fe_open = 1;
qemu_chr_add_handlers(vcon->chr, chr_can_read, chr_read,
chr_event, vcon);
qemu_chr_fe_set_handlers(&vcon->chr, chr_can_read, chr_read,
chr_event, vcon, NULL, false);
}
}
}

View File

@ -23,9 +23,11 @@
#include <sys/select.h>
#include <termios.h>
#include "qapi/error.h"
#include "hw/hw.h"
#include "sysemu/char.h"
#include "hw/xen/xen_backend.h"
#include "qapi/error.h"
#include <xen/io/console.h>
@ -43,7 +45,7 @@ struct XenConsole {
char console[XEN_BUFSIZE];
int ring_ref;
void *sring;
CharDriverState *chr;
CharBackend chr;
int backlog;
};
@ -148,11 +150,13 @@ static void xencons_send(struct XenConsole *con)
ssize_t len, size;
size = con->buffer.size - con->buffer.consumed;
if (con->chr)
len = qemu_chr_fe_write(con->chr, con->buffer.data + con->buffer.consumed,
size);
else
if (qemu_chr_fe_get_driver(&con->chr)) {
len = qemu_chr_fe_write(&con->chr,
con->buffer.data + con->buffer.consumed,
size);
} else {
len = size;
}
if (len < 1) {
if (!con->backlog) {
con->backlog = 1;
@ -196,13 +200,18 @@ static int con_init(struct XenDevice *xendev)
/* no Xen override, use qemu output device */
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 {
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:
g_free(type);
@ -235,17 +244,8 @@ static int con_initialise(struct XenDevice *xendev)
return -1;
xen_be_bind_evtchn(&con->xendev);
if (con->chr) {
if (qemu_chr_fe_claim(con->chr) == 0) {
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;
}
}
qemu_chr_fe_set_handlers(&con->chr, xencons_can_receive,
xencons_receive, NULL, con, NULL, true);
xen_be_printf(xendev, 1, "ring mfn %d, remote port %d, local port %d, limit %zd\n",
con->ring_ref,
@ -259,10 +259,7 @@ static void con_disconnect(struct XenDevice *xendev)
{
struct XenConsole *con = container_of(xendev, struct XenConsole, xendev);
if (con->chr) {
qemu_chr_add_handlers(con->chr, NULL, NULL, NULL, NULL);
qemu_chr_fe_release(con->chr);
}
qemu_chr_fe_deinit(&con->chr);
xen_be_unbind_evtchn(&con->xendev);
if (con->sring) {

View File

@ -55,7 +55,7 @@ typedef struct XilinxUARTLite {
SysBusDevice parent_obj;
MemoryRegion mmio;
CharDriverState *chr;
CharBackend chr;
qemu_irq irq;
uint8_t rx_fifo[8];
@ -107,7 +107,7 @@ uart_read(void *opaque, hwaddr addr, unsigned int size)
s->rx_fifo_len--;
uart_update_status(s);
uart_update_irq(s);
qemu_chr_accept_input(s->chr);
qemu_chr_fe_accept_input(&s->chr);
break;
default:
@ -143,11 +143,9 @@ uart_write(void *opaque, hwaddr addr,
break;
case R_TX:
if (s->chr)
/* XXX this blocks entire thread. Rewrite to use
* qemu_chr_fe_write and background I/O callbacks */
qemu_chr_fe_write_all(s->chr, &ch, 1);
/* XXX this blocks entire thread. Rewrite to use
* qemu_chr_fe_write and background I/O callbacks */
qemu_chr_fe_write_all(&s->chr, &ch, 1);
s->regs[addr] = value;
/* hax. */
@ -213,8 +211,8 @@ static void xilinx_uartlite_realize(DeviceState *dev, Error **errp)
{
XilinxUARTLite *s = XILINX_UARTLITE(dev);
if (s->chr)
qemu_chr_add_handlers(s->chr, uart_can_rx, uart_rx, uart_event, s);
qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx,
uart_event, s, NULL, true);
}
static void xilinx_uartlite_init(Object *obj)

View File

@ -160,55 +160,67 @@ PropertyInfo qdev_prop_drive = {
/* --- character device --- */
static void parse_chr(DeviceState *dev, const char *str, void **ptr,
const char *propname, Error **errp)
static void get_chr(Object *obj, Visitor *v, const char *name, void *opaque,
Error **errp)
{
CharDriverState *chr = qemu_chr_find(str);
if (chr == NULL) {
DeviceState *dev = DEVICE(obj);
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'",
object_get_typename(OBJECT(dev)), propname, str);
object_get_typename(obj), prop->name, str);
return;
}
if (qemu_chr_fe_claim(chr) != 0) {
error_setg(errp, "Property '%s.%s' can't take value '%s', it's in use",
object_get_typename(OBJECT(dev)), propname, str);
if (!qemu_chr_fe_init(be, s, errp)) {
error_prepend(errp, "Property '%s.%s' can't take value '%s': ",
object_get_typename(obj), prop->name, str);
return;
}
*ptr = chr;
}
static void release_chr(Object *obj, const char *name, void *opaque)
{
DeviceState *dev = DEVICE(obj);
Property *prop = opaque;
CharDriverState **ptr = qdev_get_prop_ptr(dev, prop);
CharDriverState *chr = *ptr;
CharBackend *be = qdev_get_prop_ptr(dev, prop);
if (chr) {
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);
qemu_chr_fe_deinit(be);
}
PropertyInfo qdev_prop_chr = {

View File

@ -1589,7 +1589,7 @@ void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
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);
a20_line = qemu_allocate_irqs(handle_a20_line_change, first_cpu, 2);

View File

@ -62,7 +62,7 @@
typedef struct IPMIBmcExtern {
IPMIBmc parent;
CharDriverState *chr;
CharBackend chr;
bool connected;
@ -105,7 +105,7 @@ static void continue_send(IPMIBmcExtern *ibe)
goto check_reset;
}
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);
if (ret > 0) {
ibe->outpos += ret;
@ -442,12 +442,13 @@ static void ipmi_bmc_extern_realize(DeviceState *dev, Error **errp)
{
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");
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)

View File

@ -283,7 +283,7 @@ static void pc87312_realize(DeviceState *dev, Error **errp)
/* FIXME use a qdev chardev prop instead of parallel_hds[] */
chr = parallel_hds[0];
if (chr == NULL) {
chr = qemu_chr_new("par0", "null", NULL);
chr = qemu_chr_new("par0", "null");
}
isa = isa_create(bus, "isa-parallel");
d = DEVICE(isa);
@ -303,7 +303,7 @@ static void pc87312_realize(DeviceState *dev, Error **errp)
chr = serial_hds[i];
if (chr == NULL) {
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");
d = DEVICE(isa);

View File

@ -374,7 +374,7 @@ static void mips_fulong2e_init(MachineState *machine)
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);
/* Sound card */

View File

@ -85,9 +85,10 @@ typedef struct {
uint32_t i2coe;
uint32_t i2cout;
uint32_t i2csel;
CharDriverState *display;
CharBackend display;
char display_text[9];
SerialState *uart;
bool display_inited;
} MaltaFPGAState;
#define TYPE_MIPS_MALTA "mips-malta"
@ -124,8 +125,10 @@ static void malta_fpga_update_display(void *opaque)
}
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, "\n\n\n\n|\e[31m%-8.8s\e[00m|", s->display_text);
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, "\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, " ");
}
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");
qemu_chr_fe_printf(chr, "+--------+\r\n");
qemu_chr_fe_printf(chr, "+ +\r\n");
qemu_chr_fe_printf(chr, "+--------+\r\n");
qemu_chr_fe_printf(chr, "\n");
qemu_chr_fe_printf(chr, "Malta ASCII\r\n");
qemu_chr_fe_printf(chr, "+--------+\r\n");
qemu_chr_fe_printf(chr, "+ +\r\n");
qemu_chr_fe_printf(chr, "+--------+\r\n");
MaltaFPGAState *s = opaque;
if (event == CHR_EVENT_OPENED && !s->display_inited) {
qemu_chr_fe_printf(&s->display, "\e[HMalta LEDBAR\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");
qemu_chr_fe_printf(&s->display, "\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,
hwaddr base, qemu_irq uart_irq, CharDriverState *uart_chr)
{
MaltaFPGAState *s;
CharDriverState *chr;
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 + 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,
230400, uart_chr, DEVICE_NATIVE_ENDIAN);
@ -1025,7 +1037,7 @@ void mips_malta_init(MachineState *machine)
if (!serial_hds[i]) {
char label[32];
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");
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);
for(i = 0; i < MAX_FD; i++) {

View File

@ -286,7 +286,7 @@ void mips_r4k_init(MachineState *machine)
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);

View File

@ -88,7 +88,7 @@ typedef struct IVShmemState {
/* exactly one of these two may be set */
HostMemoryBackend *hostmem; /* with interrupts */
CharDriverState *server_chr; /* without interrupts */
CharBackend server_chr; /* without interrupts */
/* registers */
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);
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);
if (err) {
@ -642,8 +642,8 @@ static int64_t ivshmem_recv_msg(IVShmemState *s, int *pfd, Error **errp)
n = 0;
do {
ret = qemu_chr_fe_read_all(s->server_chr, (uint8_t *)&msg + n,
sizeof(msg) - n);
ret = qemu_chr_fe_read_all(&s->server_chr, (uint8_t *)&msg + n,
sizeof(msg) - n);
if (ret < 0 && ret != -EINTR) {
error_setg_errno(errp, -ret, "read from server failed");
return INT64_MIN;
@ -651,7 +651,7 @@ static int64_t ivshmem_recv_msg(IVShmemState *s, int *pfd, Error **errp)
n += ret;
} while (n < sizeof(msg));
*pfd = qemu_chr_fe_get_msgfd(s->server_chr);
*pfd = qemu_chr_fe_get_msgfd(&s->server_chr);
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,
&error_abort);
} 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",
s->server_chr->filename);
chr->filename);
/* we allocate enough space for 16 peers and grow as needed */
resize_peers(s, 16);
@ -893,8 +894,8 @@ static void ivshmem_common_realize(PCIDevice *dev, Error **errp)
return;
}
qemu_chr_add_handlers(s->server_chr, ivshmem_can_receive,
ivshmem_read, NULL, s);
qemu_chr_fe_set_handlers(&s->server_chr, ivshmem_can_receive,
ivshmem_read, NULL, s, NULL, true);
if (ivshmem_setup_interrupts(s) < 0) {
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);
if (!s->server_chr) {
if (!qemu_chr_fe_get_driver(&s->server_chr)) {
error_setg(errp, "You must specify a 'chardev'");
return;
}
@ -1250,7 +1251,7 @@ static void ivshmem_realize(PCIDevice *dev, Error **errp)
" 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'");
return;
}

View File

@ -824,7 +824,7 @@ static void sun4uv_init(MemoryRegion *address_space_mem,
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);
for(i = 0; i < nb_nics; i++)

View File

@ -607,6 +607,7 @@ static void xilinx_spips_realize(DeviceState *dev, Error **errp)
XilinxSPIPS *s = XILINX_SPIPS(dev);
SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
XilinxSPIPSClass *xsc = XILINX_SPIPS_GET_CLASS(s);
qemu_irq *cs;
int i;
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);
ssi_auto_connect_slaves(DEVICE(s), s->cs_lines, s->spi[0]);
ssi_auto_connect_slaves(DEVICE(s), s->cs_lines, s->spi[1]);
for (i = 0, cs = s->cs_lines; i < s->num_busses; ++i, cs += s->num_cs) {
ssi_auto_connect_slaves(DEVICE(s), cs, s->spi[i]);
}
sysbus_init_irq(sbd, &s->irq);
for (i = 0; i < s->num_cs * s->num_busses; ++i) {
sysbus_init_irq(sbd, &s->cs_lines[i]);

View File

@ -48,7 +48,7 @@ typedef struct PassthruState PassthruState;
struct PassthruState {
CCIDCardState base;
CharDriverState *cs;
CharBackend cs;
uint8_t vscard_in_data[VSCARD_IN_SIZE];
uint32_t vscard_in_pos;
uint32_t vscard_in_hdr;
@ -77,9 +77,9 @@ static void ccid_card_vscard_send_msg(PassthruState *s,
scr_msg_header.length = htonl(length);
/* XXX this blocks entire thread. Rewrite to use
* 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));
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,
@ -264,7 +264,10 @@ static void ccid_card_vscard_handle_message(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;
}
@ -309,8 +312,6 @@ static void ccid_card_vscard_event(void *opaque, int event)
case CHR_EVENT_BREAK:
card->vscard_in_pos = card->vscard_in_hdr = 0;
break;
case CHR_EVENT_FOCUS:
break;
case CHR_EVENT_OPENED:
DPRINTF(card, D_INFO, "%s: CHR_EVENT_OPENED\n", __func__);
break;
@ -324,7 +325,7 @@ static void passthru_apdu_from_guest(
{
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);
return;
}
@ -345,12 +346,12 @@ static int passthru_initfn(CCIDCardState *base)
card->vscard_in_pos = 0;
card->vscard_in_hdr = 0;
if (card->cs) {
if (qemu_chr_fe_get_driver(&card->cs)) {
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_read,
ccid_card_vscard_event, card);
ccid_card_vscard_event, card, NULL, true);
ccid_card_vscard_send_init(card);
} else {
error_report("missing chardev");

View File

@ -103,7 +103,7 @@ typedef struct {
uint8_t event_trigger;
QEMUSerialSetParams params;
int latency; /* ms */
CharDriverState *cs;
CharBackend cs;
} USBSerialState;
#define TYPE_USB_SERIAL "usb-serial-dev"
@ -209,8 +209,10 @@ static uint8_t usb_get_modem_lines(USBSerialState *s)
int flags;
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;
}
ret = 0;
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:
{
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_RTS)
flags |= CHR_TIOCM_RTS;
@ -273,7 +275,7 @@ static void usb_serial_handle_control(USBDevice *dev, USBPacket *p,
else
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;
}
case DeviceOutVendor | FTDI_SET_FLOW_CTRL:
@ -292,7 +294,7 @@ static void usb_serial_handle_control(USBDevice *dev, USBPacket *p,
divisor = 1;
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;
}
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);
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 */
break;
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;
/* XXX this blocks entire thread. Rewrite to use
* 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;
break;
@ -464,8 +466,6 @@ static void usb_serial_event(void *opaque, int event)
case CHR_EVENT_BREAK:
s->event_trigger |= FTDI_BI;
break;
case CHR_EVENT_FOCUS:
break;
case CHR_EVENT_OPENED:
if (!s->dev.attached) {
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);
Error *local_err = NULL;
CharDriverState *chr = qemu_chr_fe_get_driver(&s->cs);
usb_desc_create_serial(dev);
usb_desc_init(dev);
dev->auto_attach = 0;
if (!s->cs) {
if (!chr) {
error_setg(errp, "Property chardev is required");
return;
}
@ -499,11 +500,11 @@ static void usb_serial_realize(USBDevice *dev, Error **errp)
return;
}
qemu_chr_add_handlers(s->cs, usb_serial_can_read, usb_serial_read,
usb_serial_event, s);
qemu_chr_fe_set_handlers(&s->cs, usb_serial_can_read, usb_serial_read,
usb_serial_event, s, NULL, true);
usb_serial_handle_reset(dev);
if (s->cs->be_open && !dev->attached) {
if (chr->be_open && !dev->attached) {
usb_device_attach(dev, &error_abort);
}
}
@ -547,7 +548,7 @@ static USBDevice *usb_serial_init(USBBus *bus, const char *filename)
filename++;
snprintf(label, sizeof(label), "usbserial%d", index++);
cdrv = qemu_chr_new(label, filename, NULL);
cdrv = qemu_chr_new(label, filename);
if (!cdrv)
return NULL;
@ -565,7 +566,7 @@ static USBDevice *usb_braille_init(USBBus *bus, const char *unused)
USBDevice *dev;
CharDriverState *cdrv;
cdrv = qemu_chr_new("braille", "braille", NULL);
cdrv = qemu_chr_new("braille", "braille");
if (!cdrv)
return NULL;

View File

@ -105,7 +105,7 @@ struct PacketIdQueue {
struct USBRedirDevice {
USBDevice dev;
/* Properties */
CharDriverState *cs;
CharBackend cs;
uint8_t debug;
char *filter_str;
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)
{
USBRedirDevice *dev = priv;
CharDriverState *chr = qemu_chr_fe_get_driver(&dev->cs);
int r;
if (!dev->cs->be_open) {
if (!chr->be_open) {
return 0;
}
@ -294,10 +295,10 @@ static int usbredir_write(void *priv, uint8_t *data, int count)
return 0;
}
r = qemu_chr_fe_write(dev->cs, data, count);
r = qemu_chr_fe_write(&dev->cs, data, count);
if (r < count) {
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);
}
if (r < 0) {
@ -1375,7 +1376,7 @@ static void usbredir_realize(USBDevice *udev, Error **errp)
USBRedirDevice *dev = USB_REDIRECT(udev);
int i;
if (dev->cs == NULL) {
if (!qemu_chr_fe_get_driver(&dev->cs)) {
error_setg(errp, QERR_MISSING_PARAMETER, "chardev");
return;
}
@ -1406,8 +1407,9 @@ static void usbredir_realize(USBDevice *udev, Error **errp)
dev->compatible_speedmask = USB_SPEED_MASK_FULL | USB_SPEED_MASK_HIGH;
/* Let the backend know we are ready */
qemu_chr_add_handlers(dev->cs, usbredir_chardev_can_read,
usbredir_chardev_read, usbredir_chardev_event, dev);
qemu_chr_fe_set_handlers(&dev->cs, usbredir_chardev_can_read,
usbredir_chardev_read, usbredir_chardev_event,
dev, NULL, true);
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)
{
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 */
qemu_bh_delete(dev->chardev_close_bh);
qemu_bh_delete(dev->device_reject_bh);

View File

@ -116,7 +116,7 @@ static bool ioeventfd_enabled(void)
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;
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,
int *fds, int fd_num)
{
CharDriverState *chr = dev->opaque;
CharBackend *chr = dev->opaque;
int ret, size = VHOST_USER_HDR_SIZE + msg->size;
/*

View File

@ -265,7 +265,7 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine)
}
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),

View File

@ -255,8 +255,9 @@ struct MemoryListener {
hwaddr addr, hwaddr len);
/* Lower = earlier (during add), later (during del) */
unsigned priority;
AddressSpace *address_space_filter;
AddressSpace *address_space;
QTAILQ_ENTRY(MemoryListener) link;
QTAILQ_ENTRY(MemoryListener) link_as;
};
/**
@ -278,7 +279,7 @@ struct AddressSpace {
struct AddressSpaceDispatch *dispatch;
struct AddressSpaceDispatch *next_dispatch;
MemoryListener dispatch_listener;
QTAILQ_HEAD(memory_listeners_as, MemoryListener) listeners;
QTAILQ_ENTRY(AddressSpace) address_spaces_link;
};

View File

@ -22,7 +22,7 @@ typedef struct {
/*< public >*/
MemoryRegion iomem;
CharDriverState *chr;
CharBackend chr;
qemu_irq irq;
uint8_t read_fifo[BCM2835_AUX_RX_FIFO_LEN];

View File

@ -44,7 +44,7 @@ typedef struct {
uint32_t rx_count;
uint32_t tx_count;
uint64_t char_tx_time;
CharDriverState *chr;
CharBackend chr;
qemu_irq irq;
QEMUTimer *fifo_trigger_handle;
} CadenceUARTState;

View File

@ -19,6 +19,7 @@
#define HW_CHAR_DIGIC_UART_H
#include "hw/sysbus.h"
#include "sysemu/char.h"
#define TYPE_DIGIC_UART "digic-uart"
#define DIGIC_UART(obj) \
@ -37,7 +38,7 @@ typedef struct DigicUartState {
/*< public >*/
MemoryRegion regs_region;
CharDriverState *chr;
CharBackend chr;
uint32_t reg_rx;
uint32_t reg_st;

View File

@ -19,6 +19,7 @@
#define IMX_SERIAL_H
#include "hw/sysbus.h"
#include "sysemu/char.h"
#define TYPE_IMX_SERIAL "imx.serial"
#define IMX_SERIAL(obj) OBJECT_CHECK(IMXSerialState, (obj), TYPE_IMX_SERIAL)
@ -96,7 +97,7 @@ typedef struct IMXSerialState {
uint32_t ucr3;
qemu_irq irq;
CharDriverState *chr;
CharBackend chr;
} IMXSerialState;
#endif

View File

@ -28,8 +28,10 @@
#include "hw/hw.h"
#include "sysemu/sysemu.h"
#include "sysemu/char.h"
#include "exec/memory.h"
#include "qemu/fifo8.h"
#include "sysemu/char.h"
#define UART_FIFO_LENGTH 16 /* 16550A Fifo Length */
@ -52,7 +54,7 @@ struct SerialState {
it can be reset while reading iir */
int thr_ipending;
qemu_irq irq;
CharDriverState *chr;
CharBackend chr;
int last_break_enable;
int it_shift;
int baudbase;
@ -94,6 +96,6 @@ SerialState *serial_mm_init(MemoryRegion *address_space,
/* serial-isa.c */
#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

View File

@ -67,7 +67,7 @@ typedef struct {
uint32_t usart_cr3;
uint32_t usart_gtpr;
CharDriverState *chr;
CharBackend chr;
qemu_irq irq;
} STM32F2XXUsartState;
#endif /* HW_STM32F2XX_USART_H */

View File

@ -146,7 +146,7 @@ extern PropertyInfo qdev_prop_arraylen;
DEFINE_PROP(_n, _s, _f, qdev_prop_ptr, void*)
#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_PROP(_n, _s, _f, qdev_prop_string, char*)
#define DEFINE_PROP_NETDEV(_n, _s, _f) \

View File

@ -72,16 +72,16 @@
* Add one here, and similarly in smp_rmb() and smp_read_barrier_depends().
*/
#define smp_mb() ({ barrier(); __atomic_thread_fence(__ATOMIC_SEQ_CST); })
#define smp_wmb() ({ barrier(); __atomic_thread_fence(__ATOMIC_RELEASE); })
#define smp_rmb() ({ barrier(); __atomic_thread_fence(__ATOMIC_ACQUIRE); })
#define smp_mb() ({ barrier(); __atomic_thread_fence(__ATOMIC_SEQ_CST); })
#define smp_mb_release() ({ barrier(); __atomic_thread_fence(__ATOMIC_RELEASE); })
#define smp_mb_acquire() ({ barrier(); __atomic_thread_fence(__ATOMIC_ACQUIRE); })
/* Most compilers currently treat consume and acquire the same, but really
* no processors except Alpha need a barrier here. Leave it in if
* using Thread Sanitizer to avoid warnings, otherwise optimize it away.
*/
#if defined(__SANITIZE_THREAD__)
#define smp_read_barrier_depends() ({ barrier(); __atomic_thread_fence(__ATOMIC_CONSUME); })
#define smp_read_barrier_depends() ({ barrier(); __atomic_thread_fence(__ATOMIC_CONSUME); })
#elif defined(__alpha__)
#define smp_read_barrier_depends() asm volatile("mb":::"memory")
#else
@ -135,44 +135,18 @@
__atomic_store_n(ptr, i, __ATOMIC_RELEASE); \
} while(0)
/* atomic_mb_read/set semantics map Java volatile variables. They are
* 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) \
#define atomic_load_acquire(ptr) \
({ \
QEMU_BUILD_BUG_ON(sizeof(*ptr) > sizeof(void *)); \
typeof_strip_qual(*ptr) _val; \
__atomic_load(ptr, &_val, __ATOMIC_RELAXED); \
smp_rmb(); \
__atomic_load(ptr, &_val, __ATOMIC_ACQUIRE); \
_val; \
})
#define atomic_mb_set(ptr, i) do { \
#define atomic_store_release(ptr, i) do { \
QEMU_BUILD_BUG_ON(sizeof(*ptr) > sizeof(void *)); \
smp_wmb(); \
__atomic_store_n(ptr, i, __ATOMIC_RELAXED); \
smp_mb(); \
__atomic_store_n(ptr, i, __ATOMIC_RELEASE); \
} 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 */
@ -238,8 +212,8 @@
* here (a compiler barrier only). QEMU doesn't do accesses to write-combining
* qemu memory or non-temporal load/stores from C code.
*/
#define smp_wmb() barrier()
#define smp_rmb() barrier()
#define smp_mb_release() barrier()
#define smp_mb_acquire() barrier()
/*
* __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))
/*
* Load/store with Java volatile semantics.
*/
#define atomic_mb_set(ptr, i) ((void)atomic_xchg(ptr, i))
#elif defined(_ARCH_PPC)
/*
@ -263,13 +232,15 @@
* smp_mb has the same problem as on x86 for not-very-new GCC
* (http://patchwork.ozlabs.org/patch/126184/, Nov 2011).
*/
#define smp_wmb() ({ asm volatile("eieio" ::: "memory"); (void)0; })
#define smp_wmb() ({ asm volatile("eieio" ::: "memory"); (void)0; })
#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
#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
#define smp_mb() ({ asm volatile("sync" ::: "memory"); (void)0; })
#define smp_mb() ({ asm volatile("sync" ::: "memory"); (void)0; })
#endif /* _ARCH_PPC */
@ -277,18 +248,18 @@
* For (host) platforms we don't have explicit barrier definitions
* for, we use the gcc __sync_synchronize() primitive to generate a
* 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
#define smp_mb() __sync_synchronize()
#define smp_mb() __sync_synchronize()
#endif
#ifndef smp_wmb
#define smp_wmb() __sync_synchronize()
#ifndef smp_mb_acquire
#define smp_mb_acquire() __sync_synchronize()
#endif
#ifndef smp_rmb
#define smp_rmb() __sync_synchronize()
#ifndef smp_mb_release
#define smp_mb_release() __sync_synchronize()
#endif
#ifndef smp_read_barrier_depends
@ -341,41 +312,16 @@
atomic_set(ptr, i); \
} while (0)
/* These have the same semantics as Java volatile variables.
* 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) ({ \
#define atomic_load_acquire(ptr) ({ \
typeof(*ptr) _val = atomic_read(ptr); \
smp_rmb(); \
smp_mb_acquire(); \
_val; \
})
#ifndef atomic_mb_set
#define atomic_mb_set(ptr, i) do { \
smp_wmb(); \
#define atomic_store_release(ptr, i) do { \
smp_mb_release(); \
atomic_set(ptr, i); \
smp_mb(); \
} while (0)
#endif
#ifndef atomic_xchg
#if defined(__clang__)
@ -404,4 +350,39 @@
#define atomic_or(ptr, n) ((void) __sync_fetch_and_or(ptr, n))
#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 */

View File

@ -13,12 +13,13 @@
/* character device */
#define CHR_EVENT_BREAK 0 /* serial break char */
#define CHR_EVENT_FOCUS 1 /* focus to this terminal (modal input needed) */
#define CHR_EVENT_OPENED 2 /* new connection established */
#define CHR_EVENT_MUX_IN 3 /* mux-focus was set to this terminal */
#define CHR_EVENT_MUX_OUT 4 /* mux-focus will move on */
#define CHR_EVENT_CLOSED 5 /* connection closed */
typedef enum {
CHR_EVENT_BREAK, /* serial break char */
CHR_EVENT_OPENED, /* new connection established */
CHR_EVENT_MUX_IN, /* mux-focus was set to this terminal */
CHR_EVENT_MUX_OUT, /* mux-focus will move on */
CHR_EVENT_CLOSED /* connection closed */
} QEMUChrEvent;
#define CHR_IOCTL_SERIAL_SET_PARAMS 1
@ -72,10 +73,20 @@ typedef enum {
QEMU_CHAR_FEATURE_LAST,
} 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 {
QemuMutex chr_write_lock;
void (*init)(struct CharDriverState *s);
int (*chr_write)(struct CharDriverState *s, const uint8_t *buf, int len);
int (*chr_sync_read)(struct CharDriverState *s,
const uint8_t *buf, int len);
@ -87,25 +98,17 @@ struct CharDriverState {
int (*set_msgfds)(struct CharDriverState *s, int *fds, int num);
int (*chr_add_client)(struct CharDriverState *chr, int fd);
int (*chr_wait_connected)(struct CharDriverState *chr, Error **errp);
IOEventHandler *chr_event;
IOCanReadHandler *chr_can_read;
IOReadHandler *chr_read;
void *handler_opaque;
void (*chr_close)(struct CharDriverState *chr);
void (*chr_free)(struct CharDriverState *chr);
void (*chr_disconnect)(struct CharDriverState *chr);
void (*chr_accept_input)(struct CharDriverState *chr);
void (*chr_set_echo)(struct CharDriverState *chr, bool echo);
void (*chr_set_fe_open)(struct CharDriverState *chr, int fe_open);
void (*chr_fe_event)(struct CharDriverState *chr, int event);
CharBackend *be;
void *opaque;
char *label;
char *filename;
int logfd;
int be_open;
int fe_open;
int explicit_fe_open;
int explicit_be_open;
int avail_connections;
int is_mux;
guint fd_in_tag;
bool replay;
@ -130,13 +133,11 @@ CharDriverState *qemu_chr_alloc(ChardevCommon *backend, Error **errp);
* Create a new character backend from a QemuOpts list.
*
* @opts see qemu-config.c for a list of valid options
* @init not sure..
*
* Returns: a new character backend
*/
CharDriverState *qemu_chr_new_from_opts(QemuOpts *opts,
void (*init)(struct CharDriverState *s),
Error **errp);
Error **errp);
/**
* @qemu_chr_parse_common:
@ -155,18 +156,19 @@ void qemu_chr_parse_common(QemuOpts *opts, ChardevCommon *backend);
*
* @label the name of the backend
* @filename the URI
* @init not sure..
*
* Returns: a new character backend
*/
CharDriverState *qemu_chr_new(const char *label, const char *filename,
void (*init)(struct CharDriverState *s));
CharDriverState *qemu_chr_new(const char *label, const char *filename);
/**
* @qemu_chr_disconnect:
* @qemu_chr_fe_disconnect:
*
* 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:
@ -176,11 +178,12 @@ void qemu_chr_disconnect(CharDriverState *chr);
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:
@ -191,12 +194,10 @@ int qemu_chr_wait_connected(CharDriverState *chr, Error **errp);
*
* @label the name of the backend
* @filename the URI
* @init not sure..
*
* Returns: a new character backend
*/
CharDriverState *qemu_chr_new_noreplay(const char *label, const char *filename,
void (*init)(struct CharDriverState *s));
CharDriverState *qemu_chr_new_noreplay(const char *label, const char *filename);
/**
* @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
* 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.
* Without associated CharDriver, do nothing.
*
* @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:
*
* Set character frontend open status. This is an indication that the
* 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);
/**
* @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);
void qemu_chr_fe_set_open(CharBackend *be, int fe_open);
/**
* @qemu_chr_fe_printf:
*
* Write to a character backend using a printf style interface.
* This function is thread-safe.
* Write to a character backend using a printf style interface. This
* function is thread-safe. It does nothing without associated
* CharDriver.
*
* @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);
/**
@ -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
* 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,
* return 0.
* or without associated CharDriver, return 0.
*
* @cond the condition to poll for
* @func the function to call when the condition happens
* @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);
/**
@ -277,9 +272,9 @@ guint qemu_chr_fe_add_watch(CharDriverState *s, GIOCondition cond,
* @buf the data
* @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:
@ -292,9 +287,9 @@ int qemu_chr_fe_write(CharDriverState *s, const uint8_t *buf, int len);
* @buf the data
* @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:
@ -304,9 +299,9 @@ int qemu_chr_fe_write_all(CharDriverState *s, const uint8_t *buf, int len);
* @buf the data buffer
* @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:
@ -316,10 +311,11 @@ int qemu_chr_fe_read_all(CharDriverState *s, uint8_t *buf, int len);
* @cmd see CHR_IOCTL_*
* @arg the data associated with @cmd
*
* Returns: if @cmd is not supported by the backend, -ENOTSUP, otherwise the
* return value depends on the semantics of @cmd
* Returns: if @cmd is not supported by the backend or there is no
* 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:
@ -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
* descriptor.
*/
int qemu_chr_fe_get_msgfd(CharDriverState *s);
int qemu_chr_fe_get_msgfd(CharBackend *be);
/**
* @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
* 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:
@ -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.
* 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);
/**
* @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);
int qemu_chr_fe_set_msgfds(CharBackend *be, int *fds, int num);
/**
* @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_add_handlers(CharDriverState *s,
IOCanReadHandler *fd_can_read,
IOReadHandler *fd_read,
IOEventHandler *fd_event,
void *opaque);
/**
* @qemu_chr_fe_init:
*
* Initializes a front end for the given CharBackend and
* 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,
IOCanReadHandler *fd_can_read,
IOReadHandler *fd_read,
IOEventHandler *fd_event,
void *opaque,
GMainContext *context);
/**
* @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,
IOReadHandler *fd_read,
IOEventHandler *fd_event,
void *opaque,
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_accept_input(CharDriverState *s);
void qemu_chr_fe_accept_input(CharBackend *be);
int qemu_chr_add_client(CharDriverState *s, int fd);
CharDriverState *qemu_chr_find(const char *name);
bool chr_is_ringbuf(const CharDriverState *chr);
@ -458,10 +473,15 @@ void qemu_chr_set_feature(CharDriverState *chr,
CharDriverFeature feature);
QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename);
typedef void CharDriverParse(QemuOpts *opts, ChardevBackend *backend,
Error **errp);
typedef CharDriverState *CharDriverCreate(const char *id,
ChardevBackend *backend,
ChardevReturn *ret, bool *be_opened,
Error **errp);
void register_char_driver(const char *name, ChardevBackendKind kind,
void (*parse)(QemuOpts *opts, ChardevBackend *backend, Error **errp),
CharDriverState *(*create)(const char *id, ChardevBackend *backend,
ChardevReturn *ret, Error **errp));
CharDriverParse *parse, CharDriverCreate *create);
extern int term_escape_char;

View File

@ -2215,15 +2215,14 @@ int kvm_sw_breakpoints_active(CPUState *cpu)
struct kvm_set_guest_debug_data {
struct kvm_guest_debug dbg;
CPUState *cpu;
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;
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);
}

View File

@ -3956,7 +3956,7 @@ static void handle_arg_strace(const char *arg)
static void handle_arg_version(const char *arg)
{
printf("qemu-" TARGET_NAME " version " QEMU_VERSION QEMU_PKGVERSION
", " QEMU_COPYRIGHT "\n");
"\n" QEMU_COPYRIGHT "\n");
exit(EXIT_SUCCESS);
}

View File

@ -97,13 +97,6 @@ static AddrRange addrrange_intersection(AddrRange r1, AddrRange r2)
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...) \
do { \
MemoryListener *_listener; \
@ -129,24 +122,23 @@ static bool memory_listener_match(MemoryListener *listener,
} \
} while (0)
#define MEMORY_LISTENER_CALL(_callback, _direction, _section, _args...) \
#define MEMORY_LISTENER_CALL(_as, _callback, _direction, _section, _args...) \
do { \
MemoryListener *_listener; \
struct memory_listeners_as *list = &(_as)->listeners; \
\
switch (_direction) { \
case Forward: \
QTAILQ_FOREACH(_listener, &memory_listeners, link) { \
if (_listener->_callback \
&& memory_listener_match(_listener, _section)) { \
QTAILQ_FOREACH(_listener, list, link_as) { \
if (_listener->_callback) { \
_listener->_callback(_listener, _section, ##_args); \
} \
} \
break; \
case Reverse: \
QTAILQ_FOREACH_REVERSE(_listener, &memory_listeners, \
memory_listeners, link) { \
if (_listener->_callback \
&& memory_listener_match(_listener, _section)) { \
QTAILQ_FOREACH_REVERSE(_listener, list, memory_listeners_as, \
link_as) { \
if (_listener->_callback) { \
_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...) \
do { \
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)
struct CoalescedMemoryRange {
@ -749,7 +741,7 @@ static void address_space_add_del_ioeventfds(AddressSpace *as,
.offset_within_address_space = int128_get64(fd->addr.start),
.size = fd->addr.size,
};
MEMORY_LISTENER_CALL(eventfd_del, Forward, &section,
MEMORY_LISTENER_CALL(as, eventfd_del, Forward, &section,
fd->match_data, fd->data, fd->e);
++iold;
} 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),
.size = fd->addr.size,
};
MEMORY_LISTENER_CALL(eventfd_add, Reverse, &section,
MEMORY_LISTENER_CALL(as, eventfd_add, Reverse, &section,
fd->match_data, fd->data, fd->e);
++inew;
} 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 mask = mr->dirty_log_mask;
if (global_dirty_log) {
if (global_dirty_log && mr->ram_block) {
mask |= (1 << DIRTY_MEMORY_MIGRATION);
}
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)
{
MemoryListener *listener;
AddressSpace *as;
FlatView *view;
FlatRange *fr;
QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
FlatView *view = address_space_get_flatview(as);
/* If the same address space has multiple log_sync listeners, we
* 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) {
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);
@ -1774,7 +1778,7 @@ static void memory_region_update_coalesced_range_as(MemoryRegion *mr, AddressSpa
.size = fr->addr.size,
};
MEMORY_LISTENER_CALL(coalesced_mmio_del, Reverse, &section,
MEMORY_LISTENER_CALL(as, coalesced_mmio_del, Reverse, &section,
int128_get64(fr->addr.start),
int128_get64(fr->addr.size));
QTAILQ_FOREACH(cmr, &mr->coalesced, link) {
@ -1785,7 +1789,7 @@ static void memory_region_update_coalesced_range_as(MemoryRegion *mr, AddressSpa
continue;
}
tmp = addrrange_intersection(tmp, fr->addr);
MEMORY_LISTENER_CALL(coalesced_mmio_add, Forward, &section,
MEMORY_LISTENER_CALL(as, coalesced_mmio_add, Forward, &section,
int128_get64(tmp.start),
int128_get64(tmp.size));
}
@ -2176,13 +2180,13 @@ void memory_global_dirty_log_sync(void)
if (!listener->log_sync) {
continue;
}
/* Global listeners are being phased out. */
assert(listener->address_space_filter);
as = listener->address_space_filter;
as = listener->address_space;
view = address_space_get_flatview(as);
FOR_EACH_FLAT_RANGE(fr, view) {
MemoryRegionSection mrs = section_from_flat_range(fr, as);
listener->log_sync(listener, &mrs);
if (fr->dirty_log_mask) {
MemoryRegionSection mrs = section_from_flat_range(fr, as);
listener->log_sync(listener, &mrs);
}
}
flatview_unref(view);
}
@ -2218,11 +2222,6 @@ static void listener_add_address_space(MemoryListener *listener,
FlatView *view;
FlatRange *fr;
if (listener->address_space_filter
&& listener->address_space_filter != as) {
return;
}
if (listener->begin) {
listener->begin(listener);
}
@ -2255,12 +2254,11 @@ static void listener_add_address_space(MemoryListener *listener,
flatview_unref(view);
}
void memory_listener_register(MemoryListener *listener, AddressSpace *filter)
void memory_listener_register(MemoryListener *listener, AddressSpace *as)
{
MemoryListener *other = NULL;
AddressSpace *as;
listener->address_space_filter = filter;
listener->address_space = as;
if (QTAILQ_EMPTY(&memory_listeners)
|| listener->priority >= QTAILQ_LAST(&memory_listeners,
memory_listeners)->priority) {
@ -2274,14 +2272,26 @@ void memory_listener_register(MemoryListener *listener, AddressSpace *filter)
QTAILQ_INSERT_BEFORE(other, listener, link);
}
QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
listener_add_address_space(listener, as);
if (QTAILQ_EMPTY(&as->listeners)
|| 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)
{
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)
@ -2295,6 +2305,7 @@ void address_space_init(AddressSpace *as, MemoryRegion *root, const char *name)
flatview_init(as->current_map);
as->ioeventfd_nb = 0;
as->ioeventfds = NULL;
QTAILQ_INIT(&as->listeners);
QTAILQ_INSERT_TAIL(&address_spaces, as, address_spaces_link);
as->name = g_strdup(name ? name : "anonymous");
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)
{
MemoryListener *listener;
bool do_free = as->malloced;
address_space_destroy_dispatch(as);
QTAILQ_FOREACH(listener, &memory_listeners, link) {
assert(listener->address_space_filter != as);
}
assert(QTAILQ_EMPTY(&as->listeners));
flatview_unref(as->current_map);
g_free(as->name);

View File

@ -186,7 +186,7 @@ typedef struct {
} MonitorQAPIEventConf;
struct Monitor {
CharDriverState *chr;
CharBackend chr;
int reset_seen;
int flags;
int suspend_cnt;
@ -297,7 +297,7 @@ static void monitor_flush_locked(Monitor *mon)
len = qstring_get_length(mon->outbuf);
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)) {
/* all flushed or error */
QDECREF(mon->outbuf);
@ -311,8 +311,9 @@ static void monitor_flush_locked(Monitor *mon)
mon->outbuf = tmp;
}
if (mon->out_watch == 0) {
mon->out_watch = qemu_chr_fe_add_watch(mon->chr, G_IO_OUT|G_IO_HUP,
monitor_unblocked, mon);
mon->out_watch =
qemu_chr_fe_add_watch(&mon->chr, G_IO_OUT | G_IO_HUP,
monitor_unblocked, mon);
}
}
}
@ -581,9 +582,7 @@ static void monitor_data_init(Monitor *mon)
static void monitor_data_destroy(Monitor *mon)
{
if (mon->chr) {
qemu_chr_add_handlers(mon->chr, NULL, NULL, NULL, NULL);
}
qemu_chr_fe_deinit(&mon->chr);
if (monitor_is_qmp(mon)) {
json_message_parser_destroy(&mon->qmp.parser);
}
@ -1745,7 +1744,7 @@ void qmp_getfd(const char *fdname, Error **errp)
mon_fd_t *monfd;
int fd;
fd = qemu_chr_fe_get_msgfd(cur_mon->chr);
fd = qemu_chr_fe_get_msgfd(&cur_mon->chr);
if (fd == -1) {
error_setg(errp, QERR_FD_NOT_SUPPLIED);
return;
@ -1870,7 +1869,7 @@ AddfdInfo *qmp_add_fd(bool has_fdset_id, int64_t fdset_id, bool has_opaque,
Monitor *mon = cur_mon;
AddfdInfo *fdinfo;
fd = qemu_chr_fe_get_msgfd(mon->chr);
fd = qemu_chr_fe_get_msgfd(&mon->chr);
if (fd == -1) {
error_setg(errp, QERR_FD_NOT_SUPPLIED);
goto error;
@ -3977,7 +3976,7 @@ void monitor_init(CharDriverState *chr, int flags)
mon = g_malloc(sizeof(*mon));
monitor_data_init(mon);
mon->chr = chr;
qemu_chr_fe_init(&mon->chr, chr, &error_abort);
mon->flags = flags;
if (flags & MONITOR_USE_READLINE) {
mon->rs = readline_init(monitor_readline_printf,
@ -3988,13 +3987,13 @@ void monitor_init(CharDriverState *chr, int flags)
}
if (monitor_is_qmp(mon)) {
qemu_chr_add_handlers(chr, monitor_can_read, monitor_qmp_read,
monitor_qmp_event, mon);
qemu_chr_fe_set_echo(chr, true);
qemu_chr_fe_set_handlers(&mon->chr, monitor_can_read, monitor_qmp_read,
monitor_qmp_event, mon, NULL, true);
qemu_chr_fe_set_echo(&mon->chr, true);
json_message_parser_init(&mon->qmp.parser, handle_qmp_command);
} else {
qemu_chr_add_handlers(chr, monitor_can_read, monitor_read,
monitor_event, mon);
qemu_chr_fe_set_handlers(&mon->chr, monitor_can_read, monitor_read,
monitor_event, mon, NULL, true);
}
qemu_mutex_lock(&monitor_lock);

View File

@ -68,9 +68,9 @@ typedef struct CompareState {
char *pri_indev;
char *sec_indev;
char *outdev;
CharDriverState *chr_pri_in;
CharDriverState *chr_sec_in;
CharDriverState *chr_out;
CharBackend chr_pri_in;
CharBackend chr_sec_in;
CharBackend chr_out;
SocketReadState pri_rs;
SocketReadState sec_rs;
@ -101,7 +101,7 @@ enum {
SECONDARY_IN,
};
static int compare_chr_send(CharDriverState *out,
static int compare_chr_send(CharBackend *out,
const uint8_t *buf,
uint32_t size);
@ -385,7 +385,7 @@ static void colo_compare_connection(void *opaque, void *user_data)
}
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) {
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,
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);
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");
}
}
@ -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);
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");
}
}
@ -480,10 +482,10 @@ static void *colo_compare_thread(void *opaque)
worker_context = g_main_context_new();
qemu_chr_add_handlers_full(s->chr_pri_in, compare_chr_can_read,
compare_pri_chr_in, NULL, s, worker_context);
qemu_chr_add_handlers_full(s->chr_sec_in, compare_chr_can_read,
compare_sec_chr_in, NULL, s, worker_context);
qemu_chr_fe_set_handlers(&s->chr_pri_in, compare_chr_can_read,
compare_pri_chr_in, NULL, s, worker_context, true);
qemu_chr_fe_set_handlers(&s->chr_sec_in, compare_chr_can_read,
compare_sec_chr_in, NULL, s, worker_context, true);
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)) {
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 {
/* compare connection */
g_queue_foreach(&s->conn_list, colo_compare_connection, s);
@ -589,6 +591,7 @@ static int find_and_check_chardev(CharDriverState **chr,
chr_name);
return 1;
}
return 0;
}
@ -619,6 +622,7 @@ static void check_old_packet_regular(void *opaque)
static void colo_compare_complete(UserCreatable *uc, Error **errp)
{
CompareState *s = COLO_COMPARE(uc);
CharDriverState *chr;
char thread_name[64];
static int compare_id;
@ -634,24 +638,21 @@ static void colo_compare_complete(UserCreatable *uc, Error **errp)
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;
}
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;
}
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;
}
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->sec_rs, compare_sec_rs_finalize);
@ -702,17 +703,9 @@ static void colo_compare_finalize(Object *obj)
{
CompareState *s = COLO_COMPARE(obj);
if (s->chr_pri_in) {
qemu_chr_add_handlers(s->chr_pri_in, NULL, NULL, NULL, NULL);
qemu_chr_fe_release(s->chr_pri_in);
}
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);
}
qemu_chr_fe_deinit(&s->chr_pri_in);
qemu_chr_fe_deinit(&s->chr_sec_in);
qemu_chr_fe_deinit(&s->chr_out);
g_queue_free(&s->conn_list);

View File

@ -38,12 +38,12 @@ typedef struct MirrorState {
NetFilterState parent_obj;
char *indev;
char *outdev;
CharDriverState *chr_in;
CharDriverState *chr_out;
CharBackend chr_in;
CharBackend chr_out;
SocketReadState rs;
} MirrorState;
static int filter_mirror_send(CharDriverState *chr_out,
static int filter_mirror_send(CharBackend *chr_out,
const struct iovec *iov,
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);
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) {
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;
default:
break;
@ -138,7 +140,7 @@ static ssize_t filter_mirror_receive_iov(NetFilterState *nf,
MirrorState *s = FILTER_MIRROR(nf);
int ret;
ret = filter_mirror_send(s->chr_out, iov, iovcnt);
ret = filter_mirror_send(&s->chr_out, iov, iovcnt);
if (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);
int ret;
if (s->chr_out) {
ret = filter_mirror_send(s->chr_out, iov, iovcnt);
if (qemu_chr_fe_get_driver(&s->chr_out)) {
ret = filter_mirror_send(&s->chr_out, iov, iovcnt);
if (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);
if (s->chr_out) {
qemu_chr_fe_release(s->chr_out);
}
qemu_chr_fe_deinit(&s->chr_out);
}
static void filter_redirector_cleanup(NetFilterState *nf)
{
MirrorState *s = FILTER_REDIRECTOR(nf);
if (s->chr_in) {
qemu_chr_add_handlers(s->chr_in, NULL, NULL, NULL, NULL);
qemu_chr_fe_release(s->chr_in);
}
if (s->chr_out) {
qemu_chr_fe_release(s->chr_out);
}
qemu_chr_fe_deinit(&s->chr_in);
qemu_chr_fe_deinit(&s->chr_out);
}
static void filter_mirror_setup(NetFilterState *nf, Error **errp)
{
MirrorState *s = FILTER_MIRROR(nf);
CharDriverState *chr;
if (!s->outdev) {
error_setg(errp, "filter mirror needs 'outdev' "
@ -203,17 +199,14 @@ static void filter_mirror_setup(NetFilterState *nf, Error **errp)
return;
}
s->chr_out = qemu_chr_find(s->outdev);
if (s->chr_out == NULL) {
chr = qemu_chr_find(s->outdev);
if (chr == NULL) {
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
"Device '%s' not found", s->outdev);
return;
}
if (qemu_chr_fe_claim(s->chr_out) != 0) {
error_setg(errp, QERR_DEVICE_IN_USE, s->outdev);
return;
}
qemu_chr_fe_init(&s->chr_out, chr, errp);
}
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)
{
MirrorState *s = FILTER_REDIRECTOR(nf);
CharDriverState *chr;
if (!s->indev && !s->outdev) {
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);
if (s->indev) {
s->chr_in = qemu_chr_find(s->indev);
if (s->chr_in == NULL) {
chr = qemu_chr_find(s->indev);
if (chr == NULL) {
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
"IN Device '%s' not found", s->indev);
return;
}
qemu_chr_fe_claim_no_fail(s->chr_in);
qemu_chr_add_handlers(s->chr_in, redirector_chr_can_read,
redirector_chr_read, redirector_chr_event, nf);
if (!qemu_chr_fe_init(&s->chr_in, chr, errp)) {
return;
}
qemu_chr_fe_set_handlers(&s->chr_in, redirector_chr_can_read,
redirector_chr_read, redirector_chr_event,
nf, NULL, true);
}
if (s->outdev) {
s->chr_out = qemu_chr_find(s->outdev);
if (s->chr_out == NULL) {
chr = qemu_chr_find(s->outdev);
if (chr == NULL) {
error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
"OUT Device '%s' not found", s->outdev);
return;
}
qemu_chr_fe_claim_no_fail(s->chr_out);
if (!qemu_chr_fe_init(&s->chr_out, chr, errp)) {
return;
}
}
}

View File

@ -40,6 +40,7 @@
#include "sysemu/char.h"
#include "sysemu/sysemu.h"
#include "qemu/cutils.h"
#include "qapi/error.h"
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) */
struct GuestFwd {
CharDriverState *hd;
CharBackend hd;
struct in_addr server;
int port;
Slirp *slirp;
@ -746,15 +747,24 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str,
return -1;
}
} else {
fwd = g_new(struct GuestFwd, 1);
fwd->hd = qemu_chr_new(buf, p, NULL);
if (!fwd->hd) {
Error *err = NULL;
CharDriverState *chr = qemu_chr_new(buf, p);
if (!chr) {
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);
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 "
"rule '%s'", config_str);
g_free(fwd);
@ -764,9 +774,8 @@ static int slirp_guestfwd(SlirpState *s, const char *config_str,
fwd->port = port;
fwd->slirp = s->slirp;
qemu_chr_fe_claim_no_fail(fwd->hd);
qemu_chr_add_handlers(fwd->hd, guestfwd_can_read, guestfwd_read,
NULL, fwd);
qemu_chr_fe_set_handlers(&fwd->hd, guestfwd_can_read, guestfwd_read,
NULL, fwd, NULL, true);
}
return 0;

View File

@ -20,7 +20,7 @@
typedef struct VhostUserState {
NetClientState nc;
CharDriverState *chr;
CharBackend chr; /* only queue index 0 */
VHostNetState *vhost_net;
guint watch;
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;
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]);
options.net_backend = ncs[i];
options.opaque = s->chr;
options.opaque = be;
options.busyloop_timeout = 0;
net = vhost_net_init(&options);
if (!net) {
@ -150,10 +150,8 @@ static void vhost_user_cleanup(NetClientState *nc)
g_free(s->vhost_net);
s->vhost_net = NULL;
}
if (s->chr) {
qemu_chr_add_handlers(s->chr, NULL, NULL, NULL, NULL);
qemu_chr_fe_release(s->chr);
s->chr = NULL;
if (nc->queue_index == 0) {
qemu_chr_fe_deinit(&s->chr);
}
qemu_purge_queued_packets(nc);
@ -187,7 +185,7 @@ static gboolean net_vhost_user_watch(GIOChannel *chan, GIOCondition cond,
{
VhostUserState *s = opaque;
qemu_chr_disconnect(s->chr);
qemu_chr_fe_disconnect(&s->chr);
return FALSE;
}
@ -197,6 +195,7 @@ static void net_vhost_user_event(void *opaque, int event)
const char *name = opaque;
NetClientState *ncs[MAX_QUEUE_NUM];
VhostUserState *s;
CharDriverState *chr;
Error *err = NULL;
int queues;
@ -206,13 +205,14 @@ static void net_vhost_user_event(void *opaque, int event)
assert(queues < MAX_QUEUE_NUM);
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) {
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);
if (vhost_user_start(queues, ncs) < 0) {
qemu_chr_disconnect(s->chr);
if (vhost_user_start(queues, ncs, &s->chr) < 0) {
qemu_chr_fe_disconnect(&s->chr);
return;
}
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,
int queues)
{
Error *err = NULL;
NetClientState *nc, *nc0 = NULL;
VhostUserState *s;
int i;
@ -244,28 +245,28 @@ static int net_vhost_user_init(NetClientState *peer, const char *device,
for (i = 0; i < queues; i++) {
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",
i, chr->label);
nc->queue_index = i;
if (!nc0) {
nc0 = nc;
s = DO_UPCAST(VhostUserState, nc, nc);
if (!qemu_chr_fe_init(&s->chr, chr, &err)) {
error_report_err(err);
return -1;
}
}
s = DO_UPCAST(VhostUserState, nc, nc);
s->chr = chr;
}
s = DO_UPCAST(VhostUserState, nc, nc0);
do {
Error *err = NULL;
if (qemu_chr_wait_connected(chr, &err) < 0) {
if (qemu_chr_fe_wait_connected(&s->chr, &err) < 0) {
error_report_err(err);
return -1;
}
qemu_chr_add_handlers(chr, NULL, NULL,
net_vhost_user_event, nc0->name);
qemu_chr_fe_set_handlers(&s->chr, NULL, NULL,
net_vhost_user_event, nc0->name, NULL, true);
} while (!s->started);
assert(s->vhost_net);
@ -294,8 +295,6 @@ static CharDriverState *net_vhost_claim_chardev(
return NULL;
}
qemu_chr_fe_claim_no_fail(chr);
return chr;
}

File diff suppressed because it is too large Load Diff

View File

@ -44,7 +44,7 @@
#include <getopt.h>
#define QEMU_IMG_VERSION "qemu-img version " QEMU_VERSION QEMU_PKGVERSION \
", " QEMU_COPYRIGHT "\n"
"\n" QEMU_COPYRIGHT "\n"
typedef struct img_cmd_t {
const char *name;

29
qtest.c
View File

@ -38,7 +38,7 @@ bool qtest_allowed;
static DeviceState *irq_intercept_dev;
static FILE *qtest_log_fp;
static CharDriverState *qtest_chr;
static CharBackend qtest_chr;
static GString *inbuf;
static int irq_levels[MAX_IRQ];
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;
@ -218,7 +218,7 @@ static void GCC_FMT_ATTR(1, 2) qtest_log_send(const char *fmt, ...)
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);
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));
}
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, ...)
{
va_list ap;
@ -249,7 +249,7 @@ static void qtest_irq_handler(void *opaque, int n, int level)
qemu_set_irq(old_irq, level);
if (irq_levels[n] != level) {
CharDriverState *chr = qtest_chr;
CharBackend *chr = &qtest_chr;
irq_levels[n] = level;
qtest_send_prefix(chr);
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;
@ -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;
@ -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)
{
CharDriverState *chr = opaque;
CharBackend *chr = opaque;
g_string_append_len(inbuf, (const gchar *)buf, size);
qtest_process_inbuf(chr, inbuf);
@ -670,7 +670,7 @@ void qtest_init(const char *qtest_chrdev, const char *qtest_log, Error **errp)
{
CharDriverState *chr;
chr = qemu_chr_new("qtest", qtest_chrdev, NULL);
chr = qemu_chr_new("qtest", qtest_chrdev);
if (chr == NULL) {
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;
}
qemu_chr_add_handlers(chr, qtest_can_read, qtest_read, qtest_event, chr);
qemu_chr_fe_set_echo(chr, true);
qemu_chr_fe_init(&qtest_chr, chr, errp);
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("");
qtest_chr = chr;
}
bool qtest_driver(void)
{
return qtest_chr;
return qtest_chr.chr != NULL;
}
static void qtest_accel_class_init(ObjectClass *oc, void *data)

View File

@ -199,7 +199,7 @@ static int spice_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
return read_bytes;
}
static void spice_chr_close(struct CharDriverState *chr)
static void spice_chr_free(struct CharDriverState *chr)
{
SpiceCharDriver *s = chr->opaque;
@ -236,15 +236,6 @@ static void spice_port_set_fe_open(struct CharDriverState *chr, int fe_open)
#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)
{
const char** psubtype;
@ -289,10 +280,8 @@ static CharDriverState *chr_open(const char *subtype,
chr->opaque = s;
chr->chr_write = spice_chr_write;
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->explicit_be_open = true;
chr->chr_fe_event = spice_chr_fe_event;
chr->chr_accept_input = spice_chr_accept_input;
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,
ChardevBackend *backend,
ChardevReturn *ret,
bool *be_opened,
Error **errp)
{
ChardevSpiceChannel *spicevmc = backend->u.spicevmc.data;
@ -321,6 +311,7 @@ static CharDriverState *qemu_chr_open_spice_vmc(const char *id,
return NULL;
}
*be_opened = false;
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,
ChardevBackend *backend,
ChardevReturn *ret,
bool *be_opened,
Error **errp)
{
ChardevSpicePort *spiceport = backend->u.spiceport.data;
@ -345,6 +337,7 @@ static CharDriverState *qemu_chr_open_spice_port(const char *id,
if (!chr) {
return NULL;
}
*be_opened = false;
s = chr->opaque;
s->sin.portname = g_strdup(name);

View File

@ -457,13 +457,12 @@ static void gen_lea_v_seg(DisasContext *s, TCGMemOp aflag, TCGv a0,
#endif
case MO_32:
/* 32 bit address */
if (ovr_seg < 0 && s->addseg) {
ovr_seg = def_seg;
}
if (ovr_seg < 0) {
if (s->addseg) {
ovr_seg = def_seg;
} else {
tcg_gen_ext32u_tl(cpu_A0, a0);
return;
}
tcg_gen_ext32u_tl(cpu_A0, a0);
return;
}
break;
case MO_16:
@ -5372,7 +5371,8 @@ static target_ulong disas_insn(CPUX86State *env, DisasContext *s,
{
AddressParts a = gen_lea_modrm_0(env, s, modrm);
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;

View File

@ -2097,15 +2097,9 @@ static void tcg_reg_alloc_bb_end(TCGContext *s, TCGRegSet allocated_regs)
save_globals(s, allocated_regs);
}
static void tcg_reg_alloc_movi(TCGContext *s, const TCGArg *args,
TCGLifeData arg_life)
static void tcg_reg_alloc_do_movi(TCGContext *s, TCGTemp *ots,
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) {
/* For fixed registers, we do not do any constant propagation. */
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,
const TCGArg *args, TCGLifeData arg_life)
{
@ -2141,21 +2144,29 @@ static void tcg_reg_alloc_mov(TCGContext *s, const TCGOpDef *def,
otype = ots->type;
itype = ts->type;
/* If the source value is not in a register, and we're going to be
forced to have it in a register in order to perform the copy,
then 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 (((NEED_SYNC_ARG(0) || ots->fixed_reg) && ts->val_type != TEMP_VAL_REG)
|| ts->val_type == TEMP_VAL_MEM) {
if (ts->val_type == TEMP_VAL_CONST) {
/* propagate constant or generate sti */
tcg_target_ulong val = ts->val;
if (IS_DEAD_ARG(1)) {
temp_dead(s, ts);
}
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);
}
tcg_debug_assert(ts->val_type == TEMP_VAL_REG);
if (IS_DEAD_ARG(0) && !ots->fixed_reg) {
/* mov to a non-saved dead register makes no sense (even with
liveness analysis disabled). */
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) {
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, 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 {
/* 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) {
/* the mov can be suppressed */
if (ots->val_type == TEMP_VAL_REG) {

View File

@ -8,6 +8,8 @@ SYSEMU_TARGET_LIST := $(subst -softmmu.mak,,$(notdir \
check-unit-y = tests/check-qdict$(EXESUF)
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)
gcov-files-check-qfloat-y = qobject/qfloat.c
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-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/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-aio$(EXESUF): tests/test-aio.o $(test-block-obj-y)
tests/test-rfifolock$(EXESUF): tests/test-rfifolock.o $(test-util-obj-y)

View File

@ -193,7 +193,7 @@ static void *thread_func(void *p)
rcu_register_thread();
atomic_inc(&n_ready_threads);
while (!atomic_mb_read(&test_start)) {
while (!atomic_read(&test_start)) {
cpu_relax();
}
@ -393,11 +393,11 @@ static void run_test(void)
while (atomic_read(&n_ready_threads) != n_rw_threads + n_rz_threads) {
cpu_relax();
}
atomic_mb_set(&test_start, true);
atomic_set(&test_start, true);
do {
remaining = sleep(duration);
} while (remaining);
atomic_mb_set(&test_stop, true);
atomic_set(&test_stop, true);
for (i = 0; i < n_rw_threads; i++) {
qemu_thread_join(&rw_threads[i]);

View File

@ -2250,14 +2250,14 @@ SSE_OP(a ## sd);
#define SSE_COMI(op, field)\
{\
unsigned int eflags;\
unsigned long eflags;\
XMMReg a, b;\
a.field[0] = a1;\
b.field[0] = b1;\
asm volatile (#op " %2, %1\n"\
"pushf\n"\
"pop %0\n"\
: "=m" (eflags)\
: "=rm" (eflags)\
: "x" (a.dq), "x" (b.dq));\
printf("%-9s: a=%f b=%f cc=%04x\n",\
#op, a1, b1,\

253
tests/test-char.c Normal file
View 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();
}

View File

@ -11,6 +11,7 @@
#include "qemu/osdep.h"
#include "libqtest.h"
#include "qapi/error.h"
#include "qemu/option.h"
#include "qemu/range.h"
#include "qemu/sockets.h"
@ -19,6 +20,7 @@
#include "libqos/libqos.h"
#include "libqos/pci-pc.h"
#include "libqos/virtio-pci.h"
#include "qapi/error.h"
#include "libqos/pci-pc.h"
#include "libqos/virtio-pci.h"
@ -141,7 +143,7 @@ typedef struct TestServer {
gchar *socket_path;
gchar *mig_path;
gchar *chr_name;
CharDriverState *chr;
CharBackend chr;
int fds_num;
int fds[VHOST_MEMORY_MAX_NREGIONS];
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)
{
TestServer *s = opaque;
CharDriverState *chr = s->chr;
CharBackend *chr = &s->chr;
VhostUserMsg msg;
uint8_t *p = (uint8_t *) &msg;
int fd;
if (s->test_fail) {
qemu_chr_disconnect(chr);
qemu_chr_fe_disconnect(chr);
/* now switch to non-failure */
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),
!=, 0ULL);
if (s->test_flags == TEST_FLAGS_DISCONNECT) {
qemu_chr_disconnect(chr);
qemu_chr_fe_disconnect(chr);
s->test_flags = TEST_FLAGS_BAD;
}
break;
@ -344,7 +346,8 @@ static void chr_read(void *opaque, const uint8_t *buf, int size)
case VHOST_USER_SET_MEM_TABLE:
/* received the mem table */
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 */
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)
{
gchar *chr_path;
CharDriverState *chr;
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);
qemu_chr_add_handlers(server->chr, chr_can_read, chr_read,
chr_event, server);
qemu_chr_fe_init(&server->chr, chr, &error_abort);
qemu_chr_fe_set_handlers(&server->chr, chr_can_read, chr_read,
chr_event, server, NULL, true);
}
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)
{
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++) {
close(server->fds[i]);
@ -721,7 +728,7 @@ reconnect_cb(gpointer user_data)
{
TestServer *s = user_data;
qemu_chr_disconnect(s->chr);
qemu_chr_fe_disconnect(&s->chr);
return FALSE;
}

View File

@ -1083,6 +1083,7 @@ static void kbd_send_chars(void *opaque)
void kbd_put_keysym_console(QemuConsole *s, int keysym)
{
uint8_t buf[16], *q;
CharBackend *be;
int c;
if (!s || (s->console_type == GRAPHIC_CONSOLE))
@ -1125,7 +1126,8 @@ void kbd_put_keysym_console(QemuConsole *s, int keysym)
if (s->echo) {
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);
kbd_send_chars(s);
}
@ -2033,8 +2035,6 @@ static void text_console_do_init(CharDriverState *chr, DisplayState *ds)
}
qemu_chr_be_generic_open(chr);
if (chr->init)
chr->init(chr);
}
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;
chr->opaque = s;
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) {
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 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);
}

View File

@ -1685,9 +1685,6 @@ static CharDriverState *gd_vc_handler(ChardevVC *vc, Error **errp)
/* Temporary, until gd_vc_vte_init runs. */
chr->opaque = g_new0(VirtualConsole, 1);
/* defer OPENED events until our vc is fully initialized */
chr->explicit_be_open = true;
vcs[nb_vcs++] = chr;
return chr;
@ -1789,9 +1786,6 @@ static GSList *gd_vc_vte_init(GtkDisplayState *s, VirtualConsole *vc,
gtk_label_new(vc->label));
qemu_chr_be_generic_open(vc->vte.chr);
if (vc->vte.chr->init) {
vc->vte.chr->init(vc->vte.chr);
}
return group;
}

View File

@ -360,7 +360,11 @@ void qemu_event_destroy(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) {
/* There were waiters, wake them up. */
futex_wake(ev, INT_MAX);
@ -370,7 +374,11 @@ void qemu_event_set(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),
* do nothing. Otherwise change EV_SET->EV_FREE.
@ -383,7 +391,8 @@ void qemu_event_wait(QemuEvent *ev)
{
unsigned value;
value = atomic_mb_read(&ev->value);
value = atomic_read(&ev->value);
smp_mb_acquire();
if (value != EV_SET) {
if (value == EV_FREE) {
/*

View File

@ -274,7 +274,11 @@ void qemu_event_destroy(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) {
/* There were waiters, wake them up. */
SetEvent(ev->event);
@ -284,7 +288,11 @@ void qemu_event_set(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),
* do nothing. Otherwise change EV_SET->EV_FREE.
*/
@ -296,7 +304,8 @@ void qemu_event_wait(QemuEvent *ev)
{
unsigned value;
value = atomic_mb_read(&ev->value);
value = atomic_read(&ev->value);
smp_mb_acquire();
if (value != EV_SET) {
if (value == EV_FREE) {
/* qemu_event_set is not yet going to call SetEvent, but we are

View File

@ -82,14 +82,16 @@ static void wait_for_readers(void)
/* Instead of using atomic_mb_set for index->waiting, and
* atomic_mb_read for index->ctr, memory barriers are placed
* 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, &registry, node) {
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();
QLIST_FOREACH_SAFE(index, &registry, node, tmp) {
@ -104,9 +106,6 @@ static void wait_for_readers(void)
}
}
/* atomic_mb_read has smp_rmb after. */
smp_rmb();
if (QLIST_EMPTY(&registry)) {
break;
}

15
vl.c
View File

@ -1958,7 +1958,7 @@ static void main_loop(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");
}
@ -2369,7 +2369,7 @@ static int chardev_init_func(void *opaque, QemuOpts *opts, Error **errp)
{
Error *local_err = NULL;
qemu_chr_new_from_opts(opts, NULL, &local_err);
qemu_chr_new_from_opts(opts, &local_err);
if (local_err) {
error_report_err(local_err);
return -1;
@ -2417,7 +2417,6 @@ static int mon_init_func(void *opaque, QemuOpts *opts, Error **errp)
exit(1);
}
qemu_chr_fe_claim_no_fail(chr);
monitor_init(chr, flags);
return 0;
}
@ -2514,7 +2513,7 @@ static int serial_parse(const char *devname)
exit(1);
}
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]) {
error_report("could not connect serial device"
" to character backend '%s'", devname);
@ -2536,7 +2535,7 @@ static int parallel_parse(const char *devname)
exit(1);
}
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]) {
error_report("could not connect parallel device"
" 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);
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]) {
error_report("could not connect virtio console"
" 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);
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]) {
error_report("could not connect sclp console"
" to character backend '%s'", devname);
@ -2616,7 +2615,7 @@ static int debugcon_parse(const char *devname)
{
QemuOpts *opts;
if (!qemu_chr_new("debugcon", devname, NULL)) {
if (!qemu_chr_new("debugcon", devname)) {
exit(1);
}
opts = qemu_opts_create(qemu_find_opts("device"), "debugcon", 1, NULL);