Commit 1dce7c3c2244a6f149e7afd7b1d84963ed57b7fd

Authored by bellard
1 parent effedbc9

new clock logic: cpu ticks and virtual clocks are no longer proportional - added…

… timestamps on the stdio console


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2049 c046a42c-6fe2-441c-8c8c-71466251a162
@@ -58,10 +58,19 @@ static void ioportF0_write(void *opaque, uint32_t addr, uint32_t data) @@ -58,10 +58,19 @@ static void ioportF0_write(void *opaque, uint32_t addr, uint32_t data)
58 } 58 }
59 59
60 /* TSC handling */ 60 /* TSC handling */
61 -  
62 uint64_t cpu_get_tsc(CPUX86State *env) 61 uint64_t cpu_get_tsc(CPUX86State *env)
63 { 62 {
64 - return qemu_get_clock(vm_clock); 63 + /* Note: when using kqemu, it is more logical to return the host TSC
  64 + because kqemu does not trap the RDTSC instruction for
  65 + performance reasons */
  66 +#if USE_KQEMU
  67 + if (env->kqemu_enabled) {
  68 + return cpu_get_real_ticks();
  69 + } else
  70 +#endif
  71 + {
  72 + return cpu_get_ticks();
  73 + }
65 } 74 }
66 75
67 /* IRQ handling */ 76 /* IRQ handling */
linux-user/main.c
@@ -107,29 +107,7 @@ int cpu_get_pic_interrupt(CPUState *env) @@ -107,29 +107,7 @@ int cpu_get_pic_interrupt(CPUState *env)
107 107
108 /* timers for rdtsc */ 108 /* timers for rdtsc */
109 109
110 -#if defined(__i386__)  
111 -  
112 -int64_t cpu_get_real_ticks(void)  
113 -{  
114 - int64_t val;  
115 - asm volatile ("rdtsc" : "=A" (val));  
116 - return val;  
117 -}  
118 -  
119 -#elif defined(__x86_64__)  
120 -  
121 -int64_t cpu_get_real_ticks(void)  
122 -{  
123 - uint32_t low,high;  
124 - int64_t val;  
125 - asm volatile("rdtsc" : "=a" (low), "=d" (high));  
126 - val = high;  
127 - val <<= 32;  
128 - val |= low;  
129 - return val;  
130 -}  
131 -  
132 -#else 110 +#if 0
133 111
134 static uint64_t emu_time; 112 static uint64_t emu_time;
135 113
@@ -482,114 +482,103 @@ int kbd_mouse_is_absolute(void) @@ -482,114 +482,103 @@ int kbd_mouse_is_absolute(void)
482 return qemu_put_mouse_event_absolute; 482 return qemu_put_mouse_event_absolute;
483 } 483 }
484 484
485 -/***********************************************************/  
486 -/* timers */  
487 -  
488 -#if defined(__powerpc__)  
489 -  
490 -static inline uint32_t get_tbl(void) 485 +/* compute with 96 bit intermediate result: (a*b)/c */
  486 +uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
491 { 487 {
492 - uint32_t tbl;  
493 - asm volatile("mftb %0" : "=r" (tbl));  
494 - return tbl;  
495 -} 488 + union {
  489 + uint64_t ll;
  490 + struct {
  491 +#ifdef WORDS_BIGENDIAN
  492 + uint32_t high, low;
  493 +#else
  494 + uint32_t low, high;
  495 +#endif
  496 + } l;
  497 + } u, res;
  498 + uint64_t rl, rh;
496 499
497 -static inline uint32_t get_tbu(void)  
498 -{  
499 - uint32_t tbl;  
500 - asm volatile("mftbu %0" : "=r" (tbl));  
501 - return tbl; 500 + u.ll = a;
  501 + rl = (uint64_t)u.l.low * (uint64_t)b;
  502 + rh = (uint64_t)u.l.high * (uint64_t)b;
  503 + rh += (rl >> 32);
  504 + res.l.high = rh / c;
  505 + res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c;
  506 + return res.ll;
502 } 507 }
503 508
504 -int64_t cpu_get_real_ticks(void)  
505 -{  
506 - uint32_t l, h, h1;  
507 - /* NOTE: we test if wrapping has occurred */  
508 - do {  
509 - h = get_tbu();  
510 - l = get_tbl();  
511 - h1 = get_tbu();  
512 - } while (h != h1);  
513 - return ((int64_t)h << 32) | l;  
514 -} 509 +/***********************************************************/
  510 +/* real time host monotonic timer */
