diff mbox series

[v3] powerpc: Add gpr1 and fpu save/restore functions

Message ID 375482960.15931139.1708104247383.JavaMail.zimbra@raptorengineeringinc.com (mailing list archive)
State New
Headers show
Series [v3] powerpc: Add gpr1 and fpu save/restore functions | expand

Checks

Context Check Description
snowpatch_ozlabs/github-powerpc_ppctests success Successfully ran 8 jobs.
snowpatch_ozlabs/github-powerpc_selftests success Successfully ran 8 jobs.
snowpatch_ozlabs/github-powerpc_sparse success Successfully ran 4 jobs.
snowpatch_ozlabs/github-powerpc_clang success Successfully ran 6 jobs.
snowpatch_ozlabs/github-powerpc_kernel_qemu success Successfully ran 23 jobs.

Commit Message

Timothy Pearson Feb. 16, 2024, 5:24 p.m. UTC
When building the kernel in size optimized mode with the amdgpu module enabled,
gcc will begin referencing external gpr1 and fpu save/restore functions.  This
will then cause a linker failure as we do not link against libgcc which
normally contains those builtin functions.

Implement gpr1 and fpu save/restore functions per the PowerPC 64-bit ELFv2 ABI
documentation.

Tested on a Talos II with a WX7100 installed and running in DisplayCore mode.

Reported-by: kernel test robot <lkp@intel.com>
Tested-by: Timothy Pearson <tpearson@raptorengineering.com>
Signed-off-by: Timothy Pearson <tpearson@raptorengineering.com>
---
 arch/powerpc/kernel/prom_init_check.sh |   4 +-
 arch/powerpc/lib/crtsavres.S           | 363 +++++++++++++++++--------
 scripts/mod/modpost.c                  |   4 +
 3 files changed, 253 insertions(+), 118 deletions(-)

Comments

Christophe Leroy Feb. 17, 2024, 4:39 p.m. UTC | #1
Le 16/02/2024 à 18:24, Timothy Pearson a écrit :
> When building the kernel in size optimized mode with the amdgpu module enabled,
> gcc will begin referencing external gpr1 and fpu save/restore functions.  This
> will then cause a linker failure as we do not link against libgcc which
> normally contains those builtin functions.

Right, but modules are linked with --save-restore-funcs when using gcc 
so crtsavres.o is not used and only your change to scripts/mod/modpost.c 
seems to be required to be able to build amdgpu module with GCC.

Maybe that's different with clang, but maybe worth a test and then a 
second patch ?

Nevertheless, see comments below, you can do even shorter and more 
readable using GAS macros.

