pgtable.c revision 3610cce87af0693603db171d5b6f6735f5e3dc5b
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 33unsigned 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 51void 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 */ 63unsigned 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 86void 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