aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/page.h5
-rw-r--r--arch/x86/mm/ident_map.c74
-rw-r--r--arch/x86/mm/init_64.c74
3 files changed, 80 insertions, 73 deletions
diff --git a/arch/x86/include/asm/page.h b/arch/x86/include/asm/page.h
index 802dde30c928..cf8f619b305f 100644
--- a/arch/x86/include/asm/page.h
+++ b/arch/x86/include/asm/page.h
@@ -37,7 +37,10 @@ static inline void copy_user_page(void *to, void *from, unsigned long vaddr,
37 alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr) 37 alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
38#define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE 38#define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
39 39
40#ifndef __pa
40#define __pa(x) __phys_addr((unsigned long)(x)) 41#define __pa(x) __phys_addr((unsigned long)(x))
42#endif
43
41#define __pa_nodebug(x) __phys_addr_nodebug((unsigned long)(x)) 44#define __pa_nodebug(x) __phys_addr_nodebug((unsigned long)(x))
42/* __pa_symbol should be used for C visible symbols. 45/* __pa_symbol should be used for C visible symbols.
43 This seems to be the official gcc blessed way to do such arithmetic. */ 46 This seems to be the official gcc blessed way to do such arithmetic. */
@@ -51,7 +54,9 @@ static inline void copy_user_page(void *to, void *from, unsigned long vaddr,
51#define __pa_symbol(x) \ 54#define __pa_symbol(x) \
52 __phys_addr_symbol(__phys_reloc_hide((unsigned long)(x))) 55 __phys_addr_symbol(__phys_reloc_hide((unsigned long)(x)))
53 56
57#ifndef __va
54#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET)) 58#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET))
59#endif
55 60
56#define __boot_va(x) __va(x) 61#define __boot_va(x) __va(x)
57#define __boot_pa(x) __pa(x) 62#define __boot_pa(x) __pa(x)
diff --git a/arch/x86/mm/ident_map.c b/arch/x86/mm/ident_map.c
new file mode 100644
index 000000000000..751ca920773a
--- /dev/null
+++ b/arch/x86/mm/ident_map.c
@@ -0,0 +1,74 @@
1
2static void ident_pmd_init(unsigned long pmd_flag, pmd_t *pmd_page,
3 unsigned long addr, unsigned long end)
4{
5 addr &= PMD_MASK;
6 for (; addr < end; addr += PMD_SIZE) {
7 pmd_t *pmd = pmd_page + pmd_index(addr);
8
9 if (!pmd_present(*pmd))
10 set_pmd(pmd, __pmd(addr | pmd_flag));
11 }
12}
13static int ident_pud_init(struct x86_mapping_info *info, pud_t *pud_page,
14 unsigned long addr, unsigned long end)
15{
16 unsigned long next;
17
18 for (; addr < end; addr = next) {
19 pud_t *pud = pud_page + pud_index(addr);
20 pmd_t *pmd;
21
22 next = (addr & PUD_MASK) + PUD_SIZE;
23 if (next > end)
24 next = end;
25
26 if (pud_present(*pud)) {
27 pmd = pmd_offset(pud, 0);
28 ident_pmd_init(info->pmd_flag, pmd, addr, next);
29 continue;
30 }
31 pmd = (pmd_t *)info->alloc_pgt_page(info->context);
32 if (!pmd)
33 return -ENOMEM;
34 ident_pmd_init(info->pmd_flag, pmd, addr, next);
35 set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE));
36 }
37
38 return 0;
39}
40
41int kernel_ident_mapping_init(struct x86_mapping_info *info, pgd_t *pgd_page,
42 unsigned long addr, unsigned long end)
43{
44 unsigned long next;
45 int result;
46 int off = info->kernel_mapping ? pgd_index(__PAGE_OFFSET) : 0;
47
48 for (; addr < end; addr = next) {
49 pgd_t *pgd = pgd_page + pgd_index(addr) + off;
50 pud_t *pud;
51
52 next = (addr & PGDIR_MASK) + PGDIR_SIZE;
53 if (next > end)
54 next = end;
55
56 if (pgd_present(*pgd)) {
57 pud = pud_offset(pgd, 0);
58 result = ident_pud_init(info, pud, addr, next);
59 if (result)
60 return result;
61 continue;
62 }
63
64 pud = (pud_t *)info->alloc_pgt_page(info->context);
65 if (!pud)
66 return -ENOMEM;
67 result = ident_pud_init(info, pud, addr, next);
68 if (result)
69 return result;
70 set_pgd(pgd, __pgd(__pa(pud) | _KERNPG_TABLE));
71 }
72
73 return 0;
74}
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 214afda97911..65cfbeefbec4 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -58,79 +58,7 @@
58 58
59#include "mm_internal.h" 59#include "mm_internal.h"
60 60
61static void ident_pmd_init(unsigned long pmd_flag, pmd_t *pmd_page, 61#include "ident_map.c"
62 unsigned long addr, unsigned long end)
63{
64 addr &= PMD_MASK;
65 for (; addr < end; addr += PMD_SIZE) {
66 pmd_t *pmd = pmd_page + pmd_index(addr);
67
68 if (!pmd_present(*pmd))
69 set_pmd(pmd, __pmd(addr | pmd_flag));
70 }
71}
72static int ident_pud_init(struct x86_mapping_info *info, pud_t *pud_page,
73 unsigned long addr, unsigned long end)
74{
75 unsigned long next;
76
77 for (; addr < end; addr = next) {
78 pud_t *pud = pud_page + pud_index(addr);
79 pmd_t *pmd;
80
81 next = (addr & PUD_MASK) + PUD_SIZE;
82 if (next > end)
83 next = end;
84
85 if (pud_present(*pud)) {
86 pmd = pmd_offset(pud, 0);
87 ident_pmd_init(info->pmd_flag, pmd, addr, next);
88 continue;
89 }
90 pmd = (pmd_t *)info->alloc_pgt_page(info->context);
91 if (!pmd)
92 return -ENOMEM;
93 ident_pmd_init(info->pmd_flag, pmd, addr, next);
94 set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE));
95 }
96
97 return 0;
98}
99
100int kernel_ident_mapping_init(struct x86_mapping_info *info, pgd_t *pgd_page,
101 unsigned long addr, unsigned long end)
102{
103 unsigned long next;
104 int result;
105 int off = info->kernel_mapping ? pgd_index(__PAGE_OFFSET) : 0;
106
107 for (; addr < end; addr = next) {
108 pgd_t *pgd = pgd_page + pgd_index(addr) + off;
109 pud_t *pud;
110
111 next = (addr & PGDIR_MASK) + PGDIR_SIZE;
112 if (next > end)
113 next = end;
114
115 if (pgd_present(*pgd)) {
116 pud = pud_offset(pgd, 0);
117 result = ident_pud_init(info, pud, addr, next);
118 if (result)
119 return result;
120 continue;
121 }
122
123 pud = (pud_t *)info->alloc_pgt_page(info->context);
124 if (!pud)
125 return -ENOMEM;
126 result = ident_pud_init(info, pud, addr, next);
127 if (result)
128 return result;
129 set_pgd(pgd, __pgd(__pa(pud) | _KERNPG_TABLE));
130 }
131
132 return 0;
133}
134 62
135/* 63/*
136 * NOTE: pagetable_init alloc all the fixmap pagetables contiguous on the 64 * NOTE: pagetable_init alloc all the fixmap pagetables contiguous on the