> 
> Implement gpr1 and fpu save/restore functions per the PowerPC 64-bit ELFv2 ABI
> documentation.
> 
> Tested on a Talos II with a WX7100 installed and running in DisplayCore mode.
> 
> Reported-by: kernel test robot <lkp@intel.com>
> Tested-by: Timothy Pearson <tpearson@raptorengineering.com>
> Signed-off-by: Timothy Pearson <tpearson@raptorengineering.com>
> ---
>   arch/powerpc/kernel/prom_init_check.sh |   4 +-
>   arch/powerpc/lib/crtsavres.S           | 363 +++++++++++++++++--------
>   scripts/mod/modpost.c                  |   4 +
>   3 files changed, 253 insertions(+), 118 deletions(-)
> 
> diff --git a/arch/powerpc/kernel/prom_init_check.sh b/arch/powerpc/kernel/prom_init_check.sh
> index 69623b9045d5..76c5651e29d3 100644
> --- a/arch/powerpc/kernel/prom_init_check.sh
> +++ b/arch/powerpc/kernel/prom_init_check.sh
> @@ -72,10 +72,10 @@ do
>   
>   	# ignore register save/restore funcitons
>   	case $UNDEF in
> -	_restgpr_*|_restgpr0_*|_rest32gpr_*)
> +	_restgpr_*|_restgpr0_*|_restgpr1_*|_rest32gpr_*)
>   		OK=1
>   		;;
> -	_savegpr_*|_savegpr0_*|_save32gpr_*)
> +	_savegpr_*|_savegpr0_*|_restgpr0_*|_save32gpr_*)
>   		OK=1
>   		;;
>   	esac
> diff --git a/arch/powerpc/lib/crtsavres.S b/arch/powerpc/lib/crtsavres.S
> index 7e5e1c28e56a..f97270d36720 100644
> --- a/arch/powerpc/lib/crtsavres.S
> +++ b/arch/powerpc/lib/crtsavres.S
> @@ -3,6 +3,7 @@
>    *
>    *   Copyright (C) 1995, 1996, 1998, 2000, 2001 Free Software Foundation, Inc.
>    *   Copyright 2008 Freescale Semiconductor, Inc.
> + *   Copyright 2024 Raptor Engineering, LLC
>    *   Written By Michael Meissner
>    *
>    * Based on gcc/config/rs6000/crtsavres.asm from gcc
> @@ -314,126 +315,134 @@ _GLOBAL(_restvr_31)
>   
>   #else /* CONFIG_PPC64 */
>   
> -.globl	_savegpr0_14
> -_savegpr0_14:
> -	std	r14,-144(r1)
> -.globl	_savegpr0_15
> -_savegpr0_15:
> -	std	r15,-136(r1)
> -.globl	_savegpr0_16
> -_savegpr0_16:
> -	std	r16,-128(r1)
> -.globl	_savegpr0_17
> -_savegpr0_17:
> -	std	r17,-120(r1)
> -.globl	_savegpr0_18
> -_savegpr0_18:
> -	std	r18,-112(r1)
> -.globl	_savegpr0_19
> -_savegpr0_19:
> -	std	r19,-104(r1)
> -.globl	_savegpr0_20
> -_savegpr0_20:
> -	std	r20,-96(r1)
> -.globl	_savegpr0_21
> -_savegpr0_21:
> -	std	r21,-88(r1)
> -.globl	_savegpr0_22
> -_savegpr0_22:
> -	std	r22,-80(r1)
> -.globl	_savegpr0_23
> -_savegpr0_23:
> -	std	r23,-72(r1)
> -.globl	_savegpr0_24
> -_savegpr0_24:
> -	std	r24,-64(r1)
> -.globl	_savegpr0_25
> -_savegpr0_25:
> -	std	r25,-56(r1)
> -.globl	_savegpr0_26
> -_savegpr0_26:
> -	std	r26,-48(r1)
> -.globl	_savegpr0_27
> -_savegpr0_27:
> -	std	r27,-40(r1)
> -.globl	_savegpr0_28
> -_savegpr0_28:
> -	std	r28,-32(r1)
> -.globl	_savegpr0_29
> -_savegpr0_29:
> -	std	r29,-24(r1)
> -.globl	_savegpr0_30
> -_savegpr0_30:
> -	std	r30,-16(r1)
> -.globl	_savegpr0_31
> -_savegpr0_31:
> -	std	r31,-8(r1)
> -	std	r0,16(r1)
> +#define __PPC64_SAVEGPR(n,base)	\
> +.globl	_savegpr##n##_14	\
> +_savegpr##n##_14:		\
> +	std	r14,-144(base)	\
> +.globl	_savegpr##n##_15	\
> +_savegpr##n##_15:		\
> +	std	r15,-136(base)	\
> +.globl	_savegpr##n##_16	\
> +_savegpr##n##_16:		\
> +	std	r16,-128(base)	\
> +.globl	_savegpr##n##_17	\
> +_savegpr##n##_17:		\
> +	std	r17,-120(base)	\
> +.globl	_savegpr##n##_18	\
> +_savegpr##n##_18:		\
> +	std	r18,-112(base)	\
> +.globl	_savegpr##n##_19	\
> +_savegpr##n##_19:		\
> +	std	r19,-104(base)	\
> +.globl	_savegpr##n##_20	\
> +_savegpr##n##_20:		\
> +	std	r20,-96(base)	\
> +.globl	_savegpr##n##_21	\
> +_savegpr##n##_21:		\
> +	std	r21,-88(base)	\
> +.globl	_savegpr##n##_22	\
> +_savegpr##n##_22:		\
> +	std	r22,-80(base)	\
> +.globl	_savegpr##n##_23	\
> +_savegpr##n##_23:		\
> +	std	r23,-72(base)	\
> +.globl	_savegpr##n##_24	\
> +_savegpr##n##_24:		\
> +	std	r24,-64(base)	\
> +.globl	_savegpr##n##_25	\
> +_savegpr##n##_25:		\
> +	std	r25,-56(base)	\
> +.globl	_savegpr##n##_26	\
> +_savegpr##n##_26:		\
> +	std	r26,-48(base)	\
> +.globl	_savegpr##n##_27	\
> +_savegpr##n##_27:		\
> +	std	r27,-40(base)	\
> +.globl	_savegpr##n##_28	\
> +_savegpr##n##_28:		\
> +	std	r28,-32(base)	\
> +.globl	_savegpr##n##_29	\
> +_savegpr##n##_29:		\
> +	std	r29,-24(base)	\
> +.globl	_savegpr##n##_30	\
> +_savegpr##n##_30:		\
> +	std	r30,-16(base)	\
> +.globl	_savegpr##n##_31	\
> +_savegpr##n##_31:		\
> +	std	r31,-8(base)	\
> +	std	r0,16(base)	\
>   	blr
>   
> -.globl	_restgpr0_14
> -_restgpr0_14:
> -	ld	r14,-144(r1)
> -.globl	_restgpr0_15
> -_restgpr0_15:
> -	ld	r15,-136(r1)
> -.globl	_restgpr0_16
> -_restgpr0_16:
> -	ld	r16,-128(r1)
> -.globl	_restgpr0_17
> -_restgpr0_17:
> -	ld	r17,-120(r1)
> -.globl	_restgpr0_18
> -_restgpr0_18:
> -	ld	r18,-112(r1)
> -.globl	_restgpr0_19
> -_restgpr0_19:
> -	ld	r19,-104(r1)
> -.globl	_restgpr0_20
> -_restgpr0_20:
> -	ld	r20,-96(r1)
> -.globl	_restgpr0_21
> -_restgpr0_21:
> -	ld	r21,-88(r1)
> -.globl	_restgpr0_22
> -_restgpr0_22:
> -	ld	r22,-80(r1)
> -.globl	_restgpr0_23
> -_restgpr0_23:
> -	ld	r23,-72(r1)
> -.globl	_restgpr0_24
> -_restgpr0_24:
> -	ld	r24,-64(r1)
> -.globl	_restgpr0_25
> -_restgpr0_25:
> -	ld	r25,-56(r1)
> -.globl	_restgpr0_26
> -_restgpr0_26:
> -	ld	r26,-48(r1)
> -.globl	_restgpr0_27
> -_restgpr0_27:
> -	ld	r27,-40(r1)
> -.globl	_restgpr0_28
> -_restgpr0_28:
> -	ld	r28,-32(r1)
> -.globl	_restgpr0_29
> -_restgpr0_29:
> -	ld	r0,16(r1)
> -	ld	r29,-24(r1)
> -	mtlr	r0
> -	ld	r30,-16(r1)
> -	ld	r31,-8(r1)
> +#define __PPC64_RESTGPR(n,base)	\
> +.globl	_restgpr##n##_14	\
> +_restgpr##n##_14:		\
> +	ld	r14,-144(base)	\
> +.globl	_restgpr##n##_15	\
> +_restgpr##n##_15:		\
> +	ld	r15,-136(base)	\
> +.globl	_restgpr##n##_16	\
> +_restgpr##n##_16:		\
> +	ld	r16,-128(base)	\
> +.globl	_restgpr##n##_17	\
> +_restgpr##n##_17:		\
> +	ld	r17,-120(base)	\
> +.globl	_restgpr##n##_18	\
> +_restgpr##n##_18:		\
> +	ld	r18,-112(base)	\
> +.globl	_restgpr##n##_19	\
> +_restgpr##n##_19:		\
> +	ld	r19,-104(base)	\
> +.globl	_restgpr##n##_20	\
> +_restgpr##n##_20:		\
> +	ld	r20,-96(base)	\
> +.globl	_restgpr##n##_21	\
> +_restgpr##n##_21:		\
> +	ld	r21,-88(base)	\
> +.globl	_restgpr##n##_22	\
> +_restgpr##n##_22:		\
> +	ld	r22,-80(base)	\
> +.globl	_restgpr##n##_23	\
> +_restgpr##n##_23:		\
> +	ld	r23,-72(base)	\
> +.globl	_restgpr##n##_24	\
> +_restgpr##n##_24:		\
> +	ld	r24,-64(base)	\
> +.globl	_restgpr##n##_25	\
> +_restgpr##n##_25:		\
> +	ld	r25,-56(base)	\
> +.globl	_restgpr##n##_26	\
> +_restgpr##n##_26:		\
> +	ld	r26,-48(base)	\
> +.globl	_restgpr##n##_27	\
> +_restgpr##n##_27:		\
> +	ld	r27,-40(base)	\
> +.globl	_restgpr##n##_28	\
> +_restgpr##n##_28:		\
> +	ld	r28,-32(base)	\
> +.globl	_restgpr##n##_29	\
> +_restgpr##n##_29:		\
> +	ld	r0,16(base)	\
> +	ld	r29,-24(base)	\
> +	mtlr	r0		\
> +	ld	r30,-16(base)	\
> +	ld	r31,-8(base)	\
> +	blr			\
> +				\
> +.globl	_restgpr##n##_30	\
> +_restgpr##n##_30:		\
> +	ld	r30,-16(base)	\
> +.globl	_restgpr##n##_31	\
> +_restgpr##n##_31:		\
> +	ld	r0,16(base)	\
> +	ld	r31,-8(base)	\
> +	mtlr	r0		\
>   	blr

