Re: vm changes from linux-2.6.14 to linux-2.6.15

Mark Fortescue
2007-05-01T23:08:31Z

[-- Attachment #1: Type: TEXT/PLAIN, Size: 794 bytes --]

On Wed, 2 May 2007, Benjamin Herrenschmidt wrote:

>
>> I have attached a patch (so pine does not mangle it) for linux-2.6.20.9.
>> Is this what you had in mind?
>>
>> For linux-2.6.21, more work will be needed as it has more code calling
>> ptep_set_access_flags.
>
> I'm not 100% sure we need the 'update' argument... we can remove the
> whole old_entry, pte_same, etc... and just have pte_set_access_flags()
> read the old PTE and decide wether something needs to be changed or not.
>
> Ben.
>
>

The attached patch works on sun4c (with my simple ADA compile test) but
the change in functionality may break things other platforms.

The advantage of the previous patch is that the functionality is only
changed for sparc sun4c so less testing would be required.

Regards
Mark Fortescue.

[-- Attachment #2: Type: TEXT/PLAIN, Size: 10932 bytes --]

diff -ruNpd linux-2.6.20.9/include/asm-generic/pgtable.h linux-test/include/asm-generic/pgtable.h
--- linux-2.6.20.9/include/asm-generic/pgtable.h 2007-05-01 12:57:56.000000000 +0100
+++ linux-test/include/asm-generic/pgtable.h 2007-05-01 23:13:23.000000000 +0100
@@ -30,10 +30,17 @@ do { \
* to optimize this.
*/
#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
-do { \
- set_pte_at((__vma)->vm_mm, (__address), __ptep, __entry); \
- flush_tlb_page(__vma, __address); \
-} while (0)
+({ \
+ int __update = !pte_same(*(__ptep), __entry); \
+ \
+ if (__update) { \
+ set_pte_at((__vma)->vm_mm, (__address), __ptep, __entry); \
+ flush_tlb_page(__vma, __address); \
+ } else if (__dirty) { \
+ flush_tlb_page(__vma, __address); \
+ } \
+ __update; \
+})
#endif

#ifndef __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
diff -ruNpd linux-2.6.20.9/include/asm-i386/pgtable.h linux-test/include/asm-i386/pgtable.h
--- linux-2.6.20.9/include/asm-i386/pgtable.h 2007-05-01 12:57:56.000000000 +0100
+++ linux-test/include/asm-i386/pgtable.h 2007-05-01 23:18:50.000000000 +0100
@@ -273,14 +273,19 @@ static inline pte_t pte_mkhuge(pte_t pte
* bit at the same time.
*/
#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
-#define ptep_set_access_flags(vma, address, ptep, entry, dirty) \
-do { \
- if (dirty) { \
- (ptep)->pte_low = (entry).pte_low; \
- pte_update_defer((vma)->vm_mm, (address), (ptep)); \
- flush_tlb_page(vma, address); \
- } \
-} while (0)
+#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
+({ \
+ int __update = !pte_same(*(__ptep), __entry); \
+ \
+ if (__dirty) { \
+ if (__update) { \
+ (__ptep)->pte_low = (__entry).pte_low; \
+ pte_update_defer((__vma)->vm_mm, (__address), (__ptep)); \
+ } \
+ flush_tlb_page(__vma, __address); \
+ } \
+ __update; \
+})

/*
* We don't actually have these, but we want to advertise them so that
diff -ruNpd linux-2.6.20.9/include/asm-ia64/pgtable.h linux-test/include/asm-ia64/pgtable.h
--- linux-2.6.20.9/include/asm-ia64/pgtable.h 2007-04-30 19:04:59.000000000 +0100
+++ linux-test/include/asm-ia64/pgtable.h 2007-05-01 23:16:47.000000000 +0100
@@ -537,16 +537,29 @@ extern void lazy_mmu_prot_update (pte_t
* daccess_bit in ivt.S).
*/
#ifdef CONFIG_SMP
-# define ptep_set_access_flags(__vma, __addr, __ptep, __entry, __safely_writable) \
-do { \
- if (__safely_writable) { \
- set_pte(__ptep, __entry); \
- flush_tlb_page(__vma, __addr); \
- } \
-} while (0)
+# define ptep_set_access_flags(__vma, __addr, __ptep, __entry, __dirty) \
+({ \
+ int __update = !pte_same(*(__ptep), __entry); \
+ \
+ if (__dirty) { \
+ if (__update) \
+ set_pte(__ptep, __entry); \
+ flush_tlb_page(__vma, __addr); \
+ } \
+ __update; \
+})
#else
-# define ptep_set_access_flags(__vma, __addr, __ptep, __entry, __safely_writable) \
- ptep_establish(__vma, __addr, __ptep, __entry)
+# define ptep_set_access_flags(__vma, __addr, __ptep, __entry, __dirty) \
+({ \
+ int __update = !pte_same(*(__ptep), __entry); \
+ \
+ if (__update) \
+ ptep_establish(__vma, __addr, __ptep, __entry); \
+ else if (__dirty) \
+ flush_tlb_page(__vma, __addr); \
+ } \
+ __update; \
+})
#endif

# ifdef CONFIG_VIRTUAL_MEM_MAP
diff -ruNpd linux-2.6.20.9/include/asm-powerpc/pgtable.h linux-test/include/asm-powerpc/pgtable.h
--- linux-2.6.20.9/include/asm-powerpc/pgtable.h 2007-05-01 12:57:56.000000000 +0100
+++ linux-test/include/asm-powerpc/pgtable.h 2007-05-01 23:21:18.000000000 +0100
@@ -438,10 +438,16 @@ static inline void __ptep_set_access_fla
:"cc");
}
#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
- do { \
+({ \
+ int __update = !pte_same(*(__ptep), __entry); \
+ \
+ if (__update) { \
__ptep_set_access_flags(__ptep, __entry, __dirty); \
- flush_tlb_page_nohash(__vma, __address); \
- } while(0)
+ flush_tlb_page_nohash(__vma, __address); \
+ } else if (__dirty) \
+ flush_tlb_page(__vma, __address); \
+ __update; \
+})

/*
* Macro to mark a page protection value as "uncacheable".
diff -ruNpd linux-2.6.20.9/include/asm-ppc/pgtable.h linux-test/include/asm-ppc/pgtable.h
--- linux-2.6.20.9/include/asm-ppc/pgtable.h 2007-04-30 19:05:00.000000000 +0100
+++ linux-test/include/asm-ppc/pgtable.h 2007-05-01 23:15:29.000000000 +0100
@@ -694,10 +694,16 @@ static inline void __ptep_set_access_fla
}

#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
- do { \
+({ \
+ int __update = !pte_same(*(__ptep), __entry); \
+ \
+ if (__update) { \
__ptep_set_access_flags(__ptep, __entry, __dirty); \
- flush_tlb_page_nohash(__vma, __address); \
- } while(0)
+ flush_tlb_page_nohash(__vma, __address); \
+ } else if (__dirty) \
+ flush_tlb_page(__vma, __address); \
+ __update; \
+})

/*
* Macro to mark a page protection value as "uncacheable".
diff -ruNpd linux-2.6.20.9/include/asm-s390/pgtable.h linux-test/include/asm-s390/pgtable.h
--- linux-2.6.20.9/include/asm-s390/pgtable.h 2007-05-01 12:57:56.000000000 +0100
+++ linux-test/include/asm-s390/pgtable.h 2007-05-01 23:19:58.000000000 +0100
@@ -628,8 +628,16 @@ ptep_establish(struct vm_area_struct *vm
set_pte(ptep, entry);
}

-#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
- ptep_establish(__vma, __address, __ptep, __entry)
+#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
+ ({ \
+ int __update = !pte_same(*(__ptep), __entry); \
+ \
+ if (__update) \
+ ptep_establish(__vma, __address, __ptep, __entry); \
+ else if (__dirty) \
+ flush_tlb_page(__vma, __address); \
+ __update; \
+ })

/*
* Test and clear dirty bit in storage key.
diff -ruNpd linux-2.6.20.9/include/asm-sparc/pgtable.h linux-test/include/asm-sparc/pgtable.h
--- linux-2.6.20.9/include/asm-sparc/pgtable.h 2007-04-30 19:05:01.000000000 +0100
+++ linux-test/include/asm-sparc/pgtable.h 2007-05-01 23:10:49.000000000 +0100
@@ -446,6 +446,27 @@ extern int io_remap_pfn_range(struct vm_
#define GET_IOSPACE(pfn) (pfn >> (BITS_PER_LONG - 4))
#define GET_PFN(pfn) (pfn & 0x0fffffffUL)

+#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
+#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
+({ \
+ int __update; \
+ \
+ if (sparc_cpu_model == sun4c) { \
+ set_pte_at((__vma)->vm_mm, (__address), __ptep, __entry); \
+ flush_tlb_page(__vma, __address); \
+ __update = 1; \
+ } else { \
+ __update = !pte_same(*(__ptep), __entry); \
+ if (__update) { \
+ set_pte_at((__vma)->vm_mm, (__address), __ptep, __entry); \
+ flush_tlb_page(__vma, __address); \
+ } else if (__dirty) { \
+ flush_tlb_page(__vma, __address); \
+ } \
+ } \
+ __update; \
+})
+
#include <asm-generic/pgtable.h>

#endif /* !(__ASSEMBLY__) */
diff -ruNpd linux-2.6.20.9/include/asm-x86_64/pgtable.h linux-test/include/asm-x86_64/pgtable.h
--- linux-2.6.20.9/include/asm-x86_64/pgtable.h 2007-05-01 12:57:57.000000000 +0100
+++ linux-test/include/asm-x86_64/pgtable.h 2007-05-01 23:13:53.000000000 +0100
@@ -397,12 +397,16 @@ static inline pte_t pte_modify(pte_t pte
* bit at the same time. */
#define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
#define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
- do { \
+ ({ \
+ int __update = !pte_same(*(__ptep), __entry); \
+ \
if (__dirty) { \
- set_pte(__ptep, __entry); \
+ if (__update) \
+ set_pte(__ptep, __entry); \
flush_tlb_page(__vma, __address); \
} \
- } while (0)
+ __update; \
+ })

/* Encode and de-code a swap entry */
#define __swp_type(x) (((x).val >> 1) & 0x3f)
diff -ruNpd linux-2.6.20.9/mm/hugetlb.c linux-test/mm/hugetlb.c
--- linux-2.6.20.9/mm/hugetlb.c 2007-05-01 13:01:10.000000000 +0100
+++ linux-test/mm/hugetlb.c 2007-05-01 23:02:08.000000000 +0100
@@ -313,9 +313,10 @@ static void set_huge_ptep_writable(struc
pte_t entry;

entry = pte_mkwrite(pte_mkdirty(*ptep));
- ptep_set_access_flags(vma, address, ptep, entry, 1);
- update_mmu_cache(vma, address, entry);
- lazy_mmu_prot_update(entry);
+ if (ptep_set_access_flags(vma, address, ptep, entry, 1)) {
+ update_mmu_cache(vma, address, entry);
+ lazy_mmu_prot_update(entry);
+ }
}

diff -ruNpd linux-2.6.20.9/mm/memory.c linux-test/mm/memory.c
--- linux-2.6.20.9/mm/memory.c 2007-05-01 12:57:57.000000000 +0100
+++ linux-test/mm/memory.c 2007-05-01 23:06:21.000000000 +0100
@@ -1553,9 +1553,11 @@ static int do_wp_page(struct mm_struct *
flush_cache_page(vma, address, pte_pfn(orig_pte));
entry = pte_mkyoung(orig_pte);
entry = maybe_mkwrite(pte_mkdirty(entry), vma);
- ptep_set_access_flags(vma, address, page_table, entry, 1);
- update_mmu_cache(vma, address, entry);
- lazy_mmu_prot_update(entry);
+ if (ptep_set_access_flags(vma, address,
+ page_table, entry, 1)) {
+ update_mmu_cache(vma, address, entry);
+ lazy_mmu_prot_update(entry);
+ }
ret |= VM_FAULT_WRITE;
goto unlock;
}
@@ -2387,10 +2389,9 @@ static inline int handle_pte_fault(struc
pte_t *pte, pmd_t *pmd, int write_access)
{
pte_t entry;
- pte_t old_entry;
spinlock_t *ptl;

- old_entry = entry = *pte;
+ entry = *pte;
if (!pte_present(entry)) {
if (pte_none(entry)) {
if (vma->vm_ops) {
@@ -2423,19 +2424,9 @@ static inline int handle_pte_fault(struc
entry = pte_mkdirty(entry);
}
entry = pte_mkyoung(entry);
- if (!pte_same(old_entry, entry)) {
- ptep_set_access_flags(vma, address, pte, entry, write_access);
+ if (ptep_set_access_flags(vma, address, pte, entry, write_access)) {
update_mmu_cache(vma, address, entry);
lazy_mmu_prot_update(entry);
- } else {
- /*
- * This is needed only for protection faults but the arch code
- * is not yet telling us if this is a protection fault or not.
- * This still avoids useless tlb flushes for .text page faults
- * with threads.
- */
- if (write_access)
- flush_tlb_page(vma, address);
}
unlock:
pte_unmap_unlock(pte, ptl);