#include <sys/select.h>
#ifdef CONFIG_BSD
#include <sys/stat.h>
-#if defined(__FreeBSD__) || defined(__DragonFly__)
+#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
#include <libutil.h>
#else
#include <util.h>
#endif
-#elif defined (__GLIBC__) && defined (__FreeBSD_kernel__)
-#include <freebsd/stdlib.h>
#else
#ifdef __linux__
#include <pty.h>
#include "hw/loader.h"
#include "bt-host.h"
#include "net.h"
+#include "net/slirp.h"
#include "monitor.h"
#include "console.h"
#include "sysemu.h"
#include "qemu-char.h"
#include "cache-utils.h"
#include "block.h"
+#include "block_int.h"
+#include "block-migration.h"
#include "dma.h"
#include "audio/audio.h"
#include "migration.h"
#include "balloon.h"
#include "qemu-option.h"
#include "qemu-config.h"
+#include "qemu-objects.h"
#include "disas.h"
#define DEFAULT_RAM_SIZE 128
-/* Maximum number of monitor devices */
-#define MAX_MONITOR_DEVICES 10
+#define MAX_VIRTIO_CONSOLES 1
static const char *data_dir;
const char *bios_name = NULL;
static int rtc_utc = 1;
static int rtc_date_offset = -1; /* -1 means no change */
QEMUClock *rtc_clock;
-int vga_interface_type = VGA_CIRRUS;
+int vga_interface_type = VGA_NONE;
#ifdef TARGET_SPARC
int graphic_width = 1024;
int graphic_height = 768;
static QEMUBootSetHandler *boot_set_handler;
static void *boot_set_opaque;
+static int default_serial = 1;
+static int default_parallel = 1;
+static int default_virtcon = 1;
+static int default_monitor = 1;
+static int default_vga = 1;
+static int default_floppy = 1;
+static int default_cdrom = 1;
+static int default_sdcard = 1;
+
+static struct {
+ const char *driver;
+ int *flag;
+} default_list[] = {
+ { .driver = "isa-serial", .flag = &default_serial },
+ { .driver = "isa-parallel", .flag = &default_parallel },
+ { .driver = "isa-fdc", .flag = &default_floppy },
+ { .driver = "ide-drive", .flag = &default_cdrom },
+ { .driver = "virtio-serial-pci", .flag = &default_virtcon },
+ { .driver = "virtio-serial-s390", .flag = &default_virtcon },
+ { .driver = "virtio-serial", .flag = &default_virtcon },
+ { .driver = "VGA", .flag = &default_vga },
+ { .driver = "cirrus-vga", .flag = &default_vga },
+ { .driver = "vmware-svga", .flag = &default_vga },
+};
+
+static int default_driver_check(QemuOpts *opts, void *opaque)
+{
+ const char *driver = qemu_opt_get(opts, "driver");
+ int i;
+
+ if (!driver)
+ return 0;
+ for (i = 0; i < ARRAY_SIZE(default_list); i++) {
+ if (strcmp(default_list[i].driver, driver) != 0)
+ continue;
+ *(default_list[i].flag) = 0;
+ }
+ return 0;
+}
+
/***********************************************************/
/* x86 ISA bus support */
qemu_balloon_event_opaque = opaque;
}
-void qemu_balloon(ram_addr_t target)
-{
- if (qemu_balloon_event)
- qemu_balloon_event(qemu_balloon_event_opaque, target);
-}
-
-ram_addr_t qemu_balloon_status(void)
-{
- if (qemu_balloon_event)
- return qemu_balloon_event(qemu_balloon_event_opaque, 0);
- return 0;
-}
-
-/***********************************************************/
-/* keyboard/mouse */
-
-static QEMUPutKBDEvent *qemu_put_kbd_event;
-static void *qemu_put_kbd_event_opaque;
-static QEMUPutMouseEntry *qemu_put_mouse_event_head;
-static QEMUPutMouseEntry *qemu_put_mouse_event_current;
-
-void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
-{
- qemu_put_kbd_event_opaque = opaque;
- qemu_put_kbd_event = func;
-}
-
-QEMUPutMouseEntry *qemu_add_mouse_event_handler(QEMUPutMouseEvent *func,
- void *opaque, int absolute,
- const char *name)
-{
- QEMUPutMouseEntry *s, *cursor;
-
- s = qemu_mallocz(sizeof(QEMUPutMouseEntry));
-
- s->qemu_put_mouse_event = func;
- s->qemu_put_mouse_event_opaque = opaque;
- s->qemu_put_mouse_event_absolute = absolute;
- s->qemu_put_mouse_event_name = qemu_strdup(name);
- s->next = NULL;
-
- if (!qemu_put_mouse_event_head) {
- qemu_put_mouse_event_head = qemu_put_mouse_event_current = s;
- return s;
- }
-
- cursor = qemu_put_mouse_event_head;
- while (cursor->next != NULL)
- cursor = cursor->next;
-
- cursor->next = s;
- qemu_put_mouse_event_current = s;
-
- return s;
-}
-
-void qemu_remove_mouse_event_handler(QEMUPutMouseEntry *entry)
+int qemu_balloon(ram_addr_t target, MonitorCompletion cb, void *opaque)
{
- QEMUPutMouseEntry *prev = NULL, *cursor;
-
- if (!qemu_put_mouse_event_head || entry == NULL)
- return;
-
- cursor = qemu_put_mouse_event_head;
- while (cursor != NULL && cursor != entry) {
- prev = cursor;
- cursor = cursor->next;
- }
-
- if (cursor == NULL) // does not exist or list empty
- return;
- else if (prev == NULL) { // entry is head
- qemu_put_mouse_event_head = cursor->next;
- if (qemu_put_mouse_event_current == entry)
- qemu_put_mouse_event_current = cursor->next;
- qemu_free(entry->qemu_put_mouse_event_name);
- qemu_free(entry);
- return;
- }
-
- prev->next = entry->next;
-
- if (qemu_put_mouse_event_current == entry)
- qemu_put_mouse_event_current = prev;
-
- qemu_free(entry->qemu_put_mouse_event_name);
- qemu_free(entry);
-}
-
-void kbd_put_keycode(int keycode)
-{
- if (qemu_put_kbd_event) {
- qemu_put_kbd_event(qemu_put_kbd_event_opaque, keycode);
- }
-}
-
-void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
-{
- QEMUPutMouseEvent *mouse_event;
- void *mouse_event_opaque;
- int width;
-
- if (!qemu_put_mouse_event_current) {
- return;
- }
-
- mouse_event =
- qemu_put_mouse_event_current->qemu_put_mouse_event;
- mouse_event_opaque =
- qemu_put_mouse_event_current->qemu_put_mouse_event_opaque;
-
- if (mouse_event) {
- if (graphic_rotate) {
- if (qemu_put_mouse_event_current->qemu_put_mouse_event_absolute)
- width = 0x7fff;
- else
- width = graphic_width - 1;
- mouse_event(mouse_event_opaque,
- width - dy, dx, dz, buttons_state);
- } else
- mouse_event(mouse_event_opaque,
- dx, dy, dz, buttons_state);
+ if (qemu_balloon_event) {
+ qemu_balloon_event(qemu_balloon_event_opaque, target, cb, opaque);
+ return 1;
+ } else {
+ return 0;
}
}
-int kbd_mouse_is_absolute(void)
+int qemu_balloon_status(MonitorCompletion cb, void *opaque)
{
- if (!qemu_put_mouse_event_current)
+ if (qemu_balloon_event) {
+ qemu_balloon_event(qemu_balloon_event_opaque, 0, cb, opaque);
+ return 1;
+ } else {
return 0;
-
- return qemu_put_mouse_event_current->qemu_put_mouse_event_absolute;
-}
-
-void do_info_mice(Monitor *mon)
-{
- QEMUPutMouseEntry *cursor;
- int index = 0;
-
- if (!qemu_put_mouse_event_head) {
- monitor_printf(mon, "No mouse devices connected\n");
- return;
- }
-
- monitor_printf(mon, "Mouse devices available:\n");
- cursor = qemu_put_mouse_event_head;
- while (cursor != NULL) {
- monitor_printf(mon, "%c Mouse #%d: %s\n",
- (cursor == qemu_put_mouse_event_current ? '*' : ' '),
- index, cursor->qemu_put_mouse_event_name);
- index++;
- cursor = cursor->next;
}
}
-void do_mouse_set(Monitor *mon, const QDict *qdict)
-{
- QEMUPutMouseEntry *cursor;
- int i = 0;
- int index = qdict_get_int(qdict, "index");
-
- if (!qemu_put_mouse_event_head) {
- monitor_printf(mon, "No mouse devices connected\n");
- return;
- }
- cursor = qemu_put_mouse_event_head;
- while (cursor != NULL && index != i) {
- i++;
- cursor = cursor->next;
- }
-
- if (cursor != NULL)
- qemu_put_mouse_event_current = cursor;
- else
- monitor_printf(mon, "Mouse at given index not found\n");
-}
+/***********************************************************/
+/* real time host monotonic timer */
/* compute with 96 bit intermediate result: (a*b)/c */
uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
return res.ll;
}
-/***********************************************************/
-/* real time host monotonic timer */
-
static int64_t get_clock_realtime(void)
{
struct timeval tv;
{
use_rt_clock = 0;
#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD_version >= 500000) \
- || defined(__DragonFly__)
+ || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
{
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
static int64_t get_clock(void)
{
#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD_version >= 500000) \
- || defined(__DragonFly__)
+ || defined(__DragonFly__) || defined(__FreeBSD_kernel__)
if (use_rt_clock) {
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
struct hpet_info info;
int r, fd;
- fd = open("/dev/hpet", O_RDONLY);
+ fd = qemu_open("/dev/hpet", O_RDONLY);
if (fd < 0)
return -1;
int rtc_fd;
unsigned long current_rtc_freq = 0;
- TFR(rtc_fd = open("/dev/rtc", O_RDONLY));
+ TFR(rtc_fd = qemu_open("/dev/rtc", O_RDONLY));
if (rtc_fd < 0)
return -1;
ioctl(rtc_fd, RTC_IRQP_READ, ¤t_rtc_freq);
return "\0";
}
-BlockInterfaceErrorAction drive_get_onerror(BlockDriverState *bdrv)
+BlockInterfaceErrorAction drive_get_on_error(
+ BlockDriverState *bdrv, int is_read)
{
DriveInfo *dinfo;
QTAILQ_FOREACH(dinfo, &drives, next) {
if (dinfo->bdrv == bdrv)
- return dinfo->onerror;
+ return is_read ? dinfo->on_read_error : dinfo->on_write_error;
}
- return BLOCK_ERR_STOP_ENOSPC;
+ return is_read ? BLOCK_ERR_REPORT : BLOCK_ERR_STOP_ENOSPC;
}
static void bdrv_format_print(void *opaque, const char *name)
qemu_free(dinfo);
}
+static int parse_block_error_action(const char *buf, int is_read)
+{
+ if (!strcmp(buf, "ignore")) {
+ return BLOCK_ERR_IGNORE;
+ } else if (!is_read && !strcmp(buf, "enospc")) {
+ return BLOCK_ERR_STOP_ENOSPC;
+ } else if (!strcmp(buf, "stop")) {
+ return BLOCK_ERR_STOP_ANY;
+ } else if (!strcmp(buf, "report")) {
+ return BLOCK_ERR_REPORT;
+ } else {
+ fprintf(stderr, "qemu: '%s' invalid %s error action\n",
+ buf, is_read ? "read" : "write");
+ return -1;
+ }
+}
+
DriveInfo *drive_init(QemuOpts *opts, void *opaque,
int *fatal_error)
{
int cache;
int aio = 0;
int ro = 0;
- int bdrv_flags, onerror;
+ int bdrv_flags;
+ int on_read_error, on_write_error;
const char *devaddr;
DriveInfo *dinfo;
int snapshot = 0;
}
}
- onerror = BLOCK_ERR_STOP_ENOSPC;
+ on_write_error = BLOCK_ERR_STOP_ENOSPC;
if ((buf = qemu_opt_get(opts, "werror")) != NULL) {
if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO) {
fprintf(stderr, "werror is no supported by this format\n");
return NULL;
}
- if (!strcmp(buf, "ignore"))
- onerror = BLOCK_ERR_IGNORE;
- else if (!strcmp(buf, "enospc"))
- onerror = BLOCK_ERR_STOP_ENOSPC;
- else if (!strcmp(buf, "stop"))
- onerror = BLOCK_ERR_STOP_ANY;
- else if (!strcmp(buf, "report"))
- onerror = BLOCK_ERR_REPORT;
- else {
- fprintf(stderr, "qemu: '%s' invalid write error action\n", buf);
+
+ on_write_error = parse_block_error_action(buf, 0);
+ if (on_write_error < 0) {
+ return NULL;
+ }
+ }
+
+ on_read_error = BLOCK_ERR_REPORT;
+ if ((buf = qemu_opt_get(opts, "rerror")) != NULL) {
+ if (type != IF_IDE && type != IF_VIRTIO) {
+ fprintf(stderr, "rerror is no supported by this format\n");
+ return NULL;
+ }
+
+ on_read_error = parse_block_error_action(buf, 1);
+ if (on_read_error < 0) {
return NULL;
}
}
dinfo->type = type;
dinfo->bus = bus_id;
dinfo->unit = unit_id;
- dinfo->onerror = onerror;
+ dinfo->on_read_error = on_read_error;
+ dinfo->on_write_error = on_write_error;
dinfo->opts = opts;
if (serial)
strncpy(dinfo->serial, serial, sizeof(serial));
}
if (ro == 1) {
- if (type == IF_IDE) {
- fprintf(stderr, "qemu: readonly flag not supported for drive with ide interface\n");
+ if (type != IF_SCSI && type != IF_VIRTIO && type != IF_FLOPPY) {
+ fprintf(stderr, "qemu: readonly flag not supported for drive with this interface\n");
return NULL;
}
- (void)bdrv_set_read_only(dinfo->bdrv, 1);
}
+ /*
+ * cdrom is read-only. Set it now, after above interface checking
+ * since readonly attribute not explicitly required, so no error.
+ */
+ if (media == MEDIA_CDROM) {
+ ro = 1;
+ }
+ bdrv_flags |= ro ? 0 : BDRV_O_RDWR;
if (bdrv_open2(dinfo->bdrv, file, bdrv_flags, drv) < 0) {
fprintf(stderr, "qemu: could not open disk image %s: %s\n",
threads = threads > 0 ? threads : 1;
if (smp == 0) {
smp = cores * threads * sockets;
- } else {
- sockets = smp / (cores * threads);
}
} else {
if (cores == 0) {
threads = threads > 0 ? threads : 1;
cores = smp / (sockets * threads);
} else {
- if (sockets == 0) {
- sockets = smp / (cores * threads);
- } else {
+ if (sockets) {
threads = smp / (cores * sockets);
}
}
/* the other ones */
if (strstart(devname, "host:", &p)) {
dev = usb_host_device_open(p);
- } else if (strstart(devname, "net:", &p)) {
- QemuOpts *opts;
- int idx;
-
- opts = qemu_opts_parse(&qemu_net_opts, p, NULL);
- if (!opts) {
- return -1;
- }
-
- qemu_opt_set(opts, "type", "nic");
- qemu_opt_set(opts, "model", "usb");
-
- idx = net_client_init(NULL, opts, 0);
- if (idx == -1) {
- return -1;
- }
-
- dev = usb_net_init(&nd_table[idx]);
} else if (!strcmp(devname, "bt") || strstart(devname, "bt:", &p)) {
dev = usb_bt_init(devname[2] ? hci_init(p) :
bt_new_hci(qemu_find_bt_vlan(0)));
static int usb_parse(const char *cmdline)
{
- return usb_device_add(cmdline, 0);
+ int r;
+ r = usb_device_add(cmdline, 0);
+ if (r < 0) {
+ fprintf(stderr, "qemu: could not add USB device '%s'\n", cmdline);
+ }
+ return r;
}
void do_usb_add(Monitor *mon, const QDict *qdict)
{
- usb_device_add(qdict_get_str(qdict, "devname"), 1);
+ const char *devname = qdict_get_str(qdict, "devname");
+ if (usb_device_add(devname, 1) < 0) {
+ qemu_error("could not add USB device '%s'\n", devname);
+ }
}
void do_usb_del(Monitor *mon, const QDict *qdict)
{
- usb_device_del(qdict_get_str(qdict, "devname"));
+ const char *devname = qdict_get_str(qdict, "devname");
+ if (usb_device_del(devname) < 0) {
+ qemu_error("could not delete USB device '%s'\n", devname);
+ }
}
/***********************************************************/
return found;
}
-static uint64_t bytes_transferred = 0;
+static uint64_t bytes_transferred;
static ram_addr_t ram_save_remaining(void)
{
return last_ram_offset;
}
-static int ram_save_live(QEMUFile *f, int stage, void *opaque)
+static int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque)
{
ram_addr_t addr;
uint64_t bytes_transferred_last;
double bwidth = 0;
uint64_t expected_time = 0;
+ if (stage < 0) {
+ cpu_physical_memory_set_dirty_tracking(0);
+ return 0;
+ }
+
if (cpu_physical_sync_dirty_bitmap(0, TARGET_PHYS_ADDR_MAX) != 0) {
qemu_file_set_error(f);
return 0;
}
if (stage == 1) {
+ bytes_transferred = 0;
+
/* Make sure all dirty bits are set */
for (addr = 0; addr < last_ram_offset; addr += TARGET_PAGE_SIZE) {
if (!cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG))
bwidth = 0.000001;
/* try transferring iterative blocks of memory */
-
if (stage == 3) {
-
/* flush all remaining blocks regardless of rate limiting */
while (ram_save_block(f) != 0) {
bytes_transferred += TARGET_PAGE_SIZE;
madvise(qemu_get_ram_ptr(addr), TARGET_PAGE_SIZE, MADV_DONTNEED);
}
#endif
- } else if (flags & RAM_SAVE_FLAG_PAGE)
+ } else if (flags & RAM_SAVE_FLAG_PAGE) {
qemu_get_buffer(f, qemu_get_ram_ptr(addr), TARGET_PAGE_SIZE);
+ }
+ if (qemu_file_has_error(f)) {
+ return -EIO;
+ }
} while (!(flags & RAM_SAVE_FLAG_EOS));
return 0;
static void qemu_event_increment(void)
{
static const char byte = 0;
+ ssize_t ret;
if (io_thread_fd == -1)
return;
- write(io_thread_fd, &byte, sizeof(byte));
+ ret = write(io_thread_fd, &byte, sizeof(byte));
+ if (ret < 0 && (errno != EINTR && errno != EAGAIN)) {
+ fprintf(stderr, "qemu_event_increment: write() filed: %s\n",
+ strerror(errno));
+ exit (1);
+ }
}
static void qemu_event_read(void *opaque)
int err;
int fds[2];
- err = pipe(fds);
+ err = qemu_pipe(fds);
if (err == -1)
return -errno;
{
CPUState *env = _env;
- if (kvm_enabled())
- kvm_init_vcpu(env);
env->nr_cores = smp_cores;
env->nr_threads = smp_threads;
+ if (kvm_enabled())
+ kvm_init_vcpu(env);
return;
}
{
CPUState *env = _env;
+ env->nr_cores = smp_cores;
+ env->nr_threads = smp_threads;
if (kvm_enabled())
kvm_start_vcpu(env);
else
tcg_init_vcpu(env);
- env->nr_cores = smp_cores;
- env->nr_threads = smp_threads;
}
void qemu_notify_event(void)
#endif
} while (vm_can_run());
- if (qemu_debug_requested())
+ if (qemu_debug_requested()) {
+ monitor_protocol_event(QEVENT_DEBUG, NULL);
vm_stop(EXCP_DEBUG);
+ }
if (qemu_shutdown_requested()) {
+ monitor_protocol_event(QEVENT_SHUTDOWN, NULL);
if (no_shutdown) {
vm_stop(0);
no_shutdown = 0;
break;
}
if (qemu_reset_requested()) {
+ monitor_protocol_event(QEVENT_RESET, NULL);
pause_all_vcpus();
qemu_system_reset();
resume_all_vcpus();
}
if (qemu_powerdown_requested()) {
+ monitor_protocol_event(QEVENT_POWERDOWN, NULL);
qemu_irq_raise(qemu_system_powerdown);
}
- if ((r = qemu_vmstop_requested()))
+ if ((r = qemu_vmstop_requested())) {
+ monitor_protocol_event(QEVENT_STOP, NULL);
vm_stop(r);
+ }
}
pause_all_vcpus();
}
{
const char *opts;
+ default_vga = 0;
vga_interface_type = VGA_NONE;
if (strstart(p, "std", &opts)) {
vga_interface_type = VGA_STD;
return 0;
}
+static int chardev_init_func(QemuOpts *opts, void *opaque)
+{
+ CharDriverState *chr;
+
+ chr = qemu_chr_open_opts(opts, NULL);
+ if (!chr)
+ return -1;
+ return 0;
+}
+
+static int mon_init_func(QemuOpts *opts, void *opaque)
+{
+ CharDriverState *chr;
+ const char *chardev;
+ const char *mode;
+ int flags;
+
+ mode = qemu_opt_get(opts, "mode");
+ if (mode == NULL) {
+ mode = "readline";
+ }
+ if (strcmp(mode, "readline") == 0) {
+ flags = MONITOR_USE_READLINE;
+ } else if (strcmp(mode, "control") == 0) {
+ flags = MONITOR_USE_CONTROL;
+ } else {
+ fprintf(stderr, "unknown monitor mode \"%s\"\n", mode);
+ exit(1);
+ }
+
+ if (qemu_opt_get_bool(opts, "default", 0))
+ flags |= MONITOR_IS_DEFAULT;
+
+ chardev = qemu_opt_get(opts, "chardev");
+ chr = qemu_chr_find(chardev);
+ if (chr == NULL) {
+ fprintf(stderr, "chardev \"%s\" not found\n", chardev);
+ exit(1);
+ }
+
+ monitor_init(chr, flags);
+ return 0;
+}
+
+static void monitor_parse(const char *optarg, const char *mode)
+{
+ static int monitor_device_index = 0;
+ QemuOpts *opts;
+ const char *p;
+ char label[32];
+ int def = 0;
+
+ if (strstart(optarg, "chardev:", &p)) {
+ snprintf(label, sizeof(label), "%s", p);
+ } else {
+ if (monitor_device_index) {
+ snprintf(label, sizeof(label), "monitor%d",
+ monitor_device_index);
+ } else {
+ snprintf(label, sizeof(label), "monitor");
+ def = 1;
+ }
+ opts = qemu_chr_parse_compat(label, optarg);
+ if (!opts) {
+ fprintf(stderr, "parse error: %s\n", optarg);
+ exit(1);
+ }
+ }
+
+ opts = qemu_opts_create(&qemu_mon_opts, label, 1);
+ if (!opts) {
+ fprintf(stderr, "duplicate chardev: %s\n", label);
+ exit(1);
+ }
+ qemu_opt_set(opts, "mode", mode);
+ qemu_opt_set(opts, "chardev", label);
+ if (def)
+ qemu_opt_set(opts, "default", "on");
+ monitor_device_index++;
+}
+
struct device_config {
enum {
- DEV_USB, /* -usbdevice */
- DEV_BT, /* -bt */
+ DEV_USB, /* -usbdevice */
+ DEV_BT, /* -bt */
+ DEV_SERIAL, /* -serial */
+ DEV_PARALLEL, /* -parallel */
+ DEV_VIRTCON, /* -virtioconsole */
+ DEV_DEBUGCON, /* -debugcon */
} type;
const char *cmdline;
QTAILQ_ENTRY(device_config) next;
return 0;
}
+static int serial_parse(const char *devname)
+{
+ static int index = 0;
+ char label[32];
+
+ if (strcmp(devname, "none") == 0)
+ return 0;
+ if (index == MAX_SERIAL_PORTS) {
+ fprintf(stderr, "qemu: too many serial ports\n");
+ exit(1);
+ }
+ snprintf(label, sizeof(label), "serial%d", index);
+ serial_hds[index] = qemu_chr_open(label, devname, NULL);
+ if (!serial_hds[index]) {
+ fprintf(stderr, "qemu: could not open serial device '%s': %s\n",
+ devname, strerror(errno));
+ return -1;
+ }
+ index++;
+ return 0;
+}
+
+static int parallel_parse(const char *devname)
+{
+ static int index = 0;
+ char label[32];
+
+ if (strcmp(devname, "none") == 0)
+ return 0;
+ if (index == MAX_PARALLEL_PORTS) {
+ fprintf(stderr, "qemu: too many parallel ports\n");
+ exit(1);
+ }
+ snprintf(label, sizeof(label), "parallel%d", index);
+ parallel_hds[index] = qemu_chr_open(label, devname, NULL);
+ if (!parallel_hds[index]) {
+ fprintf(stderr, "qemu: could not open parallel device '%s': %s\n",
+ devname, strerror(errno));
+ return -1;
+ }
+ index++;
+ return 0;
+}
+
+static int virtcon_parse(const char *devname)
+{
+ static int index = 0;
+ char label[32];
+ QemuOpts *bus_opts, *dev_opts;
+
+ if (strcmp(devname, "none") == 0)
+ return 0;
+ if (index == MAX_VIRTIO_CONSOLES) {
+ fprintf(stderr, "qemu: too many virtio consoles\n");
+ exit(1);
+ }
+
+ bus_opts = qemu_opts_create(&qemu_device_opts, NULL, 0);
+ qemu_opt_set(bus_opts, "driver", "virtio-serial");
+
+ dev_opts = qemu_opts_create(&qemu_device_opts, NULL, 0);
+ qemu_opt_set(dev_opts, "driver", "virtconsole");
+
+ snprintf(label, sizeof(label), "virtcon%d", index);
+ virtcon_hds[index] = qemu_chr_open(label, devname, NULL);
+ if (!virtcon_hds[index]) {
+ fprintf(stderr, "qemu: could not open virtio console '%s': %s\n",
+ devname, strerror(errno));
+ return -1;
+ }
+ qemu_opt_set(dev_opts, "chardev", label);
+
+ index++;
+ return 0;
+}
+
+static int debugcon_parse(const char *devname)
+{
+ QemuOpts *opts;
+
+ if (!qemu_chr_open("debugcon", devname, NULL)) {
+ exit(1);
+ }
+ opts = qemu_opts_create(&qemu_device_opts, "debugcon", 1);
+ if (!opts) {
+ fprintf(stderr, "qemu: already have a debugcon device\n");
+ exit(1);
+ }
+ qemu_opt_set(opts, "driver", "isa-debugcon");
+ qemu_opt_set(opts, "chardev", "debugcon");
+ return 0;
+}
+
+static const QEMUOption *lookup_opt(int argc, char **argv,
+ const char **poptarg, int *poptind)
+{
+ const QEMUOption *popt;
+ int optind = *poptind;
+ char *r = argv[optind];
+ const char *optarg;
+
+ optind++;
+ /* Treat --foo the same as -foo. */
+ if (r[1] == '-')
+ r++;
+ popt = qemu_options;
+ for(;;) {
+ if (!popt->name) {
+ fprintf(stderr, "%s: invalid option -- '%s'\n",
+ argv[0], r);
+ exit(1);
+ }
+ if (!strcmp(popt->name, r + 1))
+ break;
+ popt++;
+ }
+ if (popt->flags & HAS_ARG) {
+ if (optind >= argc) {
+ fprintf(stderr, "%s: option '%s' requires an argument\n",
+ argv[0], r);
+ exit(1);
+ }
+ optarg = argv[optind++];
+ } else {
+ optarg = NULL;
+ }
+
+ *poptarg = optarg;
+ *poptind = optind;
+
+ return popt;
+}
+
int main(int argc, char **argv, char **envp)
{
const char *gdbstub_dev = NULL;
int cyls, heads, secs, translation;
QemuOpts *hda_opts = NULL, *opts;
int optind;
- const char *r, *optarg;
- CharDriverState *monitor_hds[MAX_MONITOR_DEVICES];
- const char *monitor_devices[MAX_MONITOR_DEVICES];
- int monitor_device_index;
- const char *serial_devices[MAX_SERIAL_PORTS];
- int serial_device_index;
- const char *parallel_devices[MAX_PARALLEL_PORTS];
- int parallel_device_index;
- const char *virtio_consoles[MAX_VIRTIO_CONSOLES];
- int virtio_console_index;
+ const char *optarg;
const char *loadvm = NULL;
QEMUMachine *machine;
const char *cpu_model;
#endif
CPUState *env;
int show_vnc_port = 0;
+ int defconfig = 1;
init_clocks();
cyls = heads = secs = 0;
translation = BIOS_ATA_TRANSLATION_AUTO;
- serial_devices[0] = "vc:80Cx24C";
- for(i = 1; i < MAX_SERIAL_PORTS; i++)
- serial_devices[i] = NULL;
- serial_device_index = 0;
-
- parallel_devices[0] = "vc:80Cx24C";
- for(i = 1; i < MAX_PARALLEL_PORTS; i++)
- parallel_devices[i] = NULL;
- parallel_device_index = 0;
-
- for(i = 0; i < MAX_VIRTIO_CONSOLES; i++)
- virtio_consoles[i] = NULL;
- virtio_console_index = 0;
-
- monitor_devices[0] = "vc:80Cx24C";
- for (i = 1; i < MAX_MONITOR_DEVICES; i++) {
- monitor_devices[i] = NULL;
- }
- monitor_device_index = 0;
-
for (i = 0; i < MAX_NODES; i++) {
node_mem[i] = 0;
node_cpumask[i] = 0;
tb_size = 0;
autostart= 1;
+ /* first pass of option parsing */
+ optind = 1;
+ while (optind < argc) {
+ if (argv[optind][0] != '-') {
+ /* disk image */
+ optind++;
+ continue;
+ } else {
+ const QEMUOption *popt;
+
+ popt = lookup_opt(argc, argv, &optarg, &optind);
+ switch (popt->index) {
+ case QEMU_OPTION_nodefconfig:
+ defconfig=0;
+ break;
+ }
+ }
+ }
+
+ if (defconfig) {
+ FILE *fp;
+ fp = fopen(CONFIG_QEMU_CONFDIR "/qemu.conf", "r");
+ if (fp) {
+ if (qemu_config_parse(fp) != 0) {
+ exit(1);
+ }
+ fclose(fp);
+ }
+
+ fp = fopen(CONFIG_QEMU_CONFDIR "/target-" TARGET_ARCH ".conf", "r");
+ if (fp) {
+ if (qemu_config_parse(fp) != 0) {
+ exit(1);
+ }
+ fclose(fp);
+ }
+ }
+
+ /* second pass of option parsing */
optind = 1;
for(;;) {
if (optind >= argc)
break;
- r = argv[optind];
- if (r[0] != '-') {
+ if (argv[optind][0] != '-') {
hda_opts = drive_add(argv[optind++], HD_ALIAS, 0);
} else {
const QEMUOption *popt;
- optind++;
- /* Treat --foo the same as -foo. */
- if (r[1] == '-')
- r++;
- popt = qemu_options;
- for(;;) {
- if (!popt->name) {
- fprintf(stderr, "%s: invalid option -- '%s'\n",
- argv[0], r);
- exit(1);
- }
- if (!strcmp(popt->name, r + 1))
- break;
- popt++;
- }
- if (popt->flags & HAS_ARG) {
- if (optind >= argc) {
- fprintf(stderr, "%s: option '%s' requires an argument\n",
- argv[0], r);
- exit(1);
- }
- optarg = argv[optind++];
- } else {
- optarg = NULL;
- }
-
+ popt = lookup_opt(argc, argv, &optarg, &optind);
switch(popt->index) {
case QEMU_OPTION_M:
machine = find_machine(optarg);
if (qemu_set_option(optarg) != 0)
exit(1);
break;
+ case QEMU_OPTION_global:
+ if (qemu_global_option(optarg) != 0)
+ exit(1);
+ break;
case QEMU_OPTION_mtdblock:
drive_add(optarg, MTD_ALIAS);
break;
case QEMU_OPTION_S:
autostart = 0;
break;
-#ifndef _WIN32
case QEMU_OPTION_k:
keyboard_layout = optarg;
break;
-#endif
case QEMU_OPTION_localtime:
rtc_utc = 0;
break;
break;
}
case QEMU_OPTION_monitor:
- if (monitor_device_index >= MAX_MONITOR_DEVICES) {
- fprintf(stderr, "qemu: too many monitor devices\n");
+ monitor_parse(optarg, "readline");
+ default_monitor = 0;
+ break;
+ case QEMU_OPTION_qmp:
+ monitor_parse(optarg, "control");
+ default_monitor = 0;
+ break;
+ case QEMU_OPTION_mon:
+ opts = qemu_opts_parse(&qemu_mon_opts, optarg, "chardev");
+ if (!opts) {
+ fprintf(stderr, "parse error: %s\n", optarg);
exit(1);
}
- monitor_devices[monitor_device_index] = optarg;
- monitor_device_index++;
+ default_monitor = 0;
break;
case QEMU_OPTION_chardev:
opts = qemu_opts_parse(&qemu_chardev_opts, optarg, "backend");
fprintf(stderr, "parse error: %s\n", optarg);
exit(1);
}
- if (qemu_chr_open_opts(opts, NULL) == NULL) {
- exit(1);
- }
break;
case QEMU_OPTION_serial:
- if (serial_device_index >= MAX_SERIAL_PORTS) {
- fprintf(stderr, "qemu: too many serial ports\n");
- exit(1);
- }
- serial_devices[serial_device_index] = optarg;
- serial_device_index++;
+ add_device_config(DEV_SERIAL, optarg);
+ default_serial = 0;
break;
case QEMU_OPTION_watchdog:
if (watchdog) {
}
break;
case QEMU_OPTION_virtiocon:
- if (virtio_console_index >= MAX_VIRTIO_CONSOLES) {
- fprintf(stderr, "qemu: too many virtio consoles\n");
- exit(1);
- }
- virtio_consoles[virtio_console_index] = optarg;
- virtio_console_index++;
+ add_device_config(DEV_VIRTCON, optarg);
+ default_virtcon = 0;
break;
case QEMU_OPTION_parallel:
- if (parallel_device_index >= MAX_PARALLEL_PORTS) {
- fprintf(stderr, "qemu: too many parallel ports\n");
- exit(1);
- }
- parallel_devices[parallel_device_index] = optarg;
- parallel_device_index++;
+ add_device_config(DEV_PARALLEL, optarg);
+ default_parallel = 0;
+ break;
+ case QEMU_OPTION_debugcon:
+ add_device_config(DEV_DEBUGCON, optarg);
break;
case QEMU_OPTION_loadvm:
loadvm = optarg;
case QEMU_OPTION_incoming:
incoming = optarg;
break;
+ case QEMU_OPTION_nodefaults:
+ default_serial = 0;
+ default_parallel = 0;
+ default_virtcon = 0;
+ default_monitor = 0;
+ default_vga = 0;
+ default_net = 0;
+ default_floppy = 0;
+ default_cdrom = 0;
+ default_sdcard = 0;
+ break;
#ifndef _WIN32
case QEMU_OPTION_chroot:
chroot_dir = optarg;
exit(1);
}
- if (display_type == DT_NOGRAPHIC) {
- if (serial_device_index == 0)
- serial_devices[0] = "stdio";
- if (parallel_device_index == 0)
- parallel_devices[0] = "null";
- if (strncmp(monitor_devices[0], "vc", 2) == 0) {
- monitor_devices[0] = "stdio";
- }
+ qemu_opts_foreach(&qemu_device_opts, default_driver_check, NULL, 0);
+ qemu_opts_foreach(&qemu_global_opts, default_driver_check, NULL, 0);
+
+ if (machine->no_serial) {
+ default_serial = 0;
+ }
+ if (machine->no_parallel) {
+ default_parallel = 0;
+ }
+ if (!machine->use_virtcon) {
+ default_virtcon = 0;
+ }
+ if (machine->no_vga) {
+ default_vga = 0;
+ }
+ if (machine->no_floppy) {
+ default_floppy = 0;
+ }
+ if (machine->no_cdrom) {
+ default_cdrom = 0;
}
+ if (machine->no_sdcard) {
+ default_sdcard = 0;
+ }
+
+ if (display_type == DT_NOGRAPHIC) {
+ if (default_parallel)
+ add_device_config(DEV_PARALLEL, "null");
+ if (default_serial && default_monitor) {
+ add_device_config(DEV_SERIAL, "mon:stdio");
+ } else if (default_virtcon && default_monitor) {
+ add_device_config(DEV_VIRTCON, "mon:stdio");
+ } else {
+ if (default_serial)
+ add_device_config(DEV_SERIAL, "stdio");
+ if (default_virtcon)
+ add_device_config(DEV_VIRTCON, "stdio");
+ if (default_monitor)
+ monitor_parse("stdio", "readline");
+ }
+ } else {
+ if (default_serial)
+ add_device_config(DEV_SERIAL, "vc:80Cx24C");
+ if (default_parallel)
+ add_device_config(DEV_PARALLEL, "vc:80Cx24C");
+ if (default_monitor)
+ monitor_parse("vc:80Cx24C", "readline");
+ if (default_virtcon)
+ add_device_config(DEV_VIRTCON, "vc:80Cx24C");
+ }
+ if (default_vga)
+ vga_interface_type = VGA_CIRRUS;
+
+ if (qemu_opts_foreach(&qemu_chardev_opts, chardev_init_func, NULL, 1) != 0)
+ exit(1);
#ifndef _WIN32
if (daemonize) {
} else if (pid < 0)
exit(1);
+ close(fds[0]);
+ qemu_set_cloexec(fds[1]);
+
setsid();
pid = fork();
signal(SIGTTOU, SIG_IGN);
signal(SIGTTIN, SIG_IGN);
}
+#endif
if (pid_file && qemu_create_pidfile(pid_file) != 0) {
+#ifndef _WIN32
if (daemonize) {
uint8_t status = 1;
- write(fds[1], &status, 1);
+ if (write(fds[1], &status, 1) != 1) {
+ perror("daemonize. Writing to pipe\n");
+ }
} else
+#endif
fprintf(stderr, "Could not acquire pid file: %s\n", strerror(errno));
exit(1);
}
-#endif
if (kvm_enabled()) {
int ret;
bdrv_init_with_whitelist();
- /* we always create the cdrom drive, even if no disk is there */
- drive_add(NULL, CDROM_ALIAS);
+ blk_mig_init();
- /* we always create at least one floppy */
- drive_add(NULL, FD_ALIAS, 0);
+ if (default_cdrom) {
+ /* we always create the cdrom drive, even if no disk is there */
+ drive_add(NULL, CDROM_ALIAS);
+ }
- /* we always create one sd slot, even if no card is in it */
- drive_add(NULL, SD_ALIAS);
+ if (default_floppy) {
+ /* we always create at least one floppy */
+ drive_add(NULL, FD_ALIAS, 0);
+ }
+
+ if (default_sdcard) {
+ /* we always create one sd slot, even if no card is in it */
+ drive_add(NULL, SD_ALIAS);
+ }
/* open the virtual block devices */
if (snapshot)
exit(1);
vmstate_register(0, &vmstate_timers ,&timers_state);
- register_savevm_live("ram", 0, 3, ram_save_live, NULL, ram_load, NULL);
-
- /* Maintain compatibility with multiple stdio monitors */
- if (!strcmp(monitor_devices[0],"stdio")) {
- for (i = 0; i < MAX_SERIAL_PORTS; i++) {
- const char *devname = serial_devices[i];
- if (devname && !strcmp(devname,"mon:stdio")) {
- monitor_devices[0] = NULL;
- break;
- } else if (devname && !strcmp(devname,"stdio")) {
- monitor_devices[0] = NULL;
- serial_devices[i] = "mon:stdio";
- break;
- }
- }
- }
+ register_savevm_live("ram", 0, 3, NULL, ram_save_live, NULL,
+ ram_load, NULL);
if (nb_numa_nodes > 0) {
int i;
}
}
- for (i = 0; i < MAX_MONITOR_DEVICES; i++) {
- const char *devname = monitor_devices[i];
- if (devname && strcmp(devname, "none")) {
- char label[32];
- if (i == 0) {
- snprintf(label, sizeof(label), "monitor");
- } else {
- snprintf(label, sizeof(label), "monitor%d", i);
- }
- monitor_hds[i] = qemu_chr_open(label, devname, NULL);
- if (!monitor_hds[i]) {
- fprintf(stderr, "qemu: could not open monitor device '%s'\n",
- devname);
- exit(1);
- }
- }
- }
-
- for(i = 0; i < MAX_SERIAL_PORTS; i++) {
- const char *devname = serial_devices[i];
- if (devname && strcmp(devname, "none")) {
- char label[32];
- snprintf(label, sizeof(label), "serial%d", i);
- serial_hds[i] = qemu_chr_open(label, devname, NULL);
- if (!serial_hds[i]) {
- fprintf(stderr, "qemu: could not open serial device '%s': %s\n",
- devname, strerror(errno));
- exit(1);
- }
- }
- }
-
- for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
- const char *devname = parallel_devices[i];
- if (devname && strcmp(devname, "none")) {
- char label[32];
- snprintf(label, sizeof(label), "parallel%d", i);
- parallel_hds[i] = qemu_chr_open(label, devname, NULL);
- if (!parallel_hds[i]) {
- fprintf(stderr, "qemu: could not open parallel device '%s': %s\n",
- devname, strerror(errno));
- exit(1);
- }
- }
- }
-
- for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) {
- const char *devname = virtio_consoles[i];
- if (devname && strcmp(devname, "none")) {
- char label[32];
- snprintf(label, sizeof(label), "virtcon%d", i);
- virtcon_hds[i] = qemu_chr_open(label, devname, NULL);
- if (!virtcon_hds[i]) {
- fprintf(stderr, "qemu: could not open virtio console '%s': %s\n",
- devname, strerror(errno));
- exit(1);
- }
- }
- }
+ if (foreach_device_config(DEV_SERIAL, serial_parse) < 0)
+ exit(1);
+ if (foreach_device_config(DEV_PARALLEL, parallel_parse) < 0)
+ exit(1);
+ if (foreach_device_config(DEV_VIRTCON, virtcon_parse) < 0)
+ exit(1);
+ if (foreach_device_config(DEV_DEBUGCON, debugcon_parse) < 0)
+ exit(1);
module_call_init(MODULE_INIT_DEVICE);
}
if (machine->compat_props) {
- qdev_prop_register_compat(machine->compat_props);
+ qdev_prop_register_global_list(machine->compat_props);
}
+ qemu_add_globals();
+
machine->init(ram_size, boot_devices,
kernel_filename, kernel_cmdline, initrd_filename, cpu_model);
}
text_consoles_set_display(display_state);
- qemu_chr_initial_reset();
-
- for (i = 0; i < MAX_MONITOR_DEVICES; i++) {
- if (monitor_devices[i] && monitor_hds[i]) {
- monitor_init(monitor_hds[i],
- MONITOR_USE_READLINE |
- ((i == 0) ? MONITOR_IS_DEFAULT : 0));
- }
- }
-
- for(i = 0; i < MAX_SERIAL_PORTS; i++) {
- const char *devname = serial_devices[i];
- if (devname && strcmp(devname, "none")) {
- if (strstart(devname, "vc", 0))
- qemu_chr_printf(serial_hds[i], "serial%d console\r\n", i);
- }
- }
-
- for(i = 0; i < MAX_PARALLEL_PORTS; i++) {
- const char *devname = parallel_devices[i];
- if (devname && strcmp(devname, "none")) {
- if (strstart(devname, "vc", 0))
- qemu_chr_printf(parallel_hds[i], "parallel%d console\r\n", i);
- }
- }
- for(i = 0; i < MAX_VIRTIO_CONSOLES; i++) {
- const char *devname = virtio_consoles[i];
- if (virtcon_hds[i] && devname) {
- if (strstart(devname, "vc", 0))
- qemu_chr_printf(virtcon_hds[i], "virtio console%d\r\n", i);
- }
- }
+ if (qemu_opts_foreach(&qemu_mon_opts, mon_init_func, NULL, 1) != 0)
+ exit(1);
if (gdbstub_dev && gdbserver_start(gdbstub_dev) < 0) {
fprintf(stderr, "qemu: could not open gdbserver on device '%s'\n",
qdev_machine_creation_done();
- rom_load_all();
+ if (rom_load_all() != 0) {
+ fprintf(stderr, "rom loading failed\n");
+ exit(1);
+ }
qemu_system_reset();
if (loadvm) {
if (len != 1)
exit(1);
- chdir("/");
- TFR(fd = open("/dev/null", O_RDWR));
+ if (chdir("/")) {
+ perror("not able to chdir to /");
+ exit(1);
+ }
+ TFR(fd = qemu_open("/dev/null", O_RDWR));
if (fd == -1)
exit(1);
}
fprintf(stderr, "chroot failed\n");
exit(1);
}
- chdir("/");
+ if (chdir("/")) {
+ perror("not able to chdir to /");
+ exit(1);
+ }
}
if (run_as) {