Subject: Re: linux kernel building for mips malta target board

From: David Daney <[email-masked]>
Date: Wed, 02 Nov 2005 16:45:40 -0800

[email-masked] wrote:
>>>I would like to build latest kernel (ie kernel 2.6.13) for mips malta
>>>board. Can any one advise me the cross-compiler tools version to be 
>>>used for building the linux kernel.
>>>
>>
>>I use both gcc-3.3.1 and gcc-3.4.3 to build 2.6.x mips linux kernels.  I 
>>think for the 2.6.13 kernel any of the latest released versions of 
>>3.3.x, 3.4.x, or 4.0.x would work.  Use the latest binutils (2.16.91 
>>20050817 is what I am using).
>>
> 
> Also, make sure to NOT use any of the 4.1 GCC stuff with Linux/MIPS
> kernels. I am still tracking down errors with it.
> 

Is this the problem you are seeing?:
In file included from include/linux/nfs_fs.h:15,
                  from init/do_mounts.c:12:
include/linux/pagemap.h: In function ‘fault_in_pages_readable’:
include/linux/pagemap.h:236: error: read-only variable ‘__gu_val’ used 
as ‘asm’ output
include/linux/pagemap.h:236: error: read-only variable ‘__gu_val’ used 
as ‘asm’ output
include/linux/pagemap.h:236: error: read-only variable ‘__gu_val’ used 
as ‘asm’ output
include/linux/pagemap.h:236: error: read-only variable ‘__gu_val’ used 
as ‘asm’ output

The compiler behavior has changed since 4.0.1, but I think the new 
behavior is correct.  I am blaming the __get_user macro in 
include/asm-mips/uaccess.h.  It should be possible to fix it there.  The 
alternative is to hack up include/linux/pagemap.h.

David Daney

---

From: Stuart Anderson <[email-masked]>
Date: Wed, 2 Nov 2005 20:02:56 -0500 (EST)

On Wed, 2 Nov 2005, David Daney wrote:

> include/linux/pagemap.h: In function fault_in_pages_readable:
> include/linux/pagemap.h:236: error: read-only variable __gu_val used as 
> asm output
> include/linux/pagemap.h:236: error: read-only variable __gu_val used as 
> asm output
> include/linux/pagemap.h:236: error: read-only variable __gu_val used as 
> asm output
> include/linux/pagemap.h:236: error: read-only variable __gu_val used as 
> asm output
>
> The compiler behavior has changed since 4.0.1, but I think the new behavior 
> is correct.  I am blaming the __get_user macro in include/asm-mips/uaccess.h. 
> It should be possible to fix it there.  The alternative is to hack up 
> include/linux/pagemap.h.

__get_user() is unhappy, with tpyes that are "const". It uses __typeof()
to create a local variable that it wants to write to. I've intended to
have offer up a patch by now, but, too manyunexpected thing have happened 
in the firs thalf of this week.

                                  Stuart

Stuart R. Anderson                               [email-masked]
Network & Software Engineering                   http://www.netsweng.com/
1024D/37A79149:                                  0791 D3B8 9A4C 2CDC A31F
                                                   BD03 0A62 E534 37A7 9149

---

From: David Daney <[email-masked]>
Date: Wed, 02 Nov 2005 17:19:51 -0800

Stuart Anderson wrote:
>> include/linux/pagemap.h:236: error: read-only variable __gu_val 
>> used as asm output
>> include/linux/pagemap.h:236: error: read-only variable __gu_val 
>> used as asm output
>> include/linux/pagemap.h:236: error: read-only variable __gu_val 
>> used as asm output
>> include/linux/pagemap.h:236: error: read-only variable __gu_val 
>> used as asm output
>>
>> include/asm-mips/uaccess.h. It should be possible to fix it there.  
>> The alternative is to hack up include/linux/pagemap.h.
> 
> 
> have offer up a patch by now, but, too manyunexpected thing have 
> happened in the firs thalf of this week.
> 

That is my analysis as well.  The typeof converts the const char * into 
a const char which is then unsuitable as the destination in an inline asm.

David Daney

---

From: Stuart Anderson <[email-masked]>
Date: Wed, 2 Nov 2005 21:20:35 -0500 (EST)

On Wed, 2 Nov 2005, David Daney wrote:

>> have offer up a patch by now, but, too many unexpected thing have happened 

I shamed myself into sitting down and doing this. 8-)

The attached patch seems to work, or at least doesn't seem to cause
things to blow up. An o32 userspace on a 64-bit kernel comes up
multi-user and can build a kernel, and run a quick subset of LTP.

There was a comment on IRC that there was a register allocation issue which
lead to the current code. I'm not sure of the exact details, but I _think_
this change ends up being equivilent to the code it replaces.

                                 Stuart

Index: uaccess.h
===================================================================
--- uaccess.h	(revision 84)
+++ uaccess.h	(working copy)
@@ -210,17 +210,35 @@
 
 #define __get_user_nocheck(x,ptr,size)					\
 ({									\
-	__typeof(*(ptr)) __gu_val =  (__typeof(*(ptr))) 0;		\
 	long __gu_err = 0;						\
 									\
 	switch (size) {							\
-	case 1: __get_user_asm("lb", ptr); break;			\
-	case 2: __get_user_asm("lh", ptr); break;			\
-	case 4: __get_user_asm("lw", ptr); break;			\
-	case 8: __GET_USER_DW(ptr); break;				\
+	case 1: {							\
+		s8 __gu_val =  (s8) 0;					\
+		__get_user_asm("lb", ptr); 				\
+		(x) = (__typeof__(*(ptr))) __gu_val;			\
+		break;							\
+		}							\
+	case 2:	{							\
+		s16 __gu_val =  (s16) 0;				\
+		__get_user_asm("lh", ptr);				\
+		(x) = (__typeof__(*(ptr))) __gu_val;			\
+		break;							\
+		}							\
+	case 4:	{							\
+		s32 __gu_val = (s32) 0;					\
+		__get_user_asm("lw", ptr);				\
+		(x) = (__typeof__(*(ptr))) __gu_val;			\
+		break;							\
+		}							\
+	case 8:	{							\
+		s64 __gu_val = (s64) 0;					\
+		__GET_USER_DW(ptr);					\
+		(x) = (__typeof__(*(ptr))) __gu_val;			\
+		break;							\
+		}							\
 	default: __get_user_unknown(); break;				\
 	}								\
-	(x) = (__typeof__(*(ptr))) __gu_val;				\
 	__gu_err;							\
 })

---

From: Ralf Baechle <[email-masked]>
Date: Thu, 3 Nov 2005 16:33:06 +0000

> this change ends up being equivilent to the code it replaces.

It's correct - but triggers plenty of extra warnings and you forgot about
get_user() which has the same kind of issue.  Also you don't have the
guarantee that <linux/types.h> has been included, so in order to avoid a
yet another header file dependency I changed s8, s16 etc. to char, short,
int, long long.  Working on it but as usual uaccess.h is quite a quiz.

  Ralf