I was thinking more about GAS macro, to avoid those ugly backslashes.

Also, every three line is worth a macro in itself

+.globl	_savegpr##n##_14	\
+_savegpr##n##_14:		\
+	std	r14,-144(base)	\

Something like (untested):

.macro savegpr \n \base \num
.globl _savegpr\n_\num
_savegpr\num:
	std	\num, -256+8*\num(base)
.end

Then

.macro	__ppc64_savegpr n, base
	savegpr 14 \n \base
	savegpr 15 \n \base
	savegpr 16 \n \base
	savegpr 17 \n \base
	savegpr 18 \n \base
	savegpr 19 \n \base
	savegpr 20 \n \base
	savegpr 21 \n \base
	savegpr 22 \n \base
	savegpr 23 \n \base
	savegpr 24 \n \base
	savegpr 25 \n \base
	savegpr 26 \n \base
	savegpr 27 \n \base
	savegpr 28 \n \base
	savegpr 29 \n \base
	savegpr 30 \n \base
	savegpr 31 \n \base
	std	r0,16(\base)
	blr
.endm

>   
> -.globl	_restgpr0_30
> -_restgpr0_30:
> -	ld	r30,-16(r1)
> -.globl	_restgpr0_31
> -_restgpr0_31:
> -	ld	r0,16(r1)
> -	ld	r31,-8(r1)
> -	mtlr	r0
> -	blr
> +__PPC64_RESTGPR(0, r1)
> +__PPC64_RESTGPR(1, r12)
> +
> +__PPC64_SAVEGPR(0, r1)
> +__PPC64_SAVEGPR(1, r12)
>   
>   #ifdef CONFIG_ALTIVEC
>   /* Called with r0 pointing just beyond the end of the vector save area.  */
> @@ -540,6 +549,128 @@ _restvr_31:
>   
>   #endif /* CONFIG_ALTIVEC */
>   
> +#ifdef CONFIG_PPC_FPU
> +
> +.globl	_savefpr_14
> +_savefpr_14:
> +	stfd f14,-144(r1)
> +.globl	_savefpr_15
> +_savefpr_15:
> +	stfd f15,-136(r1)
> +.globl	_savefpr_16
> +_savefpr_16:
> +	stfd f16,-128(r1)
> +.globl	_savefpr_17
> +_savefpr_17:
> +	stfd f17,-120(r1)
> +.globl	_savefpr_18
> +_savefpr_18:
> +	stfd f18,-112(r1)
> +.globl	_savefpr_19
> +_savefpr_19:
> +	stfd f19,-104(r1)
> +.globl	_savefpr_20
> +_savefpr_20:
> +	stfd f20,-96(r1)
> +.globl	_savefpr_21
> +_savefpr_21:
> +	stfd f21,-88(r1)
> +.globl	_savefpr_22
> +_savefpr_22:
> +	stfd f22,-80(r1)
> +.globl	_savefpr_23
> +_savefpr_23:
> +	stfd f23,-72(r1)
> +.globl	_savefpr_24
> +_savefpr_24:
> +	stfd f24,-64(r1)
> +.globl	_savefpr_25
> +_savefpr_25:
> +	stfd f25,-56(r1)
> +.globl	_savefpr_26
> +_savefpr_26:
> +	stfd f26,-48(r1)
> +.globl	_savefpr_27
> +_savefpr_27:
> +	stfd f27,-40(r1)
> +.globl	_savefpr_28
> +_savefpr_28:
> +	stfd f28,-32(r1)
> +.globl	_savefpr_29
> +_savefpr_29:
> +	stfd f29,-24(r1)
> +.globl	_savefpr_30
> +_savefpr_30:
> +	stfd f30,-16(r1)
> +.globl	_savefpr_31
> +_savefpr_31:
> +	stfd f31,-8(r1)
> +	std r0, 16(r1)
> +	blr
> +
> +.globl	_restfpr_14
> +_restfpr_14:
> +	lfd f14,-144(r1)
> +.globl	_restfpr_15
> +_restfpr_15:
> +	lfd f15,-136(r1)
> +.globl	_restfpr_16
> +_restfpr_16:
> +	lfd f16,-128(r1)
> +.globl	_restfpr_17
> +_restfpr_17:
> +	lfd f17,-120(r1)
> +.globl	_restfpr_18
> +_restfpr_18:
> +	lfd f18,-112(r1)
> +.globl	_restfpr_19
> +_restfpr_19:
> +	lfd f19,-104(r1)
> +.globl	_restfpr_20
> +_restfpr_20:
> +	lfd f20,-96(r1)
> +.globl	_restfpr_21
> +_restfpr_21:
> +	lfd f21,-88(r1)
> +.globl	_restfpr_22
> +_restfpr_22:
> +	lfd f22,-80(r1)
> +.globl	_restfpr_23
> +_restfpr_23:
> +	lfd f23,-72(r1)
> +.globl	_restfpr_24
> +_restfpr_24:
> +	lfd f24,-64(r1)
> +.globl	_restfpr_25
> +_restfpr_25:
> +	lfd f25,-56(r1)
> +.globl	_restfpr_26
> +_restfpr_26:
> +	lfd f26,-48(r1)
> +.globl	_restfpr_27
> +_restfpr_27:
> +	lfd f27,-40(r1)
> +.globl	_restfpr_28
> +_restfpr_28:
> +	lfd f28,-32(r1)
> +.globl	_restfpr_29
> +_restfpr_29:
> +	ld r0, 16(r1)
> +	lfd f29,-24(r1)
> +	mtlr r0
> +	lfd f30,-16(r1)
> +	lfd f31,-8(r1)
> +	blr
> +.globl	_restfpr_30
> +_restfpr_30:
> +	lfd f30,-16(r1)
> +.globl	_restfpr_31
> +_restfpr_31:
> +	ld r0, 16(r1)
> +	lfd f31,-8(r1)
> +
> +#endif /* CONFIG_PPC_FPU */
> +
>   #endif /* CONFIG_PPC64 */
>   
>   #endif
> diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
> index 267b9a0a3abc..153a163ba3f7 100644
> --- a/scripts/mod/modpost.c
> +++ b/scripts/mod/modpost.c
> @@ -597,8 +597,12 @@ static int ignore_undef_symbol(struct elf_info *info, const char *symname)
>   		/* Special register function linked on all modules during final link of .ko */
>   		if (strstarts(symname, "_restgpr0_") ||
>   		    strstarts(symname, "_savegpr0_") ||
> +		    strstarts(symname, "_restgpr1_") ||
> +		    strstarts(symname, "_savegpr1_") ||
>   		    strstarts(symname, "_restvr_") ||
>   		    strstarts(symname, "_savevr_") ||
> +		    strstarts(symname, "_restfpr_") ||
> +		    strstarts(symname, "_savefpr_") ||
>   		    strcmp(symname, ".TOC.") == 0)
>   			return 1;
>
Timothy Pearson Feb. 17, 2024, 9:23 p.m. UTC | #2
----- Original Message -----
> From: "christophe leroy" <christophe.leroy@csgroup.eu>
> To: "Timothy Pearson" <tpearson@raptorengineering.com>
> Cc: "linuxppc-dev" <linuxppc-dev@lists.ozlabs.org>
> Sent: Saturday, February 17, 2024 10:39:06 AM
> Subject: Re: [PATCH v3] powerpc: Add gpr1 and fpu save/restore functions

