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,6 +56,7 @@ | ||
56 | #include <pty.h> | 56 | #include <pty.h> |
57 | #include <malloc.h> | 57 | #include <malloc.h> |
58 | #include <linux/rtc.h> | 58 | #include <linux/rtc.h> |
59 | +#include <linux/hpet.h> | ||
59 | #include <linux/ppdev.h> | 60 | #include <linux/ppdev.h> |
60 | #include <linux/parport.h> | 61 | #include <linux/parport.h> |
61 | #else | 62 | #else |
@@ -809,6 +810,9 @@ static void unix_stop_timer(struct qemu_alarm_timer *t); | @@ -809,6 +810,9 @@ static void unix_stop_timer(struct qemu_alarm_timer *t); | ||
809 | 810 | ||
810 | #ifdef __linux__ | 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 | static int rtc_start_timer(struct qemu_alarm_timer *t); | 816 | static int rtc_start_timer(struct qemu_alarm_timer *t); |
813 | static void rtc_stop_timer(struct qemu_alarm_timer *t); | 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,7 +822,9 @@ static void rtc_stop_timer(struct qemu_alarm_timer *t); | ||
818 | 822 | ||
819 | static struct qemu_alarm_timer alarm_timers[] = { | 823 | static struct qemu_alarm_timer alarm_timers[] = { |
820 | #ifdef __linux__ | 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 | {"rtc", rtc_start_timer, rtc_stop_timer, NULL}, | 828 | {"rtc", rtc_start_timer, rtc_stop_timer, NULL}, |
823 | #endif | 829 | #endif |
824 | #ifndef _WIN32 | 830 | #ifndef _WIN32 |
@@ -1088,6 +1094,55 @@ static void enable_sigio_timer(int fd) | @@ -1088,6 +1094,55 @@ static void enable_sigio_timer(int fd) | ||
1088 | fcntl(fd, F_SETOWN, getpid()); | 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 | static int rtc_start_timer(struct qemu_alarm_timer *t) | 1146 | static int rtc_start_timer(struct qemu_alarm_timer *t) |
1092 | { | 1147 | { |
1093 | int rtc_fd; | 1148 | int rtc_fd; |