LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH 5/5 try2] ib/ehca: discard double CQE for one WR
From: Roland Dreier @ 2008-08-12 18:35 UTC (permalink / raw)
  To: Alexander Schmidt
  Cc: Joachim Fenkes, of-ewg, lkml, linuxppc-dev, Christoph Raisch,
	of-general, Stefan Roscher
In-Reply-To: <200808121546.31057.alexs@linux.vnet.ibm.com>

thanks, applied all 5.

^ permalink raw reply

* [PATCH 1/1] powerpc: Fix vio_bus_probe oops on probe error
From: Brian King @ 2008-08-12 19:21 UTC (permalink / raw)
  To: paulus; +Cc: brking, linuxppc-dev


When CMO is enabled and booted on a non CMO system and
the VIO device's probe function fails, an oops can result
since vio_cmo_bus_remove is called when it should not.

cpu 0x0: Vector: 300 (Data Access) at [c00000000e13b3d0]
    pc: c000000000020d34: .vio_cmo_bus_remove+0xc0/0x1f4
    lr: c000000000020ca4: .vio_cmo_bus_remove+0x30/0x1f4
    sp: c00000000e13b650
   msr: 8000000000009032
   dar: 0
 dsisr: 40000000
  current = 0xc00000000e0566c0
  paca    = 0xc0000000006f9b80
    pid   = 2428, comm = modprobe
enter ? for help
[c00000000e13b6e0] c000000000021d94 .vio_bus_probe+0x2f8/0x33c
[c00000000e13b7a0] c00000000029fc88 .driver_probe_device+0x13c/0x200
[c00000000e13b830] c00000000029fdac .__driver_attach+0x60/0xa4
[c00000000e13b8c0] c00000000029f050 .bus_for_each_dev+0x80/0xd8
[c00000000e13b980] c00000000029f9ec .driver_attach+0x28/0x40
[c00000000e13ba00] c00000000029f630 .bus_add_driver+0xd4/0x284
[c00000000e13baa0] c0000000002a01bc .driver_register+0xc4/0x198
[c00000000e13bb50] c00000000002168c .vio_register_driver+0x40/0x5c
[c00000000e13bbe0] d0000000003b3f1c .ibmvfc_module_init+0x70/0x109c [ibmvfc]
[c00000000e13bc70] c0000000000acf08 .sys_init_module+0x184c/0x1a10
[c00000000e13be30] c000000000008748 syscall_exit+0x0/0x40

Signed-off-by: Brian King <brking@linux.vnet.ibm.com>
---

 arch/powerpc/kernel/vio.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff -puN arch/powerpc/kernel/vio.c~powerpc_vio_bus_probe_error arch/powerpc/kernel/vio.c
--- linux-2.6/arch/powerpc/kernel/vio.c~powerpc_vio_bus_probe_error	2008-08-12 13:43:02.000000000 -0500
+++ linux-2.6-bjking1/arch/powerpc/kernel/vio.c	2008-08-12 13:43:56.000000000 -0500
@@ -1113,7 +1113,7 @@ static int vio_bus_probe(struct device *
 				return error;
 		}
 		error = viodrv->probe(viodev, id);
-		if (error)
+		if (error && firmware_has_feature(FW_FEATURE_CMO))
 			vio_cmo_bus_remove(viodev);
 	}
 
_

^ permalink raw reply

* Re: [RFC/PATCH 1/3] powerpc: add ioremap_bat() function for setting up BAT translated IO regions.
From: Grant Likely @ 2008-08-12 19:50 UTC (permalink / raw)
  To: Kumar Gala; +Cc: paulus, miltonm, linuxppc-dev
In-Reply-To: <8A11E9B3-4B7D-48CF-ABAB-625050D8FFFE@kernel.crashing.org>

On Thu, Aug 07, 2008 at 07:04:04PM -0500, Kumar Gala wrote:
>> mem_init_done isn't a good indication. We can do page tables when it's
>> 0, we would have to use a separate mem_preinit_done or something :-)
>>
>> I initially also though about a flag to ioremap_prot to be honest. But
>> it does obfuscate the normal ioremap code path and if there's a flag,
>> that means that callers know the difference and thus may as well call
>> a separate function, don't you think ?
>
> I'm ok with exposing a separate function as far as the API goes.. I'm  
> not ok with duplicating the logic of __ioremap().

Turns out there is very little actual duplication of code with
__ioremap().  The checks for p_mapped_by_* are the same, but all the
alignment checks are different because different boundaries are used.

I attempted to break things down to a common function, but there is not
a lot there.  But I will add a function to manage modification of
ioremap_bot.

g.

^ permalink raw reply

* [PATCH] gianfar: Call gfar_halt_nodisable() from gfar_halt().
From: Scott Wood @ 2008-08-12 20:10 UTC (permalink / raw)
  To: jgarzik; +Cc: netdev, linuxppc-dev

gfar_halt() was factored out into halting and disabling by commit
d87eb12785c14de1586e3bad86ca2c0991300339, as the suspend() method
only wants to do the former.  However, the call to gfar_halt_nodisable()
from gfar_halt() apparently got lost during the patch respin process.

This adds it back.

Signed-off-by: Scott Wood <scottwood@freescale.com>
---
 drivers/net/gianfar.c |    6 ++----
 1 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c
index ca6cf6e..999d691 100644
--- a/drivers/net/gianfar.c
+++ b/drivers/net/gianfar.c
@@ -134,9 +134,7 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int l
 static void gfar_vlan_rx_register(struct net_device *netdev,
 		                struct vlan_group *grp);
 void gfar_halt(struct net_device *dev);
-#ifdef CONFIG_PM
 static void gfar_halt_nodisable(struct net_device *dev);
-#endif
 void gfar_start(struct net_device *dev);
 static void gfar_clear_exact_match(struct net_device *dev);
 static void gfar_set_mac_for_addr(struct net_device *dev, int num, u8 *addr);
@@ -631,7 +629,6 @@ static void init_registers(struct net_device *dev)
 }
 
 
-#ifdef CONFIG_PM
 /* Halt the receive and transmit queues */
 static void gfar_halt_nodisable(struct net_device *dev)
 {
@@ -657,7 +654,6 @@ static void gfar_halt_nodisable(struct net_device *dev)
 			cpu_relax();
 	}
 }
-#endif
 
 /* Halt the receive and transmit queues */
 void gfar_halt(struct net_device *dev)
@@ -666,6 +662,8 @@ void gfar_halt(struct net_device *dev)
 	struct gfar __iomem *regs = priv->regs;
 	u32 tempval;
 
+	gfar_halt_nodisable(dev);
+
 	/* Disable Rx and Tx */
 	tempval = gfar_read(&regs->maccfg1);
 	tempval &= ~(MACCFG1_RX_EN | MACCFG1_TX_EN);
-- 
1.5.6.rc1.6.gc53ad.dirty

^ permalink raw reply related

* Re: [PATCH] powerpc: some vmlinux files that should be ignored
From: Michael Neuling @ 2008-08-12 20:11 UTC (permalink / raw)
  To: Sean MacLennan; +Cc: linuxppc-dev
In-Reply-To: <20080811185629.11ed547f@lappy.seanm.ca>

In message <20080811185629.11ed547f@lappy.seanm.ca> you wrote:
> A couple of vmlinux output files that should be ignored: vmlinux.strip
> and vmlinux.lds.
> 
> Signed-off-by: Sean MacLennan <smaclennan@pikatech.com>
> ---
> diff --git a/.gitignore b/.gitignore

This will need to goto LKML.

Mikey

> index 869e1a3..f7e924a 100644
> --- a/.gitignore
> +++ b/.gitignore
> @@ -32,6 +32,7 @@
>  tags
>  TAGS
>  vmlinux
> +vmlinux.strip
>  System.map
>  Module.markers
>  Module.symvers
> diff --git a/arch/powerpc/kernel/.gitignore b/arch/powerpc/kernel/.gitignore
> new file mode 100644
> index 0000000..c5f676c
> --- /dev/null
> +++ b/arch/powerpc/kernel/.gitignore
> @@ -0,0 +1 @@
> +vmlinux.lds
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
> 

^ permalink raw reply

* [PATCH] remove redundant sysfs_remove_file calls for cache info
From: Nathan Lynch @ 2008-08-12 21:34 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Paul Mackerras

When removing a directory, the sysfs core takes care of removing files
in the directory (see sysfs_remove_dir()).  So when we are about to
delete a kobject (and thus cause its sysfs directory to be removed),
we don't have to explicitly remove the files attached to it, although
it's harmless to do so.

Signed-off-by: Nathan Lynch <ntl@pobox.com>
---
 arch/powerpc/kernel/sysfs.c |   11 ++---------
 1 files changed, 2 insertions(+), 9 deletions(-)

diff --git a/arch/powerpc/kernel/sysfs.c b/arch/powerpc/kernel/sysfs.c
index 56d172d..12058db 100644
--- a/arch/powerpc/kernel/sysfs.c
+++ b/arch/powerpc/kernel/sysfs.c
@@ -641,16 +641,9 @@ static void remove_cache_info(struct sys_device *sysdev)
 	int cpu = sysdev->id;
 
 	cache_desc = per_cpu(cache_desc, cpu);
-	if (cache_desc != NULL) {
-		sysfs_remove_file(&cache_desc->kobj, &cache_size_attr.attr);
-		sysfs_remove_file(&cache_desc->kobj, &cache_line_size_attr.attr);
-		sysfs_remove_file(&cache_desc->kobj, &cache_type_attr.attr);
-		sysfs_remove_file(&cache_desc->kobj, &cache_level_attr.attr);
-		sysfs_remove_file(&cache_desc->kobj, &cache_nr_sets_attr.attr);
-		sysfs_remove_file(&cache_desc->kobj, &cache_assoc_attr.attr);
-
+	if (cache_desc != NULL)
 		kobject_put(&cache_desc->kobj);
-	}
+
 	cache_toplevel = per_cpu(cache_toplevel, cpu);
 	if (cache_toplevel != NULL)
 		kobject_put(cache_toplevel);
-- 
1.5.5

^ permalink raw reply related

* ml507 initrd problem
From: Stu Bershtein @ 2008-08-12 23:28 UTC (permalink / raw)
  To: linuxppc-embedded

