ReplicationStatus *qmp_query_xen_replication_status(Error **errp) { #ifdef CONFIG_REPLICATION Error *err = NULL; ReplicationStatus *s = g_new0(ReplicationStatus, 1); replication_get_error_all(&err); if (err) { s->error = true; s->has_desc = true; s->desc = g_strdup(error_get_pretty(err)); } else { s->error = false; } error_free(err); return s; #else abort(); #endif }
/* handle requests/control events coming in over the channel */ static void process_event(JSONMessageParser *parser, GQueue *tokens) { GAState *s = container_of(parser, GAState, parser); QDict *qdict; Error *err = NULL; int ret; g_assert(s && parser); g_debug("process_event: called"); qdict = qobject_to(QDict, json_parser_parse_err(tokens, NULL, &err)); if (err || !qdict) { qobject_unref(qdict); if (!err) { g_warning("failed to parse event: unknown error"); error_setg(&err, QERR_JSON_PARSING); } else { g_warning("failed to parse event: %s", error_get_pretty(err)); } qdict = qmp_error_response(err); } /* handle host->guest commands */ if (qdict_haskey(qdict, "execute")) { process_command(s, qdict); } else { if (!qdict_haskey(qdict, "error")) { qobject_unref(qdict); g_warning("unrecognized payload format"); error_setg(&err, QERR_UNSUPPORTED); qdict = qmp_error_response(err); } ret = send_response(s, qdict); if (ret < 0) { g_warning("error sending error response: %s", strerror(-ret)); } } qobject_unref(qdict); }
/* handle requests/control events coming in over the channel */ static void process_event(JSONMessageParser *parser, GQueue *tokens) { GAState *s = container_of(parser, GAState, parser); QObject *obj; QDict *req, *rsp; Error *err = NULL; int ret; g_assert(s && parser); g_debug("process_event: called"); obj = json_parser_parse_err(tokens, NULL, &err); if (err) { goto err; } req = qobject_to(QDict, obj); if (!req) { error_setg(&err, QERR_JSON_PARSING); goto err; } if (!qdict_haskey(req, "execute")) { g_warning("unrecognized payload format"); error_setg(&err, QERR_UNSUPPORTED); goto err; } process_command(s, req); qobject_unref(obj); return; err: g_warning("failed to parse event: %s", error_get_pretty(err)); rsp = qmp_error_response(err); ret = send_response(s, rsp); if (ret < 0) { g_warning("error sending error response: %s", strerror(-ret)); } qobject_unref(rsp); qobject_unref(obj); }
static void quit_handler(int sig) { /* if we're frozen, don't exit unless we're absolutely forced to, * because it's basically impossible for graceful exit to complete * unless all log/pid files are on unfreezable filesystems. there's * also a very likely chance killing the agent before unfreezing * the filesystems is a mistake (or will be viewed as one later). * On Windows the freeze interval is limited to 10 seconds, so * we should quit, but first we should wait for the timeout, thaw * the filesystem and quit. */ if (ga_is_frozen(ga_state)) { #ifdef _WIN32 int i = 0; Error *err = NULL; HANDLE hEventTimeout; g_debug("Thawing filesystems before exiting"); hEventTimeout = OpenEvent(EVENT_ALL_ACCESS, FALSE, EVENT_NAME_TIMEOUT); if (hEventTimeout) { WaitForSingleObject(hEventTimeout, 0); CloseHandle(hEventTimeout); } qga_vss_fsfreeze(&i, false, &err); if (err) { g_debug("Error unfreezing filesystems prior to exiting: %s", error_get_pretty(err)); error_free(err); } #else return; #endif } g_debug("received signal num %d, quitting", sig); if (g_main_loop_is_running(ga_state->main_loop)) { g_main_loop_quit(ga_state->main_loop); } }
static int vncws_start_tls_handshake(VncState *vs) { Error *err = NULL; if (qcrypto_tls_session_handshake(vs->tls, &err) < 0) { goto error; } switch (qcrypto_tls_session_get_handshake_status(vs->tls)) { case QCRYPTO_TLS_HANDSHAKE_COMPLETE: VNC_DEBUG("Handshake done, checking credentials\n"); if (qcrypto_tls_session_check_credentials(vs->tls, &err) < 0) { goto error; } VNC_DEBUG("Client verification passed, starting TLS I/O\n"); qemu_set_fd_handler(vs->csock, vncws_handshake_read, NULL, vs); break; case QCRYPTO_TLS_HANDSHAKE_RECVING: VNC_DEBUG("Handshake interrupted (blocking read)\n"); qemu_set_fd_handler(vs->csock, vncws_tls_handshake_io, NULL, vs); break; case QCRYPTO_TLS_HANDSHAKE_SENDING: VNC_DEBUG("Handshake interrupted (blocking write)\n"); qemu_set_fd_handler(vs->csock, NULL, vncws_tls_handshake_io, vs); break; } return 0; error: VNC_DEBUG("Handshake failed %s\n", error_get_pretty(err)); error_free(err); vnc_client_error(vs); return -1; }
static void *nbd_client_thread(void *arg) { char *device = arg; off_t size; uint32_t nbdflags; int fd, sock; int ret; pthread_t show_parts_thread; Error *local_error = NULL; sock = socket_connect(saddr, &local_error, NULL, NULL); if (sock < 0) { error_report_err(local_error); goto out; } ret = nbd_receive_negotiate(sock, NULL, &nbdflags, &size, &local_error); if (ret < 0) { if (local_error) { fprintf(stderr, "%s\n", error_get_pretty(local_error)); error_free(local_error); } goto out_socket; } fd = open(device, O_RDWR); if (fd < 0) { /* Linux-only, we can use %m in printf. */ fprintf(stderr, "Failed to open %s: %m\n", device); goto out_socket; } ret = nbd_init(fd, sock, nbdflags, size); if (ret < 0) { goto out_fd; } /* update partition table */ pthread_create(&show_parts_thread, NULL, show_parts, device); if (verbose) { fprintf(stderr, "NBD device %s is now connected to %s\n", device, srcpath); } else { /* Close stderr so that the qemu-nbd process exits. */ dup2(STDOUT_FILENO, STDERR_FILENO); } ret = nbd_client(fd); if (ret) { goto out_fd; } close(fd); kill(getpid(), SIGTERM); return (void *) EXIT_SUCCESS; out_fd: close(fd); out_socket: closesocket(sock); out: kill(getpid(), SIGTERM); return (void *) EXIT_FAILURE; }
int main(int argc, char **argv) { BlockBackend *blk; BlockDriverState *bs; off_t dev_offset = 0; uint32_t nbdflags = 0; bool disconnect = false; const char *bindto = "0.0.0.0"; const char *port = NULL; char *sockpath = NULL; char *device = NULL; off_t fd_size; QemuOpts *sn_opts = NULL; const char *sn_id_or_name = NULL; const char *sopt = "hVb:o:p:rsnP:c:dvk:e:f:tl:"; struct option lopt[] = { { "help", 0, NULL, 'h' }, { "version", 0, NULL, 'V' }, { "bind", 1, NULL, 'b' }, { "port", 1, NULL, 'p' }, { "socket", 1, NULL, 'k' }, { "offset", 1, NULL, 'o' }, { "read-only", 0, NULL, 'r' }, { "partition", 1, NULL, 'P' }, { "connect", 1, NULL, 'c' }, { "disconnect", 0, NULL, 'd' }, { "snapshot", 0, NULL, 's' }, { "load-snapshot", 1, NULL, 'l' }, { "nocache", 0, NULL, 'n' }, { "cache", 1, NULL, QEMU_NBD_OPT_CACHE }, { "aio", 1, NULL, QEMU_NBD_OPT_AIO }, { "discard", 1, NULL, QEMU_NBD_OPT_DISCARD }, { "detect-zeroes", 1, NULL, QEMU_NBD_OPT_DETECT_ZEROES }, { "shared", 1, NULL, 'e' }, { "format", 1, NULL, 'f' }, { "persistent", 0, NULL, 't' }, { "verbose", 0, NULL, 'v' }, { NULL, 0, NULL, 0 } }; int ch; int opt_ind = 0; char *end; int flags = BDRV_O_RDWR; int partition = -1; int ret = 0; int fd; bool seen_cache = false; bool seen_discard = false; bool seen_aio = false; pthread_t client_thread; const char *fmt = NULL; Error *local_err = NULL; BlockdevDetectZeroesOptions detect_zeroes = BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF; QDict *options = NULL; /* The client thread uses SIGTERM to interrupt the server. A signal * handler ensures that "qemu-nbd -v -c" exits with a nice status code. */ struct sigaction sa_sigterm; memset(&sa_sigterm, 0, sizeof(sa_sigterm)); sa_sigterm.sa_handler = termsig_handler; sigaction(SIGTERM, &sa_sigterm, NULL); qemu_init_exec_dir(argv[0]); while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) { switch (ch) { case 's': flags |= BDRV_O_SNAPSHOT; break; case 'n': optarg = (char *) "none"; /* fallthrough */ case QEMU_NBD_OPT_CACHE: if (seen_cache) { errx(EXIT_FAILURE, "-n and --cache can only be specified once"); } seen_cache = true; if (bdrv_parse_cache_flags(optarg, &flags) == -1) { errx(EXIT_FAILURE, "Invalid cache mode `%s'", optarg); } break; case QEMU_NBD_OPT_AIO: if (seen_aio) { errx(EXIT_FAILURE, "--aio can only be specified once"); } seen_aio = true; if (!strcmp(optarg, "native")) { flags |= BDRV_O_NATIVE_AIO; } else if (!strcmp(optarg, "threads")) { /* this is the default */ } else { errx(EXIT_FAILURE, "invalid aio mode `%s'", optarg); } break; case QEMU_NBD_OPT_DISCARD: if (seen_discard) { errx(EXIT_FAILURE, "--discard can only be specified once"); } seen_discard = true; if (bdrv_parse_discard_flags(optarg, &flags) == -1) { errx(EXIT_FAILURE, "Invalid discard mode `%s'", optarg); } break; case QEMU_NBD_OPT_DETECT_ZEROES: detect_zeroes = qapi_enum_parse(BlockdevDetectZeroesOptions_lookup, optarg, BLOCKDEV_DETECT_ZEROES_OPTIONS_MAX, BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF, &local_err); if (local_err) { errx(EXIT_FAILURE, "Failed to parse detect_zeroes mode: %s", error_get_pretty(local_err)); } if (detect_zeroes == BLOCKDEV_DETECT_ZEROES_OPTIONS_UNMAP && !(flags & BDRV_O_UNMAP)) { errx(EXIT_FAILURE, "setting detect-zeroes to unmap is not allowed " "without setting discard operation to unmap"); } break; case 'b': bindto = optarg; break; case 'p': port = optarg; break; case 'o': dev_offset = strtoll (optarg, &end, 0); if (*end) { errx(EXIT_FAILURE, "Invalid offset `%s'", optarg); } if (dev_offset < 0) { errx(EXIT_FAILURE, "Offset must be positive `%s'", optarg); } break; case 'l': if (strstart(optarg, SNAPSHOT_OPT_BASE, NULL)) { sn_opts = qemu_opts_parse_noisily(&internal_snapshot_opts, optarg, false); if (!sn_opts) { errx(EXIT_FAILURE, "Failed in parsing snapshot param `%s'", optarg); } } else { sn_id_or_name = optarg; } /* fall through */ case 'r': nbdflags |= NBD_FLAG_READ_ONLY; flags &= ~BDRV_O_RDWR; break; case 'P': partition = strtol(optarg, &end, 0); if (*end) { errx(EXIT_FAILURE, "Invalid partition `%s'", optarg); } if (partition < 1 || partition > 8) { errx(EXIT_FAILURE, "Invalid partition %d", partition); } break; case 'k': sockpath = optarg; if (sockpath[0] != '/') { errx(EXIT_FAILURE, "socket path must be absolute\n"); } break; case 'd': disconnect = true; break; case 'c': device = optarg; break; case 'e': shared = strtol(optarg, &end, 0); if (*end) { errx(EXIT_FAILURE, "Invalid shared device number '%s'", optarg); } if (shared < 1) { errx(EXIT_FAILURE, "Shared device number must be greater than 0\n"); } break; case 'f': fmt = optarg; break; case 't': persistent = 1; break; case 'v': verbose = 1; break; case 'V': version(argv[0]); exit(0); break; case 'h': usage(argv[0]); exit(0); break; case '?': errx(EXIT_FAILURE, "Try `%s --help' for more information.", argv[0]); } } if ((argc - optind) != 1) { errx(EXIT_FAILURE, "Invalid number of argument.\n" "Try `%s --help' for more information.", argv[0]); } if (disconnect) { fd = open(argv[optind], O_RDWR); if (fd < 0) { err(EXIT_FAILURE, "Cannot open %s", argv[optind]); } nbd_disconnect(fd); close(fd); printf("%s disconnected\n", argv[optind]); return 0; } if (device && !verbose) { int stderr_fd[2]; pid_t pid; int ret; if (qemu_pipe(stderr_fd) < 0) { err(EXIT_FAILURE, "Error setting up communication pipe"); } /* Now daemonize, but keep a communication channel open to * print errors and exit with the proper status code. */ pid = fork(); if (pid < 0) { err(EXIT_FAILURE, "Failed to fork"); } else if (pid == 0) { close(stderr_fd[0]); ret = qemu_daemon(1, 0); /* Temporarily redirect stderr to the parent's pipe... */ dup2(stderr_fd[1], STDERR_FILENO); if (ret < 0) { err(EXIT_FAILURE, "Failed to daemonize"); } /* ... close the descriptor we inherited and go on. */ close(stderr_fd[1]); } else { bool errors = false; char *buf; /* In the parent. Print error messages from the child until * it closes the pipe. */ close(stderr_fd[1]); buf = g_malloc(1024); while ((ret = read(stderr_fd[0], buf, 1024)) > 0) { errors = true; ret = qemu_write_full(STDERR_FILENO, buf, ret); if (ret < 0) { exit(EXIT_FAILURE); } } if (ret < 0) { err(EXIT_FAILURE, "Cannot read from daemon"); } /* Usually the daemon should not print any message. * Exit with zero status in that case. */ exit(errors); } } if (device != NULL && sockpath == NULL) { sockpath = g_malloc(128); snprintf(sockpath, 128, SOCKET_PATH, basename(device)); } saddr = nbd_build_socket_address(sockpath, bindto, port); if (qemu_init_main_loop(&local_err)) { error_report_err(local_err); exit(EXIT_FAILURE); } bdrv_init(); atexit(bdrv_close_all); if (fmt) { options = qdict_new(); qdict_put(options, "driver", qstring_from_str(fmt)); } srcpath = argv[optind]; blk = blk_new_open("hda", srcpath, NULL, options, flags, &local_err); if (!blk) { errx(EXIT_FAILURE, "Failed to blk_new_open '%s': %s", argv[optind], error_get_pretty(local_err)); } bs = blk_bs(blk); if (sn_opts) { ret = bdrv_snapshot_load_tmp(bs, qemu_opt_get(sn_opts, SNAPSHOT_OPT_ID), qemu_opt_get(sn_opts, SNAPSHOT_OPT_NAME), &local_err); } else if (sn_id_or_name) { ret = bdrv_snapshot_load_tmp_by_id_or_name(bs, sn_id_or_name, &local_err); } if (ret < 0) { errno = -ret; err(EXIT_FAILURE, "Failed to load snapshot: %s", error_get_pretty(local_err)); } bs->detect_zeroes = detect_zeroes; fd_size = blk_getlength(blk); if (fd_size < 0) { errx(EXIT_FAILURE, "Failed to determine the image length: %s", strerror(-fd_size)); } if (partition != -1) { ret = find_partition(blk, partition, &dev_offset, &fd_size); if (ret < 0) { errno = -ret; err(EXIT_FAILURE, "Could not find partition %d", partition); } } exp = nbd_export_new(blk, dev_offset, fd_size, nbdflags, nbd_export_closed, &local_err); if (!exp) { errx(EXIT_FAILURE, "%s", error_get_pretty(local_err)); } fd = socket_listen(saddr, &local_err); if (fd < 0) { error_report_err(local_err); return 1; } if (device) { int ret; ret = pthread_create(&client_thread, NULL, nbd_client_thread, device); if (ret != 0) { errx(EXIT_FAILURE, "Failed to create client thread: %s", strerror(ret)); } } else { /* Shut up GCC warnings. */ memset(&client_thread, 0, sizeof(client_thread)); } server_fd = fd; nbd_update_server_fd_handler(fd); /* now when the initialization is (almost) complete, chdir("/") * to free any busy filesystems */ if (chdir("/") < 0) { err(EXIT_FAILURE, "Could not chdir to root directory"); } state = RUNNING; do { main_loop_wait(false); if (state == TERMINATE) { state = TERMINATING; nbd_export_close(exp); nbd_export_put(exp); exp = NULL; } } while (state != TERMINATED); blk_unref(blk); if (sockpath) { unlink(sockpath); } qemu_opts_del(sn_opts); if (device) { void *ret; pthread_join(client_thread, &ret); exit(ret != NULL); } else { exit(EXIT_SUCCESS); } }
static void handle_notify(EventNotifier *e) { VirtIOBlockDataPlane *s = container_of(e, VirtIOBlockDataPlane, host_notifier); VirtIOBlock *vblk = VIRTIO_BLK(s->vdev); event_notifier_test_and_clear(&s->host_notifier); blk_io_plug(s->conf->conf.blk); for (;;) { MultiReqBuffer mrb = { .num_writes = 0, }; int ret; /* Disable guest->host notifies to avoid unnecessary vmexits */ vring_disable_notification(s->vdev, &s->vring); for (;;) { VirtIOBlockReq *req = virtio_blk_alloc_request(vblk); ret = vring_pop(s->vdev, &s->vring, &req->elem); if (ret < 0) { virtio_blk_free_request(req); break; /* no more requests */ } trace_virtio_blk_data_plane_process_request(s, req->elem.out_num, req->elem.in_num, req->elem.index); virtio_blk_handle_request(req, &mrb); } virtio_submit_multiwrite(s->conf->conf.blk, &mrb); if (likely(ret == -EAGAIN)) { /* vring emptied */ /* Re-enable guest->host notifies and stop processing the vring. * But if the guest has snuck in more descriptors, keep processing. */ if (vring_enable_notification(s->vdev, &s->vring)) { break; } } else { /* fatal error */ break; } } blk_io_unplug(s->conf->conf.blk); } /* Context: QEMU global mutex held */ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf, VirtIOBlockDataPlane **dataplane, Error **errp) { VirtIOBlockDataPlane *s; Error *local_err = NULL; BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); *dataplane = NULL; if (!conf->data_plane && !conf->iothread) { return; } /* Don't try if transport does not support notifiers. */ if (!k->set_guest_notifiers || !k->set_host_notifier) { error_setg(errp, "device is incompatible with x-data-plane " "(transport does not support notifiers)"); return; } /* If dataplane is (re-)enabled while the guest is running there could be * block jobs that can conflict. */ if (blk_op_is_blocked(conf->conf.blk, BLOCK_OP_TYPE_DATAPLANE, &local_err)) { error_setg(errp, "cannot start dataplane thread: %s", error_get_pretty(local_err)); error_free(local_err); return; } s = g_new0(VirtIOBlockDataPlane, 1); s->vdev = vdev; s->conf = conf; if (conf->iothread) { s->iothread = conf->iothread; object_ref(OBJECT(s->iothread)); } else { /* Create per-device IOThread if none specified. This is for * x-data-plane option compatibility. If x-data-plane is removed we * can drop this. */ object_initialize(&s->internal_iothread_obj, sizeof(s->internal_iothread_obj), TYPE_IOTHREAD); user_creatable_complete(OBJECT(&s->internal_iothread_obj), &error_abort); s->iothread = &s->internal_iothread_obj; } s->ctx = iothread_get_aio_context(s->iothread); s->bh = aio_bh_new(s->ctx, notify_guest_bh, s); error_setg(&s->blocker, "block device is in use by data plane"); blk_op_block_all(conf->conf.blk, s->blocker); blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_RESIZE, s->blocker); blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_DRIVE_DEL, s->blocker); *dataplane = s; }
static void vhost_scsi_realize(DeviceState *dev, Error **errp) { VirtIOSCSICommon *vs = VIRTIO_SCSI_COMMON(dev); VHostSCSI *s = VHOST_SCSI(dev); Error *err = NULL; int vhostfd = -1; int ret; if (!vs->conf.wwpn) { error_setg(errp, "vhost-scsi: missing wwpn"); return; } if (vs->conf.vhostfd) { vhostfd = monitor_fd_param(cur_mon, vs->conf.vhostfd, &err); if (vhostfd == -1) { error_setg(errp, "vhost-scsi: unable to parse vhostfd: %s", error_get_pretty(err)); error_free(err); return; } } else { vhostfd = open("/dev/vhost-scsi", O_RDWR); if (vhostfd < 0) { error_setg(errp, "vhost-scsi: open vhost char device failed: %s", strerror(errno)); return; } } virtio_scsi_common_realize(dev, &err, vhost_dummy_handle_output, vhost_dummy_handle_output, vhost_dummy_handle_output); if (err != NULL) { error_propagate(errp, err); close(vhostfd); return; } s->dev.nvqs = VHOST_SCSI_VQ_NUM_FIXED + vs->conf.num_queues; s->dev.vqs = g_new(struct vhost_virtqueue, s->dev.nvqs); s->dev.vq_index = 0; s->dev.backend_features = 0; ret = vhost_dev_init(&s->dev, (void *)(uintptr_t)vhostfd, VHOST_BACKEND_TYPE_KERNEL, true); if (ret < 0) { error_setg(errp, "vhost-scsi: vhost initialization failed: %s", strerror(-ret)); return; } /* At present, channel and lun both are 0 for bootable vhost-scsi disk */ s->channel = 0; s->lun = 0; /* Note: we can also get the minimum tpgt from kernel */ s->target = vs->conf.boot_tpgt; error_setg(&s->migration_blocker, "vhost-scsi does not support migration"); migrate_add_blocker(s->migration_blocker); }
int main(int argc, char **argv) { BlockBackend *blk; BlockDriverState *bs; off_t dev_offset = 0; uint16_t nbdflags = 0; bool disconnect = false; const char *bindto = NULL; const char *port = NULL; char *sockpath = NULL; char *device = NULL; off_t fd_size; QemuOpts *sn_opts = NULL; const char *sn_id_or_name = NULL; const char *sopt = "hVb:o:p:rsnP:c:dvk:e:f:tl:x:T:D:"; struct option lopt[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, { "bind", required_argument, NULL, 'b' }, { "port", required_argument, NULL, 'p' }, { "socket", required_argument, NULL, 'k' }, { "offset", required_argument, NULL, 'o' }, { "read-only", no_argument, NULL, 'r' }, { "partition", required_argument, NULL, 'P' }, { "connect", required_argument, NULL, 'c' }, { "disconnect", no_argument, NULL, 'd' }, { "snapshot", no_argument, NULL, 's' }, { "load-snapshot", required_argument, NULL, 'l' }, { "nocache", no_argument, NULL, 'n' }, { "cache", required_argument, NULL, QEMU_NBD_OPT_CACHE }, { "aio", required_argument, NULL, QEMU_NBD_OPT_AIO }, { "discard", required_argument, NULL, QEMU_NBD_OPT_DISCARD }, { "detect-zeroes", required_argument, NULL, QEMU_NBD_OPT_DETECT_ZEROES }, { "shared", required_argument, NULL, 'e' }, { "format", required_argument, NULL, 'f' }, { "persistent", no_argument, NULL, 't' }, { "verbose", no_argument, NULL, 'v' }, { "object", required_argument, NULL, QEMU_NBD_OPT_OBJECT }, { "export-name", required_argument, NULL, 'x' }, { "description", required_argument, NULL, 'D' }, { "tls-creds", required_argument, NULL, QEMU_NBD_OPT_TLSCREDS }, { "image-opts", no_argument, NULL, QEMU_NBD_OPT_IMAGE_OPTS }, { "trace", required_argument, NULL, 'T' }, { "fork", no_argument, NULL, QEMU_NBD_OPT_FORK }, { NULL, 0, NULL, 0 } }; int ch; int opt_ind = 0; char *end; int flags = BDRV_O_RDWR; int partition = -1; int ret = 0; bool seen_cache = false; bool seen_discard = false; bool seen_aio = false; pthread_t client_thread; const char *fmt = NULL; Error *local_err = NULL; BlockdevDetectZeroesOptions detect_zeroes = BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF; QDict *options = NULL; const char *export_name = NULL; const char *export_description = NULL; const char *tlscredsid = NULL; bool imageOpts = false; bool writethrough = true; char *trace_file = NULL; bool fork_process = false; int old_stderr = -1; unsigned socket_activation; /* The client thread uses SIGTERM to interrupt the server. A signal * handler ensures that "qemu-nbd -v -c" exits with a nice status code. */ struct sigaction sa_sigterm; memset(&sa_sigterm, 0, sizeof(sa_sigterm)); sa_sigterm.sa_handler = termsig_handler; sigaction(SIGTERM, &sa_sigterm, NULL); #ifdef CONFIG_POSIX signal(SIGPIPE, SIG_IGN); #endif module_call_init(MODULE_INIT_TRACE); qcrypto_init(&error_fatal); module_call_init(MODULE_INIT_QOM); qemu_add_opts(&qemu_object_opts); qemu_add_opts(&qemu_trace_opts); qemu_init_exec_dir(argv[0]); while ((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) { switch (ch) { case 's': flags |= BDRV_O_SNAPSHOT; break; case 'n': optarg = (char *) "none"; /* fallthrough */ case QEMU_NBD_OPT_CACHE: if (seen_cache) { error_report("-n and --cache can only be specified once"); exit(EXIT_FAILURE); } seen_cache = true; if (bdrv_parse_cache_mode(optarg, &flags, &writethrough) == -1) { error_report("Invalid cache mode `%s'", optarg); exit(EXIT_FAILURE); } break; case QEMU_NBD_OPT_AIO: if (seen_aio) { error_report("--aio can only be specified once"); exit(EXIT_FAILURE); } seen_aio = true; if (!strcmp(optarg, "native")) { flags |= BDRV_O_NATIVE_AIO; } else if (!strcmp(optarg, "threads")) { /* this is the default */ } else { error_report("invalid aio mode `%s'", optarg); exit(EXIT_FAILURE); } break; case QEMU_NBD_OPT_DISCARD: if (seen_discard) { error_report("--discard can only be specified once"); exit(EXIT_FAILURE); } seen_discard = true; if (bdrv_parse_discard_flags(optarg, &flags) == -1) { error_report("Invalid discard mode `%s'", optarg); exit(EXIT_FAILURE); } break; case QEMU_NBD_OPT_DETECT_ZEROES: detect_zeroes = qapi_enum_parse(BlockdevDetectZeroesOptions_lookup, optarg, BLOCKDEV_DETECT_ZEROES_OPTIONS__MAX, BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF, &local_err); if (local_err) { error_reportf_err(local_err, "Failed to parse detect_zeroes mode: "); exit(EXIT_FAILURE); } if (detect_zeroes == BLOCKDEV_DETECT_ZEROES_OPTIONS_UNMAP && !(flags & BDRV_O_UNMAP)) { error_report("setting detect-zeroes to unmap is not allowed " "without setting discard operation to unmap"); exit(EXIT_FAILURE); } break; case 'b': bindto = optarg; break; case 'p': port = optarg; break; case 'o': dev_offset = strtoll (optarg, &end, 0); if (*end) { error_report("Invalid offset `%s'", optarg); exit(EXIT_FAILURE); } if (dev_offset < 0) { error_report("Offset must be positive `%s'", optarg); exit(EXIT_FAILURE); } break; case 'l': if (strstart(optarg, SNAPSHOT_OPT_BASE, NULL)) { sn_opts = qemu_opts_parse_noisily(&internal_snapshot_opts, optarg, false); if (!sn_opts) { error_report("Failed in parsing snapshot param `%s'", optarg); exit(EXIT_FAILURE); } } else { sn_id_or_name = optarg; } /* fall through */ case 'r': nbdflags |= NBD_FLAG_READ_ONLY; flags &= ~BDRV_O_RDWR; break; case 'P': partition = strtol(optarg, &end, 0); if (*end) { error_report("Invalid partition `%s'", optarg); exit(EXIT_FAILURE); } if (partition < 1 || partition > 8) { error_report("Invalid partition %d", partition); exit(EXIT_FAILURE); } break; case 'k': sockpath = optarg; if (sockpath[0] != '/') { error_report("socket path must be absolute"); exit(EXIT_FAILURE); } break; case 'd': disconnect = true; break; case 'c': device = optarg; break; case 'e': shared = strtol(optarg, &end, 0); if (*end) { error_report("Invalid shared device number '%s'", optarg); exit(EXIT_FAILURE); } if (shared < 1) { error_report("Shared device number must be greater than 0"); exit(EXIT_FAILURE); } break; case 'f': fmt = optarg; break; case 't': persistent = 1; break; case 'x': export_name = optarg; break; case 'D': export_description = optarg; break; case 'v': verbose = 1; break; case 'V': version(argv[0]); exit(0); break; case 'h': usage(argv[0]); exit(0); break; case '?': error_report("Try `%s --help' for more information.", argv[0]); exit(EXIT_FAILURE); case QEMU_NBD_OPT_OBJECT: { QemuOpts *opts; opts = qemu_opts_parse_noisily(&qemu_object_opts, optarg, true); if (!opts) { exit(EXIT_FAILURE); } } break; case QEMU_NBD_OPT_TLSCREDS: tlscredsid = optarg; break; case QEMU_NBD_OPT_IMAGE_OPTS: imageOpts = true; break; case 'T': g_free(trace_file); trace_file = trace_opt_parse(optarg); break; case QEMU_NBD_OPT_FORK: fork_process = true; break; } } if ((argc - optind) != 1) { error_report("Invalid number of arguments"); error_printf("Try `%s --help' for more information.\n", argv[0]); exit(EXIT_FAILURE); } if (qemu_opts_foreach(&qemu_object_opts, user_creatable_add_opts_foreach, NULL, NULL)) { exit(EXIT_FAILURE); } if (!trace_init_backends()) { exit(1); } trace_init_file(trace_file); qemu_set_log(LOG_TRACE); socket_activation = check_socket_activation(); if (socket_activation == 0) { setup_address_and_port(&bindto, &port); } else { /* Using socket activation - check user didn't use -p etc. */ const char *err_msg = socket_activation_validate_opts(device, sockpath, bindto, port); if (err_msg != NULL) { error_report("%s", err_msg); exit(EXIT_FAILURE); } /* qemu-nbd can only listen on a single socket. */ if (socket_activation > 1) { error_report("qemu-nbd does not support socket activation with %s > 1", "LISTEN_FDS"); exit(EXIT_FAILURE); } } if (tlscredsid) { if (sockpath) { error_report("TLS is only supported with IPv4/IPv6"); exit(EXIT_FAILURE); } if (device) { error_report("TLS is not supported with a host device"); exit(EXIT_FAILURE); } if (!export_name) { /* Set the default NBD protocol export name, since * we *must* use new style protocol for TLS */ export_name = ""; } tlscreds = nbd_get_tls_creds(tlscredsid, &local_err); if (local_err) { error_report("Failed to get TLS creds %s", error_get_pretty(local_err)); exit(EXIT_FAILURE); } } if (disconnect) { int nbdfd = open(argv[optind], O_RDWR); if (nbdfd < 0) { error_report("Cannot open %s: %s", argv[optind], strerror(errno)); exit(EXIT_FAILURE); } nbd_disconnect(nbdfd); close(nbdfd); printf("%s disconnected\n", argv[optind]); return 0; } if ((device && !verbose) || fork_process) { int stderr_fd[2]; pid_t pid; int ret; if (qemu_pipe(stderr_fd) < 0) { error_report("Error setting up communication pipe: %s", strerror(errno)); exit(EXIT_FAILURE); } /* Now daemonize, but keep a communication channel open to * print errors and exit with the proper status code. */ pid = fork(); if (pid < 0) { error_report("Failed to fork: %s", strerror(errno)); exit(EXIT_FAILURE); } else if (pid == 0) { close(stderr_fd[0]); ret = qemu_daemon(1, 0); /* Temporarily redirect stderr to the parent's pipe... */ old_stderr = dup(STDERR_FILENO); dup2(stderr_fd[1], STDERR_FILENO); if (ret < 0) { error_report("Failed to daemonize: %s", strerror(errno)); exit(EXIT_FAILURE); } /* ... close the descriptor we inherited and go on. */ close(stderr_fd[1]); } else { bool errors = false; char *buf; /* In the parent. Print error messages from the child until * it closes the pipe. */ close(stderr_fd[1]); buf = g_malloc(1024); while ((ret = read(stderr_fd[0], buf, 1024)) > 0) { errors = true; ret = qemu_write_full(STDERR_FILENO, buf, ret); if (ret < 0) { exit(EXIT_FAILURE); } } if (ret < 0) { error_report("Cannot read from daemon: %s", strerror(errno)); exit(EXIT_FAILURE); } /* Usually the daemon should not print any message. * Exit with zero status in that case. */ exit(errors); } } if (device != NULL && sockpath == NULL) { sockpath = g_malloc(128); snprintf(sockpath, 128, SOCKET_PATH, basename(device)); } if (socket_activation == 0) { server_ioc = qio_channel_socket_new(); saddr = nbd_build_socket_address(sockpath, bindto, port); if (qio_channel_socket_listen_sync(server_ioc, saddr, &local_err) < 0) { object_unref(OBJECT(server_ioc)); error_report_err(local_err); return 1; } } else { /* See comment in check_socket_activation above. */ assert(socket_activation == 1); server_ioc = qio_channel_socket_new_fd(FIRST_SOCKET_ACTIVATION_FD, &local_err); if (server_ioc == NULL) { error_report("Failed to use socket activation: %s", error_get_pretty(local_err)); exit(EXIT_FAILURE); } } if (qemu_init_main_loop(&local_err)) { error_report_err(local_err); exit(EXIT_FAILURE); } bdrv_init(); atexit(bdrv_close_all); srcpath = argv[optind]; if (imageOpts) { QemuOpts *opts; if (fmt) { error_report("--image-opts and -f are mutually exclusive"); exit(EXIT_FAILURE); } opts = qemu_opts_parse_noisily(&file_opts, srcpath, true); if (!opts) { qemu_opts_reset(&file_opts); exit(EXIT_FAILURE); } options = qemu_opts_to_qdict(opts, NULL); qemu_opts_reset(&file_opts); blk = blk_new_open(NULL, NULL, options, flags, &local_err); } else { if (fmt) { options = qdict_new(); qdict_put_str(options, "driver", fmt); } blk = blk_new_open(srcpath, NULL, options, flags, &local_err); } if (!blk) { error_reportf_err(local_err, "Failed to blk_new_open '%s': ", argv[optind]); exit(EXIT_FAILURE); } bs = blk_bs(blk); blk_set_enable_write_cache(blk, !writethrough); if (sn_opts) { ret = bdrv_snapshot_load_tmp(bs, qemu_opt_get(sn_opts, SNAPSHOT_OPT_ID), qemu_opt_get(sn_opts, SNAPSHOT_OPT_NAME), &local_err); } else if (sn_id_or_name) { ret = bdrv_snapshot_load_tmp_by_id_or_name(bs, sn_id_or_name, &local_err); } if (ret < 0) { error_reportf_err(local_err, "Failed to load snapshot: "); exit(EXIT_FAILURE); } bs->detect_zeroes = detect_zeroes; fd_size = blk_getlength(blk); if (fd_size < 0) { error_report("Failed to determine the image length: %s", strerror(-fd_size)); exit(EXIT_FAILURE); } if (dev_offset >= fd_size) { error_report("Offset (%lld) has to be smaller than the image size " "(%lld)", (long long int)dev_offset, (long long int)fd_size); exit(EXIT_FAILURE); } fd_size -= dev_offset; if (partition != -1) { ret = find_partition(blk, partition, &dev_offset, &fd_size); if (ret < 0) { error_report("Could not find partition %d: %s", partition, strerror(-ret)); exit(EXIT_FAILURE); } } exp = nbd_export_new(bs, dev_offset, fd_size, nbdflags, nbd_export_closed, writethrough, NULL, &local_err); if (!exp) { error_report_err(local_err); exit(EXIT_FAILURE); } if (export_name) { nbd_export_set_name(exp, export_name); nbd_export_set_description(exp, export_description); newproto = true; } else if (export_description) { error_report("Export description requires an export name"); exit(EXIT_FAILURE); } if (device) { int ret; ret = pthread_create(&client_thread, NULL, nbd_client_thread, device); if (ret != 0) { error_report("Failed to create client thread: %s", strerror(ret)); exit(EXIT_FAILURE); } } else { /* Shut up GCC warnings. */ memset(&client_thread, 0, sizeof(client_thread)); } nbd_update_server_watch(); /* now when the initialization is (almost) complete, chdir("/") * to free any busy filesystems */ if (chdir("/") < 0) { error_report("Could not chdir to root directory: %s", strerror(errno)); exit(EXIT_FAILURE); } if (fork_process) { dup2(old_stderr, STDERR_FILENO); close(old_stderr); } state = RUNNING; do { main_loop_wait(false); if (state == TERMINATE) { state = TERMINATING; nbd_export_close(exp); nbd_export_put(exp); exp = NULL; } } while (state != TERMINATED); blk_unref(blk); if (sockpath) { unlink(sockpath); } qemu_opts_del(sn_opts); if (device) { void *ret; pthread_join(client_thread, &ret); exit(ret != NULL); } else { exit(EXIT_SUCCESS); } }
static void zynq_init(MachineState *machine) { ram_addr_t ram_size = machine->ram_size; const char *cpu_model = machine->cpu_model; const char *kernel_filename = machine->kernel_filename; const char *kernel_cmdline = machine->kernel_cmdline; const char *initrd_filename = machine->initrd_filename; A9MPPrivState *mpcore; ObjectClass *cpu_oc; ARMCPU *cpu[MAX_CPUS]; MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *ext_ram = g_new(MemoryRegion, 1); MemoryRegion *ocm_ram = g_new(MemoryRegion, 1); DeviceState *dev; SysBusDevice *busdev; qemu_irq pic[64]; Error *err = NULL; int n; if (machine->cpu_model) { error_report("Zynq does not support CPU model override!\n"); exit(1); } if (!cpu_model) { cpu_model = "cortex-a9"; } cpu_oc = cpu_class_by_name(TYPE_ARM_CPU, cpu_model); for (n = 0; n < smp_cpus; n++) { cpu[n] = ARM_CPU(object_new(object_class_get_name(cpu_oc))); /* By default A9 CPUs have EL3 enabled. This board does not * currently support EL3 so the CPU EL3 property is disabled before * realization. */ if (object_property_find(OBJECT(cpu[n]), "has_el3", NULL)) { object_property_set_bool(OBJECT(cpu[n]), false, "has_el3", &err); if (err) { error_report("%s", error_get_pretty(err)); exit(1); } } object_property_set_int(OBJECT(cpu[n]), ZYNQ_BOARD_MIDR, "midr", &err); if (err) { error_report("%s", error_get_pretty(err)); exit(1); } object_property_set_int(OBJECT(cpu[n]), MPCORE_PERIPHBASE, "reset-cbar", &err); if (err) { error_report("%s", error_get_pretty(err)); exit(1); } object_property_set_bool(OBJECT(cpu[n]), true, "realized", &err); if (err) { error_report("%s", error_get_pretty(err)); exit(1); } } /* max 2GB ram */ if (ram_size > 0x80000000) { ram_size = 0x80000000; } /* pl353 */ dev = qdev_create(NULL, "arm.pl35x"); /* FIXME: handle this somewhere central */ object_property_add_child(container_get(qdev_get_machine(), "/unattached"), "pl353", OBJECT(dev), NULL); qdev_prop_set_uint8(dev, "x", 3); { DriveInfo *dinfo = drive_get_next(IF_PFLASH); BlockBackend *blk = dinfo ? blk_by_legacy_dinfo(dinfo) : NULL; DeviceState *att_dev = qdev_create(NULL, "cfi.pflash02"); Error *errp = NULL; if (blk && qdev_prop_set_drive(att_dev, "drive", blk)) { abort(); } qdev_prop_set_uint32(att_dev, "num-blocks", FLASH_SIZE/FLASH_SECTOR_SIZE); qdev_prop_set_uint32(att_dev, "sector-length", FLASH_SECTOR_SIZE); qdev_prop_set_uint8(att_dev, "width", 1); qdev_prop_set_uint8(att_dev, "mappings", 1); qdev_prop_set_uint8(att_dev, "big-endian", 0); qdev_prop_set_uint16(att_dev, "id0", 0x0066); qdev_prop_set_uint16(att_dev, "id1", 0x0022); qdev_prop_set_uint16(att_dev, "id2", 0x0000); qdev_prop_set_uint16(att_dev, "id3", 0x0000); qdev_prop_set_uint16(att_dev, "unlock-addr0", 0x0aaa); qdev_prop_set_uint16(att_dev, "unlock-addr1", 0x0555); qdev_prop_set_string(att_dev, "name", "pl353.pflash"); qdev_init_nofail(att_dev); object_property_set_link(OBJECT(dev), OBJECT(att_dev), "dev0", &errp); if (err) { error_report("%s", error_get_pretty(err)); exit(1); } dinfo = drive_get_next(IF_PFLASH); att_dev = nand_init(dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, NAND_MFR_STMICRO, 0xaa); object_property_set_link(OBJECT(dev), OBJECT(att_dev), "dev1", &errp); if (err) { error_report("%s", error_get_pretty(err)); exit(1); } } qdev_init_nofail(dev); busdev = SYS_BUS_DEVICE(dev); sysbus_mmio_map(busdev, 0, 0xe000e000); sysbus_mmio_map(busdev, 1, 0xe2000000); sysbus_mmio_map(busdev, 2, 0xe1000000); /* DDR remapped to address zero. */ memory_region_allocate_system_memory(ext_ram, NULL, "zynq.ext_ram", ram_size); memory_region_add_subregion(address_space_mem, 0, ext_ram); /* 256K of on-chip memory */ memory_region_init_ram(ocm_ram, NULL, "zynq.ocm_ram", 256 << 10, &error_abort); vmstate_register_ram_global(ocm_ram); memory_region_add_subregion(address_space_mem, OCM_BASE, ocm_ram); DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0); /* AMD */ pflash_cfi02_register(0xe2000000, NULL, "zynq.pflash", FLASH_SIZE, dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, FLASH_SECTOR_SIZE, FLASH_SIZE/FLASH_SECTOR_SIZE, 1, 1, 0x0066, 0x0022, 0x0000, 0x0000, 0x0555, 0x2aa, 0); dev = qdev_create(NULL, "xilinx,zynq_slcr"); qdev_init_nofail(dev); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xF8000000); for (n = 0; n < smp_cpus; n++) { qdev_connect_gpio_out(dev, n, qdev_get_gpio_in(DEVICE(cpu[n]), 0)); } mpcore = A9MPCORE_PRIV(object_new("a9mpcore_priv")); qdev_prop_set_uint32(DEVICE(mpcore), "num-cpu", smp_cpus); object_property_set_bool(OBJECT(mpcore), true, "realized", &err); if (err != NULL) { error_report("Couldn't realize the Zynq A9MPCore: %s", error_get_pretty(err)); exit(1); } busdev = SYS_BUS_DEVICE(DEVICE(mpcore)); sysbus_mmio_map(busdev, 0, MPCORE_PERIPHBASE); for (n = 0; n < smp_cpus; n++) { sysbus_connect_irq(busdev, n, qdev_get_gpio_in(DEVICE(cpu[n]), ARM_CPU_IRQ)); } for (n = 0; n < 64; n++) { pic[n] = qdev_get_gpio_in(dev, n); } zynq_init_zc70x_i2c(0xE0004000, pic[57-IRQ_OFFSET]); zynq_init_zc70x_i2c(0xE0005000, pic[80-IRQ_OFFSET]); dev = qdev_create(NULL, "xlnx,ps7-usb"); qdev_init_nofail(dev); busdev = SYS_BUS_DEVICE(dev); sysbus_mmio_map(busdev, 0, 0xE0002000); sysbus_connect_irq(busdev, 0, pic[53-IRQ_OFFSET]); dev = qdev_create(NULL, "xlnx,ps7-usb"); busdev = SYS_BUS_DEVICE(dev); qdev_init_nofail(dev); sysbus_mmio_map(busdev, 0, 0xE0003000); sysbus_connect_irq(busdev, 0, pic[76-IRQ_OFFSET]); zynq_init_spi_flashes(0xE0006000, pic[58-IRQ_OFFSET], false); zynq_init_spi_flashes(0xE0007000, pic[81-IRQ_OFFSET], false); zynq_init_spi_flashes(0xE000D000, pic[51-IRQ_OFFSET], true); sysbus_create_simple("cadence_uart", 0xE0000000, pic[59-IRQ_OFFSET]); sysbus_create_simple("cadence_uart", 0xE0001000, pic[82-IRQ_OFFSET]); sysbus_create_varargs("cadence_ttc", 0xF8001000, pic[42-IRQ_OFFSET], pic[43-IRQ_OFFSET], pic[44-IRQ_OFFSET], NULL); sysbus_create_varargs("cadence_ttc", 0xF8002000, pic[69-IRQ_OFFSET], pic[70-IRQ_OFFSET], pic[71-IRQ_OFFSET], NULL); gem_init(&nd_table[0], 0xE000B000, pic[54-IRQ_OFFSET]); gem_init(&nd_table[1], 0xE000C000, pic[77-IRQ_OFFSET]); dev = qdev_create(NULL, "generic-sdhci"); qdev_init_nofail(dev); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xE0100000); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[56-IRQ_OFFSET]); dev = qdev_create(NULL, "generic-sdhci"); qdev_init_nofail(dev); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xE0101000); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[79-IRQ_OFFSET]); dev = qdev_create(NULL, TYPE_ZYNQ_XADC); qdev_init_nofail(dev); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xF8007100); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[39-IRQ_OFFSET]); dev = qdev_create(NULL, "pl330"); qdev_prop_set_uint8(dev, "num_chnls", 8); qdev_prop_set_uint8(dev, "num_periph_req", 4); qdev_prop_set_uint8(dev, "num_events", 16); qdev_prop_set_uint8(dev, "data_width", 64); qdev_prop_set_uint8(dev, "wr_cap", 8); qdev_prop_set_uint8(dev, "wr_q_dep", 16); qdev_prop_set_uint8(dev, "rd_cap", 8); qdev_prop_set_uint8(dev, "rd_q_dep", 16); qdev_prop_set_uint16(dev, "data_buffer_dep", 256); qdev_init_nofail(dev); busdev = SYS_BUS_DEVICE(dev); sysbus_mmio_map(busdev, 0, 0xF8003000); sysbus_connect_irq(busdev, 0, pic[45-IRQ_OFFSET]); /* abort irq line */ for (n = 0; n < 8; ++n) { /* event irqs */ sysbus_connect_irq(busdev, n + 1, pic[dma_irqs[n] - IRQ_OFFSET]); } dev = qdev_create(NULL, "xlnx.ps7-dev-cfg"); object_property_add_child(qdev_get_machine(), "xilinx-devcfg", OBJECT(dev), NULL); qdev_init_nofail(dev); busdev = SYS_BUS_DEVICE(dev); sysbus_connect_irq(busdev, 0, pic[40-IRQ_OFFSET]); sysbus_mmio_map(busdev, 0, 0xF8007000); zynq_binfo.ram_size = ram_size; zynq_binfo.kernel_filename = kernel_filename; zynq_binfo.kernel_cmdline = kernel_cmdline; zynq_binfo.initrd_filename = initrd_filename; zynq_binfo.nb_cpus = smp_cpus; zynq_binfo.write_secondary_boot = zynq_write_secondary_boot; zynq_binfo.secondary_cpu_reset_hook = zynq_reset_secondary; zynq_binfo.smp_loader_start = SMP_BOOT_ADDR; zynq_binfo.board_id = 0xd32; zynq_binfo.loader_start = 0; arm_load_kernel(ARM_CPU(first_cpu), &zynq_binfo); }
void start_auth_sasl(VncState *vs) { const char *mechlist = NULL; sasl_security_properties_t secprops; int err; char *localAddr, *remoteAddr; int mechlistlen; VNC_DEBUG("Initialize SASL auth %p\n", vs->ioc); /* Get local & remote client addresses in form IPADDR;PORT */ localAddr = vnc_socket_ip_addr_string(vs->sioc, true, NULL); if (!localAddr) { goto authabort; } remoteAddr = vnc_socket_ip_addr_string(vs->sioc, false, NULL); if (!remoteAddr) { g_free(localAddr); goto authabort; } err = sasl_server_new("vnc", NULL, /* FQDN - just delegates to gethostname */ NULL, /* User realm */ localAddr, remoteAddr, NULL, /* Callbacks, not needed */ SASL_SUCCESS_DATA, &vs->sasl.conn); g_free(localAddr); g_free(remoteAddr); localAddr = remoteAddr = NULL; if (err != SASL_OK) { VNC_DEBUG("sasl context setup failed %d (%s)", err, sasl_errstring(err, NULL, NULL)); vs->sasl.conn = NULL; goto authabort; } /* Inform SASL that we've got an external SSF layer from TLS/x509 */ if (vs->auth == VNC_AUTH_VENCRYPT && vs->subauth == VNC_AUTH_VENCRYPT_X509SASL) { Error *local_err = NULL; int keysize; sasl_ssf_t ssf; keysize = qcrypto_tls_session_get_key_size(vs->tls, &local_err); if (keysize < 0) { VNC_DEBUG("cannot TLS get cipher size: %s\n", error_get_pretty(local_err)); error_free(local_err); sasl_dispose(&vs->sasl.conn); vs->sasl.conn = NULL; goto authabort; } ssf = keysize * CHAR_BIT; /* tls key size is bytes, sasl wants bits */ err = sasl_setprop(vs->sasl.conn, SASL_SSF_EXTERNAL, &ssf); if (err != SASL_OK) { VNC_DEBUG("cannot set SASL external SSF %d (%s)\n", err, sasl_errstring(err, NULL, NULL)); sasl_dispose(&vs->sasl.conn); vs->sasl.conn = NULL; goto authabort; } } else { vs->sasl.wantSSF = 1; } memset (&secprops, 0, sizeof secprops); /* Inform SASL that we've got an external SSF layer from TLS. * * Disable SSF, if using TLS+x509+SASL only. TLS without x509 * is not sufficiently strong */ if (vs->vd->is_unix || (vs->auth == VNC_AUTH_VENCRYPT && vs->subauth == VNC_AUTH_VENCRYPT_X509SASL)) { /* If we've got TLS or UNIX domain sock, we don't care about SSF */ secprops.min_ssf = 0; secprops.max_ssf = 0; secprops.maxbufsize = 8192; secprops.security_flags = 0; } else { /* Plain TCP, better get an SSF layer */ secprops.min_ssf = 56; /* Good enough to require kerberos */ secprops.max_ssf = 100000; /* Arbitrary big number */ secprops.maxbufsize = 8192; /* Forbid any anonymous or trivially crackable auth */ secprops.security_flags = SASL_SEC_NOANONYMOUS | SASL_SEC_NOPLAINTEXT; } err = sasl_setprop(vs->sasl.conn, SASL_SEC_PROPS, &secprops); if (err != SASL_OK) { VNC_DEBUG("cannot set SASL security props %d (%s)\n", err, sasl_errstring(err, NULL, NULL)); sasl_dispose(&vs->sasl.conn); vs->sasl.conn = NULL; goto authabort; } err = sasl_listmech(vs->sasl.conn, NULL, /* Don't need to set user */ "", /* Prefix */ ",", /* Separator */ "", /* Suffix */ &mechlist, NULL, NULL); if (err != SASL_OK) { VNC_DEBUG("cannot list SASL mechanisms %d (%s)\n", err, sasl_errdetail(vs->sasl.conn)); sasl_dispose(&vs->sasl.conn); vs->sasl.conn = NULL; goto authabort; } VNC_DEBUG("Available mechanisms for client: '%s'\n", mechlist); vs->sasl.mechlist = g_strdup(mechlist); mechlistlen = strlen(mechlist); vnc_write_u32(vs, mechlistlen); vnc_write(vs, mechlist, mechlistlen); vnc_flush(vs); VNC_DEBUG("Wait for client mechname length\n"); vnc_read_when(vs, protocol_client_auth_sasl_mechname_len, 4); return; authabort: vnc_client_error(vs); }
/* Context: QEMU global mutex held */ void virtio_blk_data_plane_create(VirtIODevice *vdev, VirtIOBlkConf *conf, VirtIOBlockDataPlane **dataplane, Error **errp) { VirtIOBlockDataPlane *s; Error *local_err = NULL; BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); *dataplane = NULL; if (!conf->data_plane && !conf->iothread) { return; } /* Don't try if transport does not support notifiers. */ if (!k->set_guest_notifiers || !k->set_host_notifier) { error_setg(errp, "device is incompatible with x-data-plane " "(transport does not support notifiers)"); return; } /* If dataplane is (re-)enabled while the guest is running there could be * block jobs that can conflict. */ if (blk_op_is_blocked(conf->conf.blk, BLOCK_OP_TYPE_DATAPLANE, &local_err)) { error_setg(errp, "cannot start dataplane thread: %s", error_get_pretty(local_err)); error_free(local_err); return; } s = g_new0(VirtIOBlockDataPlane, 1); s->vdev = vdev; s->conf = conf; if (conf->iothread) { s->iothread = conf->iothread; object_ref(OBJECT(s->iothread)); } else { /* Create per-device IOThread if none specified. This is for * x-data-plane option compatibility. If x-data-plane is removed we * can drop this. */ object_initialize(&s->internal_iothread_obj, sizeof(s->internal_iothread_obj), TYPE_IOTHREAD); user_creatable_complete(OBJECT(&s->internal_iothread_obj), &error_abort); s->iothread = &s->internal_iothread_obj; } s->ctx = iothread_get_aio_context(s->iothread); s->bh = aio_bh_new(s->ctx, notify_guest_bh, s); error_setg(&s->blocker, "block device is in use by data plane"); blk_op_block_all(conf->conf.blk, s->blocker); blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_RESIZE, s->blocker); blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_DRIVE_DEL, s->blocker); blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_BACKUP_SOURCE, s->blocker); blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_CHANGE, s->blocker); blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_COMMIT_SOURCE, s->blocker); blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_COMMIT_TARGET, s->blocker); blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_EJECT, s->blocker); blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_EXTERNAL_SNAPSHOT, s->blocker); blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT, s->blocker); blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_INTERNAL_SNAPSHOT_DELETE, s->blocker); blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_MIRROR, s->blocker); blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_STREAM, s->blocker); blk_op_unblock(conf->conf.blk, BLOCK_OP_TYPE_REPLACE, s->blocker); *dataplane = s; }
int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname) { char line[1024], group[64], id[64], arg[64], value[1024]; Location loc; QemuOptsList *list = NULL; Error *local_err = NULL; QemuOpts *opts = NULL; int res = -1, lno = 0; loc_push_none(&loc); while (fgets(line, sizeof(line), fp) != NULL) { loc_set_file(fname, ++lno); if (line[0] == '\n') { /* skip empty lines */ continue; } if (line[0] == '#') { /* comment */ continue; } if (sscanf(line, "[%63s \"%63[^\"]\"]", group, id) == 2) { /* group with id */ list = find_list(lists, group, &local_err); if (error_is_set(&local_err)) { error_report("%s\n", error_get_pretty(local_err)); error_free(local_err); goto out; } opts = qemu_opts_create(list, id, 1, NULL); continue; } if (sscanf(line, "[%63[^]]]", group) == 1) { /* group without id */ list = find_list(lists, group, &local_err); if (error_is_set(&local_err)) { error_report("%s\n", error_get_pretty(local_err)); error_free(local_err); goto out; } opts = qemu_opts_create(list, NULL, 0, NULL); continue; } if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2) { /* arg = value */ if (opts == NULL) { error_report("no group defined"); goto out; } if (qemu_opt_set(opts, arg, value) != 0) { goto out; } continue; } error_report("parse error"); goto out; } if (ferror(fp)) { error_report("error reading file"); goto out; } res = 0; out: loc_pop(&loc); return res; }
static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) { BCM2835PeripheralState *s = BCM2835_PERIPHERALS(dev); Object *obj; MemoryRegion *ram; Error *err = NULL; uint64_t ram_size, vcram_size; int n; obj = object_property_get_link(OBJECT(dev), "ram", &err); if (obj == NULL) { error_setg(errp, "%s: required ram link not found: %s", __func__, error_get_pretty(err)); return; } ram = MEMORY_REGION(obj); ram_size = memory_region_size(ram); /* Map peripherals and RAM into the GPU address space. */ memory_region_init_alias(&s->peri_mr_alias, OBJECT(s), "bcm2835-peripherals", &s->peri_mr, 0, memory_region_size(&s->peri_mr)); memory_region_add_subregion_overlap(&s->gpu_bus_mr, BCM2835_VC_PERI_BASE, &s->peri_mr_alias, 1); /* RAM is aliased four times (different cache configurations) on the GPU */ for (n = 0; n < 4; n++) { memory_region_init_alias(&s->ram_alias[n], OBJECT(s), "bcm2835-gpu-ram-alias[*]", ram, 0, ram_size); memory_region_add_subregion_overlap(&s->gpu_bus_mr, (hwaddr)n << 30, &s->ram_alias[n], 0); } /* Interrupt Controller */ object_property_set_bool(OBJECT(&s->ic), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, ARMCTRL_IC_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->ic), 0)); sysbus_pass_irq(SYS_BUS_DEVICE(s), SYS_BUS_DEVICE(&s->ic)); /* UART0 */ qdev_prop_set_chr(DEVICE(s->uart0), "chardev", serial_hds[0]); object_property_set_bool(OBJECT(s->uart0), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, UART0_OFFSET, sysbus_mmio_get_region(s->uart0, 0)); sysbus_connect_irq(s->uart0, 0, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_UART)); /* AUX / UART1 */ qdev_prop_set_chr(DEVICE(&s->aux), "chardev", serial_hds[1]); object_property_set_bool(OBJECT(&s->aux), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, UART1_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->aux), 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->aux), 0, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_AUX)); /* Mailboxes */ object_property_set_bool(OBJECT(&s->mboxes), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, ARMCTRL_0_SBM_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mboxes), 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->mboxes), 0, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_ARM_IRQ, INTERRUPT_ARM_MAILBOX)); /* Framebuffer */ vcram_size = object_property_get_uint(OBJECT(s), "vcram-size", &err); if (err) { error_propagate(errp, err); return; } object_property_set_uint(OBJECT(&s->fb), ram_size - vcram_size, "vcram-base", &err); if (err) { error_propagate(errp, err); return; } object_property_set_bool(OBJECT(&s->fb), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->mbox_mr, MBOX_CHAN_FB << MBOX_AS_CHAN_SHIFT, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->fb), 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->fb), 0, qdev_get_gpio_in(DEVICE(&s->mboxes), MBOX_CHAN_FB)); /* Property channel */ object_property_set_bool(OBJECT(&s->property), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->mbox_mr, MBOX_CHAN_PROPERTY << MBOX_AS_CHAN_SHIFT, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->property), 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->property), 0, qdev_get_gpio_in(DEVICE(&s->mboxes), MBOX_CHAN_PROPERTY)); /* Random Number Generator */ object_property_set_bool(OBJECT(&s->rng), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, RNG_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->rng), 0)); /* Extended Mass Media Controller */ object_property_set_int(OBJECT(&s->sdhci), BCM2835_SDHC_CAPAREG, "capareg", &err); if (err) { error_propagate(errp, err); return; } object_property_set_bool(OBJECT(&s->sdhci), true, "pending-insert-quirk", &err); if (err) { error_propagate(errp, err); return; } object_property_set_bool(OBJECT(&s->sdhci), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, EMMC_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->sdhci), 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci), 0, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_ARASANSDIO)); /* SDHOST */ object_property_set_bool(OBJECT(&s->sdhost), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, MMCI0_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->sdhost), 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhost), 0, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_SDIO)); /* DMA Channels */ object_property_set_bool(OBJECT(&s->dma), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, DMA_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dma), 0)); memory_region_add_subregion(&s->peri_mr, DMA15_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dma), 1)); for (n = 0; n <= 12; n++) { sysbus_connect_irq(SYS_BUS_DEVICE(&s->dma), n, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_DMA0 + n)); } /* GPIO */ object_property_set_bool(OBJECT(&s->gpio), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, GPIO_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->gpio), 0)); object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->gpio), "sd-bus", &err); if (err) { error_propagate(errp, err); return; } }
QObject *qmp_build_error_object(Error *err) { return qobject_from_jsonf("{ 'class': %s, 'desc': %s }", ErrorClass_lookup[error_get_class(err)], error_get_pretty(err)); }
static int blk_connect(struct XenDevice *xendev) { struct XenBlkDev *blkdev = container_of(xendev, struct XenBlkDev, xendev); int index, qflags; bool readonly = true; bool writethrough = true; int order, ring_ref; unsigned int ring_size, max_grants; unsigned int i; trace_xen_disk_connect(xendev->name); /* read-only ? */ if (blkdev->directiosafe) { qflags = BDRV_O_NOCACHE | BDRV_O_NATIVE_AIO; } else { qflags = 0; writethrough = false; } if (strcmp(blkdev->mode, "w") == 0) { qflags |= BDRV_O_RDWR; readonly = false; } if (blkdev->feature_discard) { qflags |= BDRV_O_UNMAP; } /* init qemu block driver */ index = (xendev->dev - 202 * 256) / 16; blkdev->dinfo = drive_get(IF_XEN, 0, index); if (!blkdev->dinfo) { Error *local_err = NULL; QDict *options = NULL; if (strcmp(blkdev->fileproto, "<unset>")) { options = qdict_new(); qdict_put_str(options, "driver", blkdev->fileproto); } /* setup via xenbus -> create new block driver instance */ xen_pv_printf(xendev, 2, "create new bdrv (xenbus setup)\n"); blkdev->blk = blk_new_open(blkdev->filename, NULL, options, qflags, &local_err); if (!blkdev->blk) { xen_pv_printf(xendev, 0, "error: %s\n", error_get_pretty(local_err)); error_free(local_err); return -1; } blk_set_enable_write_cache(blkdev->blk, !writethrough); } else { /* setup via qemu cmdline -> already setup for us */ xen_pv_printf(xendev, 2, "get configured bdrv (cmdline setup)\n"); blkdev->blk = blk_by_legacy_dinfo(blkdev->dinfo); if (blk_is_read_only(blkdev->blk) && !readonly) { xen_pv_printf(xendev, 0, "Unexpected read-only drive"); blkdev->blk = NULL; return -1; } /* blkdev->blk is not create by us, we get a reference * so we can blk_unref() unconditionally */ blk_ref(blkdev->blk); } blk_attach_dev_legacy(blkdev->blk, blkdev); blkdev->file_size = blk_getlength(blkdev->blk); if (blkdev->file_size < 0) { BlockDriverState *bs = blk_bs(blkdev->blk); const char *drv_name = bs ? bdrv_get_format_name(bs) : NULL; xen_pv_printf(xendev, 1, "blk_getlength: %d (%s) | drv %s\n", (int)blkdev->file_size, strerror(-blkdev->file_size), drv_name ?: "-"); blkdev->file_size = 0; }
static void bcm2836_realize(DeviceState *dev, Error **errp) { BCM2836State *s = BCM2836(dev); Object *obj; Error *err = NULL; int n; /* common peripherals from bcm2835 */ obj = OBJECT(dev); for (n = 0; n < BCM2836_NCPUS; n++) { object_initialize(&s->cpus[n], sizeof(s->cpus[n]), s->cpu_type); object_property_add_child(obj, "cpu[*]", OBJECT(&s->cpus[n]), &error_abort); } obj = object_property_get_link(OBJECT(dev), "ram", &err); if (obj == NULL) { error_setg(errp, "%s: required ram link not found: %s", __func__, error_get_pretty(err)); return; } object_property_add_const_link(OBJECT(&s->peripherals), "ram", obj, &err); if (err) { error_propagate(errp, err); return; } object_property_set_bool(OBJECT(&s->peripherals), true, "realized", &err); if (err) { error_propagate(errp, err); return; } object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->peripherals), "sd-bus", &err); if (err) { error_propagate(errp, err); return; } sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->peripherals), 0, BCM2836_PERI_BASE, 1); /* bcm2836 interrupt controller (and mailboxes, etc.) */ object_property_set_bool(OBJECT(&s->control), true, "realized", &err); if (err) { error_propagate(errp, err); return; } sysbus_mmio_map(SYS_BUS_DEVICE(&s->control), 0, BCM2836_CONTROL_BASE); sysbus_connect_irq(SYS_BUS_DEVICE(&s->peripherals), 0, qdev_get_gpio_in_named(DEVICE(&s->control), "gpu-irq", 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->peripherals), 1, qdev_get_gpio_in_named(DEVICE(&s->control), "gpu-fiq", 0)); for (n = 0; n < BCM2836_NCPUS; n++) { /* Mirror bcm2836, which has clusterid set to 0xf * TODO: this should be converted to a property of ARM_CPU */ s->cpus[n].mp_affinity = 0xF00 | n; /* set periphbase/CBAR value for CPU-local registers */ object_property_set_int(OBJECT(&s->cpus[n]), BCM2836_PERI_BASE + MCORE_OFFSET, "reset-cbar", &err); if (err) { error_propagate(errp, err); return; } /* start powered off if not enabled */ object_property_set_bool(OBJECT(&s->cpus[n]), n >= s->enabled_cpus, "start-powered-off", &err); if (err) { error_propagate(errp, err); return; } object_property_set_bool(OBJECT(&s->cpus[n]), true, "realized", &err); if (err) { error_propagate(errp, err); return; } /* Connect irq/fiq outputs from the interrupt controller. */ qdev_connect_gpio_out_named(DEVICE(&s->control), "irq", n, qdev_get_gpio_in(DEVICE(&s->cpus[n]), ARM_CPU_IRQ)); qdev_connect_gpio_out_named(DEVICE(&s->control), "fiq", n, qdev_get_gpio_in(DEVICE(&s->cpus[n]), ARM_CPU_FIQ)); /* Connect timers from the CPU to the interrupt controller */ qdev_connect_gpio_out(DEVICE(&s->cpus[n]), GTIMER_PHYS, qdev_get_gpio_in_named(DEVICE(&s->control), "cntpnsirq", n)); qdev_connect_gpio_out(DEVICE(&s->cpus[n]), GTIMER_VIRT, qdev_get_gpio_in_named(DEVICE(&s->control), "cntvirq", n)); qdev_connect_gpio_out(DEVICE(&s->cpus[n]), GTIMER_HYP, qdev_get_gpio_in_named(DEVICE(&s->control), "cnthpirq", n)); qdev_connect_gpio_out(DEVICE(&s->cpus[n]), GTIMER_SEC, qdev_get_gpio_in_named(DEVICE(&s->control), "cntpsirq", n)); } }
/* test deep nesting with refs to other user-defined types */ static void test_nested_structs(void) { QmpOutputVisitor *mo; QmpInputVisitor *mi; Visitor *v; UserDefOne ud1; UserDefOne *ud1_p = &ud1, *ud1c_p = NULL; UserDefTwo ud2; UserDefTwo *ud2_p = &ud2, *ud2c_p = NULL; Error *err = NULL; QObject *obj; QString *str; ud1.integer = 42; ud1.string = strdup("fourty two"); /* sanity check */ mo = qmp_output_visitor_new(); v = qmp_output_get_visitor(mo); visit_type_UserDefOne(v, &ud1_p, "o_O", &err); if (err) { g_error("%s", error_get_pretty(err)); } obj = qmp_output_get_qobject(mo); g_assert(obj); qobject_decref(obj); ud2.string = strdup("fourty three"); ud2.dict.string = strdup("fourty four"); ud2.dict.dict.userdef = ud1_p; ud2.dict.dict.string = strdup("fourty five"); ud2.dict.has_dict2 = true; ud2.dict.dict2.userdef = ud1_p; ud2.dict.dict2.string = strdup("fourty six"); /* c type -> qobject */ mo = qmp_output_visitor_new(); v = qmp_output_get_visitor(mo); visit_type_UserDefTwo(v, &ud2_p, "unused", &err); if (err) { g_error("%s", error_get_pretty(err)); } obj = qmp_output_get_qobject(mo); g_assert(obj); str = qobject_to_json_pretty(obj); g_print("%s\n", qstring_get_str(str)); QDECREF(str); /* qobject -> c type, should match original struct */ mi = qmp_input_visitor_new(obj); v = qmp_input_get_visitor(mi); visit_type_UserDefTwo(v, &ud2c_p, NULL, &err); if (err) { g_error("%s", error_get_pretty(err)); } g_assert(!g_strcmp0(ud2c_p->string, ud2.string)); g_assert(!g_strcmp0(ud2c_p->dict.string, ud2.dict.string)); ud1c_p = ud2c_p->dict.dict.userdef; g_assert(ud1c_p->integer == ud1_p->integer); g_assert(!g_strcmp0(ud1c_p->string, ud1_p->string)); g_assert(!g_strcmp0(ud2c_p->dict.dict.string, ud2.dict.dict.string)); ud1c_p = ud2c_p->dict.dict2.userdef; g_assert(ud1c_p->integer == ud1_p->integer); g_assert(!g_strcmp0(ud1c_p->string, ud1_p->string)); g_assert(!g_strcmp0(ud2c_p->dict.dict2.string, ud2.dict.dict2.string)); g_free(ud1.string); g_free(ud2.string); g_free(ud2.dict.string); g_free(ud2.dict.dict.string); g_free(ud2.dict.dict2.string); qapi_free_UserDefTwo(ud2c_p); qobject_decref(obj); }
static void boston_mach_init(MachineState *machine) { DeviceState *dev; BostonState *s; Error *err = NULL; const char *cpu_model; MemoryRegion *flash, *ddr, *ddr_low_alias, *lcd, *platreg; MemoryRegion *sys_mem = get_system_memory(); XilinxPCIEHost *pcie2; PCIDevice *ahci; DriveInfo *hd[6]; Chardev *chr; int fw_size, fit_err; bool is_64b; if ((machine->ram_size % G_BYTE) || (machine->ram_size > (2 * G_BYTE))) { error_report("Memory size must be 1GB or 2GB"); exit(1); } cpu_model = machine->cpu_model ?: "I6400"; dev = qdev_create(NULL, TYPE_MIPS_BOSTON); qdev_init_nofail(dev); s = BOSTON(dev); s->mach = machine; s->cps = g_new0(MIPSCPSState, 1); if (!cpu_supports_cps_smp(cpu_model)) { error_report("Boston requires CPUs which support CPS"); exit(1); } is_64b = cpu_supports_isa(cpu_model, ISA_MIPS64); object_initialize(s->cps, sizeof(MIPSCPSState), TYPE_MIPS_CPS); qdev_set_parent_bus(DEVICE(s->cps), sysbus_get_default()); object_property_set_str(OBJECT(s->cps), cpu_model, "cpu-model", &err); object_property_set_int(OBJECT(s->cps), smp_cpus, "num-vp", &err); object_property_set_bool(OBJECT(s->cps), true, "realized", &err); if (err != NULL) { error_report("%s", error_get_pretty(err)); exit(1); } sysbus_mmio_map_overlap(SYS_BUS_DEVICE(s->cps), 0, 0, 1); flash = g_new(MemoryRegion, 1); memory_region_init_rom_device(flash, NULL, &boston_flash_ops, s, "boston.flash", 128 * M_BYTE, &err); memory_region_add_subregion_overlap(sys_mem, 0x18000000, flash, 0); ddr = g_new(MemoryRegion, 1); memory_region_allocate_system_memory(ddr, NULL, "boston.ddr", machine->ram_size); memory_region_add_subregion_overlap(sys_mem, 0x80000000, ddr, 0); ddr_low_alias = g_new(MemoryRegion, 1); memory_region_init_alias(ddr_low_alias, NULL, "boston_low.ddr", ddr, 0, MIN(machine->ram_size, (256 * M_BYTE))); memory_region_add_subregion_overlap(sys_mem, 0, ddr_low_alias, 0); xilinx_pcie_init(sys_mem, 0, 0x10000000, 32 * M_BYTE, 0x40000000, 1 * G_BYTE, get_cps_irq(s->cps, 2), false); xilinx_pcie_init(sys_mem, 1, 0x12000000, 32 * M_BYTE, 0x20000000, 512 * M_BYTE, get_cps_irq(s->cps, 1), false); pcie2 = xilinx_pcie_init(sys_mem, 2, 0x14000000, 32 * M_BYTE, 0x16000000, 1 * M_BYTE, get_cps_irq(s->cps, 0), true); platreg = g_new(MemoryRegion, 1); memory_region_init_io(platreg, NULL, &boston_platreg_ops, s, "boston-platregs", 0x1000); memory_region_add_subregion_overlap(sys_mem, 0x17ffd000, platreg, 0); if (!serial_hds[0]) { serial_hds[0] = qemu_chr_new("serial0", "null"); } s->uart = serial_mm_init(sys_mem, 0x17ffe000, 2, get_cps_irq(s->cps, 3), 10000000, serial_hds[0], DEVICE_NATIVE_ENDIAN); lcd = g_new(MemoryRegion, 1); memory_region_init_io(lcd, NULL, &boston_lcd_ops, s, "boston-lcd", 0x8); memory_region_add_subregion_overlap(sys_mem, 0x17fff000, lcd, 0); chr = qemu_chr_new("lcd", "vc:320x240"); qemu_chr_fe_init(&s->lcd_display, chr, NULL); qemu_chr_fe_set_handlers(&s->lcd_display, NULL, NULL, boston_lcd_event, s, NULL, true); ahci = pci_create_simple_multifunction(&PCI_BRIDGE(&pcie2->root)->sec_bus, PCI_DEVFN(0, 0), true, TYPE_ICH9_AHCI); g_assert(ARRAY_SIZE(hd) == ICH_AHCI(ahci)->ahci.ports); ide_drive_get(hd, ICH_AHCI(ahci)->ahci.ports); ahci_ide_create_devs(ahci, hd); if (machine->firmware) { fw_size = load_image_targphys(machine->firmware, 0x1fc00000, 4 * M_BYTE); if (fw_size == -1) { error_printf("unable to load firmware image '%s'\n", machine->firmware); exit(1); } } else if (machine->kernel_filename) { fit_err = load_fit(&boston_fit_loader, machine->kernel_filename, s); if (fit_err) { error_printf("unable to load FIT image\n"); exit(1); } gen_firmware(memory_region_get_ram_ptr(flash) + 0x7c00000, s->kernel_entry, s->fdt_base, is_64b); } else if (!qtest_enabled()) { error_printf("Please provide either a -kernel or -bios argument\n"); exit(1); } }
/* test core visitor methods */ static void test_visitor_core(void) { QmpOutputVisitor *mo; QmpInputVisitor *mi; Visitor *v; TestStruct ts = { 42, 82 }; TestStruct *pts = &ts; TestStructList *lts = NULL; Error *err = NULL; QObject *obj; QList *qlist; QDict *qdict; QString *str; int64_t value = 0; mo = qmp_output_visitor_new(); v = qmp_output_get_visitor(mo); visit_type_TestStruct(v, &pts, NULL, &err); obj = qmp_output_get_qobject(mo); str = qobject_to_json(obj); printf("%s\n", qstring_get_str(str)); QDECREF(str); obj = QOBJECT(qint_from_int(0x42)); mi = qmp_input_visitor_new(obj); v = qmp_input_get_visitor(mi); visit_type_int(v, &value, NULL, &err); if (err) { g_error("%s", error_get_pretty(err)); } g_assert(value == 0x42); qobject_decref(obj); obj = qobject_from_json("{'x': 42, 'y': 84}"); mi = qmp_input_visitor_new(obj); v = qmp_input_get_visitor(mi); pts = NULL; visit_type_TestStruct(v, &pts, NULL, &err); if (err) { g_error("%s", error_get_pretty(err)); } g_assert(pts != NULL); g_assert(pts->x == 42); g_assert(pts->y == 84); qobject_decref(obj); g_free(pts); /* test list input visitor */ obj = qobject_from_json("[{'x': 42, 'y': 84}, {'x': 12, 'y': 24}]"); mi = qmp_input_visitor_new(obj); v = qmp_input_get_visitor(mi); visit_type_TestStructList(v, <s, NULL, &err); if (err) { g_error("%s", error_get_pretty(err)); } g_assert(lts != NULL); g_assert(lts->value->x == 42); g_assert(lts->value->y == 84); g_assert(lts->next != NULL); g_assert(lts->next->value->x == 12); g_assert(lts->next->value->y == 24); g_assert(lts->next->next == NULL); qobject_decref(obj); /* test list output visitor */ mo = qmp_output_visitor_new(); v = qmp_output_get_visitor(mo); visit_type_TestStructList(v, <s, NULL, &err); if (err) { g_error("%s", error_get_pretty(err)); } obj = qmp_output_get_qobject(mo); g_print("obj: %s\n", qstring_get_str(qobject_to_json(obj))); qlist = qobject_to_qlist(obj); assert(qlist); obj = qlist_pop(qlist); qdict = qobject_to_qdict(obj); assert(qdict); assert(qdict_get_int(qdict, "x") == 42); assert(qdict_get_int(qdict, "y") == 84); qobject_decref(obj); obj = qlist_pop(qlist); qdict = qobject_to_qdict(obj); assert(qdict); assert(qdict_get_int(qdict, "x") == 12); assert(qdict_get_int(qdict, "y") == 24); qobject_decref(obj); qmp_output_visitor_cleanup(mo); QDECREF(qlist); }
static void bcm2835_peripherals_realize(DeviceState *dev, Error **errp) { BCM2835PeripheralState *s = BCM2835_PERIPHERALS(dev); Object *obj; MemoryRegion *ram; Error *err = NULL; uint64_t ram_size, vcram_size; int n; obj = object_property_get_link(OBJECT(dev), "ram", &err); if (obj == NULL) { error_setg(errp, "%s: required ram link not found: %s", __func__, error_get_pretty(err)); return; } ram = MEMORY_REGION(obj); ram_size = memory_region_size(ram); /* Map peripherals and RAM into the GPU address space. */ memory_region_init_alias(&s->peri_mr_alias, OBJECT(s), "bcm2835-peripherals", &s->peri_mr, 0, memory_region_size(&s->peri_mr)); memory_region_add_subregion_overlap(&s->gpu_bus_mr, BCM2835_VC_PERI_BASE, &s->peri_mr_alias, 1); /* RAM is aliased four times (different cache configurations) on the GPU */ for (n = 0; n < 4; n++) { memory_region_init_alias(&s->ram_alias[n], OBJECT(s), "bcm2835-gpu-ram-alias[*]", ram, 0, ram_size); memory_region_add_subregion_overlap(&s->gpu_bus_mr, (hwaddr)n << 30, &s->ram_alias[n], 0); } /* Interrupt Controller */ object_property_set_bool(OBJECT(&s->ic), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, ARMCTRL_IC_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->ic), 0)); sysbus_pass_irq(SYS_BUS_DEVICE(s), SYS_BUS_DEVICE(&s->ic)); /* UART0 */ qdev_prop_set_chr(DEVICE(s->uart0), "chardev", serial_hd(0)); object_property_set_bool(OBJECT(s->uart0), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, UART0_OFFSET, sysbus_mmio_get_region(s->uart0, 0)); sysbus_connect_irq(s->uart0, 0, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_UART)); /* AUX / UART1 */ qdev_prop_set_chr(DEVICE(&s->aux), "chardev", serial_hd(1)); object_property_set_bool(OBJECT(&s->aux), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, UART1_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->aux), 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->aux), 0, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_AUX)); /* System timer */ object_property_set_bool(OBJECT(&s->st), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, ST_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->st), 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->st), 0, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_TIMER0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->st), 1, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_TIMER1)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->st), 2, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_TIMER2)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->st), 3, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_TIMER3)); /* ARM timer */ object_property_set_bool(OBJECT(&s->timer), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, ARMCTRL_TIMER0_1_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->timer), 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->timer), 0, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_ARM_IRQ, INTERRUPT_ARM_TIMER)); /* USB controller */ object_property_set_bool(OBJECT(&s->usb), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, USB_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->usb), 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->usb), 0, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_USB)); /* MPHI - Message-based Parallel Host Interface */ object_property_set_bool(OBJECT(&s->mphi), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, MPHI_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mphi), 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->mphi), 0, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_HOSTPORT)); /* Mailboxes */ object_property_set_bool(OBJECT(&s->mboxes), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, ARMCTRL_0_SBM_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->mboxes), 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->mboxes), 0, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_ARM_IRQ, INTERRUPT_ARM_MAILBOX)); /* Power management */ object_property_set_bool(OBJECT(&s->power), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->mbox_mr, MBOX_CHAN_POWER << MBOX_AS_CHAN_SHIFT, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->power), 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->power), 0, qdev_get_gpio_in(DEVICE(&s->mboxes), MBOX_CHAN_POWER)); /* Framebuffer */ vcram_size = object_property_get_uint(OBJECT(s), "vcram-size", &err); if (err) { error_propagate(errp, err); return; } object_property_set_uint(OBJECT(&s->fb), ram_size - vcram_size, "vcram-base", &err); if (err) { error_propagate(errp, err); return; } object_property_set_bool(OBJECT(&s->fb), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->mbox_mr, MBOX_CHAN_FB << MBOX_AS_CHAN_SHIFT, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->fb), 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->fb), 0, qdev_get_gpio_in(DEVICE(&s->mboxes), MBOX_CHAN_FB)); /* Property channel */ object_property_set_bool(OBJECT(&s->property), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->mbox_mr, MBOX_CHAN_PROPERTY << MBOX_AS_CHAN_SHIFT, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->property), 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->property), 0, qdev_get_gpio_in(DEVICE(&s->mboxes), MBOX_CHAN_PROPERTY)); /* Random Number Generator */ object_property_set_bool(OBJECT(&s->rng), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, RNG_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->rng), 0)); /* Extended Mass Media Controller * * Compatible with: * - SD Host Controller Specification Version 3.0 Draft 1.0 * - SDIO Specification Version 3.0 * - MMC Specification Version 4.4 * * For the exact details please refer to the Arasan documentation: * SD3.0_Host_AHB_eMMC4.4_Usersguide_ver5.9_jan11_10.pdf */ object_property_set_uint(OBJECT(&s->sdhci), 3, "sd-spec-version", &err); object_property_set_uint(OBJECT(&s->sdhci), BCM2835_SDHC_CAPAREG, "capareg", &err); object_property_set_bool(OBJECT(&s->sdhci), true, "pending-insert-quirk", &err); if (err) { error_propagate(errp, err); return; } object_property_set_bool(OBJECT(&s->sdhci), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, EMMC_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->sdhci), 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhci), 0, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_ARASANSDIO)); /* SDHOST */ object_property_set_bool(OBJECT(&s->sdhost), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, MMCI0_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->sdhost), 0)); sysbus_connect_irq(SYS_BUS_DEVICE(&s->sdhost), 0, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_SDIO)); /* DMA Channels */ object_property_set_bool(OBJECT(&s->dma), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, DMA_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dma), 0)); memory_region_add_subregion(&s->peri_mr, DMA15_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->dma), 1)); for (n = 0; n <= 12; n++) { sysbus_connect_irq(SYS_BUS_DEVICE(&s->dma), n, qdev_get_gpio_in_named(DEVICE(&s->ic), BCM2835_IC_GPU_IRQ, INTERRUPT_DMA0 + n)); } /* GPIO */ object_property_set_bool(OBJECT(&s->gpio), true, "realized", &err); if (err) { error_propagate(errp, err); return; } memory_region_add_subregion(&s->peri_mr, GPIO_OFFSET, sysbus_mmio_get_region(SYS_BUS_DEVICE(&s->gpio), 0)); object_property_add_alias(OBJECT(s), "sd-bus", OBJECT(&s->gpio), "sd-bus", &err); if (err) { error_propagate(errp, err); return; } }
static void zynq_init(MachineState *machine) { ram_addr_t ram_size = machine->ram_size; const char *cpu_model = machine->cpu_model; const char *kernel_filename = machine->kernel_filename; const char *kernel_cmdline = machine->kernel_cmdline; const char *initrd_filename = machine->initrd_filename; ObjectClass *cpu_oc; ARMCPU *cpu; MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *ext_ram = g_new(MemoryRegion, 1); MemoryRegion *ocm_ram = g_new(MemoryRegion, 1); DeviceState *dev; SysBusDevice *busdev; qemu_irq pic[64]; Error *err = NULL; int n; if (!cpu_model) { cpu_model = "cortex-a9"; } cpu_oc = cpu_class_by_name(TYPE_ARM_CPU, cpu_model); cpu = ARM_CPU(object_new(object_class_get_name(cpu_oc))); /* By default A9 CPUs have EL3 enabled. This board does not * currently support EL3 so the CPU EL3 property is disabled before * realization. */ if (object_property_find(OBJECT(cpu), "has_el3", NULL)) { object_property_set_bool(OBJECT(cpu), false, "has_el3", &err); if (err) { error_report("%s", error_get_pretty(err)); exit(1); } } object_property_set_int(OBJECT(cpu), ZYNQ_BOARD_MIDR, "midr", &err); if (err) { error_report("%s", error_get_pretty(err)); exit(1); } object_property_set_int(OBJECT(cpu), MPCORE_PERIPHBASE, "reset-cbar", &err); if (err) { error_report("%s", error_get_pretty(err)); exit(1); } object_property_set_bool(OBJECT(cpu), true, "realized", &err); if (err) { error_report("%s", error_get_pretty(err)); exit(1); } /* max 2GB ram */ if (ram_size > 0x80000000) { ram_size = 0x80000000; } /* DDR remapped to address zero. */ memory_region_init_ram(ext_ram, NULL, "zynq.ext_ram", ram_size, &error_abort); vmstate_register_ram_global(ext_ram); memory_region_add_subregion(address_space_mem, 0, ext_ram); /* 256K of on-chip memory */ memory_region_init_ram(ocm_ram, NULL, "zynq.ocm_ram", 256 << 10, &error_abort); vmstate_register_ram_global(ocm_ram); memory_region_add_subregion(address_space_mem, 0xFFFC0000, ocm_ram); DriveInfo *dinfo = drive_get(IF_PFLASH, 0, 0); /* AMD */ pflash_cfi02_register(0xe2000000, NULL, "zynq.pflash", FLASH_SIZE, dinfo ? blk_by_legacy_dinfo(dinfo) : NULL, FLASH_SECTOR_SIZE, FLASH_SIZE/FLASH_SECTOR_SIZE, 1, 1, 0x0066, 0x0022, 0x0000, 0x0000, 0x0555, 0x2aa, 0); dev = qdev_create(NULL, "xilinx,zynq_slcr"); qdev_init_nofail(dev); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xF8000000); dev = qdev_create(NULL, "a9mpcore_priv"); qdev_prop_set_uint32(dev, "num-cpu", 1); qdev_init_nofail(dev); busdev = SYS_BUS_DEVICE(dev); sysbus_mmio_map(busdev, 0, MPCORE_PERIPHBASE); sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(DEVICE(cpu), ARM_CPU_IRQ)); for (n = 0; n < 64; n++) { pic[n] = qdev_get_gpio_in(dev, n); } zynq_init_spi_flashes(0xE0006000, pic[58-IRQ_OFFSET], false); zynq_init_spi_flashes(0xE0007000, pic[81-IRQ_OFFSET], false); zynq_init_spi_flashes(0xE000D000, pic[51-IRQ_OFFSET], true); sysbus_create_simple("xlnx,ps7-usb", 0xE0002000, pic[53-IRQ_OFFSET]); sysbus_create_simple("xlnx,ps7-usb", 0xE0003000, pic[76-IRQ_OFFSET]); sysbus_create_simple("cadence_uart", 0xE0000000, pic[59-IRQ_OFFSET]); sysbus_create_simple("cadence_uart", 0xE0001000, pic[82-IRQ_OFFSET]); sysbus_create_varargs("cadence_ttc", 0xF8001000, pic[42-IRQ_OFFSET], pic[43-IRQ_OFFSET], pic[44-IRQ_OFFSET], NULL); sysbus_create_varargs("cadence_ttc", 0xF8002000, pic[69-IRQ_OFFSET], pic[70-IRQ_OFFSET], pic[71-IRQ_OFFSET], NULL); gem_init(&nd_table[0], 0xE000B000, pic[54-IRQ_OFFSET]); gem_init(&nd_table[1], 0xE000C000, pic[77-IRQ_OFFSET]); dev = qdev_create(NULL, "generic-sdhci"); qdev_init_nofail(dev); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xE0100000); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[56-IRQ_OFFSET]); dev = qdev_create(NULL, "generic-sdhci"); qdev_init_nofail(dev); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, 0xE0101000); sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, pic[79-IRQ_OFFSET]); dev = qdev_create(NULL, "pl330"); qdev_prop_set_uint8(dev, "num_chnls", 8); qdev_prop_set_uint8(dev, "num_periph_req", 4); qdev_prop_set_uint8(dev, "num_events", 16); qdev_prop_set_uint8(dev, "data_width", 64); qdev_prop_set_uint8(dev, "wr_cap", 8); qdev_prop_set_uint8(dev, "wr_q_dep", 16); qdev_prop_set_uint8(dev, "rd_cap", 8); qdev_prop_set_uint8(dev, "rd_q_dep", 16); qdev_prop_set_uint16(dev, "data_buffer_dep", 256); qdev_init_nofail(dev); busdev = SYS_BUS_DEVICE(dev); sysbus_mmio_map(busdev, 0, 0xF8003000); sysbus_connect_irq(busdev, 0, pic[45-IRQ_OFFSET]); /* abort irq line */ for (n = 0; n < 8; ++n) { /* event irqs */ sysbus_connect_irq(busdev, n + 1, pic[dma_irqs[n] - IRQ_OFFSET]); } zynq_binfo.ram_size = ram_size; zynq_binfo.kernel_filename = kernel_filename; zynq_binfo.kernel_cmdline = kernel_cmdline; zynq_binfo.initrd_filename = initrd_filename; zynq_binfo.nb_cpus = 1; zynq_binfo.board_id = 0xd32; zynq_binfo.loader_start = 0; arm_load_kernel(ARM_CPU(first_cpu), &zynq_binfo); }
static void realview_init(MachineState *machine, enum realview_board_type board_type) { ARMCPU *cpu = NULL; CPUARMState *env; ObjectClass *cpu_oc; MemoryRegion *sysmem = get_system_memory(); MemoryRegion *ram_lo = g_new(MemoryRegion, 1); MemoryRegion *ram_hi = g_new(MemoryRegion, 1); MemoryRegion *ram_alias = g_new(MemoryRegion, 1); MemoryRegion *ram_hack = g_new(MemoryRegion, 1); DeviceState *dev, *sysctl, *gpio2, *pl041; SysBusDevice *busdev; qemu_irq pic[64]; qemu_irq mmc_irq[2]; PCIBus *pci_bus = NULL; NICInfo *nd; I2CBus *i2c; int n; int done_nic = 0; qemu_irq cpu_irq[4]; int is_mpcore = 0; int is_pb = 0; uint32_t proc_id = 0; uint32_t sys_id; ram_addr_t low_ram_size; ram_addr_t ram_size = machine->ram_size; hwaddr periphbase = 0; switch (board_type) { case BOARD_EB: break; case BOARD_EB_MPCORE: is_mpcore = 1; periphbase = 0x10100000; break; case BOARD_PB_A8: is_pb = 1; break; case BOARD_PBX_A9: is_mpcore = 1; is_pb = 1; periphbase = 0x1f000000; break; } cpu_oc = cpu_class_by_name(TYPE_ARM_CPU, machine->cpu_model); if (!cpu_oc) { fprintf(stderr, "Unable to find CPU definition\n"); exit(1); } for (n = 0; n < smp_cpus; n++) { Object *cpuobj = object_new(object_class_get_name(cpu_oc)); Error *err = NULL; if (is_pb && is_mpcore) { object_property_set_int(cpuobj, periphbase, "reset-cbar", &err); if (err) { error_report("%s", error_get_pretty(err)); exit(1); } } object_property_set_bool(cpuobj, true, "realized", &err); if (err) { error_report("%s", error_get_pretty(err)); exit(1); } cpu_irq[n] = qdev_get_gpio_in(DEVICE(cpuobj), ARM_CPU_IRQ); } cpu = ARM_CPU(first_cpu); env = &cpu->env; if (arm_feature(env, ARM_FEATURE_V7)) { if (is_mpcore) { proc_id = 0x0c000000; } else { proc_id = 0x0e000000; } } else if (arm_feature(env, ARM_FEATURE_V6K)) { proc_id = 0x06000000; } else if (arm_feature(env, ARM_FEATURE_V6)) { proc_id = 0x04000000; } else { proc_id = 0x02000000; } if (is_pb && ram_size > 0x20000000) { /* Core tile RAM. */ low_ram_size = ram_size - 0x20000000; ram_size = 0x20000000; memory_region_init_ram(ram_lo, NULL, "realview.lowmem", low_ram_size, &error_abort); vmstate_register_ram_global(ram_lo); memory_region_add_subregion(sysmem, 0x20000000, ram_lo); } memory_region_init_ram(ram_hi, NULL, "realview.highmem", ram_size, &error_abort); vmstate_register_ram_global(ram_hi); low_ram_size = ram_size; if (low_ram_size > 0x10000000) low_ram_size = 0x10000000; /* SDRAM at address zero. */ memory_region_init_alias(ram_alias, NULL, "realview.alias", ram_hi, 0, low_ram_size); memory_region_add_subregion(sysmem, 0, ram_alias); if (is_pb) { /* And again at a high address. */ memory_region_add_subregion(sysmem, 0x70000000, ram_hi); } else { ram_size = low_ram_size; } sys_id = is_pb ? 0x01780500 : 0xc1400400; sysctl = qdev_create(NULL, "realview_sysctl"); qdev_prop_set_uint32(sysctl, "sys_id", sys_id); qdev_prop_set_uint32(sysctl, "proc_id", proc_id); qdev_init_nofail(sysctl); sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, 0x10000000); if (is_mpcore) { dev = qdev_create(NULL, is_pb ? "a9mpcore_priv": "realview_mpcore"); qdev_prop_set_uint32(dev, "num-cpu", smp_cpus); qdev_init_nofail(dev); busdev = SYS_BUS_DEVICE(dev); sysbus_mmio_map(busdev, 0, periphbase); for (n = 0; n < smp_cpus; n++) { sysbus_connect_irq(busdev, n, cpu_irq[n]); } sysbus_create_varargs("l2x0", periphbase + 0x2000, NULL); /* Both A9 and 11MPCore put the GIC CPU i/f at base + 0x100 */ realview_binfo.gic_cpu_if_addr = periphbase + 0x100; } else { uint32_t gic_addr = is_pb ? 0x1e000000 : 0x10040000; /* For now just create the nIRQ GIC, and ignore the others. */ dev = sysbus_create_simple("realview_gic", gic_addr, cpu_irq[0]); } for (n = 0; n < 64; n++) { pic[n] = qdev_get_gpio_in(dev, n); } pl041 = qdev_create(NULL, "pl041"); qdev_prop_set_uint32(pl041, "nc_fifo_depth", 512); qdev_init_nofail(pl041); sysbus_mmio_map(SYS_BUS_DEVICE(pl041), 0, 0x10004000); sysbus_connect_irq(SYS_BUS_DEVICE(pl041), 0, pic[19]); sysbus_create_simple("pl050_keyboard", 0x10006000, pic[20]); sysbus_create_simple("pl050_mouse", 0x10007000, pic[21]); sysbus_create_simple("pl011", 0x10009000, pic[12]); sysbus_create_simple("pl011", 0x1000a000, pic[13]); sysbus_create_simple("pl011", 0x1000b000, pic[14]); sysbus_create_simple("pl011", 0x1000c000, pic[15]); /* DMA controller is optional, apparently. */ sysbus_create_simple("pl081", 0x10030000, pic[24]); sysbus_create_simple("sp804", 0x10011000, pic[4]); sysbus_create_simple("sp804", 0x10012000, pic[5]); sysbus_create_simple("pl061", 0x10013000, pic[6]); sysbus_create_simple("pl061", 0x10014000, pic[7]); gpio2 = sysbus_create_simple("pl061", 0x10015000, pic[8]); sysbus_create_simple("pl111", 0x10020000, pic[23]); dev = sysbus_create_varargs("pl181", 0x10005000, pic[17], pic[18], NULL); /* Wire up MMC card detect and read-only signals. These have * to go to both the PL061 GPIO and the sysctl register. * Note that the PL181 orders these lines (readonly,inserted) * and the PL061 has them the other way about. Also the card * detect line is inverted. */ mmc_irq[0] = qemu_irq_split( qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_WPROT), qdev_get_gpio_in(gpio2, 1)); mmc_irq[1] = qemu_irq_split( qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_CARDIN), qemu_irq_invert(qdev_get_gpio_in(gpio2, 0))); qdev_connect_gpio_out(dev, 0, mmc_irq[0]); qdev_connect_gpio_out(dev, 1, mmc_irq[1]); sysbus_create_simple("pl031", 0x10017000, pic[10]); if (!is_pb) { dev = qdev_create(NULL, "realview_pci"); busdev = SYS_BUS_DEVICE(dev); qdev_init_nofail(dev); sysbus_mmio_map(busdev, 0, 0x10019000); /* PCI controller registers */ sysbus_mmio_map(busdev, 1, 0x60000000); /* PCI self-config */ sysbus_mmio_map(busdev, 2, 0x61000000); /* PCI config */ sysbus_mmio_map(busdev, 3, 0x62000000); /* PCI I/O */ sysbus_mmio_map(busdev, 4, 0x63000000); /* PCI memory window 1 */ sysbus_mmio_map(busdev, 5, 0x64000000); /* PCI memory window 2 */ sysbus_mmio_map(busdev, 6, 0x68000000); /* PCI memory window 3 */ sysbus_connect_irq(busdev, 0, pic[48]); sysbus_connect_irq(busdev, 1, pic[49]); sysbus_connect_irq(busdev, 2, pic[50]); sysbus_connect_irq(busdev, 3, pic[51]); pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci"); if (usb_enabled(false)) { pci_create_simple(pci_bus, -1, "pci-ohci"); } n = drive_get_max_bus(IF_SCSI); while (n >= 0) { pci_create_simple(pci_bus, -1, "lsi53c895a"); n--; } } for(n = 0; n < nb_nics; n++) { nd = &nd_table[n]; if (!done_nic && (!nd->model || strcmp(nd->model, is_pb ? "lan9118" : "smc91c111") == 0)) { if (is_pb) { lan9118_init(nd, 0x4e000000, pic[28]); } else { smc91c111_init(nd, 0x4e000000, pic[28]); } done_nic = 1; } else { if (pci_bus) { pci_nic_init_nofail(nd, pci_bus, "rtl8139", NULL); } } } dev = sysbus_create_simple("versatile_i2c", 0x10002000, NULL); i2c = (I2CBus *)qdev_get_child_bus(dev, "i2c"); i2c_create_slave(i2c, "ds1338", 0x68); /* Memory map for RealView Emulation Baseboard: */ /* 0x10000000 System registers. */ /* 0x10001000 System controller. */ /* 0x10002000 Two-Wire Serial Bus. */ /* 0x10003000 Reserved. */ /* 0x10004000 AACI. */ /* 0x10005000 MCI. */ /* 0x10006000 KMI0. */ /* 0x10007000 KMI1. */ /* 0x10008000 Character LCD. (EB) */ /* 0x10009000 UART0. */ /* 0x1000a000 UART1. */ /* 0x1000b000 UART2. */ /* 0x1000c000 UART3. */ /* 0x1000d000 SSPI. */ /* 0x1000e000 SCI. */ /* 0x1000f000 Reserved. */ /* 0x10010000 Watchdog. */ /* 0x10011000 Timer 0+1. */ /* 0x10012000 Timer 2+3. */ /* 0x10013000 GPIO 0. */ /* 0x10014000 GPIO 1. */ /* 0x10015000 GPIO 2. */ /* 0x10002000 Two-Wire Serial Bus - DVI. (PB) */ /* 0x10017000 RTC. */ /* 0x10018000 DMC. */ /* 0x10019000 PCI controller config. */ /* 0x10020000 CLCD. */ /* 0x10030000 DMA Controller. */ /* 0x10040000 GIC1. (EB) */ /* 0x10050000 GIC2. (EB) */ /* 0x10060000 GIC3. (EB) */ /* 0x10070000 GIC4. (EB) */ /* 0x10080000 SMC. */ /* 0x1e000000 GIC1. (PB) */ /* 0x1e001000 GIC2. (PB) */ /* 0x1e002000 GIC3. (PB) */ /* 0x1e003000 GIC4. (PB) */ /* 0x40000000 NOR flash. */ /* 0x44000000 DoC flash. */ /* 0x48000000 SRAM. */ /* 0x4c000000 Configuration flash. */ /* 0x4e000000 Ethernet. */ /* 0x4f000000 USB. */ /* 0x50000000 PISMO. */ /* 0x54000000 PISMO. */ /* 0x58000000 PISMO. */ /* 0x5c000000 PISMO. */ /* 0x60000000 PCI. */ /* 0x60000000 PCI Self Config. */ /* 0x61000000 PCI Config. */ /* 0x62000000 PCI IO. */ /* 0x63000000 PCI mem 0. */ /* 0x64000000 PCI mem 1. */ /* 0x68000000 PCI mem 2. */ /* ??? Hack to map an additional page of ram for the secondary CPU startup code. I guess this works on real hardware because the BootROM happens to be in ROM/flash or in memory that isn't clobbered until after Linux boots the secondary CPUs. */ memory_region_init_ram(ram_hack, NULL, "realview.hack", 0x1000, &error_abort); vmstate_register_ram_global(ram_hack); memory_region_add_subregion(sysmem, SMP_BOOT_ADDR, ram_hack); realview_binfo.ram_size = ram_size; realview_binfo.kernel_filename = machine->kernel_filename; realview_binfo.kernel_cmdline = machine->kernel_cmdline; realview_binfo.initrd_filename = machine->initrd_filename; realview_binfo.nb_cpus = smp_cpus; realview_binfo.board_id = realview_board_id[board_type]; realview_binfo.loader_start = (board_type == BOARD_PB_A8 ? 0x70000000 : 0); arm_load_kernel(ARM_CPU(first_cpu), &realview_binfo); }
static gboolean ga_channel_open(GAChannel *c, const gchar *path, GAChannelMethod method) { int ret; c->method = method; switch (c->method) { case GA_CHANNEL_VIRTIO_SERIAL: { int fd = qemu_open(path, O_RDWR | O_NONBLOCK #ifndef CONFIG_SOLARIS | O_ASYNC #endif ); if (fd == -1) { g_critical("error opening channel: %s", strerror(errno)); return false; } #ifdef CONFIG_SOLARIS ret = ioctl(fd, I_SETSIG, S_OUTPUT | S_INPUT | S_HIPRI); if (ret == -1) { g_critical("error setting event mask for channel: %s", strerror(errno)); close(fd); return false; } #endif ret = ga_channel_client_add(c, fd); if (ret) { g_critical("error adding channel to main loop"); close(fd); return false; } break; } case GA_CHANNEL_ISA_SERIAL: { struct termios tio; int fd = qemu_open(path, O_RDWR | O_NOCTTY | O_NONBLOCK); if (fd == -1) { g_critical("error opening channel: %s", strerror(errno)); return false; } tcgetattr(fd, &tio); /* set up serial port for non-canonical, dumb byte streaming */ tio.c_iflag &= ~(IGNBRK | BRKINT | IGNPAR | PARMRK | INPCK | ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXOFF | IXANY | IMAXBEL); tio.c_oflag = 0; tio.c_lflag = 0; tio.c_cflag |= GA_CHANNEL_BAUDRATE_DEFAULT; /* 1 available byte min or reads will block (we'll set non-blocking * elsewhere, else we have to deal with read()=0 instead) */ tio.c_cc[VMIN] = 1; tio.c_cc[VTIME] = 0; /* flush everything waiting for read/xmit, it's garbage at this point */ tcflush(fd, TCIFLUSH); tcsetattr(fd, TCSANOW, &tio); ret = ga_channel_client_add(c, fd); if (ret) { g_critical("error adding channel to main loop"); close(fd); return false; } break; } case GA_CHANNEL_UNIX_LISTEN: { Error *local_err = NULL; int fd = unix_listen(path, NULL, strlen(path), &local_err); if (local_err != NULL) { g_critical("%s", error_get_pretty(local_err)); error_free(local_err); return false; } ga_channel_listen_add(c, fd, true); break; } default: g_critical("error binding/listening to specified socket"); return false; } return true; }
/* * This tests sanity checking of our own certificates * * The code being tested is used when TLS creds are created, * and aim to ensure QMEU has been configured with sane * certificates. This allows us to give much much much * clearer error messages to the admin when they misconfigure * things. */ static void test_tls_creds(const void *opaque) { struct QCryptoTLSCredsTestData *data = (struct QCryptoTLSCredsTestData *)opaque; QCryptoTLSCreds *creds; Error *err = NULL; #define CERT_DIR "tests/test-crypto-tlscredsx509-certs/" mkdir(CERT_DIR, 0700); unlink(CERT_DIR QCRYPTO_TLS_CREDS_X509_CA_CERT); if (data->isServer) { unlink(CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_CERT); unlink(CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_KEY); } else { unlink(CERT_DIR QCRYPTO_TLS_CREDS_X509_CLIENT_CERT); unlink(CERT_DIR QCRYPTO_TLS_CREDS_X509_CLIENT_KEY); } if (access(data->cacrt, R_OK) == 0) { g_assert(link(data->cacrt, CERT_DIR QCRYPTO_TLS_CREDS_X509_CA_CERT) == 0); } if (data->isServer) { if (access(data->crt, R_OK) == 0) { g_assert(link(data->crt, CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_CERT) == 0); } g_assert(link(KEYFILE, CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_KEY) == 0); } else { if (access(data->crt, R_OK) == 0) { g_assert(link(data->crt, CERT_DIR QCRYPTO_TLS_CREDS_X509_CLIENT_CERT) == 0); } g_assert(link(KEYFILE, CERT_DIR QCRYPTO_TLS_CREDS_X509_CLIENT_KEY) == 0); } creds = test_tls_creds_create( (data->isServer ? QCRYPTO_TLS_CREDS_ENDPOINT_SERVER : QCRYPTO_TLS_CREDS_ENDPOINT_CLIENT), CERT_DIR, &err); if (data->expectFail) { error_free(err); g_assert(creds == NULL); } else { if (err) { g_printerr("Failed to generate creds: %s\n", error_get_pretty(err)); error_free(err); } g_assert(creds != NULL); } unlink(CERT_DIR QCRYPTO_TLS_CREDS_X509_CA_CERT); if (data->isServer) { unlink(CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_CERT); unlink(CERT_DIR QCRYPTO_TLS_CREDS_X509_SERVER_KEY); } else { unlink(CERT_DIR QCRYPTO_TLS_CREDS_X509_CLIENT_CERT); unlink(CERT_DIR QCRYPTO_TLS_CREDS_X509_CLIENT_KEY); } rmdir(CERT_DIR); if (creds) { object_unparent(OBJECT(creds)); } }
Exynos4210State *exynos4210_init(MemoryRegion *system_mem, unsigned long ram_size) { int i, n; Exynos4210State *s = g_new(Exynos4210State, 1); qemu_irq gate_irq[EXYNOS4210_NCPUS][EXYNOS4210_IRQ_GATE_NINPUTS]; unsigned long mem_size; DeviceState *dev; SysBusDevice *busdev; ObjectClass *cpu_oc; cpu_oc = cpu_class_by_name(TYPE_ARM_CPU, "cortex-a9"); assert(cpu_oc); for (n = 0; n < EXYNOS4210_NCPUS; n++) { Object *cpuobj = object_new(object_class_get_name(cpu_oc)); Error *err = NULL; /* By default A9 CPUs have EL3 enabled. This board does not currently * support EL3 so the CPU EL3 property is disabled before realization. */ if (object_property_find(cpuobj, "has_el3", NULL)) { object_property_set_bool(cpuobj, false, "has_el3", &err); if (err) { error_report("%s", error_get_pretty(err)); exit(1); } } s->cpu[n] = ARM_CPU(cpuobj); object_property_set_int(cpuobj, EXYNOS4210_SMP_PRIVATE_BASE_ADDR, "reset-cbar", &error_abort); object_property_set_bool(cpuobj, true, "realized", &err); if (err) { error_report("%s", error_get_pretty(err)); exit(1); } } /*** IRQs ***/ s->irq_table = exynos4210_init_irq(&s->irqs); /* IRQ Gate */ for (i = 0; i < EXYNOS4210_NCPUS; i++) { dev = qdev_create(NULL, "exynos4210.irq_gate"); qdev_prop_set_uint32(dev, "n_in", EXYNOS4210_IRQ_GATE_NINPUTS); qdev_init_nofail(dev); /* Get IRQ Gate input in gate_irq */ for (n = 0; n < EXYNOS4210_IRQ_GATE_NINPUTS; n++) { gate_irq[i][n] = qdev_get_gpio_in(dev, n); } busdev = SYS_BUS_DEVICE(dev); /* Connect IRQ Gate output to CPU's IRQ line */ sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(DEVICE(s->cpu[i]), ARM_CPU_IRQ)); } /* Private memory region and Internal GIC */ dev = qdev_create(NULL, "a9mpcore_priv"); qdev_prop_set_uint32(dev, "num-cpu", EXYNOS4210_NCPUS); qdev_init_nofail(dev); busdev = SYS_BUS_DEVICE(dev); sysbus_mmio_map(busdev, 0, EXYNOS4210_SMP_PRIVATE_BASE_ADDR); for (n = 0; n < EXYNOS4210_NCPUS; n++) { sysbus_connect_irq(busdev, n, gate_irq[n][0]); } for (n = 0; n < EXYNOS4210_INT_GIC_NIRQ; n++) { s->irqs.int_gic_irq[n] = qdev_get_gpio_in(dev, n); } /* Cache controller */ sysbus_create_simple("l2x0", EXYNOS4210_L2X0_BASE_ADDR, NULL); /* External GIC */ dev = qdev_create(NULL, "exynos4210.gic"); qdev_prop_set_uint32(dev, "num-cpu", EXYNOS4210_NCPUS); qdev_init_nofail(dev); busdev = SYS_BUS_DEVICE(dev); /* Map CPU interface */ sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_GIC_CPU_BASE_ADDR); /* Map Distributer interface */ sysbus_mmio_map(busdev, 1, EXYNOS4210_EXT_GIC_DIST_BASE_ADDR); for (n = 0; n < EXYNOS4210_NCPUS; n++) { sysbus_connect_irq(busdev, n, gate_irq[n][1]); } for (n = 0; n < EXYNOS4210_EXT_GIC_NIRQ; n++) { s->irqs.ext_gic_irq[n] = qdev_get_gpio_in(dev, n); } /* Internal Interrupt Combiner */ dev = qdev_create(NULL, "exynos4210.combiner"); qdev_init_nofail(dev); busdev = SYS_BUS_DEVICE(dev); for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) { sysbus_connect_irq(busdev, n, s->irqs.int_gic_irq[n]); } exynos4210_combiner_get_gpioin(&s->irqs, dev, 0); sysbus_mmio_map(busdev, 0, EXYNOS4210_INT_COMBINER_BASE_ADDR); /* External Interrupt Combiner */ dev = qdev_create(NULL, "exynos4210.combiner"); qdev_prop_set_uint32(dev, "external", 1); qdev_init_nofail(dev); busdev = SYS_BUS_DEVICE(dev); for (n = 0; n < EXYNOS4210_MAX_INT_COMBINER_OUT_IRQ; n++) { sysbus_connect_irq(busdev, n, s->irqs.ext_gic_irq[n]); } exynos4210_combiner_get_gpioin(&s->irqs, dev, 1); sysbus_mmio_map(busdev, 0, EXYNOS4210_EXT_COMBINER_BASE_ADDR); /* Initialize board IRQs. */ exynos4210_init_board_irqs(&s->irqs); /*** Memory ***/ /* Chip-ID and OMR */ memory_region_init_io(&s->chipid_mem, NULL, &exynos4210_chipid_and_omr_ops, NULL, "exynos4210.chipid", sizeof(chipid_and_omr)); memory_region_add_subregion(system_mem, EXYNOS4210_CHIPID_ADDR, &s->chipid_mem); /* Internal ROM */ memory_region_init_ram(&s->irom_mem, NULL, "exynos4210.irom", EXYNOS4210_IROM_SIZE, &error_abort); vmstate_register_ram_global(&s->irom_mem); memory_region_set_readonly(&s->irom_mem, true); memory_region_add_subregion(system_mem, EXYNOS4210_IROM_BASE_ADDR, &s->irom_mem); /* mirror of iROM */ memory_region_init_alias(&s->irom_alias_mem, NULL, "exynos4210.irom_alias", &s->irom_mem, 0, EXYNOS4210_IROM_SIZE); memory_region_set_readonly(&s->irom_alias_mem, true); memory_region_add_subregion(system_mem, EXYNOS4210_IROM_MIRROR_BASE_ADDR, &s->irom_alias_mem); /* Internal RAM */ memory_region_init_ram(&s->iram_mem, NULL, "exynos4210.iram", EXYNOS4210_IRAM_SIZE, &error_abort); vmstate_register_ram_global(&s->iram_mem); memory_region_add_subregion(system_mem, EXYNOS4210_IRAM_BASE_ADDR, &s->iram_mem); /* DRAM */ mem_size = ram_size; if (mem_size > EXYNOS4210_DRAM_MAX_SIZE) { memory_region_init_ram(&s->dram1_mem, NULL, "exynos4210.dram1", mem_size - EXYNOS4210_DRAM_MAX_SIZE, &error_abort); vmstate_register_ram_global(&s->dram1_mem); memory_region_add_subregion(system_mem, EXYNOS4210_DRAM1_BASE_ADDR, &s->dram1_mem); mem_size = EXYNOS4210_DRAM_MAX_SIZE; } memory_region_init_ram(&s->dram0_mem, NULL, "exynos4210.dram0", mem_size, &error_abort); vmstate_register_ram_global(&s->dram0_mem); memory_region_add_subregion(system_mem, EXYNOS4210_DRAM0_BASE_ADDR, &s->dram0_mem); /* PMU. * The only reason of existence at the moment is that secondary CPU boot * loader uses PMU INFORM5 register as a holding pen. */ sysbus_create_simple("exynos4210.pmu", EXYNOS4210_PMU_BASE_ADDR, NULL); /* PWM */ sysbus_create_varargs("exynos4210.pwm", EXYNOS4210_PWM_BASE_ADDR, s->irq_table[exynos4210_get_irq(22, 0)], s->irq_table[exynos4210_get_irq(22, 1)], s->irq_table[exynos4210_get_irq(22, 2)], s->irq_table[exynos4210_get_irq(22, 3)], s->irq_table[exynos4210_get_irq(22, 4)], NULL); /* RTC */ sysbus_create_varargs("exynos4210.rtc", EXYNOS4210_RTC_BASE_ADDR, s->irq_table[exynos4210_get_irq(23, 0)], s->irq_table[exynos4210_get_irq(23, 1)], NULL); /* Multi Core Timer */ dev = qdev_create(NULL, "exynos4210.mct"); qdev_init_nofail(dev); busdev = SYS_BUS_DEVICE(dev); for (n = 0; n < 4; n++) { /* Connect global timer interrupts to Combiner gpio_in */ sysbus_connect_irq(busdev, n, s->irq_table[exynos4210_get_irq(1, 4 + n)]); } /* Connect local timer interrupts to Combiner gpio_in */ sysbus_connect_irq(busdev, 4, s->irq_table[exynos4210_get_irq(51, 0)]); sysbus_connect_irq(busdev, 5, s->irq_table[exynos4210_get_irq(35, 3)]); sysbus_mmio_map(busdev, 0, EXYNOS4210_MCT_BASE_ADDR); /*** I2C ***/ for (n = 0; n < EXYNOS4210_I2C_NUMBER; n++) { uint32_t addr = EXYNOS4210_I2C_BASE_ADDR + EXYNOS4210_I2C_SHIFT * n; qemu_irq i2c_irq; if (n < 8) { i2c_irq = s->irq_table[exynos4210_get_irq(EXYNOS4210_I2C_INTG, n)]; } else { i2c_irq = s->irq_table[exynos4210_get_irq(EXYNOS4210_HDMI_INTG, 1)]; } dev = qdev_create(NULL, "exynos4210.i2c"); qdev_init_nofail(dev); busdev = SYS_BUS_DEVICE(dev); sysbus_connect_irq(busdev, 0, i2c_irq); sysbus_mmio_map(busdev, 0, addr); s->i2c_if[n] = (I2CBus *)qdev_get_child_bus(dev, "i2c"); } /*** UARTs ***/ exynos4210_uart_create(EXYNOS4210_UART0_BASE_ADDR, EXYNOS4210_UART0_FIFO_SIZE, 0, NULL, s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 0)]); exynos4210_uart_create(EXYNOS4210_UART1_BASE_ADDR, EXYNOS4210_UART1_FIFO_SIZE, 1, NULL, s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 1)]); exynos4210_uart_create(EXYNOS4210_UART2_BASE_ADDR, EXYNOS4210_UART2_FIFO_SIZE, 2, NULL, s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 2)]); exynos4210_uart_create(EXYNOS4210_UART3_BASE_ADDR, EXYNOS4210_UART3_FIFO_SIZE, 3, NULL, s->irq_table[exynos4210_get_irq(EXYNOS4210_UART_INT_GRP, 3)]); /*** Display controller (FIMD) ***/ sysbus_create_varargs("exynos4210.fimd", EXYNOS4210_FIMD0_BASE_ADDR, s->irq_table[exynos4210_get_irq(11, 0)], s->irq_table[exynos4210_get_irq(11, 1)], s->irq_table[exynos4210_get_irq(11, 2)], NULL); sysbus_create_simple(TYPE_EXYNOS4210_EHCI, EXYNOS4210_EHCI_BASE_ADDR, s->irq_table[exynos4210_get_irq(28, 3)]); return s; }
static void acpi_memory_hotplug_write(void *opaque, hwaddr addr, uint64_t data, unsigned int size) { MemHotplugState *mem_st = opaque; MemStatus *mdev; ACPIOSTInfo *info; DeviceState *dev = NULL; HotplugHandler *hotplug_ctrl = NULL; Error *local_err = NULL; if (!mem_st->dev_count) { return; } if (addr) { if (mem_st->selector >= mem_st->dev_count) { trace_mhp_acpi_invalid_slot_selected(mem_st->selector); return; } } switch (addr) { case 0x0: /* DIMM slot selector */ mem_st->selector = data; trace_mhp_acpi_write_slot(mem_st->selector); break; case 0x4: /* _OST event */ mdev = &mem_st->devs[mem_st->selector]; if (data == 1) { /* TODO: handle device insert OST event */ } else if (data == 3) { /* TODO: handle device remove OST event */ } mdev->ost_event = data; trace_mhp_acpi_write_ost_ev(mem_st->selector, mdev->ost_event); break; case 0x8: /* _OST status */ mdev = &mem_st->devs[mem_st->selector]; mdev->ost_status = data; trace_mhp_acpi_write_ost_status(mem_st->selector, mdev->ost_status); /* TODO: implement memory removal on guest signal */ info = acpi_memory_device_status(mem_st->selector, mdev); qapi_event_send_acpi_device_ost(info, &error_abort); qapi_free_ACPIOSTInfo(info); break; case 0x14: /* set is_* fields */ mdev = &mem_st->devs[mem_st->selector]; if (data & 2) { /* clear insert event */ mdev->is_inserting = false; trace_mhp_acpi_clear_insert_evt(mem_st->selector); } else if (data & 4) { mdev->is_removing = false; trace_mhp_acpi_clear_remove_evt(mem_st->selector); } else if (data & 8) { if (!mdev->is_enabled) { trace_mhp_acpi_ejecting_invalid_slot(mem_st->selector); break; } dev = DEVICE(mdev->dimm); hotplug_ctrl = qdev_get_hotplug_handler(dev); /* call pc-dimm unplug cb */ hotplug_handler_unplug(hotplug_ctrl, dev, &local_err); if (local_err) { trace_mhp_acpi_pc_dimm_delete_failed(mem_st->selector); qapi_event_send_mem_unplug_error(dev->id, error_get_pretty(local_err), &error_abort); error_free(local_err); break; } trace_mhp_acpi_pc_dimm_deleted(mem_st->selector); } break; default: break; } }