Commit 87858c89ca89bd1bb2044de0c8a9406bd6367ab7

Authored by bellard
1 parent a6f816d6

more precise timer emulation - fixed NE2000 probe problems - added VLTMPDIR support


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@286 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 143 additions and 29 deletions
@@ -745,17 +745,19 @@ void pic_init(void) @@ -745,17 +745,19 @@ void pic_init(void)
745 #define RW_STATE_LATCHED_WORD1 5 745 #define RW_STATE_LATCHED_WORD1 5
746 746
747 typedef struct PITChannelState { 747 typedef struct PITChannelState {
748 - uint16_t count; 748 + int count; /* can be 65536 */
749 uint16_t latched_count; 749 uint16_t latched_count;
750 uint8_t rw_state; 750 uint8_t rw_state;
751 uint8_t mode; 751 uint8_t mode;
752 uint8_t bcd; /* not supported */ 752 uint8_t bcd; /* not supported */
753 uint8_t gate; /* timer start */ 753 uint8_t gate; /* timer start */
754 int64_t count_load_time; 754 int64_t count_load_time;
  755 + int64_t count_last_edge_check_time;
755 } PITChannelState; 756 } PITChannelState;
756 757
757 PITChannelState pit_channels[3]; 758 PITChannelState pit_channels[3];
758 int speaker_data_on; 759 int speaker_data_on;
  760 +int pit_min_timer_count = 0;
759 761
760 int64_t ticks_per_sec; 762 int64_t ticks_per_sec;
761 763
@@ -785,13 +787,36 @@ void cpu_calibrate_ticks(void) @@ -785,13 +787,36 @@ void cpu_calibrate_ticks(void)
785 ticks_per_sec = (ticks * 1000000LL + (usec >> 1)) / usec; 787 ticks_per_sec = (ticks * 1000000LL + (usec >> 1)) / usec;
786 } 788 }
787 789
  790 +/* compute with 96 bit intermediate result: (a*b)/c */
  791 +static uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
  792 +{
  793 + union {
  794 + uint64_t ll;
  795 + struct {
  796 +#ifdef WORDS_BIGENDIAN
  797 + uint32_t high, low;
  798 +#else
  799 + uint32_t low, high;
  800 +#endif
  801 + } l;
  802 + } u, res;
  803 + uint64_t rl, rh;
  804 +
  805 + u.ll = a;
  806 + rl = (uint64_t)u.l.low * (uint64_t)b;
  807 + rh = (uint64_t)u.l.high * (uint64_t)b;
  808 + rh += (rl >> 32);
  809 + res.l.high = rh / c;
  810 + res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c;
  811 + return res.ll;
  812 +}
  813 +
