From: malc <malc@pulsesoft.com>
To: qemu-devel@nongnu.org
Subject: [Qemu-devel] Stable clock source
Date: Wed, 12 Jul 2006 01:15:43 +0400 (MSD) [thread overview]
Message-ID: <Pine.LNX.4.64.0607120112010.3918@home.oyster.ru> (raw)
[-- Attachment #1: Type: TEXT/PLAIN, Size: 312 bytes --]
Hello,
Attached is a patch that implements non-rdtsc based[1] clock source.
Gotchas:
1. Only works on Linux
2. Only works on i386 Linux
3. Only works on i386 Linux with ACPI enabled
4. Requires root privileges (though they will be dropped)
Perhaps this will be useful to someone.
--
mailto:malc@pulsesoft.com
[-- Attachment #2: Type: TEXT/PLAIN, Size: 3919 bytes --]
Index: vl.c
===================================================================
RCS file: /cvsroot/qemu/qemu/vl.c,v
retrieving revision 1.197
diff -u -r1.197 vl.c
--- vl.c 27 Jun 2006 21:02:43 -0000 1.197
+++ vl.c 11 Jul 2006 21:07:35 -0000
@@ -23,6 +23,7 @@
*/
#include "vl.h"
+#include <err.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
@@ -157,6 +158,10 @@
int acpi_enabled = 1;
int fd_bootchk = 1;
+#if !(defined TARGET_I386) || !(defined __linux__)
+#define USE_RDTSC
+#endif
+
/***********************************************************/
/* x86 ISA bus support */
@@ -515,7 +520,33 @@
#elif defined(__i386__)
-int64_t cpu_get_real_ticks(void)
+#ifndef USE_RDTSC
+#include <unistd.h>
+#include <sys/io.h>
+#define ACPI_PM_TMR_FREQ 3579545
+
+static uint32_t acpi_prev_ticks;
+static uint32_t acpi_max_ticks;
+static uint32_t acpi_pm_tmr_addr;
+static int64_t acpi_old_ticks;
+
+static int64_t acpi_get_ticks(void)
+{
+ uint32_t ticks = inl_p (acpi_pm_tmr_addr);
+ uint32_t prev = acpi_prev_ticks;
+
+ acpi_prev_ticks = ticks;
+ if (ticks < prev)
+ ticks += (acpi_max_ticks - prev);
+ acpi_old_ticks += ticks;
+ return acpi_old_ticks;
+}
+int64_t (*cpu_get_real_ticks)(void);
+#else
+#define cpu_get_real_ticks rdtsc_get_ticks
+#endif
+
+static int64_t rdtsc_get_ticks(void)
{
#ifdef _WIN32
LARGE_INTEGER ti;
@@ -5597,6 +5628,97 @@
#define MAX_NET_CLIENTS 32
+#ifdef USE_RDTSC
+#define acpi_calibrate_ticks cpu_calibrate_ticks
+#else
+static void acpi_calibrate_ticks(void)
+{
+ int fd;
+ ssize_t nread;
+ uint32_t flags;
+ off_t off;
+ int err;
+ uid_t uid;
+
+ uid = getuid ();
+ if (uid == (uid_t) -1) {
+ warn ("could not get user id");
+ goto std_calibrate1;
+ }
+
+ err = setuid (0);
+ if (err) {
+ warn ("could not setuid 0");
+ goto std_calibrate1;
+ }
+
+ fd = open ("/proc/acpi/fadt", O_RDONLY);
+ if (fd < 0) {
+ warn ("could not open fadt");
+ goto std_calibrate;
+ }
+
+ off = lseek (fd, 76, SEEK_SET);
+ if (off - 76) {
+ warn ("could not seek");
+ goto std_calibrate;
+ }
+
+ nread = read (fd, &acpi_pm_tmr_addr, 4);
+ if (nread - 4) {
+ warn ("could not read pm timer io port address nread=%d", nread);
+ goto std_calibrate;
+ }
+
+ off = lseek (fd, 112, SEEK_SET);
+ if (off - 112) {
+ warn ("could not seek");
+ goto std_calibrate;
+ }
+
+ nread = read (fd, &flags, 4);
+ if (nread - 4) {
+ warn ("could not read pm timer facp flags nread=%d", nread);
+ goto std_calibrate;
+ }
+
+ if (!(flags & (1 << 8)))
+ acpi_max_ticks = (1 << 24) - 1;
+ else
+ acpi_max_ticks = ~0U;
+
+ err = close (fd);
+ if (err)
+ warn ("could not close fadt");
+
+ if (iopl (3)) {
+ warn ("could not change iopl");
+ goto std_calibrate2;
+ }
+
+ err = setuid (uid);
+ if (err)
+ warn ("could not restore uid");
+
+ ticks_per_sec = ACPI_PM_TMR_FREQ;
+ cpu_get_real_ticks = &acpi_get_ticks;
+ return;
+
+ std_calibrate:
+ err = close (fd);
+ if (err)
+ warn ("could not close fadt");
+ std_calibrate2:
+ err = setuid (uid);
+ if (err)
+ warn ("could not restore uid");
+ std_calibrate1:
+ fprintf (stderr, "falling back on rdtsc clock\n");
+ cpu_get_real_ticks = &rdtsc_get_ticks;
+ cpu_calibrate_ticks();
+}
+#endif
+
int main(int argc, char **argv)
{
#ifdef CONFIG_GDBSTUB
@@ -6128,7 +6250,7 @@
register_savevm("ram", 0, 1, ram_save, ram_load, NULL);
init_ioports();
- cpu_calibrate_ticks();
+ acpi_calibrate_ticks();
/* terminal init */
if (nographic) {
next reply other threads:[~2006-07-11 21:15 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2006-07-11 21:15 malc [this message]
2006-07-11 21:50 ` [Qemu-devel] Stable clock source Fabrice Bellard
2006-07-11 22:06 ` malc
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Pine.LNX.4.64.0607120112010.3918@home.oyster.ru \
--to=malc@pulsesoft.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).