topology.c 9.9 KB
Newer Older
1
/*
2
 *    Copyright IBM Corp. 2007, 2011
3 4 5
 *    Author(s): Heiko Carstens <heiko.carstens@de.ibm.com>
 */

6 7 8
#define KMSG_COMPONENT "cpu"
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt

9
#include <linux/workqueue.h>
10
#include <linux/bootmem.h>
11 12 13
#include <linux/cpuset.h>
#include <linux/device.h>
#include <linux/kernel.h>
14
#include <linux/sched.h>
15 16
#include <linux/init.h>
#include <linux/delay.h>
17 18
#include <linux/cpu.h>
#include <linux/smp.h>
19
#include <linux/mm.h>
20
#include <asm/sysinfo.h>
21

H
Heiko Carstens 已提交
22 23 24
#define PTF_HORIZONTAL	(0UL)
#define PTF_VERTICAL	(1UL)
#define PTF_CHECK	(2UL)
25

26 27
struct mask_info {
	struct mask_info *next;
28
	unsigned char id;
29 30 31
	cpumask_t mask;
};

H
Heiko Carstens 已提交
32
static int topology_enabled = 1;
33
static void topology_work_fn(struct work_struct *work);
34
static struct sysinfo_15_1_x *tl_info;
35 36
static void set_topology_timer(void);
static DECLARE_WORK(topology_work, topology_work_fn);
H
Heiko Carstens 已提交
37 38
/* topology_lock protects the core linked list */
static DEFINE_SPINLOCK(topology_lock);
39

40
static struct mask_info core_info;
41
cpumask_t cpu_core_map[NR_CPUS];
42
unsigned char cpu_core_id[NR_CPUS];
43

44 45 46
static struct mask_info book_info;
cpumask_t cpu_book_map[NR_CPUS];
unsigned char cpu_book_id[NR_CPUS];
47

48
static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu)
49 50 51
{
	cpumask_t mask;

52
	cpumask_clear(&mask);
53 54 55 56
	if (!topology_enabled || !MACHINE_HAS_TOPOLOGY) {
		cpumask_copy(&mask, cpumask_of(cpu));
		return mask;
	}
57
	while (info) {
58
		if (cpumask_test_cpu(cpu, &info->mask)) {
59
			mask = info->mask;
60 61
			break;
		}
62
		info = info->next;
63
	}
64 65
	if (cpumask_empty(&mask))
		cpumask_copy(&mask, cpumask_of(cpu));
66 67 68
	return mask;
}

69 70 71
static struct mask_info *add_cpus_to_mask(struct topology_cpu *tl_cpu,
					  struct mask_info *book,
					  struct mask_info *core,
72
					  int one_core_per_cpu)
73 74 75
{
	unsigned int cpu;

76 77 78
	for (cpu = find_first_bit(&tl_cpu->mask[0], TOPOLOGY_CPU_BITS);
	     cpu < TOPOLOGY_CPU_BITS;
	     cpu = find_next_bit(&tl_cpu->mask[0], TOPOLOGY_CPU_BITS, cpu + 1))
79
	{
M
Martin Schwidefsky 已提交
80 81
		unsigned int rcpu;
		int lcpu;
82

83
		rcpu = TOPOLOGY_CPU_BITS - 1 - cpu + tl_cpu->origin;
M
Martin Schwidefsky 已提交
84 85
		lcpu = smp_find_processor_id(rcpu);
		if (lcpu >= 0) {
86
			cpumask_set_cpu(lcpu, &book->mask);
87
			cpu_book_id[lcpu] = book->id;
88
			cpumask_set_cpu(lcpu, &core->mask);
89
			if (one_core_per_cpu) {
90 91 92 93 94
				cpu_core_id[lcpu] = rcpu;
				core = core->next;
			} else {
				cpu_core_id[lcpu] = core->id;
			}
95
			smp_cpu_set_polarization(lcpu, tl_cpu->pp);
96 97
		}
	}
98
	return core;
99 100
}

