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