515 511
516 -#elif defined(__i386__) 512 +#define QEMU_TIMER_BASE 1000000000LL
517 513
518 -int64_t cpu_get_real_ticks(void)  
519 -{  
520 -#ifdef _WIN32  
521 - LARGE_INTEGER ti;  
522 - QueryPerformanceCounter(&ti);  
523 - return ti.QuadPart;  
524 -#else  
525 - int64_t val;  
526 - asm volatile ("rdtsc" : "=A" (val));  
527 - return val;  
528 -#endif  
529 -} 514 +#ifdef WIN32
530 515
531 -#elif defined(__x86_64__) 516 +static int64_t clock_freq;
532 517
533 -int64_t cpu_get_real_ticks(void) 518 +static void init_get_clock(void)
534 { 519 {
535 - uint32_t low,high;  
536 - int64_t val;  
537 - asm volatile("rdtsc" : "=a" (low), "=d" (high));  
538 - val = high;  
539 - val <<= 32;  
540 - val |= low;  
541 - return val; 520 + ret = QueryPerformanceFrequency(&freq);
  521 + if (ret == 0) {
  522 + fprintf(stderr, "Could not calibrate ticks\n");
  523 + exit(1);
  524 + }
  525 + clock_freq = freq.QuadPart;
542 } 526 }
543 527
544 -#elif defined(__ia64)  
545 -  
546 -int64_t cpu_get_real_ticks(void) 528 +static int64_t get_clock(void)
547 { 529 {
548 - int64_t val;  
549 - asm volatile ("mov %0 = ar.itc" : "=r"(val) :: "memory");  
550 - return val; 530 + LARGE_INTEGER ti;
  531 + QueryPerformanceCounter(&ti);
  532 + return muldiv64(ti.QuadPart, QEMU_TIMER_BASE, clock_freq);
551 } 533 }
552 534
553 -#elif defined(__s390__) 535 +#else
554 536
555 -int64_t cpu_get_real_ticks(void) 537 +static int use_rt_clock;
  538 +
  539 +static void init_get_clock(void)
556 { 540 {
557 - int64_t val;  
558 - asm volatile("stck 0(%1)" : "=m" (val) : "a" (&val) : "cc");  
559 - return val; 541 + use_rt_clock = 0;
  542 +#if defined(__linux__)
  543 + {
  544 + struct timespec ts;
  545 + if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
  546 + use_rt_clock = 1;
  547 + }
  548 + }
  549 +#endif
560 } 550 }
561 551
562 -#elif defined(__sparc__) && defined(HOST_SOLARIS)  
563 -  
564 -uint64_t cpu_get_real_ticks (void) 552 +static int64_t get_clock(void)
565 { 553 {
566 -#if defined(_LP64)  
567 - uint64_t rval;  
568 - asm volatile("rd %%tick,%0" : "=r"(rval));  
569 - return rval;  
570 -#else  
571 - union {  
572 - uint64_t i64;  
573 - struct {  
574 - uint32_t high;  
575 - uint32_t low;  
576 - } i32;  
577 - } rval;  
578 - asm volatile("rd %%tick,%1; srlx %1,32,%0"  
579 - : "=r"(rval.i32.high), "=r"(rval.i32.low));  
580 - return rval.i64; 554 +#if defined(__linux__)
  555 + if (use_rt_clock) {
  556 + struct timespec ts;
  557 + clock_gettime(CLOCK_MONOTONIC, &ts);
  558 + return ts.tv_sec * 1000000000LL + ts.tv_nsec;
  559 + } else
581 #endif 560 #endif
  561 + {
  562 + /* XXX: using gettimeofday leads to problems if the date
  563 + changes, so it should be avoided. */
  564 + struct timeval tv;
  565 + gettimeofday(&tv, NULL);
  566 + return tv.tv_sec * 1000000000LL + (tv.tv_usec * 1000);
  567 + }
582 } 568 }
583 569
584 -#else  
585 -#error unsupported CPU  
586 #endif 570 #endif
587 571
  572 +/***********************************************************/
  573 +/* guest cycle counter */
  574 +
588 static int64_t cpu_ticks_prev; 575 static int64_t cpu_ticks_prev;
589 static int64_t cpu_ticks_offset; 576 static int64_t cpu_ticks_offset;
  577 +static int64_t cpu_clock_offset;
590 static int cpu_ticks_enabled; 578 static int cpu_ticks_enabled;
591 579
592 -static inline int64_t cpu_get_ticks(void) 580 +/* return the host CPU cycle counter and handle stop/restart */
  581 +int64_t cpu_get_ticks(void)
