Patchwork [RFC] Refactor target specific handling out of vl.c

login
register
mail settings
Submitter Blue Swirl
Date March 27, 2010, 11:06 a.m.
Message ID <f43fc5581003270406p5bfe7823pb9bfb247ecff8dcb@mail.gmail.com>
Download mbox | patch
Permalink /patch/48740/
State New
Headers show

Comments

Blue Swirl - March 27, 2010, 11:06 a.m.
This is very much work in progress, it does not compile yet. However,
the only target dependencies remaining are QEMU_OPTION_xxx enums and
the target specific option handling in the option parsing loop. I
haven't got a good plan for that, except maybe QEMUOption structure
could have a field that specifies for which targets the option is
valid. Any ideas?

There also are some pieces (set_cpu_log, debug_requested, gdbstub.h
and kvm.h cleanup, allow balloon options to all targets) that deserve
separate patches.

RAM handling could go to a new file, perhaps in hw/ram.c instead of arch_init.c.

Comments?

This depends on the various previous patches I sent. I set up a public git tree:
http://repo.or.cz/w/qemu/blueswirl.git
git://repo.or.cz/qemu/blueswirl.git

Not-quite-signed-off-by-yet: Blue Swirl <blauwirbel@gmail.com>
---
 Makefile.objs   |    2 +-
 Makefile.target |    2 +-
 arch_init.c     |  461 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 arch_init.h     |   20 +++
 balloon.h       |    2 -
 cpu-all.h       |    1 -
 cpus.c          |   18 ++-
 cpus.h          |    1 +
 gdbstub.h       |   11 +-
 hw/smbios.c     |    1 +
 kvm.h           |    4 +-
 qemu-common.h   |    2 +
 qemu-options.hx |    2 -
 vl.c            |  475 ++++---------------------------------------------------
 14 files changed, 543 insertions(+), 459 deletions(-)
 create mode 100644 arch_init.c
 create mode 100644 arch_init.h


@@ -493,19 +472,19 @@ static void configure_rtc(QemuOpts *opts)
             exit(1);
         }
     }
-#ifdef CONFIG_TARGET_I386
-    value = qemu_opt_get(opts, "driftfix");
-    if (value) {
-        if (!strcmp(buf, "slew")) {
-            rtc_td_hack = 1;
-        } else if (!strcmp(buf, "none")) {
-            rtc_td_hack = 0;
-        } else {
-            fprintf(stderr, "qemu: invalid option value '%s'\n", value);
-            exit(1);
+    if (driftfix) {
+        value = qemu_opt_get(opts, "driftfix");
+        if (value) {
+            if (!strcmp(value, "slew")) {
+                rtc_td_hack = 1;
+            } else if (!strcmp(value, "none")) {
+                rtc_td_hack = 0;
+            } else {
+                fprintf(stderr, "qemu: invalid option value '%s'\n", value);
+                exit(1);
+            }
         }
     }
-#endif
 }

 #ifdef _WIN32
@@ -1665,206 +1644,6 @@ void qemu_del_wait_object(HANDLE handle,
WaitObjectFunc *func, void *opaque)
 #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 */

 static QEMUMachine *first_machine = NULL;
@@ -2256,8 +2035,8 @@ static void main_loop(void)
 #endif
         } while (vm_can_run());

-        if (qemu_debug_requested()) {
-            vm_stop(EXCP_DEBUG);
+        if ((r = qemu_debug_requested())) {
+            vm_stop(r);
         }
         if (qemu_shutdown_requested()) {
             monitor_protocol_event(QEVENT_SHUTDOWN, NULL);
@@ -2283,39 +2062,11 @@ static void main_loop(void)
     pause_all_vcpus();
 }

-static void version(void)
+void version(void)
 {
     printf("QEMU PC 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 DEFHEADING(text) stringify(text) "\n"
-#include "qemu-options.h"
-#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",
-           "qemu",
-           options_help);
-    exit(exitcode);
-}
-
 #define HAS_ARG 0x0001

 enum {
@@ -2328,165 +2079,6 @@ enum {
 #undef GEN_DOCS
 };

-typedef struct QEMUOption {
-    const char *name;
-    int flags;
-    int index;
-} 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 },
-#define DEFHEADING(text)
-#include "qemu-options.h"
-#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;
@@ -2521,7 +2113,6 @@ static void select_vgahw (const char *p)
     }
 }

-#ifdef TARGET_I386
 static int balloon_parse(const char *arg)
 {
     QemuOpts *opts;
@@ -2546,7 +2137,6 @@ static int balloon_parse(const char *arg)

     return -1;
 }
