/* * arch/s390/mm/pgtable.c * * Copyright IBM Corp. 2007 * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> */ #include <linux/sched.h> #include <linux/kernel.h> #include <linux/errno.h> #include <linux/mm.h> #include <linux/swap.h> #include <linux/smp.h> #include <linux/highmem.h> #include <linux/slab.h> #include <linux/pagemap.h> #include <linux/spinlock.h> #include <linux/module.h> #include <linux/quicklist.h> #include <asm/system.h> #include <asm/pgtable.h> #include <asm/pgalloc.h> #include <asm/tlb.h> #include <asm/tlbflush.h> #ifndef CONFIG_64BIT #define ALLOC_ORDER 1 #else #define ALLOC_ORDER 2 #endif unsigned long *crst_table_alloc(struct mm_struct *mm, int noexec) { struct page *page = alloc_pages(GFP_KERNEL, ALLOC_ORDER); if (!page) return NULL; page->index = 0; if (noexec) { struct page *shadow = alloc_pages(GFP_KERNEL, ALLOC_ORDER); if (!shadow) { __free_pages(page, ALLOC_ORDER); return NULL; } page->index = page_to_phys(shadow); } return (unsigned long *) page_to_phys(page); } void crst_table_free(unsigned long *table) { unsigned long *shadow = get_shadow_table(table); if (shadow) free_pages((unsigned long) shadow, ALLOC_ORDER); free_pages((unsigned long) table, ALLOC_ORDER); } /* * page table entry allocation/free routines. */ unsigned long *page_table_alloc(int noexec) { struct page *page = alloc_page(GFP_KERNEL); unsigned long *table; if (!page) return NULL; page->index = 0; if (noexec) { struct page *shadow = alloc_page(GFP_KERNEL); if (!shadow) { __free_page(page); return NULL; } table = (unsigned long *) page_to_phys(shadow); clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE); page->index = (addr_t) table; } table = (unsigned long *) page_to_phys(page); clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE); return table; } void page_table_free(unsigned long *table) { unsigned long *shadow = get_shadow_pte(table); if (shadow) free_page((unsigned long) shadow); free_page((unsigned long) table); }