2002-10-16 18:20:38

by Matthew Wilcox

[permalink] [raw]
Subject: [PATCH] shmem missing cache flush


Really, this should be a clear_user_page(), but we can't reasonable get
a user address all the way down to it, so let's just flush it instead.
Note that 2.4 needs an equivalent fix.

diff -urpNX build-tools/dontdiff linus-2.5/mm/shmem.c parisc-2.5/mm/shmem.c
--- linus-2.5/mm/shmem.c Tue Oct 8 10:54:20 2002
+++ parisc-2.5/mm/shmem.c Tue Oct 8 16:49:24 2002
@@ -848,6 +848,7 @@ repeat:
info->alloced++;
spin_unlock(&info->lock);
clear_highpage(page);
+ flush_dcache_page(page);
SetPageUptodate(page);
}


--
Revolutions do not require corporate support.


2002-10-16 23:50:45

by Hugh Dickins

[permalink] [raw]
Subject: Re: [PATCH] shmem missing cache flush

On Wed, 16 Oct 2002, Matthew Wilcox wrote:
>
> Really, this should be a clear_user_page(), but we can't reasonable get
> a user address all the way down to it, so let's just flush it instead.
> Note that 2.4 needs an equivalent fix.
>
> diff -urpNX build-tools/dontdiff linus-2.5/mm/shmem.c parisc-2.5/mm/shmem.c
> --- linus-2.5/mm/shmem.c Tue Oct 8 10:54:20 2002
> +++ parisc-2.5/mm/shmem.c Tue Oct 8 16:49:24 2002
> @@ -848,6 +848,7 @@ repeat:
> info->alloced++;
> spin_unlock(&info->lock);
> clear_highpage(page);
> + flush_dcache_page(page);
> SetPageUptodate(page);
> }

I expect you're right - even though that page is not yet mapped into
any user address space? I'm currently preparing a shmem.c patch set
to send Andrew in the next day or two, so I'll factor that in too.

I would be much happier about adding it, if you could tell me that
I can then remove the flush_page_to_ram(page) from shmem_nopage?

But suspect you won't grant me that: notice that 2.4.18 and 2.5.3
added flush_dcache_page in addition to flush_page_to_ram in
memclear_highpage_flush, which I'll take as definitive.

To x86ers, flush_page_to_ram, flush_dcache_page, flush_icache_page
etc. all seem like forlorn prayers to different gods, "Please, let
my data be seen by the user". Documentation/cachetlb.txt has for
a long time told us that flush_page_to_ram (sacrifice ram to page
god) is now deprecated, the new religion is flush_dcache_page,
and flush_icache_page can soon be forgotten. But they're all
still there to confuse us; and it seems that years can go by
without the high priests noticing where these prayers are needed.

In view of which, I don't expect to be rushing a 2.4.20 fix to
Marcelo: let it ride until 2.4.21, okay?

Hugh

2002-10-17 00:00:07

by David Miller

[permalink] [raw]
Subject: Re: [PATCH] shmem missing cache flush

From: Hugh Dickins <[email protected]>
Date: Thu, 17 Oct 2002 00:57:30 +0100 (BST)

I would be much happier about adding it, if you could tell me that
I can then remove the flush_page_to_ram(page) from shmem_nopage?

No we still have to support platforms using flush_page_to_ram()

I didn't get a chance to deprecate this in 2.5.x, I wish I had.

2002-10-17 00:14:06

by Russell King

[permalink] [raw]
Subject: Re: [PATCH] shmem missing cache flush

On Wed, Oct 16, 2002 at 04:58:34PM -0700, David S. Miller wrote:
> No we still have to support platforms using flush_page_to_ram()
>
> I didn't get a chance to deprecate this in 2.5.x, I wish I had.

I similarly wish that were so. Any cleanups in this area are most
welcome. Alas m68k and sparc still use flush_page_to_ram().

--
Russell King ([email protected]) The developer of ARM Linux
http://www.arm.linux.org.uk/personal/aboutme.html

2002-10-17 00:18:07

by David Miller

[permalink] [raw]
Subject: Re: [PATCH] shmem missing cache flush

From: Russell King <[email protected]>
Date: Thu, 17 Oct 2002 01:19:57 +0100

I similarly wish that were so. Any cleanups in this area are most
welcome. Alas m68k and sparc still use flush_page_to_ram().

I'd consider it more than rude to break this 5 days before
feature freeze. :-)

Put this at the top of the list of 2.7.x todo and let's not
forget it this time.

2002-10-21 14:42:41

by Alan

[permalink] [raw]
Subject: Re: [PATCH] shmem missing cache flush

On Thu, 2002-10-17 at 01:16, David S. Miller wrote:
> I similarly wish that were so. Any cleanups in this area are most
> welcome. Alas m68k and sparc still use flush_page_to_ram().
>
> I'd consider it more than rude to break this 5 days before
> feature freeze. :-)
>
> Put this at the top of the list of 2.7.x todo and let's not
> forget it this time.

I disagree here. Its a measurable performance item, and its actually
going to break less code than for example the last minute scsi and bio
changes have done

2002-10-21 15:24:13

by David Miller

[permalink] [raw]
Subject: Re: [PATCH] shmem missing cache flush

From: Alan Cox <[email protected]>
Date: 21 Oct 2002 16:04:17 +0100

I disagree here. Its a measurable performance item, and its actually
going to break less code than for example the last minute scsi and bio
changes have done

