Commit fd872598d8d8cf78c1f12ed9661baf9ac0943c04
1 parent
8cd0ac2f
primitive ioport debug - /dev/rtc fast timer support (needed for better simulati…
…on accuracy with Linux 2.4) git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@799 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
88 additions
and
6 deletions
cpu-all.h
| @@ -636,6 +636,7 @@ target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr); | @@ -636,6 +636,7 @@ target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr); | ||
| 636 | #define CPU_LOG_INT (1 << 4) | 636 | #define CPU_LOG_INT (1 << 4) |
| 637 | #define CPU_LOG_EXEC (1 << 5) | 637 | #define CPU_LOG_EXEC (1 << 5) |
| 638 | #define CPU_LOG_PCALL (1 << 6) | 638 | #define CPU_LOG_PCALL (1 << 6) |
| 639 | +#define CPU_LOG_IOPORT (1 << 7) | ||
| 639 | 640 | ||
| 640 | /* define log items */ | 641 | /* define log items */ |
| 641 | typedef struct CPULogItem { | 642 | typedef struct CPULogItem { |
exec.c
| @@ -1131,6 +1131,8 @@ CPULogItem cpu_log_items[] = { | @@ -1131,6 +1131,8 @@ CPULogItem cpu_log_items[] = { | ||
| 1131 | { CPU_LOG_PCALL, "pcall", | 1131 | { CPU_LOG_PCALL, "pcall", |
| 1132 | "show protected mode far calls/returns/exceptions" }, | 1132 | "show protected mode far calls/returns/exceptions" }, |
| 1133 | #endif | 1133 | #endif |
| 1134 | + { CPU_LOG_IOPORT, "ioport", | ||
| 1135 | + "show all i/o ports accesses" }, | ||
| 1134 | { 0, NULL, NULL }, | 1136 | { 0, NULL, NULL }, |
| 1135 | }; | 1137 | }; |
| 1136 | 1138 |
vl.c
| @@ -43,6 +43,7 @@ | @@ -43,6 +43,7 @@ | ||
| 43 | #include <sys/socket.h> | 43 | #include <sys/socket.h> |
| 44 | #include <linux/if.h> | 44 | #include <linux/if.h> |
| 45 | #include <linux/if_tun.h> | 45 | #include <linux/if_tun.h> |
| 46 | +#include <linux/rtc.h> | ||
| 46 | #endif | 47 | #endif |
| 47 | 48 | ||
| 48 | #if defined(CONFIG_SLIRP) | 49 | #if defined(CONFIG_SLIRP) |
| @@ -77,6 +78,7 @@ extern void __sigaction(); | @@ -77,6 +78,7 @@ extern void __sigaction(); | ||
| 77 | #define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup" | 78 | #define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup" |
| 78 | 79 | ||
| 79 | //#define DEBUG_UNUSED_IOPORT | 80 | //#define DEBUG_UNUSED_IOPORT |
| 81 | +//#define DEBUG_IOPORT | ||
| 80 | 82 | ||
| 81 | #if !defined(CONFIG_SOFTMMU) | 83 | #if !defined(CONFIG_SOFTMMU) |
| 82 | #define PHYS_RAM_MAX_SIZE (256 * 1024 * 1024) | 84 | #define PHYS_RAM_MAX_SIZE (256 * 1024 * 1024) |
| @@ -274,37 +276,67 @@ int load_image(const char *filename, uint8_t *addr) | @@ -274,37 +276,67 @@ int load_image(const char *filename, uint8_t *addr) | ||
| 274 | void cpu_outb(CPUState *env, int addr, int val) | 276 | void cpu_outb(CPUState *env, int addr, int val) |
| 275 | { | 277 | { |
| 276 | addr &= (MAX_IOPORTS - 1); | 278 | addr &= (MAX_IOPORTS - 1); |
| 279 | +#ifdef DEBUG_IOPORT | ||
| 280 | + if (loglevel & CPU_LOG_IOPORT) | ||
| 281 | + fprintf(logfile, "outb: %04x %02x\n", addr, val); | ||
| 282 | +#endif | ||
| 277 | ioport_write_table[0][addr](ioport_opaque[addr], addr, val); | 283 | ioport_write_table[0][addr](ioport_opaque[addr], addr, val); |
| 278 | } | 284 | } |
| 279 | 285 | ||
| 280 | void cpu_outw(CPUState *env, int addr, int val) | 286 | void cpu_outw(CPUState *env, int addr, int val) |
| 281 | { | 287 | { |
| 282 | addr &= (MAX_IOPORTS - 1); | 288 | addr &= (MAX_IOPORTS - 1); |
| 289 | +#ifdef DEBUG_IOPORT | ||
| 290 | + if (loglevel & CPU_LOG_IOPORT) | ||
| 291 | + fprintf(logfile, "outw: %04x %04x\n", addr, val); | ||
| 292 | +#endif | ||
| 283 | ioport_write_table[1][addr](ioport_opaque[addr], addr, val); | 293 | ioport_write_table[1][addr](ioport_opaque[addr], addr, val); |
| 284 | } | 294 | } |
| 285 | 295 | ||
| 286 | void cpu_outl(CPUState *env, int addr, int val) | 296 | void cpu_outl(CPUState *env, int addr, int val) |
| 287 | { | 297 | { |
| 288 | addr &= (MAX_IOPORTS - 1); | 298 | addr &= (MAX_IOPORTS - 1); |
| 299 | +#ifdef DEBUG_IOPORT | ||
| 300 | + if (loglevel & CPU_LOG_IOPORT) | ||
| 301 | + fprintf(logfile, "outl: %04x %08x\n", addr, val); | ||
| 302 | +#endif | ||
| 289 | ioport_write_table[2][addr](ioport_opaque[addr], addr, val); | 303 | ioport_write_table[2][addr](ioport_opaque[addr], addr, val); |
| 290 | } | 304 | } |
| 291 | 305 | ||
| 292 | int cpu_inb(CPUState *env, int addr) | 306 | int cpu_inb(CPUState *env, int addr) |
| 293 | { | 307 | { |
| 308 | + int val; | ||
| 294 | addr &= (MAX_IOPORTS - 1); | 309 | addr &= (MAX_IOPORTS - 1); |
| 295 | - return ioport_read_table[0][addr](ioport_opaque[addr], addr); | 310 | + val = ioport_read_table[0][addr](ioport_opaque[addr], addr); |
| 311 | +#ifdef DEBUG_IOPORT | ||
| 312 | + if (loglevel & CPU_LOG_IOPORT) | ||
| 313 | + fprintf(logfile, "inb : %04x %02x\n", addr, val); | ||
| 314 | +#endif | ||
| 315 | + return val; | ||
| 296 | } | 316 | } |
| 297 | 317 | ||
| 298 | int cpu_inw(CPUState *env, int addr) | 318 | int cpu_inw(CPUState *env, int addr) |
| 299 | { | 319 | { |
| 320 | + int val; | ||
| 300 | addr &= (MAX_IOPORTS - 1); | 321 | addr &= (MAX_IOPORTS - 1); |
| 301 | - return ioport_read_table[1][addr](ioport_opaque[addr], addr); | 322 | + val = ioport_read_table[1][addr](ioport_opaque[addr], addr); |
| 323 | +#ifdef DEBUG_IOPORT | ||
| 324 | + if (loglevel & CPU_LOG_IOPORT) | ||
| 325 | + fprintf(logfile, "inw : %04x %04x\n", addr, val); | ||
| 326 | +#endif | ||
| 327 | + return val; | ||
| 302 | } | 328 | } |
| 303 | 329 | ||
| 304 | int cpu_inl(CPUState *env, int addr) | 330 | int cpu_inl(CPUState *env, int addr) |
| 305 | { | 331 | { |
| 332 | + int val; | ||
| 306 | addr &= (MAX_IOPORTS - 1); | 333 | addr &= (MAX_IOPORTS - 1); |
| 307 | - return ioport_read_table[2][addr](ioport_opaque[addr], addr); | 334 | + val = ioport_read_table[2][addr](ioport_opaque[addr], addr); |
| 335 | +#ifdef DEBUG_IOPORT | ||
| 336 | + if (loglevel & CPU_LOG_IOPORT) | ||
| 337 | + fprintf(logfile, "inl : %04x %08x\n", addr, val); | ||
| 338 | +#endif | ||
| 339 | + return val; | ||
| 308 | } | 340 | } |
| 309 | 341 | ||
| 310 | /***********************************************************/ | 342 | /***********************************************************/ |
| @@ -680,6 +712,34 @@ static void host_alarm_handler(int host_signum) | @@ -680,6 +712,34 @@ static void host_alarm_handler(int host_signum) | ||
| 680 | } | 712 | } |
| 681 | } | 713 | } |
| 682 | 714 | ||
| 715 | +#ifndef _WIN32 | ||
| 716 | + | ||
| 717 | +#define RTC_FREQ 1024 | ||
| 718 | + | ||
| 719 | +static int rtc_fd; | ||
| 720 | + | ||
| 721 | +static int start_rtc_timer(void) | ||
| 722 | +{ | ||
| 723 | + rtc_fd = open("/dev/rtc", O_RDONLY); | ||
| 724 | + if (rtc_fd < 0) | ||
| 725 | + return -1; | ||
| 726 | + if (ioctl(rtc_fd, RTC_IRQP_SET, RTC_FREQ) < 0) { | ||
| 727 | + fprintf(stderr, "Could not configure '/dev/rtc' to have a 1024 Hz timer. This is not a fatal\n" | ||
| 728 | + "error, but for better emulation accuracy either use a 2.6 host Linux kernel or\n" | ||
| 729 | + "type 'echo 1024 > /proc/sys/dev/rtc/max-user-freq' as root.\n"); | ||
| 730 | + goto fail; | ||
| 731 | + } | ||
| 732 | + if (ioctl(rtc_fd, RTC_PIE_ON, 0) < 0) { | ||
| 733 | + fail: | ||
| 734 | + close(rtc_fd); | ||
| 735 | + return -1; | ||
| 736 | + } | ||
| 737 | + pit_min_timer_count = PIT_FREQ / RTC_FREQ; | ||
| 738 | + return 0; | ||
| 739 | +} | ||
| 740 | + | ||
| 741 | +#endif | ||
| 742 | + | ||
| 683 | static void init_timers(void) | 743 | static void init_timers(void) |
| 684 | { | 744 | { |
| 685 | rt_clock = qemu_new_clock(QEMU_TIMER_REALTIME); | 745 | rt_clock = qemu_new_clock(QEMU_TIMER_REALTIME); |
| @@ -715,7 +775,7 @@ static void init_timers(void) | @@ -715,7 +775,7 @@ static void init_timers(void) | ||
| 715 | #endif | 775 | #endif |
| 716 | act.sa_handler = host_alarm_handler; | 776 | act.sa_handler = host_alarm_handler; |
| 717 | sigaction(SIGALRM, &act, NULL); | 777 | sigaction(SIGALRM, &act, NULL); |
| 718 | - | 778 | + |
| 719 | itv.it_interval.tv_sec = 0; | 779 | itv.it_interval.tv_sec = 0; |
| 720 | itv.it_interval.tv_usec = 1000; | 780 | itv.it_interval.tv_usec = 1000; |
| 721 | itv.it_value.tv_sec = 0; | 781 | itv.it_value.tv_sec = 0; |
| @@ -724,8 +784,27 @@ static void init_timers(void) | @@ -724,8 +784,27 @@ static void init_timers(void) | ||
| 724 | /* we probe the tick duration of the kernel to inform the user if | 784 | /* we probe the tick duration of the kernel to inform the user if |
| 725 | the emulated kernel requested a too high timer frequency */ | 785 | the emulated kernel requested a too high timer frequency */ |
| 726 | getitimer(ITIMER_REAL, &itv); | 786 | getitimer(ITIMER_REAL, &itv); |
| 727 | - pit_min_timer_count = ((uint64_t)itv.it_interval.tv_usec * PIT_FREQ) / | ||
| 728 | - 1000000; | 787 | + |
| 788 | + if (itv.it_interval.tv_usec > 1000) { | ||
| 789 | + /* try to use /dev/rtc to have a faster timer */ | ||
| 790 | + if (start_rtc_timer() < 0) | ||
| 791 | + goto use_itimer; | ||
| 792 | + /* disable itimer */ | ||
| 793 | + itv.it_interval.tv_sec = 0; | ||
| 794 | + itv.it_interval.tv_usec = 0; | ||
| 795 | + itv.it_value.tv_sec = 0; | ||
| 796 | + itv.it_value.tv_usec = 0; | ||
| 797 | + setitimer(ITIMER_REAL, &itv, NULL); | ||
| 798 | + | ||
| 799 | + /* use the RTC */ | ||
| 800 | + sigaction(SIGIO, &act, NULL); | ||
| 801 | + fcntl(rtc_fd, F_SETFL, O_ASYNC); | ||
| 802 | + fcntl(rtc_fd, F_SETOWN, getpid()); | ||
| 803 | + } else { | ||
| 804 | + use_itimer: | ||
| 805 | + pit_min_timer_count = ((uint64_t)itv.it_interval.tv_usec * | ||
| 806 | + PIT_FREQ) / 1000000; | ||
| 807 | + } | ||
| 729 | } | 808 | } |
| 730 | #endif | 809 | #endif |
| 731 | } | 810 | } |