]> git.hungrycats.org Git - linux/commitdiff
[PATCH] flush_icache_user_range (v2.5.4)
authorPaul Mackerras <paulus@samba.org>
Wed, 13 Feb 2002 04:27:37 +0000 (20:27 -0800)
committerLinus Torvalds <torvalds@home.transmeta.com>
Wed, 13 Feb 2002 04:27:37 +0000 (20:27 -0800)
The patch below changes access_process_vm to use a new architecture
hook, flush_icache_user_range, instead of flush_icache_page, and adds
a definition of flush_icache_user_range which does the same thing as
flush_icache_page for all architectures except PPC.  (The PPC update
that is in Linus' BK tree already includes a suitable definition of
flush_icache_user_range.)

The reason for doing this is that when flush_icache_page is called
from do_no_page or do_swap_page, I want to be able to do the flush
conditionally, based on the state of the page.  In contrast,
access_process_vm needs to do the flush unconditionally since it has
just modified the page.  In the access_process_vm case it is useful to
have the information about the user address and length that have been
modified since then we can just flush the affected cache lines rather
than the whole page.

This patch should make it easy to improve performance on alpha, since
there (as I understand it) the icache flush is not needed at all in
do_no_page or do_swap_page, but is needed in access_process_vm.  All
that is needed is to make flush_icache_page a noop on alpha.  The
patch below doesn't do this, I'll let the alpha maintainers push that
change if they want.

15 files changed:
Documentation/cachetlb.txt
arch/alpha/kernel/smp.c
include/asm-alpha/pgalloc.h
include/asm-cris/pgtable.h
include/asm-i386/pgtable.h
include/asm-m68k/pgalloc.h
include/asm-mips/pgtable.h
include/asm-mips64/pgtable.h
include/asm-parisc/pgalloc.h
include/asm-s390/pgtable.h
include/asm-s390x/pgtable.h
include/asm-sh/pgtable.h
include/asm-sparc/pgtable.h
include/asm-sparc64/pgtable.h
kernel/ptrace.c

index 8852c54492f47d610e8522f0281ee268624fb300..6d56a75be9fc1ab369b19424c0fdbe674d14c860 100644 (file)
@@ -341,6 +341,17 @@ Here is the new interface:
        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.
+
   void flush_icache_page(struct vm_area_struct *vma, struct page *page)
        All the functionality of flush_icache_page can be implemented in
        flush_dcache_page and update_mmu_cache. In 2.5 the hope is to
index 7f0dc6bc8ec7f67781734be464fb6c7d7b5c601c..bf927dc702bfa454d97357b04e5ad855d7403c2b 100644 (file)
@@ -1061,7 +1061,8 @@ ipi_flush_icache_page(void *x)
 }
 
 void
-flush_icache_page(struct vm_area_struct *vma, struct page *page)
+flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
+                       unsigned long addr, int len)
 {
        struct mm_struct *mm = vma->vm_mm;
 
index f00acfd42a7308098f607d9453a1a50ad1882ff5..3463968dc087c72522b9dfd2fd15a44719f2690e 100644 (file)
@@ -70,8 +70,7 @@ flush_tlb_other(struct mm_struct *mm)
 }
 
 /* We need to flush the userspace icache after setting breakpoints in
-   ptrace.  I don't think it's needed in do_swap_page, or do_no_page,
-   but I don't know how to get rid of it either.
+   ptrace.
 
    Instead of indiscriminately using imb, take advantage of the fact
    that icache entries are tagged with the ASN and load a new mm context.  */
@@ -79,7 +78,8 @@ flush_tlb_other(struct mm_struct *mm)
 
 #ifndef CONFIG_SMP
 static inline void
-flush_icache_page(struct vm_area_struct *vma, struct page *page)
+flush_icache_user_range(struct vm_area_struct *vma, struct page *page,
+                       unsigned long addr, int len)
 {
        if (vma->vm_flags & VM_EXEC) {
                struct mm_struct *mm = vma->vm_mm;
@@ -90,9 +90,13 @@ flush_icache_page(struct vm_area_struct *vma, struct page *page)
        }
 }
 #else
-extern void flush_icache_page(struct vm_area_struct *vma, struct page *page);
+extern void flush_icache_user_range(struct vm_area_struct *vma,
+               struct page *page, unsigned long addr, int len);
 #endif
 
+/* this is used only in do_no_page and do_swap_page */
+#define flush_icache_page(vma, page)   flush_icache_user_range((vma), (page), 0, 0)
+
 /*
  * Flush just one page in the current TLB set.
  * We need to be very careful about the icache here, there
index e533400551c03c30558f32af2d9dc691497bdcc8..87c504e0ff467d281e8af65b3970bac1d9406cb9 100644 (file)
@@ -125,6 +125,7 @@ extern void paging_init(void);
 #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)
+#define flush_icache_user_range(vma,pg,adr,len) do { } while (0)
 
 /*
  * TLB flushing (implemented in arch/cris/mm/tlb.c):
index c22d56a177133b35b748a46911c885d1b0fb631d..4dc49f822b204d7c97b0928fbf5289eff57d8e20 100644 (file)
@@ -33,6 +33,7 @@ extern void paging_init(void);
 #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)
+#define flush_icache_user_range(vma,pg,adr,len)        do { } while (0)
 
 #define __flush_tlb()                                                  \
        do {                                                            \
index f67a54a355ce56877de35819a53b1cf5668dae6e..ee25f7e533972077ac17dbe2d82ec90f4f7398a7 100644 (file)
@@ -127,6 +127,7 @@ extern inline void __flush_page_to_ram(unsigned long address)
 
 #define flush_dcache_page(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)
 
 /* Push n pages at kernel virtual address and clear the icache */
 /* RZ: use cpush %bc instead of cpush %dc, cinv %ic */
