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 | 636 | #define CPU_LOG_INT (1 << 4) |
| 637 | 637 | #define CPU_LOG_EXEC (1 << 5) |
| 638 | 638 | #define CPU_LOG_PCALL (1 << 6) |
| 639 | +#define CPU_LOG_IOPORT (1 << 7) | |
| 639 | 640 | |
| 640 | 641 | /* define log items */ |
| 641 | 642 | typedef struct CPULogItem { | ... | ... |
exec.c
| ... | ... | @@ -1131,6 +1131,8 @@ CPULogItem cpu_log_items[] = { |
| 1131 | 1131 | { CPU_LOG_PCALL, "pcall", |
| 1132 | 1132 | "show protected mode far calls/returns/exceptions" }, |
| 1133 | 1133 | #endif |
| 1134 | + { CPU_LOG_IOPORT, "ioport", | |
| 1135 | + "show all i/o ports accesses" }, | |
| 1134 | 1136 | { 0, NULL, NULL }, |
| 1135 | 1137 | }; |
| 1136 | 1138 | ... | ... |
vl.c
| ... | ... | @@ -43,6 +43,7 @@ |
| 43 | 43 | #include <sys/socket.h> |
| 44 | 44 | #include <linux/if.h> |
| 45 | 45 | #include <linux/if_tun.h> |
| 46 | +#include <linux/rtc.h> | |
| 46 | 47 | #endif |
| 47 | 48 | |
| 48 | 49 | #if defined(CONFIG_SLIRP) |
| ... | ... | @@ -77,6 +78,7 @@ extern void __sigaction(); |
| 77 | 78 | #define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup" |
| 78 | 79 | |
| 79 | 80 | //#define DEBUG_UNUSED_IOPORT |
| 81 | +//#define DEBUG_IOPORT | |
| 80 | 82 | |
| 81 | 83 | #if !defined(CONFIG_SOFTMMU) |
| 82 | 84 | #define PHYS_RAM_MAX_SIZE (256 * 1024 * 1024) |
| ... | ... | @@ -274,37 +276,67 @@ int load_image(const char *filename, uint8_t *addr) |
| 274 | 276 | void cpu_outb(CPUState *env, int addr, int val) |
| 275 | 277 | { |
| 276 | 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 | 283 | ioport_write_table[0][addr](ioport_opaque[addr], addr, val); |
| 278 | 284 | } |
| 279 | 285 | |
| 280 | 286 | void cpu_outw(CPUState *env, int addr, int val) |
| 281 | 287 | { |
| 282 | 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 | 293 | ioport_write_table[1][addr](ioport_opaque[addr], addr, val); |
| 284 | 294 | } |
| 285 | 295 | |
| 286 | 296 | void cpu_outl(CPUState *env, int addr, int val) |
| 287 | 297 | { |
| 288 | 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 | 303 | ioport_write_table[2][addr](ioport_opaque[addr], addr, val); |
| 290 | 304 | } |
| 291 | 305 | |
| 292 | 306 | int cpu_inb(CPUState *env, int addr) |
| 293 | 307 | { |
| 308 | + int val; | |
| 294 | 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 | 318 | int cpu_inw(CPUState *env, int addr) |
| 299 | 319 | { |
| 320 | + int val; | |
| 300 | 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 | 330 | int cpu_inl(CPUState *env, int addr) |
| 305 | 331 | { |
| 332 | + int val; | |
| 306 | 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 | 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 | 743 | static void init_timers(void) |
| 684 | 744 | { |
| 685 | 745 | rt_clock = qemu_new_clock(QEMU_TIMER_REALTIME); |
| ... | ... | @@ -715,7 +775,7 @@ static void init_timers(void) |
| 715 | 775 | #endif |
| 716 | 776 | act.sa_handler = host_alarm_handler; |
| 717 | 777 | sigaction(SIGALRM, &act, NULL); |
| 718 | - | |
| 778 | + | |
| 719 | 779 | itv.it_interval.tv_sec = 0; |
| 720 | 780 | itv.it_interval.tv_usec = 1000; |
| 721 | 781 | itv.it_value.tv_sec = 0; |
| ... | ... | @@ -724,8 +784,27 @@ static void init_timers(void) |
| 724 | 784 | /* we probe the tick duration of the kernel to inform the user if |
| 725 | 785 | the emulated kernel requested a too high timer frequency */ |
| 726 | 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 | 809 | #endif |
| 731 | 810 | } | ... | ... |