101
static void clear_masks(void)
102
{
103
	struct mask_info *info;
104

105 106
	info = &core_info;
	while (info) {
107
		cpumask_clear(&info->mask);
108 109 110 111
		info = info->next;
	}
	info = &book_info;
	while (info) {
112
		cpumask_clear(&info->mask);
113
		info = info->next;
114 115 116
	}
}

117
static union topology_entry *next_tle(union topology_entry *tle)
118
{
119 120 121
	if (!tle->nl)
		return (union topology_entry *)((struct topology_cpu *)tle + 1);
	return (union topology_entry *)((struct topology_container *)tle + 1);
122 123
}

124
static void __tl_to_cores_generic(struct sysinfo_15_1_x *info)
125
{
126
	struct mask_info *core = &core_info;
127
	struct mask_info *book = &book_info;
128
	union topology_entry *tle, *end;
129

H
Heiko Carstens 已提交
130
	tle = info->tle;
131
	end = (union topology_entry *)((unsigned long)info + info->length);
132 133 134
	while (tle < end) {
		switch (tle->nl) {
		case 2:
135 136
			book = book->next;
			book->id = tle->container.id;
137 138 139
			break;
		case 1:
			core = core->next;
140
			core->id = tle->container.id;
141 142
			break;
		case 0:
143
			add_cpus_to_mask(&tle->cpu, book, core, 0);
144 145
			break;
		default:
146
			clear_masks();
147
			return;
148 149 150
		}
		tle = next_tle(tle);
	}
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
}

static void __tl_to_cores_z10(struct sysinfo_15_1_x *info)
{
	struct mask_info *core = &core_info;
	struct mask_info *book = &book_info;
	union topology_entry *tle, *end;

	tle = info->tle;
	end = (union topology_entry *)((unsigned long)info + info->length);
	while (tle < end) {
		switch (tle->nl) {
		case 1:
			book = book->next;
			book->id = tle->container.id;
			break;
		case 0:
			core = add_cpus_to_mask(&tle->cpu, book, core, 1);
			break;
		default:
			clear_masks();
			return;
		}
		tle = next_tle(tle);
	}
}

static void tl_to_cores(struct sysinfo_15_1_x *info)
{
	struct cpuid cpu_id;

	get_cpu_id(&cpu_id);
	spin_lock_irq(&topology_lock);
	clear_masks();
	switch (cpu_id.machine) {
	case 0x2097:
	case 0x2098:
		__tl_to_cores_z10(info);
		break;
	default:
		__tl_to_cores_generic(info);
	}
H
Heiko Carstens 已提交
193
	spin_unlock_irq(&topology_lock);
194 195
}

H
Heiko Carstens 已提交
196 197 198 199 200
static void topology_update_polarization_simple(void)
{
	int cpu;

	mutex_lock(&smp_cpu_state_mutex);
201
	for_each_possible_cpu(cpu)
202
		smp_cpu_set_polarization(cpu, POLARIZATION_HRZ);
H
Heiko Carstens 已提交
203 204 205 206
	mutex_unlock(&smp_cpu_state_mutex);
}

static int ptf(unsigned long fc)
207 208 209 210 211 212 213 214
{
	int rc;

	asm volatile(
		"	.insn	rre,0xb9a20000,%1,%1\n"
		"	ipm	%0\n"
		"	srl	%0,28\n"
		: "=d" (rc)
H
Heiko Carstens 已提交
215 216 217 218 219 220
		: "d" (fc)  : "cc");
	return rc;
}

int topology_set_cpu_management(int fc)
{
221
	int cpu, rc;
H
Heiko Carstens 已提交
222

223
	if (!MACHINE_HAS_TOPOLOGY)
H
Heiko Carstens 已提交
224 225 226 227 228 229 230
		return -EOPNOTSUPP;
	if (fc)
		rc = ptf(PTF_VERTICAL);
	else
		rc = ptf(PTF_HORIZONTAL);
	if (rc)
		return -EBUSY;
231
	for_each_possible_cpu(cpu)
232
		smp_cpu_set_polarization(cpu, POLARIZATION_UNKNOWN);
233 234 235
	return rc;
}

