From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1G0QBk-00011B-OZ for qemu-devel@nongnu.org; Tue, 11 Jul 2006 17:54:40 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1G0QBk-00010n-7j for qemu-devel@nongnu.org; Tue, 11 Jul 2006 17:54:40 -0400 Received: from [199.232.76.173] (helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1G0QBj-00010g-S5 for qemu-devel@nongnu.org; Tue, 11 Jul 2006 17:54:39 -0400 Received: from [84.96.92.61] (helo=sMtp.neuf.fr) by monty-python.gnu.org with esmtp (Exim 4.52) id 1G0QD8-0001G5-Bj for qemu-devel@nongnu.org; Tue, 11 Jul 2006 17:56:06 -0400 Received: from [84.102.211.57] by sp604002mt.gpm.neuf.ld (Sun Java System Messaging Server 6.2-5.05 (built Feb 16 2006)) with ESMTP id <0J2900KHFE0Y8YO0@sp604002mt.gpm.neuf.ld> for qemu-devel@nongnu.org; Tue, 11 Jul 2006 23:50:59 +0200 (CEST) Date: Tue, 11 Jul 2006 23:50:55 +0200 From: Fabrice Bellard Subject: Re: [Qemu-devel] Stable clock source In-reply-to: Message-id: <44B41D3F.7030908@bellard.org> MIME-version: 1.0 Content-type: text/plain; charset=us-ascii; format=flowed Content-transfer-encoding: 7BIT References: Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org 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 > #include > #include > #include > @@ -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 > +#include > +#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