[Skiboot] [PATCH v5 24/27] add little endian support

Nicholas Piggin npiggin at gmail.com
Tue Oct 15 14:07:14 AEDT 2019


This adds support for building LE skiboot with LITTLE_ENDIAN=1.

This is not complete, notably PHB3, NPU* and *CAPI*, but it is
sufficient to build and boot on mambo and OpenPOWER POWER9 systems.

LE/ELFv2 is a nicer calling convention, and results in smaller image and
less stack usage. It also follows the rest of the Linux/OpenPOWER stack
moving to LE.

The OPALv3 call interface still requires an ugly transition through BE
for compatibility, but that is all handled on the OPAL side.

Signed-off-by: Nicholas Piggin <npiggin at gmail.com>
---
 Makefile.main                            | 38 ++++++++++++--
 asm/head.S                               | 66 +++++++++++++++++-------
 core/cpu.c                               | 24 +++++++--
 core/init.c                              |  1 +
 doc/stb.rst                              |  2 +-
 include/asm-utils.h                      | 22 ++++++--
 include/cpu.h                            |  3 ++
 libpore/p9_cpu_reg_restore_instruction.H | 23 +++++----
 8 files changed, 135 insertions(+), 44 deletions(-)

diff --git a/Makefile.main b/Makefile.main
index 2d60bbbf5..1d834e81b 100644
--- a/Makefile.main
+++ b/Makefile.main
@@ -65,21 +65,35 @@ CPPFLAGS += -I$(SRC)/libfdt -I$(SRC)/libflash -I$(SRC)/libxz -I$(SRC)/libc/inclu
 CPPFLAGS += -I$(SRC)/libpore
 CPPFLAGS += -D__SKIBOOT__ -nostdinc
 CPPFLAGS += -isystem $(shell $(CC) -print-file-name=include)
-CPPFLAGS += -DBITS_PER_LONG=64 -DHAVE_BIG_ENDIAN
+CPPFLAGS += -DBITS_PER_LONG=64
+
 # We might want to remove our copy of stdint.h
 # but that means uint64_t becomes an ulong instead of an ullong
 # causing all our printf's to warn
 CPPFLAGS += -ffreestanding
 
+ifeq ($(LITTLE_ENDIAN),1)
+CPPFLAGS += -DHAVE_LITTLE_ENDIAN
+else
+CPPFLAGS += -DHAVE_BIG_ENDIAN
+endif
+
 ifeq ($(DEBUG),1)
 CPPFLAGS += -DDEBUG -DCCAN_LIST_DEBUG
 endif
 
-CFLAGS := -fno-strict-aliasing -pie -fpie -fno-pic -mbig-endian -m64 -fno-asynchronous-unwind-tables
+CFLAGS := -fno-strict-aliasing -pie -fpie -fno-pic -m64 -fno-asynchronous-unwind-tables
 CFLAGS += -mcpu=power8
 CFLAGS += -Wl,--oformat,elf64-powerpc -ggdb
 CFLAGS += $(call try-cflag,$(CC),-ffixed-r13)
 CFLAGS += $(call try-cflag,$(CC),-std=gnu11)
+
+ifeq ($(LITTLE_ENDIAN),1)
+CFLAGS += -mlittle-endian
+else
+CFLAGS += -mbig-endian
+endif
+
 ifeq ($(ELF_ABI_v2),1)
 CFLAGS += $(call try-cflag,$(CC),-mabi=elfv2)
 else
@@ -135,8 +149,8 @@ LDFLAGS := -m64 -static -nostdlib -pie
 LDFLAGS += -Wl,-pie
 LDFLAGS += -Wl,-Ttext-segment,$(LD_TEXT) -Wl,-N -Wl,--build-id=none
 LDFLAGS += -Wl,--no-multi-toc
