Skip to content

Commit

Permalink
add little endian support
Browse files Browse the repository at this point in the history
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@gmail.com>
Signed-off-by: Oliver O'Halloran <oohall@gmail.com>
  • Loading branch information
npiggin authored and oohal committed Dec 16, 2019
1 parent d71bb89 commit 35776a2
Show file tree
Hide file tree
Showing 8 changed files with 135 additions and 44 deletions.
38 changes: 33 additions & 5 deletions Makefile.main
Expand Up @@ -67,21 +67,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
Expand Down Expand Up @@ -139,20 +153,34 @@ 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

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
Expand Down
66 changes: 47 additions & 19 deletions asm/head.S
Expand Up @@ -43,6 +43,7 @@ __head:
. = 0x10
.global fdt_entry
fdt_entry:
FIXUP_ENDIAN
mr %r27,%r3
b boot_entry

Expand Down Expand Up @@ -89,13 +90,15 @@ 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 */

/* Entry point set by the FSP */
.= 0x180
hdat_entry:
FIXUP_ENDIAN
li %r27,0
b boot_entry

Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -702,14 +709,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
Expand All @@ -736,17 +747,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
Expand Down Expand Up @@ -826,6 +841,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)
Expand Down Expand Up @@ -971,20 +988,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)
Expand All @@ -993,21 +1023,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
24 changes: 21 additions & 3 deletions core/cpu.c
Expand Up @@ -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;

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions core/init.c
Expand Up @@ -632,6 +632,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 */

checksum_romem();

Expand Down
2 changes: 1 addition & 1 deletion doc/stb.rst
Expand Up @@ -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
Expand Down
22 changes: 17 additions & 5 deletions include/asm-utils.h
Expand Up @@ -28,17 +28,29 @@
/* Load an address via the TOC */
#define LOAD_ADDR_FROM_TOC(r, e) ld r,e@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 */
3 changes: 3 additions & 0 deletions include/cpu.h
Expand Up @@ -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);

Expand Down
23 changes: 12 additions & 11 deletions libpore/p9_cpu_reg_restore_instruction.H
Expand Up @@ -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

Expand Down

0 comments on commit 35776a2

Please sign in to comment.