qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Fabrice Bellard <fabrice@bellard.org>
To: qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] Stable clock source
Date: Tue, 11 Jul 2006 23:50:55 +0200	[thread overview]
Message-ID: <44B41D3F.7030908@bellard.org> (raw)
In-Reply-To: <Pine.LNX.4.64.0607120112010.3918@home.oyster.ru>

Hi malc,

In fact I am already working on the issue. My solution is different and 
it seems to work too.

Fabrice.

malc wrote:
> 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
> 
> 
> ------------------------------------------------------------------------
> 
> 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) {
> 
> 
> ------------------------------------------------------------------------
> 
> _______________________________________________
> Qemu-devel mailing list
> Qemu-devel@nongnu.org
> http://lists.nongnu.org/mailman/listinfo/qemu-devel

  reply	other threads:[~2006-07-11 21:54 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-07-11 21:15 [Qemu-devel] Stable clock source malc
2006-07-11 21:50 ` Fabrice Bellard [this message]
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=44B41D3F.7030908@bellard.org \
    --to=fabrice@bellard.org \
    --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).