#ifndef _WIN32
#include <libgen.h>
-#include <pwd.h>
#include <sys/times.h>
#include <sys/wait.h>
#include <termios.h>
#include <sys/stat.h>
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
#include <libutil.h>
+#include <sys/sysctl.h>
#else
#include <util.h>
#endif
#ifdef __linux__
#include <pty.h>
#include <malloc.h>
-#include <sys/prctl.h>
#include <linux/ppdev.h>
#include <linux/parport.h>
#include <sys/ethernet.h>
#include <sys/sockio.h>
#include <netinet/arp.h>
-#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h> // must come after ip.h
#include "hw/usb.h"
#include "hw/pcmcia.h"
#include "hw/pc.h"
-#include "hw/audiodev.h"
#include "hw/isa.h"
#include "hw/baum.h"
#include "hw/bt.h"
#include "audio/audio.h"
#include "migration.h"
#include "kvm.h"
-#include "balloon.h"
#include "qemu-option.h"
#include "qemu-config.h"
#include "qemu-objects.h"
+#include "qemu-options.h"
+#ifdef CONFIG_LINUX
+#include "fsdev/qemu-fsdev.h"
+#endif
#include "disas.h"
-#include "exec-all.h"
-
#include "qemu_socket.h"
#include "slirp/libslirp.h"
#include "qemu-queue.h"
#include "cpus.h"
+#include "arch_init.h"
//#define DEBUG_NET
//#define DEBUG_SLIRP
static int rtc_date_offset = -1; /* -1 means no change */
QEMUClock *rtc_clock;
int vga_interface_type = VGA_NONE;
-#ifdef TARGET_SPARC
-int graphic_width = 1024;
-int graphic_height = 768;
-int graphic_depth = 8;
-#else
-int graphic_width = 800;
-int graphic_height = 600;
-int graphic_depth = 15;
-#endif
static int full_screen = 0;
#ifdef CONFIG_SDL
static int no_frame = 0;
CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
CharDriverState *virtcon_hds[MAX_VIRTIO_CONSOLES];
int win2k_install_hack = 0;
-#ifdef TARGET_I386
int rtc_td_hack = 0;
-#endif
int usb_enabled = 0;
int singlestep = 0;
int smp_cpus = 1;
int cursor_hide = 1;
int graphic_rotate = 0;
uint8_t irq0override = 1;
-#ifndef _WIN32
-int daemonize = 0;
-#endif
const char *watchdog;
const char *option_rom[MAX_OPTION_ROMS];
int nb_option_roms;
int semihosting_enabled = 0;
-#ifdef TARGET_ARM
int old_param = 0;
-#endif
const char *qemu_name;
int alt_grab = 0;
int ctrl_grab = 0;
-#if defined(TARGET_SPARC) || defined(TARGET_PPC)
unsigned int nb_prom_envs = 0;
const char *prom_envs[MAX_PROM_ENVS];
-#endif
int boot_menu;
int nb_numa_nodes;
uint32_t xen_domid;
enum xen_mode xen_mode = XEN_EMULATE;
-#ifdef SIGRTMIN
-#define SIG_IPI (SIGRTMIN+4)
-#else
-#define SIG_IPI SIGUSR1
-#endif
-
static int default_serial = 1;
static int default_parallel = 1;
static int default_virtcon = 1;
return 0;
}
-/***********************************************************/
-/* x86 ISA bus support */
-
-target_phys_addr_t isa_mem_base = 0;
-PicState2 *isa_pic;
-
-static void set_proc_name(const char *s)
-{
-#if defined(__linux__) && defined(PR_SET_NAME)
- char name[16];
- if (!s)
- return;
- name[sizeof(name) - 1] = 0;
- strncpy(name, s, sizeof(name));
- /* Could rewrite argv[0] too, but that's a bit more complicated.
- This simple way is enough for `top'. */
- prctl(PR_SET_NAME, name);
-#endif
-}
-
-/***************/
-/* ballooning */
-
-static QEMUBalloonEvent *qemu_balloon_event;
-void *qemu_balloon_event_opaque;
-
-void qemu_add_balloon_handler(QEMUBalloonEvent *func, void *opaque)
-{
- qemu_balloon_event = func;
- qemu_balloon_event_opaque = opaque;
-}
-
-int qemu_balloon(ram_addr_t target, MonitorCompletion cb, void *opaque)
-{
- if (qemu_balloon_event) {
- qemu_balloon_event(qemu_balloon_event_opaque, target, cb, opaque);
- return 1;
- } else {
- return 0;
- }
-}
-
-int qemu_balloon_status(MonitorCompletion cb, void *opaque)
-{
- if (qemu_balloon_event) {
- qemu_balloon_event(qemu_balloon_event_opaque, 0, cb, opaque);
- return 1;
- } else {
- return 0;
- }
-}
-
-
/***********************************************************/
/* real time host monotonic timer */
exit(1);
}
}
-#ifdef TARGET_I386
value = qemu_opt_get(opts, "driftfix");
if (value) {
if (!strcmp(value, "slew")) {
exit(1);
}
}
-#endif
-}
-
-#ifdef _WIN32
-static void socket_cleanup(void)
-{
- WSACleanup();
-}
-
-static int socket_init(void)
-{
- WSADATA Data;
- int ret, err;
-
- ret = WSAStartup(MAKEWORD(2,2), &Data);
- if (ret != 0) {
- err = WSAGetLastError();
- fprintf(stderr, "WSAStartup: %d\n", err);
- return -1;
- }
- atexit(socket_cleanup);
- return 0;
}
-#endif
/***********************************************************/
/* Bluetooth support */
opts = qemu_opts_parse(&qemu_drive_opts, optstr, 0);
if (!opts) {
- fprintf(stderr, "%s: huh? duplicate? (%s)\n",
- __FUNCTION__, optstr);
return NULL;
}
if (file)
QEMUMachine *machine = opaque;
int max_devs;
int index;
- int cache;
- int aio = 0;
int ro = 0;
- int bdrv_flags;
+ int bdrv_flags = 0;
int on_read_error, on_write_error;
const char *devaddr;
DriveInfo *dinfo;
*fatal_error = 1;
translation = BIOS_ATA_TRANSLATION_AUTO;
- cache = 1;
if (machine && machine->use_scsi) {
type = IF_SCSI;
}
if ((buf = qemu_opt_get(opts, "cache")) != NULL) {
- if (!strcmp(buf, "off") || !strcmp(buf, "none"))
- cache = 0;
- else if (!strcmp(buf, "writethrough"))
- cache = 1;
- else if (!strcmp(buf, "writeback"))
- cache = 2;
- else {
+ if (!strcmp(buf, "off") || !strcmp(buf, "none")) {
+ bdrv_flags |= BDRV_O_NOCACHE;
+ } else if (!strcmp(buf, "writeback")) {
+ bdrv_flags |= BDRV_O_CACHE_WB;
+ } else if (!strcmp(buf, "unsafe")) {
+ bdrv_flags |= BDRV_O_CACHE_WB;
+ bdrv_flags |= BDRV_O_NO_FLUSH;
+ } else if (!strcmp(buf, "writethrough")) {
+ /* this is the default */
+ } else {
fprintf(stderr, "qemu: invalid cache option\n");
return NULL;
}
#ifdef CONFIG_LINUX_AIO
if ((buf = qemu_opt_get(opts, "aio")) != NULL) {
- if (!strcmp(buf, "threads"))
- aio = 0;
- else if (!strcmp(buf, "native"))
- aio = 1;
- else {
+ if (!strcmp(buf, "native")) {
+ bdrv_flags |= BDRV_O_NATIVE_AIO;
+ } else if (!strcmp(buf, "threads")) {
+ /* this is the default */
+ } else {
fprintf(stderr, "qemu: invalid aio option\n");
return NULL;
}
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) {
+ if (type != IF_IDE && type != IF_SCSI && type != IF_VIRTIO && type != IF_NONE) {
fprintf(stderr, "werror is no supported by this format\n");
return NULL;
}
on_read_error = BLOCK_ERR_REPORT;
if ((buf = qemu_opt_get(opts, "rerror")) != NULL) {
- if (type != IF_IDE && type != IF_VIRTIO) {
+ if (type != IF_IDE && type != IF_VIRTIO && type != IF_NONE) {
fprintf(stderr, "rerror is no supported by this format\n");
return NULL;
}
*fatal_error = 0;
return NULL;
}
- bdrv_flags = 0;
if (snapshot) {
- bdrv_flags |= BDRV_O_SNAPSHOT;
- cache = 2; /* always use write-back with snapshot */
- }
- if (cache == 0) /* no caching */
- bdrv_flags |= BDRV_O_NOCACHE;
- else if (cache == 2) /* write-back */
- bdrv_flags |= BDRV_O_CACHE_WB;
-
- if (aio == 1) {
- bdrv_flags |= BDRV_O_NATIVE_AIO;
- } else {
- bdrv_flags &= ~BDRV_O_NATIVE_AIO;
+ /* always use cache=unsafe with snapshot */
+ bdrv_flags &= ~BDRV_O_CACHE_MASK;
+ bdrv_flags |= (BDRV_O_SNAPSHOT|BDRV_O_CACHE_WB|BDRV_O_NO_FLUSH);
}
- if (ro == 1) {
- if (type != IF_SCSI && type != IF_VIRTIO && type != IF_FLOPPY) {
+ if (media == MEDIA_CDROM) {
+ /* CDROM is fine for any interface, don't check. */
+ ro = 1;
+ } else if (ro == 1) {
+ if (type != IF_SCSI && type != IF_VIRTIO && type != IF_FLOPPY && type != IF_NONE) {
fprintf(stderr, "qemu: readonly flag not supported for drive with this interface\n");
return NULL;
}
}
- /*
- * 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) {
+ if (bdrv_open(dinfo->bdrv, file, bdrv_flags, drv) < 0) {
fprintf(stderr, "qemu: could not open disk image %s: %s\n",
file, strerror(errno));
return NULL;
return boot_set_handler(boot_set_opaque, boot_devices);
}
-static int parse_bootdevices(char *devices)
+static void validate_bootdevices(char *devices)
{
/* We just do some generic consistency checks */
const char *p;
}
bitmap |= 1 << (*p - 'a');
}
- return bitmap;
}
static void restore_boot_devices(void *opaque)
{
char *standard_boot_devices = opaque;
+ static int first = 1;
+
+ /* Restore boot order and remove ourselves after the first boot */
+ if (first) {
+ first = 0;
+ return;
+ }
qemu_boot_set(standard_boot_devices);
return qemu_set_fd_handler2(fd, NULL, fd_read, fd_write, opaque);
}
-#ifdef _WIN32
-/***********************************************************/
-/* Polling handling */
-
-typedef struct PollingEntry {
- PollingFunc *func;
- void *opaque;
- struct PollingEntry *next;
-} PollingEntry;
-
-static PollingEntry *first_polling_entry;
-
-int qemu_add_polling_cb(PollingFunc *func, void *opaque)
-{
- PollingEntry **ppe, *pe;
- pe = qemu_mallocz(sizeof(PollingEntry));
- pe->func = func;
- pe->opaque = opaque;
- for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next);
- *ppe = pe;
- return 0;
-}
-
-void qemu_del_polling_cb(PollingFunc *func, void *opaque)
-{
- PollingEntry **ppe, *pe;
- for(ppe = &first_polling_entry; *ppe != NULL; ppe = &(*ppe)->next) {
- pe = *ppe;
- if (pe->func == func && pe->opaque == opaque) {
- *ppe = pe->next;
- qemu_free(pe);
- break;
- }
- }
-}
-
-/***********************************************************/
-/* Wait objects support */
-typedef struct WaitObjects {
- int num;
- HANDLE events[MAXIMUM_WAIT_OBJECTS + 1];
- WaitObjectFunc *func[MAXIMUM_WAIT_OBJECTS + 1];
- void *opaque[MAXIMUM_WAIT_OBJECTS + 1];
-} WaitObjects;
-
-static WaitObjects wait_objects = {0};
-
-int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
-{
- WaitObjects *w = &wait_objects;
-
- if (w->num >= MAXIMUM_WAIT_OBJECTS)
- return -1;
- w->events[w->num] = handle;
- w->func[w->num] = func;
- w->opaque[w->num] = opaque;
- w->num++;
- return 0;
-}
-
-void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque)
-{
- int i, found;
- WaitObjects *w = &wait_objects;
-
- found = 0;
- for (i = 0; i < w->num; i++) {
- if (w->events[i] == handle)
- found = 1;
- if (found) {
- w->events[i] = w->events[i + 1];
- w->func[i] = w->func[i + 1];
- w->opaque[i] = w->opaque[i + 1];
- }
- }
- if (found)
- w->num--;
-}
-#endif
-
-/***********************************************************/
-/* ram save/restore */
-
-#define RAM_SAVE_FLAG_FULL 0x01 /* Obsolete, not used anymore */
-#define RAM_SAVE_FLAG_COMPRESS 0x02
-#define RAM_SAVE_FLAG_MEM_SIZE 0x04
-#define RAM_SAVE_FLAG_PAGE 0x08
-#define RAM_SAVE_FLAG_EOS 0x10
-
-static int is_dup_page(uint8_t *page, uint8_t ch)
-{
- uint32_t val = ch << 24 | ch << 16 | ch << 8 | ch;
- uint32_t *array = (uint32_t *)page;
- int i;
-
- for (i = 0; i < (TARGET_PAGE_SIZE / 4); i++) {
- if (array[i] != val)
- return 0;
- }
-
- return 1;
-}
-
-static int ram_save_block(QEMUFile *f)
-{
- static ram_addr_t current_addr = 0;
- ram_addr_t saved_addr = current_addr;
- ram_addr_t addr = 0;
- int found = 0;
-
- while (addr < last_ram_offset) {
- if (cpu_physical_memory_get_dirty(current_addr, MIGRATION_DIRTY_FLAG)) {
- uint8_t *p;
-
- cpu_physical_memory_reset_dirty(current_addr,
- current_addr + TARGET_PAGE_SIZE,
- MIGRATION_DIRTY_FLAG);
-
- p = qemu_get_ram_ptr(current_addr);
-
- if (is_dup_page(p, *p)) {
- qemu_put_be64(f, current_addr | RAM_SAVE_FLAG_COMPRESS);
- qemu_put_byte(f, *p);
- } else {
- qemu_put_be64(f, current_addr | RAM_SAVE_FLAG_PAGE);
- qemu_put_buffer(f, p, TARGET_PAGE_SIZE);
- }
-
- found = 1;
- break;
- }
- addr += TARGET_PAGE_SIZE;
- current_addr = (saved_addr + addr) % last_ram_offset;
- }
-
- return found;
-}
-
-static uint64_t bytes_transferred;
-
-static ram_addr_t ram_save_remaining(void)
-{
- ram_addr_t addr;
- ram_addr_t count = 0;
-
- for (addr = 0; addr < last_ram_offset; addr += TARGET_PAGE_SIZE) {
- if (cpu_physical_memory_get_dirty(addr, MIGRATION_DIRTY_FLAG))
- count++;
- }
-
- return count;
-}
-
-uint64_t ram_bytes_remaining(void)
-{
- return ram_save_remaining() * TARGET_PAGE_SIZE;
-}
-
-uint64_t ram_bytes_transferred(void)
-{
- return bytes_transferred;
-}
-
-uint64_t ram_bytes_total(void)
-{
- return last_ram_offset;
-}
-
-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))
- cpu_physical_memory_set_dirty(addr);
- }
-
- /* Enable dirty memory tracking */
- cpu_physical_memory_set_dirty_tracking(1);
-
- qemu_put_be64(f, last_ram_offset | RAM_SAVE_FLAG_MEM_SIZE);
- }
-
- bytes_transferred_last = bytes_transferred;
- bwidth = qemu_get_clock_ns(rt_clock);
-
- while (!qemu_file_rate_limit(f)) {
- int ret;
-
- ret = ram_save_block(f);
- bytes_transferred += ret * TARGET_PAGE_SIZE;
- if (ret == 0) /* no more blocks */
- break;
- }
-
- 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
- * a very high value, but without crashing */
- if (bwidth == 0)
- 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;
- }
- cpu_physical_memory_set_dirty_tracking(0);
- }
-
- qemu_put_be64(f, RAM_SAVE_FLAG_EOS);
-
- expected_time = ram_save_remaining() * TARGET_PAGE_SIZE / bwidth;
-
- return (stage == 2) && (expected_time <= migrate_max_downtime());
-}
-
-static int ram_load(QEMUFile *f, void *opaque, int version_id)
-{
- ram_addr_t addr;
- int flags;
-
- if (version_id != 3)
- return -EINVAL;
-
- do {
- addr = qemu_get_be64(f);
-
- flags = addr & ~TARGET_PAGE_MASK;
- addr &= TARGET_PAGE_MASK;
-
- if (flags & RAM_SAVE_FLAG_MEM_SIZE) {
- if (addr != last_ram_offset)
- return -EINVAL;
- }
-
- if (flags & RAM_SAVE_FLAG_COMPRESS) {
- uint8_t ch = qemu_get_byte(f);
- memset(qemu_get_ram_ptr(addr), ch, TARGET_PAGE_SIZE);
-#ifndef _WIN32
- if (ch == 0 &&
- (!kvm_enabled() || kvm_has_sync_mmu())) {
- madvise(qemu_get_ram_ptr(addr), TARGET_PAGE_SIZE, MADV_DONTNEED);
- }
-#endif
- } 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;
-}
-
-void qemu_service_io(void)
-{
- qemu_notify_event();
-}
-
/***********************************************************/
/* machine registration */
vm_running = 1;
vm_state_notify(1, 0);
resume_all_vcpus();
+ monitor_protocol_event(QEVENT_RESUME, NULL);
}
}
static int shutdown_requested;
static int powerdown_requested;
int debug_requested;
-static int vmstop_requested;
+int vmstop_requested;
int qemu_shutdown_requested(void)
{
qemu_notify_event();
}
-#ifdef _WIN32
-static void host_main_loop_wait(int *timeout)
-{
- int ret, ret2, i;
- PollingEntry *pe;
-
-
- /* XXX: need to suppress polling by better using win32 events */
- ret = 0;
- for(pe = first_polling_entry; pe != NULL; pe = pe->next) {
- ret |= pe->func(pe->opaque);
- }
- if (ret == 0) {
- int err;
- WaitObjects *w = &wait_objects;
-
- ret = WaitForMultipleObjects(w->num, w->events, FALSE, *timeout);
- if (WAIT_OBJECT_0 + 0 <= ret && ret <= WAIT_OBJECT_0 + w->num - 1) {
- if (w->func[ret - WAIT_OBJECT_0])
- w->func[ret - WAIT_OBJECT_0](w->opaque[ret - WAIT_OBJECT_0]);
-
- /* Check for additional signaled events */
- for(i = (ret - WAIT_OBJECT_0 + 1); i < w->num; i++) {
-
- /* Check if event is signaled */
- ret2 = WaitForSingleObject(w->events[i], 0);
- if(ret2 == WAIT_OBJECT_0) {
- if (w->func[i])
- w->func[i](w->opaque[i]);
- } else if (ret2 == WAIT_TIMEOUT) {
- } else {
- err = GetLastError();
- fprintf(stderr, "WaitForSingleObject error %d %d\n", i, err);
- }
- }
- } else if (ret == WAIT_TIMEOUT) {
- } else {
- err = GetLastError();
- fprintf(stderr, "WaitForMultipleObjects error %d %d\n", ret, err);
- }
- }
-
- *timeout = 0;
-}
-#else
-static void host_main_loop_wait(int *timeout)
-{
-}
-#endif
-
void main_loop_wait(int nonblocking)
{
IOHandlerRecord *ioh;
qemu_bh_update_timeout(&timeout);
}
- host_main_loop_wait(&timeout);
+ os_host_main_loop_wait(&timeout);
/* poll any events */
/* XXX: separate device handlers from system ones */
{
int r;
-#ifdef CONFIG_IOTHREAD
- qemu_system_ready = 1;
- qemu_cond_broadcast(&qemu_system_cond);
-#endif
+ qemu_main_loop_start();
for (;;) {
do {
static void version(void)
{
- printf("QEMU PC emulator version " QEMU_VERSION QEMU_PKGVERSION ", Copyright (c) 2003-2008 Fabrice Bellard\n");
+ printf("QEMU emulator version " QEMU_VERSION QEMU_PKGVERSION ", Copyright (c) 2003-2008 Fabrice Bellard\n");
}
static void help(int exitcode)
{
const char *options_help =
-#define DEF(option, opt_arg, opt_enum, opt_help) \
- opt_help
+#define DEF(option, opt_arg, opt_enum, opt_help, arch_mask) \
+ opt_help
#define DEFHEADING(text) stringify(text) "\n"
-#include "qemu-options.h"
+#include "qemu-options.def"
#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"
+ "'disk_image' is a raw hard disk image for IDE hard disk 0\n"
"\n"
"%s\n"
"During emulation, the following keys are useful:\n"
#define HAS_ARG 0x0001
-enum {
-#define DEF(option, opt_arg, opt_enum, opt_help) \
- opt_enum,
-#define DEFHEADING(text)
-#include "qemu-options.h"
-#undef DEF
-#undef DEFHEADING
-#undef GEN_DOCS
-};
-
typedef struct QEMUOption {
const char *name;
int flags;
int index;
+ uint32_t arch_mask;
} QEMUOption;
static const QEMUOption qemu_options[] = {
- { "h", 0, QEMU_OPTION_h },
-#define DEF(option, opt_arg, opt_enum, opt_help) \
- { option, opt_arg, opt_enum },
+ { "h", 0, QEMU_OPTION_h, QEMU_ARCH_ALL },
+#define DEF(option, opt_arg, opt_enum, opt_help, arch_mask) \
+ { option, opt_arg, opt_enum, arch_mask },
#define DEFHEADING(text)
-#include "qemu-options.h"
+#include "qemu-options.def"
#undef DEF
#undef DEFHEADING
#undef GEN_DOCS
{ NULL },
};
-
-#ifdef HAS_AUDIO
-struct soundhw soundhw[] = {
-#ifdef HAS_AUDIO_CHOICE
-#if defined(TARGET_I386) || defined(TARGET_MIPS)
- {
- "pcspk",
- "PC speaker",
- 0,
- 1,
- { .init_isa = pcspk_audio_init }
- },
-#endif
-
-#ifdef CONFIG_SB16
- {
- "sb16",
- "Creative Sound Blaster 16",
- 0,
- 1,
- { .init_isa = SB16_init }
- },
-#endif
-
-#ifdef CONFIG_CS4231A
- {
- "cs4231a",
- "CS4231A",
- 0,
- 1,
- { .init_isa = cs4231a_init }
- },
-#endif
-
-#ifdef CONFIG_ADLIB
- {
- "adlib",
-#ifdef HAS_YMF262
- "Yamaha YMF262 (OPL3)",
-#else
- "Yamaha YM3812 (OPL2)",
-#endif
- 0,
- 1,
- { .init_isa = Adlib_init }
- },
-#endif
-
-#ifdef CONFIG_GUS
- {
- "gus",
- "Gravis Ultrasound GF1",
- 0,
- 1,
- { .init_isa = GUS_init }
- },
-#endif
-
-#ifdef CONFIG_AC97
- {
- "ac97",
- "Intel 82801AA AC97 Audio",
- 0,
- 0,
- { .init_pci = ac97_init }
- },
-#endif
-
-#ifdef CONFIG_ES1370
- {
- "es1370",
- "ENSONIQ AudioPCI ES1370",
- 0,
- 0,
- { .init_pci = es1370_init }
- },
-#endif
-
-#endif /* HAS_AUDIO_CHOICE */
-
- { NULL, NULL, 0, 0, { NULL } }
-};
-
-static void select_soundhw (const char *optarg)
-{
- struct soundhw *c;
-
- if (*optarg == '?') {
- show_valid_cards:
-
- printf ("Valid sound card names (comma separated):\n");
- for (c = soundhw; c->name; ++c) {
- printf ("%-11s %s\n", c->name, c->descr);
- }
- printf ("\n-soundhw all will enable all of the above\n");
- exit (*optarg != '?');
- }
- else {
- size_t l;
- const char *p;
- char *e;
- int bad_card = 0;
-
- if (!strcmp (optarg, "all")) {
- for (c = soundhw; c->name; ++c) {
- c->enabled = 1;
- }
- return;
- }
-
- p = optarg;
- while (*p) {
- e = strchr (p, ',');
- l = !e ? strlen (p) : (size_t) (e - p);
-
- for (c = soundhw; c->name; ++c) {
- if (!strncmp (c->name, p, l) && !c->name[l]) {
- c->enabled = 1;
- break;
- }
- }
-
- if (!c->name) {
- if (l > 80) {
- fprintf (stderr,
- "Unknown sound card name (too big to show)\n");
- }
- else {
- fprintf (stderr, "Unknown sound card name `%.*s'\n",
- (int) l, p);
- }
- bad_card = 1;
- }
- p += l + (e != NULL);
- }
-
- if (bad_card)
- goto show_valid_cards;
- }
-}
-#endif
-
static void select_vgahw (const char *p)
{
const char *opts;
}
}
-#ifdef TARGET_I386
static int balloon_parse(const char *arg)
{
QemuOpts *opts;
return -1;
}
-#endif
-
-#ifdef _WIN32
-static BOOL WINAPI qemu_ctrl_handler(DWORD type)
-{
- exit(STATUS_CONTROL_C_EXIT);
- return TRUE;
-}
-#endif
-
-int qemu_uuid_parse(const char *str, uint8_t *uuid)
-{
- int ret;
-
- if(strlen(str) != 36)
- return -1;
-
- ret = sscanf(str, UUID_FMT, &uuid[0], &uuid[1], &uuid[2], &uuid[3],
- &uuid[4], &uuid[5], &uuid[6], &uuid[7], &uuid[8], &uuid[9],
- &uuid[10], &uuid[11], &uuid[12], &uuid[13], &uuid[14], &uuid[15]);
-
- if(ret != 16)
- return -1;
-
-#ifdef TARGET_I386
- smbios_add_field(1, offsetof(struct smbios_type_1, uuid), 16, uuid);
-#endif
-
- return 0;
-}
-
-#ifdef TARGET_I386
-static void do_acpitable_option(const char *optarg)
-{
- if (acpi_table_add(optarg) < 0) {
- fprintf(stderr, "Wrong acpi table provided\n");
- exit(1);
- }
-}
-#endif
-
-#ifdef TARGET_I386
-static void do_smbios_option(const char *optarg)
-{
- if (smbios_entry_add(optarg) < 0) {
- fprintf(stderr, "Wrong smbios provided\n");
- exit(1);
- }
-}
-#endif
-
-static void cpudef_init(void)
-{
-#if defined(cpudef_setup)
- cpudef_setup(); /* parse cpu definitions in target config file */
-#endif
-}
-
-#ifndef _WIN32
-
-static void termsig_handler(int signal)
-{
- qemu_system_shutdown_request();
-}
-
-static void sigchld_handler(int signal)
-{
- waitpid(-1, NULL, WNOHANG);
-}
-
-static void sighandler_setup(void)
-{
- struct sigaction act;
-
- memset(&act, 0, sizeof(act));
- act.sa_handler = termsig_handler;
- sigaction(SIGINT, &act, NULL);
- sigaction(SIGHUP, &act, NULL);
- sigaction(SIGTERM, &act, NULL);
-
- act.sa_handler = sigchld_handler;
- act.sa_flags = SA_NOCLDSTOP;
- sigaction(SIGCHLD, &act, NULL);
-}
-
-#endif
-
-#ifdef _WIN32
-/* Look for support files in the same directory as the executable. */
-static char *find_datadir(const char *argv0)
-{
- char *p;
- char buf[MAX_PATH];
- DWORD len;
-
- len = GetModuleFileName(NULL, buf, sizeof(buf) - 1);
- if (len == 0) {
- return NULL;
- }
-
- buf[len] = 0;
- p = buf + len - 1;
- while (p != buf && *p != '\\')
- p--;
- *p = 0;
- if (access(buf, R_OK) == 0) {
- return qemu_strdup(buf);
- }
- return NULL;
-}
-#else /* !_WIN32 */
-
-/* Find a likely location for support files using the location of the binary.
- For installed binaries this will be "$bindir/../share/qemu". When
- running from the build tree this will be "$bindir/../pc-bios". */
-#define SHARE_SUFFIX "/share/qemu"
-#define BUILD_SUFFIX "/pc-bios"
-static char *find_datadir(const char *argv0)
-{
- char *dir;
- char *p = NULL;
- char *res;
- char buf[PATH_MAX];
- size_t max_len;
-
-#if defined(__linux__)
- {
- int len;
- len = readlink("/proc/self/exe", buf, sizeof(buf) - 1);
- if (len > 0) {
- buf[len] = 0;
- p = buf;
- }
- }
-#elif defined(__FreeBSD__)
- {
- int len;
- len = readlink("/proc/curproc/file", buf, sizeof(buf) - 1);
- if (len > 0) {
- buf[len] = 0;
- p = buf;
- }
- }
-#endif
- /* If we don't have any way of figuring out the actual executable
- location then try argv[0]. */
- if (!p) {
- p = realpath(argv0, buf);
- if (!p) {
- return NULL;
- }
- }
- dir = dirname(p);
- dir = dirname(dir);
-
- max_len = strlen(dir) +
- MAX(strlen(SHARE_SUFFIX), strlen(BUILD_SUFFIX)) + 1;
- res = qemu_mallocz(max_len);
- snprintf(res, max_len, "%s%s", dir, SHARE_SUFFIX);
- if (access(res, R_OK)) {
- snprintf(res, max_len, "%s%s", dir, BUILD_SUFFIX);
- if (access(res, R_OK)) {
- qemu_free(res);
- res = NULL;
- }
- }
-
- return res;
-}
-#undef SHARE_SUFFIX
-#undef BUILD_SUFFIX
-#endif
char *qemu_find_file(int type, const char *name)
{
return 0;
}
+#ifdef CONFIG_LINUX
+static int fsdev_init_func(QemuOpts *opts, void *opaque)
+{
+ int ret;
+ ret = qemu_fsdev_add(opts);
+
+ return ret;
+}
+#endif
+
static int mon_init_func(QemuOpts *opts, void *opaque)
{
CharDriverState *chr;
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");
+ snprintf(label, sizeof(label), "compat_monitor%d",
+ monitor_device_index);
+ if (monitor_device_index == 0) {
def = 1;
}
opts = qemu_chr_parse_compat(label, optarg);
int main(int argc, char **argv, char **envp)
{
const char *gdbstub_dev = NULL;
- uint32_t boot_devices_bitmap = 0;
int i;
- int snapshot, linux_boot, net_boot;
+ int snapshot, linux_boot;
const char *icount_option = NULL;
const char *initrd_filename;
const char *kernel_filename, *kernel_cmdline;
const char *loadvm = NULL;
QEMUMachine *machine;
const char *cpu_model;
-#ifndef _WIN32
- int fds[2];
-#endif
int tb_size;
const char *pid_file = NULL;
const char *incoming = NULL;
-#ifndef _WIN32
- int fd = 0;
- struct passwd *pwd = NULL;
- const char *chroot_dir = NULL;
- const char *run_as = NULL;
-#endif
int show_vnc_port = 0;
int defconfig = 1;
qemu_cache_utils_init(envp);
QLIST_INIT (&vm_change_state_head);
-#ifndef _WIN32
- {
- struct sigaction act;
- sigfillset(&act.sa_mask);
- act.sa_flags = 0;
- act.sa_handler = SIG_IGN;
- sigaction(SIGPIPE, &act, NULL);
- }
-#else
- SetConsoleCtrlHandler(qemu_ctrl_handler, TRUE);
- /* Note: cpu_interrupt() is currently not SMP safe, so we force
- QEMU to run on a single CPU */
- {
- HANDLE h;
- DWORD mask, smask;
- int i;
- h = GetCurrentProcess();
- if (GetProcessAffinityMask(h, &mask, &smask)) {
- for(i = 0; i < 32; i++) {
- if (mask & (1 << i))
- break;
- }
- if (i != 32) {
- mask = 1 << i;
- SetProcessAffinityMask(h, mask);
- }
- }
- }
-#endif
+ os_setup_early_signal_handling();
module_call_init(MODULE_INIT_MACHINE);
machine = find_default_machine();
}
if (defconfig) {
- const char *fname;
- FILE *fp;
+ int ret;
- fname = CONFIG_QEMU_CONFDIR "/qemu.conf";
- fp = fopen(fname, "r");
- if (fp) {
- if (qemu_config_parse(fp, fname) != 0) {
- exit(1);
- }
- fclose(fp);
+ ret = qemu_read_config_file(CONFIG_QEMU_CONFDIR "/qemu.conf");
+ if (ret < 0 && ret != -ENOENT) {
+ exit(1);
}
- fname = CONFIG_QEMU_CONFDIR "/target-" TARGET_ARCH ".conf";
- fp = fopen(fname, "r");
- if (fp) {
- if (qemu_config_parse(fp, fname) != 0) {
- exit(1);
- }
- fclose(fp);
+ ret = qemu_read_config_file(arch_config_name);
+ if (ret < 0 && ret != -ENOENT) {
+ exit(1);
}
}
cpudef_init();
const QEMUOption *popt;
popt = lookup_opt(argc, argv, &optarg, &optind);
+ if (!(popt->arch_mask & arch_type)) {
+ printf("Option %s not supported for this target\n", popt->name);
+ exit(1);
+ }
switch(popt->index) {
case QEMU_OPTION_M:
machine = find_machine(optarg);
case QEMU_OPTION_cpu:
/* hw initialization will check this */
if (*optarg == '?') {
-/* XXX: implement xxx_cpu_list for targets that still miss it */
-#if defined(cpu_list_id)
- cpu_list_id(stdout, &fprintf, optarg);
-#elif defined(cpu_list)
- cpu_list(stdout, &fprintf); /* deprecated */
-#endif
+ list_cpus(stdout, &fprintf, optarg);
exit(0);
} else {
cpu_model = optarg;
if (legacy ||
get_param_value(buf, sizeof(buf), "order", optarg)) {
- boot_devices_bitmap = parse_bootdevices(buf);
+ validate_bootdevices(buf);
pstrcpy(boot_devices, sizeof(boot_devices), buf);
}
if (!legacy) {
if (get_param_value(buf, sizeof(buf),
"once", optarg)) {
- boot_devices_bitmap |= parse_bootdevices(buf);
+ validate_bootdevices(buf);
standard_boot_devices = qemu_strdup(boot_devices);
pstrcpy(boot_devices, sizeof(boot_devices), buf);
qemu_register_reset(restore_boot_devices,
case QEMU_OPTION_fdb:
drive_add(optarg, FD_ALIAS, popt->index - QEMU_OPTION_fda);
break;
-#ifdef TARGET_I386
case QEMU_OPTION_no_fd_bootchk:
fd_bootchk = 0;
break;
-#endif
case QEMU_OPTION_netdev:
if (net_client_parse(&qemu_netdev_opts, optarg) == -1) {
exit(1);
case QEMU_OPTION_bootp:
legacy_bootp_filename = optarg;
break;
-#ifndef _WIN32
- case QEMU_OPTION_smb:
- if (net_slirp_smb(optarg) < 0)
- exit(1);
- break;
-#endif
case QEMU_OPTION_redir:
if (net_slirp_redir(optarg) < 0)
exit(1);
case QEMU_OPTION_bt:
add_device_config(DEV_BT, optarg);
break;
-#ifdef HAS_AUDIO
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;
-#endif
case QEMU_OPTION_h:
help(0);
break;
case QEMU_OPTION_vga:
select_vgahw (optarg);
break;
-#if defined(TARGET_PPC) || defined(TARGET_SPARC)
case QEMU_OPTION_g:
{
const char *p;
graphic_depth = depth;
}
break;
-#endif
case QEMU_OPTION_echr:
{
char *r;
case QEMU_OPTION_mon:
opts = qemu_opts_parse(&qemu_mon_opts, optarg, 1);
if (!opts) {
- fprintf(stderr, "parse error: %s\n", optarg);
exit(1);
}
default_monitor = 0;
break;
case QEMU_OPTION_chardev:
opts = qemu_opts_parse(&qemu_chardev_opts, optarg, 1);
+ if (!opts) {
+ exit(1);
+ }
+ break;
+#ifdef CONFIG_LINUX
+ case QEMU_OPTION_fsdev:
+ opts = qemu_opts_parse(&qemu_fsdev_opts, optarg, 1);
+ if (!opts) {
+ fprintf(stderr, "parse error: %s\n", optarg);
+ exit(1);
+ }
+ break;
+ case QEMU_OPTION_virtfs: {
+ char *arg_fsdev = NULL;
+ char *arg_9p = NULL;
+ int len = 0;
+
+ opts = qemu_opts_parse(&qemu_virtfs_opts, optarg, 1);
if (!opts) {
fprintf(stderr, "parse error: %s\n", optarg);
exit(1);
}
+
+ len = strlen(",id=,path=");
+ len += strlen(qemu_opt_get(opts, "fstype"));
+ len += strlen(qemu_opt_get(opts, "mount_tag"));
+ len += strlen(qemu_opt_get(opts, "path"));
+ arg_fsdev = qemu_malloc((len + 1) * sizeof(*arg_fsdev));
+
+ if (!arg_fsdev) {
+ fprintf(stderr, "No memory to parse -fsdev for %s\n",
+ optarg);
+ exit(1);
+ }
+
+ sprintf(arg_fsdev, "%s,id=%s,path=%s",
+ qemu_opt_get(opts, "fstype"),
+ qemu_opt_get(opts, "mount_tag"),
+ qemu_opt_get(opts, "path"));
+
+ len = strlen("virtio-9p-pci,fsdev=,mount_tag=");
+ len += 2*strlen(qemu_opt_get(opts, "mount_tag"));
+ arg_9p = qemu_malloc((len + 1) * sizeof(*arg_9p));
+
+ if (!arg_9p) {
+ fprintf(stderr, "No memory to parse -device for %s\n",
+ optarg);
+ exit(1);
+ }
+
+ sprintf(arg_9p, "virtio-9p-pci,fsdev=%s,mount_tag=%s",
+ qemu_opt_get(opts, "mount_tag"),
+ qemu_opt_get(opts, "mount_tag"));
+
+ if (!qemu_opts_parse(&qemu_fsdev_opts, arg_fsdev, 1)) {
+ fprintf(stderr, "parse error [fsdev]: %s\n", optarg);
+ exit(1);
+ }
+
+ if (!qemu_opts_parse(&qemu_device_opts, arg_9p, 1)) {
+ fprintf(stderr, "parse error [device]: %s\n", optarg);
+ exit(1);
+ }
+
+ qemu_free(arg_fsdev);
+ qemu_free(arg_9p);
break;
+ }
+#endif
case QEMU_OPTION_serial:
add_device_config(DEV_SERIAL, optarg);
default_serial = 0;
case QEMU_OPTION_pidfile:
pid_file = optarg;
break;
-#ifdef TARGET_I386
case QEMU_OPTION_win2k_hack:
win2k_install_hack = 1;
break;
case QEMU_OPTION_smbios:
do_smbios_option(optarg);
break;
-#endif
-#ifdef CONFIG_KVM
case QEMU_OPTION_enable_kvm:
kvm_allowed = 1;
break;
-#endif
case QEMU_OPTION_usb:
usb_enabled = 1;
break;
display_type = DT_VNC;
vnc_display = optarg;
break;
-#ifdef TARGET_I386
case QEMU_OPTION_no_acpi:
acpi_enabled = 0;
break;
exit(1);
}
break;
-#endif
case QEMU_OPTION_no_reboot:
no_reboot = 1;
break;
exit(1);
}
break;
-#ifndef _WIN32
- case QEMU_OPTION_daemonize:
- daemonize = 1;
- break;
-#endif
case QEMU_OPTION_option_rom:
if (nb_option_roms >= MAX_OPTION_ROMS) {
fprintf(stderr, "Too many option ROMs\n");
option_rom[nb_option_roms] = optarg;
nb_option_roms++;
break;
-#if defined(TARGET_ARM) || defined(TARGET_M68K)
case QEMU_OPTION_semihosting:
semihosting_enabled = 1;
break;
-#endif
case QEMU_OPTION_name:
qemu_name = qemu_strdup(optarg);
{
exit(1);
}
p += 8;
- set_proc_name(p);
+ os_set_proc_name(p);
}
}
break;
-#if defined(TARGET_SPARC) || defined(TARGET_PPC)
case QEMU_OPTION_prom_env:
if (nb_prom_envs >= MAX_PROM_ENVS) {
fprintf(stderr, "Too many prom variables\n");
prom_envs[nb_prom_envs] = optarg;
nb_prom_envs++;
break;
-#endif
-#ifdef TARGET_ARM
case QEMU_OPTION_old_param:
old_param = 1;
break;
-#endif
case QEMU_OPTION_clock:
configure_alarms(optarg);
break;
case QEMU_OPTION_rtc:
opts = qemu_opts_parse(&qemu_rtc_opts, optarg, 0);
if (!opts) {
- fprintf(stderr, "parse error: %s\n", optarg);
exit(1);
}
configure_rtc(opts);
default_cdrom = 0;
default_sdcard = 0;
break;
-#ifndef _WIN32
- case QEMU_OPTION_chroot:
- chroot_dir = optarg;
- break;
- case QEMU_OPTION_runas:
- run_as = optarg;
- break;
-#endif
-#ifdef CONFIG_XEN
case QEMU_OPTION_xen_domid:
+ if (!(xen_available())) {
+ printf("Option %s not supported for this target\n", popt->name);
+ exit(1);
+ }
xen_domid = atoi(optarg);
break;
case QEMU_OPTION_xen_create:
+ if (!(xen_available())) {
+ printf("Option %s not supported for this target\n", popt->name);
+ exit(1);
+ }
xen_mode = XEN_CREATE;
break;
case QEMU_OPTION_xen_attach:
+ if (!(xen_available())) {
+ printf("Option %s not supported for this target\n", popt->name);
+ exit(1);
+ }
xen_mode = XEN_ATTACH;
break;
-#endif
case QEMU_OPTION_readconfig:
{
- FILE *fp;
- fp = fopen(optarg, "r");
- if (fp == NULL) {
- fprintf(stderr, "open %s: %s\n", optarg, strerror(errno));
- exit(1);
- }
- if (qemu_config_parse(fp, optarg) != 0) {
+ int ret = qemu_read_config_file(optarg);
+ if (ret < 0) {
+ fprintf(stderr, "read config %s: %s\n", optarg,
+ strerror(-ret));
exit(1);
}
- fclose(fp);
break;
}
case QEMU_OPTION_writeconfig:
fclose(fp);
break;
}
+ default:
+ os_parse_cmd_args(popt->index, optarg);
}
}
}
/* If no data_dir is specified then try to find it relative to the
executable path. */
if (!data_dir) {
- data_dir = find_datadir(argv[0]);
+ data_dir = os_find_datadir(argv[0]);
}
/* If all else fails use the install patch specified when building. */
if (!data_dir) {
- data_dir = CONFIG_QEMU_SHAREDIR;
+ data_dir = CONFIG_QEMU_DATADIR;
}
/*
if (default_vga)
vga_interface_type = VGA_CIRRUS;
+ socket_init();
+
if (qemu_opts_foreach(&qemu_chardev_opts, chardev_init_func, NULL, 1) != 0)
exit(1);
-
-#ifndef _WIN32
- if (daemonize) {
- pid_t pid;
-
- if (pipe(fds) == -1)
- exit(1);
-
- pid = fork();
- if (pid > 0) {
- uint8_t status;
- ssize_t len;
-
- close(fds[1]);
-
- again:
- len = read(fds[0], &status, 1);
- if (len == -1 && (errno == EINTR))
- goto again;
-
- if (len != 1)
- exit(1);
- else if (status == 1) {
- fprintf(stderr, "Could not acquire pidfile: %s\n", strerror(errno));
- exit(1);
- } else
- exit(0);
- } else if (pid < 0)
- exit(1);
-
- close(fds[0]);
- qemu_set_cloexec(fds[1]);
-
- setsid();
-
- pid = fork();
- if (pid > 0)
- exit(0);
- else if (pid < 0)
- exit(1);
-
- umask(027);
-
- signal(SIGTSTP, SIG_IGN);
- signal(SIGTTOU, SIG_IGN);
- signal(SIGTTIN, SIG_IGN);
+#ifdef CONFIG_LINUX
+ if (qemu_opts_foreach(&qemu_fsdev_opts, fsdev_init_func, NULL, 1) != 0) {
+ exit(1);
}
#endif
+ os_daemonize();
+
if (pid_file && qemu_create_pidfile(pid_file) != 0) {
-#ifndef _WIN32
- if (daemonize) {
- uint8_t 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));
+ os_pidfile_error();
exit(1);
}
- if (kvm_enabled()) {
- int ret;
-
- ret = kvm_init(smp_cpus);
+ if (kvm_allowed) {
+ int ret = kvm_init(smp_cpus);
if (ret < 0) {
- fprintf(stderr, "failed to initialize KVM\n");
+ if (!kvm_available()) {
+ printf("KVM not supported for this target\n");
+ } else {
+ fprintf(stderr, "failed to initialize KVM: %s\n", strerror(-ret));
+ }
exit(1);
}
}
exit(1);
}
-#ifndef _WIN32
- /* Win32 doesn't support line-buffering and requires size >= 2 */
- setvbuf(stdout, NULL, _IOLBF, 0);
-#endif
+ os_set_line_buffering();
if (init_timer_alarm() < 0) {
fprintf(stderr, "could not initialize alarm timer\n");
}
configure_icount(icount_option);
-#ifdef _WIN32
- socket_init();
-#endif
-
if (net_init_clients() < 0) {
exit(1);
}
- net_boot = (boot_devices_bitmap >> ('n' - 'a')) & 0xF;
- net_set_boot_mask(net_boot);
-
/* init the bluetooth world */
if (foreach_device_config(DEV_BT, bt_parse))
exit(1);
}
}
+ if (qemu_opts_foreach(&qemu_mon_opts, mon_init_func, NULL, 1) != 0) {
+ exit(1);
+ }
+
if (foreach_device_config(DEV_SERIAL, serial_parse) < 0)
exit(1);
if (foreach_device_config(DEV_PARALLEL, parallel_parse) < 0)
cpu_synchronize_all_post_init();
-#ifndef _WIN32
/* must be after terminal init, SDL library changes signal handlers */
- sighandler_setup();
-#endif
+ os_setup_signal_handling();
set_numa_modes();
if (dcl->dpy_refresh != NULL) {
ds->gui_timer = qemu_new_timer(rt_clock, gui_update, ds);
qemu_mod_timer(ds->gui_timer, qemu_get_clock(rt_clock));
+ break;
}
dcl = dcl->next;
}
text_consoles_set_display(ds);
- 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",
gdbstub_dev);
vm_start();
}
-#ifndef _WIN32
- if (daemonize) {
- uint8_t status = 0;
- ssize_t len;
-
- again1:
- len = write(fds[1], &status, 1);
- if (len == -1 && (errno == EINTR))
- goto again1;
-
- if (len != 1)
- exit(1);
-
- if (chdir("/")) {
- perror("not able to chdir to /");
- exit(1);
- }
- TFR(fd = qemu_open("/dev/null", O_RDWR));
- if (fd == -1)
- exit(1);
- }
-
- if (run_as) {
- pwd = getpwnam(run_as);
- if (!pwd) {
- fprintf(stderr, "User \"%s\" doesn't exist\n", run_as);
- exit(1);
- }
- }
-
- if (chroot_dir) {
- if (chroot(chroot_dir) < 0) {
- fprintf(stderr, "chroot failed\n");
- exit(1);
- }
- if (chdir("/")) {
- perror("not able to chdir to /");
- exit(1);
- }
- }
-
- if (run_as) {
- if (setgid(pwd->pw_gid) < 0) {
- fprintf(stderr, "Failed to setgid(%d)\n", pwd->pw_gid);
- exit(1);
- }
- if (setuid(pwd->pw_uid) < 0) {
- fprintf(stderr, "Failed to setuid(%d)\n", pwd->pw_uid);
- exit(1);
- }
- if (setuid(0) != -1) {
- fprintf(stderr, "Dropping privileges failed\n");
- exit(1);
- }
- }
-
- if (daemonize) {
- dup2(fd, 0);
- dup2(fd, 1);
- dup2(fd, 2);
-
- close(fd);
- }
-#endif
+ os_setup_post();
main_loop();
quit_timers();