Commit 1b25fda0 authored by Heiko Carstens's avatar Heiko Carstens Committed by Martin Schwidefsky

s390/topology: alternative topology for topology-less machines

If running on machines that do not provide topology information we
currently generate a "fake" topology which defines the maximum
distance between each cpu: each cpu will be put into an own drawer.

Historically this used to be the best option for (virtual) machines in
overcommited hypervisors.

For some workloads however it is better to generate a different
topology where all cpus are siblings within a package (all cpus are
core siblings). This shows performance improvements of up to 10%,
depending on the workload.

In order to keep the current behaviour, but also allow to switch to
the different core sibling topology use the existing "topology="
kernel parameter:

Specifying "topology=on" on machines without topology information will
generate the core siblings (fake) topology information, instead of the
default topology information where all cpus have the maximum distance.

On machines which provide topology information specifying
"topology=on" does not have any effect.
Signed-off-by: default avatarHeiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent ba385c05
...@@ -404,18 +404,6 @@ static inline void save_vector_registers(void) ...@@ -404,18 +404,6 @@ static inline void save_vector_registers(void)
#endif #endif
} }
static int __init topology_setup(char *str)
{
bool enabled;
int rc;
rc = kstrtobool(str, &enabled);
if (!rc && !enabled)
S390_lowcore.machine_flags &= ~MACHINE_FLAG_TOPOLOGY;
return rc;
}
early_param("topology", topology_setup);
static int __init disable_vector_extension(char *str) static int __init disable_vector_extension(char *str)
{ {
S390_lowcore.machine_flags &= ~MACHINE_FLAG_VX; S390_lowcore.machine_flags &= ~MACHINE_FLAG_VX;
......
...@@ -29,12 +29,20 @@ ...@@ -29,12 +29,20 @@
#define PTF_VERTICAL (1UL) #define PTF_VERTICAL (1UL)
#define PTF_CHECK (2UL) #define PTF_CHECK (2UL)
enum {
TOPOLOGY_MODE_HW,
TOPOLOGY_MODE_SINGLE,
TOPOLOGY_MODE_PACKAGE,
TOPOLOGY_MODE_UNINITIALIZED
};
struct mask_info { struct mask_info {
struct mask_info *next; struct mask_info *next;
unsigned char id; unsigned char id;
cpumask_t mask; cpumask_t mask;
}; };
static int topology_mode = TOPOLOGY_MODE_UNINITIALIZED;
static void set_topology_timer(void); static void set_topology_timer(void);
static void topology_work_fn(struct work_struct *work); static void topology_work_fn(struct work_struct *work);
static struct sysinfo_15_1_x *tl_info; static struct sysinfo_15_1_x *tl_info;
...@@ -59,11 +67,26 @@ static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu) ...@@ -59,11 +67,26 @@ static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu)
cpumask_t mask; cpumask_t mask;
cpumask_copy(&mask, cpumask_of(cpu)); cpumask_copy(&mask, cpumask_of(cpu));
if (!MACHINE_HAS_TOPOLOGY) switch (topology_mode) {
return mask; case TOPOLOGY_MODE_HW:
for (; info; info = info->next) { while (info) {
if (cpumask_test_cpu(cpu, &info->mask)) if (cpumask_test_cpu(cpu, &info->mask)) {
return info->mask; mask = info->mask;
break;
}
info = info->next;
}
if (cpumask_empty(&mask))
cpumask_copy(&mask, cpumask_of(cpu));
break;
case TOPOLOGY_MODE_PACKAGE:
cpumask_copy(&mask, cpu_present_mask);
break;
default:
/* fallthrough */
case TOPOLOGY_MODE_SINGLE:
cpumask_copy(&mask, cpumask_of(cpu));
break;
} }
return mask; return mask;
} }
...@@ -74,7 +97,7 @@ static cpumask_t cpu_thread_map(unsigned int cpu) ...@@ -74,7 +97,7 @@ static cpumask_t cpu_thread_map(unsigned int cpu)
int i; int i;
cpumask_copy(&mask, cpumask_of(cpu)); cpumask_copy(&mask, cpumask_of(cpu));
if (!MACHINE_HAS_TOPOLOGY) if (topology_mode != TOPOLOGY_MODE_HW)
return mask; return mask;
cpu -= cpu % (smp_cpu_mtid + 1); cpu -= cpu % (smp_cpu_mtid + 1);
for (i = 0; i <= smp_cpu_mtid; i++) for (i = 0; i <= smp_cpu_mtid; i++)
...@@ -223,7 +246,7 @@ int topology_set_cpu_management(int fc) ...@@ -223,7 +246,7 @@ int topology_set_cpu_management(int fc)
static void update_cpu_masks(void) static void update_cpu_masks(void)
{ {
struct cpu_topology_s390 *topo; struct cpu_topology_s390 *topo;
int cpu; int cpu, id;
for_each_possible_cpu(cpu) { for_each_possible_cpu(cpu) {
topo = &cpu_topology[cpu]; topo = &cpu_topology[cpu];
...@@ -231,12 +254,13 @@ static void update_cpu_masks(void) ...@@ -231,12 +254,13 @@ static void update_cpu_masks(void)
topo->core_mask = cpu_group_map(&socket_info, cpu); topo->core_mask = cpu_group_map(&socket_info, cpu);
topo->book_mask = cpu_group_map(&book_info, cpu); topo->book_mask = cpu_group_map(&book_info, cpu);
topo->drawer_mask = cpu_group_map(&drawer_info, cpu); topo->drawer_mask = cpu_group_map(&drawer_info, cpu);
if (!MACHINE_HAS_TOPOLOGY) { if (topology_mode != TOPOLOGY_MODE_HW) {
id = topology_mode == TOPOLOGY_MODE_PACKAGE ? 0 : cpu;
topo->thread_id = cpu; topo->thread_id = cpu;
topo->core_id = cpu; topo->core_id = cpu;
topo->socket_id = cpu; topo->socket_id = id;
topo->book_id = cpu; topo->book_id = id;
topo->drawer_id = cpu; topo->drawer_id = id;
if (cpu_present(cpu)) if (cpu_present(cpu))
cpumask_set_cpu(cpu, &cpus_with_topology); cpumask_set_cpu(cpu, &cpus_with_topology);
} }
...@@ -459,6 +483,12 @@ void __init topology_init_early(void) ...@@ -459,6 +483,12 @@ void __init topology_init_early(void)
struct sysinfo_15_1_x *info; struct sysinfo_15_1_x *info;
set_sched_topology(s390_topology); set_sched_topology(s390_topology);
if (topology_mode == TOPOLOGY_MODE_UNINITIALIZED) {
if (MACHINE_HAS_TOPOLOGY)
topology_mode = TOPOLOGY_MODE_HW;
else
topology_mode = TOPOLOGY_MODE_SINGLE;
}
if (!MACHINE_HAS_TOPOLOGY) if (!MACHINE_HAS_TOPOLOGY)
goto out; goto out;
tl_info = memblock_virt_alloc(PAGE_SIZE, PAGE_SIZE); tl_info = memblock_virt_alloc(PAGE_SIZE, PAGE_SIZE);
...@@ -474,6 +504,26 @@ void __init topology_init_early(void) ...@@ -474,6 +504,26 @@ void __init topology_init_early(void)
__arch_update_cpu_topology(); __arch_update_cpu_topology();
} }
static inline int topology_get_mode(int enabled)
{
if (!enabled)
return TOPOLOGY_MODE_SINGLE;
return MACHINE_HAS_TOPOLOGY ? TOPOLOGY_MODE_HW : TOPOLOGY_MODE_PACKAGE;
}
static int __init topology_setup(char *str)
{
bool enabled;
int rc;
rc = kstrtobool(str, &enabled);
if (rc)
return rc;
topology_mode = topology_get_mode(enabled);
return 0;
}
early_param("topology", topology_setup);
static int __init topology_init(void) static int __init topology_init(void)
{ {
if (MACHINE_HAS_TOPOLOGY) if (MACHINE_HAS_TOPOLOGY)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment