#include <sys/stat.h>
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
#include <libutil.h>
+#include <sys/sysctl.h>
#else
#include <util.h>
#endif
#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 "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;
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;
}
/***********************************************************/
-/* x86 ISA bus support */
-
-target_phys_addr_t isa_mem_base = 0;
-PicState2 *isa_pic;
static void set_proc_name(const char *s)
{
#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 */
static int nb_hcis;
bdrv_flags &= ~BDRV_O_NATIVE_AIO;
}
- if (ro == 1) {
+ 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) {
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) {
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)
}
#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 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"
#undef DEF
#define HAS_ARG 0x0001
enum {
-#define DEF(option, opt_arg, opt_enum, opt_help) \
+#define DEF(option, opt_arg, opt_enum, opt_help, arch_mask) \
opt_enum,
#define DEFHEADING(text)
#include "qemu-options.h"
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"
#undef DEF
#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)
}
#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)
}
#elif defined(__FreeBSD__)
{
- int len;
- len = readlink("/proc/curproc/file", buf, sizeof(buf) - 1);
- if (len > 0) {
- buf[len] = 0;
+ static int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1};
+ size_t len = sizeof(buf) - 1;
+
+ *buf = '\0';
+ if (!sysctl(mib, sizeof(mib)/sizeof(*mib), buf, &len, NULL, 0) &&
+ *buf) {
+ buf[sizeof(buf) - 1] = '\0';
p = buf;
}
}
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;
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) {
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);
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_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_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:
+ if (!(kvm_available())) {
+ printf("Option %s not supported for this target\n", popt->name);
+ exit(1);
+ }
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;
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);
{
}
}
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;
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;
}
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);