[-- Attachment #1: Type: text/plain, Size: 1554 bytes --]

I have been trying to boot linux on an ml507 board for a few days now.
I am using xilinx's linux-2.6-xlnx.git kernel.  The rootfs is home
rolled.  I have had experience with NFS mounted root filesystems (not an
option here), cramfs, and romfs but have never tried running root out of
a ramdisk.  Because of that I am quite sure I have dorked this up.  Any
help will be appreciated!  I have added printk's in the kernel at
do_sys_open to get an idea what is going on.  Here is a snip of the boot
output:

 

.

Kernel command line: console=ttyS0,9600 ip=on init=/linuxrc
root=/dev/ram rw ram disk_size=9000

.

Serial: 8250/16550 driver $Revision: 1.90 $ 4 ports, IRQ sharing
disabled 83e00000.serial: ttyS0 at MMIO 0x83e00003 (irq = 16) is a
16550A

.

eth0: XLlTemac: Send Threshold = 0, Receive Threshold = 0

eth0: XLlTemac: Send Wait bound = 0, Receive Wait bound = 0

IP-Config: Incomplete network configuration information.

open /dev/ram

fd 0

open /initrd.image

fd 1

RAMDISK: Compressed image found at block 0

VFS: Mounted root (ext2 filesystem).

Freeing unused kernel memory: 144k init

open /dev/console

fd 0

code 10000000 - 1019854c, data 10195000 - 1019854c, stack bf85df00

open /dev/null

fd 3

open /etc/inittab

fd 3

 

And it gets very quiet at that point.  The kernel is still running in
ppc44x_idle.  Does this suggest anything to anyone?  I'll be more than
happy to send or describe any config files to any one who might take
pity.

 

Thanks,

Stu

 


[-- Attachment #2: Type: text/html, Size: 7720 bytes --]

^ permalink raw reply

* Re: ml507 initrd problem
From: Philipp Hachtmann @ 2008-08-13  0:41 UTC (permalink / raw)
  To: linuxppc-embedded; +Cc: Stu Bershtein
In-Reply-To: <8BB04FAC749BD24BBA250E9D09F2F18B220ABB@MAIL-SJC.quantum3d.com>


> *RAMDISK: Compressed image found at block 0*
> *VFS: Mounted root (ext2 filesystem).*
> *Freeing unused kernel memory: 144k init*
That looks normal.

> *open /dev/console*
> *fd 0*
> *code 10000000 - 1019854c, data 10195000 - 1019854c, stack bf85df00*
> *open /dev/null*
> *fd 3*
> *open /etc/inittab*
> *fd 3*
I don't know that stuff.

 > *And it gets very quiet at that point.  The kernel is still running in
 > ppc44x_idle.  Does this suggest anything to anyone?  I’ll be more than
 > happy to send or describe any config files to any one who might take 
pity.*

One question: What is in your /linuxrc? Do you have a shell in your 
initrd? What about booting into your shell with init=</path/to/shell>?


Regards,
Philipp


-- 
http://www.hachti.de

^ permalink raw reply

* [PATCH 0/5] Relocatable 64-bit kernel using linker PIE support
From: Paul Mackerras @ 2008-08-13  1:27 UTC (permalink / raw)
  To: linuxppc-dev

The following series of patches implement support for a relocatable
kernel by building it as a position-independent executable (PIE).
When the linker is given the -pie flag, it creates an executable that
contains dynamic relocations which can be used to relocate the image
at boot time for any desired base address.  This patch series adds a
CONFIG_RELOCATABLE config option for 64-bit which links the kernel
with -pie and arranges to process the relocations in early boot.

With the first 4 patches applied, a relocatable kernel will still copy
itself down to real address 0.  The last patch changes things so that
a relocatable kernel will run wherever it was loaded.  This last patch
is pretty much just a proof of concept since it doesn't do anything to
ensure appropriate alignment of the base address (the base address
needs to be 16kB aligned).  We probably want to work out whether we
are a kdump kernel and run in-place if so, or copy down to 0 if not.

Paul.

^ permalink raw reply

* [PATCH 1/5] powerpc: Move interrupt handler code to the beginning of head_64.S
From: Paul Mackerras @ 2008-08-13  1:28 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <18594.14443.340604.693747@cargo.ozlabs.ibm.com>

This rearranges head_64.S so that we have all the first-level exception
prologs together starting at 0x100, followed by all the second-level
handlers that are invoked from the first-level prologs, followed by
other code.  This doesn't make any functional change but will make
following changes for relocatable kernel support easier.

Signed-off-by: Paul Mackerras <paulus@samba.org>
---
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index cc8fb47..27935d1 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -325,16 +325,32 @@ do_stab_bolted_pSeries:
 	mfspr	r12,SPRN_SPRG2
 	EXCEPTION_PROLOG_PSERIES(PACA_EXSLB, .do_stab_bolted)
 
+#ifdef CONFIG_PPC_PSERIES
+/*
+ * Vectors for the FWNMI option.  Share common code.
+ */
+	.globl system_reset_fwnmi
+      .align 7
+system_reset_fwnmi:
+	HMT_MEDIUM
+	mtspr	SPRN_SPRG1,r13		/* save r13 */
+	EXCEPTION_PROLOG_PSERIES(PACA_EXGEN, system_reset_common)
+
+	.globl machine_check_fwnmi
+      .align 7
+machine_check_fwnmi:
+	HMT_MEDIUM
+	mtspr	SPRN_SPRG1,r13		/* save r13 */
+	EXCEPTION_PROLOG_PSERIES(PACA_EXMC, machine_check_common)
+
+#endif /* CONFIG_PPC_PSERIES */
+
+#ifdef __DISABLED__
 /*
- * We have some room here  we use that to put
- * the peries slb miss user trampoline code so it's reasonably
- * away from slb_miss_user_common to avoid problems with rfid
- *
  * This is used for when the SLB miss handler has to go virtual,
  * which doesn't happen for now anymore but will once we re-implement
  * dynamic VSIDs for shared page tables
  */
-#ifdef __DISABLED__
 slb_miss_user_pseries:
 	std	r10,PACA_EXGEN+EX_R10(r13)
 	std	r11,PACA_EXGEN+EX_R11(r13)
@@ -357,25 +373,14 @@ slb_miss_user_pseries:
 	b	.				/* prevent spec. execution */
 #endif /* __DISABLED__ */
 
-#ifdef CONFIG_PPC_PSERIES
+	.align	7
+	.globl	__end_interrupts
+__end_interrupts:
+
 /*
- * Vectors for the FWNMI option.  Share common code.
+ * Code from here down to __end_handlers is invoked from the
+ * exception prologs above.
  */
-	.globl system_reset_fwnmi
-      .align 7
-system_reset_fwnmi:
-	HMT_MEDIUM
-	mtspr	SPRN_SPRG1,r13		/* save r13 */
-	EXCEPTION_PROLOG_PSERIES_FORCE_64BIT(PACA_EXGEN, system_reset_common)
-
-	.globl machine_check_fwnmi
-      .align 7
-machine_check_fwnmi:
-	HMT_MEDIUM
-	mtspr	SPRN_SPRG1,r13		/* save r13 */
-	EXCEPTION_PROLOG_PSERIES_FORCE_64BIT(PACA_EXMC, machine_check_common)
-
-#endif /* CONFIG_PPC_PSERIES */
 
 /*** Common interrupt handlers ***/
 
@@ -457,65 +462,6 @@ bad_stack:
 	b	1b
 
 /*
- * Return from an exception with minimal checks.
- * The caller is assumed to have done EXCEPTION_PROLOG_COMMON.
- * If interrupts have been enabled, or anything has been
- * done that might have changed the scheduling status of
- * any task or sent any task a signal, you should use
- * ret_from_except or ret_from_except_lite instead of this.
- */
-fast_exc_return_irq:			/* restores irq state too */
-	ld	r3,SOFTE(r1)
-	TRACE_AND_RESTORE_IRQ(r3);
-	ld	r12,_MSR(r1)
-	rldicl	r4,r12,49,63		/* get MSR_EE to LSB */
-	stb	r4,PACAHARDIRQEN(r13)	/* restore paca->hard_enabled */
-	b	1f
-
-	.globl	fast_exception_return
-fast_exception_return:
-	ld	r12,_MSR(r1)
-1:	ld	r11,_NIP(r1)
-	andi.	r3,r12,MSR_RI		/* check if RI is set */
-	beq-	unrecov_fer
-
-#ifdef CONFIG_VIRT_CPU_ACCOUNTING
-	andi.	r3,r12,MSR_PR
-	beq	2f
-	ACCOUNT_CPU_USER_EXIT(r3, r4)
-2:
-#endif
-
-	ld	r3,_CCR(r1)
-	ld	r4,_LINK(r1)
-	ld	r5,_CTR(r1)
-	ld	r6,_XER(r1)
-	mtcr	r3
-	mtlr	r4
-	mtctr	r5
-	mtxer	r6
-	REST_GPR(0, r1)
-	REST_8GPRS(2, r1)
-
-	mfmsr	r10
-	rldicl	r10,r10,48,1		/* clear EE */
-	rldicr	r10,r10,16,61		/* clear RI (LE is 0 already) */
-	mtmsrd	r10,1
-
-	mtspr	SPRN_SRR1,r12
-	mtspr	SPRN_SRR0,r11
-	REST_4GPRS(10, r1)
-	ld	r1,GPR1(r1)
-	rfid
-	b	.	/* prevent speculative execution */
-
-unrecov_fer:
-	bl	.save_nvgprs
-1:	addi	r3,r1,STACK_FRAME_OVERHEAD
-	bl	.unrecoverable_exception
-	b	1b
-
-/*
  * Here r13 points to the paca, r9 contains the saved CR,
  * SRR0 and SRR1 are saved in r11 and r12,
  * r9 - r13 are saved in paca->exgen.
@@ -766,6 +712,85 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 	bl	.altivec_unavailable_exception
 	b	.ret_from_except
 
+	.align	7
+	.globl vsx_unavailable_common
+vsx_unavailable_common:
+	EXCEPTION_PROLOG_COMMON(0xf40, PACA_EXGEN)
+#ifdef CONFIG_VSX
+BEGIN_FTR_SECTION
+	bne	.load_up_vsx
+1:
+END_FTR_SECTION_IFSET(CPU_FTR_VSX)
+#endif
+	bl	.save_nvgprs
+	addi	r3,r1,STACK_FRAME_OVERHEAD
+	ENABLE_INTS
+	bl	.vsx_unavailable_exception
+	b	.ret_from_except
+
+	.align	7
+	.globl	__end_handlers
+__end_handlers:
+
+/*
+ * Return from an exception with minimal checks.
+ * The caller is assumed to have done EXCEPTION_PROLOG_COMMON.
+ * If interrupts have been enabled, or anything has been
+ * done that might have changed the scheduling status of
+ * any task or sent any task a signal, you should use
+ * ret_from_except or ret_from_except_lite instead of this.
+ */
+fast_exc_return_irq:			/* restores irq state too */
+	ld	r3,SOFTE(r1)
+	TRACE_AND_RESTORE_IRQ(r3);
+	ld	r12,_MSR(r1)
+	rldicl	r4,r12,49,63		/* get MSR_EE to LSB */
+	stb	r4,PACAHARDIRQEN(r13)	/* restore paca->hard_enabled */
+	b	1f
+
+	.globl	fast_exception_return
+fast_exception_return:
+	ld	r12,_MSR(r1)
+1:	ld	r11,_NIP(r1)
+	andi.	r3,r12,MSR_RI		/* check if RI is set */
+	beq-	unrecov_fer
+
+#ifdef CONFIG_VIRT_CPU_ACCOUNTING
+	andi.	r3,r12,MSR_PR
+	beq	2f
+	ACCOUNT_CPU_USER_EXIT(r3, r4)
+2:
+#endif
+
+	ld	r3,_CCR(r1)
+	ld	r4,_LINK(r1)
+	ld	r5,_CTR(r1)
+	ld	r6,_XER(r1)
+	mtcr	r3
+	mtlr	r4
+	mtctr	r5
+	mtxer	r6
+	REST_GPR(0, r1)
+	REST_8GPRS(2, r1)
+
+	mfmsr	r10
+	rldicl	r10,r10,48,1		/* clear EE */
+	rldicr	r10,r10,16,61		/* clear RI (LE is 0 already) */
+	mtmsrd	r10,1
+
+	mtspr	SPRN_SRR1,r12
+	mtspr	SPRN_SRR0,r11
+	REST_4GPRS(10, r1)
+	ld	r1,GPR1(r1)
+	rfid
+	b	.	/* prevent speculative execution */
+
+unrecov_fer:
+	bl	.save_nvgprs
+1:	addi	r3,r1,STACK_FRAME_OVERHEAD
+	bl	.unrecoverable_exception
+	b	1b
+
 #ifdef CONFIG_ALTIVEC
 /*
  * load_up_altivec(unused, unused, tsk)
@@ -840,22 +865,6 @@ _STATIC(load_up_altivec)
 	blr
 #endif /* CONFIG_ALTIVEC */
 
-	.align	7
-	.globl vsx_unavailable_common
-vsx_unavailable_common:
-	EXCEPTION_PROLOG_COMMON(0xf40, PACA_EXGEN)
-#ifdef CONFIG_VSX
-BEGIN_FTR_SECTION
-	bne	.load_up_vsx
-1:
-END_FTR_SECTION_IFSET(CPU_FTR_VSX)
-#endif
-	bl	.save_nvgprs
-	addi	r3,r1,STACK_FRAME_OVERHEAD
-	ENABLE_INTS
-	bl	.vsx_unavailable_exception
-	b	.ret_from_except
-
 #ifdef CONFIG_VSX
 /*
  * load_up_vsx(unused, unused, tsk)

^ permalink raw reply related

* [PATCH 2/5] powerpc: Make it possible to move the interrupt handlers away from the kernel
From: Paul Mackerras @ 2008-08-13  1:29 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <18594.14443.340604.693747@cargo.ozlabs.ibm.com>

This changes the way that the exception prologs transfer control to
the handlers in 64-bit kernels with the aim of making it possible to
have the prologs separate from the main body of the kernel.  Now,
instead of computing the address of the handler by taking the top
32 bits of the paca address (to get the 0xc0000000........ part) and
ORing in something in the bottom 16 bits, we get the base address of
the kernel by doing a load from the paca and add an offset.

This also replaces an mfmsr and an ori to compute the MSR value for
the handler with a load from the paca.  That makes it unnecessary to
have a separate version of EXCEPTION_PROLOG_PSERIES that forces 64-bit
mode.

We can no longer use a direct branches in the exception prolog code,
which means that the SLB miss handlers can't branch directly to
.slb_miss_realmode any more.  Instead we have to compute the address
and do an indirect branch.

Since the secondary CPUs on pSeries start execution in the first 0x100
bytes of real memory and then have to get to wherever the kernel is,
we can't use a direct branch to get there.  Instead this changes
__secondary_hold_spinloop from a flag to a function pointer.  When it
is set to a non-NULL value, the secondary CPUs jump to the function
pointed to by that value.

Finally this eliminates one code difference between 32-bit and 64-bit
by making __secondary_hold be the text address of the secondary CPU
spinloop rather than a function descriptor for it.

Signed-off-by: Paul Mackerras <paulus@samba.org>
---
diff --git a/arch/powerpc/include/asm/exception.h b/arch/powerpc/include/asm/exception.h
index 329148b..d3d4534 100644
--- a/arch/powerpc/include/asm/exception.h
+++ b/arch/powerpc/include/asm/exception.h
@@ -53,14 +53,8 @@
  * low halfword of the address, but for Kdump we need the whole low
  * word.
  */
-#ifdef CONFIG_CRASH_DUMP
 #define LOAD_HANDLER(reg, label)					\
-	oris	reg,reg,(label)@h;	/* virt addr of handler ... */	\
-	ori	reg,reg,(label)@l;	/* .. and the rest */
-#else
-#define LOAD_HANDLER(reg, label)					\
-	ori	reg,reg,(label)@l;	/* virt addr of handler ... */
-#endif
+	addi	reg,reg,(label)-_stext;	/* virt addr of handler ... */
 
 #define EXCEPTION_PROLOG_1(area)				\
 	mfspr	r13,SPRN_SPRG3;		/* get paca address into r13 */	\
@@ -72,37 +66,12 @@
 	std	r9,area+EX_R13(r13);					\
 	mfcr	r9
 
-/*
- * Equal to EXCEPTION_PROLOG_PSERIES, except that it forces 64bit mode.
- * The firmware calls the registered system_reset_fwnmi and
- * machine_check_fwnmi handlers in 32bit mode if the cpu happens to run
- * a 32bit application at the time of the event.
- * This firmware bug is present on POWER4 and JS20.
- */
-#define EXCEPTION_PROLOG_PSERIES_FORCE_64BIT(area, label)		\
-	EXCEPTION_PROLOG_1(area);					\
-	clrrdi	r12,r13,32;		/* get high part of &label */	\
-	mfmsr	r10;							\
-	/* force 64bit mode */						\
-	li	r11,5;			/* MSR_SF_LG|MSR_ISF_LG */	\
-	rldimi	r10,r11,61,0;		/* insert into top 3 bits */	\
-	/* done 64bit mode */						\
-	mfspr	r11,SPRN_SRR0;		/* save SRR0 */			\
-	LOAD_HANDLER(r12,label)						\
-	ori	r10,r10,MSR_IR|MSR_DR|MSR_RI;				\
-	mtspr	SPRN_SRR0,r12;						\
-	mfspr	r12,SPRN_SRR1;		/* and SRR1 */			\
-	mtspr	SPRN_SRR1,r10;						\
-	rfid;								\
-	b	.	/* prevent speculative execution */
-
 #define EXCEPTION_PROLOG_PSERIES(area, label)				\
 	EXCEPTION_PROLOG_1(area);					\
-	clrrdi	r12,r13,32;		/* get high part of &label */	\
-	mfmsr	r10;							\
+	ld	r12,PACAKBASE(r13);	/* get high part of &label */	\
+	ld	r10,PACAKMSR(r13);	/* get MSR value for kernel */	\
 	mfspr	r11,SPRN_SRR0;		/* save SRR0 */			\
 	LOAD_HANDLER(r12,label)						\
-	ori	r10,r10,MSR_IR|MSR_DR|MSR_RI;				\
 	mtspr	SPRN_SRR0,r12;						\
 	mfspr	r12,SPRN_SRR1;		/* and SRR1 */			\
 	mtspr	SPRN_SRR1,r10;						\
@@ -210,11 +179,10 @@ label##_pSeries:							\
 	std	r10,PACA_EXGEN+EX_R13(r13);				\
 	std	r11,PACA_EXGEN+EX_R11(r13);				\
 	std	r12,PACA_EXGEN+EX_R12(r13);				\
-	clrrdi	r12,r13,32;		/* get high part of &label */	\
-	mfmsr	r10;							\
+	ld	r12,PACAKBASE(r13);	/* get high part of &label */	\
+	ld	r10,PACAKMSR(r13);	/* get MSR value for kernel */	\
 	mfspr	r11,SPRN_SRR0;		/* save SRR0 */			\
 	LOAD_HANDLER(r12,label##_common)				\
-	ori	r10,r10,MSR_IR|MSR_DR|MSR_RI;				\
 	mtspr	SPRN_SRR0,r12;						\
 	mfspr	r12,SPRN_SRR1;		/* and SRR1 */			\
 	mtspr	SPRN_SRR1,r10;						\
diff --git a/arch/powerpc/include/asm/paca.h b/arch/powerpc/include/asm/paca.h
index 6493a39..082b3ae 100644
--- a/arch/powerpc/include/asm/paca.h
+++ b/arch/powerpc/include/asm/paca.h
@@ -62,6 +62,8 @@ struct paca_struct {
 	u16 paca_index;			/* Logical processor number */
 
 	u64 kernel_toc;			/* Kernel TOC address */
+	u64 kernelbase;			/* Base address of kernel */
+	u64 kernel_msr;			/* MSR while running in kernel */
 	u64 stab_real;			/* Absolute address of segment table */
 	u64 stab_addr;			/* Virtual address of segment table */
 	void *emergency_sp;		/* pointer to emergency stack */
diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
index 92768d3..e9c4044 100644
--- a/arch/powerpc/kernel/asm-offsets.c
+++ b/arch/powerpc/kernel/asm-offsets.c
@@ -122,6 +122,8 @@ int main(void)
 	DEFINE(PACASTABRR, offsetof(struct paca_struct, stab_rr));
 	DEFINE(PACAR1, offsetof(struct paca_struct, saved_r1));
 	DEFINE(PACATOC, offsetof(struct paca_struct, kernel_toc));
+	DEFINE(PACAKBASE, offsetof(struct paca_struct, kernelbase));
+	DEFINE(PACAKMSR, offsetof(struct paca_struct, kernel_msr));
 	DEFINE(PACASOFTIRQEN, offsetof(struct paca_struct, soft_enabled));
 	DEFINE(PACAHARDIRQEN, offsetof(struct paca_struct, hard_enabled));
 	DEFINE(PACASLBCACHE, offsetof(struct paca_struct, slb_cache));
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 27935d1..229ccd1 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -82,7 +82,11 @@ END_FTR_SECTION(0, 1)
 	/* Catch branch to 0 in real mode */
 	trap
 
-	/* Secondary processors spin on this value until it goes to 1. */
+	/* Secondary processors spin on this value until it becomes nonzero.
+	 * When it does it contains the real address of the descriptor
+	 * of the function that the cpu should jump to to continue
+	 * initialization.
+	 */
 	.globl  __secondary_hold_spinloop
 __secondary_hold_spinloop:
 	.llong	0x0
@@ -109,8 +113,11 @@ __secondary_hold_acknowledge:
  * before the bulk of the kernel has been relocated.  This code
  * is relocated to physical address 0x60 before prom_init is run.
  * All of it must fit below the first exception vector at 0x100.
+ * Use .globl here not _GLOBAL because we want __secondary_hold
+ * to be the actual text address, not a descriptor.
  */
-_GLOBAL(__secondary_hold)
+	.globl	__secondary_hold
+__secondary_hold:
 	mfmsr	r24
 	ori	r24,r24,MSR_RI
 	mtmsrd	r24			/* RI on */
@@ -126,11 +133,11 @@ _GLOBAL(__secondary_hold)
 
 	/* All secondary cpus wait here until told to start. */
 100:	ld	r4,__secondary_hold_spinloop@l(0)
-	cmpdi	0,r4,1
-	bne	100b
+	cmpdi	0,r4,0
+	beq	100b
 
 #if defined(CONFIG_SMP) || defined(CONFIG_KEXEC)
-	LOAD_REG_IMMEDIATE(r4, .generic_secondary_smp_init)
+	ld	r4,0(r4)		/* deref function descriptor */
 	mtctr	r4
 	mr	r3,r24
 	bctr
@@ -147,6 +154,10 @@ exception_marker:
 /*
  * This is the start of the interrupt handlers for pSeries
  * This code runs with relocation off.
+ * Code from here to __end_interrupts gets copied down to real
+ * address 0x100 when we are running a relocatable kernel.
+ * Therefore any relative branches in this section must only
+ * branch to labels in this section.
  */
 	. = 0x100
 	.globl __start_interrupts
@@ -200,7 +211,16 @@ data_access_slb_pSeries:
 	mfspr	r10,SPRN_SPRG1
 	std	r10,PACA_EXSLB+EX_R13(r13)
 	mfspr	r12,SPRN_SRR1		/* and SRR1 */
-	b	.slb_miss_realmode	/* Rel. branch works in real mode */
+	/*
+	 * We can't just use a direct branch to .slb_miss_realmode
+	 * because the distance from here to there depends on where
+	 * the kernel ends up being put.
+	 */
+	mfctr	r11
+	ld	r10,PACAKBASE(r13)
+	LOAD_HANDLER(r10, .slb_miss_realmode)
+	mtctr	r10
+	bctr
 
 	STD_EXCEPTION_PSERIES(0x400, instruction_access)
 
@@ -225,7 +245,12 @@ instruction_access_slb_pSeries:
 	mfspr	r10,SPRN_SPRG1
 	std	r10,PACA_EXSLB+EX_R13(r13)
 	mfspr	r12,SPRN_SRR1		/* and SRR1 */
-	b	.slb_miss_realmode	/* Rel. branch works in real mode */
+	mfctr	r11
+	ld	r10,PACAKBASE(r13)
+	LOAD_HANDLER(r10, .slb_miss_realmode)
+	mtctr	r10
+	bctr
+
 
 	MASKABLE_EXCEPTION_PSERIES(0x500, hardware_interrupt)
 	STD_EXCEPTION_PSERIES(0x600, alignment)
@@ -244,14 +269,12 @@ BEGIN_FTR_SECTION
 	beq-	1f
 END_FTR_SECTION_IFSET(CPU_FTR_REAL_LE)
 	mr	r9,r13
-	mfmsr	r10
 	mfspr	r13,SPRN_SPRG3
 	mfspr	r11,SPRN_SRR0
-	clrrdi	r12,r13,32
-	oris	r12,r12,system_call_common@h
-	ori	r12,r12,system_call_common@l
+	ld	r12,PACAKBASE(r13)
+	ld	r10,PACAKMSR(r13)
+	LOAD_HANDLER(r12, system_call_entry)
 	mtspr	SPRN_SRR0,r12
-	ori	r10,r10,MSR_IR|MSR_DR|MSR_RI
 	mfspr	r12,SPRN_SRR1
 	mtspr	SPRN_SRR1,r10
 	rfid
@@ -379,7 +402,12 @@ __end_interrupts:
 
 /*
  * Code from here down to __end_handlers is invoked from the
- * exception prologs above.
+ * exception prologs above.  Because the prologs assemble the
+ * addresses of these handlers using the LOAD_HANDLER macro,
+ * which uses an addi instruction, these handlers must be in
+ * the first 32k of the kernel image.  (This restriction could
+ * be lifted if we used an addis + addi in LOAD_HANDLER instead
+ * of just an addi.)
  */
 
 /*** Common interrupt handlers ***/
@@ -419,6 +447,10 @@ machine_check_common:
 	STD_EXCEPTION_COMMON(0x1800, cbe_thermal, .cbe_thermal_exception)
 #endif /* CONFIG_CBE_RAS */
 
+	.align	7
+system_call_entry:
+	b	system_call_common
+
 /*
  * Here we have detected that the kernel stack pointer is bad.
  * R9 contains the saved CR, r13 points to the paca,
@@ -562,6 +594,7 @@ unrecov_user_slb:
  */
 _GLOBAL(slb_miss_realmode)
 	mflr	r10
+	mtctr	r11
 
 	stw	r9,PACA_EXSLB+EX_CCR(r13)	/* save CR in exc. frame */
 	std	r10,PACA_EXSLB+EX_LR(r13)	/* save LR */
@@ -612,11 +645,10 @@ BEGIN_FW_FTR_SECTION
 END_FW_FTR_SECTION_IFSET(FW_FEATURE_ISERIES)
 #endif /* CONFIG_PPC_ISERIES */
 	mfspr	r11,SPRN_SRR0
-	clrrdi	r10,r13,32
+	ld	r10,PACAKBASE(r13)
 	LOAD_HANDLER(r10,unrecov_slb)
 	mtspr	SPRN_SRR0,r10
-	mfmsr	r10
-	ori	r10,r10,MSR_IR|MSR_DR|MSR_RI
+	ld	r10,PACAKMSR(r13)
 	mtspr	SPRN_SRR1,r10
 	rfid
 	b	.
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
index c9bf17e..623e8c3 100644
--- a/arch/powerpc/kernel/paca.c
+++ b/arch/powerpc/kernel/paca.c
@@ -79,6 +79,8 @@ void __init initialise_pacas(void)
 		new_paca->lock_token = 0x8000;
 		new_paca->paca_index = cpu;
 		new_paca->kernel_toc = kernel_toc;
+		new_paca->kernelbase = KERNELBASE;
+		new_paca->kernel_msr = MSR_KERNEL;
 		new_paca->hw_cpu_id = 0xffff;
 		new_paca->slb_shadow_ptr = &slb_shadow[cpu];
 		new_paca->__current = &init_task;
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index b72849a..1f89885 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -1321,7 +1321,7 @@ static void __init prom_initialize_tce_table(void)
  *
  * -- Cort
  */
-extern void __secondary_hold(void);
+extern char __secondary_hold;
 extern unsigned long __secondary_hold_spinloop;
 extern unsigned long __secondary_hold_acknowledge;
 
@@ -1342,13 +1342,7 @@ static void __init prom_hold_cpus(void)
 		= (void *) LOW_ADDR(__secondary_hold_spinloop);
 	unsigned long *acknowledge
 		= (void *) LOW_ADDR(__secondary_hold_acknowledge);
-#ifdef CONFIG_PPC64
-	/* __secondary_hold is actually a descriptor, not the text address */
-	unsigned long secondary_hold
-		= __pa(*PTRRELOC((unsigned long *)__secondary_hold));
-#else
 	unsigned long secondary_hold = LOW_ADDR(__secondary_hold);
-#endif
 
 	prom_debug("prom_hold_cpus: start...\n");
 	prom_debug("    1) spinloop       = 0x%x\n", (unsigned long)spinloop);
diff --git a/arch/powerpc/kernel/setup_64.c b/arch/powerpc/kernel/setup_64.c
index 8b25f51..843c0af 100644
--- a/arch/powerpc/kernel/setup_64.c
+++ b/arch/powerpc/kernel/setup_64.c
@@ -255,9 +255,11 @@ void early_setup_secondary(void)
 #endif /* CONFIG_SMP */
 
 #if defined(CONFIG_SMP) || defined(CONFIG_KEXEC)
+extern unsigned long __secondary_hold_spinloop;
+extern void generic_secondary_smp_init(void);
+
 void smp_release_cpus(void)
 {
-	extern unsigned long __secondary_hold_spinloop;
 	unsigned long *ptr;
 
 	DBG(" -> smp_release_cpus()\n");
@@ -266,12 +268,11 @@ void smp_release_cpus(void)
 	 * all now so they can start to spin on their individual paca
 	 * spinloops. For non SMP kernels, the secondary cpus never get out
 	 * of the common spinloop.
-	 * This is useless but harmless on iSeries, secondaries are already
-	 * waiting on their paca spinloops. */
+	 */
 
 	ptr  = (unsigned long *)((unsigned long)&__secondary_hold_spinloop
 			- PHYSICAL_START);
-	*ptr = 1;
+	*ptr = __pa(generic_secondary_smp_init);
 	mb();
 
 	DBG(" <- smp_release_cpus()\n");

^ permalink raw reply related

* [PATCH 3/5] powerpc: Only use LOAD_REG_IMMEDIATE for constants on 64-bit
From: Paul Mackerras @ 2008-08-13  1:30 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <18594.14443.340604.693747@cargo.ozlabs.ibm.com>

Using LOAD_REG_IMMEDIATE to get the address of kernel symbols
generates 5 instructions where LOAD_REG_ADDR can do it in one,
and will generate R_PPC64_ADDR16_* relocations in the output when
we get to making the kernel as a position-independent executable,
which we'd rather not have to handle.  This changes various bits
of assembly code to use LOAD_REG_ADDR when we need to get the
address of a symbol, or to use suitable position-independent code
for cases where we can't access the TOC for various reasons, or
if we're not running at the address we were linked at.

It also cleans up a few minor things; there's no reason to save and
restore SRR0/1 around RTAS calls, __mmu_off can get the return
address from LR more conveniently than the caller can supply it in
R4 (and we already assume elsewhere that EA == RA if the MMU is on
in early boot), and enable_64b_mode was using 5 instructions where
2 would do.

Signed-off-by: Paul Mackerras <paulus@samba.org>
---
diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index 0966899..c4a029c 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -268,7 +268,7 @@ n:
  *   Loads the value of the constant expression 'expr' into register 'rn'
  *   using immediate instructions only.  Use this when it's important not
  *   to reference other data (i.e. on ppc64 when the TOC pointer is not
- *   valid).
+ *   valid) and when 'expr' is a constant or absolute address.
  *
  * LOAD_REG_ADDR(rn, name)
  *   Loads the address of label 'name' into register 'rn'.  Use this when
diff --git a/arch/powerpc/kernel/cpu_setup_ppc970.S b/arch/powerpc/kernel/cpu_setup_ppc970.S
index bf118c3..27f2507 100644
--- a/arch/powerpc/kernel/cpu_setup_ppc970.S
+++ b/arch/powerpc/kernel/cpu_setup_ppc970.S
@@ -110,7 +110,7 @@ load_hids:
 	isync
 
 	/* Save away cpu state */
-	LOAD_REG_IMMEDIATE(r5,cpu_state_storage)
+	LOAD_REG_ADDR(r5,cpu_state_storage)
 
 	/* Save HID0,1,4 and 5 */
 	mfspr	r3,SPRN_HID0
@@ -134,7 +134,7 @@ _GLOBAL(__restore_cpu_ppc970)
 	rldicl.	r0,r0,4,63
 	beqlr
 
-	LOAD_REG_IMMEDIATE(r5,cpu_state_storage)
+	LOAD_REG_ADDR(r5,cpu_state_storage)
 	/* Before accessing memory, we make sure rm_ci is clear */
 	li	r0,0
 	mfspr	r3,SPRN_HID4
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index 2d802e9..5a8619f 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -685,10 +685,6 @@ _GLOBAL(enter_rtas)
 	std	r7,_DAR(r1)
 	mfdsisr	r8
 	std	r8,_DSISR(r1)
-	mfsrr0	r9
-	std	r9,_SRR0(r1)
-	mfsrr1	r10
-	std	r10,_SRR1(r1)
 
 	/* Temporary workaround to clear CR until RTAS can be modified to
 	 * ignore all bits.
@@ -749,6 +745,10 @@ _STATIC(rtas_return_loc)
 	mfspr	r4,SPRN_SPRG3	        /* Get PACA */
 	clrldi	r4,r4,2			/* convert to realmode address */
 
+	bcl	20,31,$+4
+0:	mflr	r3
+	ld	r3,(1f-0b)(r3)		/* get &.rtas_restore_regs */
+
 	mfmsr   r6
 	li	r0,MSR_RI
 	andc	r6,r6,r0
@@ -756,7 +756,6 @@ _STATIC(rtas_return_loc)
 	mtmsrd  r6
         
         ld	r1,PACAR1(r4)           /* Restore our SP */
-	LOAD_REG_IMMEDIATE(r3,.rtas_restore_regs)
         ld	r4,PACASAVEDMSR(r4)     /* Restore our MSR */
 
 	mtspr	SPRN_SRR0,r3
@@ -764,6 +763,8 @@ _STATIC(rtas_return_loc)
 	rfid
 	b	.	/* prevent speculative execution */
 
+1:	.llong	.rtas_restore_regs
+
 _STATIC(rtas_restore_regs)
 	/* relocation is on at this point */
 	REST_GPR(2, r1)			/* Restore the TOC */
@@ -783,10 +784,6 @@ _STATIC(rtas_restore_regs)
 	mtdar	r7
 	ld	r8,_DSISR(r1)
 	mtdsisr	r8
-	ld	r9,_SRR0(r1)
-	mtsrr0	r9
-	ld	r10,_SRR1(r1)
-	mtsrr1	r10
 
         addi	r1,r1,RTAS_FRAME_SIZE	/* Unstack our frame */
 	ld	r0,16(r1)		/* get return address */
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 229ccd1..afbd530 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -128,11 +128,11 @@ __secondary_hold:
 	/* Tell the master cpu we're here */
 	/* Relocation is off & we are located at an address less */
 	/* than 0x100, so only need to grab low order offset.    */
-	std	r24,__secondary_hold_acknowledge@l(0)
+	std	r24,__secondary_hold_acknowledge-_stext(0)
 	sync
 
 	/* All secondary cpus wait here until told to start. */
-100:	ld	r4,__secondary_hold_spinloop@l(0)
+100:	ld	r4,__secondary_hold_spinloop-_stext(0)
 	cmpdi	0,r4,0
 	beq	100b
 
@@ -1216,11 +1216,14 @@ _GLOBAL(generic_secondary_smp_init)
 	/* turn on 64-bit mode */
 	bl	.enable_64b_mode
 
+	/* get the TOC pointer (real address) */
+	bl	.relative_toc
+
 	/* Set up a paca value for this processor. Since we have the
 	 * physical cpu id in r24, we need to search the pacas to find
 	 * which logical id maps to our physical one.
 	 */
-	LOAD_REG_IMMEDIATE(r13, paca)	/* Get base vaddr of paca array	 */
+	LOAD_REG_ADDR(r13, paca)	/* Get base vaddr of paca array	 */
 	li	r5,0			/* logical cpu id                */
 1:	lhz	r6,PACAHWCPUID(r13)	/* Load HW procid from paca      */
 	cmpw	r6,r24			/* Compare to our id             */
@@ -1249,7 +1252,7 @@ _GLOBAL(generic_secondary_smp_init)
 	sync				/* order paca.run and cur_cpu_spec */
 
 	/* See if we need to call a cpu state restore handler */
-	LOAD_REG_IMMEDIATE(r23, cur_cpu_spec)
+	LOAD_REG_ADDR(r23, cur_cpu_spec)
 	ld	r23,0(r23)
 	ld	r23,CPU_SPEC_RESTORE(r23)
 	cmpdi	0,r23,0
@@ -1265,10 +1268,15 @@ _GLOBAL(generic_secondary_smp_init)
 	b	__secondary_start
 #endif
 
+/*
+ * Turn the MMU off.
+ * Assumes we're mapped EA == RA if the MMU is on.
+ */
 _STATIC(__mmu_off)
 	mfmsr	r3
 	andi.	r0,r3,MSR_IR|MSR_DR
 	beqlr
+	mflr	r4
 	andc	r3,r3,r0
 	mtspr	SPRN_SRR0,r4
 	mtspr	SPRN_SRR1,r3
@@ -1289,6 +1297,18 @@ _STATIC(__mmu_off)
  *
  */
 _GLOBAL(__start_initialization_multiplatform)
+	/* Make sure we are running in 64 bits mode */
+	bl	.enable_64b_mode
+
+	/* Get TOC pointer (current runtime address) */
+	bl	.relative_toc
+
+	/* find out where we are now */
+	bcl	20,31,$+4
+0:	mflr	r26			/* r26 = runtime addr here */
+	addis	r26,r26,(_stext - 0b)@ha
+	addi	r26,r26,(_stext - 0b)@l	/* current runtime base addr */
+
 	/*
 	 * Are we booted from a PROM Of-type client-interface ?
 	 */
@@ -1300,9 +1320,6 @@ _GLOBAL(__start_initialization_multiplatform)
 	mr	r31,r3
 	mr	r30,r4
 
-	/* Make sure we are running in 64 bits mode */
-	bl	.enable_64b_mode
-
 	/* Setup some critical 970 SPRs before switching MMU off */
 	mfspr	r0,SPRN_PVR
 	srwi	r0,r0,16
@@ -1317,9 +1334,7 @@ _GLOBAL(__start_initialization_multiplatform)
 1:	bl	.__cpu_preinit_ppc970
 2:
 
-	/* Switch off MMU if not already */
-	LOAD_REG_IMMEDIATE(r4, .__after_prom_start - KERNELBASE)
-	add	r4,r4,r30
+	/* Switch off MMU if not already off */
 	bl	.__mmu_off
 	b	.__after_prom_start
 
@@ -1334,23 +1349,10 @@ _INIT_STATIC(__boot_from_prom)
 	/*
 	 * Align the stack to 16-byte boundary
 	 * Depending on the size and layout of the ELF sections in the initial
-	 * boot binary, the stack pointer will be unalignet on PowerMac
+	 * boot binary, the stack pointer may be unaligned on PowerMac
 	 */
 	rldicr	r1,r1,0,59
 
-	/* Make sure we are running in 64 bits mode */
-	bl	.enable_64b_mode
-
-	/* put a relocation offset into r3 */
-	bl	.reloc_offset
-
-	LOAD_REG_IMMEDIATE(r2,__toc_start)
-	addi	r2,r2,0x4000
-	addi	r2,r2,0x4000
-
-	/* Relocate the TOC from a virt addr to a real addr */
-	add	r2,r2,r3
-
 	/* Restore parameters */
 	mr	r3,r31
 	mr	r4,r30
@@ -1366,53 +1368,37 @@ _INIT_STATIC(__boot_from_prom)
 _STATIC(__after_prom_start)
 
 /*
- * We need to run with __start at physical address PHYSICAL_START.
+ * We need to run with _stext at physical address PHYSICAL_START.
  * This will leave some code in the first 256B of
  * real memory, which are reserved for software use.
- * The remainder of the first page is loaded with the fixed
- * interrupt vectors.  The next two pages are filled with
- * unknown exception placeholders.
  *
  * Note: This process overwrites the OF exception vectors.
- *	r26 == relocation offset
- *	r27 == KERNELBASE
  */
-	bl	.reloc_offset
-	mr	r26,r3
-	LOAD_REG_IMMEDIATE(r27, KERNELBASE)
-
 	LOAD_REG_IMMEDIATE(r3, PHYSICAL_START)	/* target addr */
-
-	// XXX FIXME: Use phys returned by OF (r30)
-	add	r4,r27,r26 		/* source addr			 */
-					/* current address of _start	 */
-					/*   i.e. where we are running	 */
-					/*	the source addr		 */
-
-	cmpdi	r4,0			/* In some cases the loader may  */
-	bne	1f
-	b	.start_here_multiplatform /* have already put us at zero */
-					/* so we can skip the copy.      */
-1:	LOAD_REG_IMMEDIATE(r5,copy_to_here) /* # bytes of memory to copy */
-	sub	r5,r5,r27
-
+	cmpd	r3,r26			/* In some cases the loader may  */
+	beq	9f			/* have already put us at zero */
+	mr	r4,r26			/* source address */
+	lis	r5,(copy_to_here - _stext)@ha
+	addi	r5,r5,(copy_to_here - _stext)@l /* # bytes of memory to copy */
 	li	r6,0x100		/* Start offset, the first 0x100 */
 					/* bytes were copied earlier.	 */
 
 	bl	.copy_and_flush		/* copy the first n bytes	 */
 					/* this includes the code being	 */
 					/* executed here.		 */
-
-	LOAD_REG_IMMEDIATE(r0, 4f)	/* Jump to the copy of this code */
-	mtctr	r0			/* that we just made/relocated	 */
+	addis	r8,r3,(4f - _stext)@ha	/* Jump to the copy of this code */
+	addi	r8,r8,(4f - _stext)@l	/* that we just made */
+	mtctr	r8
 	bctr
 
-4:	LOAD_REG_IMMEDIATE(r5,klimit)
-	add	r5,r5,r26
-	ld	r5,0(r5)		/* get the value of klimit */
-	sub	r5,r5,r27
+4:	/* Now copy the rest of the kernel up to _end */
+	addis	r5,r26,(p_end - _stext)@ha
+	ld	r5,(p_end - _stext)@l(r5)	/* get _end */
 	bl	.copy_and_flush		/* copy the rest */
-	b	.start_here_multiplatform
+
+9:	b	.start_here_multiplatform
+
+p_end:	.llong	_end - _stext
 
 /*
  * Copy routine used to copy the kernel to start at physical address 0
@@ -1477,6 +1463,9 @@ _GLOBAL(pmac_secondary_start)
 	/* turn on 64-bit mode */
 	bl	.enable_64b_mode
 
+	/* get TOC pointer (real address) */
+	bl	.relative_toc
+
 	/* Copy some CPU settings from CPU 0 */
 	bl	.__restore_cpu_ppc970
 
@@ -1486,10 +1475,10 @@ _GLOBAL(pmac_secondary_start)
 	mtmsrd	r3			/* RI on */
 
 	/* Set up a paca value for this processor. */
-	LOAD_REG_IMMEDIATE(r4, paca)	/* Get base vaddr of paca array	*/
-	mulli	r13,r24,PACA_SIZE	 /* Calculate vaddr of right paca */
+	LOAD_REG_ADDR(r4,paca)		/* Get base vaddr of paca array	*/
+	mulli	r13,r24,PACA_SIZE	/* Calculate vaddr of right paca */
 	add	r13,r13,r4		/* for this processor.		*/
-	mtspr	SPRN_SPRG3,r13		 /* Save vaddr of paca in SPRG3	*/
+	mtspr	SPRN_SPRG3,r13		/* Save vaddr of paca in SPRG3	*/
 
 	/* Create a temp kernel stack for use before relocation is on.	*/
 	ld	r1,PACAEMERGSP(r13)
@@ -1517,9 +1506,6 @@ __secondary_start:
 	/* Set thread priority to MEDIUM */
 	HMT_MEDIUM
 
-	/* Load TOC */
-	ld	r2,PACATOC(r13)
-
 	/* Do early setup for that CPU (stab, slb, hash table pointer) */
 	bl	.early_setup_secondary
 
@@ -1556,9 +1542,11 @@ END_FW_FTR_SECTION_IFCLR(FW_FEATURE_ISERIES)
 
 /* 
  * Running with relocation on at this point.  All we want to do is
- * zero the stack back-chain pointer before going into C code.
+ * zero the stack back-chain pointer and get the TOC virtual address
+ * before going into C code.
  */
 _GLOBAL(start_secondary_prolog)
+	ld	r2,PACATOC(r13)
 	li	r3,0
 	std	r3,0(r1)		/* Zero the stack frame pointer	*/
 	bl	.start_secondary
@@ -1570,34 +1558,46 @@ _GLOBAL(start_secondary_prolog)
  */
 _GLOBAL(enable_64b_mode)
 	mfmsr	r11			/* grab the current MSR */
-	li	r12,1
-	rldicr	r12,r12,MSR_SF_LG,(63-MSR_SF_LG)
-	or	r11,r11,r12
-	li	r12,1
-	rldicr	r12,r12,MSR_ISF_LG,(63-MSR_ISF_LG)
+	li	r12,(MSR_SF | MSR_ISF)@highest
+	sldi	r12,r12,48
 	or	r11,r11,r12
 	mtmsrd	r11
 	isync
 	blr
 
 /*
+ * This puts the TOC pointer into r2, offset by 0x8000 (as expected
+ * by the toolchain).  It computes the correct value for wherever we
+ * are running at the moment, using position-independent code.
+ */
+_GLOBAL(relative_toc)
+	mflr	r0
+	bcl	20,31,$+4
+0:	mflr	r9
+	ld	r2,(p_toc - 0b)(r9)
+	add	r2,r2,r9
+	mtlr	r0
+	blr
+
+p_toc:	.llong	__toc_start + 0x8000 - 0b
+
+/*
  * This is where the main kernel code starts.
  */
 _INIT_STATIC(start_here_multiplatform)
-	/* get a new offset, now that the kernel has moved. */
-	bl	.reloc_offset
-	mr	r26,r3
+	/* set up the TOC (real address) */
+	bl	.relative_toc
 
 	/* Clear out the BSS. It may have been done in prom_init,
 	 * already but that's irrelevant since prom_init will soon
 	 * be detached from the kernel completely. Besides, we need
 	 * to clear it now for kexec-style entry.
 	 */
-	LOAD_REG_IMMEDIATE(r11,__bss_stop)
-	LOAD_REG_IMMEDIATE(r8,__bss_start)
+	LOAD_REG_ADDR(r11,__bss_stop)
+	LOAD_REG_ADDR(r8,__bss_start)
 	sub	r11,r11,r8		/* bss size			*/
 	addi	r11,r11,7		/* round up to an even double word */
-	rldicl. r11,r11,61,3		/* shift right by 3		*/
+	srdi.	r11,r11,3		/* shift right by 3		*/
 	beq	4f
 	addi	r8,r8,-8
 	li	r0,0
@@ -1610,35 +1610,28 @@ _INIT_STATIC(start_here_multiplatform)
 	ori	r6,r6,MSR_RI
 	mtmsrd	r6			/* RI on */
 
-	/* The following gets the stack and TOC set up with the regs */
+	/* The following gets the stack set up with the regs */
 	/* pointing to the real addr of the kernel stack.  This is   */
 	/* all done to support the C function call below which sets  */
 	/* up the htab.  This is done because we have relocated the  */
 	/* kernel but are still running in real mode. */
 
-	LOAD_REG_IMMEDIATE(r3,init_thread_union)
-	add	r3,r3,r26
+	LOAD_REG_ADDR(r3,init_thread_union)
 
-	/* set up a stack pointer (physical address) */
+	/* set up a stack pointer */
 	addi	r1,r3,THREAD_SIZE
 	li	r0,0
 	stdu	r0,-STACK_FRAME_OVERHEAD(r1)
 
-	/* set up the TOC (physical address) */
-	LOAD_REG_IMMEDIATE(r2,__toc_start)
-	addi	r2,r2,0x4000
-	addi	r2,r2,0x4000
-	add	r2,r2,r26
-
 	/* Do very early kernel initializations, including initial hash table,
 	 * stab and slb setup before we turn on relocation.	*/
 
 	/* Restore parameters passed from prom_init/kexec */
 	mr	r3,r31
- 	bl	.early_setup
+ 	bl	.early_setup		/* also sets r13 and SPRG3 */
 
-	LOAD_REG_IMMEDIATE(r3, .start_here_common)
-	LOAD_REG_IMMEDIATE(r4, MSR_KERNEL)
+	LOAD_REG_ADDR(r3, .start_here_common)
+	ld	r4,PACAKMSR(r13)
 	mtspr	SPRN_SRR0,r3
 	mtspr	SPRN_SRR1,r4
 	rfid
@@ -1647,20 +1640,10 @@ _INIT_STATIC(start_here_multiplatform)
 	/* This is where all platforms converge execution */
 _INIT_GLOBAL(start_here_common)
 	/* relocation is on at this point */
+	std	r1,PACAKSAVE(r13)
 
-	/* The following code sets up the SP and TOC now that we are */
-	/* running with translation enabled. */
-
-	LOAD_REG_IMMEDIATE(r3,init_thread_union)
-
-	/* set up the stack */
-	addi	r1,r3,THREAD_SIZE
-	li	r0,0
-	stdu	r0,-STACK_FRAME_OVERHEAD(r1)
-
-	/* Load the TOC */
+	/* Load the TOC (virtual address) */
 	ld	r2,PACATOC(r13)
-	std	r1,PACAKSAVE(r13)
 
 	bl	.setup_system
 
diff --git a/arch/powerpc/kernel/misc.S b/arch/powerpc/kernel/misc.S
index 85cb6f3..2d29752 100644
--- a/arch/powerpc/kernel/misc.S
+++ b/arch/powerpc/kernel/misc.S
@@ -31,11 +31,14 @@ _GLOBAL(reloc_offset)
 	mflr	r0
 	bl	1f
 1:	mflr	r3
-	LOAD_REG_IMMEDIATE(r4,1b)
+	PPC_LL	r4,(2f-1b)(r3)
 	subf	r3,r4,r3
 	mtlr	r0
 	blr
 
+	.align	3
+2:	PPC_LONG 1b
+
 /*
  * add_reloc_offset(x) returns x + reloc_offset().
  */
@@ -43,12 +46,15 @@ _GLOBAL(add_reloc_offset)
 	mflr	r0
 	bl	1f
 1:	mflr	r5
-	LOAD_REG_IMMEDIATE(r4,1b)
+	PPC_LL	r4,(2f-1b)(r5)
 	subf	r5,r4,r5
 	add	r3,r3,r5
 	mtlr	r0
 	blr
 
+	.align	3
+2:	PPC_LONG 1b
+
 _GLOBAL(kernel_execve)
 	li	r0,__NR_execve
 	sc
diff --git a/arch/powerpc/platforms/iseries/exception.S b/arch/powerpc/platforms/iseries/exception.S
index 8ff330d..2f58152 100644
--- a/arch/powerpc/platforms/iseries/exception.S
+++ b/arch/powerpc/platforms/iseries/exception.S
@@ -38,12 +38,13 @@
 
 	.globl system_reset_iSeries
 system_reset_iSeries:
+	bl	.relative_toc
 	mfspr	r13,SPRN_SPRG3		/* Get alpaca address */
-	LOAD_REG_IMMEDIATE(r23, alpaca)
+	LOAD_REG_ADDR(r23, alpaca)
 	li	r0,ALPACA_SIZE
 	sub	r23,r13,r23
 	divdu	r23,r23,r0		/* r23 has cpu number */
-	LOAD_REG_IMMEDIATE(r13, paca)
+	LOAD_REG_ADDR(r13, paca)
 	mulli	r0,r23,PACA_SIZE
 	add	r13,r13,r0
 	mtspr	SPRN_SPRG3,r13		/* Save it away for the future */
@@ -60,14 +61,14 @@ system_reset_iSeries:
 	mtspr	SPRN_CTRLT,r4
 
 /* Spin on __secondary_hold_spinloop until it is updated by the boot cpu. */
-/* In the UP case we'll yeild() later, and we will not access the paca anyway */
+/* In the UP case we'll yield() later, and we will not access the paca anyway */
 #ifdef CONFIG_SMP
 1:
 	HMT_LOW
-	LOAD_REG_IMMEDIATE(r23, __secondary_hold_spinloop)
+	LOAD_REG_ADDR(r23, __secondary_hold_spinloop)
 	ld	r23,0(r23)
 	sync
-	LOAD_REG_IMMEDIATE(r3,current_set)
+	LOAD_REG_ADDR(r3,current_set)
 	sldi	r28,r24,3		/* get current_set[cpu#] */
 	ldx	r3,r3,r28
 	addi	r1,r3,THREAD_SIZE
@@ -90,7 +91,7 @@ system_reset_iSeries:
 	lbz	r23,PACAPROCSTART(r13)	/* Test if this processor
 					 * should start */
 	sync
-	LOAD_REG_IMMEDIATE(r3,current_set)
+	LOAD_REG_ADDR(r3,current_set)
 	sldi	r28,r24,3		/* get current_set[cpu#] */
 	ldx	r3,r3,r28
 	addi	r1,r3,THREAD_SIZE
@@ -255,8 +256,8 @@ hardware_interrupt_iSeries_masked:
 
 _INIT_STATIC(__start_initialization_iSeries)
 	/* Clear out the BSS */
-	LOAD_REG_IMMEDIATE(r11,__bss_stop)
-	LOAD_REG_IMMEDIATE(r8,__bss_start)
+	LOAD_REG_ADDR(r11,__bss_stop)
+	LOAD_REG_ADDR(r8,__bss_start)
 	sub	r11,r11,r8		/* bss size			*/
 	addi	r11,r11,7		/* round up to an even double word */
 	rldicl. r11,r11,61,3		/* shift right by 3		*/
@@ -267,15 +268,11 @@ _INIT_STATIC(__start_initialization_iSeries)
 3:	stdu	r0,8(r8)
 	bdnz	3b
 4:
-	LOAD_REG_IMMEDIATE(r1,init_thread_union)
+	LOAD_REG_ADDR(r1,init_thread_union)
 	addi	r1,r1,THREAD_SIZE
 	li	r0,0
 	stdu	r0,-STACK_FRAME_OVERHEAD(r1)
 
-	LOAD_REG_IMMEDIATE(r2,__toc_start)
-	addi	r2,r2,0x4000
-	addi	r2,r2,0x4000
-
 	bl	.iSeries_early_setup
 	bl	.early_setup
 

^ permalink raw reply related

* [PATCH 4/5] powerpc: Make the 64-bit kernel as a position-independent executable
From: Paul Mackerras @ 2008-08-13  1:36 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <18594.14443.340604.693747@cargo.ozlabs.ibm.com>

This implements CONFIG_RELOCATABLE for 64-bit by making the kernel as
a position-independent executable (PIE).  This involves processing the
dynamic relocations in the image in the early stages of booting, even
if the kernel is being run at the address it is linked at, since the
linker does not necessarily fill in words in the image for which there
are dynamic relocations.

The dynamic relocations are processed by a new function relocate(addr),
where the addr parameter is the virtual address where the image will be
run.  In fact we call it twice; once before calling prom_init, and again
when starting the main kernel.  This means that reloc_offset() returns
0 in prom_init (since it has been relocated to the address it is running
at), which necessitated a few adjustments.

The relocate() function currently only handles R_PPC64_RELATIVE
relocs, which are very simple to process (and the linker puts them all
first in the dynamic relocation section, and tells us how many of them
there are).  Currently we only get R_PPC64_RELATIVE relocs, plus one
R_PPC64_NONE reloc which we can ignore, plus some relocs against weak
undefined symbols (e.g. mach_iseries, mach_powermac) which we can also
ignore.  Ideally we would have a little program to check that we
hadn't inadvertently ended up with any other relocs.

This also changes __va and __pa to use an equivalent definition that is
simpler.  With the relocatable kernel, PAGE_OFFSET and MEMORY_START are
constants (for 64-bit) whereas PHYSICAL_START is a variable (and
KERNELBASE ideally should be too, but isn't yet).

With this, relocatable kernels still copy themselves down to physical
address 0 and run there.

Signed-off-by: Paul Mackerras <paulus@samba.org>
---
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index 63c9caf..5a5cf3f 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -809,6 +809,19 @@ config PIN_TLB
 endmenu
 
 if PPC64
+config RELOCATABLE
+	bool "Build a relocatable kernel"
+	help
+	  This builds a kernel image that is capable of running anywhere
+	  in the RMA (real memory area) at any 16k-aligned base address.
+	  The kernel is linked as a position-independent executable (PIE)
+	  and contains dynamic relocations which are processed early
+	  in the bootup process.
+
+	  One use is for the kexec on panic case where the recovery kernel
+	  must live at a different physical address than the primary
+	  kernel.
+
 config PAGE_OFFSET
 	hex
 	default "0xc000000000000000"
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index 9155c93..9e5a53f 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -63,7 +63,8 @@ override CC	+= -m$(CONFIG_WORD_SIZE)
 override AR	:= GNUTARGET=elf$(CONFIG_WORD_SIZE)-powerpc $(AR)
 endif
 
-LDFLAGS_vmlinux	:= -Bstatic
+LDFLAGS_vmlinux-$(CONFIG_PPC64)$(CONFIG_RELOCATABLE) := -pie
+LDFLAGS_vmlinux	:= -Bstatic $(LDFLAGS_vmlinux-yy)
 
 CFLAGS-$(CONFIG_PPC64)	:= -mminimal-toc -mtraceback=none  -mcall-aixdesc
 CFLAGS-$(CONFIG_PPC32)	:= -ffixed-r2 -mmultiple
diff --git a/arch/powerpc/boot/Makefile b/arch/powerpc/boot/Makefile
index 14174aa..9109e1f 100644
--- a/arch/powerpc/boot/Makefile
+++ b/arch/powerpc/boot/Makefile
@@ -310,8 +310,11 @@ $(obj)/dtbImage.%: vmlinux $(wrapperbits) $(obj)/%.dtb
 $(obj)/vmlinux.strip: vmlinux
 	$(STRIP) -s -R .comment $< -o $@
 
+# The iseries hypervisor won't take an ET_DYN executable, so this
+# changes the type (byte 17) in the file to ET_EXEC (2).
 $(obj)/zImage.iseries: vmlinux
 	$(STRIP) -s -R .comment $< -o $@
+	printf "\x02" | dd of=$@ conv=notrunc bs=1 seek=17
 
 $(obj)/uImage: vmlinux $(wrapperbits)
 	$(call if_changed,wrap,uboot)
diff --git a/arch/powerpc/boot/elf_util.c b/arch/powerpc/boot/elf_util.c
index 7454aa4..1567a0c 100644
--- a/arch/powerpc/boot/elf_util.c
+++ b/arch/powerpc/boot/elf_util.c
@@ -27,7 +27,8 @@ int parse_elf64(void *hdr, struct elf_info *info)
 	      elf64->e_ident[EI_MAG3]  == ELFMAG3	&&
 	      elf64->e_ident[EI_CLASS] == ELFCLASS64	&&
 	      elf64->e_ident[EI_DATA]  == ELFDATA2MSB	&&
-	      elf64->e_type            == ET_EXEC	&&
+	      (elf64->e_type            == ET_EXEC ||
+	       elf64->e_type            == ET_DYN)	&&
 	      elf64->e_machine         == EM_PPC64))
 		return 0;
 
@@ -58,7 +59,8 @@ int parse_elf32(void *hdr, struct elf_info *info)
 	      elf32->e_ident[EI_MAG3]  == ELFMAG3	&&
 	      elf32->e_ident[EI_CLASS] == ELFCLASS32	&&
 	      elf32->e_ident[EI_DATA]  == ELFDATA2MSB	&&
-	      elf32->e_type            == ET_EXEC	&&
+	      (elf32->e_type            == ET_EXEC ||
+	       elf32->e_type            == ET_DYN)      &&
 	      elf32->e_machine         == EM_PPC))
 		return 0;
 
diff --git a/arch/powerpc/include/asm/mmu-hash64.h b/arch/powerpc/include/asm/mmu-hash64.h
index 19c7a94..91af0cb 100644
--- a/arch/powerpc/include/asm/mmu-hash64.h
+++ b/arch/powerpc/include/asm/mmu-hash64.h
@@ -437,7 +437,7 @@ typedef struct {
 	})
 #endif /* 1 */
 
