static void test_qemu_opt_get_size(void) { QemuOptsList *list; QemuOpts *opts; uint64_t opt; QDict *dict; list = qemu_find_opts("opts_list_02"); g_assert(list != NULL); g_assert(QTAILQ_EMPTY(&list->head)); g_assert_cmpstr(list->name, ==, "opts_list_02"); /* should not find anything at this point */ opts = qemu_opts_find(list, NULL); g_assert(opts == NULL); /* create the opts */ opts = qemu_opts_create(list, NULL, 0, &error_abort); g_assert(opts != NULL); g_assert(!QTAILQ_EMPTY(&list->head)); /* haven't set anything to size1 yet, so defval should be returned */ opt = qemu_opt_get_size(opts, "size1", 5); g_assert(opt == 5); dict = qdict_new(); g_assert(dict != NULL); qdict_put(dict, "size1", qstring_from_str("10")); qemu_opts_absorb_qdict(opts, dict, &error_abort); g_assert(error_abort == NULL); /* now we have set size1, should know about it */ opt = qemu_opt_get_size(opts, "size1", 5); g_assert(opt == 10); /* reset value */ qdict_put(dict, "size1", qstring_from_str("15")); qemu_opts_absorb_qdict(opts, dict, &error_abort); g_assert(error_abort == NULL); /* test the reset value */ opt = qemu_opt_get_size(opts, "size1", 5); g_assert(opt == 15); qdict_del(dict, "size1"); g_free(dict); qemu_opts_del(opts); /* should not find anything at this point */ opts = qemu_opts_find(list, NULL); g_assert(opts == NULL); }
static void ccw_init(MachineState *machine) { ram_addr_t my_ram_size = machine->ram_size; MemoryRegion *sysmem = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); sclpMemoryHotplugDev *mhd = init_sclp_memory_hotplug_dev(); uint8_t *storage_keys; int ret; VirtualCssBus *css_bus; DeviceState *dev; QemuOpts *opts = qemu_opts_find(qemu_find_opts("memory"), NULL); ram_addr_t pad_size = 0; ram_addr_t maxmem = qemu_opt_get_size(opts, "maxmem", my_ram_size); ram_addr_t standby_mem_size = maxmem - my_ram_size; uint64_t kvm_limit; /* The storage increment size is a multiple of 1M and is a power of 2. * The number of storage increments must be MAX_STORAGE_INCREMENTS or fewer. * The variable 'mhd->increment_size' is an exponent of 2 that can be * used to calculate the size (in bytes) of an increment. */ mhd->increment_size = 20; while ((my_ram_size >> mhd->increment_size) > MAX_STORAGE_INCREMENTS) { mhd->increment_size++; } while ((standby_mem_size >> mhd->increment_size) > MAX_STORAGE_INCREMENTS) { mhd->increment_size++; } /* The core and standby memory areas need to be aligned with * the increment size. In effect, this can cause the * user-specified memory size to be rounded down to align * with the nearest increment boundary. */ standby_mem_size = standby_mem_size >> mhd->increment_size << mhd->increment_size; my_ram_size = my_ram_size >> mhd->increment_size << mhd->increment_size; /* let's propagate the changed ram size into the global variable. */ ram_size = my_ram_size; machine->maxram_size = my_ram_size + standby_mem_size; ret = s390_set_memory_limit(machine->maxram_size, &kvm_limit); if (ret == -E2BIG) { hw_error("qemu: host supports a maximum of %" PRIu64 " GB", kvm_limit >> 30); } else if (ret) {
static int curl_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { BDRVCURLState *s = bs->opaque; CURLState *state = NULL; QemuOpts *opts; Error *local_err = NULL; const char *file; double d; static int inited = 0; if (flags & BDRV_O_RDWR) { error_setg(errp, "curl block device does not support writes"); return -EROFS; } opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); qemu_opts_absorb_qdict(opts, options, &local_err); if (local_err) { error_propagate(errp, local_err); goto out_noclean; } s->readahead_size = qemu_opt_get_size(opts, "readahead", READ_AHEAD_SIZE); if ((s->readahead_size & 0x1ff) != 0) { error_setg(errp, "HTTP_READAHEAD_SIZE %zd is not a multiple of 512", s->readahead_size); goto out_noclean; } file = qemu_opt_get(opts, "url"); if (file == NULL) { error_setg(errp, "curl block driver requires an 'url' option"); goto out_noclean; } if (!inited) { curl_global_init(CURL_GLOBAL_ALL); inited = 1; } DPRINTF("CURL: Opening %s\n", file); s->url = g_strdup(file); state = curl_init_state(s); if (!state) goto out_noclean; // Get file size s->accept_range = false; curl_easy_setopt(state->curl, CURLOPT_NOBODY, 1); curl_easy_setopt(state->curl, CURLOPT_HEADERFUNCTION, curl_header_cb); curl_easy_setopt(state->curl, CURLOPT_HEADERDATA, s); if (curl_easy_perform(state->curl)) goto out; curl_easy_getinfo(state->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d); if (d) s->len = (size_t)d; else if(!s->len) goto out; if ((!strncasecmp(s->url, "http://", strlen("http://")) || !strncasecmp(s->url, "https://", strlen("https://"))) && !s->accept_range) { pstrcpy(state->errmsg, CURL_ERROR_SIZE, "Server does not support 'range' (byte ranges)."); goto out; } DPRINTF("CURL: Size = %zd\n", s->len); curl_clean_state(state); curl_easy_cleanup(state->curl); state->curl = NULL; aio_timer_init(bdrv_get_aio_context(bs), &s->timer, QEMU_CLOCK_REALTIME, SCALE_NS, curl_multi_timeout_do, s); // Now we know the file exists and its size, so let's // initialize the multi interface! s->multi = curl_multi_init(); curl_multi_setopt(s->multi, CURLMOPT_SOCKETDATA, s); curl_multi_setopt(s->multi, CURLMOPT_SOCKETFUNCTION, curl_sock_cb); #ifdef NEED_CURL_TIMER_CALLBACK curl_multi_setopt(s->multi, CURLMOPT_TIMERDATA, s); curl_multi_setopt(s->multi, CURLMOPT_TIMERFUNCTION, curl_timer_cb); #endif curl_multi_do(s); qemu_opts_del(opts); return 0; out: error_setg(errp, "CURL: Error opening file: %s", state->errmsg); curl_easy_cleanup(state->curl); state->curl = NULL; out_noclean: g_free(s->url); qemu_opts_del(opts); return -EINVAL; }
static int curl_open(BlockDriverState *bs, QDict *options, int flags, Error **errp) { BDRVCURLState *s = bs->opaque; CURLState *state = NULL; QemuOpts *opts; Error *local_err = NULL; const char *file; const char *cookie; double d; static int inited = 0; if (flags & BDRV_O_RDWR) { error_setg(errp, "curl block device does not support writes"); return -EROFS; } opts = qemu_opts_create(&runtime_opts, NULL, 0, &error_abort); qemu_opts_absorb_qdict(opts, options, &local_err); if (local_err) { error_propagate(errp, local_err); goto out_noclean; } s->readahead_size = qemu_opt_get_size(opts, CURL_BLOCK_OPT_READAHEAD, READ_AHEAD_DEFAULT); if ((s->readahead_size & 0x1ff) != 0) { error_setg(errp, "HTTP_READAHEAD_SIZE %zd is not a multiple of 512", s->readahead_size); goto out_noclean; } s->timeout = qemu_opt_get_number(opts, CURL_BLOCK_OPT_TIMEOUT, CURL_TIMEOUT_DEFAULT); if (s->timeout > CURL_TIMEOUT_MAX) { error_setg(errp, "timeout parameter is too large or negative"); goto out_noclean; } s->sslverify = qemu_opt_get_bool(opts, CURL_BLOCK_OPT_SSLVERIFY, true); cookie = qemu_opt_get(opts, CURL_BLOCK_OPT_COOKIE); s->cookie = g_strdup(cookie); file = qemu_opt_get(opts, CURL_BLOCK_OPT_URL); if (file == NULL) { error_setg(errp, "curl block driver requires an 'url' option"); goto out_noclean; } if (!inited) { curl_global_init(CURL_GLOBAL_ALL); inited = 1; } DPRINTF("CURL: Opening %s\n", file); s->aio_context = bdrv_get_aio_context(bs); s->url = g_strdup(file); state = curl_init_state(bs, s); if (!state) goto out_noclean; // Get file size s->accept_range = false; curl_easy_setopt(state->curl, CURLOPT_NOBODY, 1); curl_easy_setopt(state->curl, CURLOPT_HEADERFUNCTION, curl_header_cb); curl_easy_setopt(state->curl, CURLOPT_HEADERDATA, s); if (curl_easy_perform(state->curl)) goto out; curl_easy_getinfo(state->curl, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &d); if (d) s->len = (size_t)d; else if(!s->len) goto out; if ((!strncasecmp(s->url, "http://", strlen("http://")) || !strncasecmp(s->url, "https://", strlen("https://"))) && !s->accept_range) { pstrcpy(state->errmsg, CURL_ERROR_SIZE, "Server does not support 'range' (byte ranges)."); goto out; } DPRINTF("CURL: Size = %zd\n", s->len); curl_clean_state(state); curl_easy_cleanup(state->curl); state->curl = NULL; curl_attach_aio_context(bs, bdrv_get_aio_context(bs)); qemu_opts_del(opts); return 0; out: error_setg(errp, "CURL: Error opening file: %s", state->errmsg); curl_easy_cleanup(state->curl); state->curl = NULL; out_noclean: g_free(s->cookie); g_free(s->url); qemu_opts_del(opts); return -EINVAL; }
static void ccw_init(MachineState *machine) { ram_addr_t my_ram_size = machine->ram_size; MemoryRegion *sysmem = get_system_memory(); MemoryRegion *ram = g_new(MemoryRegion, 1); sclpMemoryHotplugDev *mhd = init_sclp_memory_hotplug_dev(); uint8_t *storage_keys; int ret; VirtualCssBus *css_bus; DeviceState *dev; QemuOpts *opts = qemu_opts_find(qemu_find_opts("memory"), NULL); ram_addr_t pad_size = 0; ram_addr_t maxmem = qemu_opt_get_size(opts, "maxmem", my_ram_size); ram_addr_t standby_mem_size = maxmem - my_ram_size; /* The storage increment size is a multiple of 1M and is a power of 2. * The number of storage increments must be MAX_STORAGE_INCREMENTS or fewer. * The variable 'mhd->increment_size' is an exponent of 2 that can be * used to calculate the size (in bytes) of an increment. */ mhd->increment_size = 20; while ((my_ram_size >> mhd->increment_size) > MAX_STORAGE_INCREMENTS) { mhd->increment_size++; } while ((standby_mem_size >> mhd->increment_size) > MAX_STORAGE_INCREMENTS) { mhd->increment_size++; } /* The core and standby memory areas need to be aligned with * the increment size. In effect, this can cause the * user-specified memory size to be rounded down to align * with the nearest increment boundary. */ standby_mem_size = standby_mem_size >> mhd->increment_size << mhd->increment_size; my_ram_size = my_ram_size >> mhd->increment_size << mhd->increment_size; /* let's propagate the changed ram size into the global variable. */ ram_size = my_ram_size; /* get a BUS */ css_bus = virtual_css_bus_init(); s390_sclp_init(); s390_init_ipl_dev(machine->kernel_filename, machine->kernel_cmdline, machine->initrd_filename, "s390-ccw.img"); s390_flic_init(); dev = qdev_create(NULL, TYPE_S390_PCI_HOST_BRIDGE); object_property_add_child(qdev_get_machine(), TYPE_S390_PCI_HOST_BRIDGE, OBJECT(dev), NULL); qdev_init_nofail(dev); /* register hypercalls */ virtio_ccw_register_hcalls(); /* allocate RAM for core */ memory_region_init_ram(ram, NULL, "s390.ram", my_ram_size, &error_abort); vmstate_register_ram_global(ram); memory_region_add_subregion(sysmem, 0, ram); /* If the size of ram is not on a MEM_SECTION_SIZE boundary, calculate the pad size necessary to force this boundary. */ if (standby_mem_size) { if (my_ram_size % MEM_SECTION_SIZE) { pad_size = MEM_SECTION_SIZE - my_ram_size % MEM_SECTION_SIZE; } my_ram_size += standby_mem_size + pad_size; mhd->pad_size = pad_size; mhd->standby_mem_size = standby_mem_size; } /* allocate storage keys */ storage_keys = g_malloc0(my_ram_size / TARGET_PAGE_SIZE); /* init CPUs */ s390_init_cpus(machine->cpu_model, storage_keys); if (kvm_enabled()) { kvm_s390_enable_css_support(s390_cpu_addr2state(0)); } /* * Create virtual css and set it as default so that non mcss-e * enabled guests only see virtio devices. */ ret = css_create_css_image(VIRTUAL_CSSID, true); assert(ret == 0); /* Create VirtIO network adapters */ s390_create_virtio_net(BUS(css_bus), "virtio-net-ccw"); }