Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 15 Jan 2008 12:43:29 -0500
From:      John Baldwin <jhb@freebsd.org>
To:        freebsd-acpi@freebsd.org, Leo Bicknell <bicknell@ufp.org>
Subject:   Re: kern/119675: [acpi] apic_hpet0 probe causes divide by zero kernel panic
Message-ID:  <200801151243.30323.jhb@freebsd.org>
In-Reply-To: <200801151640.m0FGe4hT005360@freefall.freebsd.org>
References:  <200801151640.m0FGe4hT005360@freefall.freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
On Tuesday 15 January 2008 11:40:04 am Leo Bicknell wrote:
> The following reply was made to PR kern/119675; it has been noted by GNATS.
> 
> From: Leo Bicknell <bicknell@ufp.org>
> To: John Baldwin <jhb@FreeBSD.org>
> Cc: bug-followup@FreeBSD.org
> Subject: Re: kern/119675: [acpi] apic_hpet0 probe causes divide by zero kernel panic
> Date: Tue, 15 Jan 2008 11:33:14 -0500
> 
>  In a message written on Tue, Jan 15, 2008 at 10:13:07AM -0500, John Baldwin wrote:
>  > You can try the patch below.  It fixes a couple of places where we don't
>  > honor the spec (we don't shut it off in S1 and S2 as required and we don't
>  > preserve reserved bits in the global configuration register).  It also
>  > fails the attach if the period is zero which should fix your panic and
>  > just leave you with no HPET.
>  
>  Good news and bad news.
>  
>  With the patch "invalid period" is printed out, so I believe it's
>  correctly detecting the hpet0 issue.
>  
>  However, I immediately get an "integer divide fault while in kernel
>  mode" panic and the boot still fails.  I tried with boot -v and the
>  message is right after the "invalid period", so I'm not quite sure
>  what's causing it.
>  
>  Any recomendations, other than setting up a kernel debugger to see where
>  it's coming from?

I forgot to include a return() statement to make it actually fail the attach.
My bad.  Updated patch below:

--- //depot/vendor/freebsd/src/sys/dev/acpica/acpi_hpet.c	2007/10/09 07:52:34
+++ //depot/user/jhb/acpipci/dev/acpica/acpi_hpet.c	2008/01/15 17:42:12
@@ -82,6 +82,24 @@
 	return (bus_read_4(sc->mem_res, HPET_OFFSET_VALUE));
 }
 
+static void
+hpet_enable(struct acpi_hpet_softc *sc)
+{
+	uint32_t val;
+	
+	val = bus_read_4(sc->mem_res, HPET_OFFSET_ENABLE);
+	bus_write_4(sc->mem_res, HPET_OFFSET_ENABLE, val | 1);
+}
+
+static void
+hpet_disable(struct acpi_hpet_softc *sc)
+{
+	uint32_t val;
+	
+	val = bus_read_4(sc->mem_res, HPET_OFFSET_ENABLE);
+	bus_write_4(sc->mem_res, HPET_OFFSET_ENABLE, val & ~1);
+}
+
 /* Discover the HPET via the ACPI table of the same name. */
 static void 
 acpi_hpet_identify(driver_t *driver, device_t parent)
@@ -166,10 +184,17 @@
 	}
 
 	/* Be sure timer is enabled. */
-	bus_write_4(sc->mem_res, HPET_OFFSET_ENABLE, 1);
+	hpet_enable(sc);
 
 	/* Read basic statistics about the timer. */
 	val = bus_read_4(sc->mem_res, HPET_OFFSET_PERIOD);
+	if (val == 0) {
+		device_printf(dev, "invalid period\n");
+		hpet_disable(sc);
+		bus_free_resource(dev, SYS_RES_MEMORY, sc->mem_res);
+		return (ENXIO);
+	}
+
 	freq = (1000000000000000LL + val / 2) / val;
 	if (bootverbose) {
 		val = bus_read_4(sc->mem_res, HPET_OFFSET_INFO);
@@ -192,7 +217,7 @@
 	val2 = bus_read_4(sc->mem_res, HPET_OFFSET_VALUE);
 	if (val == val2) {
 		device_printf(dev, "HPET never increments, disabling\n");
-		bus_write_4(sc->mem_res, HPET_OFFSET_ENABLE, 0);
+		hpet_disable(sc);
 		bus_free_resource(dev, SYS_RES_MEMORY, sc->mem_res);
 		return (ENXIO);
 	}
@@ -214,13 +239,29 @@
 }
 
 static int
+acpi_hpet_suspend(device_t dev)
+{
+	struct acpi_hpet_softc *sc;
+
+	/*
+	 * Disable the timer during suspend.  The timer will not lose
+	 * its state in S1 or S2, but we are required to disable
+	 * it.
+	 */
+	sc = device_get_softc(dev);
+	hpet_disable(sc);
+
+	return (0);
+}
+
+static int
 acpi_hpet_resume(device_t dev)
 {
 	struct acpi_hpet_softc *sc;
 
 	/* Re-enable the timer after a resume to keep the clock advancing. */
 	sc = device_get_softc(dev);
-	bus_write_4(sc->mem_res, HPET_OFFSET_ENABLE, 1);
+	hpet_enable(sc);
 
 	return (0);
 }
@@ -260,6 +301,7 @@
 	DEVMETHOD(device_probe, acpi_hpet_probe),
 	DEVMETHOD(device_attach, acpi_hpet_attach),
 	DEVMETHOD(device_detach, acpi_hpet_detach),
+	DEVMETHOD(device_suspend, acpi_hpet_suspend),
 	DEVMETHOD(device_resume, acpi_hpet_resume),
 
 	{0, 0}

-- 
John Baldwin



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200801151243.30323.jhb>