Skip to content

Commit

Permalink
powerpc/64: Setup a paca before parsing device tree etc.
Browse files Browse the repository at this point in the history
Currently we set up the paca after parsing the device tree for CPU
features. Prior to that, r13 contains random data, which means there
is random data in r13 while we're running the generic dt parsing code.

This random data varies depending on whether we boot through a vmlinux
or a zImage: for the vmlinux case it's usually around zero, but for
zImages we see random values like 912a72603d420015.

This is poor practice, and can also lead to difficult-to-debug
crashes. For example, when kcov is enabled, the kcov instrumentation
attempts to read preempt_count out of the current task, which goes via
the paca. This then crashes in the zImage case.

Similarly stack protector can cause crashes if r13 is bogus, by
reading from the stack canary in the paca.

To resolve this:

 - move the paca setup to before the CPU feature parsing.

 - because we no longer have access to CPU feature flags in paca
 setup, change the HV feature test in the paca setup path to consider
 the actual value of the MSR rather than the CPU feature.

Translations get switched on once we leave early_setup, so I think
we'd already catch any other cases where the paca or task aren't set
up.

Boot tested on a P9 guest and host.

Fixes: fb0b0a7 ("powerpc: Enable kcov")
Fixes: 06ec27a ("powerpc/64: add stack protector support")
Cc: [email protected] # v4.20+
Reviewed-by: Andrew Donnellan <[email protected]>
Suggested-by: Michael Ellerman <[email protected]>
Signed-off-by: Daniel Axtens <[email protected]>
[mpe: Reword comments & change log a bit to mention stack protector]
Signed-off-by: Michael Ellerman <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
  • Loading branch information
daxtens authored and mpe committed Mar 25, 2020
1 parent d95fe37 commit d4a8e98
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 10 deletions.
1 change: 0 additions & 1 deletion arch/powerpc/kernel/dt_cpu_ftrs.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,6 @@ static void __init cpufeatures_setup_cpu(void)
/* Initialize the base environment -- clear FSCR/HFSCR. */
hv_mode = !!(mfmsr() & MSR_HV);
if (hv_mode) {
/* CPU_FTR_HVMODE is used early in PACA setup */
cur_cpu_spec->cpu_features |= CPU_FTR_HVMODE;
mtspr(SPRN_HFSCR, 0);
}
Expand Down
10 changes: 7 additions & 3 deletions arch/powerpc/kernel/paca.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,11 +214,15 @@ void setup_paca(struct paca_struct *new_paca)
/* On Book3E, initialize the TLB miss exception frames */
mtspr(SPRN_SPRG_TLB_EXFRAME, local_paca->extlb);
#else
/* In HV mode, we setup both HPACA and PACA to avoid problems
/*
* In HV mode, we setup both HPACA and PACA to avoid problems
* if we do a GET_PACA() before the feature fixups have been
* applied
* applied.
*
* Normally you should test against CPU_FTR_HVMODE, but CPU features
* are not yet set up when we first reach here.
*/
if (early_cpu_has_feature(CPU_FTR_HVMODE))
if (mfmsr() & MSR_HV)
mtspr(SPRN_SPRG_HPACA, local_paca);
#endif
mtspr(SPRN_SPRG_PACA, local_paca);
Expand Down
30 changes: 24 additions & 6 deletions arch/powerpc/kernel/setup_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -285,18 +285,36 @@ void __init early_setup(unsigned long dt_ptr)

/* -------- printk is _NOT_ safe to use here ! ------- */

/* Try new device tree based feature discovery ... */
if (!dt_cpu_ftrs_init(__va(dt_ptr)))
/* Otherwise use the old style CPU table */
identify_cpu(0, mfspr(SPRN_PVR));

/* Assume we're on cpu 0 for now. Don't write to the paca yet! */
/*
* Assume we're on cpu 0 for now.
*
* We need to load a PACA very early for a few reasons.
*
* The stack protector canary is stored in the paca, so as soon as we
* call any stack protected code we need r13 pointing somewhere valid.
*
* If we are using kcov it will call in_task() in its instrumentation,
* which relies on the current task from the PACA.
*
* dt_cpu_ftrs_init() calls into generic OF/fdt code, as well as
* printk(), which can trigger both stack protector and kcov.
*
* percpu variables and spin locks also use the paca.
*
* So set up a temporary paca. It will be replaced below once we know
* what CPU we are on.
*/
initialise_paca(&boot_paca, 0);
setup_paca(&boot_paca);
fixup_boot_paca();

/* -------- printk is now safe to use ------- */

/* Try new device tree based feature discovery ... */
if (!dt_cpu_ftrs_init(__va(dt_ptr)))
/* Otherwise use the old style CPU table */
identify_cpu(0, mfspr(SPRN_PVR));

/* Enable early debugging if any specified (see udbg.h) */
udbg_early_init();

Expand Down

0 comments on commit d4a8e98

Please sign in to comment.