summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Ellerman <mpe@ellerman.id.au>2017-07-24 17:10:15 +0300
committerMichael Ellerman <mpe@ellerman.id.au>2017-07-31 09:56:45 +0300
commit9227f0431435c9d664771b112c230e75ca4f9b52 (patch)
treedb9bdcb00ae0b513b077f2867748fc86b57ad551
parent3603c52f02ee3ad536e4cd08ac08e9c0c4d0c7eb (diff)
downloadlinux-9227f0431435c9d664771b112c230e75ca4f9b52.tar.xz
powerpc/udbg: Reduce the footgun potential of EARLY_DEBUG_LPAR(_HVSI)
For debugging very early boot problems we have CONFIG_PPC_EARLY_DEBUG, which allows configuring the kernel such that it unconditionally writes to a particular type of console, regardless of whether that console exists or not. This is useful sometimes when the kernel crashes before it can even determine what platform it's on, and therefore what consoles exist. However if you boot a kernel built this way on a different platform, it will generally crash because it writes to a console that doesn't exist. A particularly nasty instance of this is if you enable the hypervisor console early debug, and then boot that kernel on bare metal. The result is that the kernel calls "the hypervisor" very early in boot, but the kernel *is* the hypervisor, so we jump to the system call handler and start executing all sorts of code that isn't ready to be run. This may lead to a machine check or check stop depending on how lucky you are. Luckily there is an easy way to avoid this particular case. We simply read the MSR before installing the hooks, and if we see MSR_HV is set then we are the hypervisor and we definitely should not use the hypervisor console. Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
-rw-r--r--drivers/tty/hvc/hvc_vio.c12
1 files changed, 12 insertions, 0 deletions
diff --git a/drivers/tty/hvc/hvc_vio.c b/drivers/tty/hvc/hvc_vio.c
index b05dc5086627..6ffbdd8d50c5 100644
--- a/drivers/tty/hvc/hvc_vio.c
+++ b/drivers/tty/hvc/hvc_vio.c
@@ -442,6 +442,14 @@ void __init hvc_vio_init_early(void)
#ifdef CONFIG_PPC_EARLY_DEBUG_LPAR
void __init udbg_init_debug_lpar(void)
{
+ /*
+ * If we're running as a hypervisor then we definitely can't call the
+ * hypervisor to print debug output (we *are* the hypervisor), so don't
+ * register if we detect that MSR_HV=1.
+ */
+ if (mfmsr() & MSR_HV)
+ return;
+
hvterm_privs[0] = &hvterm_priv0;
hvterm_priv0.termno = 0;
hvterm_priv0.proto = HV_PROTOCOL_RAW;
@@ -455,6 +463,10 @@ void __init udbg_init_debug_lpar(void)
#ifdef CONFIG_PPC_EARLY_DEBUG_LPAR_HVSI
void __init udbg_init_debug_lpar_hvsi(void)
{
+ /* See comment above in udbg_init_debug_lpar() */
+ if (mfmsr() & MSR_HV)
+ return;
+
hvterm_privs[0] = &hvterm_priv0;
hvterm_priv0.termno = CONFIG_PPC_EARLY_DEBUG_HVSI_VTERMNO;
hvterm_priv0.proto = HV_PROTOCOL_HVSI;