#include "hw/pcmcia.h"
#include "hw/pc.h"
#include "hw/isa.h"
-#include "hw/baum.h"
+#include "char/baum.h"
#include "hw/bt.h"
#include "hw/watchdog.h"
#include "hw/smbios.h"
#include "hw/xen.h"
#include "hw/qdev.h"
#include "hw/loader.h"
+#include "monitor/qdev.h"
#include "bt/bt.h"
#include "net/net.h"
#include "net/slirp.h"
#define DEFAULT_RAM_SIZE 128
#define MAX_VIRTIO_CONSOLES 1
+#define MAX_SCLP_CONSOLES 1
static const char *data_dir;
const char *bios_name = NULL;
CharDriverState *serial_hds[MAX_SERIAL_PORTS];
CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
CharDriverState *virtcon_hds[MAX_VIRTIO_CONSOLES];
+CharDriverState *sclp_hds[MAX_SCLP_CONSOLES];
int win2k_install_hack = 0;
int singlestep = 0;
int smp_cpus = 1;
const char *prom_envs[MAX_PROM_ENVS];
int boot_menu;
uint8_t *boot_splash_filedata;
-int boot_splash_filedata_size;
+size_t boot_splash_filedata_size;
uint8_t qemu_extra_params_fw[2];
typedef struct FWBootEntry FWBootEntry;
static NotifierList machine_init_done_notifiers =
NOTIFIER_LIST_INITIALIZER(machine_init_done_notifiers);
-static int tcg_allowed = 1;
-int kvm_allowed = 0;
-int xen_allowed = 0;
+static bool tcg_allowed = true;
+bool kvm_allowed;
+bool xen_allowed;
uint32_t xen_domid;
enum xen_mode xen_mode = XEN_EMULATE;
static int tcg_tb_size;
static int default_serial = 1;
static int default_parallel = 1;
static int default_virtcon = 1;
+static int default_sclp = 1;
static int default_monitor = 1;
static int default_floppy = 1;
static int default_cdrom = 1;
{ .driver = "qxl-vga", .flag = &default_vga },
};
+static QemuOptsList qemu_rtc_opts = {
+ .name = "rtc",
+ .head = QTAILQ_HEAD_INITIALIZER(qemu_rtc_opts.head),
+ .desc = {
+ {
+ .name = "base",
+ .type = QEMU_OPT_STRING,
+ },{
+ .name = "clock",
+ .type = QEMU_OPT_STRING,
+ },{
+ .name = "driftfix",
+ .type = QEMU_OPT_STRING,
+ },
+ { /* end of list */ }
+ },
+};
+
+static QemuOptsList qemu_sandbox_opts = {
+ .name = "sandbox",
+ .implied_opt_name = "enable",
+ .head = QTAILQ_HEAD_INITIALIZER(qemu_sandbox_opts.head),
+ .desc = {
+ {
+ .name = "enable",
+ .type = QEMU_OPT_BOOL,
+ },
+ { /* end of list */ }
+ },
+};
+
+static QemuOptsList qemu_trace_opts = {
+ .name = "trace",
+ .implied_opt_name = "trace",
+ .head = QTAILQ_HEAD_INITIALIZER(qemu_trace_opts.head),
+ .desc = {
+ {
+ .name = "events",
+ .type = QEMU_OPT_STRING,
+ },{
+ .name = "file",
+ .type = QEMU_OPT_STRING,
+ },
+ { /* end of list */ }
+ },
+};
+
+static QemuOptsList qemu_option_rom_opts = {
+ .name = "option-rom",
+ .implied_opt_name = "romfile",
+ .head = QTAILQ_HEAD_INITIALIZER(qemu_option_rom_opts.head),
+ .desc = {
+ {
+ .name = "bootindex",
+ .type = QEMU_OPT_NUMBER,
+ }, {
+ .name = "romfile",
+ .type = QEMU_OPT_STRING,
+ },
+ { /* end of list */ }
+ },
+};
+
+static QemuOptsList qemu_machine_opts = {
+ .name = "machine",
+ .implied_opt_name = "type",
+ .merge_lists = true,
+ .head = QTAILQ_HEAD_INITIALIZER(qemu_machine_opts.head),
+ .desc = {
+ {
+ .name = "type",
+ .type = QEMU_OPT_STRING,
+ .help = "emulated machine"
+ }, {
+ .name = "accel",
+ .type = QEMU_OPT_STRING,
+ .help = "accelerator list",
+ }, {
+ .name = "kernel_irqchip",
+ .type = QEMU_OPT_BOOL,
+ .help = "use KVM in-kernel irqchip",
+ }, {
+ .name = "kvm_shadow_mem",
+ .type = QEMU_OPT_SIZE,
+ .help = "KVM shadow MMU size",
+ }, {
+ .name = "kernel",
+ .type = QEMU_OPT_STRING,
+ .help = "Linux kernel image file",
+ }, {
+ .name = "initrd",
+ .type = QEMU_OPT_STRING,
+ .help = "Linux initial ramdisk file",
+ }, {
+ .name = "append",
+ .type = QEMU_OPT_STRING,
+ .help = "Linux kernel command line",
+ }, {
+ .name = "dtb",
+ .type = QEMU_OPT_STRING,
+ .help = "Linux kernel device tree file",
+ }, {
+ .name = "dumpdtb",
+ .type = QEMU_OPT_STRING,
+ .help = "Dump current dtb to a file and quit",
+ }, {
+ .name = "phandle_start",
+ .type = QEMU_OPT_STRING,
+ .help = "The first phandle ID we may generate dynamically",
+ }, {
+ .name = "dt_compatible",
+ .type = QEMU_OPT_STRING,
+ .help = "Overrides the \"compatible\" property of the dt root node",
+ }, {
+ .name = "dump-guest-core",
+ .type = QEMU_OPT_BOOL,
+ .help = "Include guest memory in a core dump",
+ }, {
+ .name = "mem-merge",
+ .type = QEMU_OPT_BOOL,
+ .help = "enable/disable memory merge support",
+ },{
+ .name = "usb",
+ .type = QEMU_OPT_BOOL,
+ .help = "Set on/off to enable/disable usb",
+ },
+ { /* End of list */ }
+ },
+};
+
+static QemuOptsList qemu_boot_opts = {
+ .name = "boot-opts",
+ .head = QTAILQ_HEAD_INITIALIZER(qemu_boot_opts.head),
+ .desc = {
+ /* the three names below are not used now */
+ {
+ .name = "order",
+ .type = QEMU_OPT_STRING,
+ }, {
+ .name = "once",
+ .type = QEMU_OPT_STRING,
+ }, {
+ .name = "menu",
+ .type = QEMU_OPT_STRING,
+ /* following are really used */
+ }, {
+ .name = "splash",
+ .type = QEMU_OPT_STRING,
+ }, {
+ .name = "splash-time",
+ .type = QEMU_OPT_STRING,
+ }, {
+ .name = "reboot-timeout",
+ .type = QEMU_OPT_STRING,
+ },
+ { /*End of list */ }
+ },
+};
+
+static QemuOptsList qemu_add_fd_opts = {
+ .name = "add-fd",
+ .head = QTAILQ_HEAD_INITIALIZER(qemu_add_fd_opts.head),
+ .desc = {
+ {
+ .name = "fd",
+ .type = QEMU_OPT_NUMBER,
+ .help = "file descriptor of which a duplicate is added to fd set",
+ },{
+ .name = "set",
+ .type = QEMU_OPT_NUMBER,
+ .help = "ID of the fd set to add fd to",
+ },{
+ .name = "opaque",
+ .type = QEMU_OPT_STRING,
+ .help = "free-form string used to describe fd",
+ },
+ { /* end of list */ }
+ },
+};
+
+static QemuOptsList qemu_object_opts = {
+ .name = "object",
+ .implied_opt_name = "qom-type",
+ .head = QTAILQ_HEAD_INITIALIZER(qemu_object_opts.head),
+ .desc = {
+ { }
+ },
+};
+
const char *qemu_get_vm_name(void)
{
return qemu_name;
* memory pointed by "size" is assigned total length of the array in bytes
*
*/
-char *get_boot_devices_list(uint32_t *size)
+char *get_boot_devices_list(size_t *size)
{
FWBootEntry *i;
- uint32_t total = 0;
+ size_t total = 0;
char *list = NULL;
QTAILQ_FOREACH(i, &fw_boot_order, link) {
char *devpath = NULL, *bootpath;
- int len;
+ size_t len;
if (i->dev) {
devpath = qdev_get_fw_dev_path(i->dev);
return list;
}
-static void numa_add(const char *optarg)
+static void numa_node_parse_cpus(int nodenr, const char *cpus)
{
- char option[128];
char *endptr;
unsigned long long value, endvalue;
- int nodenr;
- value = endvalue = 0ULL;
+ /* Empty CPU range strings will be considered valid, they will simply
+ * not set any bit in the CPU bitmap.
+ */
+ if (!*cpus) {
+ return;
+ }
+
+ if (parse_uint(cpus, &value, &endptr, 10) < 0) {
+ goto error;
+ }
+ if (*endptr == '-') {
+ if (parse_uint_full(endptr + 1, &endvalue, 10) < 0) {
+ goto error;
+ }
+ } else if (*endptr == '\0') {
+ endvalue = value;
+ } else {
+ goto error;
+ }
+
+ if (endvalue >= MAX_CPUMASK_BITS) {
+ endvalue = MAX_CPUMASK_BITS - 1;
+ fprintf(stderr,
+ "qemu: NUMA: A max of %d VCPUs are supported\n",
+ MAX_CPUMASK_BITS);
+ }
+
+ if (endvalue < value) {
+ goto error;
+ }
+
+ bitmap_set(node_cpumask[nodenr], value, endvalue-value+1);
+ return;
+
+error:
+ fprintf(stderr, "qemu: Invalid NUMA CPU range: %s\n", cpus);
+ exit(1);
+}
+
+static void numa_add(const char *optarg)
+{
+ char option[128];
+ char *endptr;
+ unsigned long long nodenr;
- optarg = get_opt_name(option, 128, optarg, ',') + 1;
+ optarg = get_opt_name(option, 128, optarg, ',');
+ if (*optarg == ',') {
+ optarg++;
+ }
if (!strcmp(option, "node")) {
+
+ if (nb_numa_nodes >= MAX_NODES) {
+ fprintf(stderr, "qemu: too many NUMA nodes\n");
+ exit(1);
+ }
+
if (get_param_value(option, 128, "nodeid", optarg) == 0) {
nodenr = nb_numa_nodes;
} else {
- nodenr = strtoull(option, NULL, 10);
+ if (parse_uint_full(option, &nodenr, 10) < 0) {
+ fprintf(stderr, "qemu: Invalid NUMA nodeid: %s\n", option);
+ exit(1);
+ }
+ }
+
+ if (nodenr >= MAX_NODES) {
+ fprintf(stderr, "qemu: invalid NUMA nodeid: %llu\n", nodenr);
+ exit(1);
}
if (get_param_value(option, 128, "mem", optarg) == 0) {
node_mem[nodenr] = sval;
}
if (get_param_value(option, 128, "cpus", optarg) != 0) {
- value = strtoull(option, &endptr, 10);
- if (*endptr == '-') {
- endvalue = strtoull(endptr+1, &endptr, 10);
- } else {
- endvalue = value;
- }
-
- if (!(endvalue < MAX_CPUMASK_BITS)) {
- endvalue = MAX_CPUMASK_BITS - 1;
- fprintf(stderr,
- "A max of %d CPUs are supported in a guest\n",
- MAX_CPUMASK_BITS);
- }
-
- bitmap_set(node_cpumask[nodenr], value, endvalue-value+1);
+ numa_node_parse_cpus(nodenr, option);
}
nb_numa_nodes++;
+ } else {
+ fprintf(stderr, "Invalid -numa option: %s\n", option);
+ exit(1);
}
}
int bus_num, addr;
const char *p;
- if (strstart(devname, "host:", &p))
- return usb_host_device_close(p);
+ if (strstart(devname, "host:", &p)) {
+ return -1;
+ }
if (!usb_enabled(false)) {
return -1;
}
}
-void pcmcia_info(Monitor *mon)
+void pcmcia_info(Monitor *mon, const QDict *qdict)
{
struct pcmcia_socket_entry_s *iter;
#else
fprintf(stderr, "Curses support is disabled\n");
exit(1);
+#endif
+ } else if (strstart(p, "gtk", &opts)) {
+#ifdef CONFIG_GTK
+ display = DT_GTK;
+#else
+ fprintf(stderr, "GTK support is disabled\n");
+ exit(1);
#endif
} else if (strstart(p, "none", &opts)) {
display = DT_NONE;
dev = qdev_device_add(opts);
if (!dev)
return -1;
+ object_unref(OBJECT(dev));
return 0;
}
static int chardev_init_func(QemuOpts *opts, void *opaque)
{
- CharDriverState *chr;
+ Error *local_err = NULL;
- chr = qemu_chr_new_from_opts(opts, NULL);
- if (!chr)
+ qemu_chr_new_from_opts(opts, NULL, &local_err);
+ if (error_is_set(&local_err)) {
+ fprintf(stderr, "%s\n", error_get_pretty(local_err));
+ error_free(local_err);
return -1;
+ }
return 0;
}
DEV_VIRTCON, /* -virtioconsole */
DEV_DEBUGCON, /* -debugcon */
DEV_GDB, /* -gdb, -s */
+ DEV_SCLP, /* s390 sclp */
} type;
const char *cmdline;
Location loc;
return 0;
}
+static int sclp_parse(const char *devname)
+{
+ QemuOptsList *device = qemu_find_opts("device");
+ static int index = 0;
+ char label[32];
+ QemuOpts *dev_opts;
+
+ if (strcmp(devname, "none") == 0) {
+ return 0;
+ }
+ if (index == MAX_SCLP_CONSOLES) {
+ fprintf(stderr, "qemu: too many sclp consoles\n");
+ exit(1);
+ }
+
+ assert(arch_type == QEMU_ARCH_S390X);
+
+ dev_opts = qemu_opts_create(device, NULL, 0, NULL);
+ qemu_opt_set(dev_opts, "driver", "sclpconsole");
+
+ snprintf(label, sizeof(label), "sclpcon%d", index);
+ sclp_hds[index] = qemu_chr_new(label, devname, NULL);
+ if (!sclp_hds[index]) {
+ fprintf(stderr, "qemu: could not connect sclp console"
+ " to character backend '%s'\n", devname);
+ return -1;
+ }
+ qemu_opt_set(dev_opts, "chardev", label);
+
+ index++;
+ return 0;
+}
+
static int debugcon_parse(const char *devname)
{
QemuOpts *opts;
const char *name;
int (*available)(void);
int (*init)(void);
- int *allowed;
+ bool *allowed;
} accel_list[] = {
{ "tcg", "tcg", tcg_available, tcg_init, &tcg_allowed },
{ "xen", "Xen", xen_available, xen_init, &xen_allowed },
const char *p = NULL;
char buf[10];
int i, ret;
- bool accel_initialised = 0;
- bool init_failed = 0;
+ bool accel_initialised = false;
+ bool init_failed = false;
QemuOptsList *list = qemu_find_opts("machine");
if (!QTAILQ_EMPTY(&list->head)) {
p = get_opt_name(buf, sizeof (buf), p, ':');
for (i = 0; i < ARRAY_SIZE(accel_list); i++) {
if (strcmp(accel_list[i].opt_name, buf) == 0) {
- *(accel_list[i].allowed) = 1;
+ if (!accel_list[i].available()) {
+ printf("%s not supported for this target\n",
+ accel_list[i].name);
+ continue;
+ }
+ *(accel_list[i].allowed) = true;
ret = accel_list[i].init();
if (ret < 0) {
- init_failed = 1;
- if (!accel_list[i].available()) {
- printf("%s not supported for this target\n",
- accel_list[i].name);
- } else {
- fprintf(stderr, "failed to initialize %s: %s\n",
- accel_list[i].name,
- strerror(-ret));
- }
- *(accel_list[i].allowed) = 0;
+ init_failed = true;
+ fprintf(stderr, "failed to initialize %s: %s\n",
+ accel_list[i].name,
+ strerror(-ret));
+ *(accel_list[i].allowed) = false;
} else {
- accel_initialised = 1;
+ accel_initialised = true;
}
break;
}
}
if (!accel_initialised) {
- fprintf(stderr, "No accelerator found!\n");
+ if (!init_failed) {
+ fprintf(stderr, "No accelerator found!\n");
+ }
exit(1);
}
const char *icount_option = NULL;
const char *initrd_filename;
const char *kernel_filename, *kernel_cmdline;
- char boot_devices[33] = "cad"; /* default to HD->floppy->CD-ROM */
+ char boot_devices[33] = "";
DisplayState *ds;
int cyls, heads, secs, translation;
QemuOpts *hda_opts = NULL, *opts, *machine_opts;
module_call_init(MODULE_INIT_QOM);
+ qemu_add_opts(&qemu_drive_opts);
+ qemu_add_opts(&qemu_chardev_opts);
+ qemu_add_opts(&qemu_device_opts);
+ qemu_add_opts(&qemu_netdev_opts);
+ qemu_add_opts(&qemu_net_opts);
+ qemu_add_opts(&qemu_rtc_opts);
+ qemu_add_opts(&qemu_global_opts);
+ qemu_add_opts(&qemu_mon_opts);
+ qemu_add_opts(&qemu_trace_opts);
+ qemu_add_opts(&qemu_option_rom_opts);
+ qemu_add_opts(&qemu_machine_opts);
+ qemu_add_opts(&qemu_boot_opts);
+ qemu_add_opts(&qemu_sandbox_opts);
+ qemu_add_opts(&qemu_add_fd_opts);
+ qemu_add_opts(&qemu_object_opts);
+
runstate_init();
init_clocks();
drive_add(IF_MTD, -1, optarg, MTD_OPTS);
break;
case QEMU_OPTION_sd:
- drive_add(IF_SD, 0, optarg, SD_OPTS);
+ drive_add(IF_SD, -1, optarg, SD_OPTS);
break;
case QEMU_OPTION_pflash:
drive_add(IF_PFLASH, -1, optarg, PFLASH_OPTS);
}
break;
case QEMU_OPTION_numa:
- if (nb_numa_nodes >= MAX_NODES) {
- fprintf(stderr, "qemu: too many NUMA nodes\n");
- exit(1);
- }
numa_add(optarg);
break;
case QEMU_OPTION_display:
exit(1);
}
}
- qemu_opts_parse(qemu_find_opts("boot-opts"),
- optarg, 0);
+ if (!qemu_opts_parse(qemu_find_opts("boot-opts"),
+ optarg, 0)) {
+ exit(1);
+ }
}
}
break;
}
opts = qemu_opts_parse(olist, optarg, 1);
if (!opts) {
- fprintf(stderr, "parse error: %s\n", optarg);
exit(1);
}
break;
}
opts = qemu_opts_parse(olist, optarg, 1);
if (!opts) {
- fprintf(stderr, "parse error: %s\n", optarg);
exit(1);
}
olist = qemu_find_opts("machine");
opts = qemu_opts_parse(olist, optarg, 1);
if (!opts) {
- fprintf(stderr, "parse error: %s\n", optarg);
exit(1);
}
optarg = qemu_opt_get(opts, "type");
exit(1);
}
opts = qemu_opts_parse(qemu_find_opts("option-rom"), optarg, 1);
+ if (!opts) {
+ exit(1);
+ }
option_rom[nb_option_roms].name = qemu_opt_get(opts, "romfile");
option_rom[nb_option_roms].bootindex =
qemu_opt_get_number(opts, "bootindex", -1);
default_serial = 0;
default_parallel = 0;
default_virtcon = 0;
+ default_sclp = 0;
default_monitor = 0;
default_net = 0;
default_floppy = 0;
}
opts = qemu_opts_parse(olist, optarg, 0);
if (!opts) {
- fprintf(stderr, "parse error: %s\n", optarg);
exit(1);
}
+ display_remote++;
break;
case QEMU_OPTION_writeconfig:
{
case QEMU_OPTION_sandbox:
opts = qemu_opts_parse(qemu_find_opts("sandbox"), optarg, 1);
if (!opts) {
- exit(0);
+ exit(1);
}
break;
case QEMU_OPTION_add_fd:
#ifndef _WIN32
opts = qemu_opts_parse(qemu_find_opts("add-fd"), optarg, 0);
if (!opts) {
- exit(0);
+ exit(1);
}
#else
error_report("File descriptor passing is disabled on this "
break;
case QEMU_OPTION_object:
opts = qemu_opts_parse(qemu_find_opts("object"), optarg, 1);
+ if (!opts) {
+ exit(1);
+ }
break;
default:
os_parse_cmd_args(popt->index, optarg);
* location or level of logging.
*/
if (log_mask) {
+ int mask;
if (log_file) {
- set_cpu_log_filename(log_file);
+ qemu_set_log_filename(log_file);
}
- set_cpu_log(log_mask);
+
+ mask = qemu_str_to_log_mask(log_mask);
+ if (!mask) {
+ qemu_print_log_usage(stdout);
+ exit(1);
+ }
+ qemu_set_log(mask);
}
if (!trace_backend_init(trace_events, trace_file)) {
if (!machine->use_virtcon) {
default_virtcon = 0;
}
+ if (!machine->use_sclp) {
+ default_sclp = 0;
+ }
if (machine->no_floppy) {
default_floppy = 0;
}
add_device_config(DEV_SERIAL, "mon:stdio");
} else if (default_virtcon && default_monitor) {
add_device_config(DEV_VIRTCON, "mon:stdio");
+ } else if (default_sclp && default_monitor) {
+ add_device_config(DEV_SCLP, "mon:stdio");
} else {
if (default_serial)
add_device_config(DEV_SERIAL, "stdio");
if (default_virtcon)
add_device_config(DEV_VIRTCON, "stdio");
+ if (default_sclp) {
+ add_device_config(DEV_SCLP, "stdio");
+ }
if (default_monitor)
monitor_parse("stdio", "readline");
}
monitor_parse("vc:80Cx24C", "readline");
if (default_virtcon)
add_device_config(DEV_VIRTCON, "vc:80Cx24C");
+ if (default_sclp) {
+ add_device_config(DEV_SCLP, "vc:80Cx24C");
+ }
+ }
+
+ if (display_type == DT_DEFAULT && !display_remote) {
+#if defined(CONFIG_GTK)
+ display_type = DT_GTK;
+#elif defined(CONFIG_SDL) || defined(CONFIG_COCOA)
+ display_type = DT_SDL;
+#elif defined(CONFIG_VNC)
+ vnc_display = "localhost:0,to=99";
+ show_vnc_port = 1;
+#else
+ display_type = DT_NONE;
+#endif
}
+#if defined(CONFIG_GTK)
+ if (display_type == DT_GTK) {
+ early_gtk_display_init();
+ }
+#endif
+
socket_init();
if (qemu_opts_foreach(qemu_find_opts("chardev"), chardev_init_func, NULL, 1) != 0)
exit(1);
if (foreach_device_config(DEV_VIRTCON, virtcon_parse) < 0)
exit(1);
+ if (foreach_device_config(DEV_SCLP, sclp_parse) < 0) {
+ exit(1);
+ }
if (foreach_device_config(DEV_DEBUGCON, debugcon_parse) < 0)
exit(1);
qdev_machine_init();
QEMUMachineInitArgs args = { .ram_size = ram_size,
- .boot_device = boot_devices,
+ .boot_device = (boot_devices[0] == '\0') ?
+ machine->boot_order :
+ boot_devices,
.kernel_filename = kernel_filename,
.kernel_cmdline = kernel_cmdline,
.initrd_filename = initrd_filename,
/* just use the first displaystate for the moment */
ds = get_displaystate();
- if (using_spice)
- display_remote++;
- if (display_type == DT_DEFAULT && !display_remote) {
-#if defined(CONFIG_SDL) || defined(CONFIG_COCOA)
- display_type = DT_SDL;
-#elif defined(CONFIG_VNC)
- vnc_display = "localhost:0,to=99";
- show_vnc_port = 1;
-#else
- display_type = DT_NONE;
-#endif
- }
-
-
/* init local displays */
switch (display_type) {
case DT_NOGRAPHIC:
case DT_SDL:
cocoa_display_init(ds, full_screen);
break;
+#endif
+#if defined(CONFIG_GTK)
+ case DT_GTK:
+ gtk_display_init(ds);
+ break;
#endif
default:
break;