All of lore.kernel.org
 help / color / mirror / Atom feed
* initrd testing [possible solution]
@ 2004-11-04  5:38 Jurij Smakov
  2004-11-15  4:16 ` Jurij Smakov
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Jurij Smakov @ 2004-11-04  5:38 UTC (permalink / raw)
  To: sparclinux

[Please CC the responses to me as I am not on the list.]

Hello,

I have made a little research into the infamous initrd problem (short 
story: initrd cannot be mounted with 'cramfs: wrong magic', long story may 
be found in the May 2004 thread starting at [0]). I have used Debian's 
unstable 2.4.27 kernel, which suffers from that problem on my Sparcstation 
10. After inserting some debugging code I was able to figure out, that 
the initrd contents got loaded into the memory by silo and then passed 
into the /dev/ram correctly. After that kernel attempts to mount root on 
it. The relevant calls go like this:

init/do_mounts.c: handle_initrd:
  fs/namespace.c: sys_mount
   fs/namespace.c: do_mount
    fs/namespace.c: do_add_mount
     fs/super.c: do_kern_mount
      fs/super.c: get_sb_bdev
       fs/cramfs/inode.c cramfs_read_super (via fs_type->read_super)
        fs/cramfs/inode.c cramfs_read(sb, 0, sizeof(super)) (via memcpy)

In the last call cramfs_read is called to read in the superblock of the
cramfs filesystem. The source data was ok (i.e. contained the expected
cramfs magic in the beginning) all the way up to this code snippet from
cramfs_read() from fs/cramfs/inode.c:

         data = read_buffers[buffer];
         for (i = 0; i < BLKS_PER_BUF; i++) {
                 struct page *page = pages[i];
                 if (page) {
                         memcpy(data, kmap(page), PAGE_CACHE_SIZE);
                         kunmap(page);
                         page_cache_release(page);
                 } else
                         memset(data, 0, PAGE_CACHE_SIZE);
                 data += PAGE_CACHE_SIZE;
         }

So, memory at address kmap(pages[0]) contained the correct byte sequence 
for the cramfs magic, but the memory at location 'data' after the 
call to memcpy() did not (in fact, it appeared as if the first 4 bytes 
were not copied to the destination)! It turned out that memcpy() calls 
different copying routines depending on the size of the copied block (see 
include/asm-sparc/string.h). It has a special routine for copying the 
memory chunks of size PAGE_SIZE (equal to PAGE_CACHE_SIZE), called 
__copy_1page and defined in arch/sparc/lib/blockops.S. Having narrowed it 
down that much I have tried replacing memcpy() in the code above by 
__memcpy(), thus avoiding the use of __copy_1page and invoking the more 
generic (probably, slower) subroutine (__memcpy in arch/sparc/lib/memcpy.S). 
As a result, the initrd was correctly mounted!

So, my conclusion is that __copy_1page is broken, at least under certain 
(yet undetermined) conditions. If that's really the case, it either 
should be fixed (requires knowledge of assembler, which I lack) or its use 
should be avoided whatsoever. The latter is easy to achieve by modifying 
the memcpy() definition in include/asm-sparc/string.h to call __memcpy 
instead.

[0] http://marc.theaimsgroup.com/?t\x108448100400006&r=1&w=2

Best regards,

Jurij Smakov                                        jurij@wooyd.org
Key: http://www.wooyd.org/pgpkey/                   KeyID: C99E03CC

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: initrd testing [possible solution]
  2004-11-04  5:38 initrd testing [possible solution] Jurij Smakov
@ 2004-11-15  4:16 ` Jurij Smakov
  2004-11-15 23:40 ` David S. Miller
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Jurij Smakov @ 2004-11-15  4:16 UTC (permalink / raw)
  To: sparclinux

On Thu, 4 Nov 2004, Jurij Smakov wrote:
[skipped]
> So, my conclusion is that __copy_1page is broken, at least under certain (yet 
> undetermined) conditions. If that's really the case, it either should be 
> fixed (requires knowledge of assembler, which I lack) or its use should be 
> avoided whatsoever. The latter is easy to achieve by modifying the memcpy() 
> definition in include/asm-sparc/string.h to call __memcpy instead.

As a followup: I have tried fiddling more with the memcpy() routine. 
Insight from Rob Radez and comments in arch/sparc/lib/blockops.S suggest, 
that __copy_1page assumes that the memory regions copied are aligned on a 
double-word boundary. I have checked, that in the cramfs case it wasn't 
true, the destination was not aligned on the double-word boundary. So, I
have implemented a simple workaround (see patch below), which together
with Bob Breuer's iommu.c fix [0] made 2.6.8 kernel to boot on my 
machine (SS10 with Ross Hypersparc CPU)! I also confirm, that adding the 
suggested fix to the srmmu.c also [1] breaks sunlance on my machine. With 
that "fix" the line 'eth0: Memory error, status 88c3, addr 3713ba' is
displayed continuously during boot, when it comes to configuring network
interfaces. The successful patch for me is:

--- build-sparc32.orig/include/asm-sparc/string.h	2004-08-14 01:36:11.000000000 -0400
+++ build-sparc32/include/asm-sparc/string.h	2004-11-14 22:09:49.000000000 -0500
@@ -40,6 +40,9 @@

  	if(n <= 32) {
  		__builtin_memcpy(to, from, n);
+	} else if (((unsigned int) to & 7) != 0) {
+		/* Destination is not aligned on the double-word boundary */
+		__memcpy(to, from, n);
  	} else {
  		switch(n) {
  		case PAGE_SIZE:
--- build-sparc32.orig/arch/sparc/mm/iommu.c	2004-08-14 01:38:08.000000000 -0400
+++ build-sparc32/arch/sparc/mm/iommu.c	2004-11-14 22:10:09.000000000 -0500
@@ -173,6 +173,7 @@
  	}

  	iommu_viking_flush_iotlb(iopte0, npages);
+	flush_cache_all();

  	return busa0;
  }

Note, that this patch is against the unpacked Debian kernel package's 
build-sparc32 tree, so it may be fuzzy w/respect to the pristine kernel.

[0] http://marc.theaimsgroup.com/?l=linux-sparc&m\x110005632921213&w=2
[1] http://marc.theaimsgroup.com/?l=linux-sparc&m\x110014079917049&w=2

Best regards,

Jurij Smakov                                        jurij@wooyd.org
Key: http://www.wooyd.org/pgpkey/                   KeyID: C99E03CC

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: initrd testing [possible solution]
  2004-11-04  5:38 initrd testing [possible solution] Jurij Smakov
  2004-11-15  4:16 ` Jurij Smakov
