[PATCH 5/5] powerpc/64e: provide an addressing macro for use with TOC in alternate register

Nicholas Piggin npiggin at gmail.com
Fri Sep 23 13:25:12 AEST 2022


The interrupt entry code carefully saves a minimal number of registers,
so in some places the TOC is required, it is loaded into a different
register, so provide a macro that can supply an alternate TOC register.

This continues to use got addressing because TOC-relative results in
"got/toc optimization is not supported" messages by the linker. Having
r2 be one of the saved registers and using that for TOC addressing may
be the best way to avoid that and switch this to TOC addressing.

Signed-off-by: Nicholas Piggin <npiggin at gmail.com>
---
 arch/powerpc/include/asm/ppc_asm.h   | 11 +++++++++++
 arch/powerpc/kernel/exceptions-64e.S | 14 +++++++-------
 arch/powerpc/mm/nohash/tlb_low_64e.S |  2 +-
 3 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
index 17a87ecd82c9..622aaaec2be9 100644
--- a/arch/powerpc/include/asm/ppc_asm.h
+++ b/arch/powerpc/include/asm/ppc_asm.h
@@ -324,6 +324,17 @@ GLUE(.,name):
 	addis	reg,r2,name at toc@ha;		\
 	addi	reg,reg,name at toc@l
 
+#ifdef CONFIG_PPC_BOOK3E_64
+/*
+ * This is used in register-constrained interrupt handlers. Not to be used
+ * by BOOK3S. ld complains with "got/toc optimization is not supported" if r2
+ * is not used for the TOC offset, so use @got(tocreg). If the interrupt
+ * handlers saved r2 instead, LOAD_REG_ADDR could be used.
+ */
+#define LOAD_REG_ADDR_ALTTOC(reg,tocreg,name)	\
+	ld	reg,name at got(tocreg)
+#endif
+
 #define LOAD_REG_ADDRBASE(reg,name)	LOAD_REG_ADDR(reg,name)
 #define ADDROFF(name)			0
 
diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S
index c20b39d011a9..8ac9dfd38874 100644
--- a/arch/powerpc/kernel/exceptions-64e.S
+++ b/arch/powerpc/kernel/exceptions-64e.S
@@ -699,8 +699,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 
 #ifdef CONFIG_RELOCATABLE
 	__LOAD_PACA_TOC(r15)
-	ld	r14,interrupt_base_book3e at got(r15)
-	ld	r15,__end_interrupts at got(r15)
+	LOAD_REG_ADDR_ALTTOC(r14, r15, interrupt_base_book3e)
+	LOAD_REG_ADDR_ALTTOC(r15, r15, __end_interrupts)
 	cmpld	cr0,r10,r14
 	cmpld	cr1,r10,r15
 #else
@@ -770,8 +770,8 @@ kernel_dbg_exc:
 
 #ifdef CONFIG_RELOCATABLE
 	__LOAD_PACA_TOC(r15)
-	ld	r14,interrupt_base_book3e at got(r15)
-	ld	r15,__end_interrupts at got(r15)
+	LOAD_REG_ADDR_ALTTOC(r14, r15, interrupt_base_book3e)
+	LOAD_REG_ADDR_ALTTOC(r15, r15, __end_interrupts)
 	cmpld	cr0,r10,r14
 	cmpld	cr1,r10,r15
 #else
@@ -895,8 +895,8 @@ kernel_dbg_exc:
 .macro SEARCH_RESTART_TABLE
 #ifdef CONFIG_RELOCATABLE
 	__LOAD_PACA_TOC(r11)
-	ld	r14,__start___restart_table at got(r11)
-	ld	r15,__stop___restart_table at got(r11)
+	LOAD_REG_ADDR_ALTTOC(r14, r11, __start___restart_table)
+	LOAD_REG_ADDR_ALTTOC(r15, r11, __stop___restart_table)
 #else
 	LOAD_REG_IMMEDIATE_SYM(r14, r11, __start___restart_table)
 	LOAD_REG_IMMEDIATE_SYM(r15, r11, __stop___restart_table)
@@ -1315,7 +1315,7 @@ a2_tlbinit_after_linear_map:
 	/* Now we branch the new virtual address mapped by this entry */
 #ifdef CONFIG_RELOCATABLE
 	__LOAD_PACA_TOC(r5)
-	ld	r3,1f at got(r5)
+	LOAD_REG_ADDR_ALTTOC(r3, r5, 1f)
 #else
 	LOAD_REG_IMMEDIATE_SYM(r3, r5, 1f)
 #endif
diff --git a/arch/powerpc/mm/nohash/tlb_low_64e.S b/arch/powerpc/mm/nohash/tlb_low_64e.S
index 0e4d9c817382..2f3095716721 100644
--- a/arch/powerpc/mm/nohash/tlb_low_64e.S
+++ b/arch/powerpc/mm/nohash/tlb_low_64e.S
@@ -1125,7 +1125,7 @@ tlb_load_linear:
 	 * final implementation, especially when dealing with hypervisors
 	 */
 	__LOAD_PACA_TOC(r11)
-	ld	r11,linear_map_top at got(r11)
+	LOAD_REG_ADDR_ALTTOC(r11, r11, linear_map_top)
 	ld	r10,0(r11)
 	tovirt(10,10)
 	cmpld	cr0,r16,r10
-- 
2.37.2



More information about the Linuxppc-dev mailing list