> Le 16/02/2024 à 18:24, Timothy Pearson a écrit :
>> When building the kernel in size optimized mode with the amdgpu module enabled,
>> gcc will begin referencing external gpr1 and fpu save/restore functions.  This
>> will then cause a linker failure as we do not link against libgcc which
>> normally contains those builtin functions.
> 
> Right, but modules are linked with --save-restore-funcs when using gcc
> so crtsavres.o is not used and only your change to scripts/mod/modpost.c
> seems to be required to be able to build amdgpu module with GCC.
> 
> Maybe that's different with clang, but maybe worth a test and then a
> second patch ?

It looks to be gated on ld, specifically if we're CONFIG_PPC64 && CONFIG_LD_IS_BFD.  I can update the patch to match that gate if desired.

> Nevertheless, see comments below, you can do even shorter and more
> readable using GAS macros.

That's true, but my goal was to get this working, not refactor the entire file. :)  Any chance we can merge and do a fine polish later, especially if there's a distinct possibility of the entire file going away in the near future?
diff mbox series

Patch

diff --git a/arch/powerpc/kernel/prom_init_check.sh b/arch/powerpc/kernel/prom_init_check.sh
index 69623b9045d5..76c5651e29d3 100644
--- a/arch/powerpc/kernel/prom_init_check.sh
+++ b/arch/powerpc/kernel/prom_init_check.sh
@@ -72,10 +72,10 @@  do
 
 	# ignore register save/restore funcitons
 	case $UNDEF in
