topology.c 10.0 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 49

/* smp_cpu_state_mutex must be held when accessing this array */
int cpu_polarization[NR_CPUS];
50 51

static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu)
52 53 54
{
	cpumask_t mask;

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

72 73 74
static struct mask_info *add_cpus_to_mask(struct topology_cpu *tl_cpu,
					  struct mask_info *book,
					  struct mask_info *core,
75
					  int one_core_per_cpu)
76 77 78
{
	unsigned int cpu;

79 80 81
	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))
82
	{
M
Martin Schwidefsky 已提交
83 84
		unsigned int rcpu;
		int lcpu;
85

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

104
static void clear_masks(void)
105
{
106
	struct mask_info *info;
107

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

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

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

H
Heiko Carstens 已提交
133
	tle = info->tle;
134
	end = (union topology_entry *)((unsigned long)info + info->length);
135 136 137
	while (tle < end) {
		switch (tle->nl) {
		case 2:
138 139
			book = book->next;
			book->id = tle->container.id;
140 141 142
			break;
		case 1:
			core = core->next;
143
			core->id = tle->container.id;
144 145
			break;
		case 0:
146
			add_cpus_to_mask(&tle->cpu, book, core, 0);
147 148
			break;
		default:
149
			clear_masks();
150
			return;
151 152 153
		}
		tle = next_tle(tle);
	}
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 193 194 195
}

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 已提交
196
	spin_unlock_irq(&topology_lock);
197 198
}

H
Heiko Carstens 已提交
199 200 201 202 203
static void topology_update_polarization_simple(void)
{
	int cpu;

	mutex_lock(&smp_cpu_state_mutex);
204
	for_each_possible_cpu(cpu)
205
		cpu_set_polarization(cpu, POLARIZATION_HRZ);
H
Heiko Carstens 已提交
206 207 208 209
	mutex_unlock(&smp_cpu_state_mutex);
}

static int ptf(unsigned long fc)
210 211 212 213 214 215 216 217
{
	int rc;

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

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

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

239 240
static void update_cpu_core_map(void)
{
241
	unsigned long flags;
242 243
	int cpu;

244 245 246 247 248 249 250 251
	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);
}

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

260
int arch_update_cpu_topology(void)
261
{
262
	struct sysinfo_15_1_x *info = tl_info;
263
	struct device *dev;
264 265
	int cpu;

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

281 282
static void topology_work_fn(struct work_struct *work)
{
283
	rebuild_sched_domains();
284 285
}

H
Heiko Carstens 已提交
286 287 288 289 290
void topology_schedule_update(void)
{
	schedule_work(&topology_work);
}

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

298 299 300 301 302
static struct timer_list topology_timer =
	TIMER_DEFERRED_INITIALIZER(topology_timer_fn, 0, 0);

static atomic_t topology_poll = ATOMIC_INIT(0);

303 304
static void set_topology_timer(void)
{
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321
	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();
322 323
}

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

333 334
static void __init alloc_masks(struct sysinfo_15_1_x *info,
			       struct mask_info *mask, int offset)
335 336 337
{
	int i, nr_masks;

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

348 349
void __init s390_init_cpu_topology(void)
{
350
	struct sysinfo_15_1_x *info;
351 352
	int i;

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

static int cpu_management;

368 369
static ssize_t dispatching_show(struct device *dev,
				struct device_attribute *attr,
370 371 372 373 374 375 376 377 378 379
				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;
}

380 381
static ssize_t dispatching_store(struct device *dev,
				 struct device_attribute *attr,
382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397
				 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);
398 399 400 401
	if (rc)
		goto out;
	cpu_management = val;
	topology_expect_change();
402 403 404 405 406
out:
	mutex_unlock(&smp_cpu_state_mutex);
	put_online_cpus();
	return rc ? rc : count;
}
407
static DEVICE_ATTR(dispatching, 0644, dispatching_show,
408 409
			 dispatching_store);

410 411
static ssize_t cpu_polarization_show(struct device *dev,
				     struct device_attribute *attr, char *buf)
412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436
{
	int cpu = dev->id;
	ssize_t count;

	mutex_lock(&smp_cpu_state_mutex);
	switch (cpu_read_polarization(cpu)) {
	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;
}
437
static DEVICE_ATTR(polarization, 0444, cpu_polarization_show, NULL);
438 439

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

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

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

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