diff mbox series

[v2] core: detect LPAR-per-core mode and report in dt

Message ID 20220524091637.489123-1-npiggin@gmail.com
State Accepted
Headers show
Series [v2] core: detect LPAR-per-core mode and report in dt | expand

Checks

Context Check Description
snowpatch_ozlabs/github-Docker_builds_and_checks fail check_build (ubuntu-rolling) failed at step Create Docker image.

Commit Message

Nicholas Piggin May 24, 2022, 9:16 a.m. UTC
Some firmware configurations boot in LPAR-per-core mode, which is not
compatible with KVM on POWER9 and later machines.

Detect which LPAR mode the boot core is in (all others will be set
the same way), and if booted in LPAR-per-core mode then print a warning
and add a device-tree entry that the OS can test for.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
v2:
- Fix make check compile

 core/init.c              | 38 ++++++++++++++++++++++++++++++++++++++
 hdata/cpu-common.c       |  2 ++
 hdata/test/hdata_to_dt.c |  2 ++
 include/skiboot.h        |  2 ++
 4 files changed, 44 insertions(+)

Comments

Reza Arbab June 13, 2022, 8:43 p.m. UTC | #1
On Tue, May 24, 2022 at 07:16:37PM +1000, Nicholas Piggin wrote:
>Some firmware configurations boot in LPAR-per-core mode, which is not
>compatible with KVM on POWER9 and later machines.
>
>Detect which LPAR mode the boot core is in (all others will be set
>the same way), and if booted in LPAR-per-core mode then print a warning
>and add a device-tree entry that the OS can test for.

Applied to master.
diff mbox series

Patch

diff --git a/core/init.c b/core/init.c
index a1fd5f2b..005ecf31 100644
--- a/core/init.c
+++ b/core/init.c
@@ -48,6 +48,7 @@ 
 #include <debug_descriptor.h>
 #include <occ.h>
 #include <opal-dump.h>
+#include <xscom-p9-regs.h>
 #include <xscom-p10-regs.h>
 
 enum proc_gen proc_gen;
@@ -1026,6 +1027,40 @@  static void mask_pc_system_xstop(void)
         }
 }
 
+bool lpar_per_core = false;
+
+static void probe_lpar_per_core(void)
+{
+	struct cpu_thread *cpu = this_cpu();
+	uint32_t chip_id = pir_to_chip_id(cpu->pir);
+	uint32_t core_id = pir_to_core_id(cpu->pir);
+	uint64_t addr;
+	uint64_t core_thread_state;
+	int rc;
+
+	if (chip_quirk(QUIRK_MAMBO_CALLOUTS) || chip_quirk(QUIRK_AWAN))
+		return;
+
+	if (proc_gen == proc_gen_p9)
+		addr = XSCOM_ADDR_P9_EC(core_id, P9_CORE_THREAD_STATE);
+	else if (proc_gen == proc_gen_p10)
+		addr = XSCOM_ADDR_P10_EC(core_id, P10_EC_CORE_THREAD_STATE);
+	else
+		return;
+
+	rc = xscom_read(chip_id, addr, &core_thread_state);
+	if (rc) {
+		prerror("Error reading CORE_THREAD_STATE rc:%d on PIR:%x\n",
+			rc, cpu->pir);
+		return;
+	}
+
+	if (core_thread_state & PPC_BIT(62)) {
+		lpar_per_core = true;
+		prlog(PR_WARNING, "LPAR-per-core mode detected. KVM may not be usable.");
+	}
+}
+
 
 /* Called from head.S, thus no prototype. */
 void __noreturn __nomcount  main_cpu_entry(const void *fdt);
@@ -1211,6 +1246,9 @@  void __noreturn __nomcount main_cpu_entry(const void *fdt)
         /* Once all CPU are up apply this workaround */
         mask_pc_system_xstop();
 
+	/* P9/10 may be in LPAR-per-core mode, which is incompatible with KVM */
+	probe_lpar_per_core();
+
 	/* Add the /opal node to the device-tree */
 	add_opal_node();
 
diff --git a/hdata/cpu-common.c b/hdata/cpu-common.c
index 2248f9b6..4ba1430b 100644
--- a/hdata/cpu-common.c
+++ b/hdata/cpu-common.c
@@ -127,6 +127,8 @@  struct dt_node * add_core_common(struct dt_node *cpus,
 		dt_add_property_cells(cpu, "ibm,mmu-pid-bits", 20);
 		dt_add_property_cells(cpu, "ibm,mmu-lpid-bits", 12);
 	}
+	if (lpar_per_core)
+		dt_add_property(cpu, "ibm,mmu-lpar-per-core", NULL, 0);
 
 	/* HPT segment page size encodings, common to all supported CPUs */
 	dt_add_property_cells(cpu, "ibm,segment-page-sizes",
diff --git a/hdata/test/hdata_to_dt.c b/hdata/test/hdata_to_dt.c
index 1729f1ca..ead6e3c9 100644
--- a/hdata/test/hdata_to_dt.c
+++ b/hdata/test/hdata_to_dt.c
@@ -104,6 +104,8 @@  static unsigned long fake_pvr = PVR_P8;
 
 unsigned int cpu_thread_count = 8;
 
+bool lpar_per_core;
+
 static inline unsigned long mfspr(unsigned int spr)
 {
 	assert(spr == SPR_PVR);
diff --git a/include/skiboot.h b/include/skiboot.h
index db08f45f..b0b75a42 100644
--- a/include/skiboot.h
+++ b/include/skiboot.h
@@ -103,6 +103,8 @@  enum proc_gen {
 };
 extern enum proc_gen proc_gen;
 
+extern bool lpar_per_core;
+
 extern unsigned int pcie_max_link_speed;
 
 /* Convert a 4-bit number to a hex char */