Commit c40ec5a966eab19e75c98ee779145875d362b515
1 parent
c8994013
Add -clock option, by Luca Tettamanti.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3126 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
1 changed file
with
56 additions
and
1 deletions
vl.c
| ... | ... | @@ -56,6 +56,7 @@ |
| 56 | 56 | #include <pty.h> |
| 57 | 57 | #include <malloc.h> |
| 58 | 58 | #include <linux/rtc.h> |
| 59 | +#include <linux/hpet.h> | |
| 59 | 60 | #include <linux/ppdev.h> |
| 60 | 61 | #include <linux/parport.h> |
| 61 | 62 | #else |
| ... | ... | @@ -809,6 +810,9 @@ static void unix_stop_timer(struct qemu_alarm_timer *t); |
| 809 | 810 | |
| 810 | 811 | #ifdef __linux__ |
| 811 | 812 | |
| 813 | +static int hpet_start_timer(struct qemu_alarm_timer *t); | |
| 814 | +static void hpet_stop_timer(struct qemu_alarm_timer *t); | |
| 815 | + | |
| 812 | 816 | static int rtc_start_timer(struct qemu_alarm_timer *t); |
| 813 | 817 | static void rtc_stop_timer(struct qemu_alarm_timer *t); |
| 814 | 818 | |
| ... | ... | @@ -818,7 +822,9 @@ static void rtc_stop_timer(struct qemu_alarm_timer *t); |
| 818 | 822 | |
| 819 | 823 | static struct qemu_alarm_timer alarm_timers[] = { |
| 820 | 824 | #ifdef __linux__ |
| 821 | - /* RTC - if available - is preferred */ | |
| 825 | + /* HPET - if available - is preferred */ | |
| 826 | + {"hpet", hpet_start_timer, hpet_stop_timer, NULL}, | |
| 827 | + /* ...otherwise try RTC */ | |
| 822 | 828 | {"rtc", rtc_start_timer, rtc_stop_timer, NULL}, |
| 823 | 829 | #endif |
| 824 | 830 | #ifndef _WIN32 |
| ... | ... | @@ -1088,6 +1094,55 @@ static void enable_sigio_timer(int fd) |
| 1088 | 1094 | fcntl(fd, F_SETOWN, getpid()); |
| 1089 | 1095 | } |
| 1090 | 1096 | |
| 1097 | +static int hpet_start_timer(struct qemu_alarm_timer *t) | |
| 1098 | +{ | |
| 1099 | + struct hpet_info info; | |
| 1100 | + int r, fd; | |
| 1101 | + | |
| 1102 | + fd = open("/dev/hpet", O_RDONLY); | |
| 1103 | + if (fd < 0) | |
| 1104 | + return -1; | |
| 1105 | + | |
| 1106 | + /* Set frequency */ | |
| 1107 | + r = ioctl(fd, HPET_IRQFREQ, RTC_FREQ); | |
| 1108 | + if (r < 0) { | |
| 1109 | + fprintf(stderr, "Could not configure '/dev/hpet' to have a 1024Hz timer. This is not a fatal\n" | |
| 1110 | + "error, but for better emulation accuracy type:\n" | |
| 1111 | + "'echo 1024 > /proc/sys/dev/hpet/max-user-freq' as root.\n"); | |
| 1112 | + goto fail; | |
| 1113 | + } | |
| 1114 | + | |
| 1115 | + /* Check capabilities */ | |
| 1116 | + r = ioctl(fd, HPET_INFO, &info); | |
| 1117 | + if (r < 0) | |
| 1118 | + goto fail; | |
| 1119 | + | |
| 1120 | + /* Enable periodic mode */ | |
| 1121 | + r = ioctl(fd, HPET_EPI, 0); | |
| 1122 | + if (info.hi_flags && (r < 0)) | |
| 1123 | + goto fail; | |
| 1124 | + | |
| 1125 | + /* Enable interrupt */ | |
| 1126 | + r = ioctl(fd, HPET_IE_ON, 0); | |
| 1127 | + if (r < 0) | |
| 1128 | + goto fail; | |
| 1129 | + | |
| 1130 | + enable_sigio_timer(fd); | |
| 1131 | + t->priv = (void *)fd; | |
| 1132 | + | |
| 1133 | + return 0; | |
| 1134 | +fail: | |
| 1135 | + close(fd); | |
| 1136 | + return -1; | |
| 1137 | +} | |
| 1138 | + | |
| 1139 | +static void hpet_stop_timer(struct qemu_alarm_timer *t) | |
| 1140 | +{ | |
| 1141 | + int fd = (int)t->priv; | |
| 1142 | + | |
| 1143 | + close(fd); | |
| 1144 | +} | |
| 1145 | + | |
| 1091 | 1146 | static int rtc_start_timer(struct qemu_alarm_timer *t) |
| 1092 | 1147 | { |
| 1093 | 1148 | int rtc_fd; | ... | ... |