593 { 582 {
594 if (!cpu_ticks_enabled) { 583 if (!cpu_ticks_enabled) {
595 return cpu_ticks_offset; 584 return cpu_ticks_offset;
@@ -606,11 +595,24 @@ static inline int64_t cpu_get_ticks(void) @@ -606,11 +595,24 @@ static inline int64_t cpu_get_ticks(void)
606 } 595 }
607 } 596 }
608 597
  598 +/* return the host CPU monotonic timer and handle stop/restart */
  599 +static int64_t cpu_get_clock(void)
  600 +{
  601 + int64_t ti;
  602 + if (!cpu_ticks_enabled) {
  603 + return cpu_clock_offset;
  604 + } else {
  605 + ti = get_clock();
  606 + return ti + cpu_clock_offset;
  607 + }
  608 +}
  609 +
609 /* enable cpu_get_ticks() */ 610 /* enable cpu_get_ticks() */
610 void cpu_enable_ticks(void) 611 void cpu_enable_ticks(void)
611 { 612 {
612 if (!cpu_ticks_enabled) { 613 if (!cpu_ticks_enabled) {
613 cpu_ticks_offset -= cpu_get_real_ticks(); 614 cpu_ticks_offset -= cpu_get_real_ticks();
  615 + cpu_clock_offset -= get_clock();
614 cpu_ticks_enabled = 1; 616 cpu_ticks_enabled = 1;
615 } 617 }
616 } 618 }
@@ -621,69 +623,14 @@ void cpu_disable_ticks(void) @@ -621,69 +623,14 @@ void cpu_disable_ticks(void)
621 { 623 {
622 if (cpu_ticks_enabled) { 624 if (cpu_ticks_enabled) {
623 cpu_ticks_offset = cpu_get_ticks(); 625 cpu_ticks_offset = cpu_get_ticks();
  626 + cpu_clock_offset = cpu_get_clock();
624 cpu_ticks_enabled = 0; 627 cpu_ticks_enabled = 0;
625 } 628 }
626 } 629 }
627 630
628 -#ifdef _WIN32  
629 -void cpu_calibrate_ticks(void)  
630 -{  
631 - LARGE_INTEGER freq;  
632 - int ret;  
633 -  
634 - ret = QueryPerformanceFrequency(&freq);  
635 - if (ret == 0) {  
636 - fprintf(stderr, "Could not calibrate ticks\n");  
637 - exit(1);  
638 - }  
639 - ticks_per_sec = freq.QuadPart;  
640 -}  
641 -  
642 -#else  
643 -static int64_t get_clock(void)  
644 -{  
645 - struct timeval tv;  
646 - gettimeofday(&tv, NULL);  
647 - return tv.tv_sec * 1000000LL + tv.tv_usec;  
648 -}  
649 -  
650 -void cpu_calibrate_ticks(void)  
651 -{  
652 - int64_t usec, ticks;  
653 -  
654 - usec = get_clock();  
655 - ticks = cpu_get_real_ticks();  
656 - usleep(50 * 1000);  
657 - usec = get_clock() - usec;  
658 - ticks = cpu_get_real_ticks() - ticks;  
659 - ticks_per_sec = (ticks * 1000000LL + (usec >> 1)) / usec;  
660 -}  
661 -#endif /* !_WIN32 */  
662 -  
663 -/* compute with 96 bit intermediate result: (a*b)/c */  
664 -uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)  
665 -{  
666 - union {  
667 - uint64_t ll;  
668 - struct {  
669 -#ifdef WORDS_BIGENDIAN  
670 - uint32_t high, low;  
671 -#else  
672 - uint32_t low, high;  
673 -#endif  
674 - } l;  
675 - } u, res;  
676 - uint64_t rl, rh;  
677 -  
678 - u.ll = a;  
679 - rl = (uint64_t)u.l.low * (uint64_t)b;  
680 - rh = (uint64_t)u.l.high * (uint64_t)b;  
681 - rh += (rl >> 32);  
682 - res.l.high = rh / c;  
683 - res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c;  
684 - return res.ll;  
685 -}  
686 - 631 +/***********************************************************/
  632 +/* timers */
  633 +
