diff options
Diffstat (limited to 'hw')
115 files changed, 1590 insertions, 1147 deletions
diff --git a/hw/9pfs/9p-handle.c b/hw/9pfs/9p-handle.c index 1687661bc9..9875f1894c 100644 --- a/hw/9pfs/9p-handle.c +++ b/hw/9pfs/9p-handle.c @@ -378,7 +378,6 @@ static int handle_utimensat(FsContext *ctx, V9fsPath *fs_path, const struct timespec *buf) { int ret; -#ifdef CONFIG_UTIMENSAT int fd; struct handle_data *data = (struct handle_data *)ctx->private; @@ -388,10 +387,6 @@ static int handle_utimensat(FsContext *ctx, V9fsPath *fs_path, } ret = futimens(fd, buf); close(fd); -#else - ret = -1; - errno = ENOSYS; -#endif return ret; } diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c index a2486566af..1e78b7c9e9 100644 --- a/hw/9pfs/9p-local.c +++ b/hw/9pfs/9p-local.c @@ -53,13 +53,37 @@ int local_open_nofollow(FsContext *fs_ctx, const char *path, int flags, mode_t mode) { LocalData *data = fs_ctx->private; - - /* All paths are relative to the path data->mountfd points to */ - while (*path == '/') { - path++; + int fd = data->mountfd; + + while (*path && fd != -1) { + const char *c; + int next_fd; + char *head; + + /* Only relative paths without consecutive slashes */ + assert(*path != '/'); + + head = g_strdup(path); + c = strchrnul(path, '/'); + if (*c) { + /* Intermediate path element */ + head[c - path] = 0; + path = c + 1; + next_fd = openat_dir(fd, head); + } else { + /* Rightmost path element */ + next_fd = openat_file(fd, head, flags, mode); + path = c; + } + g_free(head); + if (fd != data->mountfd) { + close_preserve_errno(fd); + } + fd = next_fd; } - return relative_openat_nofollow(data->mountfd, path, flags, mode); + assert(fd != data->mountfd); + return fd; } int local_opendir_nofollow(FsContext *fs_ctx, const char *path) @@ -83,6 +107,7 @@ static void unlinkat_preserve_errno(int dirfd, const char *path, int flags) } #define VIRTFS_META_DIR ".virtfs_metadata" +#define VIRTFS_META_ROOT_FILE VIRTFS_META_DIR "_root" static FILE *local_fopenat(int dirfd, const char *name, const char *mode) { @@ -119,13 +144,17 @@ static void local_mapped_file_attr(int dirfd, const char *name, char buf[ATTR_MAX]; int map_dirfd; - map_dirfd = openat_dir(dirfd, VIRTFS_META_DIR); - if (map_dirfd == -1) { - return; - } + if (strcmp(name, ".")) { + map_dirfd = openat_dir(dirfd, VIRTFS_META_DIR); + if (map_dirfd == -1) { + return; + } - fp = local_fopenat(map_dirfd, name, "r"); - close_preserve_errno(map_dirfd); + fp = local_fopenat(map_dirfd, name, "r"); + close_preserve_errno(map_dirfd); + } else { + fp = local_fopenat(dirfd, VIRTFS_META_ROOT_FILE, "r"); + } if (!fp) { return; } @@ -203,26 +232,38 @@ static int local_set_mapped_file_attrat(int dirfd, const char *name, int ret; char buf[ATTR_MAX]; int uid = -1, gid = -1, mode = -1, rdev = -1; - int map_dirfd; - - ret = mkdirat(dirfd, VIRTFS_META_DIR, 0700); - if (ret < 0 && errno != EEXIST) { - return -1; - } - - map_dirfd = openat_dir(dirfd, VIRTFS_META_DIR); - if (map_dirfd == -1) { - return -1; - } + int map_dirfd = -1, map_fd; + bool is_root = !strcmp(name, "."); + + if (is_root) { + fp = local_fopenat(dirfd, VIRTFS_META_ROOT_FILE, "r"); + if (!fp) { + if (errno == ENOENT) { + goto update_map_file; + } else { + return -1; + } + } + } else { + ret = mkdirat(dirfd, VIRTFS_META_DIR, 0700); + if (ret < 0 && errno != EEXIST) { + return -1; + } - fp = local_fopenat(map_dirfd, name, "r"); - if (!fp) { - if (errno == ENOENT) { - goto update_map_file; - } else { - close_preserve_errno(map_dirfd); + map_dirfd = openat_dir(dirfd, VIRTFS_META_DIR); + if (map_dirfd == -1) { return -1; } + + fp = local_fopenat(map_dirfd, name, "r"); + if (!fp) { + if (errno == ENOENT) { + goto update_map_file; + } else { + close_preserve_errno(map_dirfd); + return -1; + } + } } memset(buf, 0, ATTR_MAX); while (fgets(buf, ATTR_MAX, fp)) { @@ -240,12 +281,26 @@ static int local_set_mapped_file_attrat(int dirfd, const char *name, fclose(fp); update_map_file: - fp = local_fopenat(map_dirfd, name, "w"); - close_preserve_errno(map_dirfd); + if (is_root) { + fp = local_fopenat(dirfd, VIRTFS_META_ROOT_FILE, "w"); + } else { + fp = local_fopenat(map_dirfd, name, "w"); + /* We can't go this far with map_dirfd not being a valid file descriptor + * but some versions of gcc aren't smart enough to see it. + */ + if (map_dirfd != -1) { + close_preserve_errno(map_dirfd); + } + } if (!fp) { return -1; } + map_fd = fileno(fp); + assert(map_fd != -1); + ret = fchmod(map_fd, 0600); + assert(ret == 0); + if (credp->fc_uid != -1) { uid = credp->fc_uid; } @@ -454,7 +509,8 @@ static off_t local_telldir(FsContext *ctx, V9fsFidOpenState *fs) static bool local_is_mapped_file_metadata(FsContext *fs_ctx, const char *name) { - return !strcmp(name, VIRTFS_META_DIR); + return + !strcmp(name, VIRTFS_META_DIR) || !strcmp(name, VIRTFS_META_ROOT_FILE); } static struct dirent *local_readdir(FsContext *ctx, V9fsFidOpenState *fs) @@ -471,7 +527,7 @@ again: entry->d_type = DT_UNKNOWN; } else if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { if (local_is_mapped_file_metadata(ctx, entry->d_name)) { - /* skip the meta data directory */ + /* skip the meta data */ goto again; } entry->d_type = DT_UNKNOWN; @@ -992,6 +1048,14 @@ static int local_unlinkat_common(FsContext *ctx, int dirfd, const char *name, if (ctx->export_flags & V9FS_SM_MAPPED_FILE) { int map_dirfd; + /* We need to remove the metadata as well: + * - the metadata directory if we're removing a directory + * - the metadata file in the parent's metadata directory + * + * If any of these are missing (ie, ENOENT) then we're probably + * trying to remove something that wasn't created in mapped-file + * mode. We just ignore the error. + */ if (flags == AT_REMOVEDIR) { int fd; @@ -999,32 +1063,20 @@ static int local_unlinkat_common(FsContext *ctx, int dirfd, const char *name, if (fd == -1) { goto err_out; } - /* - * If directory remove .virtfs_metadata contained in the - * directory - */ ret = unlinkat(fd, VIRTFS_META_DIR, AT_REMOVEDIR); close_preserve_errno(fd); if (ret < 0 && errno != ENOENT) { - /* - * We didn't had the .virtfs_metadata file. May be file created - * in non-mapped mode ?. Ignore ENOENT. - */ goto err_out; } } - /* - * Now remove the name from parent directory - * .virtfs_metadata directory. - */ map_dirfd = openat_dir(dirfd, VIRTFS_META_DIR); - ret = unlinkat(map_dirfd, name, 0); - close_preserve_errno(map_dirfd); - if (ret < 0 && errno != ENOENT) { - /* - * We didn't had the .virtfs_metadata file. May be file created - * in non-mapped mode ?. Ignore ENOENT. - */ + if (map_dirfd != -1) { + ret = unlinkat(map_dirfd, name, 0); + close_preserve_errno(map_dirfd); + if (ret < 0 && errno != ENOENT) { + goto err_out; + } + } else if (errno != ENOENT) { goto err_out; } } @@ -1138,14 +1190,32 @@ static int local_name_to_path(FsContext *ctx, V9fsPath *dir_path, } if (dir_path) { - v9fs_path_sprintf(target, "%s/%s", dir_path->data, name); - } else if (strcmp(name, "/")) { - v9fs_path_sprintf(target, "%s", name); + if (!strcmp(name, ".")) { + /* "." relative to "foo/bar" is "foo/bar" */ + v9fs_path_copy(target, dir_path); + } else if (!strcmp(name, "..")) { + if (!strcmp(dir_path->data, ".")) { + /* ".." relative to the root is "." */ + v9fs_path_sprintf(target, "."); + } else { + char *tmp = g_path_get_dirname(dir_path->data); + /* Symbolic links are resolved by the client. We can assume + * that ".." relative to "foo/bar" is equivalent to "foo" + */ + v9fs_path_sprintf(target, "%s", tmp); + g_free(tmp); + } + } else { + assert(!strchr(name, '/')); + v9fs_path_sprintf(target, "%s/%s", dir_path->data, name); + } + } else if (!strcmp(name, "/") || !strcmp(name, ".") || + !strcmp(name, "..")) { + /* This is the root fid */ + v9fs_path_sprintf(target, "."); } else { - /* We want the path of the export root to be relative, otherwise - * "*at()" syscalls would treat it as "/" in the host. - */ - v9fs_path_sprintf(target, "%s", "."); + assert(!strchr(name, '/')); + v9fs_path_sprintf(target, "./%s", name); } return 0; } diff --git a/hw/9pfs/9p-util.c b/hw/9pfs/9p-util.c index fdb4d57376..f709c27a1f 100644 --- a/hw/9pfs/9p-util.c +++ b/hw/9pfs/9p-util.c @@ -14,49 +14,6 @@ #include "qemu/xattr.h" #include "9p-util.h" -int relative_openat_nofollow(int dirfd, const char *path, int flags, - mode_t mode) -{ - int fd; - - fd = dup(dirfd); - if (fd == -1) { - return -1; - } - - while (*path) { - const char *c; - int next_fd; - char *head; - - /* Only relative paths without consecutive slashes */ - assert(path[0] != '/'); - - head = g_strdup(path); - c = strchr(path, '/'); - if (c) { - head[c - path] = 0; - next_fd = openat_dir(fd, head); - } else { - next_fd = openat_file(fd, head, flags, mode); - } - g_free(head); - if (next_fd == -1) { - close_preserve_errno(fd); - return -1; - } - close(fd); - fd = next_fd; - - if (!c) { - break; - } - path = c + 1; - } - - return fd; -} - ssize_t fgetxattrat_nofollow(int dirfd, const char *filename, const char *name, void *value, size_t size) { diff --git a/hw/9pfs/9p-util.h b/hw/9pfs/9p-util.h index 517027c520..91299a24b8 100644 --- a/hw/9pfs/9p-util.h +++ b/hw/9pfs/9p-util.h @@ -50,8 +50,6 @@ static inline int openat_file(int dirfd, const char *name, int flags, return fd; } -int relative_openat_nofollow(int dirfd, const char *path, int flags, - mode_t mode); ssize_t fgetxattrat_nofollow(int dirfd, const char *path, const char *name, void *value, size_t size); int fsetxattrat_nofollow(int dirfd, const char *path, const char *name, diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c index ab3e22f231..96d2683348 100644 --- a/hw/9pfs/9p.c +++ b/hw/9pfs/9p.c @@ -65,11 +65,6 @@ ssize_t pdu_unmarshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...) return ret; } -static void pdu_push_and_notify(V9fsPDU *pdu) -{ - pdu->s->transport->push_and_notify(pdu); -} - static int omode_to_uflags(int8_t mode) { int ret = 0; @@ -668,7 +663,7 @@ static void coroutine_fn pdu_complete(V9fsPDU *pdu, ssize_t len) pdu->size = len; pdu->id = id; - pdu_push_and_notify(pdu); + pdu->s->transport->push_and_notify(pdu); /* Now wakeup anybody waiting in flush for this request */ if (!qemu_co_queue_next(&pdu->complete)) { @@ -2576,7 +2571,10 @@ static int coroutine_fn v9fs_complete_rename(V9fsPDU *pdu, V9fsFidState *fidp, err = -EINVAL; goto out; } - v9fs_co_name_to_path(pdu, &dirfidp->path, name->data, &new_path); + err = v9fs_co_name_to_path(pdu, &dirfidp->path, name->data, &new_path); + if (err < 0) { + goto out; + } } else { old_name = fidp->path.data; end = strrchr(old_name, '/'); @@ -2588,8 +2586,11 @@ static int coroutine_fn v9fs_complete_rename(V9fsPDU *pdu, V9fsFidState *fidp, new_name = g_malloc0(end - old_name + name->size + 1); strncat(new_name, old_name, end - old_name); strncat(new_name + (end - old_name), name->data, name->size); - v9fs_co_name_to_path(pdu, NULL, new_name, &new_path); + err = v9fs_co_name_to_path(pdu, NULL, new_name, &new_path); g_free(new_name); + if (err < 0) { + goto out; + } } err = v9fs_co_rename(pdu, &fidp->path, &new_path); if (err < 0) { @@ -2669,20 +2670,26 @@ out_nofid: v9fs_string_free(&name); } -static void coroutine_fn v9fs_fix_fid_paths(V9fsPDU *pdu, V9fsPath *olddir, - V9fsString *old_name, - V9fsPath *newdir, - V9fsString *new_name) +static int coroutine_fn v9fs_fix_fid_paths(V9fsPDU *pdu, V9fsPath *olddir, + V9fsString *old_name, + V9fsPath *newdir, + V9fsString *new_name) { V9fsFidState *tfidp; V9fsPath oldpath, newpath; V9fsState *s = pdu->s; - + int err; v9fs_path_init(&oldpath); v9fs_path_init(&newpath); - v9fs_co_name_to_path(pdu, olddir, old_name->data, &oldpath); - v9fs_co_name_to_path(pdu, newdir, new_name->data, &newpath); + err = v9fs_co_name_to_path(pdu, olddir, old_name->data, &oldpath); + if (err < 0) { + goto out; + } + err = v9fs_co_name_to_path(pdu, newdir, new_name->data, &newpath); + if (err < 0) { + goto out; + } /* * Fixup fid's pointing to the old name to @@ -2694,8 +2701,10 @@ static void coroutine_fn v9fs_fix_fid_paths(V9fsPDU *pdu, V9fsPath *olddir, v9fs_fix_path(&tfidp->path, &newpath, strlen(oldpath.data)); } } +out: v9fs_path_free(&oldpath); v9fs_path_free(&newpath); + return err; } static int coroutine_fn v9fs_complete_renameat(V9fsPDU *pdu, int32_t olddirfid, @@ -2729,8 +2738,8 @@ static int coroutine_fn v9fs_complete_renameat(V9fsPDU *pdu, int32_t olddirfid, } if (s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT) { /* Only for path based fid we need to do the below fixup */ - v9fs_fix_fid_paths(pdu, &olddirfidp->path, old_name, - &newdirfidp->path, new_name); + err = v9fs_fix_fid_paths(pdu, &olddirfidp->path, old_name, + &newdirfidp->path, new_name); } out: if (olddirfidp) { @@ -3446,12 +3455,16 @@ static inline bool is_read_only_op(V9fsPDU *pdu) } } -void pdu_submit(V9fsPDU *pdu) +void pdu_submit(V9fsPDU *pdu, P9MsgHeader *hdr) { Coroutine *co; CoroutineEntry *handler; V9fsState *s = pdu->s; + pdu->size = le32_to_cpu(hdr->size_le); + pdu->id = hdr->id; + pdu->tag = le16_to_cpu(hdr->tag_le); + if (pdu->id >= ARRAY_SIZE(pdu_co_handlers) || (pdu_co_handlers[pdu->id] == NULL)) { handler = v9fs_op_not_supp; @@ -3462,6 +3475,8 @@ void pdu_submit(V9fsPDU *pdu) if (is_ro_export(&s->ctx) && !is_read_only_op(pdu)) { handler = v9fs_fs_ro; } + + qemu_co_queue_init(&pdu->complete); co = qemu_coroutine_create(handler, pdu); qemu_coroutine_enter(co); } diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h index 5312d8a424..c886ba78d2 100644 --- a/hw/9pfs/9p.h +++ b/hw/9pfs/9p.h @@ -347,7 +347,7 @@ ssize_t pdu_marshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...); ssize_t pdu_unmarshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...); V9fsPDU *pdu_alloc(V9fsState *s); void pdu_free(V9fsPDU *pdu); -void pdu_submit(V9fsPDU *pdu); +void pdu_submit(V9fsPDU *pdu, P9MsgHeader *hdr); void v9fs_reset(V9fsState *s); struct V9fsTransport { diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c index 3782f43702..245abd8aae 100644 --- a/hw/9pfs/virtio-9p-device.c +++ b/hw/9pfs/virtio-9p-device.c @@ -70,13 +70,7 @@ static void handle_9p_output(VirtIODevice *vdev, VirtQueue *vq) goto out_free_req; } - pdu->size = le32_to_cpu(out.size_le); - - pdu->id = out.id; - pdu->tag = le16_to_cpu(out.tag_le); - - qemu_co_queue_init(&pdu->complete); - pdu_submit(pdu); + pdu_submit(pdu, &out); } return; diff --git a/hw/9pfs/xen-9p-backend.c b/hw/9pfs/xen-9p-backend.c index 5df97c90fa..922cc967be 100644 --- a/hw/9pfs/xen-9p-backend.c +++ b/hw/9pfs/xen-9p-backend.c @@ -243,14 +243,10 @@ static int xen_9pfs_receive(Xen9pfsRing *ring) /* cannot fail, because we only handle one request per ring at a time */ pdu = pdu_alloc(&ring->priv->state); - pdu->size = le32_to_cpu(h.size_le); - pdu->id = h.id; - pdu->tag = le32_to_cpu(h.tag_le); ring->out_size = le32_to_cpu(h.size_le); ring->out_cons = cons + le32_to_cpu(h.size_le); - qemu_co_queue_init(&pdu->complete); - pdu_submit(pdu); + pdu_submit(pdu, &h); return 0; } diff --git a/hw/arm/aspeed.c b/hw/arm/aspeed.c index 283c038814..e824ea87a9 100644 --- a/hw/arm/aspeed.c +++ b/hw/arm/aspeed.c @@ -39,6 +39,7 @@ typedef struct AspeedBoardConfig { const char *fmc_model; const char *spi_model; uint32_t num_cs; + void (*i2c_init)(AspeedBoardState *bmc); } AspeedBoardConfig; enum { @@ -82,6 +83,9 @@ enum { SCU_AST2500_HW_STRAP_ACPI_ENABLE | \ SCU_HW_STRAP_SPI_MODE(SCU_HW_STRAP_SPI_MASTER)) +static void palmetto_bmc_i2c_init(AspeedBoardState *bmc); +static void ast2500_evb_i2c_init(AspeedBoardState *bmc); + static const AspeedBoardConfig aspeed_boards[] = { [PALMETTO_BMC] = { .soc_name = "ast2400-a1", @@ -89,6 +93,7 @@ static const AspeedBoardConfig aspeed_boards[] = { .fmc_model = "n25q256a", .spi_model = "mx25l25635e", .num_cs = 1, + .i2c_init = palmetto_bmc_i2c_init, }, [AST2500_EVB] = { .soc_name = "ast2500-a1", @@ -96,6 +101,7 @@ static const AspeedBoardConfig aspeed_boards[] = { .fmc_model = "n25q256a", .spi_model = "mx25l25635e", .num_cs = 1, + .i2c_init = ast2500_evb_i2c_init, }, [ROMULUS_BMC] = { .soc_name = "ast2500-a1", @@ -223,9 +229,22 @@ static void aspeed_board_init(MachineState *machine, aspeed_board_binfo.ram_size = ram_size; aspeed_board_binfo.loader_start = sc->info->sdram_base; + if (cfg->i2c_init) { + cfg->i2c_init(bmc); + } + arm_load_kernel(ARM_CPU(first_cpu), &aspeed_board_binfo); } +static void palmetto_bmc_i2c_init(AspeedBoardState *bmc) +{ + AspeedSoCState *soc = &bmc->soc; + + /* The palmetto platform expects a ds3231 RTC but a ds1338 is + * enough to provide basic RTC features. Alarms will be missing */ + i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 0), "ds1338", 0x68); +} + static void palmetto_bmc_init(MachineState *machine) { aspeed_board_init(machine, &aspeed_boards[PALMETTO_BMC]); @@ -250,6 +269,14 @@ static const TypeInfo palmetto_bmc_type = { .class_init = palmetto_bmc_class_init, }; +static void ast2500_evb_i2c_init(AspeedBoardState *bmc) +{ + AspeedSoCState *soc = &bmc->soc; + + /* The AST2500 EVB expects a LM75 but a TMP105 is compatible */ + i2c_create_slave(aspeed_i2c_get_bus(DEVICE(&soc->i2c), 7), "tmp105", 0x4d); +} + static void ast2500_evb_init(MachineState *machine) { aspeed_board_init(machine, &aspeed_boards[AST2500_EVB]); diff --git a/hw/arm/bcm2835_peripherals.c b/hw/arm/bcm2835_peripherals.c index 369ef1e3bd..502f04c02a 100644 --- a/hw/arm/bcm2835_peripherals.c +++ b/hw/arm/bcm2835_peripherals.c @@ -13,7 +13,6 @@ #include "hw/arm/bcm2835_peripherals.h" #include "hw/misc/bcm2835_mbox_defs.h" #include "hw/arm/raspi_platform.h" -#include "sysemu/char.h" #include "sysemu/sysemu.h" /* Peripheral base address on the VC (GPU) system bus */ diff --git a/hw/arm/fsl-imx25.c b/hw/arm/fsl-imx25.c index 9056f27bf8..40666b68a3 100644 --- a/hw/arm/fsl-imx25.c +++ b/hw/arm/fsl-imx25.c @@ -30,7 +30,7 @@ #include "sysemu/sysemu.h" #include "exec/address-spaces.h" #include "hw/boards.h" -#include "sysemu/char.h" +#include "chardev/char.h" static void fsl_imx25_init(Object *obj) { diff --git a/hw/arm/fsl-imx31.c b/hw/arm/fsl-imx31.c index d7e2d832b2..c30130667e 100644 --- a/hw/arm/fsl-imx31.c +++ b/hw/arm/fsl-imx31.c @@ -27,7 +27,7 @@ #include "sysemu/sysemu.h" #include "exec/address-spaces.h" #include "hw/boards.h" -#include "sysemu/char.h" +#include "chardev/char.h" static void fsl_imx31_init(Object *obj) { diff --git a/hw/arm/fsl-imx6.c b/hw/arm/fsl-imx6.c index 6969e734ad..27773c9c47 100644 --- a/hw/arm/fsl-imx6.c +++ b/hw/arm/fsl-imx6.c @@ -24,7 +24,7 @@ #include "qemu-common.h" #include "hw/arm/fsl-imx6.h" #include "sysemu/sysemu.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "qemu/error-report.h" #define NAME_SIZE 20 diff --git a/hw/arm/omap2.c b/hw/arm/omap2.c index 8afb854c74..91f573338c 100644 --- a/hw/arm/omap2.c +++ b/hw/arm/omap2.c @@ -30,7 +30,7 @@ #include "hw/arm/omap.h" #include "sysemu/sysemu.h" #include "qemu/timer.h" -#include "sysemu/char.h" +#include "chardev/char-fe.h" #include "hw/block/flash.h" #include "hw/arm/soc_dma.h" #include "hw/sysbus.h" diff --git a/hw/arm/pxa2xx.c b/hw/arm/pxa2xx.c index eea551dc16..629e6c64e6 100644 --- a/hw/arm/pxa2xx.c +++ b/hw/arm/pxa2xx.c @@ -17,7 +17,7 @@ #include "hw/char/serial.h" #include "hw/i2c/i2c.h" #include "hw/ssi/ssi.h" -#include "sysemu/char.h" +#include "chardev/char-fe.h" #include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #include "qemu/cutils.h" diff --git a/hw/arm/strongarm.c b/hw/arm/strongarm.c index 3311cc38a4..7683edc9e5 100644 --- a/hw/arm/strongarm.c +++ b/hw/arm/strongarm.c @@ -34,7 +34,8 @@ #include "strongarm.h" #include "qemu/error-report.h" #include "hw/arm/arm.h" -#include "sysemu/char.h" +#include "chardev/char-fe.h" +#include "chardev/char-serial.h" #include "sysemu/sysemu.h" #include "hw/ssi/ssi.h" #include "qemu/cutils.h" diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c index e5852067f5..3d78ff68e6 100644 --- a/hw/arm/virt-acpi-build.c +++ b/hw/arm/virt-acpi-build.c @@ -496,12 +496,10 @@ build_srat(GArray *table_data, BIOSLinker *linker, VirtMachineState *vms) srat->reserved1 = cpu_to_le32(1); for (i = 0; i < cpu_list->len; ++i) { - int node_id = cpu_list->cpus[i].props.has_node_id ? - cpu_list->cpus[i].props.node_id : 0; core = acpi_data_push(table_data, sizeof(*core)); core->type = ACPI_SRAT_PROCESSOR_GICC; core->length = sizeof(*core); - core->proximity = cpu_to_le32(node_id); + core->proximity = cpu_to_le32(cpu_list->cpus[i].props.node_id); core->acpi_processor_uid = cpu_to_le32(i); core->flags = cpu_to_le32(1); } @@ -776,6 +774,10 @@ void virt_acpi_build(VirtMachineState *vms, AcpiBuildTables *tables) if (nb_numa_nodes > 0) { acpi_add_table(table_offsets, tables_blob); build_srat(tables_blob, tables->linker, vms); + if (have_numa_distance) { + acpi_add_table(table_offsets, tables_blob); + build_slit(tables_blob, tables->linker); + } } if (its_class_name() && !vmc->no_its) { diff --git a/hw/arm/virt.c b/hw/arm/virt.c index c7c8159dfd..010f7244bf 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -219,6 +219,27 @@ static void create_fdt(VirtMachineState *vms) "clk24mhz"); qemu_fdt_setprop_cell(fdt, "/apb-pclk", "phandle", vms->clock_phandle); + if (have_numa_distance) { + int size = nb_numa_nodes * nb_numa_nodes * 3 * sizeof(uint32_t); + uint32_t *matrix = g_malloc0(size); + int idx, i, j; + + for (i = 0; i < nb_numa_nodes; i++) { + for (j = 0; j < nb_numa_nodes; j++) { + idx = (i * nb_numa_nodes + j) * 3; + matrix[idx + 0] = cpu_to_be32(i); + matrix[idx + 1] = cpu_to_be32(j); + matrix[idx + 2] = cpu_to_be32(numa_info[i].distance[j]); + } + } + + qemu_fdt_add_subnode(fdt, "/distance-map"); + qemu_fdt_setprop_string(fdt, "/distance-map", "compatible", + "numa-distance-map-v1"); + qemu_fdt_setprop(fdt, "/distance-map", "distance-matrix", + matrix, size); + g_free(matrix); + } } static void fdt_add_psci_node(const VirtMachineState *vms) @@ -1351,7 +1372,6 @@ static void machvirt_init(MachineState *machine) for (n = 0; n < possible_cpus->len; n++) { Object *cpuobj; CPUState *cs; - int node_id; if (n >= smp_cpus) { break; @@ -1364,19 +1384,8 @@ static void machvirt_init(MachineState *machine) cs = CPU(cpuobj); cs->cpu_index = n; - node_id = possible_cpus->cpus[cs->cpu_index].props.node_id; - if (!possible_cpus->cpus[cs->cpu_index].props.has_node_id) { - /* by default CPUState::numa_node was 0 if it's not set via CLI - * keep it this way for now but in future we probably should - * refuse to start up with incomplete numa mapping */ - node_id = 0; - } - if (cs->numa_node == CPU_UNSET_NUMA_NODE_ID) { - cs->numa_node = node_id; - } else { - /* CPU isn't device_add compatible yet, this shouldn't happen */ - error_setg(&error_abort, "user set node-id not implemented"); - } + numa_cpu_pre_plug(&possible_cpus->cpus[cs->cpu_index], DEVICE(cpuobj), + &error_fatal); if (!vms->secure) { object_property_set_bool(cpuobj, false, "has_el3", NULL); diff --git a/hw/bt/hci-csr.c b/hw/bt/hci-csr.c index 3c193848fc..d13192b9b5 100644 --- a/hw/bt/hci-csr.c +++ b/hw/bt/hci-csr.c @@ -20,7 +20,7 @@ #include "qemu/osdep.h" #include "qemu-common.h" -#include "sysemu/char.h" +#include "chardev/char-serial.h" #include "qemu/timer.h" #include "qemu/bswap.h" #include "hw/irq.h" @@ -82,17 +82,14 @@ enum { static inline void csrhci_fifo_wake(struct csrhci_s *s) { - Chardev *chr = (Chardev *)s; - CharBackend *be = chr->be; + Chardev *chr = CHARDEV(s); if (!s->enable || !s->out_len) return; /* XXX: Should wait for s->modem_state & CHR_TIOCM_RTS? */ - if (be && be->chr_can_read && be->chr_can_read(be->opaque) && - be->chr_read) { - be->chr_read(be->opaque, - s->outfifo + s->out_start++, 1); + if (qemu_chr_be_can_write(chr)) { + qemu_chr_be_write(chr, s->outfifo + s->out_start++, 1); s->out_len--; if (s->out_start >= s->out_size) { s->out_start = 0; diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c index 4dcee571c0..4a2c124104 100644 --- a/hw/char/cadence_uart.c +++ b/hw/char/cadence_uart.c @@ -23,7 +23,8 @@ #include "qemu/osdep.h" #include "hw/sysbus.h" -#include "sysemu/char.h" +#include "chardev/char-fe.h" +#include "chardev/char-serial.h" #include "qemu/timer.h" #include "qemu/log.h" #include "hw/char/cadence_uart.h" diff --git a/hw/char/debugcon.c b/hw/char/debugcon.c index 80dce07e7f..762e3d8ada 100644 --- a/hw/char/debugcon.c +++ b/hw/char/debugcon.c @@ -27,7 +27,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "hw/hw.h" -#include "sysemu/char.h" +#include "chardev/char-fe.h" #include "hw/isa/isa.h" #include "hw/i386/pc.h" diff --git a/hw/char/digic-uart.c b/hw/char/digic-uart.c index 029f5bbf5e..34306e11ff 100644 --- a/hw/char/digic-uart.c +++ b/hw/char/digic-uart.c @@ -29,7 +29,7 @@ #include "qemu/osdep.h" #include "hw/hw.h" #include "hw/sysbus.h" -#include "sysemu/char.h" +#include "chardev/char-fe.h" #include "qemu/log.h" #include "hw/char/digic-uart.h" diff --git a/hw/char/escc.c b/hw/char/escc.c index 9228091cec..3f787632c7 100644 --- a/hw/char/escc.c +++ b/hw/char/escc.c @@ -26,7 +26,8 @@ #include "hw/hw.h" #include "hw/sysbus.h" #include "hw/char/escc.h" -#include "sysemu/char.h" +#include "chardev/char-fe.h" +#include "chardev/char-serial.h" #include "ui/console.h" #include "ui/input.h" #include "trace.h" diff --git a/hw/char/etraxfs_ser.c b/hw/char/etraxfs_ser.c index 54383878e0..c1fba9f50f 100644 --- a/hw/char/etraxfs_ser.c +++ b/hw/char/etraxfs_ser.c @@ -24,7 +24,7 @@ #include "qemu/osdep.h" #include "hw/sysbus.h" -#include "sysemu/char.h" +#include "chardev/char-fe.h" #include "qemu/log.h" #define D(x) diff --git a/hw/char/exynos4210_uart.c b/hw/char/exynos4210_uart.c index bff706ab3a..b51d44a321 100644 --- a/hw/char/exynos4210_uart.c +++ b/hw/char/exynos4210_uart.c @@ -23,7 +23,8 @@ #include "hw/sysbus.h" #include "qemu/error-report.h" #include "sysemu/sysemu.h" -#include "sysemu/char.h" +#include "chardev/char-fe.h" +#include "chardev/char-serial.h" #include "hw/arm/exynos4210.h" diff --git a/hw/char/grlib_apbuart.c b/hw/char/grlib_apbuart.c index db686e6a6f..32d98edf49 100644 --- a/hw/char/grlib_apbuart.c +++ b/hw/char/grlib_apbuart.c @@ -24,7 +24,7 @@ #include "qemu/osdep.h" #include "hw/sysbus.h" -#include "sysemu/char.h" +#include "chardev/char-fe.h" #include "trace.h" diff --git a/hw/char/imx_serial.c b/hw/char/imx_serial.c index 52e67f8dc9..af250305be 100644 --- a/hw/char/imx_serial.c +++ b/hw/char/imx_serial.c @@ -21,7 +21,6 @@ #include "qemu/osdep.h" #include "hw/char/imx_serial.h" #include "sysemu/sysemu.h" -#include "sysemu/char.h" #include "qemu/log.h" #ifndef DEBUG_IMX_UART diff --git a/hw/char/ipoctal232.c b/hw/char/ipoctal232.c index 93929c2880..337a3e566a 100644 --- a/hw/char/ipoctal232.c +++ b/hw/char/ipoctal232.c @@ -11,7 +11,7 @@ #include "qemu/osdep.h" #include "hw/ipack/ipack.h" #include "qemu/bitops.h" -#include "sysemu/char.h" +#include "chardev/char-fe.h" /* #define DEBUG_IPOCTAL */ diff --git a/hw/char/lm32_juart.c b/hw/char/lm32_juart.c index f8c1e0d076..3948dcd332 100644 --- a/hw/char/lm32_juart.c +++ b/hw/char/lm32_juart.c @@ -21,7 +21,7 @@ #include "hw/hw.h" #include "hw/sysbus.h" #include "trace.h" -#include "sysemu/char.h" +#include "chardev/char-fe.h" #include "hw/char/lm32_juart.h" diff --git a/hw/char/lm32_uart.c b/hw/char/lm32_uart.c index 7f3597c4b0..cff8c38f90 100644 --- a/hw/char/lm32_uart.c +++ b/hw/char/lm32_uart.c @@ -26,7 +26,7 @@ #include "hw/hw.h" #include "hw/sysbus.h" #include "trace.h" -#include "sysemu/char.h" +#include "chardev/char-fe.h" #include "qemu/error-report.h" enum { diff --git a/hw/char/mcf_uart.c b/hw/char/mcf_uart.c index e69672f4e9..fe12ad5ccb 100644 --- a/hw/char/mcf_uart.c +++ b/hw/char/mcf_uart.c @@ -9,7 +9,7 @@ #include "hw/hw.h" #include "hw/sysbus.h" #include "hw/m68k/mcf.h" -#include "sysemu/char.h" +#include "chardev/char-fe.h" #include "exec/address-spaces.h" #include "qapi/error.h" diff --git a/hw/char/milkymist-uart.c b/hw/char/milkymist-uart.c index ae8e2f3554..e19d0f6520 100644 --- a/hw/char/milkymist-uart.c +++ b/hw/char/milkymist-uart.c @@ -25,7 +25,7 @@ #include "hw/hw.h" #include "hw/sysbus.h" #include "trace.h" -#include "sysemu/char.h" +#include "chardev/char-fe.h" #include "qemu/error-report.h" enum { diff --git a/hw/char/omap_uart.c b/hw/char/omap_uart.c index 31ebb1592c..6fd1b9cf6b 100644 --- a/hw/char/omap_uart.c +++ b/hw/char/omap_uart.c @@ -18,7 +18,7 @@ * with this program; if not, see <http://www.gnu.org/licenses/>. */ #include "qemu/osdep.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "hw/hw.h" #include "hw/arm/omap.h" #include "hw/char/serial.h" diff --git a/hw/char/parallel.c b/hw/char/parallel.c index c71a4a0f4f..75a1a2f55e 100644 --- a/hw/char/parallel.c +++ b/hw/char/parallel.c @@ -25,7 +25,8 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "hw/hw.h" -#include "sysemu/char.h" +#include "chardev/char-parallel.h" +#include "chardev/char-fe.h" #include "hw/isa/isa.h" #include "hw/i386/pc.h" #include "sysemu/sysemu.h" diff --git a/hw/char/pl011.c b/hw/char/pl011.c index 24ea9738b6..33802f00c8 100644 --- a/hw/char/pl011.c +++ b/hw/char/pl011.c @@ -9,7 +9,7 @@ #include "qemu/osdep.h" #include "hw/sysbus.h" -#include "sysemu/char.h" +#include "chardev/char-fe.h" #include "qemu/log.h" #include "trace.h" diff --git a/hw/char/sclpconsole-lm.c b/hw/char/sclpconsole-lm.c index 07d6ebd112..1b15046690 100644 --- a/hw/char/sclpconsole-lm.c +++ b/hw/char/sclpconsole-lm.c @@ -17,7 +17,7 @@ #include "hw/qdev.h" #include "qemu/thread.h" #include "qemu/error-report.h" -#include "sysemu/char.h" +#include "chardev/char-fe.h" #include "hw/s390x/sclp.h" #include "hw/s390x/event-facility.h" diff --git a/hw/char/sclpconsole.c b/hw/char/sclpconsole.c index b78f240a73..4a107a268d 100644 --- a/hw/char/sclpconsole.c +++ b/hw/char/sclpconsole.c @@ -19,7 +19,7 @@ #include "hw/s390x/sclp.h" #include "hw/s390x/event-facility.h" -#include "sysemu/char.h" +#include "chardev/char-fe.h" typedef struct ASCIIConsoleData { EventBufferHeader ebh; diff --git a/hw/char/serial.c b/hw/char/serial.c index 03d890ca24..e1f12507bf 100644 --- a/hw/char/serial.c +++ b/hw/char/serial.c @@ -25,7 +25,7 @@ #include "qemu/osdep.h" #include "hw/char/serial.h" -#include "sysemu/char.h" +#include "chardev/char-serial.h" #include "qapi/error.h" #include "qemu/timer.h" #include "exec/address-spaces.h" @@ -905,7 +905,7 @@ void serial_realize_core(SerialState *s, Error **errp) void serial_exit_core(SerialState *s) { - qemu_chr_fe_deinit(&s->chr); + qemu_chr_fe_deinit(&s->chr, false); timer_del(s->modem_status_poll); timer_free(s->modem_status_poll); diff --git a/hw/char/sh_serial.c b/hw/char/sh_serial.c index 303eb0a678..ca9816d045 100644 --- a/hw/char/sh_serial.c +++ b/hw/char/sh_serial.c @@ -27,7 +27,7 @@ #include "qemu/osdep.h" #include "hw/hw.h" #include "hw/sh4/sh.h" -#include "sysemu/char.h" +#include "chardev/char-fe.h" #include "exec/address-spaces.h" #include "qapi/error.h" diff --git a/hw/char/spapr_vty.c b/hw/char/spapr_vty.c index e30c8da57c..8f02f3a612 100644 --- a/hw/char/spapr_vty.c +++ b/hw/char/spapr_vty.c @@ -4,7 +4,7 @@ #include "qemu-common.h" #include "cpu.h" #include "hw/qdev.h" -#include "sysemu/char.h" +#include "chardev/char-fe.h" #include "hw/ppc/spapr.h" #include "hw/ppc/spapr_vio.h" diff --git a/hw/char/terminal3270.c b/hw/char/terminal3270.c index b2dda01baa..7b10a04f18 100644 --- a/hw/char/terminal3270.c +++ b/hw/char/terminal3270.c @@ -13,7 +13,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" -#include "sysemu/char.h" +#include "chardev/char-fe.h" #include "hw/s390x/3270-ccw.h" /* Enough spaces for different window sizes. */ diff --git a/hw/char/virtio-console.c b/hw/char/virtio-console.c index 798d9b69fd..0cb1668c8a 100644 --- a/hw/char/virtio-console.c +++ b/hw/char/virtio-console.c @@ -11,7 +11,7 @@ */ #include "qemu/osdep.h" -#include "sysemu/char.h" +#include "chardev/char-fe.h" #include "qemu/error-report.h" #include "trace.h" #include "hw/virtio/virtio-serial.h" diff --git a/hw/char/virtio-serial-bus.c b/hw/char/virtio-serial-bus.c index d797a6796e..f5bc173844 100644 --- a/hw/char/virtio-serial-bus.c +++ b/hw/char/virtio-serial-bus.c @@ -186,6 +186,9 @@ static void do_flush_queued_data(VirtIOSerialPort *port, VirtQueue *vq, port->elem->out_sg[i].iov_base + port->iov_offset, buf_size); + if (!port->elem) { /* bail if we got disconnected */ + return; + } if (port->throttled) { port->iov_idx = i; if (ret > 0) { @@ -1121,6 +1124,9 @@ static void virtio_serial_device_unrealize(DeviceState *dev, Error **errp) timer_free(vser->post_load->timer); g_free(vser->post_load); } + + qbus_set_hotplug_handler(BUS(&vser->bus), NULL, errp); + virtio_cleanup(vdev); } diff --git a/hw/char/xen_console.c b/hw/char/xen_console.c index c01f41090e..f9af8cadf4 100644 --- a/hw/char/xen_console.c +++ b/hw/char/xen_console.c @@ -25,7 +25,7 @@ #include "qapi/error.h" #include "hw/hw.h" -#include "sysemu/char.h" +#include "chardev/char-fe.h" #include "hw/xen/xen_backend.h" #include "qapi/error.h" @@ -261,7 +261,7 @@ static void con_disconnect(struct XenDevice *xendev) { struct XenConsole *con = container_of(xendev, struct XenConsole, xendev); - qemu_chr_fe_deinit(&con->chr); + qemu_chr_fe_deinit(&con->chr, false); xen_pv_unbind_evtchn(&con->xendev); if (con->sring) { diff --git a/hw/char/xilinx_uartlite.c b/hw/char/xilinx_uartlite.c index 37d313b429..71ed2fc1be 100644 --- a/hw/char/xilinx_uartlite.c +++ b/hw/char/xilinx_uartlite.c @@ -24,7 +24,7 @@ #include "qemu/osdep.h" #include "hw/sysbus.h" -#include "sysemu/char.h" +#include "chardev/char-fe.h" #define DUART(x) diff --git a/hw/core/Makefile.objs b/hw/core/Makefile.objs index 91450b2eab..f8d7a4aaed 100644 --- a/hw/core/Makefile.objs +++ b/hw/core/Makefile.objs @@ -5,7 +5,7 @@ common-obj-y += fw-path-provider.o # irq.o needed for qdev GPIO handling: common-obj-y += irq.o common-obj-y += hotplug.o -obj-y += nmi.o +common-obj-y += nmi.o common-obj-$(CONFIG_EMPTY_SLOT) += empty_slot.o common-obj-$(CONFIG_XILINX_AXI) += stream.o diff --git a/hw/core/loader.c b/hw/core/loader.c index bf17b42cbe..f72930ca4a 100644 --- a/hw/core/loader.c +++ b/hw/core/loader.c @@ -611,8 +611,9 @@ static int load_uboot_image(const char *filename, hwaddr *ep, hwaddr *loadaddr, return -1; size = read(fd, hdr, sizeof(uboot_image_header_t)); - if (size < 0) + if (size < sizeof(uboot_image_header_t)) { goto out; + } bswap_uboot_header(hdr); diff --git a/hw/core/machine.c b/hw/core/machine.c index 3adebf14c4..2e7e9778cd 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -701,26 +701,43 @@ static char *cpu_slot_to_string(const CPUArchId *cpu) return g_string_free(s, false); } -static void machine_numa_validate(MachineState *machine) +static void machine_numa_finish_init(MachineState *machine) { int i; + bool default_mapping; GString *s = g_string_new(NULL); MachineClass *mc = MACHINE_GET_CLASS(machine); const CPUArchIdList *possible_cpus = mc->possible_cpu_arch_ids(machine); assert(nb_numa_nodes); for (i = 0; i < possible_cpus->len; i++) { + if (possible_cpus->cpus[i].props.has_node_id) { + break; + } + } + default_mapping = (i == possible_cpus->len); + + for (i = 0; i < possible_cpus->len; i++) { const CPUArchId *cpu_slot = &possible_cpus->cpus[i]; - /* at this point numa mappings are initilized by CLI options - * or with default mappings so it's sufficient to list - * all not yet mapped CPUs here */ - /* TODO: make it hard error in future */ if (!cpu_slot->props.has_node_id) { - char *cpu_str = cpu_slot_to_string(cpu_slot); - g_string_append_printf(s, "%sCPU %d [%s]", s->len ? ", " : "", i, - cpu_str); - g_free(cpu_str); + /* fetch default mapping from board and enable it */ + CpuInstanceProperties props = cpu_slot->props; + + if (!default_mapping) { + /* record slots with not set mapping, + * TODO: make it hard error in future */ + char *cpu_str = cpu_slot_to_string(cpu_slot); + g_string_append_printf(s, "%sCPU %d [%s]", + s->len ? ", " : "", i, cpu_str); + g_free(cpu_str); + + /* non mapped cpus used to fallback to node 0 */ + props.node_id = 0; + } + + props.has_node_id = true; + machine_set_cpu_numa_node(machine, &props, &error_fatal); } } if (s->len && !qtest_enabled()) { @@ -738,7 +755,7 @@ void machine_run_board_init(MachineState *machine) MachineClass *machine_class = MACHINE_GET_CLASS(machine); if (nb_numa_nodes) { - machine_numa_validate(machine); + machine_numa_finish_init(machine); } machine_class->init(machine); } diff --git a/hw/core/qdev-properties-system.c b/hw/core/qdev-properties-system.c index 79c2014135..3bef41914d 100644 --- a/hw/core/qdev-properties-system.c +++ b/hw/core/qdev-properties-system.c @@ -20,7 +20,7 @@ #include "hw/block/block.h" #include "net/hub.h" #include "qapi/visitor.h" -#include "sysemu/char.h" +#include "chardev/char-fe.h" #include "sysemu/iothread.h" static void get_pointer(Object *obj, Visitor *v, Property *prop, @@ -225,7 +225,7 @@ static void release_chr(Object *obj, const char *name, void *opaque) Property *prop = opaque; CharBackend *be = qdev_get_prop_ptr(dev, prop); - qemu_chr_fe_deinit(be); + qemu_chr_fe_deinit(be, false); } PropertyInfo qdev_prop_chr = { diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c index fa3617db2d..9f1a497322 100644 --- a/hw/core/qdev-properties.c +++ b/hw/core/qdev-properties.c @@ -9,7 +9,7 @@ #include "hw/block/block.h" #include "net/hub.h" #include "qapi/visitor.h" -#include "sysemu/char.h" +#include "chardev/char.h" void qdev_prop_set_after_realize(DeviceState *dev, const char *name, Error **errp) diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 71ff95fd71..0ce45a2019 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -37,7 +37,6 @@ #include "hw/boards.h" #include "hw/sysbus.h" #include "qapi-event.h" -#include "migration/vmstate.h" bool qdev_hotplug = false; static bool qdev_hot_added = false; diff --git a/hw/core/register.c b/hw/core/register.c index da38ef3a54..900294b9c4 100644 --- a/hw/core/register.c +++ b/hw/core/register.c @@ -195,8 +195,8 @@ void register_write_memory(void *opaque, hwaddr addr, } if (!reg) { - qemu_log_mask(LOG_GUEST_ERROR, "Write to unimplemented register at " \ - "address: %#" PRIx64 "\n", addr); + qemu_log_mask(LOG_GUEST_ERROR, "%s: write to unimplemented register " \ + "at address: %#" PRIx64 "\n", reg_array->prefix, addr); return; } @@ -224,8 +224,8 @@ uint64_t register_read_memory(void *opaque, hwaddr addr, } if (!reg) { - qemu_log_mask(LOG_GUEST_ERROR, "Read to unimplemented register at " \ - "address: %#" PRIx64 "\n", addr); + qemu_log_mask(LOG_GUEST_ERROR, "%s: read to unimplemented register " \ + "at address: %#" PRIx64 "\n", reg_array->prefix, addr); return 0; } diff --git a/hw/display/xenfb.c b/hw/display/xenfb.c index 7a8727aa21..e76c0d805c 100644 --- a/hw/display/xenfb.c +++ b/hw/display/xenfb.c @@ -28,7 +28,6 @@ #include "hw/hw.h" #include "ui/console.h" -#include "sysemu/char.h" #include "hw/xen/xen_backend.h" #include <xen/event_channel.h> diff --git a/hw/dma/sparc32_dma.c b/hw/dma/sparc32_dma.c index 9c6bdc6295..eb491b50ca 100644 --- a/hw/dma/sparc32_dma.c +++ b/hw/dma/sparc32_dma.c @@ -270,23 +270,28 @@ static const VMStateDescription vmstate_dma = { } }; -static int sparc32_dma_init1(SysBusDevice *sbd) +static void sparc32_dma_init(Object *obj) { - DeviceState *dev = DEVICE(sbd); - DMAState *s = SPARC32_DMA(dev); - int reg_size; + DeviceState *dev = DEVICE(obj); + DMAState *s = SPARC32_DMA(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); sysbus_init_irq(sbd, &s->irq); - reg_size = s->is_ledma ? DMA_ETH_SIZE : DMA_SIZE; - memory_region_init_io(&s->iomem, OBJECT(s), &dma_mem_ops, s, - "dma", reg_size); sysbus_init_mmio(sbd, &s->iomem); qdev_init_gpio_in(dev, dma_set_irq, 1); qdev_init_gpio_out(dev, s->gpio, 2); +} - return 0; +static void sparc32_dma_realize(DeviceState *dev, Error **errp) +{ + DMAState *s = SPARC32_DMA(dev); + int reg_size; + + reg_size = s->is_ledma ? DMA_ETH_SIZE : DMA_SIZE; + memory_region_init_io(&s->iomem, OBJECT(dev), &dma_mem_ops, s, + "dma", reg_size); } static Property sparc32_dma_properties[] = { @@ -298,12 +303,11 @@ static Property sparc32_dma_properties[] = { static void sparc32_dma_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = sparc32_dma_init1; dc->reset = dma_reset; dc->vmsd = &vmstate_dma; dc->props = sparc32_dma_properties; + dc->realize = sparc32_dma_realize; /* Reason: pointer property "iommu_opaque" */ dc->user_creatable = false; } @@ -312,6 +316,7 @@ static const TypeInfo sparc32_dma_info = { .name = TYPE_SPARC32_DMA, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(DMAState), + .instance_init = sparc32_dma_init, .class_init = sparc32_dma_class_init, }; diff --git a/hw/dma/sun4m_iommu.c b/hw/dma/sun4m_iommu.c index b3cbc54c23..335ef63cbc 100644 --- a/hw/dma/sun4m_iommu.c +++ b/hw/dma/sun4m_iommu.c @@ -349,17 +349,16 @@ static void iommu_reset(DeviceState *d) s->regs[IOMMU_MASK_ID] = IOMMU_TS_MASK; } -static int iommu_init1(SysBusDevice *dev) +static void iommu_init(Object *obj) { - IOMMUState *s = SUN4M_IOMMU(dev); + IOMMUState *s = SUN4M_IOMMU(obj); + SysBusDevice *dev = SYS_BUS_DEVICE(obj); sysbus_init_irq(dev, &s->irq); - memory_region_init_io(&s->iomem, OBJECT(s), &iommu_mem_ops, s, "iommu", + memory_region_init_io(&s->iomem, obj, &iommu_mem_ops, s, "iommu", IOMMU_NREGS * sizeof(uint32_t)); sysbus_init_mmio(dev, &s->iomem); - - return 0; } static Property iommu_properties[] = { @@ -370,9 +369,7 @@ static Property iommu_properties[] = { static void iommu_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = iommu_init1; dc->reset = iommu_reset; dc->vmsd = &vmstate_iommu; dc->props = iommu_properties; @@ -382,6 +379,7 @@ static const TypeInfo iommu_info = { .name = TYPE_SUN4M_IOMMU, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(IOMMUState), + .instance_init = iommu_init, .class_init = iommu_class_init, }; diff --git a/hw/i2c/aspeed_i2c.c b/hw/i2c/aspeed_i2c.c index ce5b1f0fa4..c762c7366a 100644 --- a/hw/i2c/aspeed_i2c.c +++ b/hw/i2c/aspeed_i2c.c @@ -169,12 +169,33 @@ static uint64_t aspeed_i2c_bus_read(void *opaque, hwaddr offset, } } +static void aspeed_i2c_set_state(AspeedI2CBus *bus, uint8_t state) +{ + bus->cmd &= ~(I2CD_TX_STATE_MASK << I2CD_TX_STATE_SHIFT); + bus->cmd |= (state & I2CD_TX_STATE_MASK) << I2CD_TX_STATE_SHIFT; +} + +static uint8_t aspeed_i2c_get_state(AspeedI2CBus *bus) +{ + return (bus->cmd >> I2CD_TX_STATE_SHIFT) & I2CD_TX_STATE_MASK; +} + +/* + * The state machine needs some refinement. It is only used to track + * invalid STOP commands for the moment. + */ static void aspeed_i2c_bus_handle_cmd(AspeedI2CBus *bus, uint64_t value) { + bus->cmd &= ~0xFFFF; bus->cmd |= value & 0xFFFF; bus->intr_status = 0; if (bus->cmd & I2CD_M_START_CMD) { + uint8_t state = aspeed_i2c_get_state(bus) & I2CD_MACTIVE ? + I2CD_MSTARTR : I2CD_MSTART; + + aspeed_i2c_set_state(bus, state); + if (i2c_start_transfer(bus->bus, extract32(bus->buf, 1, 7), extract32(bus->buf, 0, 1))) { bus->intr_status |= I2CD_INTR_TX_NAK; @@ -182,16 +203,34 @@ static void aspeed_i2c_bus_handle_cmd(AspeedI2CBus *bus, uint64_t value) bus->intr_status |= I2CD_INTR_TX_ACK; } - } else if (bus->cmd & I2CD_M_TX_CMD) { + /* START command is also a TX command, as the slave address is + * sent on the bus */ + bus->cmd &= ~(I2CD_M_START_CMD | I2CD_M_TX_CMD); + + /* No slave found */ + if (!i2c_bus_busy(bus->bus)) { + return; + } + aspeed_i2c_set_state(bus, I2CD_MACTIVE); + } + + if (bus->cmd & I2CD_M_TX_CMD) { + aspeed_i2c_set_state(bus, I2CD_MTXD); if (i2c_send(bus->bus, bus->buf)) { - bus->intr_status |= (I2CD_INTR_TX_NAK | I2CD_INTR_ABNORMAL); + bus->intr_status |= (I2CD_INTR_TX_NAK); i2c_end_transfer(bus->bus); } else { bus->intr_status |= I2CD_INTR_TX_ACK; } + bus->cmd &= ~I2CD_M_TX_CMD; + aspeed_i2c_set_state(bus, I2CD_MACTIVE); + } - } else if (bus->cmd & I2CD_M_RX_CMD) { - int ret = i2c_recv(bus->bus); + if (bus->cmd & (I2CD_M_RX_CMD | I2CD_M_S_RX_CMD_LAST)) { + int ret; + + aspeed_i2c_set_state(bus, I2CD_MRXD); + ret = i2c_recv(bus->bus); if (ret < 0) { qemu_log_mask(LOG_GUEST_ERROR, "%s: read failed\n", __func__); ret = 0xff; @@ -199,20 +238,25 @@ static void aspeed_i2c_bus_handle_cmd(AspeedI2CBus *bus, uint64_t value) bus->intr_status |= I2CD_INTR_RX_DONE; } bus->buf = (ret & I2CD_BYTE_BUF_RX_MASK) << I2CD_BYTE_BUF_RX_SHIFT; + if (bus->cmd & I2CD_M_S_RX_CMD_LAST) { + i2c_nack(bus->bus); + } + bus->cmd &= ~(I2CD_M_RX_CMD | I2CD_M_S_RX_CMD_LAST); + aspeed_i2c_set_state(bus, I2CD_MACTIVE); } - if (bus->cmd & (I2CD_M_STOP_CMD | I2CD_M_S_RX_CMD_LAST)) { - if (!i2c_bus_busy(bus->bus)) { + if (bus->cmd & I2CD_M_STOP_CMD) { + if (!(aspeed_i2c_get_state(bus) & I2CD_MACTIVE)) { + qemu_log_mask(LOG_GUEST_ERROR, "%s: abnormal stop\n", __func__); bus->intr_status |= I2CD_INTR_ABNORMAL; } else { + aspeed_i2c_set_state(bus, I2CD_MSTOP); i2c_end_transfer(bus->bus); bus->intr_status |= I2CD_INTR_NORMAL_STOP; } + bus->cmd &= ~I2CD_M_STOP_CMD; + aspeed_i2c_set_state(bus, I2CD_IDLE); } - - /* command is handled, reset it and check for interrupts */ - bus->cmd &= ~0xFFFF; - aspeed_i2c_bus_raise_interrupt(bus); } static void aspeed_i2c_bus_write(void *opaque, hwaddr offset, @@ -262,6 +306,7 @@ static void aspeed_i2c_bus_write(void *opaque, hwaddr offset, } aspeed_i2c_bus_handle_cmd(bus, value); + aspeed_i2c_bus_raise_interrupt(bus); break; default: diff --git a/hw/i2c/i2c-ddc.c b/hw/i2c/i2c-ddc.c index 66899d7233..6b92e95c73 100644 --- a/hw/i2c/i2c-ddc.c +++ b/hw/i2c/i2c-ddc.c @@ -17,6 +17,7 @@ */ #include "qemu/osdep.h" +#include "qemu-common.h" #include "qemu/log.h" #include "hw/i2c/i2c.h" #include "hw/i2c/i2c-ddc.h" diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 82bd44f38e..ce74c84460 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -2335,8 +2335,7 @@ build_srat(GArray *table_data, BIOSLinker *linker, MachineState *machine) srat->reserved1 = cpu_to_le32(1); for (i = 0; i < apic_ids->len; i++) { - int node_id = apic_ids->cpus[i].props.has_node_id ? - apic_ids->cpus[i].props.node_id : 0; + int node_id = apic_ids->cpus[i].props.node_id; uint32_t apic_id = apic_ids->cpus[i].arch_id; if (apic_id < 255) { diff --git a/hw/i386/kvm/clock.c b/hw/i386/kvm/clock.c index 13eca374cd..363d1b5743 100644 --- a/hw/i386/kvm/clock.c +++ b/hw/i386/kvm/clock.c @@ -19,6 +19,7 @@ #include "qemu/host-utils.h" #include "sysemu/sysemu.h" #include "sysemu/kvm.h" +#include "sysemu/hw_accel.h" #include "kvm_i386.h" #include "hw/sysbus.h" #include "hw/kvm/clock.h" @@ -69,6 +70,8 @@ static uint64_t kvmclock_current_nsec(KVMClockState *s) uint64_t nsec_hi; uint64_t nsec; + cpu_synchronize_state(cpu); + if (!(env->system_time_msr & 1ULL)) { /* KVM clock not active */ return 0; diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 107a34125b..5b8c6fbbea 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -788,9 +788,7 @@ static FWCfgState *bochs_bios_init(AddressSpace *as, PCMachineState *pcms) for (i = 0; i < cpus->len; i++) { unsigned int apic_id = cpus->cpus[i].arch_id; assert(apic_id < pcms->apic_id_limit); - if (cpus->cpus[i].props.has_node_id) { - numa_fw_cfg[apic_id + 1] = cpu_to_le64(cpus->cpus[i].props.node_id); - } + numa_fw_cfg[apic_id + 1] = cpu_to_le64(cpus->cpus[i].props.node_id); } for (i = 0; i < nb_numa_nodes; i++) { numa_fw_cfg[pcms->apic_id_limit + 1 + i] = @@ -1893,7 +1891,6 @@ static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { int idx; - int node_id; CPUState *cs; CPUArchId *cpu_slot; X86CPUTopoInfo topo; @@ -1984,21 +1981,7 @@ static void pc_cpu_pre_plug(HotplugHandler *hotplug_dev, cs = CPU(cpu); cs->cpu_index = idx; - node_id = cpu_slot->props.node_id; - if (!cpu_slot->props.has_node_id) { - /* by default CPUState::numa_node was 0 if it's not set via CLI - * keep it this way for now but in future we probably should - * refuse to start up with incomplete numa mapping */ - node_id = 0; - } - if (cs->numa_node == CPU_UNSET_NUMA_NODE_ID) { - cs->numa_node = node_id; - } else if (cs->numa_node != node_id) { - error_setg(errp, "node-id %d must match numa node specified" - "with -numa option for cpu-index %d", - cs->numa_node, cs->cpu_index); - return; - } + numa_cpu_pre_plug(cpu_slot, dev, errp); } static void pc_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev, diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c index 919f09b694..1acd4de405 100644 --- a/hw/i386/xen/xen-hvm.c +++ b/hw/i386/xen/xen-hvm.c @@ -18,7 +18,6 @@ #include "hw/xen/xen_backend.h" #include "qmp-commands.h" -#include "sysemu/char.h" #include "qemu/error-report.h" #include "qemu/range.h" #include "sysemu/xen-mapcache.h" diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c index 0b208560bd..5cbafaf497 100644 --- a/hw/intc/arm_gicv3_cpuif.c +++ b/hw/intc/arm_gicv3_cpuif.c @@ -216,18 +216,35 @@ static uint32_t icv_gprio_mask(GICv3CPUState *cs, int group) { /* Return a mask word which clears the subpriority bits from * a priority value for a virtual interrupt in the specified group. - * This depends on the VBPR value: + * This depends on the VBPR value. + * If using VBPR0 then: * a BPR of 0 means the group priority bits are [7:1]; * a BPR of 1 means they are [7:2], and so on down to * a BPR of 7 meaning no group priority bits at all. + * If using VBPR1 then: + * a BPR of 0 is impossible (the minimum value is 1) + * a BPR of 1 means the group priority bits are [7:1]; + * a BPR of 2 means they are [7:2], and so on down to + * a BPR of 7 meaning the group priority is [7]. + * * Which BPR to use depends on the group of the interrupt and * the current ICH_VMCR_EL2.VCBPR settings. + * + * This corresponds to the VGroupBits() pseudocode. */ + int bpr; + if (group == GICV3_G1NS && cs->ich_vmcr_el2 & ICH_VMCR_EL2_VCBPR) { group = GICV3_G0; } - return ~0U << (read_vbpr(cs, group) + 1); + bpr = read_vbpr(cs, group); + if (group == GICV3_G1NS) { + assert(bpr > 0); + bpr--; + } + + return ~0U << (bpr + 1); } static bool icv_hppi_can_preempt(GICv3CPUState *cs, uint64_t lr) @@ -674,20 +691,37 @@ static uint32_t icc_gprio_mask(GICv3CPUState *cs, int group) { /* Return a mask word which clears the subpriority bits from * a priority value for an interrupt in the specified group. - * This depends on the BPR value: + * This depends on the BPR value. For CBPR0 (S or NS): * a BPR of 0 means the group priority bits are [7:1]; * a BPR of 1 means they are [7:2], and so on down to * a BPR of 7 meaning no group priority bits at all. + * For CBPR1 NS: + * a BPR of 0 is impossible (the minimum value is 1) + * a BPR of 1 means the group priority bits are [7:1]; + * a BPR of 2 means they are [7:2], and so on down to + * a BPR of 7 meaning the group priority is [7]. + * * Which BPR to use depends on the group of the interrupt and * the current ICC_CTLR.CBPR settings. + * + * This corresponds to the GroupBits() pseudocode. */ + int bpr; + if ((group == GICV3_G1 && cs->icc_ctlr_el1[GICV3_S] & ICC_CTLR_EL1_CBPR) || (group == GICV3_G1NS && cs->icc_ctlr_el1[GICV3_NS] & ICC_CTLR_EL1_CBPR)) { group = GICV3_G0; } - return ~0U << ((cs->icc_bpr[group] & 7) + 1); + bpr = cs->icc_bpr[group] & 7; + + if (group == GICV3_G1NS) { + assert(bpr > 0); + bpr--; + } + + return ~0U << (bpr + 1); } static bool icc_no_enabled_hppi(GICv3CPUState *cs) @@ -1388,6 +1422,7 @@ static void icc_bpr_write(CPUARMState *env, const ARMCPRegInfo *ri, { GICv3CPUState *cs = icc_cs_from_env(env); int grp = (ri->crm == 8) ? GICV3_G0 : GICV3_G1; + uint64_t minval; if (icv_access(env, grp == GICV3_G0 ? HCR_FMO : HCR_IMO)) { icv_bpr_write(env, ri, value); @@ -1415,6 +1450,11 @@ static void icc_bpr_write(CPUARMState *env, const ARMCPRegInfo *ri, return; } + minval = (grp == GICV3_G1NS) ? GIC_MIN_BPR_NS : GIC_MIN_BPR; + if (value < minval) { + value = minval; + } + cs->icc_bpr[grp] = value & 7; gicv3_cpuif_update(cs); } @@ -1999,11 +2039,7 @@ static void icc_reset(CPUARMState *env, const ARMCPRegInfo *ri) cs->icc_pmr_el1 = 0; cs->icc_bpr[GICV3_G0] = GIC_MIN_BPR; cs->icc_bpr[GICV3_G1] = GIC_MIN_BPR; - if (arm_feature(env, ARM_FEATURE_EL3)) { - cs->icc_bpr[GICV3_G1NS] = GIC_MIN_BPR_NS; - } else { - cs->icc_bpr[GICV3_G1NS] = GIC_MIN_BPR; - } + cs->icc_bpr[GICV3_G1NS] = GIC_MIN_BPR_NS; memset(cs->icc_apr, 0, sizeof(cs->icc_apr)); memset(cs->icc_igrpen, 0, sizeof(cs->icc_igrpen)); cs->icc_ctlr_el3 = ICC_CTLR_EL3_NDS | ICC_CTLR_EL3_A3V | @@ -2014,7 +2050,7 @@ static void icc_reset(CPUARMState *env, const ARMCPRegInfo *ri) cs->ich_hcr_el2 = 0; memset(cs->ich_lr_el2, 0, sizeof(cs->ich_lr_el2)); cs->ich_vmcr_el2 = ICH_VMCR_EL2_VFIQEN | - (icv_min_vbpr(cs) << ICH_VMCR_EL2_VBPR1_SHIFT) | + ((icv_min_vbpr(cs) + 1) << ICH_VMCR_EL2_VBPR1_SHIFT) | (icv_min_vbpr(cs) << ICH_VMCR_EL2_VBPR0_SHIFT); } diff --git a/hw/intc/armv7m_nvic.c b/hw/intc/armv7m_nvic.c index 32ffa0bf35..26a4b2dcb5 100644 --- a/hw/intc/armv7m_nvic.c +++ b/hw/intc/armv7m_nvic.c @@ -19,6 +19,7 @@ #include "hw/arm/arm.h" #include "hw/arm/armv7m_nvic.h" #include "target/arm/cpu.h" +#include "exec/exec-all.h" #include "qemu/log.h" #include "trace.h" @@ -528,6 +529,39 @@ static uint32_t nvic_readl(NVICState *s, uint32_t offset) case 0xd70: /* ISAR4. */ return 0x01310102; /* TODO: Implement debug registers. */ + case 0xd90: /* MPU_TYPE */ + /* Unified MPU; if the MPU is not present this value is zero */ + return cpu->pmsav7_dregion << 8; + break; + case 0xd94: /* MPU_CTRL */ + return cpu->env.v7m.mpu_ctrl; + case 0xd98: /* MPU_RNR */ + return cpu->env.cp15.c6_rgnr; + case 0xd9c: /* MPU_RBAR */ + case 0xda4: /* MPU_RBAR_A1 */ + case 0xdac: /* MPU_RBAR_A2 */ + case 0xdb4: /* MPU_RBAR_A3 */ + { + int region = cpu->env.cp15.c6_rgnr; + + if (region >= cpu->pmsav7_dregion) { + return 0; + } + return (cpu->env.pmsav7.drbar[region] & 0x1f) | (region & 0xf); + } + case 0xda0: /* MPU_RASR */ + case 0xda8: /* MPU_RASR_A1 */ + case 0xdb0: /* MPU_RASR_A2 */ + case 0xdb8: /* MPU_RASR_A3 */ + { + int region = cpu->env.cp15.c6_rgnr; + + if (region >= cpu->pmsav7_dregion) { + return 0; + } + return ((cpu->env.pmsav7.dracr[region] & 0xffff) << 16) | + (cpu->env.pmsav7.drsr[region] & 0xffff); + } default: qemu_log_mask(LOG_GUEST_ERROR, "NVIC: Bad read offset 0x%x\n", offset); return 0; @@ -627,6 +661,76 @@ static void nvic_writel(NVICState *s, uint32_t offset, uint32_t value) qemu_log_mask(LOG_UNIMP, "NVIC: Aux fault status registers unimplemented\n"); break; + case 0xd90: /* MPU_TYPE */ + return; /* RO */ + case 0xd94: /* MPU_CTRL */ + if ((value & + (R_V7M_MPU_CTRL_HFNMIENA_MASK | R_V7M_MPU_CTRL_ENABLE_MASK)) + == R_V7M_MPU_CTRL_HFNMIENA_MASK) { + qemu_log_mask(LOG_GUEST_ERROR, "MPU_CTRL: HFNMIENA and !ENABLE is " + "UNPREDICTABLE\n"); + } + cpu->env.v7m.mpu_ctrl = value & (R_V7M_MPU_CTRL_ENABLE_MASK | + R_V7M_MPU_CTRL_HFNMIENA_MASK | + R_V7M_MPU_CTRL_PRIVDEFENA_MASK); + tlb_flush(CPU(cpu)); + break; + case 0xd98: /* MPU_RNR */ + if (value >= cpu->pmsav7_dregion) { + qemu_log_mask(LOG_GUEST_ERROR, "MPU region out of range %" + PRIu32 "/%" PRIu32 "\n", + value, cpu->pmsav7_dregion); + } else { + cpu->env.cp15.c6_rgnr = value; + } + break; + case 0xd9c: /* MPU_RBAR */ + case 0xda4: /* MPU_RBAR_A1 */ + case 0xdac: /* MPU_RBAR_A2 */ + case 0xdb4: /* MPU_RBAR_A3 */ + { + int region; + + if (value & (1 << 4)) { + /* VALID bit means use the region number specified in this + * value and also update MPU_RNR.REGION with that value. + */ + region = extract32(value, 0, 4); + if (region >= cpu->pmsav7_dregion) { + qemu_log_mask(LOG_GUEST_ERROR, + "MPU region out of range %u/%" PRIu32 "\n", + region, cpu->pmsav7_dregion); + return; + } + cpu->env.cp15.c6_rgnr = region; + } else { + region = cpu->env.cp15.c6_rgnr; + } + + if (region >= cpu->pmsav7_dregion) { + return; + } + + cpu->env.pmsav7.drbar[region] = value & ~0x1f; + tlb_flush(CPU(cpu)); + break; + } + case 0xda0: /* MPU_RASR */ + case 0xda8: /* MPU_RASR_A1 */ + case 0xdb0: /* MPU_RASR_A2 */ + case 0xdb8: /* MPU_RASR_A3 */ + { + int region = cpu->env.cp15.c6_rgnr; + + if (region >= cpu->pmsav7_dregion) { + return; + } + + cpu->env.pmsav7.drsr[region] = value & 0xff3f; + cpu->env.pmsav7.dracr[region] = (value >> 16) & 0x173f; + tlb_flush(CPU(cpu)); + break; + } case 0xf00: /* Software Triggered Interrupt Register */ { /* user mode can only write to STIR if CCR.USERSETMPEND permits it */ diff --git a/hw/intc/openpic.c b/hw/intc/openpic.c index 4349e45e04..f966d0604a 100644 --- a/hw/intc/openpic.c +++ b/hw/intc/openpic.c @@ -796,27 +796,24 @@ static uint64_t openpic_gbl_read(void *opaque, hwaddr addr, unsigned len) } static void openpic_tmr_write(void *opaque, hwaddr addr, uint64_t val, - unsigned len) + unsigned len) { OpenPICState *opp = opaque; int idx; - addr += 0x10f0; - DPRINTF("%s: addr %#" HWADDR_PRIx " <= %08" PRIx64 "\n", - __func__, addr, val); + __func__, (addr + 0x10f0), val); if (addr & 0xF) { return; } - if (addr == 0x10f0) { + if (addr == 0) { /* TFRR */ opp->tfrr = val; return; } - + addr -= 0x10; /* correct for TFRR */ idx = (addr >> 6) & 0x3; - addr = addr & 0x30; switch (addr & 0x30) { case 0x00: /* TCCR */ @@ -844,16 +841,17 @@ static uint64_t openpic_tmr_read(void *opaque, hwaddr addr, unsigned len) uint32_t retval = -1; int idx; - DPRINTF("%s: addr %#" HWADDR_PRIx "\n", __func__, addr); + DPRINTF("%s: addr %#" HWADDR_PRIx "\n", __func__, addr + 0x10f0); if (addr & 0xF) { goto out; } - idx = (addr >> 6) & 0x3; - if (addr == 0x0) { + if (addr == 0) { /* TFRR */ retval = opp->tfrr; goto out; } + addr -= 0x10; /* correct for TFRR */ + idx = (addr >> 6) & 0x3; switch (addr & 0x30) { case 0x00: /* TCCR */ retval = opp->timers[idx].tccr; @@ -861,10 +859,10 @@ static uint64_t openpic_tmr_read(void *opaque, hwaddr addr, unsigned len) case 0x10: /* TBCR */ retval = opp->timers[idx].tbcr; break; - case 0x20: /* TIPV */ + case 0x20: /* TVPR */ retval = read_IRQreg_ivpr(opp, opp->irq_tim0 + idx); break; - case 0x30: /* TIDE (TIDR) */ + case 0x30: /* TDR */ retval = read_IRQreg_idr(opp, opp->irq_tim0 + idx); break; } diff --git a/hw/intc/s390_flic.c b/hw/intc/s390_flic.c index 711c11454f..a26e90670f 100644 --- a/hw/intc/s390_flic.c +++ b/hw/intc/s390_flic.c @@ -13,7 +13,6 @@ #include "qemu/osdep.h" #include "qemu/error-report.h" #include "hw/sysbus.h" -#include "migration/qemu-file.h" #include "hw/s390x/s390_flic.h" #include "trace.h" #include "hw/qdev.h" diff --git a/hw/intc/s390_flic_kvm.c b/hw/intc/s390_flic_kvm.c index cc44bc4e1e..b4c61d8300 100644 --- a/hw/intc/s390_flic_kvm.c +++ b/hw/intc/s390_flic_kvm.c @@ -17,7 +17,6 @@ #include "qemu/error-report.h" #include "hw/sysbus.h" #include "sysemu/kvm.h" -#include "migration/qemu-file.h" #include "hw/s390x/s390_flic.h" #include "hw/s390x/adapter.h" #include "trace.h" diff --git a/hw/ipmi/ipmi_bmc_extern.c b/hw/ipmi/ipmi_bmc_extern.c index e8e3d250b6..329b03e17f 100644 --- a/hw/ipmi/ipmi_bmc_extern.c +++ b/hw/ipmi/ipmi_bmc_extern.c @@ -30,7 +30,7 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qemu/timer.h" -#include "sysemu/char.h" +#include "chardev/char-fe.h" #include "sysemu/sysemu.h" #include "hw/ipmi/ipmi.h" diff --git a/hw/isa/pc87312.c b/hw/isa/pc87312.c index c707d24db4..5ce9f0a062 100644 --- a/hw/isa/pc87312.c +++ b/hw/isa/pc87312.c @@ -30,7 +30,7 @@ #include "sysemu/block-backend.h" #include "sysemu/blockdev.h" #include "sysemu/sysemu.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "trace.h" diff --git a/hw/mips/boston.c b/hw/mips/boston.c index 53d1e0ce45..a4677f7da4 100644 --- a/hw/mips/boston.c +++ b/hw/mips/boston.c @@ -35,7 +35,7 @@ #include "qemu/cutils.h" #include "qemu/error-report.h" #include "qemu/log.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "sysemu/device_tree.h" #include "sysemu/sysemu.h" #include "sysemu/qtest.h" diff --git a/hw/mips/mips_fulong2e.c b/hw/mips/mips_fulong2e.c index e636c3abaa..dbe2805acb 100644 --- a/hw/mips/mips_fulong2e.c +++ b/hw/mips/mips_fulong2e.c @@ -32,7 +32,6 @@ #include "hw/mips/mips.h" #include "hw/mips/cpudevs.h" #include "hw/pci/pci.h" -#include "sysemu/char.h" #include "sysemu/sysemu.h" #include "audio/audio.h" #include "qemu/log.h" diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c index 7814c39654..95cdabb2dd 100644 --- a/hw/mips/mips_malta.c +++ b/hw/mips/mips_malta.c @@ -37,7 +37,6 @@ #include "hw/mips/mips.h" #include "hw/mips/cpudevs.h" #include "hw/pci/pci.h" -#include "sysemu/char.h" #include "sysemu/sysemu.h" #include "sysemu/arch_init.h" #include "qemu/log.h" diff --git a/hw/misc/eccmemctl.c b/hw/misc/eccmemctl.c index a0071f3eae..bb7cc52b5e 100644 --- a/hw/misc/eccmemctl.c +++ b/hw/misc/eccmemctl.c @@ -295,22 +295,29 @@ static void ecc_reset(DeviceState *d) s->regs[ECC_ECR1] = 0; } -static int ecc_init1(SysBusDevice *dev) +static void ecc_init(Object *obj) { - ECCState *s = ECC_MEMCTL(dev); + ECCState *s = ECC_MEMCTL(obj); + SysBusDevice *dev = SYS_BUS_DEVICE(obj); sysbus_init_irq(dev, &s->irq); - s->regs[0] = s->version; - memory_region_init_io(&s->iomem, OBJECT(dev), &ecc_mem_ops, s, "ecc", ECC_SIZE); + + memory_region_init_io(&s->iomem, obj, &ecc_mem_ops, s, "ecc", ECC_SIZE); sysbus_init_mmio(dev, &s->iomem); +} + +static void ecc_realize(DeviceState *dev, Error **errp) +{ + ECCState *s = ECC_MEMCTL(dev); + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); + + s->regs[0] = s->version; if (s->version == ECC_MCC) { // SS-600MP only memory_region_init_io(&s->iomem_diag, OBJECT(dev), &ecc_diag_mem_ops, s, "ecc.diag", ECC_DIAG_SIZE); - sysbus_init_mmio(dev, &s->iomem_diag); + sysbus_init_mmio(sbd, &s->iomem_diag); } - - return 0; } static Property ecc_properties[] = { @@ -321,9 +328,8 @@ static Property ecc_properties[] = { static void ecc_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = ecc_init1; + dc->realize = ecc_realize; dc->reset = ecc_reset; dc->vmsd = &vmstate_ecc; dc->props = ecc_properties; @@ -333,6 +339,7 @@ static const TypeInfo ecc_info = { .name = TYPE_ECC_MEMCTL, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(ECCState), + .instance_init = ecc_init, .class_init = ecc_class_init, }; diff --git a/hw/misc/edu.c b/hw/misc/edu.c index 401039c100..01acacf142 100644 --- a/hw/misc/edu.c +++ b/hw/misc/edu.c @@ -343,6 +343,12 @@ static void pci_edu_realize(PCIDevice *pdev, Error **errp) EduState *edu = DO_UPCAST(EduState, pdev, pdev); uint8_t *pci_conf = pdev->config; + pci_config_set_interrupt_pin(pci_conf, 1); + + if (msi_init(pdev, 0, 1, true, false, errp)) { + return; + } + timer_init_ms(&edu->dma_timer, QEMU_CLOCK_VIRTUAL, edu_dma_timer, edu); qemu_mutex_init(&edu->thr_mutex); @@ -350,12 +356,6 @@ static void pci_edu_realize(PCIDevice *pdev, Error **errp) qemu_thread_create(&edu->thread, "edu", edu_fact_thread, edu, QEMU_THREAD_JOINABLE); - pci_config_set_interrupt_pin(pci_conf, 1); - - if (msi_init(pdev, 0, 1, true, false, errp)) { - return; - } - memory_region_init_io(&edu->mmio, OBJECT(edu), &edu_mmio_ops, edu, "edu-mmio", 1 << 20); pci_register_bar(pdev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &edu->mmio); diff --git a/hw/misc/ivshmem.c b/hw/misc/ivshmem.c index 475e36a4c7..6367d041f0 100644 --- a/hw/misc/ivshmem.c +++ b/hw/misc/ivshmem.c @@ -29,7 +29,7 @@ #include "qemu/error-report.h" #include "qemu/event_notifier.h" #include "qom/object_interfaces.h" -#include "sysemu/char.h" +#include "chardev/char-fe.h" #include "sysemu/hostmem.h" #include "sysemu/qtest.h" #include "qapi/visitor.h" diff --git a/hw/misc/slavio_misc.c b/hw/misc/slavio_misc.c index 18ff677512..0b33cdcb61 100644 --- a/hw/misc/slavio_misc.c +++ b/hw/misc/slavio_misc.c @@ -414,76 +414,73 @@ static const VMStateDescription vmstate_misc = { } }; -static int apc_init1(SysBusDevice *dev) +static void apc_init(Object *obj) { - APCState *s = APC(dev); + APCState *s = APC(obj); + SysBusDevice *dev = SYS_BUS_DEVICE(obj); sysbus_init_irq(dev, &s->cpu_halt); /* Power management (APC) XXX: not a Slavio device */ - memory_region_init_io(&s->iomem, OBJECT(s), &apc_mem_ops, s, + memory_region_init_io(&s->iomem, obj, &apc_mem_ops, s, "apc", MISC_SIZE); sysbus_init_mmio(dev, &s->iomem); - return 0; } -static int slavio_misc_init1(SysBusDevice *sbd) +static void slavio_misc_init(Object *obj) { - DeviceState *dev = DEVICE(sbd); - MiscState *s = SLAVIO_MISC(dev); + DeviceState *dev = DEVICE(obj); + MiscState *s = SLAVIO_MISC(obj); + SysBusDevice *sbd = SYS_BUS_DEVICE(obj); sysbus_init_irq(sbd, &s->irq); sysbus_init_irq(sbd, &s->fdc_tc); /* 8 bit registers */ /* Slavio control */ - memory_region_init_io(&s->cfg_iomem, OBJECT(s), &slavio_cfg_mem_ops, s, + memory_region_init_io(&s->cfg_iomem, obj, &slavio_cfg_mem_ops, s, "configuration", MISC_SIZE); sysbus_init_mmio(sbd, &s->cfg_iomem); /* Diagnostics */ - memory_region_init_io(&s->diag_iomem, OBJECT(s), &slavio_diag_mem_ops, s, + memory_region_init_io(&s->diag_iomem, obj, &slavio_diag_mem_ops, s, "diagnostic", MISC_SIZE); sysbus_init_mmio(sbd, &s->diag_iomem); /* Modem control */ - memory_region_init_io(&s->mdm_iomem, OBJECT(s), &slavio_mdm_mem_ops, s, + memory_region_init_io(&s->mdm_iomem, obj, &slavio_mdm_mem_ops, s, "modem", MISC_SIZE); sysbus_init_mmio(sbd, &s->mdm_iomem); /* 16 bit registers */ /* ss600mp diag LEDs */ - memory_region_init_io(&s->led_iomem, OBJECT(s), &slavio_led_mem_ops, s, + memory_region_init_io(&s->led_iomem, obj, &slavio_led_mem_ops, s, "leds", LED_SIZE); sysbus_init_mmio(sbd, &s->led_iomem); /* 32 bit registers */ /* System control */ - memory_region_init_io(&s->sysctrl_iomem, OBJECT(s), &slavio_sysctrl_mem_ops, s, + memory_region_init_io(&s->sysctrl_iomem, obj, &slavio_sysctrl_mem_ops, s, "system-control", SYSCTRL_SIZE); sysbus_init_mmio(sbd, &s->sysctrl_iomem); /* AUX 1 (Misc System Functions) */ - memory_region_init_io(&s->aux1_iomem, OBJECT(s), &slavio_aux1_mem_ops, s, + memory_region_init_io(&s->aux1_iomem, obj, &slavio_aux1_mem_ops, s, "misc-system-functions", MISC_SIZE); sysbus_init_mmio(sbd, &s->aux1_iomem); /* AUX 2 (Software Powerdown Control) */ - memory_region_init_io(&s->aux2_iomem, OBJECT(s), &slavio_aux2_mem_ops, s, + memory_region_init_io(&s->aux2_iomem, obj, &slavio_aux2_mem_ops, s, "software-powerdown-control", MISC_SIZE); sysbus_init_mmio(sbd, &s->aux2_iomem); qdev_init_gpio_in(dev, slavio_set_power_fail, 1); - - return 0; } static void slavio_misc_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = slavio_misc_init1; dc->reset = slavio_misc_reset; dc->vmsd = &vmstate_misc; } @@ -492,21 +489,15 @@ static const TypeInfo slavio_misc_info = { .name = TYPE_SLAVIO_MISC, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(MiscState), + .instance_init = slavio_misc_init, .class_init = slavio_misc_class_init, }; -static void apc_class_init(ObjectClass *klass, void *data) -{ - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - - k->init = apc_init1; -} - static const TypeInfo apc_info = { .name = TYPE_APC, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(MiscState), - .class_init = apc_class_init, + .instance_init = apc_init, }; static void slavio_misc_register_types(void) diff --git a/hw/net/rocker/rocker.c b/hw/net/rocker/rocker.c index 6e70fddee3..4f0f6d71e5 100644 --- a/hw/net/rocker/rocker.c +++ b/hw/net/rocker/rocker.c @@ -244,11 +244,9 @@ static int tx_consume(Rocker *r, DescInfo *info) goto err_no_mem; } - if (pci_dma_read(dev, frag_addr, iov[iovcnt].iov_base, - iov[iovcnt].iov_len)) { - err = -ROCKER_ENXIO; - goto err_bad_io; - } + pci_dma_read(dev, frag_addr, iov[iovcnt].iov_base, + iov[iovcnt].iov_len); + iovcnt++; } @@ -261,7 +259,6 @@ static int tx_consume(Rocker *r, DescInfo *info) err = fp_port_eg(r->fp_port[port], iov, iovcnt); err_too_many_frags: -err_bad_io: err_no_mem: err_bad_attr: for (i = 0; i < ROCKER_TX_FRAGS_MAX; i++) { diff --git a/hw/net/rocker/rocker_desc.c b/hw/net/rocker/rocker_desc.c index ac02797b7e..6184c40f72 100644 --- a/hw/net/rocker/rocker_desc.c +++ b/hw/net/rocker/rocker_desc.c @@ -69,9 +69,7 @@ char *desc_get_buf(DescInfo *info, bool read_only) return NULL; } - if (pci_dma_read(dev, le64_to_cpu(info->desc.buf_addr), info->buf, size)) { - return NULL; - } + pci_dma_read(dev, le64_to_cpu(info->desc.buf_addr), info->buf, size); return info->buf; } diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index 22874a9777..e037db63a3 100644 --- a/hw/net/vhost_net.c +++ b/hw/net/vhost_net.c @@ -77,6 +77,7 @@ static const int user_feature_bits[] = { VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_MTU, + VIRTIO_F_IOMMU_PLATFORM, /* This bit implies RARP isn't sent by QEMU out of band */ VIRTIO_NET_F_GUEST_ANNOUNCE, diff --git a/hw/net/vmxnet3.c b/hw/net/vmxnet3.c index 8b1fab24fd..4df31101ec 100644 --- a/hw/net/vmxnet3.c +++ b/hw/net/vmxnet3.c @@ -2262,6 +2262,11 @@ static const MemoryRegionOps b1_ops = { }, }; +static SaveVMHandlers savevm_vmxnet3_msix = { + .save_state = vmxnet3_msix_save, + .load_state = vmxnet3_msix_load, +}; + static uint64_t vmxnet3_device_serial_num(VMXNET3State *s) { uint64_t dsn_payload; @@ -2331,8 +2336,7 @@ static void vmxnet3_pci_realize(PCIDevice *pci_dev, Error **errp) vmxnet3_device_serial_num(s)); } - register_savevm(dev, "vmxnet3-msix", -1, 1, - vmxnet3_msix_save, vmxnet3_msix_load, s); + register_savevm_live(dev, "vmxnet3-msix", -1, 1, &savevm_vmxnet3_msix, s); } static void vmxnet3_instance_init(Object *obj) diff --git a/hw/net/xgmac.c b/hw/net/xgmac.c index 46b1aa17fa..0843bf185c 100644 --- a/hw/net/xgmac.c +++ b/hw/net/xgmac.c @@ -26,7 +26,6 @@ #include "qemu/osdep.h" #include "hw/sysbus.h" -#include "sysemu/char.h" #include "qemu/log.h" #include "net/net.h" #include "net/checksum.h" diff --git a/hw/nvram/spapr_nvram.c b/hw/nvram/spapr_nvram.c index aa5d2c1f5f..bc355a4348 100644 --- a/hw/nvram/spapr_nvram.c +++ b/hw/nvram/spapr_nvram.c @@ -144,7 +144,15 @@ static void spapr_nvram_realize(VIOsPAPRDevice *dev, Error **errp) int ret; if (nvram->blk) { - nvram->size = blk_getlength(nvram->blk); + int64_t len = blk_getlength(nvram->blk); + + if (len < 0) { + error_setg_errno(errp, -len, + "could not get length of backing image"); + return; + } + + nvram->size = len; ret = blk_set_perm(nvram->blk, BLK_PERM_CONSISTENT_READ | BLK_PERM_WRITE, diff --git a/hw/pci/msix.c b/hw/pci/msix.c index bb54e8b0ac..fc5fe511b3 100644 --- a/hw/pci/msix.c +++ b/hw/pci/msix.c @@ -22,6 +22,7 @@ #include "hw/xen/xen.h" #include "qemu/range.h" #include "qapi/error.h" +#include "trace.h" #define MSIX_CAP_LENGTH 12 @@ -130,10 +131,14 @@ static void msix_handle_mask_update(PCIDevice *dev, int vector, bool was_masked) } } +static bool msix_masked(PCIDevice *dev) +{ + return dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] & MSIX_MASKALL_MASK; +} + static void msix_update_function_masked(PCIDevice *dev) { - dev->msix_function_masked = !msix_enabled(dev) || - (dev->config[dev->msix_cap + MSIX_CONTROL_OFFSET] & MSIX_MASKALL_MASK); + dev->msix_function_masked = !msix_enabled(dev) || msix_masked(dev); } /* Handle MSI-X capability config write. */ @@ -148,6 +153,8 @@ void msix_write_config(PCIDevice *dev, uint32_t addr, return; } + trace_msix_write_config(dev->name, msix_enabled(dev), msix_masked(dev)); + was_masked = dev->msix_function_masked; msix_update_function_masked(dev); diff --git a/hw/pci/trace-events b/hw/pci/trace-events index 2b9cf24405..83c8f5ace7 100644 --- a/hw/pci/trace-events +++ b/hw/pci/trace-events @@ -7,3 +7,6 @@ pci_update_mappings_add(void *d, uint32_t bus, uint32_t slot, uint32_t func, int # hw/pci/pci_host.c pci_cfg_read(const char *dev, unsigned devid, unsigned fnid, unsigned offs, unsigned val) "%s %02u:%u @0x%x -> 0x%x" pci_cfg_write(const char *dev, unsigned devid, unsigned fnid, unsigned offs, unsigned val) "%s %02u:%u @0x%x <- 0x%x" + +# hw/pci/msix.c +msix_write_config(char *name, bool enabled, bool masked) "dev %s enabled %d masked %d" diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c index 231ed9735b..89b6801f67 100644 --- a/hw/ppc/pnv.c +++ b/hw/ppc/pnv.c @@ -378,8 +378,9 @@ static void powernv_populate_ipmi_bt(ISADevice *d, void *fdt, int lpc_off) _FDT(node); g_free(name); - fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)); - fdt_setprop(fdt, node, "compatible", compatible, sizeof(compatible)); + _FDT((fdt_setprop(fdt, node, "reg", io_regs, sizeof(io_regs)))); + _FDT((fdt_setprop(fdt, node, "compatible", compatible, + sizeof(compatible)))); /* Mark it as reserved to avoid Linux trying to claim it */ _FDT((fdt_setprop_string(fdt, node, "status", "reserved"))); diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index ab3aab1279..91b4057933 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -57,6 +57,7 @@ #include "hw/pci/pci.h" #include "hw/scsi/scsi.h" #include "hw/virtio/virtio-scsi.h" +#include "hw/virtio/vhost-scsi-common.h" #include "exec/address-spaces.h" #include "hw/usb.h" @@ -182,25 +183,19 @@ static int spapr_fixup_cpu_smt_dt(void *fdt, int offset, PowerPCCPU *cpu, return ret; } -static int spapr_fixup_cpu_numa_dt(void *fdt, int offset, CPUState *cs) +static int spapr_fixup_cpu_numa_dt(void *fdt, int offset, PowerPCCPU *cpu) { - int ret = 0; - PowerPCCPU *cpu = POWERPC_CPU(cs); int index = ppc_get_vcpu_dt_id(cpu); uint32_t associativity[] = {cpu_to_be32(0x5), cpu_to_be32(0x0), cpu_to_be32(0x0), cpu_to_be32(0x0), - cpu_to_be32(cs->numa_node), + cpu_to_be32(cpu->node_id), cpu_to_be32(index)}; /* Advertise NUMA via ibm,associativity */ - if (nb_numa_nodes > 1) { - ret = fdt_setprop(fdt, offset, "ibm,associativity", associativity, + return fdt_setprop(fdt, offset, "ibm,associativity", associativity, sizeof(associativity)); - } - - return ret; } /* Populate the "ibm,pa-features" property */ @@ -325,9 +320,11 @@ static int spapr_fixup_cpu_dt(void *fdt, sPAPRMachineState *spapr) return ret; } - ret = spapr_fixup_cpu_numa_dt(fdt, offset, cs); - if (ret < 0) { - return ret; + if (nb_numa_nodes > 1) { + ret = spapr_fixup_cpu_numa_dt(fdt, offset, cpu); + if (ret < 0) { + return ret; + } } ret = spapr_fixup_cpu_smt_dt(fdt, offset, cpu, compat_smt); @@ -456,15 +453,13 @@ static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset, uint32_t pft_size_prop[] = {0, cpu_to_be32(spapr->htab_shift)}; int compat_smt = MIN(smp_threads, ppc_compat_max_threads(cpu)); sPAPRDRConnector *drc; - sPAPRDRConnectorClass *drck; int drc_index; uint32_t radix_AP_encodings[PPC_PAGE_SIZES_MAX_SZ]; int i; - drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_CPU, index); + drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, index); if (drc) { - drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); - drc_index = drck->get_index(drc); + drc_index = spapr_drc_index(drc); _FDT((fdt_setprop_cell(fdt, offset, "ibm,my-drc-index", drc_index))); } @@ -542,7 +537,9 @@ static void spapr_populate_cpu_dt(CPUState *cs, void *fdt, int offset, _FDT((fdt_setprop(fdt, offset, "ibm,pft-size", pft_size_prop, sizeof(pft_size_prop)))); - _FDT(spapr_fixup_cpu_numa_dt(fdt, offset, cs)); + if (nb_numa_nodes > 1) { + _FDT(spapr_fixup_cpu_numa_dt(fdt, offset, cpu)); + } _FDT(spapr_fixup_cpu_smt_dt(fdt, offset, cpu, compat_smt)); @@ -654,15 +651,13 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt) if (i >= hotplug_lmb_start) { sPAPRDRConnector *drc; - sPAPRDRConnectorClass *drck; - drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB, i); + drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, i); g_assert(drc); - drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); dynamic_memory[0] = cpu_to_be32(addr >> 32); dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff); - dynamic_memory[2] = cpu_to_be32(drck->get_index(drc)); + dynamic_memory[2] = cpu_to_be32(spapr_drc_index(drc)); dynamic_memory[3] = cpu_to_be32(0); /* reserved */ dynamic_memory[4] = cpu_to_be32(numa_get_node(addr, NULL)); if (memory_region_present(get_system_memory(), addr)) { @@ -1915,7 +1910,7 @@ static void spapr_create_lmb_dr_connectors(sPAPRMachineState *spapr) uint64_t addr; addr = i * lmb_size + spapr->hotplug_memory.base; - drc = spapr_dr_connector_new(OBJECT(spapr), SPAPR_DR_CONNECTOR_TYPE_LMB, + drc = spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_LMB, addr/lmb_size); qemu_register_reset(spapr_drc_reset, drc); } @@ -2012,8 +2007,7 @@ static void spapr_init_cpus(sPAPRMachineState *spapr) if (mc->has_hotpluggable_cpus) { sPAPRDRConnector *drc = - spapr_dr_connector_new(OBJECT(spapr), - SPAPR_DR_CONNECTOR_TYPE_CPU, + spapr_dr_connector_new(OBJECT(spapr), TYPE_SPAPR_DRC_CPU, (core_id / smp_threads) * smt); qemu_register_reset(spapr_drc_reset, drc); @@ -2344,10 +2338,6 @@ static void ppc_spapr_init(MachineState *machine) register_savevm_live(NULL, "spapr/htab", -1, 1, &savevm_htab_handlers, spapr); - /* used by RTAS */ - QTAILQ_INIT(&spapr->ccs_list); - qemu_register_reset(spapr_ccs_reset_hook, spapr); - qemu_register_boot_set(spapr_boot_set, spapr); if (kvm_enabled()) { @@ -2388,6 +2378,7 @@ static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus, ((type *)object_dynamic_cast(OBJECT(obj), (name))) SCSIDevice *d = CAST(SCSIDevice, dev, TYPE_SCSI_DEVICE); sPAPRPHBState *phb = CAST(sPAPRPHBState, dev, TYPE_SPAPR_PCI_HOST_BRIDGE); + VHostSCSICommon *vsc = CAST(VHostSCSICommon, dev, TYPE_VHOST_SCSI_COMMON); if (d) { void *spapr = CAST(void, bus->parent, "spapr-vscsi"); @@ -2444,6 +2435,12 @@ static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus, return g_strdup_printf("pci@%"PRIX64, phb->buid); } + if (vsc) { + /* Same logic as virtio above */ + unsigned id = 0x1000000 | (vsc->target << 16) | vsc->lun; + return g_strdup_printf("disk@%"PRIX64, (uint64_t)id << 32); + } + return NULL; } @@ -2533,8 +2530,8 @@ static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, uint64_t addr = addr_start; for (i = 0; i < nr_lmbs; i++) { - drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB, - addr/SPAPR_MEMORY_BLOCK_SIZE); + drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, + addr / SPAPR_MEMORY_BLOCK_SIZE); g_assert(drc); fdt = create_device_tree(&fdt_size); @@ -2555,12 +2552,12 @@ static void spapr_add_lmbs(DeviceState *dev, uint64_t addr_start, uint64_t size, */ if (dev->hotplugged) { if (dedicated_hp_event_source) { - drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB, - addr_start / SPAPR_MEMORY_BLOCK_SIZE); + drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, + addr_start / SPAPR_MEMORY_BLOCK_SIZE); drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); spapr_hotplug_req_add_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB, nr_lmbs, - drck->get_index(drc)); + spapr_drc_index(drc)); } else { spapr_hotplug_req_add_by_count(SPAPR_DR_CONNECTOR_TYPE_LMB, nr_lmbs); @@ -2673,8 +2670,8 @@ static sPAPRDIMMState *spapr_recover_pending_dimm_state(sPAPRMachineState *ms, addr = addr_start; for (i = 0; i < nr_lmbs; i++) { - drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB, - addr / SPAPR_MEMORY_BLOCK_SIZE); + drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, + addr / SPAPR_MEMORY_BLOCK_SIZE); g_assert(drc); if (drc->indicator_state != SPAPR_DR_INDICATOR_STATE_INACTIVE) { avail_lmbs++; @@ -2757,8 +2754,8 @@ static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev, addr = addr_start; for (i = 0; i < nr_lmbs; i++) { - drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB, - addr / SPAPR_MEMORY_BLOCK_SIZE); + drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, + addr / SPAPR_MEMORY_BLOCK_SIZE); g_assert(drc); drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); @@ -2766,12 +2763,11 @@ static void spapr_memory_unplug_request(HotplugHandler *hotplug_dev, addr += SPAPR_MEMORY_BLOCK_SIZE; } - drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB, - addr_start / SPAPR_MEMORY_BLOCK_SIZE); + drc = spapr_drc_by_id(TYPE_SPAPR_DRC_LMB, + addr_start / SPAPR_MEMORY_BLOCK_SIZE); drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); spapr_hotplug_req_remove_by_count_indexed(SPAPR_DR_CONNECTOR_TYPE_LMB, - nr_lmbs, - drck->get_index(drc)); + nr_lmbs, spapr_drc_index(drc)); out: error_propagate(errp, local_err); } @@ -2839,7 +2835,7 @@ void spapr_core_unplug_request(HotplugHandler *hotplug_dev, DeviceState *dev, return; } - drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_CPU, index * smt); + drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, index * smt); g_assert(drc); drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); @@ -2874,7 +2870,7 @@ static void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev, cc->core_id); return; } - drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_CPU, index * smt); + drc = spapr_drc_by_id(TYPE_SPAPR_DRC_CPU, index * smt); g_assert(drc || !mc->has_hotpluggable_cpus); @@ -2922,11 +2918,9 @@ static void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, MachineClass *mc = MACHINE_GET_CLASS(hotplug_dev); Error *local_err = NULL; CPUCore *cc = CPU_CORE(dev); - sPAPRCPUCore *sc = SPAPR_CPU_CORE(dev); char *base_core_type = spapr_get_cpu_core_type(machine->cpu_model); const char *type = object_get_typename(OBJECT(dev)); CPUArchId *core_slot; - int node_id; int index; if (dev->hotplugged && !mc->has_hotpluggable_cpus) { @@ -2967,20 +2961,7 @@ static void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, goto out; } - node_id = core_slot->props.node_id; - if (!core_slot->props.has_node_id) { - /* by default CPUState::numa_node was 0 if it's not set via CLI - * keep it this way for now but in future we probably should - * refuse to start up with incomplete numa mapping */ - node_id = 0; - } - if (sc->node_id == CPU_UNSET_NUMA_NODE_ID) { - sc->node_id = node_id; - } else if (sc->node_id != node_id) { - error_setg(&local_err, "node-id %d must match numa node specified" - "with -numa option for cpu-index %d", sc->node_id, cc->core_id); - goto out; - } + numa_cpu_pre_plug(core_slot, dev, &local_err); out: g_free(base_core_type); diff --git a/hw/ppc/spapr_cpu_core.c b/hw/ppc/spapr_cpu_core.c index ff7058ecc0..029a14120e 100644 --- a/hw/ppc/spapr_cpu_core.c +++ b/hw/ppc/spapr_cpu_core.c @@ -184,15 +184,17 @@ static void spapr_cpu_core_realize(DeviceState *dev, Error **errp) for (i = 0; i < cc->nr_threads; i++) { char id[32]; CPUState *cs; + PowerPCCPU *cpu; obj = sc->threads + i * size; object_initialize(obj, size, typename); cs = CPU(obj); + cpu = POWERPC_CPU(cs); cs->cpu_index = cc->core_id + i; /* Set NUMA node for the threads belonged to core */ - cs->numa_node = sc->node_id; + cpu->node_id = sc->node_id; snprintf(id, sizeof(id), "thread[%d]", i); object_property_add_child(OBJECT(sc), id, obj, &local_err); diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c index cc2400bcd5..39e7f3080a 100644 --- a/hw/ppc/spapr_drc.c +++ b/hw/ppc/spapr_drc.c @@ -27,29 +27,23 @@ #define DRC_INDEX_TYPE_SHIFT 28 #define DRC_INDEX_ID_MASK ((1ULL << DRC_INDEX_TYPE_SHIFT) - 1) -static sPAPRDRConnectorTypeShift get_type_shift(sPAPRDRConnectorType type) +sPAPRDRConnectorType spapr_drc_type(sPAPRDRConnector *drc) { - uint32_t shift = 0; - - /* make sure this isn't SPAPR_DR_CONNECTOR_TYPE_ANY, or some - * other wonky value. - */ - g_assert(is_power_of_2(type)); + sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); - while (type != (1 << shift)) { - shift++; - } - return shift; + return 1 << drck->typeshift; } -static uint32_t get_index(sPAPRDRConnector *drc) +uint32_t spapr_drc_index(sPAPRDRConnector *drc) { + sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); + /* no set format for a drc index: it only needs to be globally * unique. this is how we encode the DRC type on bare-metal * however, so might as well do that here */ - return (get_type_shift(drc->type) << DRC_INDEX_TYPE_SHIFT) | - (drc->id & DRC_INDEX_ID_MASK); + return (drck->typeshift << DRC_INDEX_TYPE_SHIFT) + | (drc->id & DRC_INDEX_ID_MASK); } static uint32_t set_isolation_state(sPAPRDRConnector *drc, @@ -57,7 +51,17 @@ static uint32_t set_isolation_state(sPAPRDRConnector *drc, { sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); - trace_spapr_drc_set_isolation_state(get_index(drc), state); + trace_spapr_drc_set_isolation_state(spapr_drc_index(drc), state); + + /* if the guest is configuring a device attached to this DRC, we + * should reset the configuration state at this point since it may + * no longer be reliable (guest released device and needs to start + * over, or unplug occurred so the FDT is no longer valid) + */ + if (state == SPAPR_DR_ISOLATION_STATE_ISOLATED) { + g_free(drc->ccs); + drc->ccs = NULL; + } if (state == SPAPR_DR_ISOLATION_STATE_UNISOLATED) { /* cannot unisolate a non-existent resource, and, or resources @@ -79,7 +83,7 @@ static uint32_t set_isolation_state(sPAPRDRConnector *drc, * If the LMB being removed doesn't belong to a DIMM device that is * actually being unplugged, fail the isolation request here. */ - if (drc->type == SPAPR_DR_CONNECTOR_TYPE_LMB) { + if (spapr_drc_type(drc) == SPAPR_DR_CONNECTOR_TYPE_LMB) { if ((state == SPAPR_DR_ISOLATION_STATE_ISOLATED) && !drc->awaiting_release) { return RTAS_OUT_HW_ERROR; @@ -98,11 +102,12 @@ static uint32_t set_isolation_state(sPAPRDRConnector *drc, * PAPR+ 2.7, 13.4 */ if (drc->awaiting_release) { + uint32_t drc_index = spapr_drc_index(drc); if (drc->configured) { - trace_spapr_drc_set_isolation_state_finalizing(get_index(drc)); + trace_spapr_drc_set_isolation_state_finalizing(drc_index); drck->detach(drc, DEVICE(drc->dev), NULL); } else { - trace_spapr_drc_set_isolation_state_deferring(get_index(drc)); + trace_spapr_drc_set_isolation_state_deferring(drc_index); } } drc->configured = false; @@ -114,7 +119,7 @@ static uint32_t set_isolation_state(sPAPRDRConnector *drc, static uint32_t set_indicator_state(sPAPRDRConnector *drc, sPAPRDRIndicatorState state) { - trace_spapr_drc_set_indicator_state(get_index(drc), state); + trace_spapr_drc_set_indicator_state(spapr_drc_index(drc), state); drc->indicator_state = state; return RTAS_OUT_SUCCESS; } @@ -124,7 +129,7 @@ static uint32_t set_allocation_state(sPAPRDRConnector *drc, { sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); - trace_spapr_drc_set_allocation_state(get_index(drc), state); + trace_spapr_drc_set_allocation_state(spapr_drc_index(drc), state); if (state == SPAPR_DR_ALLOCATION_STATE_USABLE) { /* if there's no resource/device associated with the DRC, there's @@ -148,11 +153,12 @@ static uint32_t set_allocation_state(sPAPRDRConnector *drc, } } - if (drc->type != SPAPR_DR_CONNECTOR_TYPE_PCI) { + if (spapr_drc_type(drc) != SPAPR_DR_CONNECTOR_TYPE_PCI) { drc->allocation_state = state; if (drc->awaiting_release && drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_UNUSABLE) { - trace_spapr_drc_set_allocation_state_finalizing(get_index(drc)); + uint32_t drc_index = spapr_drc_index(drc); + trace_spapr_drc_set_allocation_state_finalizing(drc_index); drck->detach(drc, DEVICE(drc->dev), NULL); } else if (drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_USABLE) { drc->awaiting_allocation = false; @@ -161,36 +167,11 @@ static uint32_t set_allocation_state(sPAPRDRConnector *drc, return RTAS_OUT_SUCCESS; } -static uint32_t get_type(sPAPRDRConnector *drc) -{ - return drc->type; -} - static const char *get_name(sPAPRDRConnector *drc) { return drc->name; } -static const void *get_fdt(sPAPRDRConnector *drc, int *fdt_start_offset) -{ - if (fdt_start_offset) { - *fdt_start_offset = drc->fdt_start_offset; - } - return drc->fdt; -} - -static void set_configured(sPAPRDRConnector *drc) -{ - trace_spapr_drc_set_configured(get_index(drc)); - - if (drc->isolation_state != SPAPR_DR_ISOLATION_STATE_UNISOLATED) { - /* guest should be not configuring an isolated device */ - trace_spapr_drc_set_configured_skipping(get_index(drc)); - return; - } - drc->configured = true; -} - /* has the guest been notified of device attachment? */ static void set_signalled(sPAPRDRConnector *drc) { @@ -207,7 +188,7 @@ static void set_signalled(sPAPRDRConnector *drc) static uint32_t entity_sense(sPAPRDRConnector *drc, sPAPRDREntitySense *state) { if (drc->dev) { - if (drc->type != SPAPR_DR_CONNECTOR_TYPE_PCI && + if (spapr_drc_type(drc) != SPAPR_DR_CONNECTOR_TYPE_PCI && drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_UNUSABLE) { /* for logical DR, we return a state of UNUSABLE * iff the allocation state UNUSABLE. @@ -225,7 +206,7 @@ static uint32_t entity_sense(sPAPRDRConnector *drc, sPAPRDREntitySense *state) *state = SPAPR_DR_ENTITY_SENSE_PRESENT; } } else { - if (drc->type == SPAPR_DR_CONNECTOR_TYPE_PCI) { + if (spapr_drc_type(drc) == SPAPR_DR_CONNECTOR_TYPE_PCI) { /* PCI devices, and only PCI devices, use EMPTY * in cases where we'd otherwise use UNUSABLE */ @@ -235,7 +216,7 @@ static uint32_t entity_sense(sPAPRDRConnector *drc, sPAPRDREntitySense *state) } } - trace_spapr_drc_entity_sense(get_index(drc), *state); + trace_spapr_drc_entity_sense(spapr_drc_index(drc), *state); return RTAS_OUT_SUCCESS; } @@ -243,17 +224,7 @@ static void prop_get_index(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(obj); - sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); - uint32_t value = (uint32_t)drck->get_index(drc); - visit_type_uint32(v, name, &value, errp); -} - -static void prop_get_type(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(obj); - sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); - uint32_t value = (uint32_t)drck->get_type(drc); + uint32_t value = spapr_drc_index(drc); visit_type_uint32(v, name, &value, errp); } @@ -264,17 +235,6 @@ static char *prop_get_name(Object *obj, Error **errp) return g_strdup(drck->get_name(drc)); } -static void prop_get_entity_sense(Object *obj, Visitor *v, const char *name, - void *opaque, Error **errp) -{ - sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(obj); - sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); - uint32_t value; - - drck->entity_sense(drc, &value); - visit_type_uint32(v, name, &value, errp); -} - static void prop_get_fdt(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { @@ -354,13 +314,13 @@ static void prop_get_fdt(Object *obj, Visitor *v, const char *name, static void attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt, int fdt_start_offset, bool coldplug, Error **errp) { - trace_spapr_drc_attach(get_index(drc)); + trace_spapr_drc_attach(spapr_drc_index(drc)); if (drc->isolation_state != SPAPR_DR_ISOLATION_STATE_ISOLATED) { error_setg(errp, "an attached device is still awaiting release"); return; } - if (drc->type == SPAPR_DR_CONNECTOR_TYPE_PCI) { + if (spapr_drc_type(drc) == SPAPR_DR_CONNECTOR_TYPE_PCI) { g_assert(drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_USABLE); } g_assert(fdt || coldplug); @@ -372,7 +332,7 @@ static void attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt, * may be accessing the device, we can easily crash the guest, so we * we defer completion of removal in such cases to the reset() hook. */ - if (drc->type == SPAPR_DR_CONNECTOR_TYPE_PCI) { + if (spapr_drc_type(drc) == SPAPR_DR_CONNECTOR_TYPE_PCI) { drc->isolation_state = SPAPR_DR_ISOLATION_STATE_UNISOLATED; } drc->indicator_state = SPAPR_DR_INDICATOR_STATE_ACTIVE; @@ -390,10 +350,10 @@ static void attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt, * 'physical' DR resources such as PCI where each device/resource is * signalled individually. */ - drc->signalled = (drc->type != SPAPR_DR_CONNECTOR_TYPE_PCI) + drc->signalled = (spapr_drc_type(drc) != SPAPR_DR_CONNECTOR_TYPE_PCI) ? true : coldplug; - if (drc->type != SPAPR_DR_CONNECTOR_TYPE_PCI) { + if (spapr_drc_type(drc) != SPAPR_DR_CONNECTOR_TYPE_PCI) { drc->awaiting_allocation = true; } @@ -405,7 +365,7 @@ static void attach(sPAPRDRConnector *drc, DeviceState *d, void *fdt, static void detach(sPAPRDRConnector *drc, DeviceState *d, Error **errp) { - trace_spapr_drc_detach(get_index(drc)); + trace_spapr_drc_detach(spapr_drc_index(drc)); /* if we've signalled device presence to the guest, or if the guest * has gone ahead and configured the device (via manually-executed @@ -428,14 +388,14 @@ static void detach(sPAPRDRConnector *drc, DeviceState *d, Error **errp) } if (drc->isolation_state != SPAPR_DR_ISOLATION_STATE_ISOLATED) { - trace_spapr_drc_awaiting_isolated(get_index(drc)); + trace_spapr_drc_awaiting_isolated(spapr_drc_index(drc)); drc->awaiting_release = true; return; } - if (drc->type != SPAPR_DR_CONNECTOR_TYPE_PCI && + if (spapr_drc_type(drc) != SPAPR_DR_CONNECTOR_TYPE_PCI && drc->allocation_state != SPAPR_DR_ALLOCATION_STATE_UNUSABLE) { - trace_spapr_drc_awaiting_unusable(get_index(drc)); + trace_spapr_drc_awaiting_unusable(spapr_drc_index(drc)); drc->awaiting_release = true; return; } @@ -443,15 +403,15 @@ static void detach(sPAPRDRConnector *drc, DeviceState *d, Error **errp) if (drc->awaiting_allocation) { if (!drc->awaiting_allocation_skippable) { drc->awaiting_release = true; - trace_spapr_drc_awaiting_allocation(get_index(drc)); + trace_spapr_drc_awaiting_allocation(spapr_drc_index(drc)); return; } } drc->indicator_state = SPAPR_DR_INDICATOR_STATE_INACTIVE; - /* Calling release callbacks based on drc->type. */ - switch (drc->type) { + /* Calling release callbacks based on spapr_drc_type(drc). */ + switch (spapr_drc_type(drc)) { case SPAPR_DR_CONNECTOR_TYPE_CPU: spapr_core_release(drc->dev); break; @@ -487,7 +447,11 @@ static void reset(DeviceState *d) sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); sPAPRDREntitySense state; - trace_spapr_drc_reset(drck->get_index(drc)); + trace_spapr_drc_reset(spapr_drc_index(drc)); + + g_free(drc->ccs); + drc->ccs = NULL; + /* immediately upon reset we can safely assume DRCs whose devices * are pending removal can be safely removed, and that they will * subsequently be left in an ISOLATED state. move the DRC to this @@ -507,7 +471,7 @@ static void reset(DeviceState *d) } /* non-PCI devices may be awaiting a transition to UNUSABLE */ - if (drc->type != SPAPR_DR_CONNECTOR_TYPE_PCI && + if (spapr_drc_type(drc) != SPAPR_DR_CONNECTOR_TYPE_PCI && drc->awaiting_release) { drck->set_allocation_state(drc, SPAPR_DR_ALLOCATION_STATE_UNUSABLE); } @@ -536,22 +500,18 @@ static bool spapr_drc_needed(void *opaque) * If there is dev plugged in, we need to migrate the DRC state when * it is different from cold-plugged state */ - switch (drc->type) { + switch (spapr_drc_type(drc)) { case SPAPR_DR_CONNECTOR_TYPE_PCI: - rc = !((drc->isolation_state == SPAPR_DR_ISOLATION_STATE_UNISOLATED) && - (drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_USABLE) && - drc->configured && drc->signalled && !drc->awaiting_release); - break; case SPAPR_DR_CONNECTOR_TYPE_CPU: case SPAPR_DR_CONNECTOR_TYPE_LMB: - rc = !((drc->isolation_state == SPAPR_DR_ISOLATION_STATE_ISOLATED) && - (drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_UNUSABLE) && + rc = !((drc->isolation_state == SPAPR_DR_ISOLATION_STATE_UNISOLATED) && + (drc->allocation_state == SPAPR_DR_ALLOCATION_STATE_USABLE) && drc->configured && drc->signalled && !drc->awaiting_release); break; case SPAPR_DR_CONNECTOR_TYPE_PHB: case SPAPR_DR_CONNECTOR_TYPE_VIO: default: - g_assert(false); + g_assert_not_reached(); } return rc; } @@ -576,13 +536,12 @@ static const VMStateDescription vmstate_spapr_drc = { static void realize(DeviceState *d, Error **errp) { sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(d); - sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); Object *root_container; char link_name[256]; gchar *child_name; Error *err = NULL; - trace_spapr_drc_realize(drck->get_index(drc)); + trace_spapr_drc_realize(spapr_drc_index(drc)); /* NOTE: we do this as part of realize/unrealize due to the fact * that the guest will communicate with the DRC via RTAS calls * referencing the global DRC index. By unlinking the DRC @@ -591,9 +550,9 @@ static void realize(DeviceState *d, Error **errp) * existing in the composition tree */ root_container = container_get(object_get_root(), DRC_CONTAINER_PATH); - snprintf(link_name, sizeof(link_name), "%x", drck->get_index(drc)); + snprintf(link_name, sizeof(link_name), "%x", spapr_drc_index(drc)); child_name = object_get_canonical_path_component(OBJECT(drc)); - trace_spapr_drc_realize_child(drck->get_index(drc), child_name); + trace_spapr_drc_realize_child(spapr_drc_index(drc), child_name); object_property_add_alias(root_container, link_name, drc->owner, child_name, &err); if (err) { @@ -601,22 +560,21 @@ static void realize(DeviceState *d, Error **errp) object_unref(OBJECT(drc)); } g_free(child_name); - vmstate_register(DEVICE(drc), drck->get_index(drc), &vmstate_spapr_drc, + vmstate_register(DEVICE(drc), spapr_drc_index(drc), &vmstate_spapr_drc, drc); - trace_spapr_drc_realize_complete(drck->get_index(drc)); + trace_spapr_drc_realize_complete(spapr_drc_index(drc)); } static void unrealize(DeviceState *d, Error **errp) { sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(d); - sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); Object *root_container; char name[256]; Error *err = NULL; - trace_spapr_drc_unrealize(drck->get_index(drc)); + trace_spapr_drc_unrealize(spapr_drc_index(drc)); root_container = container_get(object_get_root(), DRC_CONTAINER_PATH); - snprintf(name, sizeof(name), "%x", drck->get_index(drc)); + snprintf(name, sizeof(name), "%x", spapr_drc_index(drc)); object_property_del(root_container, name, &err); if (err) { error_report_err(err); @@ -624,20 +582,16 @@ static void unrealize(DeviceState *d, Error **errp) } } -sPAPRDRConnector *spapr_dr_connector_new(Object *owner, - sPAPRDRConnectorType type, +sPAPRDRConnector *spapr_dr_connector_new(Object *owner, const char *type, uint32_t id) { - sPAPRDRConnector *drc = - SPAPR_DR_CONNECTOR(object_new(TYPE_SPAPR_DR_CONNECTOR)); + sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(object_new(type)); char *prop_name; - g_assert(type); - - drc->type = type; drc->id = id; drc->owner = owner; - prop_name = g_strdup_printf("dr-connector[%"PRIu32"]", get_index(drc)); + prop_name = g_strdup_printf("dr-connector[%"PRIu32"]", + spapr_drc_index(drc)); object_property_add_child(owner, prop_name, OBJECT(drc), NULL); object_property_set_bool(OBJECT(drc), true, "realized", NULL); g_free(prop_name); @@ -663,7 +617,7 @@ sPAPRDRConnector *spapr_dr_connector_new(Object *owner, * DRC names as documented by PAPR+ v2.7, 13.5.2.4 * location codes as documented by PAPR+ v2.7, 12.3.1.5 */ - switch (drc->type) { + switch (spapr_drc_type(drc)) { case SPAPR_DR_CONNECTOR_TYPE_CPU: drc->name = g_strdup_printf("CPU %d", id); break; @@ -682,7 +636,7 @@ sPAPRDRConnector *spapr_dr_connector_new(Object *owner, } /* PCI slot always start in a USABLE state, and stay there */ - if (drc->type == SPAPR_DR_CONNECTOR_TYPE_PCI) { + if (spapr_drc_type(drc) == SPAPR_DR_CONNECTOR_TYPE_PCI) { drc->allocation_state = SPAPR_DR_ALLOCATION_STATE_USABLE; } @@ -693,20 +647,10 @@ static void spapr_dr_connector_instance_init(Object *obj) { sPAPRDRConnector *drc = SPAPR_DR_CONNECTOR(obj); - object_property_add_uint32_ptr(obj, "isolation-state", - &drc->isolation_state, NULL); - object_property_add_uint32_ptr(obj, "indicator-state", - &drc->indicator_state, NULL); - object_property_add_uint32_ptr(obj, "allocation-state", - &drc->allocation_state, NULL); object_property_add_uint32_ptr(obj, "id", &drc->id, NULL); object_property_add(obj, "index", "uint32", prop_get_index, NULL, NULL, NULL, NULL); - object_property_add(obj, "connector_type", "uint32", prop_get_type, - NULL, NULL, NULL, NULL); object_property_add_str(obj, "name", prop_get_name, NULL, NULL); - object_property_add(obj, "entity-sense", "uint32", prop_get_entity_sense, - NULL, NULL, NULL, NULL); object_property_add(obj, "fdt", "struct", prop_get_fdt, NULL, NULL, NULL, NULL); } @@ -722,11 +666,7 @@ static void spapr_dr_connector_class_init(ObjectClass *k, void *data) drck->set_isolation_state = set_isolation_state; drck->set_indicator_state = set_indicator_state; drck->set_allocation_state = set_allocation_state; - drck->get_index = get_index; - drck->get_type = get_type; drck->get_name = get_name; - drck->get_fdt = get_fdt; - drck->set_configured = set_configured; drck->entity_sense = entity_sense; drck->attach = attach; drck->detach = detach; @@ -738,6 +678,30 @@ static void spapr_dr_connector_class_init(ObjectClass *k, void *data) dk->user_creatable = false; } +static void spapr_drc_cpu_class_init(ObjectClass *k, void *data) +{ + sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k); + + drck->typeshift = SPAPR_DR_CONNECTOR_TYPE_SHIFT_CPU; + drck->typename = "CPU"; +} + +static void spapr_drc_pci_class_init(ObjectClass *k, void *data) +{ + sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k); + + drck->typeshift = SPAPR_DR_CONNECTOR_TYPE_SHIFT_PCI; + drck->typename = "28"; +} + +static void spapr_drc_lmb_class_init(ObjectClass *k, void *data) +{ + sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_CLASS(k); + + drck->typeshift = SPAPR_DR_CONNECTOR_TYPE_SHIFT_LMB; + drck->typename = "MEM"; +} + static const TypeInfo spapr_dr_connector_info = { .name = TYPE_SPAPR_DR_CONNECTOR, .parent = TYPE_DEVICE, @@ -745,18 +709,47 @@ static const TypeInfo spapr_dr_connector_info = { .instance_init = spapr_dr_connector_instance_init, .class_size = sizeof(sPAPRDRConnectorClass), .class_init = spapr_dr_connector_class_init, + .abstract = true, }; -static void spapr_drc_register_types(void) -{ - type_register_static(&spapr_dr_connector_info); -} +static const TypeInfo spapr_drc_physical_info = { + .name = TYPE_SPAPR_DRC_PHYSICAL, + .parent = TYPE_SPAPR_DR_CONNECTOR, + .instance_size = sizeof(sPAPRDRConnector), + .abstract = true, +}; -type_init(spapr_drc_register_types) +static const TypeInfo spapr_drc_logical_info = { + .name = TYPE_SPAPR_DRC_LOGICAL, + .parent = TYPE_SPAPR_DR_CONNECTOR, + .instance_size = sizeof(sPAPRDRConnector), + .abstract = true, +}; + +static const TypeInfo spapr_drc_cpu_info = { + .name = TYPE_SPAPR_DRC_CPU, + .parent = TYPE_SPAPR_DRC_LOGICAL, + .instance_size = sizeof(sPAPRDRConnector), + .class_init = spapr_drc_cpu_class_init, +}; + +static const TypeInfo spapr_drc_pci_info = { + .name = TYPE_SPAPR_DRC_PCI, + .parent = TYPE_SPAPR_DRC_PHYSICAL, + .instance_size = sizeof(sPAPRDRConnector), + .class_init = spapr_drc_pci_class_init, +}; + +static const TypeInfo spapr_drc_lmb_info = { + .name = TYPE_SPAPR_DRC_LMB, + .parent = TYPE_SPAPR_DRC_LOGICAL, + .instance_size = sizeof(sPAPRDRConnector), + .class_init = spapr_drc_lmb_class_init, +}; /* helper functions for external users */ -sPAPRDRConnector *spapr_dr_connector_by_index(uint32_t index) +sPAPRDRConnector *spapr_drc_by_index(uint32_t index) { Object *obj; char name[256]; @@ -767,37 +760,13 @@ sPAPRDRConnector *spapr_dr_connector_by_index(uint32_t index) return !obj ? NULL : SPAPR_DR_CONNECTOR(obj); } -sPAPRDRConnector *spapr_dr_connector_by_id(sPAPRDRConnectorType type, - uint32_t id) +sPAPRDRConnector *spapr_drc_by_id(const char *type, uint32_t id) { - return spapr_dr_connector_by_index( - (get_type_shift(type) << DRC_INDEX_TYPE_SHIFT) | - (id & DRC_INDEX_ID_MASK)); -} - -/* generate a string the describes the DRC to encode into the - * device tree. - * - * as documented by PAPR+ v2.7, 13.5.2.6 and C.6.1 - */ -static const char *spapr_drc_get_type_str(sPAPRDRConnectorType type) -{ - switch (type) { - case SPAPR_DR_CONNECTOR_TYPE_CPU: - return "CPU"; - case SPAPR_DR_CONNECTOR_TYPE_PHB: - return "PHB"; - case SPAPR_DR_CONNECTOR_TYPE_VIO: - return "SLOT"; - case SPAPR_DR_CONNECTOR_TYPE_PCI: - return "28"; - case SPAPR_DR_CONNECTOR_TYPE_LMB: - return "MEM"; - default: - g_assert(false); - } + sPAPRDRConnectorClass *drck + = SPAPR_DR_CONNECTOR_CLASS(object_class_by_name(type)); - return NULL; + return spapr_drc_by_index(drck->typeshift << DRC_INDEX_TYPE_SHIFT + | (id & DRC_INDEX_ID_MASK)); } /** @@ -862,14 +831,14 @@ int spapr_drc_populate_dt(void *fdt, int fdt_offset, Object *owner, continue; } - if ((drc->type & drc_type_mask) == 0) { + if ((spapr_drc_type(drc) & drc_type_mask) == 0) { continue; } drc_count++; /* ibm,drc-indexes */ - drc_index = cpu_to_be32(drck->get_index(drc)); + drc_index = cpu_to_be32(spapr_drc_index(drc)); g_array_append_val(drc_indexes, drc_index); /* ibm,drc-power-domains */ @@ -881,8 +850,7 @@ int spapr_drc_populate_dt(void *fdt, int fdt_offset, Object *owner, drc_names = g_string_insert_len(drc_names, -1, "\0", 1); /* ibm,drc-types */ - drc_types = g_string_append(drc_types, - spapr_drc_get_type_str(drc->type)); + drc_types = g_string_append(drc_types, drck->typename); drc_types = g_string_insert_len(drc_types, -1, "\0", 1); } @@ -932,3 +900,276 @@ out: return ret; } + +/* + * RTAS calls + */ + +static bool sensor_type_is_dr(uint32_t sensor_type) +{ + switch (sensor_type) { + case RTAS_SENSOR_TYPE_ISOLATION_STATE: + case RTAS_SENSOR_TYPE_DR: + case RTAS_SENSOR_TYPE_ALLOCATION_STATE: + return true; + } + + return false; +} + +static void rtas_set_indicator(PowerPCCPU *cpu, sPAPRMachineState *spapr, + uint32_t token, uint32_t nargs, + target_ulong args, uint32_t nret, + target_ulong rets) +{ + uint32_t sensor_type; + uint32_t sensor_index; + uint32_t sensor_state; + uint32_t ret = RTAS_OUT_SUCCESS; + sPAPRDRConnector *drc; + sPAPRDRConnectorClass *drck; + + if (nargs != 3 || nret != 1) { + ret = RTAS_OUT_PARAM_ERROR; + goto out; + } + + sensor_type = rtas_ld(args, 0); + sensor_index = rtas_ld(args, 1); + sensor_state = rtas_ld(args, 2); + + if (!sensor_type_is_dr(sensor_type)) { + goto out_unimplemented; + } + + /* if this is a DR sensor we can assume sensor_index == drc_index */ + drc = spapr_drc_by_index(sensor_index); + if (!drc) { + trace_spapr_rtas_set_indicator_invalid(sensor_index); + ret = RTAS_OUT_PARAM_ERROR; + goto out; + } + drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); + + switch (sensor_type) { + case RTAS_SENSOR_TYPE_ISOLATION_STATE: + ret = drck->set_isolation_state(drc, sensor_state); + break; + case RTAS_SENSOR_TYPE_DR: + ret = drck->set_indicator_state(drc, sensor_state); + break; + case RTAS_SENSOR_TYPE_ALLOCATION_STATE: + ret = drck->set_allocation_state(drc, sensor_state); + break; + default: + goto out_unimplemented; + } + +out: + rtas_st(rets, 0, ret); + return; + +out_unimplemented: + /* currently only DR-related sensors are implemented */ + trace_spapr_rtas_set_indicator_not_supported(sensor_index, sensor_type); + rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED); +} + +static void rtas_get_sensor_state(PowerPCCPU *cpu, sPAPRMachineState *spapr, + uint32_t token, uint32_t nargs, + target_ulong args, uint32_t nret, + target_ulong rets) +{ + uint32_t sensor_type; + uint32_t sensor_index; + uint32_t sensor_state = 0; + sPAPRDRConnector *drc; + sPAPRDRConnectorClass *drck; + uint32_t ret = RTAS_OUT_SUCCESS; + + if (nargs != 2 || nret != 2) { + ret = RTAS_OUT_PARAM_ERROR; + goto out; + } + + sensor_type = rtas_ld(args, 0); + sensor_index = rtas_ld(args, 1); + + if (sensor_type != RTAS_SENSOR_TYPE_ENTITY_SENSE) { + /* currently only DR-related sensors are implemented */ + trace_spapr_rtas_get_sensor_state_not_supported(sensor_index, + sensor_type); + ret = RTAS_OUT_NOT_SUPPORTED; + goto out; + } + + drc = spapr_drc_by_index(sensor_index); + if (!drc) { + trace_spapr_rtas_get_sensor_state_invalid(sensor_index); + ret = RTAS_OUT_PARAM_ERROR; + goto out; + } + drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); + ret = drck->entity_sense(drc, &sensor_state); + +out: + rtas_st(rets, 0, ret); + rtas_st(rets, 1, sensor_state); +} + +/* configure-connector work area offsets, int32_t units for field + * indexes, bytes for field offset/len values. + * + * as documented by PAPR+ v2.7, 13.5.3.5 + */ +#define CC_IDX_NODE_NAME_OFFSET 2 +#define CC_IDX_PROP_NAME_OFFSET 2 +#define CC_IDX_PROP_LEN 3 +#define CC_IDX_PROP_DATA_OFFSET 4 +#define CC_VAL_DATA_OFFSET ((CC_IDX_PROP_DATA_OFFSET + 1) * 4) +#define CC_WA_LEN 4096 + +static void configure_connector_st(target_ulong addr, target_ulong offset, + const void *buf, size_t len) +{ + cpu_physical_memory_write(ppc64_phys_to_real(addr + offset), + buf, MIN(len, CC_WA_LEN - offset)); +} + +static void rtas_ibm_configure_connector(PowerPCCPU *cpu, + sPAPRMachineState *spapr, + uint32_t token, uint32_t nargs, + target_ulong args, uint32_t nret, + target_ulong rets) +{ + uint64_t wa_addr; + uint64_t wa_offset; + uint32_t drc_index; + sPAPRDRConnector *drc; + sPAPRConfigureConnectorState *ccs; + sPAPRDRCCResponse resp = SPAPR_DR_CC_RESPONSE_CONTINUE; + int rc; + + if (nargs != 2 || nret != 1) { + rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); + return; + } + + wa_addr = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 0); + + drc_index = rtas_ld(wa_addr, 0); + drc = spapr_drc_by_index(drc_index); + if (!drc) { + trace_spapr_rtas_ibm_configure_connector_invalid(drc_index); + rc = RTAS_OUT_PARAM_ERROR; + goto out; + } + + if (!drc->fdt) { + trace_spapr_rtas_ibm_configure_connector_missing_fdt(drc_index); + rc = SPAPR_DR_CC_RESPONSE_NOT_CONFIGURABLE; + goto out; + } + + ccs = drc->ccs; + if (!ccs) { + ccs = g_new0(sPAPRConfigureConnectorState, 1); + ccs->fdt_offset = drc->fdt_start_offset; + drc->ccs = ccs; + } + + do { + uint32_t tag; + const char *name; + const struct fdt_property *prop; + int fdt_offset_next, prop_len; + + tag = fdt_next_tag(drc->fdt, ccs->fdt_offset, &fdt_offset_next); + + switch (tag) { + case FDT_BEGIN_NODE: + ccs->fdt_depth++; + name = fdt_get_name(drc->fdt, ccs->fdt_offset, NULL); + + /* provide the name of the next OF node */ + wa_offset = CC_VAL_DATA_OFFSET; + rtas_st(wa_addr, CC_IDX_NODE_NAME_OFFSET, wa_offset); + configure_connector_st(wa_addr, wa_offset, name, strlen(name) + 1); + resp = SPAPR_DR_CC_RESPONSE_NEXT_CHILD; + break; + case FDT_END_NODE: + ccs->fdt_depth--; + if (ccs->fdt_depth == 0) { + sPAPRDRIsolationState state = drc->isolation_state; + uint32_t drc_index = spapr_drc_index(drc); + /* done sending the device tree, don't need to track + * the state anymore + */ + trace_spapr_drc_set_configured(drc_index); + if (state == SPAPR_DR_ISOLATION_STATE_UNISOLATED) { + drc->configured = true; + } else { + /* guest should be not configuring an isolated device */ + trace_spapr_drc_set_configured_skipping(drc_index); + } + g_free(ccs); + drc->ccs = NULL; + ccs = NULL; + resp = SPAPR_DR_CC_RESPONSE_SUCCESS; + } else { + resp = SPAPR_DR_CC_RESPONSE_PREV_PARENT; + } + break; + case FDT_PROP: + prop = fdt_get_property_by_offset(drc->fdt, ccs->fdt_offset, + &prop_len); + name = fdt_string(drc->fdt, fdt32_to_cpu(prop->nameoff)); + + /* provide the name of the next OF property */ + wa_offset = CC_VAL_DATA_OFFSET; + rtas_st(wa_addr, CC_IDX_PROP_NAME_OFFSET, wa_offset); + configure_connector_st(wa_addr, wa_offset, name, strlen(name) + 1); + + /* provide the length and value of the OF property. data gets + * placed immediately after NULL terminator of the OF property's + * name string + */ + wa_offset += strlen(name) + 1, + rtas_st(wa_addr, CC_IDX_PROP_LEN, prop_len); + rtas_st(wa_addr, CC_IDX_PROP_DATA_OFFSET, wa_offset); + configure_connector_st(wa_addr, wa_offset, prop->data, prop_len); + resp = SPAPR_DR_CC_RESPONSE_NEXT_PROPERTY; + break; + case FDT_END: + resp = SPAPR_DR_CC_RESPONSE_ERROR; + default: + /* keep seeking for an actionable tag */ + break; + } + if (ccs) { + ccs->fdt_offset = fdt_offset_next; + } + } while (resp == SPAPR_DR_CC_RESPONSE_CONTINUE); + + rc = resp; +out: + rtas_st(rets, 0, rc); +} + +static void spapr_drc_register_types(void) +{ + type_register_static(&spapr_dr_connector_info); + type_register_static(&spapr_drc_physical_info); + type_register_static(&spapr_drc_logical_info); + type_register_static(&spapr_drc_cpu_info); + type_register_static(&spapr_drc_pci_info); + type_register_static(&spapr_drc_lmb_info); + + spapr_rtas_register(RTAS_SET_INDICATOR, "set-indicator", + rtas_set_indicator); + spapr_rtas_register(RTAS_GET_SENSOR_STATE, "get-sensor-state", + rtas_get_sensor_state); + spapr_rtas_register(RTAS_IBM_CONFIGURE_CONNECTOR, "ibm,configure-connector", + rtas_ibm_configure_connector); +} +type_init(spapr_drc_register_types) diff --git a/hw/ppc/spapr_events.c b/hw/ppc/spapr_events.c index 73e2a1884f..171aedc7e0 100644 --- a/hw/ppc/spapr_events.c +++ b/hw/ppc/spapr_events.c @@ -28,7 +28,6 @@ #include "qapi/error.h" #include "cpu.h" #include "sysemu/sysemu.h" -#include "sysemu/char.h" #include "hw/qdev.h" #include "sysemu/device_tree.h" @@ -478,7 +477,7 @@ static void spapr_powerdown_req(Notifier *n, void *opaque) static void spapr_hotplug_set_signalled(uint32_t drc_index) { - sPAPRDRConnector *drc = spapr_dr_connector_by_index(drc_index); + sPAPRDRConnector *drc = spapr_drc_by_index(drc_index); sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); drck->set_signalled(drc); } @@ -571,22 +570,20 @@ static void spapr_hotplug_req_event(uint8_t hp_id, uint8_t hp_action, void spapr_hotplug_req_add_by_index(sPAPRDRConnector *drc) { - sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); - sPAPRDRConnectorType drc_type = drck->get_type(drc); + sPAPRDRConnectorType drc_type = spapr_drc_type(drc); union drc_identifier drc_id; - drc_id.index = drck->get_index(drc); + drc_id.index = spapr_drc_index(drc); spapr_hotplug_req_event(RTAS_LOG_V6_HP_ID_DRC_INDEX, RTAS_LOG_V6_HP_ACTION_ADD, drc_type, &drc_id); } void spapr_hotplug_req_remove_by_index(sPAPRDRConnector *drc) { - sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); - sPAPRDRConnectorType drc_type = drck->get_type(drc); + sPAPRDRConnectorType drc_type = spapr_drc_type(drc); union drc_identifier drc_id; - drc_id.index = drck->get_index(drc); + drc_id.index = spapr_drc_index(drc); spapr_hotplug_req_event(RTAS_LOG_V6_HP_ID_DRC_INDEX, RTAS_LOG_V6_HP_ACTION_REMOVE, drc_type, &drc_id); } diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c index aae5a62a61..aa1ffea9e5 100644 --- a/hw/ppc/spapr_hcall.c +++ b/hw/ppc/spapr_hcall.c @@ -992,9 +992,10 @@ static target_ulong h_register_process_table(PowerPCCPU *cpu, /* Update the UPRT and GTSE bits in the LPCR for all cpus */ CPU_FOREACH(cs) { - set_spr(cs, SPR_LPCR, LPCR_UPRT | LPCR_GTSE, + set_spr(cs, SPR_LPCR, ((flags & (FLAG_RADIX | FLAG_HASH_PROC_TBL)) ? LPCR_UPRT : 0) | - ((flags & FLAG_GTSE) ? LPCR_GTSE : 0)); + ((flags & FLAG_GTSE) ? LPCR_GTSE : 0), + LPCR_UPRT | LPCR_GTSE); } if (kvm_enabled()) { diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index e4daf8d5f1..0c181bbca5 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -1400,10 +1400,8 @@ static sPAPRDRConnector *spapr_phb_get_pci_func_drc(sPAPRPHBState *phb, uint32_t busnr, int32_t devfn) { - return spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_PCI, - (phb->index << 16) | - (busnr << 8) | - devfn); + return spapr_drc_by_id(TYPE_SPAPR_DRC_PCI, + (phb->index << 16) | (busnr << 8) | devfn); } static sPAPRDRConnector *spapr_phb_get_pci_drc(sPAPRPHBState *phb, @@ -1417,14 +1415,12 @@ static uint32_t spapr_phb_get_pci_drc_index(sPAPRPHBState *phb, PCIDevice *pdev) { sPAPRDRConnector *drc = spapr_phb_get_pci_drc(phb, pdev); - sPAPRDRConnectorClass *drck; if (!drc) { return 0; } - drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); - return drck->get_index(drc); + return spapr_drc_index(drc); } static void spapr_phb_hot_plug_child(HotplugHandler *plug_handler, @@ -1763,8 +1759,7 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp) /* allocate connectors for child PCI devices */ if (sphb->dr_enabled) { for (i = 0; i < PCI_SLOT_MAX * 8; i++) { - spapr_dr_connector_new(OBJECT(phb), - SPAPR_DR_CONNECTOR_TYPE_PCI, + spapr_dr_connector_new(OBJECT(phb), TYPE_SPAPR_DRC_PCI, (sphb->index << 16) | i); } } diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c index 128d993d04..707c4d4936 100644 --- a/hw/ppc/spapr_rtas.c +++ b/hw/ppc/spapr_rtas.c @@ -29,7 +29,6 @@ #include "qemu/log.h" #include "qemu/error-report.h" #include "sysemu/sysemu.h" -#include "sysemu/char.h" #include "hw/qdev.h" #include "sysemu/device_tree.h" #include "sysemu/cpus.h" @@ -48,44 +47,6 @@ #include "trace.h" #include "hw/ppc/fdt.h" -static sPAPRConfigureConnectorState *spapr_ccs_find(sPAPRMachineState *spapr, - uint32_t drc_index) -{ - sPAPRConfigureConnectorState *ccs = NULL; - - QTAILQ_FOREACH(ccs, &spapr->ccs_list, next) { - if (ccs->drc_index == drc_index) { - break; - } - } - - return ccs; -} - -static void spapr_ccs_add(sPAPRMachineState *spapr, - sPAPRConfigureConnectorState *ccs) -{ - g_assert(!spapr_ccs_find(spapr, ccs->drc_index)); - QTAILQ_INSERT_HEAD(&spapr->ccs_list, ccs, next); -} - -static void spapr_ccs_remove(sPAPRMachineState *spapr, - sPAPRConfigureConnectorState *ccs) -{ - QTAILQ_REMOVE(&spapr->ccs_list, ccs, next); - g_free(ccs); -} - -void spapr_ccs_reset_hook(void *opaque) -{ - sPAPRMachineState *spapr = opaque; - sPAPRConfigureConnectorState *ccs, *ccs_tmp; - - QTAILQ_FOREACH_SAFE(ccs, &spapr->ccs_list, next, ccs_tmp) { - spapr_ccs_remove(spapr, ccs); - } -} - static void rtas_display_character(PowerPCCPU *cpu, sPAPRMachineState *spapr, uint32_t token, uint32_t nargs, target_ulong args, @@ -390,266 +351,6 @@ static void rtas_get_power_level(PowerPCCPU *cpu, sPAPRMachineState *spapr, rtas_st(rets, 1, 100); } -static bool sensor_type_is_dr(uint32_t sensor_type) -{ - switch (sensor_type) { - case RTAS_SENSOR_TYPE_ISOLATION_STATE: - case RTAS_SENSOR_TYPE_DR: - case RTAS_SENSOR_TYPE_ALLOCATION_STATE: - return true; - } - - return false; -} - -static void rtas_set_indicator(PowerPCCPU *cpu, sPAPRMachineState *spapr, - uint32_t token, uint32_t nargs, - target_ulong args, uint32_t nret, - target_ulong rets) -{ - uint32_t sensor_type; - uint32_t sensor_index; - uint32_t sensor_state; - uint32_t ret = RTAS_OUT_SUCCESS; - sPAPRDRConnector *drc; - sPAPRDRConnectorClass *drck; - - if (nargs != 3 || nret != 1) { - ret = RTAS_OUT_PARAM_ERROR; - goto out; - } - - sensor_type = rtas_ld(args, 0); - sensor_index = rtas_ld(args, 1); - sensor_state = rtas_ld(args, 2); - - if (!sensor_type_is_dr(sensor_type)) { - goto out_unimplemented; - } - - /* if this is a DR sensor we can assume sensor_index == drc_index */ - drc = spapr_dr_connector_by_index(sensor_index); - if (!drc) { - trace_spapr_rtas_set_indicator_invalid(sensor_index); - ret = RTAS_OUT_PARAM_ERROR; - goto out; - } - drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); - - switch (sensor_type) { - case RTAS_SENSOR_TYPE_ISOLATION_STATE: - /* if the guest is configuring a device attached to this - * DRC, we should reset the configuration state at this - * point since it may no longer be reliable (guest released - * device and needs to start over, or unplug occurred so - * the FDT is no longer valid) - */ - if (sensor_state == SPAPR_DR_ISOLATION_STATE_ISOLATED) { - sPAPRConfigureConnectorState *ccs = spapr_ccs_find(spapr, - sensor_index); - if (ccs) { - spapr_ccs_remove(spapr, ccs); - } - } - ret = drck->set_isolation_state(drc, sensor_state); - break; - case RTAS_SENSOR_TYPE_DR: - ret = drck->set_indicator_state(drc, sensor_state); - break; - case RTAS_SENSOR_TYPE_ALLOCATION_STATE: - ret = drck->set_allocation_state(drc, sensor_state); - break; - default: - goto out_unimplemented; - } - -out: - rtas_st(rets, 0, ret); - return; - -out_unimplemented: - /* currently only DR-related sensors are implemented */ - trace_spapr_rtas_set_indicator_not_supported(sensor_index, sensor_type); - rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED); -} - -static void rtas_get_sensor_state(PowerPCCPU *cpu, sPAPRMachineState *spapr, - uint32_t token, uint32_t nargs, - target_ulong args, uint32_t nret, - target_ulong rets) -{ - uint32_t sensor_type; - uint32_t sensor_index; - uint32_t sensor_state = 0; - sPAPRDRConnector *drc; - sPAPRDRConnectorClass *drck; - uint32_t ret = RTAS_OUT_SUCCESS; - - if (nargs != 2 || nret != 2) { - ret = RTAS_OUT_PARAM_ERROR; - goto out; - } - - sensor_type = rtas_ld(args, 0); - sensor_index = rtas_ld(args, 1); - - if (sensor_type != RTAS_SENSOR_TYPE_ENTITY_SENSE) { - /* currently only DR-related sensors are implemented */ - trace_spapr_rtas_get_sensor_state_not_supported(sensor_index, - sensor_type); - ret = RTAS_OUT_NOT_SUPPORTED; - goto out; - } - - drc = spapr_dr_connector_by_index(sensor_index); - if (!drc) { - trace_spapr_rtas_get_sensor_state_invalid(sensor_index); - ret = RTAS_OUT_PARAM_ERROR; - goto out; - } - drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); - ret = drck->entity_sense(drc, &sensor_state); - -out: - rtas_st(rets, 0, ret); - rtas_st(rets, 1, sensor_state); -} - -/* configure-connector work area offsets, int32_t units for field - * indexes, bytes for field offset/len values. - * - * as documented by PAPR+ v2.7, 13.5.3.5 - */ -#define CC_IDX_NODE_NAME_OFFSET 2 -#define CC_IDX_PROP_NAME_OFFSET 2 -#define CC_IDX_PROP_LEN 3 -#define CC_IDX_PROP_DATA_OFFSET 4 -#define CC_VAL_DATA_OFFSET ((CC_IDX_PROP_DATA_OFFSET + 1) * 4) -#define CC_WA_LEN 4096 - -static void configure_connector_st(target_ulong addr, target_ulong offset, - const void *buf, size_t len) -{ - cpu_physical_memory_write(ppc64_phys_to_real(addr + offset), - buf, MIN(len, CC_WA_LEN - offset)); -} - -static void rtas_ibm_configure_connector(PowerPCCPU *cpu, - sPAPRMachineState *spapr, - uint32_t token, uint32_t nargs, - target_ulong args, uint32_t nret, - target_ulong rets) -{ - uint64_t wa_addr; - uint64_t wa_offset; - uint32_t drc_index; - sPAPRDRConnector *drc; - sPAPRDRConnectorClass *drck; - sPAPRConfigureConnectorState *ccs; - sPAPRDRCCResponse resp = SPAPR_DR_CC_RESPONSE_CONTINUE; - int rc; - const void *fdt; - - if (nargs != 2 || nret != 1) { - rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR); - return; - } - - wa_addr = ((uint64_t)rtas_ld(args, 1) << 32) | rtas_ld(args, 0); - - drc_index = rtas_ld(wa_addr, 0); - drc = spapr_dr_connector_by_index(drc_index); - if (!drc) { - trace_spapr_rtas_ibm_configure_connector_invalid(drc_index); - rc = RTAS_OUT_PARAM_ERROR; - goto out; - } - - drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc); - fdt = drck->get_fdt(drc, NULL); - if (!fdt) { - trace_spapr_rtas_ibm_configure_connector_missing_fdt(drc_index); - rc = SPAPR_DR_CC_RESPONSE_NOT_CONFIGURABLE; - goto out; - } - - ccs = spapr_ccs_find(spapr, drc_index); - if (!ccs) { - ccs = g_new0(sPAPRConfigureConnectorState, 1); - (void)drck->get_fdt(drc, &ccs->fdt_offset); - ccs->drc_index = drc_index; - spapr_ccs_add(spapr, ccs); - } - - do { - uint32_t tag; - const char *name; - const struct fdt_property *prop; - int fdt_offset_next, prop_len; - - tag = fdt_next_tag(fdt, ccs->fdt_offset, &fdt_offset_next); - - switch (tag) { - case FDT_BEGIN_NODE: - ccs->fdt_depth++; - name = fdt_get_name(fdt, ccs->fdt_offset, NULL); - - /* provide the name of the next OF node */ - wa_offset = CC_VAL_DATA_OFFSET; - rtas_st(wa_addr, CC_IDX_NODE_NAME_OFFSET, wa_offset); - configure_connector_st(wa_addr, wa_offset, name, strlen(name) + 1); - resp = SPAPR_DR_CC_RESPONSE_NEXT_CHILD; - break; - case FDT_END_NODE: - ccs->fdt_depth--; - if (ccs->fdt_depth == 0) { - /* done sending the device tree, don't need to track - * the state anymore - */ - drck->set_configured(drc); - spapr_ccs_remove(spapr, ccs); - ccs = NULL; - resp = SPAPR_DR_CC_RESPONSE_SUCCESS; - } else { - resp = SPAPR_DR_CC_RESPONSE_PREV_PARENT; - } - break; - case FDT_PROP: - prop = fdt_get_property_by_offset(fdt, ccs->fdt_offset, - &prop_len); - name = fdt_string(fdt, fdt32_to_cpu(prop->nameoff)); - - /* provide the name of the next OF property */ - wa_offset = CC_VAL_DATA_OFFSET; - rtas_st(wa_addr, CC_IDX_PROP_NAME_OFFSET, wa_offset); - configure_connector_st(wa_addr, wa_offset, name, strlen(name) + 1); - - /* provide the length and value of the OF property. data gets - * placed immediately after NULL terminator of the OF property's - * name string - */ - wa_offset += strlen(name) + 1, - rtas_st(wa_addr, CC_IDX_PROP_LEN, prop_len); - rtas_st(wa_addr, CC_IDX_PROP_DATA_OFFSET, wa_offset); - configure_connector_st(wa_addr, wa_offset, prop->data, prop_len); - resp = SPAPR_DR_CC_RESPONSE_NEXT_PROPERTY; - break; - case FDT_END: - resp = SPAPR_DR_CC_RESPONSE_ERROR; - default: - /* keep seeking for an actionable tag */ - break; - } - if (ccs) { - ccs->fdt_offset = fdt_offset_next; - } - } while (resp == SPAPR_DR_CC_RESPONSE_CONTINUE); - - rc = resp; -out: - rtas_st(rets, 0, rc); -} - static struct rtas_call { const char *name; spapr_rtas_fn fn; @@ -791,12 +492,6 @@ static void core_rtas_register_types(void) rtas_set_power_level); spapr_rtas_register(RTAS_GET_POWER_LEVEL, "get-power-level", rtas_get_power_level); - spapr_rtas_register(RTAS_SET_INDICATOR, "set-indicator", - rtas_set_indicator); - spapr_rtas_register(RTAS_GET_SENSOR_STATE, "get-sensor-state", - rtas_get_sensor_state); - spapr_rtas_register(RTAS_IBM_CONFIGURE_CONNECTOR, "ibm,configure-connector", - rtas_ibm_configure_connector); } type_init(core_rtas_register_types) diff --git a/hw/s390x/s390-skeys.c b/hw/s390x/s390-skeys.c index e2d4e1af79..35e7f6316f 100644 --- a/hw/s390x/s390-skeys.c +++ b/hw/s390x/s390-skeys.c @@ -12,7 +12,6 @@ #include "qemu/osdep.h" #include "hw/boards.h" #include "qmp-commands.h" -#include "migration/qemu-file.h" #include "hw/s390x/storage-keys.h" #include "qemu/error-report.h" #include "sysemu/kvm.h" @@ -363,6 +362,11 @@ static inline bool s390_skeys_get_migration_enabled(Object *obj, Error **errp) return ss->migration_enabled; } +static SaveVMHandlers savevm_s390_storage_keys = { + .save_state = s390_storage_keys_save, + .load_state = s390_storage_keys_load, +}; + static inline void s390_skeys_set_migration_enabled(Object *obj, bool value, Error **errp) { @@ -376,8 +380,8 @@ static inline void s390_skeys_set_migration_enabled(Object *obj, bool value, ss->migration_enabled = value; if (ss->migration_enabled) { - register_savevm(NULL, TYPE_S390_SKEYS, 0, 1, s390_storage_keys_save, - s390_storage_keys_load, ss); + register_savevm_live(NULL, TYPE_S390_SKEYS, 0, 1, + &savevm_s390_storage_keys, ss); } else { unregister_savevm(DEVICE(ss), TYPE_S390_SKEYS, ss); } diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c index c9021f2fa9..a806345276 100644 --- a/hw/s390x/s390-virtio-ccw.c +++ b/hw/s390x/s390-virtio-ccw.c @@ -104,6 +104,11 @@ void s390_memory_init(ram_addr_t mem_size) s390_skeys_init(); } +static SaveVMHandlers savevm_gtod = { + .save_state = gtod_save, + .load_state = gtod_load, +}; + static void ccw_init(MachineState *machine) { int ret; @@ -151,8 +156,7 @@ static void ccw_init(MachineState *machine) s390_create_virtio_net(BUS(css_bus), "virtio-net-ccw"); /* Register savevm handler for guest TOD clock */ - register_savevm(NULL, "todclock", 0, 1, - gtod_save, gtod_load, kvm_state); + register_savevm_live(NULL, "todclock", 0, 1, &savevm_gtod, kvm_state); } static void s390_cpu_plug(HotplugHandler *hotplug_dev, diff --git a/hw/scsi/lsi53c895a.c b/hw/scsi/lsi53c895a.c index 595c26017a..3e56ab267c 100644 --- a/hw/scsi/lsi53c895a.c +++ b/hw/scsi/lsi53c895a.c @@ -408,27 +408,25 @@ static void lsi_reg_writeb(LSIState *s, int offset, uint8_t val); static void lsi_execute_script(LSIState *s); static void lsi_reselect(LSIState *s, lsi_request *p); -static inline int lsi_mem_read(LSIState *s, dma_addr_t addr, +static inline void lsi_mem_read(LSIState *s, dma_addr_t addr, void *buf, dma_addr_t len) { if (s->dmode & LSI_DMODE_SIOM) { address_space_read(&s->pci_io_as, addr, MEMTXATTRS_UNSPECIFIED, buf, len); - return 0; } else { - return pci_dma_read(PCI_DEVICE(s), addr, buf, len); + pci_dma_read(PCI_DEVICE(s), addr, buf, len); } } -static inline int lsi_mem_write(LSIState *s, dma_addr_t addr, +static inline void lsi_mem_write(LSIState *s, dma_addr_t addr, const void *buf, dma_addr_t len) { if (s->dmode & LSI_DMODE_DIOM) { address_space_write(&s->pci_io_as, addr, MEMTXATTRS_UNSPECIFIED, buf, len); - return 0; } else { - return pci_dma_write(PCI_DEVICE(s), addr, buf, len); + pci_dma_write(PCI_DEVICE(s), addr, buf, len); } } diff --git a/hw/scsi/virtio-scsi.c b/hw/scsi/virtio-scsi.c index 46a3e3f280..f46f06d055 100644 --- a/hw/scsi/virtio-scsi.c +++ b/hw/scsi/virtio-scsi.c @@ -918,6 +918,9 @@ void virtio_scsi_common_unrealize(DeviceState *dev, Error **errp) static void virtio_scsi_device_unrealize(DeviceState *dev, Error **errp) { + VirtIOSCSI *s = VIRTIO_SCSI(dev); + + qbus_set_hotplug_handler(BUS(&s->bus), NULL, &error_abort); virtio_scsi_common_unrealize(dev, errp); } diff --git a/hw/sparc/leon3.c b/hw/sparc/leon3.c index 6e16478413..f415997649 100644 --- a/hw/sparc/leon3.c +++ b/hw/sparc/leon3.c @@ -28,7 +28,6 @@ #include "hw/hw.h" #include "qemu/timer.h" #include "hw/ptimer.h" -#include "sysemu/char.h" #include "sysemu/sysemu.h" #include "sysemu/qtest.h" #include "hw/boards.h" diff --git a/hw/sparc/sun4m.c b/hw/sparc/sun4m.c index 5f022cc08d..0faff4619f 100644 --- a/hw/sparc/sun4m.c +++ b/hw/sparc/sun4m.c @@ -585,30 +585,23 @@ typedef struct IDRegState { MemoryRegion mem; } IDRegState; -static int idreg_init1(SysBusDevice *dev) +static void idreg_init1(Object *obj) { - IDRegState *s = MACIO_ID_REGISTER(dev); + IDRegState *s = MACIO_ID_REGISTER(obj); + SysBusDevice *dev = SYS_BUS_DEVICE(obj); - memory_region_init_ram(&s->mem, OBJECT(s), + memory_region_init_ram(&s->mem, obj, "sun4m.idreg", sizeof(idreg_data), &error_fatal); vmstate_register_ram_global(&s->mem); memory_region_set_readonly(&s->mem, true); sysbus_init_mmio(dev, &s->mem); - return 0; -} - -static void idreg_class_init(ObjectClass *klass, void *data) -{ - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - - k->init = idreg_init1; } static const TypeInfo idreg_info = { .name = TYPE_MACIO_ID_REGISTER, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(IDRegState), - .class_init = idreg_class_init, + .instance_init = idreg_init1, }; #define TYPE_TCX_AFX "tcx_afx" @@ -633,28 +626,21 @@ static void afx_init(hwaddr addr) sysbus_mmio_map(s, 0, addr); } -static int afx_init1(SysBusDevice *dev) +static void afx_init1(Object *obj) { - AFXState *s = TCX_AFX(dev); + AFXState *s = TCX_AFX(obj); + SysBusDevice *dev = SYS_BUS_DEVICE(obj); - memory_region_init_ram(&s->mem, OBJECT(s), "sun4m.afx", 4, &error_fatal); + memory_region_init_ram(&s->mem, obj, "sun4m.afx", 4, &error_fatal); vmstate_register_ram_global(&s->mem); sysbus_init_mmio(dev, &s->mem); - return 0; -} - -static void afx_class_init(ObjectClass *klass, void *data) -{ - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - - k->init = afx_init1; } static const TypeInfo afx_info = { .name = TYPE_TCX_AFX, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(AFXState), - .class_init = afx_class_init, + .instance_init = afx_init1, }; #define TYPE_OPENPROM "openprom" @@ -707,16 +693,16 @@ static void prom_init(hwaddr addr, const char *bios_name) } } -static int prom_init1(SysBusDevice *dev) +static void prom_init1(Object *obj) { - PROMState *s = OPENPROM(dev); + PROMState *s = OPENPROM(obj); + SysBusDevice *dev = SYS_BUS_DEVICE(obj); - memory_region_init_ram(&s->prom, OBJECT(s), "sun4m.prom", PROM_SIZE_MAX, + memory_region_init_ram(&s->prom, obj, "sun4m.prom", PROM_SIZE_MAX, &error_fatal); vmstate_register_ram_global(&s->prom); memory_region_set_readonly(&s->prom, true); sysbus_init_mmio(dev, &s->prom); - return 0; } static Property prom_properties[] = { @@ -726,9 +712,7 @@ static Property prom_properties[] = { static void prom_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = prom_init1; dc->props = prom_properties; } @@ -737,6 +721,7 @@ static const TypeInfo prom_info = { .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(PROMState), .class_init = prom_class_init, + .instance_init = prom_init1, }; #define TYPE_SUN4M_MEMORY "memory" @@ -750,14 +735,14 @@ typedef struct RamDevice { } RamDevice; /* System RAM */ -static int ram_init1(SysBusDevice *dev) +static void ram_realize(DeviceState *dev, Error **errp) { RamDevice *d = SUN4M_RAM(dev); + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); memory_region_allocate_system_memory(&d->ram, OBJECT(d), "sun4m.ram", d->size); - sysbus_init_mmio(dev, &d->ram); - return 0; + sysbus_init_mmio(sbd, &d->ram); } static void ram_init(hwaddr addr, ram_addr_t RAM_size, @@ -793,9 +778,8 @@ static Property ram_properties[] = { static void ram_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = ram_init1; + dc->realize = ram_realize; dc->props = ram_properties; } diff --git a/hw/sparc64/sun4u.c b/hw/sparc64/sun4u.c index d347b6616d..69f565db25 100644 --- a/hw/sparc64/sun4u.c +++ b/hw/sparc64/sun4u.c @@ -214,7 +214,7 @@ static void isa_irq_handler(void *opaque, int n, int level) qemu_irq *irqs = opaque; int ivec; - assert(n < 16); + assert(n < ARRAY_SIZE(isa_irq_to_ivec)); ivec = isa_irq_to_ivec[n]; EBUS_DPRINTF("Set ISA IRQ %d level %d -> ivec 0x%x\n", n, level, ivec); if (ivec) { @@ -329,16 +329,16 @@ static void prom_init(hwaddr addr, const char *bios_name) } } -static int prom_init1(SysBusDevice *dev) +static void prom_init1(Object *obj) { - PROMState *s = OPENPROM(dev); + PROMState *s = OPENPROM(obj); + SysBusDevice *dev = SYS_BUS_DEVICE(obj); - memory_region_init_ram(&s->prom, OBJECT(s), "sun4u.prom", PROM_SIZE_MAX, + memory_region_init_ram(&s->prom, obj, "sun4u.prom", PROM_SIZE_MAX, &error_fatal); vmstate_register_ram_global(&s->prom); memory_region_set_readonly(&s->prom, true); sysbus_init_mmio(dev, &s->prom); - return 0; } static Property prom_properties[] = { @@ -348,9 +348,7 @@ static Property prom_properties[] = { static void prom_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = prom_init1; dc->props = prom_properties; } @@ -359,6 +357,7 @@ static const TypeInfo prom_info = { .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(PROMState), .class_init = prom_class_init, + .instance_init = prom_init1, }; @@ -373,15 +372,15 @@ typedef struct RamDevice { } RamDevice; /* System RAM */ -static int ram_init1(SysBusDevice *dev) +static void ram_realize(DeviceState *dev, Error **errp) { RamDevice *d = SUN4U_RAM(dev); + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); memory_region_init_ram(&d->ram, OBJECT(d), "sun4u.ram", d->size, &error_fatal); vmstate_register_ram_global(&d->ram); - sysbus_init_mmio(dev, &d->ram); - return 0; + sysbus_init_mmio(sbd, &d->ram); } static void ram_init(hwaddr addr, ram_addr_t RAM_size) @@ -409,9 +408,8 @@ static Property ram_properties[] = { static void ram_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = ram_init1; + dc->realize = ram_realize; dc->props = ram_properties; } diff --git a/hw/timer/altera_timer.c b/hw/timer/altera_timer.c index 6d4862661d..c9a0fc5dca 100644 --- a/hw/timer/altera_timer.c +++ b/hw/timer/altera_timer.c @@ -204,7 +204,7 @@ static void altera_timer_reset(DeviceState *dev) ptimer_stop(t->ptimer); ptimer_set_limit(t->ptimer, 0xffffffff, 1); - memset(t->regs, 0, ARRAY_SIZE(t->regs)); + memset(t->regs, 0, sizeof(t->regs)); } static Property altera_timer_properties[] = { diff --git a/hw/timer/m48t59.c b/hw/timer/m48t59.c index 4a064fbfd2..844aad540e 100644 --- a/hw/timer/m48t59.c +++ b/hw/timer/m48t59.c @@ -640,34 +640,33 @@ void m48t59_realize_common(M48t59State *s, Error **errp) s->wd_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, &watchdog_cb, s); } qemu_get_timedate(&s->alarm, 0); - - vmstate_register(NULL, -1, &vmstate_m48t59, s); } -static int m48t59_init1(SysBusDevice *dev) +static void m48t59_init1(Object *obj) { - M48txxSysBusDeviceClass *u = M48TXX_SYS_BUS_GET_CLASS(dev); - M48txxSysBusState *d = M48TXX_SYS_BUS(dev); - Object *o = OBJECT(dev); + M48txxSysBusDeviceClass *u = M48TXX_SYS_BUS_GET_CLASS(obj); + M48txxSysBusState *d = M48TXX_SYS_BUS(obj); + SysBusDevice *dev = SYS_BUS_DEVICE(obj); M48t59State *s = &d->state; - Error *err = NULL; s->model = u->info.model; s->size = u->info.size; sysbus_init_irq(dev, &s->IRQ); - memory_region_init_io(&s->iomem, o, &nvram_ops, s, "m48t59.nvram", + memory_region_init_io(&s->iomem, obj, &nvram_ops, s, "m48t59.nvram", s->size); - memory_region_init_io(&d->io, o, &m48t59_io_ops, s, "m48t59", 4); - sysbus_init_mmio(dev, &s->iomem); - sysbus_init_mmio(dev, &d->io); - m48t59_realize_common(s, &err); - if (err != NULL) { - error_free(err); - return -1; - } + memory_region_init_io(&d->io, obj, &m48t59_io_ops, s, "m48t59", 4); +} + +static void m48t59_realize(DeviceState *dev, Error **errp) +{ + M48txxSysBusState *d = M48TXX_SYS_BUS(dev); + M48t59State *s = &d->state; + SysBusDevice *sbd = SYS_BUS_DEVICE(dev); - return 0; + sysbus_init_mmio(sbd, &s->iomem); + sysbus_init_mmio(sbd, &d->io); + m48t59_realize_common(s, errp); } static uint32_t m48txx_sysbus_read(Nvram *obj, uint32_t addr) @@ -696,12 +695,12 @@ static Property m48t59_sysbus_properties[] = { static void m48txx_sysbus_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); NvramClass *nc = NVRAM_CLASS(klass); - k->init = m48t59_init1; + dc->realize = m48t59_realize; dc->reset = m48t59_reset_sysbus; dc->props = m48t59_sysbus_properties; + dc->vmsd = &vmstate_m48t59; nc->read = m48txx_sysbus_read; nc->write = m48txx_sysbus_write; nc->toggle_lock = m48txx_sysbus_toggle_lock; @@ -725,6 +724,7 @@ static const TypeInfo m48txx_sysbus_type_info = { .name = TYPE_M48TXX_SYS_BUS, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(M48txxSysBusState), + .instance_init = m48t59_init1, .abstract = true, .class_init = m48txx_sysbus_class_init, .interfaces = (InterfaceInfo[]) { diff --git a/hw/timer/mc146818rtc.c b/hw/timer/mc146818rtc.c index 93de3e1cc5..1b8d3d7d4c 100644 --- a/hw/timer/mc146818rtc.c +++ b/hw/timer/mc146818rtc.c @@ -112,7 +112,6 @@ static uint64_t get_guest_rtc_ns(RTCState *s) guest_clock - s->last_update + s->offset; } -#ifdef TARGET_I386 static void rtc_coalesced_timer_update(RTCState *s) { if (s->irq_coalesced == 0) { @@ -121,21 +120,39 @@ static void rtc_coalesced_timer_update(RTCState *s) /* divide each RTC interval to 2 - 8 smaller intervals */ int c = MIN(s->irq_coalesced, 7) + 1; int64_t next_clock = qemu_clock_get_ns(rtc_clock) + - muldiv64(s->period / c, NANOSECONDS_PER_SECOND, RTC_CLOCK_RATE); + periodic_clock_to_ns(s->period / c); timer_mod(s->coalesced_timer, next_clock); } } +static QLIST_HEAD(, RTCState) rtc_devices = + QLIST_HEAD_INITIALIZER(rtc_devices); + +#ifdef TARGET_I386 +void qmp_rtc_reset_reinjection(Error **errp) +{ + RTCState *s; + + QLIST_FOREACH(s, &rtc_devices, link) { + s->irq_coalesced = 0; + } +} + +static bool rtc_policy_slew_deliver_irq(RTCState *s) +{ + apic_reset_irq_delivered(); + qemu_irq_raise(s->irq); + return apic_get_irq_delivered(); +} + static void rtc_coalesced_timer(void *opaque) { RTCState *s = opaque; if (s->irq_coalesced != 0) { - apic_reset_irq_delivered(); s->cmos_data[RTC_REG_C] |= 0xc0; DPRINTF_C("cmos: injecting from timer\n"); - qemu_irq_raise(s->irq); - if (apic_get_irq_delivered()) { + if (rtc_policy_slew_deliver_irq(s)) { s->irq_coalesced--; DPRINTF_C("cmos: coalesced irqs decreased to %d\n", s->irq_coalesced); @@ -144,40 +161,101 @@ static void rtc_coalesced_timer(void *opaque) rtc_coalesced_timer_update(s); } +#else +static bool rtc_policy_slew_deliver_irq(RTCState *s) +{ + assert(0); + return false; +} #endif -/* handle periodic timer */ -static void periodic_timer_update(RTCState *s, int64_t current_time) +static uint32_t rtc_periodic_clock_ticks(RTCState *s) { - int period_code, period; - int64_t cur_clock, next_irq_clock; + int period_code; + + if (!(s->cmos_data[RTC_REG_B] & REG_B_PIE)) { + return 0; + } period_code = s->cmos_data[RTC_REG_A] & 0x0f; - if (period_code != 0 - && (s->cmos_data[RTC_REG_B] & REG_B_PIE)) { - if (period_code <= 2) - period_code += 7; - /* period in 32 Khz cycles */ - period = 1 << (period_code - 1); -#ifdef TARGET_I386 - if (period != s->period) { - s->irq_coalesced = (s->irq_coalesced * s->period) / period; - DPRINTF_C("cmos: coalesced irqs scaled to %d\n", s->irq_coalesced); - } - s->period = period; -#endif + + return periodic_period_to_clock(period_code); +} + +/* + * handle periodic timer. @old_period indicates the periodic timer update + * is just due to period adjustment. + */ +static void +periodic_timer_update(RTCState *s, int64_t current_time, uint32_t old_period) +{ + uint32_t period; + int64_t cur_clock, next_irq_clock, lost_clock = 0; + + period = rtc_periodic_clock_ticks(s); + + if (period) { /* compute 32 khz clock */ cur_clock = muldiv64(current_time, RTC_CLOCK_RATE, NANOSECONDS_PER_SECOND); - next_irq_clock = (cur_clock & ~(period - 1)) + period; - s->next_periodic_time = muldiv64(next_irq_clock, NANOSECONDS_PER_SECOND, - RTC_CLOCK_RATE) + 1; + /* + * if the periodic timer's update is due to period re-configuration, + * we should count the clock since last interrupt. + */ + if (old_period) { + int64_t last_periodic_clock, next_periodic_clock; + + next_periodic_clock = muldiv64(s->next_periodic_time, + RTC_CLOCK_RATE, NANOSECONDS_PER_SECOND); + last_periodic_clock = next_periodic_clock - old_period; + lost_clock = cur_clock - last_periodic_clock; + assert(lost_clock >= 0); + } + + /* + * s->irq_coalesced can change for two reasons: + * + * a) if one or more periodic timer interrupts have been lost, + * lost_clock will be more that a period. + * + * b) when the period may be reconfigured, we expect the OS to + * treat delayed tick as the new period. So, when switching + * from a shorter to a longer period, scale down the missing, + * because the OS will treat past delayed ticks as longer + * (leftovers are put back into lost_clock). When switching + * to a shorter period, scale up the missing ticks since the + * OS handler will treat past delayed ticks as shorter. + */ + if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) { + uint32_t old_irq_coalesced = s->irq_coalesced; + + s->period = period; + lost_clock += old_irq_coalesced * old_period; + s->irq_coalesced = lost_clock / s->period; + lost_clock %= s->period; + if (old_irq_coalesced != s->irq_coalesced || + old_period != s->period) { + DPRINTF_C("cmos: coalesced irqs scaled from %d to %d, " + "period scaled from %d to %d\n", old_irq_coalesced, + s->irq_coalesced, old_period, s->period); + rtc_coalesced_timer_update(s); + } + } else { + /* + * no way to compensate the interrupt if LOST_TICK_POLICY_SLEW + * is not used, we should make the time progress anyway. + */ + lost_clock = MIN(lost_clock, period); + } + + assert(lost_clock >= 0 && lost_clock <= period); + + next_irq_clock = cur_clock + period - lost_clock; + s->next_periodic_time = periodic_clock_to_ns(next_irq_clock) + 1; timer_mod(s->periodic_timer, s->next_periodic_time); } else { -#ifdef TARGET_I386 s->irq_coalesced = 0; -#endif timer_del(s->periodic_timer); } } @@ -186,25 +264,21 @@ static void rtc_periodic_timer(void *opaque) { RTCState *s = opaque; - periodic_timer_update(s, s->next_periodic_time); + periodic_timer_update(s, s->next_periodic_time, 0); s->cmos_data[RTC_REG_C] |= REG_C_PF; if (s->cmos_data[RTC_REG_B] & REG_B_PIE) { s->cmos_data[RTC_REG_C] |= REG_C_IRQF; -#ifdef TARGET_I386 if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) { if (s->irq_reinject_on_ack_count >= RTC_REINJECT_ON_ACK_COUNT) - s->irq_reinject_on_ack_count = 0; - apic_reset_irq_delivered(); - qemu_irq_raise(s->irq); - if (!apic_get_irq_delivered()) { + s->irq_reinject_on_ack_count = 0; + if (!rtc_policy_slew_deliver_irq(s)) { s->irq_coalesced++; rtc_coalesced_timer_update(s); DPRINTF_C("cmos: coalesced irqs increased to %d\n", s->irq_coalesced); } } else -#endif - qemu_irq_raise(s->irq); + qemu_irq_raise(s->irq); } } @@ -391,6 +465,8 @@ static void cmos_ioport_write(void *opaque, hwaddr addr, uint64_t data, unsigned size) { RTCState *s = opaque; + uint32_t old_period; + bool update_periodic_timer; if ((addr & 1) == 0) { s->cmos_index = data & 0x7f; @@ -423,6 +499,9 @@ static void cmos_ioport_write(void *opaque, hwaddr addr, } break; case RTC_REG_A: + update_periodic_timer = (s->cmos_data[RTC_REG_A] ^ data) & 0x0f; + old_period = rtc_periodic_clock_ticks(s); + if ((data & 0x60) == 0x60) { if (rtc_running(s)) { rtc_update_time(s); @@ -445,10 +524,19 @@ static void cmos_ioport_write(void *opaque, hwaddr addr, /* UIP bit is read only */ s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) | (s->cmos_data[RTC_REG_A] & REG_A_UIP); - periodic_timer_update(s, qemu_clock_get_ns(rtc_clock)); + + if (update_periodic_timer) { + periodic_timer_update(s, qemu_clock_get_ns(rtc_clock), + old_period); + } + check_update_timer(s); break; case RTC_REG_B: + update_periodic_timer = (s->cmos_data[RTC_REG_B] ^ data) + & REG_B_PIE; + old_period = rtc_periodic_clock_ticks(s); + if (data & REG_B_SET) { /* update cmos to when the rtc was stopping */ if (rtc_running(s)) { @@ -475,7 +563,12 @@ static void cmos_ioport_write(void *opaque, hwaddr addr, qemu_irq_lower(s->irq); } s->cmos_data[RTC_REG_B] = data; - periodic_timer_update(s, qemu_clock_get_ns(rtc_clock)); + + if (update_periodic_timer) { + periodic_timer_update(s, qemu_clock_get_ns(rtc_clock), + old_period); + } + check_update_timer(s); break; case RTC_REG_C: @@ -529,20 +622,6 @@ static void rtc_get_time(RTCState *s, struct tm *tm) rtc_from_bcd(s, s->cmos_data[RTC_CENTURY]) * 100 - 1900; } -static QLIST_HEAD(, RTCState) rtc_devices = - QLIST_HEAD_INITIALIZER(rtc_devices); - -#ifdef TARGET_I386 -void qmp_rtc_reset_reinjection(Error **errp) -{ - RTCState *s; - - QLIST_FOREACH(s, &rtc_devices, link) { - s->irq_coalesced = 0; - } -} -#endif - static void rtc_set_time(RTCState *s) { struct tm tm; @@ -662,22 +741,19 @@ static uint64_t cmos_ioport_read(void *opaque, hwaddr addr, if (ret & (REG_C_UF | REG_C_AF)) { check_update_timer(s); } -#ifdef TARGET_I386 + if(s->irq_coalesced && (s->cmos_data[RTC_REG_B] & REG_B_PIE) && s->irq_reinject_on_ack_count < RTC_REINJECT_ON_ACK_COUNT) { s->irq_reinject_on_ack_count++; s->cmos_data[RTC_REG_C] |= REG_C_IRQF | REG_C_PF; - apic_reset_irq_delivered(); DPRINTF_C("cmos: injecting on ack\n"); - qemu_irq_raise(s->irq); - if (apic_get_irq_delivered()) { + if (rtc_policy_slew_deliver_irq(s)) { s->irq_coalesced--; DPRINTF_C("cmos: coalesced irqs decreased to %d\n", s->irq_coalesced); } } -#endif break; default: ret = s->cmos_data[s->cmos_index]; @@ -743,17 +819,15 @@ static int rtc_post_load(void *opaque, int version_id) uint64_t now = qemu_clock_get_ns(rtc_clock); if (now < s->next_periodic_time || now > (s->next_periodic_time + get_max_clock_jump())) { - periodic_timer_update(s, qemu_clock_get_ns(rtc_clock)); + periodic_timer_update(s, qemu_clock_get_ns(rtc_clock), 0); } } -#ifdef TARGET_I386 if (version_id >= 2) { if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) { rtc_coalesced_timer_update(s); } } -#endif return 0; } @@ -808,13 +882,12 @@ static void rtc_notify_clock_reset(Notifier *notifier, void *data) int64_t now = *(int64_t *)data; rtc_set_date_from_host(ISA_DEVICE(s)); - periodic_timer_update(s, now); + periodic_timer_update(s, now, 0); check_update_timer(s); -#ifdef TARGET_I386 + if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) { rtc_coalesced_timer_update(s); } -#endif } /* set CMOS shutdown status register (index 0xF) as S3_resume(0xFE) @@ -835,12 +908,10 @@ static void rtc_reset(void *opaque) qemu_irq_lower(s->irq); -#ifdef TARGET_I386 if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) { s->irq_coalesced = 0; s->irq_reinject_on_ack_count = 0; } -#endif } static const MemoryRegionOps cmos_ops = { @@ -886,19 +957,19 @@ static void rtc_realizefn(DeviceState *dev, Error **errp) rtc_set_date_from_host(isadev); -#ifdef TARGET_I386 switch (s->lost_tick_policy) { +#ifdef TARGET_I386 case LOST_TICK_POLICY_SLEW: s->coalesced_timer = timer_new_ns(rtc_clock, rtc_coalesced_timer, s); break; +#endif case LOST_TICK_POLICY_DISCARD: break; default: error_setg(errp, "Invalid lost tick policy."); return; } -#endif s->periodic_timer = timer_new_ns(rtc_clock, rtc_periodic_timer, s); s->update_timer = timer_new_ns(rtc_clock, rtc_update_timer, s); diff --git a/hw/timer/slavio_timer.c b/hw/timer/slavio_timer.c index bfee1f3027..a8cc9c0148 100644 --- a/hw/timer/slavio_timer.c +++ b/hw/timer/slavio_timer.c @@ -373,9 +373,10 @@ static void slavio_timer_reset(DeviceState *d) s->cputimer_mode = 0; } -static int slavio_timer_init1(SysBusDevice *dev) +static void slavio_timer_init(Object *obj) { - SLAVIO_TIMERState *s = SLAVIO_TIMER(dev); + SLAVIO_TIMERState *s = SLAVIO_TIMER(obj); + SysBusDevice *dev = SYS_BUS_DEVICE(obj); QEMUBH *bh; unsigned int i; TimerContext *tc; @@ -394,14 +395,12 @@ static int slavio_timer_init1(SysBusDevice *dev) size = i == 0 ? SYS_TIMER_SIZE : CPU_TIMER_SIZE; snprintf(timer_name, sizeof(timer_name), "timer-%i", i); - memory_region_init_io(&tc->iomem, OBJECT(s), &slavio_timer_mem_ops, tc, + memory_region_init_io(&tc->iomem, obj, &slavio_timer_mem_ops, tc, timer_name, size); sysbus_init_mmio(dev, &tc->iomem); sysbus_init_irq(dev, &s->cputimer[i].irq); } - - return 0; } static Property slavio_timer_properties[] = { @@ -412,9 +411,7 @@ static Property slavio_timer_properties[] = { static void slavio_timer_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); - SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); - k->init = slavio_timer_init1; dc->reset = slavio_timer_reset; dc->vmsd = &vmstate_slavio_timer; dc->props = slavio_timer_properties; @@ -424,6 +421,7 @@ static const TypeInfo slavio_timer_info = { .name = TYPE_SLAVIO_TIMER, .parent = TYPE_SYS_BUS_DEVICE, .instance_size = sizeof(SLAVIO_TIMERState), + .instance_init = slavio_timer_init, .class_init = slavio_timer_class_init, }; diff --git a/hw/usb/ccid-card-emulated.c b/hw/usb/ccid-card-emulated.c index 99627860a3..e646eb243b 100644 --- a/hw/usb/ccid-card-emulated.c +++ b/hw/usb/ccid-card-emulated.c @@ -33,7 +33,7 @@ #include <vcard_emul.h> #include "qemu/thread.h" -#include "sysemu/char.h" +#include "qemu/main-loop.h" #include "ccid.h" #define DPRINTF(card, lvl, fmt, ...) \ diff --git a/hw/usb/ccid-card-passthru.c b/hw/usb/ccid-card-passthru.c index a41b0d6ec5..ac1725eeae 100644 --- a/hw/usb/ccid-card-passthru.c +++ b/hw/usb/ccid-card-passthru.c @@ -9,7 +9,7 @@ */ #include "qemu/osdep.h" -#include "sysemu/char.h" +#include "chardev/char-fe.h" #include "qemu/error-report.h" #include "qemu/sockets.h" #include "ccid.h" @@ -264,10 +264,7 @@ static void ccid_card_vscard_handle_message(PassthruState *card, static void ccid_card_vscard_drop_connection(PassthruState *card) { - Chardev *chr = qemu_chr_fe_get_driver(&card->cs); - - qemu_chr_fe_deinit(&card->cs); - object_unparent(OBJECT(chr)); + qemu_chr_fe_deinit(&card->cs, true); card->vscard_in_pos = card->vscard_in_hdr = 0; } diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c index 76ceca1f5c..bfbf7cdce7 100644 --- a/hw/usb/dev-serial.c +++ b/hw/usb/dev-serial.c @@ -15,7 +15,8 @@ #include "qemu/error-report.h" #include "hw/usb.h" #include "hw/usb/desc.h" -#include "sysemu/char.h" +#include "chardev/char-serial.h" +#include "chardev/char-fe.h" //#define DEBUG_Serial diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c index ad5ef783a6..aa22d69216 100644 --- a/hw/usb/redirect.c +++ b/hw/usb/redirect.c @@ -33,7 +33,7 @@ #include "qapi/qmp/qerror.h" #include "qemu/error-report.h" #include "qemu/iov.h" -#include "sysemu/char.h" +#include "chardev/char-fe.h" #include <usbredirparser.h> #include <usbredirfilter.h> @@ -1419,10 +1419,8 @@ static void usbredir_cleanup_device_queues(USBRedirDevice *dev) static void usbredir_unrealize(USBDevice *udev, Error **errp) { USBRedirDevice *dev = USB_REDIRECT(udev); - Chardev *chr = qemu_chr_fe_get_driver(&dev->cs); - qemu_chr_fe_deinit(&dev->cs); - object_unparent(OBJECT(chr)); + qemu_chr_fe_deinit(&dev->cs, true); /* Note must be done after qemu_chr_close, as that causes a close event */ qemu_bh_delete(dev->chardev_close_bh); diff --git a/hw/virtio/trace-events b/hw/virtio/trace-events index 1f7a7c1ae1..e24d8fa997 100644 --- a/hw/virtio/trace-events +++ b/hw/virtio/trace-events @@ -1,6 +1,7 @@ # See docs/tracing.txt for syntax documentation. # hw/virtio/virtio.c +virtqueue_alloc_element(void *elem, size_t sz, unsigned in_num, unsigned out_num) "elem %p size %zd in_num %u out_num %u" virtqueue_fill(void *vq, const void *elem, unsigned int len, unsigned int idx) "vq %p elem %p len %u idx %u" virtqueue_flush(void *vq, unsigned int count) "vq %p count %u" virtqueue_pop(void *vq, void *elem, unsigned int in_num, unsigned int out_num) "vq %p elem %p in_num %u out_num %u" diff --git a/hw/virtio/vhost-backend.c b/hw/virtio/vhost-backend.c index be927b891e..4e31de1686 100644 --- a/hw/virtio/vhost-backend.c +++ b/hw/virtio/vhost-backend.c @@ -192,7 +192,6 @@ static void vhost_kernel_iotlb_read(void *opaque) ssize_t len; while ((len = read((uintptr_t)dev->opaque, &msg, sizeof msg)) > 0) { - struct vhost_iotlb_msg *imsg = &msg.iotlb; if (len < sizeof msg) { error_report("Wrong vhost message len: %d", (int)len); break; @@ -201,70 +200,21 @@ static void vhost_kernel_iotlb_read(void *opaque) error_report("Unknown vhost iotlb message type"); break; } - switch (imsg->type) { - case VHOST_IOTLB_MISS: - vhost_device_iotlb_miss(dev, imsg->iova, - imsg->perm != VHOST_ACCESS_RO); - break; - case VHOST_IOTLB_UPDATE: - case VHOST_IOTLB_INVALIDATE: - error_report("Unexpected IOTLB message type"); - break; - case VHOST_IOTLB_ACCESS_FAIL: - /* FIXME: report device iotlb error */ - break; - default: - break; - } - } -} -static int vhost_kernel_update_device_iotlb(struct vhost_dev *dev, - uint64_t iova, uint64_t uaddr, - uint64_t len, - IOMMUAccessFlags perm) -{ - struct vhost_msg msg; - msg.type = VHOST_IOTLB_MSG; - msg.iotlb.iova = iova; - msg.iotlb.uaddr = uaddr; - msg.iotlb.size = len; - msg.iotlb.type = VHOST_IOTLB_UPDATE; - - switch (perm) { - case IOMMU_RO: - msg.iotlb.perm = VHOST_ACCESS_RO; - break; - case IOMMU_WO: - msg.iotlb.perm = VHOST_ACCESS_WO; - break; - case IOMMU_RW: - msg.iotlb.perm = VHOST_ACCESS_RW; - break; - default: - g_assert_not_reached(); - } - - if (write((uintptr_t)dev->opaque, &msg, sizeof msg) != sizeof msg) { - error_report("Fail to update device iotlb"); - return -EFAULT; + vhost_backend_handle_iotlb_msg(dev, &msg.iotlb); } - - return 0; } -static int vhost_kernel_invalidate_device_iotlb(struct vhost_dev *dev, - uint64_t iova, uint64_t len) +static int vhost_kernel_send_device_iotlb_msg(struct vhost_dev *dev, + struct vhost_iotlb_msg *imsg) { struct vhost_msg msg; msg.type = VHOST_IOTLB_MSG; - msg.iotlb.iova = iova; - msg.iotlb.size = len; - msg.iotlb.type = VHOST_IOTLB_INVALIDATE; + msg.iotlb = *imsg; if (write((uintptr_t)dev->opaque, &msg, sizeof msg) != sizeof msg) { - error_report("Fail to invalidate device iotlb"); + error_report("Fail to update device iotlb"); return -EFAULT; } @@ -311,8 +261,7 @@ static const VhostOps kernel_ops = { .vhost_vsock_set_running = vhost_kernel_vsock_set_running, #endif /* CONFIG_VHOST_VSOCK */ .vhost_set_iotlb_callback = vhost_kernel_set_iotlb_callback, - .vhost_update_device_iotlb = vhost_kernel_update_device_iotlb, - .vhost_invalidate_device_iotlb = vhost_kernel_invalidate_device_iotlb, + .vhost_send_device_iotlb_msg = vhost_kernel_send_device_iotlb_msg, }; int vhost_set_backend_type(struct vhost_dev *dev, VhostBackendType backend_type) @@ -333,3 +282,70 @@ int vhost_set_backend_type(struct vhost_dev *dev, VhostBackendType backend_type) return r; } + +int vhost_backend_update_device_iotlb(struct vhost_dev *dev, + uint64_t iova, uint64_t uaddr, + uint64_t len, + IOMMUAccessFlags perm) +{ + struct vhost_iotlb_msg imsg; + + imsg.iova = iova; + imsg.uaddr = uaddr; + imsg.size = len; + imsg.type = VHOST_IOTLB_UPDATE; + + switch (perm) { + case IOMMU_RO: + imsg.perm = VHOST_ACCESS_RO; + break; + case IOMMU_WO: + imsg.perm = VHOST_ACCESS_WO; + break; + case IOMMU_RW: + imsg.perm = VHOST_ACCESS_RW; + break; + default: + return -EINVAL; + } + + return dev->vhost_ops->vhost_send_device_iotlb_msg(dev, &imsg); +} + +int vhost_backend_invalidate_device_iotlb(struct vhost_dev *dev, + uint64_t iova, uint64_t len) +{ + struct vhost_iotlb_msg imsg; + + imsg.iova = iova; + imsg.size = len; + imsg.type = VHOST_IOTLB_INVALIDATE; + + return dev->vhost_ops->vhost_send_device_iotlb_msg(dev, &imsg); +} + +int vhost_backend_handle_iotlb_msg(struct vhost_dev *dev, + struct vhost_iotlb_msg *imsg) +{ + int ret = 0; + + switch (imsg->type) { + case VHOST_IOTLB_MISS: + ret = vhost_device_iotlb_miss(dev, imsg->iova, + imsg->perm != VHOST_ACCESS_RO); + break; + case VHOST_IOTLB_ACCESS_FAIL: + /* FIXME: report device iotlb error */ + error_report("Access failure IOTLB message type not supported"); + ret = -ENOTSUP; + break; + case VHOST_IOTLB_UPDATE: + case VHOST_IOTLB_INVALIDATE: + default: + error_report("Unexpected IOTLB message type"); + ret = -EINVAL; + break; + } + + return ret; +} diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index dde094abb4..958ee09bcb 100644 --- a/hw/virtio/vhost-user.c +++ b/hw/virtio/vhost-user.c @@ -13,7 +13,7 @@ #include "hw/virtio/vhost.h" #include "hw/virtio/vhost-backend.h" #include "hw/virtio/virtio-net.h" -#include "sysemu/char.h" +#include "chardev/char-fe.h" #include "sysemu/kvm.h" #include "qemu/error-report.h" #include "qemu/sockets.h" @@ -32,6 +32,7 @@ enum VhostUserProtocolFeature { VHOST_USER_PROTOCOL_F_RARP = 2, VHOST_USER_PROTOCOL_F_REPLY_ACK = 3, VHOST_USER_PROTOCOL_F_NET_MTU = 4, + VHOST_USER_PROTOCOL_F_SLAVE_REQ = 5, VHOST_USER_PROTOCOL_F_MAX }; @@ -60,9 +61,17 @@ typedef enum VhostUserRequest { VHOST_USER_SET_VRING_ENABLE = 18, VHOST_USER_SEND_RARP = 19, VHOST_USER_NET_SET_MTU = 20, + VHOST_USER_SET_SLAVE_REQ_FD = 21, + VHOST_USER_IOTLB_MSG = 22, VHOST_USER_MAX } VhostUserRequest; +typedef enum VhostUserSlaveRequest { + VHOST_USER_SLAVE_NONE = 0, + VHOST_USER_SLAVE_IOTLB_MSG = 1, + VHOST_USER_SLAVE_MAX +} VhostUserSlaveRequest; + typedef struct VhostUserMemoryRegion { uint64_t guest_phys_addr; uint64_t memory_size; @@ -97,6 +106,7 @@ typedef struct VhostUserMsg { struct vhost_vring_addr addr; VhostUserMemory memory; VhostUserLog log; + struct vhost_iotlb_msg iotlb; } payload; } QEMU_PACKED VhostUserMsg; @@ -110,6 +120,11 @@ static VhostUserMsg m __attribute__ ((unused)); /* The version of the protocol we support */ #define VHOST_USER_VERSION (0x1) +struct vhost_user { + CharBackend *chr; + int slave_fd; +}; + static bool ioeventfd_enabled(void) { return kvm_enabled() && kvm_eventfds_enabled(); @@ -117,7 +132,8 @@ static bool ioeventfd_enabled(void) static int vhost_user_read(struct vhost_dev *dev, VhostUserMsg *msg) { - CharBackend *chr = dev->opaque; + struct vhost_user *u = dev->opaque; + CharBackend *chr = u->chr; uint8_t *p = (uint8_t *) msg; int r, size = VHOST_USER_HDR_SIZE; @@ -202,7 +218,8 @@ static bool vhost_user_one_time_request(VhostUserRequest request) static int vhost_user_write(struct vhost_dev *dev, VhostUserMsg *msg, int *fds, int fd_num) { - CharBackend *chr = dev->opaque; + struct vhost_user *u = dev->opaque; + CharBackend *chr = u->chr; int ret, size = VHOST_USER_HDR_SIZE + msg->size; /* @@ -572,14 +589,130 @@ static int vhost_user_reset_device(struct vhost_dev *dev) return 0; } +static void slave_read(void *opaque) +{ + struct vhost_dev *dev = opaque; + struct vhost_user *u = dev->opaque; + VhostUserMsg msg = { 0, }; + int size, ret = 0; + + /* Read header */ + size = read(u->slave_fd, &msg, VHOST_USER_HDR_SIZE); + if (size != VHOST_USER_HDR_SIZE) { + error_report("Failed to read from slave."); + goto err; + } + + if (msg.size > VHOST_USER_PAYLOAD_SIZE) { + error_report("Failed to read msg header." + " Size %d exceeds the maximum %zu.", msg.size, + VHOST_USER_PAYLOAD_SIZE); + goto err; + } + + /* Read payload */ + size = read(u->slave_fd, &msg.payload, msg.size); + if (size != msg.size) { + error_report("Failed to read payload from slave."); + goto err; + } + + switch (msg.request) { + case VHOST_USER_SLAVE_IOTLB_MSG: + ret = vhost_backend_handle_iotlb_msg(dev, &msg.payload.iotlb); + break; + default: + error_report("Received unexpected msg type."); + ret = -EINVAL; + } + + /* + * REPLY_ACK feature handling. Other reply types has to be managed + * directly in their request handlers. + */ + if (msg.flags & VHOST_USER_NEED_REPLY_MASK) { + msg.flags &= ~VHOST_USER_NEED_REPLY_MASK; + msg.flags |= VHOST_USER_REPLY_MASK; + + msg.payload.u64 = !!ret; + msg.size = sizeof(msg.payload.u64); + + size = write(u->slave_fd, &msg, VHOST_USER_HDR_SIZE + msg.size); + if (size != VHOST_USER_HDR_SIZE + msg.size) { + error_report("Failed to send msg reply to slave."); + goto err; + } + } + + return; + +err: + qemu_set_fd_handler(u->slave_fd, NULL, NULL, NULL); + close(u->slave_fd); + u->slave_fd = -1; + return; +} + +static int vhost_setup_slave_channel(struct vhost_dev *dev) +{ + VhostUserMsg msg = { + .request = VHOST_USER_SET_SLAVE_REQ_FD, + .flags = VHOST_USER_VERSION, + }; + struct vhost_user *u = dev->opaque; + int sv[2], ret = 0; + bool reply_supported = virtio_has_feature(dev->protocol_features, + VHOST_USER_PROTOCOL_F_REPLY_ACK); + + if (!virtio_has_feature(dev->protocol_features, + VHOST_USER_PROTOCOL_F_SLAVE_REQ)) { + return 0; + } + + if (socketpair(PF_UNIX, SOCK_STREAM, 0, sv) == -1) { + error_report("socketpair() failed"); + return -1; + } + + u->slave_fd = sv[0]; + qemu_set_fd_handler(u->slave_fd, slave_read, NULL, dev); + + if (reply_supported) { + msg.flags |= VHOST_USER_NEED_REPLY_MASK; + } + + ret = vhost_user_write(dev, &msg, &sv[1], 1); + if (ret) { + goto out; + } + + if (reply_supported) { + ret = process_message_reply(dev, &msg); + } + +out: + close(sv[1]); + if (ret) { + qemu_set_fd_handler(u->slave_fd, NULL, NULL, NULL); + close(u->slave_fd); + u->slave_fd = -1; + } + + return ret; +} + static int vhost_user_init(struct vhost_dev *dev, void *opaque) { - uint64_t features; + uint64_t features, protocol_features; + struct vhost_user *u; int err; assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER); - dev->opaque = opaque; + u = g_new0(struct vhost_user, 1); + u->chr = opaque; + u->slave_fd = -1; + dev->opaque = u; err = vhost_user_get_features(dev, &features); if (err < 0) { @@ -590,12 +723,13 @@ static int vhost_user_init(struct vhost_dev *dev, void *opaque) dev->backend_features |= 1ULL << VHOST_USER_F_PROTOCOL_FEATURES; err = vhost_user_get_u64(dev, VHOST_USER_GET_PROTOCOL_FEATURES, - &features); + &protocol_features); if (err < 0) { return err; } - dev->protocol_features = features & VHOST_USER_PROTOCOL_FEATURE_MASK; + dev->protocol_features = + protocol_features & VHOST_USER_PROTOCOL_FEATURE_MASK; err = vhost_user_set_protocol_features(dev, dev->protocol_features); if (err < 0) { return err; @@ -609,6 +743,16 @@ static int vhost_user_init(struct vhost_dev *dev, void *opaque) return err; } } + + if (virtio_has_feature(features, VIRTIO_F_IOMMU_PLATFORM) && + !(virtio_has_feature(dev->protocol_features, + VHOST_USER_PROTOCOL_F_SLAVE_REQ) && + virtio_has_feature(dev->protocol_features, + VHOST_USER_PROTOCOL_F_REPLY_ACK))) { + error_report("IOMMU support requires reply-ack and " + "slave-req protocol features."); + return -1; + } } if (dev->migration_blocker == NULL && @@ -619,13 +763,26 @@ static int vhost_user_init(struct vhost_dev *dev, void *opaque) "VHOST_USER_PROTOCOL_F_LOG_SHMFD feature."); } + err = vhost_setup_slave_channel(dev); + if (err < 0) { + return err; + } + return 0; } static int vhost_user_cleanup(struct vhost_dev *dev) { + struct vhost_user *u; + assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_USER); + u = dev->opaque; + if (u->slave_fd >= 0) { + close(u->slave_fd); + u->slave_fd = -1; + } + g_free(u); dev->opaque = 0; return 0; @@ -722,6 +879,29 @@ static int vhost_user_net_set_mtu(struct vhost_dev *dev, uint16_t mtu) return 0; } +static int vhost_user_send_device_iotlb_msg(struct vhost_dev *dev, + struct vhost_iotlb_msg *imsg) +{ + VhostUserMsg msg = { + .request = VHOST_USER_IOTLB_MSG, + .size = sizeof(msg.payload.iotlb), + .flags = VHOST_USER_VERSION | VHOST_USER_NEED_REPLY_MASK, + .payload.iotlb = *imsg, + }; + + if (vhost_user_write(dev, &msg, NULL, 0) < 0) { + return -EFAULT; + } + + return process_message_reply(dev, &msg); +} + + +static void vhost_user_set_iotlb_callback(struct vhost_dev *dev, int enabled) +{ + /* No-op as the receive channel is not dedicated to IOTLB messages. */ +} + const VhostOps user_ops = { .backend_type = VHOST_BACKEND_TYPE_USER, .vhost_backend_init = vhost_user_init, @@ -746,4 +926,6 @@ const VhostOps user_ops = { .vhost_migration_done = vhost_user_migration_done, .vhost_backend_can_merge = vhost_user_can_merge, .vhost_net_set_mtu = vhost_user_net_set_mtu, + .vhost_set_iotlb_callback = vhost_user_set_iotlb_callback, + .vhost_send_device_iotlb_msg = vhost_user_send_device_iotlb_msg, }; diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 03a46a7429..6eddb099b0 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -724,8 +724,8 @@ static void vhost_iommu_unmap_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb) struct vhost_dev *hdev = iommu->hdev; hwaddr iova = iotlb->iova + iommu->iommu_offset; - if (hdev->vhost_ops->vhost_invalidate_device_iotlb(hdev, iova, - iotlb->addr_mask + 1)) { + if (vhost_backend_invalidate_device_iotlb(hdev, iova, + iotlb->addr_mask + 1)) { error_report("Fail to invalidate device iotlb"); } } @@ -971,18 +971,20 @@ static int vhost_memory_region_lookup(struct vhost_dev *hdev, return -EFAULT; } -void vhost_device_iotlb_miss(struct vhost_dev *dev, uint64_t iova, int write) +int vhost_device_iotlb_miss(struct vhost_dev *dev, uint64_t iova, int write) { IOMMUTLBEntry iotlb; uint64_t uaddr, len; + int ret = -EFAULT; rcu_read_lock(); iotlb = address_space_get_iotlb_entry(dev->vdev->dma_as, iova, write); if (iotlb.target_as != NULL) { - if (vhost_memory_region_lookup(dev, iotlb.translated_addr, - &uaddr, &len)) { + ret = vhost_memory_region_lookup(dev, iotlb.translated_addr, + &uaddr, &len); + if (ret) { error_report("Fail to lookup the translated address " "%"PRIx64, iotlb.translated_addr); goto out; @@ -991,14 +993,17 @@ void vhost_device_iotlb_miss(struct vhost_dev *dev, uint64_t iova, int write) len = MIN(iotlb.addr_mask + 1, len); iova = iova & ~iotlb.addr_mask; - if (dev->vhost_ops->vhost_update_device_iotlb(dev, iova, uaddr, - len, iotlb.perm)) { + ret = vhost_backend_update_device_iotlb(dev, iova, uaddr, + len, iotlb.perm); + if (ret) { error_report("Fail to update device iotlb"); goto out; } } out: rcu_read_unlock(); + + return ret; } static int vhost_virtqueue_start(struct vhost_dev *dev, diff --git a/hw/virtio/virtio.c b/hw/virtio/virtio.c index f99d99fd78..464947f76d 100644 --- a/hw/virtio/virtio.c +++ b/hw/virtio/virtio.c @@ -815,6 +815,7 @@ static void *virtqueue_alloc_element(size_t sz, unsigned out_num, unsigned in_nu assert(sz >= sizeof(VirtQueueElement)); elem = g_malloc(out_sg_end); + trace_virtqueue_alloc_element(elem, sz, in_num, out_num); elem->out_num = out_num; elem->in_num = in_num; elem->in_addr = (void *)elem + in_addr_ofs; diff --git a/hw/xen/xen-common.c b/hw/xen/xen-common.c index a9055e9eba..0bed5770c9 100644 --- a/hw/xen/xen-common.c +++ b/hw/xen/xen-common.c @@ -11,7 +11,7 @@ #include "qemu/osdep.h" #include "hw/xen/xen_backend.h" #include "qmp-commands.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "sysemu/accel.h" #include "migration/migration.h" diff --git a/hw/xen/xen_backend.c b/hw/xen/xen_backend.c index 3570f37e56..c46cbb0759 100644 --- a/hw/xen/xen_backend.c +++ b/hw/xen/xen_backend.c @@ -28,7 +28,6 @@ #include "hw/hw.h" #include "hw/sysbus.h" #include "hw/boards.h" -#include "sysemu/char.h" #include "qemu/log.h" #include "qapi/error.h" #include "hw/xen/xen_backend.h" diff --git a/hw/xtensa/sim.c b/hw/xtensa/sim.c index d2d1d3a6fd..5521e9184a 100644 --- a/hw/xtensa/sim.c +++ b/hw/xtensa/sim.c @@ -41,21 +41,21 @@ static void xtensa_create_memory_regions(const XtensaMemory *memory, const char *name) { unsigned i; - char *num_name = malloc(strlen(name) + sizeof(i) * 3 + 1); + GString *num_name = g_string_new(NULL); for (i = 0; i < memory->num; ++i) { MemoryRegion *m; - sprintf(num_name, "%s%u", name, i); - m = g_malloc(sizeof(*m)); - memory_region_init_ram(m, NULL, num_name, + g_string_printf(num_name, "%s%u", name, i); + m = g_new(MemoryRegion, 1); + memory_region_init_ram(m, NULL, num_name->str, memory->location[i].size, &error_fatal); vmstate_register_ram_global(m); memory_region_add_subregion(get_system_memory(), memory->location[i].addr, m); } - free(num_name); + g_string_free(num_name, true); } static uint64_t translate_phys_addr(void *opaque, uint64_t addr) @@ -114,6 +114,9 @@ static void xtensa_sim_init(MachineState *machine) xtensa_create_memory_regions(&sysram, "xtensa.sysram"); } + if (serial_hds[0]) { + xtensa_sim_open_console(serial_hds[0]); + } if (kernel_filename) { uint64_t elf_entry; uint64_t elf_lowaddr; @@ -136,6 +139,7 @@ static void xtensa_sim_machine_init(MachineClass *mc) mc->is_default = true; mc->init = xtensa_sim_init; mc->max_cpus = 4; + mc->no_serial = 1; } DEFINE_MACHINE("sim", xtensa_sim_machine_init) diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c index 4636f8e934..d5ac080d4a 100644 --- a/hw/xtensa/xtfpga.c +++ b/hw/xtensa/xtfpga.c @@ -40,7 +40,7 @@ #include "hw/sysbus.h" #include "hw/block/flash.h" #include "sysemu/block-backend.h" -#include "sysemu/char.h" +#include "chardev/char.h" #include "sysemu/device_tree.h" #include "qemu/error-report.h" #include "bootparam.h" |