IP12 (and perhaps other systems) appear to be buggy and incapable of

reliably supporting badaddr(). False negatives appear to occur
approximately 1.8 percent of the time, although neither false positives
nor consecutive false negatives occur. We take advantage of the latter
property and always use a wrapper that makes multiple checks.

My IP12 no longer sees occasional ghost devices and related panics during
boot.
This commit is contained in:
rumble 2006-12-29 05:26:30 +00:00
parent ebc746c114
commit 1426ceeded
8 changed files with 66 additions and 27 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: gio.c,v 1.25 2006/12/29 00:42:01 rumble Exp $ */
/* $NetBSD: gio.c,v 1.26 2006/12/29 05:26:30 rumble Exp $ */
/*
* Copyright (c) 2000 Soren S. Jorvang
@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: gio.c,v 1.25 2006/12/29 00:42:01 rumble Exp $");
__KERNEL_RCSID(0, "$NetBSD: gio.c,v 1.26 2006/12/29 05:26:30 rumble Exp $");
#include "opt_ddb.h"
@ -44,6 +44,7 @@ __KERNEL_RCSID(0, "$NetBSD: gio.c,v 1.25 2006/12/29 00:42:01 rumble Exp $");
#define _SGIMIPS_BUS_DMA_PRIVATE
#include <machine/bus.h>
#include <machine/machtype.h>
#include <machine/sysconf.h>
#include <sgimips/gio/gioreg.h>
#include <sgimips/gio/giovar.h>
@ -215,7 +216,7 @@ gio_attach(struct device *parent, struct device *self, void *aux)
ga.ga_dmat = &sgimips_default_bus_dma_tag;
ga.ga_product = -1;
if (badaddr((void *)ga.ga_ioh, sizeof(uint32_t)))
if (platform.badaddr((void *)ga.ga_ioh, sizeof(uint32_t)))
continue;
if (config_found_sm_loc(self, "gio", NULL, &ga, gio_print,
@ -258,7 +259,7 @@ gio_attach(struct device *parent, struct device *self, void *aux)
ga.ga_ioh = MIPS_PHYS_TO_KSEG1(ga.ga_addr);
ga.ga_dmat = &sgimips_default_bus_dma_tag;
if (badaddr((void *)ga.ga_ioh, sizeof(uint32_t)))
if (platform.badaddr((void *)ga.ga_ioh, sizeof(uint32_t)))
continue;
ga.ga_product = bus_space_read_4(ga.ga_iot, ga.ga_ioh, 0);
@ -375,7 +376,7 @@ gio_cnattach()
ga.ga_dmat = &sgimips_default_bus_dma_tag;
ga.ga_product = -1;
if (badaddr((void *)ga.ga_ioh,sizeof(uint32_t)))
if (platform.badaddr((void *)ga.ga_ioh,sizeof(uint32_t)))
continue;
#if (NGRTWO > 0)

View File

@ -1,4 +1,4 @@
/* $NetBSD: grtwo.c,v 1.8 2006/12/28 22:10:05 rumble Exp $ */
/* $NetBSD: grtwo.c,v 1.9 2006/12/29 05:26:30 rumble Exp $ */
/*
* Copyright (c) 2004 Christopher SEKIYA
@ -35,13 +35,15 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: grtwo.c,v 1.8 2006/12/28 22:10:05 rumble Exp $");
__KERNEL_RCSID(0, "$NetBSD: grtwo.c,v 1.9 2006/12/29 05:26:30 rumble Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/malloc.h>
#include <machine/sysconf.h>
#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsdisplayvar.h>
#include <dev/wsfont/wsfont.h>
@ -452,7 +454,8 @@ grtwo_match(struct device * parent, struct cfdata * self, void *aux)
* ID. Instead, we determine presence by looking at the HQ2 "mystery"
* register, which contains a magic number.
*/
if ( badaddr((void *) (ga->ga_ioh + HQ2_MYSTERY), sizeof(u_int32_t)) )
if ( platform.badaddr((void *) (ga->ga_ioh + HQ2_MYSTERY),
sizeof(u_int32_t)) )
return 0;
if ( (bus_space_read_4(ga->ga_iot, ga->ga_ioh, HQ2_MYSTERY)) != 0xdeadbeef)

View File

