* gdbstub fixes (Alex)

* IOMMU MemoryRegion subclass (Alexey)
 * Chardev hotswap (Anton)
 * NBD_OPT_GO support (Eric)
 * Misc bugfixes
 * DEFINE_PROP_LINK (minus the ARM patches - Fam)
 * MAINTAINERS updates (Philippe)
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2.0.22 (GNU/Linux)
 
 iQEcBAABAgAGBQJZaJejAAoJEL/70l94x66DwQ4H/0NUvh/Zfs64wE1iuZJACc24
 1za02fFaB50vFDwQKWbM0GkHzDxoXBHk4Rvn92p+VSxpKtaAX4GRwCvxRA5GeUtm
 GAYbdIJUe0UELepKExrlUVzQcK9VfljoJpK3dZkP5Zzx83L2PAI/SexrZRibN2Uf
 yRI60uvlsMWU12nenzdVnYORd+TWDNKele7BhMrX/FX9wxaS1PlnsnKZggy6CU7G
 8dwZJAZJ/s5tRGXyXyAQzLm5JZQCLnA6jxya540TbPeciFgbvvS2ydIitZ54vSPO
 VtmZ1rSWfTEbNF5xGD1Ztu8aAENr5/I05l6IjxZd45BdUCW3HxeJkc+7lE0K4uk=
 =wnVs
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging

* gdbstub fixes (Alex)
* IOMMU MemoryRegion subclass (Alexey)
* Chardev hotswap (Anton)
* NBD_OPT_GO support (Eric)
* Misc bugfixes
* DEFINE_PROP_LINK (minus the ARM patches - Fam)
* MAINTAINERS updates (Philippe)

# gpg: Signature made Fri 14 Jul 2017 11:06:27 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: (55 commits)
  spapr_rng: Convert to DEFINE_PROP_LINK
  cpu: Convert to DEFINE_PROP_LINK
  mips_cmgcr: Convert to DEFINE_PROP_LINK
  ivshmem: Convert to DEFINE_PROP_LINK
  dimm: Convert to DEFINE_PROP_LINK
  virtio-crypto: Convert to DEFINE_PROP_LINK
  virtio-rng: Convert to DEFINE_PROP_LINK
  virtio-scsi: Convert to DEFINE_PROP_LINK
  virtio-blk: Convert to DEFINE_PROP_LINK
  qdev: Add const qualifier to PropertyInfo definitions
  qmp: Use ObjectProperty.type if present
  qdev: Introduce DEFINE_PROP_LINK
  qdev: Introduce PropertyInfo.create
  qom: enforce readonly nature of link's check callback
  translate-all: remove redundant !tcg_enabled check in dump_exec_info
  vl: fix breakage of -tb-size
  nbd: Implement NBD_INFO_BLOCK_SIZE on client
  nbd: Implement NBD_INFO_BLOCK_SIZE on server
  nbd: Implement NBD_OPT_GO on client
  nbd: Implement NBD_OPT_GO on server
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2017-07-14 12:16:09 +01:00
commit 6c6076662d
123 changed files with 2021 additions and 875 deletions

View File

@ -84,14 +84,10 @@ M: Paolo Bonzini <pbonzini@redhat.com>
M: Peter Crosthwaite <crosthwaite.peter@gmail.com>
M: Richard Henderson <rth@twiddle.net>
S: Maintained
F: cpu-exec.c
F: cpu-exec-common.c
F: cpus.c
F: cputlb.c
F: exec.c
F: softmmu_template.h
F: translate-all.*
F: translate-common.c
F: accel/tcg/
F: include/exec/cpu*.h
F: include/exec/exec-all.h
F: include/exec/helper*.h
@ -277,8 +273,8 @@ Overall
M: Paolo Bonzini <pbonzini@redhat.com>
L: kvm@vger.kernel.org
S: Supported
F: kvm-*
F: */kvm.*
F: accel/kvm/
F: include/sysemu/kvm*.h
ARM
@ -327,7 +323,6 @@ M: Stefano Stabellini <sstabellini@kernel.org>
M: Anthony Perard <anthony.perard@citrix.com>
L: xen-devel@lists.xenproject.org
S: Supported
F: xen-*
F: */xen*
F: hw/9pfs/xen-9p-backend.c
F: hw/char/xen_console.c
@ -1160,6 +1155,13 @@ F: docs/specs/vmgenid.txt
F: tests/vmgenid-test.c
F: stubs/vmgenid.c
Unimplemented device
M: Peter Maydell <peter.maydell@linaro.org>
R: Philippe Mathieu-Daudé <f4bug@amsat.org>
S: Maintained
F: include/hw/misc/unimp.h
F: hw/misc/unimp.c
Subsystems
----------
Audio
@ -1650,7 +1652,7 @@ TCI target
M: Stefan Weil <sw@weilnetz.de>
S: Maintained
F: tcg/tci/
F: tci.c
F: tcg/tci.c
F: disas/tci.c
Block drivers

View File

@ -1851,11 +1851,6 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf)
tb_lock();
if (!tcg_enabled()) {
cpu_fprintf(f, "TCG not enabled\n");
return;
}
target_code_size = 0;
max_target_code_size = 0;
cross_page = 0;

View File

@ -106,7 +106,7 @@ static void rng_egd_opened(RngBackend *b, Error **errp)
/* FIXME we should resubmit pending requests when the CDS reconnects. */
qemu_chr_fe_set_handlers(&s->chr, rng_egd_chr_can_read,
rng_egd_chr_read, NULL, s, NULL, true);
rng_egd_chr_read, NULL, NULL, s, NULL, true);
}
static void rng_egd_set_chardev(Object *obj, const char *value, Error **errp)

View File

