From mboxrd@z Thu Jan 1 00:00:00 1970 From: Luca Tettamanti Subject: [PATCH/RFC 3/4] Add support for HPET periodic timer. Date: Thu, 16 Aug 2007 22:41:16 +0200 Message-ID: <11872968773524-git-send-email-kronos.it@gmail.com> References: <11872968773449-git-send-email-kronos.it@gmail.com> <11872968771257-git-send-email-kronos.it@gmail.com> <11872968773155-git-send-email-kronos.it@gmail.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Cc: Dan Kenigsberg , Luca Tettamanti , qemu-devel-qX2TKyscuCcdnm+yROfE0A@public.gmane.org To: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org Return-path: In-Reply-To: <11872968773155-git-send-email-kronos.it-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: kvm-devel-bounces-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org Errors-To: kvm-devel-bounces-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org List-Id: kvm.vger.kernel.org Linux operates the HPET timer in legacy replacement mode, which means that the periodic interrupt of the CMOS RTC is not delivered (qemu won't be able to use /dev/rtc). Add support for HPET (/dev/hpet) as a replacement for the RTC; the periodic interrupt is delivered via SIGIO and is handled in the same way as the RTC timer. Signed-off-by: Luca Tettamanti --- qemu/vl.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 56 insertions(+), 1 deletions(-) diff --git a/qemu/vl.c b/qemu/vl.c index f0b4896..0373beb 100644 --- a/qemu/vl.c +++ b/qemu/vl.c @@ -54,6 +54,7 @@ #include #include #include +#include #include #endif #endif @@ -773,6 +774,9 @@ static void unix_stop_timer(struct qemu_alarm_timer *t); #ifdef __linux__ +static int hpet_start_timer(struct qemu_alarm_timer *t); +static void hpet_stop_timer(struct qemu_alarm_timer *t); + static int rtc_start_timer(struct qemu_alarm_timer *t); static void rtc_stop_timer(struct qemu_alarm_timer *t); @@ -782,7 +786,9 @@ static void rtc_stop_timer(struct qemu_alarm_timer *t); static struct qemu_alarm_timer alarm_timers[] = { #ifdef __linux__ - /* RTC - if available - is preferred */ + /* HPET - if available - is preferred */ + {"hpet", hpet_start_timer, hpet_stop_timer, NULL}, + /* ...otherwise try RTC */ {"rtc", rtc_start_timer, rtc_stop_timer, NULL}, #endif #ifndef _WIN32 @@ -1117,6 +1123,55 @@ static void enable_sigio_timer(int fd) fcntl(fd, F_SETOWN, getpid()); } +static int hpet_start_timer(struct qemu_alarm_timer *t) +{ + struct hpet_info info; + int r, fd; + + fd = open("/dev/hpet", O_RDONLY); + if (fd < 0) + return -1; + + /* Set frequency */ + r = ioctl(fd, HPET_IRQFREQ, RTC_FREQ); + if (r < 0) { + fprintf(stderr, "Could not configure '/dev/hpet' to have a 1024Hz timer. This is not a fatal\n" + "error, but for better emulation accuracy type:\n" + "'echo 1024 > /proc/sys/dev/hpet/max-user-freq' as root.\n"); + goto fail; + } + + /* Check capabilities */ + r = ioctl(fd, HPET_INFO, &info); + if (r < 0) + goto fail; + + /* Enable periodic mode */ + r = ioctl(fd, HPET_EPI, 0); + if (info.hi_flags && (r < 0)) + goto fail; + + /* Enable interrupt */ + r = ioctl(fd, HPET_IE_ON, 0); + if (r < 0) + goto fail; + + enable_sigio_timer(fd); + t->priv = (void *)fd; + + return 0; +fail: + close(fd); + return -1; +} + +static void hpet_stop_timer(struct qemu_alarm_timer *t) +{ + int fd = (int)t->priv; + + close(fd); +} + static int rtc_start_timer(struct qemu_alarm_timer *t) { int rtc_fd; -- 1.5.2.4 ------------------------------------------------------------------------- This SF.net email is sponsored by: Splunk Inc. Still grepping through log files to find problems? Stop. Now Search log events and configuration files using AJAX and a browser. Download your FREE copy of Splunk now >> http://get.splunk.com/