MM: Make Page Tables Relocatable --relcoation code
Subsystems (13)
PATCH 2/2 MM: Make Page Tables Relocatable --relcoation code
-----
Forgot to mention in the last part, major changes from previous version are support for copying accessed/dirty bits and it at least compiles and should work with 2 and 3 level page tables as well as 4 level page tables.
arch/powerpc/mm/fault.c renamed from home/rossb/local/linux-2.6.25-rc9/arch/powerpc/mm/fault.c +2 -0
@@ -299,6 +299,8 @@ good_area:if (get_pteptr (mm, address, &ptep, &pmdp)) {spinlock_t *ptl =pte_lockptr (mm, pmdp);spin_lock (ptl); +delimbo_pte (&ptep, &ptl, &pmdp, mm, address); +if (pte_present (*ptep)) {struct page *page =pte_page (*ptep);
arch/powerpc/mm/hugetlbpage.c renamed from home/rossb/local/linux-2.6.25-rc9/arch/powerpc/mm/hugetlbpage.c +1 -0
@@ -73,6 +73,7 @@ static int __hugepte_alloc(struct mm_strreturn -ENOMEM ;spin_lock (&mm->page_table_lock); +delimbo_hpd (&hpdp, mm, address);if (!hugepd_none (*hpdp))kmem_cache_free (huge_pgtable_cache, new);else
arch/ppc/mm/fault.c renamed from home/rossb/local/linux-2.6.25-rc9/arch/ppc/mm/fault.c +1 -0
@@ -219,6 +219,7 @@ good_area:if (get_pteptr (mm, address, &ptep, &pmdp)) {spinlock_t *ptl =pte_lockptr (mm, pmdp);spin_lock (ptl); +delimbo_pte (&ptep, &ptl, &pmdp, mm, address);if (pte_present (*ptep)) {struct page *page =pte_page (*ptep);
arch/x86/mm/hugetlbpage.c renamed from home/rossb/local/linux-2.6.25-rc9/arch/x86/mm/hugetlbpage.c +1 -0
@@ -88,6 +88,7 @@ static void huge_pmd_share(struct mm_str goto out;spin_lock (&mm->page_table_lock); +delimbo_pud (&pud, mm, addr);if (pud_none (*pud))pud_populate (mm, pud, (pmd_t *)((unsigned long )spte &PAGE_MASK ));else
arch/x86/mm/pgtable_32.c renamed from home/rossb/local/linux-2.6.25-rc9/arch/x86/mm/pgtable_32.c +51 -22
98 lines not on this page · raw message
include/asm-generic/pgalloc.h renamed from home/rossb/local/linux-2.6.25-rc9/include/asm-generic/pgalloc.h +98 -0
98 lines not on this page · raw message
include/asm-generic/pgtable.h renamed from home/rossb/local/linux-2.6.25-rc9/include/asm-generic/pgtable.h +18 -0
@@ -4,6 +4,8 @@#ifndef __ASSEMBLY__#ifdef CONFIG_MMU +#include <linux/sched.h> +#ifndef __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS/* * Largely same as above, but only sets the access flags (dirty,
@@ -195,6 +197,22 @@ static inline int pmd_none_or_clear_bad( }return 0 ; } + + +/* Copy the bits that the cpu could have modified. */ +#ifndef __HAVE_ARCH_COPY_CPU_BITS_PTE +static inline void arch_copy_cpu_bits_pte (pte_t *old,pte_t *new) +{ +} +#endif + +/* Clear the bits that the cpu could have modified. */ +#ifndef __HAVE_ARCH_CLEAR_CPU_BITS_PTE +static inline void arch_clear_cpu_bits_pte (pte_t *old) +{ +} +#endif +#endif /* CONFIG_MMU */ /*
include/asm-x86/pgalloc_32.h renamed from home/rossb/local/linux-2.6.25-rc9/include/asm-x86/pgalloc_32.h +39 -2
62 lines not on this page · raw message
include/asm-x86/pgalloc_64.h renamed from home/rossb/local/linux-2.6.25-rc9/include/asm-x86/pgalloc_64.h +93 -41
178 lines not on this page · raw message
include/asm-x86/pgtable.h renamed from home/rossb/local/linux-2.6.25-rc9/include/asm-x86/pgtable.h +13 -0
@@ -364,6 +364,19 @@ static inline void ptep_set_wrprotect(st pte_update(mm, addr, ptep); } +#define __HAVE_ARCH_COPY_CPU_BITS_PTE +static inline void arch_copy_cpu_bits_pte (pte_t *old,pte_t *new) +{ +set_pte (new,__pte (pte_val (*new) | + (pte_val (*old) & (_PAGE_DIRTY | _PAGE_ACCESSED)))); +} + +#define __HAVE_ARCH_CLEAR_CPU_BITS_PTE +static inline void arch_clear_cpu_bits_pte (pte_t *old) +{ + *old =__pte (pte_val (*old) & ~(_PAGE_DIRTY | _PAGE_ACCESSED)); +} +#include <asm-generic/pgtable.h> #endif /* __ASSEMBLY__ */
include/linux/migrate.h renamed from home/rossb/local/linux-2.6.25-rc9/include/linux/migrate.h +4 -0
@@ -6,6 +6,10 @@#include <linux/pagemap.h> typedef struct page *new_page_t (struct page *,unsigned long private,int **); +typedef struct page *new_page_table_t (struct mm_struct *, +unsigned long addr, +unsigned long private, +int **,int page_table_level);#ifdef CONFIG_MIGRATION /* Check if a vma is migratable */
include/linux/mm.h renamed from home/rossb/local/linux-2.6.25-rc9/include/linux/mm.h +153 -0
165 lines not on this page · raw message
include/linux/mm_types.h renamed from home/rossb/local/linux-2.6.25-rc9/include/linux/mm_types.h +22 -2
@@ -10,6 +10,8 @@#include <linux/rbtree.h> #include <linux/rwsem.h> #include <linux/completion.h> +#include <linux/rcupdate.h> +#include <linux/workqueue.h> #include <asm/page.h> #include <asm/mmu.h>
@@ -43,6 +45,9 @@ struct page {* & limit reverse map searches. */ unsigned int inuse;/* SLUB: Nr of objects */ +int page_table_type;/* Used to keep track of the type of +* page table so we can clean it up. +*/ }; union { struct {
@@ -70,7 +75,12 @@ struct page {union {pgoff_t index;/* Our offset within mapping. */ void *freelist;/* SLUB: freelist req. slab lock */ +struct page *migrated_page;/* The page this page +* table has been migrated to +* or from. +*/ }; +struct list_head lru;/* Pageout list, eg. active_list * protected by zone->lru_lock ! */
@@ -173,7 +183,16 @@ struct mm_struct {atomic_t mm_count;/* How many references to "struct mm_struct" (users count as 1) */ int map_count;/* number of VMAs */ struct rw_semaphore mmap_sem; +unsigned long flags;/* Must use atomic bitops to access the bits */ +spinlock_t page_table_lock;/* Protects page tables and some counters */ +#ifdef CONFIG_RELOCATE_PAGE_TABLES +/* The number of page table relocations currently happening on +* this mm. Only updated/checked while holding the page_table_lock, +* so doesn't need to be an atomic_t. +*/ +int page_table_relocation_count; +#endif /* CONFIG_RELOCATE_PAGE_TABLES */ struct list_head mmlist;/* List of maybe swapped mm's. These are globally strung * together off init_mm.mmlist, and are protected
@@ -213,8 +232,6 @@ struct mm_struct {unsigned int token_priority;unsigned int last_interval; -unsigned long flags;/* Must use atomic bitops to access the bits */ -/* coredumping support */ int core_waiters;struct completion *core_startup_done, core_done;
@@ -225,6 +242,9 @@ struct mm_struct {#ifdef CONFIG_CGROUP_MEM_RES_CTLR struct mem_cgroup *mem_cgroup;#endif +#ifdef CONFIG_RELOCATE_PAGE_TABLES +struct mutex page_table_relocation_lock; +#endif };#endif /* _LINUX_MM_TYPES_H */
kernel/fork.c renamed from home/rossb/local/linux-2.6.25-rc9/kernel/fork.c +5 -0
@@ -360,6 +360,11 @@ static struct mm_struct * mm_init(struct mm->cached_hole_size = ~0UL ;mm_init_cgroup (mm, p); +#ifdef CONFIG_RELOCATE_PAGE_TABLES + mm->page_table_relocation_count =0 ; +mutex_init (&mm->page_table_relocation_lock); +#endif +if (likely (!mm_alloc_pgd (mm))) { mm->def_flags =0 ;return mm;
mm/Kconfig renamed from home/rossb/local/linux-2.6.25-rc9/mm/Kconfig +4 -0
@@ -143,6 +143,10 @@ config MEMORY_HOTREMOVE depends on MEMORY_HOTPLUG && ARCH_ENABLE_MEMORY_HOTREMOVE depends on MIGRATION +config RELOCATE_PAGE_TABLES + def_bool y + depends on X86 && MIGRATION + # Heavily threaded applications may benefit from splitting the mm-wide # page_table_lock, so that faults on different parts of the user address # space can be handled with less contention: split it at this NR_CPUS.
mm/hugetlb.c renamed from home/rossb/local/linux-2.6.25-rc9/mm/hugetlb.c +4 -0
@@ -762,6 +762,8 @@ int copy_hugetlb_page_range(struct mm_stspin_lock (&dst->page_table_lock);spin_lock (&src->page_table_lock); +delimbo_huge_pte (&src_pte, src, addr); +delimbo_huge_pte (&dst_pte, dst, addr);if (!pte_none (*src_pte)) {if (cow)ptep_set_wrprotect (src, addr, src_pte);
@@ -937,6 +939,7 @@ retry: }spin_lock (&mm->page_table_lock); +delimbo_huge_pte (&ptep, mm, address); size =i_size_read (mapping->host) >>HPAGE_SHIFT ;if (idx >= size) goto backout;
@@ -994,6 +997,7 @@ int hugetlb_fault(struct mm_struct *mm, ret =0 ;spin_lock (&mm->page_table_lock); +delimbo_huge_pte (&ptep, mm, address);/* Check for a racing update before calling hugetlb_cow */ if (likely (pte_same (entry, *ptep)))if (write_access && !pte_write (entry))
mm/memory.c renamed from home/rossb/local/linux-2.6.25-rc9/mm/memory.c +31 -3
@@ -312,6 +312,7 @@ int __pte_alloc(struct mm_struct *mm, pmreturn -ENOMEM ;spin_lock (&mm->page_table_lock); +delimbo_pmd (&pmd, mm, address);if (!pmd_present (*pmd)) {/* Has another populated it ? */ mm->nr_ptes++;pmd_populate (mm, pmd, new);
@@ -330,6 +331,7 @@ int __pte_alloc_kernel(pmd_t *pmd, unsigreturn -ENOMEM ;spin_lock (&init_mm.page_table_lock); +delimbo_pmd (&pmd, &init_mm, address);if (!pmd_present (*pmd)) {/* Has another populated it ? */ pmd_populate_kernel (&init_mm, pmd, new); new =NULL ;
@@ -513,6 +515,9 @@ again: src_pte =pte_offset_map_nested (src_pmd, addr); src_ptl =pte_lockptr (src_mm, src_pmd);spin_lock_nested (src_ptl,SINGLE_DEPTH_NESTING ); + +delimbo_pte_nested (&src_pte, &src_ptl, &src_pmd, src_mm, addr, +SINGLE_DEPTH_NESTING , dst_ptl);arch_enter_lazy_mmu_mode (); do {
@@ -1488,13 +1493,15 @@ EXPORT_SYMBOL_GPL(apply_to_page_range);* and do_anonymous_page and do_no_page can safely check later on). */ static inline int pte_unmap_same (struct mm_struct *mm,pmd_t *pmd, -pte_t *page_table,pte_t orig_pte) +pte_t *page_table,pte_t orig_pte, +unsigned long address) {int same =1 ;#if defined(CONFIG_SMP ) || defined(CONFIG_PREEMPT )if (sizeof (pte_t) >sizeof (unsigned long )) {spinlock_t *ptl =pte_lockptr (mm, pmd);spin_lock (ptl); +delimbo_pte (&page_table, &ptl, &pmd, mm, address); same =pte_same (*page_table, orig_pte);spin_unlock (ptl); }
@@ -2021,7 +2028,7 @@ static int do_swap_page(struct mm_structpte_t pte;int ret =0 ; -if (!pte_unmap_same (mm, pmd, page_table, orig_pte)) +if (!pte_unmap_same (mm, pmd, page_table, orig_pte, address)) goto out; entry =pte_to_swp_entry (orig_pte);
@@ -2100,6 +2107,10 @@ static int do_swap_page(struct mm_struct }/* No need to invalidate - it was non-present before */ +/* Unless of course the cpu might be looking at an old +copy of the pte. */ +maybe_reload_tlb_mm (mm); +update_mmu_cache (vma, address, pte); unlock:pte_unmap_unlock (page_table, ptl);
@@ -2151,6 +2162,10 @@ static int do_anonymous_page(struct mm_sset_pte_at (mm, address, page_table, entry);/* No need to invalidate - it was non-present before */ +/* Unless of course the cpu might be looking at an old +copy of the pte. */ +maybe_reload_tlb_mm (mm); +update_mmu_cache (vma, address, entry); unlock:pte_unmap_unlock (page_table, ptl);
@@ -2312,6 +2327,10 @@ static int __do_fault(struct mm_struct * }/* no need to invalidate: a not-present page won't be cached */ +/* Unless of course the cpu could be looking at an old page +table entry. */ +maybe_reload_tlb_mm (mm); +update_mmu_cache (vma, address, entry); }else {mem_cgroup_uncharge_page (page);
@@ -2418,7 +2437,7 @@ static int do_nonlinear_fault(struct mm_ (write_access ?FAULT_FLAG_WRITE :0 );pgoff_t pgoff; -if (!pte_unmap_same (mm, pmd, page_table, orig_pte)) +if (!pte_unmap_same (mm, pmd, page_table, orig_pte, address))return 0 ; if (unlikely(!(vma->vm_flags & VM_NONLINEAR) ||
@@ -2477,6 +2496,7 @@ static inline int handle_pte_fault(struc ptl =pte_lockptr (mm, pmd);spin_lock (ptl); +delimbo_pte (&pte, &ptl, &pmd, mm, address);if (unlikely (!pte_same (*pte, entry))) goto unlock;if (write_access) {
@@ -2498,6 +2518,12 @@ static inline int handle_pte_fault(strucif (write_access)flush_tlb_page (vma, address); } + +/* if the cpu could be looking at an old page table, we need to +flush out everything. */ +maybe_reload_tlb_mm (mm); + + unlock:pte_unmap_unlock (pte, ptl);return 0 ;
@@ -2547,6 +2573,7 @@ int __pud_alloc(struct mm_struct *mm, pgreturn -ENOMEM ;spin_lock (&mm->page_table_lock); +delimbo_pgd (&pgd, mm, address);if (pgd_present (*pgd))/* Another has populated it */ pud_free (mm, new);else
@@ -2568,6 +2595,7 @@ int __pmd_alloc(struct mm_struct *mm, pureturn -ENOMEM ;spin_lock (&mm->page_table_lock); +delimbo_pud (&pud, mm, address);#ifndef __ARCH_HAS_4LEVEL_HACKif (pud_present (*pud))/* Another has populated it */ pmd_free (mm, new);
mm/mempolicy.c renamed from home/rossb/local/linux-2.6.25-rc9/mm/mempolicy.c +26 -0
@@ -101,6 +101,12 @@static struct kmem_cache *policy_cache;static struct kmem_cache *sn_cache; +#ifdef CONFIG_RELOCATE_PAGE_TABLES +int migrate_page_tables_mm (struct mm_struct *mm,int source, +new_page_table_t get_new_page, +unsigned long private); +#endif +/* Highest zone. An specific allocation for a zone below that is not policied. */ enum zone_type policy_zone =0 ;
@@ -627,6 +633,20 @@ static struct page *new_node_page(structreturn alloc_pages_node (node,GFP_HIGHUSER_MOVABLE ,0 ); } +#ifdef CONFIG_RELOCATE_PAGE_TABLES +static struct page *new_node_page_page_tables (struct mm_struct *mm, +unsigned long addr, +unsigned long node, +int **x, +int level) +{ +struct page *p; + p =alloc_page_table_node (mm, addr, node, level); +return p; +} + +#endif /* CONFIG_RELOCATE_PAGE_TABLES */ +/* * Migrate pages from one node to a target node. * Returns error or the number of pages not migrated.
@@ -647,6 +667,12 @@ static int migrate_to_node(struct mm_strif (!list_empty (&pagelist)) err =migrate_pages (&pagelist, new_node_page, dest); +#ifdef CONFIG_RELOCATE_PAGE_TABLES +if (!err) + err =migrate_page_tables_mm (mm, source, + new_node_page_page_tables, dest); +#endif /* CONFIG_RELOCATE_PAGE_TABLES */ +return err; }
mm/migrate.c renamed from home/rossb/local/linux-2.6.25-rc9/mm/migrate.c +803 -1
830 lines not on this page · raw message
mm/mremap.c renamed from home/rossb/local/linux-2.6.25-rc9/mm/mremap.c +2 -0
@@ -98,6 +98,8 @@ static void move_ptes(struct vm_area_str new_ptl =pte_lockptr (mm, new_pmd);if (new_ptl != old_ptl)spin_lock_nested (new_ptl,SINGLE_DEPTH_NESTING ); +delimbo_pte_nested (&new_pte, &new_ptl, &new_pmd, mm, new_addr, +SINGLE_DEPTH_NESTING , old_ptl);arch_enter_lazy_mmu_mode (); for (; old_addr < old_end; old_pte++, old_addr += PAGE_SIZE,
mm/rmap.c renamed from home/rossb/local/linux-2.6.25-rc9/mm/rmap.c +1 -0
@@ -255,6 +255,7 @@ pte_t *page_check_address(struct page *p ptl =pte_lockptr (mm, pmd);spin_lock (ptl); +delimbo_pte (&pte, &ptl, &pmd, mm, address);if (pte_present (*pte) &&page_to_pfn (page) ==pte_pfn (*pte)) { *ptlp = ptl;return pte;
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>
Quoted 13 lines · Ross Biro
mm/migrate.c renamed from home/rossb/local/linux-2.6.25-rc9/mm/migrate.c +12
-0+void update_new_page_and_free (struct mm_struct *mm,struct page *old_page) +{ + +int type; + +/* Currently we only worry about cpu bits in ptes. */ +if (old_page->page_table_type ==PAGE_TABLE_PTE ) { +struct page *new_page = old_page->migrated_page; +spinlock_t *ptl; +pte_t *old; +pte_t *new; +int i;
mm/migrate.c int migrate_vmas(struct mm_struct *mm, c · line 1345
Quoted 10 lines
mm/migrate.c renamed from home/rossb/local/linux-2.6.25-rc9/mm/migrate.c +10
-0+#ifdef __pte_lockptr + ptl =__pte_lockptr (new_page); +#else + ptl = &mm->page_table_lock; +#endif +spin_lock (ptl); + old = (pte_t *)kmap_atomic (old_page,KM_PTE0 ); + new = (pte_t *)kmap_atomic (new_page,KM_PTE1 ); +for (i =0 ; i <PTRS_PER_PTE ; i++) +arch_copy_cpu_bits_pte (old, new);
old++, new++?
mm/migrate.c int migrate_vmas(struct mm_struct *mm, c · line 1358
Quoted 13 lines
mm/migrate.c renamed from home/rossb/local/linux-2.6.25-rc9/mm/migrate.c +13
-0+ +kunmap_atomic (new_page,KM_PTE1 ); +kunmap_atomic (old_page,KM_PTE0 ); + new_page->migrated_page =NULL ; +spin_unlock (ptl); + } + + old_page->migrated_page =NULL ; + type = old_page->page_table_type; +reset_page_mapcount (old_page); + +free_page_table_page (mm, old_page, type); +}
J
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to [email protected]. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"[email protected]"> [email protected] </a>