summaryrefslogtreecommitdiffstats
path: root/arch/s390/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kernel')
-rw-r--r--arch/s390/kernel/compat_signal.c1
-rw-r--r--arch/s390/kernel/dis.c2
-rw-r--r--arch/s390/kernel/ipl.c32
-rw-r--r--arch/s390/kernel/kprobes.c30
-rw-r--r--arch/s390/kernel/process.c1
-rw-r--r--arch/s390/kernel/setup.c111
-rw-r--r--arch/s390/kernel/signal.c1
-rw-r--r--arch/s390/kernel/smp.c1
-rw-r--r--arch/s390/kernel/stacktrace.c18
-rw-r--r--arch/s390/kernel/sys_s390.c1
-rw-r--r--arch/s390/kernel/time.c1
-rw-r--r--arch/s390/kernel/traps.c17
-rw-r--r--arch/s390/kernel/vmlinux.lds.S2
13 files changed, 150 insertions, 68 deletions
diff --git a/arch/s390/kernel/compat_signal.c b/arch/s390/kernel/compat_signal.c
index 80a54a0149ab..a5692c460bad 100644
--- a/arch/s390/kernel/compat_signal.c
+++ b/arch/s390/kernel/compat_signal.c
@@ -14,7 +14,6 @@
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
-#include <linux/smp_lock.h>
#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/errno.h>
diff --git a/arch/s390/kernel/dis.c b/arch/s390/kernel/dis.c
index dabaf98943d0..a057ebf108a7 100644
--- a/arch/s390/kernel/dis.c
+++ b/arch/s390/kernel/dis.c
@@ -23,6 +23,7 @@
#include <linux/kallsyms.h>
#include <linux/reboot.h>
#include <linux/kprobes.h>
+#include <linux/kdebug.h>
#include <asm/system.h>
#include <asm/uaccess.h>
@@ -33,7 +34,6 @@
#include <asm/s390_ext.h>
#include <asm/lowcore.h>
#include <asm/debug.h>
-#include <asm/kdebug.h>
#ifndef CONFIG_64BIT
#define ONELONG "%08lx: "
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 06833ac2b115..0ea048d350d8 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -164,7 +164,7 @@ EXPORT_SYMBOL_GPL(diag308);
/* SYSFS */
#define DEFINE_IPL_ATTR_RO(_prefix, _name, _format, _value) \
-static ssize_t sys_##_prefix##_##_name##_show(struct subsystem *subsys, \
+static ssize_t sys_##_prefix##_##_name##_show(struct kset *kset, \
char *page) \
{ \
return sprintf(page, _format, _value); \
@@ -173,13 +173,13 @@ static struct subsys_attribute sys_##_prefix##_##_name##_attr = \
__ATTR(_name, S_IRUGO, sys_##_prefix##_##_name##_show, NULL);
#define DEFINE_IPL_ATTR_RW(_prefix, _name, _fmt_out, _fmt_in, _value) \
-static ssize_t sys_##_prefix##_##_name##_show(struct subsystem *subsys, \
+static ssize_t sys_##_prefix##_##_name##_show(struct kset *kset, \
char *page) \
{ \
return sprintf(page, _fmt_out, \
(unsigned long long) _value); \
} \
-static ssize_t sys_##_prefix##_##_name##_store(struct subsystem *subsys,\
+static ssize_t sys_##_prefix##_##_name##_store(struct kset *kset, \
const char *buf, size_t len) \
{ \
unsigned long long value; \
@@ -194,12 +194,12 @@ static struct subsys_attribute sys_##_prefix##_##_name##_attr = \
sys_##_prefix##_##_name##_store);
#define DEFINE_IPL_ATTR_STR_RW(_prefix, _name, _fmt_out, _fmt_in, _value)\
-static ssize_t sys_##_prefix##_##_name##_show(struct subsystem *subsys, \
+static ssize_t sys_##_prefix##_##_name##_show(struct kset *kset, \
char *page) \
{ \
return sprintf(page, _fmt_out, _value); \
} \
-static ssize_t sys_##_prefix##_##_name##_store(struct subsystem *subsys,\
+static ssize_t sys_##_prefix##_##_name##_store(struct kset *kset, \
const char *buf, size_t len) \
{ \
if (sscanf(buf, _fmt_in, _value) != 1) \
@@ -272,14 +272,14 @@ void __init setup_ipl_info(void)
struct ipl_info ipl_info;
EXPORT_SYMBOL_GPL(ipl_info);
-static ssize_t ipl_type_show(struct subsystem *subsys, char *page)
+static ssize_t ipl_type_show(struct kset *kset, char *page)
{
return sprintf(page, "%s\n", ipl_type_str(ipl_info.type));
}
static struct subsys_attribute sys_ipl_type_attr = __ATTR_RO(ipl_type);
-static ssize_t sys_ipl_device_show(struct subsystem *subsys, char *page)
+static ssize_t sys_ipl_device_show(struct kset *kset, char *page)
{
struct ipl_parameter_block *ipl = IPL_PARMBLOCK_START;
@@ -371,7 +371,7 @@ static struct attribute_group ipl_fcp_attr_group = {
/* CCW ipl device attributes */
-static ssize_t ipl_ccw_loadparm_show(struct subsystem *subsys, char *page)
+static ssize_t ipl_ccw_loadparm_show(struct kset *kset, char *page)
{
char loadparm[LOADPARM_LEN + 1] = {};
@@ -469,7 +469,7 @@ static void reipl_get_ascii_loadparm(char *loadparm)
strstrip(loadparm);
}
-static ssize_t reipl_ccw_loadparm_show(struct subsystem *subsys, char *page)
+static ssize_t reipl_ccw_loadparm_show(struct kset *kset, char *page)
{
char buf[LOADPARM_LEN + 1];
@@ -477,7 +477,7 @@ static ssize_t reipl_ccw_loadparm_show(struct subsystem *subsys, char *page)
return sprintf(page, "%s\n", buf);
}
-static ssize_t reipl_ccw_loadparm_store(struct subsystem *subsys,
+static ssize_t reipl_ccw_loadparm_store(struct kset *kset,
const char *buf, size_t len)
{
int i, lp_len;
@@ -572,12 +572,12 @@ static int reipl_set_type(enum ipl_type type)
return 0;
}
-static ssize_t reipl_type_show(struct subsystem *subsys, char *page)
+static ssize_t reipl_type_show(struct kset *kset, char *page)
{
return sprintf(page, "%s\n", ipl_type_str(reipl_type));
}
-static ssize_t reipl_type_store(struct subsystem *subsys, const char *buf,
+static ssize_t reipl_type_store(struct kset *kset, const char *buf,
size_t len)
{
int rc = -EINVAL;
@@ -665,12 +665,12 @@ static int dump_set_type(enum dump_type type)
return 0;
}
-static ssize_t dump_type_show(struct subsystem *subsys, char *page)
+static ssize_t dump_type_show(struct kset *kset, char *page)
{
return sprintf(page, "%s\n", dump_type_str(dump_type));
}
-static ssize_t dump_type_store(struct subsystem *subsys, const char *buf,
+static ssize_t dump_type_store(struct kset *kset, const char *buf,
size_t len)
{
int rc = -EINVAL;
@@ -697,12 +697,12 @@ static decl_subsys(shutdown_actions, NULL, NULL);
/* on panic */
-static ssize_t on_panic_show(struct subsystem *subsys, char *page)
+static ssize_t on_panic_show(struct kset *kset, char *page)
{
return sprintf(page, "%s\n", shutdown_action_str(on_panic_action));
}
-static ssize_t on_panic_store(struct subsystem *subsys, const char *buf,
+static ssize_t on_panic_store(struct kset *kset, const char *buf,
size_t len)
{
if (strncmp(buf, SHUTDOWN_REIPL_STR, strlen(SHUTDOWN_REIPL_STR)) == 0)
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index 993f35381496..e39333ae0fcf 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -24,8 +24,8 @@
#include <linux/ptrace.h>
#include <linux/preempt.h>
#include <linux/stop_machine.h>
+#include <linux/kdebug.h>
#include <asm/cacheflush.h>
-#include <asm/kdebug.h>
#include <asm/sections.h>
#include <asm/uaccess.h>
#include <linux/module.h>
@@ -271,23 +271,13 @@ static void __kprobes set_current_kprobe(struct kprobe *p, struct pt_regs *regs,
}
/* Called with kretprobe_lock held */
-void __kprobes arch_prepare_kretprobe(struct kretprobe *rp,
+void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
struct pt_regs *regs)
{
- struct kretprobe_instance *ri;
+ ri->ret_addr = (kprobe_opcode_t *) regs->gprs[14];
- if ((ri = get_free_rp_inst(rp)) != NULL) {
- ri->rp = rp;
- ri->task = current;
- ri->ret_addr = (kprobe_opcode_t *) regs->gprs[14];
-
- /* Replace the return addr with trampoline addr */
- regs->gprs[14] = (unsigned long)&kretprobe_trampoline;
-
- add_rp_inst(ri);
- } else {
- rp->nmissed++;
- }
+ /* Replace the return addr with trampoline addr */
+ regs->gprs[14] = (unsigned long)&kretprobe_trampoline;
}
static int __kprobes kprobe_handler(struct pt_regs *regs)
@@ -516,7 +506,7 @@ out:
return 1;
}
-static int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
+int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
{
struct kprobe *cur = kprobe_running();
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
@@ -603,7 +593,6 @@ int __kprobes kprobe_exceptions_notify(struct notifier_block *self,
ret = NOTIFY_STOP;
break;
case DIE_TRAP:
- case DIE_PAGE_FAULT:
/* kprobe_running() needs smp_processor_id() */
preempt_disable();
if (kprobe_running() &&
@@ -672,3 +661,10 @@ int __init arch_init_kprobes(void)
{
return register_kprobe(&trampoline_p);
}
+
+int __kprobes arch_trampoline_kprobe(struct kprobe *p)
+{
+ if (p->addr == (kprobe_opcode_t *) & kretprobe_trampoline)
+ return 1;
+ return 0;
+}
diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c
index 11d9b0197626..eb43c3b31269 100644
--- a/arch/s390/kernel/process.c
+++ b/arch/s390/kernel/process.c
@@ -22,7 +22,6 @@
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/smp.h>
-#include <linux/smp_lock.h>
#include <linux/stddef.h>
#include <linux/unistd.h>
#include <linux/ptrace.h>
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 3dfd0985861c..6bfb0889eb10 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -65,7 +65,7 @@ long psw_user_bits = (PSW_BASE_BITS | PSW_MASK_DAT | PSW_ASC_HOME |
* User copy operations.
*/
struct uaccess_ops uaccess;
-EXPORT_SYMBOL_GPL(uaccess);
+EXPORT_SYMBOL(uaccess);
/*
* Machine setup..
@@ -74,6 +74,8 @@ unsigned int console_mode = 0;
unsigned int console_devno = -1;
unsigned int console_irq = -1;
unsigned long machine_flags = 0;
+unsigned long elf_hwcap = 0;
+char elf_platform[ELF_PLATFORM_SIZE];
struct mem_chunk __initdata memory_chunk[MEMORY_CHUNKS];
volatile int __cpu_logical_map[NR_CPUS]; /* logical cpu to cpu address */
@@ -749,6 +751,98 @@ setup_memory(void)
#endif
}
+static __init unsigned int stfl(void)
+{
+ asm volatile(
+ " .insn s,0xb2b10000,0(0)\n" /* stfl */
+ "0:\n"
+ EX_TABLE(0b,0b));
+ return S390_lowcore.stfl_fac_list;
+}
+
+static __init int stfle(unsigned long long *list, int doublewords)
+{
+ typedef struct { unsigned long long _[doublewords]; } addrtype;
+ register unsigned long __nr asm("0") = doublewords - 1;
+
+ asm volatile(".insn s,0xb2b00000,%0" /* stfle */
+ : "=m" (*(addrtype *) list), "+d" (__nr) : : "cc");
+ return __nr + 1;
+}
+
+/*
+ * Setup hardware capabilities.
+ */
+static void __init setup_hwcaps(void)
+{
+ static const int stfl_bits[6] = { 0, 2, 7, 17, 19, 21 };
+ struct cpuinfo_S390 *cpuinfo = &S390_lowcore.cpu_data;
+ unsigned long long facility_list_extended;
+ unsigned int facility_list;
+ int i;
+
+ facility_list = stfl();
+ /*
+ * The store facility list bits numbers as found in the principles
+ * of operation are numbered with bit 1UL<<31 as number 0 to
+ * bit 1UL<<0 as number 31.
+ * Bit 0: instructions named N3, "backported" to esa-mode
+ * Bit 2: z/Architecture mode is active
+ * Bit 7: the store-facility-list-extended facility is installed
+ * Bit 17: the message-security assist is installed
+ * Bit 19: the long-displacement facility is installed
+ * Bit 21: the extended-immediate facility is installed
+ * These get translated to:
+ * HWCAP_S390_ESAN3 bit 0, HWCAP_S390_ZARCH bit 1,
+ * HWCAP_S390_STFLE bit 2, HWCAP_S390_MSA bit 3,
+ * HWCAP_S390_LDISP bit 4, and HWCAP_S390_EIMM bit 5.
+ */
+ for (i = 0; i < 6; i++)
+ if (facility_list & (1UL << (31 - stfl_bits[i])))
+ elf_hwcap |= 1UL << i;
+
+ /*
+ * Check for additional facilities with store-facility-list-extended.
+ * stfle stores doublewords (8 byte) with bit 1ULL<<63 as bit 0
+ * and 1ULL<<0 as bit 63. Bits 0-31 contain the same information
+ * as stored by stfl, bits 32-xxx contain additional facilities.
+ * How many facility words are stored depends on the number of
+ * doublewords passed to the instruction. The additional facilites
+ * are:
+ * Bit 43: decimal floating point facility is installed
+ * translated to:
+ * HWCAP_S390_DFP bit 6.
+ */
+ if ((elf_hwcap & (1UL << 2)) &&
+ stfle(&facility_list_extended, 1) > 0) {
+ if (facility_list_extended & (1ULL << (64 - 43)))
+ elf_hwcap |= 1UL << 6;
+ }
+
+ switch (cpuinfo->cpu_id.machine) {
+ case 0x9672:
+#if !defined(CONFIG_64BIT)
+ default: /* Use "g5" as default for 31 bit kernels. */
+#endif
+ strcpy(elf_platform, "g5");
+ break;
+ case 0x2064:
+ case 0x2066:
+#if defined(CONFIG_64BIT)
+ default: /* Use "z900" as default for 64 bit kernels. */
+#endif
+ strcpy(elf_platform, "z900");
+ break;
+ case 0x2084:
+ case 0x2086:
+ strcpy(elf_platform, "z990");
+ break;
+ case 0x2094:
+ strcpy(elf_platform, "z9-109");
+ break;
+ }
+}
+
/*
* Setup function called from init/main.c just after the banner
* was printed.
@@ -805,6 +899,11 @@ setup_arch(char **cmdline_p)
smp_setup_cpu_possible_map();
/*
+ * Setup capabilities (ELF_HWCAP & ELF_PLATFORM).
+ */
+ setup_hwcaps();
+
+ /*
* Create kernel page tables and switch to virtual addressing.
*/
paging_init();
@@ -839,8 +938,12 @@ void print_cpu_info(struct cpuinfo_S390 *cpuinfo)
static int show_cpuinfo(struct seq_file *m, void *v)
{
+ static const char *hwcap_str[7] = {
+ "esan3", "zarch", "stfle", "msa", "ldisp", "eimm", "dfp"
+ };
struct cpuinfo_S390 *cpuinfo;
unsigned long n = (unsigned long) v - 1;
+ int i;
s390_adjust_jiffies();
preempt_disable();
@@ -850,7 +953,13 @@ static int show_cpuinfo(struct seq_file *m, void *v)
"bogomips per cpu: %lu.%02lu\n",
num_online_cpus(), loops_per_jiffy/(500000/HZ),
(loops_per_jiffy/(5000/HZ))%100);
+ seq_puts(m, "features\t: ");
+ for (i = 0; i < 7; i++)
+ if (hwcap_str[i] && (elf_hwcap & (1UL << i)))
+ seq_printf(m, "%s ", hwcap_str[i]);
+ seq_puts(m, "\n");
}
+
if (cpu_online(n)) {
#ifdef CONFIG_SMP
if (smp_processor_id() == n)
diff --git a/arch/s390/kernel/signal.c b/arch/s390/kernel/signal.c
index 3c41907799a1..d264671c1b71 100644
--- a/arch/s390/kernel/signal.c
+++ b/arch/s390/kernel/signal.c
@@ -14,7 +14,6 @@
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
-#include <linux/smp_lock.h>
#include <linux/kernel.h>
#include <linux/signal.h>
#include <linux/errno.h>
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 3754e2031b39..b7977027a28f 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -25,7 +25,6 @@
#include <linux/mm.h>
#include <linux/spinlock.h>
#include <linux/kernel_stat.h>
-#include <linux/smp_lock.h>
#include <linux/delay.h>
#include <linux/cache.h>
#include <linux/interrupt.h>
diff --git a/arch/s390/kernel/stacktrace.c b/arch/s390/kernel/stacktrace.c
index 2e5c65a1863e..515ff9011dd7 100644
--- a/arch/s390/kernel/stacktrace.c
+++ b/arch/s390/kernel/stacktrace.c
@@ -59,7 +59,7 @@ static unsigned long save_context_stack(struct stack_trace *trace,
}
}
-void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
+void save_stack_trace(struct stack_trace *trace)
{
register unsigned long sp asm ("15");
unsigned long orig_sp, new_sp;
@@ -69,20 +69,16 @@ void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
new_sp = save_context_stack(trace, &trace->skip, orig_sp,
S390_lowcore.panic_stack - PAGE_SIZE,
S390_lowcore.panic_stack);
- if ((new_sp != orig_sp) && !trace->all_contexts)
+ if (new_sp != orig_sp)
return;
new_sp = save_context_stack(trace, &trace->skip, new_sp,
S390_lowcore.async_stack - ASYNC_SIZE,
S390_lowcore.async_stack);
- if ((new_sp != orig_sp) && !trace->all_contexts)
+ if (new_sp != orig_sp)
return;
- if (task)
- save_context_stack(trace, &trace->skip, new_sp,
- (unsigned long) task_stack_page(task),
- (unsigned long) task_stack_page(task) + THREAD_SIZE);
- else
- save_context_stack(trace, &trace->skip, new_sp,
- S390_lowcore.thread_info,
- S390_lowcore.thread_info + THREAD_SIZE);
+
+ save_context_stack(trace, &trace->skip, new_sp,
+ S390_lowcore.thread_info,
+ S390_lowcore.thread_info + THREAD_SIZE);
return;
}
diff --git a/arch/s390/kernel/sys_s390.c b/arch/s390/kernel/sys_s390.c
index 3a77c22cda78..1c90c7e99978 100644
--- a/arch/s390/kernel/sys_s390.c
+++ b/arch/s390/kernel/sys_s390.c
@@ -17,7 +17,6 @@
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
-#include <linux/smp_lock.h>
#include <linux/sem.h>
#include <linux/msg.h>
#include <linux/shm.h>
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 711dae8da7ad..9c2872a7cca7 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -21,6 +21,7 @@
#include <linux/mm.h>
#include <linux/interrupt.h>
#include <linux/time.h>
+#include <linux/sysdev.h>
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/smp.h>
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c
index 49dec830373a..cbfe73034c30 100644
--- a/arch/s390/kernel/traps.c
+++ b/arch/s390/kernel/traps.c
@@ -22,11 +22,11 @@
#include <linux/timer.h>
#include <linux/mm.h>
#include <linux/smp.h>
-#include <linux/smp_lock.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/module.h>
+#include <linux/kdebug.h>
#include <linux/kallsyms.h>
#include <linux/reboot.h>
#include <linux/kprobes.h>
@@ -40,7 +40,6 @@
#include <asm/s390_ext.h>
#include <asm/lowcore.h>
#include <asm/debug.h>
-#include <asm/kdebug.h>
/* Called from entry.S only */
extern void handle_per_exception(struct pt_regs *regs);
@@ -70,20 +69,6 @@ static int kstack_depth_to_print = 12;
static int kstack_depth_to_print = 20;
#endif /* CONFIG_64BIT */
-ATOMIC_NOTIFIER_HEAD(s390die_chain);
-
-int register_die_notifier(struct notifier_block *nb)
-{
- return atomic_notifier_chain_register(&s390die_chain, nb);
-}
-EXPORT_SYMBOL(register_die_notifier);
-
-int unregister_die_notifier(struct notifier_block *nb)
-{
- return atomic_notifier_chain_unregister(&s390die_chain, nb);
-}
-EXPORT_SYMBOL(unregister_die_notifier);
-
/*
* For show_trace we have tree different stack to consider:
* - the panic stack which is used if the kernel stack has overflown
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index 418f6426a949..e9d3432aba60 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -107,7 +107,7 @@ SECTIONS
. = ALIGN(2);
__initramfs_end = .;
#endif
- . = ALIGN(256);
+ . = ALIGN(4096);
__per_cpu_start = .;
.data.percpu : { *(.data.percpu) }
__per_cpu_end = .;
OpenPOWER on IntegriCloud