aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/mm
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/mm')
-rw-r--r--arch/s390/mm/Makefile2
-rw-r--r--arch/s390/mm/init.c28
-rw-r--r--arch/s390/mm/pgtable.c94
-rw-r--r--arch/s390/mm/vmem.c19
4 files changed, 114 insertions, 29 deletions
diff --git a/arch/s390/mm/Makefile b/arch/s390/mm/Makefile
index f95449b29fa5..66401930f83e 100644
--- a/arch/s390/mm/Makefile
+++ b/arch/s390/mm/Makefile
@@ -2,6 +2,6 @@
2# Makefile for the linux s390-specific parts of the memory manager. 2# Makefile for the linux s390-specific parts of the memory manager.
3# 3#
4 4
5obj-y := init.o fault.o extmem.o mmap.o vmem.o 5obj-y := init.o fault.o extmem.o mmap.o vmem.o pgtable.o
6obj-$(CONFIG_CMM) += cmm.o 6obj-$(CONFIG_CMM) += cmm.o
7 7
diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c
index 3a25bbf2eb0a..90ec058aa7db 100644
--- a/arch/s390/mm/init.c
+++ b/arch/s390/mm/init.c
@@ -103,32 +103,28 @@ static void __init setup_ro_region(void)
103 */ 103 */
104void __init paging_init(void) 104void __init paging_init(void)
105{ 105{
106 pgd_t *pg_dir;
107 int i;
108 unsigned long pgdir_k;
109 static const int ssm_mask = 0x04000000L; 106 static const int ssm_mask = 0x04000000L;
110 unsigned long max_zone_pfns[MAX_NR_ZONES]; 107 unsigned long max_zone_pfns[MAX_NR_ZONES];
108 unsigned long pgd_type;
111 109
112 pg_dir = swapper_pg_dir; 110 init_mm.pgd = swapper_pg_dir;
113 111 S390_lowcore.kernel_asce = __pa(init_mm.pgd) & PAGE_MASK;
114#ifdef CONFIG_64BIT 112#ifdef CONFIG_64BIT
115 pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) | _KERN_REGION_TABLE; 113 S390_lowcore.kernel_asce |= _ASCE_TYPE_REGION3 | _ASCE_TABLE_LENGTH;
116 for (i = 0; i < PTRS_PER_PGD; i++) 114 pgd_type = _REGION3_ENTRY_EMPTY;
117 pgd_clear_kernel(pg_dir + i);
118#else 115#else
119 pgdir_k = (__pa(swapper_pg_dir) & PAGE_MASK) | _KERNSEG_TABLE; 116 S390_lowcore.kernel_asce |= _ASCE_TABLE_LENGTH;
120 for (i = 0; i < PTRS_PER_PGD; i++) 117 pgd_type = _SEGMENT_ENTRY_EMPTY;
121 pmd_clear_kernel((pmd_t *)(pg_dir + i));
122#endif 118#endif
119 clear_table((unsigned long *) init_mm.pgd, pgd_type,
120 sizeof(unsigned long)*2048);
123 vmem_map_init(); 121 vmem_map_init();
124 setup_ro_region(); 122 setup_ro_region();
125 123
126 S390_lowcore.kernel_asce = pgdir_k;
127
128 /* enable virtual mapping in kernel mode */ 124 /* enable virtual mapping in kernel mode */
129 __ctl_load(pgdir_k, 1, 1); 125 __ctl_load(S390_lowcore.kernel_asce, 1, 1);
130 __ctl_load(pgdir_k, 7, 7); 126 __ctl_load(S390_lowcore.kernel_asce, 7, 7);
131 __ctl_load(pgdir_k, 13, 13); 127 __ctl_load(S390_lowcore.kernel_asce, 13, 13);
132 __raw_local_irq_ssm(ssm_mask); 128 __raw_local_irq_ssm(ssm_mask);
133 129
134 memset(max_zone_pfns, 0, sizeof(max_zone_pfns)); 130 memset(max_zone_pfns, 0, sizeof(max_zone_pfns));
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
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}
diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c
index fd594d5fe142..1bd51d840484 100644
--- a/arch/s390/mm/vmem.c
+++ b/arch/s390/mm/vmem.c
@@ -75,29 +75,24 @@ static void __init_refok *vmem_alloc_pages(unsigned int order)
75 75
76static inline pmd_t *vmem_pmd_alloc(void) 76static inline pmd_t *vmem_pmd_alloc(void)
77{ 77{
78 pmd_t *pmd; 78 pmd_t *pmd = NULL;
79 int i;
80 79
81 pmd = vmem_alloc_pages(PMD_ALLOC_ORDER); 80#ifdef CONFIG_64BIT
81 pmd = vmem_alloc_pages(2);
82 if (!pmd) 82 if (!pmd)
83 return NULL; 83 return NULL;
84 for (i = 0; i < PTRS_PER_PMD; i++) 84 clear_table((unsigned long *) pmd, _SEGMENT_ENTRY_EMPTY, PAGE_SIZE*4);
85 pmd_clear_kernel(pmd + i); 85#endif
86 return pmd; 86 return pmd;
87} 87}
88 88
89static inline pte_t *vmem_pte_alloc(void) 89static inline pte_t *vmem_pte_alloc(void)
90{ 90{
91 pte_t *pte; 91 pte_t *pte = vmem_alloc_pages(0);
92 pte_t empty_pte;
93 int i;
94 92
95 pte = vmem_alloc_pages(PTE_ALLOC_ORDER);
96 if (!pte) 93 if (!pte)
97 return NULL; 94 return NULL;
98 pte_val(empty_pte) = _PAGE_TYPE_EMPTY; 95 clear_table((unsigned long *) pte, _PAGE_TYPE_EMPTY, PAGE_SIZE);
99 for (i = 0; i < PTRS_PER_PTE; i++)
100 pte[i] = empty_pte;
101 return pte; 96 return pte;
102} 97}
103 98