#include "hw/boards.h"
#include "sysemu/accel.h"
#include "hw/usb.h"
-#include "hw/pcmcia.h"
#include "hw/i386/pc.h"
#include "hw/isa/isa.h"
#include "hw/bt.h"
int max_numa_nodeid;
NodeInfo numa_info[MAX_NODES];
+/* The bytes in qemu_uuid[] are in the order specified by RFC4122, _not_ in the
+ * little-endian "wire format" described in the SMBIOS 2.6 specification.
+ */
uint8_t qemu_uuid[16];
bool qemu_uuid_set;
-static QEMUBootSetHandler *boot_set_handler;
-static void *boot_set_opaque;
-
static NotifierList exit_notifiers =
NOTIFIER_LIST_INITIALIZER(exit_notifiers);
.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_NUMBER,
- .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",
- },{
- .name = "firmware",
- .type = QEMU_OPT_STRING,
- .help = "firmware image",
- },{
- .name = "kvm-type",
- .type = QEMU_OPT_STRING,
- .help = "Specifies the KVM virtualization mode (HV, PR)",
- },{
- .name = PC_MACHINE_MAX_RAM_BELOW_4G,
- .type = QEMU_OPT_SIZE,
- .help = "maximum ram below the 4G boundary (32bit boundary)",
- },{
- .name = "iommu",
- .type = QEMU_OPT_BOOL,
- .help = "Set on/off to enable/disable Intel IOMMU (VT-d)",
- },
- { /* End of list */ }
+ /*
+ * no elements => accept any
+ * sanity checking will happen later
+ * when setting machine properties
+ */
+ { }
},
};
},
};
+static QemuOptsList qemu_semihosting_config_opts = {
+ .name = "semihosting-config",
+ .implied_opt_name = "enable",
+ .head = QTAILQ_HEAD_INITIALIZER(qemu_semihosting_config_opts.head),
+ .desc = {
+ {
+ .name = "enable",
+ .type = QEMU_OPT_BOOL,
+ }, {
+ .name = "target",
+ .type = QEMU_OPT_STRING,
+ },
+ { /* end of list */ }
+ },
+};
+
/**
* Get machine options
*
}
-void qemu_register_boot_set(QEMUBootSetHandler *func, void *opaque)
-{
- boot_set_handler = func;
- boot_set_opaque = opaque;
-}
-
-int qemu_boot_set(const char *boot_order)
-{
- if (!boot_set_handler) {
- return -EINVAL;
- }
- return boot_set_handler(boot_set_opaque, boot_order);
-}
-
-static void validate_bootdevices(const char *devices)
-{
- /* We just do some generic consistency checks */
- const char *p;
- int bitmap = 0;
-
- for (p = devices; *p != '\0'; p++) {
- /* Allowed boot devices are:
- * a-b: floppy disk drives
- * c-f: IDE disk drives
- * g-m: machine implementation dependent drives
- * n-p: network devices
- * It's up to each machine implementation to check if the given boot
- * devices match the actual hardware implementation and firmware
- * features.
- */
- if (*p < 'a' || *p > 'p') {
- fprintf(stderr, "Invalid boot device '%c'\n", *p);
- exit(1);
- }
- if (bitmap & (1 << (*p - 'a'))) {
- fprintf(stderr, "Boot device '%c' was given twice\n", *p);
- exit(1);
- }
- bitmap |= 1 << (*p - 'a');
- }
-}
-
-static void restore_boot_order(void *opaque)
-{
- char *normal_boot_order = opaque;
- static int first = 1;
-
- /* Restore boot order and remove ourselves after the first boot */
- if (first) {
- first = 0;
- return;
- }
-
- qemu_boot_set(normal_boot_order);
-
- qemu_unregister_reset(restore_boot_order, normal_boot_order);
- g_free(normal_boot_order);
-}
-
static QemuOptsList qemu_smp_opts = {
.name = "smp-opts",
.implied_opt_name = "cpus",
}
}
-/***********************************************************/
-/* PCMCIA/Cardbus */
-
-static struct pcmcia_socket_entry_s {
- PCMCIASocket *socket;
- struct pcmcia_socket_entry_s *next;
-} *pcmcia_sockets = 0;
-
-void pcmcia_socket_register(PCMCIASocket *socket)
-{
- struct pcmcia_socket_entry_s *entry;
-
- entry = g_malloc(sizeof(struct pcmcia_socket_entry_s));
- entry->socket = socket;
- entry->next = pcmcia_sockets;
- pcmcia_sockets = entry;
-}
-
-void pcmcia_socket_unregister(PCMCIASocket *socket)
-{
- struct pcmcia_socket_entry_s *entry, **ptr;
-
- ptr = &pcmcia_sockets;
- for (entry = *ptr; entry; ptr = &entry->next, entry = *ptr)
- if (entry->socket == socket) {
- *ptr = entry->next;
- g_free(entry);
- }
-}
-
-void pcmcia_info(Monitor *mon, const QDict *qdict)
-{
- struct pcmcia_socket_entry_s *iter;
-
- if (!pcmcia_sockets)
- monitor_printf(mon, "No PCMCIA sockets\n");
-
- for (iter = pcmcia_sockets; iter; iter = iter->next)
- monitor_printf(mon, "%s: %s\n", iter->socket->slot_string,
- iter->socket->attached ? iter->socket->card_string :
- "Empty");
-}
-
/***********************************************************/
/* machine registration */
MachineClass *mc = MACHINE_CLASS(oc);
QEMUMachine *qm = data;
+ mc->family = qm->family;
mc->name = qm->name;
mc->alias = qm->alias;
mc->desc = qm->desc;
mc->no_floppy = qm->no_floppy;
mc->no_cdrom = qm->no_cdrom;
mc->no_sdcard = qm->no_sdcard;
+ mc->has_dynamic_sysbus = qm->has_dynamic_sysbus;
mc->is_default = qm->is_default;
mc->default_machine_opts = qm->default_machine_opts;
mc->default_boot_order = qm->default_boot_order;
+ mc->default_display = qm->default_display;
mc->compat_props = qm->compat_props;
mc->hw_version = qm->hw_version;
}
return mach_list;
}
+static int machine_help_func(QemuOpts *opts, MachineState *machine)
+{
+ ObjectProperty *prop;
+
+ if (!qemu_opt_has_help_opt(opts)) {
+ return 0;
+ }
+
+ QTAILQ_FOREACH(prop, &OBJECT(machine)->properties, node) {
+ if (!prop->set) {
+ continue;
+ }
+
+ error_printf("%s.%s=%s", MACHINE_GET_CLASS(machine)->name,
+ prop->name, prop->type);
+ if (prop->description) {
+ error_printf(" (%s)\n", prop->description);
+ } else {
+ error_printf("\n");
+ }
+ }
+
+ return 1;
+}
+
/***********************************************************/
/* main execution loop */
static int qemu_shutdown_requested(void)
{
- int r = shutdown_requested;
- shutdown_requested = 0;
- return r;
+ return atomic_xchg(&shutdown_requested, 0);
}
static void qemu_kill_report(void)
return 0;
}
-static void monitor_parse(const char *optarg, const char *mode)
+static void monitor_parse(const char *optarg, const char *mode, bool pretty)
{
static int monitor_device_index = 0;
QemuOpts *opts;
}
qemu_opt_set(opts, "mode", mode);
qemu_opt_set(opts, "chardev", label);
+ qemu_opt_set_bool(opts, "pretty", pretty);
if (def)
qemu_opt_set(opts, "default", "on");
monitor_device_index++;
return 0;
}
-static MachineClass *machine_parse(const char *name)
+static gint machine_class_cmp(gconstpointer a, gconstpointer b)
+{
+ const MachineClass *mc1 = a, *mc2 = b;
+ int res;
+
+ if (mc1->family == NULL) {
+ if (mc2->family == NULL) {
+ /* Compare standalone machine types against each other; they sort
+ * in increasing order.
+ */
+ return strcmp(object_class_get_name(OBJECT_CLASS(mc1)),
+ object_class_get_name(OBJECT_CLASS(mc2)));
+ }
+
+ /* Standalone machine types sort after families. */
+ return 1;
+ }
+
+ if (mc2->family == NULL) {
+ /* Families sort before standalone machine types. */
+ return -1;
+ }
+
+ /* Families sort between each other alphabetically increasingly. */
+ res = strcmp(mc1->family, mc2->family);
+ if (res != 0) {
+ return res;
+ }
+
+ /* Within the same family, machine types sort in decreasing order. */
+ return strcmp(object_class_get_name(OBJECT_CLASS(mc2)),
+ object_class_get_name(OBJECT_CLASS(mc1)));
+}
+
+ static MachineClass *machine_parse(const char *name)
{
MachineClass *mc = NULL;
GSList *el, *machines = object_class_get_list(TYPE_MACHINE, false);
error_printf("Use -machine help to list supported machines!\n");
} else {
printf("Supported machines are:\n");
+ machines = g_slist_sort(machines, machine_class_cmp);
for (el = machines; el; el = el->next) {
MachineClass *mc = el->data;
if (mc->alias) {
void *opaque)
{
Object *obj = OBJECT(opaque);
- StringInputVisitor *siv;
Error *local_err = NULL;
char *c, *qom_name;
}
}
- siv = string_input_visitor_new(value);
- object_property_set(obj, string_input_get_visitor(siv), qom_name, &local_err);
- string_input_visitor_cleanup(siv);
+ object_property_parse(obj, value, qom_name, &local_err);
g_free(qom_name);
if (local_err) {
qemu_add_opts(&qemu_name_opts);
qemu_add_opts(&qemu_numa_opts);
qemu_add_opts(&qemu_icount_opts);
+ qemu_add_opts(&qemu_semihosting_config_opts);
runstate_init();
case QEMU_OPTION_monitor:
default_monitor = 0;
if (strncmp(optarg, "none", 4)) {
- monitor_parse(optarg, "readline");
+ monitor_parse(optarg, "readline", false);
}
break;
case QEMU_OPTION_qmp:
- monitor_parse(optarg, "control");
+ monitor_parse(optarg, "control", false);
+ default_monitor = 0;
+ break;
+ case QEMU_OPTION_qmp_pretty:
+ monitor_parse(optarg, "control", true);
default_monitor = 0;
break;
case QEMU_OPTION_mon:
break;
case QEMU_OPTION_semihosting:
semihosting_enabled = 1;
+ semihosting_target = SEMIHOSTING_TARGET_AUTO;
+ break;
+ case QEMU_OPTION_semihosting_config:
+ semihosting_enabled = 1;
+ opts = qemu_opts_parse(qemu_find_opts("semihosting-config"),
+ optarg, 0);
+ if (opts != NULL) {
+ semihosting_enabled = qemu_opt_get_bool(opts, "enable",
+ true);
+ const char *target = qemu_opt_get(opts, "target");
+ if (target != NULL) {
+ if (strcmp("native", target) == 0) {
+ semihosting_target = SEMIHOSTING_TARGET_NATIVE;
+ } else if (strcmp("gdb", target) == 0) {
+ semihosting_target = SEMIHOSTING_TARGET_GDB;
+ } else if (strcmp("auto", target) == 0) {
+ semihosting_target = SEMIHOSTING_TARGET_AUTO;
+ } else {
+ fprintf(stderr, "Unsupported semihosting-config"
+ " %s\n",
+ optarg);
+ exit(1);
+ }
+ } else {
+ semihosting_target = SEMIHOSTING_TARGET_AUTO;
+ }
+ } else {
+ fprintf(stderr, "Unsupported semihosting-config %s\n",
+ optarg);
+ exit(1);
+ }
break;
case QEMU_OPTION_tdf:
fprintf(stderr, "Warning: user space PIT time drift fix "
configure_msg(opts);
break;
case QEMU_OPTION_dump_vmstate:
+ if (vmstate_dump_file) {
+ fprintf(stderr, "qemu: only one '-dump-vmstate' "
+ "option may be given\n");
+ exit(1);
+ }
vmstate_dump_file = fopen(optarg, "w");
if (vmstate_dump_file == NULL) {
fprintf(stderr, "open %s: %s\n", optarg, strerror(errno));
current_machine = MACHINE(object_new(object_class_get_name(
OBJECT_CLASS(machine_class))));
+ if (machine_help_func(qemu_get_machine_opts(), current_machine)) {
+ exit(0);
+ }
object_property_add_child(object_get_root(), "machine",
OBJECT(current_machine), &error_abort);
cpu_exec_init_all();
add_device_config(DEV_SCLP, "stdio");
}
if (default_monitor)
- monitor_parse("stdio", "readline");
+ monitor_parse("stdio", "readline", false);
}
} else {
if (default_serial)
if (default_parallel)
add_device_config(DEV_PARALLEL, "vc:80Cx24C");
if (default_monitor)
- monitor_parse("vc:80Cx24C", "readline");
+ monitor_parse("vc:80Cx24C", "readline", false);
if (default_virtcon)
add_device_config(DEV_VIRTCON, "vc:80Cx24C");
if (default_sclp) {
#endif
if (pid_file && qemu_create_pidfile(pid_file) != 0) {
- os_pidfile_error();
+ fprintf(stderr, "Could not acquire pid file: %s\n", strerror(errno));
exit(1);
}
if (opts) {
char *normal_boot_order;
const char *order, *once;
+ Error *local_err = NULL;
order = qemu_opt_get(opts, "order");
if (order) {
- validate_bootdevices(order);
+ validate_bootdevices(order, &local_err);
+ if (local_err) {
+ error_report("%s", error_get_pretty(local_err));
+ exit(1);
+ }
boot_order = order;
}
once = qemu_opt_get(opts, "once");
if (once) {
- validate_bootdevices(once);
+ validate_bootdevices(once, &local_err);
+ if (local_err) {
+ error_report("%s", error_get_pretty(local_err));
+ exit(1);
+ }
normal_boot_order = g_strdup(boot_order);
boot_order = once;
qemu_register_reset(restore_boot_order, normal_boot_order);
/* If no default VGA is requested, the default is "none". */
if (default_vga) {
- if (cirrus_vga_available()) {
+ if (machine_class->default_display) {
+ vga_model = machine_class->default_display;
+ } else if (cirrus_vga_available()) {
vga_model = "cirrus";
} else if (vga_available()) {
vga_model = "std";