-	_restgpr_*|_restgpr0_*|_rest32gpr_*)
+	_restgpr_*|_restgpr0_*|_restgpr1_*|_rest32gpr_*)
 		OK=1
 		;;
-	_savegpr_*|_savegpr0_*|_save32gpr_*)
+	_savegpr_*|_savegpr0_*|_restgpr0_*|_save32gpr_*)
 		OK=1
 		;;
 	esac
diff --git a/arch/powerpc/lib/crtsavres.S b/arch/powerpc/lib/crtsavres.S
index 7e5e1c28e56a..f97270d36720 100644
--- a/arch/powerpc/lib/crtsavres.S
+++ b/arch/powerpc/lib/crtsavres.S
@@ -3,6 +3,7 @@ 
  *
  *   Copyright (C) 1995, 1996, 1998, 2000, 2001 Free Software Foundation, Inc.
  *   Copyright 2008 Freescale Semiconductor, Inc.
+ *   Copyright 2024 Raptor Engineering, LLC
  *   Written By Michael Meissner
  *
  * Based on gcc/config/rs6000/crtsavres.asm from gcc
@@ -314,126 +315,134 @@  _GLOBAL(_restvr_31)
 
 #else /* CONFIG_PPC64 */
 
-.globl	_savegpr0_14
-_savegpr0_14:
-	std	r14,-144(r1)
-.globl	_savegpr0_15
-_savegpr0_15:
-	std	r15,-136(r1)
-.globl	_savegpr0_16
-_savegpr0_16:
-	std	r16,-128(r1)
-.globl	_savegpr0_17
-_savegpr0_17:
-	std	r17,-120(r1)
-.globl	_savegpr0_18
-_savegpr0_18:
-	std	r18,-112(r1)
-.globl	_savegpr0_19
-_savegpr0_19:
-	std	r19,-104(r1)
-.globl	_savegpr0_20
-_savegpr0_20:
-	std	r20,-96(r1)
-.globl	_savegpr0_21
-_savegpr0_21:
-	std	r21,-88(r1)
-.globl	_savegpr0_22
-_savegpr0_22:
-	std	r22,-80(r1)
-.globl	_savegpr0_23
-_savegpr0_23:
-	std	r23,-72(r1)
-.globl	_savegpr0_24
-_savegpr0_24:
-	std	r24,-64(r1)
-.globl	_savegpr0_25
-_savegpr0_25:
-	std	r25,-56(r1)
-.globl	_savegpr0_26
-_savegpr0_26:
-	std	r26,-48(r1)
-.globl	_savegpr0_27
-_savegpr0_27:
-	std	r27,-40(r1)
-.globl	_savegpr0_28
-_savegpr0_28:
-	std	r28,-32(r1)
-.globl	_savegpr0_29
-_savegpr0_29:
-	std	r29,-24(r1)
-.globl	_savegpr0_30
-_savegpr0_30:
-	std	r30,-16(r1)
-.globl	_savegpr0_31
-_savegpr0_31:
-	std	r31,-8(r1)
-	std	r0,16(r1)
+#define __PPC64_SAVEGPR(n,base)	\
+.globl	_savegpr##n##_14	\
+_savegpr##n##_14:		\
+	std	r14,-144(base)	\
+.globl	_savegpr##n##_15	\
+_savegpr##n##_15:		\
+	std	r15,-136(base)	\
+.globl	_savegpr##n##_16	\
+_savegpr##n##_16:		\
+	std	r16,-128(base)	\
+.globl	_savegpr##n##_17	\
+_savegpr##n##_17:		\
+	std	r17,-120(base)	\
+.globl	_savegpr##n##_18	\
+_savegpr##n##_18:		\
+	std	r18,-112(base)	\
+.globl	_savegpr##n##_19	\
+_savegpr##n##_19:		\
+	std	r19,-104(base)	\
+.globl	_savegpr##n##_20	\
+_savegpr##n##_20:		\
+	std	r20,-96(base)	\
+.globl	_savegpr##n##_21	\
+_savegpr##n##_21:		\
+	std	r21,-88(base)	\
+.globl	_savegpr##n##_22	\
+_savegpr##n##_22:		\
+	std	r22,-80(base)	\
+.globl	_savegpr##n##_23	\
+_savegpr##n##_23:		\
+	std	r23,-72(base)	\
+.globl	_savegpr##n##_24	\
+_savegpr##n##_24:		\
+	std	r24,-64(base)	\
+.globl	_savegpr##n##_25	\
+_savegpr##n##_25:		\
+	std	r25,-56(base)	\
+.globl	_savegpr##n##_26	\
+_savegpr##n##_26:		\
+	std	r26,-48(base)	\
+.globl	_savegpr##n##_27	\
+_savegpr##n##_27:		\
+	std	r27,-40(base)	\
+.globl	_savegpr##n##_28	\
+_savegpr##n##_28:		\
+	std	r28,-32(base)	\
+.globl	_savegpr##n##_29	\
+_savegpr##n##_29:		\
+	std	r29,-24(base)	\
+.globl	_savegpr##n##_30	\
+_savegpr##n##_30:		\
+	std	r30,-16(base)	\
+.globl	_savegpr##n##_31	\
+_savegpr##n##_31:		\
+	std	r31,-8(base)	\
+	std	r0,16(base)	\
 	blr
 
