On Mon, Aug 13, 2012 at 03:04:10PM +0200, Gerd Hoffmann wrote: > This patch makes seabios use the acpi pmtimer instead of tsc for > timekeeping. The pmtimer has a fixed frequency and doesn't need > calibration, thus it doesn't suffer from calibration errors due to a > loaded host machine. > > Signed-off-by: Gerd Hoffmann <kraxel@xxxxxxxxxx> > --- > src/clock.c | 29 +++++++++++++++++++++++++++++ > src/pciinit.c | 5 +++++ > src/util.h | 1 + > 3 files changed, 35 insertions(+), 0 deletions(-) > > diff --git a/src/clock.c b/src/clock.c > index 69e9f17..59f269b 100644 > --- a/src/clock.c > +++ b/src/clock.c > @@ -129,11 +129,40 @@ emulate_tsc(void) > return ret; > } > > +u16 pmtimer_ioport VAR16VISIBLE; > +u32 pmtimer_wraps VARLOW; > +u32 pmtimer_last VARLOW; > + > +void pmtimer_init(u16 ioport, u32 khz) > +{ > + dprintf(1, "Using pmtimer, ioport 0x%x, freq %d kHz\n", ioport, khz); > + SET_GLOBAL(pmtimer_ioport, ioport); > + SET_GLOBAL(cpu_khz, khz); > +} > + > +static u64 pmtimer_get(void) > +{ > + u16 ioport = GET_GLOBAL(pmtimer_ioport); > + u32 wraps = GET_LOW(pmtimer_wraps); > + u32 pmtimer = inl(ioport); > + > + if (pmtimer < GET_LOW(pmtimer_last)) { > + wraps++; > + SET_LOW(pmtimer_wraps, wraps); > + } > + SET_LOW(pmtimer_last, pmtimer); > + > + dprintf(9, "pmtimer: %u:%u\n", wraps, pmtimer); > + return (u64)wraps << 24 | pmtimer; > +} > + > static u64 > get_tsc(void) > { > if (unlikely(GET_GLOBAL(no_tsc))) > return emulate_tsc(); > + if (GET_GLOBAL(pmtimer_ioport)) > + return pmtimer_get(); > return rdtscll(); > } > > diff --git a/src/pciinit.c b/src/pciinit.c > index 68f302a..31115ee 100644 > --- a/src/pciinit.c > +++ b/src/pciinit.c > @@ -180,6 +180,9 @@ static const struct pci_device_id pci_class_tbl[] = { > PCI_DEVICE_END, > }; > > +/* PM Timer ticks per second (HZ) */ > +#define PM_TIMER_FREQUENCY 3579545 > + > /* PIIX4 Power Management device (for ACPI) */ > static void piix4_pm_init(struct pci_device *pci, void *arg) > { > @@ -191,6 +194,8 @@ static void piix4_pm_init(struct pci_device *pci, void *arg) > pci_config_writeb(bdf, 0x80, 0x01); /* enable PM io space */ > pci_config_writel(bdf, 0x90, PORT_SMB_BASE | 1); > pci_config_writeb(bdf, 0xd2, 0x09); /* enable SMBus io space */ > + > + pmtimer_init(PORT_ACPI_PM_BASE + 0x08, PM_TIMER_FREQUENCY / 1000); > } > > static const struct pci_device_id pci_device_tbl[] = { > diff --git a/src/util.h b/src/util.h > index 89e928c..1603a57 100644 > --- a/src/util.h > +++ b/src/util.h > @@ -312,6 +312,7 @@ void lpt_setup(void); > // clock.c > #define PIT_TICK_RATE 1193180 // Underlying HZ of PIT > #define PIT_TICK_INTERVAL 65536 // Default interval for 18.2Hz timer > +void pmtimer_init(u16 ioport, u32 khz); > int check_tsc(u64 end); > void timer_setup(void); > void ndelay(u32 count); Looks good. -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html