diff options
| -rw-r--r-- | arch/s390/include/asm/topology.h | 24 | ||||
| -rw-r--r-- | arch/s390/kernel/cache.c | 25 | ||||
| -rw-r--r-- | arch/s390/kernel/early.c | 12 | ||||
| -rw-r--r-- | arch/s390/kernel/setup.c | 1 | ||||
| -rw-r--r-- | arch/s390/kernel/smp.c | 54 | ||||
| -rw-r--r-- | arch/s390/kernel/topology.c | 134 | ||||
| -rw-r--r-- | arch/s390/kernel/vdso64/clock_gettime.S | 6 | ||||
| -rw-r--r-- | arch/s390/mm/mmap.c | 5 |
8 files changed, 119 insertions, 142 deletions
diff --git a/arch/s390/include/asm/topology.h b/arch/s390/include/asm/topology.h index c4fbb9527c5c..b1453a2ae1ca 100644 --- a/arch/s390/include/asm/topology.h +++ b/arch/s390/include/asm/topology.h | |||
| @@ -18,15 +18,15 @@ struct cpu_topology_s390 { | |||
| 18 | cpumask_t book_mask; | 18 | cpumask_t book_mask; |
| 19 | }; | 19 | }; |
| 20 | 20 | ||
| 21 | extern struct cpu_topology_s390 cpu_topology[NR_CPUS]; | 21 | DECLARE_PER_CPU(struct cpu_topology_s390, cpu_topology); |
| 22 | 22 | ||
| 23 | #define topology_physical_package_id(cpu) (cpu_topology[cpu].socket_id) | 23 | #define topology_physical_package_id(cpu) (per_cpu(cpu_topology, cpu).socket_id) |
| 24 | #define topology_thread_id(cpu) (cpu_topology[cpu].thread_id) | 24 | #define topology_thread_id(cpu) (per_cpu(cpu_topology, cpu).thread_id) |
| 25 | #define topology_thread_cpumask(cpu) (&cpu_topology[cpu].thread_mask) | 25 | #define topology_thread_cpumask(cpu) (&per_cpu(cpu_topology, cpu).thread_mask) |
| 26 | #define topology_core_id(cpu) (cpu_topology[cpu].core_id) | 26 | #define topology_core_id(cpu) (per_cpu(cpu_topology, cpu).core_id) |
| 27 | #define topology_core_cpumask(cpu) (&cpu_topology[cpu].core_mask) | 27 | #define topology_core_cpumask(cpu) (&per_cpu(cpu_topology, cpu).core_mask) |
| 28 | #define topology_book_id(cpu) (cpu_topology[cpu].book_id) | 28 | #define topology_book_id(cpu) (per_cpu(cpu_topology, cpu).book_id) |
| 29 | #define topology_book_cpumask(cpu) (&cpu_topology[cpu].book_mask) | 29 | #define topology_book_cpumask(cpu) (&per_cpu(cpu_topology, cpu).book_mask) |
| 30 | 30 | ||
| 31 | #define mc_capable() 1 | 31 | #define mc_capable() 1 |
| 32 | 32 | ||
| @@ -51,14 +51,6 @@ static inline void topology_expect_change(void) { } | |||
| 51 | #define POLARIZATION_VM (2) | 51 | #define POLARIZATION_VM (2) |
| 52 | #define POLARIZATION_VH (3) | 52 | #define POLARIZATION_VH (3) |
| 53 | 53 | ||
| 54 | #ifdef CONFIG_SCHED_BOOK | ||
| 55 | void s390_init_cpu_topology(void); | ||
| 56 | #else | ||
| 57 | static inline void s390_init_cpu_topology(void) | ||
| 58 | { | ||
| 59 | }; | ||
| 60 | #endif | ||
| 61 | |||
| 62 | #include <asm-generic/topology.h> | 54 | #include <asm-generic/topology.h> |
| 63 | 55 | ||
| 64 | #endif /* _ASM_S390_TOPOLOGY_H */ | 56 | #endif /* _ASM_S390_TOPOLOGY_H */ |
diff --git a/arch/s390/kernel/cache.c b/arch/s390/kernel/cache.c index 632fa06ea162..0969d113b3d6 100644 --- a/arch/s390/kernel/cache.c +++ b/arch/s390/kernel/cache.c | |||
| @@ -91,12 +91,9 @@ static inline enum cache_type get_cache_type(struct cache_info *ci, int level) | |||
| 91 | { | 91 | { |
| 92 | if (level >= CACHE_MAX_LEVEL) | 92 | if (level >= CACHE_MAX_LEVEL) |
| 93 | return CACHE_TYPE_NOCACHE; | 93 | return CACHE_TYPE_NOCACHE; |
| 94 | |||
| 95 | ci += level; | 94 | ci += level; |
| 96 | |||
| 97 | if (ci->scope != CACHE_SCOPE_SHARED && ci->scope != CACHE_SCOPE_PRIVATE) | 95 | if (ci->scope != CACHE_SCOPE_SHARED && ci->scope != CACHE_SCOPE_PRIVATE) |
| 98 | return CACHE_TYPE_NOCACHE; | 96 | return CACHE_TYPE_NOCACHE; |
| 99 | |||
| 100 | return cache_type_map[ci->type]; | 97 | return cache_type_map[ci->type]; |
| 101 | } | 98 | } |
| 102 | 99 | ||
| @@ -111,23 +108,19 @@ static inline unsigned long ecag(int ai, int li, int ti) | |||
| 111 | } | 108 | } |
| 112 | 109 | ||
| 113 | static void ci_leaf_init(struct cacheinfo *this_leaf, int private, | 110 | static void ci_leaf_init(struct cacheinfo *this_leaf, int private, |
| 114 | enum cache_type type, unsigned int level) | 111 | enum cache_type type, unsigned int level, int cpu) |
| 115 | { | 112 | { |
| 116 | int ti, num_sets; | 113 | int ti, num_sets; |
| 117 | int cpu = smp_processor_id(); | ||
| 118 | 114 | ||
| 119 | if (type == CACHE_TYPE_INST) | 115 | if (type == CACHE_TYPE_INST) |
| 120 | ti = CACHE_TI_INSTRUCTION; | 116 | ti = CACHE_TI_INSTRUCTION; |
| 121 | else | 117 | else |
| 122 | ti = CACHE_TI_UNIFIED; | 118 | ti = CACHE_TI_UNIFIED; |
| 123 | |||
| 124 | this_leaf->level = level + 1; | 119 | this_leaf->level = level + 1; |
| 125 | this_leaf->type = type; | 120 | this_leaf->type = type; |
| 126 | this_leaf->coherency_line_size = ecag(EXTRACT_LINE_SIZE, level, ti); | 121 | this_leaf->coherency_line_size = ecag(EXTRACT_LINE_SIZE, level, ti); |
| 127 | this_leaf->ways_of_associativity = ecag(EXTRACT_ASSOCIATIVITY, | 122 | this_leaf->ways_of_associativity = ecag(EXTRACT_ASSOCIATIVITY, level, ti); |
| 128 | level, ti); | ||
| 129 | this_leaf->size = ecag(EXTRACT_SIZE, level, ti); | 123 | this_leaf->size = ecag(EXTRACT_SIZE, level, ti); |
| 130 | |||
| 131 | num_sets = this_leaf->size / this_leaf->coherency_line_size; | 124 | num_sets = this_leaf->size / this_leaf->coherency_line_size; |
| 132 | num_sets /= this_leaf->ways_of_associativity; | 125 | num_sets /= this_leaf->ways_of_associativity; |
| 133 | this_leaf->number_of_sets = num_sets; | 126 | this_leaf->number_of_sets = num_sets; |
| @@ -145,7 +138,6 @@ int init_cache_level(unsigned int cpu) | |||
| 145 | 138 | ||
| 146 | if (!this_cpu_ci) | 139 | if (!this_cpu_ci) |
| 147 | return -EINVAL; | 140 | return -EINVAL; |
| 148 | |||
| 149 | ct.raw = ecag(EXTRACT_TOPOLOGY, 0, 0); | 141 | ct.raw = ecag(EXTRACT_TOPOLOGY, 0, 0); |
| 150 | do { | 142 | do { |
| 151 | ctype = get_cache_type(&ct.ci[0], level); | 143 | ctype = get_cache_type(&ct.ci[0], level); |
| @@ -154,34 +146,31 @@ int init_cache_level(unsigned int cpu) | |||
| 154 | /* Separate instruction and data caches */ | 146 | /* Separate instruction and data caches */ |
| 155 | leaves += (ctype == CACHE_TYPE_SEPARATE) ? 2 : 1; | 147 | leaves += (ctype == CACHE_TYPE_SEPARATE) ? 2 : 1; |
| 156 | } while (++level < CACHE_MAX_LEVEL); | 148 | } while (++level < CACHE_MAX_LEVEL); |
| 157 | |||
| 158 | this_cpu_ci->num_levels = level; | 149 | this_cpu_ci->num_levels = level; |
| 159 | this_cpu_ci->num_leaves = leaves; | 150 | this_cpu_ci->num_leaves = leaves; |
| 160 | |||
| 161 | return 0; | 151 | return 0; |
| 162 | } | 152 | } |
| 163 | 153 | ||
| 164 | int populate_cache_leaves(unsigned int cpu) | 154 | int populate_cache_leaves(unsigned int cpu) |
| 165 | { | 155 | { |
| 156 | struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); | ||
| 157 | struct cacheinfo *this_leaf = this_cpu_ci->info_list; | ||
| 166 | unsigned int level, idx, pvt; | 158 | unsigned int level, idx, pvt; |
| 167 | union cache_topology ct; | 159 | union cache_topology ct; |
| 168 | enum cache_type ctype; | 160 | enum cache_type ctype; |
| 169 | struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu); | ||
| 170 | struct cacheinfo *this_leaf = this_cpu_ci->info_list; | ||
| 171 | 161 | ||
| 172 | ct.raw = ecag(EXTRACT_TOPOLOGY, 0, 0); | 162 | ct.raw = ecag(EXTRACT_TOPOLOGY, 0, 0); |
| 173 | for (idx = 0, level = 0; level < this_cpu_ci->num_levels && | 163 | for (idx = 0, level = 0; level < this_cpu_ci->num_levels && |
| 174 | idx < this_cpu_ci->num_leaves; idx++, level++) { | 164 | idx < this_cpu_ci->num_leaves; idx++, level++) { |
| 175 | if (!this_leaf) | 165 | if (!this_leaf) |
| 176 | return -EINVAL; | 166 | return -EINVAL; |
| 177 | |||
| 178 | pvt = (ct.ci[level].scope == CACHE_SCOPE_PRIVATE) ? 1 : 0; | 167 | pvt = (ct.ci[level].scope == CACHE_SCOPE_PRIVATE) ? 1 : 0; |
| 179 | ctype = get_cache_type(&ct.ci[0], level); | 168 | ctype = get_cache_type(&ct.ci[0], level); |
| 180 | if (ctype == CACHE_TYPE_SEPARATE) { | 169 | if (ctype == CACHE_TYPE_SEPARATE) { |
| 181 | ci_leaf_init(this_leaf++, pvt, CACHE_TYPE_DATA, level); | 170 | ci_leaf_init(this_leaf++, pvt, CACHE_TYPE_DATA, level, cpu); |
| 182 | ci_leaf_init(this_leaf++, pvt, CACHE_TYPE_INST, level); | 171 | ci_leaf_init(this_leaf++, pvt, CACHE_TYPE_INST, level, cpu); |
| 183 | } else { | 172 | } else { |
| 184 | ci_leaf_init(this_leaf++, pvt, ctype, level); | 173 | ci_leaf_init(this_leaf++, pvt, ctype, level, cpu); |
| 185 | } | 174 | } |
| 186 | } | 175 | } |
| 187 | return 0; | 176 | return 0; |
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 70a329450901..4427ab7ac23a 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c | |||
| @@ -393,17 +393,19 @@ static __init void detect_machine_facilities(void) | |||
| 393 | S390_lowcore.machine_flags |= MACHINE_FLAG_TLB_LC; | 393 | S390_lowcore.machine_flags |= MACHINE_FLAG_TLB_LC; |
| 394 | if (test_facility(129)) | 394 | if (test_facility(129)) |
| 395 | S390_lowcore.machine_flags |= MACHINE_FLAG_VX; | 395 | S390_lowcore.machine_flags |= MACHINE_FLAG_VX; |
| 396 | if (test_facility(128)) | ||
| 397 | S390_lowcore.machine_flags |= MACHINE_FLAG_CAD; | ||
| 398 | #endif | 396 | #endif |
| 399 | } | 397 | } |
| 400 | 398 | ||
| 401 | static int __init nocad_setup(char *str) | 399 | static int __init cad_setup(char *str) |
| 402 | { | 400 | { |
| 403 | S390_lowcore.machine_flags &= ~MACHINE_FLAG_CAD; | 401 | int val; |
| 402 | |||
| 403 | get_option(&str, &val); | ||
| 404 | if (val && test_facility(128)) | ||
| 405 | S390_lowcore.machine_flags |= MACHINE_FLAG_CAD; | ||
| 404 | return 0; | 406 | return 0; |
| 405 | } | 407 | } |
| 406 | early_param("nocad", nocad_setup); | 408 | early_param("cad", cad_setup); |
| 407 | 409 | ||
| 408 | static int __init cad_init(void) | 410 | static int __init cad_init(void) |
| 409 | { | 411 | { |
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index bfac77ada4f2..a5ea8bc17cb3 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c | |||
| @@ -909,7 +909,6 @@ void __init setup_arch(char **cmdline_p) | |||
| 909 | setup_lowcore(); | 909 | setup_lowcore(); |
| 910 | smp_fill_possible_mask(); | 910 | smp_fill_possible_mask(); |
| 911 | cpu_init(); | 911 | cpu_init(); |
| 912 | s390_init_cpu_topology(); | ||
| 913 | 912 | ||
| 914 | /* | 913 | /* |
| 915 | * Setup capabilities (ELF_HWCAP & ELF_PLATFORM). | 914 | * Setup capabilities (ELF_HWCAP & ELF_PLATFORM). |
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index a668993ff577..db8f1115a3bf 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c | |||
| @@ -59,14 +59,13 @@ enum { | |||
| 59 | CPU_STATE_CONFIGURED, | 59 | CPU_STATE_CONFIGURED, |
| 60 | }; | 60 | }; |
| 61 | 61 | ||
| 62 | static DEFINE_PER_CPU(struct cpu *, cpu_device); | ||
| 63 | |||
| 62 | struct pcpu { | 64 | struct pcpu { |
| 63 | struct cpu *cpu; | ||
| 64 | struct _lowcore *lowcore; /* lowcore page(s) for the cpu */ | 65 | struct _lowcore *lowcore; /* lowcore page(s) for the cpu */ |
| 65 | unsigned long async_stack; /* async stack for the cpu */ | ||
| 66 | unsigned long panic_stack; /* panic stack for the cpu */ | ||
| 67 | unsigned long ec_mask; /* bit mask for ec_xxx functions */ | 66 | unsigned long ec_mask; /* bit mask for ec_xxx functions */ |
| 68 | int state; /* physical cpu state */ | 67 | signed char state; /* physical cpu state */ |
| 69 | int polarization; /* physical polarization */ | 68 | signed char polarization; /* physical polarization */ |
| 70 | u16 address; /* physical cpu address */ | 69 | u16 address; /* physical cpu address */ |
| 71 | }; | 70 | }; |
| 72 | 71 | ||
| @@ -173,25 +172,30 @@ static void pcpu_ec_call(struct pcpu *pcpu, int ec_bit) | |||
| 173 | pcpu_sigp_retry(pcpu, order, 0); | 172 | pcpu_sigp_retry(pcpu, order, 0); |
| 174 | } | 173 | } |
| 175 | 174 | ||
| 175 | #define ASYNC_FRAME_OFFSET (ASYNC_SIZE - STACK_FRAME_OVERHEAD - __PT_SIZE) | ||
| 176 | #define PANIC_FRAME_OFFSET (PAGE_SIZE - STACK_FRAME_OVERHEAD - __PT_SIZE) | ||
| 177 | |||
| 176 | static int pcpu_alloc_lowcore(struct pcpu *pcpu, int cpu) | 178 | static int pcpu_alloc_lowcore(struct pcpu *pcpu, int cpu) |
| 177 | { | 179 | { |
| 180 | unsigned long async_stack, panic_stack; | ||
| 178 | struct _lowcore *lc; | 181 | struct _lowcore *lc; |
| 179 | 182 | ||
| 180 | if (pcpu != &pcpu_devices[0]) { | 183 | if (pcpu != &pcpu_devices[0]) { |
| 181 | pcpu->lowcore = (struct _lowcore *) | 184 | pcpu->lowcore = (struct _lowcore *) |
| 182 | __get_free_pages(GFP_KERNEL | GFP_DMA, LC_ORDER); | 185 | __get_free_pages(GFP_KERNEL | GFP_DMA, LC_ORDER); |
| 183 | pcpu->async_stack = __get_free_pages(GFP_KERNEL, ASYNC_ORDER); | 186 | async_stack = __get_free_pages(GFP_KERNEL, ASYNC_ORDER); |
| 184 | pcpu->panic_stack = __get_free_page(GFP_KERNEL); | 187 | panic_stack = __get_free_page(GFP_KERNEL); |
| 185 | if (!pcpu->lowcore || !pcpu->panic_stack || !pcpu->async_stack) | 188 | if (!pcpu->lowcore || !panic_stack || !async_stack) |
| 186 | goto out; | 189 | goto out; |
| 190 | } else { | ||
| 191 | async_stack = pcpu->lowcore->async_stack - ASYNC_FRAME_OFFSET; | ||
| 192 | panic_stack = pcpu->lowcore->panic_stack - PANIC_FRAME_OFFSET; | ||
| 187 | } | 193 | } |
| 188 | lc = pcpu->lowcore; | 194 | lc = pcpu->lowcore; |
| 189 | memcpy(lc, &S390_lowcore, 512); | 195 | memcpy(lc, &S390_lowcore, 512); |
| 190 | memset((char *) lc + 512, 0, sizeof(*lc) - 512); | 196 | memset((char *) lc + 512, 0, sizeof(*lc) - 512); |
| 191 | lc->async_stack = pcpu->async_stack + ASYNC_SIZE | 197 | lc->async_stack = async_stack + ASYNC_FRAME_OFFSET; |
| 192 | - STACK_FRAME_OVERHEAD - sizeof(struct pt_regs); | 198 | lc->panic_stack = panic_stack + PANIC_FRAME_OFFSET; |
| 193 | lc->panic_stack = pcpu->panic_stack + PAGE_SIZE | ||
| 194 | - STACK_FRAME_OVERHEAD - sizeof(struct pt_regs); | ||
| 195 | lc->cpu_nr = cpu; | 199 | lc->cpu_nr = cpu; |
| 196 | lc->spinlock_lockval = arch_spin_lockval(cpu); | 200 | lc->spinlock_lockval = arch_spin_lockval(cpu); |
| 197 | #ifndef CONFIG_64BIT | 201 | #ifndef CONFIG_64BIT |
| @@ -212,8 +216,8 @@ static int pcpu_alloc_lowcore(struct pcpu *pcpu, int cpu) | |||
| 212 | return 0; | 216 | return 0; |
| 213 | out: | 217 | out: |
| 214 | if (pcpu != &pcpu_devices[0]) { | 218 | if (pcpu != &pcpu_devices[0]) { |
| 215 | free_page(pcpu->panic_stack); | 219 | free_page(panic_stack); |
| 216 | free_pages(pcpu->async_stack, ASYNC_ORDER); | 220 | free_pages(async_stack, ASYNC_ORDER); |
| 217 | free_pages((unsigned long) pcpu->lowcore, LC_ORDER); | 221 | free_pages((unsigned long) pcpu->lowcore, LC_ORDER); |
| 218 | } | 222 | } |
| 219 | return -ENOMEM; | 223 | return -ENOMEM; |
| @@ -235,11 +239,11 @@ static void pcpu_free_lowcore(struct pcpu *pcpu) | |||
| 235 | #else | 239 | #else |
| 236 | vdso_free_per_cpu(pcpu->lowcore); | 240 | vdso_free_per_cpu(pcpu->lowcore); |
| 237 | #endif | 241 | #endif |
| 238 | if (pcpu != &pcpu_devices[0]) { | 242 | if (pcpu == &pcpu_devices[0]) |
| 239 | free_page(pcpu->panic_stack); | 243 | return; |
| 240 | free_pages(pcpu->async_stack, ASYNC_ORDER); | 244 | free_page(pcpu->lowcore->panic_stack-PANIC_FRAME_OFFSET); |
| 241 | free_pages((unsigned long) pcpu->lowcore, LC_ORDER); | 245 | free_pages(pcpu->lowcore->async_stack-ASYNC_FRAME_OFFSET, ASYNC_ORDER); |
| 242 | } | 246 | free_pages((unsigned long) pcpu->lowcore, LC_ORDER); |
| 243 | } | 247 | } |
| 244 | 248 | ||
| 245 | #endif /* CONFIG_HOTPLUG_CPU */ | 249 | #endif /* CONFIG_HOTPLUG_CPU */ |
| @@ -366,7 +370,8 @@ void smp_call_online_cpu(void (*func)(void *), void *data) | |||
| 366 | void smp_call_ipl_cpu(void (*func)(void *), void *data) | 370 | void smp_call_ipl_cpu(void (*func)(void *), void *data) |
| 367 | { | 371 | { |
| 368 | pcpu_delegate(&pcpu_devices[0], func, data, | 372 | pcpu_delegate(&pcpu_devices[0], func, data, |
| 369 | pcpu_devices->panic_stack + PAGE_SIZE); | 373 | pcpu_devices->lowcore->panic_stack - |
| 374 | PANIC_FRAME_OFFSET + PAGE_SIZE); | ||
| 370 | } | 375 | } |
| 371 | 376 | ||
| 372 | int smp_find_processor_id(u16 address) | 377 | int smp_find_processor_id(u16 address) |
| @@ -935,10 +940,6 @@ void __init smp_prepare_boot_cpu(void) | |||
| 935 | pcpu->state = CPU_STATE_CONFIGURED; | 940 | pcpu->state = CPU_STATE_CONFIGURED; |
| 936 | pcpu->address = stap(); | 941 | pcpu->address = stap(); |
| 937 | pcpu->lowcore = (struct _lowcore *)(unsigned long) store_prefix(); | 942 | pcpu->lowcore = (struct _lowcore *)(unsigned long) store_prefix(); |
| 938 | pcpu->async_stack = S390_lowcore.async_stack - ASYNC_SIZE | ||
| 939 | + STACK_FRAME_OVERHEAD + sizeof(struct pt_regs); | ||
| 940 | pcpu->panic_stack = S390_lowcore.panic_stack - PAGE_SIZE | ||
| 941 | + STACK_FRAME_OVERHEAD + sizeof(struct pt_regs); | ||
| 942 | S390_lowcore.percpu_offset = __per_cpu_offset[0]; | 943 | S390_lowcore.percpu_offset = __per_cpu_offset[0]; |
| 943 | smp_cpu_set_polarization(0, POLARIZATION_UNKNOWN); | 944 | smp_cpu_set_polarization(0, POLARIZATION_UNKNOWN); |
| 944 | set_cpu_present(0, true); | 945 | set_cpu_present(0, true); |
| @@ -1078,8 +1079,7 @@ static int smp_cpu_notify(struct notifier_block *self, unsigned long action, | |||
| 1078 | void *hcpu) | 1079 | void *hcpu) |
| 1079 | { | 1080 | { |
| 1080 | unsigned int cpu = (unsigned int)(long)hcpu; | 1081 | unsigned int cpu = (unsigned int)(long)hcpu; |
| 1081 | struct cpu *c = pcpu_devices[cpu].cpu; | 1082 | struct device *s = &per_cpu(cpu_device, cpu)->dev; |
| 1082 | struct device *s = &c->dev; | ||
| 1083 | int err = 0; | 1083 | int err = 0; |
| 1084 | 1084 | ||
| 1085 | switch (action & ~CPU_TASKS_FROZEN) { | 1085 | switch (action & ~CPU_TASKS_FROZEN) { |
| @@ -1102,7 +1102,7 @@ static int smp_add_present_cpu(int cpu) | |||
| 1102 | c = kzalloc(sizeof(*c), GFP_KERNEL); | 1102 | c = kzalloc(sizeof(*c), GFP_KERNEL); |
| 1103 | if (!c) | 1103 | if (!c) |
| 1104 | return -ENOMEM; | 1104 | return -ENOMEM; |
| 1105 | pcpu_devices[cpu].cpu = c; | 1105 | per_cpu(cpu_device, cpu) = c; |
| 1106 | s = &c->dev; | 1106 | s = &c->dev; |
| 1107 | c->hotpluggable = 1; | 1107 | c->hotpluggable = 1; |
| 1108 | rc = register_cpu(c, cpu); | 1108 | rc = register_cpu(c, cpu); |
diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c index 24ee33f1af24..14da43b801d9 100644 --- a/arch/s390/kernel/topology.c +++ b/arch/s390/kernel/topology.c | |||
| @@ -7,14 +7,14 @@ | |||
| 7 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | 7 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt |
| 8 | 8 | ||
| 9 | #include <linux/workqueue.h> | 9 | #include <linux/workqueue.h> |
| 10 | #include <linux/bootmem.h> | ||
| 11 | #include <linux/cpuset.h> | 10 | #include <linux/cpuset.h> |
| 12 | #include <linux/device.h> | 11 | #include <linux/device.h> |
| 13 | #include <linux/export.h> | 12 | #include <linux/export.h> |
| 14 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
| 15 | #include <linux/sched.h> | 14 | #include <linux/sched.h> |
| 16 | #include <linux/init.h> | ||
| 17 | #include <linux/delay.h> | 15 | #include <linux/delay.h> |
| 16 | #include <linux/init.h> | ||
| 17 | #include <linux/slab.h> | ||
| 18 | #include <linux/cpu.h> | 18 | #include <linux/cpu.h> |
| 19 | #include <linux/smp.h> | 19 | #include <linux/smp.h> |
| 20 | #include <linux/mm.h> | 20 | #include <linux/mm.h> |
| @@ -42,8 +42,8 @@ static DEFINE_SPINLOCK(topology_lock); | |||
| 42 | static struct mask_info socket_info; | 42 | static struct mask_info socket_info; |
| 43 | static struct mask_info book_info; | 43 | static struct mask_info book_info; |
| 44 | 44 | ||
| 45 | struct cpu_topology_s390 cpu_topology[NR_CPUS]; | 45 | DEFINE_PER_CPU(struct cpu_topology_s390, cpu_topology); |
| 46 | EXPORT_SYMBOL_GPL(cpu_topology); | 46 | EXPORT_PER_CPU_SYMBOL_GPL(cpu_topology); |
| 47 | 47 | ||
| 48 | static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu) | 48 | static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu) |
| 49 | { | 49 | { |
| @@ -90,15 +90,15 @@ static struct mask_info *add_cpus_to_mask(struct topology_core *tl_core, | |||
| 90 | if (lcpu < 0) | 90 | if (lcpu < 0) |
| 91 | continue; | 91 | continue; |
| 92 | for (i = 0; i <= smp_cpu_mtid; i++) { | 92 | for (i = 0; i <= smp_cpu_mtid; i++) { |
| 93 | cpu_topology[lcpu + i].book_id = book->id; | 93 | per_cpu(cpu_topology, lcpu + i).book_id = book->id; |
| 94 | cpu_topology[lcpu + i].core_id = rcore; | 94 | per_cpu(cpu_topology, lcpu + i).core_id = rcore; |
| 95 | cpu_topology[lcpu + i].thread_id = lcpu + i; | 95 | per_cpu(cpu_topology, lcpu + i).thread_id = lcpu + i; |
| 96 | cpumask_set_cpu(lcpu + i, &book->mask); | 96 | cpumask_set_cpu(lcpu + i, &book->mask); |
| 97 | cpumask_set_cpu(lcpu + i, &socket->mask); | 97 | cpumask_set_cpu(lcpu + i, &socket->mask); |
| 98 | if (one_socket_per_cpu) | 98 | if (one_socket_per_cpu) |
| 99 | cpu_topology[lcpu + i].socket_id = rcore; | 99 | per_cpu(cpu_topology, lcpu + i).socket_id = rcore; |
| 100 | else | 100 | else |
| 101 | cpu_topology[lcpu + i].socket_id = socket->id; | 101 | per_cpu(cpu_topology, lcpu + i).socket_id = socket->id; |
| 102 | smp_cpu_set_polarization(lcpu + i, tl_core->pp); | 102 | smp_cpu_set_polarization(lcpu + i, tl_core->pp); |
| 103 | } | 103 | } |
| 104 | if (one_socket_per_cpu) | 104 | if (one_socket_per_cpu) |
| @@ -249,14 +249,14 @@ static void update_cpu_masks(void) | |||
| 249 | 249 | ||
| 250 | spin_lock_irqsave(&topology_lock, flags); | 250 | spin_lock_irqsave(&topology_lock, flags); |
| 251 | for_each_possible_cpu(cpu) { | 251 | for_each_possible_cpu(cpu) { |
| 252 | cpu_topology[cpu].thread_mask = cpu_thread_map(cpu); | 252 | per_cpu(cpu_topology, cpu).thread_mask = cpu_thread_map(cpu); |
| 253 | cpu_topology[cpu].core_mask = cpu_group_map(&socket_info, cpu); | 253 | per_cpu(cpu_topology, cpu).core_mask = cpu_group_map(&socket_info, cpu); |
| 254 | cpu_topology[cpu].book_mask = cpu_group_map(&book_info, cpu); | 254 | per_cpu(cpu_topology, cpu).book_mask = cpu_group_map(&book_info, cpu); |
| 255 | if (!MACHINE_HAS_TOPOLOGY) { | 255 | if (!MACHINE_HAS_TOPOLOGY) { |
| 256 | cpu_topology[cpu].thread_id = cpu; | 256 | per_cpu(cpu_topology, cpu).thread_id = cpu; |
| 257 | cpu_topology[cpu].core_id = cpu; | 257 | per_cpu(cpu_topology, cpu).core_id = cpu; |
| 258 | cpu_topology[cpu].socket_id = cpu; | 258 | per_cpu(cpu_topology, cpu).socket_id = cpu; |
| 259 | cpu_topology[cpu].book_id = cpu; | 259 | per_cpu(cpu_topology, cpu).book_id = cpu; |
| 260 | } | 260 | } |
| 261 | } | 261 | } |
| 262 | spin_unlock_irqrestore(&topology_lock, flags); | 262 | spin_unlock_irqrestore(&topology_lock, flags); |
| @@ -334,50 +334,6 @@ void topology_expect_change(void) | |||
| 334 | set_topology_timer(); | 334 | set_topology_timer(); |
| 335 | } | 335 | } |
| 336 | 336 | ||
| 337 | static int __init early_parse_topology(char *p) | ||
| 338 | { | ||
| 339 | if (strncmp(p, "off", 3)) | ||
| 340 | return 0; | ||
| 341 | topology_enabled = 0; | ||
| 342 | return 0; | ||
| 343 | } | ||
| 344 | early_param("topology", early_parse_topology); | ||
| 345 | |||
| 346 | static void __init alloc_masks(struct sysinfo_15_1_x *info, | ||
| 347 | struct mask_info *mask, int offset) | ||
| 348 | { | ||
| 349 | int i, nr_masks; | ||
| 350 | |||
| 351 | nr_masks = info->mag[TOPOLOGY_NR_MAG - offset]; | ||
| 352 | for (i = 0; i < info->mnest - offset; i++) | ||
| 353 | nr_masks *= info->mag[TOPOLOGY_NR_MAG - offset - 1 - i]; | ||
| 354 | nr_masks = max(nr_masks, 1); | ||
| 355 | for (i = 0; i < nr_masks; i++) { | ||
| 356 | mask->next = alloc_bootmem_align( | ||
| 357 | roundup_pow_of_two(sizeof(struct mask_info)), | ||
| 358 | roundup_pow_of_two(sizeof(struct mask_info))); | ||
| 359 | mask = mask->next; | ||
| 360 | } | ||
| 361 | } | ||
| 362 | |||
| 363 | void __init s390_init_cpu_topology(void) | ||
| 364 | { | ||
| 365 | struct sysinfo_15_1_x *info; | ||
| 366 | int i; | ||
| 367 | |||
| 368 | if (!MACHINE_HAS_TOPOLOGY) | ||
| 369 | return; | ||
| 370 | tl_info = alloc_bootmem_pages(PAGE_SIZE); | ||
| 371 | info = tl_info; | ||
| 372 | store_topology(info); | ||
| 373 | pr_info("The CPU configuration topology of the machine is:"); | ||
| 374 | for (i = 0; i < TOPOLOGY_NR_MAG; i++) | ||
| 375 | printk(KERN_CONT " %d", info->mag[i]); | ||
| 376 | printk(KERN_CONT " / %d\n", info->mnest); | ||
| 377 | alloc_masks(info, &socket_info, 1); | ||
| 378 | alloc_masks(info, &book_info, 2); | ||
| 379 | } | ||
| 380 | |||
| 381 | static int cpu_management; | 337 | static int cpu_management; |
| 382 | 338 | ||
| 383 | static ssize_t dispatching_show(struct device *dev, | 339 | static ssize_t dispatching_show(struct device *dev, |
| @@ -467,20 +423,29 @@ int topology_cpu_init(struct cpu *cpu) | |||
| 467 | 423 | ||
| 468 | const struct cpumask *cpu_thread_mask(int cpu) | 424 | const struct cpumask *cpu_thread_mask(int cpu) |
| 469 | { | 425 | { |
| 470 | return &cpu_topology[cpu].thread_mask; | 426 | return &per_cpu(cpu_topology, cpu).thread_mask; |
| 471 | } | 427 | } |
| 472 | 428 | ||
| 473 | 429 | ||
| 474 | const struct cpumask *cpu_coregroup_mask(int cpu) | 430 | const struct cpumask *cpu_coregroup_mask(int cpu) |
| 475 | { | 431 | { |
| 476 | return &cpu_topology[cpu].core_mask; | 432 | return &per_cpu(cpu_topology, cpu).core_mask; |
| 477 | } | 433 | } |
| 478 | 434 | ||
| 479 | static const struct cpumask *cpu_book_mask(int cpu) | 435 | static const struct cpumask *cpu_book_mask(int cpu) |
| 480 | { | 436 | { |
| 481 | return &cpu_topology[cpu].book_mask; | 437 | return &per_cpu(cpu_topology, cpu).book_mask; |
| 482 | } | 438 | } |
| 483 | 439 | ||
| 440 | static int __init early_parse_topology(char *p) | ||
| 441 | { | ||
| 442 | if (strncmp(p, "off", 3)) | ||
| 443 | return 0; | ||
| 444 | topology_enabled = 0; | ||
| 445 | return 0; | ||
| 446 | } | ||
| 447 | early_param("topology", early_parse_topology); | ||
| 448 | |||
| 484 | static struct sched_domain_topology_level s390_topology[] = { | 449 | static struct sched_domain_topology_level s390_topology[] = { |
| 485 | { cpu_thread_mask, cpu_smt_flags, SD_INIT_NAME(SMT) }, | 450 | { cpu_thread_mask, cpu_smt_flags, SD_INIT_NAME(SMT) }, |
| 486 | { cpu_coregroup_mask, cpu_core_flags, SD_INIT_NAME(MC) }, | 451 | { cpu_coregroup_mask, cpu_core_flags, SD_INIT_NAME(MC) }, |
| @@ -489,6 +454,42 @@ static struct sched_domain_topology_level s390_topology[] = { | |||
| 489 | { NULL, }, | 454 | { NULL, }, |
| 490 | }; | 455 | }; |
| 491 | 456 | ||
| 457 | static void __init alloc_masks(struct sysinfo_15_1_x *info, | ||
| 458 | struct mask_info *mask, int offset) | ||
| 459 | { | ||
| 460 | int i, nr_masks; | ||
| 461 | |||
| 462 | nr_masks = info->mag[TOPOLOGY_NR_MAG - offset]; | ||
| 463 | for (i = 0; i < info->mnest - offset; i++) | ||
| 464 | nr_masks *= info->mag[TOPOLOGY_NR_MAG - offset - 1 - i]; | ||
| 465 | nr_masks = max(nr_masks, 1); | ||
| 466 | for (i = 0; i < nr_masks; i++) { | ||
| 467 | mask->next = kzalloc(sizeof(*mask->next), GFP_KERNEL); | ||
| 468 | mask = mask->next; | ||
| 469 | } | ||
| 470 | } | ||
| 471 | |||
| 472 | static int __init s390_topology_init(void) | ||
| 473 | { | ||
| 474 | struct sysinfo_15_1_x *info; | ||
| 475 | int i; | ||
| 476 | |||
| 477 | if (!MACHINE_HAS_TOPOLOGY) | ||
| 478 | return 0; | ||
| 479 | tl_info = (struct sysinfo_15_1_x *)__get_free_page(GFP_KERNEL); | ||
| 480 | info = tl_info; | ||
| 481 | store_topology(info); | ||
| 482 | pr_info("The CPU configuration topology of the machine is:"); | ||
| 483 | for (i = 0; i < TOPOLOGY_NR_MAG; i++) | ||
| 484 | printk(KERN_CONT " %d", info->mag[i]); | ||
| 485 | printk(KERN_CONT " / %d\n", info->mnest); | ||
| 486 | alloc_masks(info, &socket_info, 1); | ||
| 487 | alloc_masks(info, &book_info, 2); | ||
| 488 | set_sched_topology(s390_topology); | ||
| 489 | return 0; | ||
| 490 | } | ||
| 491 | early_initcall(s390_topology_init); | ||
| 492 | |||
| 492 | static int __init topology_init(void) | 493 | static int __init topology_init(void) |
| 493 | { | 494 | { |
| 494 | if (MACHINE_HAS_TOPOLOGY) | 495 | if (MACHINE_HAS_TOPOLOGY) |
| @@ -498,10 +499,3 @@ static int __init topology_init(void) | |||
| 498 | return device_create_file(cpu_subsys.dev_root, &dev_attr_dispatching); | 499 | return device_create_file(cpu_subsys.dev_root, &dev_attr_dispatching); |
| 499 | } | 500 | } |
| 500 | device_initcall(topology_init); | 501 | device_initcall(topology_init); |
| 501 | |||
| 502 | static int __init early_topology_init(void) | ||
| 503 | { | ||
| 504 | set_sched_topology(s390_topology); | ||
| 505 | return 0; | ||
| 506 | } | ||
| 507 | early_initcall(early_topology_init); | ||
diff --git a/arch/s390/kernel/vdso64/clock_gettime.S b/arch/s390/kernel/vdso64/clock_gettime.S index 7699e735ae28..61541fb93dc6 100644 --- a/arch/s390/kernel/vdso64/clock_gettime.S +++ b/arch/s390/kernel/vdso64/clock_gettime.S | |||
| @@ -25,9 +25,7 @@ __kernel_clock_gettime: | |||
| 25 | je 4f | 25 | je 4f |
| 26 | cghi %r2,__CLOCK_REALTIME | 26 | cghi %r2,__CLOCK_REALTIME |
| 27 | je 5f | 27 | je 5f |
| 28 | cghi %r2,__CLOCK_THREAD_CPUTIME_ID | 28 | cghi %r2,-3 /* Per-thread CPUCLOCK with PID=0, VIRT=1 */ |
| 29 | je 9f | ||
| 30 | cghi %r2,-2 /* Per-thread CPUCLOCK with PID=0, VIRT=1 */ | ||
| 31 | je 9f | 29 | je 9f |
| 32 | cghi %r2,__CLOCK_MONOTONIC_COARSE | 30 | cghi %r2,__CLOCK_MONOTONIC_COARSE |
| 33 | je 3f | 31 | je 3f |
| @@ -106,7 +104,7 @@ __kernel_clock_gettime: | |||
| 106 | aghi %r15,16 | 104 | aghi %r15,16 |
| 107 | br %r14 | 105 | br %r14 |
| 108 | 106 | ||
| 109 | /* CLOCK_THREAD_CPUTIME_ID for this thread */ | 107 | /* CPUCLOCK_VIRT for this thread */ |
| 110 | 9: icm %r0,15,__VDSO_ECTG_OK(%r5) | 108 | 9: icm %r0,15,__VDSO_ECTG_OK(%r5) |
| 111 | jz 12f | 109 | jz 12f |
| 112 | ear %r2,%a4 | 110 | ear %r2,%a4 |
diff --git a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c index d008f638b2cd..179a2c20b01f 100644 --- a/arch/s390/mm/mmap.c +++ b/arch/s390/mm/mmap.c | |||
| @@ -183,7 +183,10 @@ unsigned long randomize_et_dyn(void) | |||
| 183 | { | 183 | { |
| 184 | unsigned long base; | 184 | unsigned long base; |
| 185 | 185 | ||
| 186 | base = (STACK_TOP / 3 * 2) & (~mmap_align_mask << PAGE_SHIFT); | 186 | base = STACK_TOP / 3 * 2; |
| 187 | if (!is_32bit_task()) | ||
| 188 | /* Align to 4GB */ | ||
| 189 | base &= ~((1UL << 32) - 1); | ||
| 187 | return base + mmap_rnd(); | 190 | return base + mmap_rnd(); |
| 188 | } | 191 | } |
| 189 | 192 | ||