That's a good point.

So, if you want to merge the deprecation to Linus when he returns
I'd fully support it :-)

2002-10-21 15:50:46

by Alan

[permalink] [raw]
Subject: Re: [PATCH] shmem missing cache flush

On Mon, 2002-10-21 at 16:21, David S. Miller wrote:
> From: Alan Cox <[email protected]>
> Date: 21 Oct 2002 16:04:17 +0100
>
> I disagree here. Its a measurable performance item, and its actually
> going to break less code than for example the last minute scsi and bio
> changes have done
>
> That's a good point.
>
> So, if you want to merge the deprecation to Linus when he returns
> I'd fully support it :-)

Fine by me. The m68k people can thank me for all the 5380 fixing I've
been doing instead. Send me the diffs Im happy to give them a spin.
Compared to a bit of vm work the rest of the stuff needed is way way
worse. I'd hate to be fixing the atari st ide support in 2.5 8) although
I do want to see suspend to disk on an amiga


Alan

2002-10-28 14:14:23

by David Miller

[permalink] [raw]
Subject: Re: [PATCH] shmem missing cache flush

From: Alan Cox <[email protected]>
Date: 21 Oct 2002 17:12:22 +0100

Send me the diffs Im happy to give them a spin.

Here goes. I contacted Anton and Paulus about flush_icache_page as
that is on the hitlist next and ppc/ppc64 is the only well maintained
port using that.

--- ./Documentation/cachetlb.txt.~1~ Mon Oct 28 06:03:18 2002
+++ ./Documentation/cachetlb.txt Mon Oct 28 06:08:05 2002
@@ -235,41 +235,14 @@ this value.
NOTE: This does not fix shared mmaps, check out the sparc64 port for
one way to solve this (in particular SPARC_FLAG_MMAPSHARED).

-Next, you have two methods to solve the D-cache aliasing issue for all
+Here is the method to solve the D-cache aliasing issue for all
other cases. Please keep in mind that fact that, for a given page
mapped into some user address space, there is always at least one more
mapping, that of the kernel in it's linear mapping starting at
PAGE_OFFSET. So immediately, once the first user maps a given
physical page into its address space, by implication the D-cache
aliasing problem has the potential to exist since the kernel already
-maps this page at its virtual address.
-
-First, I describe the old method to deal with this problem. I am
-describing it for documentation purposes, but it is deprecated and the
-latter method I describe next should be used by all new ports and all
-existing ports should move over to the new mechanism as well.
-
- flush_page_to_ram(struct page *page)
-
- The physical page 'page' is about to be place into the
- user address space of a process. If it is possible for
- stores done recently by the kernel into this physical
- page, to not be visible to an arbitrary mapping in userspace,
- you must flush this page from the D-cache.
-
- If the D-cache is writeback in nature, the dirty data (if
- any) for this physical page must be written back to main
- memory before the cache lines are invalidated.
-
-Admittedly, the author did not think very much when designing this
-interface. It does not give the architecture enough information about
-what exactly is going on, and there is no context to base a judgment
-on about whether an alias is possible at all. The new interfaces to
-deal with D-cache aliasing are meant to address this by telling the
-architecture specific code exactly which is going on at the proper points
-in time.
-
-Here is the new interface:
+maps this page at its virtual address:

