aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/include/asm/page.h85
-rw-r--r--arch/powerpc/mm/init_32.c7
2 files changed, 89 insertions, 3 deletions
diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h
index f149967ee6b5..f072e974f8a2 100644
--- a/arch/powerpc/include/asm/page.h
+++ b/arch/powerpc/include/asm/page.h
@@ -97,12 +97,26 @@ extern unsigned int HPAGE_SHIFT;
97 97
98extern phys_addr_t memstart_addr; 98extern phys_addr_t memstart_addr;
99extern phys_addr_t kernstart_addr; 99extern phys_addr_t kernstart_addr;
100
101#ifdef CONFIG_RELOCATABLE_PPC32
102extern long long virt_phys_offset;
100#endif 103#endif
104
105#endif /* __ASSEMBLY__ */
101#define PHYSICAL_START kernstart_addr 106#define PHYSICAL_START kernstart_addr
102#else 107
108#else /* !CONFIG_NONSTATIC_KERNEL */
103#define PHYSICAL_START ASM_CONST(CONFIG_PHYSICAL_START) 109#define PHYSICAL_START ASM_CONST(CONFIG_PHYSICAL_START)
104#endif 110#endif
105 111
112/* See Description below for VIRT_PHYS_OFFSET */
113#ifdef CONFIG_RELOCATABLE_PPC32
114#define VIRT_PHYS_OFFSET virt_phys_offset
115#else
116#define VIRT_PHYS_OFFSET (KERNELBASE - PHYSICAL_START)
117#endif
118
119
106#ifdef CONFIG_PPC64 120#ifdef CONFIG_PPC64
107#define MEMORY_START 0UL 121#define MEMORY_START 0UL
108#elif defined(CONFIG_NONSTATIC_KERNEL) 122#elif defined(CONFIG_NONSTATIC_KERNEL)
@@ -125,12 +139,77 @@ extern phys_addr_t kernstart_addr;
125 * determine MEMORY_START until then. However we can determine PHYSICAL_START 139 * determine MEMORY_START until then. However we can determine PHYSICAL_START
126 * from information at hand (program counter, TLB lookup). 140 * from information at hand (program counter, TLB lookup).
127 * 141 *
142 * On BookE with RELOCATABLE (RELOCATABLE_PPC32)
143 *
144 * With RELOCATABLE_PPC32, we support loading the kernel at any physical
145 * address without any restriction on the page alignment.
146 *
147 * We find the runtime address of _stext and relocate ourselves based on
148 * the following calculation:
149 *
150 * virtual_base = ALIGN_DOWN(KERNELBASE,256M) +
151 * MODULO(_stext.run,256M)
152 * and create the following mapping:
153 *
154 * ALIGN_DOWN(_stext.run,256M) => ALIGN_DOWN(KERNELBASE,256M)
155 *
156 * When we process relocations, we cannot depend on the
157 * existing equation for the __va()/__pa() translations:
158 *
159 * __va(x) = (x) - PHYSICAL_START + KERNELBASE
160 *
161 * Where:
162 * PHYSICAL_START = kernstart_addr = Physical address of _stext
163 * KERNELBASE = Compiled virtual address of _stext.
164 *
165 * This formula holds true iff, kernel load address is TLB page aligned.
166 *
167 * In our case, we need to also account for the shift in the kernel Virtual
168 * address.
169 *
170 * E.g.,
171 *
172 * Let the kernel be loaded at 64MB and KERNELBASE be 0xc0000000 (same as PAGE_OFFSET).
173 * In this case, we would be mapping 0 to 0xc0000000, and kernstart_addr = 64M
174 *
175 * Now __va(1MB) = (0x100000) - (0x4000000) + 0xc0000000
176 * = 0xbc100000 , which is wrong.
177 *
178 * Rather, it should be : 0xc0000000 + 0x100000 = 0xc0100000
179 * according to our mapping.
180 *
181 * Hence we use the following formula to get the translations right:
182 *
183 * __va(x) = (x) - [ PHYSICAL_START - Effective KERNELBASE ]
184 *
185 * Where :
186 * PHYSICAL_START = dynamic load address.(kernstart_addr variable)
187 * Effective KERNELBASE = virtual_base =
188 * = ALIGN_DOWN(KERNELBASE,256M) +
189 * MODULO(PHYSICAL_START,256M)
190 *
191 * To make the cost of __va() / __pa() more light weight, we introduce
192 * a new variable virt_phys_offset, which will hold :
193 *
194 * virt_phys_offset = Effective KERNELBASE - PHYSICAL_START
195 * = ALIGN_DOWN(KERNELBASE,256M) -
196 * ALIGN_DOWN(PHYSICALSTART,256M)
197 *
198 * Hence :
199 *
200 * __va(x) = x - PHYSICAL_START + Effective KERNELBASE
201 * = x + virt_phys_offset
202 *
203 * and
204 * __pa(x) = x + PHYSICAL_START - Effective KERNELBASE
205 * = x - virt_phys_offset
206 *
128 * On non-Book-E PPC64 PAGE_OFFSET and MEMORY_START are constants so use 207 * On non-Book-E PPC64 PAGE_OFFSET and MEMORY_START are constants so use
129 * the other definitions for __va & __pa. 208 * the other definitions for __va & __pa.
130 */ 209 */
131#ifdef CONFIG_BOOKE 210#ifdef CONFIG_BOOKE
132#define __va(x) ((void *)(unsigned long)((phys_addr_t)(x) - PHYSICAL_START + KERNELBASE)) 211#define __va(x) ((void *)(unsigned long)((phys_addr_t)(x) + VIRT_PHYS_OFFSET))
133#define __pa(x) ((unsigned long)(x) + PHYSICAL_START - KERNELBASE) 212#define __pa(x) ((unsigned long)(x) - VIRT_PHYS_OFFSET)
134#else 213#else
135#define __va(x) ((void *)(unsigned long)((phys_addr_t)(x) + PAGE_OFFSET - MEMORY_START)) 214#define __va(x) ((void *)(unsigned long)((phys_addr_t)(x) + PAGE_OFFSET - MEMORY_START))
136#define __pa(x) ((unsigned long)(x) - PAGE_OFFSET + MEMORY_START) 215#define __pa(x) ((unsigned long)(x) - PAGE_OFFSET + MEMORY_START)
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
index 161cefde5c15..60a4e4e84e8c 100644
--- a/arch/powerpc/mm/init_32.c
+++ b/arch/powerpc/mm/init_32.c
@@ -65,6 +65,13 @@ phys_addr_t memstart_addr = (phys_addr_t)~0ull;
65EXPORT_SYMBOL(memstart_addr); 65EXPORT_SYMBOL(memstart_addr);
66phys_addr_t kernstart_addr; 66phys_addr_t kernstart_addr;
67EXPORT_SYMBOL(kernstart_addr); 67EXPORT_SYMBOL(kernstart_addr);
68
69#ifdef CONFIG_RELOCATABLE_PPC32
70/* Used in __va()/__pa() */
71long long virt_phys_offset;
72EXPORT_SYMBOL(virt_phys_offset);
73#endif
74
68phys_addr_t lowmem_end_addr; 75phys_addr_t lowmem_end_addr;
69 76
70int boot_mapsize; 77int boot_mapsize;