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
}
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;
}
/* 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. */
#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;
}
}
#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
#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):
#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 { \
#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 */
#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))
/*
#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 { \
#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) \
#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)
#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
#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
#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)
#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);
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
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)
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);