-LDFLAGS += -mcpu=power8 -mbig-endian -Wl,--oformat,elf64-powerpc
-LDFLAGS_FINAL = -EB -m elf64ppc --no-multi-toc -N --build-id=none --whole-archive
+LDFLAGS += -mcpu=power8 -Wl,--oformat,elf64-powerpc
+LDFLAGS_FINAL = -m elf64lppc --no-multi-toc -N --build-id=none --whole-archive
 LDFLAGS_FINAL += -static -nostdlib -pie -Ttext-segment=$(LD_TEXT) --oformat=elf64-powerpc
 LDFLAGS_FINAL += --orphan-handling=warn
 
@@ -144,11 +158,25 @@ LDRFLAGS=-melf64ppc
 # Debug stuff
 #LDFLAGS += -Wl,-v -Wl,-Map,foomap 
 
+ifeq ($(LITTLE_ENDIAN),1)
+LDFLAGS += -mlittle-endian
+LDFLAGS_FINAL += -EL
+else
+LDFLAGS += -mbig-endian
+LDFLAGS_FINAL += -EB
+endif
+
 ifeq ($(DEAD_CODE_ELIMINATION),1)
 LDFLAGS += -Wl,--gc-sections
 endif
 
-AFLAGS := -D__ASSEMBLY__ -mbig-endian -m64
+AFLAGS := -D__ASSEMBLY__ -m64
+ifeq ($(LITTLE_ENDIAN),1)
+AFLAGS += -mlittle-endian
+else
+AFLAGS += -mbig-endian
+endif
+
 ifeq ($(ELF_ABI_v2),1)
 AFLAGS += $(call try-cflag,$(CC),-mabi=elfv2)
 else
diff --git a/asm/head.S b/asm/head.S
index e70462299..d396f16c9 100644
--- a/asm/head.S
+++ b/asm/head.S
@@ -43,6 +43,7 @@ __head:
 	. = 0x10
 .global fdt_entry
 fdt_entry:
+	FIXUP_ENDIAN
 	mr	%r27,%r3
 	b	boot_entry
 
@@ -89,6 +90,7 @@ hir_trigger:
 	. = 0x100
 sreset_vector:
 	/* BML entry, load up r3 with device tree location */
+	FIXUP_ENDIAN
 	li	%r3, 0
 	oris	%r3, %r3, 0xa
 	b	fdt_entry /* hack for lab boot */
@@ -96,6 +98,7 @@ sreset_vector:
 	/* Entry point set by the FSP */
 	.= 0x180
 hdat_entry:
+	FIXUP_ENDIAN
 	li	%r27,0
 	b	boot_entry
 
@@ -364,7 +367,11 @@ boot_entry:
 	add	%r2,%r2,%r29
 
 	/* Fixup our MSR (remove TA) */
+#if HAVE_BIG_ENDIAN
 	LOAD_IMM64(%r3, (MSR_HV | MSR_SF))
+#else
+	LOAD_IMM64(%r3, (MSR_HV | MSR_SF | MSR_LE))
+#endif
 	mtmsrd	%r3,0
 
 	/* Check our PIR, avoid threads */
@@ -698,14 +705,18 @@ init_shared_sprs:
 	mtspr	SPR_TSCR, %r3
 
 	/* HID0: Clear bit 13 (enable core recovery)
-	 *       Clear bit 19 (HILE)
+	 *       Set/clear bit 19 (HILE) depending on skiboot endian
 	 */
 	mfspr	%r3,SPR_HID0
 	li	%r0,1
 	sldi	%r4,%r0,(63-13)
-	sldi	%r5,%r0,(63-19)
-	or	%r0,%r4,%r5
-	andc	%r3,%r3,%r0
+	andc	%r3,%r3,%r4
+	sldi	%r4,%r0,(63-19)
+#if HAVE_BIG_ENDIAN
+	andc	%r3,%r3,%r4
+#else
+	or	%r3,%r3,%r4
+#endif
 	sync
 	mtspr	SPR_HID0,%r3
 	mfspr	%r3,SPR_HID0