-/* This is only valid for addresses >= KERNELBASE */
+/* This is only valid for addresses >= PAGE_OFFSET */
 static inline unsigned long get_kernel_vsid(unsigned long ea, int ssize)
 {
 	if (ssize == MMU_SEGSIZE_256M)
diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h
index e088545..64e1445 100644
--- a/arch/powerpc/include/asm/page.h
+++ b/arch/powerpc/include/asm/page.h
@@ -71,15 +71,21 @@
 #define PAGE_OFFSET	ASM_CONST(CONFIG_PAGE_OFFSET)
 #define LOAD_OFFSET	ASM_CONST((CONFIG_KERNEL_START-CONFIG_PHYSICAL_START))
 
-#if defined(CONFIG_RELOCATABLE) && defined(CONFIG_FLATMEM)
+#if defined(CONFIG_RELOCATABLE)
 #ifndef __ASSEMBLY__
 extern phys_addr_t memstart_addr;
 extern phys_addr_t kernstart_addr;
 #endif
 #define PHYSICAL_START	kernstart_addr
-#define MEMORY_START	memstart_addr
 #else
 #define PHYSICAL_START	ASM_CONST(CONFIG_PHYSICAL_START)
+#endif
+
+#ifdef CONFIG_PPC64
+#define MEMORY_START	0UL
+#elif defined(CONFIG_RELOCATABLE)
+#define MEMORY_START	memstart_addr
+#else
 #define MEMORY_START	(PHYSICAL_START + PAGE_OFFSET - KERNELBASE)
 #endif
 
@@ -92,8 +98,8 @@ extern phys_addr_t kernstart_addr;
 #define pfn_to_kaddr(pfn)	__va((pfn) << PAGE_SHIFT)
 #define virt_addr_valid(kaddr)	pfn_valid(__pa(kaddr) >> PAGE_SHIFT)
 
-#define __va(x) ((void *)((unsigned long)(x) - PHYSICAL_START + KERNELBASE))
-#define __pa(x) ((unsigned long)(x) + PHYSICAL_START - KERNELBASE)
+#define __va(x) ((void *)((unsigned long)(x) + PAGE_OFFSET - MEMORY_START))
+#define __pa(x) ((unsigned long)(x) - PAGE_OFFSET + MEMORY_START)
 
 /*
  * Unfortunately the PLT is in the BSS in the PPC32 ELF ABI,
diff --git a/arch/powerpc/include/asm/sections.h b/arch/powerpc/include/asm/sections.h
index 916018e..0336a6c 100644
--- a/arch/powerpc/include/asm/sections.h
+++ b/arch/powerpc/include/asm/sections.h
@@ -7,6 +7,7 @@
 #ifdef __powerpc64__
 
 extern char _end[];
+extern char __start_interrupts[], __end_interrupts[];
 
 static inline int in_kernel_text(unsigned long addr)
 {
@@ -16,6 +17,12 @@ static inline int in_kernel_text(unsigned long addr)
 	return 0;
 }
 
+static inline int overlaps_kernel_text(unsigned long start, unsigned long end)
+{
+	return start < (unsigned long)__init_end &&
+		(unsigned long)_stext < end;
+}
+
 #endif
 
 #endif /* __KERNEL__ */
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 64f5948..1fbc953 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -34,6 +34,7 @@ obj-$(CONFIG_PPC64)		+= setup_64.o sys_ppc32.o \
 				   paca.o cpu_setup_ppc970.o \
 				   cpu_setup_pa6t.o \
 				   firmware.o sysfs.o nvram_64.o
+obj64-$(CONFIG_RELOCATABLE)	+= reloc_64.o
 obj-$(CONFIG_PPC64)		+= vdso64/
 obj-$(CONFIG_ALTIVEC)		+= vecemu.o vector.o
 obj-$(CONFIG_PPC_970_NAP)	+= idle_power4.o
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index afbd530..abb3bfe 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -1353,6 +1353,12 @@ _INIT_STATIC(__boot_from_prom)
 	 */
 	rldicr	r1,r1,0,59
 
+#ifdef CONFIG_RELOCATABLE
+	/* Relocate code for where we are now */
+	mr	r3,r26
+	bl	.relocate
+#endif
+
 	/* Restore parameters */
 	mr	r3,r31
 	mr	r4,r30
@@ -1361,11 +1367,19 @@ _INIT_STATIC(__boot_from_prom)
 	mr	r7,r27
 
 	/* Do all of the interaction with OF client interface */
+	mr	r8,r26
 	bl	.prom_init
 	/* We never return */
 	trap
 
 _STATIC(__after_prom_start)
+#ifdef CONFIG_RELOCATABLE
+	/* process relocations for the final address of the kernel */
+	lis	r25,PAGE_OFFSET@highest	/* compute virtual base of kernel */
+	sldi	r25,r25,32
+	mr	r3,r25
+	bl	.relocate
+#endif
 
 /*
  * We need to run with _stext at physical address PHYSICAL_START.
@@ -1374,10 +1388,9 @@ _STATIC(__after_prom_start)
  *
  * Note: This process overwrites the OF exception vectors.
  */
-	LOAD_REG_IMMEDIATE(r3, PHYSICAL_START)	/* target addr */
-	cmpd	r3,r26			/* In some cases the loader may  */
+	li	r3,0			/* target addr */
+	mr.	r4,r26			/* In some cases the loader may  */
 	beq	9f			/* have already put us at zero */
-	mr	r4,r26			/* source address */
 	lis	r5,(copy_to_here - _stext)@ha
 	addi	r5,r5,(copy_to_here - _stext)@l /* # bytes of memory to copy */
 	li	r6,0x100		/* Start offset, the first 0x100 */
@@ -1610,6 +1623,13 @@ _INIT_STATIC(start_here_multiplatform)
 	ori	r6,r6,MSR_RI
 	mtmsrd	r6			/* RI on */
 
+#ifdef CONFIG_RELOCATABLE
+	/* Save the physical address we're running at in kernstart_addr */
+	LOAD_REG_ADDR(r4, kernstart_addr)
+	clrldi	r0,r25,2
+	std	r0,0(r4)
+#endif
+
 	/* The following gets the stack set up with the regs */
 	/* pointing to the real addr of the kernel stack.  This is   */
 	/* all done to support the C function call below which sets  */
diff --git a/arch/powerpc/kernel/paca.c b/arch/powerpc/kernel/paca.c
index 623e8c3..48a3471 100644
--- a/arch/powerpc/kernel/paca.c
+++ b/arch/powerpc/kernel/paca.c
@@ -12,6 +12,7 @@
 
 #include <asm/lppaca.h>
 #include <asm/paca.h>
+#include <asm/sections.h>
 
 /* This symbol is provided by the linker - let it fill in the paca
  * field correctly */
@@ -79,7 +80,7 @@ void __init initialise_pacas(void)
 		new_paca->lock_token = 0x8000;
 		new_paca->paca_index = cpu;
 		new_paca->kernel_toc = kernel_toc;
-		new_paca->kernelbase = KERNELBASE;
+		new_paca->kernelbase = (unsigned long) _stext;
 		new_paca->kernel_msr = MSR_KERNEL;
 		new_paca->hw_cpu_id = 0xffff;
 		new_paca->slb_shadow_ptr = &slb_shadow[cpu];
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 87d83c5..4df797e 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -1163,7 +1163,9 @@ void __init early_init_devtree(void *params)
 	parse_early_param();
 
 	/* Reserve LMB regions used by kernel, initrd, dt, etc... */
-	lmb_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START);
+	lmb_reserve(0, __end_interrupts - _stext);
+	lmb_reserve(__pa(__end_interrupts),
+		    klimit - (unsigned long)__end_interrupts);
 	reserve_kdump_trampoline();
 	reserve_crashkernel();
 	early_reserve_mem();
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 1f89885..2cbbbc7 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -2309,13 +2309,14 @@ static void __init prom_check_initrd(unsigned long r3, unsigned long r4)
 
 unsigned long __init prom_init(unsigned long r3, unsigned long r4,
 			       unsigned long pp,
-			       unsigned long r6, unsigned long r7)
+			       unsigned long r6, unsigned long r7,
+			       unsigned long kbase)
 {	
 	struct prom_t *_prom;
 	unsigned long hdr;
-	unsigned long offset = reloc_offset();
 
 #ifdef CONFIG_PPC32
+	unsigned long offset = reloc_offset();
 	reloc_got2(offset);
 #endif
 
@@ -2371,7 +2372,7 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
 	 * Copy the CPU hold code
 	 */
 	if (RELOC(of_platform) != PLATFORM_POWERMAC)
-		copy_and_flush(0, KERNELBASE + offset, 0x100, 0);
+		copy_and_flush(0, kbase, 0x100, 0);
 
 	/*
 	 * Do early parsing of command line
@@ -2474,7 +2475,7 @@ unsigned long __init prom_init(unsigned long r3, unsigned long r4,
 	reloc_got2(-offset);
 #endif
 
-	__start(hdr, KERNELBASE + offset, 0);
+	__start(hdr, kbase, 0);
 
 	return 0;
 }
diff --git a/arch/powerpc/kernel/reloc_64.S b/arch/powerpc/kernel/reloc_64.S
new file mode 100644
index 0000000..b47a0e1
--- /dev/null
+++ b/arch/powerpc/kernel/reloc_64.S
@@ -0,0 +1,87 @@
+/*
+ * Code to process dynamic relocations in the kernel.
+ *
+ * Copyright 2008 Paul Mackerras, IBM Corp.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version
+ *  2 of the License, or (at your option) any later version.
+ */
+
+#include <asm/ppc_asm.h>
+
+RELA = 7
+RELACOUNT = 0x6ffffff9
+R_PPC64_RELATIVE = 22
+
+/*
+ * r3 = desired final address of kernel
+ */
+_GLOBAL(relocate)
+	mflr	r0
+	bcl	20,31,$+4
+0:	mflr	r12		/* r12 has runtime addr of label 0 */
+	mtlr	r0
+	ld	r11,(p_dyn - 0b)(r12)
+	add	r11,r11,r12	/* r11 has runtime addr of .dynamic section */
+	ld	r9,(p_rela - 0b)(r12)
+	add	r9,r9,r12	/* r9 has runtime addr of .rela.dyn section */
+	ld	r10,(p_st - 0b)(r12)
+	add	r10,r10,r12	/* r10 has runtime addr of _stext */
+
+	/*
+	 * Scan the dynamic section for the RELA and RELACOUNT entries.
+	 */
+	li	r7,0
+	li	r8,0
+1:	ld	r6,0(r11)	/* get tag */
+	cmpdi	r6,0
+	beq	4f		/* end of list */
+	cmpdi	r6,RELA
+	bne	2f
+	ld	r7,8(r11)	/* get RELA pointer in r7 */
+	b	3f
+2:	addis	r6,r6,(-RELACOUNT)@ha
+	cmpdi	r6,RELACOUNT@l
+	bne	3f
+	ld	r8,8(r11)	/* get RELACOUNT value in r8 */
+3:	addi	r11,r11,16
+	b	1b
+4:	cmpdi	r7,0		/* check we have both RELA and RELACOUNT */
+	cmpdi	cr1,r8,0
+	beq	6f
+	beq	cr1,6f
+
+	/*
+	 * Work out linktime address of _stext and hence the
+	 * relocation offset to be applied.
+	 * cur_offset [r7] = rela.run [r9] - rela.link [r7]
+	 * _stext.link [r10] = _stext.run [r10] - cur_offset [r7]
+	 * final_offset [r3] = _stext.final [r3] - _stext.link [r10]
+	 */
+	subf	r7,r7,r9	/* cur_offset */
+	subf	r10,r7,r10
+	subf	r3,r10,r3	/* final_offset */
+
+	/*
+	 * Run through the list of relocations and process the
+	 * R_PPC64_RELATIVE ones.
+	 */
+	mtctr	r8
+5:	lwz	r0,12(9)	/* ELF64_R_TYPE(reloc->r_info) */
+	cmpwi	r0,R_PPC64_RELATIVE
+	bne	6f
+	ld	r6,0(r9)	/* reloc->r_offset */
+	ld	r0,16(r9)	/* reloc->r_addend */
+	add	r0,r0,r3
+	stdx	r0,r7,r6
+	addi	r9,r9,24
+	bdnz	5b
+
+6:	blr
+
+p_dyn:	.llong	__dynamic_start - 0b
+p_rela:	.llong	__rela_dyn_start - 0b
+p_st:	.llong	_stext - 0b
+
diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
index 4a8ce62..115c16d 100644
--- a/arch/powerpc/kernel/vmlinux.lds.S
+++ b/arch/powerpc/kernel/vmlinux.lds.S
@@ -186,6 +186,21 @@ SECTIONS
 		*(.machine.desc)
 		__machine_desc_end = . ;
 	}