-.globl	_restgpr0_14
-_restgpr0_14:
-	ld	r14,-144(r1)
-.globl	_restgpr0_15
-_restgpr0_15:
-	ld	r15,-136(r1)
-.globl	_restgpr0_16
-_restgpr0_16:
-	ld	r16,-128(r1)
-.globl	_restgpr0_17
-_restgpr0_17:
-	ld	r17,-120(r1)
-.globl	_restgpr0_18
-_restgpr0_18:
-	ld	r18,-112(r1)
-.globl	_restgpr0_19
-_restgpr0_19:
-	ld	r19,-104(r1)
-.globl	_restgpr0_20
-_restgpr0_20:
-	ld	r20,-96(r1)
-.globl	_restgpr0_21
-_restgpr0_21:
-	ld	r21,-88(r1)
-.globl	_restgpr0_22
-_restgpr0_22:
-	ld	r22,-80(r1)
-.globl	_restgpr0_23
-_restgpr0_23:
-	ld	r23,-72(r1)
-.globl	_restgpr0_24
-_restgpr0_24:
-	ld	r24,-64(r1)
-.globl	_restgpr0_25
-_restgpr0_25:
-	ld	r25,-56(r1)
-.globl	_restgpr0_26
-_restgpr0_26:
-	ld	r26,-48(r1)
-.globl	_restgpr0_27
-_restgpr0_27:
-	ld	r27,-40(r1)
-.globl	_restgpr0_28
-_restgpr0_28:
-	ld	r28,-32(r1)
-.globl	_restgpr0_29
-_restgpr0_29:
-	ld	r0,16(r1)
-	ld	r29,-24(r1)
-	mtlr	r0
-	ld	r30,-16(r1)
-	ld	r31,-8(r1)
+#define __PPC64_RESTGPR(n,base)	\
+.globl	_restgpr##n##_14	\
+_restgpr##n##_14:		\
+	ld	r14,-144(base)	\
+.globl	_restgpr##n##_15	\
+_restgpr##n##_15:		\
+	ld	r15,-136(base)	\
+.globl	_restgpr##n##_16	\
+_restgpr##n##_16:		\
+	ld	r16,-128(base)	\
+.globl	_restgpr##n##_17	\
+_restgpr##n##_17:		\
+	ld	r17,-120(base)	\
+.globl	_restgpr##n##_18	\
+_restgpr##n##_18:		\
+	ld	r18,-112(base)	\
+.globl	_restgpr##n##_19	\
+_restgpr##n##_19:		\
+	ld	r19,-104(base)	\
+.globl	_restgpr##n##_20	\
+_restgpr##n##_20:		\
+	ld	r20,-96(base)	\
+.globl	_restgpr##n##_21	\
+_restgpr##n##_21:		\
+	ld	r21,-88(base)	\
+.globl	_restgpr##n##_22	\
+_restgpr##n##_22:		\
+	ld	r22,-80(base)	\
+.globl	_restgpr##n##_23	\
+_restgpr##n##_23:		\
+	ld	r23,-72(base)	\
+.globl	_restgpr##n##_24	\
+_restgpr##n##_24:		\
+	ld	r24,-64(base)	\
+.globl	_restgpr##n##_25	\
+_restgpr##n##_25:		\
+	ld	r25,-56(base)	\
+.globl	_restgpr##n##_26	\
+_restgpr##n##_26:		\
+	ld	r26,-48(base)	\
+.globl	_restgpr##n##_27	\
+_restgpr##n##_27:		\
+	ld	r27,-40(base)	\
+.globl	_restgpr##n##_28	\
+_restgpr##n##_28:		\
+	ld	r28,-32(base)	\
+.globl	_restgpr##n##_29	\
+_restgpr##n##_29:		\
+	ld	r0,16(base)	\
+	ld	r29,-24(base)	\
+	mtlr	r0		\
+	ld	r30,-16(base)	\
+	ld	r31,-8(base)	\
+	blr			\
+				\
+.globl	_restgpr##n##_30	\
+_restgpr##n##_30:		\
+	ld	r30,-16(base)	\
+.globl	_restgpr##n##_31	\
+_restgpr##n##_31:		\
+	ld	r0,16(base)	\
+	ld	r31,-8(base)	\
+	mtlr	r0		\
 	blr
 
