summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorNathan Fontenot <nfont@linux.vnet.ibm.com>2015-10-23 12:45:57 -0500
committerMichael Ellerman <mpe@ellerman.id.au>2015-12-17 22:41:01 +1100
commit1f859adb9253c201079962582253236e9b2cc3ce (patch)
tree530f2fdf162205d654e5f7df1c3726fa9586b41d /arch
parent4450022b4952ce67d2f3006b4c38e12a0f38cd77 (diff)
downloadlinux-1f859adb9253c201079962582253236e9b2cc3ce.tar.bz2
powerpc/pseries: Verify CPU doesn't exist before adding
When DLPAR adding a CPU we should verify that the CPU does not already exist. Failure to do so can generate a kernel oops; [ 9.465585] kernel BUG at arch/powerpc/platforms/pseries/dlpar.c:382! [ 9.465796] Oops: Exception in kernel mode, sig: 5 [#1] This oops can be generated by causing a probe to be performed on a cpu by writing to the sysfs cpu probe file (/sys/devices/system/cpu/probe). This patch adds a check for the existence of cpu prior to probing the cpu so userspace doing the wrong thing won't trigger a BUG_ON(). Signed-off-by: Nathan Fontenot <nfont@linux.vnet.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/platforms/pseries/dlpar.c43
1 files changed, 39 insertions, 4 deletions
diff --git a/arch/powerpc/platforms/pseries/dlpar.c b/arch/powerpc/platforms/pseries/dlpar.c
index f244dcb4f2cf..fe6320db9255 100644
--- a/arch/powerpc/platforms/pseries/dlpar.c
+++ b/arch/powerpc/platforms/pseries/dlpar.c
@@ -381,6 +381,32 @@ out:
}
+static bool dlpar_cpu_exists(struct device_node *parent, u32 drc_index)
+{
+ struct device_node *child = NULL;
+ u32 my_drc_index;
+ bool found;
+ int rc;
+
+ /* Assume cpu doesn't exist */
+ found = false;
+
+ for_each_child_of_node(parent, child) {
+ rc = of_property_read_u32(child, "ibm,my-drc-index",
+ &my_drc_index);
+ if (rc)
+ continue;
+
+ if (my_drc_index == drc_index) {
+ of_node_put(child);
+ found = true;
+ break;
+ }
+ }
+
+ return found;
+}
+
static ssize_t dlpar_cpu_probe(const char *buf, size_t count)
{
struct device_node *dn, *parent;
@@ -391,14 +417,23 @@ static ssize_t dlpar_cpu_probe(const char *buf, size_t count)
if (rc)
return -EINVAL;
- rc = dlpar_acquire_drc(drc_index);
- if (rc)
- return -EINVAL;
-
parent = of_find_node_by_path("/cpus");
if (!parent)
return -ENODEV;
+ if (dlpar_cpu_exists(parent, drc_index)) {
+ of_node_put(parent);
+ printk(KERN_WARNING "CPU with drc index %x already exists\n",
+ drc_index);
+ return -EINVAL;
+ }
+
+ rc = dlpar_acquire_drc(drc_index);
+ if (rc) {
+ of_node_put(parent);
+ return -EINVAL;
+ }
+
dn = dlpar_configure_connector(cpu_to_be32(drc_index), parent);
of_node_put(parent);
if (!dn) {