Re: add page argument to copy/clear_user_page

2001-05-23 Thread Paul Mackerras

Linus Torvalds writes:

> > As for the `to' argument, yes it is redundant since it is just kmap(page).
> 
> And why not let "clear_page()" just do that itself?

OK, here's a patch that does that.

> The thing is, copy/clear_page shouldn't exist at all (or rather, the
> "highpage" versions should be renamed to the non-highpage names, because
> the non-highmem case simply isn't interesting any more).

Each architecture already had a clear_page that was functionally
equivalent to memset(p, 0, PAGE_SIZE), but often in assembler, and
likewise a copy_page that was equivalent to memcpy(d, s, PAGE_SIZE).
So I renamed all the existing clear_page's and copy_page's to
__clear_page and __copy_page (since they are "lower-level" or "raw"
clear/copy page routines).

In highmem.h I have renamed copy_highpage to copy_page and
clear_highpage to clear_page.  I also have default versions of
copy_user_page and clear_user_page which just do copy_page/clear_page
for those architectures that don't have any cache issues to deal
with.  Architectures can define __HAVE_ARCH_USER_PAGE in asm/page.h
and then define their own copy/clear_user_page routines if they want
to.

I have fixed up all the architectures except sparc64.  There the
copy/clear_user_page routines are in assembler and my sparc assembler
is pretty rusty these days (particularly when DaveM goes doing hairy
things with the %g registers :).  I'll let Dave fix that one up; the
change is that copy/clear_user_page take page * arguments instead of
void * arguments.

This patch is a fair bit bigger than the last one, but most of the
bulk is just the renaming of clear_page to __clear_page and copy_page
to __copy_page.  I also renamed memclear_highpage to memclear_page
(which isn't actually used anywhere) and memclear_highpage_flush to
memclear_page_flush.

Let me know what you think of this; if it's OK, could you apply it to
your tree?

Thanks,
Paul.

diff -urN linux/Documentation/cachetlb.txt linux.new/Documentation/cachetlb.txt
--- linux/Documentation/cachetlb.txtSat Mar 31 03:05:54 2001
+++ linux.new/Documentation/cachetlb.txtWed May 23 20:48:38 2001
@@ -260,8 +260,9 @@
 
 Here is the new interface:
 
-  void copy_user_page(void *to, void *from, unsigned long address)
-  void clear_user_page(void *to, unsigned long address)
+  void copy_user_page(struct page *to, struct page *from,
+ unsigned long address)
+  void clear_user_page(struct page *to, unsigned long address)
 
These two routines store data in user anonymous or COW
pages.  It allows a port to efficiently avoid D-cache alias
@@ -279,6 +280,11 @@
 
If D-cache aliasing is not an issue, these two routines may
simply call memcpy/memset directly and do nothing more.
+
+   There are default versions of these procedures supplied in
+   include/linux/highmem.h.  If a port does not want to use the
+   default versions it should declare them and define the symbol
+   __HAVE_ARCH_USER_PAGE in include/asm/page.h.
 
   void flush_dcache_page(struct page *page)
 
diff -urN linux/arch/alpha/kernel/alpha_ksyms.c 
linux.new/arch/alpha/kernel/alpha_ksyms.c
--- linux/arch/alpha/kernel/alpha_ksyms.c   Sat Apr 28 23:02:30 2001
+++ linux.new/arch/alpha/kernel/alpha_ksyms.c   Wed May 23 20:39:23 2001
@@ -98,8 +98,8 @@
 EXPORT_SYMBOL(__memset);
 EXPORT_SYMBOL(__memsetw);
 EXPORT_SYMBOL(__constant_c_memset);
-EXPORT_SYMBOL(copy_page);
-EXPORT_SYMBOL(clear_page);
+EXPORT_SYMBOL(__copy_page);
+EXPORT_SYMBOL(__clear_page);
 
 EXPORT_SYMBOL(__direct_map_base);
 EXPORT_SYMBOL(__direct_map_size);
diff -urN linux/arch/alpha/lib/clear_page.S linux.new/arch/alpha/lib/clear_page.S
--- linux/arch/alpha/lib/clear_page.S   Thu Feb 22 14:24:52 2001
+++ linux.new/arch/alpha/lib/clear_page.S   Wed May 23 20:39:23 2001
@@ -6,9 +6,9 @@
 
.text
.align 4
-   .global clear_page
-   .ent clear_page
-clear_page:
+   .global __clear_page
+   .ent __clear_page
+__clear_page:
.prologue 0
 
lda $0,128
@@ -36,4 +36,4 @@
unop
nop
 
-   .end clear_page
+   .end __clear_page
diff -urN linux/arch/alpha/lib/copy_page.S linux.new/arch/alpha/lib/copy_page.S
--- linux/arch/alpha/lib/copy_page.SThu Feb 22 14:24:52 2001
+++ linux.new/arch/alpha/lib/copy_page.SWed May 23 21:05:31 2001
@@ -6,9 +6,9 @@
 
.text
.align 4
-   .global copy_page
-   .ent copy_page
-copy_page:
+   .global __copy_page
+   .ent __copy_page
+__copy_page:
.prologue 0
 
lda $18,128
@@ -46,4 +46,4 @@
unop
nop
 
-   .end copy_page
+   .end __copy_page
diff -urN linux/arch/alpha/lib/ev6-clear_page.S 
linux.new/arch/alpha/lib/ev6-clear_page.S
--- linux/arch/alpha/lib/ev6-clear_page.S   Thu Feb 22 14:24:52 2001
+++ linux.new/arch/alpha/lib/ev6-clear_page.S   Wed May 23 20:39:23 2001
@@ -6,9 +6,9 @@
 
 .text
 .align 4
-.global clear_page

Re: add page argument to copy/clear_user_page

2001-05-22 Thread Linus Torvalds


On Mon, 21 May 2001, Paul Mackerras wrote:
> 
> As for the `to' argument, yes it is redundant since it is just kmap(page).

