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 | } | ... | ... |