diff options
Diffstat (limited to 'arch/s390/mm/pgtable.c')
-rw-r--r-- | arch/s390/mm/pgtable.c | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c new file mode 100644 index 000000000000..e60e0ae13402 --- /dev/null +++ b/arch/s390/mm/pgtable.c | |||
@@ -0,0 +1,94 @@ | |||
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 | } | ||