1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
// SPDX-License-Identifier: Apache-2.0
/* Copyright 2013-2019 IBM Corp. */
/*
*
* 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
* instead 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 up to three 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.
*
* For GPU nodes we add a third level of NUMA, such that the
* distance of the GPU node from all other nodes is uniformly
* the highest.
*/
if (PVR_TYPE(mfspr(SPR_PVR)) == PVR_TYPE_P8E)
ref2 = 0x3;
dt_add_property_cells(opal_node, "ibm,associativity-reference-points",
0x4, ref2, 0x2);
}
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_p8)
core_id = (cpu->pir >> 3) & 0xf;
else if (proc_gen == proc_gen_p9)
core_id = (cpu->pir >> 2) & 0x1f;
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);
}
|