@@ -732,17 +743,21 @@ init_shared_sprs:
 	LOAD_IMM32(%r3,0x80287880)
 	mtspr	SPR_TSCR, %r3
 	/* HID0: Clear bit 5 (enable core recovery)
-	 *       Clear bit 4 (HILE)
+	 *       Set/clear bit 4 (HILE) depending on skiboot endian
 	 *       Set bit 8 (radix)
 	 */
 	mfspr	%r3,SPR_HID0
 	li	%r0,1
-	sldi	%r4,%r0,(63-8)
+	sldi	%r4,%r0,(63-4)
+#if HAVE_BIG_ENDIAN
+	andc	%r3,%r3,%r4
+#else
 	or	%r3,%r3,%r4
+#endif
 	sldi	%r4,%r0,(63-5)
-	sldi	%r5,%r0,(63-4)
-	or	%r0,%r4,%r5
-	andc	%r3,%r3,%r0
+	andc	%r3,%r3,%r4
+	sldi	%r4,%r0,(63-8)
+	or	%r3,%r3,%r4
 	sync
 	mtspr	SPR_HID0,%r3
 	isync
@@ -822,6 +837,8 @@ enter_nap:
 	.balign	0x10
 .global opal_entry
 opal_entry:
+	OPAL_ENTRY_TO_SKIBOOT_ENDIAN
+
 	/* Get our per CPU pointer in r12 to check for quiesce */
 	mfspr	%r12,SPR_PIR
 	GET_STACK(%r12,%r12)
@@ -968,20 +985,33 @@ opal_entry:
 	lwz	%r11,CPUTHREAD_IN_OPAL_CALL(%r12)
 	subi	%r11,%r11,1
 	stw	%r11,CPUTHREAD_IN_OPAL_CALL(%r12)
+#if HAVE_BIG_ENDIAN
 	/*
 	 * blr with BH=01b means it's not a function return, OPAL was entered
 	 * via (h)rfid not bl, so we don't have a corresponding link stack
 	 * prediction to return to here.
 	 */
 	bclr	20,0,1
+#else
+	mflr	%r12
+	mtspr	SPR_HSRR0,%r12
+	mfmsr	%r11
+	li	%r12,MSR_LE
+	andc	%r11,%r11,%r12
+	mtspr	SPR_HSRR1,%r11
+	hrfid
+#endif
 
 .global start_kernel
 start_kernel:
+	LOAD_IMM64(%r10,MSR_HV|MSR_SF)
+__start_kernel:
 	sync
 	icbi	0,%r3
 	sync
 	isync
-	mtctr	%r3
+	mtspr	SPR_HSRR0,%r3
+	mtspr	SPR_HSRR1,%r10
 	mr	%r3,%r4
 	LOAD_IMM64(%r8,SKIBOOT_BASE);
 	LOAD_IMM32(%r10, opal_entry - __head)
@@ -990,21 +1020,19 @@ start_kernel:
 	addi	%r7,%r5,1
 	li	%r4,0
 	li	%r5,0
-	bctr
+	hrfid
 
 	.global start_kernel32
 start_kernel32:
-	mfmsr	%r10
-	clrldi	%r10,%r10,1
-	mtmsrd	%r10,0
-	sync
-	isync
-	b	start_kernel
+	LOAD_IMM64(%r10,MSR_HV)
+	b	__start_kernel
 
 .global start_kernel_secondary
 start_kernel_secondary:
 	sync
 	isync
-	mtctr	%r3
+	LOAD_IMM64(%r10,MSR_HV|MSR_SF)
+	mtspr	SPR_HSRR0,%r3
+	mtspr	SPR_HSRR1,%r10
 	mfspr	%r3,SPR_PIR
-	bctr
+	hrfid
diff --git a/core/cpu.c b/core/cpu.c
index b3433aef5..3d6a59033 100644
--- a/core/cpu.c
+++ b/core/cpu.c
@@ -42,7 +42,7 @@ static unsigned long hid0_attn;
 static bool sreset_enabled;
 static bool ipi_enabled;
 static bool pm_enabled;
