Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d34696c2 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull s390 fixes from Martin Schwidefsky:
 "Two patches to save some memory if CONFIG_NR_CPUS is large, a changed
  default for the use of compare-and-delay, and a couple of bug fixes"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux:
  s390/spinlock: disabled compare-and-delay by default
  s390/mm: align 64-bit PIE binaries to 4GB
  s390/cacheinfo: coding style changes
  s390/cacheinfo: fix shared cpu masks
  s390/smp: reduce size of struct pcpu
  s390/topology: convert cpu_topology array to per cpu variable
  s390/topology: delay initialization of topology cpu masks
  s390/vdso: fix clock_gettime for CLOCK_THREAD_CPUTIME_ID, -2 and -3
parents f9677375 61b0b016
Loading
Loading
Loading
Loading
+8 −16
Original line number Diff line number Diff line
@@ -18,15 +18,15 @@ struct cpu_topology_s390 {
	cpumask_t book_mask;
};

extern struct cpu_topology_s390 cpu_topology[NR_CPUS];
DECLARE_PER_CPU(struct cpu_topology_s390, cpu_topology);

#define topology_physical_package_id(cpu)	(cpu_topology[cpu].socket_id)
#define topology_thread_id(cpu)			(cpu_topology[cpu].thread_id)
#define topology_thread_cpumask(cpu)		(&cpu_topology[cpu].thread_mask)
#define topology_core_id(cpu)			(cpu_topology[cpu].core_id)
#define topology_core_cpumask(cpu)		(&cpu_topology[cpu].core_mask)
#define topology_book_id(cpu)			(cpu_topology[cpu].book_id)
#define topology_book_cpumask(cpu)		(&cpu_topology[cpu].book_mask)
#define topology_physical_package_id(cpu) (per_cpu(cpu_topology, cpu).socket_id)
#define topology_thread_id(cpu)		  (per_cpu(cpu_topology, cpu).thread_id)
#define topology_thread_cpumask(cpu)	  (&per_cpu(cpu_topology, cpu).thread_mask)
#define topology_core_id(cpu)		  (per_cpu(cpu_topology, cpu).core_id)
#define topology_core_cpumask(cpu)	  (&per_cpu(cpu_topology, cpu).core_mask)
#define topology_book_id(cpu)		  (per_cpu(cpu_topology, cpu).book_id)
#define topology_book_cpumask(cpu)	  (&per_cpu(cpu_topology, cpu).book_mask)

#define mc_capable() 1

@@ -51,14 +51,6 @@ static inline void topology_expect_change(void) { }
#define POLARIZATION_VM		(2)
#define POLARIZATION_VH		(3)

#ifdef CONFIG_SCHED_BOOK
void s390_init_cpu_topology(void);
#else
static inline void s390_init_cpu_topology(void)
{
};
#endif

#include <asm-generic/topology.h>

#endif /* _ASM_S390_TOPOLOGY_H */
+7 −18
Original line number Diff line number Diff line
@@ -91,12 +91,9 @@ static inline enum cache_type get_cache_type(struct cache_info *ci, int level)
{
	if (level >= CACHE_MAX_LEVEL)
		return CACHE_TYPE_NOCACHE;

	ci += level;

	if (ci->scope != CACHE_SCOPE_SHARED && ci->scope != CACHE_SCOPE_PRIVATE)
		return CACHE_TYPE_NOCACHE;

	return cache_type_map[ci->type];
}

@@ -111,23 +108,19 @@ static inline unsigned long ecag(int ai, int li, int ti)
}

static void ci_leaf_init(struct cacheinfo *this_leaf, int private,
			 enum cache_type type, unsigned int level)
			 enum cache_type type, unsigned int level, int cpu)
{
	int ti, num_sets;
	int cpu = smp_processor_id();

	if (type == CACHE_TYPE_INST)
		ti = CACHE_TI_INSTRUCTION;
	else
		ti = CACHE_TI_UNIFIED;

	this_leaf->level = level + 1;
	this_leaf->type = type;
	this_leaf->coherency_line_size = ecag(EXTRACT_LINE_SIZE, level, ti);
	this_leaf->ways_of_associativity = ecag(EXTRACT_ASSOCIATIVITY,
						level, ti);
	this_leaf->ways_of_associativity = ecag(EXTRACT_ASSOCIATIVITY, level, ti);
	this_leaf->size = ecag(EXTRACT_SIZE, level, ti);

	num_sets = this_leaf->size / this_leaf->coherency_line_size;
	num_sets /= this_leaf->ways_of_associativity;
	this_leaf->number_of_sets = num_sets;
@@ -145,7 +138,6 @@ int init_cache_level(unsigned int cpu)

	if (!this_cpu_ci)
		return -EINVAL;

