MM: Make Page Tables Relcatable -- relocation code
Subsystems (13)
PATCH 2/2 MM: Make Page Tables Relcatable -- relocation code
-----
arch/powerpc/mm/fault.c renamed from home/rossb/local/linux-2.6.25-rc8/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-rc8/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-rc8/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-rc8/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
include/asm-generic/pgalloc.h renamed from home/rossb/local/linux-2.6.25-rc8/include/asm-generic/pgalloc.h +37 -0
@@ -0,0 +1,37 @@ +#ifndef _ASM_GENERIC_PGALLOC_H +#define _ASM_GENERIC_PGALLOC_H + + + +/* Page Table Levels used for alloc_page_table. */ +#define PAGE_TABLE_PGD 0 +#define PAGE_TABLE_PUD 1 +#define PAGE_TABLE_PMD 2 +#define PAGE_TABLE_PTE 3 + +static inline struct page *alloc_page_table_node (struct mm_struct *mm, +unsigned long addr, +int node, +int page_table_level) +{ +switch (page_table_level) { +case PAGE_TABLE_PGD : +return virt_to_page (pgd_alloc_node (mm, node)); + +case PAGE_TABLE_PUD : +return virt_to_page (pud_alloc_one_node (mm, addr, node)); + +case PAGE_TABLE_PMD : +return virt_to_page (pmd_alloc_one_node (mm, addr, node)); + +case PAGE_TABLE_PTE : +return pte_alloc_one_node (mm, addr, node); + +default : +BUG (); +return NULL ; + } +} + + +#endif /* _ASM_GENERIC_PGALLOC_H */
include/asm-generic/pgtable.h renamed from home/rossb/local/linux-2.6.25-rc8/include/asm-generic/pgtable.h +44 -0
56 lines not on this page · raw message
include/asm-x86/pgalloc_64.h renamed from home/rossb/local/linux-2.6.25-rc8/include/asm-x86/pgalloc_64.h +138 -33
205 lines not on this page · raw message
include/linux/migrate.h renamed from home/rossb/local/linux-2.6.25-rc8/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-rc8/include/linux/mm.h +95 -0
113 lines not on this page · raw message
include/linux/mm_types.h renamed from home/rossb/local/linux-2.6.25-rc8/include/linux/mm_types.h +19 -2
@@ -10,6 +10,9 @@#include <linux/rbtree.h> #include <linux/rwsem.h> #include <linux/completion.h> +#include <linux/rcupdate.h> +#include <linux/semaphore.h> +#include <linux/workqueue.h> #include <asm/page.h> #include <asm/mmu.h>
@@ -74,9 +77,18 @@ struct page {pgoff_t index;/* Our offset within mapping. */ void *freelist;/* SLUB: freelist req. slab lock */ }; + +union {struct list_head lru;/* Pageout list, eg. active_list * protected by zone->lru_lock ! */ +struct rcu_head rcu;/* Used by page table relocation code +* to remember page for later freeing, +* after we are sure anyone +* poking at the page tables is no +* longer looking at this page. +*/ + };/* * On machines where all RAM is mapped into kernel address space, * we can simply calculate the virtual address. On machines with
@@ -182,6 +194,8 @@ struct mm_struct {int map_count;/* number of VMAs */ int core_waiters;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 */ struct list_head mmlist;/* List of maybe swapped mm's. These are globally strung
@@ -222,8 +236,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 */ struct completion *core_startup_done, core_done;
@@ -239,6 +251,11 @@ struct mm_struct {struct file *exe_file;unsigned long num_exe_file_vmas;#endif + +#ifdef CONFIG_RELOCATE_PAGE_TABLES +/* Page table relocation support. */ +struct semaphore page_table_relocation_lock; +#endif /* CONFIG_RELOCATE_PAGE_TABLES */ };#endif /* _LINUX_MM_TYPES_H */
kernel/fork.c renamed from home/rossb/local/linux-2.6.25-rc8/kernel/fork.c +4 -0
@@ -360,6 +360,10 @@ static struct mm_struct * mm_init(struct mm->cached_hole_size = ~0UL ;mm_init_cgroup (mm, p); +#ifdef CONFIG_RELOCATE_PAGE_TABLES +init_MUTEX (&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-rc8/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_64 && 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-rc8/mm/hugetlb.c +4 -0
@@ -784,6 +784,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 (!huge_pte_none (huge_ptep_get (src_pte))) {if (cow)huge_ptep_set_wrprotect (src, addr, src_pte);
@@ -960,6 +962,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;
@@ -1017,6 +1020,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,huge_ptep_get (ptep))))if (write_access && !pte_write (entry))
mm/memory.c renamed from home/rossb/local/linux-2.6.25-rc8/mm/memory.c +30 -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 ;
@@ -549,6 +551,8 @@ 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 (&src_pte, &src_ptl, &src_pmd, src_mm, addr);arch_enter_lazy_mmu_mode (); do {
@@ -1566,13 +1570,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); }
@@ -2099,7 +2105,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);
@@ -2178,6 +2184,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);
@@ -2229,6 +2239,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);
@@ -2379,6 +2393,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);
@@ -2488,7 +2506,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) ||
@@ -2547,6 +2565,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) {
@@ -2568,6 +2587,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 ;
@@ -2617,6 +2642,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
@@ -2638,6 +2664,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-rc8/mm/mempolicy.c +26 -0
@@ -100,6 +100,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 ;
@@ -730,6 +736,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.
@@ -750,6 +770,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-rc8/mm/migrate.c +353 -1
380 lines not on this page · raw message
mm/mremap.c renamed from home/rossb/local/linux-2.6.25-rc8/mm/mremap.c +1 -0
@@ -98,6 +98,7 @@ 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 (&new_pte, &new_ptl, &new_pmd, mm, new_addr);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-rc8/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>