static int whpx_vcpu_run(CPUState *cpu) { HRESULT hr; struct whpx_state *whpx = &whpx_global; struct whpx_vcpu *vcpu = get_whpx_vcpu(cpu); int ret; whpx_vcpu_process_async_events(cpu); if (cpu->halted) { cpu->exception_index = EXCP_HLT; atomic_set(&cpu->exit_request, false); return 0; } qemu_mutex_unlock_iothread(); cpu_exec_start(cpu); do { if (cpu->vcpu_dirty) { whpx_set_registers(cpu); cpu->vcpu_dirty = false; } whpx_vcpu_pre_run(cpu); if (atomic_read(&cpu->exit_request)) { whpx_vcpu_kick(cpu); } hr = WHvRunVirtualProcessor(whpx->partition, cpu->cpu_index, &vcpu->exit_ctx, sizeof(vcpu->exit_ctx)); if (FAILED(hr)) { error_report("WHPX: Failed to exec a virtual processor," " hr=%08lx", hr); ret = -1; break; } whpx_vcpu_post_run(cpu); switch (vcpu->exit_ctx.ExitReason) { case WHvRunVpExitReasonMemoryAccess: ret = whpx_handle_mmio(cpu, &vcpu->exit_ctx.MemoryAccess); break; case WHvRunVpExitReasonX64IoPortAccess: ret = whpx_handle_portio(cpu, &vcpu->exit_ctx.IoPortAccess); break; case WHvRunVpExitReasonX64InterruptWindow: vcpu->window_registered = 0; break; case WHvRunVpExitReasonX64Halt: ret = whpx_handle_halt(cpu); break; case WHvRunVpExitReasonCanceled: cpu->exception_index = EXCP_INTERRUPT; ret = 1; break; case WHvRunVpExitReasonNone: case WHvRunVpExitReasonUnrecoverableException: case WHvRunVpExitReasonInvalidVpRegisterValue: case WHvRunVpExitReasonUnsupportedFeature: case WHvRunVpExitReasonX64MsrAccess: case WHvRunVpExitReasonX64Cpuid: case WHvRunVpExitReasonException: default: error_report("WHPX: Unexpected VP exit code %d", vcpu->exit_ctx.ExitReason); whpx_get_registers(cpu); qemu_mutex_lock_iothread(); qemu_system_guest_panicked(cpu_get_crash_info(cpu)); qemu_mutex_unlock_iothread(); break; } } while (!ret); cpu_exec_end(cpu); qemu_mutex_lock_iothread(); current_cpu = cpu; atomic_set(&cpu->exit_request, false); return ret < 0; }
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:x:"; 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' }, { "tls-creds", required_argument, NULL, QEMU_NBD_OPT_TLSCREDS }, { "image-opts", no_argument, NULL, QEMU_NBD_OPT_IMAGE_OPTS }, { 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 *tlscredsid = NULL; bool imageOpts = false; bool writethrough = true; /* 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); module_call_init(MODULE_INIT_QOM); qemu_add_opts(&qemu_object_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 '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; } } 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, &local_err)) { error_report_err(local_err); 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) { 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... */ 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)); } 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); 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(options, "driver", qstring_from_str(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 (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(blk, dev_offset, fd_size, nbdflags, nbd_export_closed, &local_err); if (!exp) { error_report_err(local_err); exit(EXIT_FAILURE); } if (export_name) { nbd_export_set_name(exp, export_name); newproto = true; } server_ioc = qio_channel_socket_new(); if (qio_channel_socket_listen_sync(server_ioc, saddr, &local_err) < 0) { object_unref(OBJECT(server_ioc)); error_report_err(local_err); return 1; } 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); } 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 fw_cfg_bootsplash(FWCfgState *s) { int boot_splash_time = -1; const char *boot_splash_filename = NULL; char *p; char *filename, *file_data; size_t file_size; int file_type; const char *temp; /* get user configuration */ QemuOptsList *plist = qemu_find_opts("boot-opts"); QemuOpts *opts = QTAILQ_FIRST(&plist->head); if (opts != NULL) { temp = qemu_opt_get(opts, "splash"); if (temp != NULL) { boot_splash_filename = temp; } temp = qemu_opt_get(opts, "splash-time"); if (temp != NULL) { p = (char *)temp; boot_splash_time = strtol(p, (char **)&p, 10); } } /* insert splash time if user configurated */ if (boot_splash_time >= 0) { /* validate the input */ if (boot_splash_time > 0xffff) { error_report("splash time is big than 65535, force it to 65535."); boot_splash_time = 0xffff; } /* use little endian format */ qemu_extra_params_fw[0] = (uint8_t)(boot_splash_time & 0xff); qemu_extra_params_fw[1] = (uint8_t)((boot_splash_time >> 8) & 0xff); fw_cfg_add_file(s, "etc/boot-menu-wait", qemu_extra_params_fw, 2); } /* insert splash file if user configurated */ if (boot_splash_filename != NULL) { filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, boot_splash_filename); if (filename == NULL) { error_report("failed to find file '%s'.", boot_splash_filename); return; } /* loading file data */ file_data = read_splashfile(filename, &file_size, &file_type); if (file_data == NULL) { g_free(filename); return; } if (boot_splash_filedata != NULL) { g_free(boot_splash_filedata); } boot_splash_filedata = (uint8_t *)file_data; boot_splash_filedata_size = file_size; /* insert data */ if (file_type == JPG_FILE) { fw_cfg_add_file(s, "bootsplash.jpg", boot_splash_filedata, boot_splash_filedata_size); } else { fw_cfg_add_file(s, "bootsplash.bmp", boot_splash_filedata, boot_splash_filedata_size); } g_free(filename); } }
static int vhost_scsi_start(VHostSCSI *s) { int ret, abi_version, i; VirtIODevice *vdev = VIRTIO_DEVICE(s); BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); const VhostOps *vhost_ops = s->dev.vhost_ops; if (!k->set_guest_notifiers) { error_report("binding does not support guest notifiers"); return -ENOSYS; } ret = vhost_ops->vhost_call(&s->dev, VHOST_SCSI_GET_ABI_VERSION, &abi_version); if (ret < 0) { return -errno; } if (abi_version > VHOST_SCSI_ABI_VERSION) { error_report("vhost-scsi: The running tcm_vhost kernel abi_version:" " %d is greater than vhost_scsi userspace supports: %d, please" " upgrade your version of QEMU", abi_version, VHOST_SCSI_ABI_VERSION); return -ENOSYS; } ret = vhost_dev_enable_notifiers(&s->dev, vdev); if (ret < 0) { return ret; } s->dev.acked_features = vdev->guest_features; ret = vhost_dev_start(&s->dev, vdev); if (ret < 0) { error_report("Error start vhost dev"); goto err_notifiers; } ret = vhost_scsi_set_endpoint(s); if (ret < 0) { error_report("Error set vhost-scsi endpoint"); goto err_vhost_stop; } ret = k->set_guest_notifiers(qbus->parent, s->dev.nvqs, true); if (ret < 0) { error_report("Error binding guest notifier"); goto err_endpoint; } /* guest_notifier_mask/pending not used yet, so just unmask * everything here. virtio-pci will do the right thing by * enabling/disabling irqfd. */ for (i = 0; i < s->dev.nvqs; i++) { vhost_virtqueue_mask(&s->dev, vdev, i, false); } return ret; err_endpoint: vhost_scsi_clear_endpoint(s); err_vhost_stop: vhost_dev_stop(&s->dev, vdev); err_notifiers: vhost_dev_disable_notifiers(&s->dev, vdev); return ret; }
void* error_test_thread( void ) { error_context_t* context = 0; EXPECT_EQ( error(), ERROR_NONE ); EXPECT_EQ( error(), ERROR_NONE ); error_report( ERRORLEVEL_WARNING, ERROR_ACCESS_DENIED ); EXPECT_EQ( error(), ERROR_ACCESS_DENIED ); EXPECT_EQ( error(), ERROR_NONE ); error_report( ERRORLEVEL_ERROR, ERROR_INVALID_VALUE ); EXPECT_EQ( error(), ERROR_INVALID_VALUE ); EXPECT_EQ( error(), ERROR_NONE ); context = error_context(); if( context ) EXPECT_EQ( context->depth, 0 ); error_context_push( "error test", "data" ); context = error_context(); #if BUILD_ENABLE_ERROR_CONTEXT EXPECT_NE( context, 0 ); EXPECT_EQ( context->depth, 1 ); EXPECT_STREQ( context->frame[0].name, "error test" ); EXPECT_STREQ( context->frame[0].data, "data" ); #else EXPECT_EQ( context, 0 ); #endif error_context_pop(); context = error_context(); #if BUILD_ENABLE_ERROR_CONTEXT EXPECT_NE( context, 0 ); EXPECT_EQ( context->depth, 0 ); #else EXPECT_EQ( context, 0 ); #endif error_context_push( "error test", "data" ); error_context_push( "another test", "more data" ); context = error_context(); #if BUILD_ENABLE_ERROR_CONTEXT EXPECT_NE( context, 0 ); EXPECT_EQ( context->depth, 2 ); EXPECT_STREQ( context->frame[0].name, "error test" ); EXPECT_STREQ( context->frame[0].data, "data" ); EXPECT_STREQ( context->frame[1].name, "another test" ); EXPECT_STREQ( context->frame[1].data, "more data" ); #else EXPECT_EQ( context, 0 ); #endif error_context_pop(); context = error_context(); #if BUILD_ENABLE_ERROR_CONTEXT EXPECT_NE( context, 0 ); EXPECT_EQ( context->depth, 1 ); EXPECT_STREQ( context->frame[0].name, "error test" ); EXPECT_STREQ( context->frame[0].data, "data" ); #else EXPECT_EQ( context, 0 ); #endif error_context_pop(); return 0; }
static void mips_mipssim_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; char *filename; MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *isa = g_new(MemoryRegion, 1); MemoryRegion *ram = g_new(MemoryRegion, 1); MemoryRegion *bios = g_new(MemoryRegion, 1); MIPSCPU *cpu; CPUMIPSState *env; ResetData *reset_info; int bios_size; /* Init CPUs. */ if (cpu_model == NULL) { #ifdef TARGET_MIPS64 cpu_model = "5Kf"; #else cpu_model = "24Kf"; #endif } cpu = cpu_mips_init(cpu_model); if (cpu == NULL) { fprintf(stderr, "Unable to find CPU definition\n"); exit(1); } env = &cpu->env; reset_info = g_malloc0(sizeof(ResetData)); reset_info->cpu = cpu; reset_info->vector = env->active_tc.PC; qemu_register_reset(main_cpu_reset, reset_info); /* Allocate RAM. */ memory_region_allocate_system_memory(ram, NULL, "mips_mipssim.ram", ram_size); memory_region_init_ram(bios, NULL, "mips_mipssim.bios", BIOS_SIZE, &error_fatal); vmstate_register_ram_global(bios); memory_region_set_readonly(bios, true); memory_region_add_subregion(address_space_mem, 0, ram); /* Map the BIOS / boot exception handler. */ memory_region_add_subregion(address_space_mem, 0x1fc00000LL, bios); /* Load a BIOS / boot exception handler image. */ if (bios_name == NULL) bios_name = BIOS_FILENAME; filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); if (filename) { bios_size = load_image_targphys(filename, 0x1fc00000LL, BIOS_SIZE); g_free(filename); } else { bios_size = -1; } if ((bios_size < 0 || bios_size > BIOS_SIZE) && !kernel_filename && !qtest_enabled()) { /* Bail out if we have neither a kernel image nor boot vector code. */ error_report("Could not load MIPS bios '%s', and no " "-kernel argument was specified", bios_name); exit(1); } else { /* We have a boot vector start address. */ env->active_tc.PC = (target_long)(int32_t)0xbfc00000; } if (kernel_filename) { loaderparams.ram_size = ram_size; loaderparams.kernel_filename = kernel_filename; loaderparams.kernel_cmdline = kernel_cmdline; loaderparams.initrd_filename = initrd_filename; reset_info->vector = load_kernel(); } /* Init CPU internal devices. */ cpu_mips_irq_init_cpu(cpu); cpu_mips_clock_init(cpu); /* Register 64 KB of ISA IO space at 0x1fd00000. */ memory_region_init_alias(isa, NULL, "isa_mmio", get_system_io(), 0, 0x00010000); memory_region_add_subregion(get_system_memory(), 0x1fd00000, isa); /* A single 16450 sits at offset 0x3f8. It is attached to MIPS CPU INT2, which is interrupt 4. */ if (serial_hds[0]) serial_init(0x3f8, env->irq[4], 115200, serial_hds[0], get_system_io()); if (nd_table[0].used) /* MIPSnet uses the MIPS CPU INT0, which is interrupt 2. */ mipsnet_init(0x4200, env->irq[2], &nd_table[0]); }
/* * Proxy->header and proxy->request written to socket by QEMU process. * This request read by proxy helper process * returns 0 on success and -errno on error */ static int v9fs_request(V9fsProxy *proxy, int type, void *response, ...) { dev_t rdev; va_list ap; int size = 0; int retval = 0; uint64_t offset; ProxyHeader header = { 0, 0}; struct timespec spec[2]; int flags, mode, uid, gid; V9fsString *name, *value; V9fsString *path, *oldpath; struct iovec *iovec = NULL, *reply = NULL; qemu_mutex_lock(&proxy->mutex); if (proxy->sockfd == -1) { retval = -EIO; goto err_out; } iovec = &proxy->out_iovec; reply = &proxy->in_iovec; va_start(ap, response); switch (type) { case T_OPEN: path = va_arg(ap, V9fsString *); flags = va_arg(ap, int); retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sd", path, flags); if (retval > 0) { header.size = retval; header.type = T_OPEN; } break; case T_CREATE: path = va_arg(ap, V9fsString *); flags = va_arg(ap, int); mode = va_arg(ap, int); uid = va_arg(ap, int); gid = va_arg(ap, int); retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sdddd", path, flags, mode, uid, gid); if (retval > 0) { header.size = retval; header.type = T_CREATE; } break; case T_MKNOD: path = va_arg(ap, V9fsString *); mode = va_arg(ap, int); rdev = va_arg(ap, long int); uid = va_arg(ap, int); gid = va_arg(ap, int); retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ddsdq", uid, gid, path, mode, rdev); if (retval > 0) { header.size = retval; header.type = T_MKNOD; } break; case T_MKDIR: path = va_arg(ap, V9fsString *); mode = va_arg(ap, int); uid = va_arg(ap, int); gid = va_arg(ap, int); retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ddsd", uid, gid, path, mode); if (retval > 0) { header.size = retval; header.type = T_MKDIR; } break; case T_SYMLINK: oldpath = va_arg(ap, V9fsString *); path = va_arg(ap, V9fsString *); uid = va_arg(ap, int); gid = va_arg(ap, int); retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ddss", uid, gid, oldpath, path); if (retval > 0) { header.size = retval; header.type = T_SYMLINK; } break; case T_LINK: oldpath = va_arg(ap, V9fsString *); path = va_arg(ap, V9fsString *); retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ss", oldpath, path); if (retval > 0) { header.size = retval; header.type = T_LINK; } break; case T_LSTAT: path = va_arg(ap, V9fsString *); retval = proxy_marshal(iovec, PROXY_HDR_SZ, "s", path); if (retval > 0) { header.size = retval; header.type = T_LSTAT; } break; case T_READLINK: path = va_arg(ap, V9fsString *); size = va_arg(ap, int); retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sd", path, size); if (retval > 0) { header.size = retval; header.type = T_READLINK; } break; case T_STATFS: path = va_arg(ap, V9fsString *); retval = proxy_marshal(iovec, PROXY_HDR_SZ, "s", path); if (retval > 0) { header.size = retval; header.type = T_STATFS; } break; case T_CHMOD: path = va_arg(ap, V9fsString *); mode = va_arg(ap, int); retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sd", path, mode); if (retval > 0) { header.size = retval; header.type = T_CHMOD; } break; case T_CHOWN: path = va_arg(ap, V9fsString *); uid = va_arg(ap, int); gid = va_arg(ap, int); retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sdd", path, uid, gid); if (retval > 0) { header.size = retval; header.type = T_CHOWN; } break; case T_TRUNCATE: path = va_arg(ap, V9fsString *); offset = va_arg(ap, uint64_t); retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sq", path, offset); if (retval > 0) { header.size = retval; header.type = T_TRUNCATE; } break; case T_UTIME: path = va_arg(ap, V9fsString *); spec[0].tv_sec = va_arg(ap, long); spec[0].tv_nsec = va_arg(ap, long); spec[1].tv_sec = va_arg(ap, long); spec[1].tv_nsec = va_arg(ap, long); retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sqqqq", path, spec[0].tv_sec, spec[1].tv_nsec, spec[1].tv_sec, spec[1].tv_nsec); if (retval > 0) { header.size = retval; header.type = T_UTIME; } break; case T_RENAME: oldpath = va_arg(ap, V9fsString *); path = va_arg(ap, V9fsString *); retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ss", oldpath, path); if (retval > 0) { header.size = retval; header.type = T_RENAME; } break; case T_REMOVE: path = va_arg(ap, V9fsString *); retval = proxy_marshal(iovec, PROXY_HDR_SZ, "s", path); if (retval > 0) { header.size = retval; header.type = T_REMOVE; } break; case T_LGETXATTR: size = va_arg(ap, int); path = va_arg(ap, V9fsString *); name = va_arg(ap, V9fsString *); retval = proxy_marshal(iovec, PROXY_HDR_SZ, "dss", size, path, name); if (retval > 0) { header.size = retval; header.type = T_LGETXATTR; } break; case T_LLISTXATTR: size = va_arg(ap, int); path = va_arg(ap, V9fsString *); retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ds", size, path); if (retval > 0) { header.size = retval; header.type = T_LLISTXATTR; } break; case T_LSETXATTR: path = va_arg(ap, V9fsString *); name = va_arg(ap, V9fsString *); value = va_arg(ap, V9fsString *); size = va_arg(ap, int); flags = va_arg(ap, int); retval = proxy_marshal(iovec, PROXY_HDR_SZ, "sssdd", path, name, value, size, flags); if (retval > 0) { header.size = retval; header.type = T_LSETXATTR; } break; case T_LREMOVEXATTR: path = va_arg(ap, V9fsString *); name = va_arg(ap, V9fsString *); retval = proxy_marshal(iovec, PROXY_HDR_SZ, "ss", path, name); if (retval > 0) { header.size = retval; header.type = T_LREMOVEXATTR; } break; case T_GETVERSION: path = va_arg(ap, V9fsString *); retval = proxy_marshal(iovec, PROXY_HDR_SZ, "s", path); if (retval > 0) { header.size = retval; header.type = T_GETVERSION; } break; default: error_report("Invalid type %d", type); retval = -EINVAL; break; } va_end(ap); if (retval < 0) { goto err_out; } /* marshal the header details */ proxy_marshal(iovec, 0, "dd", header.type, header.size); header.size += PROXY_HDR_SZ; retval = qemu_write_full(proxy->sockfd, iovec->iov_base, header.size); if (retval != header.size) { goto close_error; } switch (type) { case T_OPEN: case T_CREATE: /* * A file descriptor is returned as response for * T_OPEN,T_CREATE on success */ if (v9fs_receivefd(proxy->sockfd, &retval) < 0) { goto close_error; } break; case T_MKNOD: case T_MKDIR: case T_SYMLINK: case T_LINK: case T_CHMOD: case T_CHOWN: case T_RENAME: case T_TRUNCATE: case T_UTIME: case T_REMOVE: case T_LSETXATTR: case T_LREMOVEXATTR: if (v9fs_receive_status(proxy, reply, &retval) < 0) { goto close_error; } break; case T_LSTAT: case T_READLINK: case T_STATFS: case T_GETVERSION: if (v9fs_receive_response(proxy, type, &retval, response) < 0) { goto close_error; } break; case T_LGETXATTR: case T_LLISTXATTR: if (!size) { if (v9fs_receive_status(proxy, reply, &retval) < 0) { goto close_error; } } else { if (v9fs_receive_response(proxy, type, &retval, response) < 0) { goto close_error; } } break; } err_out: qemu_mutex_unlock(&proxy->mutex); return retval; close_error: close(proxy->sockfd); proxy->sockfd = -1; qemu_mutex_unlock(&proxy->mutex); return -EIO; }
/* * We support iscsi url's on the form * iscsi://[<username>%<password>@]<host>[:<port>]/<targetname>/<lun> */ static int iscsi_open(BlockDriverState *bs, const char *filename, int flags) { IscsiLun *iscsilun = bs->opaque; struct iscsi_context *iscsi = NULL; struct iscsi_url *iscsi_url = NULL; struct scsi_task *task = NULL; struct scsi_inquiry_standard *inq = NULL; struct scsi_readcapacity10 *rc10 = NULL; struct scsi_readcapacity16 *rc16 = NULL; char *initiator_name = NULL; int ret; if ((BDRV_SECTOR_SIZE % 512) != 0) { error_report("iSCSI: Invalid BDRV_SECTOR_SIZE. " "BDRV_SECTOR_SIZE(%lld) is not a multiple " "of 512", BDRV_SECTOR_SIZE); return -EINVAL; } iscsi_url = iscsi_parse_full_url(iscsi, filename); if (iscsi_url == NULL) { error_report("Failed to parse URL : %s", filename); ret = -EINVAL; goto out; } memset(iscsilun, 0, sizeof(IscsiLun)); initiator_name = parse_initiator_name(iscsi_url->target); iscsi = iscsi_create_context(initiator_name); if (iscsi == NULL) { error_report("iSCSI: Failed to create iSCSI context."); ret = -ENOMEM; goto out; } if (iscsi_set_targetname(iscsi, iscsi_url->target)) { error_report("iSCSI: Failed to set target name."); ret = -EINVAL; goto out; } if (iscsi_url->user != NULL) { ret = iscsi_set_initiator_username_pwd(iscsi, iscsi_url->user, iscsi_url->passwd); if (ret != 0) { error_report("Failed to set initiator username and password"); ret = -EINVAL; goto out; } } /* check if we got CHAP username/password via the options */ if (parse_chap(iscsi, iscsi_url->target) != 0) { error_report("iSCSI: Failed to set CHAP user/password"); ret = -EINVAL; goto out; } if (iscsi_set_session_type(iscsi, ISCSI_SESSION_NORMAL) != 0) { error_report("iSCSI: Failed to set session type to normal."); ret = -EINVAL; goto out; } iscsi_set_header_digest(iscsi, ISCSI_HEADER_DIGEST_NONE_CRC32C); /* check if we got HEADER_DIGEST via the options */ parse_header_digest(iscsi, iscsi_url->target); if (iscsi_full_connect_sync(iscsi, iscsi_url->portal, iscsi_url->lun) != 0) { error_report("iSCSI: Failed to connect to LUN : %s", iscsi_get_error(iscsi)); ret = -EINVAL; goto out; } iscsilun->iscsi = iscsi; iscsilun->lun = iscsi_url->lun; task = iscsi_inquiry_sync(iscsi, iscsilun->lun, 0, 0, 36); if (task == NULL || task->status != SCSI_STATUS_GOOD) { error_report("iSCSI: failed to send inquiry command."); ret = -EINVAL; goto out; } inq = scsi_datain_unmarshall(task); if (inq == NULL) { error_report("iSCSI: Failed to unmarshall inquiry data."); ret = -EINVAL; goto out; } iscsilun->type = inq->periperal_device_type; scsi_free_scsi_task(task); switch (iscsilun->type) { case TYPE_DISK: task = iscsi_readcapacity16_sync(iscsi, iscsilun->lun); if (task == NULL || task->status != SCSI_STATUS_GOOD) { error_report("iSCSI: failed to send readcapacity16 command."); ret = -EINVAL; goto out; } rc16 = scsi_datain_unmarshall(task); if (rc16 == NULL) { error_report("iSCSI: Failed to unmarshall readcapacity16 data."); ret = -EINVAL; goto out; } iscsilun->block_size = rc16->block_length; iscsilun->num_blocks = rc16->returned_lba + 1; break; case TYPE_ROM: task = iscsi_readcapacity10_sync(iscsi, iscsilun->lun, 0, 0); if (task == NULL || task->status != SCSI_STATUS_GOOD) { error_report("iSCSI: failed to send readcapacity10 command."); ret = -EINVAL; goto out; } rc10 = scsi_datain_unmarshall(task); if (rc10 == NULL) { error_report("iSCSI: Failed to unmarshall readcapacity10 data."); ret = -EINVAL; goto out; } iscsilun->block_size = rc10->block_size; if (rc10->lba == 0) { /* blank disk loaded */ iscsilun->num_blocks = 0; } else { iscsilun->num_blocks = rc10->lba + 1; } break; default: break; } bs->total_sectors = iscsilun->num_blocks * iscsilun->block_size / BDRV_SECTOR_SIZE ; /* Medium changer or tape. We dont have any emulation for this so this must * be sg ioctl compatible. We force it to be sg, otherwise qemu will try * to read from the device to guess the image format. */ if (iscsilun->type == TYPE_MEDIUM_CHANGER || iscsilun->type == TYPE_TAPE) { bs->sg = 1; } ret = 0; #if defined(LIBISCSI_FEATURE_NOP_COUNTER) /* Set up a timer for sending out iSCSI NOPs */ iscsilun->nop_timer = qemu_new_timer_ms(rt_clock, iscsi_nop_timed_event, iscsilun); qemu_mod_timer(iscsilun->nop_timer, qemu_get_clock_ms(rt_clock) + NOP_INTERVAL); #endif out: if (initiator_name != NULL) { g_free(initiator_name); } if (iscsi_url != NULL) { iscsi_destroy_url(iscsi_url); } if (task != NULL) { scsi_free_scsi_task(task); } if (ret) { if (iscsi != NULL) { iscsi_destroy_context(iscsi); } memset(iscsilun, 0, sizeof(IscsiLun)); } return ret; }
int main(int argc, char **argv) { BlockBackend *blk; BlockDriverState *bs; BlockDriver *drv; off_t dev_offset = 0; uint32_t nbdflags = 0; bool disconnect = false; const char *bindto = "0.0.0.0"; char *device = NULL; int port = NBD_DEFAULT_PORT; 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 }, #ifdef CONFIG_LINUX_AIO { "aio", 1, NULL, QEMU_NBD_OPT_AIO }, #endif { "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; int li; char *end; int flags = BDRV_O_RDWR; int partition = -1; int ret; int fd; bool seen_cache = false; bool seen_discard = false; #ifdef CONFIG_LINUX_AIO bool seen_aio = false; #endif pthread_t client_thread; const char *fmt = NULL; Error *local_err = NULL; BlockdevDetectZeroesOptions detect_zeroes = BLOCKDEV_DETECT_ZEROES_OPTIONS_OFF; /* 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; #ifdef CONFIG_LINUX_AIO 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; #endif 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': li = strtol(optarg, &end, 0); if (*end) { errx(EXIT_FAILURE, "Invalid port `%s'", optarg); } if (li < 1 || li > 65535) { errx(EXIT_FAILURE, "Port out of range `%s'", optarg); } port = (uint16_t)li; 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(&internal_snapshot_opts, optarg, 0); 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) { 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)); } if (qemu_init_main_loop(&local_err)) { error_report("%s", error_get_pretty(local_err)); error_free(local_err); exit(EXIT_FAILURE); } bdrv_init(); atexit(bdrv_close_all); if (fmt) { drv = bdrv_find_format(fmt); if (!drv) { errx(EXIT_FAILURE, "Unknown file format '%s'", fmt); } } else { drv = NULL; } blk = blk_new_with_bs("hda", &error_abort); bs = blk_bs(blk); srcpath = argv[optind]; ret = bdrv_open(&bs, srcpath, NULL, NULL, flags, drv, &local_err); if (ret < 0) { errno = -ret; err(EXIT_FAILURE, "Failed to bdrv_open '%s': %s", argv[optind], error_get_pretty(local_err)); } 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 (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); if (sockpath) { fd = unix_socket_incoming(sockpath); } else { fd = tcp_socket_incoming(bindto, port); } if (fd < 0) { 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)); } qemu_set_fd_handler2(fd, nbd_can_accept, nbd_accept, NULL, (void *)(uintptr_t)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 BlockDriverAIOCB * iscsi_aio_readv(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque) { IscsiLun *iscsilun = bs->opaque; struct iscsi_context *iscsi = iscsilun->iscsi; IscsiAIOCB *acb; size_t qemu_read_size; int i; uint64_t lba; uint32_t num_sectors; qemu_read_size = BDRV_SECTOR_SIZE * (size_t)nb_sectors; acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque); trace_iscsi_aio_readv(iscsi, sector_num, nb_sectors, opaque, acb); acb->iscsilun = iscsilun; acb->qiov = qiov; acb->canceled = 0; acb->bh = NULL; acb->status = -EINPROGRESS; acb->read_size = qemu_read_size; acb->buf = NULL; /* If LUN blocksize is bigger than BDRV_BLOCK_SIZE a read from QEMU * may be misaligned to the LUN, so we may need to read some extra * data. */ acb->read_offset = 0; if (iscsilun->block_size > BDRV_SECTOR_SIZE) { uint64_t bdrv_offset = BDRV_SECTOR_SIZE * sector_num; acb->read_offset = bdrv_offset % iscsilun->block_size; } num_sectors = (qemu_read_size + iscsilun->block_size + acb->read_offset - 1) / iscsilun->block_size; acb->task = malloc(sizeof(struct scsi_task)); if (acb->task == NULL) { error_report("iSCSI: Failed to allocate task for scsi READ16 " "command. %s", iscsi_get_error(iscsi)); qemu_aio_release(acb); return NULL; } memset(acb->task, 0, sizeof(struct scsi_task)); acb->task->xfer_dir = SCSI_XFER_READ; lba = sector_qemu2lun(sector_num, iscsilun); acb->task->expxferlen = qemu_read_size; switch (iscsilun->type) { case TYPE_DISK: acb->task->cdb_size = 16; acb->task->cdb[0] = 0x88; *(uint32_t *)&acb->task->cdb[2] = htonl(lba >> 32); *(uint32_t *)&acb->task->cdb[6] = htonl(lba & 0xffffffff); *(uint32_t *)&acb->task->cdb[10] = htonl(num_sectors); break; default: acb->task->cdb_size = 10; acb->task->cdb[0] = 0x28; *(uint32_t *)&acb->task->cdb[2] = htonl(lba); *(uint16_t *)&acb->task->cdb[7] = htons(num_sectors); break; } if (iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task, iscsi_aio_read16_cb, NULL, acb) != 0) { scsi_free_scsi_task(acb->task); qemu_aio_release(acb); return NULL; } for (i = 0; i < acb->qiov->niov; i++) { scsi_task_add_data_in_buffer(acb->task, acb->qiov->iov[i].iov_len, acb->qiov->iov[i].iov_base); } iscsi_set_events(iscsilun); return &acb->common; }
static BlockDriverAIOCB *iscsi_aio_ioctl(BlockDriverState *bs, unsigned long int req, void *buf, BlockDriverCompletionFunc *cb, void *opaque) { IscsiLun *iscsilun = bs->opaque; struct iscsi_context *iscsi = iscsilun->iscsi; struct iscsi_data data; IscsiAIOCB *acb; assert(req == SG_IO); acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque); acb->iscsilun = iscsilun; acb->canceled = 0; acb->bh = NULL; acb->status = -EINPROGRESS; acb->buf = NULL; acb->ioh = buf; acb->task = malloc(sizeof(struct scsi_task)); if (acb->task == NULL) { error_report("iSCSI: Failed to allocate task for scsi command. %s", iscsi_get_error(iscsi)); qemu_aio_release(acb); return NULL; } memset(acb->task, 0, sizeof(struct scsi_task)); switch (acb->ioh->dxfer_direction) { case SG_DXFER_TO_DEV: acb->task->xfer_dir = SCSI_XFER_WRITE; break; case SG_DXFER_FROM_DEV: acb->task->xfer_dir = SCSI_XFER_READ; break; default: acb->task->xfer_dir = SCSI_XFER_NONE; break; } acb->task->cdb_size = acb->ioh->cmd_len; memcpy(&acb->task->cdb[0], acb->ioh->cmdp, acb->ioh->cmd_len); acb->task->expxferlen = acb->ioh->dxfer_len; if (acb->task->xfer_dir == SCSI_XFER_WRITE) { data.data = acb->ioh->dxferp; data.size = acb->ioh->dxfer_len; } if (iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task, iscsi_aio_ioctl_cb, (acb->task->xfer_dir == SCSI_XFER_WRITE) ? &data : NULL, acb) != 0) { scsi_free_scsi_task(acb->task); qemu_aio_release(acb); return NULL; } /* tell libiscsi to read straight into the buffer we got from ioctl */ if (acb->task->xfer_dir == SCSI_XFER_READ) { scsi_task_add_data_in_buffer(acb->task, acb->ioh->dxfer_len, acb->ioh->dxferp); } iscsi_set_events(iscsilun); return &acb->common; }
static BlockDriverAIOCB * iscsi_aio_writev(BlockDriverState *bs, int64_t sector_num, QEMUIOVector *qiov, int nb_sectors, BlockDriverCompletionFunc *cb, void *opaque) { IscsiLun *iscsilun = bs->opaque; struct iscsi_context *iscsi = iscsilun->iscsi; IscsiAIOCB *acb; size_t size; uint32_t num_sectors; uint64_t lba; struct iscsi_data data; acb = qemu_aio_get(&iscsi_aiocb_info, bs, cb, opaque); trace_iscsi_aio_writev(iscsi, sector_num, nb_sectors, opaque, acb); acb->iscsilun = iscsilun; acb->qiov = qiov; acb->canceled = 0; acb->bh = NULL; acb->status = -EINPROGRESS; /* XXX we should pass the iovec to write16 to avoid the extra copy */ /* this will allow us to get rid of 'buf' completely */ size = nb_sectors * BDRV_SECTOR_SIZE; data.size = MIN(size, acb->qiov->size); /* if the iovec only contains one buffer we can pass it directly */ if (acb->qiov->niov == 1) { acb->buf = NULL; data.data = acb->qiov->iov[0].iov_base; } else { acb->buf = g_malloc(data.size); qemu_iovec_to_buf(acb->qiov, 0, acb->buf, data.size); data.data = acb->buf; } acb->task = malloc(sizeof(struct scsi_task)); if (acb->task == NULL) { error_report("iSCSI: Failed to allocate task for scsi WRITE16 " "command. %s", iscsi_get_error(iscsi)); qemu_aio_release(acb); return NULL; } memset(acb->task, 0, sizeof(struct scsi_task)); acb->task->xfer_dir = SCSI_XFER_WRITE; acb->task->cdb_size = 16; acb->task->cdb[0] = 0x8a; lba = sector_qemu2lun(sector_num, iscsilun); *(uint32_t *)&acb->task->cdb[2] = htonl(lba >> 32); *(uint32_t *)&acb->task->cdb[6] = htonl(lba & 0xffffffff); num_sectors = size / iscsilun->block_size; *(uint32_t *)&acb->task->cdb[10] = htonl(num_sectors); acb->task->expxferlen = size; if (iscsi_scsi_command_async(iscsi, iscsilun->lun, acb->task, iscsi_aio_write16_cb, &data, acb) != 0) { scsi_free_scsi_task(acb->task); g_free(acb->buf); qemu_aio_release(acb); return NULL; } iscsi_set_events(iscsilun); return &acb->common; }
static void vexpress_common_init(MachineState *machine) { VexpressMachineState *vms = VEXPRESS_MACHINE(machine); VexpressMachineClass *vmc = VEXPRESS_MACHINE_GET_CLASS(machine); VEDBoardInfo *daughterboard = vmc->daughterboard; DeviceState *dev, *sysctl, *pl041; qemu_irq pic[64]; uint32_t sys_id; DriveInfo *dinfo; pflash_t *pflash0; ram_addr_t vram_size, sram_size; MemoryRegion *sysmem = get_system_memory(); MemoryRegion *vram = g_new(MemoryRegion, 1); MemoryRegion *sram = g_new(MemoryRegion, 1); MemoryRegion *flashalias = g_new(MemoryRegion, 1); MemoryRegion *flash0mem; const hwaddr *map = daughterboard->motherboard_map; int i; daughterboard->init(vms, machine->ram_size, machine->cpu_model, pic); /* * If a bios file was provided, attempt to map it into memory */ if (bios_name) { char *fn; int image_size; if (drive_get(IF_PFLASH, 0, 0)) { error_report("The contents of the first flash device may be " "specified with -bios or with -drive if=pflash... " "but you cannot use both options at once"); exit(1); } fn = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); if (!fn) { error_report("Could not find ROM image '%s'", bios_name); exit(1); } image_size = load_image_targphys(fn, map[VE_NORFLASH0], VEXPRESS_FLASH_SIZE); g_free(fn); if (image_size < 0) { error_report("Could not load ROM image '%s'", bios_name); exit(1); } } /* Motherboard peripherals: the wiring is the same but the * addresses vary between the legacy and A-Series memory maps. */ sys_id = 0x1190f500; sysctl = qdev_create(NULL, "realview_sysctl"); qdev_prop_set_uint32(sysctl, "sys_id", sys_id); qdev_prop_set_uint32(sysctl, "proc_id", daughterboard->proc_id); qdev_prop_set_uint32(sysctl, "len-db-voltage", daughterboard->num_voltage_sensors); for (i = 0; i < daughterboard->num_voltage_sensors; i++) { char *propname = g_strdup_printf("db-voltage[%d]", i); qdev_prop_set_uint32(sysctl, propname, daughterboard->voltages[i]); g_free(propname); } qdev_prop_set_uint32(sysctl, "len-db-clock", daughterboard->num_clocks); for (i = 0; i < daughterboard->num_clocks; i++) { char *propname = g_strdup_printf("db-clock[%d]", i); qdev_prop_set_uint32(sysctl, propname, daughterboard->clocks[i]); g_free(propname); } qdev_init_nofail(sysctl); sysbus_mmio_map(SYS_BUS_DEVICE(sysctl), 0, map[VE_SYSREGS]); /* VE_SP810: not modelled */ /* VE_SERIALPCI: not modelled */ 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, map[VE_PL041]); sysbus_connect_irq(SYS_BUS_DEVICE(pl041), 0, pic[11]); dev = sysbus_create_varargs("pl181", map[VE_MMCI], pic[9], pic[10], NULL); /* Wire up MMC card detect and read-only signals */ qdev_connect_gpio_out(dev, 0, qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_WPROT)); qdev_connect_gpio_out(dev, 1, qdev_get_gpio_in(sysctl, ARM_SYSCTL_GPIO_MMC_CARDIN)); sysbus_create_simple("pl050_keyboard", map[VE_KMI0], pic[12]); sysbus_create_simple("pl050_mouse", map[VE_KMI1], pic[13]); pl011_create(map[VE_UART0], pic[5], serial_hds[0]); pl011_create(map[VE_UART1], pic[6], serial_hds[1]); pl011_create(map[VE_UART2], pic[7], serial_hds[2]); pl011_create(map[VE_UART3], pic[8], serial_hds[3]); sysbus_create_simple("sp804", map[VE_TIMER01], pic[2]); sysbus_create_simple("sp804", map[VE_TIMER23], pic[3]); /* VE_SERIALDVI: not modelled */ sysbus_create_simple("pl031", map[VE_RTC], pic[4]); /* RTC */ /* VE_COMPACTFLASH: not modelled */ sysbus_create_simple("pl111", map[VE_CLCD], pic[14]); dinfo = drive_get_next(IF_PFLASH); pflash0 = ve_pflash_cfi01_register(map[VE_NORFLASH0], "vexpress.flash0", dinfo); if (!pflash0) { fprintf(stderr, "vexpress: error registering flash 0.\n"); exit(1); } if (map[VE_NORFLASHALIAS] != -1) { /* Map flash 0 as an alias into low memory */ flash0mem = sysbus_mmio_get_region(SYS_BUS_DEVICE(pflash0), 0); memory_region_init_alias(flashalias, NULL, "vexpress.flashalias", flash0mem, 0, VEXPRESS_FLASH_SIZE); memory_region_add_subregion(sysmem, map[VE_NORFLASHALIAS], flashalias); } dinfo = drive_get_next(IF_PFLASH); if (!ve_pflash_cfi01_register(map[VE_NORFLASH1], "vexpress.flash1", dinfo)) { fprintf(stderr, "vexpress: error registering flash 1.\n"); exit(1); } sram_size = 0x2000000; memory_region_init_ram(sram, NULL, "vexpress.sram", sram_size, &error_fatal); vmstate_register_ram_global(sram); memory_region_add_subregion(sysmem, map[VE_SRAM], sram); vram_size = 0x800000; memory_region_init_ram(vram, NULL, "vexpress.vram", vram_size, &error_fatal); vmstate_register_ram_global(vram); memory_region_add_subregion(sysmem, map[VE_VIDEORAM], vram); /* 0x4e000000 LAN9118 Ethernet */ if (nd_table[0].used) { lan9118_init(&nd_table[0], map[VE_ETHERNET], pic[15]); } /* VE_USB: not modelled */ /* VE_DAPROM: not modelled */ /* Create mmio transports, so the user can create virtio backends * (which will be automatically plugged in to the transports). If * no backend is created the transport will just sit harmlessly idle. */ for (i = 0; i < NUM_VIRTIO_TRANSPORTS; i++) { sysbus_create_simple("virtio-mmio", map[VE_VIRTIO] + 0x200 * i, pic[40 + i]); } daughterboard->bootinfo.ram_size = machine->ram_size; daughterboard->bootinfo.kernel_filename = machine->kernel_filename; daughterboard->bootinfo.kernel_cmdline = machine->kernel_cmdline; daughterboard->bootinfo.initrd_filename = machine->initrd_filename; daughterboard->bootinfo.nb_cpus = smp_cpus; daughterboard->bootinfo.board_id = VEXPRESS_BOARD_ID; daughterboard->bootinfo.loader_start = daughterboard->loader_start; daughterboard->bootinfo.smp_loader_start = map[VE_SRAM]; daughterboard->bootinfo.smp_bootreg_addr = map[VE_SYSREGS] + 0x30; daughterboard->bootinfo.gic_cpu_if_addr = daughterboard->gic_cpu_if_addr; daughterboard->bootinfo.modify_dtb = vexpress_modify_dtb; /* Indicate that when booting Linux we should be in secure state */ daughterboard->bootinfo.secure_boot = true; arm_load_kernel(ARM_CPU(first_cpu), &daughterboard->bootinfo); }
/* PC hardware initialisation */ static void pc_init1(MachineState *machine, int pci_enabled, int kvmclock_enabled) { PCMachineState *pc_machine = PC_MACHINE(machine); MemoryRegion *system_memory = get_system_memory(); MemoryRegion *system_io = get_system_io(); int i; ram_addr_t below_4g_mem_size, above_4g_mem_size; PCIBus *pci_bus; ISABus *isa_bus; PCII440FXState *i440fx_state; int piix3_devfn = -1; qemu_irq *cpu_irq; qemu_irq *gsi; qemu_irq *i8259; qemu_irq *smi_irq; GSIState *gsi_state; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; BusState *idebus[MAX_IDE_BUS]; ISADevice *rtc_state; ISADevice *floppy; MemoryRegion *ram_memory; MemoryRegion *pci_memory; MemoryRegion *rom_memory; DeviceState *icc_bridge; FWCfgState *fw_cfg = NULL; PcGuestInfo *guest_info; ram_addr_t lowmem; /* Check whether RAM fits below 4G (leaving 1/2 GByte for IO memory). * If it doesn't, we need to split it in chunks below and above 4G. * In any case, try to make sure that guest addresses aligned at * 1G boundaries get mapped to host addresses aligned at 1G boundaries. * For old machine types, use whatever split we used historically to avoid * breaking migration. */ if (machine->ram_size >= 0xe0000000) { lowmem = gigabyte_align ? 0xc0000000 : 0xe0000000; } else { lowmem = 0xe0000000; } /* Handle the machine opt max-ram-below-4g. It is basically doing * min(qemu limit, user limit). */ if (lowmem > pc_machine->max_ram_below_4g) { lowmem = pc_machine->max_ram_below_4g; if (machine->ram_size - lowmem > lowmem && lowmem & ((1ULL << 30) - 1)) { error_report("Warning: Large machine and max_ram_below_4g(%"PRIu64 ") not a multiple of 1G; possible bad performance.", pc_machine->max_ram_below_4g); } } if (machine->ram_size >= lowmem) { above_4g_mem_size = machine->ram_size - lowmem; below_4g_mem_size = lowmem; } else { above_4g_mem_size = 0; below_4g_mem_size = machine->ram_size; } if (xen_enabled() && xen_hvm_init(&below_4g_mem_size, &above_4g_mem_size, &ram_memory) != 0) { fprintf(stderr, "xen hardware virtual machine initialisation failed\n"); exit(1); } icc_bridge = qdev_create(NULL, TYPE_ICC_BRIDGE); object_property_add_child(qdev_get_machine(), "icc-bridge", OBJECT(icc_bridge), NULL); pc_cpus_init(machine->cpu_model, icc_bridge); if (kvm_enabled() && kvmclock_enabled) { kvmclock_create(); } if (pci_enabled) { pci_memory = g_new(MemoryRegion, 1); memory_region_init(pci_memory, NULL, "pci", UINT64_MAX); rom_memory = pci_memory; } else { pci_memory = NULL; rom_memory = system_memory; } guest_info = pc_guest_info_init(below_4g_mem_size, above_4g_mem_size); guest_info->has_acpi_build = has_acpi_build; guest_info->legacy_acpi_table_size = legacy_acpi_table_size; guest_info->isapc_ram_fw = !pci_enabled; guest_info->has_reserved_memory = has_reserved_memory; guest_info->rsdp_in_ram = rsdp_in_ram; if (smbios_defaults) { MachineClass *mc = MACHINE_GET_CLASS(machine); /* These values are guest ABI, do not change */ smbios_set_defaults("QEMU", "Standard PC (i440FX + PIIX, 1996)", mc->name, smbios_legacy_mode, smbios_uuid_encoded); } /* allocate ram and load rom/bios */ if (!xen_enabled()) { fw_cfg = pc_memory_init(machine, system_memory, below_4g_mem_size, above_4g_mem_size, rom_memory, &ram_memory, guest_info); } else if (machine->kernel_filename != NULL) { /* For xen HVM direct kernel boot, load linux here */ fw_cfg = xen_load_linux(machine->kernel_filename, machine->kernel_cmdline, machine->initrd_filename, below_4g_mem_size, guest_info); } gsi_state = g_malloc0(sizeof(*gsi_state)); if (kvm_irqchip_in_kernel()) { kvm_pc_setup_irq_routing(pci_enabled); gsi = qemu_allocate_irqs(kvm_pc_gsi_handler, gsi_state, GSI_NUM_PINS); } else { gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS); } if (pci_enabled) { pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, &isa_bus, gsi, system_memory, system_io, machine->ram_size, below_4g_mem_size, above_4g_mem_size, pci_memory, ram_memory); } else { pci_bus = NULL; i440fx_state = NULL; isa_bus = isa_bus_new(NULL, get_system_memory(), system_io); no_hpet = 1; } isa_bus_irqs(isa_bus, gsi); if (kvm_irqchip_in_kernel()) { i8259 = kvm_i8259_init(isa_bus); } else if (xen_enabled()) { i8259 = xen_interrupt_controller_init(); } else { cpu_irq = pc_allocate_cpu_irq(); i8259 = i8259_init(isa_bus, cpu_irq[0]); } for (i = 0; i < ISA_NUM_IRQS; i++) { gsi_state->i8259_irq[i] = i8259[i]; } if (pci_enabled) { ioapic_init_gsi(gsi_state, "i440fx"); } qdev_init_nofail(icc_bridge); pc_register_ferr_irq(gsi[13]); pc_vga_init(isa_bus, pci_enabled ? pci_bus : NULL); assert(pc_machine->vmport != ON_OFF_AUTO_MAX); if (pc_machine->vmport == ON_OFF_AUTO_AUTO) { pc_machine->vmport = xen_enabled() ? ON_OFF_AUTO_OFF : ON_OFF_AUTO_ON; } /* init basic PC hardware */ pc_basic_device_init(isa_bus, gsi, &rtc_state, &floppy, (pc_machine->vmport != ON_OFF_AUTO_ON), 0x4); pc_nic_init(isa_bus, pci_bus); ide_drive_get(hd, ARRAY_SIZE(hd)); if (pci_enabled) { PCIDevice *dev; if (xen_enabled()) { dev = pci_piix3_xen_ide_init(pci_bus, hd, piix3_devfn + 1); } else { dev = pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1); } idebus[0] = qdev_get_child_bus(&dev->qdev, "ide.0"); idebus[1] = qdev_get_child_bus(&dev->qdev, "ide.1"); } else { for(i = 0; i < MAX_IDE_BUS; i++) { ISADevice *dev; char busname[] = "ide.0"; dev = isa_ide_init(isa_bus, ide_iobase[i], ide_iobase2[i], ide_irq[i], hd[MAX_IDE_DEVS * i], hd[MAX_IDE_DEVS * i + 1]); /* * The ide bus name is ide.0 for the first bus and ide.1 for the * second one. */ busname[4] = '0' + i; idebus[i] = qdev_get_child_bus(DEVICE(dev), busname); } } pc_cmos_init(below_4g_mem_size, above_4g_mem_size, machine->boot_order, machine, floppy, idebus[0], idebus[1], rtc_state); if (pci_enabled && usb_enabled()) { pci_create_simple(pci_bus, piix3_devfn + 2, "piix3-usb-uhci"); } if (pci_enabled && acpi_enabled) { DeviceState *piix4_pm; I2CBus *smbus; smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt, first_cpu, 1); /* TODO: Populate SPD eeprom data. */ smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100, gsi[9], *smi_irq, kvm_enabled(), fw_cfg, &piix4_pm); smbus_eeprom_init(smbus, 8, NULL, 0); object_property_add_link(OBJECT(machine), PC_MACHINE_ACPI_DEVICE_PROP, TYPE_HOTPLUG_HANDLER, (Object **)&pc_machine->acpi_dev, object_property_allow_set_link, OBJ_PROP_LINK_UNREF_ON_RELEASE, &error_abort); object_property_set_link(OBJECT(machine), OBJECT(piix4_pm), PC_MACHINE_ACPI_DEVICE_PROP, &error_abort); } if (pci_enabled) { pc_pci_device_init(pci_bus); } }
/* PowerPC Mac99 hardware initialisation */ static void ppc_core99_init(MachineState *machine) { ram_addr_t ram_size = machine->ram_size; const char *kernel_filename = machine->kernel_filename; const char *kernel_cmdline = machine->kernel_cmdline; const char *initrd_filename = machine->initrd_filename; const char *boot_device = machine->boot_order; PowerPCCPU *cpu = NULL; CPUPPCState *env = NULL; char *filename; qemu_irq *pic, **openpic_irqs; MemoryRegion *isa = g_new(MemoryRegion, 1); MemoryRegion *unin_memory = g_new(MemoryRegion, 1); MemoryRegion *unin2_memory = g_new(MemoryRegion, 1); int linux_boot, i, j, k; MemoryRegion *ram = g_new(MemoryRegion, 1), *bios = g_new(MemoryRegion, 1); hwaddr kernel_base, initrd_base, cmdline_base = 0; long kernel_size, initrd_size; PCIBus *pci_bus; NewWorldMacIOState *macio; MACIOIDEState *macio_ide; BusState *adb_bus; MacIONVRAMState *nvr; int bios_size, ndrv_size; uint8_t *ndrv_file; int ppc_boot_device; DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; void *fw_cfg; int machine_arch; SysBusDevice *s; DeviceState *dev, *pic_dev; int *token = g_new(int, 1); hwaddr nvram_addr = 0xFFF04000; uint64_t tbfreq; linux_boot = (kernel_filename != NULL); /* init CPUs */ for (i = 0; i < smp_cpus; i++) { cpu = POWERPC_CPU(cpu_create(machine->cpu_type)); env = &cpu->env; /* Set time-base frequency to 100 Mhz */ cpu_ppc_tb_init(env, TBFREQ); qemu_register_reset(ppc_core99_reset, cpu); } /* allocate RAM */ memory_region_allocate_system_memory(ram, NULL, "ppc_core99.ram", ram_size); memory_region_add_subregion(get_system_memory(), 0, ram); /* allocate and load BIOS */ memory_region_init_ram(bios, NULL, "ppc_core99.bios", BIOS_SIZE, &error_fatal); if (bios_name == NULL) bios_name = PROM_FILENAME; filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name); memory_region_set_readonly(bios, true); memory_region_add_subregion(get_system_memory(), PROM_ADDR, bios); /* Load OpenBIOS (ELF) */ if (filename) { bios_size = load_elf(filename, NULL, NULL, NULL, NULL, NULL, 1, PPC_ELF_MACHINE, 0, 0); g_free(filename); } else { bios_size = -1; } if (bios_size < 0 || bios_size > BIOS_SIZE) { error_report("could not load PowerPC bios '%s'", bios_name); exit(1); } if (linux_boot) { uint64_t lowaddr = 0; int bswap_needed; #ifdef BSWAP_NEEDED bswap_needed = 1; #else bswap_needed = 0; #endif kernel_base = KERNEL_LOAD_ADDR; kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL, NULL, &lowaddr, NULL, 1, PPC_ELF_MACHINE, 0, 0); if (kernel_size < 0) kernel_size = load_aout(kernel_filename, kernel_base, ram_size - kernel_base, bswap_needed, TARGET_PAGE_SIZE); if (kernel_size < 0) kernel_size = load_image_targphys(kernel_filename, kernel_base, ram_size - kernel_base); if (kernel_size < 0) { error_report("could not load kernel '%s'", kernel_filename); exit(1); } /* load initrd */ if (initrd_filename) { initrd_base = TARGET_PAGE_ALIGN(kernel_base + kernel_size + KERNEL_GAP); initrd_size = load_image_targphys(initrd_filename, initrd_base, ram_size - initrd_base); if (initrd_size < 0) { error_report("could not load initial ram disk '%s'", initrd_filename); exit(1); } cmdline_base = TARGET_PAGE_ALIGN(initrd_base + initrd_size); } else { initrd_base = 0; initrd_size = 0; cmdline_base = TARGET_PAGE_ALIGN(kernel_base + kernel_size + KERNEL_GAP); } ppc_boot_device = 'm'; } else { kernel_base = 0; kernel_size = 0; initrd_base = 0; initrd_size = 0; ppc_boot_device = '\0'; /* We consider that NewWorld PowerMac never have any floppy drive * For now, OHW cannot boot from the network. */ for (i = 0; boot_device[i] != '\0'; i++) { if (boot_device[i] >= 'c' && boot_device[i] <= 'f') { ppc_boot_device = boot_device[i]; break; } } if (ppc_boot_device == '\0') { error_report("No valid boot device for Mac99 machine"); exit(1); } } /* Register 8 MB of ISA IO space */ memory_region_init_alias(isa, NULL, "isa_mmio", get_system_io(), 0, 0x00800000); memory_region_add_subregion(get_system_memory(), 0xf2000000, isa); /* UniN init: XXX should be a real device */ memory_region_init_io(unin_memory, NULL, &unin_ops, token, "unin", 0x1000); memory_region_add_subregion(get_system_memory(), 0xf8000000, unin_memory); memory_region_init_io(unin2_memory, NULL, &unin_ops, token, "unin", 0x1000); memory_region_add_subregion(get_system_memory(), 0xf3000000, unin2_memory); openpic_irqs = g_malloc0(smp_cpus * sizeof(qemu_irq *)); openpic_irqs[0] = g_malloc0(smp_cpus * sizeof(qemu_irq) * OPENPIC_OUTPUT_NB); for (i = 0; i < smp_cpus; i++) { /* Mac99 IRQ connection between OpenPIC outputs pins * and PowerPC input pins */ switch (PPC_INPUT(env)) { case PPC_FLAGS_INPUT_6xx: openpic_irqs[i] = openpic_irqs[0] + (i * OPENPIC_OUTPUT_NB); openpic_irqs[i][OPENPIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT]; openpic_irqs[i][OPENPIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_INT]; openpic_irqs[i][OPENPIC_OUTPUT_MCK] = ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_MCP]; /* Not connected ? */ openpic_irqs[i][OPENPIC_OUTPUT_DEBUG] = NULL; /* Check this */ openpic_irqs[i][OPENPIC_OUTPUT_RESET] = ((qemu_irq *)env->irq_inputs)[PPC6xx_INPUT_HRESET]; break; #if defined(TARGET_PPC64) case PPC_FLAGS_INPUT_970: openpic_irqs[i] = openpic_irqs[0] + (i * OPENPIC_OUTPUT_NB); openpic_irqs[i][OPENPIC_OUTPUT_INT] = ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_INT]; openpic_irqs[i][OPENPIC_OUTPUT_CINT] = ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_INT]; openpic_irqs[i][OPENPIC_OUTPUT_MCK] = ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_MCP]; /* Not connected ? */ openpic_irqs[i][OPENPIC_OUTPUT_DEBUG] = NULL; /* Check this */ openpic_irqs[i][OPENPIC_OUTPUT_RESET] = ((qemu_irq *)env->irq_inputs)[PPC970_INPUT_HRESET]; break; #endif /* defined(TARGET_PPC64) */ default: error_report("Bus model not supported on mac99 machine"); exit(1); } } pic = g_new0(qemu_irq, 64); pic_dev = qdev_create(NULL, TYPE_OPENPIC); qdev_prop_set_uint32(pic_dev, "model", OPENPIC_MODEL_KEYLARGO); qdev_init_nofail(pic_dev); s = SYS_BUS_DEVICE(pic_dev); k = 0; for (i = 0; i < smp_cpus; i++) { for (j = 0; j < OPENPIC_OUTPUT_NB; j++) { sysbus_connect_irq(s, k++, openpic_irqs[i][j]); } } for (i = 0; i < 64; i++) { pic[i] = qdev_get_gpio_in(pic_dev, i); } if (PPC_INPUT(env) == PPC_FLAGS_INPUT_970) { /* 970 gets a U3 bus */ pci_bus = pci_pmac_u3_init(pic, get_system_memory(), get_system_io()); machine_arch = ARCH_MAC99_U3; } else { pci_bus = pci_pmac_init(pic, get_system_memory(), get_system_io()); machine_arch = ARCH_MAC99; } object_property_set_bool(OBJECT(pci_bus), true, "realized", &error_abort); machine->usb |= defaults_enabled() && !machine->usb_disabled; /* Timebase Frequency */ if (kvm_enabled()) { tbfreq = kvmppc_get_tbfreq(); } else { tbfreq = TBFREQ; } /* MacIO */ macio = NEWWORLD_MACIO(pci_create(pci_bus, -1, TYPE_NEWWORLD_MACIO)); dev = DEVICE(macio); qdev_connect_gpio_out(dev, 0, pic[0x19]); /* CUDA */ qdev_connect_gpio_out(dev, 1, pic[0x24]); /* ESCC-B */ qdev_connect_gpio_out(dev, 2, pic[0x25]); /* ESCC-A */ qdev_connect_gpio_out(dev, 3, pic[0x0d]); /* IDE */ qdev_connect_gpio_out(dev, 4, pic[0x02]); /* IDE DMA */ qdev_connect_gpio_out(dev, 5, pic[0x0e]); /* IDE */ qdev_connect_gpio_out(dev, 6, pic[0x03]); /* IDE DMA */ qdev_prop_set_uint64(dev, "frequency", tbfreq); object_property_set_link(OBJECT(macio), OBJECT(pic_dev), "pic", &error_abort); qdev_init_nofail(dev); /* We only emulate 2 out of 3 IDE controllers for now */ ide_drive_get(hd, ARRAY_SIZE(hd)); macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio), "ide[0]")); macio_ide_init_drives(macio_ide, hd); macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio), "ide[1]")); macio_ide_init_drives(macio_ide, &hd[MAX_IDE_DEVS]); dev = DEVICE(object_resolve_path_component(OBJECT(macio), "cuda")); adb_bus = qdev_get_child_bus(dev, "adb.0"); dev = qdev_create(adb_bus, TYPE_ADB_KEYBOARD); qdev_init_nofail(dev); dev = qdev_create(adb_bus, TYPE_ADB_MOUSE); qdev_init_nofail(dev); if (machine->usb) { pci_create_simple(pci_bus, -1, "pci-ohci"); /* U3 needs to use USB for input because Linux doesn't support via-cuda on PPC64 */ if (machine_arch == ARCH_MAC99_U3) { USBBus *usb_bus = usb_bus_find(-1); usb_create_simple(usb_bus, "usb-kbd"); usb_create_simple(usb_bus, "usb-mouse"); } } pci_vga_init(pci_bus); if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8) { graphic_depth = 15; } for (i = 0; i < nb_nics; i++) { pci_nic_init_nofail(&nd_table[i], pci_bus, "ne2k_pci", NULL); } /* The NewWorld NVRAM is not located in the MacIO device */ #ifdef CONFIG_KVM if (kvm_enabled() && getpagesize() > 4096) { /* We can't combine read-write and read-only in a single page, so move the NVRAM out of ROM again for KVM */ nvram_addr = 0xFFE00000; } #endif dev = qdev_create(NULL, TYPE_MACIO_NVRAM); qdev_prop_set_uint32(dev, "size", 0x2000); qdev_prop_set_uint32(dev, "it_shift", 1); qdev_init_nofail(dev); sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, nvram_addr); nvr = MACIO_NVRAM(dev); pmac_format_nvram_partition(nvr, 0x2000); /* No PCI init: the BIOS will do it */ fw_cfg = fw_cfg_init_mem(CFG_ADDR, CFG_ADDR + 2); fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, (uint16_t)smp_cpus); fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus); fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, machine_arch); fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, kernel_base); fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size); if (kernel_cmdline) { fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, cmdline_base); pstrcpy_targphys("cmdline", cmdline_base, TARGET_PAGE_SIZE, kernel_cmdline); } else { fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0); } fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, initrd_base); fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, initrd_size); fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, ppc_boot_device); fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_WIDTH, graphic_width); fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_HEIGHT, graphic_height); fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_DEPTH, graphic_depth); fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_IS_KVM, kvm_enabled()); if (kvm_enabled()) { #ifdef CONFIG_KVM uint8_t *hypercall; hypercall = g_malloc(16); kvmppc_get_hypercall(env, hypercall, 16); fw_cfg_add_bytes(fw_cfg, FW_CFG_PPC_KVM_HC, hypercall, 16); fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_KVM_PID, getpid()); #endif } fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, tbfreq); /* Mac OS X requires a "known good" clock-frequency value; pass it one. */ fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_CLOCKFREQ, CLOCKFREQ); fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_BUSFREQ, BUSFREQ); fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_NVRAM_ADDR, nvram_addr); /* MacOS NDRV VGA driver */ filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, NDRV_VGA_FILENAME); if (filename) { ndrv_size = get_image_size(filename); if (ndrv_size != -1) { ndrv_file = g_malloc(ndrv_size); ndrv_size = load_image(filename, ndrv_file); fw_cfg_add_file(fw_cfg, "ndrv/qemu_vga.ndrv", ndrv_file, ndrv_size); } g_free(filename); } qemu_register_boot_set(fw_cfg_boot_set, fw_cfg); }
/* PC hardware initialisation */ static void pc_q35_init(MachineState *machine) { PCMachineState *pcms = PC_MACHINE(machine); PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms); Q35PCIHost *q35_host; PCIHostState *phb; PCIBus *host_bus; PCIDevice *lpc; DeviceState *lpc_dev; BusState *idebus[MAX_SATA_PORTS]; ISADevice *rtc_state; MemoryRegion *system_io = get_system_io(); MemoryRegion *pci_memory; MemoryRegion *rom_memory; MemoryRegion *ram_memory; GSIState *gsi_state; ISABus *isa_bus; qemu_irq *i8259; int i; ICH9LPCState *ich9_lpc; PCIDevice *ahci; ram_addr_t lowmem; DriveInfo *hd[MAX_SATA_PORTS]; MachineClass *mc = MACHINE_GET_CLASS(machine); /* Check whether RAM fits below 4G (leaving 1/2 GByte for IO memory * and 256 Mbytes for PCI Express Enhanced Configuration Access Mapping * also known as MMCFG). * If it doesn't, we need to split it in chunks below and above 4G. * In any case, try to make sure that guest addresses aligned at * 1G boundaries get mapped to host addresses aligned at 1G boundaries. */ if (machine->ram_size >= 0xb0000000) { lowmem = 0x80000000; } else { lowmem = 0xb0000000; } /* Handle the machine opt max-ram-below-4g. It is basically doing * min(qemu limit, user limit). */ if (!pcms->max_ram_below_4g) { pcms->max_ram_below_4g = 1ULL << 32; /* default: 4G */; } if (lowmem > pcms->max_ram_below_4g) { lowmem = pcms->max_ram_below_4g; if (machine->ram_size - lowmem > lowmem && lowmem & ((1ULL << 30) - 1)) { error_report("Warning: Large machine and max_ram_below_4g(%"PRIu64 ") not a multiple of 1G; possible bad performance.", pcms->max_ram_below_4g); } } if (machine->ram_size >= lowmem) { pcms->above_4g_mem_size = machine->ram_size - lowmem; pcms->below_4g_mem_size = lowmem; } else { pcms->above_4g_mem_size = 0; pcms->below_4g_mem_size = machine->ram_size; } if (xen_enabled()) { xen_hvm_init(pcms, &ram_memory); } pc_cpus_init(pcms); kvmclock_create(); /* pci enabled */ if (pcmc->pci_enabled) { pci_memory = g_new(MemoryRegion, 1); memory_region_init(pci_memory, NULL, "pci", UINT64_MAX); rom_memory = pci_memory; } else { pci_memory = NULL; rom_memory = get_system_memory(); } pc_guest_info_init(pcms); if (pcmc->smbios_defaults) { /* These values are guest ABI, do not change */ smbios_set_defaults("QEMU", "Standard PC (Q35 + ICH9, 2009)", mc->name, pcmc->smbios_legacy_mode, pcmc->smbios_uuid_encoded, SMBIOS_ENTRY_POINT_21); } /* allocate ram and load rom/bios */ if (!xen_enabled()) { pc_memory_init(pcms, get_system_memory(), rom_memory, &ram_memory); } /* irq lines */ gsi_state = g_malloc0(sizeof(*gsi_state)); if (kvm_ioapic_in_kernel()) { kvm_pc_setup_irq_routing(pcmc->pci_enabled); pcms->gsi = qemu_allocate_irqs(kvm_pc_gsi_handler, gsi_state, GSI_NUM_PINS); } else { pcms->gsi = qemu_allocate_irqs(gsi_handler, gsi_state, GSI_NUM_PINS); } /* create pci host bus */ q35_host = Q35_HOST_DEVICE(qdev_create(NULL, TYPE_Q35_HOST_DEVICE)); object_property_add_child(qdev_get_machine(), "q35", OBJECT(q35_host), NULL); object_property_set_link(OBJECT(q35_host), OBJECT(ram_memory), MCH_HOST_PROP_RAM_MEM, NULL); object_property_set_link(OBJECT(q35_host), OBJECT(pci_memory), MCH_HOST_PROP_PCI_MEM, NULL); object_property_set_link(OBJECT(q35_host), OBJECT(get_system_memory()), MCH_HOST_PROP_SYSTEM_MEM, NULL); object_property_set_link(OBJECT(q35_host), OBJECT(system_io), MCH_HOST_PROP_IO_MEM, NULL); object_property_set_int(OBJECT(q35_host), pcms->below_4g_mem_size, PCI_HOST_BELOW_4G_MEM_SIZE, NULL); object_property_set_int(OBJECT(q35_host), pcms->above_4g_mem_size, PCI_HOST_ABOVE_4G_MEM_SIZE, NULL); /* pci */ qdev_init_nofail(DEVICE(q35_host)); phb = PCI_HOST_BRIDGE(q35_host); host_bus = phb->bus; /* create ISA bus */ lpc = pci_create_simple_multifunction(host_bus, PCI_DEVFN(ICH9_LPC_DEV, ICH9_LPC_FUNC), true, TYPE_ICH9_LPC_DEVICE); object_property_add_link(OBJECT(machine), PC_MACHINE_ACPI_DEVICE_PROP, TYPE_HOTPLUG_HANDLER, (Object **)&pcms->acpi_dev, object_property_allow_set_link, OBJ_PROP_LINK_UNREF_ON_RELEASE, &error_abort); object_property_set_link(OBJECT(machine), OBJECT(lpc), PC_MACHINE_ACPI_DEVICE_PROP, &error_abort); ich9_lpc = ICH9_LPC_DEVICE(lpc); lpc_dev = DEVICE(lpc); for (i = 0; i < GSI_NUM_PINS; i++) { qdev_connect_gpio_out_named(lpc_dev, ICH9_GPIO_GSI, i, pcms->gsi[i]); } pci_bus_irqs(host_bus, ich9_lpc_set_irq, ich9_lpc_map_irq, ich9_lpc, ICH9_LPC_NB_PIRQS); pci_bus_set_route_irq_fn(host_bus, ich9_route_intx_pin_to_irq); isa_bus = ich9_lpc->isa_bus; if (kvm_pic_in_kernel()) { i8259 = kvm_i8259_init(isa_bus); } else if (xen_enabled()) { i8259 = xen_interrupt_controller_init(); } else { i8259 = i8259_init(isa_bus, pc_allocate_cpu_irq()); } for (i = 0; i < ISA_NUM_IRQS; i++) { gsi_state->i8259_irq[i] = i8259[i]; } g_free(i8259); if (pcmc->pci_enabled) { ioapic_init_gsi(gsi_state, "q35"); } pc_register_ferr_irq(pcms->gsi[13]); assert(pcms->vmport != ON_OFF_AUTO__MAX); if (pcms->vmport == ON_OFF_AUTO_AUTO) { pcms->vmport = ON_OFF_AUTO_OFF; } /* init basic PC hardware */ pc_basic_device_init(isa_bus, pcms->gsi, &rtc_state, !mc->no_floppy, (pcms->vmport != ON_OFF_AUTO_ON), 0xff0104); /* connect pm stuff to lpc */ ich9_lpc_pm_init(lpc, pc_machine_is_smm_enabled(pcms)); /* ahci and SATA device, for q35 1 ahci controller is built-in */ ahci = pci_create_simple_multifunction(host_bus, PCI_DEVFN(ICH9_SATA1_DEV, ICH9_SATA1_FUNC), true, "ich9-ahci"); idebus[0] = qdev_get_child_bus(&ahci->qdev, "ide.0"); idebus[1] = qdev_get_child_bus(&ahci->qdev, "ide.1"); g_assert(MAX_SATA_PORTS == ICH_AHCI(ahci)->ahci.ports); ide_drive_get(hd, ICH_AHCI(ahci)->ahci.ports); ahci_ide_create_devs(ahci, hd); if (machine_usb(machine)) { /* Should we create 6 UHCI according to ich9 spec? */ ehci_create_ich9_with_companions(host_bus, 0x1d); } /* TODO: Populate SPD eeprom data. */ smbus_eeprom_init(ich9_smb_init(host_bus, PCI_DEVFN(ICH9_SMB_DEV, ICH9_SMB_FUNC), 0xb100), 8, NULL, 0); pc_cmos_init(pcms, idebus[0], idebus[1], rtc_state); /* the rest devices to which pci devfn is automatically assigned */ pc_vga_init(isa_bus, host_bus); pc_nic_init(isa_bus, host_bus); if (pcmc->pci_enabled) { pc_pci_device_init(host_bus); } if (pcms->acpi_nvdimm_state.is_enabled) { nvdimm_init_acpi_state(&pcms->acpi_nvdimm_state, system_io, pcms->fw_cfg, OBJECT(pcms)); } }
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 int img_create(int argc, char **argv) { int c, ret = 0; uint64_t img_size = -1; const char *fmt = "raw"; const char *base_fmt = NULL; const char *filename; const char *base_filename = NULL; char *options = NULL; for(;;) { c = getopt(argc, argv, "F:b:f:he6o:"); if (c == -1) { break; } switch(c) { case '?': case 'h': help(); break; case 'F': base_fmt = optarg; break; case 'b': base_filename = optarg; break; case 'f': fmt = optarg; break; case 'e': error_report("qemu-img: option -e is deprecated, please use \'-o " "encryption\' instead!"); return 1; case '6': error_report("qemu-img: option -6 is deprecated, please use \'-o " "compat6\' instead!"); return 1; case 'o': options = optarg; break; } } /* Get the filename */ if (optind >= argc) { help(); } filename = argv[optind++]; /* Get image size, if specified */ if (optind < argc) { int64_t sval; sval = strtosz_suffix(argv[optind++], NULL, STRTOSZ_DEFSUFFIX_B); if (sval < 0) { error_report("Invalid image size specified! You may use k, M, G or " "T suffixes for "); error_report("kilobytes, megabytes, gigabytes and terabytes."); ret = -1; goto out; } img_size = (uint64_t)sval; } if (options && !strcmp(options, "?")) { ret = print_block_option_help(filename, fmt); goto out; } ret = bdrv_img_create(filename, fmt, base_filename, base_fmt, options, img_size, BDRV_O_FLAGS); out: if (ret) { return 1; } return 0; }
/* * Scan the assigned devices for the devices that have an option ROM, and then * load the corresponding ROM data to RAM. If an error occurs while loading an * option ROM, we just ignore that option ROM and continue with the next one. */ void *pci_assign_dev_load_option_rom(PCIDevice *dev, struct Object *owner, int *size, unsigned int domain, unsigned int bus, unsigned int slot, unsigned int function) { char name[32], rom_file[64]; FILE *fp; uint8_t val; struct stat st; void *ptr = NULL; /* If loading ROM from file, pci handles it */ if (dev->romfile || !dev->rom_bar) { return NULL; } snprintf(rom_file, sizeof(rom_file), "/sys/bus/pci/devices/%04x:%02x:%02x.%01x/rom", domain, bus, slot, function); /* Write "1" to the ROM file to enable it */ fp = fopen(rom_file, "r+"); if (fp == NULL) { if (errno != ENOENT) { error_report("pci-assign: Cannot open %s: %s", rom_file, strerror(errno)); } return NULL; } if (fstat(fileno(fp), &st) == -1) { error_report("pci-assign: Cannot stat %s: %s", rom_file, strerror(errno)); goto close_rom; } val = 1; if (fwrite(&val, 1, 1, fp) != 1) { goto close_rom; } fseek(fp, 0, SEEK_SET); snprintf(name, sizeof(name), "%s.rom", object_get_typename(owner)); memory_region_init_ram(&dev->rom, owner, name, st.st_size, &error_abort); vmstate_register_ram(&dev->rom, &dev->qdev); ptr = memory_region_get_ram_ptr(&dev->rom); memset(ptr, 0xff, st.st_size); if (!fread(ptr, 1, st.st_size, fp)) { error_report("pci-assign: Cannot read from host %s", rom_file); error_printf("Device option ROM contents are probably invalid " "(check dmesg).\nSkip option ROM probe with rombar=0, " "or load from file with romfile=\n"); goto close_rom; } pci_register_bar(dev, PCI_ROM_SLOT, 0, &dev->rom); dev->has_rom = true; *size = st.st_size; close_rom: /* Write "0" to disable ROM */ fseek(fp, 0, SEEK_SET); val = 0; if (!fwrite(&val, 1, 1, fp)) { DEBUG("%s\n", "Failed to disable pci-sysfs rom file"); } fclose(fp); return ptr; }
/* * Checks an image for consistency. Exit codes: * * 0 - Check completed, image is good * 1 - Check not completed because of internal errors * 2 - Check completed, image is corrupted * 3 - Check completed, image has leaked clusters, but is good otherwise */ static int img_check(int argc, char **argv) { int c, ret; const char *filename, *fmt; BlockDriverState *bs; BdrvCheckResult result; fmt = NULL; for(;;) { c = getopt(argc, argv, "f:h"); if (c == -1) { break; } switch(c) { case '?': case 'h': help(); break; case 'f': fmt = optarg; break; } } if (optind >= argc) { help(); } filename = argv[optind++]; bs = bdrv_new_open(filename, fmt, BDRV_O_FLAGS); if (!bs) { return 1; } ret = bdrv_check(bs, &result); if (ret == -ENOTSUP) { error_report("This image format does not support checks"); bdrv_delete(bs); return 1; } if (!(result.corruptions || result.leaks || result.check_errors)) { printf("No errors were found on the image.\n"); } else { if (result.corruptions) { printf("\n%d errors were found on the image.\n" "Data may be corrupted, or further writes to the image " "may corrupt it.\n", result.corruptions); } if (result.leaks) { printf("\n%d leaked clusters were found on the image.\n" "This means waste of disk space, but no harm to data.\n", result.leaks); } if (result.check_errors) { printf("\n%d internal errors have occurred during the check.\n", result.check_errors); } } bdrv_delete(bs); if (ret < 0 || result.check_errors) { printf("\nAn error has occurred during the check: %s\n" "The check is not complete and may have missed error.\n", strerror(-ret)); return 1; } if (result.corruptions) { return 2; } else if (result.leaks) { return 3; } else { return 0; } }
static void vfio_prereg_listener_region_add(MemoryListener *listener, MemoryRegionSection *section) { VFIOContainer *container = container_of(listener, VFIOContainer, prereg_listener); const hwaddr gpa = section->offset_within_address_space; hwaddr end; int ret; hwaddr page_mask = qemu_real_host_page_mask; struct vfio_iommu_spapr_register_memory reg = { .argsz = sizeof(reg), .flags = 0, }; if (vfio_prereg_listener_skipped_section(section)) { trace_vfio_prereg_listener_region_add_skip( section->offset_within_address_space, section->offset_within_address_space + int128_get64(int128_sub(section->size, int128_one()))); return; } if (unlikely((section->offset_within_address_space & ~page_mask) || (section->offset_within_region & ~page_mask) || (int128_get64(section->size) & ~page_mask))) { error_report("%s received unaligned region", __func__); return; } end = section->offset_within_address_space + int128_get64(section->size); if (gpa >= end) { return; } memory_region_ref(section->mr); reg.vaddr = (uintptr_t) vfio_prereg_gpa_to_vaddr(section, gpa); reg.size = end - gpa; ret = ioctl(container->fd, VFIO_IOMMU_SPAPR_REGISTER_MEMORY, ®); trace_vfio_prereg_register(reg.vaddr, reg.size, ret ? -errno : 0); if (ret) { /* * On the initfn path, store the first error in the container so we * can gracefully fail. Runtime, there's not much we can do other * than throw a hardware error. */ if (!container->initialized) { if (!container->error) { container->error = ret; } } else { hw_error("vfio: Memory registering failed, unable to continue"); } } } static void vfio_prereg_listener_region_del(MemoryListener *listener, MemoryRegionSection *section) { VFIOContainer *container = container_of(listener, VFIOContainer, prereg_listener); const hwaddr gpa = section->offset_within_address_space; hwaddr end; int ret; hwaddr page_mask = qemu_real_host_page_mask; struct vfio_iommu_spapr_register_memory reg = { .argsz = sizeof(reg), .flags = 0, }; if (vfio_prereg_listener_skipped_section(section)) { trace_vfio_prereg_listener_region_del_skip( section->offset_within_address_space, section->offset_within_address_space + int128_get64(int128_sub(section->size, int128_one()))); return; } if (unlikely((section->offset_within_address_space & ~page_mask) || (section->offset_within_region & ~page_mask) || (int128_get64(section->size) & ~page_mask))) { error_report("%s received unaligned region", __func__); return; } end = section->offset_within_address_space + int128_get64(section->size); if (gpa >= end) { return; } reg.vaddr = (uintptr_t) vfio_prereg_gpa_to_vaddr(section, gpa); reg.size = end - gpa; ret = ioctl(container->fd, VFIO_IOMMU_SPAPR_UNREGISTER_MEMORY, ®); trace_vfio_prereg_unregister(reg.vaddr, reg.size, ret ? -errno : 0); } const MemoryListener vfio_prereg_listener = { .region_add = vfio_prereg_listener_region_add, .region_del = vfio_prereg_listener_region_del, }; int vfio_spapr_create_window(VFIOContainer *container, MemoryRegionSection *section, hwaddr *pgsize) { int ret; IOMMUMemoryRegion *iommu_mr = IOMMU_MEMORY_REGION(section->mr); unsigned pagesize = memory_region_iommu_get_min_page_size(iommu_mr); unsigned entries, pages; struct vfio_iommu_spapr_tce_create create = { .argsz = sizeof(create) }; /* * FIXME: For VFIO iommu types which have KVM acceleration to * avoid bouncing all map/unmaps through qemu this way, this * would be the right place to wire that up (tell the KVM * device emulation the VFIO iommu handles to use). */ create.window_size = int128_get64(section->size); create.page_shift = ctz64(pagesize); /* * SPAPR host supports multilevel TCE tables, there is some * heuristic to decide how many levels we want for our table: * 0..64 = 1; 65..4096 = 2; 4097..262144 = 3; 262145.. = 4 */ entries = create.window_size >> create.page_shift; pages = MAX((entries * sizeof(uint64_t)) / getpagesize(), 1); pages = MAX(pow2ceil(pages) - 1, 1); /* Round up */ create.levels = ctz64(pages) / 6 + 1; ret = ioctl(container->fd, VFIO_IOMMU_SPAPR_TCE_CREATE, &create); if (ret) { error_report("Failed to create a window, ret = %d (%m)", ret); return -errno; } if (create.start_addr != section->offset_within_address_space) { vfio_spapr_remove_window(container, create.start_addr); error_report("Host doesn't support DMA window at %"HWADDR_PRIx", must be %"PRIx64, section->offset_within_address_space, (uint64_t)create.start_addr); return -EINVAL; } trace_vfio_spapr_create_window(create.page_shift, create.window_size, create.start_addr); *pgsize = pagesize; return 0; } int vfio_spapr_remove_window(VFIOContainer *container, hwaddr offset_within_address_space) { struct vfio_iommu_spapr_tce_remove remove = { .argsz = sizeof(remove), .start_addr = offset_within_address_space, }; int ret; ret = ioctl(container->fd, VFIO_IOMMU_SPAPR_TCE_REMOVE, &remove); if (ret) { error_report("Failed to remove window at %"PRIx64, (uint64_t)remove.start_addr); return -errno; } trace_vfio_spapr_remove_window(offset_within_address_space); return 0; }
static int img_convert(int argc, char **argv) { int c, ret = 0, n, n1, bs_n, bs_i, compress, cluster_size, cluster_sectors; const char *fmt, *out_fmt, *out_baseimg, *out_filename; BlockDriver *drv, *proto_drv; BlockDriverState **bs = NULL, *out_bs = NULL; int64_t total_sectors, nb_sectors, sector_num, bs_offset; uint64_t bs_sectors; uint8_t * buf = NULL; const uint8_t *buf1; BlockDriverInfo bdi; QEMUOptionParameter *param = NULL, *create_options = NULL; QEMUOptionParameter *out_baseimg_param; char *options = NULL; const char *snapshot_name = NULL; fmt = NULL; out_fmt = "raw"; out_baseimg = NULL; compress = 0; for(;;) { c = getopt(argc, argv, "f:O:B:s:hce6o:"); if (c == -1) { break; } switch(c) { case '?': case 'h': help(); break; case 'f': fmt = optarg; break; case 'O': out_fmt = optarg; break; case 'B': out_baseimg = optarg; break; case 'c': compress = 1; break; case 'e': error_report("qemu-img: option -e is deprecated, please use \'-o " "encryption\' instead!"); return 1; case '6': error_report("qemu-img: option -6 is deprecated, please use \'-o " "compat6\' instead!"); return 1; case 'o': options = optarg; break; case 's': snapshot_name = optarg; break; } } bs_n = argc - optind - 1; if (bs_n < 1) { help(); } out_filename = argv[argc - 1]; if (options && !strcmp(options, "?")) { ret = print_block_option_help(out_filename, out_fmt); goto out; } if (bs_n > 1 && out_baseimg) { error_report("-B makes no sense when concatenating multiple input " "images"); ret = -1; goto out; } bs = qemu_mallocz(bs_n * sizeof(BlockDriverState *)); total_sectors = 0; for (bs_i = 0; bs_i < bs_n; bs_i++) { bs[bs_i] = bdrv_new_open(argv[optind + bs_i], fmt, BDRV_O_FLAGS); if (!bs[bs_i]) { error_report("Could not open '%s'", argv[optind + bs_i]); ret = -1; goto out; } bdrv_get_geometry(bs[bs_i], &bs_sectors); total_sectors += bs_sectors; } if (snapshot_name != NULL) { if (bs_n > 1) { error_report("No support for concatenating multiple snapshot\n"); ret = -1; goto out; } if (bdrv_snapshot_load_tmp(bs[0], snapshot_name) < 0) { error_report("Failed to load snapshot\n"); ret = -1; goto out; } } /* Find driver and parse its options */ drv = bdrv_find_format(out_fmt); if (!drv) { error_report("Unknown file format '%s'", out_fmt); ret = -1; goto out; } proto_drv = bdrv_find_protocol(out_filename); if (!proto_drv) { error_report("Unknown protocol '%s'", out_filename); ret = -1; goto out; } create_options = append_option_parameters(create_options, drv->create_options); create_options = append_option_parameters(create_options, proto_drv->create_options); if (options) { param = parse_option_parameters(options, create_options, param); if (param == NULL) { error_report("Invalid options for file format '%s'.", out_fmt); ret = -1; goto out; } } else { param = parse_option_parameters("", create_options, param); } set_option_parameter_int(param, BLOCK_OPT_SIZE, total_sectors * 512); ret = add_old_style_options(out_fmt, param, out_baseimg, NULL); if (ret < 0) { goto out; } /* Get backing file name if -o backing_file was used */ out_baseimg_param = get_option_parameter(param, BLOCK_OPT_BACKING_FILE); if (out_baseimg_param) { out_baseimg = out_baseimg_param->value.s; } /* Check if compression is supported */ if (compress) { QEMUOptionParameter *encryption = get_option_parameter(param, BLOCK_OPT_ENCRYPT); if (!drv->bdrv_write_compressed) { error_report("Compression not supported for this file format"); ret = -1; goto out; } if (encryption && encryption->value.n) { error_report("Compression and encryption not supported at " "the same time"); ret = -1; goto out; } } /* Create the new image */ ret = bdrv_create(drv, out_filename, param); if (ret < 0) { if (ret == -ENOTSUP) { error_report("Formatting not supported for file format '%s'", out_fmt); } else if (ret == -EFBIG) { error_report("The image size is too large for file format '%s'", out_fmt); } else { error_report("%s: error while converting %s: %s", out_filename, out_fmt, strerror(-ret)); } goto out; } out_bs = bdrv_new_open(out_filename, out_fmt, BDRV_O_FLAGS | BDRV_O_RDWR | BDRV_O_NO_FLUSH); if (!out_bs) { ret = -1; goto out; } bs_i = 0; bs_offset = 0; bdrv_get_geometry(bs[0], &bs_sectors); buf = qemu_malloc(IO_BUF_SIZE); if (compress) { ret = bdrv_get_info(out_bs, &bdi); if (ret < 0) { error_report("could not get block driver info"); goto out; } cluster_size = bdi.cluster_size; if (cluster_size <= 0 || cluster_size > IO_BUF_SIZE) { error_report("invalid cluster size"); ret = -1; goto out; } cluster_sectors = cluster_size >> 9; sector_num = 0; for(;;) { int64_t bs_num; int remainder; uint8_t *buf2; nb_sectors = total_sectors - sector_num; if (nb_sectors <= 0) break; if (nb_sectors >= cluster_sectors) n = cluster_sectors; else n = nb_sectors; bs_num = sector_num - bs_offset; assert (bs_num >= 0); remainder = n; buf2 = buf; while (remainder > 0) { int nlow; while (bs_num == bs_sectors) { bs_i++; assert (bs_i < bs_n); bs_offset += bs_sectors; bdrv_get_geometry(bs[bs_i], &bs_sectors); bs_num = 0; /* printf("changing part: sector_num=%" PRId64 ", " "bs_i=%d, bs_offset=%" PRId64 ", bs_sectors=%" PRId64 "\n", sector_num, bs_i, bs_offset, bs_sectors); */ } assert (bs_num < bs_sectors); nlow = (remainder > bs_sectors - bs_num) ? bs_sectors - bs_num : remainder; ret = bdrv_read(bs[bs_i], bs_num, buf2, nlow); if (ret < 0) { error_report("error while reading"); goto out; } buf2 += nlow * 512; bs_num += nlow; remainder -= nlow; } assert (remainder == 0); if (n < cluster_sectors) { memset(buf + n * 512, 0, cluster_size - n * 512); } if (is_not_zero(buf, cluster_size)) { ret = bdrv_write_compressed(out_bs, sector_num, buf, cluster_sectors); if (ret != 0) { error_report("error while compressing sector %" PRId64, sector_num); goto out; } } sector_num += n; } /* signal EOF to align */ bdrv_write_compressed(out_bs, 0, NULL, 0); } else {
static void ahci_port_write(AHCIState *s, int port, int offset, uint32_t val) { AHCIPortRegs *pr = &s->dev[port].port_regs; DPRINTF(port, "offset: 0x%x val: 0x%x\n", offset, val); switch (offset) { case PORT_LST_ADDR: pr->lst_addr = val; break; case PORT_LST_ADDR_HI: pr->lst_addr_hi = val; break; case PORT_FIS_ADDR: pr->fis_addr = val; break; case PORT_FIS_ADDR_HI: pr->fis_addr_hi = val; break; case PORT_IRQ_STAT: pr->irq_stat &= ~val; ahci_check_irq(s); break; case PORT_IRQ_MASK: pr->irq_mask = val & 0xfdc000ff; ahci_check_irq(s); break; case PORT_CMD: /* Block any Read-only fields from being set; * including LIST_ON and FIS_ON. */ pr->cmd = (pr->cmd & PORT_CMD_RO_MASK) | (val & ~PORT_CMD_RO_MASK); if (pr->cmd & PORT_CMD_START) { if (ahci_map_clb_address(&s->dev[port])) { pr->cmd |= PORT_CMD_LIST_ON; } else { error_report("AHCI: Failed to start DMA engine: " "bad command list buffer address"); } } else if (pr->cmd & PORT_CMD_LIST_ON) { ahci_unmap_clb_address(&s->dev[port]); pr->cmd = pr->cmd & ~(PORT_CMD_LIST_ON); } if (pr->cmd & PORT_CMD_FIS_RX) { if (ahci_map_fis_address(&s->dev[port])) { pr->cmd |= PORT_CMD_FIS_ON; } else { error_report("AHCI: Failed to start FIS receive engine: " "bad FIS receive buffer address"); } } else if (pr->cmd & PORT_CMD_FIS_ON) { ahci_unmap_fis_address(&s->dev[port]); pr->cmd = pr->cmd & ~(PORT_CMD_FIS_ON); } /* XXX usually the FIS would be pending on the bus here and issuing deferred until the OS enables FIS receival. Instead, we only submit it once - which works in most cases, but is a hack. */ if ((pr->cmd & PORT_CMD_FIS_ON) && !s->dev[port].init_d2h_sent) { ahci_init_d2h(&s->dev[port]); s->dev[port].init_d2h_sent = true; } check_cmd(s, port); break; case PORT_TFDATA: /* Read Only. */ break; case PORT_SIG: /* Read Only */ break; case PORT_SCR_STAT: /* Read Only */ break; case PORT_SCR_CTL: if (((pr->scr_ctl & AHCI_SCR_SCTL_DET) == 1) && ((val & AHCI_SCR_SCTL_DET) == 0)) { ahci_reset_port(s, port); } pr->scr_ctl = val; break; case PORT_SCR_ERR: pr->scr_err &= ~val; break; case PORT_SCR_ACT: /* RW1 */ pr->scr_act |= val; break; case PORT_CMD_ISSUE: pr->cmd_issue |= val; check_cmd(s, port); break; default: break; } }
static int qemu_rbd_create(const char *filename, QEMUOptionParameter *options) { int64_t bytes = 0; int64_t objsize; int obj_order = 0; char pool[RBD_MAX_POOL_NAME_SIZE]; char name[RBD_MAX_IMAGE_NAME_SIZE]; char snap_buf[RBD_MAX_SNAP_NAME_SIZE]; char conf[RBD_MAX_CONF_SIZE]; char clientname_buf[RBD_MAX_CONF_SIZE]; char *clientname; rados_t cluster; rados_ioctx_t io_ctx; int ret; if (qemu_rbd_parsename(filename, pool, sizeof(pool), snap_buf, sizeof(snap_buf), name, sizeof(name), conf, sizeof(conf)) < 0) { return -EINVAL; } /* Read out options */ while (options && options->name) { if (!strcmp(options->name, BLOCK_OPT_SIZE)) { bytes = options->value.n; } else if (!strcmp(options->name, BLOCK_OPT_CLUSTER_SIZE)) { if (options->value.n) { objsize = options->value.n; if ((objsize - 1) & objsize) { /* not a power of 2? */ error_report("obj size needs to be power of 2"); return -EINVAL; } if (objsize < 4096) { error_report("obj size too small"); return -EINVAL; } obj_order = ffs(objsize) - 1; } } options++; } clientname = qemu_rbd_parse_clientname(conf, clientname_buf); if (rados_create(&cluster, clientname) < 0) { error_report("error initializing"); return -EIO; } if (strstr(conf, "conf=") == NULL) { /* try default location, but ignore failure */ rados_conf_read_file(cluster, NULL); } if (conf[0] != '\0' && qemu_rbd_set_conf(cluster, conf) < 0) { error_report("error setting config options"); rados_shutdown(cluster); return -EIO; } if (rados_connect(cluster) < 0) { error_report("error connecting"); rados_shutdown(cluster); return -EIO; } if (rados_ioctx_create(cluster, pool, &io_ctx) < 0) { error_report("error opening pool %s", pool); rados_shutdown(cluster); return -EIO; } ret = rbd_create(io_ctx, name, bytes, &obj_order); rados_ioctx_destroy(io_ctx); rados_shutdown(cluster); return ret; }
static void *nbd_client_thread(void *arg) { char *device = arg; off_t size; uint32_t nbdflags; QIOChannelSocket *sioc; int fd; int ret; pthread_t show_parts_thread; Error *local_error = NULL; sioc = qio_channel_socket_new(); if (qio_channel_socket_connect_sync(sioc, saddr, &local_error) < 0) { error_report_err(local_error); goto out; } ret = nbd_receive_negotiate(QIO_CHANNEL(sioc), NULL, &nbdflags, NULL, NULL, NULL, &size, &local_error); if (ret < 0) { if (local_error) { error_report_err(local_error); } goto out_socket; } fd = open(device, O_RDWR); if (fd < 0) { /* Linux-only, we can use %m in printf. */ error_report("Failed to open %s: %m", device); goto out_socket; } ret = nbd_init(fd, sioc, 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); object_unref(OBJECT(sioc)); kill(getpid(), SIGTERM); return (void *) EXIT_SUCCESS; out_fd: close(fd); out_socket: object_unref(OBJECT(sioc)); out: kill(getpid(), SIGTERM); return (void *) EXIT_FAILURE; }
static int qemu_rbd_open(BlockDriverState *bs, const char *filename, int flags) { BDRVRBDState *s = bs->opaque; char pool[RBD_MAX_POOL_NAME_SIZE]; char snap_buf[RBD_MAX_SNAP_NAME_SIZE]; char conf[RBD_MAX_CONF_SIZE]; char clientname_buf[RBD_MAX_CONF_SIZE]; char *clientname; int r; if (qemu_rbd_parsename(filename, pool, sizeof(pool), snap_buf, sizeof(snap_buf), s->name, sizeof(s->name), conf, sizeof(conf)) < 0) { return -EINVAL; } clientname = qemu_rbd_parse_clientname(conf, clientname_buf); r = rados_create(&s->cluster, clientname); if (r < 0) { error_report("error initializing"); return r; } s->snap = NULL; if (snap_buf[0] != '\0') { s->snap = g_strdup(snap_buf); } /* * Fallback to more conservative semantics if setting cache * options fails. Ignore errors from setting rbd_cache because the * only possible error is that the option does not exist, and * librbd defaults to no caching. If write through caching cannot * be set up, fall back to no caching. */ if (flags & BDRV_O_NOCACHE) { rados_conf_set(s->cluster, "rbd_cache", "false"); } else { rados_conf_set(s->cluster, "rbd_cache", "true"); } if (strstr(conf, "conf=") == NULL) { /* try default location, but ignore failure */ rados_conf_read_file(s->cluster, NULL); } if (conf[0] != '\0') { r = qemu_rbd_set_conf(s->cluster, conf); if (r < 0) { error_report("error setting config options"); goto failed_shutdown; } } r = rados_connect(s->cluster); if (r < 0) { error_report("error connecting"); goto failed_shutdown; } r = rados_ioctx_create(s->cluster, pool, &s->io_ctx); if (r < 0) { error_report("error opening pool %s", pool); goto failed_shutdown; } r = rbd_open(s->io_ctx, s->name, &s->image, s->snap); if (r < 0) { error_report("error reading header from %s", s->name); goto failed_open; } bs->read_only = (s->snap != NULL); s->event_reader_pos = 0; r = qemu_pipe(s->fds); if (r < 0) { error_report("error opening eventfd"); goto failed; } fcntl(s->fds[0], F_SETFL, O_NONBLOCK); fcntl(s->fds[1], F_SETFL, O_NONBLOCK); qemu_aio_set_fd_handler(s->fds[RBD_FD_READ], qemu_rbd_aio_event_reader, NULL, qemu_rbd_aio_flush_cb, s); return 0; failed: rbd_close(s->image); failed_open: rados_ioctx_destroy(s->io_ctx); failed_shutdown: rados_shutdown(s->cluster); g_free(s->snap); return r; }
static void sun4m_hw_init(const struct sun4m_hwdef *hwdef, MachineState *machine) { const char *cpu_model = machine->cpu_model; unsigned int i; void *iommu, *espdma, *ledma, *nvram; qemu_irq *cpu_irqs[MAX_CPUS], slavio_irq[32], slavio_cpu_irq[MAX_CPUS], espdma_irq, ledma_irq; qemu_irq esp_reset, dma_enable; qemu_irq fdc_tc; unsigned long kernel_size; DriveInfo *fd[MAX_FD]; FWCfgState *fw_cfg; unsigned int num_vsimms; /* init CPUs */ if (!cpu_model) cpu_model = hwdef->default_cpu_model; for(i = 0; i < smp_cpus; i++) { cpu_devinit(cpu_model, i, hwdef->slavio_base, &cpu_irqs[i]); } for (i = smp_cpus; i < MAX_CPUS; i++) cpu_irqs[i] = qemu_allocate_irqs(dummy_cpu_set_irq, NULL, MAX_PILS); /* set up devices */ ram_init(0, machine->ram_size, hwdef->max_mem); /* models without ECC don't trap when missing ram is accessed */ if (!hwdef->ecc_base) { empty_slot_init(machine->ram_size, hwdef->max_mem - machine->ram_size); } prom_init(hwdef->slavio_base, bios_name); slavio_intctl = slavio_intctl_init(hwdef->intctl_base, hwdef->intctl_base + 0x10000ULL, cpu_irqs); for (i = 0; i < 32; i++) { slavio_irq[i] = qdev_get_gpio_in(slavio_intctl, i); } for (i = 0; i < MAX_CPUS; i++) { slavio_cpu_irq[i] = qdev_get_gpio_in(slavio_intctl, 32 + i); } if (hwdef->idreg_base) { idreg_init(hwdef->idreg_base); } if (hwdef->afx_base) { afx_init(hwdef->afx_base); } iommu = iommu_init(hwdef->iommu_base, hwdef->iommu_version, slavio_irq[30]); if (hwdef->iommu_pad_base) { /* On the real hardware (SS-5, LX) the MMU is not padded, but aliased. Software shouldn't use aliased addresses, neither should it crash when does. Using empty_slot instead of aliasing can help with debugging such accesses */ empty_slot_init(hwdef->iommu_pad_base,hwdef->iommu_pad_len); } espdma = sparc32_dma_init(hwdef->dma_base, slavio_irq[18], iommu, &espdma_irq, 0); ledma = sparc32_dma_init(hwdef->dma_base + 16ULL, slavio_irq[16], iommu, &ledma_irq, 1); if (graphic_depth != 8 && graphic_depth != 24) { error_report("Unsupported depth: %d", graphic_depth); exit (1); } num_vsimms = 0; if (num_vsimms == 0) { if (vga_interface_type == VGA_CG3) { if (graphic_depth != 8) { error_report("Unsupported depth: %d", graphic_depth); exit(1); } if (!(graphic_width == 1024 && graphic_height == 768) && !(graphic_width == 1152 && graphic_height == 900)) { error_report("Unsupported resolution: %d x %d", graphic_width, graphic_height); exit(1); } /* sbus irq 5 */ cg3_init(hwdef->tcx_base, slavio_irq[11], 0x00100000, graphic_width, graphic_height, graphic_depth); } else { /* If no display specified, default to TCX */ if (graphic_depth != 8 && graphic_depth != 24) { error_report("Unsupported depth: %d", graphic_depth); exit(1); } if (!(graphic_width == 1024 && graphic_height == 768)) { error_report("Unsupported resolution: %d x %d", graphic_width, graphic_height); exit(1); } tcx_init(hwdef->tcx_base, slavio_irq[11], 0x00100000, graphic_width, graphic_height, graphic_depth); } } for (i = num_vsimms; i < MAX_VSIMMS; i++) { /* vsimm registers probed by OBP */ if (hwdef->vsimm[i].reg_base) { empty_slot_init(hwdef->vsimm[i].reg_base, 0x2000); } } if (hwdef->sx_base) { empty_slot_init(hwdef->sx_base, 0x2000); } lance_init(&nd_table[0], hwdef->le_base, ledma, ledma_irq); nvram = m48t59_init(slavio_irq[0], hwdef->nvram_base, 0, 0x2000, 1968, 8); slavio_timer_init_all(hwdef->counter_base, slavio_irq[19], slavio_cpu_irq, smp_cpus); slavio_serial_ms_kbd_init(hwdef->ms_kb_base, slavio_irq[14], display_type == DT_NOGRAPHIC, ESCC_CLOCK, 1); /* Slavio TTYA (base+4, Linux ttyS0) is the first QEMU serial device Slavio TTYB (base+0, Linux ttyS1) is the second QEMU serial device */ escc_init(hwdef->serial_base, slavio_irq[15], slavio_irq[15], serial_hds[0], serial_hds[1], ESCC_CLOCK, 1); if (hwdef->apc_base) { apc_init(hwdef->apc_base, qemu_allocate_irq(cpu_halt_signal, NULL, 0)); } if (hwdef->fd_base) { /* there is zero or one floppy drive */ memset(fd, 0, sizeof(fd)); fd[0] = drive_get(IF_FLOPPY, 0, 0); sun4m_fdctrl_init(slavio_irq[22], hwdef->fd_base, fd, &fdc_tc); } else { fdc_tc = qemu_allocate_irq(dummy_fdc_tc, NULL, 0); } slavio_misc_init(hwdef->slavio_base, hwdef->aux1_base, hwdef->aux2_base, slavio_irq[30], fdc_tc); if (drive_get_max_bus(IF_SCSI) > 0) { fprintf(stderr, "qemu: too many SCSI bus\n"); exit(1); } esp_init(hwdef->esp_base, 2, espdma_memory_read, espdma_memory_write, espdma, espdma_irq, &esp_reset, &dma_enable); qdev_connect_gpio_out(espdma, 0, esp_reset); qdev_connect_gpio_out(espdma, 1, dma_enable); if (hwdef->cs_base) { sysbus_create_simple("SUNW,CS4231", hwdef->cs_base, slavio_irq[5]); } if (hwdef->dbri_base) { /* ISDN chip with attached CS4215 audio codec */ /* prom space */ empty_slot_init(hwdef->dbri_base+0x1000, 0x30); /* reg space */ empty_slot_init(hwdef->dbri_base+0x10000, 0x100); } if (hwdef->bpp_base) { /* parallel port */ empty_slot_init(hwdef->bpp_base, 0x20); } kernel_size = sun4m_load_kernel(machine->kernel_filename, machine->initrd_filename, machine->ram_size); nvram_init(nvram, (uint8_t *)&nd_table[0].macaddr, machine->kernel_cmdline, machine->boot_order, machine->ram_size, kernel_size, graphic_width, graphic_height, graphic_depth, hwdef->nvram_machine_id, "Sun4m"); if (hwdef->ecc_base) ecc_init(hwdef->ecc_base, slavio_irq[28], hwdef->ecc_version); fw_cfg = fw_cfg_init_mem(CFG_ADDR, CFG_ADDR + 2); fw_cfg_add_i16(fw_cfg, FW_CFG_MAX_CPUS, (uint16_t)max_cpus); fw_cfg_add_i64(fw_cfg, FW_CFG_RAM_SIZE, (uint64_t)ram_size); fw_cfg_add_i16(fw_cfg, FW_CFG_MACHINE_ID, hwdef->machine_id); fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_DEPTH, graphic_depth); fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_WIDTH, graphic_width); fw_cfg_add_i16(fw_cfg, FW_CFG_SUN4M_HEIGHT, graphic_height); fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_ADDR, KERNEL_LOAD_ADDR); fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_SIZE, kernel_size); if (machine->kernel_cmdline) { fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, CMDLINE_ADDR); pstrcpy_targphys("cmdline", CMDLINE_ADDR, TARGET_PAGE_SIZE, machine->kernel_cmdline); fw_cfg_add_string(fw_cfg, FW_CFG_CMDLINE_DATA, machine->kernel_cmdline); fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, strlen(machine->kernel_cmdline) + 1); } else { fw_cfg_add_i32(fw_cfg, FW_CFG_KERNEL_CMDLINE, 0); fw_cfg_add_i32(fw_cfg, FW_CFG_CMDLINE_SIZE, 0); } fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_ADDR, INITRD_LOAD_ADDR); fw_cfg_add_i32(fw_cfg, FW_CFG_INITRD_SIZE, 0); // not used fw_cfg_add_i16(fw_cfg, FW_CFG_BOOT_DEVICE, machine->boot_order[0]); qemu_register_boot_set(fw_cfg_boot_set, fw_cfg); }
int main(int argc, char *argv[]) { int i; int opt; char *filterstring=NULL; struct sigaction sigact; int count = -1; libtrace_filter_t *filter = NULL;/*trace_bpf_setfilter(filterstring); */ while (1) { int option_index; struct option long_options[] = { { "count", 1, 0, 'c' }, { "ecn", 0, 0, 'C' }, { "direction", 0, 0, 'd' }, { "drops", 0, 0, 'D' }, { "error", 0, 0, 'e' }, { "flow", 0, 0, 'F' }, { "filter", 1, 0, 'f' }, { "help", 0, 0, 'H' }, { "misc", 0, 0, 'm' }, { "nlp", 0, 0, 'n' }, { "tcpoptions", 0, 0, 'O' }, { "synoptions", 0, 0, 'o' }, { "protocol", 0, 0, 'P' }, { "port", 0, 0, 'p' }, { "tcpsegment", 0, 0, 's' }, { "tos", 0, 0, 'T' }, { "ttl", 0, 0, 't' }, { NULL, 0, 0, 0 } }; opt = getopt_long(argc, argv, "Df:HemFPpTtOondCsc:", long_options, &option_index); if (opt == -1) break; switch (opt) { case 'c': count = atoi(optarg); break; case 'C': reports_required |= REPORT_TYPE_ECN; break; case 'd': reports_required |= REPORT_TYPE_DIR; break; case 'D': reports_required |= REPORT_TYPE_DROPS; break; case 'e': reports_required |= REPORT_TYPE_ERROR; break; case 'F': reports_required |= REPORT_TYPE_FLOW; break; case 'f': filterstring = optarg; break; case 'H': usage(argv[0]); break; case 'm': reports_required |= REPORT_TYPE_MISC; break; case 'n': reports_required |= REPORT_TYPE_NLP; break; case 'O': reports_required |= REPORT_TYPE_TCPOPT; break; case 'o': reports_required |= REPORT_TYPE_SYNOPT; break; case 'P': reports_required |= REPORT_TYPE_PROTO; break; case 'p': reports_required |= REPORT_TYPE_PORT; break; case 's': reports_required |= REPORT_TYPE_TCPSEG; break; case 'T': reports_required |= REPORT_TYPE_TOS; break; case 't': reports_required |= REPORT_TYPE_TTL; break; default: usage(argv[0]); } } /* Default to all reports, instead of no reports at all. It's annoying * waiting for 10 minutes for a trace to process then discover you * forgot to ask for any reports! */ if (reports_required == 0) { reports_required = ~0; /* Except we might want to not do the flow report, because * that can be rather resource-intensive */ reports_required &= ~REPORT_TYPE_FLOW; } if (filterstring) { filter = trace_create_filter(filterstring); } sigact.sa_handler = cleanup_signal; sigemptyset(&sigact.sa_mask); sigact.sa_flags = SA_RESTART; sigaction(SIGINT, &sigact, NULL); sigaction(SIGTERM, &sigact, NULL); for(i=optind;i<argc;++i) { /* This is handy for knowing how far through the traceset * we are - printing to stderr because we use stdout for * genuine output at the moment */ fprintf(stderr, "Reading from trace: %s\n", argv[i]); run_trace(argv[i],filter, count); } if (reports_required & REPORT_TYPE_MISC) misc_report(); if (reports_required & REPORT_TYPE_ERROR) error_report(); if (reports_required & REPORT_TYPE_FLOW) flow_report(); if (reports_required & REPORT_TYPE_TOS) tos_report(); if (reports_required & REPORT_TYPE_PROTO) protocol_report(); if (reports_required & REPORT_TYPE_PORT) port_report(); if (reports_required & REPORT_TYPE_TTL) ttl_report(); if (reports_required & REPORT_TYPE_TCPOPT) tcpopt_report(); if (reports_required & REPORT_TYPE_SYNOPT) synopt_report(); if (reports_required & REPORT_TYPE_NLP) nlp_report(); if (reports_required & REPORT_TYPE_DIR) dir_report(); if (reports_required & REPORT_TYPE_ECN) ecn_report(); if (reports_required & REPORT_TYPE_TCPSEG) tcpseg_report(); if (reports_required & REPORT_TYPE_DROPS) drops_report(); return 0; }
int main() { bool init_ok = false; uint32_t err_code; //lint -save -e514 Unusual use of a boolean expression (use of &= assignment). const app_uart_comm_params_t comm_params = { RX_PIN_NUMBER, TX_PIN_NUMBER, RTS_PIN_NUMBER, CTS_PIN_NUMBER, APP_UART_FLOW_CONTROL_ENABLED, false, UART_BAUDRATE_BAUDRATE_Baud38400 }; APP_UART_FIFO_INIT(&comm_params, UART_RX_BUF_SIZE, UART_TX_BUF_SIZE, uart_error_handle, APP_IRQ_PRIORITY_LOW, err_code); (void)err_code; UNUSED_VARIABLE(bsp_init(BSP_INIT_BUTTONS,0,NULL)); printf("Desktop emulator example\n"); // Initialize and enable "mouse sensor" init_ok = mouse_sensor_init(MOUSE_SENSOR_SAMPLE_PERIOD_8_MS); mouse_sensor_enable(); // Initialize and enable Gazell init_ok &= nrf_gzll_init(NRF_GZLL_MODE_DEVICE); // Ensure Gazell parameters are configured. init_ok &= nrf_gzll_set_max_tx_attempts(150); init_ok &= nrf_gzll_set_device_channel_selection_policy(NRF_GZLLDE_DEVICE_CHANNEL_SELECTION_POLICY); init_ok &= nrf_gzll_set_timeslot_period(NRF_GZLLDE_RXPERIOD_DIV_2); init_ok &= nrf_gzll_set_sync_lifetime(0); // Asynchronous mode, more efficient for pairing. switch(gzp_get_pairing_status()) { case -2: host_id_received = false; system_addr_received = false; break; case -1: host_id_received = false; system_addr_received = true; break; default: host_id_received = true; system_addr_received = true; } gzp_init(); init_ok &= nrf_gzll_enable(); if(init_ok) { while(1) { // If BUTTON_SEND_MOUSE_DATA button is pressed. bool send_mouse_data_button_pressed; err_code = bsp_button_is_pressed(SEND_MOUSE_DATA_BUTTON_ID,&(send_mouse_data_button_pressed)); if( send_mouse_data_button_pressed) { read_mouse_and_send(); } else { //indicate mouse button not pressed } // If BUTTON_SEND_KEYBOARD_DATA button is pressed bool send_keyboard_data_button_pressed; err_code = bsp_button_is_pressed(SEND_KEYBOARD_DATA_BUTTON_ID,&(send_keyboard_data_button_pressed)); if(send_keyboard_data_button_pressed) { read_keyboard_and_send(); } else { //indicate keyboard button not pressed } error_report(); /* CPU sleep. We will wake up from all enabled interrupts, which here are the internal Gazell interrupts and the "mouse sensor" internal timer interrupt. */ //__WFI(); } } else { /* The initialization failed. Use nrf_gzll_get_error_code() to investigate the cause. */ } //lint -restore }
static void whpx_vcpu_pre_run(CPUState *cpu) { HRESULT hr; struct whpx_state *whpx = &whpx_global; struct whpx_vcpu *vcpu = get_whpx_vcpu(cpu); struct CPUX86State *env = (CPUArchState *)(cpu->env_ptr); X86CPU *x86_cpu = X86_CPU(cpu); int irq; uint8_t tpr; WHV_X64_PENDING_INTERRUPTION_REGISTER new_int = {0}; UINT32 reg_count = 0; WHV_REGISTER_VALUE reg_values[3] = {0}; WHV_REGISTER_NAME reg_names[3]; qemu_mutex_lock_iothread(); /* Inject NMI */ if (!vcpu->interrupt_in_flight.InterruptionPending && cpu->interrupt_request & (CPU_INTERRUPT_NMI | CPU_INTERRUPT_SMI)) { if (cpu->interrupt_request & CPU_INTERRUPT_NMI) { cpu->interrupt_request &= ~CPU_INTERRUPT_NMI; vcpu->interruptable = false; new_int.InterruptionType = WHvX64PendingNmi; new_int.InterruptionPending = 1; new_int.InterruptionVector = 2; } if (cpu->interrupt_request & CPU_INTERRUPT_SMI) { cpu->interrupt_request &= ~CPU_INTERRUPT_SMI; } } /* * Force the VCPU out of its inner loop to process any INIT requests or * commit pending TPR access. */ if (cpu->interrupt_request & (CPU_INTERRUPT_INIT | CPU_INTERRUPT_TPR)) { if ((cpu->interrupt_request & CPU_INTERRUPT_INIT) && !(env->hflags & HF_SMM_MASK)) { cpu->exit_request = 1; } if (cpu->interrupt_request & CPU_INTERRUPT_TPR) { cpu->exit_request = 1; } } /* Get pending hard interruption or replay one that was overwritten */ if (!vcpu->interrupt_in_flight.InterruptionPending && vcpu->interruptable && (env->eflags & IF_MASK)) { assert(!new_int.InterruptionPending); if (cpu->interrupt_request & CPU_INTERRUPT_HARD) { cpu->interrupt_request &= ~CPU_INTERRUPT_HARD; irq = cpu_get_pic_interrupt(env); if (irq >= 0) { new_int.InterruptionType = WHvX64PendingInterrupt; new_int.InterruptionPending = 1; new_int.InterruptionVector = irq; } } } /* Setup interrupt state if new one was prepared */ if (new_int.InterruptionPending) { reg_values[reg_count].PendingInterruption = new_int; reg_names[reg_count] = WHvRegisterPendingInterruption; reg_count += 1; } /* Sync the TPR to the CR8 if was modified during the intercept */ tpr = cpu_get_apic_tpr(x86_cpu->apic_state); if (tpr != vcpu->tpr) { vcpu->tpr = tpr; reg_values[reg_count].Reg64 = tpr; cpu->exit_request = 1; reg_names[reg_count] = WHvX64RegisterCr8; reg_count += 1; } /* Update the state of the interrupt delivery notification */ if (!vcpu->window_registered && cpu->interrupt_request & CPU_INTERRUPT_HARD) { reg_values[reg_count].DeliverabilityNotifications.InterruptNotification = 1; vcpu->window_registered = 1; reg_names[reg_count] = WHvX64RegisterDeliverabilityNotifications; reg_count += 1; } qemu_mutex_unlock_iothread(); if (reg_count) { hr = WHvSetVirtualProcessorRegisters(whpx->partition, cpu->cpu_index, reg_names, reg_count, reg_values); if (FAILED(hr)) { error_report("WHPX: Failed to set interrupt state registers," " hr=%08lx", hr); } } return; }