	ct.raw = ecag(EXTRACT_TOPOLOGY, 0, 0);
	do {
		ctype = get_cache_type(&ct.ci[0], level);
@@ -154,34 +146,31 @@ int init_cache_level(unsigned int cpu)
		/* Separate instruction and data caches */
		leaves += (ctype == CACHE_TYPE_SEPARATE) ? 2 : 1;
	} while (++level < CACHE_MAX_LEVEL);

	this_cpu_ci->num_levels = level;
	this_cpu_ci->num_leaves = leaves;

	return 0;
}

int populate_cache_leaves(unsigned int cpu)
{
	struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
	struct cacheinfo *this_leaf = this_cpu_ci->info_list;
	unsigned int level, idx, pvt;
	union cache_topology ct;
	enum cache_type ctype;
	struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
	struct cacheinfo *this_leaf = this_cpu_ci->info_list;

	ct.raw = ecag(EXTRACT_TOPOLOGY, 0, 0);
	for (idx = 0, level = 0; level < this_cpu_ci->num_levels &&
	     idx < this_cpu_ci->num_leaves; idx++, level++) {
		if (!this_leaf)
			return -EINVAL;

		pvt = (ct.ci[level].scope == CACHE_SCOPE_PRIVATE) ? 1 : 0;
		ctype = get_cache_type(&ct.ci[0], level);
		if (ctype == CACHE_TYPE_SEPARATE) {
			ci_leaf_init(this_leaf++, pvt, CACHE_TYPE_DATA, level);
			ci_leaf_init(this_leaf++, pvt, CACHE_TYPE_INST, level);
			ci_leaf_init(this_leaf++, pvt, CACHE_TYPE_DATA, level, cpu);
			ci_leaf_init(this_leaf++, pvt, CACHE_TYPE_INST, level, cpu);
		} else {
			ci_leaf_init(this_leaf++, pvt, ctype, level);
			ci_leaf_init(this_leaf++, pvt, ctype, level, cpu);
		}
	}
	return 0;
+7 −5
Original line number Diff line number Diff line
@@ -393,17 +393,19 @@ static __init void detect_machine_facilities(void)
		S390_lowcore.machine_flags |= MACHINE_FLAG_TLB_LC;
	if (test_facility(129))
		S390_lowcore.machine_flags |= MACHINE_FLAG_VX;
	if (test_facility(128))
		S390_lowcore.machine_flags |= MACHINE_FLAG_CAD;
#endif
}

static int __init nocad_setup(char *str)
static int __init cad_setup(char *str)
{
	S390_lowcore.machine_flags &= ~MACHINE_FLAG_CAD;
	int val;

	get_option(&str, &val);
	if (val && test_facility(128))
		S390_lowcore.machine_flags |= MACHINE_FLAG_CAD;
	return 0;
}
early_param("nocad", nocad_setup);
early_param("cad", cad_setup);

static int __init cad_init(void)
{
+0 −1
Original line number Diff line number Diff line
@@ -909,7 +909,6 @@ void __init setup_arch(char **cmdline_p)
	setup_lowcore();
	smp_fill_possible_mask();
        cpu_init();
	s390_init_cpu_topology();

	/*
	 * Setup capabilities (ELF_HWCAP & ELF_PLATFORM).
+27 −27
Original line number Diff line number Diff line
@@ -59,14 +59,13 @@ enum {
	CPU_STATE_CONFIGURED,
};

static DEFINE_PER_CPU(struct cpu *, cpu_device);

struct pcpu {
	struct cpu *cpu;
	struct _lowcore *lowcore;	/* lowcore page(s) for the cpu */
	unsigned long async_stack;	/* async stack for the cpu */
	unsigned long panic_stack;	/* panic stack for the cpu */
	unsigned long ec_mask;		/* bit mask for ec_xxx functions */
	int state;			/* physical cpu state */
	int polarization;		/* physical polarization */
	signed char state;		/* physical cpu state */
	signed char polarization;	/* physical polarization */
	u16 address;			/* physical cpu address */
};

@@ -173,25 +172,30 @@ static void pcpu_ec_call(struct pcpu *pcpu, int ec_bit)
	pcpu_sigp_retry(pcpu, order, 0);
}

#define ASYNC_FRAME_OFFSET (ASYNC_SIZE - STACK_FRAME_OVERHEAD - __PT_SIZE)
#define PANIC_FRAME_OFFSET (PAGE_SIZE - STACK_FRAME_OVERHEAD - __PT_SIZE)