236 237
static void update_cpu_core_map(void)
{
238
	unsigned long flags;
239 240
	int cpu;

241 242 243 244 245 246 247 248
	spin_lock_irqsave(&topology_lock, flags);
	for_each_possible_cpu(cpu) {
		cpu_core_map[cpu] = cpu_group_map(&core_info, cpu);
		cpu_book_map[cpu] = cpu_group_map(&book_info, cpu);
	}
	spin_unlock_irqrestore(&topology_lock, flags);
}

249
void store_topology(struct sysinfo_15_1_x *info)
250
{
251 252 253 254
	if (topology_max_mnest >= 3)
		stsi(info, 15, 1, 3);
	else
		stsi(info, 15, 1, 2);
255 256
}

257
int arch_update_cpu_topology(void)
258
{
259
	struct sysinfo_15_1_x *info = tl_info;
260
	struct device *dev;
261 262
	int cpu;

263
	if (!MACHINE_HAS_TOPOLOGY) {
264
		update_cpu_core_map();
H
Heiko Carstens 已提交
265
		topology_update_polarization_simple();
266
		return 0;
H
Heiko Carstens 已提交
267
	}
268
	store_topology(info);
269
	tl_to_cores(info);
270
	update_cpu_core_map();
271
	for_each_online_cpu(cpu) {
272 273
		dev = get_cpu_device(cpu);
		kobject_uevent(&dev->kobj, KOBJ_CHANGE);
274
	}
275
	return 1;
276 277
}

278 279
static void topology_work_fn(struct work_struct *work)
{
280
	rebuild_sched_domains();
281 282
}

H
Heiko Carstens 已提交
283 284 285 286 287
void topology_schedule_update(void)
{
	schedule_work(&topology_work);
}

288 289
static void topology_timer_fn(unsigned long ignored)
{
H
Heiko Carstens 已提交
290 291
	if (ptf(PTF_CHECK))
		topology_schedule_update();
292 293 294
	set_topology_timer();
}

295 296 297 298 299
static struct timer_list topology_timer =
	TIMER_DEFERRED_INITIALIZER(topology_timer_fn, 0, 0);

static atomic_t topology_poll = ATOMIC_INIT(0);

300 301
static void set_topology_timer(void)
{
302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318
	if (atomic_add_unless(&topology_poll, -1, 0))
		mod_timer(&topology_timer, jiffies + HZ / 10);
	else
		mod_timer(&topology_timer, jiffies + HZ * 60);
}

void topology_expect_change(void)
{
	if (!MACHINE_HAS_TOPOLOGY)
		return;
	/* This is racy, but it doesn't matter since it is just a heuristic.
	 * Worst case is that we poll in a higher frequency for a bit longer.
	 */
	if (atomic_read(&topology_poll) > 60)
		return;
	atomic_add(60, &topology_poll);
	set_topology_timer();
319 320
}

321
static int __init early_parse_topology(char *p)
322
{
H
Heiko Carstens 已提交
323
	if (strncmp(p, "off", 3))
324
		return 0;
H
Heiko Carstens 已提交
325
	topology_enabled = 0;
326
	return 0;
327
}
328
early_param("topology", early_parse_topology);
329

330 331
static void __init alloc_masks(struct sysinfo_15_1_x *info,
			       struct mask_info *mask, int offset)
332 333 334
{
	int i, nr_masks;

335
	nr_masks = info->mag[TOPOLOGY_NR_MAG - offset];
336
	for (i = 0; i < info->mnest - offset; i++)
337
		nr_masks *= info->mag[TOPOLOGY_NR_MAG - offset - 1 - i];
338 339 340 341 342 343 344
	nr_masks = max(nr_masks, 1);
	for (i = 0; i < nr_masks; i++) {
		mask->next = alloc_bootmem(sizeof(struct mask_info));
		mask = mask->next;
	}
}

345 346
void __init s390_init_cpu_topology(void)
{
347
	struct sysinfo_15_1_x *info;
348 349
	int i;

350
	if (!MACHINE_HAS_TOPOLOGY)
351 352 353
		return;
	tl_info = alloc_bootmem_pages(PAGE_SIZE);
	info = tl_info;
354
	store_topology(info);
355
	pr_info("The CPU configuration topology of the machine is:");
356
	for (i = 0; i < TOPOLOGY_NR_MAG; i++)
357 358
		printk(KERN_CONT " %d", info->mag[i]);
	printk(KERN_CONT " / %d\n", info->mnest);
359 360
	alloc_masks(info, &core_info, 1);
	alloc_masks(info, &book_info, 2);
361
}
362 363 364

static int cpu_management;

365 366
static ssize_t dispatching_show(struct device *dev,
				struct device_attribute *attr,
367 368 369 370 371 372 373 374 375 376
				char *buf)
{
	ssize_t count;

	mutex_lock(&smp_cpu_state_mutex);
	count = sprintf(buf, "%d\n", cpu_management);
	mutex_unlock(&smp_cpu_state_mutex);
	return count;
}

377 378
static ssize_t dispatching_store(struct device *dev,
				 struct device_attribute *attr,
379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394
				 const char *buf,
				 size_t count)
{
	int val, rc;
	char delim;

	if (sscanf(buf, "%d %c", &val, &delim) != 1)
		return -EINVAL;
	if (val != 0 && val != 1)
		return -EINVAL;
	rc = 0;
	get_online_cpus();
	mutex_lock(&smp_cpu_state_mutex);
	if (cpu_management == val)
		goto out;
	rc = topology_set_cpu_management(val);
395 396 397 398
	if (rc)
		goto out;
	cpu_management = val;
	topology_expect_change();
399 400 401 402 403
out:
	mutex_unlock(&smp_cpu_state_mutex);
	put_online_cpus();
	return rc ? rc : count;
}
404
static DEVICE_ATTR(dispatching, 0644, dispatching_show,
405 406
			 dispatching_store);

407 408
static ssize_t cpu_polarization_show(struct device *dev,
				     struct device_attribute *attr, char *buf)
409 410 411 412 413
{
	int cpu = dev->id;
	ssize_t count;

	mutex_lock(&smp_cpu_state_mutex);
414
	switch (smp_cpu_get_polarization(cpu)) {
415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433
	case POLARIZATION_HRZ:
		count = sprintf(buf, "horizontal\n");
		break;
	case POLARIZATION_VL:
		count = sprintf(buf, "vertical:low\n");
		break;
	case POLARIZATION_VM:
		count = sprintf(buf, "vertical:medium\n");
		break;
	case POLARIZATION_VH:
		count = sprintf(buf, "vertical:high\n");
		break;
	default:
		count = sprintf(buf, "unknown\n");
		break;
	}
	mutex_unlock(&smp_cpu_state_mutex);
	return count;
}
434
static DEVICE_ATTR(polarization, 0444, cpu_polarization_show, NULL);
435 436

static struct attribute *topology_cpu_attrs[] = {
437
	&dev_attr_polarization.attr,
438 439 440 441 442 443 444 445 446
	NULL,
};

static struct attribute_group topology_cpu_attr_group = {
	.attrs = topology_cpu_attrs,
};

int topology_cpu_init(struct cpu *cpu)
{
447
	return sysfs_create_group(&cpu->dev.kobj, &topology_cpu_attr_group);
448 449 450 451 452 453 454 455 456 457 458
}

static int __init topology_init(void)
{
	if (!MACHINE_HAS_TOPOLOGY) {
		topology_update_polarization_simple();
		goto out;
	}
	set_topology_timer();
out:
	update_cpu_core_map();
459
	return device_create_file(cpu_subsys.dev_root, &dev_attr_dispatching);
460 461
}
device_initcall(topology_init);