diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-11-21 11:27:49 -0500 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-02-21 14:24:14 -0500 |
commit | 516295e5ab4bf986865cfff856d484ec678e3b0b (patch) | |
tree | 2125f49635462fca18ac6d36ebf7363d3cc6d521 /arch/arm | |
parent | f60892d3e36dcdd0d9f30db05beae7a446a93f28 (diff) |
ARM: pgtable: add pud-level code
Add pud_offset() et.al. between the pgd and pmd code in preparation of
using pgtable-nopud.h rather than 4level-fixup.h.
This incorporates a fix from Jamie Iles <jamie@jamieiles.com> for
uaccess_with_memcpy.c.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/include/asm/pgtable.h | 1 | ||||
-rw-r--r-- | arch/arm/lib/uaccess_with_memcpy.c | 7 | ||||
-rw-r--r-- | arch/arm/mm/dma-mapping.c | 11 | ||||
-rw-r--r-- | arch/arm/mm/fault-armv.c | 7 | ||||
-rw-r--r-- | arch/arm/mm/fault.c | 29 | ||||
-rw-r--r-- | arch/arm/mm/idmap.c | 35 | ||||
-rw-r--r-- | arch/arm/mm/mm.h | 2 | ||||
-rw-r--r-- | arch/arm/mm/mmu.c | 22 | ||||
-rw-r--r-- | arch/arm/mm/pgd.c | 24 |
9 files changed, 116 insertions, 22 deletions
diff --git a/arch/arm/include/asm/pgtable.h b/arch/arm/include/asm/pgtable.h index ca567914d303..5750704e0271 100644 --- a/arch/arm/include/asm/pgtable.h +++ b/arch/arm/include/asm/pgtable.h | |||
@@ -301,6 +301,7 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; | |||
301 | #define pgd_present(pgd) (1) | 301 | #define pgd_present(pgd) (1) |
302 | #define pgd_clear(pgdp) do { } while (0) | 302 | #define pgd_clear(pgdp) do { } while (0) |
303 | #define set_pgd(pgd,pgdp) do { } while (0) | 303 | #define set_pgd(pgd,pgdp) do { } while (0) |
304 | #define set_pud(pud,pudp) do { } while (0) | ||
304 | 305 | ||
305 | 306 | ||
306 | /* Find an entry in the second-level page table.. */ | 307 | /* Find an entry in the second-level page table.. */ |
diff --git a/arch/arm/lib/uaccess_with_memcpy.c b/arch/arm/lib/uaccess_with_memcpy.c index e2d2f2cd0c4f..8b9b13649f81 100644 --- a/arch/arm/lib/uaccess_with_memcpy.c +++ b/arch/arm/lib/uaccess_with_memcpy.c | |||
@@ -27,13 +27,18 @@ pin_page_for_write(const void __user *_addr, pte_t **ptep, spinlock_t **ptlp) | |||
27 | pgd_t *pgd; | 27 | pgd_t *pgd; |
28 | pmd_t *pmd; | 28 | pmd_t *pmd; |
29 | pte_t *pte; | 29 | pte_t *pte; |
30 | pud_t *pud; | ||
30 | spinlock_t *ptl; | 31 | spinlock_t *ptl; |
31 | 32 | ||
32 | pgd = pgd_offset(current->mm, addr); | 33 | pgd = pgd_offset(current->mm, addr); |
33 | if (unlikely(pgd_none(*pgd) || pgd_bad(*pgd))) | 34 | if (unlikely(pgd_none(*pgd) || pgd_bad(*pgd))) |
34 | return 0; | 35 | return 0; |
35 | 36 | ||
36 | pmd = pmd_offset(pgd, addr); | 37 | pud = pud_offset(pgd, addr); |
38 | if (unlikely(pud_none(*pud) || pud_bad(*pud))) | ||
39 | return 0; | ||
40 | |||
41 | pmd = pmd_offset(pud, addr); | ||
37 | if (unlikely(pmd_none(*pmd) || pmd_bad(*pmd))) | 42 | if (unlikely(pmd_none(*pmd) || pmd_bad(*pmd))) |
38 | return 0; | 43 | return 0; |
39 | 44 | ||
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index ac6a36142fcd..a9bdfcda23f4 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c | |||
@@ -148,6 +148,7 @@ static int __init consistent_init(void) | |||
148 | { | 148 | { |
149 | int ret = 0; | 149 | int ret = 0; |
150 | pgd_t *pgd; | 150 | pgd_t *pgd; |
151 | pud_t *pud; | ||
151 | pmd_t *pmd; | 152 | pmd_t *pmd; |
152 | pte_t *pte; | 153 | pte_t *pte; |
153 | int i = 0; | 154 | int i = 0; |
@@ -155,7 +156,15 @@ static int __init consistent_init(void) | |||
155 | 156 | ||
156 | do { | 157 | do { |
157 | pgd = pgd_offset(&init_mm, base); | 158 | pgd = pgd_offset(&init_mm, base); |
158 | pmd = pmd_alloc(&init_mm, pgd, base); | 159 | |
160 | pud = pud_alloc(&init_mm, pgd, base); | ||
161 | if (!pud) { | ||
162 | printk(KERN_ERR "%s: no pud tables\n", __func__); | ||
163 | ret = -ENOMEM; | ||
164 | break; | ||
165 | } | ||
166 | |||
167 | pmd = pmd_alloc(&init_mm, pud, base); | ||
159 | if (!pmd) { | 168 | if (!pmd) { |
160 | printk(KERN_ERR "%s: no pmd tables\n", __func__); | 169 | printk(KERN_ERR "%s: no pmd tables\n", __func__); |
161 | ret = -ENOMEM; | 170 | ret = -ENOMEM; |
diff --git a/arch/arm/mm/fault-armv.c b/arch/arm/mm/fault-armv.c index 01210dba0221..7cab79179421 100644 --- a/arch/arm/mm/fault-armv.c +++ b/arch/arm/mm/fault-armv.c | |||
@@ -95,6 +95,7 @@ static int adjust_pte(struct vm_area_struct *vma, unsigned long address, | |||
95 | { | 95 | { |
96 | spinlock_t *ptl; | 96 | spinlock_t *ptl; |
97 | pgd_t *pgd; | 97 | pgd_t *pgd; |
98 | pud_t *pud; | ||
98 | pmd_t *pmd; | 99 | pmd_t *pmd; |
99 | pte_t *pte; | 100 | pte_t *pte; |
100 | int ret; | 101 | int ret; |
@@ -103,7 +104,11 @@ static int adjust_pte(struct vm_area_struct *vma, unsigned long address, | |||
103 | if (pgd_none_or_clear_bad(pgd)) | 104 | if (pgd_none_or_clear_bad(pgd)) |
104 | return 0; | 105 | return 0; |
105 | 106 | ||
106 | pmd = pmd_offset(pgd, address); | 107 | pud = pud_offset(pgd, address); |
108 | if (pud_none_or_clear_bad(pud)) | ||
109 | return 0; | ||
110 | |||
111 | pmd = pmd_offset(pud, address); | ||
107 | if (pmd_none_or_clear_bad(pmd)) | 112 | if (pmd_none_or_clear_bad(pmd)) |
108 | return 0; | 113 | return 0; |
109 | 114 | ||
diff --git a/arch/arm/mm/fault.c b/arch/arm/mm/fault.c index ef0e24f578ef..bc0e1d88fd3b 100644 --- a/arch/arm/mm/fault.c +++ b/arch/arm/mm/fault.c | |||
@@ -80,6 +80,7 @@ void show_pte(struct mm_struct *mm, unsigned long addr) | |||
80 | addr, (long long)pgd_val(*pgd)); | 80 | addr, (long long)pgd_val(*pgd)); |
81 | 81 | ||
82 | do { | 82 | do { |
83 | pud_t *pud; | ||
83 | pmd_t *pmd; | 84 | pmd_t *pmd; |
84 | pte_t *pte; | 85 | pte_t *pte; |
85 | 86 | ||
@@ -91,7 +92,19 @@ void show_pte(struct mm_struct *mm, unsigned long addr) | |||
91 | break; | 92 | break; |
92 | } | 93 | } |
93 | 94 | ||
94 | pmd = pmd_offset(pgd, addr); | 95 | pud = pud_offset(pgd, addr); |
96 | if (PTRS_PER_PUD != 1) | ||
97 | printk(", *pud=%08lx", pud_val(*pud)); | ||
98 | |||
99 | if (pud_none(*pud)) | ||
100 | break; | ||
101 | |||
102 | if (pud_bad(*pud)) { | ||
103 | printk("(bad)"); | ||
104 | break; | ||
105 | } | ||
106 | |||
107 | pmd = pmd_offset(pud, addr); | ||
95 | if (PTRS_PER_PMD != 1) | 108 | if (PTRS_PER_PMD != 1) |
96 | printk(", *pmd=%08llx", (long long)pmd_val(*pmd)); | 109 | printk(", *pmd=%08llx", (long long)pmd_val(*pmd)); |
97 | 110 | ||
@@ -390,6 +403,7 @@ do_translation_fault(unsigned long addr, unsigned int fsr, | |||
390 | { | 403 | { |
391 | unsigned int index; | 404 | unsigned int index; |
392 | pgd_t *pgd, *pgd_k; | 405 | pgd_t *pgd, *pgd_k; |
406 | pud_t *pud, *pud_k; | ||
393 | pmd_t *pmd, *pmd_k; | 407 | pmd_t *pmd, *pmd_k; |
394 | 408 | ||
395 | if (addr < TASK_SIZE) | 409 | if (addr < TASK_SIZE) |
@@ -408,12 +422,19 @@ do_translation_fault(unsigned long addr, unsigned int fsr, | |||
408 | 422 | ||
409 | if (pgd_none(*pgd_k)) | 423 | if (pgd_none(*pgd_k)) |
410 | goto bad_area; | 424 | goto bad_area; |
411 | |||
412 | if (!pgd_present(*pgd)) | 425 | if (!pgd_present(*pgd)) |
413 | set_pgd(pgd, *pgd_k); | 426 | set_pgd(pgd, *pgd_k); |
414 | 427 | ||
415 | pmd_k = pmd_offset(pgd_k, addr); | 428 | pud = pud_offset(pgd, addr); |
416 | pmd = pmd_offset(pgd, addr); | 429 | pud_k = pud_offset(pgd_k, addr); |
430 | |||
431 | if (pud_none(*pud_k)) | ||
432 | goto bad_area; | ||
433 | if (!pud_present(*pud)) | ||
434 | set_pud(pud, *pud_k); | ||
435 | |||
436 | pmd = pmd_offset(pud, addr); | ||
437 | pmd_k = pmd_offset(pud_k, addr); | ||
417 | 438 | ||
418 | /* | 439 | /* |
419 | * On ARM one Linux PGD entry contains two hardware entries (see page | 440 | * On ARM one Linux PGD entry contains two hardware entries (see page |
diff --git a/arch/arm/mm/idmap.c b/arch/arm/mm/idmap.c index 57299446f787..2be9139a4ef3 100644 --- a/arch/arm/mm/idmap.c +++ b/arch/arm/mm/idmap.c | |||
@@ -4,10 +4,10 @@ | |||
4 | #include <asm/pgalloc.h> | 4 | #include <asm/pgalloc.h> |
5 | #include <asm/pgtable.h> | 5 | #include <asm/pgtable.h> |
6 | 6 | ||
7 | static void idmap_add_pmd(pgd_t *pgd, unsigned long addr, unsigned long end, | 7 | static void idmap_add_pmd(pud_t *pud, unsigned long addr, unsigned long end, |
8 | unsigned long prot) | 8 | unsigned long prot) |
9 | { | 9 | { |
10 | pmd_t *pmd = pmd_offset(pgd, addr); | 10 | pmd_t *pmd = pmd_offset(pud, addr); |
11 | 11 | ||
12 | addr = (addr & PMD_MASK) | prot; | 12 | addr = (addr & PMD_MASK) | prot; |
13 | pmd[0] = __pmd(addr); | 13 | pmd[0] = __pmd(addr); |
@@ -16,6 +16,18 @@ static void idmap_add_pmd(pgd_t *pgd, unsigned long addr, unsigned long end, | |||
16 | flush_pmd_entry(pmd); | 16 | flush_pmd_entry(pmd); |
17 | } | 17 | } |
18 | 18 | ||
19 | static void idmap_add_pud(pgd_t *pgd, unsigned long addr, unsigned long end, | ||
20 | unsigned long prot) | ||
21 | { | ||
22 | pud_t *pud = pud_offset(pgd, addr); | ||
23 | unsigned long next; | ||
24 | |||
25 | do { | ||
26 | next = pud_addr_end(addr, end); | ||
27 | idmap_add_pmd(pud, addr, next, prot); | ||
28 | } while (pud++, addr = next, addr != end); | ||
29 | } | ||
30 | |||
19 | void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long end) | 31 | void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long end) |
20 | { | 32 | { |
21 | unsigned long prot, next; | 33 | unsigned long prot, next; |
@@ -27,17 +39,28 @@ void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long end) | |||
27 | pgd += pgd_index(addr); | 39 | pgd += pgd_index(addr); |
28 | do { | 40 | do { |
29 | next = pgd_addr_end(addr, end); | 41 | next = pgd_addr_end(addr, end); |
30 | idmap_add_pmd(pgd, addr, next, prot); | 42 | idmap_add_pud(pgd, addr, next, prot); |
31 | } while (pgd++, addr = next, addr != end); | 43 | } while (pgd++, addr = next, addr != end); |
32 | } | 44 | } |
33 | 45 | ||
34 | #ifdef CONFIG_SMP | 46 | #ifdef CONFIG_SMP |
35 | static void idmap_del_pmd(pgd_t *pgd, unsigned long addr, unsigned long end) | 47 | static void idmap_del_pmd(pud_t *pud, unsigned long addr, unsigned long end) |
36 | { | 48 | { |
37 | pmd_t *pmd = pmd_offset(pgd, addr); | 49 | pmd_t *pmd = pmd_offset(pud, addr); |
38 | pmd_clear(pmd); | 50 | pmd_clear(pmd); |
39 | } | 51 | } |
40 | 52 | ||
53 | static void idmap_del_pud(pgd_t *pgd, unsigned long addr, unsigned long end) | ||
54 | { | ||
55 | pud_t *pud = pud_offset(pgd, addr); | ||
56 | unsigned long next; | ||
57 | |||
58 | do { | ||
59 | next = pud_addr_end(addr, end); | ||
60 | idmap_del_pmd(pud, addr, next); | ||
61 | } while (pud++, addr = next, addr != end); | ||
62 | } | ||
63 | |||
41 | void identity_mapping_del(pgd_t *pgd, unsigned long addr, unsigned long end) | 64 | void identity_mapping_del(pgd_t *pgd, unsigned long addr, unsigned long end) |
42 | { | 65 | { |
43 | unsigned long next; | 66 | unsigned long next; |
@@ -45,7 +68,7 @@ void identity_mapping_del(pgd_t *pgd, unsigned long addr, unsigned long end) | |||
45 | pgd += pgd_index(addr); | 68 | pgd += pgd_index(addr); |
46 | do { | 69 | do { |
47 | next = pgd_addr_end(addr, end); | 70 | next = pgd_addr_end(addr, end); |
48 | idmap_del_pmd(pgd, addr, next); | 71 | idmap_del_pud(pgd, addr, next); |
49 | } while (pgd++, addr = next, addr != end); | 72 | } while (pgd++, addr = next, addr != end); |
50 | } | 73 | } |
51 | #endif | 74 | #endif |
diff --git a/arch/arm/mm/mm.h b/arch/arm/mm/mm.h index 36960df5fb76..d2384106af9c 100644 --- a/arch/arm/mm/mm.h +++ b/arch/arm/mm/mm.h | |||
@@ -7,7 +7,7 @@ extern pmd_t *top_pmd; | |||
7 | 7 | ||
8 | static inline pmd_t *pmd_off(pgd_t *pgd, unsigned long virt) | 8 | static inline pmd_t *pmd_off(pgd_t *pgd, unsigned long virt) |
9 | { | 9 | { |
10 | return pmd_offset(pgd, virt); | 10 | return pmd_offset(pud_offset(pgd, virt), virt); |
11 | } | 11 | } |
12 | 12 | ||
13 | static inline pmd_t *pmd_off_k(unsigned long virt) | 13 | static inline pmd_t *pmd_off_k(unsigned long virt) |
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index 176749010935..82ef6966ae09 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c | |||
@@ -550,11 +550,11 @@ static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr, | |||
550 | } while (pte++, addr += PAGE_SIZE, addr != end); | 550 | } while (pte++, addr += PAGE_SIZE, addr != end); |
551 | } | 551 | } |
552 | 552 | ||
553 | static void __init alloc_init_section(pgd_t *pgd, unsigned long addr, | 553 | static void __init alloc_init_section(pud_t *pud, unsigned long addr, |
554 | unsigned long end, phys_addr_t phys, | 554 | unsigned long end, phys_addr_t phys, |
555 | const struct mem_type *type) | 555 | const struct mem_type *type) |
556 | { | 556 | { |
557 | pmd_t *pmd = pmd_offset(pgd, addr); | 557 | pmd_t *pmd = pmd_offset(pud, addr); |
558 | 558 | ||
559 | /* | 559 | /* |
560 | * Try a section mapping - end, addr and phys must all be aligned | 560 | * Try a section mapping - end, addr and phys must all be aligned |
@@ -583,6 +583,19 @@ static void __init alloc_init_section(pgd_t *pgd, unsigned long addr, | |||
583 | } | 583 | } |
584 | } | 584 | } |
585 | 585 | ||
586 | static void alloc_init_pud(pgd_t *pgd, unsigned long addr, unsigned long end, | ||
587 | unsigned long phys, const struct mem_type *type) | ||
588 | { | ||
589 | pud_t *pud = pud_offset(pgd, addr); | ||
590 | unsigned long next; | ||
591 | |||
592 | do { | ||
593 | next = pud_addr_end(addr, end); | ||
594 | alloc_init_section(pud, addr, next, phys, type); | ||
595 | phys += next - addr; | ||
596 | } while (pud++, addr = next, addr != end); | ||
597 | } | ||
598 | |||
586 | static void __init create_36bit_mapping(struct map_desc *md, | 599 | static void __init create_36bit_mapping(struct map_desc *md, |
587 | const struct mem_type *type) | 600 | const struct mem_type *type) |
588 | { | 601 | { |
@@ -630,7 +643,8 @@ static void __init create_36bit_mapping(struct map_desc *md, | |||
630 | pgd = pgd_offset_k(addr); | 643 | pgd = pgd_offset_k(addr); |
631 | end = addr + length; | 644 | end = addr + length; |
632 | do { | 645 | do { |
633 | pmd_t *pmd = pmd_offset(pgd, addr); | 646 | pud_t *pud = pud_offset(pgd, addr); |
647 | pmd_t *pmd = pmd_offset(pud, addr); | ||
634 | int i; | 648 | int i; |
635 | 649 | ||
636 | for (i = 0; i < 16; i++) | 650 | for (i = 0; i < 16; i++) |
@@ -696,7 +710,7 @@ static void __init create_mapping(struct map_desc *md) | |||
696 | do { | 710 | do { |
697 | unsigned long next = pgd_addr_end(addr, end); | 711 | unsigned long next = pgd_addr_end(addr, end); |
698 | 712 | ||
699 | alloc_init_section(pgd, addr, next, phys, type); | 713 | alloc_init_pud(pgd, addr, next, phys, type); |
700 | 714 | ||
701 | phys += next - addr; | 715 | phys += next - addr; |
702 | addr = next; | 716 | addr = next; |
diff --git a/arch/arm/mm/pgd.c b/arch/arm/mm/pgd.c index 93292a18cf77..f7fafb1741f4 100644 --- a/arch/arm/mm/pgd.c +++ b/arch/arm/mm/pgd.c | |||
@@ -23,6 +23,7 @@ | |||
23 | pgd_t *pgd_alloc(struct mm_struct *mm) | 23 | pgd_t *pgd_alloc(struct mm_struct *mm) |
24 | { | 24 | { |
25 | pgd_t *new_pgd, *init_pgd; | 25 | pgd_t *new_pgd, *init_pgd; |
26 | pud_t *new_pud, *init_pud; | ||
26 | pmd_t *new_pmd, *init_pmd; | 27 | pmd_t *new_pmd, *init_pmd; |
27 | pte_t *new_pte, *init_pte; | 28 | pte_t *new_pte, *init_pte; |
28 | 29 | ||
@@ -46,7 +47,11 @@ pgd_t *pgd_alloc(struct mm_struct *mm) | |||
46 | * On ARM, first page must always be allocated since it | 47 | * On ARM, first page must always be allocated since it |
47 | * contains the machine vectors. | 48 | * contains the machine vectors. |
48 | */ | 49 | */ |
49 | new_pmd = pmd_alloc(mm, new_pgd, 0); | 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); | ||
50 | if (!new_pmd) | 55 | if (!new_pmd) |
51 | goto no_pmd; | 56 | goto no_pmd; |
52 | 57 | ||
@@ -54,7 +59,8 @@ pgd_t *pgd_alloc(struct mm_struct *mm) | |||
54 | if (!new_pte) | 59 | if (!new_pte) |
55 | goto no_pte; | 60 | goto no_pte; |
56 | 61 | ||
57 | init_pmd = pmd_offset(init_pgd, 0); | 62 | init_pud = pud_offset(init_pgd, 0); |
63 | init_pmd = pmd_offset(init_pud, 0); | ||
58 | init_pte = pte_offset_map(init_pmd, 0); | 64 | init_pte = pte_offset_map(init_pmd, 0); |
59 | set_pte_ext(new_pte, *init_pte, 0); | 65 | set_pte_ext(new_pte, *init_pte, 0); |
60 | pte_unmap(init_pte); | 66 | pte_unmap(init_pte); |
@@ -66,6 +72,8 @@ pgd_t *pgd_alloc(struct mm_struct *mm) | |||
66 | no_pte: | 72 | no_pte: |
67 | pmd_free(mm, new_pmd); | 73 | pmd_free(mm, new_pmd); |
68 | no_pmd: | 74 | no_pmd: |
75 | pud_free(mm, new_pud); | ||
76 | no_pud: | ||
69 | free_pages((unsigned long)new_pgd, 2); | 77 | free_pages((unsigned long)new_pgd, 2); |
70 | no_pgd: | 78 | no_pgd: |
71 | return NULL; | 79 | return NULL; |
@@ -74,6 +82,7 @@ no_pgd: | |||
74 | void pgd_free(struct mm_struct *mm, pgd_t *pgd_base) | 82 | void pgd_free(struct mm_struct *mm, pgd_t *pgd_base) |
75 | { | 83 | { |
76 | pgd_t *pgd; | 84 | pgd_t *pgd; |
85 | pud_t *pud; | ||
77 | pmd_t *pmd; | 86 | pmd_t *pmd; |
78 | pgtable_t pte; | 87 | pgtable_t pte; |
79 | 88 | ||
@@ -84,7 +93,11 @@ void pgd_free(struct mm_struct *mm, pgd_t *pgd_base) | |||
84 | if (pgd_none_or_clear_bad(pgd)) | 93 | if (pgd_none_or_clear_bad(pgd)) |
85 | goto no_pgd; | 94 | goto no_pgd; |
86 | 95 | ||
87 | pmd = pmd_offset(pgd, 0); | 96 | pud = pud_offset(pgd, 0); |
97 | if (pud_none_or_clear_bad(pud)) | ||
98 | goto no_pud; | ||
99 | |||
100 | pmd = pmd_offset(pud, 0); | ||
88 | if (pmd_none_or_clear_bad(pmd)) | 101 | if (pmd_none_or_clear_bad(pmd)) |
89 | goto no_pmd; | 102 | goto no_pmd; |
90 | 103 | ||
@@ -92,8 +105,11 @@ void pgd_free(struct mm_struct *mm, pgd_t *pgd_base) | |||
92 | pmd_clear(pmd); | 105 | pmd_clear(pmd); |
93 | pte_free(mm, pte); | 106 | pte_free(mm, pte); |
94 | no_pmd: | 107 | no_pmd: |
95 | pgd_clear(pgd); | 108 | pud_clear(pud); |
96 | pmd_free(mm, pmd); | 109 | pmd_free(mm, pmd); |
110 | no_pud: | ||
111 | pgd_clear(pgd); | ||
112 | pud_free(mm, pud); | ||
97 | no_pgd: | 113 | no_pgd: |
98 | free_pages((unsigned long) pgd_base, 2); | 114 | free_pages((unsigned long) pgd_base, 2); |
99 | } | 115 | } |