Revision 67b915a5 vl.c
b/vl.c | ||
---|---|---|
21 | 21 |
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
22 | 22 |
* THE SOFTWARE. |
23 | 23 |
*/ |
24 |
#include <stdlib.h> |
|
25 |
#include <stdio.h> |
|
26 |
#include <stdarg.h> |
|
27 |
#include <string.h> |
|
28 |
#include <ctype.h> |
|
24 |
#include "vl.h" |
|
25 |
|
|
29 | 26 |
#include <getopt.h> |
30 |
#include <inttypes.h> |
|
31 | 27 |
#include <unistd.h> |
32 |
#include <sys/mman.h> |
|
33 | 28 |
#include <fcntl.h> |
34 | 29 |
#include <signal.h> |
35 | 30 |
#include <time.h> |
36 |
#include <sys/time.h> |
|
37 | 31 |
#include <malloc.h> |
38 |
#include <termios.h> |
|
39 |
#include <sys/poll.h> |
|
40 | 32 |
#include <errno.h> |
33 |
#include <sys/time.h> |
|
34 |
|
|
35 |
#ifndef _WIN32 |
|
36 |
#include <sys/times.h> |
|
41 | 37 |
#include <sys/wait.h> |
42 | 38 |
#include <pty.h> |
43 |
#include <sys/times.h> |
|
44 |
|
|
39 |
#include <termios.h> |
|
40 |
#include <sys/poll.h> |
|
41 |
#include <sys/mman.h> |
|
45 | 42 |
#include <sys/ioctl.h> |
46 | 43 |
#include <sys/socket.h> |
47 | 44 |
#include <linux/if.h> |
48 | 45 |
#include <linux/if_tun.h> |
46 |
#endif |
|
47 |
|
|
48 |
#ifdef _WIN32 |
|
49 |
#include <sys/timeb.h> |
|
50 |
#include <windows.h> |
|
51 |
#define getopt_long_only getopt_long |
|
52 |
#define memalign(align, size) malloc(size) |
|
53 |
#endif |
|
54 |
|
|
49 | 55 |
|
50 | 56 |
#include "disas.h" |
51 | 57 |
|
52 |
#include "vl.h" |
|
53 | 58 |
#include "exec-all.h" |
54 | 59 |
|
55 | 60 |
#define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup" |
... | ... | |
375 | 380 |
} |
376 | 381 |
} |
377 | 382 |
|
378 |
int64_t get_clock(void) |
|
383 |
static int64_t get_clock(void)
|
|
379 | 384 |
{ |
385 |
#ifdef _WIN32 |
|
386 |
struct _timeb tb; |
|
387 |
_ftime(&tb); |
|
388 |
return ((int64_t)tb.time * 1000 + (int64_t)tb.millitm) * 1000; |
|
389 |
#else |
|
380 | 390 |
struct timeval tv; |
381 | 391 |
gettimeofday(&tv, NULL); |
382 | 392 |
return tv.tv_sec * 1000000LL + tv.tv_usec; |
393 |
#endif |
|
383 | 394 |
} |
384 | 395 |
|
385 | 396 |
void cpu_calibrate_ticks(void) |
... | ... | |
388 | 399 |
|
389 | 400 |
usec = get_clock(); |
390 | 401 |
ticks = cpu_get_real_ticks(); |
402 |
#ifdef _WIN32 |
|
403 |
Sleep(50); |
|
404 |
#else |
|
391 | 405 |
usleep(50 * 1000); |
406 |
#endif |
|
392 | 407 |
usec = get_clock() - usec; |
393 | 408 |
ticks = cpu_get_real_ticks() - ticks; |
394 | 409 |
ticks_per_sec = (ticks * 1000000LL + (usec >> 1)) / usec; |
... | ... | |
438 | 453 |
QEMUClock *vm_clock; |
439 | 454 |
|
440 | 455 |
static QEMUTimer *active_timers[2]; |
456 |
#ifndef _WIN32 |
|
441 | 457 |
/* frequency of the times() clock tick */ |
442 | 458 |
static int timer_freq; |
459 |
#endif |
|
443 | 460 |
|
444 | 461 |
QEMUClock *qemu_new_clock(int type) |
445 | 462 |
{ |
... | ... | |
550 | 567 |
{ |
551 | 568 |
switch(clock->type) { |
552 | 569 |
case QEMU_TIMER_REALTIME: |
570 |
#ifdef _WIN32 |
|
571 |
return GetTickCount(); |
|
572 |
#else |
|
553 | 573 |
/* XXX: portability among Linux hosts */ |
554 | 574 |
if (timer_freq == 100) { |
555 | 575 |
return times(NULL) * 10; |
556 | 576 |
} else { |
557 | 577 |
return ((int64_t)times(NULL) * 1000) / timer_freq; |
558 | 578 |
} |
579 |
#endif |
|
559 | 580 |
default: |
560 | 581 |
case QEMU_TIMER_VIRTUAL: |
561 | 582 |
return cpu_get_ticks(); |
... | ... | |
608 | 629 |
return 0; |
609 | 630 |
} |
610 | 631 |
|
632 |
#ifdef _WIN32 |
|
633 |
void CALLBACK host_alarm_handler(UINT uTimerID, UINT uMsg, |
|
634 |
DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2) |
|
635 |
#else |
|
611 | 636 |
static void host_alarm_handler(int host_signum) |
637 |
#endif |
|
612 | 638 |
{ |
613 | 639 |
if (qemu_timer_expired(active_timers[QEMU_TIMER_VIRTUAL], |
614 | 640 |
qemu_get_clock(vm_clock)) || |
... | ... | |
621 | 647 |
|
622 | 648 |
static void init_timers(void) |
623 | 649 |
{ |
624 |
struct sigaction act; |
|
625 |
struct itimerval itv; |
|
626 |
|
|
627 |
/* get times() syscall frequency */ |
|
628 |
timer_freq = sysconf(_SC_CLK_TCK); |
|
629 |
|
|
630 | 650 |
rt_clock = qemu_new_clock(QEMU_TIMER_REALTIME); |
631 | 651 |
vm_clock = qemu_new_clock(QEMU_TIMER_VIRTUAL); |
632 | 652 |
|
633 |
/* timer signal */ |
|
634 |
sigfillset(&act.sa_mask); |
|
635 |
act.sa_flags = 0; |
|
653 |
#ifdef _WIN32 |
|
654 |
{ |
|
655 |
int count=0; |
|
656 |
MMRESULT timerID = timeSetEvent(10, // interval (ms) |
|
657 |
0, // resolution |
|
658 |
host_alarm_handler, // function |
|
659 |
(DWORD)&count, // user parameter |
|
660 |
TIME_PERIODIC | TIME_CALLBACK_FUNCTION); |
|
661 |
if( !timerID ) { |
|
662 |
perror("failed timer alarm"); |
|
663 |
exit(1); |
|
664 |
} |
|
665 |
} |
|
666 |
pit_min_timer_count = ((uint64_t)10000 * PIT_FREQ) / 1000000; |
|
667 |
#else |
|
668 |
{ |
|
669 |
struct sigaction act; |
|
670 |
struct itimerval itv; |
|
671 |
|
|
672 |
/* get times() syscall frequency */ |
|
673 |
timer_freq = sysconf(_SC_CLK_TCK); |
|
674 |
|
|
675 |
/* timer signal */ |
|
676 |
sigfillset(&act.sa_mask); |
|
677 |
act.sa_flags = 0; |
|
636 | 678 |
#if defined (TARGET_I386) && defined(USE_CODE_COPY) |
637 |
act.sa_flags |= SA_ONSTACK; |
|
679 |
act.sa_flags |= SA_ONSTACK; |
|
680 |
#endif |
|
681 |
act.sa_handler = host_alarm_handler; |
|
682 |
sigaction(SIGALRM, &act, NULL); |
|
683 |
|
|
684 |
itv.it_interval.tv_sec = 0; |
|
685 |
itv.it_interval.tv_usec = 1000; |
|
686 |
itv.it_value.tv_sec = 0; |
|
687 |
itv.it_value.tv_usec = 10 * 1000; |
|
688 |
setitimer(ITIMER_REAL, &itv, NULL); |
|
689 |
/* we probe the tick duration of the kernel to inform the user if |
|
690 |
the emulated kernel requested a too high timer frequency */ |
|
691 |
getitimer(ITIMER_REAL, &itv); |
|
692 |
pit_min_timer_count = ((uint64_t)itv.it_interval.tv_usec * PIT_FREQ) / |
|
693 |
1000000; |
|
694 |
} |
|
638 | 695 |
#endif |
639 |
act.sa_handler = host_alarm_handler; |
|
640 |
sigaction(SIGALRM, &act, NULL); |
|
641 |
|
|
642 |
itv.it_interval.tv_sec = 0; |
|
643 |
itv.it_interval.tv_usec = 1000; |
|
644 |
itv.it_value.tv_sec = 0; |
|
645 |
itv.it_value.tv_usec = 10 * 1000; |
|
646 |
setitimer(ITIMER_REAL, &itv, NULL); |
|
647 |
/* we probe the tick duration of the kernel to inform the user if |
|
648 |
the emulated kernel requested a too high timer frequency */ |
|
649 |
getitimer(ITIMER_REAL, &itv); |
|
650 |
pit_min_timer_count = ((uint64_t)itv.it_interval.tv_usec * PIT_FREQ) / |
|
651 |
1000000; |
|
652 | 696 |
} |
653 | 697 |
|
654 | 698 |
/***********************************************************/ |
655 | 699 |
/* serial device */ |
656 | 700 |
|
701 |
#ifdef _WIN32 |
|
702 |
|
|
703 |
int serial_open_device(void) |
|
704 |
{ |
|
705 |
return -1; |
|
706 |
} |
|
707 |
|
|
708 |
#else |
|
709 |
|
|
657 | 710 |
int serial_open_device(void) |
658 | 711 |
{ |
659 | 712 |
char slave_name[1024]; |
... | ... | |
672 | 725 |
} |
673 | 726 |
} |
674 | 727 |
|
728 |
#endif |
|
729 |
|
|
675 | 730 |
/***********************************************************/ |
676 | 731 |
/* Linux network device redirector */ |
677 | 732 |
|
733 |
#ifdef _WIN32 |
|
734 |
|
|
735 |
static int net_init(void) |
|
736 |
{ |
|
737 |
return 0; |
|
738 |
} |
|
739 |
|
|
740 |
void net_send_packet(NetDriverState *nd, const uint8_t *buf, int size) |
|
741 |
{ |
|
742 |
} |
|
743 |
|
|
744 |
#else |
|
745 |
|
|
678 | 746 |
static int tun_open(char *ifname, int ifname_size) |
679 | 747 |
{ |
680 | 748 |
struct ifreq ifr; |
... | ... | |
753 | 821 |
write(nd->fd, buf, size); |
754 | 822 |
} |
755 | 823 |
|
824 |
#endif |
|
825 |
|
|
756 | 826 |
/***********************************************************/ |
757 | 827 |
/* dumb display */ |
758 | 828 |
|
829 |
#ifdef _WIN32 |
|
830 |
|
|
831 |
static void term_exit(void) |
|
832 |
{ |
|
833 |
} |
|
834 |
|
|
835 |
static void term_init(void) |
|
836 |
{ |
|
837 |
} |
|
838 |
|
|
839 |
#else |
|
840 |
|
|
759 | 841 |
/* init terminal so that we can grab keys */ |
760 | 842 |
static struct termios oldtty; |
761 | 843 |
|
... | ... | |
790 | 872 |
fcntl(0, F_SETFL, O_NONBLOCK); |
791 | 873 |
} |
792 | 874 |
|
875 |
#endif |
|
876 |
|
|
793 | 877 |
static void dumb_update(DisplayState *ds, int x, int y, int w, int h) |
794 | 878 |
{ |
795 | 879 |
} |
... | ... | |
1396 | 1480 |
|
1397 | 1481 |
int main_loop(void) |
1398 | 1482 |
{ |
1483 |
#ifndef _WIN32 |
|
1399 | 1484 |
struct pollfd ufds[MAX_IO_HANDLERS + 1], *pf; |
1400 |
int ret, n, timeout, max_size; |
|
1401 |
uint8_t buf[4096]; |
|
1402 | 1485 |
IOHandlerRecord *ioh, *ioh_next; |
1486 |
uint8_t buf[4096]; |
|
1487 |
int n, max_size; |
|
1488 |
#endif |
|
1489 |
int ret, timeout; |
|
1403 | 1490 |
CPUState *env = global_env; |
1404 | 1491 |
|
1405 | 1492 |
for(;;) { |
... | ... | |
1422 | 1509 |
timeout = 10; |
1423 | 1510 |
} |
1424 | 1511 |
|
1512 |
#ifndef _WIN32 |
|
1425 | 1513 |
/* poll any events */ |
1426 | 1514 |
/* XXX: separate device handlers from system ones */ |
1427 | 1515 |
pf = ufds; |
... | ... | |
1471 | 1559 |
} |
1472 | 1560 |
} |
1473 | 1561 |
} |
1562 |
#endif |
|
1474 | 1563 |
|
1475 | 1564 |
if (vm_running) { |
1476 | 1565 |
qemu_run_timers(&active_timers[QEMU_TIMER_VIRTUAL], |
... | ... | |
1592 | 1681 |
|
1593 | 1682 |
int main(int argc, char **argv) |
1594 | 1683 |
{ |
1595 |
int c, i, use_gdbstub, gdbstub_port, long_index, has_cdrom; |
|
1684 |
#ifdef CONFIG_GDBSTUB |
|
1685 |
int use_gdbstub, gdbstub_port; |
|
1686 |
#endif |
|
1687 |
int c, i, long_index, has_cdrom; |
|
1596 | 1688 |
int snapshot, linux_boot; |
1597 | 1689 |
CPUState *env; |
1598 | 1690 |
const char *initrd_filename; |
... | ... | |
1601 | 1693 |
DisplayState *ds = &display_state; |
1602 | 1694 |
int cyls, heads, secs; |
1603 | 1695 |
|
1696 |
#if !defined(CONFIG_SOFTMMU) |
|
1604 | 1697 |
/* we never want that malloc() uses mmap() */ |
1605 | 1698 |
mallopt(M_MMAP_THRESHOLD, 4096 * 1024); |
1699 |
#endif |
|
1606 | 1700 |
initrd_filename = NULL; |
1607 | 1701 |
for(i = 0; i < MAX_FD; i++) |
1608 | 1702 |
fd_filename[i] = NULL; |
... | ... | |
1611 | 1705 |
ram_size = 32 * 1024 * 1024; |
1612 | 1706 |
vga_ram_size = VGA_RAM_SIZE; |
1613 | 1707 |
pstrcpy(network_script, sizeof(network_script), DEFAULT_NETWORK_SCRIPT); |
1708 |
#ifdef CONFIG_GDBSTUB |
|
1614 | 1709 |
use_gdbstub = 0; |
1615 | 1710 |
gdbstub_port = DEFAULT_GDBSTUB_PORT; |
1711 |
#endif |
|
1616 | 1712 |
snapshot = 0; |
1617 | 1713 |
nographic = 0; |
1618 | 1714 |
kernel_filename = NULL; |
... | ... | |
1773 | 1869 |
case 'n': |
1774 | 1870 |
pstrcpy(network_script, sizeof(network_script), optarg); |
1775 | 1871 |
break; |
1872 |
#ifdef CONFIG_GDBSTUB |
|
1776 | 1873 |
case 's': |
1777 | 1874 |
use_gdbstub = 1; |
1778 | 1875 |
break; |
1779 | 1876 |
case 'p': |
1780 | 1877 |
gdbstub_port = atoi(optarg); |
1781 | 1878 |
break; |
1879 |
#endif |
|
1782 | 1880 |
case 'L': |
1783 | 1881 |
bios_dir = optarg; |
1784 | 1882 |
break; |
... | ... | |
1976 | 2074 |
} |
1977 | 2075 |
#endif |
1978 | 2076 |
|
2077 |
#ifndef _WIN32 |
|
1979 | 2078 |
{ |
1980 | 2079 |
struct sigaction act; |
1981 | 2080 |
sigfillset(&act.sa_mask); |
... | ... | |
1983 | 2082 |
act.sa_handler = SIG_IGN; |
1984 | 2083 |
sigaction(SIGPIPE, &act, NULL); |
1985 | 2084 |
} |
2085 |
#endif |
|
1986 | 2086 |
|
1987 | 2087 |
gui_timer = qemu_new_timer(rt_clock, gui_update, NULL); |
1988 | 2088 |
qemu_mod_timer(gui_timer, qemu_get_clock(rt_clock)); |
1989 | 2089 |
|
2090 |
#ifdef CONFIG_GDBSTUB |
|
1990 | 2091 |
if (use_gdbstub) { |
1991 | 2092 |
if (gdbserver_start(gdbstub_port) < 0) { |
1992 | 2093 |
fprintf(stderr, "Could not open gdbserver socket on port %d\n", |
... | ... | |
1995 | 2096 |
} else { |
1996 | 2097 |
printf("Waiting gdb connection on port %d\n", gdbstub_port); |
1997 | 2098 |
} |
1998 |
} else { |
|
2099 |
} else |
|
2100 |
#endif |
|
2101 |
{ |
|
1999 | 2102 |
vm_start(); |
2000 | 2103 |
} |
2001 | 2104 |
term_init(); |
Also available in: Unified diff