summaryrefslogtreecommitdiffstats
path: root/core/affinity.c
diff options
context:
space:
mode:
Diffstat (limited to 'core/affinity.c')
-rw-r--r--core/affinity.c132
1 files changed, 132 insertions, 0 deletions
diff --git a/core/affinity.c b/core/affinity.c
new file mode 100644
index 00000000..d5eea829
--- /dev/null
+++ b/core/affinity.c
@@ -0,0 +1,132 @@
+/* Copyright 2013-2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ * implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ *
+ * We currently construct our associativity properties as such:
+ *
+ * - For "chip" devices (bridges, memory, ...), 4 entries:
+ *
+ * - CCM node ID
+ * - HW card ID
+ * - HW module ID
+ * - Chip ID
+ *
+ * The information is constructed based on the chip ID which (unlike
+ * pHyp) is our HW chip ID (aka "XSCOM" chip ID). We use it to retrieve
+ * the other properties from the corresponding chip/xscom node in the
+ * device-tree. If those properties are absent, 0 is used.
+ *
+ * - For "core" devices, we add a 5th entry:
+ *
+ * - Core ID
+ *
+ * Here too, we do not use the "cooked" HW processor ID from HDAT but
+ * intead use the real HW core ID which is basically the interrupt
+ * server number of thread 0 on that core.
+ *
+ *
+ * The ibm,associativity-reference-points property is currently set to
+ * 4,4 indicating that the chip ID is our only reference point. This
+ * should be extended to encompass the node IDs eventually.
+ */
+#include <skiboot.h>
+#include <opal.h>
+#include <device.h>
+#include <console.h>
+#include <trace.h>
+#include <chip.h>
+#include <cpu.h>
+#include <affinity.h>
+
+static uint32_t get_chip_node_id(struct proc_chip *chip)
+{
+ /* If the xscom node has an ibm,ccm-node-id property, use it */
+ if (dt_has_node_property(chip->devnode, "ibm,ccm-node-id", NULL))
+ return dt_prop_get_u32(chip->devnode, "ibm,ccm-node-id");
+
+ /*
+ * Else use the 3 top bits of the chip ID which should be
+ * the node on both P7 and P8
+ */
+ return chip->id >> 3;
+}
+
+void add_associativity_ref_point(void)
+{
+ int ref2 = 0x4;
+
+ /*
+ * Note about our use of reference points:
+ *
+ * Linux currently supports two levels of NUMA. We use the first
+ * reference point for the node ID and the second reference point
+ * for a second level of affinity. We always use the chip ID (4)
+ * for the first reference point.
+ *
+ * Choosing the second level of affinity is model specific
+ * unfortunately. Current POWER8E models should use the DCM
+ * as a second level of NUMA.
+ *
+ * If there is a way to obtain this information from the FSP
+ * that would be ideal, but for now hardwire our POWER8E setting.
+ */
+ if (PVR_TYPE(mfspr(SPR_PVR)) == PVR_TYPE_P8E)
+ ref2 = 0x3;
+
+ dt_add_property_cells(opal_node, "ibm,associativity-reference-points",
+ 0x4, ref2);
+}
+
+void add_chip_dev_associativity(struct dt_node *dev)
+{
+ uint32_t chip_id = dt_get_chip_id(dev);
+ struct proc_chip *chip = get_chip(chip_id);
+ uint32_t hw_cid, hw_mid;
+
+ if (!chip)
+ return;
+
+ hw_cid = dt_prop_get_u32_def(chip->devnode, "ibm,hw-card-id", 0);
+ hw_mid = dt_prop_get_u32_def(chip->devnode, "ibm,hw-module-id", 0);
+
+ dt_add_property_cells(dev, "ibm,associativity", 4,
+ get_chip_node_id(chip),
+ hw_cid, hw_mid, chip_id);
+}
+
+void add_core_associativity(struct cpu_thread *cpu)
+{
+ struct proc_chip *chip = get_chip(cpu->chip_id);
+ uint32_t hw_cid, hw_mid, core_id;
+
+ if (!chip)
+ return;
+
+ if (proc_gen == proc_gen_p7)
+ core_id = (cpu->pir >> 2) & 0x7;
+ else if (proc_gen == proc_gen_p8)
+ core_id = (cpu->pir >> 3) & 0xf;
+ else
+ return;
+
+ hw_cid = dt_prop_get_u32_def(chip->devnode, "ibm,hw-card-id", 0);
+ hw_mid = dt_prop_get_u32_def(chip->devnode, "ibm,hw-module-id", 0);
+
+ dt_add_property_cells(cpu->node, "ibm,associativity", 5,
+ get_chip_node_id(chip),
+ hw_cid, hw_mid, chip->id, core_id);
+}
OpenPOWER on IntegriCloud