| 83 |
|
|
| 84 |
#include "exec-all.h" |
#include "exec-all.h" |
| 85 |
|
|
|
//#define DO_TB_FLUSH |
|
|
|
|
| 86 |
#define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup" |
#define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup" |
| 87 |
|
|
| 88 |
//#define DEBUG_UNUSED_IOPORT |
//#define DEBUG_UNUSED_IOPORT |
| 107 |
|
|
| 108 |
const char *bios_dir = CONFIG_QEMU_SHAREDIR; |
const char *bios_dir = CONFIG_QEMU_SHAREDIR; |
| 109 |
char phys_ram_file[1024]; |
char phys_ram_file[1024]; |
|
CPUState *global_env; |
|
|
CPUState *cpu_single_env; |
|
| 110 |
void *ioport_opaque[MAX_IOPORTS]; |
void *ioport_opaque[MAX_IOPORTS]; |
| 111 |
IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS]; |
IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS]; |
| 112 |
IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS]; |
IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS]; |
| 152 |
USBPort *vm_usb_ports[MAX_VM_USB_PORTS]; |
USBPort *vm_usb_ports[MAX_VM_USB_PORTS]; |
| 153 |
USBDevice *vm_usb_hub; |
USBDevice *vm_usb_hub; |
| 154 |
static VLANState *first_vlan; |
static VLANState *first_vlan; |
| 155 |
|
int smp_cpus = 1; |
| 156 |
|
|
| 157 |
/***********************************************************/ |
/***********************************************************/ |
| 158 |
/* x86 ISA bus support */ |
/* x86 ISA bus support */ |
| 424 |
void hw_error(const char *fmt, ...) |
void hw_error(const char *fmt, ...) |
| 425 |
{ |
{ |
| 426 |
va_list ap; |
va_list ap; |
| 427 |
|
CPUState *env; |
| 428 |
|
|
| 429 |
va_start(ap, fmt); |
va_start(ap, fmt); |
| 430 |
fprintf(stderr, "qemu: hardware error: "); |
fprintf(stderr, "qemu: hardware error: "); |
| 431 |
vfprintf(stderr, fmt, ap); |
vfprintf(stderr, fmt, ap); |
| 432 |
fprintf(stderr, "\n"); |
fprintf(stderr, "\n"); |
| 433 |
|
for(env = first_cpu; env != NULL; env = env->next_cpu) { |
| 434 |
|
fprintf(stderr, "CPU #%d:\n", env->cpu_index); |
| 435 |
#ifdef TARGET_I386 |
#ifdef TARGET_I386 |
| 436 |
cpu_dump_state(global_env, stderr, fprintf, X86_DUMP_FPU | X86_DUMP_CCOP); |
cpu_dump_state(env, stderr, fprintf, X86_DUMP_FPU); |
| 437 |
#else |
#else |
| 438 |
cpu_dump_state(global_env, stderr, fprintf, 0); |
cpu_dump_state(env, stderr, fprintf, 0); |
| 439 |
#endif |
#endif |
| 440 |
|
} |
| 441 |
va_end(ap); |
va_end(ap); |
| 442 |
abort(); |
abort(); |
| 443 |
} |
} |
| 880 |
qemu_get_clock(vm_clock)) || |
qemu_get_clock(vm_clock)) || |
| 881 |
qemu_timer_expired(active_timers[QEMU_TIMER_REALTIME], |
qemu_timer_expired(active_timers[QEMU_TIMER_REALTIME], |
| 882 |
qemu_get_clock(rt_clock))) { |
qemu_get_clock(rt_clock))) { |
| 883 |
/* stop the cpu because a timer occured */ |
CPUState *env = cpu_single_env; |
| 884 |
cpu_interrupt(global_env, CPU_INTERRUPT_EXIT); |
if (env) { |
| 885 |
|
/* stop the currently executing cpu because a timer occured */ |
| 886 |
|
cpu_interrupt(env, CPU_INTERRUPT_EXIT); |
| 887 |
#ifdef USE_KQEMU |
#ifdef USE_KQEMU |
| 888 |
if (global_env->kqemu_enabled) { |
if (env->kqemu_enabled) { |
| 889 |
kqemu_cpu_interrupt(global_env); |
kqemu_cpu_interrupt(env); |
| 890 |
} |
} |
| 891 |
#endif |
#endif |
| 892 |
|
} |
| 893 |
} |
} |
| 894 |
} |
} |
| 895 |
|
|
| 2974 |
goto the_end; |
goto the_end; |
| 2975 |
} |
} |
| 2976 |
for(;;) { |
for(;;) { |
|
#if defined (DO_TB_FLUSH) |
|
|
tb_flush(global_env); |
|
|
#endif |
|
| 2977 |
len = qemu_get_byte(f); |
len = qemu_get_byte(f); |
| 2978 |
if (feof(f)) |
if (feof(f)) |
| 2979 |
break; |
break; |
| 3584 |
void qemu_system_reset_request(void) |
void qemu_system_reset_request(void) |
| 3585 |
{ |
{ |
| 3586 |
reset_requested = 1; |
reset_requested = 1; |
| 3587 |
cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT); |
if (cpu_single_env) |
| 3588 |
|
cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT); |
| 3589 |
} |
} |
| 3590 |
|
|
| 3591 |
void qemu_system_shutdown_request(void) |
void qemu_system_shutdown_request(void) |
| 3592 |
{ |
{ |
| 3593 |
shutdown_requested = 1; |
shutdown_requested = 1; |
| 3594 |
cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT); |
if (cpu_single_env) |
| 3595 |
|
cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT); |
| 3596 |
} |
} |
| 3597 |
|
|
| 3598 |
void qemu_system_powerdown_request(void) |
void qemu_system_powerdown_request(void) |
| 3599 |
{ |
{ |
| 3600 |
powerdown_requested = 1; |
powerdown_requested = 1; |
| 3601 |
cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT); |
if (cpu_single_env) |
| 3602 |
} |
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 |
|
| 3603 |
} |
} |
| 3604 |
|
|
| 3605 |
void main_loop_wait(int timeout) |
void main_loop_wait(int timeout) |
| 3680 |
qemu_get_clock(rt_clock)); |
qemu_get_clock(rt_clock)); |
| 3681 |
} |
} |
| 3682 |
|
|
| 3683 |
|
static CPUState *cur_cpu; |
| 3684 |
|
|
| 3685 |
|
static CPUState *find_next_cpu(void) |
| 3686 |
|
{ |
| 3687 |
|
CPUState *env; |
| 3688 |
|
env = cur_cpu; |
| 3689 |
|
for(;;) { |
| 3690 |
|
/* get next cpu */ |
| 3691 |
|
env = env->next_cpu; |
| 3692 |
|
if (!env) |
| 3693 |
|
env = first_cpu; |
| 3694 |
|
if (!env->cpu_halted) |
| 3695 |
|
break; |
| 3696 |
|
/* all CPUs are halted ? */ |
| 3697 |
|
if (env == cur_cpu) |
| 3698 |
|
return NULL; |
| 3699 |
|
} |
| 3700 |
|
cur_cpu = env; |
| 3701 |
|
return env; |
| 3702 |
|
} |
| 3703 |
|
|
| 3704 |
int main_loop(void) |
int main_loop(void) |
| 3705 |
{ |
{ |
| 3706 |
int ret, timeout; |
int ret, timeout; |
| 3707 |
CPUState *env = global_env; |
CPUState *env; |
| 3708 |
|
|
| 3709 |
|
cur_cpu = first_cpu; |
| 3710 |
for(;;) { |
for(;;) { |
| 3711 |
if (vm_running) { |
if (vm_running) { |
| 3712 |
ret = cpu_exec(env); |
/* find next cpu to run */ |
| 3713 |
|
/* XXX: handle HLT correctly */ |
| 3714 |
|
env = find_next_cpu(); |
| 3715 |
|
if (!env) |
| 3716 |
|
ret = EXCP_HLT; |
| 3717 |
|
else |
| 3718 |
|
ret = cpu_exec(env); |
| 3719 |
if (shutdown_requested) { |
if (shutdown_requested) { |
| 3720 |
ret = EXCP_INTERRUPT; |
ret = EXCP_INTERRUPT; |
| 3721 |
break; |
break; |
| 3798 |
" connect the host TAP network interface to VLAN 'n' and use\n" |
" connect the host TAP network interface to VLAN 'n' and use\n" |
| 3799 |
" the network script 'file' (default=%s);\n" |
" the network script 'file' (default=%s);\n" |
| 3800 |
" use 'fd=h' to connect to an already opened TAP interface\n" |
" use 'fd=h' to connect to an already opened TAP interface\n" |
| 3801 |
"-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" |
| 3802 |
" connect the vlan 'n' to another VLAN using a socket connection\n" |
" connect the vlan 'n' to another VLAN using a socket connection\n" |
| 3803 |
#endif |
#endif |
| 3804 |
"-net none use it alone to have zero network devices; if no -net option\n" |
"-net none use it alone to have zero network devices; if no -net option\n" |
| 3923 |
QEMU_OPTION_win2k_hack, |
QEMU_OPTION_win2k_hack, |
| 3924 |
QEMU_OPTION_usb, |
QEMU_OPTION_usb, |
| 3925 |
QEMU_OPTION_usbdevice, |
QEMU_OPTION_usbdevice, |
| 3926 |
|
QEMU_OPTION_smp, |
| 3927 |
}; |
}; |
| 3928 |
|
|
| 3929 |
typedef struct QEMUOption { |
typedef struct QEMUOption { |
| 3990 |
{ "pidfile", HAS_ARG, QEMU_OPTION_pidfile }, |
{ "pidfile", HAS_ARG, QEMU_OPTION_pidfile }, |
| 3991 |
{ "win2k-hack", 0, QEMU_OPTION_win2k_hack }, |
{ "win2k-hack", 0, QEMU_OPTION_win2k_hack }, |
| 3992 |
{ "usbdevice", HAS_ARG, QEMU_OPTION_usbdevice }, |
{ "usbdevice", HAS_ARG, QEMU_OPTION_usbdevice }, |
| 3993 |
|
{ "smp", HAS_ARG, QEMU_OPTION_smp }, |
| 3994 |
|
|
| 3995 |
/* temporary options */ |
/* temporary options */ |
| 3996 |
{ "usb", 0, QEMU_OPTION_usb }, |
{ "usb", 0, QEMU_OPTION_usb }, |
| 4146 |
#endif |
#endif |
| 4147 |
int i, cdrom_index; |
int i, cdrom_index; |
| 4148 |
int snapshot, linux_boot; |
int snapshot, linux_boot; |
|
CPUState *env; |
|
| 4149 |
const char *initrd_filename; |
const char *initrd_filename; |
| 4150 |
const char *hd_filename[MAX_DISKS], *fd_filename[MAX_FD]; |
const char *hd_filename[MAX_DISKS], *fd_filename[MAX_FD]; |
| 4151 |
const char *kernel_filename, *kernel_cmdline; |
const char *kernel_filename, *kernel_cmdline; |
| 4536 |
optarg); |
optarg); |
| 4537 |
usb_devices_index++; |
usb_devices_index++; |
| 4538 |
break; |
break; |
| 4539 |
|
case QEMU_OPTION_smp: |
| 4540 |
|
smp_cpus = atoi(optarg); |
| 4541 |
|
if (smp_cpus < 1 || smp_cpus > 8) { |
| 4542 |
|
fprintf(stderr, "Invalid number of CPUs\n"); |
| 4543 |
|
exit(1); |
| 4544 |
|
} |
| 4545 |
|
break; |
| 4546 |
} |
} |
| 4547 |
} |
} |
| 4548 |
} |
} |
| 4691 |
} |
} |
| 4692 |
} |
} |
| 4693 |
|
|
| 4694 |
/* init CPU state */ |
register_savevm("timer", 0, 1, timer_save, timer_load, NULL); |
|
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); |
|
| 4695 |
register_savevm("ram", 0, 1, ram_save, ram_load, NULL); |
register_savevm("ram", 0, 1, ram_save, ram_load, NULL); |
|
qemu_register_reset(main_cpu_reset, global_env); |
|
| 4696 |
|
|
| 4697 |
init_ioports(); |
init_ioports(); |
| 4698 |
cpu_calibrate_ticks(); |
cpu_calibrate_ticks(); |