-#endif

 #ifdef _WIN32
 static BOOL WINAPI qemu_ctrl_handler(DWORD type)
@@ -2570,10 +2160,6 @@ int qemu_uuid_parse(const char *str, uint8_t *uuid)
     if(ret != 16)
         return -1;

-#ifdef TARGET_I386
-    smbios_add_field(1, offsetof(struct smbios_type_1, uuid), 16, uuid);
-#endif
-
     return 0;
 }

@@ -3116,7 +2702,7 @@ int main(int argc, char **argv, char **envp)
             fclose(fp);
         }

-        fname = CONFIG_QEMU_CONFDIR "/target-" TARGET_ARCH ".conf";
+        fname = arch_config_name;
         fp = fopen(fname, "r");
         if (fp) {
             if (qemu_config_parse(fp, fname) != 0) {
@@ -3433,20 +3019,7 @@ int main(int argc, char **argv, char **envp)
                 break;
 #endif
             case QEMU_OPTION_d:
-                {
-                    int mask;
-                    const CPULogItem *item;
-
-                    mask = cpu_str_to_log_mask(optarg);
-                    if (!mask) {
-                        printf("Log items (comma separated):\n");
-                    for(item = cpu_log_items; item->mask != 0; item++) {
-                        printf("%-10s %s\n", item->name, item->help);
-                    }
-                    exit(1);
-                    }
-                    cpu_set_log(mask);
-                }
+                set_cpu_log(optarg);
                 break;
             case QEMU_OPTION_s:
                 gdbstub_dev = "tcp::" DEFAULT_GDBSTUB_PORT;
@@ -3670,13 +3243,13 @@ int main(int argc, char **argv, char **envp)
             case QEMU_OPTION_no_hpet:
                 no_hpet = 1;
                 break;
+#endif
             case QEMU_OPTION_balloon:
                 if (balloon_parse(optarg) < 0) {
                     fprintf(stderr, "Unknown -balloon argument %s\n", optarg);
                     exit(1);
                 }
                 break;
-#endif
             case QEMU_OPTION_no_reboot:
                 no_reboot = 1;
                 break;
@@ -3692,6 +3265,10 @@ int main(int argc, char **argv, char **envp)
                             " Wrong format.\n");
                     exit(1);
                 }
+#ifdef TARGET_I386
+                smbios_add_field(1, offsetof(struct smbios_type_1, uuid), 16,
+                                 qemu_uuid);
+#endif
                 break;
 #ifndef _WIN32
 	    case QEMU_OPTION_daemonize:
@@ -3753,7 +3330,11 @@ int main(int argc, char **argv, char **envp)
                     fprintf(stderr, "parse error: %s\n", optarg);
                     exit(1);
                 }
-                configure_rtc(opts);
+#ifdef TARGET_I386
+                configure_rtc(opts, 1);
+#else
+                configure_rtc(opts, 0);
+#endif
                 break;
             case QEMU_OPTION_tb_size:
                 tb_size = strtol(optarg, NULL, 0);

Patch

diff --git a/Makefile.objs b/Makefile.objs
index 1c360a6..4ff3214 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -127,7 +127,7 @@  user-obj-y += cutils.o cache-utils.o
 # libhw

 hw-obj-y =
-hw-obj-y += loader.o
+hw-obj-y += vl.o loader.o
 hw-obj-y += virtio.o virtio-console.o
 hw-obj-$(CONFIG_VIRTIO_PCI) += virtio-pci.o
 hw-obj-y += fw_cfg.o pci.o pci_host.o pcie_host.o
diff --git a/Makefile.target b/Makefile.target
index 156b4bd..98cf52c 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -161,7 +161,7 @@  endif #CONFIG_BSD_USER
 # System emulator target
 ifdef CONFIG_SOFTMMU

-obj-y = vl.o cpus.o monitor.o machine.o gdbstub.o
+obj-y = arch_init.o cpus.o monitor.o machine.o gdbstub.o
 obj-y += qemu-timer.o
 # virtio has to be here due to weird dependency between PCI and virtio-net.
 # need to fix this properly