index afc0148e9b830303a3b5bb1308cd0ddf2262e38e..e24c6bde77f5ef015f80e4be46488f32ef5d8ea8 100644 (file)
@@ -51,6 +51,8 @@ extern void (*_flush_icache_page)(struct vm_area_struct *vma,
 
 #define flush_icache_range(start, end) _flush_icache_range(start,end)
 #define flush_icache_page(vma, page)   _flush_icache_page(vma, page)
+#define flush_icache_user_range(vma, page, addr, len)  \
+                                       _flush_icache_page((vma), (page))
 
 
 /*
index 6c35e0d93c81b7b2327d495444a2348a24c02a14..9b041abb4083df59642af488f77fa9b2df031ae7 100644 (file)
@@ -43,6 +43,8 @@ extern void (*_flush_page_to_ram)(struct page * 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)  \
+                                       flush_icache_page((vma), (page))
 
 #define flush_icache_page(vma, page)                                   \
 do {                                                                   \
@@ -66,6 +68,8 @@ extern void andes_flush_icache_page(unsigned long);
 #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))
 #define flush_icache_page(vma, page)                                   \
 do {                                                                   \
        if ((vma)->vm_flags & VM_EXEC)                                  \
index d458ec27b74c764c32ef22f537d69304e0914afb..b29fa8aef9be4ed5f6db6c37e0739f7def0e8639 100644 (file)
@@ -106,6 +106,9 @@ extern inline void flush_cache_mm(struct mm_struct *mm) {
 #define flush_icache_range(start, end) \
         __flush_icache_range(start, end - start)
 
+#define flush_icache_user_range(vma, page, addr, len) \
+       flush_icache_page((vma), (page))
+
 #define flush_icache_page(vma, page) \
        __flush_icache_range(page_address(page), PAGE_SIZE)
 
index ce43b50b7471ebfd892baedbf60de2147f2c7934..5e22205addb8363d267e406acbdccabb10ee342b 100644 (file)
@@ -42,6 +42,7 @@ extern void paging_init(void);
 #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)
+#define flush_icache_user_range(vma,pg,adr,len)        do { } while (0)
 
 /*
  * The S390 doesn't have any external MMU info: the kernel page
index 25b30c8607cce5c06c1f744f4653387cad556514..2dcb8b438f836fb5497002ad9190493c5dbfa7d2 100644 (file)
@@ -38,6 +38,7 @@ extern void paging_init(void);
 #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)
+#define flush_icache_user_range(vma,pg,adr,len)        do { } while (0)
 
 /*
  * The S390 doesn't have any external MMU info: the kernel page
index 38dee49f4c9716cd59fb76997d907c06f5c8b476..ce68ec2d2bd1e0dfa21a2f5a86867e67995720d5 100644 (file)
@@ -41,6 +41,7 @@ extern void paging_init(void);
 #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)
+#define flush_icache_user_range(vma,pg,adr,len)        do { } while (0)
 #define flush_cache_sigtramp(vaddr)            do { } while (0)
 
 #define p3_cache_init()                                do { } while (0)
@@ -64,6 +65,7 @@ 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)
 
 /* Initialization of P3 area for copy_user_page */
 extern void p3_cache_init(void);
index 4ed3aed45357710de8226366b0d030a04b2e703e..b73aaa20847e00d5fa5ba91647b8318073157d46 100644 (file)
@@ -348,6 +348,7 @@ BTFIXUPDEF_CALL(pte_t *, pte_offset, pmd_t *, unsigned long)
 extern unsigned int pg_iobits;
 
 #define flush_icache_page(vma, pg)      do { } while(0)
+#define flush_icache_user_range(vma,pg,adr,len)        do { } while (0)
 
 /* Certain architectures need to do special things when pte's
  * within a page table are directly modified.  Thus, the following
index 0df00266817b42fda97b7105121a0791b0ad5bcc..ebf8ac1060bc4e6d0c76e5c3d8b4c6e90347932b 100644 (file)
@@ -277,6 +277,7 @@ extern pgd_t swapper_pg_dir[1];
 extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t);
 
 #define flush_icache_page(vma, pg)     do { } while(0)
+#define flush_icache_user_range(vma,pg,adr,len)        do { } while (0)
 
 /* Make a non-present pseudo-TTE. */
 extern inline pte_t mk_pte_io(unsigned long page, pgprot_t prot, int space)
index 79af05d4f3535c0b2f3138dce27bf1bebaed7ab0..a5db3a5c57935a6eff1c43cf1e24a5470c04a9f5 100644 (file)
@@ -151,7 +151,7 @@ int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, in
                if (write) {
                        memcpy(maddr + offset, buf, bytes);
                        flush_page_to_ram(page);
-                       flush_icache_page(vma, page);
+                       flush_icache_user_range(vma, page, addr, bytes);
                } else {
                        memcpy(buf, maddr + offset, bytes);
                        flush_page_to_ram(page);