788 static int pit_get_count(PITChannelState *s) 814 static int pit_get_count(PITChannelState *s)
789 { 815 {
790 - int64_t d; 816 + uint64_t d;
791 int counter; 817 int counter;
792 818
793 - d = ((cpu_get_ticks() - s->count_load_time) * PIT_FREQ) /  
794 - ticks_per_sec; 819 + d = muldiv64(cpu_get_ticks() - s->count_load_time, PIT_FREQ, ticks_per_sec);
795 switch(s->mode) { 820 switch(s->mode) {
796 case 0: 821 case 0:
797 case 1: 822 case 1:
@@ -809,11 +834,10 @@ static int pit_get_count(PITChannelState *s) @@ -809,11 +834,10 @@ static int pit_get_count(PITChannelState *s)
809 /* get pit output bit */ 834 /* get pit output bit */
810 static int pit_get_out(PITChannelState *s) 835 static int pit_get_out(PITChannelState *s)
811 { 836 {
812 - int64_t d; 837 + uint64_t d;
813 int out; 838 int out;
814 839
815 - d = ((cpu_get_ticks() - s->count_load_time) * PIT_FREQ) /  
816 - ticks_per_sec; 840 + d = muldiv64(cpu_get_ticks() - s->count_load_time, PIT_FREQ, ticks_per_sec);
817 switch(s->mode) { 841 switch(s->mode) {
818 default: 842 default:
819 case 0: 843 case 0:
@@ -839,11 +863,74 @@ static int pit_get_out(PITChannelState *s) @@ -839,11 +863,74 @@ static int pit_get_out(PITChannelState *s)
839 return out; 863 return out;
840 } 864 }
841 865
  866 +/* get the number of 0 to 1 transitions we had since we call this
  867 + function */
  868 +/* XXX: maybe better to use ticks precision to avoid getting edges
  869 + twice if checks are done at very small intervals */
  870 +static int pit_get_out_edges(PITChannelState *s)
  871 +{
  872 + uint64_t d1, d2;
  873 + int64_t ticks;
  874 + int ret, v;
  875 +
  876 + ticks = cpu_get_ticks();
  877 + d1 = muldiv64(s->count_last_edge_check_time - s->count_load_time,
  878 + PIT_FREQ, ticks_per_sec);
  879 + d2 = muldiv64(ticks - s->count_load_time,
  880 + PIT_FREQ, ticks_per_sec);
  881 + s->count_last_edge_check_time = ticks;
  882 + switch(s->mode) {
  883 + default:
  884 + case 0:
  885 + if (d1 < s->count && d2 >= s->count)
  886 + ret = 1;
  887 + else
  888 + ret = 0;
  889 + break;
  890 + case 1:
  891 + ret = 0;
  892 + break;
  893 + case 2:
  894 + d1 /= s->count;
  895 + d2 /= s->count;
  896 + ret = d2 - d1;
  897 + break;
  898 + case 3:
  899 + v = s->count - (s->count >> 1);
  900 + d1 = (d1 + v) / s->count;
  901 + d2 = (d2 + v) / s->count;
  902 + ret = d2 - d1;
  903 + break;
  904 + case 4:
  905 + case 5:
  906 + if (d1 < s->count && d2 >= s->count)
  907 + ret = 1;
  908 + else
  909 + ret = 0;
  910 + break;
  911 + }
  912 + return ret;
  913 +}
  914 +
  915 +static inline void pit_load_count(PITChannelState *s, int val)
  916 +{
  917 + if (val == 0)
  918 + val = 0x10000;
  919 + s->count_load_time = cpu_get_ticks();
  920 + s->count_last_edge_check_time = s->count_load_time;
  921 + s->count = val;
  922 + if (s == &pit_channels[0] && val <= pit_min_timer_count) {
  923 + fprintf(stderr,
  924 + "\nWARNING: vl: on your system, accurate timer emulation is impossible if its frequency is more than %d Hz. If using a 2.5.xx Linux kernel, you must patch asm/param.h to change HZ from 1000 to 100.\n\n",
  925 + PIT_FREQ / pit_min_timer_count);
  926 + }
  927 +}
  928 +
842 void pit_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) 929 void pit_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val)
843 { 930 {
844 int channel, access; 931 int channel, access;
845 PITChannelState *s; 932 PITChannelState *s;
846 - 933 +
847 addr &= 3; 934 addr &= 3;
848 if (addr == 3) { 935 if (addr == 3) {
849 channel = val >> 6; 936 channel = val >> 6;
@@ -857,27 +944,24 @@ void pit_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) @@ -857,27 +944,24 @@ void pit_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val)
857 s->rw_state = RW_STATE_LATCHED_WORD0; 944 s->rw_state = RW_STATE_LATCHED_WORD0;
858 break; 945 break;
859 default: 946 default:
  947 + s->mode = (val >> 1) & 7;
  948 + s->bcd = val & 1;
860 s->rw_state = access - 1 + RW_STATE_LSB; 949 s->rw_state = access - 1 + RW_STATE_LSB;
861 break; 950 break;
862 } 951 }
863 - s->mode = (val >> 1) & 7;  
864 - s->bcd = val & 1;  
865 } else { 952 } else {
866 s = &pit_channels[addr]; 953 s = &pit_channels[addr];
867 switch(s->rw_state) { 954 switch(s->rw_state) {
868 case RW_STATE_LSB: 955 case RW_STATE_LSB:
869 - s->count_load_time = cpu_get_ticks();  
870 - s->count = val; 956 + pit_load_count(s, val);
871 break; 957 break;
872 case RW_STATE_MSB: 958 case RW_STATE_MSB:
873 - s->count_load_time = cpu_get_ticks();  
874 - s->count = (val << 8); 959 + pit_load_count(s, val << 8);
875 break; 960 break;
876 case RW_STATE_WORD0: 961 case RW_STATE_WORD0:
877 case RW_STATE_WORD1: 962 case RW_STATE_WORD1:
878 if (s->rw_state & 1) { 963 if (s->rw_state & 1) {
879 - s->count_load_time = cpu_get_ticks();  
880 - s->count = (s->latched_count & 0xff) | (val << 8); 964 + pit_load_count(s, (s->latched_count & 0xff) | (val << 8));
881 } else { 965 } else {
882 s->latched_count = val; 966 s->latched_count = val;
883 } 967 }
@@ -935,16 +1019,23 @@ uint32_t speaker_ioport_read(CPUX86State *env, uint32_t addr) @@ -935,16 +1019,23 @@ uint32_t speaker_ioport_read(CPUX86State *env, uint32_t addr)
935 1019
936 void pit_init(void) 1020 void pit_init(void)
937 { 1021 {
938 - pit_channels[0].gate = 1;  
939 - pit_channels[1].gate = 1;  
940 - pit_channels[2].gate = 0;  
941 - 1022 + PITChannelState *s;
  1023 + int i;
  1024 +
  1025 + cpu_calibrate_ticks();
  1026 +
  1027 + for(i = 0;i < 3; i++) {
  1028 + s = &pit_channels[i];
  1029 + s->mode = 3;
  1030 + s->gate = (i != 2);
  1031 + pit_load_count(s, 0);
  1032 + }
  1033 +
942 register_ioport_writeb(0x40, 4, pit_ioport_write); 1034 register_ioport_writeb(0x40, 4, pit_ioport_write);
943 register_ioport_readb(0x40, 3, pit_ioport_read); 1035 register_ioport_readb(0x40, 3, pit_ioport_read);
944 1036
945 register_ioport_readb(0x61, 1, speaker_ioport_read); 1037 register_ioport_readb(0x61, 1, speaker_ioport_read);
946 register_ioport_writeb(0x61, 1, speaker_ioport_write); 1038 register_ioport_writeb(0x61, 1, speaker_ioport_write);
947 - cpu_calibrate_ticks();  
948 } 1039 }
949 1040
950 /***********************************************************/ 1041 /***********************************************************/
@@ -1462,6 +1553,8 @@ void ne2000_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val) @@ -1462,6 +1553,8 @@ void ne2000_ioport_write(CPUX86State *env, uint32_t addr, uint32_t val)
1462 s->rcnt == 0) { 1553 s->rcnt == 0) {
1463 s->isr |= ENISR_RDC; 1554 s->isr |= ENISR_RDC;
1464 ne2000_update_irq(s); 1555 ne2000_update_irq(s);
  1556 + /* XXX: find a better solution for irqs */
  1557 + cpu_x86_interrupt(global_env);
1465 } 1558 }
1466 if (val & E8390_TRANS) { 1559 if (val & E8390_TRANS) {
1467 net_send_packet(s, s->mem + (s->tpsr << 8), s->tcnt); 1560 net_send_packet(s, s->mem + (s->tpsr << 8), s->tcnt);
@@ -1671,13 +1764,23 @@ static void host_segv_handler(int host_signum, siginfo_t *info, @@ -1671,13 +1764,23 @@ static void host_segv_handler(int host_signum, siginfo_t *info,
1671 } 1764 }
1672 1765
1673 static int timer_irq_pending; 1766 static int timer_irq_pending;
  1767 +static int timer_irq_count;
1674 1768
1675 static void host_alarm_handler(int host_signum, siginfo_t *info, 1769 static void host_alarm_handler(int host_signum, siginfo_t *info,
1676 void *puc) 1770 void *puc)
1677 { 1771 {
1678 - /* just exit from the cpu to have a chance to handle timers */  
1679 - cpu_x86_interrupt(global_env);  
1680 - timer_irq_pending = 1; 1772 + /* NOTE: since usually the OS asks a 100 Hz clock, there can be
  1773 + some drift between cpu_get_ticks() and the interrupt time. So
  1774 + we queue some interrupts to avoid missing some */
  1775 + timer_irq_count += pit_get_out_edges(&pit_channels[0]);
  1776 + if (timer_irq_count) {
  1777 + if (timer_irq_count > 2)
  1778 + timer_irq_count = 2;
  1779 + timer_irq_count--;
  1780 + /* just exit from the cpu to have a chance to handle timers */
  1781 + cpu_x86_interrupt(global_env);
  1782 + timer_irq_pending = 1;
  1783 + }
1681 } 1784 }
1682 1785
1683 void help(void) 1786 void help(void)
@@ -1705,7 +1808,8 @@ int main(int argc, char **argv) @@ -1705,7 +1808,8 @@ int main(int argc, char **argv)
1705 struct sigaction act; 1808 struct sigaction act;
1706 struct itimerval itv; 1809 struct itimerval itv;
1707 CPUX86State *env; 1810 CPUX86State *env;
1708 - 1811 + const char *tmpdir;
  1812 +
1709 /* we never want that malloc() uses mmap() */ 1813 /* we never want that malloc() uses mmap() */
1710 mallopt(M_MMAP_THRESHOLD, 4096 * 1024); 1814 mallopt(M_MMAP_THRESHOLD, 4096 * 1024);
1711 1815
@@ -1749,14 +1853,19 @@ int main(int argc, char **argv) @@ -1749,14 +1853,19 @@ int main(int argc, char **argv)
1749 net_init(); 1853 net_init();
1750 1854
1751 /* init the memory */ 1855 /* init the memory */
1752 - strcpy(phys_ram_file, "/tmp/vlXXXXXX"); 1856 + tmpdir = getenv("VLTMPDIR");
  1857 + if (!tmpdir)
  1858 + tmpdir = "/tmp";
  1859 + snprintf(phys_ram_file, sizeof(phys_ram_file), "%s/vlXXXXXX", tmpdir);
1753 if (mkstemp(phys_ram_file) < 0) { 1860 if (mkstemp(phys_ram_file) < 0) {
1754 - fprintf(stderr, "Could not create temporary memory file\n"); 1861 + fprintf(stderr, "Could not create temporary memory file '%s'\n",
  1862 + phys_ram_file);
1755 exit(1); 1863 exit(1);
1756 } 1864 }
1757 phys_ram_fd = open(phys_ram_file, O_CREAT | O_TRUNC | O_RDWR, 0600); 1865 phys_ram_fd = open(phys_ram_file, O_CREAT | O_TRUNC | O_RDWR, 0600);
1758 if (phys_ram_fd < 0) { 1866 if (phys_ram_fd < 0) {
1759 - fprintf(stderr, "Could not open temporary memory file\n"); 1867 + fprintf(stderr, "Could not open temporary memory file '%s'\n",
  1868 + phys_ram_file);
1760 exit(1); 1869 exit(1);
1761 } 1870 }
1762 ftruncate(phys_ram_fd, phys_ram_size); 1871 ftruncate(phys_ram_fd, phys_ram_size);
@@ -1856,10 +1965,15 @@ int main(int argc, char **argv) @@ -1856,10 +1965,15 @@ int main(int argc, char **argv)
1856 env->eflags = 0x2; 1965 env->eflags = 0x2;
1857 1966
1858 itv.it_interval.tv_sec = 0; 1967 itv.it_interval.tv_sec = 0;
1859 - itv.it_interval.tv_usec = 10 * 1000; 1968 + itv.it_interval.tv_usec = 1000;
1860 itv.it_value.tv_sec = 0; 1969 itv.it_value.tv_sec = 0;
1861 itv.it_value.tv_usec = 10 * 1000; 1970 itv.it_value.tv_usec = 10 * 1000;
1862 setitimer(ITIMER_REAL, &itv, NULL); 1971 setitimer(ITIMER_REAL, &itv, NULL);
  1972 + /* we probe the tick duration of the kernel to inform the user if
  1973 + the emulated kernel requested a too high timer frequency */
  1974 + getitimer(ITIMER_REAL, &itv);
  1975 + pit_min_timer_count = ((uint64_t)itv.it_interval.tv_usec * PIT_FREQ) /
  1976 + 1000000;
1863 1977
1864 for(;;) { 1978 for(;;) {
1865 struct pollfd ufds[2], *pf, *serial_ufd, *net_ufd; 1979 struct pollfd ufds[2], *pf, *serial_ufd, *net_ufd;