/*
* QEMU System Emulator
*
- * Copyright (c) 2003-2004 Fabrice Bellard
+ * Copyright (c) 2003-2005 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
#endif
#endif /* CONFIG_SDL */
+#ifdef CONFIG_COCOA
+#undef main
+#define main qemu_main
+#endif /* CONFIG_COCOA */
+
#include "disas.h"
#include "exec-all.h"
int prep_enabled = 0;
int rtc_utc = 1;
int cirrus_vga_enabled = 1;
+#ifdef TARGET_SPARC
+int graphic_width = 1024;
+int graphic_height = 768;
+#else
int graphic_width = 800;
int graphic_height = 600;
+#endif
int graphic_depth = 15;
int full_screen = 0;
TextConsole *vga_console;
CharDriverState *serial_hds[MAX_SERIAL_PORTS];
CharDriverState *parallel_hds[MAX_PARALLEL_PORTS];
+#ifdef TARGET_I386
+int win2k_install_hack = 0;
+#endif
/***********************************************************/
/* x86 ISA bus support */
target_phys_addr_t isa_mem_base = 0;
+PicState2 *isa_pic;
uint32_t default_ioport_readb(void *opaque, uint32_t address)
{
return val;
}
+#elif defined(__ia64)
+
+int64_t cpu_get_real_ticks(void)
+{
+ int64_t val;
+ asm volatile ("mov %0 = ar.itc" : "=r"(val) :: "memory");
+ return val;
+}
+
+#elif defined(__s390__)
+
+int64_t cpu_get_real_ticks(void)
+{
+ int64_t val;
+ asm volatile("stck 0(%1)" : "=m" (val) : "a" (&val) : "cc");
+ return val;
+}
+
#else
#error unsupported CPU
#endif
/* timer signal */
sigfillset(&act.sa_mask);
- act.sa_flags = 0;
+ act.sa_flags = 0;
#if defined (TARGET_I386) && defined(USE_CODE_COPY)
act.sa_flags |= SA_ONSTACK;
#endif
}
fprintf(f,
"[global]\n"
+ "private dir=%s\n"
+ "smb ports=0\n"
+ "socket address=127.0.0.1\n"
"pid directory=%s\n"
"lock directory=%s\n"
"log file=%s/log.smbd\n"
smb_dir,
smb_dir,
smb_dir,
+ smb_dir,
exported_dir
);
fclose(f);
}
env->fpuc = fpuc;
+ /* XXX: restore FPU round state */
env->fpstt = (fpus >> 11) & 7;
env->fpus = fpus & ~0x3800;
fptag ^= 0xff;
{
return 0;
}
+
+#elif defined(TARGET_MIPS)
+void cpu_save(QEMUFile *f, void *opaque)
+{
+}
+
+int cpu_load(QEMUFile *f, void *opaque, int version_id)
+{
+ return 0;
+}
+
#elif defined(TARGET_SPARC)
void cpu_save(QEMUFile *f, void *opaque)
{
qemu_put_betls(f, &env->y);
tmp = GET_PSR(env);
qemu_put_be32(f, tmp);
- qemu_put_be32s(f, &env->fsr);
+ qemu_put_betls(f, &env->fsr);
+ qemu_put_betls(f, &env->tbr);
+#ifndef TARGET_SPARC64
qemu_put_be32s(f, &env->wim);
- qemu_put_be32s(f, &env->tbr);
/* MMU */
for(i = 0; i < 16; i++)
qemu_put_be32s(f, &env->mmuregs[i]);
+#endif
}
int cpu_load(QEMUFile *f, void *opaque, int version_id)
env->cwp = 0; /* needed to ensure that the wrapping registers are
correctly updated */
PUT_PSR(env, tmp);
- qemu_get_be32s(f, &env->fsr);
+ qemu_get_betls(f, &env->fsr);
+ qemu_get_betls(f, &env->tbr);
+#ifndef TARGET_SPARC64
qemu_get_be32s(f, &env->wim);
- qemu_get_be32s(f, &env->tbr);
/* MMU */
for(i = 0; i < 16; i++)
qemu_get_be32s(f, &env->mmuregs[i]);
-
+#endif
tlb_flush(env, 1);
return 0;
}
}
/***********************************************************/
+/* machine registration */
+
+QEMUMachine *first_machine = NULL;
+
+int qemu_register_machine(QEMUMachine *m)
+{
+ QEMUMachine **pm;
+ pm = &first_machine;
+ while (*pm != NULL)
+ pm = &(*pm)->next;
+ m->next = NULL;
+ *pm = m;
+ return 0;
+}
+
+QEMUMachine *find_machine(const char *name)
+{
+ QEMUMachine *m;
+
+ for(m = first_machine; m != NULL; m = m->next) {
+ if (!strcmp(m->name, name))
+ return m;
+ }
+ return NULL;
+}
+
+/***********************************************************/
/* main execution loop */
void gui_update(void *opaque)
static QEMUResetEntry *first_reset_entry;
static int reset_requested;
static int shutdown_requested;
+static int powerdown_requested;
void qemu_register_reset(QEMUResetHandler *func, void *opaque)
{
cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT);
}
+void qemu_system_powerdown_request(void)
+{
+ powerdown_requested = 1;
+ cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT);
+}
+
static void main_cpu_reset(void *opaque)
{
#if defined(TARGET_I386) || defined(TARGET_SPARC)
if (vm_running) {
ret = cpu_exec(env);
if (shutdown_requested) {
- ret = EXCP_INTERRUPT;
+ ret = EXCP_INTERRUPT;
break;
}
if (reset_requested) {
reset_requested = 0;
qemu_system_reset();
- ret = EXCP_INTERRUPT;
+ ret = EXCP_INTERRUPT;
+ }
+ if (powerdown_requested) {
+ powerdown_requested = 0;
+ qemu_system_powerdown();
+ ret = EXCP_INTERRUPT;
}
if (ret == EXCP_DEBUG) {
vm_stop(EXCP_DEBUG);
}
/* if hlt instruction, we wait until the next IRQ */
/* XXX: use timeout computed from timers */
- if (ret == EXCP_HLT)
+ if (ret == EXCP_HLT)
timeout = 10;
else
timeout = 0;
"'disk_image' is a raw hard image image for IDE hard disk 0\n"
"\n"
"Standard options:\n"
+ "-M machine select emulated machine (-M ? for list)\n"
"-fda/-fdb file use 'file' as floppy disk 0/1 image\n"
"-hda/-hdb file use 'file' as IDE hard disk 0/1 image\n"
"-hdc/-hdd file use 'file' as IDE hard disk 2/3 image\n"
"-enable-audio enable audio support\n"
"-localtime set the real time clock to local time [default=utc]\n"
"-full-screen start in full screen\n"
-#ifdef TARGET_PPC
- "-prep Simulate a PREP system (default is PowerMAC)\n"
- "-g WxH[xDEPTH] Set the initial VGA graphic mode\n"
+#ifdef TARGET_I386
+ "-win2k-hack use it when installing Windows 2000 to avoid a disk full bug\n"
+#endif
+#if defined(TARGET_PPC) || defined(TARGET_SPARC)
+ "-g WxH[xDEPTH] Set the initial graphical resolution and depth\n"
#endif
"\n"
"Network options:\n"
"-hdachs c,h,s[,t] force hard disk 0 physical geometry and the optional BIOS\n"
" translation (t=none or lba) (usually qemu can guess them)\n"
"-L path set the directory for the BIOS and VGA BIOS\n"
+#ifdef USE_KQEMU
+ "-no-kqemu disable KQEMU kernel module usage\n"
+#endif
#ifdef USE_CODE_COPY
"-no-code-copy disable code copy acceleration\n"
#endif
enum {
QEMU_OPTION_h,
+ QEMU_OPTION_M,
QEMU_OPTION_fda,
QEMU_OPTION_fdb,
QEMU_OPTION_hda,
QEMU_OPTION_loadvm,
QEMU_OPTION_full_screen,
QEMU_OPTION_pidfile,
+ QEMU_OPTION_no_kqemu,
+ QEMU_OPTION_win2k_hack,
};
typedef struct QEMUOption {
const QEMUOption qemu_options[] = {
{ "h", 0, QEMU_OPTION_h },
+ { "M", HAS_ARG, QEMU_OPTION_M },
{ "fda", HAS_ARG, QEMU_OPTION_fda },
{ "fdb", HAS_ARG, QEMU_OPTION_fdb },
{ "hda", HAS_ARG, QEMU_OPTION_hda },
{ "hdachs", HAS_ARG, QEMU_OPTION_hdachs },
{ "L", HAS_ARG, QEMU_OPTION_L },
{ "no-code-copy", 0, QEMU_OPTION_no_code_copy },
+#ifdef USE_KQEMU
+ { "no-kqemu", 0, QEMU_OPTION_no_kqemu },
+#endif
#ifdef TARGET_PPC
{ "prep", 0, QEMU_OPTION_prep },
+#endif
+#if defined(TARGET_PPC) || defined(TARGET_SPARC)
{ "g", 1, QEMU_OPTION_g },
#endif
{ "localtime", 0, QEMU_OPTION_localtime },
{ "loadvm", HAS_ARG, QEMU_OPTION_loadvm },
{ "full-screen", 0, QEMU_OPTION_full_screen },
{ "pidfile", HAS_ARG, QEMU_OPTION_pidfile },
-
+ { "win2k-hack", 0, QEMU_OPTION_win2k_hack },
+
/* temporary options */
{ "pci", 0, QEMU_OPTION_pci },
{ "cirrusvga", 0, QEMU_OPTION_cirrusvga },
}
}
+/* XXX: currently we cannot use simultaneously different CPUs */
+void register_machines(void)
+{
+#if defined(TARGET_I386)
+ qemu_register_machine(&pc_machine);
+#elif defined(TARGET_PPC)
+ qemu_register_machine(&heathrow_machine);
+ qemu_register_machine(&core99_machine);
+ qemu_register_machine(&prep_machine);
+#elif defined(TARGET_MIPS)
+ qemu_register_machine(&mips_machine);
+#elif defined(TARGET_SPARC)
+#ifdef TARGET_SPARC64
+ qemu_register_machine(&sun4u_machine);
+#else
+ qemu_register_machine(&sun4m_machine);
+#endif
+#endif
+}
+
#define NET_IF_TUN 0
#define NET_IF_USER 1
#define NET_IF_DUMMY 2
#ifdef CONFIG_GDBSTUB
int use_gdbstub, gdbstub_port;
#endif
- int i, has_cdrom;
+ int i, cdrom_index;
int snapshot, linux_boot;
CPUState *env;
const char *initrd_filename;
char parallel_devices[MAX_PARALLEL_PORTS][128];
int parallel_device_index;
const char *loadvm = NULL;
-
+ QEMUMachine *machine;
+
#if !defined(CONFIG_SOFTMMU)
/* we never want that malloc() uses mmap() */
mallopt(M_MMAP_THRESHOLD, 4096 * 1024);
#endif
+ register_machines();
+ machine = first_machine;
initrd_filename = NULL;
for(i = 0; i < MAX_FD; i++)
fd_filename[i] = NULL;
nographic = 0;
kernel_filename = NULL;
kernel_cmdline = "";
- has_cdrom = 1;
+#ifdef TARGET_PPC
+ cdrom_index = 1;
+#else
+ cdrom_index = 2;
+#endif
cyls = heads = secs = 0;
translation = BIOS_ATA_TRANSLATION_AUTO;
pstrcpy(monitor_device, sizeof(monitor_device), "vc");
}
switch(popt->index) {
+ case QEMU_OPTION_M:
+ machine = find_machine(optarg);
+ if (!machine) {
+ QEMUMachine *m;
+ printf("Supported machines are:\n");
+ for(m = first_machine; m != NULL; m = m->next) {
+ printf("%-10s %s%s\n",
+ m->name, m->desc,
+ m == first_machine ? " (default)" : "");
+ }
+ exit(1);
+ }
+ break;
case QEMU_OPTION_initrd:
initrd_filename = optarg;
break;
case QEMU_OPTION_hda:
- hd_filename[0] = optarg;
- break;
case QEMU_OPTION_hdb:
- hd_filename[1] = optarg;
+ case QEMU_OPTION_hdc:
+ case QEMU_OPTION_hdd:
+ {
+ int hd_index;
+ hd_index = popt->index - QEMU_OPTION_hda;
+ hd_filename[hd_index] = optarg;
+ if (hd_index == cdrom_index)
+ cdrom_index = -1;
+ }
break;
case QEMU_OPTION_snapshot:
snapshot = 1;
}
}
break;
- case QEMU_OPTION_hdc:
- hd_filename[2] = optarg;
- has_cdrom = 0;
- break;
- case QEMU_OPTION_hdd:
- hd_filename[3] = optarg;
- break;
case QEMU_OPTION_cdrom:
- hd_filename[2] = optarg;
- has_cdrom = 1;
+ if (cdrom_index >= 0) {
+ hd_filename[cdrom_index] = optarg;
+ }
break;
case QEMU_OPTION_boot:
boot_device = optarg[0];
if (boot_device != 'a' &&
+#ifdef TARGET_SPARC
+ // Network boot
+ boot_device != 'n' &&
+#endif
boot_device != 'c' && boot_device != 'd') {
fprintf(stderr, "qemu: invalid boot device '%c'\n", boot_device);
exit(1);
case QEMU_OPTION_pidfile:
create_pidfile(optarg);
break;
+#ifdef TARGET_I386
+ case QEMU_OPTION_win2k_hack:
+ win2k_install_hack = 1;
+ break;
+#endif
+#ifdef USE_KQEMU
+ case QEMU_OPTION_no_kqemu:
+ kqemu_allowed = 0;
+ break;
+#endif
}
}
}
linux_boot = (kernel_filename != NULL);
- if (!linux_boot && hd_filename[0] == '\0' && hd_filename[2] == '\0' &&
+ if (!linux_boot &&
+ hd_filename[0] == '\0' &&
+ (cdrom_index >= 0 && hd_filename[cdrom_index] == '\0') &&
fd_filename[0] == '\0')
help();
phys_ram_size = ram_size + vga_ram_size + bios_size;
#ifdef CONFIG_SOFTMMU
-#ifdef _BSD
- /* mallocs are always aligned on BSD. valloc is better for correctness */
- phys_ram_base = valloc(phys_ram_size);
-#else
- phys_ram_base = memalign(TARGET_PAGE_SIZE, phys_ram_size);
-#endif
+ phys_ram_base = qemu_vmalloc(phys_ram_size);
if (!phys_ram_base) {
fprintf(stderr, "Could not allocate physical memory\n");
exit(1);
/* we always create the cdrom drive, even if no disk is there */
bdrv_init();
- if (has_cdrom) {
- bs_table[2] = bdrv_new("cdrom");
- bdrv_set_type_hint(bs_table[2], BDRV_TYPE_CDROM);
+ if (cdrom_index >= 0) {
+ bs_table[cdrom_index] = bdrv_new("cdrom");
+ bdrv_set_type_hint(bs_table[cdrom_index], BDRV_TYPE_CDROM);
}
/* open the virtual block devices */
if (nographic) {
dumb_display_init(ds);
} else {
-#ifdef CONFIG_SDL
+#if defined(CONFIG_SDL)
sdl_display_init(ds, full_screen);
+#elif defined(CONFIG_COCOA)
+ cocoa_display_init(ds, full_screen);
#else
dumb_display_init(ds);
#endif
#endif
init_timers();
-#if defined(TARGET_I386)
- pc_init(ram_size, vga_ram_size, boot_device,
- ds, fd_filename, snapshot,
- kernel_filename, kernel_cmdline, initrd_filename);
-#elif defined(TARGET_PPC)
- ppc_init(ram_size, vga_ram_size, boot_device,
- ds, fd_filename, snapshot,
- kernel_filename, kernel_cmdline, initrd_filename);
-#elif defined(TARGET_SPARC)
- sun4m_init(ram_size, vga_ram_size, boot_device,
- ds, fd_filename, snapshot,
- kernel_filename, kernel_cmdline, initrd_filename);
-#endif
+ machine->init(ram_size, vga_ram_size, boot_device,
+ ds, fd_filename, snapshot,
+ kernel_filename, kernel_cmdline, initrd_filename);
gui_timer = qemu_new_timer(rt_clock, gui_update, NULL);
qemu_mod_timer(gui_timer, qemu_get_clock(rt_clock));