X-Git-Url: https://repo.jachan.dev/qemu.git/blobdiff_plain/3525c42fd3b70182b1f98d74439e8aeabb565803..5847d9e1399d3497be8eeca6f3a20a18a40b114b:/vl.c diff --git a/vl.c b/vl.c index 204d85bcf6..8d305ca59b 100644 --- a/vl.c +++ b/vl.c @@ -28,6 +28,7 @@ #include #include #include +#include "bitmap.h" /* Needed early for CONFIG_BSD etc. */ #include "config-host.h" @@ -62,6 +63,11 @@ #include #include #endif + +#ifdef CONFIG_SECCOMP +#include "qemu-seccomp.h" +#endif + #ifdef __sun__ #include #include @@ -130,8 +136,8 @@ int main(int argc, char **argv) #include "qemu-timer.h" #include "qemu-char.h" #include "cache-utils.h" -#include "block.h" #include "blockdev.h" +#include "hw/block-common.h" #include "block-migration.h" #include "dma.h" #include "audio/audio.h" @@ -159,6 +165,7 @@ int main(int argc, char **argv) #include "qemu-queue.h" #include "cpus.h" #include "arch_init.h" +#include "osdep.h" #include "ui/qemu-spice.h" @@ -240,7 +247,7 @@ QTAILQ_HEAD(, FWBootEntry) fw_boot_order = QTAILQ_HEAD_INITIALIZER(fw_boot_order int nb_numa_nodes; uint64_t node_mem[MAX_NODES]; -uint64_t node_cpumask[MAX_NODES]; +unsigned long *node_cpumask[MAX_NODES]; uint8_t qemu_uuid[16]; @@ -291,6 +298,11 @@ static struct { { .driver = "qxl-vga", .flag = &default_vga }, }; +const char *qemu_get_vm_name(void) +{ + return qemu_name; +} + static void res_free(void) { if (boot_splash_filedata != NULL) { @@ -758,6 +770,26 @@ static int bt_parse(const char *opt) return 1; } +static int parse_sandbox(QemuOpts *opts, void *opaque) +{ + /* FIXME: change this to true for 1.3 */ + if (qemu_opt_get_bool(opts, "enable", false)) { +#ifdef CONFIG_SECCOMP + if (seccomp_start() < 0) { + qerror_report(ERROR_CLASS_GENERIC_ERROR, + "failed to install seccomp syscall filter in the kernel"); + return -1; + } +#else + qerror_report(ERROR_CLASS_GENERIC_ERROR, + "sandboxing request but seccomp is not compiled into this build"); + return -1; +#endif + } + + return 0; +} + /***********************************************************/ /* QEMU Block devices */ @@ -951,6 +983,8 @@ static void numa_add(const char *optarg) unsigned long long value, endvalue; int nodenr; + value = endvalue = 0ULL; + optarg = get_opt_name(option, 128, optarg, ',') + 1; if (!strcmp(option, "node")) { if (get_param_value(option, 128, "nodeid", optarg) == 0) { @@ -970,27 +1004,22 @@ static void numa_add(const char *optarg) } node_mem[nodenr] = sval; } - if (get_param_value(option, 128, "cpus", optarg) == 0) { - node_cpumask[nodenr] = 0; - } else { + if (get_param_value(option, 128, "cpus", optarg) != 0) { value = strtoull(option, &endptr, 10); - if (value >= 64) { - value = 63; - fprintf(stderr, "only 64 CPUs in NUMA mode supported.\n"); + if (*endptr == '-') { + endvalue = strtoull(endptr+1, &endptr, 10); } else { - if (*endptr == '-') { - endvalue = strtoull(endptr+1, &endptr, 10); - if (endvalue >= 63) { - endvalue = 62; - fprintf(stderr, - "only 63 CPUs in NUMA mode supported.\n"); - } - value = (2ULL << endvalue) - (1ULL << value); - } else { - value = 1ULL << value; - } + endvalue = value; } - node_cpumask[nodenr] = 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); } nb_numa_nodes++; } @@ -1209,6 +1238,37 @@ QEMUMachine *find_default_machine(void) return NULL; } +MachineInfoList *qmp_query_machines(Error **errp) +{ + MachineInfoList *mach_list = NULL; + QEMUMachine *m; + + for (m = first_machine; m; m = m->next) { + MachineInfoList *entry; + MachineInfo *info; + + info = g_malloc0(sizeof(*info)); + if (m->is_default) { + info->has_is_default = true; + info->is_default = true; + } + + if (m->alias) { + info->has_alias = true; + info->alias = g_strdup(m->alias); + } + + info->name = g_strdup(m->name); + + entry = g_malloc0(sizeof(*entry)); + entry->value = info; + entry->next = mach_list; + mach_list = entry; + } + + return mach_list; +} + /***********************************************************/ /* main execution loop */ @@ -1294,6 +1354,9 @@ static pid_t shutdown_pid; static int powerdown_requested; static int debug_requested; static int suspend_requested; +static int wakeup_requested; +static NotifierList powerdown_notifiers = + NOTIFIER_LIST_INITIALIZER(powerdown_notifiers); static NotifierList suspend_notifiers = NOTIFIER_LIST_INITIALIZER(suspend_notifiers); static NotifierList wakeup_notifiers = @@ -1348,6 +1411,13 @@ static int qemu_suspend_requested(void) return r; } +static int qemu_wakeup_requested(void) +{ + int r = wakeup_requested; + wakeup_requested = 0; + return r; +} + int qemu_powerdown_requested(void) { int r = powerdown_requested; @@ -1396,7 +1466,7 @@ void qemu_unregister_reset(QEMUResetHandler *func, void *opaque) } } -void qemu_system_reset(bool report) +void qemu_devices_reset(void) { QEMUResetEntry *re, *nre; @@ -1404,6 +1474,15 @@ void qemu_system_reset(bool report) QTAILQ_FOREACH_SAFE(re, &reset_handlers, entry, nre) { re->func(re->opaque); } +} + +void qemu_system_reset(bool report) +{ + if (current_machine && current_machine->reset) { + current_machine->reset(); + } else { + qemu_devices_reset(); + } if (report) { monitor_protocol_event(QEVENT_RESET, NULL); } @@ -1453,9 +1532,8 @@ void qemu_system_wakeup_request(WakeupReason reason) return; } runstate_set(RUN_STATE_RUNNING); - monitor_protocol_event(QEVENT_WAKEUP, NULL); notifier_list_notify(&wakeup_notifiers, &reason); - reset_requested = 1; + wakeup_requested = 1; qemu_notify_event(); } @@ -1487,12 +1565,23 @@ void qemu_system_shutdown_request(void) qemu_notify_event(); } +static void qemu_system_powerdown(void) +{ + monitor_protocol_event(QEVENT_POWERDOWN, NULL); + notifier_list_notify(&powerdown_notifiers, NULL); +} + void qemu_system_powerdown_request(void) { powerdown_requested = 1; qemu_notify_event(); } +void qemu_register_powerdown_notifier(Notifier *notifier) +{ + notifier_list_add(&powerdown_notifiers, notifier); +} + void qemu_system_debug_request(void) { debug_requested = 1; @@ -1505,8 +1594,6 @@ void qemu_system_vmstop_request(RunState state) qemu_notify_event(); } -qemu_irq qemu_system_powerdown; - static bool main_loop_should_exit(void) { RunState r; @@ -1535,9 +1622,15 @@ static bool main_loop_should_exit(void) runstate_set(RUN_STATE_PAUSED); } } + if (qemu_wakeup_requested()) { + pause_all_vcpus(); + cpu_synchronize_all_states(); + qemu_system_reset(VMRESET_SILENT); + resume_all_vcpus(); + monitor_protocol_event(QEVENT_WAKEUP, NULL); + } if (qemu_powerdown_requested()) { - monitor_protocol_event(QEVENT_POWERDOWN, NULL); - qemu_irq_raise(qemu_system_powerdown); + qemu_system_powerdown(); } if (qemu_vmstop_requested(&r)) { vm_stop(r); @@ -1795,9 +1888,8 @@ char *qemu_find_file(int type, const char *name) const char *subdir; char *buf; - /* If name contains path separators then try it as a straight path. */ - if ((strchr(name, '/') || strchr(name, '\\')) - && access(name, R_OK) == 0) { + /* Try the name as a straight path first */ + if (access(name, R_OK) == 0) { return g_strdup(name); } switch (type) { @@ -1985,8 +2077,8 @@ static int serial_parse(const char *devname) snprintf(label, sizeof(label), "serial%d", index); serial_hds[index] = qemu_chr_new(label, devname, NULL); if (!serial_hds[index]) { - fprintf(stderr, "qemu: could not open serial device '%s': %s\n", - devname, strerror(errno)); + fprintf(stderr, "qemu: could not connect serial device" + " to character backend '%s'\n", devname); return -1; } index++; @@ -2007,8 +2099,8 @@ static int parallel_parse(const char *devname) snprintf(label, sizeof(label), "parallel%d", index); parallel_hds[index] = qemu_chr_new(label, devname, NULL); if (!parallel_hds[index]) { - fprintf(stderr, "qemu: could not open parallel device '%s': %s\n", - devname, strerror(errno)); + fprintf(stderr, "qemu: could not connect parallel device" + " to character backend '%s'\n", devname); return -1; } index++; @@ -2042,8 +2134,8 @@ static int virtcon_parse(const char *devname) snprintf(label, sizeof(label), "virtcon%d", index); virtcon_hds[index] = qemu_chr_new(label, devname, NULL); if (!virtcon_hds[index]) { - fprintf(stderr, "qemu: could not open virtio console '%s': %s\n", - devname, strerror(errno)); + fprintf(stderr, "qemu: could not connect virtio console" + " to character backend '%s'\n", devname); return -1; } qemu_opt_set(dev_opts, "chardev", label); @@ -2087,7 +2179,7 @@ static QEMUMachine *machine_parse(const char *name) printf("%-20s %s%s\n", m->name, m->desc, m->is_default ? " (default)" : ""); } - exit(!name || *name != '?'); + exit(!name || !is_help_option(name)); } static int tcg_init(void) @@ -2331,7 +2423,7 @@ int main(int argc, char **argv, char **envp) for (i = 0; i < MAX_NODES; i++) { node_mem[i] = 0; - node_cpumask[i] = 0; + node_cpumask[i] = bitmap_new(MAX_CPUMASK_BITS); } nb_numa_nodes = 0; @@ -2540,7 +2632,8 @@ int main(int argc, char **argv, char **envp) { static const char * const params[] = { "order", "once", "menu", - "splash", "splash-time", NULL + "splash", "splash-time", + "reboot-timeout", NULL }; char buf[sizeof(boot_devices)]; char *standard_boot_devices; @@ -2653,6 +2746,7 @@ int main(int argc, char **argv, char **envp) break; case QEMU_OPTION_m: { int64_t value; + uint64_t sz; char *end; value = strtosz(optarg, &end); @@ -2660,12 +2754,12 @@ int main(int argc, char **argv, char **envp) fprintf(stderr, "qemu: invalid ram size: %s\n", optarg); exit(1); } - - if (value != (uint64_t)(ram_addr_t)value) { + sz = QEMU_ALIGN_UP((uint64_t)value, 8192); + ram_size = sz; + if (ram_size != sz) { fprintf(stderr, "qemu: ram size too large\n"); exit(1); } - ram_size = value; break; } case QEMU_OPTION_mempath: @@ -3199,6 +3293,12 @@ int main(int argc, char **argv, char **envp) case QEMU_OPTION_qtest_log: qtest_log = optarg; break; + case QEMU_OPTION_sandbox: + opts = qemu_opts_parse(qemu_find_opts("sandbox"), optarg, 1); + if (!opts) { + exit(0); + } + break; default: os_parse_cmd_args(popt->index, optarg); } @@ -3206,6 +3306,19 @@ int main(int argc, char **argv, char **envp) } loc_set_none(); + if (qemu_opts_foreach(qemu_find_opts("sandbox"), parse_sandbox, NULL, 0)) { + exit(1); + } + + if (machine == NULL) { + fprintf(stderr, "No machine found.\n"); + exit(1); + } + + if (machine->hw_version) { + qemu_set_version(machine->hw_version); + } + /* Init CPU def lists, based on config * - Must be called after all the qemu_read_config_file() calls * - Must be called before list_cpus() @@ -3213,7 +3326,7 @@ int main(int argc, char **argv, char **envp) */ cpudef_init(); - if (cpu_model && *cpu_model == '?') { + if (cpu_model && is_help_option(cpu_model)) { list_cpus(stdout, &fprintf, cpu_model); exit(0); } @@ -3244,11 +3357,6 @@ int main(int argc, char **argv, char **envp) data_dir = CONFIG_QEMU_DATADIR; } - if (machine == NULL) { - fprintf(stderr, "No machine found.\n"); - exit(1); - } - /* * Default to max_cpus = smp_cpus, in case the user doesn't * specify a max_cpus value. @@ -3343,6 +3451,11 @@ int main(int argc, char **argv, char **envp) ram_size = DEFAULT_RAM_SIZE * 1024 * 1024; } + if (qemu_opts_foreach(qemu_find_opts("device"), device_help_func, NULL, 0) + != 0) { + exit(0); + } + configure_accelerator(); qemu_init_cpu_loop(); @@ -3434,8 +3547,7 @@ int main(int argc, char **argv, char **envp) default_drive(default_sdcard, snapshot, machine->use_scsi, IF_SD, 0, SD_OPTS); - register_savevm_live(NULL, "ram", 0, 4, NULL, ram_save_live, NULL, - ram_load, NULL); + register_savevm_live(NULL, "ram", 0, 4, &savevm_ram_handlers, NULL); if (nb_numa_nodes > 0) { int i; @@ -3465,8 +3577,9 @@ int main(int argc, char **argv, char **envp) } for (i = 0; i < nb_numa_nodes; i++) { - if (node_cpumask[i] != 0) + if (!bitmap_empty(node_cpumask[i], MAX_CPUMASK_BITS)) { break; + } } /* assigning the VCPUs round-robin is easier to implement, guest OSes * must cope with this anyway, because there are BIOSes out there in @@ -3474,7 +3587,7 @@ int main(int argc, char **argv, char **envp) */ if (i == nb_numa_nodes) { for (i = 0; i < max_cpus; i++) { - node_cpumask[i % nb_numa_nodes] |= 1 << i; + set_bit(i, node_cpumask[i % nb_numa_nodes]); } } } @@ -3498,9 +3611,6 @@ int main(int argc, char **argv, char **envp) } select_vgahw(vga_model); - if (qemu_opts_foreach(qemu_find_opts("device"), device_help_func, NULL, 0) != 0) - exit(0); - if (watchdog) { i = select_watchdog(watchdog); if (i > 0) @@ -3558,7 +3668,9 @@ int main(int argc, char **argv, char **envp) break; #if defined(CONFIG_CURSES) case DT_CURSES: - curses_display_init(ds, full_screen); + if (!is_daemonized()) { + curses_display_init(ds, full_screen); + } break; #endif #if defined(CONFIG_SDL) @@ -3581,8 +3693,11 @@ int main(int argc, char **argv, char **envp) /* init remote displays */ if (vnc_display) { vnc_display_init(ds); - if (vnc_display_open(ds, vnc_display) < 0) + if (vnc_display_open(ds, vnc_display) < 0) { + fprintf(stderr, "Failed to start VNC server on `%s'\n", + vnc_display); exit(1); + } if (show_vnc_port) { printf("VNC server running on `%s'\n", vnc_display_local_addr(ds));