@ -1,4 +1,4 @@
/* $Id: light.c,v 1.3 2006/12/29 00:31:48 rumble Exp $ */
/* $Id: light.c,v 1.4 2006/12/29 05:26:30 rumble Exp $ */
/*
* Copyright (c) 2006 Stephen M. Rumble
@ -43,13 +43,15 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: light.c,v 1.3 2006/12/29 00:31:48 rumble Exp $");
__KERNEL_RCSID(0, "$NetBSD: light.c,v 1.4 2006/12/29 05:26:30 rumble Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/malloc.h>
#include <machine/sysconf.h>
#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsdisplayvar.h>
#include <dev/wsfont/wsfont.h>
@ -270,7 +272,8 @@ light_match(struct device *parent, struct cfdata *self, void *aux)
if (ga->ga_addr != LIGHT_ADDR_0 && ga->ga_addr != LIGHT_ADDR_1)
return (0);
if (badaddr((void *)(ga->ga_ioh + REX_PAGE1_SET + REX_P1REG_XYOFFSET),
if (platform.badaddr(
(void *)(ga->ga_ioh + REX_PAGE1_SET + REX_P1REG_XYOFFSET),
sizeof(uint32_t)))
return (0);

View File

@ -1,4 +1,4 @@
/* $NetBSD: newport.c,v 1.8 2006/12/28 22:08:04 rumble Exp $ */
/* $NetBSD: newport.c,v 1.9 2006/12/29 05:26:30 rumble Exp $ */
/*
* Copyright (c) 2003 Ilpo Ruotsalainen
@ -30,13 +30,15 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: newport.c,v 1.8 2006/12/28 22:08:04 rumble Exp $");
__KERNEL_RCSID(0, "$NetBSD: newport.c,v 1.9 2006/12/29 05:26:30 rumble Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/device.h>
#include <sys/malloc.h>
#include <machine/sysconf.h>
#include <dev/wscons/wsconsio.h>
#include <dev/wscons/wsdisplayvar.h>
#include <dev/wsfont/wsfont.h>
@ -575,11 +577,11 @@ newport_match(struct device *parent, struct cfdata *self, void *aux)
if (newport_is_console && ga->ga_addr == newport_console_dc.dc_addr)
return 1;
if (badaddr(
if (platform.badaddr(
(void *)(ga->ga_ioh + NEWPORT_REX3_OFFSET + REX3_REG_XSTARTI),
sizeof(uint32_t)))
return 0;
if (badaddr(
if (platform.badaddr(
(void *)(ga->ga_ioh + NEWPORT_REX3_OFFSET + REX3_REG_XSTART),
sizeof(uint32_t)))
return 0;

View File

@ -1,4 +1,4 @@
/* $NetBSD: haltwo.c,v 1.10 2006/09/04 22:06:06 rumble Exp $ */
/* $NetBSD: haltwo.c,v 1.11 2006/12/29 05:26:30 rumble Exp $ */
/*
* Copyright (c) 2003 Ilpo Ruotsalainen
@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: haltwo.c,v 1.10 2006/09/04 22:06:06 rumble Exp $");
__KERNEL_RCSID(0, "$NetBSD: haltwo.c,v 1.11 2006/12/29 05:26:30 rumble Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -44,6 +44,7 @@ __KERNEL_RCSID(0, "$NetBSD: haltwo.c,v 1.10 2006/09/04 22:06:06 rumble Exp $");
#include <uvm/uvm_extern.h>
#include <machine/bus.h>
#include <machine/sysconf.h>
#include <sgimips/hpc/hpcvar.h>
#include <sgimips/hpc/hpcreg.h>
@ -266,10 +267,12 @@ haltwo_match(struct device *parent, struct cfdata *cf, void *aux)
if (strcmp(haa->ha_name, cf->cf_name))
return 0;
if ( badaddr((void *)(haa->ha_sh + haa->ha_devoff), sizeof(u_int32_t)) )
if ( platform.badaddr((void *)(haa->ha_sh + haa->ha_devoff),
sizeof(u_int32_t)) )
return 0;
if ( badaddr((void *)(haa->ha_sh + haa->ha_devoff + HAL2_REG_CTL_REV),
if ( platform.badaddr(
(void *)(haa->ha_sh + haa->ha_devoff + HAL2_REG_CTL_REV),
sizeof(u_int32_t)) )
return 0;

View File

@ -1,4 +1,4 @@
/* $NetBSD: hpc.c,v 1.49 2006/12/22 23:36:42 rumble Exp $ */
/* $NetBSD: hpc.c,v 1.50 2006/12/29 05:26:30 rumble Exp $ */
/*
* Copyright (c) 2000 Soren S. Jorvang
@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: hpc.c,v 1.49 2006/12/22 23:36:42 rumble Exp $");
__KERNEL_RCSID(0, "$NetBSD: hpc.c,v 1.50 2006/12/29 05:26:30 rumble Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -47,6 +47,7 @@ __KERNEL_RCSID(0, "$NetBSD: hpc.c,v 1.49 2006/12/22 23:36:42 rumble Exp $");
#define _SGIMIPS_BUS_DMA_PRIVATE
#include <machine/bus.h>
#include <machine/machtype.h>
#include <machine/sysconf.h>
#include <sgimips/gio/gioreg.h>
#include <sgimips/gio/giovar.h>
@ -360,7 +361,8 @@ hpc_match(struct device *parent, struct cfdata *cf, void *aux)
struct gio_attach_args* ga = aux;
/* Make sure it's actually there and readable */
if (badaddr((void*)MIPS_PHYS_TO_KSEG1(ga->ga_addr), sizeof(u_int32_t)))
if (platform.badaddr((void*)MIPS_PHYS_TO_KSEG1(ga->ga_addr),
sizeof(u_int32_t)))
return 0;
return 1;
@ -519,7 +521,7 @@ hpc_revision(struct hpc_softc *sc, struct gio_attach_args *ga)
if (mach_type == MACH_SGI_IP12 || mach_type == MACH_SGI_IP20) {
u_int32_t reg;
if (!badaddr((void *)MIPS_PHYS_TO_KSEG1(ga->ga_addr +
if (!platform.badaddr((void *)MIPS_PHYS_TO_KSEG1(ga->ga_addr +
HPC1_BIGENDIAN), 4)) {
reg = *(uint32_t *)MIPS_PHYS_TO_KSEG1(ga->ga_addr +
HPC1_BIGENDIAN);
@ -553,7 +555,7 @@ hpc_revision(struct hpc_softc *sc, struct gio_attach_args *ga)
* that this probe succeeds with my E++ adapter in slot 1,
* but it appears to do the right thing in slot 0!
*/
if (badaddr((void *)MIPS_PHYS_TO_KSEG1(ga->ga_addr +
if (platform.badaddr((void *)MIPS_PHYS_TO_KSEG1(ga->ga_addr +
HPC3_PBUS_CH7_BP), 4))
return (15);
else

View File

@ -1,4 +1,4 @@
/* $NetBSD: sysconf.h,v 1.6 2005/12/11 12:18:53 christos Exp $ */
/* $NetBSD: sysconf.h,v 1.7 2006/12/29 05:26:30 rumble Exp $ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
@ -56,6 +56,7 @@
struct platform {
/*
* Platform Specific Function Hooks
* bad_addr - badaddr, or workaround replacement
* bus_reset - clear memory error condition
* cons_init - console initialization
* intr_establish - establish interrupt handler
@ -66,6 +67,7 @@ struct platform {
* intr0-intr5 - CPU interrupt handler
*/
int (*badaddr)(void *, size_t);
void (*bus_reset)(void);
void (*cons_init)(void);
void *(*intr_establish)(int , int, int (*)(void *), void *);

View File

@ -1,4 +1,4 @@
/* $NetBSD: machdep.c,v 1.102 2006/12/28 16:15:11 rumble Exp $ */
/* $NetBSD: machdep.c,v 1.103 2006/12/29 05:26:30 rumble Exp $ */
/*
* Copyright (c) 2000 Soren S. Jorvang
@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.102 2006/12/28 16:15:11 rumble Exp $");
__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.103 2006/12/29 05:26:30 rumble Exp $");
#include "opt_ddb.h"
#include "opt_kgdb.h"
@ -210,7 +210,10 @@ static void nullvoid(void);
void ddb_trap_hook(int where);
static int badaddr_workaround(void *, size_t);
struct platform platform = {
.badaddr = badaddr_workaround,
.bus_reset = unimpl_bus_reset,
.cons_init = unimpl_cons_init,
.intr_establish = unimpl_intr_establish,
@ -758,6 +761,26 @@ void delay(unsigned long n)
} while (__N > 0);
}
/*
* IP12 appears to be buggy and unable to support reliably support badaddr.
* The problem is that approximately 1.8% of the time a false negative is
* generated and we stomp on invalid registers. Testing shows that neither
* false negatives, nor consecutive false positives appear to occur.
*/
static int
badaddr_workaround(void *addr, size_t size)
{
int i, bad;
for (i = bad = 0; i < 100; i++) {
if (badaddr(addr, size))
bad++;
}
/* false positives appear not to occur */
return (bad != 0);
}
/*
* Ensure all platform vectors are always initialized.
*/