pgd.c (94bd217e2d683719ab21a4ac117d8a1b91cbedc9) pgd.c (da02877987e6e173ebba137d4e1e155e1f1151cd)
1/*
2 * linux/arch/arm/mm/pgd.c
3 *
4 * Copyright (C) 1998-2005 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/mm.h>
11#include <linux/gfp.h>
12#include <linux/highmem.h>
1/*
2 * linux/arch/arm/mm/pgd.c
3 *
4 * Copyright (C) 1998-2005 Russell King
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10#include <linux/mm.h>
11#include <linux/gfp.h>
12#include <linux/highmem.h>
13#include <linux/slab.h>
13
14#include <asm/pgalloc.h>
15#include <asm/page.h>
16#include <asm/tlbflush.h>
17
18#include "mm.h"
19
14
15#include <asm/pgalloc.h>
16#include <asm/page.h>
17#include <asm/tlbflush.h>
18
19#include "mm.h"
20
21#ifdef CONFIG_ARM_LPAE
22#define __pgd_alloc() kmalloc(PTRS_PER_PGD * sizeof(pgd_t), GFP_KERNEL)
23#define __pgd_free(pgd) kfree(pgd)
24#else
25#define __pgd_alloc() (pgd_t *)__get_free_pages(GFP_KERNEL, 2)
26#define __pgd_free(pgd) free_pages((unsigned long)pgd, 2)
27#endif
28
20/*
21 * need to get a 16k page for level 1
22 */
23pgd_t *pgd_alloc(struct mm_struct *mm)
24{
25 pgd_t *new_pgd, *init_pgd;
26 pud_t *new_pud, *init_pud;
27 pmd_t *new_pmd, *init_pmd;
28 pte_t *new_pte, *init_pte;
29
29/*
30 * need to get a 16k page for level 1
31 */
32pgd_t *pgd_alloc(struct mm_struct *mm)
33{
34 pgd_t *new_pgd, *init_pgd;
35 pud_t *new_pud, *init_pud;
36 pmd_t *new_pmd, *init_pmd;
37 pte_t *new_pte, *init_pte;
38
30 new_pgd = (pgd_t *)__get_free_pages(GFP_KERNEL, 2);
39 new_pgd = __pgd_alloc();
31 if (!new_pgd)
32 goto no_pgd;
33
34 memset(new_pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
35
36 /*
37 * Copy over the kernel and IO PGD entries
38 */
39 init_pgd = pgd_offset_k(0);
40 memcpy(new_pgd + USER_PTRS_PER_PGD, init_pgd + USER_PTRS_PER_PGD,
41 (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
42
43 clean_dcache_area(new_pgd, PTRS_PER_PGD * sizeof(pgd_t));
44
40 if (!new_pgd)
41 goto no_pgd;
42
43 memset(new_pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
44
45 /*
46 * Copy over the kernel and IO PGD entries
47 */
48 init_pgd = pgd_offset_k(0);
49 memcpy(new_pgd + USER_PTRS_PER_PGD, init_pgd + USER_PTRS_PER_PGD,
50 (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
51
52 clean_dcache_area(new_pgd, PTRS_PER_PGD * sizeof(pgd_t));
53
54#ifdef CONFIG_ARM_LPAE
55 /*
56 * Allocate PMD table for modules and pkmap mappings.
57 */
58 new_pud = pud_alloc(mm, new_pgd + pgd_index(MODULES_VADDR),
59 MODULES_VADDR);
60 if (!new_pud)
61 goto no_pud;
62
63 new_pmd = pmd_alloc(mm, new_pud, 0);
64 if (!new_pmd)
65 goto no_pmd;
66#endif
67
45 if (!vectors_high()) {
46 /*
47 * On ARM, first page must always be allocated since it
68 if (!vectors_high()) {
69 /*
70 * On ARM, first page must always be allocated since it
48 * contains the machine vectors.
71 * contains the machine vectors. The vectors are always high
72 * with LPAE.
49 */
50 new_pud = pud_alloc(mm, new_pgd, 0);
51 if (!new_pud)
52 goto no_pud;
53
54 new_pmd = pmd_alloc(mm, new_pud, 0);
55 if (!new_pmd)
56 goto no_pmd;

--- 12 unchanged lines hidden (view full) ---

69
70 return new_pgd;
71
72no_pte:
73 pmd_free(mm, new_pmd);
74no_pmd:
75 pud_free(mm, new_pud);
76no_pud:
73 */
74 new_pud = pud_alloc(mm, new_pgd, 0);
75 if (!new_pud)
76 goto no_pud;
77
78 new_pmd = pmd_alloc(mm, new_pud, 0);
79 if (!new_pmd)
80 goto no_pmd;

--- 12 unchanged lines hidden (view full) ---

93
94 return new_pgd;
95
96no_pte:
97 pmd_free(mm, new_pmd);
98no_pmd:
99 pud_free(mm, new_pud);
100no_pud:
77 free_pages((unsigned long)new_pgd, 2);
101 __pgd_free(new_pgd);
78no_pgd:
79 return NULL;
80}
81
82void pgd_free(struct mm_struct *mm, pgd_t *pgd_base)
83{
84 pgd_t *pgd;
85 pud_t *pud;

--- 20 unchanged lines hidden (view full) ---

106 pte_free(mm, pte);
107no_pmd:
108 pud_clear(pud);
109 pmd_free(mm, pmd);
110no_pud:
111 pgd_clear(pgd);
112 pud_free(mm, pud);
113no_pgd:
102no_pgd:
103 return NULL;
104}
105
106void pgd_free(struct mm_struct *mm, pgd_t *pgd_base)
107{
108 pgd_t *pgd;
109 pud_t *pud;

--- 20 unchanged lines hidden (view full) ---

130 pte_free(mm, pte);
131no_pmd:
132 pud_clear(pud);
133 pmd_free(mm, pmd);
134no_pud:
135 pgd_clear(pgd);
136 pud_free(mm, pud);
137no_pgd:
114 free_pages((unsigned long) pgd_base, 2);
138#ifdef CONFIG_ARM_LPAE
139 /*
140 * Free modules/pkmap or identity pmd tables.
141 */
142 for (pgd = pgd_base; pgd < pgd_base + PTRS_PER_PGD; pgd++) {
143 if (pgd_none_or_clear_bad(pgd))
144 continue;
145 if (pgd_val(*pgd) & L_PGD_SWAPPER)
146 continue;
147 pud = pud_offset(pgd, 0);
148 if (pud_none_or_clear_bad(pud))
149 continue;
150 pmd = pmd_offset(pud, 0);
151 pud_clear(pud);
152 pmd_free(mm, pmd);
153 pgd_clear(pgd);
154 pud_free(mm, pud);
155 }
156#endif
157 __pgd_free(pgd_base);
115}
158}