1 /* 2 * arch/s390/mm/pgtable.c 3 * 4 * Copyright IBM Corp. 2007 5 * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com> 6 */ 7 8 #include <linux/sched.h> 9 #include <linux/kernel.h> 10 #include <linux/errno.h> 11 #include <linux/mm.h> 12 #include <linux/swap.h> 13 #include <linux/smp.h> 14 #include <linux/highmem.h> 15 #include <linux/slab.h> 16 #include <linux/pagemap.h> 17 #include <linux/spinlock.h> 18 #include <linux/module.h> 19 #include <linux/quicklist.h> 20 21 #include <asm/system.h> 22 #include <asm/pgtable.h> 23 #include <asm/pgalloc.h> 24 #include <asm/tlb.h> 25 #include <asm/tlbflush.h> 26 27 #ifndef CONFIG_64BIT 28 #define ALLOC_ORDER 1 29 #else 30 #define ALLOC_ORDER 2 31 #endif 32 33 unsigned long *crst_table_alloc(struct mm_struct *mm, int noexec) 34 { 35 struct page *page = alloc_pages(GFP_KERNEL, ALLOC_ORDER); 36 37 if (!page) 38 return NULL; 39 page->index = 0; 40 if (noexec) { 41 struct page *shadow = alloc_pages(GFP_KERNEL, ALLOC_ORDER); 42 if (!shadow) { 43 __free_pages(page, ALLOC_ORDER); 44 return NULL; 45 } 46 page->index = page_to_phys(shadow); 47 } 48 return (unsigned long *) page_to_phys(page); 49 } 50 51 void crst_table_free(unsigned long *table) 52 { 53 unsigned long *shadow = get_shadow_table(table); 54 55 if (shadow) 56 free_pages((unsigned long) shadow, ALLOC_ORDER); 57 free_pages((unsigned long) table, ALLOC_ORDER); 58 } 59 60 /* 61 * page table entry allocation/free routines. 62 */ 63 unsigned long *page_table_alloc(int noexec) 64 { 65 struct page *page = alloc_page(GFP_KERNEL); 66 unsigned long *table; 67 68 if (!page) 69 return NULL; 70 page->index = 0; 71 if (noexec) { 72 struct page *shadow = alloc_page(GFP_KERNEL); 73 if (!shadow) { 74 __free_page(page); 75 return NULL; 76 } 77 table = (unsigned long *) page_to_phys(shadow); 78 clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE); 79 page->index = (addr_t) table; 80 } 81 table = (unsigned long *) page_to_phys(page); 82 clear_table(table, _PAGE_TYPE_EMPTY, PAGE_SIZE); 83 return table; 84 } 85 86 void page_table_free(unsigned long *table) 87 { 88 unsigned long *shadow = get_shadow_pte(table); 89 90 if (shadow) 91 free_page((unsigned long) shadow); 92 free_page((unsigned long) table); 93 94 } 95