Module Name: src
Committed By: yamt
Date: Mon Oct 31 12:47:15 UTC 2011
Modified Files:
src/sys/dev/ic: hpet.c hpetreg.h
Log Message:
hpet:
- fix an integer overflow bug introduced by hpet.c rev.1.11.
- a workaround for AMD SB700 based systems, inspired from linux.
To generate a diff of this commit:
cvs rdiff -u -r1.12 -r1.13 src/sys/dev/ic/hpet.c
cvs rdiff -u -r1.3 -r1.4 src/sys/dev/ic/hpetreg.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/dev/ic/hpet.c
diff -u src/sys/dev/ic/hpet.c:1.12 src/sys/dev/ic/hpet.c:1.13
--- src/sys/dev/ic/hpet.c:1.12 Fri Jul 29 19:19:14 2011
+++ src/sys/dev/ic/hpet.c Mon Oct 31 12:47:15 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: hpet.c,v 1.12 2011/07/29 19:19:14 jakllsch Exp $ */
+/* $NetBSD: hpet.c,v 1.13 2011/10/31 12:47:15 yamt Exp $ */
/*
* Copyright (c) 2006 Nicolas Joly
@@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: hpet.c,v 1.12 2011/07/29 19:19:14 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: hpet.c,v 1.13 2011/10/31 12:47:15 yamt Exp $");
#include <sys/systm.h>
#include <sys/device.h>
@@ -71,7 +71,9 @@ hpet_attach_subr(device_t dv)
{
struct hpet_softc *sc = device_private(dv);
struct timecounter *tc;
+ uint64_t tmp;
uint32_t val;
+ int i;
tc = &sc->sc_tc;
@@ -83,12 +85,27 @@ hpet_attach_subr(device_t dv)
/* Get frequency */
val = bus_space_read_4(sc->sc_memt, sc->sc_memh, HPET_PERIOD);
- if (val == 0) {
+ if (val == 0 || val > HPET_PERIOD_MAX) {
aprint_error_dev(dv, "invalid timer period\n");
return;
}
- val = (1000000000000000ULL * 2) / val;
- tc->tc_frequency = (val / 2) + (val & 1);
+
+ /*
+ * The following loop is a workaround for AMD SB700 based systems.
+ * http://kerneltrap.org/mailarchive/git-commits-head/2008/8/17/2964724
+ * http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=a6825f1c1fa83b1e92b6715ee5771a4d6524d3b9
+ */
+ for (i = 0; bus_space_read_4(sc->sc_memt, sc->sc_memh, HPET_CONFIG)
+ == 0xffffffff; i++) {
+ if (i >= 1000) {
+ aprint_error_dev(dv,
+ "HPET_CONFIG value = 0xffffffff\n");
+ return;
+ }
+ }
+
+ tmp = (1000000000000000ULL * 2) / val;
+ tc->tc_frequency = (tmp / 2) + (tmp & 1);
/* Enable timer */
val = bus_space_read_4(sc->sc_memt, sc->sc_memh, HPET_CONFIG);
Index: src/sys/dev/ic/hpetreg.h
diff -u src/sys/dev/ic/hpetreg.h:1.3 src/sys/dev/ic/hpetreg.h:1.4
--- src/sys/dev/ic/hpetreg.h:1.3 Fri Feb 15 22:14:10 2008
+++ src/sys/dev/ic/hpetreg.h Mon Oct 31 12:47:15 2011
@@ -1,4 +1,4 @@
-/* $NetBSD: hpetreg.h,v 1.3 2008/02/15 22:14:10 jmcneill Exp $ */
+/* $NetBSD: hpetreg.h,v 1.4 2011/10/31 12:47:15 yamt Exp $ */
/*
* Copyright (c) 2006 Nicolas Joly
@@ -36,6 +36,7 @@
#define HPET_INFO 0x00
#define HPET_INFO_64BITS 0x2000
#define HPET_PERIOD 0x04
+#define HPET_PERIOD_MAX 100000000
#define HPET_CONFIG 0x10
#define HPET_CONFIG_ENABLE 0x0001
#define HPET_CONFIG_LEGRTCNF 0x0002