aboutsummaryrefslogtreecommitdiff
path: root/arch/s390/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/kernel')
-rw-r--r--arch/s390/kernel/Makefile2
-rw-r--r--arch/s390/kernel/audit.c7
-rw-r--r--arch/s390/kernel/audit.h15
-rw-r--r--arch/s390/kernel/compat_audit.c1
-rw-r--r--arch/s390/kernel/cpcmd.c100
-rw-r--r--arch/s390/kernel/diag.c102
-rw-r--r--arch/s390/kernel/dis.c7
-rw-r--r--arch/s390/kernel/ipl.c4
-rw-r--r--arch/s390/kernel/irq.c1
-rw-r--r--arch/s390/kernel/kprobes.c2
-rw-r--r--arch/s390/kernel/s390_ksyms.c1
-rw-r--r--arch/s390/kernel/vmlinux.lds.S234
12 files changed, 310 insertions, 166 deletions
diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile
index 3195d375bd5..56cb71007cd 100644
--- a/arch/s390/kernel/Makefile
+++ b/arch/s390/kernel/Makefile
@@ -6,7 +6,7 @@ EXTRA_AFLAGS := -traditional
obj-y := bitmap.o traps.o time.o process.o base.o early.o \
setup.o sys_s390.o ptrace.o signal.o cpcmd.o ebcdic.o \
- semaphore.o s390_ext.o debug.o irq.o ipl.o dis.o
+ semaphore.o s390_ext.o debug.o irq.o ipl.o dis.o diag.o
obj-y += $(if $(CONFIG_64BIT),entry64.o,entry.o)
obj-y += $(if $(CONFIG_64BIT),reipl64.o,reipl.o)
diff --git a/arch/s390/kernel/audit.c b/arch/s390/kernel/audit.c
index d1c76fe10f2..f4932c22ebe 100644
--- a/arch/s390/kernel/audit.c
+++ b/arch/s390/kernel/audit.c
@@ -2,6 +2,7 @@
#include <linux/types.h>
#include <linux/audit.h>
#include <asm/unistd.h>
+#include "audit.h"
static unsigned dir_class[] = {
#include <asm-generic/audit_dir_write.h>
@@ -40,7 +41,6 @@ int audit_classify_arch(int arch)
int audit_classify_syscall(int abi, unsigned syscall)
{
#ifdef CONFIG_COMPAT
- extern int s390_classify_syscall(unsigned);
if (abi == AUDIT_ARCH_S390)
return s390_classify_syscall(syscall);
#endif
@@ -61,11 +61,6 @@ int audit_classify_syscall(int abi, unsigned syscall)
static int __init audit_classes_init(void)
{
#ifdef CONFIG_COMPAT
- extern __u32 s390_dir_class[];
- extern __u32 s390_write_class[];
- extern __u32 s390_read_class[];
- extern __u32 s390_chattr_class[];
- extern __u32 s390_signal_class[];
audit_register_class(AUDIT_CLASS_WRITE_32, s390_write_class);
audit_register_class(AUDIT_CLASS_READ_32, s390_read_class);
audit_register_class(AUDIT_CLASS_DIR_WRITE_32, s390_dir_class);
diff --git a/arch/s390/kernel/audit.h b/arch/s390/kernel/audit.h
new file mode 100644
index 00000000000..12b56f4b5a7
--- /dev/null
+++ b/arch/s390/kernel/audit.h
@@ -0,0 +1,15 @@
+#ifndef __ARCH_S390_KERNEL_AUDIT_H
+#define __ARCH_S390_KERNEL_AUDIT_H
+
+#include <linux/types.h>
+
+#ifdef CONFIG_COMPAT
+extern int s390_classify_syscall(unsigned);
+extern __u32 s390_dir_class[];
+extern __u32 s390_write_class[];
+extern __u32 s390_read_class[];
+extern __u32 s390_chattr_class[];
+extern __u32 s390_signal_class[];
+#endif /* CONFIG_COMPAT */
+
+#endif /* __ARCH_S390_KERNEL_AUDIT_H */
diff --git a/arch/s390/kernel/compat_audit.c b/arch/s390/kernel/compat_audit.c
index 0569f5126e4..d6487bf879e 100644
--- a/arch/s390/kernel/compat_audit.c
+++ b/arch/s390/kernel/compat_audit.c
@@ -1,5 +1,6 @@
#undef __s390x__
#include <asm/unistd.h>
+#include "audit.h"
unsigned s390_dir_class[] = {
#include <asm-generic/audit_dir_write.h>
diff --git a/arch/s390/kernel/cpcmd.c b/arch/s390/kernel/cpcmd.c
index 6c89f30c8e3..d8c1131e081 100644
--- a/arch/s390/kernel/cpcmd.c
+++ b/arch/s390/kernel/cpcmd.c
@@ -2,7 +2,7 @@
* arch/s390/kernel/cpcmd.c
*
* S390 version
- * Copyright (C) 1999,2005 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright IBM Corp. 1999,2007
* Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com),
* Christian Borntraeger (cborntra@de.ibm.com),
*/
@@ -21,6 +21,49 @@
static DEFINE_SPINLOCK(cpcmd_lock);
static char cpcmd_buf[241];
+static int diag8_noresponse(int cmdlen)
+{
+ register unsigned long reg2 asm ("2") = (addr_t) cpcmd_buf;
+ register unsigned long reg3 asm ("3") = cmdlen;
+
+ asm volatile(
+#ifndef CONFIG_64BIT
+ " diag %1,%0,0x8\n"
+#else /* CONFIG_64BIT */
+ " sam31\n"
+ " diag %1,%0,0x8\n"
+ " sam64\n"
+#endif /* CONFIG_64BIT */
+ : "+d" (reg3) : "d" (reg2) : "cc");
+ return reg3;
+}
+
+static int diag8_response(int cmdlen, char *response, int *rlen)
+{
+ register unsigned long reg2 asm ("2") = (addr_t) cpcmd_buf;
+ register unsigned long reg3 asm ("3") = (addr_t) response;
+ register unsigned long reg4 asm ("4") = cmdlen | 0x40000000L;
+ register unsigned long reg5 asm ("5") = *rlen;
+
+ asm volatile(
+#ifndef CONFIG_64BIT
+ " diag %2,%0,0x8\n"
+ " brc 8,1f\n"
+ " ar %1,%4\n"
+#else /* CONFIG_64BIT */
+ " sam31\n"
+ " diag %2,%0,0x8\n"
+ " sam64\n"
+ " brc 8,1f\n"
+ " agr %1,%4\n"
+#endif /* CONFIG_64BIT */
+ "1:\n"
+ : "+d" (reg4), "+d" (reg5)
+ : "d" (reg2), "d" (reg3), "d" (*rlen) : "cc");
+ *rlen = reg5;
+ return reg4;
+}
+
/*
* __cpcmd has some restrictions over cpcmd
* - the response buffer must reside below 2GB (if any)
@@ -28,59 +71,27 @@ static char cpcmd_buf[241];
*/
int __cpcmd(const char *cmd, char *response, int rlen, int *response_code)
{
- unsigned cmdlen;
- int return_code, return_len;
+ int cmdlen;
+ int rc;
+ int response_len;
cmdlen = strlen(cmd);
BUG_ON(cmdlen > 240);
memcpy(cpcmd_buf, cmd, cmdlen);
ASCEBC(cpcmd_buf, cmdlen);
- if (response != NULL && rlen > 0) {
- register unsigned long reg2 asm ("2") = (addr_t) cpcmd_buf;
- register unsigned long reg3 asm ("3") = (addr_t) response;
- register unsigned long reg4 asm ("4") = cmdlen | 0x40000000L;
- register unsigned long reg5 asm ("5") = rlen;
-
+ if (response) {
memset(response, 0, rlen);
- asm volatile(
-#ifndef CONFIG_64BIT
- " diag %2,%0,0x8\n"
- " brc 8,1f\n"
- " ar %1,%4\n"
-#else /* CONFIG_64BIT */
- " sam31\n"
- " diag %2,%0,0x8\n"
- " sam64\n"
- " brc 8,1f\n"
- " agr %1,%4\n"
-#endif /* CONFIG_64BIT */
- "1:\n"
- : "+d" (reg4), "+d" (reg5)
- : "d" (reg2), "d" (reg3), "d" (rlen) : "cc");
- return_code = (int) reg4;
- return_len = (int) reg5;
- EBCASC(response, rlen);
+ response_len = rlen;
+ rc = diag8_response(cmdlen, response, &rlen);
+ EBCASC(response, response_len);
} else {
- register unsigned long reg2 asm ("2") = (addr_t) cpcmd_buf;
- register unsigned long reg3 asm ("3") = cmdlen;
- return_len = 0;
- asm volatile(
-#ifndef CONFIG_64BIT
- " diag %1,%0,0x8\n"
-#else /* CONFIG_64BIT */
- " sam31\n"
- " diag %1,%0,0x8\n"
- " sam64\n"
-#endif /* CONFIG_64BIT */
- : "+d" (reg3) : "d" (reg2) : "cc");
- return_code = (int) reg3;
+ rc = diag8_noresponse(cmdlen);
}
- if (response_code != NULL)
- *response_code = return_code;
- return return_len;
+ if (response_code)
+ *response_code = rc;
+ return rlen;
}
-
EXPORT_SYMBOL(__cpcmd);
int cpcmd(const char *cmd, char *response, int rlen, int *response_code)
@@ -109,5 +120,4 @@ int cpcmd(const char *cmd, char *response, int rlen, int *response_code)
}
return len;
}
-
EXPORT_SYMBOL(cpcmd);
diff --git a/arch/s390/kernel/diag.c b/arch/s390/kernel/diag.c
new file mode 100644
index 00000000000..c032d11da8a
--- /dev/null
+++ b/arch/s390/kernel/diag.c
@@ -0,0 +1,102 @@
+/*
+ * Implementation of s390 diagnose codes
+ *
+ * Copyright IBM Corp. 2007
+ * Author(s): Michael Holzheu <holzheu@de.ibm.com>
+ */
+
+#include <linux/module.h>
+#include <asm/diag.h>
+
+/*
+ * Diagnose 10: Release pages
+ */
+void diag10(unsigned long addr)
+{
+ if (addr >= 0x7ff00000)
+ return;
+ asm volatile(
+#ifdef CONFIG_64BIT
+ " sam31\n"
+ " diag %0,%0,0x10\n"
+ "0: sam64\n"
+#else
+ " diag %0,%0,0x10\n"
+ "0:\n"
+#endif
+ EX_TABLE(0b, 0b)
+ : : "a" (addr));
+}
+EXPORT_SYMBOL(diag10);
+
+/*
+ * Diagnose 14: Input spool file manipulation
+ */
+int diag14(unsigned long rx, unsigned long ry1, unsigned long subcode)
+{
+ register unsigned long _ry1 asm("2") = ry1;
+ register unsigned long _ry2 asm("3") = subcode;
+ int rc = 0;
+
+ asm volatile(
+#ifdef CONFIG_64BIT
+ " sam31\n"
+ " diag %2,2,0x14\n"
+ " sam64\n"
+#else
+ " diag %2,2,0x14\n"
+#endif
+ " ipm %0\n"
+ " srl %0,28\n"
+ : "=d" (rc), "+d" (_ry2)
+ : "d" (rx), "d" (_ry1)
+ : "cc");
+
+ return rc;
+}
+EXPORT_SYMBOL(diag14);
+
+/*
+ * Diagnose 210: Get information about a virtual device
+ */
+int diag210(struct diag210 *addr)
+{
+ /*
+ * diag 210 needs its data below the 2GB border, so we
+ * use a static data area to be sure
+ */
+ static struct diag210 diag210_tmp;
+ static DEFINE_SPINLOCK(diag210_lock);
+ unsigned long flags;
+ int ccode;
+
+ spin_lock_irqsave(&diag210_lock, flags);
+ diag210_tmp = *addr;
+
+#ifdef CONFIG_64BIT
+ asm volatile(
+ " lhi %0,-1\n"
+ " sam31\n"
+ " diag %1,0,0x210\n"
+ "0: ipm %0\n"
+ " srl %0,28\n"
+ "1: sam64\n"
+ EX_TABLE(0b, 1b)
+ : "=&d" (ccode) : "a" (&diag210_tmp) : "cc", "memory");
+#else
+ asm volatile(
+ " lhi %0,-1\n"
+ " diag %1,0,0x210\n"
+ "0: ipm %0\n"
+ " srl %0,28\n"
+ "1:\n"
+ EX_TABLE(0b, 1b)
+ : "=&d" (ccode) : "a" (&diag210_tmp) : "cc", "memory");
+#endif
+
+ *addr = diag210_tmp;
+ spin_unlock_irqrestore(&diag210_lock, flags);
+
+ return ccode;
+}
+EXPORT_SYMBOL(diag210);
diff --git a/arch/s390/kernel/dis.c b/arch/s390/kernel/dis.c
index d3057318f2b..c14a336f630 100644
--- a/arch/s390/kernel/dis.c
+++ b/arch/s390/kernel/dis.c
@@ -577,7 +577,7 @@ static struct insn opcode_b2[] = {
{ "esta", 0x4a, INSTR_RRE_RR },
{ "lura", 0x4b, INSTR_RRE_RR },
{ "tar", 0x4c, INSTR_RRE_AR },
- { "cpya", INSTR_RRE_AA },
+ { "cpya", 0x4d, INSTR_RRE_AA },
{ "sar", 0x4e, INSTR_RRE_AR },
{ "ear", 0x4f, INSTR_RRE_RA },
{ "csp", 0x50, INSTR_RRE_RR },
@@ -1162,6 +1162,7 @@ static int print_insn(char *buffer, unsigned char *code, unsigned long addr)
unsigned int value;
char separator;
char *ptr;
+ int i;
ptr = buffer;
insn = find_insn(code);
@@ -1169,7 +1170,8 @@ static int print_insn(char *buffer, unsigned char *code, unsigned long addr)
ptr += sprintf(ptr, "%.5s\t", insn->name);
/* Extract the operands. */
separator = 0;
- for (ops = formats[insn->format] + 1; *ops != 0; ops++) {
+ for (ops = formats[insn->format] + 1, i = 0;
+ *ops != 0 && i < 6; ops++, i++) {
operand = operands + *ops;
value = extract_operand(code, operand);
if ((operand->flags & OPERAND_INDEX) && value == 0)
@@ -1241,7 +1243,6 @@ void show_code(struct pt_regs *regs)
}
/* Find a starting point for the disassembly. */
while (start < 32) {
- hops = 0;
for (i = 0, hops = 0; start + i < 32 && hops < 3; hops++) {
if (!find_insn(code + start + i))
break;
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index 8b8f136d9cc..66b51901c87 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -735,10 +735,10 @@ void do_reipl(void)
case REIPL_METHOD_CCW_VM:
reipl_get_ascii_loadparm(loadparm);
if (strlen(loadparm) == 0)
- sprintf(buf, "IPL %X",
+ sprintf(buf, "IPL %X CLEAR",
reipl_block_ccw->ipl_info.ccw.devno);
else
- sprintf(buf, "IPL %X LOADPARM '%s'",
+ sprintf(buf, "IPL %X CLEAR LOADPARM '%s'",
reipl_block_ccw->ipl_info.ccw.devno, loadparm);
__cpcmd(buf, NULL, 0, NULL);
break;
diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c
index 8f0cbca3120..c36d8123ca1 100644
--- a/arch/s390/kernel/irq.c
+++ b/arch/s390/kernel/irq.c
@@ -95,7 +95,6 @@ asmlinkage void do_softirq(void)
local_irq_restore(flags);
}
-EXPORT_SYMBOL(do_softirq);
void init_irq_proc(void)
{
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index 358d2bbbc48..e40373d9fbc 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -85,7 +85,7 @@ void __kprobes get_instruction_type(struct arch_specific_insn *ainsn)
ainsn->reg = (*ainsn->insn & 0xf0) >> 4;
/* save the instruction length (pop 5-5) in bytes */
- switch (*(__u8 *) (ainsn->insn) >> 4) {
+ switch (*(__u8 *) (ainsn->insn) >> 6) {
case 0:
ainsn->ilen = 2;
break;
diff --git a/arch/s390/kernel/s390_ksyms.c b/arch/s390/kernel/s390_ksyms.c
index 90b5ef529eb..7234c737f82 100644
--- a/arch/s390/kernel/s390_ksyms.c
+++ b/arch/s390/kernel/s390_ksyms.c
@@ -25,7 +25,6 @@ EXPORT_SYMBOL(_oi_bitmap);
EXPORT_SYMBOL(_ni_bitmap);
EXPORT_SYMBOL(_zb_findmap);
EXPORT_SYMBOL(_sb_findmap);
-EXPORT_SYMBOL(diag10);
/*
* semaphore ops
diff --git a/arch/s390/kernel/vmlinux.lds.S b/arch/s390/kernel/vmlinux.lds.S
index b4622a3889b..849120e3e28 100644
--- a/arch/s390/kernel/vmlinux.lds.S
+++ b/arch/s390/kernel/vmlinux.lds.S
@@ -2,6 +2,7 @@
* Written by Martin Schwidefsky (schwidefsky@de.ibm.com)
*/
+#include <asm/page.h>
#include <asm-generic/vmlinux.lds.h>
#ifndef CONFIG_64BIT
@@ -18,121 +19,142 @@ jiffies = jiffies_64;
SECTIONS
{
- . = 0x00000000;
- _text = .; /* Text and read-only data */
- .text : {
- *(.text.head)
+ . = 0x00000000;
+ .text : {
+ _text = .; /* Text and read-only data */
+ *(.text.head)
TEXT_TEXT
- SCHED_TEXT
- LOCK_TEXT
- KPROBES_TEXT
- *(.fixup)
- *(.gnu.warning)
+ SCHED_TEXT
+ LOCK_TEXT
+ KPROBES_TEXT
+ *(.fixup)
+ *(.gnu.warning)
} = 0x0700
- _etext = .; /* End of text section */
+ _etext = .; /* End of text section */
- RODATA
+ RODATA
#ifdef CONFIG_SHARED_KERNEL
- . = ALIGN(1048576); /* VM shared segments are 1MB aligned */
+ . = ALIGN(0x100000); /* VM shared segments are 1MB aligned */
#endif
- . = ALIGN(4096);
- _eshared = .; /* End of shareable data */
-
- . = ALIGN(16); /* Exception table */
- __start___ex_table = .;
- __ex_table : { *(__ex_table) }
- __stop___ex_table = .;
-
- NOTES
-
- BUG_TABLE
-
- .data : { /* Data */
- DATA_DATA
- CONSTRUCTORS
- }
-
- . = ALIGN(4096);
- __nosave_begin = .;
- .data_nosave : { *(.data.nosave) }
- . = ALIGN(4096);
- __nosave_end = .;
-
- . = ALIGN(4096);
- .data.page_aligned : { *(.data.idt) }
-
- . = ALIGN(256);
- .data.cacheline_aligned : { *(.data.cacheline_aligned) }
-
- . = ALIGN(256);
- .data.read_mostly : { *(.data.read_mostly) }
- _edata = .; /* End of data section */
-
- . = ALIGN(8192); /* init_task */
- .data.init_task : { *(.data.init_task) }
-
- /* will be freed after init */
- . = ALIGN(4096); /* Init code and data */
- __init_begin = .;
- .init.text : {
- _sinittext = .;
- *(.init.text)
- _einittext = .;
- }
- /*
- * .exit.text is discarded at runtime, not link time,
- * to deal with references from __bug_table
- */
- .exit.text : { *(.exit.text) }
-
- .init.data : { *(.init.data) }
- . = ALIGN(256);
- __setup_start = .;
- .init.setup : { *(.init.setup) }
- __setup_end = .;
- __initcall_start = .;
- .initcall.init : {
- INITCALLS
- }
- __initcall_end = .;
- __con_initcall_start = .;
- .con_initcall.init : { *(.con_initcall.init) }
- __con_initcall_end = .;
- SECURITY_INIT
+ . = ALIGN(PAGE_SIZE);
+ _eshared = .; /* End of shareable data */
+
+ . = ALIGN(16); /* Exception table */
+ __ex_table : {
+ __start___ex_table = .;
+ *(__ex_table)
+ __stop___ex_table = .;
+ }
+
+ NOTES
+ BUG_TABLE
+
+ .data : { /* Data */
+ DATA_DATA
+ CONSTRUCTORS
+ }
+
+ . = ALIGN(PAGE_SIZE);
+ .data_nosave : {
+ __nosave_begin = .;
+ *(.data.nosave)
+ }
+ . = ALIGN(PAGE_SIZE);
+ __nosave_end = .;
+
+ . = ALIGN(PAGE_SIZE);
+ .data.page_aligned : {
+ *(.data.idt)
+ }
+
+ . = ALIGN(0x100);
+ .data.cacheline_aligned : {
+ *(.data.cacheline_aligned)
+ }
+
+ . = ALIGN(0x100);
+ .data.read_mostly : {
+ *(.data.read_mostly)
+ }
+ _edata = .; /* End of data section */
+
+ . = ALIGN(2 * PAGE_SIZE); /* init_task */
+ .data.init_task : {
+ *(.data.init_task)
+ }
+
+ /* will be freed after init */
+ . = ALIGN(PAGE_SIZE); /* Init code and data */
+ __init_begin = .;
+ .init.text : {
+ _sinittext = .;
+ *(.init.text)
+ _einittext = .;
+ }
+ /*
+ * .exit.text is discarded at runtime, not link time,
+ * to deal with references from __bug_table
+ */
+ .exit.text : {
+ *(.exit.text)
+ }
+
+ .init.data : {
+ *(.init.data)
+ }
+ . = ALIGN(0x100);
+ .init.setup : {
+ __setup_start = .;
+ *(.init.setup)
+ __setup_end = .;
+ }
+ .initcall.init : {
+ __initcall_start = .;
+ INITCALLS
+ __initcall_end = .;
+ }
+
+ .con_initcall.init : {
+ __con_initcall_start = .;
+ *(.con_initcall.init)
+ __con_initcall_end = .;
+ }
+ SECURITY_INIT
#ifdef CONFIG_BLK_DEV_INITRD
- . = ALIGN(256);
- __initramfs_start = .;
- .init.ramfs : { *(.init.initramfs) }
- . = ALIGN(2);
- __initramfs_end = .;
+ . = ALIGN(0x100);
+ .init.ramfs : {
+ __initramfs_start = .;
+ *(.init.ramfs)
+ . = ALIGN(2);
+ __initramfs_end = .;
+ }
#endif
- PERCPU(4096)
- . = ALIGN(4096);
- __init_end = .;
- /* freed after init ends here */
-
- __bss_start = .; /* BSS */
- .bss : { *(.bss) }
- . = ALIGN(2);
- __bss_stop = .;
-
- _end = . ;
-
- /* Sections to be discarded */
- /DISCARD/ : {
- *(.exit.data) *(.exitcall.exit)
- }
-
- /* Stabs debugging sections. */
- .stab 0 : { *(.stab) }
- .stabstr 0 : { *(.stabstr) }
- .stab.excl 0 : { *(.stab.excl) }
- .stab.exclstr 0 : { *(.stab.exclstr) }
- .stab.index 0 : { *(.stab.index) }
- .stab.indexstr 0 : { *(.stab.indexstr) }
- .comment 0 : { *(.comment) }
+
+ PERCPU(PAGE_SIZE)
+ . = ALIGN(PAGE_SIZE);
+ __init_end = .; /* freed after init ends here */
+
+ /* BSS */
+ .bss : {
+ __bss_start = .;
+ *(.bss)
+ . = ALIGN(2);
+ __bss_stop = .;
+ }
+
+ _end = . ;
+
+ /* Sections to be discarded */
+ /DISCARD/ : {
+ *(.exit.data)
+ *(.exitcall.exit)
+ }
+
+ /* Debugging sections. */
+ STABS_DEBUG
+ DWARF_DEBUG
}