static int pcpu_alloc_lowcore(struct pcpu *pcpu, int cpu)
{
	unsigned long async_stack, panic_stack;
	struct _lowcore *lc;

	if (pcpu != &pcpu_devices[0]) {
		pcpu->lowcore =	(struct _lowcore *)
			__get_free_pages(GFP_KERNEL | GFP_DMA, LC_ORDER);
		pcpu->async_stack = __get_free_pages(GFP_KERNEL, ASYNC_ORDER);
		pcpu->panic_stack = __get_free_page(GFP_KERNEL);
		if (!pcpu->lowcore || !pcpu->panic_stack || !pcpu->async_stack)
		async_stack = __get_free_pages(GFP_KERNEL, ASYNC_ORDER);
		panic_stack = __get_free_page(GFP_KERNEL);
		if (!pcpu->lowcore || !panic_stack || !async_stack)
			goto out;
	} else {
		async_stack = pcpu->lowcore->async_stack - ASYNC_FRAME_OFFSET;
		panic_stack = pcpu->lowcore->panic_stack - PANIC_FRAME_OFFSET;
	}
	lc = pcpu->lowcore;
	memcpy(lc, &S390_lowcore, 512);
	memset((char *) lc + 512, 0, sizeof(*lc) - 512);
	lc->async_stack = pcpu->async_stack + ASYNC_SIZE
		- STACK_FRAME_OVERHEAD - sizeof(struct pt_regs);
	lc->panic_stack = pcpu->panic_stack + PAGE_SIZE
		- STACK_FRAME_OVERHEAD - sizeof(struct pt_regs);
	lc->async_stack = async_stack + ASYNC_FRAME_OFFSET;
	lc->panic_stack = panic_stack + PANIC_FRAME_OFFSET;
	lc->cpu_nr = cpu;
	lc->spinlock_lockval = arch_spin_lockval(cpu);
#ifndef CONFIG_64BIT
@@ -212,8 +216,8 @@ static int pcpu_alloc_lowcore(struct pcpu *pcpu, int cpu)
	return 0;
out:
	if (pcpu != &pcpu_devices[0]) {
		free_page(pcpu->panic_stack);
		free_pages(pcpu->async_stack, ASYNC_ORDER);
		free_page(panic_stack);
		free_pages(async_stack, ASYNC_ORDER);
		free_pages((unsigned long) pcpu->lowcore, LC_ORDER);
	}
	return -ENOMEM;
@@ -235,12 +239,12 @@ static void pcpu_free_lowcore(struct pcpu *pcpu)
#else
	vdso_free_per_cpu(pcpu->lowcore);
#endif
	if (pcpu != &pcpu_devices[0]) {
		free_page(pcpu->panic_stack);
		free_pages(pcpu->async_stack, ASYNC_ORDER);
	if (pcpu == &pcpu_devices[0])
		return;
	free_page(pcpu->lowcore->panic_stack-PANIC_FRAME_OFFSET);
	free_pages(pcpu->lowcore->async_stack-ASYNC_FRAME_OFFSET, ASYNC_ORDER);
	free_pages((unsigned long) pcpu->lowcore, LC_ORDER);
}
}

#endif /* CONFIG_HOTPLUG_CPU */

@@ -366,7 +370,8 @@ void smp_call_online_cpu(void (*func)(void *), void *data)
void smp_call_ipl_cpu(void (*func)(void *), void *data)
{
	pcpu_delegate(&pcpu_devices[0], func, data,
		      pcpu_devices->panic_stack + PAGE_SIZE);
		      pcpu_devices->lowcore->panic_stack -
		      PANIC_FRAME_OFFSET + PAGE_SIZE);
}

int smp_find_processor_id(u16 address)
@@ -935,10 +940,6 @@ void __init smp_prepare_boot_cpu(void)
	pcpu->state = CPU_STATE_CONFIGURED;
	pcpu->address = stap();
	pcpu->lowcore = (struct _lowcore *)(unsigned long) store_prefix();
	pcpu->async_stack = S390_lowcore.async_stack - ASYNC_SIZE
		+ STACK_FRAME_OVERHEAD + sizeof(struct pt_regs);
	pcpu->panic_stack = S390_lowcore.panic_stack - PAGE_SIZE
		+ STACK_FRAME_OVERHEAD + sizeof(struct pt_regs);
	S390_lowcore.percpu_offset = __per_cpu_offset[0];
	smp_cpu_set_polarization(0, POLARIZATION_UNKNOWN);
	set_cpu_present(0, true);
@@ -1078,8 +1079,7 @@ static int smp_cpu_notify(struct notifier_block *self, unsigned long action,
			  void *hcpu)
{
	unsigned int cpu = (unsigned int)(long)hcpu;
	struct cpu *c = pcpu_devices[cpu].cpu;
	struct device *s = &c->dev;
	struct device *s = &per_cpu(cpu_device, cpu)->dev;
	int err = 0;

	switch (action & ~CPU_TASKS_FROZEN) {
@@ -1102,7 +1102,7 @@ static int smp_add_present_cpu(int cpu)
	c = kzalloc(sizeof(*c), GFP_KERNEL);
	if (!c)
		return -ENOMEM;
	pcpu_devices[cpu].cpu = c;
	per_cpu(cpu_device, cpu) = c;
	s = &c->dev;
	c->hotpluggable = 1;
	rc = register_cpu(c, cpu);
Loading