aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Kleikamp <shaggy@linux.vnet.ibm.com>2011-07-04 14:36:57 -0400
committerJosh Boyer <jwboyer@linux.vnet.ibm.com>2011-07-12 10:34:24 -0400
commit9661534d6ad75f881d8bbeb73dd7372f41cbad99 (patch)
treed5614734cd9bbc6484eaf05996ee4dd2ef350873
parent3052091c67faee59fd12570e9f36971950b25216 (diff)
powerpc/47x: allow kernel to be loaded in higher physical memory
The 44x code (which is shared by 47x) assumes the available physical memory begins at 0x00000000. This is not necessarily the case in an AMP environment. Support CONFIG_RELOCATABLE for 476 in order to allow the kernel to be loaded into a higher memory range. Signed-off-by: Tony Breeds <tony@bakeyournoodle.com> Signed-off-by: Dave Kleikamp <shaggy@linux.vnet.ibm.com> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Josh Boyer <jwboyer@linux.vnet.ibm.com> Cc: linuxppc-dev@lists.ozlabs.org Signed-off-by: Josh Boyer <jwboyer@linux.vnet.ibm.com>
-rw-r--r--arch/powerpc/Kconfig2
-rw-r--r--arch/powerpc/configs/44x/iss476-smp_defconfig6
-rw-r--r--arch/powerpc/kernel/head_44x.S42
-rw-r--r--arch/powerpc/mm/44x_mmu.c13
4 files changed, 48 insertions, 15 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index c15f2e61e4fd..f8e578be5806 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -842,7 +842,7 @@ config LOWMEM_CAM_NUM
842 842
843config RELOCATABLE 843config RELOCATABLE
844 bool "Build a relocatable kernel (EXPERIMENTAL)" 844 bool "Build a relocatable kernel (EXPERIMENTAL)"
845 depends on EXPERIMENTAL && ADVANCED_OPTIONS && FLATMEM && FSL_BOOKE 845 depends on EXPERIMENTAL && ADVANCED_OPTIONS && FLATMEM && (FSL_BOOKE || PPC_47x)
846 help 846 help
847 This builds a kernel image that is capable of running at the 847 This builds a kernel image that is capable of running at the
848 location the kernel is loaded at (some alignment restrictions may 848 location the kernel is loaded at (some alignment restrictions may
diff --git a/arch/powerpc/configs/44x/iss476-smp_defconfig b/arch/powerpc/configs/44x/iss476-smp_defconfig
index 92f863ac8443..a6eb6ad05b2d 100644
--- a/arch/powerpc/configs/44x/iss476-smp_defconfig
+++ b/arch/powerpc/configs/44x/iss476-smp_defconfig
@@ -3,8 +3,8 @@ CONFIG_SMP=y
3CONFIG_EXPERIMENTAL=y 3CONFIG_EXPERIMENTAL=y
4CONFIG_SYSVIPC=y 4CONFIG_SYSVIPC=y
5CONFIG_POSIX_MQUEUE=y 5CONFIG_POSIX_MQUEUE=y
6CONFIG_SPARSE_IRQ=y
6CONFIG_LOG_BUF_SHIFT=14 7CONFIG_LOG_BUF_SHIFT=14
7CONFIG_SYSFS_DEPRECATED_V2=y
8CONFIG_BLK_DEV_INITRD=y 8CONFIG_BLK_DEV_INITRD=y
9# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set 9# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
10CONFIG_EXPERT=y 10CONFIG_EXPERT=y
@@ -21,10 +21,11 @@ CONFIG_ISS4xx=y
21CONFIG_HZ_100=y 21CONFIG_HZ_100=y
22CONFIG_MATH_EMULATION=y 22CONFIG_MATH_EMULATION=y
23CONFIG_IRQ_ALL_CPUS=y 23CONFIG_IRQ_ALL_CPUS=y
24CONFIG_SPARSE_IRQ=y
25CONFIG_CMDLINE_BOOL=y 24CONFIG_CMDLINE_BOOL=y
26CONFIG_CMDLINE="root=/dev/issblk0" 25CONFIG_CMDLINE="root=/dev/issblk0"
27# CONFIG_PCI is not set 26# CONFIG_PCI is not set
27CONFIG_ADVANCED_OPTIONS=y
28CONFIG_RELOCATABLE=y
28CONFIG_NET=y 29CONFIG_NET=y
29CONFIG_PACKET=y 30CONFIG_PACKET=y
30CONFIG_UNIX=y 31CONFIG_UNIX=y
@@ -67,7 +68,6 @@ CONFIG_EXT3_FS=y
67# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set 68# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
68CONFIG_EXT3_FS_POSIX_ACL=y 69CONFIG_EXT3_FS_POSIX_ACL=y
69CONFIG_EXT3_FS_SECURITY=y 70CONFIG_EXT3_FS_SECURITY=y
70CONFIG_INOTIFY=y
71CONFIG_PROC_KCORE=y 71CONFIG_PROC_KCORE=y
72CONFIG_TMPFS=y 72CONFIG_TMPFS=y
73CONFIG_CRAMFS=y 73CONFIG_CRAMFS=y
diff --git a/arch/powerpc/kernel/head_44x.S b/arch/powerpc/kernel/head_44x.S
index 5e12b741ba5f..f8e971ba94f5 100644
--- a/arch/powerpc/kernel/head_44x.S
+++ b/arch/powerpc/kernel/head_44x.S
@@ -93,6 +93,30 @@ _ENTRY(_start);
93 93
94 bl early_init 94 bl early_init
95 95
96#ifdef CONFIG_RELOCATABLE
97 /*
98 * r25 will contain RPN/ERPN for the start address of memory
99 *
100 * Add the difference between KERNELBASE and PAGE_OFFSET to the
101 * start of physical memory to get kernstart_addr.
102 */
103 lis r3,kernstart_addr@ha
104 la r3,kernstart_addr@l(r3)
105
106 lis r4,KERNELBASE@h
107 ori r4,r4,KERNELBASE@l
108 lis r5,PAGE_OFFSET@h
109 ori r5,r5,PAGE_OFFSET@l
110 subf r4,r5,r4
111
112 rlwinm r6,r25,0,28,31 /* ERPN */
113 rlwinm r7,r25,0,0,3 /* RPN - assuming 256 MB page size */
114 add r7,r7,r4
115
116 stw r6,0(r3)
117 stw r7,4(r3)
118#endif
119
96/* 120/*
97 * Decide what sort of machine this is and initialize the MMU. 121 * Decide what sort of machine this is and initialize the MMU.
98 */ 122 */
@@ -1001,9 +1025,6 @@ clear_utlb_entry:
1001 lis r3,PAGE_OFFSET@h 1025 lis r3,PAGE_OFFSET@h
1002 ori r3,r3,PAGE_OFFSET@l 1026 ori r3,r3,PAGE_OFFSET@l
1003 1027
1004 /* Kernel is at the base of RAM */
1005 li r4, 0 /* Load the kernel physical address */
1006
1007 /* Load the kernel PID = 0 */ 1028 /* Load the kernel PID = 0 */
1008 li r0,0 1029 li r0,0
1009 mtspr SPRN_PID,r0 1030 mtspr SPRN_PID,r0
@@ -1013,9 +1034,8 @@ clear_utlb_entry:
1013 clrrwi r3,r3,12 /* Mask off the effective page number */ 1034 clrrwi r3,r3,12 /* Mask off the effective page number */
1014 ori r3,r3,PPC47x_TLB0_VALID | PPC47x_TLB0_256M 1035 ori r3,r3,PPC47x_TLB0_VALID | PPC47x_TLB0_256M
1015 1036
1016 /* Word 1 */ 1037 /* Word 1 - use r25. RPN is the same as the original entry */
1017 clrrwi r4,r4,12 /* Mask off the real page number */ 1038
1018 /* ERPN is 0 for first 4GB page */
1019 /* Word 2 */ 1039 /* Word 2 */
1020 li r5,0 1040 li r5,0
1021 ori r5,r5,PPC47x_TLB2_S_RWX 1041 ori r5,r5,PPC47x_TLB2_S_RWX
@@ -1026,7 +1046,7 @@ clear_utlb_entry:
1026 /* We write to way 0 and bolted 0 */ 1046 /* We write to way 0 and bolted 0 */
1027 lis r0,0x8800 1047 lis r0,0x8800
1028 tlbwe r3,r0,0 1048 tlbwe r3,r0,0
1029 tlbwe r4,r0,1 1049 tlbwe r25,r0,1
1030 tlbwe r5,r0,2 1050 tlbwe r5,r0,2
1031 1051
1032/* 1052/*
@@ -1124,7 +1144,13 @@ head_start_common:
1124 lis r4,interrupt_base@h /* IVPR only uses the high 16-bits */ 1144 lis r4,interrupt_base@h /* IVPR only uses the high 16-bits */
1125 mtspr SPRN_IVPR,r4 1145 mtspr SPRN_IVPR,r4
1126 1146
1127 addis r22,r22,KERNELBASE@h 1147 /*
1148 * If the kernel was loaded at a non-zero 256 MB page, we need to
1149 * mask off the most significant 4 bits to get the relative address
1150 * from the start of physical memory
1151 */
1152 rlwinm r22,r22,0,4,31
1153 addis r22,r22,PAGE_OFFSET@h
1128 mtlr r22 1154 mtlr r22
1129 isync 1155 isync
1130 blr 1156 blr
diff --git a/arch/powerpc/mm/44x_mmu.c b/arch/powerpc/mm/44x_mmu.c
index 024acab588fd..f60e006d90c3 100644
--- a/arch/powerpc/mm/44x_mmu.c
+++ b/arch/powerpc/mm/44x_mmu.c
@@ -186,10 +186,11 @@ void __init MMU_init_hw(void)
186unsigned long __init mmu_mapin_ram(unsigned long top) 186unsigned long __init mmu_mapin_ram(unsigned long top)
187{ 187{
188 unsigned long addr; 188 unsigned long addr;
189 unsigned long memstart = memstart_addr & ~(PPC_PIN_SIZE - 1);
189 190
190 /* Pin in enough TLBs to cover any lowmem not covered by the 191 /* Pin in enough TLBs to cover any lowmem not covered by the
191 * initial 256M mapping established in head_44x.S */ 192 * initial 256M mapping established in head_44x.S */
192 for (addr = PPC_PIN_SIZE; addr < lowmem_end_addr; 193 for (addr = memstart + PPC_PIN_SIZE; addr < lowmem_end_addr;
193 addr += PPC_PIN_SIZE) { 194 addr += PPC_PIN_SIZE) {
194 if (mmu_has_feature(MMU_FTR_TYPE_47x)) 195 if (mmu_has_feature(MMU_FTR_TYPE_47x))
195 ppc47x_pin_tlb(addr + PAGE_OFFSET, addr); 196 ppc47x_pin_tlb(addr + PAGE_OFFSET, addr);
@@ -218,19 +219,25 @@ unsigned long __init mmu_mapin_ram(unsigned long top)
218void setup_initial_memory_limit(phys_addr_t first_memblock_base, 219void setup_initial_memory_limit(phys_addr_t first_memblock_base,
219 phys_addr_t first_memblock_size) 220 phys_addr_t first_memblock_size)
220{ 221{
222 u64 size;
223
224#ifndef CONFIG_RELOCATABLE
221 /* We don't currently support the first MEMBLOCK not mapping 0 225 /* We don't currently support the first MEMBLOCK not mapping 0
222 * physical on those processors 226 * physical on those processors
223 */ 227 */
224 BUG_ON(first_memblock_base != 0); 228 BUG_ON(first_memblock_base != 0);
229#endif
225 230
226 /* 44x has a 256M TLB entry pinned at boot */ 231 /* 44x has a 256M TLB entry pinned at boot */
227 memblock_set_current_limit(min_t(u64, first_memblock_size, PPC_PIN_SIZE)); 232 size = (min_t(u64, first_memblock_size, PPC_PIN_SIZE));
233 memblock_set_current_limit(first_memblock_base + size);
228} 234}
229 235
230#ifdef CONFIG_SMP 236#ifdef CONFIG_SMP
231void __cpuinit mmu_init_secondary(int cpu) 237void __cpuinit mmu_init_secondary(int cpu)
232{ 238{
233 unsigned long addr; 239 unsigned long addr;
240 unsigned long memstart = memstart_addr & ~(PPC_PIN_SIZE - 1);
234 241
235 /* Pin in enough TLBs to cover any lowmem not covered by the 242 /* Pin in enough TLBs to cover any lowmem not covered by the
236 * initial 256M mapping established in head_44x.S 243 * initial 256M mapping established in head_44x.S
@@ -241,7 +248,7 @@ void __cpuinit mmu_init_secondary(int cpu)
241 * stack. current (r2) isn't initialized, smp_processor_id() 248 * stack. current (r2) isn't initialized, smp_processor_id()
242 * will not work, current thread info isn't accessible, ... 249 * will not work, current thread info isn't accessible, ...
243 */ 250 */
244 for (addr = PPC_PIN_SIZE; addr < lowmem_end_addr; 251 for (addr = memstart + PPC_PIN_SIZE; addr < lowmem_end_addr;
245 addr += PPC_PIN_SIZE) { 252 addr += PPC_PIN_SIZE) {
246 if (mmu_has_feature(MMU_FTR_TYPE_47x)) 253 if (mmu_has_feature(MMU_FTR_TYPE_47x))
247 ppc47x_pin_tlb(addr + PAGE_OFFSET, addr); 254 ppc47x_pin_tlb(addr + PAGE_OFFSET, addr);