Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/ic hpet:



details:   https://anonhg.NetBSD.org/src/rev/ad48673c2842
branches:  trunk
changeset: 770731:ad48673c2842
user:      yamt <yamt%NetBSD.org@localhost>
date:      Mon Oct 31 12:47:15 2011 +0000

description:
hpet:
- fix an integer overflow bug introduced by hpet.c rev.1.11.
- a workaround for AMD SB700 based systems, inspired from linux.

diffstat:

 sys/dev/ic/hpet.c    |  27 ++++++++++++++++++++++-----
 sys/dev/ic/hpetreg.h |   3 ++-
 2 files changed, 24 insertions(+), 6 deletions(-)

diffs (76 lines):

diff -r 03f316f4a3f4 -r ad48673c2842 sys/dev/ic/hpet.c
--- a/sys/dev/ic/hpet.c Mon Oct 31 12:42:36 2011 +0000
+++ b/sys/dev/ic/hpet.c Mon Oct 31 12:47:15 2011 +0000
@@ -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 @@
 {
        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 @@
 
        /* 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);
diff -r 03f316f4a3f4 -r ad48673c2842 sys/dev/ic/hpetreg.h
--- a/sys/dev/ic/hpetreg.h      Mon Oct 31 12:42:36 2011 +0000
+++ b/sys/dev/ic/hpetreg.h      Mon Oct 31 12:47:15 2011 +0000
@@ -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



Home | Main Index | Thread Index | Old Index