Lines 39-45
Link Here
|
39 |
#include <asm/fixmap.h> |
39 |
#include <asm/fixmap.h> |
40 |
|
40 |
|
41 |
static pgd_t save_pgd __initdata; |
41 |
static pgd_t save_pgd __initdata; |
42 |
static unsigned long efi_flags __initdata; |
42 |
static DEFINE_PER_CPU(unsigned long, efi_flags); |
|
|
43 |
static DEFINE_PER_CPU(unsigned long, save_cr3); |
44 |
static pgd_t efi_pgd[PTRS_PER_PGD] __page_aligned_bss; |
43 |
|
45 |
|
44 |
static void __init early_mapping_set_exec(unsigned long start, |
46 |
static void __init early_mapping_set_exec(unsigned long start, |
45 |
unsigned long end, |
47 |
unsigned long end, |
Lines 80-86
void __init efi_call_phys_prelog(void)
Link Here
|
80 |
unsigned long vaddress; |
82 |
unsigned long vaddress; |
81 |
|
83 |
|
82 |
early_runtime_code_mapping_set_exec(1); |
84 |
early_runtime_code_mapping_set_exec(1); |
83 |
local_irq_save(efi_flags); |
85 |
local_irq_save(get_cpu_var(efi_flags)); |
84 |
vaddress = (unsigned long)__va(0x0UL); |
86 |
vaddress = (unsigned long)__va(0x0UL); |
85 |
save_pgd = *pgd_offset_k(0x0UL); |
87 |
save_pgd = *pgd_offset_k(0x0UL); |
86 |
set_pgd(pgd_offset_k(0x0UL), *pgd_offset_k(vaddress)); |
88 |
set_pgd(pgd_offset_k(0x0UL), *pgd_offset_k(vaddress)); |
Lines 94-103
void __init efi_call_phys_epilog(void)
Link Here
|
94 |
*/ |
96 |
*/ |
95 |
set_pgd(pgd_offset_k(0x0UL), save_pgd); |
97 |
set_pgd(pgd_offset_k(0x0UL), save_pgd); |
96 |
__flush_tlb_all(); |
98 |
__flush_tlb_all(); |
97 |
local_irq_restore(efi_flags); |
99 |
local_irq_restore(get_cpu_var(efi_flags)); |
98 |
early_runtime_code_mapping_set_exec(0); |
100 |
early_runtime_code_mapping_set_exec(0); |
99 |
} |
101 |
} |
100 |
|
102 |
|
|
|
103 |
void efi_call_phys_prelog_in_physmode(void) |
104 |
{ |
105 |
local_irq_save(get_cpu_var(efi_flags)); |
106 |
get_cpu_var(save_cr3)= read_cr3(); |
107 |
write_cr3(virt_to_phys(efi_pgd)); |
108 |
} |
109 |
|
110 |
void efi_call_phys_epilog_in_physmode(void) |
111 |
{ |
112 |
write_cr3(get_cpu_var(save_cr3)); |
113 |
local_irq_restore(get_cpu_var(efi_flags)); |
114 |
} |
115 |
|
101 |
void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size, |
116 |
void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size, |
102 |
u32 type) |
117 |
u32 type) |
103 |
{ |
118 |
{ |
Lines 112-114
void __iomem *__init efi_ioremap(unsigned long phys_addr, unsigned long size,
Link Here
|
112 |
|
127 |
|
113 |
return (void __iomem *)__va(phys_addr); |
128 |
return (void __iomem *)__va(phys_addr); |
114 |
} |
129 |
} |
|
|
130 |
|
131 |
static pud_t *fill_pud(pgd_t *pgd, unsigned long vaddr) |
132 |
{ |
133 |
if (pgd_none(*pgd)) { |
134 |
pud_t *pud = (pud_t *)get_zeroed_page(GFP_ATOMIC); |
135 |
set_pgd(pgd, __pgd(_PAGE_TABLE | __pa(pud))); |
136 |
if (pud != pud_offset(pgd, 0)) |
137 |
printk(KERN_ERR "EFI PAGETABLE BUG #00! %p <-> %p\n", |
138 |
pud, pud_offset(pgd, 0)); |
139 |
} |
140 |
return pud_offset(pgd, vaddr); |
141 |
} |
142 |
|
143 |
static pmd_t *fill_pmd(pud_t *pud, unsigned long vaddr) |
144 |
{ |
145 |
if (pud_none(*pud)) { |
146 |
pmd_t *pmd = (pmd_t *)get_zeroed_page(GFP_ATOMIC); |
147 |
set_pud(pud, __pud(_PAGE_TABLE | __pa(pmd))); |
148 |
if (pmd != pmd_offset(pud, 0)) |
149 |
printk(KERN_ERR "EFI PAGETABLE BUG #01! %p <-> %p\n", |
150 |
pmd, pmd_offset(pud, 0)); |
151 |
} |
152 |
return pmd_offset(pud, vaddr); |
153 |
} |
154 |
|
155 |
static pte_t *fill_pte(pmd_t *pmd, unsigned long vaddr) |
156 |
{ |
157 |
if (pmd_none(*pmd)) { |
158 |
pte_t *pte = (pte_t *)get_zeroed_page(GFP_ATOMIC); |
159 |
set_pmd(pmd, __pmd(_PAGE_TABLE | __pa(pte))); |
160 |
if (pte != pte_offset_kernel(pmd, 0)) |
161 |
printk(KERN_ERR "EFI PAGETABLE BUG #02!\n"); |
162 |
} |
163 |
return pte_offset_kernel(pmd, vaddr); |
164 |
} |
165 |
|
166 |
void __init efi_pagetable_init(void) |
167 |
{ |
168 |
efi_memory_desc_t *md; |
169 |
unsigned long size; |
170 |
u64 start_pfn, end_pfn, pfn, vaddr; |
171 |
void *p; |
172 |
pgd_t *pgd; |
173 |
pud_t *pud; |
174 |
pmd_t *pmd; |
175 |
pte_t *pte; |
176 |
|
177 |
memset(efi_pgd, 0, sizeof(efi_pgd)); |
178 |
for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) { |
179 |
md = p; |
180 |
if (!(md->type & EFI_RUNTIME_SERVICES_CODE) && |
181 |
!(md->type & EFI_RUNTIME_SERVICES_DATA)) |
182 |
continue; |
183 |
|
184 |
start_pfn = md->phys_addr >> PAGE_SHIFT; |
185 |
size = md->num_pages << EFI_PAGE_SHIFT; |
186 |
end_pfn = PFN_UP(md->phys_addr + size); |
187 |
|
188 |
for (pfn = start_pfn; pfn <= end_pfn; pfn++) { |
189 |
vaddr = pfn << PAGE_SHIFT; |
190 |
pgd = efi_pgd + pgd_index(vaddr); |
191 |
pud = fill_pud(pgd, vaddr); |
192 |
pmd = fill_pmd(pud, vaddr); |
193 |
pte = fill_pte(pmd, vaddr); |
194 |
if (md->type & EFI_RUNTIME_SERVICES_CODE) |
195 |
set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC)); |
196 |
else |
197 |
set_pte(pte, pfn_pte(pfn, PAGE_KERNEL)); |
198 |
} |
199 |
} |
200 |
pgd = efi_pgd + pgd_index(PAGE_OFFSET); |
201 |
set_pgd(pgd, *pgd_offset_k(PAGE_OFFSET)); |
202 |
pgd = efi_pgd + pgd_index(__START_KERNEL_map); |
203 |
set_pgd(pgd, *pgd_offset_k(__START_KERNEL_map)); |
204 |
} |