687 #define QEMU_TIMER_REALTIME 0 634 #define QEMU_TIMER_REALTIME 0
688 #define QEMU_TIMER_VIRTUAL 1 635 #define QEMU_TIMER_VIRTUAL 1
689 636
@@ -822,28 +769,21 @@ int64_t qemu_get_clock(QEMUClock *clock) @@ -822,28 +769,21 @@ int64_t qemu_get_clock(QEMUClock *clock)
822 { 769 {
823 switch(clock->type) { 770 switch(clock->type) {
824 case QEMU_TIMER_REALTIME: 771 case QEMU_TIMER_REALTIME:
825 -#ifdef _WIN32  
826 - return GetTickCount();  
827 -#else  
828 - {  
829 - struct tms tp;  
830 -  
831 - /* Note that using gettimeofday() is not a good solution  
832 - for timers because its value change when the date is  
833 - modified. */  
834 - if (timer_freq == 100) {  
835 - return times(&tp) * 10;  
836 - } else {  
837 - return ((int64_t)times(&tp) * 1000) / timer_freq;  
838 - }  
839 - }  
840 -#endif 772 + return get_clock() / 1000000;
841 default: 773 default:
842 case QEMU_TIMER_VIRTUAL: 774 case QEMU_TIMER_VIRTUAL:
843 - return cpu_get_ticks(); 775 + return cpu_get_clock();
844 } 776 }
845 } 777 }
846 778
  779 +static void init_timers(void)
  780 +{
  781 + init_get_clock();
  782 + ticks_per_sec = QEMU_TIMER_BASE;
  783 + rt_clock = qemu_new_clock(QEMU_TIMER_REALTIME);
  784 + vm_clock = qemu_new_clock(QEMU_TIMER_VIRTUAL);
  785 +}
  786 +
847 /* save a timer */ 787 /* save a timer */
848 void qemu_put_timer(QEMUFile *f, QEMUTimer *ts) 788 void qemu_put_timer(QEMUFile *f, QEMUTimer *ts)
849 { 789 {
@@ -985,11 +925,8 @@ static int start_rtc_timer(void) @@ -985,11 +925,8 @@ static int start_rtc_timer(void)
985 925
986 #endif /* !defined(_WIN32) */ 926 #endif /* !defined(_WIN32) */
987 927
988 -static void init_timers(void) 928 +static void init_timer_alarm(void)
989 { 929 {
990 - rt_clock = qemu_new_clock(QEMU_TIMER_REALTIME);  
991 - vm_clock = qemu_new_clock(QEMU_TIMER_VIRTUAL);  
992 -  
993 #ifdef _WIN32 930 #ifdef _WIN32
994 { 931 {
995 int count=0; 932 int count=0;
@@ -1354,7 +1291,9 @@ CharDriverState *qemu_chr_open_pipe(const char *filename) @@ -1354,7 +1291,9 @@ CharDriverState *qemu_chr_open_pipe(const char *filename)
1354 1291
1355 static int term_got_escape, client_index; 1292 static int term_got_escape, client_index;
1356 static uint8_t term_fifo[TERM_FIFO_MAX_SIZE]; 1293 static uint8_t term_fifo[TERM_FIFO_MAX_SIZE];
1357 -int term_fifo_size; 1294 +static int term_fifo_size;
  1295 +static int term_timestamps;
  1296 +static int64_t term_timestamps_start;
1358 1297
1359 void term_print_help(void) 1298 void term_print_help(void)
1360 { 1299 {
@@ -1363,6 +1302,7 @@ void term_print_help(void) @@ -1363,6 +1302,7 @@ void term_print_help(void)
1363 "C-a x exit emulator\n" 1302 "C-a x exit emulator\n"
1364 "C-a s save disk data back to file (if -snapshot)\n" 1303 "C-a s save disk data back to file (if -snapshot)\n"
1365 "C-a b send break (magic sysrq)\n" 1304 "C-a b send break (magic sysrq)\n"
  1305 + "C-a t toggle console timestamps\n"
1366 "C-a c switch between console and monitor\n" 1306 "C-a c switch between console and monitor\n"
1367 "C-a C-a send C-a\n" 1307 "C-a C-a send C-a\n"
1368 ); 1308 );
@@ -1409,6 +1349,10 @@ static void stdio_received_byte(int ch) @@ -1409,6 +1349,10 @@ static void stdio_received_byte(int ch)
1409 goto send_char; 1349 goto send_char;
1410 } 1350 }
1411 break; 1351 break;
  1352 + case 't':
  1353 + term_timestamps = !term_timestamps;
  1354 + term_timestamps_start = -1;
  1355 + break;
1412 case TERM_ESCAPE: 1356 case TERM_ESCAPE:
1413 goto send_char; 1357 goto send_char;
1414 } 1358 }
@@ -1466,6 +1410,39 @@ static void stdio_read(void *opaque) @@ -1466,6 +1410,39 @@ static void stdio_read(void *opaque)
1466 stdio_received_byte(buf[0]); 1410 stdio_received_byte(buf[0]);
1467 } 1411 }
1468 1412
  1413 +static int stdio_write(CharDriverState *chr, const uint8_t *buf, int len)
  1414 +{
  1415 + FDCharDriver *s = chr->opaque;
  1416 + if (!term_timestamps) {
  1417 + return unix_write(s->fd_out, buf, len);
  1418 + } else {
  1419 + int i;
  1420 + char buf1[64];
  1421 +
  1422 + for(i = 0; i < len; i++) {
  1423 + unix_write(s->fd_out, buf + i, 1);
  1424 + if (buf[i] == '\n') {
  1425 + int64_t ti;
  1426 + int secs;
  1427 +
  1428 + ti = get_clock();
  1429 + if (term_timestamps_start == -1)
  1430 + term_timestamps_start = ti;
  1431 + ti -= term_timestamps_start;
  1432 + secs = ti / 1000000000;
  1433 + snprintf(buf1, sizeof(buf1),
  1434 + "[%02d:%02d:%02d.%03d] ",
  1435 + secs / 3600,
  1436 + (secs / 60) % 60,
  1437 + secs % 60,
  1438 + (int)((ti / 1000000) % 1000));
  1439 + unix_write(s->fd_out, buf1, strlen(buf1));
  1440 + }
  1441 + }
  1442 + return len;
  1443 + }
  1444 +}
  1445 +
