Subject: Re: port-alpha/36628: cdhdtape image panics with memory management
To: None <tsutsui@NetBSD.org, gnats-admin@netbsd.org,>
From: Izumi Tsutsui <tsutsui@ceres.dti.ne.jp>
List: netbsd-bugs
Date: 07/20/2007 20:25:02
The following reply was made to PR port-alpha/36628; it has been noted by GNATS.

From: Izumi Tsutsui <tsutsui@ceres.dti.ne.jp>
To: gnats-bugs@NetBSD.org
Cc: ChristophFranzen@gmx.net, tsutsui@ceres.dti.ne.jp
Subject: Re: port-alpha/36628: cdhdtape image panics with memory management
	 trap on Jensen
Date: Sat, 21 Jul 2007 05:24:22 +0900

 ChristophFranzen@gmx.net wrote:
 
 > the Result is attached.
  :
 > > http://www.ceres.dti.ne.jp/~tsutsui/netbsd/cdhdtape-20070719.gz
 > 
 > I did not send this to GNATS because the attachment ist rather large, 
 > and I don't know which information you need so I haven't shortened 
 > the file.
 
 Thanks, it shows that reading config data region of invalid slots
 causes the problem:
 
 ---
  :
 
 eisa0 at jensenio0
 EISA config header at 0x1ac061000
 EISA config at 0x1a0000000
 EISA config stride: 512
 SLOT 0: offset 0x18386800 eisaid DEC2400
 SLOT 1: offset 0x18397000 eisaid ELS8041
 SLOT 2: offset 0x183b4800 eisaid ADP0002
 SLOT 3: offset 0x183c6400 eisaid CPQ6101
 SLOT 8: offset 0x00000008 eisaid <DD><DD><DD><DD><DD><DD><DD>
 SLOT 9: offset 0x00009b63 eisaid <FF><FF><FF><FF><FF><FF><FF>
 SLOT 10: offset 0xffffffff eisaid <FF><FF><FF><FF><FF><FF><FF>
 SLOT 11: offset 0xffffffff eisaid <FF><FF><FF><FF><FF><FF><FF>
 SLOT 12: offset 0xffffffff eisaid <FF><FF><FF><FF><FF><FF><FF>
 SLOT 13: offset 0xffffffff eisaid <FF><FF><FF><FF><FF><FF><FF>
 SLOT 14: offset 0xffffffff eisaid <FF><FF><FF><FF><FF><FF><FF>
 SLOT 15: offset 0xffffffff eisaid <FF><FF><FF><FF><FF><FF><FF>
 
  :
 
 SLOT 8 compressed data length 48:
 0x01 0x09 0x10 0x01 0x55 0x00 0xaa 0xff 0x56 0x31 0x2e 0x31 0x20 0x20 0x20 0x20 
 0x44 0x45 0x43 0x20 0x20 0x20 0x20 0x20 0x4a 0x45 0x4e 0x53 0x5f 0x53 0x59 0x53 
 0x41 0x4c 0x50 0x48 0xff 0xff 0xff 0xff 0x17 0x01 0x01 0x00 0xc0 0x03 0x00 0x00 
 SLOT 8 uncompressed header data:
 0x01 0x09 0x10 0x01 0x55 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00 
 SLOT 8: ndevfuncs 0
 Slot 8:0 done
 Reading config bytes to cdata[0] at 0x1a0009b63
 Reading config bytes to cdata[1] at 0x1a0009d63
 
  :
 
 Reading config bytes to cdata[62463] at 0x1a1e89963
 Reading config bytes to cdata[62464] at 0x1a1e89b63
 
 CPU 0: fatal kernel trap:
 
 CPU 0    trap entry = 0x2 (memory management fault)
 CPU 0    a0         = 0xfffffe0000058000
 CPU 0    a1         = 0x1
 CPU 0    a2         = 0x0
 CPU 0    pc         = 0xfffffc000058fa10
 CPU 0    ra         = 0xfffffc000059008c
  :
 ---
 
 Maybe we shouldn't check slots more than 8 at least on Jensen
 (though I'm not sure how it worked in the past).
 How about this one?
 
 http://www.ceres.dti.ne.jp/~tsutsui/netbsd/cdhdtape-20070720.gz
 
 ---
 Index: eisa/eisa_machdep.c
 ===================================================================
 RCS file: /cvsroot/src/sys/arch/alpha/eisa/eisa_machdep.c,v
 retrieving revision 1.5
 diff -u -r1.5 eisa_machdep.c
 --- eisa/eisa_machdep.c	1 Jun 2002 23:50:53 -0000	1.5
 +++ eisa/eisa_machdep.c	20 Jul 2007 20:20:21 -0000
 @@ -79,6 +79,7 @@
  #define	ECUF_DMA_ENTRY_CNT	4
  #define	ECUF_IO_ENTRY_CNT	20
  
 +#define	CBUFSIZE		512
  /*
   * EISA configuration space, as set up by the ECU, may be sparse.
   */
 @@ -162,7 +163,9 @@
  	int i;
  
  	for (i = 0; i < ECUF_MEM_ENTRY_CNT; i++) {
 -		ecum = malloc(sizeof(*ecum), M_DEVBUF, M_WAITOK);
 +		ecum = malloc(sizeof(*ecum), M_DEVBUF, M_ZERO|M_WAITOK);
 +		if (ecum == NULL)
 +			panic("%s: can't allocate memory for ecum", __func__);
  
  		ecum->ecum_mem.ecm_isram = dp[0] & 0x1;
  		ecum->ecum_mem.ecm_unitsize = dp[1] & 0x3;
 @@ -174,7 +177,7 @@
  			ecum->ecum_mem.ecm_size = (1 << 26);
  		SIMPLEQ_INSERT_TAIL(&ecuf->ecuf_mem, ecum, ecum_list);
  
 -#if 0
 +#ifdef EISA_DEBUG
  		printf("MEM 0x%lx 0x%lx %d %d %d\n",
  		    ecum->ecum_mem.ecm_addr, ecum->ecum_mem.ecm_size,
  		    ecum->ecum_mem.ecm_isram, ecum->ecum_mem.ecm_unitsize,
 @@ -194,17 +197,19 @@
  	int i;
  
  	for (i = 0; i < ECUF_IRQ_ENTRY_CNT; i++) {
 -		ecui = malloc(sizeof(*ecui), M_DEVBUF, M_WAITOK);
 +		ecui = malloc(sizeof(*ecui), M_DEVBUF, M_ZERO|M_WAITOK);
 +		if (ecui == NULL)
 +			panic("%s: can't allocate memory for ecui", __func__);
  
  		ecui->ecui_irq.eci_irq = dp[0] & 0xf;
  		ecui->ecui_irq.eci_ist = (dp[0] & 0x20) ? IST_LEVEL : IST_EDGE;
  		ecui->ecui_irq.eci_shared = (dp[0] & 0x40) ? 1 : 0;
  		SIMPLEQ_INSERT_TAIL(&ecuf->ecuf_irq, ecui, ecui_list);
  
 -#if 0
 -		printf("IRQ %d %s%s\n", ecui->eci_irq.ecui_irq,
 -		    ecui->eci_irq.ecui_ist == IST_LEVEL ? "level" : "edge",
 -		    ecui->eci_irq.ecui_shared ? " shared" : "");
 +#ifdef EISA_DEBUG
 +		printf("IRQ %d %s%s\n", ecui->ecui_irq.eci_irq,
 +		    ecui->ecui_irq.eci_ist == IST_LEVEL ? "level" : "edge",
 +		    ecui->ecui_irq.eci_shared ? " shared" : "");
  #endif
  
  		if ((dp[0] & 0x80) == 0)
 @@ -220,7 +225,9 @@
  	int i;
  
  	for (i = 0; i < ECUF_DMA_ENTRY_CNT; i++) {
 -		ecud = malloc(sizeof(*ecud), M_DEVBUF, M_WAITOK);
 +		ecud = malloc(sizeof(*ecud), M_DEVBUF, M_ZERO|M_WAITOK);
 +		if (ecud == NULL)
 +			panic("%s: can't allocate memory for ecud", __func__);
  
  		ecud->ecud_dma.ecd_drq = dp[0] & 0x7;
  		ecud->ecud_dma.ecd_shared = dp[0] & 0x40;
 @@ -228,7 +235,7 @@
  		ecud->ecud_dma.ecd_timing = (dp[1] >> 4) & 0x3;
  		SIMPLEQ_INSERT_TAIL(&ecuf->ecuf_dma, ecud, ecud_list);
  
 -#if 0
 +#ifdef EISA_DEBUG
  		printf("DRQ %d%s %d %d\n", ecud->ecud_dma.ecd_drq,
  		    ecud->ecud_dma.ecd_shared ? " shared" : "",
  		    ecud->ecud_dma.ecd_size, ecud->ecud_dma.ecd_timing);
 @@ -247,13 +254,15 @@
  	int i;
  
  	for (i = 0; i < ECUF_IO_ENTRY_CNT; i++) {
 -		ecuio = malloc(sizeof(*ecuio), M_DEVBUF, M_WAITOK);
 +		ecuio = malloc(sizeof(*ecuio), M_DEVBUF, M_ZERO|M_WAITOK);
 +		if (ecuio == NULL)
 +			panic("%s: can't allocate memory for ecuio", __func__);
  
  		ecuio->ecuio_io.ecio_addr = dp[1] | (dp[2] << 8);
  		ecuio->ecuio_io.ecio_size = (dp[0] & 0x1f) + 1;
  		ecuio->ecuio_io.ecio_shared = (dp[0] & 0x40) ? 1 : 0;
  
 -#if 0
 +#ifdef EISA_DEBUG
  		printf("IO 0x%lx 0x%lx%s\n", ecuio->ecuio_io.ecio_addr,
  		    ecuio->ecuio_io.ecio_size,
  		    ecuio->ecuio_io.ecio_shared ? " shared" : "");
 @@ -285,7 +294,7 @@
  	int i;
  
  	for (i = 0; i < sizeof(val); i++) {
 -		val |= (u_int)(*src << (i * 8));
 +		val |= (u_int)*src << (i * 8);
  		src += eisa_config_stride;
  	}
  
 @@ -314,7 +323,7 @@
  }
  
  void
 -eisa_init()
 +eisa_init(eisa_chipset_tag_t ec)
  {
  	struct ecu_data *ecud;
  	paddr_t cfgaddr;
 @@ -340,30 +349,36 @@
  	}
  
  	eisa_config_header_addr = hwrpb->rpb_condat_off;
 -#if 0
 -	printf("\nEISA config header at 0x%lx\n", eisa_config_header_addr);
 -#endif
  	if (eisa_config_stride == 0)
  		eisa_config_stride = 1;
  
 +#ifdef EISA_DEBUG
 +	printf("\nEISA config header at 0x%lx\n", eisa_config_header_addr);
 +	printf("EISA config at 0x%lx\n", eisa_config_addr);
 +	printf("EISA config stride: %ld\n", eisa_config_stride);
 +#endif
 +
  	/*
  	 * Read the slot headers, and allocate config structures for
  	 * valid slots.
  	 */
 -	for (cfgaddr = eisa_config_header_addr, i = 0; i < 16 /* XXX */; i++) {
 +	for (cfgaddr = eisa_config_header_addr, i = 0;
 +	    i < eisa_maxslots(ec); i++) {
  		eisa_read_config_bytes(cfgaddr, eisaid, sizeof(eisaid));
  		eisaid[EISA_IDSTRINGLEN - 1] = '\0';	/* sanity */
  		cfgaddr += sizeof(eisaid) * eisa_config_stride;
  		eisa_read_config_word(cfgaddr, &offset);
  		cfgaddr += sizeof(offset) * eisa_config_stride;
  
 -		if (offset != 0) {
 -#if 0
 +		if (offset != 0 || offset != 0xffffffff) {
 +#ifdef EISA_DEBUG
  			printf("SLOT %d: offset 0x%08x eisaid %s\n",
  			    i, offset, eisaid);
  #endif
 -			ecud = malloc(sizeof(*ecud), M_DEVBUF, M_WAITOK);
 -			memset(ecud, 0, sizeof(*ecud));
 +			ecud = malloc(sizeof(*ecud), M_DEVBUF, M_ZERO|M_WAITOK);
 +			if (ecud == NULL)
 +				panic("%s: can't allocate memory for ecud",
 +				    __func__);
  
  			SIMPLEQ_INIT(&ecud->ecud_funcs);
  
 @@ -378,22 +393,42 @@
  	 * Now traverse the valid slots and read the info.
  	 */
  
 -	cdata = malloc(512, M_TEMP, M_WAITOK);
 -	data = malloc(512, M_TEMP, M_WAITOK);
 +	cdata = malloc(CBUFSIZE, M_TEMP, M_ZERO|M_WAITOK);
 +	if (cdata == NULL)
 +		panic("%s: can't allocate memory for cdata", __func__);
 +	data = malloc(CBUFSIZE, M_TEMP, M_ZERO|M_WAITOK);
 +	if (data == NULL)
 +		panic("%s: can't allocate memory for data", __func__);
  
  	SIMPLEQ_FOREACH(ecud, &ecu_data_list, ecud_list) {
  		cfgaddr = eisa_config_addr + ecud->ecud_offset;
 +#ifdef EISA_DEBUG
 +		printf("Checking SLOT %d\n", ecud->ecud_slot);
 +		printf("Reading config bytes at 0x%lx to cdata[0]\n", cfgaddr);
 +#endif
  		eisa_read_config_bytes(cfgaddr, &cdata[0], 1);
  		cfgaddr += eisa_config_stride;
  
 -		for (i = 1; ; cfgaddr += eisa_config_stride, i++) {
 +		for (i = 1; i < CBUFSIZE; cfgaddr += eisa_config_stride, i++) {
 +#ifdef EISA_DEBUG
 +			printf("Reading config bytes at 0x%lx to cdata[%d]\n",
 +			    cfgaddr, i);
 +#endif
  			eisa_read_config_bytes(cfgaddr, &cdata[i], 1);
  			if (cdata[i - 1] == 0 && cdata[i] == 0)
  				break;
  		}
 +		if (i == CBUFSIZE) {
 +			/* assume this compressed data invalid */
 +#ifdef EISA_DEBUG
 +			printf("SLOT %d has invalid config\n", ecud->ecud_slot);
 +#endif
 +			continue;
 +		}
 +
  		i++;	/* index -> length */
  
 -#if 0
 +#ifdef EISA_DEBUG
  		printf("SLOT %d compressed data length %d:",
  		    ecud->ecud_slot, i);
  		{
 @@ -413,7 +448,7 @@
  
  		/* Uncompress the slot header. */
  		cdp += eisa_uncompress(cdp, dp, EISA_SLOT_HEADER_SIZE);
 -#if 0
 +#ifdef EISA_DEBUG
  		printf("SLOT %d uncompressed header data:",
  		    ecud->ecud_slot);
  		{
 @@ -439,7 +474,7 @@
  		memcpy(&ecud->ecud_comp_id, dp, sizeof(ecud->ecud_comp_id));
  		dp += sizeof(ecud->ecud_comp_id);
  
 -#if 0
 +#ifdef EISA_DEBUG
  		printf("SLOT %d: ndevfuncs %d\n", ecud->ecud_slot,
  		    ecud->ecud_ndevfuncs);
  #endif
 @@ -447,7 +482,7 @@
  		for (func = 0; func < ecud->ecud_ndevfuncs; func++) {
  			dp = data;
  			cdp += eisa_uncompress(cdp, dp, EISA_CONFIG_BLOCK_SIZE);
 -#if 0
 +#ifdef EISA_DEBUG
  			printf("SLOT %d:%d uncompressed data:",
  			    ecud->ecud_slot, func);
  			{
 @@ -464,7 +499,7 @@
  
  			/* Skip disabled functions. */
  			if (dp[EISA_FUNC_INFO_OFFSET] & ECUF_DISABLED) {
 -#if 0
 +#ifdef EISA_DEBUG
  				printf("SLOT %d:%d disabled\n",
  				    ecud->ecud_slot, func);
  #endif
 @@ -472,6 +507,9 @@
  			}
  
  			ecuf = malloc(sizeof(*ecuf), M_DEVBUF, M_WAITOK);
 +			if (ecuf == NULL)
 +				panic("%s: can't allocate memory for ecuf",
 +				    __func__);
  			ecuf_init(ecuf);
  			ecuf->ecuf_funcno = func;
  			SIMPLEQ_INSERT_TAIL(&ecud->ecud_funcs, ecuf,
 Index: include/eisa_machdep.h
 ===================================================================
 RCS file: /cvsroot/src/sys/arch/alpha/include/eisa_machdep.h,v
 retrieving revision 1.7
 diff -u -r1.7 eisa_machdep.h
 --- include/eisa_machdep.h	11 Aug 2000 00:43:20 -0000	1.7
 +++ include/eisa_machdep.h	20 Jul 2007 20:20:21 -0000
 @@ -78,7 +78,7 @@
   * Internal functions, NOT TO BE USED BY MACHINE-INDEPENDENT CODE!
   */
  
 -void	eisa_init(void);
 +void	eisa_init(eisa_chipset_tag_t);
  
  extern bus_size_t eisa_config_stride;
  extern paddr_t eisa_config_addr;
 Index: jensenio/jensenio.c
 ===================================================================
 RCS file: /cvsroot/src/sys/arch/alpha/jensenio/jensenio.c,v
 retrieving revision 1.13
 diff -u -r1.13 jensenio.c
 --- jensenio/jensenio.c	11 Dec 2005 12:16:17 -0000	1.13
 +++ jensenio/jensenio.c	20 Jul 2007 20:20:21 -0000
 @@ -244,7 +244,7 @@
  	 */
  	eisa_config_stride = 0x200;
  	eisa_config_addr = JENSEN_FEPROM1;
 -	eisa_init();
 +	eisa_init(eba->eba_ec);
  #endif
  }
  
 @@ -252,7 +252,7 @@
  jensenio_eisa_maxslots(void *v)
  {
  
 -	return (16);	/* as good a number as any.  only 8, maybe? */
 +	return (8);	/* jensen seems to have only 8 valid slots */
  }
  
  void
 Index: pci/sio.c
 ===================================================================
 RCS file: /cvsroot/src/sys/arch/alpha/pci/sio.c,v
 retrieving revision 1.40
 diff -u -r1.40 sio.c
 --- pci/sio.c	11 Dec 2005 12:16:17 -0000	1.40
 +++ pci/sio.c	20 Jul 2007 20:20:21 -0000
 @@ -318,7 +318,7 @@
  {
  
  #if NEISA > 0
 -	eisa_init();
 +	eisa_init(eba->eba_ec);
  #endif
  }
  
 ---
 Izumi Tsutsui