diff options
Diffstat (limited to 'arch/s390/kernel')
28 files changed, 1071 insertions, 384 deletions
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index 9733b3f0eb6d..4da52fe31743 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile | |||
@@ -23,10 +23,11 @@ CFLAGS_sysinfo.o += -Iinclude/math-emu -Iarch/s390/math-emu -w | |||
23 | obj-y := bitmap.o traps.o time.o process.o base.o early.o setup.o vtime.o \ | 23 | obj-y := bitmap.o traps.o time.o process.o base.o early.o setup.o vtime.o \ |
24 | processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o \ | 24 | processor.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o nmi.o \ |
25 | debug.o irq.o ipl.o dis.o diag.o mem_detect.o sclp.o vdso.o \ | 25 | debug.o irq.o ipl.o dis.o diag.o mem_detect.o sclp.o vdso.o \ |
26 | sysinfo.o jump_label.o lgr.o os_info.o | 26 | sysinfo.o jump_label.o lgr.o os_info.o machine_kexec.o |
27 | 27 | ||
28 | obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o) | 28 | obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o) |
29 | obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o) | 29 | obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o) |
30 | obj-y += $(if $(CONFIG_64BIT),relocate_kernel64.o,relocate_kernel.o) | ||
30 | 31 | ||
31 | extra-y += head.o vmlinux.lds | 32 | extra-y += head.o vmlinux.lds |
32 | extra-y += $(if $(CONFIG_64BIT),head64.o,head31.o) | 33 | extra-y += $(if $(CONFIG_64BIT),head64.o,head31.o) |
@@ -48,12 +49,11 @@ obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o | |||
48 | obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o | 49 | obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o |
49 | obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o | 50 | obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o |
50 | obj-$(CONFIG_CRASH_DUMP) += crash_dump.o | 51 | obj-$(CONFIG_CRASH_DUMP) += crash_dump.o |
51 | obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_cpum_cf.o | ||
52 | 52 | ||
53 | # Kexec part | 53 | ifdef CONFIG_64BIT |
54 | S390_KEXEC_OBJS := machine_kexec.o crash.o | 54 | obj-$(CONFIG_PERF_EVENTS) += perf_event.o perf_cpum_cf.o |
55 | S390_KEXEC_OBJS += $(if $(CONFIG_64BIT),relocate_kernel64.o,relocate_kernel.o) | 55 | obj-y += runtime_instr.o cache.o |
56 | obj-$(CONFIG_KEXEC) += $(S390_KEXEC_OBJS) | 56 | endif |
57 | 57 | ||
58 | # vdso | 58 | # vdso |
59 | obj-$(CONFIG_64BIT) += vdso64/ | 59 | obj-$(CONFIG_64BIT) += vdso64/ |
diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index 45ef1a7b08f9..fface87056eb 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c | |||
@@ -157,6 +157,8 @@ int main(void) | |||
157 | DEFINE(__LC_LAST_BREAK, offsetof(struct _lowcore, breaking_event_addr)); | 157 | DEFINE(__LC_LAST_BREAK, offsetof(struct _lowcore, breaking_event_addr)); |
158 | DEFINE(__LC_VDSO_PER_CPU, offsetof(struct _lowcore, vdso_per_cpu_data)); | 158 | DEFINE(__LC_VDSO_PER_CPU, offsetof(struct _lowcore, vdso_per_cpu_data)); |
159 | DEFINE(__LC_GMAP, offsetof(struct _lowcore, gmap)); | 159 | DEFINE(__LC_GMAP, offsetof(struct _lowcore, gmap)); |
160 | DEFINE(__LC_PGM_TDB, offsetof(struct _lowcore, pgm_tdb)); | ||
161 | DEFINE(__THREAD_trap_tdb, offsetof(struct task_struct, thread.trap_tdb)); | ||
160 | DEFINE(__GMAP_ASCE, offsetof(struct gmap, asce)); | 162 | DEFINE(__GMAP_ASCE, offsetof(struct gmap, asce)); |
161 | #endif /* CONFIG_32BIT */ | 163 | #endif /* CONFIG_32BIT */ |
162 | return 0; | 164 | return 0; |
diff --git a/arch/s390/kernel/cache.c b/arch/s390/kernel/cache.c new file mode 100644 index 000000000000..8df8d8a19c98 --- /dev/null +++ b/arch/s390/kernel/cache.c | |||
@@ -0,0 +1,385 @@ | |||
1 | /* | ||
2 | * Extract CPU cache information and expose them via sysfs. | ||
3 | * | ||
4 | * Copyright IBM Corp. 2012 | ||
5 | * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com> | ||
6 | */ | ||
7 | |||
8 | #include <linux/notifier.h> | ||
9 | #include <linux/seq_file.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/list.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/cpu.h> | ||
14 | #include <asm/facility.h> | ||
15 | |||
16 | struct cache { | ||
17 | unsigned long size; | ||
18 | unsigned int line_size; | ||
19 | unsigned int associativity; | ||
20 | unsigned int nr_sets; | ||
21 | unsigned int level : 3; | ||
22 | unsigned int type : 2; | ||
23 | unsigned int private : 1; | ||
24 | struct list_head list; | ||
25 | }; | ||
26 | |||
27 | struct cache_dir { | ||
28 | struct kobject *kobj; | ||
29 | struct cache_index_dir *index; | ||
30 | }; | ||
31 | |||
32 | struct cache_index_dir { | ||
33 | struct kobject kobj; | ||
34 | int cpu; | ||
35 | struct cache *cache; | ||
36 | struct cache_index_dir *next; | ||
37 | }; | ||
38 | |||
39 | enum { | ||
40 | CACHE_SCOPE_NOTEXISTS, | ||
41 | CACHE_SCOPE_PRIVATE, | ||
42 | CACHE_SCOPE_SHARED, | ||
43 | CACHE_SCOPE_RESERVED, | ||
44 | }; | ||
45 | |||
46 | enum { | ||
47 | CACHE_TYPE_SEPARATE, | ||
48 | CACHE_TYPE_DATA, | ||
49 | CACHE_TYPE_INSTRUCTION, | ||
50 | CACHE_TYPE_UNIFIED, | ||
51 | }; | ||
52 | |||
53 | enum { | ||
54 | EXTRACT_TOPOLOGY, | ||
55 | EXTRACT_LINE_SIZE, | ||
56 | EXTRACT_SIZE, | ||
57 | EXTRACT_ASSOCIATIVITY, | ||
58 | }; | ||
59 | |||
60 | enum { | ||
61 | CACHE_TI_UNIFIED = 0, | ||
62 | CACHE_TI_INSTRUCTION = 0, | ||
63 | CACHE_TI_DATA, | ||
64 | }; | ||
65 | |||
66 | struct cache_info { | ||
67 | unsigned char : 4; | ||
68 | unsigned char scope : 2; | ||
69 | unsigned char type : 2; | ||
70 | }; | ||
71 | |||
72 | #define CACHE_MAX_LEVEL 8 | ||
73 | |||
74 | union cache_topology { | ||
75 | struct cache_info ci[CACHE_MAX_LEVEL]; | ||
76 | unsigned long long raw; | ||
77 | }; | ||
78 | |||
79 | static const char * const cache_type_string[] = { | ||
80 | "Data", | ||
81 | "Instruction", | ||
82 | "Unified", | ||
83 | }; | ||
84 | |||
85 | static struct cache_dir *cache_dir_cpu[NR_CPUS]; | ||
86 | static LIST_HEAD(cache_list); | ||
87 | |||
88 | void show_cacheinfo(struct seq_file *m) | ||
89 | { | ||
90 | struct cache *cache; | ||
91 | int index = 0; | ||
92 | |||
93 | list_for_each_entry(cache, &cache_list, list) { | ||
94 | seq_printf(m, "cache%-11d: ", index); | ||
95 | seq_printf(m, "level=%d ", cache->level); | ||
96 | seq_printf(m, "type=%s ", cache_type_string[cache->type]); | ||
97 | seq_printf(m, "scope=%s ", cache->private ? "Private" : "Shared"); | ||
98 | seq_printf(m, "size=%luK ", cache->size >> 10); | ||
99 | seq_printf(m, "line_size=%u ", cache->line_size); | ||
100 | seq_printf(m, "associativity=%d", cache->associativity); | ||
101 | seq_puts(m, "\n"); | ||
102 | index++; | ||
103 | } | ||
104 | } | ||
105 | |||
106 | static inline unsigned long ecag(int ai, int li, int ti) | ||
107 | { | ||
108 | unsigned long cmd, val; | ||
109 | |||
110 | cmd = ai << 4 | li << 1 | ti; | ||
111 | asm volatile(".insn rsy,0xeb000000004c,%0,0,0(%1)" /* ecag */ | ||
112 | : "=d" (val) : "a" (cmd)); | ||
113 | return val; | ||
114 | } | ||
115 | |||
116 | static int __init cache_add(int level, int private, int type) | ||
117 | { | ||
118 | struct cache *cache; | ||
119 | int ti; | ||
120 | |||
121 | cache = kzalloc(sizeof(*cache), GFP_KERNEL); | ||
122 | if (!cache) | ||
123 | return -ENOMEM; | ||
124 | ti = type == CACHE_TYPE_DATA ? CACHE_TI_DATA : CACHE_TI_UNIFIED; | ||
125 | cache->size = ecag(EXTRACT_SIZE, level, ti); | ||
126 | cache->line_size = ecag(EXTRACT_LINE_SIZE, level, ti); | ||
127 | cache->associativity = ecag(EXTRACT_ASSOCIATIVITY, level, ti); | ||
128 | cache->nr_sets = cache->size / cache->associativity; | ||
129 | cache->nr_sets /= cache->line_size; | ||
130 | cache->private = private; | ||
131 | cache->level = level + 1; | ||
132 | cache->type = type - 1; | ||
133 | list_add_tail(&cache->list, &cache_list); | ||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | static void __init cache_build_info(void) | ||
138 | { | ||
139 | struct cache *cache, *next; | ||
140 | union cache_topology ct; | ||
141 | int level, private, rc; | ||
142 | |||
143 | ct.raw = ecag(EXTRACT_TOPOLOGY, 0, 0); | ||
144 | for (level = 0; level < CACHE_MAX_LEVEL; level++) { | ||
145 | switch (ct.ci[level].scope) { | ||
146 | case CACHE_SCOPE_NOTEXISTS: | ||
147 | case CACHE_SCOPE_RESERVED: | ||
148 | return; | ||
149 | case CACHE_SCOPE_SHARED: | ||
150 | private = 0; | ||
151 | break; | ||
152 | case CACHE_SCOPE_PRIVATE: | ||
153 | private = 1; | ||
154 | break; | ||
155 | } | ||
156 | if (ct.ci[level].type == CACHE_TYPE_SEPARATE) { | ||
157 | rc = cache_add(level, private, CACHE_TYPE_DATA); | ||
158 | rc |= cache_add(level, private, CACHE_TYPE_INSTRUCTION); | ||
159 | } else { | ||
160 | rc = cache_add(level, private, ct.ci[level].type); | ||
161 | } | ||
162 | if (rc) | ||
163 | goto error; | ||
164 | } | ||
165 | return; | ||
166 | error: | ||
167 | list_for_each_entry_safe(cache, next, &cache_list, list) { | ||
168 | list_del(&cache->list); | ||
169 | kfree(cache); | ||
170 | } | ||
171 | } | ||
172 | |||
173 | static struct cache_dir *__cpuinit cache_create_cache_dir(int cpu) | ||
174 | { | ||
175 | struct cache_dir *cache_dir; | ||
176 | struct kobject *kobj = NULL; | ||
177 | struct device *dev; | ||
178 | |||
179 | dev = get_cpu_device(cpu); | ||
180 | if (!dev) | ||
181 | goto out; | ||
182 | kobj = kobject_create_and_add("cache", &dev->kobj); | ||
183 | if (!kobj) | ||
184 | goto out; | ||
185 | cache_dir = kzalloc(sizeof(*cache_dir), GFP_KERNEL); | ||
186 | if (!cache_dir) | ||
187 | goto out; | ||
188 | cache_dir->kobj = kobj; | ||
189 | cache_dir_cpu[cpu] = cache_dir; | ||
190 | return cache_dir; | ||
191 | out: | ||
192 | kobject_put(kobj); | ||
193 | return NULL; | ||
194 | } | ||
195 | |||
196 | static struct cache_index_dir *kobj_to_cache_index_dir(struct kobject *kobj) | ||
197 | { | ||
198 | return container_of(kobj, struct cache_index_dir, kobj); | ||
199 | } | ||
200 | |||
201 | static void cache_index_release(struct kobject *kobj) | ||
202 | { | ||
203 | struct cache_index_dir *index; | ||
204 | |||
205 | index = kobj_to_cache_index_dir(kobj); | ||
206 | kfree(index); | ||
207 | } | ||
208 | |||
209 | static ssize_t cache_index_show(struct kobject *kobj, | ||
210 | struct attribute *attr, char *buf) | ||
211 | { | ||
212 | struct kobj_attribute *kobj_attr; | ||
213 | |||
214 | kobj_attr = container_of(attr, struct kobj_attribute, attr); | ||
215 | return kobj_attr->show(kobj, kobj_attr, buf); | ||
216 | } | ||
217 | |||
218 | #define DEFINE_CACHE_ATTR(_name, _format, _value) \ | ||
219 | static ssize_t cache_##_name##_show(struct kobject *kobj, \ | ||
220 | struct kobj_attribute *attr, \ | ||
221 | char *buf) \ | ||
222 | { \ | ||
223 | struct cache_index_dir *index; \ | ||
224 | \ | ||
225 | index = kobj_to_cache_index_dir(kobj); \ | ||
226 | return sprintf(buf, _format, _value); \ | ||
227 | } \ | ||
228 | static struct kobj_attribute cache_##_name##_attr = \ | ||
229 | __ATTR(_name, 0444, cache_##_name##_show, NULL); | ||
230 | |||
231 | DEFINE_CACHE_ATTR(size, "%luK\n", index->cache->size >> 10); | ||
232 | DEFINE_CACHE_ATTR(coherency_line_size, "%u\n", index->cache->line_size); | ||
233 | DEFINE_CACHE_ATTR(number_of_sets, "%u\n", index->cache->nr_sets); | ||
234 | DEFINE_CACHE_ATTR(ways_of_associativity, "%u\n", index->cache->associativity); | ||
235 | DEFINE_CACHE_ATTR(type, "%s\n", cache_type_string[index->cache->type]); | ||
236 | DEFINE_CACHE_ATTR(level, "%d\n", index->cache->level); | ||
237 | |||
238 | static ssize_t shared_cpu_map_func(struct kobject *kobj, int type, char *buf) | ||
239 | { | ||
240 | struct cache_index_dir *index; | ||
241 | int len; | ||
242 | |||
243 | index = kobj_to_cache_index_dir(kobj); | ||
244 | len = type ? | ||
245 | cpulist_scnprintf(buf, PAGE_SIZE - 2, cpumask_of(index->cpu)) : | ||
246 | cpumask_scnprintf(buf, PAGE_SIZE - 2, cpumask_of(index->cpu)); | ||
247 | len += sprintf(&buf[len], "\n"); | ||
248 | return len; | ||
249 | } | ||
250 | |||
251 | static ssize_t shared_cpu_map_show(struct kobject *kobj, | ||
252 | struct kobj_attribute *attr, char *buf) | ||
253 | { | ||
254 | return shared_cpu_map_func(kobj, 0, buf); | ||
255 | } | ||
256 | static struct kobj_attribute cache_shared_cpu_map_attr = | ||
257 | __ATTR(shared_cpu_map, 0444, shared_cpu_map_show, NULL); | ||
258 | |||
259 | static ssize_t shared_cpu_list_show(struct kobject *kobj, | ||
260 | struct kobj_attribute *attr, char *buf) | ||
261 | { | ||
262 | return shared_cpu_map_func(kobj, 1, buf); | ||
263 | } | ||
264 | static struct kobj_attribute cache_shared_cpu_list_attr = | ||
265 | __ATTR(shared_cpu_list, 0444, shared_cpu_list_show, NULL); | ||
266 | |||
267 | static struct attribute *cache_index_default_attrs[] = { | ||
268 | &cache_type_attr.attr, | ||
269 | &cache_size_attr.attr, | ||
270 | &cache_number_of_sets_attr.attr, | ||
271 | &cache_ways_of_associativity_attr.attr, | ||
272 | &cache_level_attr.attr, | ||
273 | &cache_coherency_line_size_attr.attr, | ||
274 | &cache_shared_cpu_map_attr.attr, | ||
275 | &cache_shared_cpu_list_attr.attr, | ||
276 | NULL, | ||
277 | }; | ||
278 | |||
279 | static const struct sysfs_ops cache_index_ops = { | ||
280 | .show = cache_index_show, | ||
281 | }; | ||
282 | |||
283 | static struct kobj_type cache_index_type = { | ||
284 | .sysfs_ops = &cache_index_ops, | ||
285 | .release = cache_index_release, | ||
286 | .default_attrs = cache_index_default_attrs, | ||
287 | }; | ||
288 | |||
289 | static int __cpuinit cache_create_index_dir(struct cache_dir *cache_dir, | ||
290 | struct cache *cache, int index, | ||
291 | int cpu) | ||
292 | { | ||
293 | struct cache_index_dir *index_dir; | ||
294 | int rc; | ||
295 | |||
296 | index_dir = kzalloc(sizeof(*index_dir), GFP_KERNEL); | ||
297 | if (!index_dir) | ||
298 | return -ENOMEM; | ||
299 | index_dir->cache = cache; | ||
300 | index_dir->cpu = cpu; | ||
301 | rc = kobject_init_and_add(&index_dir->kobj, &cache_index_type, | ||
302 | cache_dir->kobj, "index%d", index); | ||
303 | if (rc) | ||
304 | goto out; | ||
305 | index_dir->next = cache_dir->index; | ||
306 | cache_dir->index = index_dir; | ||
307 | return 0; | ||
308 | out: | ||
309 | kfree(index_dir); | ||
310 | return rc; | ||
311 | } | ||
312 | |||
313 | static int __cpuinit cache_add_cpu(int cpu) | ||
314 | { | ||
315 | struct cache_dir *cache_dir; | ||
316 | struct cache *cache; | ||
317 | int rc, index = 0; | ||
318 | |||
319 | if (list_empty(&cache_list)) | ||
320 | return 0; | ||
321 | cache_dir = cache_create_cache_dir(cpu); | ||
322 | if (!cache_dir) | ||
323 | return -ENOMEM; | ||
324 | list_for_each_entry(cache, &cache_list, list) { | ||
325 | if (!cache->private) | ||
326 | break; | ||
327 | rc = cache_create_index_dir(cache_dir, cache, index, cpu); | ||
328 | if (rc) | ||
329 | return rc; | ||
330 | index++; | ||
331 | } | ||
332 | return 0; | ||
333 | } | ||
334 | |||
335 | static void __cpuinit cache_remove_cpu(int cpu) | ||
336 | { | ||
337 | struct cache_index_dir *index, *next; | ||
338 | struct cache_dir *cache_dir; | ||
339 | |||
340 | cache_dir = cache_dir_cpu[cpu]; | ||
341 | if (!cache_dir) | ||
342 | return; | ||
343 | index = cache_dir->index; | ||
344 | while (index) { | ||
345 | next = index->next; | ||
346 | kobject_put(&index->kobj); | ||
347 | index = next; | ||
348 | } | ||
349 | kobject_put(cache_dir->kobj); | ||
350 | kfree(cache_dir); | ||
351 | cache_dir_cpu[cpu] = NULL; | ||
352 | } | ||
353 | |||
354 | static int __cpuinit cache_hotplug(struct notifier_block *nfb, | ||
355 | unsigned long action, void *hcpu) | ||
356 | { | ||
357 | int cpu = (long)hcpu; | ||
358 | int rc = 0; | ||
359 | |||
360 | switch (action & ~CPU_TASKS_FROZEN) { | ||
361 | case CPU_ONLINE: | ||
362 | rc = cache_add_cpu(cpu); | ||
363 | if (rc) | ||
364 | cache_remove_cpu(cpu); | ||
365 | break; | ||
366 | case CPU_DEAD: | ||
367 | cache_remove_cpu(cpu); | ||
368 | break; | ||
369 | } | ||
370 | return rc ? NOTIFY_BAD : NOTIFY_OK; | ||
371 | } | ||
372 | |||
373 | static int __init cache_init(void) | ||
374 | { | ||
375 | int cpu; | ||
376 | |||
377 | if (!test_facility(34)) | ||
378 | return 0; | ||
379 | cache_build_info(); | ||
380 | for_each_online_cpu(cpu) | ||
381 | cache_add_cpu(cpu); | ||
382 | hotcpu_notifier(cache_hotplug, 0); | ||
383 | return 0; | ||
384 | } | ||
385 | device_initcall(cache_init); | ||
diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c index f606d935f495..189963c90c6e 100644 --- a/arch/s390/kernel/compat_linux.c +++ b/arch/s390/kernel/compat_linux.c | |||
@@ -131,13 +131,19 @@ asmlinkage long sys32_setresuid16(u16 ruid, u16 euid, u16 suid) | |||
131 | low2highuid(suid)); | 131 | low2highuid(suid)); |
132 | } | 132 | } |
133 | 133 | ||
134 | asmlinkage long sys32_getresuid16(u16 __user *ruid, u16 __user *euid, u16 __user *suid) | 134 | asmlinkage long sys32_getresuid16(u16 __user *ruidp, u16 __user *euidp, u16 __user *suidp) |
135 | { | 135 | { |
136 | const struct cred *cred = current_cred(); | ||
136 | int retval; | 137 | int retval; |
138 | u16 ruid, euid, suid; | ||
137 | 139 | ||
138 | if (!(retval = put_user(high2lowuid(current->cred->uid), ruid)) && | 140 | ruid = high2lowuid(from_kuid_munged(cred->user_ns, cred->uid)); |
139 | !(retval = put_user(high2lowuid(current->cred->euid), euid))) | 141 | euid = high2lowuid(from_kuid_munged(cred->user_ns, cred->euid)); |
140 | retval = put_user(high2lowuid(current->cred->suid), suid); | 142 | suid = high2lowuid(from_kuid_munged(cred->user_ns, cred->suid)); |
143 | |||
144 | if (!(retval = put_user(ruid, ruidp)) && | ||
145 | !(retval = put_user(euid, euidp))) | ||
146 | retval = put_user(suid, suidp); | ||
141 | 147 | ||
142 | return retval; | 148 | return retval; |
143 | } | 149 | } |
@@ -148,13 +154,19 @@ asmlinkage long sys32_setresgid16(u16 rgid, u16 egid, u16 sgid) | |||
148 | low2highgid(sgid)); | 154 | low2highgid(sgid)); |
149 | } | 155 | } |
150 | 156 | ||
151 | asmlinkage long sys32_getresgid16(u16 __user *rgid, u16 __user *egid, u16 __user *sgid) | 157 | asmlinkage long sys32_getresgid16(u16 __user *rgidp, u16 __user *egidp, u16 __user *sgidp) |
152 | { | 158 | { |
159 | const struct cred *cred = current_cred(); | ||
153 | int retval; | 160 | int retval; |
161 | u16 rgid, egid, sgid; | ||
162 | |||
163 | rgid = high2lowgid(from_kgid_munged(cred->user_ns, cred->gid)); | ||
164 | egid = high2lowgid(from_kgid_munged(cred->user_ns, cred->egid)); | ||
165 | sgid = high2lowgid(from_kgid_munged(cred->user_ns, cred->sgid)); | ||
154 | 166 | ||
155 | if (!(retval = put_user(high2lowgid(current->cred->gid), rgid)) && | 167 | if (!(retval = put_user(rgid, rgidp)) && |
156 | !(retval = put_user(high2lowgid(current->cred->egid), egid))) | 168 | !(retval = put_user(egid, egidp))) |
157 | retval = put_user(high2lowgid(current->cred->sgid), sgid); | 169 | retval = put_user(sgid, sgidp); |
158 | 170 | ||
159 | return retval; | 171 | return retval; |
160 | } | 172 | } |
@@ -258,22 +270,22 @@ asmlinkage long sys32_setgroups16(int gidsetsize, u16 __user *grouplist) | |||
258 | 270 | ||
259 | asmlinkage long sys32_getuid16(void) | 271 | asmlinkage long sys32_getuid16(void) |
260 | { | 272 | { |
261 | return high2lowuid(current->cred->uid); | 273 | return high2lowuid(from_kuid_munged(current_user_ns(), current_uid())); |
262 | } | 274 | } |
263 | 275 | ||
264 | asmlinkage long sys32_geteuid16(void) | 276 | asmlinkage long sys32_geteuid16(void) |
265 | { | 277 | { |
266 | return high2lowuid(current->cred->euid); | 278 | return high2lowuid(from_kuid_munged(current_user_ns(), current_euid())); |
267 | } | 279 | } |
268 | 280 | ||
269 | asmlinkage long sys32_getgid16(void) | 281 | asmlinkage long sys32_getgid16(void) |
270 | { | 282 | { |
271 | return high2lowgid(current->cred->gid); | 283 | return high2lowgid(from_kgid_munged(current_user_ns(), current_gid())); |
272 | } | 284 | } |
273 | 285 | ||
274 | asmlinkage long sys32_getegid16(void) | 286 | asmlinkage long sys32_getegid16(void) |
275 | { | 287 | { |
276 | return high2lowgid(current->cred->egid); | 288 | return high2lowgid(from_kgid_munged(current_user_ns(), current_egid())); |
277 | } | 289 | } |
278 | 290 | ||
279 | /* | 291 | /* |
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S index 2d82cfcbce5b..3afba804fe97 100644 --- a/arch/s390/kernel/compat_wrapper.S +++ b/arch/s390/kernel/compat_wrapper.S | |||
@@ -1646,3 +1646,16 @@ ENTRY(compat_sys_process_vm_writev_wrapper) | |||
1646 | llgf %r0,164(%r15) # unsigned long | 1646 | llgf %r0,164(%r15) # unsigned long |
1647 | stg %r0,160(%r15) | 1647 | stg %r0,160(%r15) |
1648 | jg compat_sys_process_vm_writev | 1648 | jg compat_sys_process_vm_writev |
1649 | |||
1650 | ENTRY(sys_s390_runtime_instr_wrapper) | ||
1651 | lgfr %r2,%r2 # int | ||
1652 | lgfr %r3,%r3 # int | ||
1653 | jg sys_s390_runtime_instr | ||
1654 | |||
1655 | ENTRY(sys_kcmp_wrapper) | ||
1656 | lgfr %r2,%r2 # pid_t | ||
1657 | lgfr %r3,%r3 # pid_t | ||
1658 | lgfr %r4,%r4 # int | ||
1659 | llgfr %r5,%r5 # unsigned long | ||
1660 | llgfr %r6,%r6 # unsigned long | ||
1661 | jg sys_kcmp | ||
diff --git a/arch/s390/kernel/crash.c b/arch/s390/kernel/crash.c deleted file mode 100644 index 3819153de8bd..000000000000 --- a/arch/s390/kernel/crash.c +++ /dev/null | |||
@@ -1,14 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright IBM Corp. 2005 | ||
3 | * | ||
4 | * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com> | ||
5 | * | ||
6 | */ | ||
7 | |||
8 | #include <linux/threads.h> | ||
9 | #include <linux/kexec.h> | ||
10 | #include <linux/reboot.h> | ||
11 | |||
12 | void machine_crash_shutdown(struct pt_regs *regs) | ||
13 | { | ||
14 | } | ||
diff --git a/arch/s390/kernel/crash_dump.c b/arch/s390/kernel/crash_dump.c index cc1172b26873..fb8d8781a011 100644 --- a/arch/s390/kernel/crash_dump.c +++ b/arch/s390/kernel/crash_dump.c | |||
@@ -13,8 +13,9 @@ | |||
13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
14 | #include <linux/bootmem.h> | 14 | #include <linux/bootmem.h> |
15 | #include <linux/elf.h> | 15 | #include <linux/elf.h> |
16 | #include <asm/ipl.h> | ||
17 | #include <asm/os_info.h> | 16 | #include <asm/os_info.h> |
17 | #include <asm/elf.h> | ||
18 | #include <asm/ipl.h> | ||
18 | 19 | ||
19 | #define PTR_ADD(x, y) (((char *) (x)) + ((unsigned long) (y))) | 20 | #define PTR_ADD(x, y) (((char *) (x)) + ((unsigned long) (y))) |
20 | #define PTR_SUB(x, y) (((char *) (x)) - ((unsigned long) (y))) | 21 | #define PTR_SUB(x, y) (((char *) (x)) - ((unsigned long) (y))) |
diff --git a/arch/s390/kernel/dis.c b/arch/s390/kernel/dis.c index 619c5d350726..cc84a24c023f 100644 --- a/arch/s390/kernel/dis.c +++ b/arch/s390/kernel/dis.c | |||
@@ -315,6 +315,11 @@ enum { | |||
315 | LONG_INSN_POPCNT, | 315 | LONG_INSN_POPCNT, |
316 | LONG_INSN_RISBHG, | 316 | LONG_INSN_RISBHG, |
317 | LONG_INSN_RISBLG, | 317 | LONG_INSN_RISBLG, |
318 | LONG_INSN_RINEXT, | ||
319 | LONG_INSN_RIEMIT, | ||
320 | LONG_INSN_TABORT, | ||
321 | LONG_INSN_TBEGIN, | ||
322 | LONG_INSN_TBEGINC, | ||
318 | }; | 323 | }; |
319 | 324 | ||
320 | static char *long_insn_name[] = { | 325 | static char *long_insn_name[] = { |
@@ -329,7 +334,12 @@ static char *long_insn_name[] = { | |||
329 | [LONG_INSN_LLGHRL] = "llghrl", | 334 | [LONG_INSN_LLGHRL] = "llghrl", |
330 | [LONG_INSN_POPCNT] = "popcnt", | 335 | [LONG_INSN_POPCNT] = "popcnt", |
331 | [LONG_INSN_RISBHG] = "risbhg", | 336 | [LONG_INSN_RISBHG] = "risbhg", |
332 | [LONG_INSN_RISBLG] = "risblk", | 337 | [LONG_INSN_RISBLG] = "risblg", |
338 | [LONG_INSN_RINEXT] = "rinext", | ||
339 | [LONG_INSN_RIEMIT] = "riemit", | ||
340 | [LONG_INSN_TABORT] = "tabort", | ||
341 | [LONG_INSN_TBEGIN] = "tbegin", | ||
342 | [LONG_INSN_TBEGINC] = "tbeginc", | ||
333 | }; | 343 | }; |
334 | 344 | ||
335 | static struct insn opcode[] = { | 345 | static struct insn opcode[] = { |
@@ -582,6 +592,17 @@ static struct insn opcode_a7[] = { | |||
582 | { "", 0, INSTR_INVALID } | 592 | { "", 0, INSTR_INVALID } |
583 | }; | 593 | }; |
584 | 594 | ||
595 | static struct insn opcode_aa[] = { | ||
596 | #ifdef CONFIG_64BIT | ||
597 | { { 0, LONG_INSN_RINEXT }, 0x00, INSTR_RI_RI }, | ||
598 | { "rion", 0x01, INSTR_RI_RI }, | ||
599 | { "tric", 0x02, INSTR_RI_RI }, | ||
600 | { "rioff", 0x03, INSTR_RI_RI }, | ||
601 | { { 0, LONG_INSN_RIEMIT }, 0x04, INSTR_RI_RI }, | ||
602 | #endif | ||
603 | { "", 0, INSTR_INVALID } | ||
604 | }; | ||
605 | |||
585 | static struct insn opcode_b2[] = { | 606 | static struct insn opcode_b2[] = { |
586 | #ifdef CONFIG_64BIT | 607 | #ifdef CONFIG_64BIT |
587 | { "sske", 0x2b, INSTR_RRF_M0RR }, | 608 | { "sske", 0x2b, INSTR_RRF_M0RR }, |
@@ -594,6 +615,9 @@ static struct insn opcode_b2[] = { | |||
594 | { "lpswe", 0xb2, INSTR_S_RD }, | 615 | { "lpswe", 0xb2, INSTR_S_RD }, |
595 | { "srnmt", 0xb9, INSTR_S_RD }, | 616 | { "srnmt", 0xb9, INSTR_S_RD }, |
596 | { "lfas", 0xbd, INSTR_S_RD }, | 617 | { "lfas", 0xbd, INSTR_S_RD }, |
618 | { "etndg", 0xec, INSTR_RRE_R0 }, | ||
619 | { { 0, LONG_INSN_TABORT }, 0xfc, INSTR_S_RD }, | ||
620 | { "tend", 0xf8, INSTR_S_RD }, | ||
597 | #endif | 621 | #endif |
598 | { "stidp", 0x02, INSTR_S_RD }, | 622 | { "stidp", 0x02, INSTR_S_RD }, |
599 | { "sck", 0x04, INSTR_S_RD }, | 623 | { "sck", 0x04, INSTR_S_RD }, |
@@ -1150,6 +1174,7 @@ static struct insn opcode_e3[] = { | |||
1150 | { "stfh", 0xcb, INSTR_RXY_RRRD }, | 1174 | { "stfh", 0xcb, INSTR_RXY_RRRD }, |
1151 | { "chf", 0xcd, INSTR_RXY_RRRD }, | 1175 | { "chf", 0xcd, INSTR_RXY_RRRD }, |
1152 | { "clhf", 0xcf, INSTR_RXY_RRRD }, | 1176 | { "clhf", 0xcf, INSTR_RXY_RRRD }, |
1177 | { "ntstg", 0x25, INSTR_RXY_RRRD }, | ||
1153 | #endif | 1178 | #endif |
1154 | { "lrv", 0x1e, INSTR_RXY_RRRD }, | 1179 | { "lrv", 0x1e, INSTR_RXY_RRRD }, |
1155 | { "lrvh", 0x1f, INSTR_RXY_RRRD }, | 1180 | { "lrvh", 0x1f, INSTR_RXY_RRRD }, |
@@ -1173,6 +1198,8 @@ static struct insn opcode_e5[] = { | |||
1173 | { "mvhhi", 0x44, INSTR_SIL_RDI }, | 1198 | { "mvhhi", 0x44, INSTR_SIL_RDI }, |
1174 | { "mvhi", 0x4c, INSTR_SIL_RDI }, | 1199 | { "mvhi", 0x4c, INSTR_SIL_RDI }, |
1175 | { "mvghi", 0x48, INSTR_SIL_RDI }, | 1200 | { "mvghi", 0x48, INSTR_SIL_RDI }, |
1201 | { { 0, LONG_INSN_TBEGIN }, 0x60, INSTR_SIL_RDU }, | ||
1202 | { { 0, LONG_INSN_TBEGINC }, 0x61, INSTR_SIL_RDU }, | ||
1176 | #endif | 1203 | #endif |
1177 | { "lasp", 0x00, INSTR_SSE_RDRD }, | 1204 | { "lasp", 0x00, INSTR_SSE_RDRD }, |
1178 | { "tprot", 0x01, INSTR_SSE_RDRD }, | 1205 | { "tprot", 0x01, INSTR_SSE_RDRD }, |
@@ -1210,6 +1237,9 @@ static struct insn opcode_eb[] = { | |||
1210 | { "cliy", 0x55, INSTR_SIY_URD }, | 1237 | { "cliy", 0x55, INSTR_SIY_URD }, |
1211 | { "oiy", 0x56, INSTR_SIY_URD }, | 1238 | { "oiy", 0x56, INSTR_SIY_URD }, |
1212 | { "xiy", 0x57, INSTR_SIY_URD }, | 1239 | { "xiy", 0x57, INSTR_SIY_URD }, |
1240 | { "lric", 0x60, INSTR_RSY_RDRM }, | ||
1241 | { "stric", 0x61, INSTR_RSY_RDRM }, | ||
1242 | { "mric", 0x62, INSTR_RSY_RDRM }, | ||
1213 | { "icmh", 0x80, INSTR_RSE_RURD }, | 1243 | { "icmh", 0x80, INSTR_RSE_RURD }, |
1214 | { "icmh", 0x80, INSTR_RSY_RURD }, | 1244 | { "icmh", 0x80, INSTR_RSY_RURD }, |
1215 | { "icmy", 0x81, INSTR_RSY_RURD }, | 1245 | { "icmy", 0x81, INSTR_RSY_RURD }, |
@@ -1408,6 +1438,9 @@ static struct insn *find_insn(unsigned char *code) | |||
1408 | case 0xa7: | 1438 | case 0xa7: |
1409 | table = opcode_a7; | 1439 | table = opcode_a7; |
1410 | break; | 1440 | break; |
1441 | case 0xaa: | ||
1442 | table = opcode_aa; | ||
1443 | break; | ||
1411 | case 0xb2: | 1444 | case 0xb2: |
1412 | table = opcode_b2; | 1445 | table = opcode_b2; |
1413 | break; | 1446 | break; |
@@ -1601,3 +1634,26 @@ void show_code(struct pt_regs *regs) | |||
1601 | } | 1634 | } |
1602 | printk("\n"); | 1635 | printk("\n"); |
1603 | } | 1636 | } |
1637 | |||
1638 | void print_fn_code(unsigned char *code, unsigned long len) | ||
1639 | { | ||
1640 | char buffer[64], *ptr; | ||
1641 | int opsize, i; | ||
1642 | |||
1643 | while (len) { | ||
1644 | ptr = buffer; | ||
1645 | opsize = insn_length(*code); | ||
1646 | ptr += sprintf(ptr, "%p: ", code); | ||
1647 | for (i = 0; i < opsize; i++) | ||
1648 | ptr += sprintf(ptr, "%02x", code[i]); | ||
1649 | *ptr++ = '\t'; | ||
1650 | if (i < 4) | ||
1651 | *ptr++ = '\t'; | ||
1652 | ptr += print_insn(ptr, code, (unsigned long) code); | ||
1653 | *ptr++ = '\n'; | ||
1654 | *ptr++ = 0; | ||
1655 | printk(buffer); | ||
1656 | code += opsize; | ||
1657 | len -= opsize; | ||
1658 | } | ||
1659 | } | ||
diff --git a/arch/s390/kernel/early.c b/arch/s390/kernel/early.c index 83c3271c442b..7f4717675c19 100644 --- a/arch/s390/kernel/early.c +++ b/arch/s390/kernel/early.c | |||
@@ -215,36 +215,54 @@ static noinline __init void init_kernel_storage_key(void) | |||
215 | PAGE_DEFAULT_KEY, 0); | 215 | PAGE_DEFAULT_KEY, 0); |
216 | } | 216 | } |
217 | 217 | ||
218 | static __initdata struct sysinfo_3_2_2 vmms __aligned(PAGE_SIZE); | 218 | static __initdata char sysinfo_page[PAGE_SIZE] __aligned(PAGE_SIZE); |
219 | 219 | ||
220 | static noinline __init void detect_machine_type(void) | 220 | static noinline __init void detect_machine_type(void) |
221 | { | 221 | { |
222 | struct sysinfo_3_2_2 *vmms = (struct sysinfo_3_2_2 *)&sysinfo_page; | ||
223 | |||
222 | /* Check current-configuration-level */ | 224 | /* Check current-configuration-level */ |
223 | if ((stsi(NULL, 0, 0, 0) >> 28) <= 2) { | 225 | if (stsi(NULL, 0, 0, 0) <= 2) { |
224 | S390_lowcore.machine_flags |= MACHINE_FLAG_LPAR; | 226 | S390_lowcore.machine_flags |= MACHINE_FLAG_LPAR; |
225 | return; | 227 | return; |
226 | } | 228 | } |
227 | /* Get virtual-machine cpu information. */ | 229 | /* Get virtual-machine cpu information. */ |
228 | if (stsi(&vmms, 3, 2, 2) == -ENOSYS || !vmms.count) | 230 | if (stsi(vmms, 3, 2, 2) || !vmms->count) |
229 | return; | 231 | return; |
230 | 232 | ||
231 | /* Running under KVM? If not we assume z/VM */ | 233 | /* Running under KVM? If not we assume z/VM */ |
232 | if (!memcmp(vmms.vm[0].cpi, "\xd2\xe5\xd4", 3)) | 234 | if (!memcmp(vmms->vm[0].cpi, "\xd2\xe5\xd4", 3)) |
233 | S390_lowcore.machine_flags |= MACHINE_FLAG_KVM; | 235 | S390_lowcore.machine_flags |= MACHINE_FLAG_KVM; |
234 | else | 236 | else |
235 | S390_lowcore.machine_flags |= MACHINE_FLAG_VM; | 237 | S390_lowcore.machine_flags |= MACHINE_FLAG_VM; |
236 | } | 238 | } |
237 | 239 | ||
240 | static __init void setup_topology(void) | ||
241 | { | ||
242 | #ifdef CONFIG_64BIT | ||
243 | int max_mnest; | ||
244 | |||
245 | if (!test_facility(11)) | ||
246 | return; | ||
247 | S390_lowcore.machine_flags |= MACHINE_FLAG_TOPOLOGY; | ||
248 | for (max_mnest = 6; max_mnest > 1; max_mnest--) { | ||
249 | if (stsi(&sysinfo_page, 15, 1, max_mnest) == 0) | ||
250 | break; | ||
251 | } | ||
252 | topology_max_mnest = max_mnest; | ||
253 | #endif | ||
254 | } | ||
255 | |||
238 | static void early_pgm_check_handler(void) | 256 | static void early_pgm_check_handler(void) |
239 | { | 257 | { |
240 | unsigned long addr; | ||
241 | const struct exception_table_entry *fixup; | 258 | const struct exception_table_entry *fixup; |
259 | unsigned long addr; | ||
242 | 260 | ||
243 | addr = S390_lowcore.program_old_psw.addr; | 261 | addr = S390_lowcore.program_old_psw.addr; |
244 | fixup = search_exception_tables(addr & PSW_ADDR_INSN); | 262 | fixup = search_exception_tables(addr & PSW_ADDR_INSN); |
245 | if (!fixup) | 263 | if (!fixup) |
246 | disabled_wait(0); | 264 | disabled_wait(0); |
247 | S390_lowcore.program_old_psw.addr = fixup->fixup | PSW_ADDR_AMODE; | 265 | S390_lowcore.program_old_psw.addr = extable_fixup(fixup)|PSW_ADDR_AMODE; |
248 | } | 266 | } |
249 | 267 | ||
250 | static noinline __init void setup_lowcore_early(void) | 268 | static noinline __init void setup_lowcore_early(void) |
@@ -267,12 +285,10 @@ static noinline __init void setup_facility_list(void) | |||
267 | 285 | ||
268 | static noinline __init void setup_hpage(void) | 286 | static noinline __init void setup_hpage(void) |
269 | { | 287 | { |
270 | #ifndef CONFIG_DEBUG_PAGEALLOC | ||
271 | if (!test_facility(2) || !test_facility(8)) | 288 | if (!test_facility(2) || !test_facility(8)) |
272 | return; | 289 | return; |
273 | S390_lowcore.machine_flags |= MACHINE_FLAG_HPAGE; | 290 | S390_lowcore.machine_flags |= MACHINE_FLAG_HPAGE; |
274 | __ctl_set_bit(0, 23); | 291 | __ctl_set_bit(0, 23); |
275 | #endif | ||
276 | } | 292 | } |
277 | 293 | ||
278 | static __init void detect_mvpg(void) | 294 | static __init void detect_mvpg(void) |
@@ -366,12 +382,12 @@ static __init void detect_machine_facilities(void) | |||
366 | S390_lowcore.machine_flags |= MACHINE_FLAG_IDTE; | 382 | S390_lowcore.machine_flags |= MACHINE_FLAG_IDTE; |
367 | if (test_facility(8)) | 383 | if (test_facility(8)) |
368 | S390_lowcore.machine_flags |= MACHINE_FLAG_PFMF; | 384 | S390_lowcore.machine_flags |= MACHINE_FLAG_PFMF; |
369 | if (test_facility(11)) | ||
370 | S390_lowcore.machine_flags |= MACHINE_FLAG_TOPOLOGY; | ||
371 | if (test_facility(27)) | 385 | if (test_facility(27)) |
372 | S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS; | 386 | S390_lowcore.machine_flags |= MACHINE_FLAG_MVCOS; |
373 | if (test_facility(40)) | 387 | if (test_facility(40)) |
374 | S390_lowcore.machine_flags |= MACHINE_FLAG_SPP; | 388 | S390_lowcore.machine_flags |= MACHINE_FLAG_SPP; |
389 | if (test_facility(50) && test_facility(73)) | ||
390 | S390_lowcore.machine_flags |= MACHINE_FLAG_TE; | ||
375 | #endif | 391 | #endif |
376 | } | 392 | } |
377 | 393 | ||
@@ -441,7 +457,6 @@ static void __init setup_boot_command_line(void) | |||
441 | append_to_cmdline(append_ipl_scpdata); | 457 | append_to_cmdline(append_ipl_scpdata); |
442 | } | 458 | } |
443 | 459 | ||
444 | |||
445 | /* | 460 | /* |
446 | * Save ipl parameters, clear bss memory, initialize storage keys | 461 | * Save ipl parameters, clear bss memory, initialize storage keys |
447 | * and create a kernel NSS at startup if the SAVESYS= parm is defined | 462 | * and create a kernel NSS at startup if the SAVESYS= parm is defined |
@@ -468,6 +483,7 @@ void __init startup_init(void) | |||
468 | detect_diag44(); | 483 | detect_diag44(); |
469 | detect_machine_facilities(); | 484 | detect_machine_facilities(); |
470 | setup_hpage(); | 485 | setup_hpage(); |
486 | setup_topology(); | ||
471 | sclp_facilities_detect(); | 487 | sclp_facilities_detect(); |
472 | detect_memory_layout(memory_chunk); | 488 | detect_memory_layout(memory_chunk); |
473 | #ifdef CONFIG_DYNAMIC_FTRACE | 489 | #ifdef CONFIG_DYNAMIC_FTRACE |
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 349b7eeb348a..7549985402f7 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S | |||
@@ -10,6 +10,7 @@ | |||
10 | 10 | ||
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <linux/linkage.h> | 12 | #include <linux/linkage.h> |
13 | #include <asm/processor.h> | ||
13 | #include <asm/cache.h> | 14 | #include <asm/cache.h> |
14 | #include <asm/errno.h> | 15 | #include <asm/errno.h> |
15 | #include <asm/ptrace.h> | 16 | #include <asm/ptrace.h> |
@@ -412,6 +413,11 @@ ENTRY(pgm_check_handler) | |||
412 | 1: UPDATE_VTIME %r14,__LC_SYNC_ENTER_TIMER | 413 | 1: UPDATE_VTIME %r14,__LC_SYNC_ENTER_TIMER |
413 | LAST_BREAK %r14 | 414 | LAST_BREAK %r14 |
414 | lg %r15,__LC_KERNEL_STACK | 415 | lg %r15,__LC_KERNEL_STACK |
416 | lg %r14,__TI_task(%r12) | ||
417 | lghi %r13,__LC_PGM_TDB | ||
418 | tm __LC_PGM_ILC+2,0x02 # check for transaction abort | ||
419 | jz 2f | ||
420 | mvc __THREAD_trap_tdb(256,%r14),0(%r13) | ||
415 | 2: aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) | 421 | 2: aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) |
416 | la %r11,STACK_FRAME_OVERHEAD(%r15) | 422 | la %r11,STACK_FRAME_OVERHEAD(%r15) |
417 | stmg %r0,%r7,__PT_R0(%r11) | 423 | stmg %r0,%r7,__PT_R0(%r11) |
@@ -422,13 +428,12 @@ ENTRY(pgm_check_handler) | |||
422 | stg %r10,__PT_ARGS(%r11) | 428 | stg %r10,__PT_ARGS(%r11) |
423 | tm __LC_PGM_ILC+3,0x80 # check for per exception | 429 | tm __LC_PGM_ILC+3,0x80 # check for per exception |
424 | jz 0f | 430 | jz 0f |
425 | lg %r1,__TI_task(%r12) | ||
426 | tmhh %r8,0x0001 # kernel per event ? | 431 | tmhh %r8,0x0001 # kernel per event ? |
427 | jz pgm_kprobe | 432 | jz pgm_kprobe |
428 | oi __TI_flags+7(%r12),_TIF_PER_TRAP | 433 | oi __TI_flags+7(%r12),_TIF_PER_TRAP |
429 | mvc __THREAD_per_address(8,%r1),__LC_PER_ADDRESS | 434 | mvc __THREAD_per_address(8,%r14),__LC_PER_ADDRESS |
430 | mvc __THREAD_per_cause(2,%r1),__LC_PER_CAUSE | 435 | mvc __THREAD_per_cause(2,%r14),__LC_PER_CAUSE |
431 | mvc __THREAD_per_paid(1,%r1),__LC_PER_PAID | 436 | mvc __THREAD_per_paid(1,%r14),__LC_PER_PAID |
432 | 0: REENABLE_IRQS | 437 | 0: REENABLE_IRQS |
433 | xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) | 438 | xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) |
434 | larl %r1,pgm_check_table | 439 | larl %r1,pgm_check_table |
@@ -1004,9 +1009,7 @@ sie_fault: | |||
1004 | .Lhost_id: | 1009 | .Lhost_id: |
1005 | .quad 0 | 1010 | .quad 0 |
1006 | 1011 | ||
1007 | .section __ex_table,"a" | 1012 | EX_TABLE(sie_loop,sie_fault) |
1008 | .quad sie_loop,sie_fault | ||
1009 | .previous | ||
1010 | #endif | 1013 | #endif |
1011 | 1014 | ||
1012 | .section .rodata, "a" | 1015 | .section .rodata, "a" |
diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c index dd7630d8aab7..6cdc55b26d68 100644 --- a/arch/s390/kernel/irq.c +++ b/arch/s390/kernel/irq.c | |||
@@ -30,33 +30,35 @@ struct irq_class { | |||
30 | }; | 30 | }; |
31 | 31 | ||
32 | static const struct irq_class intrclass_names[] = { | 32 | static const struct irq_class intrclass_names[] = { |
33 | {.name = "EXT" }, | 33 | [EXTERNAL_INTERRUPT] = {.name = "EXT"}, |
34 | {.name = "I/O" }, | 34 | [IO_INTERRUPT] = {.name = "I/O"}, |
35 | {.name = "CLK", .desc = "[EXT] Clock Comparator" }, | 35 | [EXTINT_CLK] = {.name = "CLK", .desc = "[EXT] Clock Comparator"}, |
36 | {.name = "EXC", .desc = "[EXT] External Call" }, | 36 | [EXTINT_EXC] = {.name = "EXC", .desc = "[EXT] External Call"}, |
37 | {.name = "EMS", .desc = "[EXT] Emergency Signal" }, | 37 | [EXTINT_EMS] = {.name = "EMS", .desc = "[EXT] Emergency Signal"}, |
38 | {.name = "TMR", .desc = "[EXT] CPU Timer" }, | 38 | [EXTINT_TMR] = {.name = "TMR", .desc = "[EXT] CPU Timer"}, |
39 | {.name = "TAL", .desc = "[EXT] Timing Alert" }, | 39 | [EXTINT_TLA] = {.name = "TAL", .desc = "[EXT] Timing Alert"}, |
40 | {.name = "PFL", .desc = "[EXT] Pseudo Page Fault" }, | 40 | [EXTINT_PFL] = {.name = "PFL", .desc = "[EXT] Pseudo Page Fault"}, |
41 | {.name = "DSD", .desc = "[EXT] DASD Diag" }, | 41 | [EXTINT_DSD] = {.name = "DSD", .desc = "[EXT] DASD Diag"}, |
42 | {.name = "VRT", .desc = "[EXT] Virtio" }, | 42 | [EXTINT_VRT] = {.name = "VRT", .desc = "[EXT] Virtio"}, |
43 | {.name = "SCP", .desc = "[EXT] Service Call" }, | 43 | [EXTINT_SCP] = {.name = "SCP", .desc = "[EXT] Service Call"}, |
44 | {.name = "IUC", .desc = "[EXT] IUCV" }, | 44 | [EXTINT_IUC] = {.name = "IUC", .desc = "[EXT] IUCV"}, |
45 | {.name = "CMS", .desc = "[EXT] CPU-Measurement: Sampling" }, | 45 | [EXTINT_CMS] = {.name = "CMS", .desc = "[EXT] CPU-Measurement: Sampling"}, |
46 | {.name = "CMC", .desc = "[EXT] CPU-Measurement: Counter" }, | 46 | [EXTINT_CMC] = {.name = "CMC", .desc = "[EXT] CPU-Measurement: Counter"}, |
47 | {.name = "CIO", .desc = "[I/O] Common I/O Layer Interrupt" }, | 47 | [EXTINT_CMR] = {.name = "CMR", .desc = "[EXT] CPU-Measurement: RI"}, |
48 | {.name = "QAI", .desc = "[I/O] QDIO Adapter Interrupt" }, | 48 | [IOINT_CIO] = {.name = "CIO", .desc = "[I/O] Common I/O Layer Interrupt"}, |
49 | {.name = "DAS", .desc = "[I/O] DASD" }, | 49 | [IOINT_QAI] = {.name = "QAI", .desc = "[I/O] QDIO Adapter Interrupt"}, |
50 | {.name = "C15", .desc = "[I/O] 3215" }, | 50 | [IOINT_DAS] = {.name = "DAS", .desc = "[I/O] DASD"}, |
51 | {.name = "C70", .desc = "[I/O] 3270" }, | 51 | [IOINT_C15] = {.name = "C15", .desc = "[I/O] 3215"}, |
52 | {.name = "TAP", .desc = "[I/O] Tape" }, | 52 | [IOINT_C70] = {.name = "C70", .desc = "[I/O] 3270"}, |
53 | {.name = "VMR", .desc = "[I/O] Unit Record Devices" }, | 53 | [IOINT_TAP] = {.name = "TAP", .desc = "[I/O] Tape"}, |
54 | {.name = "LCS", .desc = "[I/O] LCS" }, | 54 | [IOINT_VMR] = {.name = "VMR", .desc = "[I/O] Unit Record Devices"}, |
55 | {.name = "CLW", .desc = "[I/O] CLAW" }, | 55 | [IOINT_LCS] = {.name = "LCS", .desc = "[I/O] LCS"}, |
56 | {.name = "CTC", .desc = "[I/O] CTC" }, | 56 | [IOINT_CLW] = {.name = "CLW", .desc = "[I/O] CLAW"}, |
57 | {.name = "APB", .desc = "[I/O] AP Bus" }, | 57 | [IOINT_CTC] = {.name = "CTC", .desc = "[I/O] CTC"}, |
58 | {.name = "CSC", .desc = "[I/O] CHSC Subchannel" }, | 58 | [IOINT_APB] = {.name = "APB", .desc = "[I/O] AP Bus"}, |
59 | {.name = "NMI", .desc = "[NMI] Machine Check" }, | 59 | [IOINT_ADM] = {.name = "ADM", .desc = "[I/O] EADM Subchannel"}, |
60 | [IOINT_CSC] = {.name = "CSC", .desc = "[I/O] CHSC Subchannel"}, | ||
61 | [NMI_NMI] = {.name = "NMI", .desc = "[NMI] Machine Check"}, | ||
60 | }; | 62 | }; |
61 | 63 | ||
62 | /* | 64 | /* |
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c index 8aa634f5944b..d1c7214e157c 100644 --- a/arch/s390/kernel/kprobes.c +++ b/arch/s390/kernel/kprobes.c | |||
@@ -547,7 +547,7 @@ static int __kprobes kprobe_trap_handler(struct pt_regs *regs, int trapnr) | |||
547 | */ | 547 | */ |
548 | entry = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN); | 548 | entry = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN); |
549 | if (entry) { | 549 | if (entry) { |
550 | regs->psw.addr = entry->fixup | PSW_ADDR_AMODE; | 550 | regs->psw.addr = extable_fixup(entry) | PSW_ADDR_AMODE; |
551 | return 1; | 551 | return 1; |
552 | } | 552 | } |
553 | 553 | ||
diff --git a/arch/s390/kernel/lgr.c b/arch/s390/kernel/lgr.c index eca94e74d19a..6ea6d69339b5 100644 --- a/arch/s390/kernel/lgr.c +++ b/arch/s390/kernel/lgr.c | |||
@@ -51,16 +51,6 @@ static struct lgr_info lgr_info_cur; | |||
51 | static struct debug_info *lgr_dbf; | 51 | static struct debug_info *lgr_dbf; |
52 | 52 | ||
53 | /* | 53 | /* |
54 | * Return number of valid stsi levels | ||
55 | */ | ||
56 | static inline int stsi_0(void) | ||
57 | { | ||
58 | int rc = stsi(NULL, 0, 0, 0); | ||
59 | |||
60 | return rc == -ENOSYS ? rc : (((unsigned int) rc) >> 28); | ||
61 | } | ||
62 | |||
63 | /* | ||
64 | * Copy buffer and then convert it to ASCII | 54 | * Copy buffer and then convert it to ASCII |
65 | */ | 55 | */ |
66 | static void cpascii(char *dst, char *src, int size) | 56 | static void cpascii(char *dst, char *src, int size) |
@@ -76,7 +66,7 @@ static void lgr_stsi_1_1_1(struct lgr_info *lgr_info) | |||
76 | { | 66 | { |
77 | struct sysinfo_1_1_1 *si = (void *) lgr_page; | 67 | struct sysinfo_1_1_1 *si = (void *) lgr_page; |
78 | 68 | ||
79 | if (stsi(si, 1, 1, 1) == -ENOSYS) | 69 | if (stsi(si, 1, 1, 1)) |
80 | return; | 70 | return; |
81 | cpascii(lgr_info->manufacturer, si->manufacturer, | 71 | cpascii(lgr_info->manufacturer, si->manufacturer, |
82 | sizeof(si->manufacturer)); | 72 | sizeof(si->manufacturer)); |
@@ -93,7 +83,7 @@ static void lgr_stsi_2_2_2(struct lgr_info *lgr_info) | |||
93 | { | 83 | { |
94 | struct sysinfo_2_2_2 *si = (void *) lgr_page; | 84 | struct sysinfo_2_2_2 *si = (void *) lgr_page; |
95 | 85 | ||
96 | if (stsi(si, 2, 2, 2) == -ENOSYS) | 86 | if (stsi(si, 2, 2, 2)) |
97 | return; | 87 | return; |
98 | cpascii(lgr_info->name, si->name, sizeof(si->name)); | 88 | cpascii(lgr_info->name, si->name, sizeof(si->name)); |
99 | memcpy(&lgr_info->lpar_number, &si->lpar_number, | 89 | memcpy(&lgr_info->lpar_number, &si->lpar_number, |
@@ -108,7 +98,7 @@ static void lgr_stsi_3_2_2(struct lgr_info *lgr_info) | |||
108 | struct sysinfo_3_2_2 *si = (void *) lgr_page; | 98 | struct sysinfo_3_2_2 *si = (void *) lgr_page; |
109 | int i; | 99 | int i; |
110 | 100 | ||
111 | if (stsi(si, 3, 2, 2) == -ENOSYS) | 101 | if (stsi(si, 3, 2, 2)) |
112 | return; | 102 | return; |
113 | for (i = 0; i < min_t(u8, si->count, VM_LEVEL_MAX); i++) { | 103 | for (i = 0; i < min_t(u8, si->count, VM_LEVEL_MAX); i++) { |
114 | cpascii(lgr_info->vm[i].name, si->vm[i].name, | 104 | cpascii(lgr_info->vm[i].name, si->vm[i].name, |
@@ -124,16 +114,17 @@ static void lgr_stsi_3_2_2(struct lgr_info *lgr_info) | |||
124 | */ | 114 | */ |
125 | static void lgr_info_get(struct lgr_info *lgr_info) | 115 | static void lgr_info_get(struct lgr_info *lgr_info) |
126 | { | 116 | { |
117 | int level; | ||
118 | |||
127 | memset(lgr_info, 0, sizeof(*lgr_info)); | 119 | memset(lgr_info, 0, sizeof(*lgr_info)); |
128 | stfle(lgr_info->stfle_fac_list, ARRAY_SIZE(lgr_info->stfle_fac_list)); | 120 | stfle(lgr_info->stfle_fac_list, ARRAY_SIZE(lgr_info->stfle_fac_list)); |
129 | lgr_info->level = stsi_0(); | 121 | level = stsi(NULL, 0, 0, 0); |
130 | if (lgr_info->level == -ENOSYS) | 122 | lgr_info->level = level; |
131 | return; | 123 | if (level >= 1) |
132 | if (lgr_info->level >= 1) | ||
133 | lgr_stsi_1_1_1(lgr_info); | 124 | lgr_stsi_1_1_1(lgr_info); |
134 | if (lgr_info->level >= 2) | 125 | if (level >= 2) |
135 | lgr_stsi_2_2_2(lgr_info); | 126 | lgr_stsi_2_2_2(lgr_info); |
136 | if (lgr_info->level >= 3) | 127 | if (level >= 3) |
137 | lgr_stsi_3_2_2(lgr_info); | 128 | lgr_stsi_3_2_2(lgr_info); |
138 | } | 129 | } |
139 | 130 | ||
diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c index 493304bdf1c7..b3de27700016 100644 --- a/arch/s390/kernel/machine_kexec.c +++ b/arch/s390/kernel/machine_kexec.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <asm/reset.h> | 21 | #include <asm/reset.h> |
22 | #include <asm/ipl.h> | 22 | #include <asm/ipl.h> |
23 | #include <asm/diag.h> | 23 | #include <asm/diag.h> |
24 | #include <asm/elf.h> | ||
24 | #include <asm/asm-offsets.h> | 25 | #include <asm/asm-offsets.h> |
25 | #include <asm/os_info.h> | 26 | #include <asm/os_info.h> |
26 | 27 | ||
@@ -31,8 +32,6 @@ extern const unsigned long long relocate_kernel_len; | |||
31 | 32 | ||
32 | #ifdef CONFIG_CRASH_DUMP | 33 | #ifdef CONFIG_CRASH_DUMP |
33 | 34 | ||
34 | void *fill_cpu_elf_notes(void *ptr, struct save_area *sa); | ||
35 | |||
36 | /* | 35 | /* |
37 | * Create ELF notes for one CPU | 36 | * Create ELF notes for one CPU |
38 | */ | 37 | */ |
@@ -159,7 +158,7 @@ int machine_kexec_prepare(struct kimage *image) | |||
159 | 158 | ||
160 | /* Can't replace kernel image since it is read-only. */ | 159 | /* Can't replace kernel image since it is read-only. */ |
161 | if (ipl_flags & IPL_NSS_VALID) | 160 | if (ipl_flags & IPL_NSS_VALID) |
162 | return -ENOSYS; | 161 | return -EOPNOTSUPP; |
163 | 162 | ||
164 | if (image->type == KEXEC_TYPE_CRASH) | 163 | if (image->type == KEXEC_TYPE_CRASH) |
165 | return machine_kexec_prepare_kdump(); | 164 | return machine_kexec_prepare_kdump(); |
@@ -191,6 +190,10 @@ void machine_shutdown(void) | |||
191 | { | 190 | { |
192 | } | 191 | } |
193 | 192 | ||
193 | void machine_crash_shutdown(struct pt_regs *regs) | ||
194 | { | ||
195 | } | ||
196 | |||
194 | /* | 197 | /* |
195 | * Do normal kexec | 198 | * Do normal kexec |
196 | */ | 199 | */ |
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 733175373a4c..5024be27df44 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c | |||
@@ -26,10 +26,12 @@ | |||
26 | #include <asm/io.h> | 26 | #include <asm/io.h> |
27 | #include <asm/processor.h> | 27 | #include <asm/processor.h> |
28 | #include <asm/vtimer.h> | 28 | #include <asm/vtimer.h> |
29 | #include <asm/exec.h> | ||
29 | #include <asm/irq.h> | 30 | #include <asm/irq.h> |
30 | #include <asm/nmi.h> | 31 | #include <asm/nmi.h> |
31 | #include <asm/smp.h> | 32 | #include <asm/smp.h> |
32 | #include <asm/switch_to.h> | 33 | #include <asm/switch_to.h> |
34 | #include <asm/runtime_instr.h> | ||
33 | #include "entry.h" | 35 | #include "entry.h" |
34 | 36 | ||
35 | asmlinkage void ret_from_fork(void) asm ("ret_from_fork"); | 37 | asmlinkage void ret_from_fork(void) asm ("ret_from_fork"); |
@@ -132,6 +134,7 @@ EXPORT_SYMBOL(kernel_thread); | |||
132 | */ | 134 | */ |
133 | void exit_thread(void) | 135 | void exit_thread(void) |
134 | { | 136 | { |
137 | exit_thread_runtime_instr(); | ||
135 | } | 138 | } |
136 | 139 | ||
137 | void flush_thread(void) | 140 | void flush_thread(void) |
@@ -170,6 +173,11 @@ int copy_thread(unsigned long clone_flags, unsigned long new_stackp, | |||
170 | /* Save access registers to new thread structure. */ | 173 | /* Save access registers to new thread structure. */ |
171 | save_access_regs(&p->thread.acrs[0]); | 174 | save_access_regs(&p->thread.acrs[0]); |
172 | 175 | ||
176 | /* Don't copy runtime instrumentation info */ | ||
177 | p->thread.ri_cb = NULL; | ||
178 | p->thread.ri_signum = 0; | ||
179 | frame->childregs.psw.mask &= ~PSW_MASK_RI; | ||
180 | |||
173 | #ifndef CONFIG_64BIT | 181 | #ifndef CONFIG_64BIT |
174 | /* | 182 | /* |
175 | * save fprs to current->thread.fp_regs to merge them with | 183 | * save fprs to current->thread.fp_regs to merge them with |
diff --git a/arch/s390/kernel/processor.c b/arch/s390/kernel/processor.c index 572d4c9cb33b..753c41d0ffd3 100644 --- a/arch/s390/kernel/processor.c +++ b/arch/s390/kernel/processor.c | |||
@@ -39,9 +39,9 @@ void __cpuinit cpu_init(void) | |||
39 | */ | 39 | */ |
40 | static int show_cpuinfo(struct seq_file *m, void *v) | 40 | static int show_cpuinfo(struct seq_file *m, void *v) |
41 | { | 41 | { |
42 | static const char *hwcap_str[10] = { | 42 | static const char *hwcap_str[] = { |
43 | "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp", | 43 | "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp", |
44 | "edat", "etf3eh", "highgprs" | 44 | "edat", "etf3eh", "highgprs", "te" |
45 | }; | 45 | }; |
46 | unsigned long n = (unsigned long) v - 1; | 46 | unsigned long n = (unsigned long) v - 1; |
47 | int i; | 47 | int i; |
@@ -54,10 +54,11 @@ static int show_cpuinfo(struct seq_file *m, void *v) | |||
54 | num_online_cpus(), loops_per_jiffy/(500000/HZ), | 54 | num_online_cpus(), loops_per_jiffy/(500000/HZ), |
55 | (loops_per_jiffy/(5000/HZ))%100); | 55 | (loops_per_jiffy/(5000/HZ))%100); |
56 | seq_puts(m, "features\t: "); | 56 | seq_puts(m, "features\t: "); |
57 | for (i = 0; i < 10; i++) | 57 | for (i = 0; i < ARRAY_SIZE(hwcap_str); i++) |
58 | if (hwcap_str[i] && (elf_hwcap & (1UL << i))) | 58 | if (hwcap_str[i] && (elf_hwcap & (1UL << i))) |
59 | seq_printf(m, "%s ", hwcap_str[i]); | 59 | seq_printf(m, "%s ", hwcap_str[i]); |
60 | seq_puts(m, "\n"); | 60 | seq_puts(m, "\n"); |
61 | show_cacheinfo(m); | ||
61 | } | 62 | } |
62 | get_online_cpus(); | 63 | get_online_cpus(); |
63 | if (cpu_online(n)) { | 64 | if (cpu_online(n)) { |
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index e4be113fbac6..a314c57f4e94 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c | |||
@@ -42,6 +42,7 @@ enum s390_regset { | |||
42 | REGSET_GENERAL, | 42 | REGSET_GENERAL, |
43 | REGSET_FP, | 43 | REGSET_FP, |
44 | REGSET_LAST_BREAK, | 44 | REGSET_LAST_BREAK, |
45 | REGSET_TDB, | ||
45 | REGSET_SYSTEM_CALL, | 46 | REGSET_SYSTEM_CALL, |
46 | REGSET_GENERAL_EXTENDED, | 47 | REGSET_GENERAL_EXTENDED, |
47 | }; | 48 | }; |
@@ -52,6 +53,22 @@ void update_per_regs(struct task_struct *task) | |||
52 | struct thread_struct *thread = &task->thread; | 53 | struct thread_struct *thread = &task->thread; |
53 | struct per_regs old, new; | 54 | struct per_regs old, new; |
54 | 55 | ||
56 | #ifdef CONFIG_64BIT | ||
57 | /* Take care of the enable/disable of transactional execution. */ | ||
58 | if (MACHINE_HAS_TE) { | ||
59 | unsigned long cr0, cr0_new; | ||
60 | |||
61 | __ctl_store(cr0, 0, 0); | ||
62 | /* set or clear transaction execution bits 8 and 9. */ | ||
63 | if (task->thread.per_flags & PER_FLAG_NO_TE) | ||
64 | cr0_new = cr0 & ~(3UL << 54); | ||
65 | else | ||
66 | cr0_new = cr0 | (3UL << 54); | ||
67 | /* Only load control register 0 if necessary. */ | ||
68 | if (cr0 != cr0_new) | ||
69 | __ctl_load(cr0_new, 0, 0); | ||
70 | } | ||
71 | #endif | ||
55 | /* Copy user specified PER registers */ | 72 | /* Copy user specified PER registers */ |
56 | new.control = thread->per_user.control; | 73 | new.control = thread->per_user.control; |
57 | new.start = thread->per_user.start; | 74 | new.start = thread->per_user.start; |
@@ -60,6 +77,10 @@ void update_per_regs(struct task_struct *task) | |||
60 | /* merge TIF_SINGLE_STEP into user specified PER registers. */ | 77 | /* merge TIF_SINGLE_STEP into user specified PER registers. */ |
61 | if (test_tsk_thread_flag(task, TIF_SINGLE_STEP)) { | 78 | if (test_tsk_thread_flag(task, TIF_SINGLE_STEP)) { |
62 | new.control |= PER_EVENT_IFETCH; | 79 | new.control |= PER_EVENT_IFETCH; |
80 | #ifdef CONFIG_64BIT | ||
81 | new.control |= PER_CONTROL_SUSPENSION; | ||
82 | new.control |= PER_EVENT_TRANSACTION_END; | ||
83 | #endif | ||
63 | new.start = 0; | 84 | new.start = 0; |
64 | new.end = PSW_ADDR_INSN; | 85 | new.end = PSW_ADDR_INSN; |
65 | } | 86 | } |
@@ -100,6 +121,7 @@ void ptrace_disable(struct task_struct *task) | |||
100 | memset(&task->thread.per_event, 0, sizeof(task->thread.per_event)); | 121 | memset(&task->thread.per_event, 0, sizeof(task->thread.per_event)); |
101 | clear_tsk_thread_flag(task, TIF_SINGLE_STEP); | 122 | clear_tsk_thread_flag(task, TIF_SINGLE_STEP); |
102 | clear_tsk_thread_flag(task, TIF_PER_TRAP); | 123 | clear_tsk_thread_flag(task, TIF_PER_TRAP); |
124 | task->thread.per_flags = 0; | ||
103 | } | 125 | } |
104 | 126 | ||
105 | #ifndef CONFIG_64BIT | 127 | #ifndef CONFIG_64BIT |
@@ -416,6 +438,16 @@ long arch_ptrace(struct task_struct *child, long request, | |||
416 | put_user(task_thread_info(child)->last_break, | 438 | put_user(task_thread_info(child)->last_break, |
417 | (unsigned long __user *) data); | 439 | (unsigned long __user *) data); |
418 | return 0; | 440 | return 0; |
441 | case PTRACE_ENABLE_TE: | ||
442 | if (!MACHINE_HAS_TE) | ||
443 | return -EIO; | ||
444 | child->thread.per_flags &= ~PER_FLAG_NO_TE; | ||
445 | return 0; | ||
446 | case PTRACE_DISABLE_TE: | ||
447 | if (!MACHINE_HAS_TE) | ||
448 | return -EIO; | ||
449 | child->thread.per_flags |= PER_FLAG_NO_TE; | ||
450 | return 0; | ||
419 | default: | 451 | default: |
420 | /* Removing high order bit from addr (only for 31 bit). */ | 452 | /* Removing high order bit from addr (only for 31 bit). */ |
421 | addr &= PSW_ADDR_INSN; | 453 | addr &= PSW_ADDR_INSN; |
@@ -903,6 +935,28 @@ static int s390_last_break_set(struct task_struct *target, | |||
903 | return 0; | 935 | return 0; |
904 | } | 936 | } |
905 | 937 | ||
938 | static int s390_tdb_get(struct task_struct *target, | ||
939 | const struct user_regset *regset, | ||
940 | unsigned int pos, unsigned int count, | ||
941 | void *kbuf, void __user *ubuf) | ||
942 | { | ||
943 | struct pt_regs *regs = task_pt_regs(target); | ||
944 | unsigned char *data; | ||
945 | |||
946 | if (!(regs->int_code & 0x200)) | ||
947 | return -ENODATA; | ||
948 | data = target->thread.trap_tdb; | ||
949 | return user_regset_copyout(&pos, &count, &kbuf, &ubuf, data, 0, 256); | ||
950 | } | ||
951 | |||
952 | static int s390_tdb_set(struct task_struct *target, | ||
953 | const struct user_regset *regset, | ||
954 | unsigned int pos, unsigned int count, | ||
955 | const void *kbuf, const void __user *ubuf) | ||
956 | { | ||
957 | return 0; | ||
958 | } | ||
959 | |||
906 | #endif | 960 | #endif |
907 | 961 | ||
908 | static int s390_system_call_get(struct task_struct *target, | 962 | static int s390_system_call_get(struct task_struct *target, |
@@ -951,6 +1005,14 @@ static const struct user_regset s390_regsets[] = { | |||
951 | .get = s390_last_break_get, | 1005 | .get = s390_last_break_get, |
952 | .set = s390_last_break_set, | 1006 | .set = s390_last_break_set, |
953 | }, | 1007 | }, |
1008 | [REGSET_TDB] = { | ||
1009 | .core_note_type = NT_S390_TDB, | ||
1010 | .n = 1, | ||
1011 | .size = 256, | ||
1012 | .align = 1, | ||
1013 | .get = s390_tdb_get, | ||
1014 | .set = s390_tdb_set, | ||
1015 | }, | ||
954 | #endif | 1016 | #endif |
955 | [REGSET_SYSTEM_CALL] = { | 1017 | [REGSET_SYSTEM_CALL] = { |
956 | .core_note_type = NT_S390_SYSTEM_CALL, | 1018 | .core_note_type = NT_S390_SYSTEM_CALL, |
@@ -1148,6 +1210,14 @@ static const struct user_regset s390_compat_regsets[] = { | |||
1148 | .get = s390_compat_last_break_get, | 1210 | .get = s390_compat_last_break_get, |
1149 | .set = s390_compat_last_break_set, | 1211 | .set = s390_compat_last_break_set, |
1150 | }, | 1212 | }, |
1213 | [REGSET_TDB] = { | ||
1214 | .core_note_type = NT_S390_TDB, | ||
1215 | .n = 1, | ||
1216 | .size = 256, | ||
1217 | .align = 1, | ||
1218 | .get = s390_tdb_get, | ||
1219 | .set = s390_tdb_set, | ||
1220 | }, | ||
1151 | [REGSET_SYSTEM_CALL] = { | 1221 | [REGSET_SYSTEM_CALL] = { |
1152 | .core_note_type = NT_S390_SYSTEM_CALL, | 1222 | .core_note_type = NT_S390_SYSTEM_CALL, |
1153 | .n = 1, | 1223 | .n = 1, |
diff --git a/arch/s390/kernel/runtime_instr.c b/arch/s390/kernel/runtime_instr.c new file mode 100644 index 000000000000..61066f6f71a5 --- /dev/null +++ b/arch/s390/kernel/runtime_instr.c | |||
@@ -0,0 +1,150 @@ | |||
1 | /* | ||
2 | * Copyright IBM Corp. 2012 | ||
3 | * Author(s): Jan Glauber <jang@linux.vnet.ibm.com> | ||
4 | */ | ||
5 | |||
6 | #include <linux/kernel.h> | ||
7 | #include <linux/syscalls.h> | ||
8 | #include <linux/signal.h> | ||
9 | #include <linux/mm.h> | ||
10 | #include <linux/slab.h> | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/errno.h> | ||
13 | #include <linux/kernel_stat.h> | ||
14 | #include <asm/runtime_instr.h> | ||
15 | #include <asm/cpu_mf.h> | ||
16 | #include <asm/irq.h> | ||
17 | |||
18 | /* empty control block to disable RI by loading it */ | ||
19 | struct runtime_instr_cb runtime_instr_empty_cb; | ||
20 | |||
21 | static int runtime_instr_avail(void) | ||
22 | { | ||
23 | return test_facility(64); | ||
24 | } | ||
25 | |||
26 | static void disable_runtime_instr(void) | ||
27 | { | ||
28 | struct pt_regs *regs = task_pt_regs(current); | ||
29 | |||
30 | load_runtime_instr_cb(&runtime_instr_empty_cb); | ||
31 | |||
32 | /* | ||
33 | * Make sure the RI bit is deleted from the PSW. If the user did not | ||
34 | * switch off RI before the system call the process will get a | ||
35 | * specification exception otherwise. | ||
36 | */ | ||
37 | regs->psw.mask &= ~PSW_MASK_RI; | ||
38 | } | ||
39 | |||
40 | static void init_runtime_instr_cb(struct runtime_instr_cb *cb) | ||
41 | { | ||
42 | cb->buf_limit = 0xfff; | ||
43 | if (s390_user_mode == HOME_SPACE_MODE) | ||
44 | cb->home_space = 1; | ||
45 | cb->int_requested = 1; | ||
46 | cb->pstate = 1; | ||
47 | cb->pstate_set_buf = 1; | ||
48 | cb->pstate_sample = 1; | ||
49 | cb->pstate_collect = 1; | ||
50 | cb->key = PAGE_DEFAULT_KEY; | ||
51 | cb->valid = 1; | ||
52 | } | ||
53 | |||
54 | void exit_thread_runtime_instr(void) | ||
55 | { | ||
56 | struct task_struct *task = current; | ||
57 | |||
58 | if (!task->thread.ri_cb) | ||
59 | return; | ||
60 | disable_runtime_instr(); | ||
61 | kfree(task->thread.ri_cb); | ||
62 | task->thread.ri_signum = 0; | ||
63 | task->thread.ri_cb = NULL; | ||
64 | } | ||
65 | |||
66 | static void runtime_instr_int_handler(struct ext_code ext_code, | ||
67 | unsigned int param32, unsigned long param64) | ||
68 | { | ||
69 | struct siginfo info; | ||
70 | |||
71 | if (!(param32 & CPU_MF_INT_RI_MASK)) | ||
72 | return; | ||
73 | |||
74 | kstat_cpu(smp_processor_id()).irqs[EXTINT_CMR]++; | ||
75 | |||
76 | if (!current->thread.ri_cb) | ||
77 | return; | ||
78 | if (current->thread.ri_signum < SIGRTMIN || | ||
79 | current->thread.ri_signum > SIGRTMAX) { | ||
80 | WARN_ON_ONCE(1); | ||
81 | return; | ||
82 | } | ||
83 | |||
84 | memset(&info, 0, sizeof(info)); | ||
85 | info.si_signo = current->thread.ri_signum; | ||
86 | info.si_code = SI_QUEUE; | ||
87 | if (param32 & CPU_MF_INT_RI_BUF_FULL) | ||
88 | info.si_int = ENOBUFS; | ||
89 | else if (param32 & CPU_MF_INT_RI_HALTED) | ||
90 | info.si_int = ECANCELED; | ||
91 | else | ||
92 | return; /* unknown reason */ | ||
93 | |||
94 | send_sig_info(current->thread.ri_signum, &info, current); | ||
95 | } | ||
96 | |||
97 | SYSCALL_DEFINE2(s390_runtime_instr, int, command, int, signum) | ||
98 | { | ||
99 | struct runtime_instr_cb *cb; | ||
100 | |||
101 | if (!runtime_instr_avail()) | ||
102 | return -EOPNOTSUPP; | ||
103 | |||
104 | if (command == S390_RUNTIME_INSTR_STOP) { | ||
105 | preempt_disable(); | ||
106 | exit_thread_runtime_instr(); | ||
107 | preempt_enable(); | ||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | if (command != S390_RUNTIME_INSTR_START || | ||
112 | (signum < SIGRTMIN || signum > SIGRTMAX)) | ||
113 | return -EINVAL; | ||
114 | |||
115 | if (!current->thread.ri_cb) { | ||
116 | cb = kzalloc(sizeof(*cb), GFP_KERNEL); | ||
117 | if (!cb) | ||
118 | return -ENOMEM; | ||
119 | } else { | ||
120 | cb = current->thread.ri_cb; | ||
121 | memset(cb, 0, sizeof(*cb)); | ||
122 | } | ||
123 | |||
124 | init_runtime_instr_cb(cb); | ||
125 | current->thread.ri_signum = signum; | ||
126 | |||
127 | /* now load the control block to make it available */ | ||
128 | preempt_disable(); | ||
129 | current->thread.ri_cb = cb; | ||
130 | load_runtime_instr_cb(cb); | ||
131 | preempt_enable(); | ||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | static int __init runtime_instr_init(void) | ||
136 | { | ||
137 | int rc; | ||
138 | |||
139 | if (!runtime_instr_avail()) | ||
140 | return 0; | ||
141 | |||
142 | measurement_alert_subclass_register(); | ||
143 | rc = register_external_interrupt(0x1407, runtime_instr_int_handler); | ||
144 | if (rc) | ||
145 | measurement_alert_subclass_unregister(); | ||
146 | else | ||
147 | pr_info("Runtime instrumentation facility initialized\n"); | ||
148 | return rc; | ||
149 | } | ||
150 | device_initcall(runtime_instr_init); | ||
diff --git a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c index 57b536649b00..9bdbcef1da9e 100644 --- a/arch/s390/kernel/s390_ksyms.c +++ b/arch/s390/kernel/s390_ksyms.c | |||
@@ -8,3 +8,5 @@ EXPORT_SYMBOL(_mcount); | |||
8 | #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) | 8 | #if defined(CONFIG_KVM) || defined(CONFIG_KVM_MODULE) |
9 | EXPORT_SYMBOL(sie64a); | 9 | EXPORT_SYMBOL(sie64a); |
10 | #endif | 10 | #endif |
11 | EXPORT_SYMBOL(memcpy); | ||
12 | EXPORT_SYMBOL(memset); | ||
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 40b57693de38..afa9fdba200e 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c | |||
@@ -302,10 +302,10 @@ static int __init parse_vmalloc(char *arg) | |||
302 | } | 302 | } |
303 | early_param("vmalloc", parse_vmalloc); | 303 | early_param("vmalloc", parse_vmalloc); |
304 | 304 | ||
305 | unsigned int addressing_mode = HOME_SPACE_MODE; | 305 | unsigned int s390_user_mode = PRIMARY_SPACE_MODE; |
306 | EXPORT_SYMBOL_GPL(addressing_mode); | 306 | EXPORT_SYMBOL_GPL(s390_user_mode); |
307 | 307 | ||
308 | static int set_amode_primary(void) | 308 | static void __init set_user_mode_primary(void) |
309 | { | 309 | { |
310 | psw_kernel_bits = (psw_kernel_bits & ~PSW_MASK_ASC) | PSW_ASC_HOME; | 310 | psw_kernel_bits = (psw_kernel_bits & ~PSW_MASK_ASC) | PSW_ASC_HOME; |
311 | psw_user_bits = (psw_user_bits & ~PSW_MASK_ASC) | PSW_ASC_PRIMARY; | 311 | psw_user_bits = (psw_user_bits & ~PSW_MASK_ASC) | PSW_ASC_PRIMARY; |
@@ -313,48 +313,30 @@ static int set_amode_primary(void) | |||
313 | psw32_user_bits = | 313 | psw32_user_bits = |
314 | (psw32_user_bits & ~PSW32_MASK_ASC) | PSW32_ASC_PRIMARY; | 314 | (psw32_user_bits & ~PSW32_MASK_ASC) | PSW32_ASC_PRIMARY; |
315 | #endif | 315 | #endif |
316 | 316 | uaccess = MACHINE_HAS_MVCOS ? uaccess_mvcos_switch : uaccess_pt; | |
317 | if (MACHINE_HAS_MVCOS) { | ||
318 | memcpy(&uaccess, &uaccess_mvcos_switch, sizeof(uaccess)); | ||
319 | return 1; | ||
320 | } else { | ||
321 | memcpy(&uaccess, &uaccess_pt, sizeof(uaccess)); | ||
322 | return 0; | ||
323 | } | ||
324 | } | ||
325 | |||
326 | /* | ||
327 | * Switch kernel/user addressing modes? | ||
328 | */ | ||
329 | static int __init early_parse_switch_amode(char *p) | ||
330 | { | ||
331 | addressing_mode = PRIMARY_SPACE_MODE; | ||
332 | return 0; | ||
333 | } | 317 | } |
334 | early_param("switch_amode", early_parse_switch_amode); | ||
335 | 318 | ||
336 | static int __init early_parse_user_mode(char *p) | 319 | static int __init early_parse_user_mode(char *p) |
337 | { | 320 | { |
338 | if (p && strcmp(p, "primary") == 0) | 321 | if (p && strcmp(p, "primary") == 0) |
339 | addressing_mode = PRIMARY_SPACE_MODE; | 322 | s390_user_mode = PRIMARY_SPACE_MODE; |
340 | else if (!p || strcmp(p, "home") == 0) | 323 | else if (!p || strcmp(p, "home") == 0) |
341 | addressing_mode = HOME_SPACE_MODE; | 324 | s390_user_mode = HOME_SPACE_MODE; |
342 | else | 325 | else |
343 | return 1; | 326 | return 1; |
344 | return 0; | 327 | return 0; |
345 | } | 328 | } |
346 | early_param("user_mode", early_parse_user_mode); | 329 | early_param("user_mode", early_parse_user_mode); |
347 | 330 | ||
348 | static void setup_addressing_mode(void) | 331 | static void __init setup_addressing_mode(void) |
349 | { | 332 | { |
350 | if (addressing_mode == PRIMARY_SPACE_MODE) { | 333 | if (s390_user_mode != PRIMARY_SPACE_MODE) |
351 | if (set_amode_primary()) | 334 | return; |
352 | pr_info("Address spaces switched, " | 335 | set_user_mode_primary(); |
353 | "mvcos available\n"); | 336 | if (MACHINE_HAS_MVCOS) |
354 | else | 337 | pr_info("Address spaces switched, mvcos available\n"); |
355 | pr_info("Address spaces switched, " | 338 | else |
356 | "mvcos not available\n"); | 339 | pr_info("Address spaces switched, mvcos not available\n"); |
357 | } | ||
358 | } | 340 | } |
359 | 341 | ||
360 | void *restart_stack __attribute__((__section__(".data"))); | 342 | void *restart_stack __attribute__((__section__(".data"))); |
@@ -602,9 +584,7 @@ static void __init setup_memory_end(void) | |||
602 | 584 | ||
603 | static void __init setup_vmcoreinfo(void) | 585 | static void __init setup_vmcoreinfo(void) |
604 | { | 586 | { |
605 | #ifdef CONFIG_KEXEC | ||
606 | mem_assign_absolute(S390_lowcore.vmcore_info, paddr_vmcoreinfo_note()); | 587 | mem_assign_absolute(S390_lowcore.vmcore_info, paddr_vmcoreinfo_note()); |
607 | #endif | ||
608 | } | 588 | } |
609 | 589 | ||
610 | #ifdef CONFIG_CRASH_DUMP | 590 | #ifdef CONFIG_CRASH_DUMP |
@@ -980,6 +960,12 @@ static void __init setup_hwcaps(void) | |||
980 | * HWCAP_S390_HIGH_GPRS is bit 9. | 960 | * HWCAP_S390_HIGH_GPRS is bit 9. |
981 | */ | 961 | */ |
982 | elf_hwcap |= HWCAP_S390_HIGH_GPRS; | 962 | elf_hwcap |= HWCAP_S390_HIGH_GPRS; |
963 | |||
964 | /* | ||
965 | * Transactional execution support HWCAP_S390_TE is bit 10. | ||
966 | */ | ||
967 | if (test_facility(50) && test_facility(73)) | ||
968 | elf_hwcap |= HWCAP_S390_TE; | ||
983 | #endif | 969 | #endif |
984 | 970 | ||
985 | get_cpu_id(&cpu_id); | 971 | get_cpu_id(&cpu_id); |
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c index 720fda1620f2..ea431e551c6b 100644 --- a/arch/s390/kernel/smp.c +++ b/arch/s390/kernel/smp.c | |||
@@ -66,7 +66,7 @@ struct pcpu { | |||
66 | unsigned long panic_stack; /* panic 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 */ | 67 | unsigned long ec_mask; /* bit mask for ec_xxx functions */ |
68 | int state; /* physical cpu state */ | 68 | int state; /* physical cpu state */ |
69 | u32 status; /* last status received via sigp */ | 69 | int polarization; /* physical polarization */ |
70 | u16 address; /* physical cpu address */ | 70 | u16 address; /* physical cpu address */ |
71 | }; | 71 | }; |
72 | 72 | ||
@@ -74,6 +74,10 @@ static u8 boot_cpu_type; | |||
74 | static u16 boot_cpu_address; | 74 | static u16 boot_cpu_address; |
75 | static struct pcpu pcpu_devices[NR_CPUS]; | 75 | static struct pcpu pcpu_devices[NR_CPUS]; |
76 | 76 | ||
77 | /* | ||
78 | * The smp_cpu_state_mutex must be held when changing the state or polarization | ||
79 | * member of a pcpu data structure within the pcpu_devices arreay. | ||
80 | */ | ||
77 | DEFINE_MUTEX(smp_cpu_state_mutex); | 81 | DEFINE_MUTEX(smp_cpu_state_mutex); |
78 | 82 | ||
79 | /* | 83 | /* |
@@ -99,7 +103,7 @@ static inline int __pcpu_sigp_relax(u16 addr, u8 order, u32 parm, u32 *status) | |||
99 | int cc; | 103 | int cc; |
100 | 104 | ||
101 | while (1) { | 105 | while (1) { |
102 | cc = __pcpu_sigp(addr, order, parm, status); | 106 | cc = __pcpu_sigp(addr, order, parm, NULL); |
103 | if (cc != SIGP_CC_BUSY) | 107 | if (cc != SIGP_CC_BUSY) |
104 | return cc; | 108 | return cc; |
105 | cpu_relax(); | 109 | cpu_relax(); |
@@ -111,7 +115,7 @@ static int pcpu_sigp_retry(struct pcpu *pcpu, u8 order, u32 parm) | |||
111 | int cc, retry; | 115 | int cc, retry; |
112 | 116 | ||
113 | for (retry = 0; ; retry++) { | 117 | for (retry = 0; ; retry++) { |
114 | cc = __pcpu_sigp(pcpu->address, order, parm, &pcpu->status); | 118 | cc = __pcpu_sigp(pcpu->address, order, parm, NULL); |
115 | if (cc != SIGP_CC_BUSY) | 119 | if (cc != SIGP_CC_BUSY) |
116 | break; | 120 | break; |
117 | if (retry >= 3) | 121 | if (retry >= 3) |
@@ -122,16 +126,18 @@ static int pcpu_sigp_retry(struct pcpu *pcpu, u8 order, u32 parm) | |||
122 | 126 | ||
123 | static inline int pcpu_stopped(struct pcpu *pcpu) | 127 | static inline int pcpu_stopped(struct pcpu *pcpu) |
124 | { | 128 | { |
129 | u32 uninitialized_var(status); | ||
130 | |||
125 | if (__pcpu_sigp(pcpu->address, SIGP_SENSE, | 131 | if (__pcpu_sigp(pcpu->address, SIGP_SENSE, |
126 | 0, &pcpu->status) != SIGP_CC_STATUS_STORED) | 132 | 0, &status) != SIGP_CC_STATUS_STORED) |
127 | return 0; | 133 | return 0; |
128 | return !!(pcpu->status & (SIGP_STATUS_CHECK_STOP|SIGP_STATUS_STOPPED)); | 134 | return !!(status & (SIGP_STATUS_CHECK_STOP|SIGP_STATUS_STOPPED)); |
129 | } | 135 | } |
130 | 136 | ||
131 | static inline int pcpu_running(struct pcpu *pcpu) | 137 | static inline int pcpu_running(struct pcpu *pcpu) |
132 | { | 138 | { |
133 | if (__pcpu_sigp(pcpu->address, SIGP_SENSE_RUNNING, | 139 | if (__pcpu_sigp(pcpu->address, SIGP_SENSE_RUNNING, |
134 | 0, &pcpu->status) != SIGP_CC_STATUS_STORED) | 140 | 0, NULL) != SIGP_CC_STATUS_STORED) |
135 | return 1; | 141 | return 1; |
136 | /* Status stored condition code is equivalent to cpu not running. */ | 142 | /* Status stored condition code is equivalent to cpu not running. */ |
137 | return 0; | 143 | return 0; |
@@ -586,6 +592,16 @@ static inline void smp_get_save_area(int cpu, u16 address) { } | |||
586 | 592 | ||
587 | #endif /* CONFIG_ZFCPDUMP || CONFIG_CRASH_DUMP */ | 593 | #endif /* CONFIG_ZFCPDUMP || CONFIG_CRASH_DUMP */ |
588 | 594 | ||
595 | void smp_cpu_set_polarization(int cpu, int val) | ||
596 | { | ||
597 | pcpu_devices[cpu].polarization = val; | ||
598 | } | ||
599 | |||
600 | int smp_cpu_get_polarization(int cpu) | ||
601 | { | ||
602 | return pcpu_devices[cpu].polarization; | ||
603 | } | ||
604 | |||
589 | static struct sclp_cpu_info *smp_get_cpu_info(void) | 605 | static struct sclp_cpu_info *smp_get_cpu_info(void) |
590 | { | 606 | { |
591 | static int use_sigp_detection; | 607 | static int use_sigp_detection; |
@@ -628,7 +644,7 @@ static int __devinit __smp_rescan_cpus(struct sclp_cpu_info *info, | |||
628 | pcpu->address = info->cpu[i].address; | 644 | pcpu->address = info->cpu[i].address; |
629 | pcpu->state = (cpu >= info->configured) ? | 645 | pcpu->state = (cpu >= info->configured) ? |
630 | CPU_STATE_STANDBY : CPU_STATE_CONFIGURED; | 646 | CPU_STATE_STANDBY : CPU_STATE_CONFIGURED; |
631 | cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); | 647 | smp_cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); |
632 | set_cpu_present(cpu, true); | 648 | set_cpu_present(cpu, true); |
633 | if (sysfs_add && smp_add_present_cpu(cpu) != 0) | 649 | if (sysfs_add && smp_add_present_cpu(cpu) != 0) |
634 | set_cpu_present(cpu, false); | 650 | set_cpu_present(cpu, false); |
@@ -796,7 +812,7 @@ void __init smp_prepare_boot_cpu(void) | |||
796 | pcpu->async_stack = S390_lowcore.async_stack - ASYNC_SIZE; | 812 | pcpu->async_stack = S390_lowcore.async_stack - ASYNC_SIZE; |
797 | pcpu->panic_stack = S390_lowcore.panic_stack - PAGE_SIZE; | 813 | pcpu->panic_stack = S390_lowcore.panic_stack - PAGE_SIZE; |
798 | S390_lowcore.percpu_offset = __per_cpu_offset[0]; | 814 | S390_lowcore.percpu_offset = __per_cpu_offset[0]; |
799 | cpu_set_polarization(0, POLARIZATION_UNKNOWN); | 815 | smp_cpu_set_polarization(0, POLARIZATION_UNKNOWN); |
800 | set_cpu_present(0, true); | 816 | set_cpu_present(0, true); |
801 | set_cpu_online(0, true); | 817 | set_cpu_online(0, true); |
802 | } | 818 | } |
@@ -862,7 +878,7 @@ static ssize_t cpu_configure_store(struct device *dev, | |||
862 | if (rc) | 878 | if (rc) |
863 | break; | 879 | break; |
864 | pcpu->state = CPU_STATE_STANDBY; | 880 | pcpu->state = CPU_STATE_STANDBY; |
865 | cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); | 881 | smp_cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); |
866 | topology_expect_change(); | 882 | topology_expect_change(); |
867 | break; | 883 | break; |
868 | case 1: | 884 | case 1: |
@@ -872,7 +888,7 @@ static ssize_t cpu_configure_store(struct device *dev, | |||
872 | if (rc) | 888 | if (rc) |
873 | break; | 889 | break; |
874 | pcpu->state = CPU_STATE_CONFIGURED; | 890 | pcpu->state = CPU_STATE_CONFIGURED; |
875 | cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); | 891 | smp_cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); |
876 | topology_expect_change(); | 892 | topology_expect_change(); |
877 | break; | 893 | break; |
878 | default: | 894 | default: |
@@ -959,23 +975,17 @@ static int __cpuinit smp_cpu_notify(struct notifier_block *self, | |||
959 | struct device *s = &c->dev; | 975 | struct device *s = &c->dev; |
960 | int err = 0; | 976 | int err = 0; |
961 | 977 | ||
962 | switch (action) { | 978 | switch (action & ~CPU_TASKS_FROZEN) { |
963 | case CPU_ONLINE: | 979 | case CPU_ONLINE: |
964 | case CPU_ONLINE_FROZEN: | ||
965 | err = sysfs_create_group(&s->kobj, &cpu_online_attr_group); | 980 | err = sysfs_create_group(&s->kobj, &cpu_online_attr_group); |
966 | break; | 981 | break; |
967 | case CPU_DEAD: | 982 | case CPU_DEAD: |
968 | case CPU_DEAD_FROZEN: | ||
969 | sysfs_remove_group(&s->kobj, &cpu_online_attr_group); | 983 | sysfs_remove_group(&s->kobj, &cpu_online_attr_group); |
970 | break; | 984 | break; |
971 | } | 985 | } |
972 | return notifier_from_errno(err); | 986 | return notifier_from_errno(err); |
973 | } | 987 | } |
974 | 988 | ||
975 | static struct notifier_block __cpuinitdata smp_cpu_nb = { | ||
976 | .notifier_call = smp_cpu_notify, | ||
977 | }; | ||
978 | |||
979 | static int __devinit smp_add_present_cpu(int cpu) | 989 | static int __devinit smp_add_present_cpu(int cpu) |
980 | { | 990 | { |
981 | struct cpu *c = &pcpu_devices[cpu].cpu; | 991 | struct cpu *c = &pcpu_devices[cpu].cpu; |
@@ -1050,7 +1060,7 @@ static int __init s390_smp_init(void) | |||
1050 | { | 1060 | { |
1051 | int cpu, rc; | 1061 | int cpu, rc; |
1052 | 1062 | ||
1053 | register_cpu_notifier(&smp_cpu_nb); | 1063 | hotcpu_notifier(smp_cpu_notify, 0); |
1054 | #ifdef CONFIG_HOTPLUG_CPU | 1064 | #ifdef CONFIG_HOTPLUG_CPU |
1055 | rc = device_create_file(cpu_subsys.dev_root, &dev_attr_rescan); | 1065 | rc = device_create_file(cpu_subsys.dev_root, &dev_attr_rescan); |
1056 | if (rc) | 1066 | if (rc) |
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S index bcab2f04ba58..48174850f3b0 100644 --- a/arch/s390/kernel/syscalls.S +++ b/arch/s390/kernel/syscalls.S | |||
@@ -350,3 +350,5 @@ SYSCALL(sys_syncfs,sys_syncfs,sys_syncfs_wrapper) | |||
350 | SYSCALL(sys_setns,sys_setns,sys_setns_wrapper) | 350 | SYSCALL(sys_setns,sys_setns,sys_setns_wrapper) |
351 | SYSCALL(sys_process_vm_readv,sys_process_vm_readv,compat_sys_process_vm_readv_wrapper) /* 340 */ | 351 | SYSCALL(sys_process_vm_readv,sys_process_vm_readv,compat_sys_process_vm_readv_wrapper) /* 340 */ |
352 | SYSCALL(sys_process_vm_writev,sys_process_vm_writev,compat_sys_process_vm_writev_wrapper) | 352 | SYSCALL(sys_process_vm_writev,sys_process_vm_writev,compat_sys_process_vm_writev_wrapper) |
353 | SYSCALL(sys_ni_syscall,sys_s390_runtime_instr,sys_s390_runtime_instr_wrapper) | ||
354 | SYSCALL(sys_kcmp,sys_kcmp,sys_kcmp_wrapper) | ||
diff --git a/arch/s390/kernel/sysinfo.c b/arch/s390/kernel/sysinfo.c index fa0eb238dac7..62f89d98e880 100644 --- a/arch/s390/kernel/sysinfo.c +++ b/arch/s390/kernel/sysinfo.c | |||
@@ -22,17 +22,41 @@ | |||
22 | #include <math-emu/soft-fp.h> | 22 | #include <math-emu/soft-fp.h> |
23 | #include <math-emu/single.h> | 23 | #include <math-emu/single.h> |
24 | 24 | ||
25 | static inline int stsi_0(void) | 25 | int topology_max_mnest; |
26 | |||
27 | /* | ||
28 | * stsi - store system information | ||
29 | * | ||
30 | * Returns the current configuration level if function code 0 was specified. | ||
31 | * Otherwise returns 0 on success or a negative value on error. | ||
32 | */ | ||
33 | int stsi(void *sysinfo, int fc, int sel1, int sel2) | ||
26 | { | 34 | { |
27 | int rc = stsi(NULL, 0, 0, 0); | 35 | register int r0 asm("0") = (fc << 28) | sel1; |
28 | return rc == -ENOSYS ? rc : (((unsigned int) rc) >> 28); | 36 | register int r1 asm("1") = sel2; |
37 | int rc = 0; | ||
38 | |||
39 | asm volatile( | ||
40 | " stsi 0(%3)\n" | ||
41 | "0: jz 2f\n" | ||
42 | "1: lhi %1,%4\n" | ||
43 | "2:\n" | ||
44 | EX_TABLE(0b, 1b) | ||
45 | : "+d" (r0), "+d" (rc) | ||
46 | : "d" (r1), "a" (sysinfo), "K" (-EOPNOTSUPP) | ||
47 | : "cc", "memory"); | ||
48 | if (rc) | ||
49 | return rc; | ||
50 | return fc ? 0 : ((unsigned int) r0) >> 28; | ||
29 | } | 51 | } |
52 | EXPORT_SYMBOL(stsi); | ||
30 | 53 | ||
31 | static int stsi_1_1_1(struct sysinfo_1_1_1 *info, char *page, int len) | 54 | static void stsi_1_1_1(struct seq_file *m, struct sysinfo_1_1_1 *info) |
32 | { | 55 | { |
33 | if (stsi(info, 1, 1, 1) == -ENOSYS) | 56 | int i; |
34 | return len; | ||
35 | 57 | ||
58 | if (stsi(info, 1, 1, 1)) | ||
59 | return; | ||
36 | EBCASC(info->manufacturer, sizeof(info->manufacturer)); | 60 | EBCASC(info->manufacturer, sizeof(info->manufacturer)); |
37 | EBCASC(info->type, sizeof(info->type)); | 61 | EBCASC(info->type, sizeof(info->type)); |
38 | EBCASC(info->model, sizeof(info->model)); | 62 | EBCASC(info->model, sizeof(info->model)); |
@@ -41,242 +65,197 @@ static int stsi_1_1_1(struct sysinfo_1_1_1 *info, char *page, int len) | |||
41 | EBCASC(info->model_capacity, sizeof(info->model_capacity)); | 65 | EBCASC(info->model_capacity, sizeof(info->model_capacity)); |
42 | EBCASC(info->model_perm_cap, sizeof(info->model_perm_cap)); | 66 | EBCASC(info->model_perm_cap, sizeof(info->model_perm_cap)); |
43 | EBCASC(info->model_temp_cap, sizeof(info->model_temp_cap)); | 67 | EBCASC(info->model_temp_cap, sizeof(info->model_temp_cap)); |
44 | len += sprintf(page + len, "Manufacturer: %-16.16s\n", | 68 | seq_printf(m, "Manufacturer: %-16.16s\n", info->manufacturer); |
45 | info->manufacturer); | 69 | seq_printf(m, "Type: %-4.4s\n", info->type); |
46 | len += sprintf(page + len, "Type: %-4.4s\n", | 70 | /* |
47 | info->type); | 71 | * Sigh: the model field has been renamed with System z9 |
72 | * to model_capacity and a new model field has been added | ||
73 | * after the plant field. To avoid confusing older programs | ||
74 | * the "Model:" prints "model_capacity model" or just | ||
75 | * "model_capacity" if the model string is empty . | ||
76 | */ | ||
77 | seq_printf(m, "Model: %-16.16s", info->model_capacity); | ||
48 | if (info->model[0] != '\0') | 78 | if (info->model[0] != '\0') |
49 | /* | 79 | seq_printf(m, " %-16.16s", info->model); |
50 | * Sigh: the model field has been renamed with System z9 | 80 | seq_putc(m, '\n'); |
51 | * to model_capacity and a new model field has been added | 81 | seq_printf(m, "Sequence Code: %-16.16s\n", info->sequence); |
52 | * after the plant field. To avoid confusing older programs | 82 | seq_printf(m, "Plant: %-4.4s\n", info->plant); |
53 | * the "Model:" prints "model_capacity model" or just | 83 | seq_printf(m, "Model Capacity: %-16.16s %08u\n", |
54 | * "model_capacity" if the model string is empty . | 84 | info->model_capacity, info->model_cap_rating); |
55 | */ | 85 | if (info->model_perm_cap_rating) |
56 | len += sprintf(page + len, | 86 | seq_printf(m, "Model Perm. Capacity: %-16.16s %08u\n", |
57 | "Model: %-16.16s %-16.16s\n", | 87 | info->model_perm_cap, |
58 | info->model_capacity, info->model); | 88 | info->model_perm_cap_rating); |
59 | else | 89 | if (info->model_temp_cap_rating) |
60 | len += sprintf(page + len, "Model: %-16.16s\n", | 90 | seq_printf(m, "Model Temp. Capacity: %-16.16s %08u\n", |
61 | info->model_capacity); | 91 | info->model_temp_cap, |
62 | len += sprintf(page + len, "Sequence Code: %-16.16s\n", | 92 | info->model_temp_cap_rating); |
63 | info->sequence); | 93 | if (info->ncr) |
64 | len += sprintf(page + len, "Plant: %-4.4s\n", | 94 | seq_printf(m, "Nominal Cap. Rating: %08u\n", info->ncr); |
65 | info->plant); | 95 | if (info->npr) |
66 | len += sprintf(page + len, "Model Capacity: %-16.16s %08u\n", | 96 | seq_printf(m, "Nominal Perm. Rating: %08u\n", info->npr); |
67 | info->model_capacity, *(u32 *) info->model_cap_rating); | 97 | if (info->ntr) |
68 | if (info->model_perm_cap[0] != '\0') | 98 | seq_printf(m, "Nominal Temp. Rating: %08u\n", info->ntr); |
69 | len += sprintf(page + len, | ||
70 | "Model Perm. Capacity: %-16.16s %08u\n", | ||
71 | info->model_perm_cap, | ||
72 | *(u32 *) info->model_perm_cap_rating); | ||
73 | if (info->model_temp_cap[0] != '\0') | ||
74 | len += sprintf(page + len, | ||
75 | "Model Temp. Capacity: %-16.16s %08u\n", | ||
76 | info->model_temp_cap, | ||
77 | *(u32 *) info->model_temp_cap_rating); | ||
78 | if (info->cai) { | 99 | if (info->cai) { |
79 | len += sprintf(page + len, | 100 | seq_printf(m, "Capacity Adj. Ind.: %d\n", info->cai); |
80 | "Capacity Adj. Ind.: %d\n", | 101 | seq_printf(m, "Capacity Ch. Reason: %d\n", info->ccr); |
81 | info->cai); | 102 | seq_printf(m, "Capacity Transient: %d\n", info->t); |
82 | len += sprintf(page + len, "Capacity Ch. Reason: %d\n", | 103 | } |
83 | info->ccr); | 104 | if (info->p) { |
105 | for (i = 1; i <= ARRAY_SIZE(info->typepct); i++) { | ||
106 | seq_printf(m, "Type %d Percentage: %d\n", | ||
107 | i, info->typepct[i - 1]); | ||
108 | } | ||
84 | } | 109 | } |
85 | return len; | ||
86 | } | 110 | } |
87 | 111 | ||
88 | static int stsi_15_1_x(struct sysinfo_15_1_x *info, char *page, int len) | 112 | static void stsi_15_1_x(struct seq_file *m, struct sysinfo_15_1_x *info) |
89 | { | 113 | { |
90 | static int max_mnest; | 114 | static int max_mnest; |
91 | int i, rc; | 115 | int i, rc; |
92 | 116 | ||
93 | len += sprintf(page + len, "\n"); | 117 | seq_putc(m, '\n'); |
94 | if (!MACHINE_HAS_TOPOLOGY) | 118 | if (!MACHINE_HAS_TOPOLOGY) |
95 | return len; | 119 | return; |
96 | if (max_mnest) { | 120 | if (stsi(info, 15, 1, topology_max_mnest)) |
97 | stsi(info, 15, 1, max_mnest); | 121 | return; |
98 | } else { | 122 | seq_printf(m, "CPU Topology HW: "); |
99 | for (max_mnest = 6; max_mnest > 1; max_mnest--) { | ||
100 | rc = stsi(info, 15, 1, max_mnest); | ||
101 | if (rc != -ENOSYS) | ||
102 | break; | ||
103 | } | ||
104 | } | ||
105 | len += sprintf(page + len, "CPU Topology HW: "); | ||
106 | for (i = 0; i < TOPOLOGY_NR_MAG; i++) | 123 | for (i = 0; i < TOPOLOGY_NR_MAG; i++) |
107 | len += sprintf(page + len, " %d", info->mag[i]); | 124 | seq_printf(m, " %d", info->mag[i]); |
108 | len += sprintf(page + len, "\n"); | 125 | seq_putc(m, '\n'); |
109 | #ifdef CONFIG_SCHED_MC | 126 | #ifdef CONFIG_SCHED_MC |
110 | store_topology(info); | 127 | store_topology(info); |
111 | len += sprintf(page + len, "CPU Topology SW: "); | 128 | seq_printf(m, "CPU Topology SW: "); |
112 | for (i = 0; i < TOPOLOGY_NR_MAG; i++) | 129 | for (i = 0; i < TOPOLOGY_NR_MAG; i++) |
113 | len += sprintf(page + len, " %d", info->mag[i]); | 130 | seq_printf(m, " %d", info->mag[i]); |
114 | len += sprintf(page + len, "\n"); | 131 | seq_putc(m, '\n'); |
115 | #endif | 132 | #endif |
116 | return len; | ||
117 | } | 133 | } |
118 | 134 | ||
119 | static int stsi_1_2_2(struct sysinfo_1_2_2 *info, char *page, int len) | 135 | static void stsi_1_2_2(struct seq_file *m, struct sysinfo_1_2_2 *info) |
120 | { | 136 | { |
121 | struct sysinfo_1_2_2_extension *ext; | 137 | struct sysinfo_1_2_2_extension *ext; |
122 | int i; | 138 | int i; |
123 | 139 | ||
124 | if (stsi(info, 1, 2, 2) == -ENOSYS) | 140 | if (stsi(info, 1, 2, 2)) |
125 | return len; | 141 | return; |
126 | ext = (struct sysinfo_1_2_2_extension *) | 142 | ext = (struct sysinfo_1_2_2_extension *) |
127 | ((unsigned long) info + info->acc_offset); | 143 | ((unsigned long) info + info->acc_offset); |
128 | 144 | seq_printf(m, "CPUs Total: %d\n", info->cpus_total); | |
129 | len += sprintf(page + len, "CPUs Total: %d\n", | 145 | seq_printf(m, "CPUs Configured: %d\n", info->cpus_configured); |
130 | info->cpus_total); | 146 | seq_printf(m, "CPUs Standby: %d\n", info->cpus_standby); |
131 | len += sprintf(page + len, "CPUs Configured: %d\n", | 147 | seq_printf(m, "CPUs Reserved: %d\n", info->cpus_reserved); |
132 | info->cpus_configured); | 148 | /* |
133 | len += sprintf(page + len, "CPUs Standby: %d\n", | 149 | * Sigh 2. According to the specification the alternate |
134 | info->cpus_standby); | 150 | * capability field is a 32 bit floating point number |
135 | len += sprintf(page + len, "CPUs Reserved: %d\n", | 151 | * if the higher order 8 bits are not zero. Printing |
136 | info->cpus_reserved); | 152 | * a floating point number in the kernel is a no-no, |
137 | 153 | * always print the number as 32 bit unsigned integer. | |
138 | if (info->format == 1) { | 154 | * The user-space needs to know about the strange |
139 | /* | 155 | * encoding of the alternate cpu capability. |
140 | * Sigh 2. According to the specification the alternate | 156 | */ |
141 | * capability field is a 32 bit floating point number | 157 | seq_printf(m, "Capability: %u", info->capability); |
142 | * if the higher order 8 bits are not zero. Printing | 158 | if (info->format == 1) |
143 | * a floating point number in the kernel is a no-no, | 159 | seq_printf(m, " %u", ext->alt_capability); |
144 | * always print the number as 32 bit unsigned integer. | 160 | seq_putc(m, '\n'); |
145 | * The user-space needs to know about the strange | 161 | if (info->nominal_cap) |
146 | * encoding of the alternate cpu capability. | 162 | seq_printf(m, "Nominal Capability: %d\n", info->nominal_cap); |
147 | */ | 163 | if (info->secondary_cap) |
148 | len += sprintf(page + len, "Capability: %u %u\n", | 164 | seq_printf(m, "Secondary Capability: %d\n", info->secondary_cap); |
149 | info->capability, ext->alt_capability); | 165 | for (i = 2; i <= info->cpus_total; i++) { |
150 | for (i = 2; i <= info->cpus_total; i++) | 166 | seq_printf(m, "Adjustment %02d-way: %u", |
151 | len += sprintf(page + len, | 167 | i, info->adjustment[i-2]); |
152 | "Adjustment %02d-way: %u %u\n", | 168 | if (info->format == 1) |
153 | i, info->adjustment[i-2], | 169 | seq_printf(m, " %u", ext->alt_adjustment[i-2]); |
154 | ext->alt_adjustment[i-2]); | 170 | seq_putc(m, '\n'); |
155 | |||
156 | } else { | ||
157 | len += sprintf(page + len, "Capability: %u\n", | ||
158 | info->capability); | ||
159 | for (i = 2; i <= info->cpus_total; i++) | ||
160 | len += sprintf(page + len, | ||
161 | "Adjustment %02d-way: %u\n", | ||
162 | i, info->adjustment[i-2]); | ||
163 | } | 171 | } |
164 | |||
165 | if (info->secondary_capability != 0) | ||
166 | len += sprintf(page + len, "Secondary Capability: %d\n", | ||
167 | info->secondary_capability); | ||
168 | return len; | ||
169 | } | 172 | } |
170 | 173 | ||
171 | static int stsi_2_2_2(struct sysinfo_2_2_2 *info, char *page, int len) | 174 | static void stsi_2_2_2(struct seq_file *m, struct sysinfo_2_2_2 *info) |
172 | { | 175 | { |
173 | if (stsi(info, 2, 2, 2) == -ENOSYS) | 176 | if (stsi(info, 2, 2, 2)) |
174 | return len; | 177 | return; |
175 | |||
176 | EBCASC(info->name, sizeof(info->name)); | 178 | EBCASC(info->name, sizeof(info->name)); |
177 | 179 | seq_putc(m, '\n'); | |
178 | len += sprintf(page + len, "\n"); | 180 | seq_printf(m, "LPAR Number: %d\n", info->lpar_number); |
179 | len += sprintf(page + len, "LPAR Number: %d\n", | 181 | seq_printf(m, "LPAR Characteristics: "); |
180 | info->lpar_number); | ||
181 | |||
182 | len += sprintf(page + len, "LPAR Characteristics: "); | ||
183 | if (info->characteristics & LPAR_CHAR_DEDICATED) | 182 | if (info->characteristics & LPAR_CHAR_DEDICATED) |
184 | len += sprintf(page + len, "Dedicated "); | 183 | seq_printf(m, "Dedicated "); |
185 | if (info->characteristics & LPAR_CHAR_SHARED) | 184 | if (info->characteristics & LPAR_CHAR_SHARED) |
186 | len += sprintf(page + len, "Shared "); | 185 | seq_printf(m, "Shared "); |
187 | if (info->characteristics & LPAR_CHAR_LIMITED) | 186 | if (info->characteristics & LPAR_CHAR_LIMITED) |
188 | len += sprintf(page + len, "Limited "); | 187 | seq_printf(m, "Limited "); |
189 | len += sprintf(page + len, "\n"); | 188 | seq_putc(m, '\n'); |
190 | 189 | seq_printf(m, "LPAR Name: %-8.8s\n", info->name); | |
191 | len += sprintf(page + len, "LPAR Name: %-8.8s\n", | 190 | seq_printf(m, "LPAR Adjustment: %d\n", info->caf); |
192 | info->name); | 191 | seq_printf(m, "LPAR CPUs Total: %d\n", info->cpus_total); |
193 | 192 | seq_printf(m, "LPAR CPUs Configured: %d\n", info->cpus_configured); | |
194 | len += sprintf(page + len, "LPAR Adjustment: %d\n", | 193 | seq_printf(m, "LPAR CPUs Standby: %d\n", info->cpus_standby); |
195 | info->caf); | 194 | seq_printf(m, "LPAR CPUs Reserved: %d\n", info->cpus_reserved); |
196 | 195 | seq_printf(m, "LPAR CPUs Dedicated: %d\n", info->cpus_dedicated); | |
197 | len += sprintf(page + len, "LPAR CPUs Total: %d\n", | 196 | seq_printf(m, "LPAR CPUs Shared: %d\n", info->cpus_shared); |
198 | info->cpus_total); | ||
199 | len += sprintf(page + len, "LPAR CPUs Configured: %d\n", | ||
200 | info->cpus_configured); | ||
201 | len += sprintf(page + len, "LPAR CPUs Standby: %d\n", | ||
202 | info->cpus_standby); | ||
203 | len += sprintf(page + len, "LPAR CPUs Reserved: %d\n", | ||
204 | info->cpus_reserved); | ||
205 | len += sprintf(page + len, "LPAR CPUs Dedicated: %d\n", | ||
206 | info->cpus_dedicated); | ||
207 | len += sprintf(page + len, "LPAR CPUs Shared: %d\n", | ||
208 | info->cpus_shared); | ||
209 | return len; | ||
210 | } | 197 | } |
211 | 198 | ||
212 | static int stsi_3_2_2(struct sysinfo_3_2_2 *info, char *page, int len) | 199 | static void stsi_3_2_2(struct seq_file *m, struct sysinfo_3_2_2 *info) |
213 | { | 200 | { |
214 | int i; | 201 | int i; |
215 | 202 | ||
216 | if (stsi(info, 3, 2, 2) == -ENOSYS) | 203 | if (stsi(info, 3, 2, 2)) |
217 | return len; | 204 | return; |
218 | for (i = 0; i < info->count; i++) { | 205 | for (i = 0; i < info->count; i++) { |
219 | EBCASC(info->vm[i].name, sizeof(info->vm[i].name)); | 206 | EBCASC(info->vm[i].name, sizeof(info->vm[i].name)); |
220 | EBCASC(info->vm[i].cpi, sizeof(info->vm[i].cpi)); | 207 | EBCASC(info->vm[i].cpi, sizeof(info->vm[i].cpi)); |
221 | len += sprintf(page + len, "\n"); | 208 | seq_putc(m, '\n'); |
222 | len += sprintf(page + len, "VM%02d Name: %-8.8s\n", | 209 | seq_printf(m, "VM%02d Name: %-8.8s\n", i, info->vm[i].name); |
223 | i, info->vm[i].name); | 210 | seq_printf(m, "VM%02d Control Program: %-16.16s\n", i, info->vm[i].cpi); |
224 | len += sprintf(page + len, "VM%02d Control Program: %-16.16s\n", | 211 | seq_printf(m, "VM%02d Adjustment: %d\n", i, info->vm[i].caf); |
225 | i, info->vm[i].cpi); | 212 | seq_printf(m, "VM%02d CPUs Total: %d\n", i, info->vm[i].cpus_total); |
226 | 213 | seq_printf(m, "VM%02d CPUs Configured: %d\n", i, info->vm[i].cpus_configured); | |
227 | len += sprintf(page + len, "VM%02d Adjustment: %d\n", | 214 | seq_printf(m, "VM%02d CPUs Standby: %d\n", i, info->vm[i].cpus_standby); |
228 | i, info->vm[i].caf); | 215 | seq_printf(m, "VM%02d CPUs Reserved: %d\n", i, info->vm[i].cpus_reserved); |
229 | |||
230 | len += sprintf(page + len, "VM%02d CPUs Total: %d\n", | ||
231 | i, info->vm[i].cpus_total); | ||
232 | len += sprintf(page + len, "VM%02d CPUs Configured: %d\n", | ||
233 | i, info->vm[i].cpus_configured); | ||
234 | len += sprintf(page + len, "VM%02d CPUs Standby: %d\n", | ||
235 | i, info->vm[i].cpus_standby); | ||
236 | len += sprintf(page + len, "VM%02d CPUs Reserved: %d\n", | ||
237 | i, info->vm[i].cpus_reserved); | ||
238 | } | 216 | } |
239 | return len; | ||
240 | } | 217 | } |
241 | 218 | ||
242 | static int proc_read_sysinfo(char *page, char **start, | 219 | static int sysinfo_show(struct seq_file *m, void *v) |
243 | off_t off, int count, | ||
244 | int *eof, void *data) | ||
245 | { | 220 | { |
246 | unsigned long info = get_zeroed_page(GFP_KERNEL); | 221 | void *info = (void *)get_zeroed_page(GFP_KERNEL); |
247 | int level, len; | 222 | int level; |
248 | 223 | ||
249 | if (!info) | 224 | if (!info) |
250 | return 0; | 225 | return 0; |
251 | 226 | level = stsi(NULL, 0, 0, 0); | |
252 | len = 0; | ||
253 | level = stsi_0(); | ||
254 | if (level >= 1) | 227 | if (level >= 1) |
255 | len = stsi_1_1_1((struct sysinfo_1_1_1 *) info, page, len); | 228 | stsi_1_1_1(m, info); |
256 | |||
257 | if (level >= 1) | 229 | if (level >= 1) |
258 | len = stsi_15_1_x((struct sysinfo_15_1_x *) info, page, len); | 230 | stsi_15_1_x(m, info); |
259 | |||
260 | if (level >= 1) | 231 | if (level >= 1) |
261 | len = stsi_1_2_2((struct sysinfo_1_2_2 *) info, page, len); | 232 | stsi_1_2_2(m, info); |
262 | |||
263 | if (level >= 2) | 233 | if (level >= 2) |
264 | len = stsi_2_2_2((struct sysinfo_2_2_2 *) info, page, len); | 234 | stsi_2_2_2(m, info); |
265 | |||
266 | if (level >= 3) | 235 | if (level >= 3) |
267 | len = stsi_3_2_2((struct sysinfo_3_2_2 *) info, page, len); | 236 | stsi_3_2_2(m, info); |
237 | free_page((unsigned long)info); | ||
238 | return 0; | ||
239 | } | ||
268 | 240 | ||
269 | free_page(info); | 241 | static int sysinfo_open(struct inode *inode, struct file *file) |
270 | return len; | 242 | { |
243 | return single_open(file, sysinfo_show, NULL); | ||
271 | } | 244 | } |
272 | 245 | ||
273 | static __init int create_proc_sysinfo(void) | 246 | static const struct file_operations sysinfo_fops = { |
247 | .open = sysinfo_open, | ||
248 | .read = seq_read, | ||
249 | .llseek = seq_lseek, | ||
250 | .release = single_release, | ||
251 | }; | ||
252 | |||
253 | static int __init sysinfo_create_proc(void) | ||
274 | { | 254 | { |
275 | create_proc_read_entry("sysinfo", 0444, NULL, | 255 | proc_create("sysinfo", 0444, NULL, &sysinfo_fops); |
276 | proc_read_sysinfo, NULL); | ||
277 | return 0; | 256 | return 0; |
278 | } | 257 | } |
279 | device_initcall(create_proc_sysinfo); | 258 | device_initcall(sysinfo_create_proc); |
280 | 259 | ||
281 | /* | 260 | /* |
282 | * Service levels interface. | 261 | * Service levels interface. |
@@ -407,7 +386,7 @@ void s390_adjust_jiffies(void) | |||
407 | if (!info) | 386 | if (!info) |
408 | return; | 387 | return; |
409 | 388 | ||
410 | if (stsi(info, 1, 2, 2) != -ENOSYS) { | 389 | if (stsi(info, 1, 2, 2) == 0) { |
411 | /* | 390 | /* |
412 | * Major sigh. The cpu capability encoding is "special". | 391 | * Major sigh. The cpu capability encoding is "special". |
413 | * If the first 9 bits of info->capability are 0 then it | 392 | * If the first 9 bits of info->capability are 0 then it |
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index dcec960fc724..2db1011b8b19 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c | |||
@@ -329,7 +329,7 @@ static unsigned long clock_sync_flags; | |||
329 | * The synchronous get_clock function. It will write the current clock | 329 | * The synchronous get_clock function. It will write the current clock |
330 | * value to the clock pointer and return 0 if the clock is in sync with | 330 | * value to the clock pointer and return 0 if the clock is in sync with |
331 | * the external time source. If the clock mode is local it will return | 331 | * the external time source. If the clock mode is local it will return |
332 | * -ENOSYS and -EAGAIN if the clock is not in sync with the external | 332 | * -EOPNOTSUPP and -EAGAIN if the clock is not in sync with the external |
333 | * reference. | 333 | * reference. |
334 | */ | 334 | */ |
335 | int get_sync_clock(unsigned long long *clock) | 335 | int get_sync_clock(unsigned long long *clock) |
@@ -347,7 +347,7 @@ int get_sync_clock(unsigned long long *clock) | |||
347 | return 0; | 347 | return 0; |
348 | if (!test_bit(CLOCK_SYNC_HAS_ETR, &clock_sync_flags) && | 348 | if (!test_bit(CLOCK_SYNC_HAS_ETR, &clock_sync_flags) && |
349 | !test_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags)) | 349 | !test_bit(CLOCK_SYNC_HAS_STP, &clock_sync_flags)) |
350 | return -ENOSYS; | 350 | return -EOPNOTSUPP; |
351 | if (!test_bit(CLOCK_SYNC_ETR, &clock_sync_flags) && | 351 | if (!test_bit(CLOCK_SYNC_ETR, &clock_sync_flags) && |
352 | !test_bit(CLOCK_SYNC_STP, &clock_sync_flags)) | 352 | !test_bit(CLOCK_SYNC_STP, &clock_sync_flags)) |
353 | return -EACCES; | 353 | return -EACCES; |
diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c index 05151e06c388..54d93f4b6818 100644 --- a/arch/s390/kernel/topology.c +++ b/arch/s390/kernel/topology.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/cpu.h> | 17 | #include <linux/cpu.h> |
18 | #include <linux/smp.h> | 18 | #include <linux/smp.h> |
19 | #include <linux/mm.h> | 19 | #include <linux/mm.h> |
20 | #include <asm/sysinfo.h> | ||
20 | 21 | ||
21 | #define PTF_HORIZONTAL (0UL) | 22 | #define PTF_HORIZONTAL (0UL) |
22 | #define PTF_VERTICAL (1UL) | 23 | #define PTF_VERTICAL (1UL) |
@@ -44,9 +45,6 @@ static struct mask_info book_info; | |||
44 | cpumask_t cpu_book_map[NR_CPUS]; | 45 | cpumask_t cpu_book_map[NR_CPUS]; |
45 | unsigned char cpu_book_id[NR_CPUS]; | 46 | unsigned char cpu_book_id[NR_CPUS]; |
46 | 47 | ||
47 | /* smp_cpu_state_mutex must be held when accessing this array */ | ||
48 | int cpu_polarization[NR_CPUS]; | ||
49 | |||
50 | 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) |
51 | { | 49 | { |
52 | cpumask_t mask; | 50 | cpumask_t mask; |
@@ -75,10 +73,7 @@ static struct mask_info *add_cpus_to_mask(struct topology_cpu *tl_cpu, | |||
75 | { | 73 | { |
76 | unsigned int cpu; | 74 | unsigned int cpu; |
77 | 75 | ||
78 | for (cpu = find_first_bit(&tl_cpu->mask[0], TOPOLOGY_CPU_BITS); | 76 | for_each_set_bit(cpu, &tl_cpu->mask[0], TOPOLOGY_CPU_BITS) { |
79 | cpu < TOPOLOGY_CPU_BITS; | ||
80 | cpu = find_next_bit(&tl_cpu->mask[0], TOPOLOGY_CPU_BITS, cpu + 1)) | ||
81 | { | ||
82 | unsigned int rcpu; | 77 | unsigned int rcpu; |
83 | int lcpu; | 78 | int lcpu; |
84 | 79 | ||
@@ -94,7 +89,7 @@ static struct mask_info *add_cpus_to_mask(struct topology_cpu *tl_cpu, | |||
94 | } else { | 89 | } else { |
95 | cpu_core_id[lcpu] = core->id; | 90 | cpu_core_id[lcpu] = core->id; |
96 | } | 91 | } |
97 | cpu_set_polarization(lcpu, tl_cpu->pp); | 92 | smp_cpu_set_polarization(lcpu, tl_cpu->pp); |
98 | } | 93 | } |
99 | } | 94 | } |
100 | return core; | 95 | return core; |
@@ -201,7 +196,7 @@ static void topology_update_polarization_simple(void) | |||
201 | 196 | ||
202 | mutex_lock(&smp_cpu_state_mutex); | 197 | mutex_lock(&smp_cpu_state_mutex); |
203 | for_each_possible_cpu(cpu) | 198 | for_each_possible_cpu(cpu) |
204 | cpu_set_polarization(cpu, POLARIZATION_HRZ); | 199 | smp_cpu_set_polarization(cpu, POLARIZATION_HRZ); |
205 | mutex_unlock(&smp_cpu_state_mutex); | 200 | mutex_unlock(&smp_cpu_state_mutex); |
206 | } | 201 | } |
207 | 202 | ||
@@ -231,7 +226,7 @@ int topology_set_cpu_management(int fc) | |||
231 | if (rc) | 226 | if (rc) |
232 | return -EBUSY; | 227 | return -EBUSY; |
233 | for_each_possible_cpu(cpu) | 228 | for_each_possible_cpu(cpu) |
234 | cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); | 229 | smp_cpu_set_polarization(cpu, POLARIZATION_UNKNOWN); |
235 | return rc; | 230 | return rc; |
236 | } | 231 | } |
237 | 232 | ||
@@ -250,12 +245,10 @@ static void update_cpu_core_map(void) | |||
250 | 245 | ||
251 | void store_topology(struct sysinfo_15_1_x *info) | 246 | void store_topology(struct sysinfo_15_1_x *info) |
252 | { | 247 | { |
253 | int rc; | 248 | if (topology_max_mnest >= 3) |
254 | 249 | stsi(info, 15, 1, 3); | |
255 | rc = stsi(info, 15, 1, 3); | 250 | else |
256 | if (rc != -ENOSYS) | 251 | stsi(info, 15, 1, 2); |
257 | return; | ||
258 | stsi(info, 15, 1, 2); | ||
259 | } | 252 | } |
260 | 253 | ||
261 | int arch_update_cpu_topology(void) | 254 | int arch_update_cpu_topology(void) |
@@ -415,7 +408,7 @@ static ssize_t cpu_polarization_show(struct device *dev, | |||
415 | ssize_t count; | 408 | ssize_t count; |
416 | 409 | ||
417 | mutex_lock(&smp_cpu_state_mutex); | 410 | mutex_lock(&smp_cpu_state_mutex); |
418 | switch (cpu_read_polarization(cpu)) { | 411 | switch (smp_cpu_get_polarization(cpu)) { |
419 | case POLARIZATION_HRZ: | 412 | case POLARIZATION_HRZ: |
420 | count = sprintf(buf, "horizontal\n"); | 413 | count = sprintf(buf, "horizontal\n"); |
421 | break; | 414 | break; |
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index 01775c04a90e..3d2b0fa37db0 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c | |||
@@ -57,6 +57,23 @@ static int kstack_depth_to_print = 12; | |||
57 | static int kstack_depth_to_print = 20; | 57 | static int kstack_depth_to_print = 20; |
58 | #endif /* CONFIG_64BIT */ | 58 | #endif /* CONFIG_64BIT */ |
59 | 59 | ||
60 | static inline void __user *get_trap_ip(struct pt_regs *regs) | ||
61 | { | ||
62 | #ifdef CONFIG_64BIT | ||
63 | unsigned long address; | ||
64 | |||
65 | if (regs->int_code & 0x200) | ||
66 | address = *(unsigned long *)(current->thread.trap_tdb + 24); | ||
67 | else | ||
68 | address = regs->psw.addr; | ||
69 | return (void __user *) | ||
70 | ((address - (regs->int_code >> 16)) & PSW_ADDR_INSN); | ||
71 | #else | ||
72 | return (void __user *) | ||
73 | ((regs->psw.addr - (regs->int_code >> 16)) & PSW_ADDR_INSN); | ||
74 | #endif | ||
75 | } | ||
76 | |||
60 | /* | 77 | /* |
61 | * For show_trace we have tree different stack to consider: | 78 | * For show_trace we have tree different stack to consider: |
62 | * - the panic stack which is used if the kernel stack has overflown | 79 | * - the panic stack which is used if the kernel stack has overflown |
@@ -214,7 +231,6 @@ void show_registers(struct pt_regs *regs) | |||
214 | 231 | ||
215 | void show_regs(struct pt_regs *regs) | 232 | void show_regs(struct pt_regs *regs) |
216 | { | 233 | { |
217 | print_modules(); | ||
218 | printk("CPU: %d %s %s %.*s\n", | 234 | printk("CPU: %d %s %s %.*s\n", |
219 | task_thread_info(current)->cpu, print_tainted(), | 235 | task_thread_info(current)->cpu, print_tainted(), |
220 | init_utsname()->release, | 236 | init_utsname()->release, |
@@ -254,6 +270,7 @@ void die(struct pt_regs *regs, const char *str) | |||
254 | #endif | 270 | #endif |
255 | printk("\n"); | 271 | printk("\n"); |
256 | notify_die(DIE_OOPS, str, regs, 0, regs->int_code & 0xffff, SIGSEGV); | 272 | notify_die(DIE_OOPS, str, regs, 0, regs->int_code & 0xffff, SIGSEGV); |
273 | print_modules(); | ||
257 | show_regs(regs); | 274 | show_regs(regs); |
258 | bust_spinlocks(0); | 275 | bust_spinlocks(0); |
259 | add_taint(TAINT_DIE); | 276 | add_taint(TAINT_DIE); |
@@ -285,12 +302,6 @@ int is_valid_bugaddr(unsigned long addr) | |||
285 | return 1; | 302 | return 1; |
286 | } | 303 | } |
287 | 304 | ||
288 | static inline void __user *get_psw_address(struct pt_regs *regs) | ||
289 | { | ||
290 | return (void __user *) | ||
291 | ((regs->psw.addr - (regs->int_code >> 16)) & PSW_ADDR_INSN); | ||
292 | } | ||
293 | |||
294 | static void __kprobes do_trap(struct pt_regs *regs, | 305 | static void __kprobes do_trap(struct pt_regs *regs, |
295 | int si_signo, int si_code, char *str) | 306 | int si_signo, int si_code, char *str) |
296 | { | 307 | { |
@@ -304,14 +315,14 @@ static void __kprobes do_trap(struct pt_regs *regs, | |||
304 | info.si_signo = si_signo; | 315 | info.si_signo = si_signo; |
305 | info.si_errno = 0; | 316 | info.si_errno = 0; |
306 | info.si_code = si_code; | 317 | info.si_code = si_code; |
307 | info.si_addr = get_psw_address(regs); | 318 | info.si_addr = get_trap_ip(regs); |
308 | force_sig_info(si_signo, &info, current); | 319 | force_sig_info(si_signo, &info, current); |
309 | report_user_fault(regs, si_signo); | 320 | report_user_fault(regs, si_signo); |
310 | } else { | 321 | } else { |
311 | const struct exception_table_entry *fixup; | 322 | const struct exception_table_entry *fixup; |
312 | fixup = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN); | 323 | fixup = search_exception_tables(regs->psw.addr & PSW_ADDR_INSN); |
313 | if (fixup) | 324 | if (fixup) |
314 | regs->psw.addr = fixup->fixup | PSW_ADDR_AMODE; | 325 | regs->psw.addr = extable_fixup(fixup) | PSW_ADDR_AMODE; |
315 | else { | 326 | else { |
316 | enum bug_trap_type btt; | 327 | enum bug_trap_type btt; |
317 | 328 | ||
@@ -381,6 +392,11 @@ DO_ERROR_INFO(special_op_exception, SIGILL, ILL_ILLOPN, | |||
381 | DO_ERROR_INFO(translation_exception, SIGILL, ILL_ILLOPN, | 392 | DO_ERROR_INFO(translation_exception, SIGILL, ILL_ILLOPN, |
382 | "translation exception") | 393 | "translation exception") |
383 | 394 | ||
395 | #ifdef CONFIG_64BIT | ||
396 | DO_ERROR_INFO(transaction_exception, SIGILL, ILL_ILLOPN, | ||
397 | "transaction constraint exception") | ||
398 | #endif | ||
399 | |||
384 | static inline void do_fp_trap(struct pt_regs *regs, int fpc) | 400 | static inline void do_fp_trap(struct pt_regs *regs, int fpc) |
385 | { | 401 | { |
386 | int si_code = 0; | 402 | int si_code = 0; |
@@ -408,7 +424,7 @@ static void __kprobes illegal_op(struct pt_regs *regs) | |||
408 | __u16 __user *location; | 424 | __u16 __user *location; |
409 | int signal = 0; | 425 | int signal = 0; |
410 | 426 | ||
411 | location = get_psw_address(regs); | 427 | location = get_trap_ip(regs); |
412 | 428 | ||
413 | if (user_mode(regs)) { | 429 | if (user_mode(regs)) { |
414 | if (get_user(*((__u16 *) opcode), (__u16 __user *) location)) | 430 | if (get_user(*((__u16 *) opcode), (__u16 __user *) location)) |
@@ -476,7 +492,7 @@ void specification_exception(struct pt_regs *regs) | |||
476 | __u16 __user *location = NULL; | 492 | __u16 __user *location = NULL; |
477 | int signal = 0; | 493 | int signal = 0; |
478 | 494 | ||
479 | location = (__u16 __user *) get_psw_address(regs); | 495 | location = (__u16 __user *) get_trap_ip(regs); |
480 | 496 | ||
481 | if (user_mode(regs)) { | 497 | if (user_mode(regs)) { |
482 | get_user(*((__u16 *) opcode), location); | 498 | get_user(*((__u16 *) opcode), location); |
@@ -525,7 +541,7 @@ static void data_exception(struct pt_regs *regs) | |||
525 | __u16 __user *location; | 541 | __u16 __user *location; |
526 | int signal = 0; | 542 | int signal = 0; |
527 | 543 | ||
528 | location = get_psw_address(regs); | 544 | location = get_trap_ip(regs); |
529 | 545 | ||
530 | if (MACHINE_HAS_IEEE) | 546 | if (MACHINE_HAS_IEEE) |
531 | asm volatile("stfpc %0" : "=m" (current->thread.fp_regs.fpc)); | 547 | asm volatile("stfpc %0" : "=m" (current->thread.fp_regs.fpc)); |
@@ -641,6 +657,7 @@ void __init trap_init(void) | |||
641 | pgm_check_table[0x12] = &translation_exception; | 657 | pgm_check_table[0x12] = &translation_exception; |
642 | pgm_check_table[0x13] = &special_op_exception; | 658 | pgm_check_table[0x13] = &special_op_exception; |
643 | #ifdef CONFIG_64BIT | 659 | #ifdef CONFIG_64BIT |
660 | pgm_check_table[0x18] = &transaction_exception; | ||
644 | pgm_check_table[0x38] = &do_asce_exception; | 661 | pgm_check_table[0x38] = &do_asce_exception; |
645 | pgm_check_table[0x39] = &do_dat_exception; | 662 | pgm_check_table[0x39] = &do_dat_exception; |
646 | pgm_check_table[0x3A] = &do_dat_exception; | 663 | pgm_check_table[0x3A] = &do_dat_exception; |
diff --git a/arch/s390/kernel/vdso.c b/arch/s390/kernel/vdso.c index 9a19ca367c17..d7776281cb60 100644 --- a/arch/s390/kernel/vdso.c +++ b/arch/s390/kernel/vdso.c | |||
@@ -85,7 +85,7 @@ struct vdso_data *vdso_data = &vdso_data_store.data; | |||
85 | static void vdso_init_data(struct vdso_data *vd) | 85 | static void vdso_init_data(struct vdso_data *vd) |
86 | { | 86 | { |
87 | vd->ectg_available = | 87 | vd->ectg_available = |
88 | addressing_mode != HOME_SPACE_MODE && test_facility(31); | 88 | s390_user_mode != HOME_SPACE_MODE && test_facility(31); |
89 | } | 89 | } |
90 | 90 | ||
91 | #ifdef CONFIG_64BIT | 91 | #ifdef CONFIG_64BIT |
@@ -102,7 +102,7 @@ int vdso_alloc_per_cpu(struct _lowcore *lowcore) | |||
102 | 102 | ||
103 | lowcore->vdso_per_cpu_data = __LC_PASTE; | 103 | lowcore->vdso_per_cpu_data = __LC_PASTE; |
104 | 104 | ||
105 | if (addressing_mode == HOME_SPACE_MODE || !vdso_enabled) | 105 | if (s390_user_mode == HOME_SPACE_MODE || !vdso_enabled) |
106 | return 0; | 106 | return 0; |
107 | 107 | ||
108 | segment_table = __get_free_pages(GFP_KERNEL, SEGMENT_ORDER); | 108 | segment_table = __get_free_pages(GFP_KERNEL, SEGMENT_ORDER); |
@@ -147,7 +147,7 @@ void vdso_free_per_cpu(struct _lowcore *lowcore) | |||
147 | unsigned long segment_table, page_table, page_frame; | 147 | unsigned long segment_table, page_table, page_frame; |
148 | u32 *psal, *aste; | 148 | u32 *psal, *aste; |
149 | 149 | ||
150 | if (addressing_mode == HOME_SPACE_MODE || !vdso_enabled) | 150 | if (s390_user_mode == HOME_SPACE_MODE || !vdso_enabled) |
151 | return; | 151 | return; |
152 | 152 | ||
153 | psal = (u32 *)(addr_t) lowcore->paste[4]; | 153 | psal = (u32 *)(addr_t) lowcore->paste[4]; |
@@ -165,7 +165,7 @@ static void vdso_init_cr5(void) | |||
165 | { | 165 | { |
166 | unsigned long cr5; | 166 | unsigned long cr5; |
167 | 167 | ||
168 | if (addressing_mode == HOME_SPACE_MODE || !vdso_enabled) | 168 | if (s390_user_mode == HOME_SPACE_MODE || !vdso_enabled) |
169 | return; | 169 | return; |
170 | cr5 = offsetof(struct _lowcore, paste); | 170 | cr5 = offsetof(struct _lowcore, paste); |
171 | __ctl_load(cr5, 5, 5); | 171 | __ctl_load(cr5, 5, 5); |
diff --git a/arch/s390/kernel/vtime.c b/arch/s390/kernel/vtime.c index 4fc97b40a6e1..790334427895 100644 --- a/arch/s390/kernel/vtime.c +++ b/arch/s390/kernel/vtime.c | |||
@@ -99,7 +99,7 @@ static int do_account_vtime(struct task_struct *tsk, int hardirq_offset) | |||
99 | return virt_timer_forward(user + system); | 99 | return virt_timer_forward(user + system); |
100 | } | 100 | } |
101 | 101 | ||
102 | void account_vtime(struct task_struct *prev, struct task_struct *next) | 102 | void vtime_task_switch(struct task_struct *prev) |
103 | { | 103 | { |
104 | struct thread_info *ti; | 104 | struct thread_info *ti; |
105 | 105 | ||
@@ -107,7 +107,7 @@ void account_vtime(struct task_struct *prev, struct task_struct *next) | |||
107 | ti = task_thread_info(prev); | 107 | ti = task_thread_info(prev); |
108 | ti->user_timer = S390_lowcore.user_timer; | 108 | ti->user_timer = S390_lowcore.user_timer; |
109 | ti->system_timer = S390_lowcore.system_timer; | 109 | ti->system_timer = S390_lowcore.system_timer; |
110 | ti = task_thread_info(next); | 110 | ti = task_thread_info(current); |
111 | S390_lowcore.user_timer = ti->user_timer; | 111 | S390_lowcore.user_timer = ti->user_timer; |
112 | S390_lowcore.system_timer = ti->system_timer; | 112 | S390_lowcore.system_timer = ti->system_timer; |
113 | } | 113 | } |
@@ -122,7 +122,7 @@ void account_process_tick(struct task_struct *tsk, int user_tick) | |||
122 | * Update process times based on virtual cpu times stored by entry.S | 122 | * Update process times based on virtual cpu times stored by entry.S |
123 | * to the lowcore fields user_timer, system_timer & steal_clock. | 123 | * to the lowcore fields user_timer, system_timer & steal_clock. |
124 | */ | 124 | */ |
125 | void account_system_vtime(struct task_struct *tsk) | 125 | void vtime_account(struct task_struct *tsk) |
126 | { | 126 | { |
127 | struct thread_info *ti = task_thread_info(tsk); | 127 | struct thread_info *ti = task_thread_info(tsk); |
128 | u64 timer, system; | 128 | u64 timer, system; |
@@ -138,7 +138,7 @@ void account_system_vtime(struct task_struct *tsk) | |||
138 | 138 | ||
139 | virt_timer_forward(system); | 139 | virt_timer_forward(system); |
140 | } | 140 | } |
141 | EXPORT_SYMBOL_GPL(account_system_vtime); | 141 | EXPORT_SYMBOL_GPL(vtime_account); |
142 | 142 | ||
143 | void __kprobes vtime_stop_cpu(void) | 143 | void __kprobes vtime_stop_cpu(void) |
144 | { | 144 | { |
@@ -378,9 +378,8 @@ static int __cpuinit s390_nohz_notify(struct notifier_block *self, | |||
378 | long cpu = (long) hcpu; | 378 | long cpu = (long) hcpu; |
379 | 379 | ||
380 | idle = &per_cpu(s390_idle, cpu); | 380 | idle = &per_cpu(s390_idle, cpu); |
381 | switch (action) { | 381 | switch (action & ~CPU_TASKS_FROZEN) { |
382 | case CPU_DYING: | 382 | case CPU_DYING: |
383 | case CPU_DYING_FROZEN: | ||
384 | idle->nohz_delay = 0; | 383 | idle->nohz_delay = 0; |
385 | default: | 384 | default: |
386 | break; | 385 | break; |