@ 2004-11-15 23:40 ` David S. Miller
  2004-11-15 23:56 ` William Lee Irwin III
  2004-11-16  2:11 ` Rob Radez
  3 siblings, 0 replies; 5+ messages in thread
From: David S. Miller @ 2004-11-15 23:40 UTC (permalink / raw)
  To: sparclinux

On Sun, 14 Nov 2004 23:16:40 -0500 (EST)
Jurij Smakov <jurij@wooyd.org> wrote:

> --- build-sparc32.orig/include/asm-sparc/string.h	2004-08-14 01:36:11.000000000 -0400
> +++ build-sparc32/include/asm-sparc/string.h	2004-11-14 22:09:49.000000000 -0500
> @@ -40,6 +40,9 @@
> 
>   	if(n <= 32) {
>   		__builtin_memcpy(to, from, n);
> +	} else if (((unsigned int) to & 7) != 0) {
> +		/* Destination is not aligned on the double-word boundary */
> +		__memcpy(to, from, n);
>   	} else {
>   		switch(n) {
>   		case PAGE_SIZE:

This patch is perfectly fine, good catch.

wli, you got this?

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: initrd testing [possible solution]
  2004-11-04  5:38 initrd testing [possible solution] Jurij Smakov
  2004-11-15  4:16 ` Jurij Smakov
  2004-11-15 23:40 ` David S. Miller
@ 2004-11-15 23:56 ` William Lee Irwin III
  2004-11-16  2:11 ` Rob Radez
  3 siblings, 0 replies; 5+ messages in thread
From: William Lee Irwin III @ 2004-11-15 23:56 UTC (permalink / raw)
  To: sparclinux

On Sun, 14 Nov 2004 23:16:40 -0500 (EST) Jurij Smakov <jurij@wooyd.org> wrote:
> > --- build-sparc32.orig/include/asm-sparc/string.h	2004-08-14 01:36:11.000000000 -0400
> > +++ build-sparc32/include/asm-sparc/string.h	2004-11-14 22:09:49.000000000 -0500
> > @@ -40,6 +40,9 @@
> > 
> >   	if(n <= 32) {
> >   		__builtin_memcpy(to, from, n);
> > +	} else if (((unsigned int) to & 7) != 0) {
> > +		/* Destination is not aligned on the double-word boundary */
> > +		__memcpy(to, from, n);
> >   	} else {
> >   		switch(n) {
> >   		case PAGE_SIZE:

On Mon, Nov 15, 2004 at 03:40:23PM -0800, David S. Miller wrote:
> This patch is perfectly fine, good catch.
> wli, you got this?

Absolutely.

-- wli

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: initrd testing [possible solution]
  2004-11-04  5:38 initrd testing [possible solution] Jurij Smakov
                   ` (2 preceding siblings ...)
  2004-11-15 23:56 ` William Lee Irwin III
@ 2004-11-16  2:11 ` Rob Radez
  3 siblings, 0 replies; 5+ messages in thread
From: Rob Radez @ 2004-11-16  2:11 UTC (permalink / raw)
  To: sparclinux

On Mon, Nov 15, 2004 at 03:56:03PM -0800, William Lee Irwin III wrote:
> On Sun, 14 Nov 2004 23:16:40 -0500 (EST) Jurij Smakov <jurij@wooyd.org> wrote:
> > > --- build-sparc32.orig/include/asm-sparc/string.h	2004-08-14 01:36:11.000000000 -0400
> > > +++ build-sparc32/include/asm-sparc/string.h	2004-11-14 22:09:49.000000000 -0500
> > > @@ -40,6 +40,9 @@
> > > 
> > >   	if(n <= 32) {
> > >   		__builtin_memcpy(to, from, n);
> > > +	} else if (((unsigned int) to & 7) != 0) {
> > > +		/* Destination is not aligned on the double-word boundary */
> > > +		__memcpy(to, from, n);
> > >   	} else {
> > >   		switch(n) {
> > >   		case PAGE_SIZE:
> 
> On Mon, Nov 15, 2004 at 03:40:23PM -0800, David S. Miller wrote:
> > This patch is perfectly fine, good catch.
> > wli, you got this?
> 
> Absolutely.

I was looking at something like this; do we lose the benefit that comes
from knowing that n is a constant and if so, should we delete the
preprocessing macro that checks if n is constant?

Rob

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2004-11-16  2:11 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-11-04  5:38 initrd testing [possible solution] Jurij Smakov
2004-11-15  4:16 ` Jurij Smakov
2004-11-15 23:40 ` David S. Miller
2004-11-15 23:56 ` William Lee Irwin III
2004-11-16  2:11 ` Rob Radez

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.