diff options
author | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2005-11-21 23:25:50 +0000 |
---|---|---|
committer | bellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162> | 2005-11-21 23:25:50 +0000 |
commit | 6a00d60127dc0e1d4efadafe1feb88f05030fe52 (patch) | |
tree | db2e5b6984751b052a7d16b565fc1730a001c351 /vl.c | |
parent | f0aca8227fbdb0cec65331cb59dbe768e2586e7d (diff) |
SMP support
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1640 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'vl.c')
-rw-r--r-- | vl.c | 99 |
1 files changed, 62 insertions, 37 deletions
@@ -83,8 +83,6 @@ #include "exec-all.h" -//#define DO_TB_FLUSH - #define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup" //#define DEBUG_UNUSED_IOPORT @@ -109,8 +107,6 @@ const char *bios_dir = CONFIG_QEMU_SHAREDIR; char phys_ram_file[1024]; -CPUState *global_env; -CPUState *cpu_single_env; void *ioport_opaque[MAX_IOPORTS]; IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS]; IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS]; @@ -156,6 +152,7 @@ int usb_enabled = 0; USBPort *vm_usb_ports[MAX_VM_USB_PORTS]; USBDevice *vm_usb_hub; static VLANState *first_vlan; +int smp_cpus = 1; /***********************************************************/ /* x86 ISA bus support */ @@ -427,16 +424,20 @@ int cpu_inl(CPUState *env, int addr) void hw_error(const char *fmt, ...) { va_list ap; + CPUState *env; va_start(ap, fmt); fprintf(stderr, "qemu: hardware error: "); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); + for(env = first_cpu; env != NULL; env = env->next_cpu) { + fprintf(stderr, "CPU #%d:\n", env->cpu_index); #ifdef TARGET_I386 - cpu_dump_state(global_env, stderr, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP); + cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU); #else - cpu_dump_state(global_env, stderr, fprintf, 0); + cpu_dump_state(env, stderr, fprintf, 0); #endif + } va_end(ap); abort(); } @@ -879,13 +880,16 @@ static void host_alarm_handler(int host_signum) qemu_get_clock(vm_clock)) || qemu_timer_expired(active_timers[QEMU_TIMER_REALTIME], qemu_get_clock(rt_clock))) { - /* stop the cpu because a timer occured */ - cpu_interrupt(global_env, CPU_INTERRUPT_EXIT); + CPUState *env = cpu_single_env; + if (env) { + /* stop the currently executing cpu because a timer occured */ + cpu_interrupt(env, CPU_INTERRUPT_EXIT); #ifdef USE_KQEMU - if (global_env->kqemu_enabled) { - kqemu_cpu_interrupt(global_env); - } + if (env->kqemu_enabled) { + kqemu_cpu_interrupt(env); + } #endif + } } } @@ -2970,9 +2974,6 @@ int qemu_loadvm(const char *filename) goto the_end; } for(;;) { -#if defined (DO_TB_FLUSH) - tb_flush(global_env); -#endif len = qemu_get_byte(f); if (feof(f)) break; @@ -3583,27 +3584,22 @@ void qemu_system_reset(void) void qemu_system_reset_request(void) { reset_requested = 1; - cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT); + if (cpu_single_env) + cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT); } void qemu_system_shutdown_request(void) { shutdown_requested = 1; - cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT); + if (cpu_single_env) + 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) - CPUState *env = opaque; - cpu_reset(env); -#endif + if (cpu_single_env) + cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT); } void main_loop_wait(int timeout) @@ -3684,14 +3680,42 @@ void main_loop_wait(int timeout) qemu_get_clock(rt_clock)); } +static CPUState *cur_cpu; + +static CPUState *find_next_cpu(void) +{ + CPUState *env; + env = cur_cpu; + for(;;) { + /* get next cpu */ + env = env->next_cpu; + if (!env) + env = first_cpu; + if (!env->cpu_halted) + break; + /* all CPUs are halted ? */ + if (env == cur_cpu) + return NULL; + } + cur_cpu = env; + return env; +} + int main_loop(void) { int ret, timeout; - CPUState *env = global_env; + CPUState *env; + cur_cpu = first_cpu; for(;;) { if (vm_running) { - ret = cpu_exec(env); + /* find next cpu to run */ + /* XXX: handle HLT correctly */ + env = find_next_cpu(); + if (!env) + ret = EXCP_HLT; + else + ret = cpu_exec(env); if (shutdown_requested) { ret = EXCP_INTERRUPT; break; @@ -3774,7 +3798,7 @@ void help(void) " connect the host TAP network interface to VLAN 'n' and use\n" " the network script 'file' (default=%s);\n" " use 'fd=h' to connect to an already opened TAP interface\n" - "-net socket[,vlan=n][,fd=x][,listen=[host]:port][,connect=host:port]\n" + "-net socket[,vlan=n][,fd=h][,listen=[host]:port][,connect=host:port]\n" " connect the vlan 'n' to another VLAN using a socket connection\n" #endif "-net none use it alone to have zero network devices; if no -net option\n" @@ -3899,6 +3923,7 @@ enum { QEMU_OPTION_win2k_hack, QEMU_OPTION_usb, QEMU_OPTION_usbdevice, + QEMU_OPTION_smp, }; typedef struct QEMUOption { @@ -3965,6 +3990,7 @@ const QEMUOption qemu_options[] = { { "pidfile", HAS_ARG, QEMU_OPTION_pidfile }, { "win2k-hack", 0, QEMU_OPTION_win2k_hack }, { "usbdevice", HAS_ARG, QEMU_OPTION_usbdevice }, + { "smp", HAS_ARG, QEMU_OPTION_smp }, /* temporary options */ { "usb", 0, QEMU_OPTION_usb }, @@ -4120,7 +4146,6 @@ int main(int argc, char **argv) #endif int i, cdrom_index; int snapshot, linux_boot; - CPUState *env; const char *initrd_filename; const char *hd_filename[MAX_DISKS], *fd_filename[MAX_FD]; const char *kernel_filename, *kernel_cmdline; @@ -4511,6 +4536,13 @@ int main(int argc, char **argv) optarg); usb_devices_index++; break; + case QEMU_OPTION_smp: + smp_cpus = atoi(optarg); + if (smp_cpus < 1 || smp_cpus > 8) { + fprintf(stderr, "Invalid number of CPUs\n"); + exit(1); + } + break; } } } @@ -4659,15 +4691,8 @@ int main(int argc, char **argv) } } - /* init CPU state */ - env = cpu_init(); - global_env = env; - cpu_single_env = env; - - register_savevm("timer", 0, 1, timer_save, timer_load, env); - register_savevm("cpu", 0, 3, cpu_save, cpu_load, env); + register_savevm("timer", 0, 1, timer_save, timer_load, NULL); register_savevm("ram", 0, 1, ram_save, ram_load, NULL); - qemu_register_reset(main_cpu_reset, global_env); init_ioports(); cpu_calibrate_ticks(); |