#include <malloc.h>
#include <sys/timeb.h>
#include <windows.h>
-#include <winsock2.h>
-#include <ws2tcpip.h>
#define getopt_long_only getopt_long
#define memalign(align, size) malloc(size)
#endif
+#include "qemu_socket.h"
+
#ifdef CONFIG_SDL
#ifdef __APPLE__
#include <SDL/SDL.h>
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)
#else
#define MAX_CPUS 1
#endif
+int acpi_enabled = 1;
/***********************************************************/
/* x86 ISA bus support */
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__)
#error unsupported CPU
#endif
+static int64_t cpu_ticks_prev;
static int64_t cpu_ticks_offset;
static int cpu_ticks_enabled;
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;
}
}
}
}
-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)
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)
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;
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 */
#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);
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
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;
{
#ifdef _WIN32
timeKillEvent(timerID);
+ timeEndPeriod(period);
+ if (host_alarm) {
+ CloseHandle(host_alarm);
+ host_alarm = NULL;
+ }
#endif
}
#ifdef _WIN32
-#define socket_error() WSAGetLastError()
-#undef EINTR
-#define EWOULDBLOCK WSAEWOULDBLOCK
-#define EINTR WSAEINTR
-#define EINPROGRESS WSAEINPROGRESS
-
static void socket_cleanup(void)
{
WSACleanup();
#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;
#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
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;
}
#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 */
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 ||
#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) {
}
}
}
-#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],
" 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
#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"
QEMU_OPTION_usb,
QEMU_OPTION_usbdevice,
QEMU_OPTION_smp,
+ QEMU_OPTION_vnc,
+ QEMU_OPTION_no_acpi,
};
typedef struct QEMUOption {
{ "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 },
};
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
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;
}
}
}
/* 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);