Skip to content

Commit a1ff574

Browse files
oohalmpe
authored andcommitted
powerpc/boot: Fix the early OPAL console wrappers
When configured with CONFIG_PPC_EARLY_DEBUG_OPAL=y the kernel expects the OPAL entry and base addresses to be passed in r8 and r9 respectively. Currently the wrapper does not attempt to restore these values before entering the decompressed kernel which causes the kernel to branch into whatever happens to be in r9 when doing a write to the OPAL console in early boot. This patch adds a platform_ops hook that can be used to branch into the new kernel. The OPAL console driver patches this at runtime so that if the console is used it will be restored just prior to entering the kernel. Fixes: 656ad58 ("powerpc/boot: Add OPAL console to epapr wrappers") Cc: stable@vger.kernel.org # v4.8+ Signed-off-by: Oliver O'Halloran <oohall@gmail.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
1 parent 9e5f688 commit a1ff574

4 files changed

Lines changed: 31 additions & 2 deletions

File tree

arch/powerpc/boot/main.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,8 +232,12 @@ void start(void)
232232
console_ops.close();
233233

234234
kentry = (kernel_entry_t) vmlinux.addr;
235-
if (ft_addr)
236-
kentry(ft_addr, 0, NULL);
235+
if (ft_addr) {
236+
if(platform_ops.kentry)
237+
platform_ops.kentry(ft_addr, vmlinux.addr);
238+
else
239+
kentry(ft_addr, 0, NULL);
240+
}
237241
else
238242
kentry((unsigned long)initrd.addr, initrd.size,
239243
loader_info.promptr);

arch/powerpc/boot/opal-calls.S

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,19 @@
1212

1313
.text
1414

15+
.globl opal_kentry
16+
opal_kentry:
17+
/* r3 is the fdt ptr */
18+
mtctr r4
19+
li r4, 0
20+
li r5, 0
21+
li r6, 0
22+
li r7, 0
23+
ld r11,opal@got(r2)
24+
ld r8,0(r11)
25+
ld r9,8(r11)
26+
bctr
27+
1528
#define OPAL_CALL(name, token) \
1629
.globl name; \
1730
name: \

arch/powerpc/boot/opal.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,25 @@ struct opal {
2323

2424
static u32 opal_con_id;
2525

26+
/* see opal-wrappers.S */
2627
int64_t opal_console_write(int64_t term_number, u64 *length, const u8 *buffer);
2728
int64_t opal_console_read(int64_t term_number, uint64_t *length, u8 *buffer);
2829
int64_t opal_console_write_buffer_space(uint64_t term_number, uint64_t *length);
2930
int64_t opal_console_flush(uint64_t term_number);
3031
int64_t opal_poll_events(uint64_t *outstanding_event_mask);
3132

33+
void opal_kentry(unsigned long fdt_addr, void *vmlinux_addr);
34+
3235
static int opal_con_open(void)
3336
{
37+
/*
38+
* When OPAL loads the boot kernel it stashes the OPAL base and entry
39+
* address in r8 and r9 so the kernel can use the OPAL console
40+
* before unflattening the devicetree. While executing the wrapper will
41+
* probably trash r8 and r9 so this kentry hook restores them before
42+
* entering the decompressed kernel.
43+
*/
44+
platform_ops.kentry = opal_kentry;
3445
return 0;
3546
}
3647

arch/powerpc/boot/ops.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ struct platform_ops {
3030
void * (*realloc)(void *ptr, unsigned long size);
3131
void (*exit)(void);
3232
void * (*vmlinux_alloc)(unsigned long size);
33+
void (*kentry)(unsigned long fdt_addr, void *vmlinux_addr);
3334
};
3435
extern struct platform_ops platform_ops;
3536

0 commit comments

Comments
 (0)