And why not let "clear_page()" just do that itself?

The only place that doesn't already do "kmap(page)" is basically
get_zeroed_page(), and the only reason it doesn't do that is because the
whole function is fundamentally not able to handle high memory pages (it
returns a fixed address, not the "struct page *".

But that function is also likely to not care about the extra five cycles
or so of having to do the kmap() by making clear_page() (and copy_page())
always use "struct page *" and do kmap() internally. Because most people
who care about performance are already using other functions (in fact, the
functions that _can_ allocate high memory).

And I hate redundancy, and having different functions for the same thing.

> But copy/clear_user_page isn't the interface that gets called from the
> MM stuff, copy/clear_user_highpage is, defined in include/linux/highmem.h.
> These are two of a whole series of functions which all do kmap, do
> something, kunmap.

The thing is, copy/clear_page shouldn't exist at all (or rather, the
"highpage" versions should be renamed to the non-highpage names, because
the non-highmem case simply isn't interesting any more).

The highmem special casing used to make sense back when highmem was a rare
special case. These days, we should just get rid of the distinction as
much as possible,

Linus

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/



Re: add page argument to copy/clear_user_page

2001-05-20 Thread Paul Mackerras

Linus Torvalds writes:

> If you add the page argument, why leave the old arguments lingering there
> at all? They only create confusion, and add no information. 

You mean the `to' pointer argument, or the `vaddr' argument?  The
`vaddr' argument isn't redundant, it's the user virtual address where
the page is mapped, and sparc64 needs it in order to avoid D-cache
aliasing issues I believe. (Dave?)

As for the `to' argument, yes it is redundant since it is just kmap(page).
But copy/clear_user_page isn't the interface that gets called from the
MM stuff, copy/clear_user_highpage is, defined in include/linux/highmem.h.
These are two of a whole series of functions which all do kmap, do
something, kunmap.

IMHO having the kmap/kunmap calls in copy/clear_user_highpage in
include/linux/highmem.h is the best approach because it means that
most architectures can just #define copy/clear_user_page as
copy/clear_page in include/asm/page.h (as they do at the moment).  It
means that the kmap/kunmap calls are in one place only instead of
being duplicated in every architecture.

But we could instead push the kmap/kunmap down into copy/clear_user_page.
Then we might as well rename them into copy/clear_user_highpage.  Here
is how it might turn out in include/asm-i386/page.h (and asm-alpha,
asm-arm, asm-crus, asm-s390, asm-sh, asm-s390x...):

extern void clear_page(void *page);
extern void copy_page(void * _to, void * _from);

#define clear_user_highpage(page, vaddr)\
do {\
struct page *__page = page; \
clear_page(kmap(__page));   \
kunmap(__page); \
} while (0)

#define copy_user_highpage(to, from, vaddr) \
do {\
struct page *__to = to, *__from = from; \
copy_page(kmap(__to), kmap(__from));\
kunmap(__from); \
kunmap(__to);   \
} while (0)

Doing it with inline functions would be cleaner but would mean that we
would need the declaration of kmap/kunmap in page.h.  That would mean
that we would need to #include  in include/asm/page.h
which is starting to get pretty messy and inviting circular
inclusions.  We could move these declarations to another file in
include/asm - include/asm/highmem.h might seem the natural place but
it is only used if CONFIG_HIGHMEM is defined and not all ports have
it.

I assume nobody wants to do these functions out-of-line. :)

So on the whole the way I had it seems cleanest to me.  But I can whip
up a patch to do the kmap/kunmap in the architecture-specific files
instead, if you prefer - if so, do you prefer the macro version or the
inline function version?

Paul.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/



Re: add page argument to copy/clear_user_page

2001-05-20 Thread Linus Torvalds


On Sun, 20 May 2001, Paul Mackerras wrote:
> 
> The patch below adds a page * argument to copy_user_page and
> clear_user_page.

If you add the page argument, why leave the old arguments lingering there
at all? They only create confusion, and add no information. 

Linus

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/