X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=vl.c;h=6e6225f09b51a11d4e671464d89161f560fffbe9;hb=4e906d567a97ee45b4922001bf521dad0bde5268;hp=d6f6422de43ed8d2ebdcc55c4db049fe4f12a7d0;hpb=5f1399651eaab1b04e49107250d182968a227aa6;p=qemu.git diff --git a/vl.c b/vl.c index d6f6422de..6e6225f09 100644 --- a/vl.c +++ b/vl.c @@ -117,16 +117,16 @@ int main(int argc, char **argv) #include "hw/boards.h" #include "hw/usb.h" #include "hw/pcmcia.h" -#include "hw/pc.h" -#include "hw/isa.h" -#include "hw/baum.h" +#include "hw/i386/pc.h" +#include "hw/isa/isa.h" #include "hw/bt.h" -#include "hw/watchdog.h" -#include "hw/smbios.h" -#include "hw/xen.h" +#include "sysemu/watchdog.h" +#include "hw/i386/smbios.h" +#include "hw/xen/xen.h" #include "hw/qdev.h" #include "hw/loader.h" -#include "bt/bt.h" +#include "monitor/qdev.h" +#include "sysemu/bt.h" #include "net/net.h" #include "net/slirp.h" #include "monitor/monitor.h" @@ -134,11 +134,12 @@ int main(int argc, char **argv) #include "sysemu/sysemu.h" #include "exec/gdbstub.h" #include "qemu/timer.h" -#include "char/char.h" +#include "sysemu/char.h" #include "qemu/cache-utils.h" #include "sysemu/blockdev.h" -#include "hw/block-common.h" +#include "hw/block/block.h" #include "migration/block.h" +#include "sysemu/tpm.h" #include "sysemu/dma.h" #include "audio/audio.h" #include "migration/migration.h" @@ -178,7 +179,8 @@ int main(int argc, char **argv) #define MAX_VIRTIO_CONSOLES 1 #define MAX_SCLP_CONSOLES 1 -static const char *data_dir; +static const char *data_dir[16]; +static int data_dir_idx; const char *bios_name = NULL; enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB; DisplayType display_type = DT_DEFAULT; @@ -232,6 +234,7 @@ int ctrl_grab = 0; unsigned int nb_prom_envs = 0; const char *prom_envs[MAX_PROM_ENVS]; int boot_menu; +bool boot_strict; uint8_t *boot_splash_filedata; size_t boot_splash_filedata_size; uint8_t qemu_extra_params_fw[2]; @@ -264,7 +267,6 @@ static NotifierList machine_init_done_notifiers = NOTIFIER_LIST_INITIALIZER(machine_init_done_notifiers); static bool tcg_allowed = true; -bool kvm_allowed; bool xen_allowed; uint32_t xen_domid; enum xen_mode xen_mode = XEN_EMULATE; @@ -456,6 +458,9 @@ static QemuOptsList qemu_boot_opts = { }, { .name = "reboot-timeout", .type = QEMU_OPT_STRING, + }, { + .name = "strict", + .type = QEMU_OPT_STRING, }, { /*End of list */ } }, @@ -491,6 +496,28 @@ static QemuOptsList qemu_object_opts = { }, }; +static QemuOptsList qemu_tpmdev_opts = { + .name = "tpmdev", + .implied_opt_name = "type", + .head = QTAILQ_HEAD_INITIALIZER(qemu_tpmdev_opts.head), + .desc = { + /* options are defined in the TPM backends */ + { /* end of list */ } + }, +}; + +static QemuOptsList qemu_realtime_opts = { + .name = "realtime", + .head = QTAILQ_HEAD_INITIALIZER(qemu_realtime_opts.head), + .desc = { + { + .name = "mlock", + .type = QEMU_OPT_BOOL, + }, + { /* end of list */ } + }, +}; + const char *qemu_get_vm_name(void) { return qemu_name; @@ -566,6 +593,7 @@ static const RunStateTransition runstate_transitions_def[] = { { RUN_STATE_RUNNING, RUN_STATE_SAVE_VM }, { RUN_STATE_RUNNING, RUN_STATE_SHUTDOWN }, { RUN_STATE_RUNNING, RUN_STATE_WATCHDOG }, + { RUN_STATE_RUNNING, RUN_STATE_GUEST_PANICKED }, { RUN_STATE_SAVE_VM, RUN_STATE_RUNNING }, @@ -580,6 +608,8 @@ static const RunStateTransition runstate_transitions_def[] = { { RUN_STATE_WATCHDOG, RUN_STATE_RUNNING }, { RUN_STATE_WATCHDOG, RUN_STATE_FINISH_MIGRATE }, + { RUN_STATE_GUEST_PANICKED, RUN_STATE_PAUSED }, + { RUN_STATE_MAX, RUN_STATE_MAX }, }; @@ -612,7 +642,7 @@ void runstate_set(RunState new_state) RunState_lookup[new_state]); abort(); } - + trace_runstate_set(new_state); current_run_state = new_state; } @@ -621,6 +651,13 @@ int runstate_is_running(void) return runstate_check(RUN_STATE_RUNNING); } +bool runstate_needs_reset(void) +{ + return runstate_check(RUN_STATE_INTERNAL_ERROR) || + runstate_check(RUN_STATE_SHUTDOWN) || + runstate_check(RUN_STATE_GUEST_PANICKED); +} + StatusInfo *qmp_query_status(Error **errp) { StatusInfo *info = g_malloc0(sizeof(*info)); @@ -1194,6 +1231,24 @@ void add_boot_device_path(int32_t bootindex, DeviceState *dev, QTAILQ_INSERT_TAIL(&fw_boot_order, node, link); } +DeviceState *get_boot_device(uint32_t position) +{ + uint32_t counter = 0; + FWBootEntry *i = NULL; + DeviceState *res = NULL; + + if (!QTAILQ_EMPTY(&fw_boot_order)) { + QTAILQ_FOREACH(i, &fw_boot_order, link) { + if (counter == position) { + res = i->dev; + break; + } + counter++; + } + } + return res; +} + /* * This function returns null terminated string that consist of new line * separated device paths. @@ -1241,18 +1296,65 @@ char *get_boot_devices_list(size_t *size) *size = total; + if (boot_strict && *size > 0) { + list[total-1] = '\n'; + list = g_realloc(list, total + 5); + memcpy(&list[total], "HALT", 5); + *size = total + 5; + } return list; } +static void numa_node_parse_cpus(int nodenr, const char *cpus) +{ + char *endptr; + unsigned long long value, endvalue; + + /* 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 value, endvalue; unsigned long long nodenr; - value = endvalue = 0ULL; - optarg = get_opt_name(option, 128, optarg, ','); if (*optarg == ',') { optarg++; @@ -1290,21 +1392,7 @@ static void numa_add(const char *optarg) 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 { @@ -1357,6 +1445,20 @@ static void smp_parse(const char *optarg) max_cpus = smp_cpus; } +static void configure_realtime(QemuOpts *opts) +{ + bool enable_mlock; + + enable_mlock = qemu_opt_get_bool(opts, "mlock", true); + + if (enable_mlock) { + if (os_mlock() < 0) { + fprintf(stderr, "qemu: locking memory failed\n"); + exit(1); + } + } +} + /***********************************************************/ /* USB devices */ @@ -1400,8 +1502,9 @@ static int usb_device_del(const char *devname) 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; @@ -1548,6 +1651,7 @@ MachineInfoList *qmp_query_machines(Error **errp) } info->name = g_strdup(m->name); + info->cpu_max = !m->max_cpus ? 1 : m->max_cpus; entry = g_malloc0(sizeof(*entry)); entry->value = info; @@ -1561,55 +1665,6 @@ MachineInfoList *qmp_query_machines(Error **errp) /***********************************************************/ /* main execution loop */ -static void gui_update(void *opaque) -{ - uint64_t interval = GUI_REFRESH_INTERVAL; - DisplayState *ds = opaque; - DisplayChangeListener *dcl; - - dpy_refresh(ds); - - QLIST_FOREACH(dcl, &ds->listeners, next) { - if (dcl->gui_timer_interval && - dcl->gui_timer_interval < interval) - interval = dcl->gui_timer_interval; - } - qemu_mod_timer(ds->gui_timer, interval + qemu_get_clock_ms(rt_clock)); -} - -void gui_setup_refresh(DisplayState *ds) -{ - DisplayChangeListener *dcl; - bool need_timer = false; - bool have_gfx = false; - bool have_text = false; - - QLIST_FOREACH(dcl, &ds->listeners, next) { - if (dcl->dpy_refresh != NULL) { - need_timer = true; - } - if (dcl->dpy_gfx_update != NULL) { - have_gfx = true; - } - if (dcl->dpy_text_update != NULL) { - have_text = true; - } - } - - if (need_timer && ds->gui_timer == NULL) { - ds->gui_timer = qemu_new_timer_ms(rt_clock, gui_update, ds); - qemu_mod_timer(ds->gui_timer, qemu_get_clock_ms(rt_clock)); - } - if (!need_timer && ds->gui_timer != NULL) { - qemu_del_timer(ds->gui_timer); - qemu_free_timer(ds->gui_timer); - ds->gui_timer = NULL; - } - - ds->have_gfx = have_gfx; - ds->have_text = have_text; -} - struct vm_change_state_entry { VMChangeStateHandler *cb; void *opaque; @@ -1938,8 +1993,7 @@ static bool main_loop_should_exit(void) cpu_synchronize_all_states(); qemu_system_reset(VMRESET_REPORT); resume_all_vcpus(); - if (runstate_check(RUN_STATE_INTERNAL_ERROR) || - runstate_check(RUN_STATE_SHUTDOWN)) { + if (runstate_needs_reset()) { runstate_set(RUN_STATE_PAUSED); } } @@ -2178,6 +2232,13 @@ static DisplayType select_display(const char *p) #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; @@ -2216,14 +2277,16 @@ static int balloon_parse(const char *arg) char *qemu_find_file(int type, const char *name) { - int len; + int i; const char *subdir; char *buf; /* Try the name as a straight path first */ if (access(name, R_OK) == 0) { + trace_load_file(name, name); return g_strdup(name); } + switch (type) { case QEMU_FILE_TYPE_BIOS: subdir = ""; @@ -2234,14 +2297,16 @@ char *qemu_find_file(int type, const char *name) default: abort(); } - len = strlen(data_dir) + strlen(name) + strlen(subdir) + 2; - buf = g_malloc0(len); - snprintf(buf, len, "%s/%s%s", data_dir, subdir, name); - if (access(buf, R_OK)) { + + for (i = 0; i < data_dir_idx; i++) { + buf = g_strdup_printf("%s/%s%s", data_dir[i], subdir, name); + if (access(buf, R_OK) == 0) { + trace_load_file(name, buf); + return buf; + } g_free(buf); - return NULL; } - return buf; + return NULL; } static int device_help_func(QemuOpts *opts, void *opaque) @@ -2316,6 +2381,7 @@ static int mon_init_func(QemuOpts *opts, void *opaque) exit(1); } + qemu_chr_fe_claim_no_fail(chr); monitor_init(chr, flags); return 0; } @@ -2465,7 +2531,7 @@ static int virtcon_parse(const char *devname) qemu_opt_set(bus_opts, "driver", "virtio-serial-s390"); } else { qemu_opt_set(bus_opts, "driver", "virtio-serial-pci"); - } + } dev_opts = qemu_opts_create_nofail(device); qemu_opt_set(dev_opts, "driver", "virtconsole"); @@ -2517,7 +2583,7 @@ static int sclp_parse(const char *devname) } static int debugcon_parse(const char *devname) -{ +{ QemuOpts *opts; if (!qemu_chr_new("debugcon", devname, NULL)) { @@ -2833,6 +2899,8 @@ int main(int argc, char **argv, char **envp) qemu_add_opts(&qemu_sandbox_opts); qemu_add_opts(&qemu_add_fd_opts); qemu_add_opts(&qemu_object_opts); + qemu_add_opts(&qemu_tpmdev_opts); + qemu_add_opts(&qemu_realtime_opts); runstate_init(); @@ -2860,6 +2928,8 @@ int main(int argc, char **argv, char **envp) nb_numa_nodes = 0; nb_nics = 0; + bdrv_init_with_whitelist(); + autostart= 1; /* first pass of option parsing */ @@ -2959,7 +3029,7 @@ int main(int argc, char **argv, char **envp) 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); @@ -3065,7 +3135,7 @@ int main(int argc, char **argv, char **envp) static const char * const params[] = { "order", "once", "menu", "splash", "splash-time", - "reboot-timeout", NULL + "reboot-timeout", "strict", NULL }; char buf[sizeof(boot_devices)]; char *standard_boot_devices; @@ -3108,8 +3178,23 @@ int main(int argc, char **argv, char **envp) exit(1); } } - qemu_opts_parse(qemu_find_opts("boot-opts"), - optarg, 0); + if (get_param_value(buf, sizeof(buf), + "strict", optarg)) { + if (!strcmp(buf, "on")) { + boot_strict = true; + } else if (!strcmp(buf, "off")) { + boot_strict = false; + } else { + fprintf(stderr, + "qemu: invalid option value '%s'\n", + buf); + exit(1); + } + } + if (!qemu_opts_parse(qemu_find_opts("boot-opts"), + optarg, 0)) { + exit(1); + } } } break; @@ -3155,18 +3240,10 @@ int main(int argc, char **argv, char **envp) add_device_config(DEV_BT, optarg); break; case QEMU_OPTION_audio_help: - if (!(audio_available())) { - printf("Option %s not supported for this target\n", popt->name); - exit(1); - } AUD_help (); exit (0); break; case QEMU_OPTION_soundhw: - if (!(audio_available())) { - printf("Option %s not supported for this target\n", popt->name); - exit(1); - } select_soundhw (optarg); break; case QEMU_OPTION_h: @@ -3194,6 +3271,13 @@ int main(int argc, char **argv, char **envp) } break; } +#ifdef CONFIG_TPM + case QEMU_OPTION_tpmdev: + if (tpm_config_parse(qemu_find_opts("tpmdev"), optarg) < 0) { + exit(1); + } + break; +#endif case QEMU_OPTION_mempath: mem_path = optarg; break; @@ -3215,7 +3299,9 @@ int main(int argc, char **argv, char **envp) add_device_config(DEV_GDB, optarg); break; case QEMU_OPTION_L: - data_dir = optarg; + if (data_dir_idx < ARRAY_SIZE(data_dir)) { + data_dir[data_dir_idx++] = optarg; + } break; case QEMU_OPTION_bios: bios_name = optarg; @@ -3307,7 +3393,6 @@ int main(int argc, char **argv, char **envp) } opts = qemu_opts_parse(olist, optarg, 1); if (!opts) { - fprintf(stderr, "parse error: %s\n", optarg); exit(1); } break; @@ -3323,7 +3408,6 @@ int main(int argc, char **argv, char **envp) } opts = qemu_opts_parse(olist, optarg, 1); if (!opts) { - fprintf(stderr, "parse error: %s\n", optarg); exit(1); } @@ -3481,7 +3565,9 @@ int main(int argc, char **argv, char **envp) break; } case QEMU_OPTION_acpitable: - do_acpitable_option(optarg); + opts = qemu_opts_parse(qemu_find_opts("acpi"), optarg, 1); + g_assert(opts != NULL); + do_acpitable_option(opts); break; case QEMU_OPTION_smbios: do_smbios_option(optarg); @@ -3494,7 +3580,6 @@ int main(int argc, char **argv, char **envp) 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"); @@ -3599,6 +3684,9 @@ int main(int argc, char **argv, char **envp) 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); @@ -3627,8 +3715,8 @@ int main(int argc, char **argv, char **envp) } p += 8; os_set_proc_name(p); - } - } + } + } break; case QEMU_OPTION_prom_env: if (nb_prom_envs >= MAX_PROM_ENVS) { @@ -3728,9 +3816,9 @@ int main(int argc, char **argv, char **envp) } 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: { @@ -3757,14 +3845,14 @@ int main(int argc, char **argv, char **envp) 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 " @@ -3774,6 +3862,16 @@ int main(int argc, char **argv, char **envp) break; case QEMU_OPTION_object: opts = qemu_opts_parse(qemu_find_opts("object"), optarg, 1); + if (!opts) { + exit(1); + } + break; + case QEMU_OPTION_realtime: + opts = qemu_opts_parse(qemu_find_opts("realtime"), optarg, 0); + if (!opts) { + exit(1); + } + configure_realtime(opts); break; default: os_parse_cmd_args(popt->index, optarg); @@ -3833,10 +3931,17 @@ int main(int argc, char **argv, char **envp) * 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); + } + + mask = qemu_str_to_log_mask(log_mask); + if (!mask) { + qemu_print_log_usage(stdout); + exit(1); } - set_cpu_log(log_mask); + qemu_set_log(mask); } if (!trace_backend_init(trace_events, trace_file)) { @@ -3845,12 +3950,15 @@ int main(int argc, char **argv, char **envp) /* If no data_dir is specified then try to find it relative to the executable path. */ - if (!data_dir) { - data_dir = os_find_datadir(argv[0]); + if (data_dir_idx < ARRAY_SIZE(data_dir)) { + data_dir[data_dir_idx] = os_find_datadir(argv[0]); + if (data_dir[data_dir_idx] != NULL) { + data_dir_idx++; + } } /* If all else fails use the install path specified when building. */ - if (!data_dir) { - data_dir = CONFIG_QEMU_DATADIR; + if (data_dir_idx < ARRAY_SIZE(data_dir)) { + data_dir[data_dir_idx++] = CONFIG_QEMU_DATADIR; } /* @@ -3960,6 +4068,25 @@ int main(int argc, char **argv, char **envp) } } + 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) @@ -3989,6 +4116,10 @@ int main(int argc, char **argv, char **envp) configure_accelerator(); + if (!qtest_enabled() && qtest_chrdev) { + qtest_init(); + } + machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0); if (machine_opts) { kernel_filename = qemu_opt_get(machine_opts, "kernel"); @@ -4042,6 +4173,12 @@ int main(int argc, char **argv, char **envp) exit(1); } +#ifdef CONFIG_TPM + if (tpm_init() < 0) { + exit(1); + } +#endif + /* init the bluetooth world */ if (foreach_device_config(DEV_BT, bt_parse)) exit(1); @@ -4056,8 +4193,6 @@ int main(int argc, char **argv, char **envp) cpu_exec_init_all(); - bdrv_init_with_whitelist(); - blk_mig_init(); /* open the virtual block devices */ @@ -4167,6 +4302,8 @@ int main(int argc, char **argv, char **envp) .cpu_model = cpu_model }; machine->init(&args); + audio_init(); + cpu_synchronize_all_post_init(); set_numa_modes(); @@ -4185,22 +4322,7 @@ int main(int argc, char **argv, char **envp) net_check_clients(); - /* 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 - } - + ds = init_displaystate(); /* init local displays */ switch (display_type) { @@ -4219,6 +4341,11 @@ int main(int argc, char **argv, char **envp) 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; @@ -4251,9 +4378,6 @@ int main(int argc, char **argv, char **envp) } #endif - /* display setup */ - text_consoles_set_display(ds); - if (foreach_device_config(DEV_GDB, gdbserver_start) < 0) { exit(1); } @@ -4291,11 +4415,13 @@ int main(int argc, char **argv, char **envp) os_setup_post(); - resume_all_vcpus(); main_loop(); bdrv_close_all(); pause_all_vcpus(); res_free(); +#ifdef CONFIG_TPM + tpm_cleanup(); +#endif return 0; }