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