-.globl	_restgpr0_30
-_restgpr0_30:
-	ld	r30,-16(r1)
-.globl	_restgpr0_31
-_restgpr0_31:
-	ld	r0,16(r1)
-	ld	r31,-8(r1)
-	mtlr	r0
-	blr
+__PPC64_RESTGPR(0, r1)
+__PPC64_RESTGPR(1, r12)
+
+__PPC64_SAVEGPR(0, r1)
+__PPC64_SAVEGPR(1, r12)
 
 #ifdef CONFIG_ALTIVEC
 /* Called with r0 pointing just beyond the end of the vector save area.  */
@@ -540,6 +549,128 @@  _restvr_31:
 
 #endif /* CONFIG_ALTIVEC */
 
+#ifdef CONFIG_PPC_FPU
+
+.globl	_savefpr_14
+_savefpr_14:
+	stfd f14,-144(r1)
+.globl	_savefpr_15
+_savefpr_15:
+	stfd f15,-136(r1)
+.globl	_savefpr_16
+_savefpr_16:
+	stfd f16,-128(r1)
+.globl	_savefpr_17
+_savefpr_17:
+	stfd f17,-120(r1)
+.globl	_savefpr_18
+_savefpr_18:
+	stfd f18,-112(r1)
+.globl	_savefpr_19
+_savefpr_19:
+	stfd f19,-104(r1)
+.globl	_savefpr_20
+_savefpr_20:
+	stfd f20,-96(r1)
+.globl	_savefpr_21
+_savefpr_21:
+	stfd f21,-88(r1)
+.globl	_savefpr_22
+_savefpr_22:
+	stfd f22,-80(r1)
+.globl	_savefpr_23
+_savefpr_23:
+	stfd f23,-72(r1)
+.globl	_savefpr_24
+_savefpr_24:
+	stfd f24,-64(r1)
+.globl	_savefpr_25
+_savefpr_25:
+	stfd f25,-56(r1)
+.globl	_savefpr_26
+_savefpr_26:
+	stfd f26,-48(r1)
+.globl	_savefpr_27
+_savefpr_27:
+	stfd f27,-40(r1)
+.globl	_savefpr_28
+_savefpr_28:
+	stfd f28,-32(r1)
+.globl	_savefpr_29
+_savefpr_29:
+	stfd f29,-24(r1)
+.globl	_savefpr_30
+_savefpr_30:
+	stfd f30,-16(r1)
+.globl	_savefpr_31
+_savefpr_31:
+	stfd f31,-8(r1)
+	std r0, 16(r1)
+	blr
+
+.globl	_restfpr_14
+_restfpr_14:
+	lfd f14,-144(r1)
+.globl	_restfpr_15
+_restfpr_15:
+	lfd f15,-136(r1)
+.globl	_restfpr_16
+_restfpr_16:
+	lfd f16,-128(r1)
+.globl	_restfpr_17
+_restfpr_17:
+	lfd f17,-120(r1)
+.globl	_restfpr_18
+_restfpr_18:
+	lfd f18,-112(r1)
+.globl	_restfpr_19
+_restfpr_19:
+	lfd f19,-104(r1)
+.globl	_restfpr_20
+_restfpr_20:
+	lfd f20,-96(r1)
+.globl	_restfpr_21
+_restfpr_21:
+	lfd f21,-88(r1)
+.globl	_restfpr_22
+_restfpr_22:
+	lfd f22,-80(r1)
+.globl	_restfpr_23
+_restfpr_23:
+	lfd f23,-72(r1)
+.globl	_restfpr_24
+_restfpr_24:
+	lfd f24,-64(r1)
+.globl	_restfpr_25
+_restfpr_25:
+	lfd f25,-56(r1)
+.globl	_restfpr_26
+_restfpr_26:
+	lfd f26,-48(r1)
+.globl	_restfpr_27
+_restfpr_27:
+	lfd f27,-40(r1)
+.globl	_restfpr_28
+_restfpr_28:
+	lfd f28,-32(r1)
+.globl	_restfpr_29
+_restfpr_29:
+	ld r0, 16(r1)
+	lfd f29,-24(r1)
+	mtlr r0
+	lfd f30,-16(r1)
+	lfd f31,-8(r1)
+	blr
+.globl	_restfpr_30
+_restfpr_30:
+	lfd f30,-16(r1)
+.globl	_restfpr_31
+_restfpr_31:
+	ld r0, 16(r1)
+	lfd f31,-8(r1)
+
+#endif /* CONFIG_PPC_FPU */
+
 #endif /* CONFIG_PPC64 */
 
 #endif
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 267b9a0a3abc..153a163ba3f7 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -597,8 +597,12 @@  static int ignore_undef_symbol(struct elf_info *info, const char *symname)
 		/* Special register function linked on all modules during final link of .ko */
 		if (strstarts(symname, "_restgpr0_") ||
 		    strstarts(symname, "_savegpr0_") ||
+		    strstarts(symname, "_restgpr1_") ||
+		    strstarts(symname, "_savegpr1_") ||
 		    strstarts(symname, "_restvr_") ||
 		    strstarts(symname, "_savevr_") ||
+		    strstarts(symname, "_restfpr_") ||
+		    strstarts(symname, "_savefpr_") ||
 		    strcmp(symname, ".TOC.") == 0)
 			return 1;