1469 /* init terminal so that we can grab keys */ 1446 /* init terminal so that we can grab keys */
1470 static struct termios oldtty; 1447 static struct termios oldtty;
1471 static int old_fd0_flags; 1448 static int old_fd0_flags;
@@ -1511,6 +1488,7 @@ CharDriverState *qemu_chr_open_stdio(void) @@ -1511,6 +1488,7 @@ CharDriverState *qemu_chr_open_stdio(void)
1511 if (stdio_nb_clients >= STDIO_MAX_CLIENTS) 1488 if (stdio_nb_clients >= STDIO_MAX_CLIENTS)
1512 return NULL; 1489 return NULL;
1513 chr = qemu_chr_open_fd(0, 1); 1490 chr = qemu_chr_open_fd(0, 1);
  1491 + chr->chr_write = stdio_write;
1514 if (stdio_nb_clients == 0) 1492 if (stdio_nb_clients == 0)
1515 qemu_set_fd_handler2(0, stdio_read_poll, stdio_read, NULL, NULL); 1493 qemu_set_fd_handler2(0, stdio_read_poll, stdio_read, NULL, NULL);
1516 client_index = stdio_nb_clients; 1494 client_index = stdio_nb_clients;
@@ -5638,6 +5616,7 @@ int main(int argc, char **argv) @@ -5638,6 +5616,7 @@ int main(int argc, char **argv)
5638 SetConsoleCtrlHandler(qemu_ctrl_handler, TRUE); 5616 SetConsoleCtrlHandler(qemu_ctrl_handler, TRUE);
5639 #endif 5617 #endif
5640 init_timers(); 5618 init_timers();
  5619 + init_timer_alarm();
5641 5620
5642 register_machines(); 5621 register_machines();
5643 machine = first_machine; 5622 machine = first_machine;
@@ -6128,7 +6107,6 @@ int main(int argc, char **argv) @@ -6128,7 +6107,6 @@ int main(int argc, char **argv)
6128 register_savevm("ram", 0, 1, ram_save, ram_load, NULL); 6107 register_savevm("ram", 0, 1, ram_save, ram_load, NULL);
6129 6108
6130 init_ioports(); 6109 init_ioports();
6131 - cpu_calibrate_ticks();  
6132 6110
6133 /* terminal init */ 6111 /* terminal init */
6134 if (nographic) { 6112 if (nographic) {
@@ -390,6 +390,7 @@ int qemu_timer_pending(QEMUTimer *ts); @@ -390,6 +390,7 @@ int qemu_timer_pending(QEMUTimer *ts);
390 extern int64_t ticks_per_sec; 390 extern int64_t ticks_per_sec;
391 extern int pit_min_timer_count; 391 extern int pit_min_timer_count;
392 392
  393 +int64_t cpu_get_ticks(void);
393 void cpu_enable_ticks(void); 394 void cpu_enable_ticks(void);
394 void cpu_disable_ticks(void); 395 void cpu_disable_ticks(void);
395 396