X-Git-Url: http://vcs.maemo.org/git/?a=blobdiff_plain;f=vl.c;h=e828d316ad05bb696990f5946506ca254dc570de;hb=7ef4da1c3a753888e2678388150f1b846b025168;hp=8b6b33ce95683a8e033e7576d8c276e650322e21;hpb=ec530c81efea6ddb1f75758658fd6769a29c3ade;p=qemu diff --git a/vl.c b/vl.c index 8b6b33c..e828d31 100644 --- a/vl.c +++ b/vl.c @@ -66,12 +66,12 @@ #include #include #include -#include -#include #define getopt_long_only getopt_long #define memalign(align, size) malloc(size) #endif +#include "qemu_socket.h" + #ifdef CONFIG_SDL #ifdef __APPLE__ #include @@ -149,6 +149,7 @@ USBPort *vm_usb_ports[MAX_VM_USB_PORTS]; USBDevice *vm_usb_hub; static VLANState *first_vlan; int smp_cpus = 1; +int vnc_display = -1; #if defined(TARGET_SPARC) #define MAX_CPUS 16 #elif defined(TARGET_I386) @@ -156,6 +157,7 @@ int smp_cpus = 1; #else #define MAX_CPUS 1 #endif +int acpi_enabled = 1; /***********************************************************/ /* x86 ISA bus support */ @@ -517,9 +519,15 @@ int64_t cpu_get_real_ticks(void) int64_t cpu_get_real_ticks(void) { +#ifdef _WIN32 + LARGE_INTEGER ti; + QueryPerformanceCounter(&ti); + return ti.QuadPart; +#else int64_t val; asm volatile ("rdtsc" : "=A" (val)); return val; +#endif } #elif defined(__x86_64__) @@ -557,6 +565,7 @@ int64_t cpu_get_real_ticks(void) #error unsupported CPU #endif +static int64_t cpu_ticks_prev; static int64_t cpu_ticks_offset; static int cpu_ticks_enabled; @@ -565,7 +574,15 @@ static inline int64_t cpu_get_ticks(void) if (!cpu_ticks_enabled) { return cpu_ticks_offset; } else { - return cpu_get_real_ticks() + cpu_ticks_offset; + int64_t ticks; + ticks = cpu_get_real_ticks(); + if (cpu_ticks_prev > ticks) { + /* Note: non increasing ticks may happen if the host uses + software suspend */ + cpu_ticks_offset += cpu_ticks_prev - ticks; + } + cpu_ticks_prev = ticks; + return ticks + cpu_ticks_offset; } } @@ -588,17 +605,26 @@ void cpu_disable_ticks(void) } } -static int64_t get_clock(void) -{ #ifdef _WIN32 - struct _timeb tb; - _ftime(&tb); - return ((int64_t)tb.time * 1000 + (int64_t)tb.millitm) * 1000; +void cpu_calibrate_ticks(void) +{ + LARGE_INTEGER freq; + int ret; + + ret = QueryPerformanceFrequency(&freq); + if (ret == 0) { + fprintf(stderr, "Could not calibrate ticks\n"); + exit(1); + } + ticks_per_sec = freq.QuadPart; +} + #else +static int64_t get_clock(void) +{ struct timeval tv; gettimeofday(&tv, NULL); return tv.tv_sec * 1000000LL + tv.tv_usec; -#endif } void cpu_calibrate_ticks(void) @@ -607,15 +633,12 @@ void cpu_calibrate_ticks(void) usec = get_clock(); ticks = cpu_get_real_ticks(); -#ifdef _WIN32 - Sleep(50); -#else usleep(50 * 1000); -#endif usec = get_clock() - usec; ticks = cpu_get_real_ticks() - ticks; ticks_per_sec = (ticks * 1000000LL + (usec >> 1)) / usec; } +#endif /* !_WIN32 */ /* compute with 96 bit intermediate result: (a*b)/c */ uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c) @@ -663,6 +686,8 @@ QEMUClock *vm_clock; static QEMUTimer *active_timers[2]; #ifdef _WIN32 static MMRESULT timerID; +static HANDLE host_alarm = NULL; +static unsigned int period = 1; #else /* frequency of the times() clock tick */ static int timer_freq; @@ -885,6 +910,9 @@ 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))) { +#ifdef _WIN32 + SetEvent(host_alarm); +#endif CPUState *env = cpu_single_env; if (env) { /* stop the currently executing cpu because a timer occured */ @@ -945,8 +973,15 @@ static void init_timers(void) #ifdef _WIN32 { int count=0; + TIMECAPS tc; + + ZeroMemory(&tc, sizeof(TIMECAPS)); + timeGetDevCaps(&tc, sizeof(TIMECAPS)); + if (period < tc.wPeriodMin) + period = tc.wPeriodMin; + timeBeginPeriod(period); timerID = timeSetEvent(1, // interval (ms) - 0, // resolution + period, // resolution host_alarm_handler, // function (DWORD)&count, // user parameter TIME_PERIODIC | TIME_CALLBACK_FUNCTION); @@ -954,6 +989,12 @@ static void init_timers(void) perror("failed timer alarm"); exit(1); } + host_alarm = CreateEvent(NULL, FALSE, FALSE, NULL); + if (!host_alarm) { + perror("failed CreateEvent"); + exit(1); + } + ResetEvent(host_alarm); } pit_min_timer_count = ((uint64_t)10000 * PIT_FREQ) / 1000000; #else @@ -983,7 +1024,11 @@ static void init_timers(void) getitimer(ITIMER_REAL, &itv); #if defined(__linux__) - if (itv.it_interval.tv_usec > 1000) { + /* XXX: force /dev/rtc usage because even 2.6 kernels may not + have timers with 1 ms resolution. The correct solution will + be to use the POSIX real time timers available in recent + 2.6 kernels */ + if (itv.it_interval.tv_usec > 1000 || 1) { /* try to use /dev/rtc to have a faster timer */ if (start_rtc_timer() < 0) goto use_itimer; @@ -1013,6 +1058,11 @@ void quit_timers(void) { #ifdef _WIN32 timeKillEvent(timerID); + timeEndPeriod(period); + if (host_alarm) { + CloseHandle(host_alarm); + host_alarm = NULL; + } #endif } @@ -1084,12 +1134,6 @@ CharDriverState *qemu_chr_open_null(void) #ifdef _WIN32 -#define socket_error() WSAGetLastError() -#undef EINTR -#define EWOULDBLOCK WSAEWOULDBLOCK -#define EINTR WSAEINTR -#define EINPROGRESS WSAEINPROGRESS - static void socket_cleanup(void) { WSACleanup(); @@ -1141,9 +1185,6 @@ void socket_set_nonblock(int fd) #else -#define socket_error() errno -#define closesocket(s) close(s) - static int unix_write(int fd, const uint8_t *buf, int len1) { int ret, len; @@ -3131,9 +3172,7 @@ int net_client_init(const char *str) #ifdef CONFIG_SLIRP if (!strcmp(device, "user")) { if (get_param_value(buf, sizeof(buf), "hostname", p)) { - if (strlen(buf) > 32) - buf[32] = 0; - strcpy(slirp_hostname, buf); + pstrcpy(slirp_hostname, sizeof(slirp_hostname), buf); } ret = net_slirp_init(vlan); } else @@ -4371,7 +4410,7 @@ void qemu_system_powerdown_request(void) void main_loop_wait(int timeout) { IOHandlerRecord *ioh, *ioh_next; - fd_set rfds, wfds; + fd_set rfds, wfds, xfds; int ret, nfds; struct timeval tv; PollingEntry *pe; @@ -4384,7 +4423,21 @@ void main_loop_wait(int timeout) } #ifdef _WIN32 if (ret == 0 && timeout > 0) { - Sleep(timeout); + int err; + HANDLE hEvents[1]; + + hEvents[0] = host_alarm; + ret = WaitForMultipleObjects(1, hEvents, FALSE, timeout); + switch(ret) { + case WAIT_OBJECT_0 + 0: + break; + case WAIT_TIMEOUT: + break; + default: + err = GetLastError(); + fprintf(stderr, "Wait error %d %d\n", ret, err); + break; + } } #endif /* poll any events */ @@ -4392,6 +4445,7 @@ void main_loop_wait(int timeout) nfds = -1; FD_ZERO(&rfds); FD_ZERO(&wfds); + FD_ZERO(&xfds); for(ioh = first_io_handler; ioh != NULL; ioh = ioh->next) { if (ioh->fd_read && (!ioh->fd_read_poll || @@ -4413,7 +4467,12 @@ void main_loop_wait(int timeout) #else tv.tv_usec = timeout * 1000; #endif - ret = select(nfds + 1, &rfds, &wfds, NULL, &tv); +#if defined(CONFIG_SLIRP) + if (slirp_inited) { + slirp_select_fill(&nfds, &rfds, &wfds, &xfds); + } +#endif + ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv); if (ret > 0) { /* XXX: better handling of removal */ for(ioh = first_io_handler; ioh != NULL; ioh = ioh_next) { @@ -4426,30 +4485,19 @@ void main_loop_wait(int timeout) } } } -#ifdef _WIN32 - tap_win32_poll(); -#endif - #if defined(CONFIG_SLIRP) - /* XXX: merge with the previous select() */ if (slirp_inited) { - fd_set rfds, wfds, xfds; - int nfds; - struct timeval tv; - - nfds = -1; - FD_ZERO(&rfds); - FD_ZERO(&wfds); - FD_ZERO(&xfds); - slirp_select_fill(&nfds, &rfds, &wfds, &xfds); - tv.tv_sec = 0; - tv.tv_usec = 0; - ret = select(nfds + 1, &rfds, &wfds, &xfds, &tv); - if (ret >= 0) { - slirp_select_poll(&rfds, &wfds, &xfds); + if (ret < 0) { + FD_ZERO(&rfds); + FD_ZERO(&wfds); + FD_ZERO(&xfds); } + slirp_select_poll(&rfds, &wfds, &xfds); } #endif +#ifdef _WIN32 + tap_win32_poll(); +#endif if (vm_running) { qemu_run_timers(&active_timers[QEMU_TIMER_VIRTUAL], @@ -4628,6 +4676,7 @@ void help(void) " 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 + "-kernel-kqemu enable KQEMU full virtualization (default is user mode only)\n" "-no-kqemu disable KQEMU kernel module usage\n" #endif #ifdef USE_CODE_COPY @@ -4636,8 +4685,10 @@ void help(void) #ifdef TARGET_I386 "-std-vga simulate a standard VGA card with VESA Bochs Extensions\n" " (default is CL-GD5446 PCI VGA)\n" + "-no-acpi disable ACPI\n" #endif "-loadvm file start right away with a saved state (loadvm in monitor)\n" + "-vnc display start a VNC server on display\n" "\n" "During emulation, the following keys are useful:\n" "ctrl-alt-f toggle full screen\n" @@ -4721,6 +4772,8 @@ enum { QEMU_OPTION_usb, QEMU_OPTION_usbdevice, QEMU_OPTION_smp, + QEMU_OPTION_vnc, + QEMU_OPTION_no_acpi, }; typedef struct QEMUOption { @@ -4788,10 +4841,12 @@ const QEMUOption qemu_options[] = { { "win2k-hack", 0, QEMU_OPTION_win2k_hack }, { "usbdevice", HAS_ARG, QEMU_OPTION_usbdevice }, { "smp", HAS_ARG, QEMU_OPTION_smp }, + { "vnc", HAS_ARG, QEMU_OPTION_vnc }, /* temporary options */ { "usb", 0, QEMU_OPTION_usb }, { "cirrusvga", 0, QEMU_OPTION_cirrusvga }, + { "no-acpi", 0, QEMU_OPTION_no_acpi }, { NULL }, }; @@ -4863,6 +4918,9 @@ void register_machines(void) qemu_register_machine(&integratorcp926_machine); qemu_register_machine(&integratorcp1026_machine); qemu_register_machine(&versatilepb_machine); + qemu_register_machine(&versatileab_machine); +#elif defined(TARGET_SH4) + qemu_register_machine(&shix_machine); #else #error unsupported CPU #endif @@ -5383,6 +5441,16 @@ int main(int argc, char **argv) exit(1); } break; + case QEMU_OPTION_vnc: + vnc_display = atoi(optarg); + if (vnc_display < 0) { + fprintf(stderr, "Invalid VNC display\n"); + exit(1); + } + break; + case QEMU_OPTION_no_acpi: + acpi_enabled = 0; + break; } } } @@ -5548,6 +5616,8 @@ int main(int argc, char **argv) /* terminal init */ if (nographic) { dumb_display_init(ds); + } else if (vnc_display != -1) { + vnc_display_init(ds, vnc_display); } else { #if defined(CONFIG_SDL) sdl_display_init(ds, full_screen);