diff --git a/arch_init.c b/arch_init.c
new file mode 100644
index 0000000..eb4dc07
--- /dev/null
+++ b/arch_init.c
@@ -0,0 +1,461 @@ 
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2008 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the
"Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include <stdint.h>
+#include <stdarg.h>
+#include <sys/mman.h>
+#include "config.h"
+#include "monitor.h"
+#include "sysemu.h"
+#include "arch_init.h"
+#include "audio/audio.h"
+#include "hw/pc.h"
+#include "hw/pci.h"
+#include "hw/audiodev.h"
+#include "kvm.h"
+#include "migration.h"
+#include "net.h"
+#include "gdbstub.h"
+
+#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
+
+#ifdef TARGET_I386
+int rtc_td_hack = 0;
+#endif
+
+#ifdef TARGET_ARM
+int old_param = 0;
+#endif
+
+#if defined(TARGET_SPARC) || defined(TARGET_PPC)
+unsigned int nb_prom_envs = 0;
+const char *prom_envs[MAX_PROM_ENVS];
+#endif
+
+const char arch_config_name[] = CONFIG_QEMU_CONFDIR "/target-"
TARGET_ARCH ".conf";
+
+/***********************************************************/
+/* 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;
+}
+
+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());
+}
+
+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();
+}
+
+#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 } }
+};
+
+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
+
+void help(int exitcode)
+{
+    const char *options_help =
+#define DEF(option, opt_arg, opt_enum, opt_help)        \
+           opt_help
+#define DEFHEADING(text) stringify(text) "\n"
+#include "qemu-options.h"
+#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",
+           "qemu",
+           options_help);
+    exit(exitcode);
+}
+
+#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
+};
+
+const QEMUOption qemu_options[] = {
+    { "h", 0, QEMU_OPTION_h },
+#define DEF(option, opt_arg, opt_enum, opt_help)        \
+    { option, opt_arg, opt_enum },
+#define DEFHEADING(text)
+#include "qemu-options.h"
+#undef DEF
+#undef DEFHEADING
+#undef GEN_DOCS
+    { NULL },
+};
+
diff --git a/arch_init.h b/arch_init.h
new file mode 100644
index 0000000..67d504b
--- /dev/null
+++ b/arch_init.h
@@ -0,0 +1,20 @@ 
+#ifndef QEMU_ARCH_INIT_H
+#define QEMU_ARCH_INIT_H
+
+extern const char arch_config_name[];
+
+typedef struct QEMUOption {
+    const char *name;
+    int flags;
+    int index;
+} QEMUOption;
+
+extern const QEMUOption qemu_options[];
+
+void select_soundhw(const char *optarg);
+int ram_save_live(Monitor *mon, QEMUFile *f, int stage, void *opaque);
+int ram_load(QEMUFile *f, void *opaque, int version_id);
+void help(int exitcode);
+void version(void);
+
+#endif
diff --git a/balloon.h b/balloon.h
index c3a1ad3..8c019eb 100644
--- a/balloon.h
+++ b/balloon.h
@@ -14,8 +14,6 @@ 
 #ifndef _QEMU_BALLOON_H
 #define _QEMU_BALLOON_H

-#include "cpu-defs.h"
-
 typedef void (QEMUBalloonEvent)(void *opaque, ram_addr_t target,
                                 MonitorCompletion cb, void *cb_data);

diff --git a/cpu-all.h b/cpu-all.h
index f281a91..9942d49 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -756,7 +756,6 @@  void page_set_flags(target_ulong start,
target_ulong end, int flags);
 int page_check_range(target_ulong start, target_ulong len, int flags);
 #endif

-void cpu_exec_init_all(unsigned long tb_size);
 CPUState *cpu_copy(CPUState *env);
 CPUState *qemu_get_cpu(int cpu);

diff --git a/cpus.c b/cpus.c
index c7b0520..9a8c2f7 100644
--- a/cpus.c
+++ b/cpus.c
@@ -735,7 +735,7 @@  bool tcg_cpu_exec(void)

         if (ret == EXCP_DEBUG) {
             gdb_set_stop_cpu(env);
-            debug_requested = 1;
+            debug_requested = EXCP_DEBUG;
             break;
         }
     }
@@ -755,3 +755,19 @@  void set_numa_modes(void)
         }
     }
 }
+
+void set_cpu_log(const char *optarg)
+{
+    int mask;
+    const CPULogItem *item;
+
+    mask = cpu_str_to_log_mask(optarg);
+    if (!mask) {
+        printf("Log items (comma separated):\n");
+        for (item = cpu_log_items; item->mask != 0; item++) {
+            printf("%-10s %s\n", item->name, item->help);
+        }
+        exit(1);
+    }
+    cpu_set_log(mask);
+}
diff --git a/cpus.h b/cpus.h
index e543b30..67c9a3b 100644
--- a/cpus.h
+++ b/cpus.h
@@ -13,5 +13,6 @@  extern int debug_requested;
 void vm_state_notify(int running, int reason);
 bool tcg_cpu_exec(void);
 void set_numa_modes(void);
+void set_cpu_log(const char *optarg);

 #endif
diff --git a/gdbstub.h b/gdbstub.h
index 5740041..08fbe9c 100644
--- a/gdbstub.h
+++ b/gdbstub.h
@@ -10,6 +10,7 @@ 
 #define GDB_WATCHPOINT_READ      3
 #define GDB_WATCHPOINT_ACCESS    4

+#ifdef NEED_CPU_H
 typedef void (*gdb_syscall_complete_cb)(CPUState *env,
                                         target_ulong ret, target_ulong err);

@@ -21,15 +22,19 @@  int gdb_queuesig (void);
 int gdb_handlesig (CPUState *, int);
 void gdb_exit(CPUState *, int);
 void gdb_signalled(CPUState *, int);
-int gdbserver_start(int);
 void gdbserver_fork(CPUState *);
-#else
-int gdbserver_start(const char *port);
 #endif
 /* Get or set a register.  Returns the size of the register.  */
 typedef int (*gdb_reg_cb)(CPUState *env, uint8_t *buf, int reg);
 void gdb_register_coprocessor(CPUState *env,
                               gdb_reg_cb get_reg, gdb_reg_cb set_reg,
                               int num_regs, const char *xml, int g_pos);