+	. = ALIGN(8);
+	.dynsym : { *(.dynsym) }
+	.dynstr : { *(.dynstr) }
+	.dynamic :
+	{
+		__dynamic_start = .;
+		*(.dynamic)
+	}
+	.hash : { *(.hash) }
+	.interp : { *(.interp) }
+	.rela.dyn :
+	{
+		__rela_dyn_start = .;
+		*(.rela*)
+	}
 
 	/* freed after init ends here */
 	. = ALIGN(PAGE_SIZE);
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index 5ce5a4d..f5dc515 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -173,14 +173,12 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
 		tmp_mode = mode;
 		
 		/* Make non-kernel text non-executable */
-		if (!in_kernel_text(vaddr))
+		if (!overlaps_kernel_text(vaddr, vaddr + step))
 			tmp_mode = mode | HPTE_R_N;
 
 		hash = hpt_hash(va, shift, ssize);
 		hpteg = ((hash & htab_hash_mask) * HPTES_PER_GROUP);
 
-		DBG("htab_bolt_mapping: calling %p\n", ppc_md.hpte_insert);
-
 		BUG_ON(!ppc_md.hpte_insert);
 		ret = ppc_md.hpte_insert(hpteg, va, paddr,
 				tmp_mode, HPTE_V_BOLTED, psize, ssize);
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index 4ae3d00..40f72c2 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -787,7 +787,7 @@ static void __devinit smp_core99_kick_cpu(int nr)
 {
 	unsigned int save_vector;
 	unsigned long target, flags;
-	unsigned int *vector = (unsigned int *)(KERNELBASE+0x100);
+	unsigned int *vector = (unsigned int *)(PAGE_OFFSET+0x100);
 
 	if (nr < 0 || nr > 3)
 		return;
@@ -801,7 +801,7 @@ static void __devinit smp_core99_kick_cpu(int nr)
 	save_vector = *vector;
 
 	/* Setup fake reset vector that does
-	 *   b __secondary_start_pmac_0 + nr*8 - KERNELBASE
+	 *   b __secondary_start_pmac_0 + nr*8
 	 */
 	target = (unsigned long) __secondary_start_pmac_0 + nr * 8;
 	patch_branch(vector, target, BRANCH_SET_LINK);

^ permalink raw reply related

* [PATCH 5/5] powerpc: Run relocatable kernel where it's loaded
From: Paul Mackerras @ 2008-08-13  1:38 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <18594.14443.340604.693747@cargo.ozlabs.ibm.com>

This demonstrates that the relocatable kernel doesn't have to run at
real address 0.  It only copies the interrupt vectors down and leaves
the rest of the kernel where it was loaded, and runs it there.

This is mostly just a proof of concept, since it doesn't do anything
to ensure that the kernel base address is 16kB-aligned, and we
probably want to move the kernel down to 0 in most cases (except for
kdump kernels) anyway.

Signed-off-by: Paul Mackerras <paulus@samba.org>
---
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index abb3bfe..fdb8565 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -1377,6 +1377,7 @@ _STATIC(__after_prom_start)
 	/* process relocations for the final address of the kernel */
 	lis	r25,PAGE_OFFSET@highest	/* compute virtual base of kernel */
 	sldi	r25,r25,32
+	add	r25,r25,r26
 	mr	r3,r25
 	bl	.relocate
 #endif
@@ -1391,10 +1392,13 @@ _STATIC(__after_prom_start)
 	li	r3,0			/* target addr */
 	mr.	r4,r26			/* In some cases the loader may  */
 	beq	9f			/* have already put us at zero */
-	lis	r5,(copy_to_here - _stext)@ha
-	addi	r5,r5,(copy_to_here - _stext)@l /* # bytes of memory to copy */
 	li	r6,0x100		/* Start offset, the first 0x100 */
 					/* bytes were copied earlier.	 */
+#ifdef CONFIG_RELOCATABLE
+	li	r5,__end_interrupts - _stext	/* just copy interrupts */
+#else
+	lis	r5,(copy_to_here - _stext)@ha
+	addi	r5,r5,(copy_to_here - _stext)@l /* # bytes of memory to copy */
 
 	bl	.copy_and_flush		/* copy the first n bytes	 */
 					/* this includes the code being	 */
@@ -1404,15 +1408,16 @@ _STATIC(__after_prom_start)
 	mtctr	r8
 	bctr
 
+p_end:	.llong	_end - _stext
+
 4:	/* Now copy the rest of the kernel up to _end */
 	addis	r5,r26,(p_end - _stext)@ha
 	ld	r5,(p_end - _stext)@l(r5)	/* get _end */
+#endif
 	bl	.copy_and_flush		/* copy the rest */
 
 9:	b	.start_here_multiplatform
 
-p_end:	.llong	_end - _stext
-
 /*
  * Copy routine used to copy the kernel to start at physical address 0
  * and flush and invalidate the caches as needed.

^ permalink raw reply related

* serial problem of cpm2
From: 朱利达 @ 2008-08-13  2:36 UTC (permalink / raw)
  To: linuxppc-embedded

[-- Attachment #1: Type: text/plain, Size: 914 bytes --]


hi everybody:  These days a problem drive me to read the code about mpc8247 cpm2 smc or scc uart.The problem is that, very very occasionally when my system bring up, I find the serial port can not work. The serial port connects with smc1 and is a console port. when the problem occured, the tx of smc1 is still ok. I send 'break' to the port, and dump the register of smc . The indicators of 'break' len and 'break' times show it reciverd thesignal. Catting /proc/interrupts I find the interrupts counter do not increase.It seemed the irq of smc disabled by systerm. Somehow, when the problem occured, there were a lot of 'break' signal recived the serial port, maybe this is hardware mistake.And the mistake lead the problem. 
       Do anyone troubled with these problem?
_________________________________________________________________
用手机MSN聊天写邮件看空间,无限沟通,分享精彩!
http://mobile.msn.com.cn/

[-- Attachment #2: Type: text/html, Size: 1211 bytes --]

^ permalink raw reply

* [RFC/PATCH v2] powerpc: add ioremap_early() function for mapping IO regions before MMU_init()
From: Grant Likely @ 2008-08-13  3:03 UTC (permalink / raw)
  To: linuxppc-dev, benh, jwboyer, galak, miltonm, paulus, scottwood

From: Grant Likely <grant.likely@secretlab.ca>

ioremap_early() is useful for things like mapping SoC internally memory mapped
register and early text because it allows mappings to devices to be setup
early in the boot process where they are needed, and the mappings persist
after the MMU is configured.

Without ioremap_early(), setting up the MMU would cause the early text
mappings to get lost and mostly likely result in a kernel panic on the next
attempt at output.

Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
---

I've made changes based on the comments I've received.  I tried to share
code between __ioremap() and ioremap_early(), but when it came down to
writing the code, there was very little that was actually common.  Most
of it was around access to the ioremap_bot variable, but due to the
different alignments, the code ended up being different anyway.

I've not made any attempt to have this routine work after mem_init() time.
I don't think the use case justifies the extra code and I think I want to
enforce mapping with BATs (or other large region methods) to be performed
before smaller ioremaps() to maximize the performance gains.  If the BATs
are mapped first, then many smaller ioremaps() get to use them 'for free'.

Comments?
g.

 arch/powerpc/kernel/setup_32.c   |    4 +
 arch/powerpc/mm/init_32.c        |    7 --
 arch/powerpc/mm/mmu_decl.h       |    7 +-
 arch/powerpc/mm/pgtable_32.c     |   75 ++++++++++++++++++++
 arch/powerpc/mm/ppc_mmu_32.c     |  140 ++++++++++++++++++++++++++++++++------
 arch/powerpc/sysdev/cpm_common.c |    2 -
 include/asm-powerpc/io.h         |    8 ++
 7 files changed, 209 insertions(+), 34 deletions(-)

diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c
index 066e65c..822ae7e 100644
--- a/arch/powerpc/kernel/setup_32.c
+++ b/arch/powerpc/kernel/setup_32.c
@@ -40,6 +40,7 @@
 #include <asm/udbg.h>
 
 #include "setup.h"
+#include "mm/mmu_decl.h"
 
 #define DBG(fmt...)
 
@@ -113,6 +114,9 @@ notrace unsigned long __init early_init(unsigned long dt_ptr)
  */
 notrace void __init machine_init(unsigned long dt_ptr, unsigned long phys)
 {
+	/* Get ready to allocate IO virtual address regions */
+	ioremap_init();
+
 	/* Enable early debugging if any specified (see udbg.h) */
 	udbg_early_init();
 
diff --git a/arch/powerpc/mm/init_32.c b/arch/powerpc/mm/init_32.c
index 388ceda..a3d9b4e 100644
--- a/arch/powerpc/mm/init_32.c
+++ b/arch/powerpc/mm/init_32.c
@@ -169,13 +169,6 @@ void __init MMU_init(void)
 		ppc_md.progress("MMU:mapin", 0x301);
 	mapin_ram();
 
-#ifdef CONFIG_HIGHMEM
-	ioremap_base = PKMAP_BASE;
-#else
-	ioremap_base = 0xfe000000UL;	/* for now, could be 0xfffff000 */
-#endif /* CONFIG_HIGHMEM */
-	ioremap_bot = ioremap_base;
-
 	/* Map in I/O resources */
 	if (ppc_md.progress)
 		ppc_md.progress("MMU:setio", 0x302);
diff --git a/arch/powerpc/mm/mmu_decl.h b/arch/powerpc/mm/mmu_decl.h
index fab3cfa..3c951d5 100644
--- a/arch/powerpc/mm/mmu_decl.h
+++ b/arch/powerpc/mm/mmu_decl.h
@@ -29,11 +29,14 @@ extern void hash_preload(struct mm_struct *mm, unsigned long ea,
 #ifdef CONFIG_PPC32
 extern void mapin_ram(void);
 extern int map_page(unsigned long va, phys_addr_t pa, int flags);
-extern void setbat(int index, unsigned long virt, phys_addr_t phys,
-		   unsigned int size, int flags);
+extern int setbat(unsigned long virt, phys_addr_t phys, unsigned int size,
+		  int flags);
+extern int loadbat(unsigned long virt, phys_addr_t phys, unsigned int size,
+		   int flags);
 extern void settlbcam(int index, unsigned long virt, phys_addr_t phys,
 		      unsigned int size, int flags, unsigned int pid);
 extern void invalidate_tlbcam_entry(int index);
+extern void ioremap_init(void); /* called by machine_init() */
 
 extern int __map_without_bats;
 extern unsigned long ioremap_base;
diff --git a/arch/powerpc/mm/pgtable_32.c b/arch/powerpc/mm/pgtable_32.c
index 2001abd..40820fa 100644
--- a/arch/powerpc/mm/pgtable_32.c
+++ b/arch/powerpc/mm/pgtable_32.c
@@ -55,8 +55,6 @@ extern void hash_page_sync(void);
 #ifdef HAVE_BATS
 extern phys_addr_t v_mapped_by_bats(unsigned long va);
 extern unsigned long p_mapped_by_bats(phys_addr_t pa);
-void setbat(int index, unsigned long virt, phys_addr_t phys,
-	    unsigned int size, int flags);
 
 #else /* !HAVE_BATS */
 #define v_mapped_by_bats(x)	(0UL)
@@ -142,6 +140,21 @@ void pte_free(struct mm_struct *mm, pgtable_t ptepage)
 	__free_page(ptepage);
 }
 
+/**
+ * ioremap_init - setup ioremap address range
+ */
+void __init ioremap_init(void)
+{
+	if (ioremap_base)
+		return;
+#ifdef CONFIG_HIGHMEM
+	ioremap_base = PKMAP_BASE;
+#else
+	ioremap_base = 0xfe000000UL;	/* for now, could be 0xfffff000 */
+#endif
+	ioremap_bot = ioremap_base;
+}
+
 void __iomem *
 ioremap(phys_addr_t addr, unsigned long size)
 {
@@ -265,6 +278,64 @@ void iounmap(volatile void __iomem *addr)
 }
 EXPORT_SYMBOL(iounmap);
 
+/**
+ * ioremap_early - Allow large persistant IO regions to be mapped early.
+ * @addr: physical address of region
+ * @size: size of region
+ *
+ * This routine uses setbat() to set up IO ranges before the MMU is
+ * fully configured.
+ *
+ * This routine can be called really early, before MMU_init() is called.  It
+ * is useful for setting up early debug output consoles and frequently
+ * accessed IO regions, like the internally memory mapped registers (IMMR)
+ * in an SoC.  Ranges mapped with this function persist even after MMU_init()
+ * is called and the MMU is turned on 'for real.'
+ *
+ * The region mapped is large (minimum size of 128k) and virtual mapping must
+ * be aligned against this boundary.  Therefore, to avoid fragmentation all
+ * calls to ioremap_early() are best made before any calls to ioremap
+ * for smaller regions.
+ */
+void __iomem * __init
+ioremap_early(phys_addr_t addr, unsigned long size)
+{
+	unsigned long v, p;
+	int i;
+
+	/* Be loud and annoying if someone calls this too late.
+	 * No need to crash the kernel though */
+	WARN_ON(mem_init_done);
+	if (mem_init_done)
+		return NULL;
+
+	/* Make sure request is sane */
+	if (size == 0)
+		return NULL;
+
+	/* If the region is already block mapped, then there is nothing
+	 * to do; just return the mapped address */
+	v = p_mapped_by_bats(addr);
+	if (v)
+		return (void __iomem *)v;
+
+	/* Adjust size to reflect aligned region */
+	p = _ALIGN_DOWN(addr, 128 << 10); /* BATs align on 128k boundaries */
+	size = ALIGN(addr - p + size, 128 << 10);
+
+	/* Allocate the aligned virtual base address.  ALIGN_DOWN is used
+	 * to ensure no overlaps occur with normal 4k ioremaps. */
+	v = ioremap_bot = _ALIGN_DOWN(ioremap_bot, 128 << 10) - size;
+
+	/* Set up a BAT for this IO region */
+	i = loadbat(v, p, size, _PAGE_IO);
+	if (i < 0)
+		return NULL;
+
+	return (void __iomem *) (v + (addr - p));
+}
+
+
 int map_page(unsigned long va, phys_addr_t pa, int flags)
 {
 	pmd_t *pd;
diff --git a/arch/powerpc/mm/ppc_mmu_32.c b/arch/powerpc/mm/ppc_mmu_32.c
index c53145f..676b2a0 100644
--- a/arch/powerpc/mm/ppc_mmu_32.c
+++ b/arch/powerpc/mm/ppc_mmu_32.c
@@ -72,41 +72,44 @@ unsigned long p_mapped_by_bats(phys_addr_t pa)
 	return 0;
 }
 
+/**
+ * mmu_mapin_ram - Map as much of RAM as possible into kernel space using BATs
+ */
 unsigned long __init mmu_mapin_ram(void)
 {
 #ifdef CONFIG_POWER4
 	return 0;
 #else
 	unsigned long tot, bl, done;
-	unsigned long max_size = (256<<20);
+	int rc;
 
 	if (__map_without_bats) {
 		printk(KERN_DEBUG "RAM mapped without BATs\n");
 		return 0;
 	}
 
-	/* Set up BAT2 and if necessary BAT3 to cover RAM. */
-
-	/* Make sure we don't map a block larger than the
-	   smallest alignment of the physical address. */
+	/* Set up BATs to cover RAM. */
 	tot = total_lowmem;
-	for (bl = 128<<10; bl < max_size; bl <<= 1) {
-		if (bl * 2 > tot)
+	done = 0;
+	while (done < tot) {
+		/* determine the smallest block size need to map the region.
+		 * Don't use a BAT mapping if the remaining region is less
+		 * that 128k */
+		if (tot - done <= 128<<10)
 			break;
-	}
-
-	setbat(2, KERNELBASE, 0, bl, _PAGE_RAM);
-	done = (unsigned long)bat_addrs[2].limit - KERNELBASE + 1;
-	if ((done < tot) && !bat_addrs[3].limit) {
-		/* use BAT3 to cover a bit more */
-		tot -= done;
-		for (bl = 128<<10; bl < max_size; bl <<= 1)
-			if (bl * 2 > tot)
+		for (bl = 128<<10; bl < (256<<20); bl <<= 1)
+			if ((bl * 2) > (tot - done))
 				break;
-		setbat(3, KERNELBASE+done, done, bl, _PAGE_RAM);
-		done = (unsigned long)bat_addrs[3].limit - KERNELBASE + 1;
+
+		/* Allocate the BAT and recalculate amount of RAM mapped */
+		rc = setbat(KERNELBASE+done, done, bl, _PAGE_RAM);
+		if (rc < 0)
+			break;
+		done = (unsigned long)bat_addrs[rc].limit - KERNELBASE + 1;
 	}
 
+	if (done == 0)
+		printk(KERN_CRIT "Weird; No BATs available for RAM.\n");
 	return done;
 #endif
 }
@@ -116,12 +119,29 @@ unsigned long __init mmu_mapin_ram(void)
  * The parameters are not checked; in particular size must be a power
  * of 2 between 128k and 256M.
  */
-void __init setbat(int index, unsigned long virt, phys_addr_t phys,
-		   unsigned int size, int flags)
+int __init setbat(unsigned long virt, phys_addr_t phys,
+		  unsigned int size, int flags)
 {
 	unsigned int bl;
-	int wimgxpp;
-	struct ppc_bat *bat = BATS[index];
+	int wimgxpp, index, nr_bats;
+	struct ppc_bat *bat;
+
+	/* Find a free BAT
+	 *
+	 * Special case; Keep the first entry in reserve for mapping RAM.
+	 * Otherwise the too many other users can prevent RAM from getting
+	 * mapped at all with a BAT.
+	 */
+	index = (flags == _PAGE_RAM) ? 0 : 1;
+	nr_bats = cpu_has_feature(CPU_FTR_HAS_HIGH_BATS) ? 8 : 4;
+	for (; index < nr_bats; index++) {
+		if ((BATS[index][0].batu == 0) && (BATS[index][1].batu == 0))
+			break;
+	}
+	if (index == nr_bats)
+		return -1;
+
+	bat = BATS[index];
 
 	if (((flags & _PAGE_NO_CACHE) == 0) &&
 	    cpu_has_feature(CPU_FTR_NEED_COHERENT))
@@ -162,8 +182,84 @@ void __init setbat(int index, unsigned long virt, phys_addr_t phys,
 	bat_addrs[index].start = virt;
 	bat_addrs[index].limit = virt + ((bl + 1) << 17) - 1;
 	bat_addrs[index].phys = phys;
+	return index;
 }
 
+/**
+ * loadbat - Set up and configure one of the I/D BAT register pairs.
+ * @virt - virtual address, 128k aligned
+ * @phys - physical address, 128k aligned
+ * @size - size of mapping
+ * @flags - region attribute flags
+ *
+ * Uses setbat() to allocate a BAT pair and immediately writes the
+ * configuration into the BAT registers (instead of waiting for load_up_mmu)
+ */
+int __init loadbat(unsigned long virt, phys_addr_t phys,
+		   unsigned int size, int flags)
+{
+	struct ppc_bat *bat;
+	int i;
+
+	i = setbat(virt, phys, size, flags);
+	if (i < 0)
+		return i;
+	bat = BATS[i];
+
+	/* BATs must be set with a switch statement because there is no way
+	 * to paramaterize mtspr/mfspr instructions.
+	 *
+	 * Note: BAT0 is not handled here because early boot code depends
+	 * on BAT0 for mapping first 16M of RAM.  setbat() keeps BAT0 in
+	 * reserve for mapping main memory anyway, so this is okay.
+	 */
+	switch (i) {
+	case 1:
+		mtspr(SPRN_IBAT1U, bat[0].batu);
+		mtspr(SPRN_IBAT1L, bat[0].batl);
+		mtspr(SPRN_DBAT1U, bat[1].batu);
+		mtspr(SPRN_DBAT1L, bat[1].batl);
+		break;
+	case 2:
+		mtspr(SPRN_IBAT2U, bat[0].batu);
+		mtspr(SPRN_IBAT2L, bat[0].batl);
+		mtspr(SPRN_DBAT2U, bat[1].batu);
+		mtspr(SPRN_DBAT2L, bat[1].batl);
+		break;
+	case 3:
+		mtspr(SPRN_IBAT3U, bat[0].batu);
+		mtspr(SPRN_IBAT3L, bat[0].batl);
+		mtspr(SPRN_DBAT3U, bat[1].batu);
+		mtspr(SPRN_DBAT3L, bat[1].batl);
+		break;
+	case 4:
+		mtspr(SPRN_IBAT4U, bat[0].batu);
+		mtspr(SPRN_IBAT4L, bat[0].batl);
+		mtspr(SPRN_DBAT4U, bat[1].batu);
+		mtspr(SPRN_DBAT4L, bat[1].batl);
+		break;
+	case 5:
+		mtspr(SPRN_IBAT5U, bat[0].batu);
+		mtspr(SPRN_IBAT5L, bat[0].batl);
+		mtspr(SPRN_DBAT5U, bat[1].batu);
+		mtspr(SPRN_DBAT5L, bat[1].batl);
+		break;
+	case 6:
+		mtspr(SPRN_IBAT6U, bat[0].batu);
+		mtspr(SPRN_IBAT6L, bat[0].batl);
+		mtspr(SPRN_DBAT6U, bat[1].batu);
+		mtspr(SPRN_DBAT6L, bat[1].batl);
+		break;
+	case 7:
+		mtspr(SPRN_IBAT7U, bat[0].batu);
+		mtspr(SPRN_IBAT7L, bat[0].batl);
+		mtspr(SPRN_DBAT7U, bat[1].batu);
+		mtspr(SPRN_DBAT7L, bat[1].batl);
+		break;
+	}
+
+	return i;
+}
 /*
  * Preload a translation in the hash table
  */
diff --git a/arch/powerpc/sysdev/cpm_common.c b/arch/powerpc/sysdev/cpm_common.c
index 53da8a0..b3b4f8c 100644
--- a/arch/powerpc/sysdev/cpm_common.c
+++ b/arch/powerpc/sysdev/cpm_common.c
@@ -56,7 +56,7 @@ void __init udbg_init_cpm(void)
 {
 	if (cpm_udbg_txdesc) {
 #ifdef CONFIG_CPM2
-		setbat(1, 0xf0000000, 0xf0000000, 1024*1024, _PAGE_IO);
+		setbat(0xf0000000, 0xf0000000, 1024*1024, _PAGE_IO);
 #endif
 		udbg_putc = udbg_putc_cpm;
 	}
diff --git a/include/asm-powerpc/io.h b/include/asm-powerpc/io.h
index 77c7fa0..e343f76 100644
--- a/include/asm-powerpc/io.h
+++ b/include/asm-powerpc/io.h
@@ -624,6 +624,12 @@ static inline void iosync(void)
  *
  * * iounmap undoes such a mapping and can be hooked
  *
+ * * ioremap_early is for setting up mapping regions during early boot.  Useful
+ *   for console devices or mapping an entire region of SoC internal registers.
+ *   ioremap_early becomes usable at machine_init() time.  Care must be taken
+ *   when using this routine because it can consume limited resources like BAT
+ *   registers.
+ *
  * * __ioremap_at (and the pending __iounmap_at) are low level functions to
  *   create hand-made mappings for use only by the PCI code and cannot
  *   currently be hooked. Must be page aligned.
@@ -644,6 +650,8 @@ extern void __iomem *ioremap_flags(phys_addr_t address, unsigned long size,
 
 extern void iounmap(volatile void __iomem *addr);
 
+extern void __iomem *ioremap_early(phys_addr_t addr, unsigned long size);
+
 extern void __iomem *__ioremap(phys_addr_t, unsigned long size,
 			       unsigned long flags);
 extern void __iounmap(volatile void __iomem *addr);

^ permalink raw reply related

* Re: [PATCH 5121 pci 1/3] powerpc: 83xx: pci: Remove need for get_immrbase from mpc83xx_add_bridge.
From: Grant Likely @ 2008-08-13  5:09 UTC (permalink / raw)
  To: John Rigby; +Cc: linuxppc-dev
In-Reply-To: <1218130587-31176-1-git-send-email-jrigby@freescale.com>

On Thu, Aug 07, 2008 at 11:36:25AM -0600, John Rigby wrote:
> Modify mpc83xx_add_bridge to get config space register base address from the device
> tree instead of immr + hardcoded offset.
> 
> 83xx pci nodes have these changes:
>     register properties now contain two address length tuples:
> 	First is the pci bridge register base, this has always been there.
> 	Second is the config base, this is new.
>     The primary pci bus should have the "primary" property.
> 
> These are documented in Documentation/powerpc/dts-bindings/fsl/83xx-512x-pci.txt

Looks mostly good to me.  I only have one comment on the device tree
binding...

> diff --git a/Documentation/powerpc/dts-bindings/fsl/83xx-512x-pci.txt b/Documentation/powerpc/dts-bindings/fsl/83xx-512x-pci.txt
> new file mode 100644
> index 0000000..51214a0
> --- /dev/null
> +++ b/Documentation/powerpc/dts-bindings/fsl/83xx-512x-pci.txt
> @@ -0,0 +1,43 @@
> +* Freescale 83xx and 512x PCI bridges
> +
> +Freescale 83xx and 512x SOCs include the same pci bridge core.
> +
> +83xx/512x specific notes:
> +- reg: should contain two address length tuples
> +    The first is for the internal pci bridge registers
> +    The second is for the pci config space access registers
> +- primary: 
> +    This property should be present for the primary pci bridge

Can you use something like 'fsl,primary-pci-bridge' instead?  'primary'
is a little too generic for my taste.  Also, the purpose of identifying
one of the PCI bridges as primary should be documented (This is me
pushing against encoding Linux internal implementation details into the
device tree, I suspect that 'primary' doesn't belong in the device tree
at all).

^ permalink raw reply

* Re: [PATCH 3/5] Apply relocation
From: Paul Mackerras @ 2008-08-13  5:11 UTC (permalink / raw)
  To: mohan; +Cc: ppcdev, miltonm
In-Reply-To: <20080812081028.GC19619@in.ibm.com>

Mohan Kumar M writes:

> This code is a wrapper around regular kernel. This checks whether the
> kernel is loaded at 32MB, if its not loaded at 32MB, its treated as a
> regular kernel and the control is given to the kernel immediately. If
> the kernel is loaded at 32MB, it applies relocation delta to each offset
> in the list which was generated and appended by patch 1 and 2. After
> updating all offsets, control is given to the relocatable kernel.

In patch 1, you output the addresses for three kinds of relocations,
but here you only seem to handle two (R_PPC64_ADDR64 and
R_PPC64_ADDR16_HI, I assume).  How does that work?

In general with this patch series, I would like to have seen much more
detailed patch descriptions.  I think most of these patches could have
used 4 or 5 paragraphs of description (or more if you like) telling us
things such as why you handle the particular relocations you do and
not others.

Paul.

^ permalink raw reply

* Re: [PATCH 5121 pci 2/3] powerpc: 5121: Add PCI support.
From: Grant Likely @ 2008-08-13  5:12 UTC (permalink / raw)
  To: John Rigby; +Cc: linuxppc-dev
In-Reply-To: <1218130587-31176-2-git-send-email-jrigby@freescale.com>

On Thu, Aug 07, 2008 at 11:36:26AM -0600, John Rigby wrote:
> Uses mpc83xx_add_bridge in fsl_pci.c
> 
> Adds second register tuple to pci node register property
> as previously done for 83xx device trees in a previous patch.
> 
> Signed-off-by: John Rigby <jrigby@freescale.com>

Looks good to me.

Acked-by: Grant Likely <grant.likely@secretlab.ca>

I'll pick this one up once 1/3 is sorted out.

g.

^ permalink raw reply

* Re: [PATCH 5121 pci 3/3] powerpc: pci: 5121: Hide pci bridge.
From: Grant Likely @ 2008-08-13  5:16 UTC (permalink / raw)
  To: John Rigby; +Cc: linuxppc-dev
In-Reply-To: <1218130587-31176-3-git-send-email-jrigby@freescale.com>

On Thu, Aug 07, 2008 at 11:36:27AM -0600, John Rigby wrote:
> The class of the MPC5121 pci host bridge is PCI_CLASS_BRIDGE_OTHER
> while other freescale host bridges have class set to
> PCI_CLASS_PROCESSOR_POWERPC.
> 
> This patch makes fixup_hide_host_resource_fsl match
> PCI_CLASS_BRIDGE_OTHER in addition to PCI_CLASS_PROCESSOR_POWERPC.
> 
> Signed-off-by: John Rigby <jrigby@freescale.com>

I think this is okay, but it might need to be more conservative.  I'm
not the PCI expert.  Kumar, thoughts?

g.

> ---
>  arch/powerpc/kernel/pci_32.c |    5 +++--
>  1 files changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c
> index 88db4ff..162c3a8 100644
> --- a/arch/powerpc/kernel/pci_32.c
> +++ b/arch/powerpc/kernel/pci_32.c
> @@ -54,11 +54,12 @@ LIST_HEAD(hose_list);
>  static int pci_bus_count;
>  
>  static void
> -fixup_hide_host_resource_fsl(struct pci_dev* dev)
> +fixup_hide_host_resource_fsl(struct pci_dev *dev)
>  {
>  	int i, class = dev->class >> 8;
>  
> -	if ((class == PCI_CLASS_PROCESSOR_POWERPC) &&
> +	if ((class == PCI_CLASS_PROCESSOR_POWERPC ||
> +	     class == PCI_CLASS_BRIDGE_OTHER) &&
>  		(dev->hdr_type == PCI_HEADER_TYPE_NORMAL) &&
>  		(dev->bus->parent == NULL)) {
>  		for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
> -- 
> 
> 
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev

^ permalink raw reply

* Re: [PATCH 4/5] Relocation support
From: Paul Mackerras @ 2008-08-13  5:20 UTC (permalink / raw)
  To: mohan; +Cc: ppcdev, miltonm
In-Reply-To: <20080812081103.GD19619@in.ibm.com>

Mohan Kumar M writes:

> Add relocatable kernel support like avoiding copying the vmlinux
> image to compile address, adding relocation delta to the absolute
> symbol references etc. ld does not provide relocation entries for
> .got section, and the user space relocation extraction program
> can not process @got entries.  So use LOAD_REG_IMMEDIATE macro
> instead of LOAD_REG_ADDR macro for relocatable kernel.

I think this is a symptom of the more general problem that
--emit-relocs doesn't actually give us all of the relocations we
need.  That, and the fact that the relevant code paths in ld are more
widely used and better tested, is why I would prefer to build the
kernel as a position-independent executable.

>  static inline int in_kernel_text(unsigned long addr)
>  {
> -	if (addr >= (unsigned long)_stext && addr < (unsigned long)__init_end)
> +	if (addr >= (unsigned long)_stext && addr < (unsigned long)__init_end
> +								+ kernel_base)

Your patch adds kernel_base to some addresses but not to all of them,
so your patch description should have told us why you added it in the
those places and not others.  If you tell us the general principle
you're following (even if it seems obvious to you) it will be useful
to people chasing bugs or adding new code later on, or even just
trying to understand what the code does.

> -	RELOC(alloc_bottom) = PAGE_ALIGN((unsigned long)&RELOC(_end) + 0x4000);
> +#ifndef CONFIG_RELOCATABLE_PPC64
> + 	RELOC(alloc_bottom) = PAGE_ALIGN((unsigned long)&RELOC(_end) + 0x4000);
> +#else
> +	RELOC(alloc_bottom) = PAGE_ALIGN((unsigned long)&RELOC(_end) + 0x4000 +
> +							RELOC(reloc_delta));
> +#endif

Ifdefs in code inside a function are frowned upon in the Linux
kernel.  Try to find an alternative way to do this, such as ensuring
that reloc_delta is 0 when CONFIG_RELOCATABLE_PPC64 is not set.
Also it's not clear (to me at least) why you need to add reloc_data in
the relocatable case.

> +#ifndef CONFIG_RELOCATABLE_PPC64
>  	unsigned long *spinloop
>  		= (void *) LOW_ADDR(__secondary_hold_spinloop);
>  	unsigned long *acknowledge
>  		= (void *) LOW_ADDR(__secondary_hold_acknowledge);
> +#else
> +	unsigned long *spinloop
> +		= (void *) &__secondary_hold_spinloop;
> +	unsigned long *acknowledge
> +		= (void *) &__secondary_hold_acknowledge;
> +#endif

This also needs some explanation.  (Put it in the patch description or
in a comment in the code, not in a reply to this mail. :)

> +#ifndef CONFIG_RELOCATABLE_PPC64
>  	ld	r4,htab_hash_mask@got(2)
> +#else
> +	LOAD_REG_IMMEDIATE(r4,htab_hash_mask)
> +#endif
>  	ld	r27,0(r4)	/* htab_hash_mask -> r27 */

Here and in the other similar places, I would prefer you just changed
it to LOAD_REG_ADDR and not have any ifdef.

Paul.

^ permalink raw reply

* Re: [RFC/PATCH 2/3] of: add of_lookup_stdout() utility function
From: Grant Likely @ 2008-08-13  5:41 UTC (permalink / raw)
  To: Timur Tabi, miltonm, linuxppc-dev, paulus
In-Reply-To: <20080807061254.GB12571@yookeroo.seuss>

On Thu, Aug 07, 2008 at 04:12:54PM +1000, David Gibson wrote:
> On Wed, Aug 06, 2008 at 11:46:47AM -0500, Timur Tabi wrote:
> > On Wed, Aug 6, 2008 at 1:02 AM, Grant Likely <grant.likely@secretlab.ca> wrote:
> > > From: Grant Likely <grant.likely@secretlab.ca>
> > >
> > > of_lookup_stdout() is useful for figuring out what device to use as output
> > > for early boot progress messages.  It returns the node pointed to by the
> > > linux,stdout-path property in the chosen node.
> > 
> > I thought linux,stdout-path is deprecated are we're supposed to be
> > using the aliases node instead?
> 
> During the ePAPR process this idea came up - standardising a 'stdout'
> alias that would replace linux,stdout-path in chosen.  However that
> was done in ignorance of the history of the linux,stdout-path property
> and its connection to the stdout ihandle in chosen.  In any case, the
> proposed 'stdout' alias didn't make the final cut for ePAPR, so how to
> address this for flat-tree systems is still an open question.

So, seeing as settling on a way to determine stdout still up in the air,
it probably makes sense to condense that code down to a single
authoritative function so that changes in this area are contained in one
place.  For now, I'll stick with decoding linux,stdout-path and on Sparc
decoding the ihandle with the expectation that there will be further
refinements to be made.

g.

^ permalink raw reply

* Re: [PATCH]: [MPC5200] Add ATA DMA support
From: Tim Yamin @ 2008-08-13  5:57 UTC (permalink / raw)
  To: Daniel Schnell; +Cc: linuxppc-dev
In-Reply-To: <DD39B5C3F4963040ADC9768BE7E430CB03203B75@is-hdq-exchange.marel.net>

On Tue, Aug 12, 2008 at 6:30 PM, Daniel Schnell
<daniel.schnell@marel.com> wrote:
> Hi Tim,
>
> Continuing the discussion on the mailing list ...
>
> Looking at the original patch I don't undestand why you had to duplicate
> the bestcomm data structures and functions. The only apparent difference
> is that you have a minimal data length of 2 bytes instead of 1. Does
> this make any difference as the bd_size will be filled with the correct
> length value anyway ?

The "new" version of the patch does this the correct way. I just
haven't back ported this to the 2.6.24 version that I sent you.

Tim

^ permalink raw reply

* Re: [PATCH]: [MPC5200] Add ATA DMA support
From: Grant Likely @ 2008-08-13  6:02 UTC (permalink / raw)
  To: Tim Yamin; +Cc: linuxppc-dev
In-Reply-To: <792f5f410808122257t3711eb2lfc1e02bacade16a3@mail.gmail.com>

On Tue, Aug 12, 2008 at 11:57 PM, Tim Yamin <plasm@roo.me.uk> wrote:
> On Tue, Aug 12, 2008 at 6:30 PM, Daniel Schnell
> <daniel.schnell@marel.com> wrote:
>> Hi Tim,
>>
>> Continuing the discussion on the mailing list ...
>>
>> Looking at the original patch I don't undestand why you had to duplicate
>> the bestcomm data structures and functions. The only apparent difference
>> is that you have a minimal data length of 2 bytes instead of 1. Does
>> this make any difference as the bd_size will be filled with the correct
>> length value anyway ?
>
> The "new" version of the patch does this the correct way. I just
> haven't back ported this to the 2.6.24 version that I sent you.

While on this topic; have you had a chance to address the comments you
received on v2 of your patch?  I'm keen to get your change merged in,
but there are a few more things that need to be sorted out.

Cheers,
g.

-- 
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply

* Re: [PATCH]: [MPC5200] Add ATA DMA support
From: Tim Yamin @ 2008-08-13  6:06 UTC (permalink / raw)
  To: Grant Likely; +Cc: linuxppc-dev
In-Reply-To: <fa686aa40808122302g197a8e90idc721796aa35ff05@mail.gmail.com>

On Wed, Aug 13, 2008 at 7:02 AM, Grant Likely <grant.likely@secretlab.ca> wrote:
> While on this topic; have you had a chance to address the comments you
> received on v2 of your patch?  I'm keen to get your change merged in,
> but there are a few more things that need to be sorted out.

I'm still trying to determine whether the locking stuff is needed or
not. I think ultimately it might be a bug caused by hardware problems
at this end as opposed to silicon problems affecting everybody, but I
won't have an answer regarding this for a while because new hardware
needs to be prototyped to test out this theory.

I think the patch can probably be resubmitted with the locking stuff
removed, and the driver can be marked as experimental for everybody to
try out: if people experience any corruption problems I'm sure they
can speak up :-)

Any objections?

Tim

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox