Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9661534d authored by Dave Kleikamp's avatar Dave Kleikamp Committed by Josh Boyer
Browse files

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: default avatarTony Breeds <tony@bakeyournoodle.com>
Signed-off-by: default avatarDave 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: default avatarJosh Boyer <jwboyer@linux.vnet.ibm.com>
parent 3052091c
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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
+3 −3
Original line number Diff line number Diff line
@@ -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
@@ -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
@@ -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
+34 −8
Original line number Diff line number Diff line
@@ -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.
 */
@@ -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
@@ -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
@@ -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

/*
@@ -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
+10 −3
Original line number Diff line number Diff line
@@ -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);
@@ -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
@@ -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);