+#endif
+
+#ifdef CONFIG_USER_ONLY
+int gdbserver_start(int);
+#else
+int gdbserver_start(const char *port);
+#endif

 #endif
diff --git a/hw/smbios.c b/hw/smbios.c
index a3ae1de..9f2fe1b 100644
--- a/hw/smbios.c
+++ b/hw/smbios.c
@@ -167,6 +167,7 @@  static void smbios_build_type_1_fields(const char *t)
             fprintf(stderr, "Invalid SMBIOS UUID string\n");
             exit(1);
         }
+        smbios_add_field(1, offsetof(struct smbios_type_1, uuid), 16, buf);
     }
     if (get_param_value(buf, sizeof(buf), "sku", t))
         smbios_add_field(1, offsetof(struct smbios_type_1, sku_number_str),
diff --git a/kvm.h b/kvm.h
index fd8d0c1..3bee843 100644
--- a/kvm.h
+++ b/kvm.h
@@ -14,7 +14,7 @@ 
 #ifndef QEMU_KVM_H
 #define QEMU_KVM_H

-#include "config.h"
+#include "config-host.h"
 #include "qemu-queue.h"

 #ifdef CONFIG_KVM
@@ -31,6 +31,7 @@  struct kvm_run;

 int kvm_init(int smp_cpus);

+#ifdef NEED_CPU_H
 int kvm_init_vcpu(CPUState *env);

 int kvm_cpu_exec(CPUState *env);
@@ -162,3 +163,4 @@  static inline void cpu_synchronize_post_init(CPUState *env)
 }

 #endif
+#endif
diff --git a/qemu-common.h b/qemu-common.h
index 087c034..d881a39 100644
--- a/qemu-common.h
+++ b/qemu-common.h
@@ -231,6 +231,8 @@  typedef struct SSIBus SSIBus;

 typedef uint64_t pcibus_t;

+void cpu_exec_init_all(unsigned long tb_size);
+
 /* CPU save/load.  */
 void cpu_save(QEMUFile *f, void *opaque);
 int cpu_load(QEMUFile *f, void *opaque, int version_id);
diff --git a/qemu-options.hx b/qemu-options.hx
index 8450b45..c972984 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -807,12 +807,10 @@  STEXI
 Disable HPET support.
 ETEXI

-#ifdef TARGET_I386
 DEF("balloon", HAS_ARG, QEMU_OPTION_balloon,
     "-balloon none   disable balloon device\n"
     "-balloon virtio[,addr=str]\n"
     "                enable virtio balloon device (default)\n")
-#endif
 STEXI
 @item -balloon none
 @findex -balloon
diff --git a/vl.c b/vl.c
index 2eef69e..50d419f 100644
--- a/vl.c
+++ b/vl.c
@@ -120,7 +120,6 @@  int main(int argc, char **argv)
 #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"
@@ -153,14 +152,13 @@  int main(int argc, char **argv)

 #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
@@ -191,15 +189,6 @@  static int rtc_utc = 1;
 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;
@@ -209,9 +198,6 @@  CharDriverState *serial_hds[MAX_SERIAL_PORTS];
 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;
@@ -234,16 +220,9 @@  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;
@@ -468,7 +447,7 @@  static void configure_rtc_date_offset(const char
*startdate, int legacy)
     }
 }

-static void configure_rtc(QemuOpts *opts)
+static void configure_rtc(QemuOpts *opts, int driftfix)
 {
     const char *value;