-static bool current_hile_mode;
+static bool current_hile_mode = HAVE_LITTLE_ENDIAN;
 static bool current_radix_mode = true;
 static bool tm_suspend_enabled;
 
@@ -1415,6 +1415,24 @@ static int64_t cpu_change_all_hid0(struct hid0_change_req *req)
 	return OPAL_SUCCESS;
 }
 
+void cpu_set_hile_mode(bool hile)
+{
+	struct hid0_change_req req;
+
+	if (hile == current_hile_mode)
+		return;
+
+	if (hile) {
+		req.clr_bits = 0;
+		req.set_bits = hid0_hile;
+	} else {
+		req.clr_bits = hid0_hile;
+		req.set_bits = 0;
+	}
+	cpu_change_all_hid0(&req);
+	current_hile_mode = hile;
+}
+
 static void cpu_cleanup_one(void *param __unused)
 {
 	mtspr(SPR_AMR, 0);
@@ -1453,8 +1471,8 @@ static int64_t cpu_cleanup_all(void)
 
 void cpu_fast_reboot_complete(void)
 {
-	/* Fast reboot will have cleared HID0:HILE */
-	current_hile_mode = false;
+	/* Fast reboot will have set HID0:HILE to skiboot endian */
+	current_hile_mode = HAVE_LITTLE_ENDIAN;
 
 	/* and set HID0:RADIX */
 	current_radix_mode = true;
diff --git a/core/init.c b/core/init.c
index 67185c9e1..0b63655bc 100644
--- a/core/init.c
+++ b/core/init.c
@@ -630,6 +630,7 @@ void __noreturn load_and_boot_kernel(bool is_reboot)
 	cpu_disable_ME_RI_all();
 
 	patch_traps(false);
+	cpu_set_hile_mode(false); /* Clear HILE on all CPUs */
 
 	debug_descriptor.state_flags |= OPAL_BOOT_COMPLETE;
 
diff --git a/doc/stb.rst b/doc/stb.rst
index 6fc8f73da..84855ca55 100644
--- a/doc/stb.rst
+++ b/doc/stb.rst
@@ -92,7 +92,7 @@ CVC-verify Service
 .. code-block:: c
 
         int call_cvc_verify(void *buf, size_t size, const void *hw_key_hash,
-                            size_t hw_key_hash_size, uint64_t *log)
+                            size_t hw_key_hash_size, __be64 *log)
 
 This function wrapper calls into the *CVC-verify*, which verifies if the
 firmware code provided in ``@buf`` is properly signed with the keys trusted by
diff --git a/include/asm-utils.h b/include/asm-utils.h
index 2d26545e7..c3d8c09ea 100644
--- a/include/asm-utils.h
+++ b/include/asm-utils.h
@@ -28,17 +28,29 @@
 /* Load an address via the TOC */
 #define LOAD_ADDR_FROM_TOC(r, e)	ld r,e at got(%r2)
 
-#define FIXUP_ENDIAN						   \
-	tdi   0,0,0x48;	  /* Reverse endian of b . + 8		*/ \
-	b     191f;	  /* Skip trampoline if endian is good	*/ \
+/* This must preserve LR, so can't use Linux kernel's FIXUP_ENDIAN */
+#define SWITCH_ENDIAN						   \
 	.long 0xa600607d; /* mfmsr r11				*/ \
 	.long 0x01006b69; /* xori r11,r11,1			*/ \
+	.long 0xa64b7b7d; /* mthsrr1 r11			*/ \
+	.long 0xa602687d; /* mflr r11				*/ \
 	.long 0x05009f42; /* bcl 20,31,$+4			*/ \
 	.long 0xa602487d; /* mflr r10				*/ \
 	.long 0x14004a39; /* addi r10,r10,20			*/ \
 	.long 0xa64b5a7d; /* mthsrr0 r10			*/ \
-	.long 0xa64b7b7d; /* mthsrr1 r11			*/ \
-	.long 0x2402004c; /* hrfid				*/ \
+	.long 0xa603687d; /* mtlr r11				*/ \
+	.long 0x2402004c  /* hrfid				*/
+
+#define FIXUP_ENDIAN						   \
+	tdi   0,0,0x48;	  /* Reverse endian of b . + 8		*/ \
+	b     191f;	  /* Skip trampoline if endian is good	*/ \
+	SWITCH_ENDIAN;	  /* Do the switch			*/ \
 191:
 
+#if HAVE_BIG_ENDIAN
+#define OPAL_ENTRY_TO_SKIBOOT_ENDIAN
+#else
+#define OPAL_ENTRY_TO_SKIBOOT_ENDIAN SWITCH_ENDIAN
+#endif
+
 #endif /* __ASM_UTILS_H */
diff --git a/include/cpu.h b/include/cpu.h
index cda78644d..008f08a68 100644
--- a/include/cpu.h
+++ b/include/cpu.h
@@ -282,6 +282,9 @@ extern void cpu_process_local_jobs(void);
 /* Check if there's any job pending */
 bool cpu_check_jobs(struct cpu_thread *cpu);
 
+/* Set/clear HILE on all CPUs */
+void cpu_set_hile_mode(bool hile);
+
 /* OPAL sreset vector in place at 0x100 */
 void cpu_set_sreset_enable(bool sreset_enabled);
 
diff --git a/libpore/p9_cpu_reg_restore_instruction.H b/libpore/p9_cpu_reg_restore_instruction.H
index dd4358a82..cf00ff5e5 100644
--- a/libpore/p9_cpu_reg_restore_instruction.H
+++ b/libpore/p9_cpu_reg_restore_instruction.H
@@ -61,23 +61,24 @@ enum
     RLDICR_CONST        =   1,
     MTSPR_CONST1        =   467,
     MTMSRD_CONST1       =   178,
-    MR_R0_TO_R10        =   0x7c0a0378, //mr r10, r0
-    MR_R0_TO_R21        =   0x7c150378, //mr r21, r0
-    MR_R0_TO_R9         =   0x7c090378, //mr r9, r0
-    URMOR_CORRECTION    =   0x7d397ba6,
     MFSPR_CONST         =   339,
-    BLR_INST            =   0x4e800020,
-    MTSPR_BASE_OPCODE   =   0x7c0003a6,
-    ATTN_OPCODE         =   0x00000200,
     OPCODE_18           =   18,
     SELF_SAVE_FUNC_ADD  =   0x2300,
     SELF_SAVE_OFFSET    =   0x180,
-    SKIP_SPR_REST_INST  =   0x4800001c, //b . +0x01c
-    MFLR_R30            =   0x7fc802a6,
-    SKIP_SPR_SELF_SAVE  =   0x3bff0020, //addi r31 r31, 0x20
-    MTLR_INST           =   0x7fc803a6  //mtlr r30
 };
 
+#define MR_R0_TO_R10            0x7c0a0378UL //mr r10 r0
+#define MR_R0_TO_R21            0x7c150378UL //mr r21 r0
+#define MR_R0_TO_R9             0x7c090378UL //mr r9 r0
+#define URMOR_CORRECTION        0x7d397ba6UL
+#define BLR_INST                0x4e800020UL
+#define MTSPR_BASE_OPCODE       0x7c0003a6UL
+#define ATTN_OPCODE             0x00000200UL
+#define SKIP_SPR_REST_INST      0x4800001cUL //b . +0x01c
+#define MFLR_R30                0x7fc802a6UL
+#define SKIP_SPR_SELF_SAVE      0x3bff0020UL //addi r31 r31 0x20
+#define MTLR_INST               0x7fc803a6UL //mtlr r30
+
 #ifdef __cplusplus
 } // namespace stopImageSection ends
 
-- 
2.23.0



More information about the Skiboot mailing list