void copy_user_page(void *to, void *from, unsigned long address)
void clear_user_page(void *to, unsigned long address)
--- ./arch/ia64/mm/init.c.~1~ Mon Oct 28 05:56:41 2002
+++ ./arch/ia64/mm/init.c Mon Oct 28 05:57:29 2002
@@ -250,7 +250,6 @@ put_gate_page (struct page *page, unsign
pte_unmap(pte);
goto out;
}
- flush_page_to_ram(page);
set_pte(pte, mk_pte(page, PAGE_GATE));
pte_unmap(pte);
}
--- ./arch/ppc64/kernel/sys_ppc32.c.~1~ Mon Oct 28 05:56:41 2002
+++ ./arch/ppc64/kernel/sys_ppc32.c Mon Oct 28 05:57:36 2002
@@ -3464,7 +3464,6 @@ static int copy_strings32(int argc, u32

err = copy_from_user(kaddr + offset, (char *)A(str),
bytes_to_copy);
- flush_page_to_ram(page);
kunmap((unsigned long)kaddr);

if (err)
--- ./arch/s390x/kernel/linux32.c.~1~ Mon Oct 28 05:56:41 2002
+++ ./arch/s390x/kernel/linux32.c Mon Oct 28 05:57:44 2002
@@ -3019,7 +3019,6 @@ static int copy_strings32(int argc, u32

err = copy_from_user(kaddr + offset, (char *)A(str),
bytes_to_copy);
- flush_page_to_ram(page);
kunmap(page);

if (err)
--- ./fs/binfmt_elf.c.~1~ Mon Oct 28 05:56:41 2002
+++ ./fs/binfmt_elf.c Mon Oct 28 05:57:53 2002
@@ -1253,7 +1253,6 @@ static int elf_core_dump(long signr, str
flush_cache_page(vma, addr);
kaddr = kmap(page);
DUMP_WRITE(kaddr, PAGE_SIZE);
- flush_page_to_ram(page);
kunmap(page);
}
page_cache_release(page);
--- ./fs/exec.c.~1~ Mon Oct 28 05:56:41 2002
+++ ./fs/exec.c Mon Oct 28 05:57:58 2002
@@ -308,7 +308,6 @@ void put_dirty_page(struct task_struct *
}
lru_cache_add(page);
flush_dcache_page(page);
- flush_page_to_ram(page);
set_pte(pte, pte_mkdirty(pte_mkwrite(mk_pte(page, PAGE_COPY))));
page_add_rmap(page, pte);
pte_unmap(pte);
--- ./include/asm-alpha/cacheflush.h.~1~ Mon Oct 28 05:56:41 2002
+++ ./include/asm-alpha/cacheflush.h Mon Oct 28 05:58:04 2002
@@ -9,7 +9,6 @@
#define flush_cache_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr) do { } while (0)
-#define flush_page_to_ram(page) do { } while (0)
#define flush_dcache_page(page) do { } while (0)

/* Note that the following two definitions are _highly_ dependent
--- ./include/asm-arm/proc-armo/cache.h.~1~ Mon Oct 28 05:56:41 2002
+++ ./include/asm-arm/proc-armo/cache.h Mon Oct 28 05:58:10 2002
@@ -13,7 +13,6 @@
#define flush_cache_mm(mm) do { } while (0)
#define flush_cache_range(vma,start,end) do { } while (0)
#define flush_cache_page(vma,vmaddr) do { } while (0)
-#define flush_page_to_ram(page) do { } while (0)

#define invalidate_dcache_range(start,end) do { } while (0)
#define clean_dcache_range(start,end) do { } while (0)
--- ./include/asm-arm/proc-armv/cache.h.~1~ Mon Oct 28 05:56:41 2002
+++ ./include/asm-arm/proc-armv/cache.h Mon Oct 28 05:58:16 2002
@@ -71,13 +71,6 @@
((unsigned long)start) + size, 0);

/*
- * This is an obsolete interface; the functionality that was provided by this
- * function is now merged into our flush_dcache_page, flush_icache_page,
- * copy_user_page and clear_user_page functions.
- */
-#define flush_page_to_ram(page) do { } while (0)
-
-/*
* flush_dcache_page is used when the kernel has written to the page
* cache page at virtual address page->virtual.
*
--- ./include/asm-cris/pgtable.h.~1~ Mon Oct 28 05:56:41 2002
+++ ./include/asm-cris/pgtable.h Mon Oct 28 05:58:25 2002
@@ -121,7 +121,6 @@ extern void paging_init(void);
#define flush_cache_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr) do { } while (0)
-#define flush_page_to_ram(page) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
#define flush_icache_range(start, end) do { } while (0)
#define flush_icache_page(vma,pg) do { } while (0)
--- ./include/asm-i386/cacheflush.h.~1~ Mon Oct 28 05:56:41 2002
+++ ./include/asm-i386/cacheflush.h Mon Oct 28 05:58:31 2002
@@ -9,7 +9,6 @@
#define flush_cache_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr) do { } while (0)
-#define flush_page_to_ram(page) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
#define flush_icache_range(start, end) do { } while (0)
#define flush_icache_page(vma,pg) do { } while (0)
--- ./include/asm-ia64/cacheflush.h.~1~ Mon Oct 28 05:56:41 2002
+++ ./include/asm-ia64/cacheflush.h Mon Oct 28 05:58:36 2002
@@ -20,7 +20,6 @@
#define flush_cache_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr) do { } while (0)
-#define flush_page_to_ram(page) do { } while (0)
#define flush_icache_page(vma,page) do { } while (0)

#define flush_dcache_page(page) \
--- ./include/asm-m68k/cacheflush.h.~1~ Mon Oct 28 05:56:41 2002
+++ ./include/asm-m68k/cacheflush.h Mon Oct 28 05:59:02 2002
@@ -106,7 +106,7 @@ extern inline void flush_cache_page(stru

/* Push the page at kernel virtual address and clear the icache */
/* RZ: use cpush %bc instead of cpush %dc, cinv %ic */
-#define flush_page_to_ram(page) __flush_page_to_ram(page_address(page))
+#error flush_page_to_ram is obsoleted, please convert to flush_dcache_page
extern inline void __flush_page_to_ram(void *vaddr)
{
if (CPU_IS_040_OR_060) {
--- ./include/asm-mips/pgtable.h.~1~ Mon Oct 28 05:56:41 2002
+++ ./include/asm-mips/pgtable.h Mon Oct 28 05:59:32 2002
@@ -24,7 +24,6 @@
* - flush_cache_mm(mm) flushes the specified mm context's cache lines
* - flush_cache_page(mm, vmaddr) flushes a single page
* - flush_cache_range(vma, start, end) flushes a range of pages
- * - flush_page_to_ram(page) write back kernel page to ram
* - flush_icache_range(start, end) flush a range of instructions
*/
extern void (*_flush_cache_all)(void);
@@ -34,7 +33,7 @@ extern void (*_flush_cache_range)(struct
unsigned long end);
extern void (*_flush_cache_page)(struct vm_area_struct *vma, unsigned long page);
extern void (*_flush_cache_sigtramp)(unsigned long addr);
-extern void (*_flush_page_to_ram)(struct page * page);
+#error flush_page_to_ram is obsoleted, please convert to flush_dcache_page
extern void (*_flush_icache_range)(unsigned long start, unsigned long end);
extern void (*_flush_icache_page)(struct vm_area_struct *vma,
struct page *page);
@@ -47,7 +46,6 @@ extern void (*_flush_icache_page)(struct
#define flush_cache_range(vma,start,end) _flush_cache_range(vma,start,end)
#define flush_cache_page(vma,page) _flush_cache_page(vma, page)
#define flush_cache_sigtramp(addr) _flush_cache_sigtramp(addr)
-#define flush_page_to_ram(page) _flush_page_to_ram(page)

#define flush_icache_range(start, end) _flush_icache_range(start,end)
#define flush_icache_page(vma, page) _flush_icache_page(vma, page)
--- ./include/asm-mips64/pgtable.h.~1~ Mon Oct 28 05:56:41 2002
+++ ./include/asm-mips64/pgtable.h Mon Oct 28 05:59:55 2002
@@ -25,13 +25,12 @@
* - flush_cache_mm(mm) flushes the specified mm context's cache lines
* - flush_cache_page(mm, vmaddr) flushes a single page
* - flush_cache_range(vma, start, end) flushes a range of pages
- * - flush_page_to_ram(page) write back kernel page to ram
*/
extern void (*_flush_cache_mm)(struct mm_struct *mm);
extern void (*_flush_cache_range)(struct vm_area_struct *vma, unsigned long start,
unsigned long end);
extern void (*_flush_cache_page)(struct vm_area_struct *vma, unsigned long page);
-extern void (*_flush_page_to_ram)(struct page * page);
+#error flush_page_to_ram is obsoleted, please convert to flush_dcache_page

#define flush_cache_all() do { } while(0)
#define flush_dcache_page(page) do { } while (0)
@@ -40,7 +39,6 @@ extern void (*_flush_page_to_ram)(struct
#define flush_cache_mm(mm) _flush_cache_mm(mm)
#define flush_cache_range(vma,start,end) _flush_cache_range(vma,start,end)
#define flush_cache_page(vma,page) _flush_cache_page(vma, page)
-#define flush_page_to_ram(page) _flush_page_to_ram(page)

#define flush_icache_range(start, end) _flush_cache_l1()
#define flush_icache_user_range(vma, page, addr, len) \
@@ -66,7 +64,6 @@ extern void andes_flush_icache_page(unsi
#define flush_cache_mm(mm) do { } while(0)
#define flush_cache_range(vma,start,end) do { } while(0)
#define flush_cache_page(vma,page) do { } while(0)
-#define flush_page_to_ram(page) do { } while(0)
#define flush_icache_range(start, end) _flush_cache_l1()
#define flush_icache_user_range(vma, page, addr, len) \
flush_icache_page((vma), (page))
--- ./include/asm-parisc/pgalloc.h.~1~ Mon Oct 28 05:56:41 2002
+++ ./include/asm-parisc/pgalloc.h Mon Oct 28 06:00:13 2002
@@ -72,7 +72,7 @@ flush_kernel_dcache_range(unsigned long
asm volatile("syncdma" : : );
}

-extern void __flush_page_to_ram(unsigned long address);
+#error flush_page_to_ram is obsoleted, please convert to flush_dcache_page

#define flush_cache_all() flush_all_caches()
#define flush_cache_mm(foo) flush_all_caches()
@@ -99,9 +99,6 @@ extern inline void flush_cache_mm(struct
__flush_dcache_range(vmaddr, PAGE_SIZE); \
__flush_icache_range(vmaddr, PAGE_SIZE); \
} while(0)
-
-#define flush_page_to_ram(page) \
- __flush_page_to_ram((unsigned long)page_address(page))

#define flush_icache_range(start, end) \
__flush_icache_range(start, end - start)
--- ./include/asm-ppc/cacheflush.h.~1~ Mon Oct 28 05:56:41 2002
+++ ./include/asm-ppc/cacheflush.h Mon Oct 28 06:00:28 2002
@@ -23,7 +23,6 @@
#define flush_cache_mm(mm) do { } while (0)
#define flush_cache_range(vma, a, b) do { } while (0)
#define flush_cache_page(vma, p) do { } while (0)
-#define flush_page_to_ram(page) do { } while (0)

extern void flush_dcache_page(struct page *page);
extern void flush_icache_page(struct vm_area_struct *vma, struct page *page);
--- ./include/asm-ppc64/cacheflush.h.~1~ Mon Oct 28 05:56:41 2002
+++ ./include/asm-ppc64/cacheflush.h Mon Oct 28 06:00:35 2002
@@ -13,7 +13,6 @@
#define flush_cache_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr) do { } while (0)
-#define flush_page_to_ram(page) do { } while (0)

extern void flush_dcache_page(struct page *page);
extern void flush_icache_range(unsigned long, unsigned long);
--- ./include/asm-s390/cacheflush.h.~1~ Mon Oct 28 05:56:41 2002
+++ ./include/asm-s390/cacheflush.h Mon Oct 28 06:00:40 2002
@@ -9,7 +9,6 @@
#define flush_cache_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr) do { } while (0)
-#define flush_page_to_ram(page) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
#define flush_icache_range(start, end) do { } while (0)
#define flush_icache_page(vma,pg) do { } while (0)
--- ./include/asm-s390x/cacheflush.h.~1~ Mon Oct 28 05:56:41 2002
+++ ./include/asm-s390x/cacheflush.h Mon Oct 28 06:00:45 2002
@@ -9,7 +9,6 @@
#define flush_cache_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr) do { } while (0)
-#define flush_page_to_ram(page) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
#define flush_icache_range(start, end) do { } while (0)
#define flush_icache_page(vma,pg) do { } while (0)
--- ./include/asm-sh/pgtable.h.~1~ Mon Oct 28 05:56:41 2002
+++ ./include/asm-sh/pgtable.h Mon Oct 28 06:00:53 2002
@@ -26,7 +26,6 @@ extern void paging_init(void);
* - flush_cache_range(vma, start, end) flushes a range of pages
*
* - flush_dcache_page(pg) flushes(wback&invalidates) a page for dcache
- * - flush_page_to_ram(page) write back kernel page to ram
* - flush_icache_range(start, end) flushes(invalidates) a range for icache
* - flush_icache_page(vma, pg) flushes(invalidates) a page for icache
*
@@ -37,7 +36,6 @@ extern void paging_init(void);
#define flush_cache_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr) do { } while (0)
-#define flush_page_to_ram(page) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
#define flush_icache_range(start, end) do { } while (0)
#define flush_icache_page(vma,pg) do { } while (0)
@@ -63,7 +61,6 @@ extern void flush_dcache_page(struct pag
extern void flush_icache_range(unsigned long start, unsigned long end);
extern void flush_cache_sigtramp(unsigned long addr);

-#define flush_page_to_ram(page) do { } while (0)
#define flush_icache_page(vma,pg) do { } while (0)
#define flush_icache_user_range(vma,pg,adr,len) do { } while (0)

--- ./include/asm-sparc/cacheflush.h.~1~ Mon Oct 28 05:56:41 2002
+++ ./include/asm-sparc/cacheflush.h Mon Oct 28 06:01:31 2002
@@ -24,10 +24,8 @@ BTFIXUPDEF_CALL(void, local_flush_cache_
#define local_flush_cache_range(vma,start,end) BTFIXUP_CALL(local_flush_cache_range)(vma,start,end)
#define local_flush_cache_page(vma,addr) BTFIXUP_CALL(local_flush_cache_page)(vma,addr)

-BTFIXUPDEF_CALL(void, local_flush_page_to_ram, unsigned long)
BTFIXUPDEF_CALL(void, local_flush_sig_insns, struct mm_struct *, unsigned long)

-#define local_flush_page_to_ram(addr) BTFIXUP_CALL(local_flush_page_to_ram)(addr)
#define local_flush_sig_insns(mm,insn_addr) BTFIXUP_CALL(local_flush_sig_insns)(mm,insn_addr)

extern void smp_flush_cache_all(void);
@@ -37,7 +35,6 @@ extern void smp_flush_cache_range(struct
unsigned long end);
extern void smp_flush_cache_page(struct vm_area_struct *vma, unsigned long page);

-extern void smp_flush_page_to_ram(unsigned long page);
extern void smp_flush_sig_insns(struct mm_struct *mm, unsigned long insn_addr);

#endif /* CONFIG_SMP */
@@ -56,13 +53,11 @@ BTFIXUPDEF_CALL(void, flush_cache_page,

#define flush_icache_user_range(vma,pg,adr,len) do { } while (0)

-BTFIXUPDEF_CALL(void, __flush_page_to_ram, unsigned long)
BTFIXUPDEF_CALL(void, flush_sig_insns, struct mm_struct *, unsigned long)

-#define __flush_page_to_ram(addr) BTFIXUP_CALL(__flush_page_to_ram)(addr)
#define flush_sig_insns(mm,insn_addr) BTFIXUP_CALL(flush_sig_insns)(mm,insn_addr)

-extern void flush_page_to_ram(struct page *page);
+#error flush_page_to_ram is obsoleted, please convert to flush_dcache_page

#define flush_dcache_page(page) do { } while (0)

--- ./include/asm-sparc64/cacheflush.h.~1~ Mon Oct 28 05:56:41 2002
+++ ./include/asm-sparc64/cacheflush.h Mon Oct 28 06:01:41 2002
@@ -50,7 +50,4 @@ extern void smp_flush_cache_all(void);

extern void flush_dcache_page(struct page *page);

-/* This is unnecessary on the SpitFire since D-CACHE is write-through. */
-#define flush_page_to_ram(page) do { } while (0)
-
#endif /* _SPARC64_CACHEFLUSH_H */
--- ./include/asm-x86_64/cacheflush.h.~1~ Mon Oct 28 05:56:58 2002
+++ ./include/asm-x86_64/cacheflush.h Mon Oct 28 06:01:47 2002
@@ -9,7 +9,6 @@
#define flush_cache_mm(mm) do { } while (0)
#define flush_cache_range(vma, start, end) do { } while (0)
#define flush_cache_page(vma, vmaddr) do { } while (0)
-#define flush_page_to_ram(page) do { } while (0)
#define flush_dcache_page(page) do { } while (0)
#define flush_icache_range(start, end) do { } while (0)
#define flush_icache_page(vma,pg) do { } while (0)
--- ./include/linux/highmem.h.~1~ Mon Oct 28 05:56:41 2002
+++ ./include/linux/highmem.h Mon Oct 28 06:01:55 2002
@@ -58,7 +58,6 @@ static inline void memclear_highpage_flu
kaddr = kmap_atomic(page, KM_USER0);
memset((char *)kaddr + offset, 0, size);
flush_dcache_page(page);
- flush_page_to_ram(page);
kunmap_atomic(kaddr, KM_USER0);
}

--- ./kernel/ptrace.c.~1~ Mon Oct 28 05:56:41 2002
+++ ./kernel/ptrace.c Mon Oct 28 06:02:07 2002
@@ -181,11 +181,9 @@ int access_process_vm(struct task_struct
maddr = kmap(page);
if (write) {
memcpy(maddr + offset, buf, bytes);
- flush_page_to_ram(page);
flush_icache_user_range(vma, page, addr, bytes);
} else {
memcpy(buf, maddr + offset, bytes);
- flush_page_to_ram(page);
}
kunmap(page);
page_cache_release(page);
--- ./kernel/ptrace.c.~1~ Mon Oct 28 05:56:41 2002
+++ ./kernel/ptrace.c Mon Oct 28 06:02:07 2002
@@ -181,11 +181,9 @@ int access_process_vm(struct task_struct
maddr = kmap(page);
if (write) {
memcpy(maddr + offset, buf, bytes);
- flush_page_to_ram(page);
flush_icache_user_range(vma, page, addr, bytes);
} else {
memcpy(buf, maddr + offset, bytes);
- flush_page_to_ram(page);
}
kunmap(page);
page_cache_release(page);
--- ./mm/filemap.c.~1~ Mon Oct 28 05:56:41 2002
+++ ./mm/filemap.c Mon Oct 28 06:02:13 2002
@@ -1077,7 +1077,6 @@ success:
* and possibly copy it over to another page..
*/
mark_page_accessed(page);
- flush_page_to_ram(page);
return page;

no_cached_page:
--- ./mm/memory.c.~1~ Mon Oct 28 05:56:41 2002
+++ ./mm/memory.c Mon Oct 28 06:02:22 2002
@@ -760,7 +760,6 @@ static inline void break_cow(struct vm_a
pte_t *page_table)
{
invalidate_vcache(address, vma->vm_mm, new_page);
- flush_page_to_ram(new_page);
flush_cache_page(vma, address);
establish_pte(vma, address, page_table, pte_mkwrite(pte_mkdirty(mk_pte(new_page, vma->vm_page_prot))));
}
@@ -1032,7 +1031,6 @@ static int do_swap_page(struct mm_struct
pte = pte_mkdirty(pte_mkwrite(pte));
unlock_page(page);

- flush_page_to_ram(page);
flush_icache_page(vma, page);
set_pte(page_table, pte);
page_add_rmap(page, page_table);
@@ -1078,7 +1076,6 @@ static int do_anonymous_page(struct mm_s
return VM_FAULT_MINOR;
}
mm->rss++;
- flush_page_to_ram(page);
entry = pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
lru_cache_add(page);
mark_page_accessed(page);
@@ -1159,7 +1156,6 @@ static int do_no_page(struct mm_struct *
/* Only go through if we didn't race with anybody else... */
if (pte_none(*page_table)) {
++mm->rss;
- flush_page_to_ram(new_page);
flush_icache_page(vma, new_page);
entry = mk_pte(new_page, vma->vm_page_prot);
if (write_access)
--- ./mm/shmem.c.~1~ Mon Oct 28 05:56:41 2002
+++ ./mm/shmem.c Mon Oct 28 06:02:27 2002
@@ -904,7 +904,6 @@ struct page *shmem_nopage(struct vm_area
return (error == -ENOMEM)? NOPAGE_OOM: NOPAGE_SIGBUS;

unlock_page(page);
- flush_page_to_ram(page);
return page;
}

--- ./mm/swapfile.c.~1~ Mon Oct 28 05:56:42 2002
+++ ./mm/swapfile.c Mon Oct 28 06:02:32 2002
@@ -615,7 +615,6 @@ static int try_to_unuse(unsigned int typ
shmem = 0;
swcount = *swap_map;
if (swcount > 1) {
- flush_page_to_ram(page);
if (start_mm == &init_mm)
shmem = shmem_unuse(entry, page);
else

2002-10-28 14:26:10

by Matthew Wilcox

[permalink] [raw]
Subject: Re: [PATCH] shmem missing cache flush

On Mon, Oct 28, 2002 at 06:10:59AM -0800, David S. Miller wrote:
> Here goes. I contacted Anton and Paulus about flush_icache_page as
> that is on the hitlist next and ppc/ppc64 is the only well maintained
> port using that.

s/well maintained port/port that linus takes patches from regularly/

What do you want to do about flush_icache_page? You want to change it
to flush_dcache_page at eviction time, and then we can purge that page
from our icache in update_mmu_cache?

> --- ./include/asm-parisc/pgalloc.h.~1~ Mon Oct 28 05:56:41 2002
> +++ ./include/asm-parisc/pgalloc.h Mon Oct 28 06:00:13 2002
> @@ -72,7 +72,7 @@ flush_kernel_dcache_range(unsigned long
> asm volatile("syncdma" : : );
> }
>
> -extern void __flush_page_to_ram(unsigned long address);
> +#error flush_page_to_ram is obsoleted, please convert to flush_dcache_page
>
> #define flush_cache_all() flush_all_caches()
> #define flush_cache_mm(foo) flush_all_caches()
> @@ -99,9 +99,6 @@ extern inline void flush_cache_mm(struct
> __flush_dcache_range(vmaddr, PAGE_SIZE); \
> __flush_icache_range(vmaddr, PAGE_SIZE); \
> } while(0)
> -
> -#define flush_page_to_ram(page) \
> - __flush_page_to_ram((unsigned long)page_address(page))
>
> #define flush_icache_range(start, end) \
> __flush_icache_range(start, end - start)

You may as well drop this hunk from the diff; our current tree doesn't
even have these functions; just:

static inline void
flush_page_to_ram(struct page *page)
{
}

in asm/cacheflush.h

--
Revolutions do not require corporate support.

2002-10-28 14:29:53

by David Miller

[permalink] [raw]
Subject: Re: [PATCH] shmem missing cache flush

From: Hugh Dickins <[email protected]>
Date: Mon, 28 Oct 2002 14:35:15 +0000 (GMT)

I like your patch, but what has changed? Are those platforms which
were using flush_page_to_ram() now committed to its elimination?
Or have they already replaced it (not seen in your patch)?

No they have to fix their port to use the supported interface,
simply. That's why I added the "#error " lines telling the person
compiling on such a platform what needs to happen.


2002-10-28 14:29:14

by David Miller

[permalink] [raw]
Subject: Re: [PATCH] shmem missing cache flush

From: Matthew Wilcox <[email protected]>
Date: Mon, 28 Oct 2002 14:32:26 +0000

s/well maintained port/port that linus takes patches from regularly/

If you can't get purely arch/* include/asm-* patches to him,
that isn't my problem.

Yes, you might have to retransmit that patch 20/30 times over the
course of a few days depending upon how busy Linus is, just get over
it. :-)

What do you want to do about flush_icache_page? You want to change it
to flush_dcache_page at eviction time, and then we can purge that page
from our icache in update_mmu_cache?

That's the idea. The other idea is "well these particular call spots
really are special, so let's document flush_icache_page properly".

You may as well drop this hunk from the diff; our current tree doesn't
even have these functions; just:

static inline void
flush_page_to_ram(struct page *page)
{
}

I gave Alan a patch that applies to 2.5.44 as-is, that is the most
useful form of the patch.

If you code is different now, you or Alan can deal with the conflict
once it does arrise and your "other code" is in 2.5.x. For now it
isn't so it doesn't make any sense for me to patch against something
that isn't there :-)

2002-10-28 14:28:15

by Hugh Dickins

[permalink] [raw]
Subject: Re: [PATCH] shmem missing cache flush

> On Wed, 16 Oct 2002, David S. Miller wrote:
> From: Hugh Dickins <[email protected]>
> Date: Thu, 17 Oct 2002 00:57:30 +0100 (BST)
>
> I would be much happier about adding it, if you could tell me that
> I can then remove the flush_page_to_ram(page) from shmem_nopage?
>
> No we still have to support platforms using flush_page_to_ram()
>
> I didn't get a chance to deprecate this in 2.5.x, I wish I had.

On Mon, 28 Oct 2002, David S. Miller wrote:
> From: Alan Cox <[email protected]>
> Date: 21 Oct 2002 17:12:22 +0100
>
> Send me the diffs Im happy to give them a spin.
>
> Here goes. I contacted Anton and Paulus about flush_icache_page as
> that is on the hitlist next and ppc/ppc64 is the only well maintained
> port using that.

I like your patch, but what has changed? Are those platforms which
were using flush_page_to_ram() now committed to its elimination?
Or have they already replaced it (not seen in your patch)?

Hugh

2002-10-28 16:30:30

by Matthew Wilcox

[permalink] [raw]
Subject: Re: [PATCH] shmem missing cache flush

On Mon, Oct 28, 2002 at 06:26:08AM -0800, David S. Miller wrote:
> If you can't get purely arch/* include/asm-* patches to him,
> that isn't my problem.
>
> Yes, you might have to retransmit that patch 20/30 times over the
> course of a few days depending upon how busy Linus is, just get over
> it. :-)

I've been more concerned with getting core changes we need to him than
updating arch/parisc and include/asm-parisc. Maybe I should have been
more pushy.

> What do you want to do about flush_icache_page? You want to change it
> to flush_dcache_page at eviction time, and then we can purge that page
> from our icache in update_mmu_cache?
>
> That's the idea. The other idea is "well these particular call spots
> really are special, so let's document flush_icache_page properly".

What data do you need to make that decision? AFAICT (I'm not really
a PA CPU guru..) it's exactly the same amount of code, no matter which
way we do it.

While we're on the subject of cache flushing... these make no sense:

fs/binfmt_aout.c:357: flush_icache_range(text_addr, text_addr+ex.a_text+ex.a_data);
fs/binfmt_aout.c:381: flush_icache_range((unsigned long) N_TXTADDR(ex),
fs/binfmt_aout.c:479: flush_icache_range((unsigned long) start_addr,
fs/binfmt_elf.c:422: flush_icache_range((unsigned long)addr,

the kernel doesn't execute the code ranges here, userspace does. Which
means that the only place in the entire kernel which does need to call
flush_icache_range() is kernel/module.c, and that could all be done in
module_arch_init(). So I think we don't need flush_icache_range() at all.

--
Revolutions do not require corporate support.

2002-10-28 16:43:32

by Alan

[permalink] [raw]
Subject: Re: [PATCH] shmem missing cache flush

On Mon, 2002-10-28 at 16:36, Matthew Wilcox wrote:
> fs/binfmt_aout.c:357: flush_icache_range(text_addr, text_addr+ex.a_text+ex.a_data);
> fs/binfmt_aout.c:381: flush_icache_range((unsigned long) N_TXTADDR(ex),
> fs/binfmt_aout.c:479: flush_icache_range((unsigned long) start_addr,
> fs/binfmt_elf.c:422: flush_icache_range((unsigned long)addr,
>
> the kernel doesn't execute the code ranges here, userspace does. Which
> means that the only place in the entire kernel which does need to call

Suppose those addresses are already in the userspace icache from a
different exec ?

2002-10-28 16:46:39

by Matthew Wilcox

[permalink] [raw]
Subject: Re: [PATCH] shmem missing cache flush

On Mon, Oct 28, 2002 at 05:08:17PM +0000, Alan Cox wrote:
> Suppose those addresses are already in the userspace icache from a
> different exec ?

Documentation/cachetlb.txt:

void flush_icache_range(unsigned long start, unsigned long end)
When the kernel stores into addresses that it will execute
out of (eg when loading modules), this function is called.

If the icache does not snoop stores then this routine will need
to flush it.

void flush_icache_user_range(struct vm_area_struct *vma,
struct page *page, unsigned long addr, int len)
This is called when the kernel stores into addresses that are
part of the address space of a user process (which may be some
other process than the current process). The addr argument
gives the virtual address in that process's address space,
page is the page which is being modified, and len indicates
how many bytes have been modified. The modified region must
not cross a page boundary. Currently this is only called from
kernel/ptrace.c.

so either they're using the wrong function or these calls aren't needed
for some other reason (eg, the update_mmu_cache() thing davem suggested
earlier).

--
Revolutions do not require corporate support.

2002-10-28 16:44:33

by Manfred Spraul

[permalink] [raw]
Subject: Re: [PATCH] shmem missing cache flush

Is it permitted to call flush_dcache_page() on pages that are not in the
page cache?
The documentation is ambiguous, it only mentions how archs can handle
dcache aliases for page cache users.

What about the user space accesses that kmap user space pages directly,
without copy_*_user?

For example:
- ptrace
- disk transfers that end up calling __bio_kmap() - RAID-5, ide error
handling.
Could be from irq context!
- hole handling for O_DIRECT file access.

In all 3 cases, the target could be outside of the page cache.

--
Manfred

2002-10-28 17:00:15

by Matthew Wilcox

[permalink] [raw]
Subject: Re: [PATCH] shmem missing cache flush

On Mon, Oct 28, 2002 at 08:55:36AM -0800, David S. Miller wrote:
> Need to go into the revision history, discover who added these
> calls, and ask them why they were added.

They're in 2.2.20, if it helps...

--
Revolutions do not require corporate support.

2002-10-28 16:58:51

by David Miller

[permalink] [raw]
Subject: Re: [PATCH] shmem missing cache flush

From: Matthew Wilcox <[email protected]>
Date: Mon, 28 Oct 2002 16:36:49 +0000

While we're on the subject of cache flushing... these make no sense:

fs/binfmt_aout.c:357: flush_icache_range(text_addr, text_addr+ex.a_text+ex.a_data);
fs/binfmt_aout.c:381: flush_icache_range((unsigned long) N_TXTADDR(ex),
fs/binfmt_aout.c:479: flush_icache_range((unsigned long) start_addr,
fs/binfmt_elf.c:422: flush_icache_range((unsigned long)addr,

the kernel doesn't execute the code ranges here, userspace does. Which
means that the only place in the entire kernel which does need to call
flush_icache_range() is kernel/module.c, and that could all be done in
module_arch_init(). So I think we don't need flush_icache_range() at all.

Need to go into the revision history, discover who added these
calls, and ask them why they were added.

2002-10-28 17:01:58

by David Miller

[permalink] [raw]
Subject: Re: [PATCH] shmem missing cache flush

From: Matthew Wilcox <[email protected]>
Date: Mon, 28 Oct 2002 17:06:33 +0000

On Mon, Oct 28, 2002 at 08:55:36AM -0800, David S. Miller wrote:
> Need to go into the revision history, discover who added these
> calls, and ask them why they were added.

They're in 2.2.20, if it helps...

That's not so useful, it's the who and why that matters. :-)

2002-10-29 21:46:09

by Matthew Wilcox

[permalink] [raw]
Subject: Re: [PATCH] shmem missing cache flush

On Mon, Oct 28, 2002 at 08:58:51AM -0800, David S. Miller wrote:
> From: Matthew Wilcox <[email protected]>
> Date: Mon, 28 Oct 2002 17:06:33 +0000
>
> On Mon, Oct 28, 2002 at 08:55:36AM -0800, David S. Miller wrote:
> > Need to go into the revision history, discover who added these
> > calls, and ask them why they were added.
>
> They're in 2.2.20, if it helps...
>
> That's not so useful, it's the who and why that matters. :-)

Well, that's kind of hard... which revision history? They were
added at some point during 2.1, before anyone but sparc64 supported
flush_dcache_page, and certainly long before cachetlb.txt was written.
Arguably, cachetlb.txt is the buggy one since it coopted this interface
without reference to the current users.

PA-RISC doesn't use a.out in any way, shape or form, so it doesn't
matter to me, but m68k might like it fixed, i guess. Why the calls are
there seems fairly straightforward -- we're effectively doing a read()
of the text segment into the process' address space, and we're about to
execute it.

So flush_icache_user_range() seems like the right thing to do there.
Except that cachetlb says it can't cross a page boundary. Maybe the
right thing to do is to change the definition of flush_icache_range in
cachetlb to indicate that the addresses are user, not kernel, addresses;
remove the flush_icache_range() in kernel/module.c and put a #error into
every arch's module_arch_init() warning them they may need to flush the
range mod to mod->size.

--
Revolutions do not require corporate support.