#define DEFAULT_RAM_SIZE 128
+#define MAX_VIRTIO_CONSOLES 1
+
static const char *data_dir;
const char *bios_name = NULL;
/* Note: drives_table[MAX_DRIVES] is a dummy block driver if none available
struct drivelist drives = QTAILQ_HEAD_INITIALIZER(drives);
struct driveoptlist driveopts = QTAILQ_HEAD_INITIALIZER(driveopts);
enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB;
-static DisplayState *display_state;
DisplayType display_type = DT_DEFAULT;
const char* keyboard_layout = NULL;
ram_addr_t ram_size;
{ .driver = "isa-parallel", .flag = &default_parallel },
{ .driver = "isa-fdc", .flag = &default_floppy },
{ .driver = "ide-drive", .flag = &default_cdrom },
- { .driver = "virtio-console-pci", .flag = &default_virtcon },
- { .driver = "virtio-console-s390", .flag = &default_virtcon },
+ { .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 },
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)
+int qemu_balloon(ram_addr_t target, MonitorCompletion cb, void *opaque)
{
- 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)
-{
- 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);
- }
-}
-
-int kbd_mouse_is_absolute(void)
-{
- if (!qemu_put_mouse_event_current)
+ if (qemu_balloon_event) {
+ qemu_balloon_event(qemu_balloon_event_opaque, target, cb, opaque);
+ return 1;
+ } else {
return 0;
-
- return qemu_put_mouse_event_current->qemu_put_mouse_event_absolute;
-}
-
-static void info_mice_iter(QObject *data, void *opaque)
-{
- QDict *mouse;
- Monitor *mon = opaque;
-
- mouse = qobject_to_qdict(data);
- monitor_printf(mon, "%c Mouse #%" PRId64 ": %s\n",
- (qdict_get_bool(mouse, "current") ? '*' : ' '),
- qdict_get_int(mouse, "index"), qdict_get_str(mouse, "name"));
-}
-
-void do_info_mice_print(Monitor *mon, const QObject *data)
-{
- QList *mice_list;
-
- mice_list = qobject_to_qlist(data);
- if (qlist_empty(mice_list)) {
- monitor_printf(mon, "No mouse devices connected\n");
- return;
}
-
- qlist_iter(mice_list, info_mice_iter, mon);
}
-/**
- * do_info_mice(): Show VM mice information
- *
- * Each mouse is represented by a QDict, the returned QObject is a QList of
- * all mice.
- *
- * The mouse QDict contains the following:
- *
- * - "name": mouse's name
- * - "index": mouse's index
- * - "current": true if this mouse is receiving events, false otherwise
- *
- * Example:
- *
- * [ { "name": "QEMU Microsoft Mouse", "index": 0, "current": false },
- * { "name": "QEMU PS/2 Mouse", "index": 1, "current": true } ]
- */
-void do_info_mice(Monitor *mon, QObject **ret_data)
+int qemu_balloon_status(MonitorCompletion cb, void *opaque)
{
- QEMUPutMouseEntry *cursor;
- QList *mice_list;
- int index = 0;
-
- mice_list = qlist_new();
-
- if (!qemu_put_mouse_event_head) {
- goto out;
- }
-
- cursor = qemu_put_mouse_event_head;
- while (cursor != NULL) {
- QObject *obj;
- obj = qobject_from_jsonf("{ 'name': %s, 'index': %d, 'current': %i }",
- cursor->qemu_put_mouse_event_name,
- index, cursor == qemu_put_mouse_event_current);
- qlist_append_obj(mice_list, obj);
- index++;
- cursor = cursor->next;
+ if (qemu_balloon_event) {
+ qemu_balloon_event(qemu_balloon_event_opaque, 0, cb, opaque);
+ return 1;
+ } else {
+ return 0;
}
-
-out:
- *ret_data = QOBJECT(mice_list);
}
-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;
}
}
+int64_t qemu_get_clock_ns(QEMUClock *clock)
+{
+ switch(clock->type) {
+ case QEMU_CLOCK_REALTIME:
+ return get_clock();
+ default:
+ case QEMU_CLOCK_VIRTUAL:
+ if (use_icount) {
+ return cpu_get_icount();
+ } else {
+ return cpu_get_clock();
+ }
+ case QEMU_CLOCK_HOST:
+ return get_clock_realtime();
+ }
+}
+
static void init_clocks(void)
{
init_get_clock();
}
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",
fprintf(stderr,
"only 63 CPUs in NUMA mode supported.\n");
}
- value = (1 << (endvalue + 1)) - (1 << value);
+ value = (2ULL << endvalue) - (1ULL << value);
} else {
- value = 1 << value;
+ value = 1ULL << value;
}
}
node_cpumask[nodenr] = value;
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);
}
}
"Empty");
}
-/***********************************************************/
-/* register display */
-
-struct DisplayAllocator default_allocator = {
- defaultallocator_create_displaysurface,
- defaultallocator_resize_displaysurface,
- defaultallocator_free_displaysurface
-};
-
-void register_displaystate(DisplayState *ds)
-{
- DisplayState **s;
- s = &display_state;
- while (*s != NULL)
- s = &(*s)->next;
- ds->next = NULL;
- *s = ds;
-}
-
-DisplayState *get_displaystate(void)
-{
- return display_state;
-}
-
-DisplayAllocator *register_displayallocator(DisplayState *ds, DisplayAllocator *da)
-{
- if(ds->allocator == &default_allocator) ds->allocator = da;
- return ds->allocator;
-}
-
-/* dumb display */
-
-static void dumb_display_init(void)
-{
- DisplayState *ds = qemu_mallocz(sizeof(DisplayState));
- ds->allocator = &default_allocator;
- ds->surface = qemu_create_displaysurface(ds, 640, 480);
- register_displaystate(ds);
-}
-
/***********************************************************/
/* I/O handling */
}
bytes_transferred_last = bytes_transferred;
- bwidth = get_clock();
+ bwidth = qemu_get_clock_ns(rt_clock);
while (!qemu_file_rate_limit(f)) {
int ret;
break;
}
- bwidth = get_clock() - bwidth;
+ bwidth = qemu_get_clock_ns(rt_clock) - bwidth;
bwidth = (bytes_transferred - bytes_transferred_last) / bwidth;
/* if we haven't transferred anything this round, force expected_time to a
DisplayState *ds = opaque;
DisplayChangeListener *dcl = ds->listeners;
+ qemu_flush_coalesced_mmio_buffer();
dpy_refresh(ds);
while (dcl != NULL) {
{
uint64_t interval = GUI_REFRESH_INTERVAL;
+ qemu_flush_coalesced_mmio_buffer();
qemu_mod_timer(nographic_timer, interval + qemu_get_clock(rt_clock));
}
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));
+ do {
+ ret = write(io_thread_fd, &byte, sizeof(byte));
+ } while (ret < 0 && errno == EINTR);
+
+ /* EAGAIN is fine, a read must be pending. */
+ if (ret < 0 && errno != EAGAIN) {
+ fprintf(stderr, "qemu_event_increment: write() filed: %s\n",
+ strerror(errno));
+ exit (1);
+ }
}
static void qemu_event_read(void *opaque)
{
int fd = (unsigned long)opaque;
ssize_t len;
+ char buffer[512];
/* Drain the notify pipe */
do {
- char buffer[512];
len = read(fd, buffer, sizeof(buffer));
- } while ((len == -1 && errno == EINTR) || len > 0);
+ } while ((len == -1 && errno == EINTR) || len == sizeof(buffer));
}
static int qemu_event_init(void)
return 0;
if (env->stopped)
return 0;
+ if (!vm_running)
+ return 0;
return 1;
}
for (; next_cpu != NULL; next_cpu = next_cpu->next_cpu) {
CPUState *env = cur_cpu = next_cpu;
- if (!vm_running)
- break;
if (timer_alarm_pending) {
timer_alarm_pending = 0;
break;
}
if (cpu_can_run(env))
ret = qemu_cpu_exec(env);
+ else if (env->stop)
+ break;
+
if (ret == EXCP_DEBUG) {
gdb_set_stop_cpu(env);
debug_requested = 1;
static void help(int exitcode)
{
- version();
- printf("usage: %s [options] [disk_image]\n"
- "\n"
- "'disk_image' is a raw hard image image for IDE hard disk 0\n"
- "\n"
+ const char *options_help =
#define DEF(option, opt_arg, opt_enum, opt_help) \
opt_help
#define DEFHEADING(text) stringify(text) "\n"
#undef DEF
#undef DEFHEADING
#undef GEN_DOCS
+ ;
+ version();
+ printf("usage: %s [options] [disk_image]\n"
+ "\n"
+ "'disk_image' is a raw hard image image for IDE hard disk 0\n"
"\n"
+ "%s\n"
"During emulation, the following keys are useful:\n"
"ctrl-alt-f toggle full screen\n"
"ctrl-alt-n switch to virtual console 'n'\n"
"ctrl-alt toggle mouse and keyboard grab\n"
"\n"
- "When using -nographic, press 'ctrl-a h' to get some help.\n"
- ,
+ "When using -nographic, press 'ctrl-a h' to get some help.\n",
"qemu",
- DEFAULT_RAM_SIZE,
-#ifndef _WIN32
- DEFAULT_NETWORK_SCRIPT,
- DEFAULT_NETWORK_DOWN_SCRIPT,
-#endif
- DEFAULT_GDBSTUB_PORT,
- "/tmp/qemu.log");
+ options_help);
exit(exitcode);
}
return buf;
}
+static int device_help_func(QemuOpts *opts, void *opaque)
+{
+ return qdev_device_help(opts);
+}
+
static int device_init_func(QemuOpts *opts, void *opaque)
{
DeviceState *dev;
{
static int index = 0;
char label[32];
+ QemuOpts *bus_opts, *dev_opts;
if (strcmp(devname, "none") == 0)
return 0;
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]) {
devname, strerror(errno));
return -1;
}
+ qemu_opt_set(dev_opts, "chardev", label);
+
index++;
return 0;
}
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;
+ 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();
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);
#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));
module_call_init(MODULE_INIT_DEVICE);
+ if (qemu_opts_foreach(&qemu_device_opts, device_help_func, NULL, 0) != 0)
+ exit(0);
+
if (watchdog) {
i = select_watchdog(watchdog);
if (i > 0)
if (qemu_opts_foreach(&qemu_device_opts, device_init_func, NULL, 1) != 0)
exit(1);
- if (!display_state)
- dumb_display_init();
+ net_check_clients();
+
/* just use the first displaystate for the moment */
- ds = display_state;
+ ds = get_displaystate();
if (display_type == DT_DEFAULT) {
#if defined(CONFIG_SDL) || defined(CONFIG_COCOA)
qemu_mod_timer(nographic_timer, qemu_get_clock(rt_clock));
}
- text_consoles_set_display(display_state);
+ text_consoles_set_display(ds);
if (qemu_opts_foreach(&qemu_mon_opts, mon_init_func, NULL, 1) != 0)
exit(1);
if (len != 1)
exit(1);
- chdir("/");
+ 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) {