X-Git-Url: https://vcs.maemo.org/git/?a=blobdiff_plain;f=vl.c;h=46ce9008d8bd840c6e26ccdf06a27e25ed079cc7;hb=30032c940a625f0aa8f04becf78e47274ec3a319;hp=7dcfb5831879a36e5e2bbb522aeea05b815a978a;hpb=36ddb83bd8fcb587e5d3b759543a13680e6836fb;p=qemu diff --git a/vl.c b/vl.c index 7dcfb58..46ce900 100644 --- a/vl.c +++ b/vl.c @@ -1,8 +1,8 @@ /* * QEMU System Emulator - * + * * Copyright (c) 2003-2007 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 * in the Software without restriction, including without limitation the rights @@ -42,11 +42,15 @@ #include #include #include +#include +#include #ifdef _BSD #include #ifndef __APPLE__ #include #endif +#elif defined (__GLIBC__) && defined (__FreeBSD_kernel__) +#include #else #ifndef __sun__ #include @@ -54,13 +58,18 @@ #include #include #include + +/* For the benefit of older linux systems which don't supply it, + we use a local copy of hpet.h. */ +/* #include */ +#include "hpet.h" + #include #include #else #include #include #include -#include #include #include #include @@ -73,6 +82,9 @@ #include #endif #endif +#else +#include +int inet_aton(const char *cp, struct in_addr *ia); #endif #if defined(CONFIG_SLIRP) @@ -153,7 +165,6 @@ int ram_size; int pit_min_timer_count = 0; int nb_nics; NICInfo nd_table[MAX_NICS]; -QEMUTimer *gui_timer; int vm_running; int rtc_utc = 1; int cirrus_vga_enabled = 1; @@ -196,12 +207,18 @@ const char *option_rom[MAX_OPTION_ROMS]; int nb_option_roms; int semihosting_enabled = 0; int autostart = 1; +#ifdef TARGET_ARM +int old_param = 0; +#endif const char *qemu_name; +int alt_grab = 0; #ifdef TARGET_SPARC unsigned int nb_prom_envs = 0; const char *prom_envs[MAX_PROM_ENVS]; #endif +#define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR) + /***********************************************************/ /* x86 ISA bus support */ @@ -270,7 +287,7 @@ void init_ioports(void) } /* size is the word size in byte */ -int register_ioport_read(int start, int length, int size, +int register_ioport_read(int start, int length, int size, IOPortReadFunc *func, void *opaque) { int i, bsize; @@ -295,7 +312,7 @@ int register_ioport_read(int start, int length, int size, } /* size is the word size in byte */ -int register_ioport_write(int start, int length, int size, +int register_ioport_write(int start, int length, int size, IOPortWriteFunc *func, void *opaque) { int i, bsize; @@ -341,7 +358,7 @@ void cpu_outb(CPUState *env, int addr, int val) #ifdef DEBUG_IOPORT if (loglevel & CPU_LOG_IOPORT) fprintf(logfile, "outb: %04x %02x\n", addr, val); -#endif +#endif ioport_write_table[0][addr](ioport_opaque[addr], addr, val); #ifdef USE_KQEMU if (env) @@ -354,7 +371,7 @@ void cpu_outw(CPUState *env, int addr, int val) #ifdef DEBUG_IOPORT if (loglevel & CPU_LOG_IOPORT) fprintf(logfile, "outw: %04x %04x\n", addr, val); -#endif +#endif ioport_write_table[1][addr](ioport_opaque[addr], addr, val); #ifdef USE_KQEMU if (env) @@ -617,7 +634,7 @@ uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c) uint32_t high, low; #else uint32_t low, high; -#endif +#endif } l; } u, res; uint64_t rl, rh; @@ -683,7 +700,7 @@ static int64_t get_clock(void) struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return ts.tv_sec * 1000000000LL + ts.tv_nsec; - } else + } else #endif { /* XXX: using gettimeofday leads to problems if the date @@ -757,7 +774,7 @@ void cpu_disable_ticks(void) /***********************************************************/ /* timers */ - + #define QEMU_TIMER_REALTIME 0 #define QEMU_TIMER_VIRTUAL 1 @@ -774,18 +791,158 @@ struct QEMUTimer { struct QEMUTimer *next; }; -QEMUClock *rt_clock; -QEMUClock *vm_clock; +struct qemu_alarm_timer { + char const *name; + unsigned int flags; + + int (*start)(struct qemu_alarm_timer *t); + void (*stop)(struct qemu_alarm_timer *t); + void (*rearm)(struct qemu_alarm_timer *t); + void *priv; +}; + +#define ALARM_FLAG_DYNTICKS 0x1 + +static inline int alarm_has_dynticks(struct qemu_alarm_timer *t) +{ + return t->flags & ALARM_FLAG_DYNTICKS; +} + +static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t) +{ + if (!alarm_has_dynticks(t)) + return; + + t->rearm(t); +} + +/* TODO: MIN_TIMER_REARM_US should be optimized */ +#define MIN_TIMER_REARM_US 250 + +static struct qemu_alarm_timer *alarm_timer; -static QEMUTimer *active_timers[2]; #ifdef _WIN32 -static MMRESULT timerID; -static HANDLE host_alarm = NULL; -static unsigned int period = 1; + +struct qemu_alarm_win32 { + MMRESULT timerId; + HANDLE host_alarm; + unsigned int period; +} alarm_win32_data = {0, NULL, -1}; + +static int win32_start_timer(struct qemu_alarm_timer *t); +static void win32_stop_timer(struct qemu_alarm_timer *t); +static void win32_rearm_timer(struct qemu_alarm_timer *t); + #else -/* frequency of the times() clock tick */ -static int timer_freq; + +static int unix_start_timer(struct qemu_alarm_timer *t); +static void unix_stop_timer(struct qemu_alarm_timer *t); + +#ifdef __linux__ + +static int dynticks_start_timer(struct qemu_alarm_timer *t); +static void dynticks_stop_timer(struct qemu_alarm_timer *t); +static void dynticks_rearm_timer(struct qemu_alarm_timer *t); + +static int hpet_start_timer(struct qemu_alarm_timer *t); +static void hpet_stop_timer(struct qemu_alarm_timer *t); + +static int rtc_start_timer(struct qemu_alarm_timer *t); +static void rtc_stop_timer(struct qemu_alarm_timer *t); + +#endif /* __linux__ */ + +#endif /* _WIN32 */ + +static struct qemu_alarm_timer alarm_timers[] = { +#ifndef _WIN32 +#ifdef __linux__ + {"dynticks", ALARM_FLAG_DYNTICKS, dynticks_start_timer, + dynticks_stop_timer, dynticks_rearm_timer, NULL}, + /* HPET - if available - is preferred */ + {"hpet", 0, hpet_start_timer, hpet_stop_timer, NULL, NULL}, + /* ...otherwise try RTC */ + {"rtc", 0, rtc_start_timer, rtc_stop_timer, NULL, NULL}, +#endif + {"unix", 0, unix_start_timer, unix_stop_timer, NULL, NULL}, +#else + {"dynticks", ALARM_FLAG_DYNTICKS, win32_start_timer, + win32_stop_timer, win32_rearm_timer, &alarm_win32_data}, + {"win32", 0, win32_start_timer, + win32_stop_timer, NULL, &alarm_win32_data}, #endif + {NULL, } +}; + +static void show_available_alarms() +{ + int i; + + printf("Available alarm timers, in order of precedence:\n"); + for (i = 0; alarm_timers[i].name; i++) + printf("%s\n", alarm_timers[i].name); +} + +static void configure_alarms(char const *opt) +{ + int i; + int cur = 0; + int count = (sizeof(alarm_timers) / sizeof(*alarm_timers)) - 1; + char *arg; + char *name; + + if (!strcmp(opt, "help")) { + show_available_alarms(); + exit(0); + } + + arg = strdup(opt); + + /* Reorder the array */ + name = strtok(arg, ","); + while (name) { + struct qemu_alarm_timer tmp; + + for (i = 0; i < count && alarm_timers[i].name; i++) { + if (!strcmp(alarm_timers[i].name, name)) + break; + } + + if (i == count) { + fprintf(stderr, "Unknown clock %s\n", name); + goto next; + } + + if (i < cur) + /* Ignore */ + goto next; + + /* Swap */ + tmp = alarm_timers[i]; + alarm_timers[i] = alarm_timers[cur]; + alarm_timers[cur] = tmp; + + cur++; +next: + name = strtok(NULL, ","); + } + + free(arg); + + if (cur) { + /* Disable remaining timers */ + for (i = cur; i < count; i++) + alarm_timers[i].name = NULL; + } + + /* debug */ + show_available_alarms(); +} + +QEMUClock *rt_clock; +QEMUClock *vm_clock; + +static QEMUTimer *active_timers[2]; QEMUClock *qemu_new_clock(int type) { @@ -831,6 +988,8 @@ void qemu_del_timer(QEMUTimer *ts) } pt = &t->next; } + + qemu_rearm_alarm_timer(alarm_timer); } /* modify the current timer so that it will be fired when current_time @@ -849,7 +1008,7 @@ void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time) t = *pt; if (!t) break; - if (t->expire_time > expire_time) + if (t->expire_time > expire_time) break; pt = &t->next; } @@ -878,7 +1037,7 @@ static inline int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time static void qemu_run_timers(QEMUTimer **ptimer_head, int64_t current_time) { QEMUTimer *ts; - + for(;;) { ts = *ptimer_head; if (!ts || ts->expire_time > current_time) @@ -886,10 +1045,11 @@ static void qemu_run_timers(QEMUTimer **ptimer_head, int64_t current_time) /* remove timer from the list before calling the callback */ *ptimer_head = ts->next; ts->next = NULL; - + /* run the callback (the timer list can be modified) */ ts->cb(ts->opaque); } + qemu_rearm_alarm_timer(alarm_timer); } int64_t qemu_get_clock(QEMUClock *clock) @@ -962,7 +1122,7 @@ static int timer_load(QEMUFile *f, void *opaque, int version_id) } #ifdef _WIN32 -void CALLBACK host_alarm_handler(UINT uTimerID, UINT uMsg, +void CALLBACK host_alarm_handler(UINT uTimerID, UINT uMsg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2) #else static void host_alarm_handler(int host_signum) @@ -997,12 +1157,14 @@ static void host_alarm_handler(int host_signum) last_clock = ti; } #endif - if (qemu_timer_expired(active_timers[QEMU_TIMER_VIRTUAL], + if (alarm_has_dynticks(alarm_timer) || + qemu_timer_expired(active_timers[QEMU_TIMER_VIRTUAL], qemu_get_clock(vm_clock)) || qemu_timer_expired(active_timers[QEMU_TIMER_REALTIME], qemu_get_clock(rt_clock))) { #ifdef _WIN32 - SetEvent(host_alarm); + struct qemu_alarm_win32 *data = ((struct qemu_alarm_timer*)dwUser)->priv; + SetEvent(data->host_alarm); #endif CPUState *env = cpu_single_env; if (env) { @@ -1017,17 +1179,107 @@ static void host_alarm_handler(int host_signum) } } +static uint64_t qemu_next_deadline(void) +{ + int64_t nearest_delta_us = UINT64_MAX; + int64_t vmdelta_us; + + if (active_timers[QEMU_TIMER_REALTIME]) + nearest_delta_us = (active_timers[QEMU_TIMER_REALTIME]->expire_time - + qemu_get_clock(rt_clock))*1000; + + if (active_timers[QEMU_TIMER_VIRTUAL]) { + /* round up */ + vmdelta_us = (active_timers[QEMU_TIMER_VIRTUAL]->expire_time - + qemu_get_clock(vm_clock)+999)/1000; + if (vmdelta_us < nearest_delta_us) + nearest_delta_us = vmdelta_us; + } + + /* Avoid arming the timer to negative, zero, or too low values */ + if (nearest_delta_us <= MIN_TIMER_REARM_US) + nearest_delta_us = MIN_TIMER_REARM_US; + + return nearest_delta_us; +} + #ifndef _WIN32 #if defined(__linux__) #define RTC_FREQ 1024 -static int rtc_fd; +static void enable_sigio_timer(int fd) +{ + struct sigaction act; + + /* timer signal */ + sigfillset(&act.sa_mask); + act.sa_flags = 0; +#if defined (TARGET_I386) && defined(USE_CODE_COPY) + act.sa_flags |= SA_ONSTACK; +#endif + act.sa_handler = host_alarm_handler; + + sigaction(SIGIO, &act, NULL); + fcntl(fd, F_SETFL, O_ASYNC); + fcntl(fd, F_SETOWN, getpid()); +} + +static int hpet_start_timer(struct qemu_alarm_timer *t) +{ + struct hpet_info info; + int r, fd; + + fd = open("/dev/hpet", O_RDONLY); + if (fd < 0) + return -1; + + /* Set frequency */ + r = ioctl(fd, HPET_IRQFREQ, RTC_FREQ); + if (r < 0) { + fprintf(stderr, "Could not configure '/dev/hpet' to have a 1024Hz timer. This is not a fatal\n" + "error, but for better emulation accuracy type:\n" + "'echo 1024 > /proc/sys/dev/hpet/max-user-freq' as root.\n"); + goto fail; + } + + /* Check capabilities */ + r = ioctl(fd, HPET_INFO, &info); + if (r < 0) + goto fail; + + /* Enable periodic mode */ + r = ioctl(fd, HPET_EPI, 0); + if (info.hi_flags && (r < 0)) + goto fail; + + /* Enable interrupt */ + r = ioctl(fd, HPET_IE_ON, 0); + if (r < 0) + goto fail; + + enable_sigio_timer(fd); + t->priv = (void *)(long)fd; + + return 0; +fail: + close(fd); + return -1; +} + +static void hpet_stop_timer(struct qemu_alarm_timer *t) +{ + int fd = (long)t->priv; + + close(fd); +} -static int start_rtc_timer(void) +static int rtc_start_timer(struct qemu_alarm_timer *t) { - rtc_fd = open("/dev/rtc", O_RDONLY); + int rtc_fd; + + TFR(rtc_fd = open("/dev/rtc", O_RDONLY)); if (rtc_fd < 0) return -1; if (ioctl(rtc_fd, RTC_IRQP_SET, RTC_FREQ) < 0) { @@ -1041,117 +1293,250 @@ static int start_rtc_timer(void) close(rtc_fd); return -1; } - pit_min_timer_count = PIT_FREQ / RTC_FREQ; + + enable_sigio_timer(rtc_fd); + + t->priv = (void *)(long)rtc_fd; + return 0; } -#else +static void rtc_stop_timer(struct qemu_alarm_timer *t) +{ + int rtc_fd = (long)t->priv; -static int start_rtc_timer(void) + close(rtc_fd); +} + +static int dynticks_start_timer(struct qemu_alarm_timer *t) { - return -1; + struct sigevent ev; + timer_t host_timer; + struct sigaction act; + + sigfillset(&act.sa_mask); + act.sa_flags = 0; +#if defined(TARGET_I386) && defined(USE_CODE_COPY) + act.sa_flags |= SA_ONSTACK; +#endif + act.sa_handler = host_alarm_handler; + + sigaction(SIGALRM, &act, NULL); + + ev.sigev_value.sival_int = 0; + ev.sigev_notify = SIGEV_SIGNAL; + ev.sigev_signo = SIGALRM; + + if (timer_create(CLOCK_REALTIME, &ev, &host_timer)) { + perror("timer_create"); + + /* disable dynticks */ + fprintf(stderr, "Dynamic Ticks disabled\n"); + + return -1; + } + + t->priv = (void *)host_timer; + + return 0; } -#endif /* !defined(__linux__) */ +static void dynticks_stop_timer(struct qemu_alarm_timer *t) +{ + timer_t host_timer = (timer_t)t->priv; -#endif /* !defined(_WIN32) */ + timer_delete(host_timer); +} -static void init_timer_alarm(void) +static void dynticks_rearm_timer(struct qemu_alarm_timer *t) { -#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) - period, // resolution - host_alarm_handler, // function - (DWORD)&count, // user parameter - TIME_PERIODIC | TIME_CALLBACK_FUNCTION); - if( !timerID ) { - perror("failed timer alarm"); - exit(1); - } - host_alarm = CreateEvent(NULL, FALSE, FALSE, NULL); - if (!host_alarm) { - perror("failed CreateEvent"); - exit(1); - } - qemu_add_wait_object(host_alarm, NULL, NULL); + timer_t host_timer = (timer_t)t->priv; + struct itimerspec timeout; + int64_t nearest_delta_us = INT64_MAX; + int64_t current_us; + + if (!active_timers[QEMU_TIMER_REALTIME] && + !active_timers[QEMU_TIMER_VIRTUAL]) + return; + + nearest_delta_us = qemu_next_deadline(); + + /* check whether a timer is already running */ + if (timer_gettime(host_timer, &timeout)) { + perror("gettime"); + fprintf(stderr, "Internal timer error: aborting\n"); + exit(1); } - pit_min_timer_count = ((uint64_t)10000 * PIT_FREQ) / 1000000; -#else - { - struct sigaction act; - struct itimerval itv; - - /* get times() syscall frequency */ - timer_freq = sysconf(_SC_CLK_TCK); - - /* timer signal */ - sigfillset(&act.sa_mask); - act.sa_flags = 0; -#if defined (TARGET_I386) && defined(USE_CODE_COPY) - act.sa_flags |= SA_ONSTACK; -#endif - act.sa_handler = host_alarm_handler; - sigaction(SIGALRM, &act, NULL); + current_us = timeout.it_value.tv_sec * 1000000 + timeout.it_value.tv_nsec/1000; + if (current_us && current_us <= nearest_delta_us) + return; - itv.it_interval.tv_sec = 0; - itv.it_interval.tv_usec = 999; /* for i386 kernel 2.6 to get 1 ms */ - itv.it_value.tv_sec = 0; - itv.it_value.tv_usec = 10 * 1000; - setitimer(ITIMER_REAL, &itv, NULL); - /* we probe the tick duration of the kernel to inform the user if - the emulated kernel requested a too high timer frequency */ - getitimer(ITIMER_REAL, &itv); + timeout.it_interval.tv_sec = 0; + timeout.it_interval.tv_nsec = 0; /* 0 for one-shot timer */ + timeout.it_value.tv_sec = nearest_delta_us / 1000000; + timeout.it_value.tv_nsec = (nearest_delta_us % 1000000) * 1000; + if (timer_settime(host_timer, 0 /* RELATIVE */, &timeout, NULL)) { + perror("settime"); + fprintf(stderr, "Internal timer error: aborting\n"); + exit(1); + } +} -#if defined(__linux__) - /* 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; - /* disable itimer */ - itv.it_interval.tv_sec = 0; - itv.it_interval.tv_usec = 0; - itv.it_value.tv_sec = 0; - itv.it_value.tv_usec = 0; - setitimer(ITIMER_REAL, &itv, NULL); - - /* use the RTC */ - sigaction(SIGIO, &act, NULL); - fcntl(rtc_fd, F_SETFL, O_ASYNC); - fcntl(rtc_fd, F_SETOWN, getpid()); - } else #endif /* defined(__linux__) */ - { - use_itimer: - pit_min_timer_count = ((uint64_t)itv.it_interval.tv_usec * - PIT_FREQ) / 1000000; - } - } + +static int unix_start_timer(struct qemu_alarm_timer *t) +{ + struct sigaction act; + struct itimerval itv; + int err; + + /* timer signal */ + sigfillset(&act.sa_mask); + act.sa_flags = 0; +#if defined(TARGET_I386) && defined(USE_CODE_COPY) + act.sa_flags |= SA_ONSTACK; #endif + act.sa_handler = host_alarm_handler; + + sigaction(SIGALRM, &act, NULL); + + itv.it_interval.tv_sec = 0; + /* for i386 kernel 2.6 to get 1 ms */ + itv.it_interval.tv_usec = 999; + itv.it_value.tv_sec = 0; + itv.it_value.tv_usec = 10 * 1000; + + err = setitimer(ITIMER_REAL, &itv, NULL); + if (err) + return -1; + + return 0; } -void quit_timers(void) +static void unix_stop_timer(struct qemu_alarm_timer *t) { + struct itimerval itv; + + memset(&itv, 0, sizeof(itv)); + setitimer(ITIMER_REAL, &itv, NULL); +} + +#endif /* !defined(_WIN32) */ + #ifdef _WIN32 - timeKillEvent(timerID); - timeEndPeriod(period); - if (host_alarm) { - CloseHandle(host_alarm); - host_alarm = NULL; + +static int win32_start_timer(struct qemu_alarm_timer *t) +{ + TIMECAPS tc; + struct qemu_alarm_win32 *data = t->priv; + UINT flags; + + data->host_alarm = CreateEvent(NULL, FALSE, FALSE, NULL); + if (!data->host_alarm) { + perror("Failed CreateEvent"); + return -1; + } + + memset(&tc, 0, sizeof(tc)); + timeGetDevCaps(&tc, sizeof(tc)); + + if (data->period < tc.wPeriodMin) + data->period = tc.wPeriodMin; + + timeBeginPeriod(data->period); + + flags = TIME_CALLBACK_FUNCTION; + if (alarm_has_dynticks(t)) + flags |= TIME_ONESHOT; + else + flags |= TIME_PERIODIC; + + data->timerId = timeSetEvent(1, // interval (ms) + data->period, // resolution + host_alarm_handler, // function + (DWORD)t, // parameter + flags); + + if (!data->timerId) { + perror("Failed to initialize win32 alarm timer"); + + timeEndPeriod(data->period); + CloseHandle(data->host_alarm); + return -1; + } + + qemu_add_wait_object(data->host_alarm, NULL, NULL); + + return 0; +} + +static void win32_stop_timer(struct qemu_alarm_timer *t) +{ + struct qemu_alarm_win32 *data = t->priv; + + timeKillEvent(data->timerId); + timeEndPeriod(data->period); + + CloseHandle(data->host_alarm); +} + +static void win32_rearm_timer(struct qemu_alarm_timer *t) +{ + struct qemu_alarm_win32 *data = t->priv; + uint64_t nearest_delta_us; + + if (!active_timers[QEMU_TIMER_REALTIME] && + !active_timers[QEMU_TIMER_VIRTUAL]) + return; + + nearest_delta_us = qemu_next_deadline(); + nearest_delta_us /= 1000; + + timeKillEvent(data->timerId); + + data->timerId = timeSetEvent(1, + data->period, + host_alarm_handler, + (DWORD)t, + TIME_ONESHOT | TIME_PERIODIC); + + if (!data->timerId) { + perror("Failed to re-arm win32 alarm timer"); + + timeEndPeriod(data->period); + CloseHandle(data->host_alarm); + exit(1); } -#endif +} + +#endif /* _WIN32 */ + +static void init_timer_alarm(void) +{ + struct qemu_alarm_timer *t; + int i, err = -1; + + for (i = 0; alarm_timers[i].name; i++) { + t = &alarm_timers[i]; + + err = t->start(t); + if (!err) + break; + } + + if (err) { + fprintf(stderr, "Unable to find any suitable alarm timer.\n"); + fprintf(stderr, "Terminating\n"); + exit(1); + } + + alarm_timer = t; +} + +void quit_timers(void) +{ + alarm_timer->stop(alarm_timer); + alarm_timer = NULL; } /***********************************************************/ @@ -1221,8 +1606,8 @@ void qemu_chr_send_event(CharDriverState *s, int event) s->chr_send_event(s, event); } -void qemu_chr_add_handlers(CharDriverState *s, - IOCanRWHandler *fd_can_read, +void qemu_chr_add_handlers(CharDriverState *s, + IOCanRWHandler *fd_can_read, IOReadHandler *fd_read, IOEventHandler *fd_event, void *opaque) @@ -1234,7 +1619,7 @@ void qemu_chr_add_handlers(CharDriverState *s, if (s->chr_update_read_handler) s->chr_update_read_handler(s); } - + static int null_chr_write(CharDriverState *chr, const uint8_t *buf, int len) { return len; @@ -1362,6 +1747,8 @@ static int mux_proc_byte(CharDriverState *chr, MuxDriver *d, int ch) if (bs_table[i]) bdrv_commit(bs_table[i]); } + if (mtd_bdrv) + bdrv_commit(mtd_bdrv); } break; case 'b': @@ -1487,7 +1874,7 @@ static int socket_init(void) static int send_all(int fd, const uint8_t *buf, int len1) { int ret, len; - + len = len1; while (len > 0) { ret = send(fd, buf, len, 0); @@ -1577,7 +1964,7 @@ static void fd_chr_read(void *opaque) FDCharDriver *s = chr->opaque; int size, len; uint8_t buf[1024]; - + len = sizeof(buf); if (len > s->max_size) len = s->max_size; @@ -1601,7 +1988,7 @@ static void fd_chr_update_read_handler(CharDriverState *chr) if (s->fd_in >= 0) { if (nographic && s->fd_in == 0) { } else { - qemu_set_fd_handler2(s->fd_in, fd_chr_read_poll, + qemu_set_fd_handler2(s->fd_in, fd_chr_read_poll, fd_chr_read, NULL, chr); } } @@ -1636,7 +2023,7 @@ static CharDriverState *qemu_chr_open_file_out(const char *file_out) { int fd_out; - fd_out = open(file_out, O_WRONLY | O_TRUNC | O_CREAT | O_BINARY, 0666); + TFR(fd_out = open(file_out, O_WRONLY | O_TRUNC | O_CREAT | O_BINARY, 0666)); if (fd_out < 0) return NULL; return qemu_chr_open_fd(-1, fd_out); @@ -1649,14 +2036,14 @@ static CharDriverState *qemu_chr_open_pipe(const char *filename) snprintf(filename_in, 256, "%s.in", filename); snprintf(filename_out, 256, "%s.out", filename); - fd_in = open(filename_in, O_RDWR | O_BINARY); - fd_out = open(filename_out, O_RDWR | O_BINARY); + TFR(fd_in = open(filename_in, O_RDWR | O_BINARY)); + TFR(fd_out = open(filename_out, O_RDWR | O_BINARY)); if (fd_in < 0 || fd_out < 0) { if (fd_in >= 0) close(fd_in); if (fd_out >= 0) close(fd_out); - fd_in = fd_out = open(filename, O_RDWR | O_BINARY); + TFR(fd_in = fd_out = open(filename, O_RDWR | O_BINARY)); if (fd_in < 0) return NULL; } @@ -1738,7 +2125,7 @@ static void term_init(void) tty.c_cflag |= CS8; tty.c_cc[VMIN] = 1; tty.c_cc[VTIME] = 0; - + tcsetattr (0, TCSANOW, &tty); atexit(term_exit); @@ -1760,18 +2147,20 @@ static CharDriverState *qemu_chr_open_stdio(void) return chr; } -#if defined(__linux__) +#if defined(__linux__) || defined(__sun__) static CharDriverState *qemu_chr_open_pty(void) { struct termios tty; char slave_name[1024]; int master_fd, slave_fd; - + +#if defined(__linux__) /* Not satisfying */ if (openpty(&master_fd, &slave_fd, slave_name, NULL, NULL) < 0) { return NULL; } - +#endif + /* Disabling local echo and line-buffered output */ tcgetattr (master_fd, &tty); tty.c_lflag &= ~(ECHO|ICANON|ISIG); @@ -1783,14 +2172,14 @@ static CharDriverState *qemu_chr_open_pty(void) return qemu_chr_open_fd(master_fd, master_fd); } -static void tty_serial_init(int fd, int speed, +static void tty_serial_init(int fd, int speed, int parity, int data_bits, int stop_bits) { struct termios tty; speed_t spd; #if 0 - printf("tty_serial_init: speed=%d parity=%c data=%d stop=%d\n", + printf("tty_serial_init: speed=%d parity=%c data=%d stop=%d\n", speed, parity, data_bits, stop_bits); #endif tcgetattr (fd, &tty); @@ -1871,19 +2260,19 @@ static void tty_serial_init(int fd, int speed, } if (stop_bits == 2) tty.c_cflag |= CSTOPB; - + tcsetattr (fd, TCSANOW, &tty); } static int tty_serial_ioctl(CharDriverState *chr, int cmd, void *arg) { FDCharDriver *s = chr->opaque; - + switch(cmd) { case CHR_IOCTL_SERIAL_SET_PARAMS: { QEMUSerialSetParams *ssp = arg; - tty_serial_init(s->fd_in, ssp->speed, ssp->parity, + tty_serial_init(s->fd_in, ssp->speed, ssp->parity, ssp->data_bits, ssp->stop_bits); } break; @@ -1905,19 +2294,26 @@ static CharDriverState *qemu_chr_open_tty(const char *filename) CharDriverState *chr; int fd; - fd = open(filename, O_RDWR | O_NONBLOCK); - if (fd < 0) - return NULL; + TFR(fd = open(filename, O_RDWR | O_NONBLOCK)); fcntl(fd, F_SETFL, O_NONBLOCK); tty_serial_init(fd, 115200, 'N', 8, 1); chr = qemu_chr_open_fd(fd, fd); - if (!chr) + if (!chr) { + close(fd); return NULL; + } chr->chr_ioctl = tty_serial_ioctl; qemu_chr_reset(chr); return chr; } +#else /* ! __linux__ && ! __sun__ */ +static CharDriverState *qemu_chr_open_pty(void) +{ + return NULL; +} +#endif /* __linux__ || __sun__ */ +#if defined(__linux__) typedef struct { int fd; int mode; @@ -2028,7 +2424,7 @@ static CharDriverState *qemu_chr_open_pp(const char *filename) ParallelCharDriver *drv; int fd; - fd = open(filename, O_RDWR); + TFR(fd = open(filename, O_RDWR)); if (fd < 0) return NULL; @@ -2060,17 +2456,10 @@ static CharDriverState *qemu_chr_open_pp(const char *filename) return chr; } +#endif /* __linux__ */ -#else -static CharDriverState *qemu_chr_open_pty(void) -{ - return NULL; -} -#endif - -#endif /* !defined(_WIN32) */ +#else /* _WIN32 */ -#ifdef _WIN32 typedef struct { int max_size; HANDLE hcom, hrecv, hsend; @@ -2117,7 +2506,7 @@ static int win_chr_init(CharDriverState *chr, const char *filename) COMSTAT comstat; DWORD size; DWORD err; - + s->hsend = CreateEvent(NULL, TRUE, FALSE, NULL); if (!s->hsend) { fprintf(stderr, "Failed CreateEvent\n"); @@ -2136,12 +2525,12 @@ static int win_chr_init(CharDriverState *chr, const char *filename) s->hcom = NULL; goto fail; } - + if (!SetupComm(s->hcom, NRECVBUF, NSENDBUF)) { fprintf(stderr, "Failed SetupComm\n"); goto fail; } - + ZeroMemory(&comcfg, sizeof(COMMCONFIG)); size = sizeof(COMMCONFIG); GetDefaultCommConfig(filename, &comcfg, &size); @@ -2163,7 +2552,7 @@ static int win_chr_init(CharDriverState *chr, const char *filename) fprintf(stderr, "Failed SetCommTimeouts\n"); goto fail; } - + if (!ClearCommError(s->hcom, &err, &comstat)) { fprintf(stderr, "Failed ClearCommError\n"); goto fail; @@ -2224,7 +2613,7 @@ static void win_chr_readfile(CharDriverState *chr) int ret, err; uint8_t buf[1024]; DWORD size; - + ZeroMemory(&s->orecv, sizeof(s->orecv)); s->orecv.hEvent = s->hrecv; ret = ReadFile(s->hcom, buf, s->len, &size, &s->orecv); @@ -2248,7 +2637,7 @@ static void win_chr_read(CharDriverState *chr) s->len = s->max_size; if (s->len == 0) return; - + win_chr_readfile(chr); } @@ -2258,7 +2647,7 @@ static int win_chr_poll(void *opaque) WinCharState *s = chr->opaque; COMSTAT status; DWORD comerr; - + ClearCommError(s->hcom, &comerr, &status); if (status.cbInQue > 0) { s->len = status.cbInQue; @@ -2273,7 +2662,7 @@ static CharDriverState *qemu_chr_open_win(const char *filename) { CharDriverState *chr; WinCharState *s; - + chr = qemu_mallocz(sizeof(CharDriverState)); if (!chr) return NULL; @@ -2318,7 +2707,7 @@ static int win_chr_pipe_init(CharDriverState *chr, const char *filename) int ret; DWORD size; char openname[256]; - + s->fpipe = TRUE; s->hsend = CreateEvent(NULL, TRUE, FALSE, NULL); @@ -2331,7 +2720,7 @@ static int win_chr_pipe_init(CharDriverState *chr, const char *filename) fprintf(stderr, "Failed CreateEvent\n"); goto fail; } - + snprintf(openname, sizeof(openname), "\\\\.\\pipe\\%s", filename); s->hcom = CreateNamedPipe(openname, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | @@ -2390,7 +2779,7 @@ static CharDriverState *qemu_chr_open_win_pipe(const char *filename) chr->opaque = s; chr->chr_write = win_chr_write; chr->chr_close = win_chr_close; - + if (win_chr_pipe_init(chr, filename) < 0) { free(s); free(chr); @@ -2428,7 +2817,7 @@ static CharDriverState *qemu_chr_open_win_con(const char *filename) static CharDriverState *qemu_chr_open_win_file_out(const char *file_out) { HANDLE fd_out; - + fd_out = CreateFile(file_out, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (fd_out == INVALID_HANDLE_VALUE) @@ -2436,7 +2825,7 @@ static CharDriverState *qemu_chr_open_win_file_out(const char *file_out) return qemu_chr_open_win_file(fd_out); } -#endif +#endif /* !_WIN32 */ /***********************************************************/ /* UDP Net console */ @@ -2760,7 +3149,7 @@ static void tcp_chr_close(CharDriverState *chr) qemu_free(s); } -static CharDriverState *qemu_chr_open_tcp(const char *host_str, +static CharDriverState *qemu_chr_open_tcp(const char *host_str, int is_telnet, int is_unix) { @@ -2823,8 +3212,8 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str, else #endif fd = socket(PF_INET, SOCK_STREAM, 0); - - if (fd < 0) + + if (fd < 0) goto fail; if (!is_waitconnect) @@ -2854,7 +3243,7 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str, val = 1; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val)); } - + ret = bind(fd, addr, addrlen); if (ret < 0) goto fail; @@ -2894,7 +3283,7 @@ static CharDriverState *qemu_chr_open_tcp(const char *host_str, else qemu_set_fd_handler(s->fd, NULL, tcp_chr_connect, chr); } - + if (is_listen && is_waitconnect) { printf("QEMU waiting for connection on: %s\n", host_str); tcp_chr_accept(chr); @@ -2915,10 +3304,12 @@ CharDriverState *qemu_chr_open(const char *filename) const char *p; if (!strcmp(filename, "vc")) { - return text_console_init(&display_state); + return text_console_init(&display_state, 0); + } else if (strstart(filename, "vc:", &p)) { + return text_console_init(&display_state, p); } else if (!strcmp(filename, "null")) { return qemu_chr_open_null(); - } else + } else if (strstart(filename, "tcp:", &p)) { return qemu_chr_open_tcp(p, 0, 0); } else @@ -2949,17 +3340,18 @@ CharDriverState *qemu_chr_open(const char *filename) return qemu_chr_open_pty(); } else if (!strcmp(filename, "stdio")) { return qemu_chr_open_stdio(); - } else -#endif + } else #if defined(__linux__) if (strstart(filename, "/dev/parport", NULL)) { return qemu_chr_open_pp(filename); - } else + } else +#endif +#if defined(__linux__) || defined(__sun__) if (strstart(filename, "/dev/", NULL)) { return qemu_chr_open_tty(filename); - } else + } else #endif -#ifdef _WIN32 +#else /* !_WIN32 */ if (strstart(filename, "COM", NULL)) { return qemu_chr_open_win(filename); } else @@ -3019,10 +3411,10 @@ static int parse_macaddr(uint8_t *macaddr, const char *p) for(i = 0; i < 6; i++) { macaddr[i] = strtol(p, (char **)&p, 16); if (i == 5) { - if (*p != '\0') + if (*p != '\0') return -1; } else { - if (*p != ':') + if (*p != ':') return -1; p++; } @@ -3188,11 +3580,11 @@ int qemu_can_send_packet(VLANClientState *vc1) for(vc = vlan->first_client; vc != NULL; vc = vc->next) { if (vc != vc1) { - if (vc->fd_can_read && !vc->fd_can_read(vc->opaque)) - return 0; + if (vc->fd_can_read && vc->fd_can_read(vc->opaque)) + return 1; } } - return 1; + return 0; } void qemu_send_packet(VLANClientState *vc1, const uint8_t *buf, int size) @@ -3249,7 +3641,7 @@ static int net_slirp_init(VLANState *vlan) slirp_inited = 1; slirp_init(); } - slirp_vc = qemu_new_vlan_client(vlan, + slirp_vc = qemu_new_vlan_client(vlan, slirp_receive, NULL, NULL); snprintf(slirp_vc->info_str, sizeof(slirp_vc->info_str), "user redirector"); return 0; @@ -3262,7 +3654,7 @@ static void net_slirp_redir(const char *redir_str) const char *p; struct in_addr guest_addr; int host_port, guest_port; - + if (!slirp_inited) { slirp_inited = 1; slirp_init(); @@ -3292,11 +3684,11 @@ static void net_slirp_redir(const char *redir_str) } if (!inet_aton(buf, &guest_addr)) goto fail; - + guest_port = strtol(p, &r, 0); if (r == p) goto fail; - + if (slirp_redir(is_udp, host_port, guest_addr, guest_port) < 0) { fprintf(stderr, "qemu: could not set up redirection\n"); exit(1); @@ -3306,7 +3698,7 @@ static void net_slirp_redir(const char *redir_str) fprintf(stderr, "qemu: syntax: -redir [tcp|udp]:host-port:[guest-host]:guest-port\n"); exit(1); } - + #ifndef _WIN32 char smb_dir[1024]; @@ -3325,7 +3717,7 @@ static void smb_exit(void) break; if (strcmp(de->d_name, ".") != 0 && strcmp(de->d_name, "..") != 0) { - snprintf(filename, sizeof(filename), "%s/%s", + snprintf(filename, sizeof(filename), "%s/%s", smb_dir, de->d_name); unlink(filename); } @@ -3353,13 +3745,13 @@ void net_slirp_smb(const char *exported_dir) exit(1); } snprintf(smb_conf, sizeof(smb_conf), "%s/%s", smb_dir, "smb.conf"); - + f = fopen(smb_conf, "w"); if (!f) { fprintf(stderr, "qemu: could not create samba server configuration file '%s'\n", smb_conf); exit(1); } - fprintf(f, + fprintf(f, "[global]\n" "private dir=%s\n" "smb ports=0\n" @@ -3385,7 +3777,7 @@ void net_slirp_smb(const char *exported_dir) snprintf(smb_cmdline, sizeof(smb_cmdline), "%s -s %s", SMBD_COMMAND, smb_conf); - + slirp_add_exec(0, smb_cmdline, 4, 139); } @@ -3449,14 +3841,14 @@ static TAPState *net_tap_fd_init(VLANState *vlan, int fd) return s; } -#ifdef _BSD +#if defined (_BSD) || defined (__FreeBSD_kernel__) static int tap_open(char *ifname, int ifname_size) { int fd; char *dev; struct stat s; - fd = open("/dev/tap", O_RDWR); + TFR(fd = open("/dev/tap", O_RDWR)); if (fd < 0) { fprintf(stderr, "warning: could not open /dev/tap: no virtual network emulation\n"); return -1; @@ -3471,10 +3863,10 @@ static int tap_open(char *ifname, int ifname_size) } #elif defined(__sun__) #define TUNNEWPPA (('T'<<16) | 0x0001) -/* - * Allocate TAP device, returns opened fd. +/* + * Allocate TAP device, returns opened fd. * Stores dev name in the first arg(must be large enough). - */ + */ int tap_alloc(char *dev) { int tap_fd, if_fd, ppa = -1; @@ -3491,8 +3883,8 @@ int tap_alloc(char *dev) memset(&ifr, 0x0, sizeof(ifr)); if( *dev ){ - ptr = dev; - while( *ptr && !isdigit((int)*ptr) ) ptr++; + ptr = dev; + while( *ptr && !isdigit((int)*ptr) ) ptr++; ppa = atoi(ptr); } @@ -3500,12 +3892,14 @@ int tap_alloc(char *dev) if( ip_fd ) close(ip_fd); - if( (ip_fd = open("/dev/udp", O_RDWR, 0)) < 0){ + TFR(ip_fd = open("/dev/udp", O_RDWR, 0)); + if (ip_fd < 0) { syslog(LOG_ERR, "Can't open /dev/ip (actually /dev/udp)"); return -1; } - if( (tap_fd = open("/dev/tap", O_RDWR, 0)) < 0){ + TFR(tap_fd = open("/dev/tap", O_RDWR, 0)); + if (tap_fd < 0) { syslog(LOG_ERR, "Can't open /dev/tap"); return -1; } @@ -3518,7 +3912,8 @@ int tap_alloc(char *dev) if ((ppa = ioctl (tap_fd, I_STR, &strioc_ppa)) < 0) syslog (LOG_ERR, "Can't assign new interface"); - if( (if_fd = open("/dev/tap", O_RDWR, 0)) < 0){ + TFR(if_fd = open("/dev/tap", O_RDWR, 0)); + if (if_fd < 0) { syslog(LOG_ERR, "Can't open /dev/tap (2)"); return -1; } @@ -3550,7 +3945,8 @@ int tap_alloc(char *dev) if (ioctl (ip_fd, I_PUSH, "arp") < 0) syslog (LOG_ERR, "Can't push ARP module (3)\n"); /* Open arp_fd */ - if ((arp_fd = open ("/dev/tap", O_RDWR, 0)) < 0) + TFR(arp_fd = open ("/dev/tap", O_RDWR, 0)); + if (arp_fd < 0) syslog (LOG_ERR, "Can't open %s\n", "/dev/tap"); /* Set ifname to arp */ @@ -3605,8 +4001,8 @@ static int tap_open(char *ifname, int ifname_size) { struct ifreq ifr; int fd, ret; - - fd = open("/dev/net/tun", O_RDWR); + + TFR(fd = open("/dev/net/tun", O_RDWR)); if (fd < 0) { fprintf(stderr, "warning: could not open /dev/net/tun: no virtual network emulation\n"); return -1; @@ -3642,7 +4038,7 @@ static int net_tap_init(VLANState *vlan, const char *ifname1, pstrcpy(ifname, sizeof(ifname), ifname1); else ifname[0] = '\0'; - fd = tap_open(ifname, sizeof(ifname)); + TFR(fd = tap_open(ifname, sizeof(ifname))); if (fd < 0) return -1; @@ -3680,7 +4076,7 @@ static int net_tap_init(VLANState *vlan, const char *ifname1, s = net_tap_fd_init(vlan, fd); if (!s) return -1; - snprintf(s->vc->info_str, sizeof(s->vc->info_str), + snprintf(s->vc->info_str, sizeof(s->vc->info_str), "tap: ifname=%s setup_script=%s", ifname, setup_script); return 0; } @@ -3717,7 +4113,7 @@ static void net_socket_receive(void *opaque, const uint8_t *buf, int size) static void net_socket_receive_dgram(void *opaque, const uint8_t *buf, int size) { NetSocketState *s = opaque; - sendto(s->fd, buf, size, 0, + sendto(s->fd, buf, size, 0, (struct sockaddr *)&s->dgram_dst, sizeof(s->dgram_dst)); } @@ -3731,7 +4127,7 @@ static void net_socket_send(void *opaque) size = recv(s->fd, buf1, sizeof(buf1), 0); if (size < 0) { err = socket_error(); - if (err != EWOULDBLOCK) + if (err != EWOULDBLOCK) goto eoc; } else if (size == 0) { /* end of connection */ @@ -3783,7 +4179,7 @@ static void net_socket_send_dgram(void *opaque) int size; size = recv(s->fd, s->buf, sizeof(s->buf), 0); - if (size < 0) + if (size < 0) return; if (size == 0) { /* end of connection */ @@ -3800,7 +4196,7 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr) int val, ret; if (!IN_MULTICAST(ntohl(mcastaddr->sin_addr.s_addr))) { fprintf(stderr, "qemu: error: specified mcastaddr \"%s\" (0x%08x) does not contain a multicast address\n", - inet_ntoa(mcastaddr->sin_addr), + inet_ntoa(mcastaddr->sin_addr), (int)ntohl(mcastaddr->sin_addr.s_addr)); return -1; @@ -3812,7 +4208,7 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr) } val = 1; - ret=setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, + ret=setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val)); if (ret < 0) { perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)"); @@ -3824,12 +4220,12 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr) perror("bind"); goto fail; } - + /* Add host to multicast group */ imr.imr_multiaddr = mcastaddr->sin_addr; imr.imr_interface.s_addr = htonl(INADDR_ANY); - ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, + ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char *)&imr, sizeof(struct ip_mreq)); if (ret < 0) { perror("setsockopt(IP_ADD_MEMBERSHIP)"); @@ -3838,7 +4234,7 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr) /* Force mcast msgs to loopback (eg. several QEMUs in same host */ val = 1; - ret=setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, + ret=setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, (const char *)&val, sizeof(val)); if (ret < 0) { perror("setsockopt(SOL_IP, IP_MULTICAST_LOOP)"); @@ -3848,12 +4244,12 @@ static int net_socket_mcast_create(struct sockaddr_in *mcastaddr) socket_set_nonblock(fd); return fd; fail: - if (fd >= 0) + if (fd >= 0) closesocket(fd); return -1; } -static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan, int fd, +static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan, int fd, int is_connected) { struct sockaddr_in saddr; @@ -3862,7 +4258,7 @@ static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan, int fd, NetSocketState *s; /* fd passed: multicast: "learn" dgram_dst address from bound address and save it - * Because this may be "shared" socket from a "master" process, datagrams would be recv() + * Because this may be "shared" socket from a "master" process, datagrams would be recv() * by ONLY ONE process: we must "clone" this dgram socket --jjo */ @@ -3884,7 +4280,7 @@ static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan, int fd, /* clone newfd to fd, close newfd */ dup2(newfd, fd); close(newfd); - + } else { fprintf(stderr, "qemu: error: init_dgram: fd=%d failed getsockname(): %s\n", fd, strerror(errno)); @@ -3904,7 +4300,7 @@ static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan, int fd, if (is_connected) s->dgram_dst=saddr; snprintf(s->vc->info_str, sizeof(s->vc->info_str), - "socket: fd=%d (%s mcast=%s:%d)", + "socket: fd=%d (%s mcast=%s:%d)", fd, is_connected? "cloned" : "", inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); return s; @@ -3916,7 +4312,7 @@ static void net_socket_connect(void *opaque) qemu_set_fd_handler(s->fd, net_socket_send, NULL, s); } -static NetSocketState *net_socket_fd_init_stream(VLANState *vlan, int fd, +static NetSocketState *net_socket_fd_init_stream(VLANState *vlan, int fd, int is_connected) { NetSocketState *s; @@ -3924,7 +4320,7 @@ static NetSocketState *net_socket_fd_init_stream(VLANState *vlan, int fd, if (!s) return NULL; s->fd = fd; - s->vc = qemu_new_vlan_client(vlan, + s->vc = qemu_new_vlan_client(vlan, net_socket_receive, NULL, s); snprintf(s->vc->info_str, sizeof(s->vc->info_str), "socket: fd=%d", fd); @@ -3936,7 +4332,7 @@ static NetSocketState *net_socket_fd_init_stream(VLANState *vlan, int fd, return s; } -static NetSocketState *net_socket_fd_init(VLANState *vlan, int fd, +static NetSocketState *net_socket_fd_init(VLANState *vlan, int fd, int is_connected) { int so_type=-1, optlen=sizeof(so_type); @@ -3960,7 +4356,7 @@ static NetSocketState *net_socket_fd_init(VLANState *vlan, int fd, static void net_socket_accept(void *opaque) { - NetSocketListenState *s = opaque; + NetSocketListenState *s = opaque; NetSocketState *s1; struct sockaddr_in saddr; socklen_t len; @@ -3975,12 +4371,12 @@ static void net_socket_accept(void *opaque) break; } } - s1 = net_socket_fd_init(s->vlan, fd, 1); + s1 = net_socket_fd_init(s->vlan, fd, 1); if (!s1) { closesocket(fd); } else { snprintf(s1->vc->info_str, sizeof(s1->vc->info_str), - "socket: connection from %s:%d", + "socket: connection from %s:%d", inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); } } @@ -3993,7 +4389,7 @@ static int net_socket_listen_init(VLANState *vlan, const char *host_str) if (parse_host_port(&saddr, host_str) < 0) return -1; - + s = qemu_mallocz(sizeof(NetSocketListenState)); if (!s) return -1; @@ -4008,7 +4404,7 @@ static int net_socket_listen_init(VLANState *vlan, const char *host_str) /* allow fast reuse */ val = 1; setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val)); - + ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)); if (ret < 0) { perror("bind"); @@ -4067,7 +4463,7 @@ static int net_socket_connect_init(VLANState *vlan, const char *host_str) if (!s) return -1; snprintf(s->vc->info_str, sizeof(s->vc->info_str), - "socket: connect to %s:%d", + "socket: connect to %s:%d", inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); return 0; } @@ -4091,9 +4487,9 @@ static int net_socket_mcast_init(VLANState *vlan, const char *host_str) return -1; s->dgram_dst = saddr; - + snprintf(s->vc->info_str, sizeof(s->vc->info_str), - "socket: mcast=%s:%d", + "socket: mcast=%s:%d", inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); return 0; @@ -4195,6 +4591,7 @@ static int net_client_init(const char *str) } nd->vlan = vlan; nb_nics++; + vlan->nb_guest_devs++; ret = 0; } else if (!strcmp(device, "none")) { @@ -4207,6 +4604,7 @@ static int net_client_init(const char *str) if (get_param_value(buf, sizeof(buf), "hostname", p)) { pstrcpy(slirp_hostname, sizeof(slirp_hostname), buf); } + vlan->nb_host_devs++; ret = net_slirp_init(vlan); } else #endif @@ -4217,6 +4615,7 @@ static int net_client_init(const char *str) fprintf(stderr, "tap: no interface name\n"); return -1; } + vlan->nb_host_devs++; ret = tap_win32_init(vlan, ifname); } else #else @@ -4224,6 +4623,7 @@ static int net_client_init(const char *str) char ifname[64]; char setup_script[1024]; int fd; + vlan->nb_host_devs++; if (get_param_value(buf, sizeof(buf), "fd", p) > 0) { fd = strtol(buf, NULL, 0); ret = -1; @@ -4257,6 +4657,7 @@ static int net_client_init(const char *str) fprintf(stderr, "Unknown socket options: %s\n", p); return -1; } + vlan->nb_host_devs++; } else { fprintf(stderr, "Unknown network device: %s\n", device); @@ -4265,7 +4666,7 @@ static int net_client_init(const char *str) if (ret < 0) { fprintf(stderr, "Could not initialize device '%s'\n", device); } - + return ret; } @@ -4312,9 +4713,13 @@ static int usb_device_add(const char *devname) } else if (!strcmp(devname, "mouse")) { dev = usb_mouse_init(); } else if (!strcmp(devname, "tablet")) { - dev = usb_tablet_init(); + dev = usb_tablet_init(); + } else if (!strcmp(devname, "keyboard")) { + dev = usb_keyboard_init(); } else if (strstart(devname, "disk:", &p)) { dev = usb_msd_init(p); + } else if (!strcmp(devname, "wacom-tablet")) { + dev = usb_wacom_init(); } else { return -1; } @@ -4355,7 +4760,7 @@ static int usb_device_del(const char *devname) return -1; p = strchr(devname, '.'); - if (!p) + if (!p) return -1; bus_num = strtoul(devname, NULL, 0); addr = strtoul(p + 1, NULL, 0); @@ -4385,7 +4790,7 @@ void do_usb_add(const char *devname) { int ret; ret = usb_device_add(devname); - if (ret < 0) + if (ret < 0) term_printf("Could not add USB device '%s'\n", devname); } @@ -4393,7 +4798,7 @@ void do_usb_del(const char *devname) { int ret; ret = usb_device_del(devname); - if (ret < 0) + if (ret < 0) term_printf("Could not remove USB device '%s'\n", devname); } @@ -4413,20 +4818,20 @@ void usb_info(void) if (!dev) continue; switch(dev->speed) { - case USB_SPEED_LOW: - speed_str = "1.5"; + case USB_SPEED_LOW: + speed_str = "1.5"; break; - case USB_SPEED_FULL: - speed_str = "12"; + case USB_SPEED_FULL: + speed_str = "12"; break; - case USB_SPEED_HIGH: - speed_str = "480"; + case USB_SPEED_HIGH: + speed_str = "480"; break; default: - speed_str = "?"; + speed_str = "?"; break; } - term_printf(" Device %d.%d, Speed %s Mb/s, Product %s\n", + term_printf(" Device %d.%d, Speed %s Mb/s, Product %s\n", 0, dev->addr, speed_str, dev->devname); } } @@ -4486,10 +4891,12 @@ static void dumb_resize(DisplayState *ds, int w, int h) static void dumb_refresh(DisplayState *ds) { +#if defined(CONFIG_SDL) vga_hw_update(); +#endif } -void dumb_display_init(DisplayState *ds) +static void dumb_display_init(DisplayState *ds) { ds->data = NULL; ds->linesize = 0; @@ -4520,10 +4927,10 @@ static IOHandlerRecord *first_io_handler; /* XXX: fd_read_poll should be suppressed, but an API change is necessary in the character devices to suppress fd_can_read(). */ -int qemu_set_fd_handler2(int fd, - IOCanRWHandler *fd_read_poll, - IOHandler *fd_read, - IOHandler *fd_write, +int qemu_set_fd_handler2(int fd, + IOCanRWHandler *fd_read_poll, + IOHandler *fd_read, + IOHandler *fd_write, void *opaque) { IOHandlerRecord **pioh, *ioh; @@ -4561,9 +4968,9 @@ int qemu_set_fd_handler2(int fd, return 0; } -int qemu_set_fd_handler(int fd, - IOHandler *fd_read, - IOHandler *fd_write, +int qemu_set_fd_handler(int fd, + IOHandler *fd_read, + IOHandler *fd_write, void *opaque) { return qemu_set_fd_handler2(fd, NULL, fd_read, fd_write, opaque); @@ -4617,7 +5024,7 @@ typedef struct WaitObjects { } WaitObjects; static WaitObjects wait_objects = {0}; - + int qemu_add_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque) { WaitObjects *w = &wait_objects; @@ -4644,7 +5051,7 @@ void qemu_del_wait_object(HANDLE handle, WaitObjectFunc *func, void *opaque) w->events[i] = w->events[i + 1]; w->func[i] = w->func[i + 1]; w->opaque[i] = w->opaque[i + 1]; - } + } } if (found) w->num--; @@ -4718,7 +5125,7 @@ void qemu_fflush(QEMUFile *f) fseek(f->outfile, f->buf_offset, SEEK_SET); fwrite(f->buf, 1, f->buf_index, f->outfile); } else { - bdrv_pwrite(f->bs, f->base_offset + f->buf_offset, + bdrv_pwrite(f->bs, f->base_offset + f->buf_offset, f->buf, f->buf_index); } f->buf_offset += f->buf_index; @@ -4738,7 +5145,7 @@ static void qemu_fill_buffer(QEMUFile *f) if (len < 0) len = 0; } else { - len = bdrv_pread(f->bs, f->base_offset + f->buf_offset, + len = bdrv_pread(f->bs, f->base_offset + f->buf_offset, f->buf, IO_BUF_SIZE); if (len < 0) len = 0; @@ -4898,8 +5305,8 @@ typedef struct SaveStateEntry { static SaveStateEntry *first_se; -int register_savevm(const char *idstr, - int instance_id, +int register_savevm(const char *idstr, + int instance_id, int version_id, SaveStateHandler *save_state, LoadStateHandler *load_state, @@ -4952,7 +5359,7 @@ int qemu_savevm_state(QEMUFile *f) /* record size: filled later */ len_pos = qemu_ftell(f); qemu_put_be32(f, 0); - + se->save_state(f, se->opaque); /* fill record size */ @@ -4976,7 +5383,7 @@ static SaveStateEntry *find_se(const char *idstr, int instance_id) SaveStateEntry *se; for(se = first_se; se != NULL; se = se->next) { - if (!strcmp(se->idstr, idstr) && + if (!strcmp(se->idstr, idstr) && instance_id == se->instance_id) return se; } @@ -4990,7 +5397,7 @@ int qemu_loadvm_state(QEMUFile *f) int64_t total_len, end_pos, cur_pos; unsigned int v; char idstr[256]; - + v = qemu_get_be32(f); if (v != QEMU_VM_FILE_MAGIC) goto fail; @@ -5012,18 +5419,18 @@ int qemu_loadvm_state(QEMUFile *f) version_id = qemu_get_be32(f); record_len = qemu_get_be32(f); #if 0 - printf("idstr=%s instance=0x%x version=%d len=%d\n", + printf("idstr=%s instance=0x%x version=%d len=%d\n", idstr, instance_id, version_id, record_len); #endif cur_pos = qemu_ftell(f); se = find_se(idstr, instance_id); if (!se) { - fprintf(stderr, "qemu: warning: instance 0x%x of device '%s' not present in current VM\n", + fprintf(stderr, "qemu: warning: instance 0x%x of device '%s' not present in current VM\n", instance_id, idstr); } else { ret = se->load_state(f, se->opaque, version_id); if (ret < 0) { - fprintf(stderr, "qemu: warning: error while loading state for instance 0x%x of device '%s'\n", + fprintf(stderr, "qemu: warning: error while loading state for instance 0x%x of device '%s'\n", instance_id, idstr); } } @@ -5074,7 +5481,7 @@ static int bdrv_snapshot_find(BlockDriverState *bs, QEMUSnapshotInfo *sn_info, { QEMUSnapshotInfo *sn_tab, *sn; int nb_sns, i, ret; - + ret = -ENOENT; nb_sns = bdrv_snapshot_list(bs, &sn_tab); if (nb_sns < 0) @@ -5116,7 +5523,7 @@ void do_savevm(const char *name) saved_vm_running = vm_running; vm_stop(0); - + must_delete = 0; if (name) { ret = bdrv_snapshot_find(bs, old_sn, name); @@ -5144,13 +5551,13 @@ void do_savevm(const char *name) sn->date_nsec = tv.tv_usec * 1000; #endif sn->vm_clock_nsec = qemu_get_clock(vm_clock); - + if (bdrv_get_info(bs, bdi) < 0 || bdi->vm_state_offset <= 0) { term_printf("Device %s does not support VM state snapshots\n", bdrv_get_device_name(bs)); goto the_end; } - + /* save the VM state */ f = qemu_fopen_bdrv(bs, bdi->vm_state_offset, 1); if (!f) { @@ -5164,7 +5571,7 @@ void do_savevm(const char *name) term_printf("Error %d while writing VM\n", ret); goto the_end; } - + /* create the snapshots */ for(i = 0; i < MAX_DISKS; i++) { @@ -5203,7 +5610,7 @@ void do_loadvm(const char *name) term_printf("No block device supports snapshots\n"); return; } - + /* Flush all IO requests so they don't interfere with the new state. */ qemu_aio_flush(); @@ -5243,7 +5650,7 @@ void do_loadvm(const char *name) bdrv_get_device_name(bs)); return; } - + /* restore the VM state */ f = qemu_fopen_bdrv(bs, bdi->vm_state_offset, 0); if (!f) { @@ -5270,7 +5677,7 @@ void do_delvm(const char *name) term_printf("No block device supports snapshots\n"); return; } - + for(i = 0; i <= MAX_DISKS; i++) { bs1 = bs_table[i]; if (bdrv_has_snapshot(bs1)) { @@ -5350,14 +5757,14 @@ void cpu_save(QEMUFile *f, void *opaque) uint16_t fptag, fpus, fpuc, fpregs_format; uint32_t hflags; int i; - + for(i = 0; i < CPU_NB_REGS; i++) qemu_put_betls(f, &env->regs[i]); qemu_put_betls(f, &env->eip); qemu_put_betls(f, &env->eflags); hflags = env->hflags; /* XXX: suppress most of the redundant hflags */ qemu_put_be32s(f, &hflags); - + /* FPU */ fpuc = env->fpuc; fpus = (env->fpus & ~0x3800) | (env->fpstt & 0x7) << 11; @@ -5365,7 +5772,7 @@ void cpu_save(QEMUFile *f, void *opaque) for(i = 0; i < 8; i++) { fptag |= ((!env->fptags[i]) << i); } - + qemu_put_be16s(f, &fpuc); qemu_put_be16s(f, &fpus); qemu_put_be16s(f, &fptag); @@ -5376,7 +5783,7 @@ void cpu_save(QEMUFile *f, void *opaque) fpregs_format = 1; #endif qemu_put_be16s(f, &fpregs_format); - + for(i = 0; i < 8; i++) { #ifdef USE_X86LDOUBLE { @@ -5403,16 +5810,16 @@ void cpu_save(QEMUFile *f, void *opaque) cpu_put_seg(f, &env->tr); cpu_put_seg(f, &env->gdt); cpu_put_seg(f, &env->idt); - + qemu_put_be32s(f, &env->sysenter_cs); qemu_put_be32s(f, &env->sysenter_esp); qemu_put_be32s(f, &env->sysenter_eip); - + qemu_put_betls(f, &env->cr[0]); qemu_put_betls(f, &env->cr[2]); qemu_put_betls(f, &env->cr[3]); qemu_put_betls(f, &env->cr[4]); - + for(i = 0; i < 8; i++) qemu_put_betls(f, &env->dr[i]); @@ -5480,7 +5887,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) qemu_get_be16s(f, &fpus); qemu_get_be16s(f, &fptag); qemu_get_be16s(f, &fpregs_format); - + /* NOTE: we cannot always restore the FPU state if the image come from a host with a different 'USE_X86LDOUBLE' define. We guess if we are in an MMX state to restore correctly in that case. */ @@ -5488,7 +5895,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) for(i = 0; i < 8; i++) { uint64_t mant; uint16_t exp; - + switch(fpregs_format) { case 0: mant = qemu_get_be64(f); @@ -5519,7 +5926,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) } #else env->fpregs[i].mmx.MMX_Q(0) = mant; -#endif +#endif break; default: return -EINVAL; @@ -5534,23 +5941,23 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) for(i = 0; i < 8; i++) { env->fptags[i] = (fptag >> i) & 1; } - + for(i = 0; i < 6; i++) cpu_get_seg(f, &env->segs[i]); cpu_get_seg(f, &env->ldt); cpu_get_seg(f, &env->tr); cpu_get_seg(f, &env->gdt); cpu_get_seg(f, &env->idt); - + qemu_get_be32s(f, &env->sysenter_cs); qemu_get_be32s(f, &env->sysenter_esp); qemu_get_be32s(f, &env->sysenter_eip); - + qemu_get_betls(f, &env->cr[0]); qemu_get_betls(f, &env->cr[2]); qemu_get_betls(f, &env->cr[3]); qemu_get_betls(f, &env->cr[4]); - + for(i = 0; i < 8; i++) qemu_get_betls(f, &env->dr[i]); @@ -5571,7 +5978,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) qemu_get_be64s(f, &env->fmask); qemu_get_be64s(f, &env->kernelgsbase); #endif - if (version_id >= 4) + if (version_id >= 4) qemu_get_be32s(f, &env->smbase); /* XXX: compute hflags from scratch, except for CPL and IIF */ @@ -5679,13 +6086,146 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id) #elif defined(TARGET_ARM) -/* ??? Need to implement these. */ void cpu_save(QEMUFile *f, void *opaque) { + int i; + CPUARMState *env = (CPUARMState *)opaque; + + for (i = 0; i < 16; i++) { + qemu_put_be32(f, env->regs[i]); + } + qemu_put_be32(f, cpsr_read(env)); + qemu_put_be32(f, env->spsr); + for (i = 0; i < 6; i++) { + qemu_put_be32(f, env->banked_spsr[i]); + qemu_put_be32(f, env->banked_r13[i]); + qemu_put_be32(f, env->banked_r14[i]); + } + for (i = 0; i < 5; i++) { + qemu_put_be32(f, env->usr_regs[i]); + qemu_put_be32(f, env->fiq_regs[i]); + } + qemu_put_be32(f, env->cp15.c0_cpuid); + qemu_put_be32(f, env->cp15.c0_cachetype); + qemu_put_be32(f, env->cp15.c1_sys); + qemu_put_be32(f, env->cp15.c1_coproc); + qemu_put_be32(f, env->cp15.c1_xscaleauxcr); + qemu_put_be32(f, env->cp15.c2_base); + qemu_put_be32(f, env->cp15.c2_data); + qemu_put_be32(f, env->cp15.c2_insn); + qemu_put_be32(f, env->cp15.c3); + qemu_put_be32(f, env->cp15.c5_insn); + qemu_put_be32(f, env->cp15.c5_data); + for (i = 0; i < 8; i++) { + qemu_put_be32(f, env->cp15.c6_region[i]); + } + qemu_put_be32(f, env->cp15.c6_insn); + qemu_put_be32(f, env->cp15.c6_data); + qemu_put_be32(f, env->cp15.c9_insn); + qemu_put_be32(f, env->cp15.c9_data); + qemu_put_be32(f, env->cp15.c13_fcse); + qemu_put_be32(f, env->cp15.c13_context); + qemu_put_be32(f, env->cp15.c15_cpar); + + qemu_put_be32(f, env->features); + + if (arm_feature(env, ARM_FEATURE_VFP)) { + for (i = 0; i < 16; i++) { + CPU_DoubleU u; + u.d = env->vfp.regs[i]; + qemu_put_be32(f, u.l.upper); + qemu_put_be32(f, u.l.lower); + } + for (i = 0; i < 16; i++) { + qemu_put_be32(f, env->vfp.xregs[i]); + } + + /* TODO: Should use proper FPSCR access functions. */ + qemu_put_be32(f, env->vfp.vec_len); + qemu_put_be32(f, env->vfp.vec_stride); + } + + if (arm_feature(env, ARM_FEATURE_IWMMXT)) { + for (i = 0; i < 16; i++) { + qemu_put_be64(f, env->iwmmxt.regs[i]); + } + for (i = 0; i < 16; i++) { + qemu_put_be32(f, env->iwmmxt.cregs[i]); + } + } } int cpu_load(QEMUFile *f, void *opaque, int version_id) { + CPUARMState *env = (CPUARMState *)opaque; + int i; + + if (version_id != 0) + return -EINVAL; + + for (i = 0; i < 16; i++) { + env->regs[i] = qemu_get_be32(f); + } + cpsr_write(env, qemu_get_be32(f), 0xffffffff); + env->spsr = qemu_get_be32(f); + for (i = 0; i < 6; i++) { + env->banked_spsr[i] = qemu_get_be32(f); + env->banked_r13[i] = qemu_get_be32(f); + env->banked_r14[i] = qemu_get_be32(f); + } + for (i = 0; i < 5; i++) { + env->usr_regs[i] = qemu_get_be32(f); + env->fiq_regs[i] = qemu_get_be32(f); + } + env->cp15.c0_cpuid = qemu_get_be32(f); + env->cp15.c0_cachetype = qemu_get_be32(f); + env->cp15.c1_sys = qemu_get_be32(f); + env->cp15.c1_coproc = qemu_get_be32(f); + env->cp15.c1_xscaleauxcr = qemu_get_be32(f); + env->cp15.c2_base = qemu_get_be32(f); + env->cp15.c2_data = qemu_get_be32(f); + env->cp15.c2_insn = qemu_get_be32(f); + env->cp15.c3 = qemu_get_be32(f); + env->cp15.c5_insn = qemu_get_be32(f); + env->cp15.c5_data = qemu_get_be32(f); + for (i = 0; i < 8; i++) { + env->cp15.c6_region[i] = qemu_get_be32(f); + } + env->cp15.c6_insn = qemu_get_be32(f); + env->cp15.c6_data = qemu_get_be32(f); + env->cp15.c9_insn = qemu_get_be32(f); + env->cp15.c9_data = qemu_get_be32(f); + env->cp15.c13_fcse = qemu_get_be32(f); + env->cp15.c13_context = qemu_get_be32(f); + env->cp15.c15_cpar = qemu_get_be32(f); + + env->features = qemu_get_be32(f); + + if (arm_feature(env, ARM_FEATURE_VFP)) { + for (i = 0; i < 16; i++) { + CPU_DoubleU u; + u.l.upper = qemu_get_be32(f); + u.l.lower = qemu_get_be32(f); + env->vfp.regs[i] = u.d; + } + for (i = 0; i < 16; i++) { + env->vfp.xregs[i] = qemu_get_be32(f); + } + + /* TODO: Should use proper FPSCR access functions. */ + env->vfp.vec_len = qemu_get_be32(f); + env->vfp.vec_stride = qemu_get_be32(f); + } + + if (arm_feature(env, ARM_FEATURE_IWMMXT)) { + for (i = 0; i < 16; i++) { + env->iwmmxt.regs[i] = qemu_get_be64(f); + } + for (i = 0; i < 16; i++) { + env->iwmmxt.cregs[i] = qemu_get_be32(f); + } + } + return 0; } @@ -5748,7 +6288,7 @@ static int ram_compress_open(RamCompressState *s, QEMUFile *f) memset(s, 0, sizeof(*s)); s->f = f; ret = deflateInit2(&s->zstream, 1, - Z_DEFLATED, 15, + Z_DEFLATED, 15, 9, Z_DEFAULT_STRATEGY); if (ret != Z_OK) return -1; @@ -5859,7 +6399,7 @@ static void ram_save(QEMUFile *f, void *opaque) int i; RamCompressState s1, *s = &s1; uint8_t buf[10]; - + qemu_put_be32(f, phys_ram_size); if (ram_compress_open(s, f) < 0) return; @@ -5874,7 +6414,7 @@ static void ram_save(QEMUFile *f, void *opaque) sector_num = -1; for(j = 0; j < MAX_DISKS; j++) { if (bs_table[j]) { - sector_num = bdrv_hash_find(bs_table[j], + sector_num = bdrv_hash_find(bs_table[j], phys_ram_base + i, BDRV_HASH_BLOCK_SIZE); if (sector_num >= 0) break; @@ -5886,7 +6426,7 @@ static void ram_save(QEMUFile *f, void *opaque) buf[1] = j; cpu_to_be64wu((uint64_t *)(buf + 2), sector_num); ram_compress_buf(s, buf, 10); - } else + } else #endif { // normal_compress: @@ -5922,7 +6462,7 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id) fprintf(stderr, "Error while reading ram block address=0x%08x", i); goto error; } - } else + } else #if 0 if (buf[0] == 1) { int bs_index; @@ -5935,13 +6475,13 @@ static int ram_load(QEMUFile *f, void *opaque, int version_id) fprintf(stderr, "Invalid block device index %d\n", bs_index); goto error; } - if (bdrv_read(bs_table[bs_index], sector_num, phys_ram_base + i, + if (bdrv_read(bs_table[bs_index], sector_num, phys_ram_base + i, BDRV_HASH_BLOCK_SIZE / 512) < 0) { - fprintf(stderr, "Error while reading sector %d:%" PRId64 "\n", + fprintf(stderr, "Error while reading sector %d:%" PRId64 "\n", bs_index, sector_num); goto error; } - } else + } else #endif { error: @@ -6060,8 +6600,9 @@ QEMUMachine *find_machine(const char *name) void gui_update(void *opaque) { - display_state.dpy_refresh(&display_state); - qemu_mod_timer(gui_timer, GUI_REFRESH_INTERVAL + qemu_get_clock(rt_clock)); + DisplayState *ds = opaque; + ds->dpy_refresh(ds); + qemu_mod_timer(ds->gui_timer, GUI_REFRESH_INTERVAL + qemu_get_clock(rt_clock)); } struct vm_change_state_entry { @@ -6124,10 +6665,11 @@ void vm_start(void) cpu_enable_ticks(); vm_running = 1; vm_state_notify(1); + qemu_rearm_alarm_timer(alarm_timer); } } -void vm_stop(int reason) +void vm_stop(int reason) { if (vm_running) { cpu_disable_ticks(); @@ -6224,15 +6766,15 @@ void main_loop_wait(int timeout) if (ret == 0) { int err; WaitObjects *w = &wait_objects; - + ret = WaitForMultipleObjects(w->num, w->events, FALSE, timeout); if (WAIT_OBJECT_0 + 0 <= ret && ret <= WAIT_OBJECT_0 + w->num - 1) { if (w->func[ret - WAIT_OBJECT_0]) w->func[ret - WAIT_OBJECT_0](w->opaque[ret - WAIT_OBJECT_0]); - - /* Check for additional signaled events */ + + /* Check for additional signaled events */ for(i = (ret - WAIT_OBJECT_0 + 1); i < w->num; i++) { - + /* Check if event is signaled */ ret2 = WaitForSingleObject(w->events[i], 0); if(ret2 == WAIT_OBJECT_0) { @@ -6242,8 +6784,8 @@ void main_loop_wait(int timeout) } else { err = GetLastError(); fprintf(stderr, "WaitForSingleObject error %d %d\n", i, err); - } - } + } + } } else if (ret == WAIT_TIMEOUT) { } else { err = GetLastError(); @@ -6273,7 +6815,7 @@ void main_loop_wait(int timeout) nfds = ioh->fd; } } - + tv.tv_sec = 0; #ifdef _WIN32 tv.tv_usec = 0; @@ -6290,12 +6832,10 @@ void main_loop_wait(int timeout) IOHandlerRecord **pioh; for(ioh = first_io_handler; ioh != NULL; ioh = ioh->next) { - if (ioh->deleted) - continue; - if (FD_ISSET(ioh->fd, &rfds)) { + if (!ioh->deleted && ioh->fd_read && FD_ISSET(ioh->fd, &rfds)) { ioh->fd_read(ioh->opaque); } - if (FD_ISSET(ioh->fd, &wfds)) { + if (!ioh->deleted && ioh->fd_write && FD_ISSET(ioh->fd, &wfds)) { ioh->fd_write(ioh->opaque); } } @@ -6307,7 +6847,7 @@ void main_loop_wait(int timeout) if (ioh->deleted) { *pioh = ioh->next; qemu_free(ioh); - } else + } else pioh = &ioh->next; } } @@ -6322,18 +6862,22 @@ void main_loop_wait(int timeout) } #endif qemu_aio_poll(); - qemu_bh_poll(); if (vm_running) { - qemu_run_timers(&active_timers[QEMU_TIMER_VIRTUAL], + qemu_run_timers(&active_timers[QEMU_TIMER_VIRTUAL], qemu_get_clock(vm_clock)); /* run dma transfers, if any */ DMA_run(); } - + /* real time timers */ - qemu_run_timers(&active_timers[QEMU_TIMER_REALTIME], + qemu_run_timers(&active_timers[QEMU_TIMER_REALTIME], qemu_get_clock(rt_clock)); + + /* Check bottom-halves last in case any of the earlier events triggered + them. */ + qemu_bh_poll(); + } static CPUState *cur_cpu; @@ -6414,7 +6958,7 @@ int main_loop(void) return ret; } -void help(void) +static void help(int exitcode) { printf("QEMU PC emulator version " QEMU_VERSION ", Copyright (c) 2003-2007 Fabrice Bellard\n" "usage: %s [options] [disk_image]\n" @@ -6435,6 +6979,7 @@ void help(void) "-snapshot write to temporary files instead of disk image files\n" #ifdef CONFIG_SDL "-no-frame open SDL window without a frame and window decorations\n" + "-alt-grab use Ctrl-Alt-Shift to grab mouse (instead of Ctrl-Alt)\n" "-no-quit disable SDL window close capability\n" #endif #ifdef TARGET_I386 @@ -6540,6 +7085,8 @@ void help(void) #ifdef TARGET_SPARC "-prom-env variable=value set OpenBIOS nvram variables\n" #endif + "-clock force the use of the given methods for timer alarm.\n" + " To see what timers are available use -clock help\n" "\n" "During emulation, the following keys are useful:\n" "ctrl-alt-f toggle full screen\n" @@ -6555,7 +7102,7 @@ void help(void) #endif DEFAULT_GDBSTUB_PORT, "/tmp/qemu.log"); - exit(1); + exit(exitcode); } #define HAS_ARG 0x0001 @@ -6618,6 +7165,7 @@ enum { QEMU_OPTION_loadvm, QEMU_OPTION_full_screen, QEMU_OPTION_no_frame, + QEMU_OPTION_alt_grab, QEMU_OPTION_no_quit, QEMU_OPTION_pidfile, QEMU_OPTION_no_kqemu, @@ -6635,6 +7183,8 @@ enum { QEMU_OPTION_semihosting, QEMU_OPTION_name, QEMU_OPTION_prom_env, + QEMU_OPTION_old_param, + QEMU_OPTION_clock, }; typedef struct QEMUOption { @@ -6703,14 +7253,15 @@ const QEMUOption qemu_options[] = { #endif { "localtime", 0, QEMU_OPTION_localtime }, { "std-vga", 0, QEMU_OPTION_std_vga }, - { "echr", 1, QEMU_OPTION_echr }, - { "monitor", 1, QEMU_OPTION_monitor }, - { "serial", 1, QEMU_OPTION_serial }, - { "parallel", 1, QEMU_OPTION_parallel }, + { "echr", HAS_ARG, QEMU_OPTION_echr }, + { "monitor", HAS_ARG, QEMU_OPTION_monitor }, + { "serial", HAS_ARG, QEMU_OPTION_serial }, + { "parallel", HAS_ARG, QEMU_OPTION_parallel }, { "loadvm", HAS_ARG, QEMU_OPTION_loadvm }, { "full-screen", 0, QEMU_OPTION_full_screen }, #ifdef CONFIG_SDL { "no-frame", 0, QEMU_OPTION_no_frame }, + { "alt-grab", 0, QEMU_OPTION_alt_grab }, { "no-quit", 0, QEMU_OPTION_no_quit }, #endif { "pidfile", HAS_ARG, QEMU_OPTION_pidfile }, @@ -6728,13 +7279,17 @@ const QEMUOption qemu_options[] = { { "show-cursor", 0, QEMU_OPTION_show_cursor }, { "daemonize", 0, QEMU_OPTION_daemonize }, { "option-rom", HAS_ARG, QEMU_OPTION_option_rom }, -#if defined(TARGET_ARM) +#if defined(TARGET_ARM) || defined(TARGET_M68K) { "semihosting", 0, QEMU_OPTION_semihosting }, #endif { "name", HAS_ARG, QEMU_OPTION_name }, #if defined(TARGET_SPARC) { "prom-env", HAS_ARG, QEMU_OPTION_prom_env }, #endif +#if defined(TARGET_ARM) + { "old-param", 0, QEMU_OPTION_old_param }, +#endif + { "clock", HAS_ARG, QEMU_OPTION_clock }, { NULL }, }; @@ -6825,10 +7380,15 @@ void register_machines(void) qemu_register_machine(&spitzpda_machine); qemu_register_machine(&borzoipda_machine); qemu_register_machine(&terrierpda_machine); + qemu_register_machine(&palmte_machine); #elif defined(TARGET_SH4) qemu_register_machine(&shix_machine); + qemu_register_machine(&r2d_machine); #elif defined(TARGET_ALPHA) /* XXX: TODO */ +#elif defined(TARGET_M68K) + qemu_register_machine(&mcf5208evb_machine); + qemu_register_machine(&an5206_machine); #else #error unsupported CPU #endif @@ -6992,6 +7552,7 @@ int main(int argc, char **argv) int usb_devices_index; int fds[2]; const char *pid_file = NULL; + VLANState *vlan; LIST_INIT (&vm_change_state_head); #ifndef _WIN32 @@ -7060,19 +7621,19 @@ int main(int argc, char **argv) for(i = 1; i < MAX_SERIAL_PORTS; i++) serial_devices[i][0] = '\0'; serial_device_index = 0; - + pstrcpy(parallel_devices[0], sizeof(parallel_devices[0]), "vc"); for(i = 1; i < MAX_PARALLEL_PORTS; i++) parallel_devices[i][0] = '\0'; parallel_device_index = 0; - + usb_devices_index = 0; - + nb_net_clients = 0; nb_nics = 0; /* default mac address of the first network interface */ - + optind = 1; for(;;) { if (optind >= argc) @@ -7090,7 +7651,7 @@ int main(int argc, char **argv) popt = qemu_options; for(;;) { if (!popt->name) { - fprintf(stderr, "%s: invalid option -- '%s'\n", + fprintf(stderr, "%s: invalid option -- '%s'\n", argv[0], r); exit(1); } @@ -7117,15 +7678,15 @@ int main(int argc, char **argv) printf("Supported machines are:\n"); for(m = first_machine; m != NULL; m = m->next) { printf("%-10s %s%s\n", - m->name, m->desc, + m->name, m->desc, m == first_machine ? " (default)" : ""); } - exit(1); + exit(*optarg != '?'); } break; case QEMU_OPTION_cpu: /* hw initialization will check this */ - if (optarg[0] == '?') { + if (*optarg == '?') { #if defined(TARGET_PPC) ppc_cpu_list(stdout, &fprintf); #elif defined(TARGET_ARM) @@ -7135,7 +7696,7 @@ int main(int argc, char **argv) #elif defined(TARGET_SPARC) sparc_cpu_list(stdout, &fprintf); #endif - exit(1); + exit(0); } else { cpu_model = optarg; } @@ -7229,7 +7790,7 @@ int main(int argc, char **argv) break; case QEMU_OPTION_boot: boot_device = optarg[0]; - if (boot_device != 'a' && + if (boot_device != 'a' && #if defined(TARGET_SPARC) || defined(TARGET_I386) // Network boot boot_device != 'n' && @@ -7276,7 +7837,7 @@ int main(int argc, char **argv) break; #endif case QEMU_OPTION_redir: - net_slirp_redir(optarg); + net_slirp_redir(optarg); break; #endif #ifdef HAS_AUDIO @@ -7289,12 +7850,12 @@ int main(int argc, char **argv) break; #endif case QEMU_OPTION_h: - help(); + help(0); break; case QEMU_OPTION_m: ram_size = atoi(optarg) * 1024 * 1024; if (ram_size <= 0) - help(); + help(1); if (ram_size > PHYS_RAM_MAX_SIZE) { fprintf(stderr, "qemu: at most %d MB RAM can be simulated\n", PHYS_RAM_MAX_SIZE / (1024 * 1024)); @@ -7305,7 +7866,7 @@ int main(int argc, char **argv) { int mask; CPULogItem *item; - + mask = cpu_str_to_log_mask(optarg); if (!mask) { printf("Log items (comma separated):\n"); @@ -7369,7 +7930,7 @@ int main(int argc, char **argv) if (*p == 'x') { p++; depth = strtol(p, (char **)&p, 10); - if (depth != 8 && depth != 15 && depth != 16 && + if (depth != 8 && depth != 15 && depth != 16 && depth != 24 && depth != 32) goto graphic_error; } else if (*p == '\0') { @@ -7377,7 +7938,7 @@ int main(int argc, char **argv) } else { goto graphic_error; } - + graphic_width = w; graphic_height = h; graphic_depth = depth; @@ -7399,7 +7960,7 @@ int main(int argc, char **argv) fprintf(stderr, "qemu: too many serial ports\n"); exit(1); } - pstrcpy(serial_devices[serial_device_index], + pstrcpy(serial_devices[serial_device_index], sizeof(serial_devices[0]), optarg); serial_device_index++; break; @@ -7408,7 +7969,7 @@ int main(int argc, char **argv) fprintf(stderr, "qemu: too many parallel ports\n"); exit(1); } - pstrcpy(parallel_devices[parallel_device_index], + pstrcpy(parallel_devices[parallel_device_index], sizeof(parallel_devices[0]), optarg); parallel_device_index++; break; @@ -7422,6 +7983,9 @@ int main(int argc, char **argv) case QEMU_OPTION_no_frame: no_frame = 1; break; + case QEMU_OPTION_alt_grab: + alt_grab = 1; + break; case QEMU_OPTION_no_quit: no_quit = 1; break; @@ -7502,6 +8066,13 @@ int main(int argc, char **argv) nb_prom_envs++; break; #endif +#ifdef TARGET_ARM + case QEMU_OPTION_old_param: + old_param = 1; +#endif + case QEMU_OPTION_clock: + configure_alarms(optarg); + break; } } } @@ -7574,10 +8145,10 @@ int main(int argc, char **argv) if (!linux_boot && boot_device != 'n' && - hd_filename[0] == '\0' && + hd_filename[0] == '\0' && (cdrom_index >= 0 && hd_filename[cdrom_index] == '\0') && fd_filename[0] == '\0') - help(); + help(1); /* boot to floppy or the default cd if no hard disk defined yet */ if (hd_filename[0] == '\0' && boot_device == 'c') { @@ -7588,7 +8159,7 @@ int main(int argc, char **argv) } setvbuf(stdout, NULL, _IOLBF, 0); - + init_timers(); init_timer_alarm(); qemu_aio_init(); @@ -7611,6 +8182,18 @@ int main(int argc, char **argv) if (net_client_init(net_clients[i]) < 0) exit(1); } + for(vlan = first_vlan; vlan != NULL; vlan = vlan->next) { + if (vlan->nb_guest_devs == 0 && vlan->nb_host_devs == 0) + continue; + if (vlan->nb_guest_devs == 0) { + fprintf(stderr, "Invalid vlan (%d) with no nics\n", vlan->id); + exit(1); + } + if (vlan->nb_host_devs == 0) + fprintf(stderr, + "Warning: vlan %d is not connected to host network\n", + vlan->id); + } #ifdef TARGET_I386 if (boot_device == 'n') { @@ -7630,7 +8213,6 @@ int main(int argc, char **argv) fprintf(stderr, "No valid PXE rom found for network device\n"); exit(1); } - boot_device = 'c'; /* to prevent confusion by the BIOS */ } #endif @@ -7741,17 +8323,19 @@ int main(int argc, char **argv) init_ioports(); /* terminal init */ + memset(&display_state, 0, sizeof(display_state)); if (nographic) { + /* nearly nothing to do */ dumb_display_init(ds); } else if (vnc_display != NULL) { - vnc_display_init(ds, vnc_display); + vnc_display_init(ds); + if (vnc_display_open(ds, vnc_display) < 0) + exit(1); } else { #if defined(CONFIG_SDL) sdl_display_init(ds, full_screen, no_frame); #elif defined(CONFIG_COCOA) cocoa_display_init(ds, full_screen); -#else - dumb_display_init(ds); #endif } @@ -7782,11 +8366,11 @@ int main(int argc, char **argv) if (devname[0] != '\0' && strcmp(devname, "none")) { serial_hds[i] = qemu_chr_open(devname); if (!serial_hds[i]) { - fprintf(stderr, "qemu: could not open serial device '%s'\n", + fprintf(stderr, "qemu: could not open serial device '%s'\n", devname); exit(1); } - if (!strcmp(devname, "vc")) + if (strstart(devname, "vc", 0)) qemu_chr_printf(serial_hds[i], "serial%d console\r\n", i); } } @@ -7796,11 +8380,11 @@ int main(int argc, char **argv) if (devname[0] != '\0' && strcmp(devname, "none")) { parallel_hds[i] = qemu_chr_open(devname); if (!parallel_hds[i]) { - fprintf(stderr, "qemu: could not open parallel device '%s'\n", + fprintf(stderr, "qemu: could not open parallel device '%s'\n", devname); exit(1); } - if (!strcmp(devname, "vc")) + if (strstart(devname, "vc", 0)) qemu_chr_printf(parallel_hds[i], "parallel%d console\r\n", i); } } @@ -7819,8 +8403,10 @@ int main(int argc, char **argv) } } - gui_timer = qemu_new_timer(rt_clock, gui_update, NULL); - qemu_mod_timer(gui_timer, qemu_get_clock(rt_clock)); + if (display_state.dpy_refresh) { + display_state.gui_timer = qemu_new_timer(rt_clock, gui_update, &display_state); + qemu_mod_timer(display_state.gui_timer, qemu_get_clock(rt_clock)); + } #ifdef CONFIG_GDBSTUB if (use_gdbstub) { @@ -7831,8 +8417,9 @@ int main(int argc, char **argv) gdbstub_port); exit(1); } - } else + } #endif + if (loadvm) do_loadvm(loadvm); @@ -7857,7 +8444,7 @@ int main(int argc, char **argv) if (len != 1) exit(1); - fd = open("/dev/null", O_RDWR); + TFR(fd = open("/dev/null", O_RDWR)); if (fd == -1) exit(1);