Skip to content

Commit

Permalink
powerpc/47x: allow kernel to be loaded in higher physical memory
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Dave Kleikamp authored and Josh Boyer committed Jul 12, 2011
1 parent 3052091 commit 9661534
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 15 deletions.
2 changes: 1 addition & 1 deletion arch/powerpc/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -842,7 +842,7 @@ config LOWMEM_CAM_NUM

config RELOCATABLE
bool "Build a relocatable kernel (EXPERIMENTAL)"
depends on EXPERIMENTAL && ADVANCED_OPTIONS && FLATMEM && FSL_BOOKE
depends on EXPERIMENTAL && ADVANCED_OPTIONS && FLATMEM && (FSL_BOOKE || PPC_47x)
help
This builds a kernel image that is capable of running at the
location the kernel is loaded at (some alignment restrictions may
Expand Down
6 changes: 3 additions & 3 deletions arch/powerpc/configs/44x/iss476-smp_defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ CONFIG_SMP=y
CONFIG_EXPERIMENTAL=y
CONFIG_SYSVIPC=y
CONFIG_POSIX_MQUEUE=y
CONFIG_SPARSE_IRQ=y
CONFIG_LOG_BUF_SHIFT=14
CONFIG_SYSFS_DEPRECATED_V2=y
CONFIG_BLK_DEV_INITRD=y
# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
CONFIG_EXPERT=y
Expand All @@ -21,10 +21,11 @@ CONFIG_ISS4xx=y
CONFIG_HZ_100=y
CONFIG_MATH_EMULATION=y
CONFIG_IRQ_ALL_CPUS=y
CONFIG_SPARSE_IRQ=y
CONFIG_CMDLINE_BOOL=y
CONFIG_CMDLINE="root=/dev/issblk0"
# CONFIG_PCI is not set
CONFIG_ADVANCED_OPTIONS=y
CONFIG_RELOCATABLE=y
CONFIG_NET=y
CONFIG_PACKET=y
CONFIG_UNIX=y
Expand Down Expand Up @@ -67,7 +68,6 @@ CONFIG_EXT3_FS=y
# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
CONFIG_EXT3_FS_POSIX_ACL=y
CONFIG_EXT3_FS_SECURITY=y
CONFIG_INOTIFY=y
CONFIG_PROC_KCORE=y
CONFIG_TMPFS=y
CONFIG_CRAMFS=y
Expand Down
42 changes: 34 additions & 8 deletions arch/powerpc/kernel/head_44x.S
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,30 @@ _ENTRY(_start);

bl early_init

#ifdef CONFIG_RELOCATABLE
/*
* r25 will contain RPN/ERPN for the start address of memory
*
* Add the difference between KERNELBASE and PAGE_OFFSET to the
* start of physical memory to get kernstart_addr.
*/
lis r3,kernstart_addr@ha
la r3,kernstart_addr@l(r3)

lis r4,KERNELBASE@h
ori r4,r4,KERNELBASE@l
lis r5,PAGE_OFFSET@h
ori r5,r5,PAGE_OFFSET@l
subf r4,r5,r4

rlwinm r6,r25,0,28,31 /* ERPN */
rlwinm r7,r25,0,0,3 /* RPN - assuming 256 MB page size */
add r7,r7,r4

stw r6,0(r3)
stw r7,4(r3)
#endif

/*
* Decide what sort of machine this is and initialize the MMU.
*/
Expand Down Expand Up @@ -1001,9 +1025,6 @@ clear_utlb_entry:
lis r3,PAGE_OFFSET@h
ori r3,r3,PAGE_OFFSET@l

/* Kernel is at the base of RAM */
li r4, 0 /* Load the kernel physical address */

/* Load the kernel PID = 0 */
li r0,0
mtspr SPRN_PID,r0
Expand All @@ -1013,9 +1034,8 @@ clear_utlb_entry:
clrrwi r3,r3,12 /* Mask off the effective page number */
ori r3,r3,PPC47x_TLB0_VALID | PPC47x_TLB0_256M

/* Word 1 */
clrrwi r4,r4,12 /* Mask off the real page number */
/* ERPN is 0 for first 4GB page */
/* Word 1 - use r25. RPN is the same as the original entry */

/* Word 2 */
li r5,0
ori r5,r5,PPC47x_TLB2_S_RWX
Expand All @@ -1026,7 +1046,7 @@ clear_utlb_entry:
/* We write to way 0 and bolted 0 */
lis r0,0x8800
tlbwe r3,r0,0
tlbwe r4,r0,1
tlbwe r25,r0,1
tlbwe r5,r0,2

/*
Expand Down Expand Up @@ -1124,7 +1144,13 @@ head_start_common:
lis r4,interrupt_base@h /* IVPR only uses the high 16-bits */
mtspr SPRN_IVPR,r4

addis r22,r22,KERNELBASE@h
/*
* If the kernel was loaded at a non-zero 256 MB page, we need to
* mask off the most significant 4 bits to get the relative address
* from the start of physical memory
*/
rlwinm r22,r22,0,4,31
addis r22,r22,PAGE_OFFSET@h
mtlr r22
isync
blr
Expand Down
13 changes: 10 additions & 3 deletions arch/powerpc/mm/44x_mmu.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,10 +186,11 @@ void __init MMU_init_hw(void)
unsigned long __init mmu_mapin_ram(unsigned long top)
{
unsigned long addr;
unsigned long memstart = memstart_addr & ~(PPC_PIN_SIZE - 1);

/* Pin in enough TLBs to cover any lowmem not covered by the
* initial 256M mapping established in head_44x.S */
for (addr = PPC_PIN_SIZE; addr < lowmem_end_addr;
for (addr = memstart + PPC_PIN_SIZE; addr < lowmem_end_addr;
addr += PPC_PIN_SIZE) {
if (mmu_has_feature(MMU_FTR_TYPE_47x))
ppc47x_pin_tlb(addr + PAGE_OFFSET, addr);
Expand Down Expand Up @@ -218,19 +219,25 @@ unsigned long __init mmu_mapin_ram(unsigned long top)
void setup_initial_memory_limit(phys_addr_t first_memblock_base,
phys_addr_t first_memblock_size)
{
u64 size;

#ifndef CONFIG_RELOCATABLE
/* We don't currently support the first MEMBLOCK not mapping 0
* physical on those processors
*/
BUG_ON(first_memblock_base != 0);
#endif

/* 44x has a 256M TLB entry pinned at boot */
memblock_set_current_limit(min_t(u64, first_memblock_size, PPC_PIN_SIZE));
size = (min_t(u64, first_memblock_size, PPC_PIN_SIZE));
memblock_set_current_limit(first_memblock_base + size);
}

#ifdef CONFIG_SMP
void __cpuinit mmu_init_secondary(int cpu)
{
unsigned long addr;
unsigned long memstart = memstart_addr & ~(PPC_PIN_SIZE - 1);

/* Pin in enough TLBs to cover any lowmem not covered by the
* initial 256M mapping established in head_44x.S
Expand All @@ -241,7 +248,7 @@ void __cpuinit mmu_init_secondary(int cpu)
* stack. current (r2) isn't initialized, smp_processor_id()
* will not work, current thread info isn't accessible, ...
*/
for (addr = PPC_PIN_SIZE; addr < lowmem_end_addr;
for (addr = memstart + PPC_PIN_SIZE; addr < lowmem_end_addr;
addr += PPC_PIN_SIZE) {
if (mmu_has_feature(MMU_FTR_TYPE_47x))
ppc47x_pin_tlb(addr + PAGE_OFFSET, addr);
Expand Down

0 comments on commit 9661534

Please sign in to comment.