@ -242,7 +242,7 @@ int nbd_client_co_pwritev(BlockDriverState *bs, uint64_t offset,
ssize_t ret;
if (flags & BDRV_REQ_FUA) {
assert(client->nbdflags & NBD_FLAG_SEND_FUA);
assert(client->info.flags & NBD_FLAG_SEND_FUA);
request.flags |= NBD_CMD_FLAG_FUA;
}
@ -270,12 +270,12 @@ int nbd_client_co_pwrite_zeroes(BlockDriverState *bs, int64_t offset,
};
NBDReply reply;
if (!(client->nbdflags & NBD_FLAG_SEND_WRITE_ZEROES)) {
if (!(client->info.flags & NBD_FLAG_SEND_WRITE_ZEROES)) {
return -ENOTSUP;
}
if (flags & BDRV_REQ_FUA) {
assert(client->nbdflags & NBD_FLAG_SEND_FUA);
assert(client->info.flags & NBD_FLAG_SEND_FUA);
request.flags |= NBD_CMD_FLAG_FUA;
}
if (!(flags & BDRV_REQ_MAY_UNMAP)) {
@ -299,7 +299,7 @@ int nbd_client_co_flush(BlockDriverState *bs)
NBDReply reply;
ssize_t ret;
if (!(client->nbdflags & NBD_FLAG_SEND_FLUSH)) {
if (!(client->info.flags & NBD_FLAG_SEND_FLUSH)) {
return 0;
}
@ -327,7 +327,7 @@ int nbd_client_co_pdiscard(BlockDriverState *bs, int64_t offset, int bytes)
NBDReply reply;
ssize_t ret;
if (!(client->nbdflags & NBD_FLAG_SEND_TRIM)) {
if (!(client->info.flags & NBD_FLAG_SEND_TRIM)) {
return 0;
}
@ -384,22 +384,24 @@ int nbd_client_init(BlockDriverState *bs,
logout("session init %s\n", export);
qio_channel_set_blocking(QIO_CHANNEL(sioc), true, NULL);
client->info.request_sizes = true;
ret = nbd_receive_negotiate(QIO_CHANNEL(sioc), export,
&client->nbdflags,
tlscreds, hostname,
&client->ioc,
&client->size, errp);
&client->ioc, &client->info, errp);
if (ret < 0) {
logout("Failed to negotiate with the NBD server\n");
return ret;
}
if (client->nbdflags & NBD_FLAG_SEND_FUA) {
if (client->info.flags & NBD_FLAG_SEND_FUA) {
bs->supported_write_flags = BDRV_REQ_FUA;
bs->supported_zero_flags |= BDRV_REQ_FUA;
}
if (client->nbdflags & NBD_FLAG_SEND_WRITE_ZEROES) {
if (client->info.flags & NBD_FLAG_SEND_WRITE_ZEROES) {
bs->supported_zero_flags |= BDRV_REQ_MAY_UNMAP;
}
if (client->info.min_block > bs->bl.request_alignment) {
bs->bl.request_alignment = client->info.min_block;
}
qemu_co_mutex_init(&client->send_mutex);
qemu_co_queue_init(&client->free_sema);

View File

@ -20,8 +20,7 @@
typedef struct NBDClientSession {
QIOChannelSocket *sioc; /* The master data channel */
QIOChannel *ioc; /* The current I/O channel which may differ (eg TLS) */
uint16_t nbdflags;
off_t size;
NBDExportInfo info;
CoMutex send_mutex;
CoQueue free_sema;

View File

@ -472,9 +472,17 @@ static int nbd_co_flush(BlockDriverState *bs)
static void nbd_refresh_limits(BlockDriverState *bs, Error **errp)
{
bs->bl.max_pdiscard = NBD_MAX_BUFFER_SIZE;
bs->bl.max_pwrite_zeroes = NBD_MAX_BUFFER_SIZE;
bs->bl.max_transfer = NBD_MAX_BUFFER_SIZE;
NBDClientSession *s = nbd_get_client_session(bs);
uint32_t max = MIN_NON_ZERO(NBD_MAX_BUFFER_SIZE, s->info.max_block);
bs->bl.max_pdiscard = max;
bs->bl.max_pwrite_zeroes = max;
bs->bl.max_transfer = max;
if (s->info.opt_block &&
s->info.opt_block > bs->bl.opt_transfer) {
bs->bl.opt_transfer = s->info.opt_block;
}
}
static void nbd_close(BlockDriverState *bs)
@ -492,7 +500,7 @@ static int64_t nbd_getlength(BlockDriverState *bs)
{
BDRVNBDState *s = bs->opaque;
return s->client.size;
return s->client.info.size;
}
static void nbd_detach_aio_context(BlockDriverState *bs)

View File

@ -85,6 +85,8 @@ struct emulated_sigtable {
/* NOTE: we force a big alignment so that the stack stored after is
aligned too */
typedef struct TaskState {
pid_t ts_tid; /* tid (or pid) of this task */
struct TaskState *next;
int used; /* non zero if used */
struct image_info *info;

View File

@ -179,9 +179,21 @@ void qemu_chr_fe_printf(CharBackend *be, const char *fmt, ...)
Chardev *qemu_chr_fe_get_driver(CharBackend *be)
{
/* this is unsafe for the users that support chardev hotswap */
assert(be->chr_be_change == NULL);
return be->chr;
}
bool qemu_chr_fe_backend_connected(CharBackend *be)
{
return !!be->chr;
}
bool qemu_chr_fe_backend_open(CharBackend *be)
{
return be->chr && be->chr->be_open;
}
bool qemu_chr_fe_init(CharBackend *b, Chardev *s, Error **errp)
{
int tag = 0;
@ -216,7 +228,7 @@ void qemu_chr_fe_deinit(CharBackend *b, bool del)
assert(b);
if (b->chr) {
qemu_chr_fe_set_handlers(b, NULL, NULL, NULL, NULL, NULL, true);
qemu_chr_fe_set_handlers(b, NULL, NULL, NULL, NULL, NULL, NULL, true);
if (b->chr->be == b) {
b->chr->be = NULL;
}
@ -235,6 +247,7 @@ void qemu_chr_fe_set_handlers(CharBackend *b,
IOCanReadHandler *fd_can_read,
IOReadHandler *fd_read,
IOEventHandler *fd_event,
BackendChangeHandler *be_change,
void *opaque,
GMainContext *context,
bool set_open)
@ -258,6 +271,7 @@ void qemu_chr_fe_set_handlers(CharBackend *b,
b->chr_can_read = fd_can_read;
b->chr_read = fd_read;
b->chr_event = fd_event;
b->chr_be_change = be_change;
b->opaque = opaque;
if (cc->chr_update_read_handler) {
cc->chr_update_read_handler(s, context);

View File

@ -278,6 +278,7 @@ void mux_chr_set_handlers(Chardev *chr, GMainContext *context)
mux_chr_can_read,
mux_chr_read,
mux_chr_event,
NULL,
chr,
context, true);
}

View File

@ -454,7 +454,9 @@ static int tcp_chr_sync_read(Chardev *chr, const uint8_t *buf, int len)
return 0;
}
qio_channel_set_blocking(s->ioc, true, NULL);
size = tcp_chr_recv(chr, (void *) buf, len);
qio_channel_set_blocking(s->ioc, false, NULL);
if (size == 0) {
/* connection closed */
tcp_chr_disconnect(chr);

View File

@ -556,17 +556,23 @@ help_string_append(const char *name, void *opaque)
g_string_append_printf(str, "\n%s", name);
}
Chardev *qemu_chr_new_from_opts(QemuOpts *opts,
Error **errp)
static const char *chardev_alias_translate(const char *name)
{
int i;
for (i = 0; i < (int)ARRAY_SIZE(chardev_alias_table); i++) {
if (g_strcmp0(chardev_alias_table[i].alias, name) == 0) {
return chardev_alias_table[i].typename;
}
}
return name;
}
ChardevBackend *qemu_chr_parse_opts(QemuOpts *opts, Error **errp)
{
Error *local_err = NULL;
const ChardevClass *cc;
Chardev *chr;
int i;
ChardevBackend *backend = NULL;
const char *name = qemu_opt_get(opts, "backend");
const char *id = qemu_opts_id(opts);
char *bid = NULL;
const char *name = chardev_alias_translate(qemu_opt_get(opts, "backend"));
if (name == NULL) {
error_setg(errp, "chardev: \"%s\" missing backend",
@ -574,7 +580,40 @@ Chardev *qemu_chr_new_from_opts(QemuOpts *opts,
return NULL;
}
if (is_help_option(name)) {
cc = char_get_class(name, errp);
if (cc == NULL) {
return NULL;
}
backend = g_new0(ChardevBackend, 1);
backend->type = CHARDEV_BACKEND_KIND_NULL;
if (cc->parse) {
cc->parse(opts, backend, &local_err);
if (local_err) {
error_propagate(errp, local_err);
qapi_free_ChardevBackend(backend);
return NULL;
}
} else {
ChardevCommon *ccom = g_new0(ChardevCommon, 1);
qemu_chr_parse_common(opts, ccom);
backend->u.null.data = ccom; /* Any ChardevCommon member would work */
}
return backend;
}
Chardev *qemu_chr_new_from_opts(QemuOpts *opts, Error **errp)
{
const ChardevClass *cc;
Chardev *chr = NULL;
ChardevBackend *backend = NULL;
const char *name = chardev_alias_translate(qemu_opt_get(opts, "backend"));
const char *id = qemu_opts_id(opts);
char *bid = NULL;
if (name && is_help_option(name)) {
GString *str = g_string_new("");
chardev_name_foreach(help_string_append, str);
@ -589,38 +628,20 @@ Chardev *qemu_chr_new_from_opts(QemuOpts *opts,
return NULL;
}
for (i = 0; i < (int)ARRAY_SIZE(chardev_alias_table); i++) {
if (g_strcmp0(chardev_alias_table[i].alias, name) == 0) {
name = chardev_alias_table[i].typename;
break;
}
backend = qemu_chr_parse_opts(opts, errp);
if (backend == NULL) {
return NULL;
}
cc = char_get_class(name, errp);
if (cc == NULL) {
return NULL;
goto out;
}
backend = g_new0(ChardevBackend, 1);
backend->type = CHARDEV_BACKEND_KIND_NULL;
if (qemu_opt_get_bool(opts, "mux", 0)) {
bid = g_strdup_printf("%s-base", id);
}
chr = NULL;
if (cc->parse) {
cc->parse(opts, backend, &local_err);
if (local_err) {
error_propagate(errp, local_err);
goto out;
}
} else {
ChardevCommon *ccom = g_new0(ChardevCommon, 1);
qemu_chr_parse_common(opts, ccom);
backend->u.null.data = ccom; /* Any ChardevCommon member would work */
}
chr = qemu_chardev_new(bid ? bid : id,
object_class_get_name(OBJECT_CLASS(cc)),
backend, errp);
@ -930,6 +951,89 @@ ChardevReturn *qmp_chardev_add(const char *id, ChardevBackend *backend,
return ret;
}
ChardevReturn *qmp_chardev_change(const char *id, ChardevBackend *backend,
Error **errp)
{
CharBackend *be;
const ChardevClass *cc;
Chardev *chr, *chr_new;
bool closed_sent = false;
ChardevReturn *ret;
chr = qemu_chr_find(id);
if (!chr) {
error_setg(errp, "Chardev '%s' does not exist", id);
return NULL;
}
if (CHARDEV_IS_MUX(chr)) {
error_setg(errp, "Mux device hotswap not supported yet");
return NULL;
}
if (qemu_chr_replay(chr)) {
error_setg(errp,
"Chardev '%s' cannot be changed in record/replay mode", id);
return NULL;
}
be = chr->be;
if (!be) {
/* easy case */
object_unparent(OBJECT(chr));
return qmp_chardev_add(id, backend, errp);
}
if (!be->chr_be_change) {
error_setg(errp, "Chardev user does not support chardev hotswap");
return NULL;
}
cc = char_get_class(ChardevBackendKind_lookup[backend->type], errp);
if (!cc) {
return NULL;
}
chr_new = qemu_chardev_new(NULL, object_class_get_name(OBJECT_CLASS(cc)),
backend, errp);
if (!chr_new) {
return NULL;
}
chr_new->label = g_strdup(id);
if (chr->be_open && !chr_new->be_open) {
qemu_chr_be_event(chr, CHR_EVENT_CLOSED);
closed_sent = true;
}
chr->be = NULL;
qemu_chr_fe_init(be, chr_new, &error_abort);
if (be->chr_be_change(be->opaque) < 0) {
error_setg(errp, "Chardev '%s' change failed", chr_new->label);
chr_new->be = NULL;
qemu_chr_fe_init(be, chr, &error_abort);
if (closed_sent) {
qemu_chr_be_event(chr, CHR_EVENT_OPENED);
}
object_unref(OBJECT(chr_new));
return NULL;
}
object_unparent(OBJECT(chr));
object_property_add_child(get_chardevs_root(), chr_new->label,
OBJECT(chr_new), &error_abort);
object_unref(OBJECT(chr_new));
ret = g_new0(ChardevReturn, 1);
if (CHARDEV_IS_PTY(chr_new)) {
ret->pty = g_strdup(chr_new->filename + 4);
ret->has_pty = true;
}
return ret;
}
void qmp_chardev_remove(const char *id, Error **errp)
{
Chardev *chr;

2
configure vendored
View File

@ -1583,7 +1583,7 @@ gcc_flags="-Wold-style-declaration -Wold-style-definition -Wtype-limits"
gcc_flags="-Wformat-security -Wformat-y2k -Winit-self -Wignored-qualifiers $gcc_flags"
gcc_flags="-Wno-missing-include-dirs -Wempty-body -Wnested-externs $gcc_flags"
gcc_flags="-Wendif-labels -Wno-shift-negative-value $gcc_flags"
gcc_flags="-Wno-initializer-overrides $gcc_flags"
gcc_flags="-Wno-initializer-overrides -Wexpansion-to-defined $gcc_flags"
gcc_flags="-Wno-string-plus-int $gcc_flags"
# Note that we do not add -Werror to gcc_flags here, because that would
# enable it for all configure tests. If a configure test failed due

70
exec.c
View File

@ -27,6 +27,7 @@
#include "exec/target_page.h"
#include "tcg.h"
#include "hw/qdev-core.h"
#include "hw/qdev-properties.h"
#if !defined(CONFIG_USER_ONLY)
#include "hw/boards.h"
#include "hw/xen/xen.h"
@ -480,19 +481,21 @@ static MemoryRegionSection address_space_do_translate(AddressSpace *as,
{
IOMMUTLBEntry iotlb;
MemoryRegionSection *section;
MemoryRegion *mr;
IOMMUMemoryRegion *iommu_mr;
IOMMUMemoryRegionClass *imrc;
for (;;) {
AddressSpaceDispatch *d = atomic_rcu_read(&as->dispatch);
section = address_space_translate_internal(d, addr, &addr, plen, is_mmio);
mr = section->mr;
if (!mr->iommu_ops) {
iommu_mr = memory_region_get_iommu(section->mr);
if (!iommu_mr) {
break;
}
imrc = memory_region_get_iommu_class_nocheck(iommu_mr);
iotlb = mr->iommu_ops->translate(mr, addr, is_write ?
IOMMU_WO : IOMMU_RO);
iotlb = imrc->translate(iommu_mr, addr, is_write ?
IOMMU_WO : IOMMU_RO);
addr = ((iotlb.translated_addr & ~iotlb.addr_mask)
| (addr & iotlb.addr_mask));
*plen = MIN(*plen, (addr | iotlb.addr_mask) - addr + 1);
@ -588,7 +591,7 @@ address_space_translate_for_iotlb(CPUState *cpu, int asidx, hwaddr addr,
section = address_space_translate_internal(d, addr, xlat, plen, false);
assert(!section->mr->iommu_ops);
assert(!memory_region_is_iommu(section->mr));
return section;
}
#endif
@ -735,6 +738,20 @@ void cpu_exec_unrealizefn(CPUState *cpu)
}
}
Property cpu_common_props[] = {
#ifndef CONFIG_USER_ONLY
/* Create a memory property for softmmu CPU object,
* so users can wire up its memory. (This can't go in qom/cpu.c
* because that file is compiled only once for both user-mode
* and system builds.) The default if no link is set up is to use
* the system address space.
*/
DEFINE_PROP_LINK("memory", CPUState, memory, TYPE_MEMORY_REGION,
MemoryRegion *),
#endif
DEFINE_PROP_END_OF_LIST(),
};
void cpu_exec_initfn(CPUState *cpu)
{
cpu->as = NULL;
@ -742,18 +759,6 @@ void cpu_exec_initfn(CPUState *cpu)
#ifndef CONFIG_USER_ONLY
cpu->thread_id = qemu_get_thread_id();
/* This is a softmmu CPU object, so create a property for it
* so users can wire up its memory. (This can't go in qom/cpu.c
* because that file is compiled only once for both user-mode
* and system builds.) The default if no link is set up is to use
* the system address space.
*/
object_property_add_link(OBJECT(cpu), "memory", TYPE_MEMORY_REGION,
(Object **)&cpu->memory,
qdev_prop_allow_set_link_before_realize,
OBJ_PROP_LINK_UNREF_ON_RELEASE,
&error_abort);
cpu->memory = system_memory;
object_ref(OBJECT(cpu->memory));
#endif
@ -775,15 +780,28 @@ void cpu_exec_realizefn(CPUState *cpu, Error **errp)
#endif
}
#if defined(CONFIG_USER_ONLY)
static void breakpoint_invalidate(CPUState *cpu, target_ulong pc)
{
/* Flush the whole TB as this will not have race conditions
* even if we don't have proper locking yet.
* Ideally we would just invalidate the TBs for the
* specified PC.
*/
tb_flush(cpu);
mmap_lock();
tb_lock();
tb_invalidate_phys_page_range(pc, pc + 1, 0);
tb_unlock();
mmap_unlock();
}
#else
static void breakpoint_invalidate(CPUState *cpu, target_ulong pc)
{
MemTxAttrs attrs;
hwaddr phys = cpu_get_phys_page_attrs_debug(cpu, pc, &attrs);
int asidx = cpu_asidx_from_attrs(cpu, attrs);
if (phys != -1) {
/* Locks grabbed by tb_invalidate_phys_addr */
tb_invalidate_phys_addr(cpu->cpu_ases[asidx].as,
phys | (pc & ~TARGET_PAGE_MASK));
}
}
#endif
#if defined(CONFIG_USER_ONLY)
void cpu_watchpoint_remove_all(CPUState *cpu, int mask)
@ -2929,7 +2947,7 @@ static MemTxResult address_space_write_continue(AddressSpace *as, hwaddr addr,
}
} else {
/* RAM case */
ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
ptr = qemu_ram_ptr_length(mr->ram_block, addr1, &l);
memcpy(ptr, buf, l);
invalidate_and_set_dirty(mr, addr1, l);
}
@ -3020,7 +3038,7 @@ MemTxResult address_space_read_continue(AddressSpace *as, hwaddr addr,
}
} else {
/* RAM case */
ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
ptr = qemu_ram_ptr_length(mr->ram_block, addr1, &l);
memcpy(buf, ptr, l);
}

121
gdbstub.c
View File

@ -56,6 +56,21 @@ static inline int target_memory_rw_debug(CPUState *cpu, target_ulong addr,
return cpu_memory_rw_debug(cpu, addr, buf, len, is_write);
}
/* Return the GDB index for a given vCPU state.
*
* For user mode this is simply the thread id. In system mode GDB
* numbers CPUs from 1 as 0 is reserved as an "any cpu" index.
*/
static inline int cpu_gdb_index(CPUState *cpu)
{
#if defined(CONFIG_USER_ONLY)
TaskState *ts = (TaskState *) cpu->opaque;
return ts->ts_tid;
#else
return cpu->cpu_index + 1;
#endif
}
enum {
GDB_SIGNAL_0 = 0,
GDB_SIGNAL_INT = 2,
@ -272,7 +287,20 @@ static int gdb_signal_to_target (int sig)
return -1;
}
//#define DEBUG_GDB
/* #define DEBUG_GDB */
#ifdef DEBUG_GDB
# define DEBUG_GDB_GATE 1
#else
# define DEBUG_GDB_GATE 0
#endif
#define gdb_debug(fmt, ...) do { \
if (DEBUG_GDB_GATE) { \
fprintf(stderr, "%s: " fmt, __func__, ## __VA_ARGS__); \
} \
} while (0)
typedef struct GDBRegisterState {
int base_reg;
@ -548,9 +576,7 @@ static int put_packet_binary(GDBState *s, const char *buf, int len)
/* return -1 if error, 0 if OK */
static int put_packet(GDBState *s, const char *buf)
{
#ifdef DEBUG_GDB
printf("reply='%s'\n", buf);
#endif
gdb_debug("reply='%s'\n", buf);
return put_packet_binary(s, buf, strlen(buf));
}
@ -827,7 +853,7 @@ static CPUState *find_cpu(uint32_t thread_id)
CPUState *cpu;
CPU_FOREACH(cpu) {
if (cpu_index(cpu) == thread_id) {
if (cpu_gdb_index(cpu) == thread_id) {
return cpu;
}
}
@ -912,23 +938,16 @@ static int gdb_handle_vcont(GDBState *s, const char *p)
if (res) {
goto out;
}
idx = tmp;
/* 0 means any thread, so we pick the first valid CPU */
if (!idx) {
idx = cpu_index(first_cpu);
}
/*
* If we are in user mode, the thread specified is actually a
* thread id, and not an index. We need to find the actual
* CPU first, and only then we can use its index.
*/
cpu = find_cpu(idx);
/* 0 means any thread, so we pick the first valid CPU */
cpu = tmp ? find_cpu(tmp) : first_cpu;
/* invalid CPU/thread specified */
if (!idx || !cpu) {
if (!cpu) {
res = -EINVAL;
goto out;
}
/* only use if no previous match occourred */
if (newstates[cpu->cpu_index] == 1) {
newstates[cpu->cpu_index] = cur_action;
@ -956,16 +975,16 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
uint8_t *registers;
target_ulong addr, len;
#ifdef DEBUG_GDB
printf("command='%s'\n", line_buf);
#endif
gdb_debug("command='%s'\n", line_buf);
p = line_buf;
ch = *p++;
switch(ch) {
case '?':
/* TODO: Make this return the correct value for user-mode. */
snprintf(buf, sizeof(buf), "T%02xthread:%02x;", GDB_SIGNAL_TRAP,
cpu_index(s->c_cpu));
cpu_gdb_index(s->c_cpu));
put_packet(s, buf);
/* Remove all the breakpoints when this query is issued,
* because gdb is doing and initial connect and the state
@ -1233,7 +1252,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
} else if (strcmp(p,"sThreadInfo") == 0) {
report_cpuinfo:
if (s->query_cpu) {
snprintf(buf, sizeof(buf), "m%x", cpu_index(s->query_cpu));
snprintf(buf, sizeof(buf), "m%x", cpu_gdb_index(s->query_cpu));
put_packet(s, buf);
s->query_cpu = CPU_NEXT(s->query_cpu);
} else
@ -1390,7 +1409,7 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state)
}
snprintf(buf, sizeof(buf),
"T%02xthread:%02x;%swatch:" TARGET_FMT_lx ";",
GDB_SIGNAL_TRAP, cpu_index(cpu), type,
GDB_SIGNAL_TRAP, cpu_gdb_index(cpu), type,
(target_ulong)cpu->watchpoint_hit->vaddr);
cpu->watchpoint_hit = NULL;
goto send_packet;
@ -1424,7 +1443,7 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state)
break;
}
gdb_set_stop_cpu(cpu);
snprintf(buf, sizeof(buf), "T%02xthread:%02x;", ret, cpu_index(cpu));
snprintf(buf, sizeof(buf), "T%02xthread:%02x;", ret, cpu_gdb_index(cpu));
send_packet:
put_packet(s, buf);
@ -1519,17 +1538,14 @@ static void gdb_read_byte(GDBState *s, int ch)
/* Waiting for a response to the last packet. If we see the start
of a new command then abandon the previous response. */
if (ch == '-') {
#ifdef DEBUG_GDB
printf("Got NACK, retransmitting\n");
#endif
gdb_debug("Got NACK, retransmitting\n");
put_buffer(s, (uint8_t *)s->last_packet, s->last_packet_len);
} else if (ch == '+') {
gdb_debug("Got ACK\n");
} else {
gdb_debug("Got '%c' when expecting ACK/NACK\n", ch);
}
#ifdef DEBUG_GDB
else if (ch == '+')
printf("Got ACK\n");
else
printf("Got '%c' when expecting ACK/NACK\n", ch);
#endif
if (ch == '+' || ch == '$')
s->last_packet_len = 0;
if (ch != '$')
@ -1550,9 +1566,7 @@ static void gdb_read_byte(GDBState *s, int ch)
s->line_sum = 0;
s->state = RS_GETLINE;
} else {
#ifdef DEBUG_GDB
printf("gdbstub received garbage between packets: 0x%x\n", ch);
#endif
gdb_debug("received garbage between packets: 0x%x\n", ch);
}
break;
case RS_GETLINE:
@ -1568,9 +1582,7 @@ static void gdb_read_byte(GDBState *s, int ch)
/* end of command, start of checksum*/
s->state = RS_CHKSUM1;
} else if (s->line_buf_index >= sizeof(s->line_buf) - 1) {
#ifdef DEBUG_GDB
printf("gdbstub command buffer overrun, dropping command\n");
#endif
gdb_debug("command buffer overrun, dropping command\n");
s->state = RS_IDLE;
} else {
/* unescaped command character */
@ -1584,9 +1596,7 @@ static void gdb_read_byte(GDBState *s, int ch)
s->state = RS_CHKSUM1;
} else if (s->line_buf_index >= sizeof(s->line_buf) - 1) {
/* command buffer overrun */
#ifdef DEBUG_GDB
printf("gdbstub command buffer overrun, dropping command\n");
#endif
gdb_debug("command buffer overrun, dropping command\n");
s->state = RS_IDLE;
} else {
/* parse escaped character and leave escape state */
@ -1598,25 +1608,18 @@ static void gdb_read_byte(GDBState *s, int ch)
case RS_GETLINE_RLE:
if (ch < ' ') {
/* invalid RLE count encoding */
#ifdef DEBUG_GDB
printf("gdbstub got invalid RLE count: 0x%x\n", ch);
#endif
gdb_debug("got invalid RLE count: 0x%x\n", ch);
s->state = RS_GETLINE;
} else {
/* decode repeat length */
int repeat = (unsigned char)ch - ' ' + 3;
if (s->line_buf_index + repeat >= sizeof(s->line_buf) - 1) {
/* that many repeats would overrun the command buffer */
#ifdef DEBUG_GDB
printf("gdbstub command buffer overrun,"
" dropping command\n");
#endif
gdb_debug("command buffer overrun, dropping command\n");
s->state = RS_IDLE;
} else if (s->line_buf_index < 1) {
/* got a repeat but we have nothing to repeat */
#ifdef DEBUG_GDB
printf("gdbstub got invalid RLE sequence\n");
#endif
gdb_debug("got invalid RLE sequence\n");
s->state = RS_GETLINE;
} else {
/* repeat the last character */
@ -1631,9 +1634,7 @@ static void gdb_read_byte(GDBState *s, int ch)
case RS_CHKSUM1:
/* get high hex digit of checksum */
if (!isxdigit(ch)) {
#ifdef DEBUG_GDB
printf("gdbstub got invalid command checksum digit\n");
#endif
gdb_debug("got invalid command checksum digit\n");
s->state = RS_GETLINE;
break;
}
@ -1644,21 +1645,17 @@ static void gdb_read_byte(GDBState *s, int ch)
case RS_CHKSUM2:
/* get low hex digit of checksum */
if (!isxdigit(ch)) {
#ifdef DEBUG_GDB
printf("gdbstub got invalid command checksum digit\n");
#endif
gdb_debug("got invalid command checksum digit\n");
s->state = RS_GETLINE;
break;
}
s->line_csum |= fromhex(ch);
if (s->line_csum != (s->line_sum & 0xff)) {
gdb_debug("got command packet with incorrect checksum\n");
/* send NAK reply */
reply = '-';
put_buffer(s, &reply, 1);
#ifdef DEBUG_GDB
printf("gdbstub got command packet with incorrect checksum\n");
#endif
s->state = RS_IDLE;
} else {
/* send ACK reply */
@ -2003,7 +2000,7 @@ int gdbserver_start(const char *device)
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);
gdb_chr_event, NULL, NULL, NULL, true);
}
s->state = chr ? RS_IDLE : RS_INACTIVE;
s->mon_chr = mon_chr;

View File

@ -1726,7 +1726,23 @@ ETEXI
STEXI
@item chardev-add args
@findex chardev-add
chardev_add accepts the same parameters as the -chardev command line switch.
chardev-add accepts the same parameters as the -chardev command line switch.
ETEXI
{
.name = "chardev-change",
.args_type = "id:s,args:s",
.params = "id args",
.help = "change chardev",
.cmd = hmp_chardev_change,
},
STEXI
@item chardev-change args
@findex chardev-change
chardev-change accepts existing chardev @var{id} and then the same arguments
as the -chardev command line switch (except for "id").
ETEXI

34
hmp.c
View File

@ -2197,6 +2197,40 @@ void hmp_chardev_add(Monitor *mon, const QDict *qdict)
hmp_handle_error(mon, &err);
}
void hmp_chardev_change(Monitor *mon, const QDict *qdict)
{
const char *args = qdict_get_str(qdict, "args");
const char *id;
Error *err = NULL;
ChardevBackend *backend = NULL;
ChardevReturn *ret = NULL;
QemuOpts *opts = qemu_opts_parse_noisily(qemu_find_opts("chardev"), args,
true);
if (!opts) {
error_setg(&err, "Parsing chardev args failed");
goto end;
}
id = qdict_get_str(qdict, "id");
if (qemu_opts_id(opts)) {
error_setg(&err, "Unexpected 'id' parameter");
goto end;
}
backend = qemu_chr_parse_opts(opts, &err);
if (!backend) {
goto end;
}
ret = qmp_chardev_change(id, backend, &err);
end:
qapi_free_ChardevReturn(ret);
qapi_free_ChardevBackend(backend);
qemu_opts_del(opts);
hmp_handle_error(mon, &err);
}
void hmp_chardev_remove(Monitor *mon, const QDict *qdict)
{
Error *local_err = NULL;

1
hmp.h
View File

@ -102,6 +102,7 @@ void hmp_nbd_server_start(Monitor *mon, const QDict *qdict);
void hmp_nbd_server_add(Monitor *mon, const QDict *qdict);
void hmp_nbd_server_stop(Monitor *mon, const QDict *qdict);
void hmp_chardev_add(Monitor *mon, const QDict *qdict);
void hmp_chardev_change(Monitor *mon, const QDict *qdict);
void hmp_chardev_remove(Monitor *mon, const QDict *qdict);
void hmp_chardev_send_break(Monitor *mon, const QDict *qdict);
void hmp_qemu_io(Monitor *mon, const QDict *qdict);

View File

@ -17,6 +17,7 @@
#define TYPE_TYPHOON_PCI_HOST_BRIDGE "typhoon-pcihost"
#define TYPE_TYPHOON_IOMMU_MEMORY_REGION "typhoon-iommu-memory-region"
typedef struct TyphoonCchip {
MemoryRegion region;
@ -41,7 +42,7 @@ typedef struct TyphoonPchip {
MemoryRegion reg_conf;
AddressSpace iommu_as;
MemoryRegion iommu;
IOMMUMemoryRegion iommu;
uint64_t ctl;
TyphoonWindow win[4];
@ -663,7 +664,8 @@ static bool window_translate(TyphoonWindow *win, hwaddr addr,
/* Handle PCI-to-system address translation. */
/* TODO: A translation failure here ought to set PCI error codes on the
Pchip and generate a machine check interrupt. */
static IOMMUTLBEntry typhoon_translate_iommu(MemoryRegion *iommu, hwaddr addr,
static IOMMUTLBEntry typhoon_translate_iommu(IOMMUMemoryRegion *iommu,
hwaddr addr,
IOMMUAccessFlags flag)
{
TyphoonPchip *pchip = container_of(iommu, TyphoonPchip, iommu);
@ -724,10 +726,6 @@ static IOMMUTLBEntry typhoon_translate_iommu(MemoryRegion *iommu, hwaddr addr,
return ret;
}
static const MemoryRegionIOMMUOps typhoon_iommu_ops = {
.translate = typhoon_translate_iommu,
};
static AddressSpace *typhoon_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
{
TyphoonState *s = opaque;
@ -891,9 +889,11 @@ PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
qdev_init_nofail(dev);
/* Host memory as seen from the PCI side, via the IOMMU. */
memory_region_init_iommu(&s->pchip.iommu, OBJECT(s), &typhoon_iommu_ops,
memory_region_init_iommu(&s->pchip.iommu, sizeof(s->pchip.iommu),
TYPE_TYPHOON_IOMMU_MEMORY_REGION, OBJECT(s),
"iommu-typhoon", UINT64_MAX);
address_space_init(&s->pchip.iommu_as, &s->pchip.iommu, "pchip0-pci");
address_space_init(&s->pchip.iommu_as, MEMORY_REGION(&s->pchip.iommu),
"pchip0-pci");
pci_setup_iommu(b, typhoon_pci_dma_iommu, s);
/* Pchip0 PCI special/interrupt acknowledge, 0x801.F800.0000, 64MB. */
@ -951,9 +951,24 @@ static const TypeInfo typhoon_pcihost_info = {
.class_init = typhoon_pcihost_class_init,
};
static void typhoon_iommu_memory_region_class_init(ObjectClass *klass,
void *data)
{
IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
imrc->translate = typhoon_translate_iommu;
}
static const TypeInfo typhoon_iommu_memory_region_info = {
.parent = TYPE_IOMMU_MEMORY_REGION,
.name = TYPE_TYPHOON_IOMMU_MEMORY_REGION,
.class_init = typhoon_iommu_memory_region_class_init,
};
static void typhoon_register_types(void)
{
type_register_static(&typhoon_pcihost_info);
type_register_static(&typhoon_iommu_memory_region_info);
}
type_init(typhoon_register_types)

View File

@ -1970,7 +1970,8 @@ static void pxa2xx_fir_realize(DeviceState *dev, Error **errp)
PXA2xxFIrState *s = PXA2XX_FIR(dev);
qemu_chr_fe_set_handlers(&s->chr, pxa2xx_fir_is_empty,
pxa2xx_fir_rx, pxa2xx_fir_event, s, NULL, true);
pxa2xx_fir_rx, pxa2xx_fir_event, NULL, s, NULL,
true);
}
static bool pxa2xx_fir_vmstate_validate(void *opaque, int version_id)

View File

@ -1106,7 +1106,7 @@ 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 (qemu_chr_fe_get_driver(&s->chr)) {
} else if (qemu_chr_fe_backend_connected(&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);
@ -1247,7 +1247,7 @@ static void strongarm_uart_realize(DeviceState *dev, Error **errp)
strongarm_uart_can_receive,
strongarm_uart_receive,
strongarm_uart_event,
s, NULL, true);
NULL, s, NULL, true);
}
static void strongarm_uart_reset(DeviceState *dev)

View File

@ -983,10 +983,6 @@ static void virtio_blk_instance_init(Object *obj)
{
VirtIOBlock *s = VIRTIO_BLK(obj);
object_property_add_link(obj, "iothread", TYPE_IOTHREAD,
(Object **)&s->conf.iothread,
qdev_prop_allow_set_link_before_realize,
OBJ_PROP_LINK_UNREF_ON_RELEASE, NULL);
device_add_bootindex_property(obj, &s->conf.conf.bootindex,
"bootindex", "/disk@0,0",
DEVICE(obj), NULL);
@ -1014,6 +1010,8 @@ static Property virtio_blk_properties[] = {
DEFINE_PROP_BIT("request-merging", VirtIOBlock, conf.request_merging, 0,
true),
DEFINE_PROP_UINT16("num-queues", VirtIOBlock, conf.num_queues, 1),
DEFINE_PROP_LINK("iothread", VirtIOBlock, conf.iothread, TYPE_IOTHREAD,
IOThread *),
DEFINE_PROP_END_OF_LIST(),
};

View File

@ -279,7 +279,7 @@ static void bcm2835_aux_realize(DeviceState *dev, Error **errp)
BCM2835AuxState *s = BCM2835_AUX(dev);
qemu_chr_fe_set_handlers(&s->chr, bcm2835_aux_can_receive,
bcm2835_aux_receive, NULL, s, NULL, true);
bcm2835_aux_receive, NULL, NULL, s, NULL, true);
}
static Property bcm2835_aux_props[] = {

View File

@ -279,7 +279,7 @@ static gboolean cadence_uart_xmit(GIOChannel *chan, GIOCondition cond,
int ret;
/* instant drain the fifo when there's no back-end */
if (!qemu_chr_fe_get_driver(&s->chr)) {
if (!qemu_chr_fe_backend_connected(&s->chr)) {
s->tx_count = 0;
return FALSE;
}
@ -485,7 +485,7 @@ static void cadence_uart_realize(DeviceState *dev, Error **errp)
fifo_trigger_update, s);
qemu_chr_fe_set_handlers(&s->chr, uart_can_receive, uart_receive,
uart_event, s, NULL, true);
uart_event, NULL, s, NULL, true);
}
static void cadence_uart_init(Object *obj)

View File

@ -87,12 +87,12 @@ static const MemoryRegionOps debugcon_ops = {
static void debugcon_realize_core(DebugconState *s, Error **errp)
{
if (!qemu_chr_fe_get_driver(&s->chr)) {
if (!qemu_chr_fe_backend_connected(&s->chr)) {
error_setg(errp, "Can't create debugcon device, empty char device");
return;
}
qemu_chr_fe_set_handlers(&s->chr, NULL, NULL, NULL, s, NULL, true);
qemu_chr_fe_set_handlers(&s->chr, NULL, NULL, NULL, NULL, s, NULL, true);
}
static void debugcon_isa_realizefn(DeviceState *dev, Error **errp)

View File

@ -146,7 +146,7 @@ static void digic_uart_realize(DeviceState *dev, Error **errp)
DigicUartState *s = DIGIC_UART(dev);
qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx,
uart_event, s, NULL, true);
uart_event, NULL, s, NULL, true);
}
static void digic_uart_init(Object *obj)

View File

@ -417,7 +417,7 @@ static void escc_update_parameters(ChannelState *s)
int speed, parity, data_bits, stop_bits;
QEMUSerialSetParams ssp;
if (!qemu_chr_fe_get_driver(&s->chr) || s->type != ser)
if (!qemu_chr_fe_backend_connected(&s->chr) || s->type != ser)
return;
if (s->wregs[W_TXCTRL1] & TXCTRL1_PAREN) {
@ -557,7 +557,7 @@ 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 (qemu_chr_fe_get_driver(&s->chr)) {
if (qemu_chr_fe_backend_connected(&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);
@ -1013,10 +1013,10 @@ static void escc_realize(DeviceState *dev, Error **errp)
ESCC_SIZE << s->it_shift);
for (i = 0; i < 2; i++) {
if (qemu_chr_fe_get_driver(&s->chn[i].chr)) {
if (qemu_chr_fe_backend_connected(&s->chn[i].chr)) {
s->chn[i].clock = s->frequency / 2;
qemu_chr_fe_set_handlers(&s->chn[i].chr, serial_can_receive,
serial_receive1, serial_event,
serial_receive1, serial_event, NULL,
&s->chn[i], NULL, true);
}
}

View File

@ -233,7 +233,7 @@ static void etraxfs_ser_realize(DeviceState *dev, Error **errp)
qemu_chr_fe_set_handlers(&s->chr,
serial_can_receive, serial_receive,
serial_event, s, NULL, true);
serial_event, NULL, s, NULL, true);
}
static void etraxfs_ser_class_init(ObjectClass *klass, void *data)

View File

@ -380,7 +380,7 @@ static void exynos4210_uart_write(void *opaque, hwaddr offset,
break;
case UTXH:
if (qemu_chr_fe_get_driver(&s->chr)) {
if (qemu_chr_fe_backend_connected(&s->chr)) {
s->reg[I_(UTRSTAT)] &= ~(UTRSTAT_TRANSMITTER_EMPTY |
UTRSTAT_Tx_BUFFER_EMPTY);
ch = (uint8_t)val;
@ -645,7 +645,7 @@ static void exynos4210_uart_realize(DeviceState *dev, Error **errp)
qemu_chr_fe_set_handlers(&s->chr, exynos4210_uart_can_receive,
exynos4210_uart_receive, exynos4210_uart_event,
s, NULL, true);
NULL, s, NULL, true);
}
static Property exynos4210_uart_properties[] = {

View File

@ -201,7 +201,7 @@ 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 (qemu_chr_fe_get_driver(&uart->chr) &&
if (qemu_chr_fe_backend_connected(&uart->chr) &&
(uart->control & UART_TRANSMIT_ENABLE)) {
c = value & 0xFF;
/* XXX this blocks entire thread. Rewrite to use
@ -247,7 +247,7 @@ static int grlib_apbuart_init(SysBusDevice *dev)
grlib_apbuart_can_receive,
grlib_apbuart_receive,
grlib_apbuart_event,
uart, NULL, true);
NULL, uart, NULL, true);
sysbus_init_irq(dev, &uart->irq);

View File

@ -315,7 +315,7 @@ static void imx_serial_realize(DeviceState *dev, Error **errp)
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);
imx_event, NULL, s, NULL, true);
}
static void imx_serial_init(Object *obj)

View File

@ -542,10 +542,10 @@ static void ipoctal_realize(DeviceState *dev, Error **errp)
ch->ipoctal = s;
/* Redirect IP-Octal channels to host character devices */
if (qemu_chr_fe_get_driver(&ch->dev)) {
if (qemu_chr_fe_backend_connected(&ch->dev)) {
qemu_chr_fe_set_handlers(&ch->dev, hostdev_can_receive,
hostdev_receive, hostdev_event,
ch, NULL, true);
NULL, 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

@ -119,7 +119,7 @@ static void lm32_juart_realize(DeviceState *dev, Error **errp)
LM32JuartState *s = LM32_JUART(dev);
qemu_chr_fe_set_handlers(&s->chr, juart_can_rx, juart_rx,
juart_event, s, NULL, true);
juart_event, NULL, s, NULL, true);
}
static const VMStateDescription vmstate_lm32_juart = {

View File

@ -266,7 +266,7 @@ static void lm32_uart_realize(DeviceState *dev, Error **errp)
LM32UartState *s = LM32_UART(dev);
qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx,
uart_event, s, NULL, true);
uart_event, NULL, s, NULL, true);
}
static const VMStateDescription vmstate_lm32_uart = {

View File

@ -305,7 +305,7 @@ static void mcf_uart_realize(DeviceState *dev, Error **errp)
mcf_uart_state *s = MCF_UART(dev);
qemu_chr_fe_set_handlers(&s->chr, mcf_uart_can_receive, mcf_uart_receive,
mcf_uart_event, s, NULL, true);
mcf_uart_event, NULL, s, NULL, true);
}
static Property mcf_uart_properties[] = {

View File

@ -199,7 +199,7 @@ static void milkymist_uart_realize(DeviceState *dev, Error **errp)
MilkymistUartState *s = MILKYMIST_UART(dev);
qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx,
uart_event, s, NULL, true);
uart_event, NULL, s, NULL, true);
}
static void milkymist_uart_init(Object *obj)

View File

@ -503,6 +503,10 @@ static const VMStateDescription vmstate_parallel_isa = {
}
};
static int parallel_can_receive(void *opaque)
{
return 1;
}
static void parallel_isa_realizefn(DeviceState *dev, Error **errp)
{
@ -513,7 +517,7 @@ static void parallel_isa_realizefn(DeviceState *dev, Error **errp)
int base;
uint8_t dummy;
if (!qemu_chr_fe_get_driver(&s->chr)) {
if (!qemu_chr_fe_backend_connected(&s->chr)) {
error_setg(errp, "Can't create parallel device, empty char device");
return;
}
@ -535,6 +539,8 @@ static void parallel_isa_realizefn(DeviceState *dev, Error **errp)
isa_init_irq(isadev, &s->irq, isa->isairq);
qemu_register_reset(parallel_reset, s);
qemu_chr_fe_set_handlers(&s->chr, parallel_can_receive, NULL,
NULL, NULL, s, NULL, true);
if (qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_PP_READ_STATUS, &dummy) == 0) {
s->hw_driver = 1;
s->status = dummy;

View File

@ -329,7 +329,7 @@ static void pl011_realize(DeviceState *dev, Error **errp)
PL011State *s = PL011(dev);
qemu_chr_fe_set_handlers(&s->chr, pl011_can_receive, pl011_receive,
pl011_event, s, NULL, true);
pl011_event, NULL, s, NULL, true);
}
static void pl011_class_init(ObjectClass *oc, void *data)

View File

@ -195,7 +195,7 @@ static int write_console_data(SCLPEvent *event, const uint8_t *buf, int len)
{
SCLPConsoleLM *scon = SCLPLM_CONSOLE(event);
if (!qemu_chr_fe_get_driver(&scon->chr)) {
if (!qemu_chr_fe_backend_connected(&scon->chr)) {
/* If there's no backend, we can just say we consumed all data. */
return len;
}
@ -313,7 +313,7 @@ static int console_init(SCLPEvent *event)
console_available = true;
qemu_chr_fe_set_handlers(&scon->chr, chr_can_read,
chr_read, NULL, scon, NULL, true);
chr_read, NULL, NULL, scon, NULL, true);
return 0;
}

View File

@ -163,7 +163,7 @@ static ssize_t write_console_data(SCLPEvent *event, const uint8_t *buf,
{
SCLPConsole *scon = SCLP_CONSOLE(event);
if (!qemu_chr_fe_get_driver(&scon->chr)) {
if (!qemu_chr_fe_backend_connected(&scon->chr)) {
/* If there's no backend, we can just say we consumed all data. */
return len;
}
@ -228,7 +228,7 @@ static int console_init(SCLPEvent *event)
}
console_available = true;
qemu_chr_fe_set_handlers(&scon->chr, chr_can_read,
chr_read, NULL, scon, NULL, true);
chr_read, NULL, NULL, scon, NULL, true);
return 0;
}

View File

@ -312,6 +312,24 @@ static void serial_write_fcr(SerialState *s, uint8_t val)
}
}
static void serial_update_tiocm(SerialState *s)
{
int flags;
qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_GET_TIOCM, &flags);
flags &= ~(CHR_TIOCM_RTS | CHR_TIOCM_DTR);
if (s->mcr & UART_MCR_RTS) {
flags |= CHR_TIOCM_RTS;
}
if (s->mcr & UART_MCR_DTR) {
flags |= CHR_TIOCM_DTR;
}
qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_TIOCM, &flags);
}
static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val,
unsigned size)
{
@ -426,24 +444,13 @@ static void serial_ioport_write(void *opaque, hwaddr addr, uint64_t val,
break;
case 4:
{
int flags;
int old_mcr = s->mcr;
s->mcr = val & 0x1f;
if (val & UART_MCR_LOOP)
break;
if (s->poll_msl >= 0 && old_mcr != s->mcr) {
qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_GET_TIOCM, &flags);
flags &= ~(CHR_TIOCM_RTS | CHR_TIOCM_DTR);
if (val & UART_MCR_RTS)
flags |= CHR_TIOCM_RTS;
if (val & UART_MCR_DTR)
flags |= CHR_TIOCM_DTR;
qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_TIOCM, &flags);
serial_update_tiocm(s);
/* 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);
@ -884,9 +891,37 @@ static void serial_reset(void *opaque)
s->msr &= ~UART_MSR_ANY_DELTA;
}
static int serial_be_change(void *opaque)
{
SerialState *s = opaque;
qemu_chr_fe_set_handlers(&s->chr, serial_can_receive1, serial_receive1,
serial_event, serial_be_change, s, NULL, true);
serial_update_parameters(s);
qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_BREAK,
&s->last_break_enable);
s->poll_msl = (s->ier & UART_IER_MSI) ? 1 : 0;
serial_update_msl(s);
if (s->poll_msl >= 0 && !(s->mcr & UART_MCR_LOOP)) {
serial_update_tiocm(s);
}
if (s->watch_tag > 0) {
g_source_remove(s->watch_tag);
s->watch_tag = qemu_chr_fe_add_watch(&s->chr, G_IO_OUT | G_IO_HUP,
serial_watch_cb, s);
}
return 0;
}
void serial_realize_core(SerialState *s, Error **errp)
{
if (!qemu_chr_fe_get_driver(&s->chr)) {
if (!qemu_chr_fe_backend_connected(&s->chr)) {
error_setg(errp, "Can't create serial device, empty char device");
return;
}
@ -897,7 +932,7 @@ void serial_realize_core(SerialState *s, Error **errp)
qemu_register_reset(serial_reset, s);
qemu_chr_fe_set_handlers(&s->chr, serial_can_receive1, serial_receive1,
serial_event, s, NULL, true);
serial_event, serial_be_change, s, NULL, true);
fifo8_create(&s->recv_fifo, UART_FIFO_LENGTH);
fifo8_create(&s->xmit_fifo, UART_FIFO_LENGTH);
serial_reset(s);

View File

@ -110,7 +110,7 @@ static void sh_serial_write(void *opaque, hwaddr offs,
}
return;
case 0x0c: /* FTDR / TDR */
if (qemu_chr_fe_get_driver(&s->chr)) {
if (qemu_chr_fe_backend_connected(&s->chr)) {
ch = val;
/* XXX this blocks entire thread. Rewrite to use
* qemu_chr_fe_write and background I/O callbacks */
@ -400,7 +400,7 @@ void sh_serial_init(MemoryRegion *sysmem,
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);
sh_serial_event, NULL, s, NULL, true);
}
s->eri = eri_source;

View File

@ -78,13 +78,13 @@ static void spapr_vty_realize(VIOsPAPRDevice *sdev, Error **errp)
{
VIOsPAPRVTYDevice *dev = VIO_SPAPR_VTY_DEVICE(sdev);
if (!qemu_chr_fe_get_driver(&dev->chardev)) {
if (!qemu_chr_fe_backend_connected(&dev->chardev)) {
error_setg(errp, "chardev property not set");
return;
}
qemu_chr_fe_set_handlers(&dev->chardev, vty_can_receive,
vty_receive, NULL, dev, NULL, true);
vty_receive, NULL, NULL, dev, NULL, true);
}
/* Forward declaration */

View File

@ -207,7 +207,8 @@ static void stm32f2xx_usart_realize(DeviceState *dev, Error **errp)
STM32F2XXUsartState *s = STM32F2XX_USART(dev);
qemu_chr_fe_set_handlers(&s->chr, stm32f2xx_usart_can_receive,
stm32f2xx_usart_receive, NULL, s, NULL, true);
stm32f2xx_usart_receive, NULL, NULL,
s, NULL, true);
}
static void stm32f2xx_usart_class_init(ObjectClass *klass, void *data)

View File

@ -179,7 +179,7 @@ static void terminal_init(EmulatedCcw3270Device *dev, Error **errp)
}
terminal_available = true;
qemu_chr_fe_set_handlers(&t->chr, terminal_can_read,
terminal_read, chr_event, t, NULL, true);
terminal_read, chr_event, NULL, t, NULL, true);
}
static int read_payload_3270(EmulatedCcw3270Device *dev, uint32_t cda,
@ -239,7 +239,7 @@ static int write_payload_3270(EmulatedCcw3270Device *dev, uint8_t cmd,
return 0;
}
}
if (!qemu_chr_fe_get_driver(&t->chr)) {
if (!qemu_chr_fe_backend_connected(&t->chr)) {
/* We just say we consumed all data if there's no backend. */
return count;
}

View File

@ -49,7 +49,7 @@ static ssize_t flush_buf(VirtIOSerialPort *port,
VirtConsole *vcon = VIRTIO_CONSOLE(port);
ssize_t ret;
if (!qemu_chr_fe_get_driver(&vcon->chr)) {
if (!qemu_chr_fe_backend_connected(&vcon->chr)) {
/* If there's no backend, we can just say we consumed all data. */
return len;
}
@ -163,12 +163,35 @@ static void chr_event(void *opaque, int event)
}
}
static int chr_be_change(void *opaque)
{
VirtConsole *vcon = opaque;
VirtIOSerialPort *port = VIRTIO_SERIAL_PORT(vcon);
VirtIOSerialPortClass *k = VIRTIO_SERIAL_PORT_GET_CLASS(port);
if (k->is_console) {
qemu_chr_fe_set_handlers(&vcon->chr, chr_can_read, chr_read,
NULL, chr_be_change, vcon, NULL, true);
} else {
qemu_chr_fe_set_handlers(&vcon->chr, chr_can_read, chr_read,
chr_event, chr_be_change, vcon, NULL, false);
}
if (vcon->watch) {
g_source_remove(vcon->watch);
vcon->watch = qemu_chr_fe_add_watch(&vcon->chr,
G_IO_OUT | G_IO_HUP,
chr_write_unblocked, vcon);
}
return 0;
}
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);
Chardev *chr = qemu_chr_fe_get_driver(&vcon->chr);
if (port->id == 0 && !k->is_console) {
error_setg(errp, "Port number 0 on virtio-serial devices reserved "
@ -176,7 +199,7 @@ static void virtconsole_realize(DeviceState *dev, Error **errp)
return;
}
if (chr) {
if (qemu_chr_fe_backend_connected(&vcon->chr)) {
/*
* For consoles we don't block guest data transfer just
* because nothing is connected - we'll just let it go
@ -188,11 +211,13 @@ static void virtconsole_realize(DeviceState *dev, Error **errp)
*/
if (k->is_console) {
qemu_chr_fe_set_handlers(&vcon->chr, chr_can_read, chr_read,
NULL, vcon, NULL, true);
NULL, chr_be_change,
vcon, NULL, true);
virtio_serial_open(port);
} else {
qemu_chr_fe_set_handlers(&vcon->chr, chr_can_read, chr_read,
chr_event, vcon, NULL, false);
chr_event, chr_be_change,
vcon, NULL, false);
}
}
}

View File

@ -150,7 +150,7 @@ static void xencons_send(struct XenConsole *con)
ssize_t len, size;
size = con->buffer.size - con->buffer.consumed;
if (qemu_chr_fe_get_driver(&con->chr)) {
if (qemu_chr_fe_backend_connected(&con->chr)) {
len = qemu_chr_fe_write(&con->chr,
con->buffer.data + con->buffer.consumed,
size);
@ -246,7 +246,7 @@ static int con_initialise(struct XenDevice *xendev)
xen_be_bind_evtchn(&con->xendev);
qemu_chr_fe_set_handlers(&con->chr, xencons_can_receive,
xencons_receive, NULL, con, NULL, true);
xencons_receive, NULL, NULL, con, NULL, true);
xen_pv_printf(xendev, 1,
"ring mfn %d, remote port %d, local port %d, limit %zd\n",

View File

@ -212,7 +212,7 @@ static void xilinx_uartlite_realize(DeviceState *dev, Error **errp)
XilinxUARTLite *s = XILINX_UARTLITE(dev);
qemu_chr_fe_set_handlers(&s->chr, uart_can_rx, uart_rx,
uart_event, s, NULL, true);
uart_event, NULL, s, NULL, true);
}
static void xilinx_uartlite_init(Object *obj)

View File

@ -159,7 +159,7 @@ static void set_drive(Object *obj, Visitor *v, const char *name, void *opaque,
set_pointer(obj, v, opaque, parse_drive, name, errp);
}
PropertyInfo qdev_prop_drive = {
const PropertyInfo qdev_prop_drive = {
.name = "str",
.description = "Node name or ID of a block device to use as a backend",
.get = get_drive,
@ -228,7 +228,7 @@ static void release_chr(Object *obj, const char *name, void *opaque)
qemu_chr_fe_deinit(be, false);
}
PropertyInfo qdev_prop_chr = {
const PropertyInfo qdev_prop_chr = {
.name = "str",
.description = "ID of a chardev to use as a backend",
.get = get_chr,
@ -313,7 +313,7 @@ out:
g_free(str);
}
PropertyInfo qdev_prop_netdev = {
const PropertyInfo qdev_prop_netdev = {
.name = "str",
.description = "ID of a netdev to use as a backend",
.get = get_netdev,
@ -393,7 +393,7 @@ static void set_vlan(Object *obj, Visitor *v, const char *name, void *opaque,
*ptr = hubport;
}
PropertyInfo qdev_prop_vlan = {
const PropertyInfo qdev_prop_vlan = {
.name = "int32",
.description = "Integer VLAN id to connect to",
.print = print_vlan,

View File

@ -25,7 +25,8 @@ void qdev_prop_set_after_realize(DeviceState *dev, const char *name,
}
}
void qdev_prop_allow_set_link_before_realize(Object *obj, const char *name,
void qdev_prop_allow_set_link_before_realize(const Object *obj,
const char *name,
Object *val, Error **errp)
{
DeviceState *dev = DEVICE(obj);
@ -131,7 +132,7 @@ static void set_default_value_bool(Object *obj, const Property *prop)
object_property_set_bool(obj, prop->defval.u, prop->name, &error_abort);
}
PropertyInfo qdev_prop_bit = {
const PropertyInfo qdev_prop_bit = {
.name = "bool",
.description = "on/off",
.get = prop_get_bit,
@ -190,7 +191,7 @@ static void prop_set_bit64(Object *obj, Visitor *v, const char *name,
bit64_prop_set(dev, prop, value);
}
PropertyInfo qdev_prop_bit64 = {
const PropertyInfo qdev_prop_bit64 = {
.name = "bool",
.description = "on/off",
.get = prop_get_bit64,
@ -225,7 +226,7 @@ static void set_bool(Object *obj, Visitor *v, const char *name, void *opaque,
visit_type_bool(v, name, ptr, errp);
}
PropertyInfo qdev_prop_bool = {
const PropertyInfo qdev_prop_bool = {
.name = "bool",
.get = get_bool,
.set = set_bool,
@ -269,7 +270,7 @@ static void set_default_value_uint(Object *obj, const Property *prop)
object_property_set_uint(obj, prop->defval.u, prop->name, &error_abort);
}
PropertyInfo qdev_prop_uint8 = {
const PropertyInfo qdev_prop_uint8 = {
.name = "uint8",
.get = get_uint8,
.set = set_uint8,
@ -303,7 +304,7 @@ static void set_uint16(Object *obj, Visitor *v, const char *name,
visit_type_uint16(v, name, ptr, errp);
}
PropertyInfo qdev_prop_uint16 = {
const PropertyInfo qdev_prop_uint16 = {
.name = "uint16",
.get = get_uint16,
.set = set_uint16,
@ -362,14 +363,14 @@ static void set_int32(Object *obj, Visitor *v, const char *name, void *opaque,
visit_type_int32(v, name, ptr, errp);
}
PropertyInfo qdev_prop_uint32 = {
const PropertyInfo qdev_prop_uint32 = {
.name = "uint32",
.get = get_uint32,
.set = set_uint32,
.set_default_value = set_default_value_uint,
};
PropertyInfo qdev_prop_int32 = {
const PropertyInfo qdev_prop_int32 = {
.name = "int32",
.get = get_int32,
.set = set_int32,
@ -403,7 +404,7 @@ static void set_uint64(Object *obj, Visitor *v, const char *name,
visit_type_uint64(v, name, ptr, errp);
}
PropertyInfo qdev_prop_uint64 = {
const PropertyInfo qdev_prop_uint64 = {
.name = "uint64",
.get = get_uint64,
.set = set_uint64,
@ -456,7 +457,7 @@ static void set_string(Object *obj, Visitor *v, const char *name,
*ptr = str;
}
PropertyInfo qdev_prop_string = {
const PropertyInfo qdev_prop_string = {
.name = "str",
.release = release_string,
.get = get_string,
@ -466,7 +467,7 @@ PropertyInfo qdev_prop_string = {
/* --- pointer --- */
/* Not a proper property, just for dirty hacks. TODO Remove it! */
PropertyInfo qdev_prop_ptr = {
const PropertyInfo qdev_prop_ptr = {
.name = "ptr",
};
@ -540,7 +541,7 @@ inval:
g_free(str);
}
PropertyInfo qdev_prop_macaddr = {
const PropertyInfo qdev_prop_macaddr = {
.name = "str",
.description = "Ethernet 6-byte MAC Address, example: 52:54:00:12:34:56",
.get = get_mac,
@ -549,7 +550,7 @@ PropertyInfo qdev_prop_macaddr = {
/* --- on/off/auto --- */
PropertyInfo qdev_prop_on_off_auto = {
const PropertyInfo qdev_prop_on_off_auto = {
.name = "OnOffAuto",
.description = "on/off/auto",
.enum_table = OnOffAuto_lookup,
@ -562,7 +563,7 @@ PropertyInfo qdev_prop_on_off_auto = {
QEMU_BUILD_BUG_ON(sizeof(LostTickPolicy) != sizeof(int));
PropertyInfo qdev_prop_losttickpolicy = {
const PropertyInfo qdev_prop_losttickpolicy = {
.name = "LostTickPolicy",
.enum_table = LostTickPolicy_lookup,
.get = get_enum,
@ -574,7 +575,7 @@ PropertyInfo qdev_prop_losttickpolicy = {
QEMU_BUILD_BUG_ON(sizeof(BlockdevOnError) != sizeof(int));
PropertyInfo qdev_prop_blockdev_on_error = {
const PropertyInfo qdev_prop_blockdev_on_error = {
.name = "BlockdevOnError",
.description = "Error handling policy, "
"report/ignore/enospc/stop/auto",
@ -588,7 +589,7 @@ PropertyInfo qdev_prop_blockdev_on_error = {
QEMU_BUILD_BUG_ON(sizeof(BiosAtaTranslation) != sizeof(int));
PropertyInfo qdev_prop_bios_chs_trans = {
const PropertyInfo qdev_prop_bios_chs_trans = {
.name = "BiosAtaTranslation",
.description = "Logical CHS translation algorithm, "
"auto/none/lba/large/rechs",
@ -600,7 +601,7 @@ PropertyInfo qdev_prop_bios_chs_trans = {
/* --- FDC default drive types */
PropertyInfo qdev_prop_fdc_drive_type = {
const PropertyInfo qdev_prop_fdc_drive_type = {
.name = "FdcDriveType",
.description = "FDC drive type, "
"144/288/120/none/auto",
@ -676,7 +677,7 @@ static int print_pci_devfn(DeviceState *dev, Property *prop, char *dest,
}
}
PropertyInfo qdev_prop_pci_devfn = {
const PropertyInfo qdev_prop_pci_devfn = {
.name = "int32",
.description = "Slot and optional function number, example: 06.0 or 06",
.print = print_pci_devfn,
@ -725,7 +726,7 @@ static void set_blocksize(Object *obj, Visitor *v, const char *name,
*ptr = value;
}
PropertyInfo qdev_prop_blocksize = {
const PropertyInfo qdev_prop_blocksize = {
.name = "uint16",
.description = "A power of two between 512 and 32768",
.get = get_uint16,
@ -840,7 +841,7 @@ inval:
g_free(str);
}
PropertyInfo qdev_prop_pci_host_devaddr = {
const PropertyInfo qdev_prop_pci_host_devaddr = {
.name = "str",
.description = "Address (bus/device/function) of "
"the host device, example: 04:10.0",
@ -949,7 +950,7 @@ static void set_prop_arraylen(Object *obj, Visitor *v, const char *name,
}
}
PropertyInfo qdev_prop_arraylen = {
const PropertyInfo qdev_prop_arraylen = {
.name = "uint32",
.get = get_uint32,
.set = set_prop_arraylen,
@ -1207,9 +1208,27 @@ static void set_size(Object *obj, Visitor *v, const char *name, void *opaque,
visit_type_size(v, name, ptr, errp);
}
PropertyInfo qdev_prop_size = {
const PropertyInfo qdev_prop_size = {
.name = "size",
.get = get_size,
.set = set_size,
.set_default_value = set_default_value_uint,
};
/* --- object link property --- */
static void create_link_property(Object *obj, Property *prop, Error **errp)
{
Object **child = qdev_get_prop_ptr(DEVICE(obj), prop);
object_property_add_link(obj, prop->name, prop->link_type,
child,
qdev_prop_allow_set_link_before_realize,
OBJ_PROP_LINK_UNREF_ON_RELEASE,
errp);
}
const PropertyInfo qdev_prop_link = {
.name = "link",
.create = create_link_property,
};

View File

@ -744,6 +744,10 @@ static void qdev_property_add_legacy(DeviceState *dev, Property *prop,
return;
}
if (prop->info->create) {
return;
}
name = g_strdup_printf("legacy-%s", prop->name);
object_property_add(OBJECT(dev), name, "str",
prop->info->print ? qdev_get_legacy_property : prop->info->get,
@ -770,20 +774,23 @@ void qdev_property_add_static(DeviceState *dev, Property *prop,
Error *local_err = NULL;
Object *obj = OBJECT(dev);
/*
* TODO qdev_prop_ptr does not have getters or setters. It must
* go now that it can be replaced with links. The test should be
* removed along with it: all static properties are read/write.
*/
if (!prop->info->get && !prop->info->set) {
return;
if (prop->info->create) {
prop->info->create(obj, prop, &local_err);
} else {
/*
* TODO qdev_prop_ptr does not have getters or setters. It must
* go now that it can be replaced with links. The test should be
* removed along with it: all static properties are read/write.
*/
if (!prop->info->get && !prop->info->set) {
return;
}
object_property_add(obj, prop->name, prop->info->name,
prop->info->get, prop->info->set,
prop->info->release,
prop, &local_err);
}
object_property_add(obj, prop->name, prop->info->name,
prop->info->get, prop->info->set,
prop->info->release,
prop, &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;

View File

@ -515,7 +515,7 @@ static void xlnx_dp_aux_set_command(XlnxDPState *s, uint32_t value)
s->core_registers[DP_INTERRUPT_SIGNAL_STATE] |= 0x04;
}
static void xlnx_dp_set_dpdma(Object *obj, const char *name, Object *val,
static void xlnx_dp_set_dpdma(const Object *obj, const char *name, Object *val,
Error **errp)
{
XlnxDPState *s = XLNX_DP(obj);

View File

@ -54,6 +54,8 @@ typedef struct dma_pagetable_entry {
#define RC4030(obj) \
OBJECT_CHECK(rc4030State, (obj), TYPE_RC4030)
#define TYPE_RC4030_IOMMU_MEMORY_REGION "rc4030-iommu-memory-region"
typedef struct rc4030State
{
SysBusDevice parent;
@ -90,7 +92,7 @@ typedef struct rc4030State
qemu_irq jazz_bus_irq;
/* whole DMA memory region, root of DMA address space */
MemoryRegion dma_mr;
IOMMUMemoryRegion dma_mr;
AddressSpace dma_as;
MemoryRegion iomem_chipset;
@ -488,7 +490,7 @@ static const MemoryRegionOps jazzio_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
static IOMMUTLBEntry rc4030_dma_translate(MemoryRegion *iommu, hwaddr addr,
static IOMMUTLBEntry rc4030_dma_translate(IOMMUMemoryRegion *iommu, hwaddr addr,
IOMMUAccessFlags flag)
{
rc4030State *s = container_of(iommu, rc4030State, dma_mr);
@ -516,10 +518,6 @@ static IOMMUTLBEntry rc4030_dma_translate(MemoryRegion *iommu, hwaddr addr,
return ret;
}
static const MemoryRegionIOMMUOps rc4030_dma_ops = {
.translate = rc4030_dma_translate,
};
static void rc4030_reset(DeviceState *dev)
{
rc4030State *s = RC4030(dev);
@ -677,9 +675,10 @@ static void rc4030_realize(DeviceState *dev, Error **errp)
memory_region_init_io(&s->iomem_jazzio, NULL, &jazzio_ops, s,
"rc4030.jazzio", 0x00001000);
memory_region_init_iommu(&s->dma_mr, o, &rc4030_dma_ops,
"rc4030.dma", UINT32_MAX);
address_space_init(&s->dma_as, &s->dma_mr, "rc4030-dma");
memory_region_init_iommu(&s->dma_mr, sizeof(s->dma_mr),
TYPE_RC4030_IOMMU_MEMORY_REGION,
o, "rc4030.dma", UINT32_MAX);
address_space_init(&s->dma_as, MEMORY_REGION(&s->dma_mr), "rc4030-dma");
}
static void rc4030_unrealize(DeviceState *dev, Error **errp)
@ -710,14 +709,29 @@ static const TypeInfo rc4030_info = {
.class_init = rc4030_class_init,
};
static void rc4030_iommu_memory_region_class_init(ObjectClass *klass,
void *data)
{
IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
imrc->translate = rc4030_dma_translate;
}
static const TypeInfo rc4030_iommu_memory_region_info = {
.parent = TYPE_IOMMU_MEMORY_REGION,
.name = TYPE_RC4030_IOMMU_MEMORY_REGION,
.class_init = rc4030_iommu_memory_region_class_init,
};
static void rc4030_register_types(void)
{
type_register_static(&rc4030_info);
type_register_static(&rc4030_iommu_memory_region_info);
}
type_init(rc4030_register_types)
DeviceState *rc4030_init(rc4030_dma **dmas, MemoryRegion **dma_mr)
DeviceState *rc4030_init(rc4030_dma **dmas, IOMMUMemoryRegion **dma_mr)
{
DeviceState *dev;

View File

@ -52,7 +52,7 @@ struct AMDVIAddressSpace {
uint8_t bus_num; /* bus number */
uint8_t devfn; /* device function */
AMDVIState *iommu_state; /* AMDVI - one per machine */
MemoryRegion iommu; /* Device's address translation region */
IOMMUMemoryRegion iommu; /* Device's address translation region */
MemoryRegion iommu_ir; /* Device's interrupt remapping region */
AddressSpace as; /* device's corresponding address space */
};
@ -987,7 +987,7 @@ static inline bool amdvi_is_interrupt_addr(hwaddr addr)
return addr >= AMDVI_INT_ADDR_FIRST && addr <= AMDVI_INT_ADDR_LAST;
}
static IOMMUTLBEntry amdvi_translate(MemoryRegion *iommu, hwaddr addr,
static IOMMUTLBEntry amdvi_translate(IOMMUMemoryRegion *iommu, hwaddr addr,
IOMMUAccessFlags flag)
{
AMDVIAddressSpace *as = container_of(iommu, AMDVIAddressSpace, iommu);
@ -1044,9 +1044,13 @@ static AddressSpace *amdvi_host_dma_iommu(PCIBus *bus, void *opaque, int devfn)
iommu_as[devfn]->devfn = (uint8_t)devfn;
iommu_as[devfn]->iommu_state = s;
memory_region_init_iommu(&iommu_as[devfn]->iommu, OBJECT(s),
&s->iommu_ops, "amd-iommu", UINT64_MAX);
address_space_init(&iommu_as[devfn]->as, &iommu_as[devfn]->iommu,
memory_region_init_iommu(&iommu_as[devfn]->iommu,
sizeof(iommu_as[devfn]->iommu),
TYPE_AMD_IOMMU_MEMORY_REGION,
OBJECT(s),
"amd-iommu", UINT64_MAX);
address_space_init(&iommu_as[devfn]->as,
MEMORY_REGION(&iommu_as[devfn]->iommu),
"amd-iommu");
}
return &iommu_as[devfn]->as;
@ -1067,7 +1071,7 @@ static const MemoryRegionOps mmio_mem_ops = {
}
};
static void amdvi_iommu_notify_flag_changed(MemoryRegion *iommu,
static void amdvi_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu,
IOMMUNotifierFlag old,
IOMMUNotifierFlag new)
{
@ -1085,8 +1089,6 @@ static void amdvi_init(AMDVIState *s)
{
amdvi_iotlb_reset(s);
s->iommu_ops.translate = amdvi_translate;
s->iommu_ops.notify_flag_changed = amdvi_iommu_notify_flag_changed;
s->devtab_len = 0;
s->cmdbuf_len = 0;
s->cmdbuf_head = 0;
@ -1227,10 +1229,25 @@ static const TypeInfo amdviPCI = {
.instance_size = sizeof(AMDVIPCIState),
};
static void amdvi_iommu_memory_region_class_init(ObjectClass *klass, void *data)
{
IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
imrc->translate = amdvi_translate;
imrc->notify_flag_changed = amdvi_iommu_notify_flag_changed;
}
static const TypeInfo amdvi_iommu_memory_region_info = {
.parent = TYPE_IOMMU_MEMORY_REGION,
.name = TYPE_AMD_IOMMU_MEMORY_REGION,
.class_init = amdvi_iommu_memory_region_class_init,
};
static void amdviPCI_register_types(void)
{
type_register_static(&amdviPCI);
type_register_static(&amdvi);
type_register_static(&amdvi_iommu_memory_region_info);
}
type_init(amdviPCI_register_types);

View File

@ -220,6 +220,8 @@
#define TYPE_AMD_IOMMU_PCI "AMDVI-PCI"
#define TYPE_AMD_IOMMU_MEMORY_REGION "amd-iommu-iommu-memory-region"
typedef struct AMDVIAddressSpace AMDVIAddressSpace;
/* functions to steal PCI config space */
@ -276,9 +278,6 @@ typedef struct AMDVIState {
uint8_t romask[AMDVI_MMIO_SIZE]; /* MMIO read/only mask */
bool mmio_enabled;
/* IOMMU function */
MemoryRegionIOMMUOps iommu_ops;
/* for each served device */
AMDVIAddressSpace **address_spaces[PCI_BUS_MAX];

View File

@ -972,9 +972,9 @@ static bool vtd_switch_address_space(VTDAddressSpace *as)
/* Turn off first then on the other */
if (use_iommu) {
memory_region_set_enabled(&as->sys_alias, false);
memory_region_set_enabled(&as->iommu, true);
memory_region_set_enabled(MEMORY_REGION(&as->iommu), true);
} else {
memory_region_set_enabled(&as->iommu, false);
memory_region_set_enabled(MEMORY_REGION(&as->iommu), false);
memory_region_set_enabled(&as->sys_alias, true);
}
@ -1366,7 +1366,7 @@ static void vtd_iotlb_domain_invalidate(IntelIOMMUState *s, uint16_t domain_id)
static int vtd_page_invalidate_notify_hook(IOMMUTLBEntry *entry,
void *private)
{
memory_region_notify_iommu((MemoryRegion *)private, *entry);
memory_region_notify_iommu((IOMMUMemoryRegion *)private, *entry);
return 0;
}
@ -2264,7 +2264,7 @@ static void vtd_mem_write(void *opaque, hwaddr addr,
}
}
static IOMMUTLBEntry vtd_iommu_translate(MemoryRegion *iommu, hwaddr addr,
static IOMMUTLBEntry vtd_iommu_translate(IOMMUMemoryRegion *iommu, hwaddr addr,
IOMMUAccessFlags flag)
{
VTDAddressSpace *vtd_as = container_of(iommu, VTDAddressSpace, iommu);
@ -2303,7 +2303,7 @@ static IOMMUTLBEntry vtd_iommu_translate(MemoryRegion *iommu, hwaddr addr,
return iotlb;
}
static void vtd_iommu_notify_flag_changed(MemoryRegion *iommu,
static void vtd_iommu_notify_flag_changed(IOMMUMemoryRegion *iommu,
IOMMUNotifierFlag old,
IOMMUNotifierFlag new)
{
@ -2718,8 +2718,9 @@ VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, int devfn)
* vtd_sys_alias and intel_iommu regions. IR region is always
* enabled.
*/
memory_region_init_iommu(&vtd_dev_as->iommu, OBJECT(s),
&s->iommu_ops, "intel_iommu_dmar",
memory_region_init_iommu(&vtd_dev_as->iommu, sizeof(vtd_dev_as->iommu),
TYPE_INTEL_IOMMU_MEMORY_REGION, OBJECT(s),
"intel_iommu_dmar",
UINT64_MAX);
memory_region_init_alias(&vtd_dev_as->sys_alias, OBJECT(s),
"vtd_sys_alias", get_system_memory(),
@ -2736,7 +2737,8 @@ VTDAddressSpace *vtd_find_add_as(IntelIOMMUState *s, PCIBus *bus, int devfn)
memory_region_add_subregion_overlap(&vtd_dev_as->root, 0,
&vtd_dev_as->sys_alias, 1);
memory_region_add_subregion_overlap(&vtd_dev_as->root, 0,
&vtd_dev_as->iommu, 1);
MEMORY_REGION(&vtd_dev_as->iommu),
1);
vtd_switch_address_space(vtd_dev_as);
}
return vtd_dev_as;
@ -2816,9 +2818,9 @@ static int vtd_replay_hook(IOMMUTLBEntry *entry, void *private)
return 0;
}
static void vtd_iommu_replay(MemoryRegion *mr, IOMMUNotifier *n)
static void vtd_iommu_replay(IOMMUMemoryRegion *iommu_mr, IOMMUNotifier *n)
{
VTDAddressSpace *vtd_as = container_of(mr, VTDAddressSpace, iommu);
VTDAddressSpace *vtd_as = container_of(iommu_mr, VTDAddressSpace, iommu);
IntelIOMMUState *s = vtd_as->iommu_state;
uint8_t bus_n = pci_bus_num(vtd_as->bus);
VTDContextEntry ce;
@ -2856,9 +2858,6 @@ static void vtd_init(IntelIOMMUState *s)
memset(s->w1cmask, 0, DMAR_REG_SIZE);
memset(s->womask, 0, DMAR_REG_SIZE);
s->iommu_ops.translate = vtd_iommu_translate;
s->iommu_ops.notify_flag_changed = vtd_iommu_notify_flag_changed;
s->iommu_ops.replay = vtd_iommu_replay;
s->root = 0;
s->root_extended = false;
s->dmar_enabled = false;
@ -3073,9 +3072,26 @@ static const TypeInfo vtd_info = {
.class_init = vtd_class_init,
};
static void vtd_iommu_memory_region_class_init(ObjectClass *klass,
void *data)
{
IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
imrc->translate = vtd_iommu_translate;
imrc->notify_flag_changed = vtd_iommu_notify_flag_changed;
imrc->replay = vtd_iommu_replay;
}
static const TypeInfo vtd_iommu_memory_region_info = {
.parent = TYPE_IOMMU_MEMORY_REGION,
.name = TYPE_INTEL_IOMMU_MEMORY_REGION,
.class_init = vtd_iommu_memory_region_class_init,
};
static void vtd_register_types(void)
{
type_register_static(&vtd_info);
type_register_static(&vtd_iommu_memory_region_info);
}
type_init(vtd_register_types)

View File

@ -383,8 +383,7 @@ static void patch_byte(X86CPU *cpu, target_ulong addr, uint8_t byte)
cpu_memory_rw_debug(CPU(cpu), addr, &byte, 1, 1);
}
static void patch_call(VAPICROMState *s, X86CPU *cpu, target_ulong ip,
uint32_t target)
static void patch_call(X86CPU *cpu, target_ulong ip, uint32_t target)
{
uint32_t offset;
@ -393,16 +392,59 @@ static void patch_call(VAPICROMState *s, X86CPU *cpu, target_ulong ip,
cpu_memory_rw_debug(CPU(cpu), ip + 1, (void *)&offset, sizeof(offset), 1);
}
typedef struct PatchInfo {
VAPICHandlers *handler;
target_ulong ip;
} PatchInfo;
static void do_patch_instruction(CPUState *cs, run_on_cpu_data data)
{
X86CPU *x86_cpu = X86_CPU(cs);
PatchInfo *info = (PatchInfo *) data.host_ptr;
VAPICHandlers *handlers = info->handler;
target_ulong ip = info->ip;
uint8_t opcode[2];
uint32_t imm32 = 0;
cpu_memory_rw_debug(cs, ip, opcode, sizeof(opcode), 0);
switch (opcode[0]) {
case 0x89: /* mov r32 to r/m32 */
patch_byte(x86_cpu, ip, 0x50 + modrm_reg(opcode[1])); /* push reg */
patch_call(x86_cpu, ip + 1, handlers->set_tpr);
break;
case 0x8b: /* mov r/m32 to r32 */
patch_byte(x86_cpu, ip, 0x90);
patch_call(x86_cpu, ip + 1, handlers->get_tpr[modrm_reg(opcode[1])]);
break;
case 0xa1: /* mov abs to eax */
patch_call(x86_cpu, ip, handlers->get_tpr[0]);
break;
case 0xa3: /* mov eax to abs */
patch_call(x86_cpu, ip, handlers->set_tpr_eax);
break;
case 0xc7: /* mov imm32, r/m32 (c7/0) */
patch_byte(x86_cpu, ip, 0x68); /* push imm32 */
cpu_memory_rw_debug(cs, ip + 6, (void *)&imm32, sizeof(imm32), 0);
cpu_memory_rw_debug(cs, ip + 1, (void *)&imm32, sizeof(imm32), 1);
patch_call(x86_cpu, ip + 5, handlers->set_tpr);
break;
case 0xff: /* push r/m32 */
patch_byte(x86_cpu, ip, 0x50); /* push eax */
patch_call(x86_cpu, ip + 1, handlers->get_tpr_stack);
break;
default:
abort();
}
g_free(info);
}
static void patch_instruction(VAPICROMState *s, X86CPU *cpu, target_ulong ip)
{
CPUState *cs = CPU(cpu);
CPUX86State *env = &cpu->env;
VAPICHandlers *handlers;
uint8_t opcode[2];
uint32_t imm32 = 0;
target_ulong current_pc = 0;
target_ulong current_cs_base = 0;
uint32_t current_flags = 0;
PatchInfo *info;
if (smp_cpus == 1) {
handlers = &s->rom_state.up;
@ -410,60 +452,11 @@ static void patch_instruction(VAPICROMState *s, X86CPU *cpu, target_ulong ip)
handlers = &s->rom_state.mp;
}
if (tcg_enabled()) {
cpu_restore_state(cs, cs->mem_io_pc);
cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
&current_flags);
/* Account this instruction, because we will exit the tb.
This is the first instruction in the block. Therefore
there is no need in restoring CPU state. */
if (use_icount) {
--cs->icount_decr.u16.low;
}
}
info = g_new(PatchInfo, 1);
info->handler = handlers;
info->ip = ip;
pause_all_vcpus();
cpu_memory_rw_debug(cs, ip, opcode, sizeof(opcode), 0);
switch (opcode[0]) {
case 0x89: /* mov r32 to r/m32 */
patch_byte(cpu, ip, 0x50 + modrm_reg(opcode[1])); /* push reg */
patch_call(s, cpu, ip + 1, handlers->set_tpr);
break;
case 0x8b: /* mov r/m32 to r32 */
patch_byte(cpu, ip, 0x90);
patch_call(s, cpu, ip + 1, handlers->get_tpr[modrm_reg(opcode[1])]);
break;
case 0xa1: /* mov abs to eax */
patch_call(s, cpu, ip, handlers->get_tpr[0]);
break;
case 0xa3: /* mov eax to abs */
patch_call(s, cpu, ip, handlers->set_tpr_eax);
break;
case 0xc7: /* mov imm32, r/m32 (c7/0) */
patch_byte(cpu, ip, 0x68); /* push imm32 */
cpu_memory_rw_debug(cs, ip + 6, (void *)&imm32, sizeof(imm32), 0);
cpu_memory_rw_debug(cs, ip + 1, (void *)&imm32, sizeof(imm32), 1);
patch_call(s, cpu, ip + 5, handlers->set_tpr);
break;
case 0xff: /* push r/m32 */
patch_byte(cpu, ip, 0x50); /* push eax */
patch_call(s, cpu, ip + 1, handlers->get_tpr_stack);
break;
default:
abort();
}
resume_all_vcpus();
if (tcg_enabled()) {
/* Both tb_lock and iothread_mutex will be reset when
* longjmps back into the cpu_exec loop. */
tb_lock();
tb_gen_code(cs, current_pc, current_cs_base, current_flags, 1);
cpu_loop_exit_noexc(cs);
}
async_safe_run_on_cpu(cs, do_patch_instruction, RUN_ON_CPU_HOST_PTR(info));
}
void vapic_report_tpr_access(DeviceState *dev, CPUState *cs, target_ulong ip,

View File

@ -90,7 +90,7 @@ static TypeInfo ipmi_interface_type_info = {
.class_init = ipmi_interface_class_init,
};
static void isa_ipmi_bmc_check(Object *obj, const char *name,
static void isa_ipmi_bmc_check(const Object *obj, const char *name,
Object *val, Error **errp)
{
IPMIBmc *bmc = IPMI_BMC(val);

View File

@ -447,13 +447,13 @@ static void ipmi_bmc_extern_realize(DeviceState *dev, Error **errp)
{
IPMIBmcExtern *ibe = IPMI_BMC_EXTERN(dev);
if (!qemu_chr_fe_get_driver(&ibe->chr)) {
if (!qemu_chr_fe_backend_connected(&ibe->chr)) {
error_setg(errp, "IPMI external bmc requires chardev attribute");
return;
}
qemu_chr_fe_set_handlers(&ibe->chr, can_receive, receive,
chr_event, ibe, NULL, true);
chr_event, NULL, ibe, NULL, true);
}
static int ipmi_bmc_extern_post_migrate(void *opaque, int version_id)

View File

@ -350,6 +350,8 @@ static Property pc_dimm_properties[] = {
DEFINE_PROP_UINT32(PC_DIMM_NODE_PROP, PCDIMMDevice, node, 0),
DEFINE_PROP_INT32(PC_DIMM_SLOT_PROP, PCDIMMDevice, slot,
PC_DIMM_UNASSIGNED_SLOT),
DEFINE_PROP_LINK(PC_DIMM_MEMDEV_PROP, PCDIMMDevice, hostmem,
TYPE_MEMORY_BACKEND, HostMemoryBackend *),
DEFINE_PROP_END_OF_LIST(),
};
@ -367,33 +369,10 @@ static void pc_dimm_get_size(Object *obj, Visitor *v, const char *name,
visit_type_uint64(v, name, &value, errp);
}
static void pc_dimm_check_memdev_is_busy(Object *obj, const char *name,
Object *val, Error **errp)
{
Error *local_err = NULL;
if (host_memory_backend_is_mapped(MEMORY_BACKEND(val))) {
char *path = object_get_canonical_path_component(val);
error_setg(&local_err, "can't use already busy memdev: %s", path);
g_free(path);
} else {
qdev_prop_allow_set_link_before_realize(obj, name, val, &local_err);
}
error_propagate(errp, local_err);
}
static void pc_dimm_init(Object *obj)
{
PCDIMMDevice *dimm = PC_DIMM(obj);
object_property_add(obj, PC_DIMM_SIZE_PROP, "uint64", pc_dimm_get_size,
NULL, NULL, NULL, &error_abort);
object_property_add_link(obj, PC_DIMM_MEMDEV_PROP, TYPE_MEMORY_BACKEND,
(Object **)&dimm->hostmem,
pc_dimm_check_memdev_is_busy,
OBJ_PROP_LINK_UNREF_ON_RELEASE,
&error_abort);
}
static void pc_dimm_realize(DeviceState *dev, Error **errp)
@ -404,6 +383,11 @@ static void pc_dimm_realize(DeviceState *dev, Error **errp)
if (!dimm->hostmem) {
error_setg(errp, "'" PC_DIMM_MEMDEV_PROP "' property is not set");
return;
} else if (host_memory_backend_is_mapped(dimm->hostmem)) {
char *path = object_get_canonical_path_component(OBJECT(dimm->hostmem));
error_setg(errp, "can't use already busy memdev: %s", path);
g_free(path);
return;
}
if (((nb_numa_nodes > 0) && (dimm->node >= nb_numa_nodes)) ||
(!nb_numa_nodes && dimm->node)) {

View File

@ -533,7 +533,7 @@ static void boston_mach_init(MachineState *machine)
chr = qemu_chr_new("lcd", "vc:320x240");
qemu_chr_fe_init(&s->lcd_display, chr, NULL);
qemu_chr_fe_set_handlers(&s->lcd_display, NULL, NULL,
boston_lcd_event, s, NULL, true);
boston_lcd_event, NULL, s, NULL, true);
ahci = pci_create_simple_multifunction(&PCI_BRIDGE(&pcie2->root)->sec_bus,
PCI_DEVFN(0, 0),

View File

@ -130,7 +130,7 @@ static void mips_jazz_init(MachineState *machine,
CPUMIPSState *env;
qemu_irq *i8259;
rc4030_dma *dmas;
MemoryRegion *rc4030_dma_mr;
IOMMUMemoryRegion *rc4030_dma_mr;
MemoryRegion *isa_mem = g_new(MemoryRegion, 1);
MemoryRegion *isa_io = g_new(MemoryRegion, 1);
MemoryRegion *rtc = g_new(MemoryRegion, 1);

View File

@ -570,7 +570,7 @@ static MaltaFPGAState *malta_fpga_init(MemoryRegion *address_space,
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);
malta_fgpa_display_event, NULL, s, NULL, true);
s->uart = serial_mm_init(address_space, base + 0x900, 3, uart_irq,
230400, uart_chr, DEVICE_NATIVE_ENDIAN);

View File

@ -894,7 +894,7 @@ static void ivshmem_common_realize(PCIDevice *dev, Error **errp)
}
qemu_chr_fe_set_handlers(&s->server_chr, ivshmem_can_receive,
ivshmem_read, NULL, s, NULL, true);
ivshmem_read, NULL, NULL, s, NULL, true);
if (ivshmem_setup_interrupts(s, errp) < 0) {
error_prepend(errp, "Failed to initialize interrupts: ");
@ -1009,18 +1009,6 @@ static const TypeInfo ivshmem_common_info = {
.class_init = ivshmem_common_class_init,
};
static void ivshmem_check_memdev_is_busy(Object *obj, const char *name,
Object *val, Error **errp)
{
if (host_memory_backend_is_mapped(MEMORY_BACKEND(val))) {
char *path = object_get_canonical_path_component(val);
error_setg(errp, "can't use already busy memdev: %s", path);
g_free(path);
} else {
qdev_prop_allow_set_link_before_realize(obj, name, val, errp);
}
}
static const VMStateDescription ivshmem_plain_vmsd = {
.name = TYPE_IVSHMEM_PLAIN,
.version_id = 0,
@ -1037,6 +1025,8 @@ static const VMStateDescription ivshmem_plain_vmsd = {
static Property ivshmem_plain_properties[] = {
DEFINE_PROP_ON_OFF_AUTO("master", IVShmemState, master, ON_OFF_AUTO_OFF),
DEFINE_PROP_LINK("memdev", IVShmemState, hostmem, TYPE_MEMORY_BACKEND,
HostMemoryBackend *),
DEFINE_PROP_END_OF_LIST(),
};
@ -1044,11 +1034,6 @@ static void ivshmem_plain_init(Object *obj)
{
IVShmemState *s = IVSHMEM_PLAIN(obj);
object_property_add_link(obj, "memdev", TYPE_MEMORY_BACKEND,
(Object **)&s->hostmem,
ivshmem_check_memdev_is_busy,
OBJ_PROP_LINK_UNREF_ON_RELEASE,
&error_abort);
s->not_legacy_32bit = 1;
}
@ -1059,6 +1044,11 @@ static void ivshmem_plain_realize(PCIDevice *dev, Error **errp)
if (!s->hostmem) {
error_setg(errp, "You must specify a 'memdev'");
return;
} else if (host_memory_backend_is_mapped(s->hostmem)) {
char *path = object_get_canonical_path_component(OBJECT(s->hostmem));
error_setg(errp, "can't use already busy memdev: %s", path);
g_free(path);
return;
}
ivshmem_common_realize(dev, errp);
@ -1128,7 +1118,7 @@ static void ivshmem_doorbell_realize(PCIDevice *dev, Error **errp)
{
IVShmemState *s = IVSHMEM_COMMON(dev);
if (!qemu_chr_fe_get_driver(&s->server_chr)) {
if (!qemu_chr_fe_backend_connected(&s->server_chr)) {
error_setg(errp, "You must specify a 'chardev'");
return;
}
@ -1257,7 +1247,7 @@ static void ivshmem_realize(PCIDevice *dev, Error **errp)
" or ivshmem-doorbell instead");
}
if (!!qemu_chr_fe_get_driver(&s->server_chr) + !!s->shmobj != 1) {
if (qemu_chr_fe_backend_connected(&s->server_chr) + !!s->shmobj != 1) {
error_setg(errp, "You must specify either 'shm' or 'chardev'");
return;
}

View File

@ -181,18 +181,6 @@ static void mips_gcr_init(Object *obj)
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
MIPSGCRState *s = MIPS_GCR(obj);
object_property_add_link(obj, "gic", TYPE_MEMORY_REGION,
(Object **)&s->gic_mr,
qdev_prop_allow_set_link_before_realize,
OBJ_PROP_LINK_UNREF_ON_RELEASE,
&error_abort);
object_property_add_link(obj, "cpc", TYPE_MEMORY_REGION,
(Object **)&s->cpc_mr,
qdev_prop_allow_set_link_before_realize,
OBJ_PROP_LINK_UNREF_ON_RELEASE,
&error_abort);
memory_region_init_io(&s->iomem, OBJECT(s), &gcr_ops, s,
"mips-gcr", GCR_ADDRSPACE_SZ);
sysbus_init_mmio(sbd, &s->iomem);
@ -227,6 +215,10 @@ static Property mips_gcr_properties[] = {
DEFINE_PROP_INT32("num-vp", MIPSGCRState, num_vps, 1),
DEFINE_PROP_INT32("gcr-rev", MIPSGCRState, gcr_rev, 0x800),
DEFINE_PROP_UINT64("gcr-base", MIPSGCRState, gcr_base, GCR_BASE_ADDR),
DEFINE_PROP_LINK("gic", MIPSGCRState, gic_mr, TYPE_MEMORY_REGION,
MemoryRegion *),
DEFINE_PROP_LINK("cpc", MIPSGCRState, cpc_mr, TYPE_MEMORY_REGION,
MemoryRegion *),
DEFINE_PROP_END_OF_LIST(),
};

View File

@ -123,7 +123,7 @@ do { printf("IOMMU: " fmt , ## __VA_ARGS__); } while (0)
typedef struct IOMMUState {
AddressSpace iommu_as;
MemoryRegion iommu;
IOMMUMemoryRegion iommu;
uint64_t regs[IOMMU_NREGS];
} IOMMUState;
@ -133,6 +133,8 @@ typedef struct IOMMUState {
#define APB_DEVICE(obj) \
OBJECT_CHECK(APBState, (obj), TYPE_APB)
#define TYPE_APB_IOMMU_MEMORY_REGION "pbm-iommu-memory-region"
typedef struct APBState {
PCIHostState parent_obj;
@ -208,7 +210,7 @@ static AddressSpace *pbm_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
}
/* Called from RCU critical section */
static IOMMUTLBEntry pbm_translate_iommu(MemoryRegion *iommu, hwaddr addr,
static IOMMUTLBEntry pbm_translate_iommu(IOMMUMemoryRegion *iommu, hwaddr addr,
IOMMUAccessFlags flag)
{
IOMMUState *is = container_of(iommu, IOMMUState, iommu);
@ -322,10 +324,6 @@ static IOMMUTLBEntry pbm_translate_iommu(MemoryRegion *iommu, hwaddr addr,
return ret;
}
static MemoryRegionIOMMUOps pbm_iommu_ops = {
.translate = pbm_translate_iommu,
};
static void iommu_config_write(void *opaque, hwaddr addr,
uint64_t val, unsigned size)
{
@ -697,9 +695,10 @@ PCIBus *pci_apb_init(hwaddr special_base,
is = &d->iommu;
memset(is, 0, sizeof(IOMMUState));
memory_region_init_iommu(&is->iommu, OBJECT(dev), &pbm_iommu_ops,
memory_region_init_iommu(&is->iommu, sizeof(is->iommu),
TYPE_APB_IOMMU_MEMORY_REGION, OBJECT(dev),
"iommu-apb", UINT64_MAX);
address_space_init(&is->iommu_as, &is->iommu, "pbm-as");
address_space_init(&is->iommu_as, MEMORY_REGION(&is->iommu), "pbm-as");
pci_setup_iommu(phb->bus, pbm_pci_dma_iommu, is);
/* APB secondary busses */
@ -860,11 +859,25 @@ static const TypeInfo pbm_pci_bridge_info = {
.class_init = pbm_pci_bridge_class_init,
};
static void pbm_iommu_memory_region_class_init(ObjectClass *klass, void *data)
{
IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
imrc->translate = pbm_translate_iommu;
}
static const TypeInfo pbm_iommu_memory_region_info = {
.parent = TYPE_IOMMU_MEMORY_REGION,
.name = TYPE_APB_IOMMU_MEMORY_REGION,
.class_init = pbm_iommu_memory_region_class_init,
};
static void pbm_register_types(void)
{
type_register_static(&pbm_host_info);
type_register_static(&pbm_pci_host_info);
type_register_static(&pbm_pci_bridge_info);
type_register_static(&pbm_iommu_memory_region_info);
}
type_init(pbm_register_types)

View File

@ -110,7 +110,8 @@ static void spapr_tce_free_table(uint64_t *table, int fd, uint32_t nb_table)
}
/* Called from RCU critical section */
static IOMMUTLBEntry spapr_tce_translate_iommu(MemoryRegion *iommu, hwaddr addr,
static IOMMUTLBEntry spapr_tce_translate_iommu(IOMMUMemoryRegion *iommu,
hwaddr addr,
IOMMUAccessFlags flag)
{
sPAPRTCETable *tcet = container_of(iommu, sPAPRTCETable, iommu);
@ -150,14 +151,14 @@ static void spapr_tce_table_pre_save(void *opaque)
tcet->bus_offset, tcet->page_shift);
}
static uint64_t spapr_tce_get_min_page_size(MemoryRegion *iommu)
static uint64_t spapr_tce_get_min_page_size(IOMMUMemoryRegion *iommu)
{
sPAPRTCETable *tcet = container_of(iommu, sPAPRTCETable, iommu);
return 1ULL << tcet->page_shift;
}
static void spapr_tce_notify_flag_changed(MemoryRegion *iommu,
static void spapr_tce_notify_flag_changed(IOMMUMemoryRegion *iommu,
IOMMUNotifierFlag old,
IOMMUNotifierFlag new)
{
@ -247,12 +248,6 @@ static const VMStateDescription vmstate_spapr_tce_table = {
}
};
static MemoryRegionIOMMUOps spapr_iommu_ops = {
.translate = spapr_tce_translate_iommu,
.get_min_page_size = spapr_tce_get_min_page_size,
.notify_flag_changed = spapr_tce_notify_flag_changed,
};
static int spapr_tce_table_realize(DeviceState *dev)
{
sPAPRTCETable *tcet = SPAPR_TCE_TABLE(dev);
@ -265,7 +260,9 @@ static int spapr_tce_table_realize(DeviceState *dev)
memory_region_init(&tcet->root, tcetobj, tmp, UINT64_MAX);
snprintf(tmp, sizeof(tmp), "tce-iommu-%x", tcet->liobn);
memory_region_init_iommu(&tcet->iommu, tcetobj, &spapr_iommu_ops, tmp, 0);
memory_region_init_iommu(&tcet->iommu, sizeof(tcet->iommu),
TYPE_SPAPR_IOMMU_MEMORY_REGION,
tcetobj, tmp, 0);
QLIST_INSERT_HEAD(&spapr_tce_tables, tcet, list);
@ -348,9 +345,10 @@ void spapr_tce_table_enable(sPAPRTCETable *tcet,
&tcet->fd,
tcet->need_vfio);
memory_region_set_size(&tcet->iommu,
memory_region_set_size(MEMORY_REGION(&tcet->iommu),
(uint64_t)tcet->nb_table << tcet->page_shift);
memory_region_add_subregion(&tcet->root, tcet->bus_offset, &tcet->iommu);
memory_region_add_subregion(&tcet->root, tcet->bus_offset,
MEMORY_REGION(&tcet->iommu));
}
void spapr_tce_table_disable(sPAPRTCETable *tcet)
@ -359,8 +357,8 @@ void spapr_tce_table_disable(sPAPRTCETable *tcet)
return;
}
memory_region_del_subregion(&tcet->root, &tcet->iommu);
memory_region_set_size(&tcet->iommu, 0);
memory_region_del_subregion(&tcet->root, MEMORY_REGION(&tcet->iommu));
memory_region_set_size(MEMORY_REGION(&tcet->iommu), 0);
spapr_tce_free_table(tcet->table, tcet->fd, tcet->nb_table);
tcet->fd = -1;
@ -637,9 +635,25 @@ static TypeInfo spapr_tce_table_info = {
.class_init = spapr_tce_table_class_init,
};
static void spapr_iommu_memory_region_class_init(ObjectClass *klass, void *data)
{
IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
imrc->translate = spapr_tce_translate_iommu;
imrc->get_min_page_size = spapr_tce_get_min_page_size;
imrc->notify_flag_changed = spapr_tce_notify_flag_changed;
}
static const TypeInfo spapr_iommu_memory_region_info = {
.parent = TYPE_IOMMU_MEMORY_REGION,
.name = TYPE_SPAPR_IOMMU_MEMORY_REGION,
.class_init = spapr_iommu_memory_region_class_init,
};
static void register_types(void)
{
type_register_static(&spapr_tce_table_info);
type_register_static(&spapr_iommu_memory_region_info);
}
type_init(register_types);

View File

@ -96,17 +96,11 @@ static target_ulong h_random(PowerPCCPU *cpu, sPAPRMachineState *spapr,
static void spapr_rng_instance_init(Object *obj)
{
sPAPRRngState *rngstate = SPAPR_RNG(obj);
if (object_resolve_path_type("", TYPE_SPAPR_RNG, NULL) != NULL) {
error_report("spapr-rng can not be instantiated twice!");
return;
}
object_property_add_link(obj, "rng", TYPE_RNG_BACKEND,
(Object **)&rngstate->backend,
object_property_allow_set_link,
OBJ_PROP_LINK_UNREF_ON_RELEASE, NULL);
object_property_set_description(obj, "rng",
"ID of the random number generator backend",
NULL);
@ -163,6 +157,8 @@ int spapr_rng_populate_dt(void *fdt)
static Property spapr_rng_properties[] = {
DEFINE_PROP_BOOL("use-kvm", sPAPRRngState, use_kvm, false),
DEFINE_PROP_LINK("rng", sPAPRRngState, backend, TYPE_RNG_BACKEND,
RngBackend *),
DEFINE_PROP_END_OF_LIST(),
};

View File

@ -2095,7 +2095,7 @@ out:
g_free(str);
}
PropertyInfo css_devid_propinfo = {
const PropertyInfo css_devid_propinfo = {
.name = "str",
.description = "Identifier of an I/O device in the channel "
"subsystem, example: fe.1.23ab",
@ -2103,7 +2103,7 @@ PropertyInfo css_devid_propinfo = {
.set = set_css_devid,
};
PropertyInfo css_devid_ro_propinfo = {
const PropertyInfo css_devid_ro_propinfo = {
.name = "str",
.description = "Read-only identifier of an I/O device in the channel "
"subsystem, example: fe.1.23ab",

View File

@ -356,7 +356,7 @@ out:
return pte;
}
static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *mr, hwaddr addr,
static IOMMUTLBEntry s390_translate_iommu(IOMMUMemoryRegion *mr, hwaddr addr,
IOMMUAccessFlags flag)
{
uint64_t pte;
@ -407,10 +407,6 @@ static IOMMUTLBEntry s390_translate_iommu(MemoryRegion *mr, hwaddr addr,
return ret;
}
static const MemoryRegionIOMMUOps s390_iommu_ops = {
.translate = s390_translate_iommu,
};
static S390PCIIOMMU *s390_pci_get_iommu(S390pciState *s, PCIBus *bus,
int devfn)
{
@ -522,17 +518,18 @@ static const MemoryRegionOps s390_msi_ctrl_ops = {
void s390_pci_iommu_enable(S390PCIIOMMU *iommu)
{
char *name = g_strdup_printf("iommu-s390-%04x", iommu->pbdev->uid);
memory_region_init_iommu(&iommu->iommu_mr, OBJECT(&iommu->mr),
&s390_iommu_ops, name, iommu->pal + 1);
memory_region_init_iommu(&iommu->iommu_mr, sizeof(iommu->iommu_mr),
TYPE_S390_IOMMU_MEMORY_REGION, OBJECT(&iommu->mr),
name, iommu->pal + 1);
iommu->enabled = true;
memory_region_add_subregion(&iommu->mr, 0, &iommu->iommu_mr);
memory_region_add_subregion(&iommu->mr, 0, MEMORY_REGION(&iommu->iommu_mr));
g_free(name);
}
void s390_pci_iommu_disable(S390PCIIOMMU *iommu)
{
iommu->enabled = false;
memory_region_del_subregion(&iommu->mr, &iommu->iommu_mr);
memory_region_del_subregion(&iommu->mr, MEMORY_REGION(&iommu->iommu_mr));
object_unparent(OBJECT(&iommu->iommu_mr));
}
@ -1018,7 +1015,7 @@ static void s390_pci_set_fid(Object *obj, Visitor *v, const char *name,
zpci->fid_defined = true;
}
static PropertyInfo s390_pci_fid_propinfo = {
static const PropertyInfo s390_pci_fid_propinfo = {
.name = "zpci_fid",
.get = s390_pci_get_fid,
.set = s390_pci_set_fid,
@ -1058,12 +1055,26 @@ static TypeInfo s390_pci_iommu_info = {
.instance_size = sizeof(S390PCIIOMMU),
};
static void s390_iommu_memory_region_class_init(ObjectClass *klass, void *data)
{
IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_CLASS(klass);
imrc->translate = s390_translate_iommu;
}
static const TypeInfo s390_iommu_memory_region_info = {
.parent = TYPE_IOMMU_MEMORY_REGION,
.name = TYPE_S390_IOMMU_MEMORY_REGION,
.class_init = s390_iommu_memory_region_class_init,
};
static void s390_pci_register_types(void)
{
type_register_static(&s390_pcihost_info);
type_register_static(&s390_pcibus_info);
type_register_static(&s390_pci_device_info);
type_register_static(&s390_pci_iommu_info);
type_register_static(&s390_iommu_memory_region_info);
}
type_init(s390_pci_register_types)

View File

@ -24,6 +24,7 @@
#define TYPE_S390_PCI_BUS "s390-pcibus"
#define TYPE_S390_PCI_DEVICE "zpci"
#define TYPE_S390_PCI_IOMMU "s390-pci-iommu"
#define TYPE_S390_IOMMU_MEMORY_REGION "s390-iommu-memory-region"
#define FH_MASK_ENABLE 0x80000000
#define FH_MASK_INSTANCE 0x7f000000
#define FH_MASK_SHM 0x00ff0000
@ -266,7 +267,7 @@ typedef struct S390PCIIOMMU {
S390PCIBusDevice *pbdev;
AddressSpace as;
MemoryRegion mr;
MemoryRegion iommu_mr;
IOMMUMemoryRegion iommu_mr;
bool enabled;
uint64_t g_iota;
uint64_t pba;

View File

@ -563,7 +563,8 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
S390PCIIOMMU *iommu;
hwaddr start, end;
IOMMUTLBEntry entry;
MemoryRegion *mr;
IOMMUMemoryRegion *iommu_mr;
IOMMUMemoryRegionClass *imrc;
cpu_synchronize_state(CPU(cpu));
@ -622,9 +623,11 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
goto out;
}
mr = &iommu->iommu_mr;
iommu_mr = &iommu->iommu_mr;
imrc = IOMMU_MEMORY_REGION_GET_CLASS(iommu_mr);
while (start < end) {
entry = mr->iommu_ops->translate(mr, start, IOMMU_NONE);
entry = imrc->translate(iommu_mr, start, IOMMU_NONE);
if (!entry.translated_addr) {
pbdev->state = ZPCI_FS_ERROR;
@ -635,7 +638,7 @@ int rpcit_service_call(S390CPU *cpu, uint8_t r1, uint8_t r2)
goto out;
}
memory_region_notify_iommu(mr, entry);
memory_region_notify_iommu(iommu_mr, entry);
start += entry.addr_mask + 1;
}

View File

@ -867,8 +867,6 @@ static void virtio_ccw_blk_instance_init(Object *obj)
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
TYPE_VIRTIO_BLK);
object_property_add_alias(obj, "iothread", OBJECT(&dev->vdev),"iothread",
&error_abort);
object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev),
"bootindex", &error_abort);
}
@ -952,8 +950,6 @@ static void virtio_ccw_scsi_instance_init(Object *obj)
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
TYPE_VIRTIO_SCSI);
object_property_add_alias(obj, "iothread", OBJECT(&dev->vdev), "iothread",
&error_abort);
}
#ifdef CONFIG_VHOST_SCSI
@ -1552,8 +1548,6 @@ static void virtio_ccw_rng_instance_init(Object *obj)
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
TYPE_VIRTIO_RNG);
object_property_add_alias(obj, "rng", OBJECT(&dev->vdev),
"rng", &error_abort);
}
static Property virtio_ccw_rng_properties[] = {
@ -1600,9 +1594,6 @@ static void virtio_ccw_crypto_instance_init(Object *obj)
ccw_dev->force_revision_1 = true;
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
TYPE_VIRTIO_CRYPTO);
object_property_add_alias(obj, "cryptodev", OBJECT(&dev->vdev),
"cryptodev", &error_abort);
}
static void virtio_ccw_crypto_class_init(ObjectClass *klass, void *data)

View File

@ -898,16 +898,6 @@ static void virtio_scsi_device_realize(DeviceState *dev, Error **errp)
virtio_scsi_dataplane_setup(s, errp);
}
static void virtio_scsi_instance_init(Object *obj)
{
VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(obj);
object_property_add_link(obj, "iothread", TYPE_IOTHREAD,
(Object **)&vs->conf.iothread,
qdev_prop_allow_set_link_before_realize,
OBJ_PROP_LINK_UNREF_ON_RELEASE, &error_abort);
}
void virtio_scsi_common_unrealize(DeviceState *dev, Error **errp)
{
VirtIODevice *vdev = VIRTIO_DEVICE(dev);
@ -935,6 +925,8 @@ static Property virtio_scsi_properties[] = {
VIRTIO_SCSI_F_HOTPLUG, true),
DEFINE_PROP_BIT("param_change", VirtIOSCSI, host_features,
VIRTIO_SCSI_F_CHANGE, true),
DEFINE_PROP_LINK("iothread", VirtIOSCSI, parent_obj.conf.iothread,
TYPE_IOTHREAD, IOThread *),
DEFINE_PROP_END_OF_LIST(),
};
@ -989,7 +981,6 @@ static const TypeInfo virtio_scsi_info = {
.name = TYPE_VIRTIO_SCSI,
.parent = TYPE_VIRTIO_SCSI_COMMON,
.instance_size = sizeof(VirtIOSCSI),
.instance_init = virtio_scsi_instance_init,
.class_init = virtio_scsi_class_init,
.interfaces = (InterfaceInfo[]) {
{ TYPE_HOTPLUG_HANDLER },

View File

@ -322,7 +322,7 @@ static void passthru_apdu_from_guest(
{
PassthruState *card = PASSTHRU_CCID_CARD(base);
if (!qemu_chr_fe_get_driver(&card->cs)) {
if (!qemu_chr_fe_backend_connected(&card->cs)) {
printf("ccid-passthru: no chardev, discarding apdu length %d\n", len);
return;
}
@ -343,12 +343,12 @@ static int passthru_initfn(CCIDCardState *base)
card->vscard_in_pos = 0;
card->vscard_in_hdr = 0;
if (qemu_chr_fe_get_driver(&card->cs)) {
if (qemu_chr_fe_backend_connected(&card->cs)) {
DPRINTF(card, D_INFO, "initing chardev\n");
qemu_chr_fe_set_handlers(&card->cs,
ccid_card_vscard_can_read,
ccid_card_vscard_read,
ccid_card_vscard_event, card, NULL, true);
ccid_card_vscard_event, NULL, card, NULL, true);
ccid_card_vscard_send_init(card);
} else {
error_report("missing chardev");

View File

@ -484,13 +484,12 @@ static void usb_serial_realize(USBDevice *dev, Error **errp)
{
USBSerialState *s = USB_SERIAL_DEV(dev);
Error *local_err = NULL;
Chardev *chr = qemu_chr_fe_get_driver(&s->cs);
usb_desc_create_serial(dev);
usb_desc_init(dev);
dev->auto_attach = 0;
if (!chr) {
if (!qemu_chr_fe_backend_connected(&s->cs)) {
error_setg(errp, "Property chardev is required");
return;
}
@ -502,10 +501,10 @@ static void usb_serial_realize(USBDevice *dev, Error **errp)
}
qemu_chr_fe_set_handlers(&s->cs, usb_serial_can_read, usb_serial_read,
usb_serial_event, s, NULL, true);
usb_serial_event, NULL, s, NULL, true);
usb_serial_handle_reset(dev);
if (chr->be_open && !dev->attached) {
if (qemu_chr_fe_backend_open(&s->cs) && !dev->attached) {
usb_device_attach(dev, &error_abort);
}
}

View File

@ -273,10 +273,9 @@ static gboolean usbredir_write_unblocked(GIOChannel *chan, GIOCondition cond,
static int usbredir_write(void *priv, uint8_t *data, int count)
{
USBRedirDevice *dev = priv;
Chardev *chr = qemu_chr_fe_get_driver(&dev->cs);
int r;
if (!chr->be_open) {
if (!qemu_chr_fe_backend_open(&dev->cs)) {
return 0;
}
@ -1366,7 +1365,7 @@ static void usbredir_realize(USBDevice *udev, Error **errp)
USBRedirDevice *dev = USB_REDIRECT(udev);
int i;
if (!qemu_chr_fe_get_driver(&dev->cs)) {
if (!qemu_chr_fe_backend_connected(&dev->cs)) {
error_setg(errp, QERR_MISSING_PARAMETER, "chardev");
return;
}
@ -1399,7 +1398,7 @@ static void usbredir_realize(USBDevice *udev, Error **errp)
/* Let the backend know we are ready */
qemu_chr_fe_set_handlers(&dev->cs, usbredir_chardev_can_read,
usbredir_chardev_read, usbredir_chardev_event,
dev, NULL, true);
NULL, dev, NULL, true);
dev->vmstate =
qemu_add_vm_change_state_handler(usbredir_vm_state_change, dev);

View File

@ -479,6 +479,7 @@ static void vfio_listener_region_add(MemoryListener *listener,
if (memory_region_is_iommu(section->mr)) {
VFIOGuestIOMMU *giommu;
IOMMUMemoryRegion *iommu_mr = IOMMU_MEMORY_REGION(section->mr);
trace_vfio_listener_region_add_iommu(iova, end);
/*
@ -488,7 +489,7 @@ static void vfio_listener_region_add(MemoryListener *listener,
* device emulation the VFIO iommu handles to use).
*/
giommu = g_malloc0(sizeof(*giommu));
giommu->iommu = section->mr;
giommu->iommu = iommu_mr;
giommu->iommu_offset = section->offset_within_address_space -
section->offset_within_region;
giommu->container = container;
@ -501,7 +502,7 @@ static void vfio_listener_region_add(MemoryListener *listener,
int128_get64(llend));
QLIST_INSERT_HEAD(&container->giommu_list, giommu, giommu_next);
memory_region_register_iommu_notifier(giommu->iommu, &giommu->n);
memory_region_register_iommu_notifier(section->mr, &giommu->n);
memory_region_iommu_replay(giommu->iommu, &giommu->n);
return;
@ -569,9 +570,9 @@ static void vfio_listener_region_del(MemoryListener *listener,
VFIOGuestIOMMU *giommu;
QLIST_FOREACH(giommu, &container->giommu_list, giommu_next) {
if (giommu->iommu == section->mr &&
if (MEMORY_REGION(giommu->iommu) == section->mr &&
giommu->n.start == section->offset_within_region) {
memory_region_unregister_iommu_notifier(giommu->iommu,
memory_region_unregister_iommu_notifier(section->mr,
&giommu->n);
QLIST_REMOVE(giommu, giommu_next);
g_free(giommu);
@ -1163,7 +1164,8 @@ static void vfio_disconnect_container(VFIOGroup *group)
QLIST_REMOVE(container, next);
QLIST_FOREACH_SAFE(giommu, &container->giommu_list, giommu_next, tmp) {
memory_region_unregister_iommu_notifier(giommu->iommu, &giommu->n);
memory_region_unregister_iommu_notifier(
MEMORY_REGION(giommu->iommu), &giommu->n);
QLIST_REMOVE(giommu, giommu_next);
g_free(giommu);
}

View File

@ -143,7 +143,8 @@ int vfio_spapr_create_window(VFIOContainer *container,
hwaddr *pgsize)
{
int ret;
unsigned pagesize = memory_region_iommu_get_min_page_size(section->mr);
IOMMUMemoryRegion *iommu_mr = IOMMU_MEMORY_REGION(section->mr);
unsigned pagesize = memory_region_iommu_get_min_page_size(iommu_mr);
unsigned entries, pages;
struct vfio_iommu_spapr_tce_create create = { .argsz = sizeof(create) };

View File

@ -62,8 +62,6 @@ static void virtio_crypto_initfn(Object *obj)
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
TYPE_VIRTIO_CRYPTO);
object_property_add_alias(obj, "cryptodev", OBJECT(&dev->vdev),
"cryptodev", &error_abort);
}
static const TypeInfo virtio_crypto_pci_info = {

View File

@ -781,6 +781,11 @@ static void virtio_crypto_device_realize(DeviceState *dev, Error **errp)
if (vcrypto->cryptodev == NULL) {
error_setg(errp, "'cryptodev' parameter expects a valid object");
return;
} else if (cryptodev_backend_is_used(vcrypto->cryptodev)) {
char *path = object_get_canonical_path_component(OBJECT(vcrypto->conf.cryptodev));
error_setg(errp, "can't use already used cryptodev backend: %s", path);
g_free(path);
return;
}
vcrypto->max_queues = MAX(vcrypto->cryptodev->conf.peers.queues, 1);
@ -845,6 +850,8 @@ static const VMStateDescription vmstate_virtio_crypto = {
};
static Property virtio_crypto_properties[] = {
DEFINE_PROP_LINK("cryptodev", VirtIOCrypto, conf.cryptodev,
TYPE_CRYPTODEV_BACKEND, CryptoDevBackend *),
DEFINE_PROP_END_OF_LIST(),
};
@ -888,20 +895,6 @@ static void virtio_crypto_class_init(ObjectClass *klass, void *data)
vdc->reset = virtio_crypto_reset;
}
static void
virtio_crypto_check_cryptodev_is_used(Object *obj, const char *name,
Object *val, Error **errp)
{
if (cryptodev_backend_is_used(CRYPTODEV_BACKEND(val))) {
char *path = object_get_canonical_path_component(val);
error_setg(errp,
"can't use already used cryptodev backend: %s", path);
g_free(path);
} else {
qdev_prop_allow_set_link_before_realize(obj, name, val, errp);
}
}
static void virtio_crypto_instance_init(Object *obj)
{
VirtIOCrypto *vcrypto = VIRTIO_CRYPTO(obj);
@ -911,12 +904,6 @@ static void virtio_crypto_instance_init(Object *obj)
* Can be overriden with virtio_crypto_set_config_size.
*/
vcrypto->config_size = sizeof(struct virtio_crypto_config);
object_property_add_link(obj, "cryptodev",
TYPE_CRYPTODEV_BACKEND,
(Object **)&vcrypto->conf.cryptodev,
virtio_crypto_check_cryptodev_is_used,
OBJ_PROP_LINK_UNREF_ON_RELEASE, NULL);
}
static const TypeInfo virtio_crypto_info = {

View File

@ -2000,8 +2000,6 @@ static void virtio_blk_pci_instance_init(Object *obj)
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
TYPE_VIRTIO_BLK);
object_property_add_alias(obj, "iothread", OBJECT(&dev->vdev),"iothread",
&error_abort);
object_property_add_alias(obj, "bootindex", OBJECT(&dev->vdev),
"bootindex", &error_abort);
}
@ -2071,8 +2069,6 @@ static void virtio_scsi_pci_instance_init(Object *obj)
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
TYPE_VIRTIO_SCSI);
object_property_add_alias(obj, "iothread", OBJECT(&dev->vdev), "iothread",
&error_abort);
}
static const TypeInfo virtio_scsi_pci_info = {
@ -2467,8 +2463,6 @@ static void virtio_rng_initfn(Object *obj)
virtio_instance_init_common(obj, &dev->vdev, sizeof(dev->vdev),
TYPE_VIRTIO_RNG);
object_property_add_alias(obj, "rng", OBJECT(&dev->vdev), "rng",
&error_abort);
}
static const TypeInfo virtio_rng_pci_info = {

View File

@ -246,6 +246,7 @@ static Property virtio_rng_properties[] = {
*/
DEFINE_PROP_UINT64("max-bytes", VirtIORNG, conf.max_bytes, INT64_MAX),
DEFINE_PROP_UINT32("period", VirtIORNG, conf.period_ms, 1 << 16),
DEFINE_PROP_LINK("rng", VirtIORNG, conf.rng, TYPE_RNG_BACKEND, RngBackend *),
DEFINE_PROP_END_OF_LIST(),
};
@ -262,21 +263,10 @@ static void virtio_rng_class_init(ObjectClass *klass, void *data)
vdc->get_features = get_features;
}
static void virtio_rng_initfn(Object *obj)
{
VirtIORNG *vrng = VIRTIO_RNG(obj);
object_property_add_link(obj, "rng", TYPE_RNG_BACKEND,
(Object **)&vrng->conf.rng,
qdev_prop_allow_set_link_before_realize,
OBJ_PROP_LINK_UNREF_ON_RELEASE, NULL);
}
static const TypeInfo virtio_rng_info = {
.name = TYPE_VIRTIO_RNG,
.parent = TYPE_VIRTIO_DEVICE,
.instance_size = sizeof(VirtIORNG),
.instance_init = virtio_rng_initfn,
.class_init = virtio_rng_class_init,
};

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 Red Hat, Inc.
* Copyright (C) 2016-2017 Red Hat, Inc.
* Copyright (C) 2005 Anthony Liguori <anthony@codemonkey.ws>
*
* Network Block Device
@ -83,18 +83,37 @@ typedef struct NBDReply NBDReply;
#define NBD_FLAG_C_FIXED_NEWSTYLE (1 << 0) /* Fixed newstyle protocol. */
#define NBD_FLAG_C_NO_ZEROES (1 << 1) /* End handshake without zeroes. */
/* Reply types. */
/* Option requests. */
#define NBD_OPT_EXPORT_NAME (1)
#define NBD_OPT_ABORT (2)
#define NBD_OPT_LIST (3)
/* #define NBD_OPT_PEEK_EXPORT (4) not in use */
#define NBD_OPT_STARTTLS (5)
#define NBD_OPT_INFO (6)
#define NBD_OPT_GO (7)
#define NBD_OPT_STRUCTURED_REPLY (8)
/* Option reply types. */
#define NBD_REP_ERR(value) ((UINT32_C(1) << 31) | (value))
#define NBD_REP_ACK (1) /* Data sending finished. */
#define NBD_REP_SERVER (2) /* Export description. */
#define NBD_REP_INFO (3) /* NBD_OPT_INFO/GO. */
#define NBD_REP_ERR_UNSUP NBD_REP_ERR(1) /* Unknown option */
#define NBD_REP_ERR_POLICY NBD_REP_ERR(2) /* Server denied */
#define NBD_REP_ERR_INVALID NBD_REP_ERR(3) /* Invalid length */
#define NBD_REP_ERR_PLATFORM NBD_REP_ERR(4) /* Not compiled in */
#define NBD_REP_ERR_TLS_REQD NBD_REP_ERR(5) /* TLS required */
#define NBD_REP_ERR_SHUTDOWN NBD_REP_ERR(7) /* Server shutting down */
#define NBD_REP_ERR_UNSUP NBD_REP_ERR(1) /* Unknown option */
#define NBD_REP_ERR_POLICY NBD_REP_ERR(2) /* Server denied */
#define NBD_REP_ERR_INVALID NBD_REP_ERR(3) /* Invalid length */
#define NBD_REP_ERR_PLATFORM NBD_REP_ERR(4) /* Not compiled in */
#define NBD_REP_ERR_TLS_REQD NBD_REP_ERR(5) /* TLS required */
#define NBD_REP_ERR_UNKNOWN NBD_REP_ERR(6) /* Export unknown */
#define NBD_REP_ERR_SHUTDOWN NBD_REP_ERR(7) /* Server shutting down */
#define NBD_REP_ERR_BLOCK_SIZE_REQD NBD_REP_ERR(8) /* Need INFO_BLOCK_SIZE */
/* Info types, used during NBD_REP_INFO */
#define NBD_INFO_EXPORT 0
#define NBD_INFO_NAME 1
#define NBD_INFO_DESCRIPTION 2
#define NBD_INFO_BLOCK_SIZE 3
/* Request flags, sent from client to server during transmission phase */
#define NBD_CMD_FLAG_FUA (1 << 0) /* 'force unit access' during write */
@ -123,13 +142,26 @@ enum {
* aren't overflowing some other buffer. */
#define NBD_MAX_NAME_SIZE 256
/* Details collected by NBD_OPT_EXPORT_NAME and NBD_OPT_GO */
struct NBDExportInfo {
/* Set by client before nbd_receive_negotiate() */
bool request_sizes;
/* Set by server results during nbd_receive_negotiate() */
uint64_t size;
uint16_t flags;
uint32_t min_block;
uint32_t opt_block;
uint32_t max_block;
};
typedef struct NBDExportInfo NBDExportInfo;
ssize_t nbd_rwv(QIOChannel *ioc, struct iovec *iov, size_t niov, size_t length,
bool do_read, Error **errp);
int nbd_receive_negotiate(QIOChannel *ioc, const char *name, uint16_t *flags,
int nbd_receive_negotiate(QIOChannel *ioc, const char *name,
QCryptoTLSCreds *tlscreds, const char *hostname,
QIOChannel **outioc,
off_t *size, Error **errp);
int nbd_init(int fd, QIOChannelSocket *sioc, uint16_t flags, off_t size,
QIOChannel **outioc, NBDExportInfo *info,
Error **errp);
int nbd_init(int fd, QIOChannelSocket *sioc, NBDExportInfo *info,
Error **errp);
ssize_t nbd_send_request(QIOChannel *ioc, NBDRequest *request);
ssize_t nbd_receive_reply(QIOChannel *ioc, NBDReply *reply, Error **errp);

View File

@ -4,6 +4,7 @@
#include "chardev/char.h"
typedef void IOEventHandler(void *opaque, int event);
typedef int BackendChangeHandler(void *opaque);
/* This is the backend as seen by frontend, the actual backend is
* Chardev */
@ -12,6 +13,7 @@ struct CharBackend {
IOEventHandler *chr_event;
IOCanReadHandler *chr_can_read;
IOReadHandler *chr_read;
BackendChangeHandler *chr_be_change;
void *opaque;
int tag;
int fe_open;
@ -44,9 +46,26 @@ void qemu_chr_fe_deinit(CharBackend *b, bool del);
*
* Returns the driver associated with a CharBackend or NULL if no
* associated Chardev.
* Note: avoid this function as the driver should never be accessed directly,
* especially by the frontends that support chardevice hotswap.
* Consider qemu_chr_fe_backend_connected() to check for driver existence
*/
Chardev *qemu_chr_fe_get_driver(CharBackend *be);
/**
* @qemu_chr_fe_backend_connected:
*
* Returns true if there is a chardevice associated with @be.
*/
bool qemu_chr_fe_backend_connected(CharBackend *be);
/**
* @qemu_chr_fe_backend_open:
*
* Returns true if chardevice associated with @be is open.
*/
bool qemu_chr_fe_backend_open(CharBackend *be);
/**
* @qemu_chr_fe_set_handlers:
* @b: a CharBackend
@ -54,6 +73,8 @@ Chardev *qemu_chr_fe_get_driver(CharBackend *be);
* receive
* @fd_read: callback to receive data from char
* @fd_event: event callback
* @be_change: backend change callback; passing NULL means hot backend change
* is not supported and will not be attempted
* @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
@ -68,6 +89,7 @@ void qemu_chr_fe_set_handlers(CharBackend *b,
IOCanReadHandler *fd_can_read,
IOReadHandler *fd_read,
IOEventHandler *fd_event,
BackendChangeHandler *be_change,
void *opaque,
GMainContext *context,
bool set_open);

View File

@ -80,6 +80,16 @@ Chardev *qemu_chr_new_from_opts(QemuOpts *opts,
*/
void qemu_chr_parse_common(QemuOpts *opts, ChardevCommon *backend);
/**
* @qemu_chr_parse_opts:
*
* Parse the options to the ChardevBackend struct.
*
* Returns: a new backend or NULL on error
*/
ChardevBackend *qemu_chr_parse_opts(QemuOpts *opts,
Error **errp);
/**
* @qemu_chr_new:
*
@ -92,6 +102,15 @@ void qemu_chr_parse_common(QemuOpts *opts, ChardevCommon *backend);
*/
Chardev *qemu_chr_new(const char *label, const char *filename);
/**
* @qemu_chr_change:
*
* Change an existing character backend
*
* @opts the new backend options
*/
void qemu_chr_change(QemuOpts *opts, Error **errp);
/**
* @qemu_chr_cleanup:
*

View File

@ -290,6 +290,9 @@ static inline void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu,
uint16_t idxmap)
{
}
static inline void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr)
{
}
#endif
#define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */

View File

@ -58,15 +58,6 @@ void gdb_register_coprocessor(CPUState *cpu,
gdb_reg_cb get_reg, gdb_reg_cb set_reg,
int num_regs, const char *xml, int g_pos);
static inline int cpu_index(CPUState *cpu)
{
#if defined(CONFIG_USER_ONLY)
return cpu->host_tid;
#else
return cpu->cpu_index + 1;
#endif
}
/* The GDB remote protocol transfers values in target byte order. This means
* we can use the raw memory access routines to access the value buffer.
* Conveniently, these also handle the case where the buffer is mis-aligned.

View File

@ -25,6 +25,7 @@
#include "qemu/notify.h"
#include "qom/object.h"
#include "qemu/rcu.h"
#include "hw/qdev-core.h"
#define RAM_ADDR_INVALID (~(ram_addr_t)0)
@ -35,6 +36,16 @@
#define MEMORY_REGION(obj) \
OBJECT_CHECK(MemoryRegion, (obj), TYPE_MEMORY_REGION)
#define TYPE_IOMMU_MEMORY_REGION "qemu:iommu-memory-region"
#define IOMMU_MEMORY_REGION(obj) \
OBJECT_CHECK(IOMMUMemoryRegion, (obj), TYPE_IOMMU_MEMORY_REGION)
#define IOMMU_MEMORY_REGION_CLASS(klass) \
OBJECT_CLASS_CHECK(IOMMUMemoryRegionClass, (klass), \
TYPE_IOMMU_MEMORY_REGION)
#define IOMMU_MEMORY_REGION_GET_CLASS(obj) \
OBJECT_GET_CLASS(IOMMUMemoryRegionClass, (obj), \
TYPE_IOMMU_MEMORY_REGION)
typedef struct MemoryRegionOps MemoryRegionOps;
typedef struct MemoryRegionMmio MemoryRegionMmio;
@ -189,26 +200,27 @@ struct MemoryRegionOps {
const MemoryRegionMmio old_mmio;
};
typedef struct MemoryRegionIOMMUOps MemoryRegionIOMMUOps;
typedef struct IOMMUMemoryRegionClass {
/* private */
struct DeviceClass parent_class;
struct MemoryRegionIOMMUOps {
/*
* Return a TLB entry that contains a given address. Flag should
* be the access permission of this translation operation. We can
* set flag to IOMMU_NONE to mean that we don't need any
* read/write permission checks, like, when for region replay.
*/
IOMMUTLBEntry (*translate)(MemoryRegion *iommu, hwaddr addr,
IOMMUTLBEntry (*translate)(IOMMUMemoryRegion *iommu, hwaddr addr,
IOMMUAccessFlags flag);
/* Returns minimum supported page size */
uint64_t (*get_min_page_size)(MemoryRegion *iommu);
uint64_t (*get_min_page_size)(IOMMUMemoryRegion *iommu);
/* Called when IOMMU Notifier flag changed */
void (*notify_flag_changed)(MemoryRegion *iommu,
void (*notify_flag_changed)(IOMMUMemoryRegion *iommu,
IOMMUNotifierFlag old_flags,
IOMMUNotifierFlag new_flags);
/* Set this up to provide customized IOMMU replay function */
void (*replay)(MemoryRegion *iommu, IOMMUNotifier *notifier);
};
void (*replay)(IOMMUMemoryRegion *iommu, IOMMUNotifier *notifier);
} IOMMUMemoryRegionClass;
typedef struct CoalescedMemoryRange CoalescedMemoryRange;
typedef struct MemoryRegionIoeventfd MemoryRegionIoeventfd;
@ -227,9 +239,9 @@ struct MemoryRegion {
bool flush_coalesced_mmio;
bool global_locking;
uint8_t dirty_log_mask;
bool is_iommu;
RAMBlock *ram_block;
Object *owner;
const MemoryRegionIOMMUOps *iommu_ops;
const MemoryRegionOps *ops;
void *opaque;
@ -252,6 +264,11 @@ struct MemoryRegion {
const char *name;
unsigned ioeventfd_nb;
MemoryRegionIoeventfd *ioeventfds;
};
struct IOMMUMemoryRegion {
MemoryRegion parent_obj;
QLIST_HEAD(, IOMMUNotifier) iommu_notify;
IOMMUNotifierFlag iommu_notify_flags;
};
@ -612,21 +629,24 @@ static inline void memory_region_init_reservation(MemoryRegion *mr,
}
/**
* memory_region_init_iommu: Initialize a memory region that translates
* addresses
* memory_region_init_iommu: Initialize a memory region of a custom type
* that translates addresses
*
* An IOMMU region translates addresses and forwards accesses to a target
* memory region.
*
* @mr: the #MemoryRegion to be initialized
* @typename: QOM class name
* @_iommu_mr: the #IOMMUMemoryRegion to be initialized
* @instance_size: the IOMMUMemoryRegion subclass instance size
* @owner: the object that tracks the region's reference count
* @ops: a function that translates addresses into the @target region
* @name: used for debugging; not visible to the user or ABI
* @size: size of the region.
*/
void memory_region_init_iommu(MemoryRegion *mr,
struct Object *owner,
const MemoryRegionIOMMUOps *ops,
void memory_region_init_iommu(void *_iommu_mr,
size_t instance_size,
const char *mrtypename,
Object *owner,
const char *name,
uint64_t size);
@ -679,20 +699,40 @@ static inline bool memory_region_is_romd(MemoryRegion *mr)
}
/**
* memory_region_is_iommu: check whether a memory region is an iommu
* memory_region_get_iommu: check whether a memory region is an iommu
*
* Returns %true is a memory region is an iommu.
* Returns pointer to IOMMUMemoryRegion if a memory region is an iommu,
* otherwise NULL.
*
* @mr: the memory region being queried
*/
static inline bool memory_region_is_iommu(MemoryRegion *mr)
static inline IOMMUMemoryRegion *memory_region_get_iommu(MemoryRegion *mr)
{
if (mr->alias) {
return memory_region_is_iommu(mr->alias);
return memory_region_get_iommu(mr->alias);
}
return mr->iommu_ops;
if (mr->is_iommu) {
return (IOMMUMemoryRegion *) mr;
}
return NULL;
}
/**
* memory_region_get_iommu_class_nocheck: returns iommu memory region class
* if an iommu or NULL if not
*
* Returns pointer to IOMMUMemoryRegioniClass if a memory region is an iommu,
* otherwise NULL. This is fast path avoinding QOM checking, use with caution.
*
* @mr: the memory region being queried
*/
static inline IOMMUMemoryRegionClass *memory_region_get_iommu_class_nocheck(
IOMMUMemoryRegion *iommu_mr)
{
return (IOMMUMemoryRegionClass *) (((Object *)iommu_mr)->class);
}
#define memory_region_is_iommu(mr) (memory_region_get_iommu(mr) != NULL)
/**
* memory_region_iommu_get_min_page_size: get minimum supported page size
@ -700,9 +740,9 @@ static inline bool memory_region_is_iommu(MemoryRegion *mr)
*
* Returns minimum supported page size for an iommu.
*
* @mr: the memory region being queried
* @iommu_mr: the memory region being queried
*/
uint64_t memory_region_iommu_get_min_page_size(MemoryRegion *mr);
uint64_t memory_region_iommu_get_min_page_size(IOMMUMemoryRegion *iommu_mr);
/**
* memory_region_notify_iommu: notify a change in an IOMMU translation entry.
@ -716,12 +756,12 @@ uint64_t memory_region_iommu_get_min_page_size(MemoryRegion *mr);
* Note: for any IOMMU implementation, an in-place mapping change
* should be notified with an UNMAP followed by a MAP.
*
* @mr: the memory region that was changed
* @iommu_mr: the memory region that was changed
* @entry: the new entry in the IOMMU translation table. The entry
* replaces all old entries for the same virtual I/O address range.
* Deleted entries have .@perm == 0.
*/
void memory_region_notify_iommu(MemoryRegion *mr,
void memory_region_notify_iommu(IOMMUMemoryRegion *iommu_mr,
IOMMUTLBEntry entry);
/**
@ -756,18 +796,18 @@ void memory_region_register_iommu_notifier(MemoryRegion *mr,
* a notifier with the minimum page granularity returned by
* mr->iommu_ops->get_page_size().
*
* @mr: the memory region to observe
* @iommu_mr: the memory region to observe
* @n: the notifier to which to replay iommu mappings
*/
void memory_region_iommu_replay(MemoryRegion *mr, IOMMUNotifier *n);
void memory_region_iommu_replay(IOMMUMemoryRegion *iommu_mr, IOMMUNotifier *n);
/**
* memory_region_iommu_replay_all: replay existing IOMMU translations
* to all the notifiers registered.
*
* @mr: the memory region to observe
* @iommu_mr: the memory region to observe
*/
void memory_region_iommu_replay_all(MemoryRegion *mr);
void memory_region_iommu_replay_all(IOMMUMemoryRegion *iommu_mr);
/**
* memory_region_unregister_iommu_notifier: unregister a notifier for

View File

@ -32,6 +32,8 @@
#define INTEL_IOMMU_DEVICE(obj) \
OBJECT_CHECK(IntelIOMMUState, (obj), TYPE_INTEL_IOMMU_DEVICE)
#define TYPE_INTEL_IOMMU_MEMORY_REGION "intel-iommu-iommu-memory-region"
/* DMAR Hardware Unit Definition address (IOMMU unit) */
#define Q35_HOST_BRIDGE_IOMMU_ADDR 0xfed90000ULL
@ -83,7 +85,7 @@ struct VTDAddressSpace {
PCIBus *bus;
uint8_t devfn;
AddressSpace as;
MemoryRegion iommu;
IOMMUMemoryRegion iommu;
MemoryRegion root;
MemoryRegion sys_alias;
MemoryRegion iommu_ir; /* Interrupt region: 0xfeeXXXXX */
@ -289,7 +291,6 @@ struct IntelIOMMUState {
uint32_t context_cache_gen; /* Should be in [1,MAX] */
GHashTable *iotlb; /* IOTLB */
MemoryRegionIOMMUOps iommu_ops;
GHashTable *vtd_as_by_busptr; /* VTDBus objects indexed by PCIBus* reference */
VTDBus *vtd_as_by_bus_num[VTD_PCI_BUS_MAX]; /* VTDBus objects indexed by bus number */
/* list of registered notifiers */

View File

@ -19,6 +19,6 @@ typedef struct rc4030DMAState *rc4030_dma;
void rc4030_dma_read(void *dma, uint8_t *buf, int len);
void rc4030_dma_write(void *dma, uint8_t *buf, int len);
DeviceState *rc4030_init(rc4030_dma **dmas, MemoryRegion **dma_mr);
DeviceState *rc4030_init(rc4030_dma **dmas, IOMMUMemoryRegion **dma_mr);
#endif

View File

@ -582,6 +582,10 @@ typedef struct sPAPRTCETable sPAPRTCETable;
#define SPAPR_TCE_TABLE(obj) \
OBJECT_CHECK(sPAPRTCETable, (obj), TYPE_SPAPR_TCE_TABLE)
#define TYPE_SPAPR_IOMMU_MEMORY_REGION "spapr-iommu-memory-region"
#define SPAPR_IOMMU_MEMORY_REGION(obj) \
OBJECT_CHECK(IOMMUMemoryRegion, (obj), TYPE_SPAPR_IOMMU_MEMORY_REGION)
struct sPAPRTCETable {
DeviceState parent;
uint32_t liobn;
@ -594,7 +598,8 @@ struct sPAPRTCETable {
bool bypass;
bool need_vfio;
int fd;
MemoryRegion root, iommu;
MemoryRegion root;
IOMMUMemoryRegion iommu;
struct VIOsPAPRDevice *vdev; /* for @bypass migration compatibility only */
QLIST_ENTRY(sPAPRTCETable) list;
};

View File

@ -223,7 +223,7 @@ struct BusState {
struct Property {
const char *name;
PropertyInfo *info;
const PropertyInfo *info;
ptrdiff_t offset;
uint8_t bitnr;
union {
@ -231,8 +231,9 @@ struct Property {
uint64_t u;
} defval;
int arrayoffset;
PropertyInfo *arrayinfo;
const PropertyInfo *arrayinfo;
int arrayfieldsize;
const char *link_type;
};
struct PropertyInfo {
@ -241,6 +242,7 @@ struct PropertyInfo {
const char * const *enum_table;
int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len);
void (*set_default_value)(Object *obj, const Property *prop);
void (*create)(Object *obj, Property *prop, Error **errp);
ObjectPropertyAccessor *get;
ObjectPropertyAccessor *set;
ObjectPropertyRelease *release;

View File

@ -5,31 +5,32 @@
/*** qdev-properties.c ***/
extern PropertyInfo qdev_prop_bit;
extern PropertyInfo qdev_prop_bit64;
extern PropertyInfo qdev_prop_bool;
extern PropertyInfo qdev_prop_uint8;
extern PropertyInfo qdev_prop_uint16;
extern PropertyInfo qdev_prop_uint32;
extern PropertyInfo qdev_prop_int32;
extern PropertyInfo qdev_prop_uint64;
extern PropertyInfo qdev_prop_size;
extern PropertyInfo qdev_prop_string;
extern PropertyInfo qdev_prop_chr;
extern PropertyInfo qdev_prop_ptr;
extern PropertyInfo qdev_prop_macaddr;
extern PropertyInfo qdev_prop_on_off_auto;
extern PropertyInfo qdev_prop_losttickpolicy;
extern PropertyInfo qdev_prop_blockdev_on_error;
extern PropertyInfo qdev_prop_bios_chs_trans;
extern PropertyInfo qdev_prop_fdc_drive_type;
extern PropertyInfo qdev_prop_drive;
extern PropertyInfo qdev_prop_netdev;
extern PropertyInfo qdev_prop_vlan;
extern PropertyInfo qdev_prop_pci_devfn;
extern PropertyInfo qdev_prop_blocksize;
extern PropertyInfo qdev_prop_pci_host_devaddr;
extern PropertyInfo qdev_prop_arraylen;
extern const PropertyInfo qdev_prop_bit;
extern const PropertyInfo qdev_prop_bit64;
extern const PropertyInfo qdev_prop_bool;
extern const PropertyInfo qdev_prop_uint8;
extern const PropertyInfo qdev_prop_uint16;
extern const PropertyInfo qdev_prop_uint32;
extern const PropertyInfo qdev_prop_int32;
extern const PropertyInfo qdev_prop_uint64;
extern const PropertyInfo qdev_prop_size;
extern const PropertyInfo qdev_prop_string;
extern const PropertyInfo qdev_prop_chr;
extern const PropertyInfo qdev_prop_ptr;
extern const PropertyInfo qdev_prop_macaddr;
extern const PropertyInfo qdev_prop_on_off_auto;
extern const PropertyInfo qdev_prop_losttickpolicy;
extern const PropertyInfo qdev_prop_blockdev_on_error;
extern const PropertyInfo qdev_prop_bios_chs_trans;
extern const PropertyInfo qdev_prop_fdc_drive_type;
extern const PropertyInfo qdev_prop_drive;
extern const PropertyInfo qdev_prop_netdev;
extern const PropertyInfo qdev_prop_vlan;
extern const PropertyInfo qdev_prop_pci_devfn;
extern const PropertyInfo qdev_prop_blocksize;
extern const PropertyInfo qdev_prop_pci_host_devaddr;
extern const PropertyInfo qdev_prop_arraylen;
extern const PropertyInfo qdev_prop_link;
#define DEFINE_PROP(_name, _state, _field, _prop, _type) { \
.name = (_name), \
@ -117,6 +118,14 @@ extern PropertyInfo qdev_prop_arraylen;
.arrayoffset = offsetof(_state, _arrayfield), \
}
#define DEFINE_PROP_LINK(_name, _state, _field, _type, _ptr_type) { \
.name = (_name), \
.info = &(qdev_prop_link), \
.offset = offsetof(_state, _field) \
+ type_check(_ptr_type, typeof_field(_state, _field)), \
.link_type = _type, \
}
#define DEFINE_PROP_UINT8(_n, _s, _f, _d) \
DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, qdev_prop_uint8, uint8_t)
#define DEFINE_PROP_UINT16(_n, _s, _f, _d) \
@ -272,7 +281,8 @@ void qdev_prop_set_after_realize(DeviceState *dev, const char *name,
* This function should be used as the check() argument to
* object_property_add_link().
*/
void qdev_prop_allow_set_link_before_realize(Object *obj, const char *name,
void qdev_prop_allow_set_link_before_realize(const Object *obj,
const char *name,
Object *val, Error **errp);
#endif

View File

@ -112,7 +112,7 @@ typedef struct CssDevId {
bool valid;
} CssDevId;
extern PropertyInfo css_devid_propinfo;
extern const PropertyInfo css_devid_propinfo;
#define DEFINE_PROP_CSS_DEV_ID(_n, _s, _f) \
DEFINE_PROP(_n, _s, _f, css_devid_propinfo, CssDevId)
@ -196,7 +196,7 @@ int css_do_rchp(uint8_t cssid, uint8_t chpid);
bool css_present(uint8_t cssid);
#endif
extern PropertyInfo css_devid_ro_propinfo;
extern const PropertyInfo css_devid_ro_propinfo;
#define DEFINE_PROP_CSS_DEV_ID_RO(_n, _s, _f) \
DEFINE_PROP(_n, _s, _f, css_devid_ro_propinfo, CssDevId)

View File

@ -95,7 +95,7 @@ typedef struct VFIOContainer {
typedef struct VFIOGuestIOMMU {
VFIOContainer *container;
MemoryRegion *iommu;
IOMMUMemoryRegion *iommu;
hwaddr iommu_offset;
IOMMUNotifier n;
QLIST_ENTRY(VFIOGuestIOMMU) giommu_next;

View File

@ -45,6 +45,7 @@ typedef struct MachineState MachineState;
typedef struct MemoryListener MemoryListener;
typedef struct MemoryMappingList MemoryMappingList;
typedef struct MemoryRegion MemoryRegion;
typedef struct IOMMUMemoryRegion IOMMUMemoryRegion;
typedef struct MemoryRegionCache MemoryRegionCache;
typedef struct MemoryRegionSection MemoryRegionSection;
typedef struct MigrationIncomingState MigrationIncomingState;

View File

@ -265,7 +265,6 @@ struct qemu_work_item;
* @cpu_index: CPU index (informative).
* @nr_cores: Number of cores within this CPU package.
* @nr_threads: Number of threads within this CPU.
* @host_tid: Host thread ID.
* @running: #true if CPU is currently running (lockless).
* @has_waiter: #true if a CPU is currently waiting for the cpu_exec_end;
* valid under cpu_list_lock.
@ -319,7 +318,6 @@ struct CPUState {
HANDLE hThread;
#endif
int thread_id;
uint32_t host_tid;
bool running, has_waiter;
struct QemuCond *halt_cond;
bool thread_kicked;
@ -1015,6 +1013,7 @@ AddressSpace *cpu_get_address_space(CPUState *cpu, int asidx);
void QEMU_NORETURN cpu_abort(CPUState *cpu, const char *fmt, ...)
GCC_FMT_ATTR(2, 3);
extern Property cpu_common_props[];
void cpu_exec_initfn(CPUState *cpu);
void cpu_exec_realizefn(CPUState *cpu, Error **errp);
void cpu_exec_unrealizefn(CPUState *cpu);

View File

@ -764,7 +764,7 @@ ObjectClass *object_get_class(Object *obj);
*
* Returns: The QOM typename of @obj.
*/
const char *object_get_typename(Object *obj);
const char *object_get_typename(const Object *obj);
/**
* type_register_static:
@ -1319,7 +1319,7 @@ typedef enum {
* callback function. It allows the link property to be set and never returns
* an error.
*/
void object_property_allow_set_link(Object *, const char *,
void object_property_allow_set_link(const Object *, const char *,
Object *, Error **);
/**
@ -1352,7 +1352,7 @@ void object_property_allow_set_link(Object *, const char *,
*/
void object_property_add_link(Object *obj, const char *name,
const char *type, Object **child,
void (*check)(Object *obj, const char *name,
void (*check)(const Object *obj, const char *name,
Object *val, Error **errp),
ObjectPropertyLinkFlags flags,
Error **errp);

View File

@ -6219,7 +6219,6 @@ static void *clone_func(void *arg)
thread_cpu = cpu;
ts = (TaskState *)cpu->opaque;
info->tid = gettid();
cpu->host_tid = info->tid;
task_settid(ts);
if (info->child_tidptr)
put_user_u32(info->tid, info->child_tidptr);

113
memory.c
View File

@ -977,12 +977,11 @@ static char *memory_region_escape_name(const char *name)
return escaped;
}
void memory_region_init(MemoryRegion *mr,
Object *owner,
const char *name,
uint64_t size)
static void memory_region_do_init(MemoryRegion *mr,
Object *owner,
const char *name,
uint64_t size)
{
object_initialize(mr, sizeof(*mr), TYPE_MEMORY_REGION);
mr->size = int128_make64(size);
if (size == UINT64_MAX) {
mr->size = int128_2_64();
@ -1006,6 +1005,15 @@ void memory_region_init(MemoryRegion *mr,
}
}
void memory_region_init(MemoryRegion *mr,
Object *owner,
const char *name,
uint64_t size)
{
object_initialize(mr, sizeof(*mr), TYPE_MEMORY_REGION);
memory_region_do_init(mr, owner, name, size);
}
static void memory_region_get_addr(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
@ -1092,6 +1100,13 @@ static void memory_region_initfn(Object *obj)
NULL, NULL, &error_abort);
}
static void iommu_memory_region_initfn(Object *obj)
{
MemoryRegion *mr = MEMORY_REGION(obj);
mr->is_iommu = true;
}
static uint64_t unassigned_mem_read(void *opaque, hwaddr addr,
unsigned size)
{
@ -1491,17 +1506,23 @@ void memory_region_init_rom_device(MemoryRegion *mr,
mr->ram_block = qemu_ram_alloc(size, mr, errp);
}
void memory_region_init_iommu(MemoryRegion *mr,
void memory_region_init_iommu(void *_iommu_mr,
size_t instance_size,
const char *mrtypename,
Object *owner,
const MemoryRegionIOMMUOps *ops,
const char *name,
uint64_t size)
{
memory_region_init(mr, owner, name, size);
mr->iommu_ops = ops,
struct IOMMUMemoryRegion *iommu_mr;
struct MemoryRegion *mr;
object_initialize(_iommu_mr, instance_size, mrtypename);
mr = MEMORY_REGION(_iommu_mr);
memory_region_do_init(mr, owner, name, size);
iommu_mr = IOMMU_MEMORY_REGION(mr);
mr->terminates = true; /* then re-forwards */
QLIST_INIT(&mr->iommu_notify);
mr->iommu_notify_flags = IOMMU_NOTIFIER_NONE;
QLIST_INIT(&iommu_mr->iommu_notify);
iommu_mr->iommu_notify_flags = IOMMU_NOTIFIER_NONE;
}
static void memory_region_finalize(Object *obj)
@ -1596,63 +1617,70 @@ bool memory_region_is_logging(MemoryRegion *mr, uint8_t client)
return memory_region_get_dirty_log_mask(mr) & (1 << client);
}
static void memory_region_update_iommu_notify_flags(MemoryRegion *mr)
static void memory_region_update_iommu_notify_flags(IOMMUMemoryRegion *iommu_mr)
{
IOMMUNotifierFlag flags = IOMMU_NOTIFIER_NONE;
IOMMUNotifier *iommu_notifier;
IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_GET_CLASS(iommu_mr);
IOMMU_NOTIFIER_FOREACH(iommu_notifier, mr) {
IOMMU_NOTIFIER_FOREACH(iommu_notifier, iommu_mr) {
flags |= iommu_notifier->notifier_flags;
}
if (flags != mr->iommu_notify_flags &&
mr->iommu_ops->notify_flag_changed) {
mr->iommu_ops->notify_flag_changed(mr, mr->iommu_notify_flags,
flags);
if (flags != iommu_mr->iommu_notify_flags && imrc->notify_flag_changed) {
imrc->notify_flag_changed(iommu_mr,
iommu_mr->iommu_notify_flags,
flags);
}
mr->iommu_notify_flags = flags;
iommu_mr->iommu_notify_flags = flags;
}
void memory_region_register_iommu_notifier(MemoryRegion *mr,
IOMMUNotifier *n)
{
IOMMUMemoryRegion *iommu_mr;
if (mr->alias) {
memory_region_register_iommu_notifier(mr->alias, n);
return;
}
/* We need to register for at least one bitfield */
iommu_mr = IOMMU_MEMORY_REGION(mr);
assert(n->notifier_flags != IOMMU_NOTIFIER_NONE);
assert(n->start <= n->end);
QLIST_INSERT_HEAD(&mr->iommu_notify, n, node);
memory_region_update_iommu_notify_flags(mr);
QLIST_INSERT_HEAD(&iommu_mr->iommu_notify, n, node);
memory_region_update_iommu_notify_flags(iommu_mr);
}
uint64_t memory_region_iommu_get_min_page_size(MemoryRegion *mr)
uint64_t memory_region_iommu_get_min_page_size(IOMMUMemoryRegion *iommu_mr)
{
assert(memory_region_is_iommu(mr));
if (mr->iommu_ops && mr->iommu_ops->get_min_page_size) {
return mr->iommu_ops->get_min_page_size(mr);
IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_GET_CLASS(iommu_mr);
if (imrc->get_min_page_size) {
return imrc->get_min_page_size(iommu_mr);
}
return TARGET_PAGE_SIZE;
}
void memory_region_iommu_replay(MemoryRegion *mr, IOMMUNotifier *n)
void memory_region_iommu_replay(IOMMUMemoryRegion *iommu_mr, IOMMUNotifier *n)
{
MemoryRegion *mr = MEMORY_REGION(iommu_mr);
IOMMUMemoryRegionClass *imrc = IOMMU_MEMORY_REGION_GET_CLASS(iommu_mr);
hwaddr addr, granularity;
IOMMUTLBEntry iotlb;
/* If the IOMMU has its own replay callback, override */
if (mr->iommu_ops->replay) {
mr->iommu_ops->replay(mr, n);
if (imrc->replay) {
imrc->replay(iommu_mr, n);
return;
}
granularity = memory_region_iommu_get_min_page_size(mr);
granularity = memory_region_iommu_get_min_page_size(iommu_mr);
for (addr = 0; addr < memory_region_size(mr); addr += granularity) {
iotlb = mr->iommu_ops->translate(mr, addr, IOMMU_NONE);
iotlb = imrc->translate(iommu_mr, addr, IOMMU_NONE);
if (iotlb.perm != IOMMU_NONE) {
n->notify(n, &iotlb);
}
@ -1665,24 +1693,27 @@ void memory_region_iommu_replay(MemoryRegion *mr, IOMMUNotifier *n)
}
}
void memory_region_iommu_replay_all(MemoryRegion *mr)
void memory_region_iommu_replay_all(IOMMUMemoryRegion *iommu_mr)
{
IOMMUNotifier *notifier;
IOMMU_NOTIFIER_FOREACH(notifier, mr) {
memory_region_iommu_replay(mr, notifier);
IOMMU_NOTIFIER_FOREACH(notifier, iommu_mr) {
memory_region_iommu_replay(iommu_mr, notifier);
}
}
void memory_region_unregister_iommu_notifier(MemoryRegion *mr,
IOMMUNotifier *n)
{
IOMMUMemoryRegion *iommu_mr;
if (mr->alias) {
memory_region_unregister_iommu_notifier(mr->alias, n);
return;
}
QLIST_REMOVE(n, node);
memory_region_update_iommu_notify_flags(mr);
iommu_mr = IOMMU_MEMORY_REGION(mr);
memory_region_update_iommu_notify_flags(iommu_mr);
}
void memory_region_notify_one(IOMMUNotifier *notifier,
@ -1710,14 +1741,14 @@ void memory_region_notify_one(IOMMUNotifier *notifier,
}
}
void memory_region_notify_iommu(MemoryRegion *mr,
void memory_region_notify_iommu(IOMMUMemoryRegion *iommu_mr,
IOMMUTLBEntry entry)
{
IOMMUNotifier *iommu_notifier;
assert(memory_region_is_iommu(mr));
assert(memory_region_is_iommu(MEMORY_REGION(iommu_mr)));
IOMMU_NOTIFIER_FOREACH(iommu_notifier, mr) {
IOMMU_NOTIFIER_FOREACH(iommu_notifier, iommu_mr) {
memory_region_notify_one(iommu_notifier, &entry);
}
}
@ -2825,9 +2856,19 @@ static const TypeInfo memory_region_info = {
.instance_finalize = memory_region_finalize,
};
static const TypeInfo iommu_memory_region_info = {
.parent = TYPE_MEMORY_REGION,
.name = TYPE_IOMMU_MEMORY_REGION,
.class_size = sizeof(IOMMUMemoryRegionClass),
.instance_size = sizeof(IOMMUMemoryRegion),
.instance_init = iommu_memory_region_initfn,
.abstract = true,
};
static void memory_register_types(void)
{
type_register_static(&memory_region_info);
type_register_static(&iommu_memory_region_info);
}
type_init(memory_register_types)

Some files were not shown because too many files have changed in this diff Show More