Subject: Bug in (binutils-mipsel-linux-2.9.5-3 + egcs-mipsel-linux-1.1.2-4) - Also any suggestion for binutils/gcc versions to use for mips.

From: C Hanish Menon <[email-masked]>
Date: Mon, 18 Mar 2002 00:05:56 +0530

Hi

Sometime back I had ported Linux to LSI's SC2005 (TinyMips core with Mips1
and some Mips2 instructions) based board as part of my work.
We wanted to release the code to opensource. However we found
a bug in the code that it was corrupting the softirq's pending, which I
wanted to fix before releaseing to opensource. At that time I
temporarily fixed the problem by checking that the softirq is pointing
to a proper logic rather than 0 before calling it.

Recently I found time to look into the problem, and found the code
generated by the compiler is wrong, in that instead of setting the
ksoftirqd_task element of the irq_stat structure its setting the pending
element, thus causing the system to crash.

As mentioned in the subject I was using

binutils-mipsel-linux-2.95.3 and egcs-mipsel-linux-1.1.2-4 binary packages
from oss.sgi.com on a Redhat 7.2 system.

To show the problem I added some test code into the kernel/softirq.c
file, as can be noted from the code below the compiler generates proper
code in certain places, but wrong code at other instances:

-----------------------------------------------------------------------------
binutils-mipsel-linux-2.9.5-3
egcs-mipsel-linux-1.1.2-4

******************************* ISSUE 1 ****************************

Location of irq_stat[]
----------------------

00000000800f5d38 g     F .text	00000000000000d8 __tcp_mem_reclaim
00000000801614d0 g     O .data	0000000000000020 irq_stat
00000000800820dc g     F .text	0000000000000034 show_buffers

************************************************
In ksoftirqd function /** The actual code - wrong code generated **/
---------------------

	ksoftirqd_task(cpu) = current;
	/* added by me */
	debugkvc_softirq_pending("ksoftirqd: before for");

	for (;;) {
		if (!softirq_pending(cpu))

0000000080059b38 <ksoftirqd>:
      80059bf0:	3c108016 	lui	$s0,0x8016
      80059bf4:	261014d0 	addiu	$s0,$s0,5328
      80059bf8:	0c01667e 	jal	800599f8 <debugkvc_softirq_pending>
      80059bfc:	ae1c0000 	sw	$gp,0($s0) /** NOTE ksoftirqd_task offset is wrong **/
      80059c00:	2610fff0 	addiu	$s0,$s0,-16 /** Nice way to calculate the pending element
offset but its wrong has the ksoftirqd_task element offset itself is wrong **/
      80059c04:	8e020000 	lw	$v0,0($s0) /** as mentioned above the pending element offset wrong **/
      80059c08:	00000000 	nop
      80059c0c:	14400003 	bnez	$v0,80059c1c <ksoftirqd+0xe4>

************************************************

void debugkvc_show_gcc_bug_1(void) /* Test case 1 - Proper code generated */
{
	int cpu = smp_processor_id();
	int pending;

	/* TEMPORARY TO SHOW THE CROSS GCC bUg */
	pending = softirq_pending(cpu);
	pending += 1;
	softirq_pending(cpu) = pending;
	ksoftirqd_task(cpu) = current;
	/* END */
}

0000000080059994 <debugkvc_show_gcc_bug_1>:
      80059994:	3c038016 	lui	$v1,0x8016
      80059998:	246314d0 	addiu	$v1,$v1,5328
      8005999c:	8c620000 	lw	$v0,0($v1)
      800599a0:	ac7c0010 	sw	$gp,16($v1) /** Proper offset for ksoftirqd_task element **/
      800599a4:	24420001 	addiu	$v0,$v0,1
      800599a8:	03e00008 	jr	$ra
      800599ac:	ac620000 	sw	$v0,0($v1)

************************************************

void debugkvc_show_gcc_bug_3(void) /* Test case 2 - WRONG code generated */
{
	int cpu = smp_processor_id();

	/* TEMPORARY TO SHOW THE CROSS GCC bUg */
	ksoftirqd_task(cpu) = current;
	/* END */
}

00000000800599cc <debugkvc_show_gcc_bug_3>:
      800599cc:	3c018016 	lui	$at,0x8016
      800599d0:	ac3c14d0 	sw	$gp,5328($at) /** wrong offset **/
      800599d4:	03e00008 	jr	$ra
      800599d8:	00000000 	nop

************************************************

void debugkvc_show_gcc_bug_4(void) /* Test case 3 - WRONG code generated */
{
	int cpu = smp_processor_id();
	volatile void * task;

	/* TEMPORARY TO SHOW THE CROSS GCC bUg */
	task = ksoftirqd_task(cpu);
	ksoftirqd_task(cpu) = current;
	ksoftirqd_task(cpu) = task+1;
	/* END */
}

00000000800599dc <debugkvc_show_gcc_bug_4>:
      800599dc:	3c038016 	lui	$v1,0x8016
      800599e0:	246314d0 	addiu	$v1,$v1,5328
      800599e4:	8c620000 	lw	$v0,0($v1) /** wrong offset **/
      800599e8:	00000000 	nop
      800599ec:	24420001 	addiu	$v0,$v0,1
      800599f0:	03e00008 	jr	$ra
      800599f4:	ac620000 	sw	$v0,0($v1)

00000000800599f8 <debugkvc_softirq_pending>:

******************************* ISSUE 2 ****************************

mipsel-linux-ld doesn't seem to understand elf32-littlemips even thou
mipsel-linux-objdump -i gives elf32-littlemips has part of its output

This issue affects the logic used in arch/mips/ramdisk/Makefile to
convert the
ramdisk.gz file to ramdisk.o

Had to force elf32-little for the logic to work.

-----------------------------------------------------------------------------

*************** Current status *****************

Because of this, I download the sources for binutils 2.12 and gcc 3.0.4 and
created cross compilers for mipsel-linux. Now the compiler is generating
proper code for the above case. But linux is failing in the gzips
inflate logic (Compressed ramdisk) in some cases, have to verify it
properly and identify the issue. It again seems like a compiler problem,
but haven't verified it yet.

Also I have currently used 2.4.16 with code from linux-mips-kernel on
sourceforge as the base on which I have done my porting. Once I find the
issue with the gzip logic and also move it to 2.4.18 (or 2.4.19 if it
gets released by then), we will release the port to the opensource.

**************** Any suggestions ****************

In the mean time what do you people think is the best binutils/gcc
combination for working with latest Linux kernels for Mips.

Keep :-)
HanishKVC

_________________________________________________________
Do You Yahoo!?
Get your free @yahoo.com address at http://mail.yahoo.com