This source file includes following definitions.
- wait_for_sync_step
- update_hid_in_slw
- unsplit_core
- split_core
- cpu_do_split
- cpu_core_split_required
- update_subcore_sibling_mask
- cpu_update_split_mode
- set_subcores_per_core
- store_subcores_per_core
- show_subcores_per_core
- subcore_init
1
2
3
4
5
6 #define pr_fmt(fmt) "powernv: " fmt
7
8 #include <linux/kernel.h>
9 #include <linux/cpu.h>
10 #include <linux/cpumask.h>
11 #include <linux/device.h>
12 #include <linux/gfp.h>
13 #include <linux/smp.h>
14 #include <linux/stop_machine.h>
15
16 #include <asm/cputhreads.h>
17 #include <asm/cpuidle.h>
18 #include <asm/kvm_ppc.h>
19 #include <asm/machdep.h>
20 #include <asm/opal.h>
21 #include <asm/smp.h>
22
23 #include "subcore.h"
24 #include "powernv.h"
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
124
125
126 static int subcores_per_core;
127
128
129
130
131
132
133
134
135
136
137 static int new_split_mode;
138
139 static cpumask_var_t cpu_offline_mask;
140
141 struct split_state {
142 u8 step;
143 u8 master;
144 };
145
146 static DEFINE_PER_CPU(struct split_state, split_state);
147
148 static void wait_for_sync_step(int step)
149 {
150 int i, cpu = smp_processor_id();
151
152 for (i = cpu + 1; i < cpu + threads_per_core; i++)
153 while(per_cpu(split_state, i).step < step)
154 barrier();
155
156
157 mb();
158 }
159
160 static void update_hid_in_slw(u64 hid0)
161 {
162 u64 idle_states = pnv_get_supported_cpuidle_states();
163
164 if (idle_states & OPAL_PM_WINKLE_ENABLED) {
165
166 u64 cpu_pir = hard_smp_processor_id();
167
168 opal_slw_set_reg(cpu_pir, SPRN_HID0, hid0);
169 }
170 }
171
172 static void unsplit_core(void)
173 {
174 u64 hid0, mask;
175 int i, cpu;
176
177 mask = HID0_POWER8_2LPARMODE | HID0_POWER8_4LPARMODE;
178
179 cpu = smp_processor_id();
180 if (cpu_thread_in_core(cpu) != 0) {
181 while (mfspr(SPRN_HID0) & mask)
182 power7_idle_type(PNV_THREAD_NAP);
183
184 per_cpu(split_state, cpu).step = SYNC_STEP_UNSPLIT;
185 return;
186 }
187
188 hid0 = mfspr(SPRN_HID0);
189 hid0 &= ~HID0_POWER8_DYNLPARDIS;
190 update_power8_hid0(hid0);
191 update_hid_in_slw(hid0);
192
193 while (mfspr(SPRN_HID0) & mask)
194 cpu_relax();
195
196
197 for (i = cpu + 1; i < cpu + threads_per_core; i++)
198 smp_send_reschedule(i);
199
200 wait_for_sync_step(SYNC_STEP_UNSPLIT);
201 }
202
203 static void split_core(int new_mode)
204 {
205 struct { u64 value; u64 mask; } split_parms[2] = {
206 { HID0_POWER8_1TO2LPAR, HID0_POWER8_2LPARMODE },
207 { HID0_POWER8_1TO4LPAR, HID0_POWER8_4LPARMODE }
208 };
209 int i, cpu;
210 u64 hid0;
211
212
213 i = (new_mode >> 1) - 1;
214 BUG_ON(i < 0 || i > 1);
215
216 cpu = smp_processor_id();
217 if (cpu_thread_in_core(cpu) != 0) {
218 split_core_secondary_loop(&per_cpu(split_state, cpu).step);
219 return;
220 }
221
222 wait_for_sync_step(SYNC_STEP_REAL_MODE);
223
224
225 hid0 = mfspr(SPRN_HID0);
226 hid0 |= HID0_POWER8_DYNLPARDIS | split_parms[i].value;
227 update_power8_hid0(hid0);
228 update_hid_in_slw(hid0);
229
230
231 while (!(mfspr(SPRN_HID0) & split_parms[i].mask))
232 cpu_relax();
233 }
234
235 static void cpu_do_split(int new_mode)
236 {
237
238
239
240
241
242
243 if (subcores_per_core != 1)
244 unsplit_core();
245
246 if (new_mode != 1)
247 split_core(new_mode);
248
249 mb();
250 per_cpu(split_state, smp_processor_id()).step = SYNC_STEP_FINISHED;
251 }
252
253 bool cpu_core_split_required(void)
254 {
255 smp_rmb();
256
257 if (!new_split_mode)
258 return false;
259
260 cpu_do_split(new_split_mode);
261
262 return true;
263 }
264
265 void update_subcore_sibling_mask(void)
266 {
267 int cpu;
268
269
270
271
272 int sibling_mask_first_cpu = (1 << threads_per_subcore) - 1;
273
274 for_each_possible_cpu(cpu) {
275 int tid = cpu_thread_in_core(cpu);
276 int offset = (tid / threads_per_subcore) * threads_per_subcore;
277 int mask = sibling_mask_first_cpu << offset;
278
279 paca_ptrs[cpu]->subcore_sibling_mask = mask;
280
281 }
282 }
283
284 static int cpu_update_split_mode(void *data)
285 {
286 int cpu, new_mode = *(int *)data;
287
288 if (this_cpu_ptr(&split_state)->master) {
289 new_split_mode = new_mode;
290 smp_wmb();
291
292 cpumask_andnot(cpu_offline_mask, cpu_present_mask,
293 cpu_online_mask);
294
295
296 for_each_cpu(cpu, cpu_offline_mask)
297 smp_send_reschedule(cpu);
298 }
299
300 cpu_do_split(new_mode);
301
302 if (this_cpu_ptr(&split_state)->master) {
303
304 for_each_present_cpu(cpu) {
305 if (cpu >= setup_max_cpus)
306 break;
307
308 while(per_cpu(split_state, cpu).step < SYNC_STEP_FINISHED)
309 barrier();
310 }
311
312 new_split_mode = 0;
313
314
315 subcores_per_core = new_mode;
316 threads_per_subcore = threads_per_core / subcores_per_core;
317 update_subcore_sibling_mask();
318
319
320 mb();
321 }
322
323 return 0;
324 }
325
326 static int set_subcores_per_core(int new_mode)
327 {
328 struct split_state *state;
329 int cpu;
330
331 if (kvm_hv_mode_active()) {
332 pr_err("Unable to change split core mode while KVM active.\n");
333 return -EBUSY;
334 }
335
336
337
338
339
340 BUG_ON(new_mode < 1 || new_mode > 4 || new_mode == 3);
341
342 for_each_present_cpu(cpu) {
343 state = &per_cpu(split_state, cpu);
344 state->step = SYNC_STEP_INITIAL;
345 state->master = 0;
346 }
347
348 cpus_read_lock();
349
350
351 this_cpu_ptr(&split_state)->master = 1;
352
353
354 mb();
355
356 stop_machine_cpuslocked(cpu_update_split_mode, &new_mode,
357 cpu_online_mask);
358
359 cpus_read_unlock();
360
361 return 0;
362 }
363
364 static ssize_t __used store_subcores_per_core(struct device *dev,
365 struct device_attribute *attr, const char *buf,
366 size_t count)
367 {
368 unsigned long val;
369 int rc;
370
371
372
373 rc = sscanf(buf, "%lx", &val);
374 if (rc != 1)
375 return -EINVAL;
376
377 switch (val) {
378 case 1:
379 case 2:
380 case 4:
381 if (subcores_per_core == val)
382
383 goto out;
384 break;
385 default:
386 return -EINVAL;
387 }
388
389 rc = set_subcores_per_core(val);
390 if (rc)
391 return rc;
392
393 out:
394 return count;
395 }
396
397 static ssize_t show_subcores_per_core(struct device *dev,
398 struct device_attribute *attr, char *buf)
399 {
400 return sprintf(buf, "%x\n", subcores_per_core);
401 }
402
403 static DEVICE_ATTR(subcores_per_core, 0644,
404 show_subcores_per_core, store_subcores_per_core);
405
406 static int subcore_init(void)
407 {
408 unsigned pvr_ver;
409
410 pvr_ver = PVR_VER(mfspr(SPRN_PVR));
411
412 if (pvr_ver != PVR_POWER8 &&
413 pvr_ver != PVR_POWER8E &&
414 pvr_ver != PVR_POWER8NVL)
415 return 0;
416
417
418
419
420
421 if (setup_max_cpus % threads_per_core)
422 return 0;
423
424 BUG_ON(!alloc_cpumask_var(&cpu_offline_mask, GFP_KERNEL));
425
426 set_subcores_per_core(1);
427
428 return device_create_file(cpu_subsys.dev_root,
429 &dev_attr_subcores_per_core);
430 }
431 machine_device_initcall(powernv, subcore_init);