diff options
Diffstat (limited to 'arch/s390')
30 files changed, 418 insertions, 106 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 821a141889de..2f4f70c4dbb2 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig @@ -7,6 +7,14 @@ config MMU bool default y +config LOCKDEP_SUPPORT + bool + default y + +config STACKTRACE_SUPPORT + bool + default y + config RWSEM_GENERIC_SPINLOCK bool @@ -110,12 +118,9 @@ config SYSVIPC_COMPAT depends on COMPAT && SYSVIPC default y -config BINFMT_ELF32 - tristate "Kernel support for 31 bit ELF binaries" - depends on COMPAT - help - This allows you to run 32-bit Linux/ELF binaries on your zSeries - in 64 bit mode. Everybody wants this; say Y. +config AUDIT_ARCH + bool + default y comment "Code generation options" diff --git a/arch/s390/Kconfig.debug b/arch/s390/Kconfig.debug index f53b6d5300e5..2283933a9a93 100644 --- a/arch/s390/Kconfig.debug +++ b/arch/s390/Kconfig.debug @@ -1,5 +1,9 @@ menu "Kernel hacking" +config TRACE_IRQFLAGS_SUPPORT + bool + default y + source "lib/Kconfig.debug" endmenu diff --git a/arch/s390/Makefile b/arch/s390/Makefile index b3791fb094a8..74ef57dcfa60 100644 --- a/arch/s390/Makefile +++ b/arch/s390/Makefile @@ -34,6 +34,11 @@ cflags-$(CONFIG_MARCH_G5) += $(call cc-option,-march=g5) cflags-$(CONFIG_MARCH_Z900) += $(call cc-option,-march=z900) cflags-$(CONFIG_MARCH_Z990) += $(call cc-option,-march=z990) +# +# Prevent tail-call optimizations, to get clearer backtraces: +# +cflags-$(CONFIG_FRAME_POINTER) += -fno-optimize-sibling-calls + # old style option for packed stacks ifeq ($(call cc-option-yn,-mkernel-backchain),y) cflags-$(CONFIG_PACK_STACK) += -mkernel-backchain -D__PACK_STACK diff --git a/arch/s390/appldata/appldata_base.c b/arch/s390/appldata/appldata_base.c index d0f82c995af6..a0a94e0ef8d1 100644 --- a/arch/s390/appldata/appldata_base.c +++ b/arch/s390/appldata/appldata_base.c @@ -617,6 +617,7 @@ appldata_offline_cpu(int cpu) spin_unlock(&appldata_timer_lock); } +#ifdef CONFIG_HOTPLUG_CPU static int __cpuinit appldata_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) @@ -625,20 +626,19 @@ appldata_cpu_notify(struct notifier_block *self, case CPU_ONLINE: appldata_online_cpu((long) hcpu); break; -#ifdef CONFIG_HOTPLUG_CPU case CPU_DEAD: appldata_offline_cpu((long) hcpu); break; -#endif default: break; } return NOTIFY_OK; } -static struct notifier_block __devinitdata appldata_nb = { +static struct notifier_block appldata_nb = { .notifier_call = appldata_cpu_notify, }; +#endif /* * appldata_init() @@ -662,7 +662,7 @@ static int __init appldata_init(void) appldata_online_cpu(i); /* Register cpu hotplug notifier */ - register_cpu_notifier(&appldata_nb); + register_hotcpu_notifier(&appldata_nb); appldata_sysctl_header = register_sysctl_table(appldata_dir_table, 1); #ifdef MODULE diff --git a/arch/s390/defconfig b/arch/s390/defconfig index f4dfc10026d2..f1d4591eddbb 100644 --- a/arch/s390/defconfig +++ b/arch/s390/defconfig @@ -1,13 +1,16 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.17-rc1 -# Mon Apr 3 14:34:15 2006 +# Linux kernel version: 2.6.18-rc2 +# Thu Jul 27 13:51:07 2006 # CONFIG_MMU=y +CONFIG_LOCKDEP_SUPPORT=y +CONFIG_STACKTRACE_SUPPORT=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_GENERIC_HWEIGHT=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_S390=y +CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # # Code maturity level options @@ -25,6 +28,7 @@ CONFIG_SWAP=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y # CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_TASKSTATS is not set CONFIG_SYSCTL=y CONFIG_AUDIT=y # CONFIG_AUDITSYSCALL is not set @@ -43,10 +47,12 @@ CONFIG_PRINTK=y CONFIG_BUG=y CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y +CONFIG_RT_MUTEXES=y CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_SHMEM=y CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 # CONFIG_SLOB is not set @@ -94,7 +100,6 @@ CONFIG_HOTPLUG_CPU=y CONFIG_DEFAULT_MIGRATION_COST=1000000 CONFIG_COMPAT=y CONFIG_SYSVIPC_COMPAT=y -CONFIG_BINFMT_ELF32=y # # Code generation options @@ -115,6 +120,7 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_RESOURCES_64BIT=y # # I/O subsystem configuration @@ -142,6 +148,7 @@ CONFIG_VIRT_CPU_ACCOUNTING=y # CONFIG_APPLDATA_BASE is not set CONFIG_NO_IDLE_HZ=y CONFIG_NO_IDLE_HZ_INIT=y +CONFIG_S390_HYPFS_FS=y CONFIG_KEXEC=y # @@ -174,6 +181,8 @@ CONFIG_IP_FIB_HASH=y # CONFIG_INET_IPCOMP is not set # CONFIG_INET_XFRM_TUNNEL is not set # CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set @@ -186,7 +195,10 @@ CONFIG_IPV6=y # CONFIG_INET6_IPCOMP is not set # CONFIG_INET6_XFRM_TUNNEL is not set # CONFIG_INET6_TUNNEL is not set +CONFIG_INET6_XFRM_MODE_TRANSPORT=y +CONFIG_INET6_XFRM_MODE_TUNNEL=y # CONFIG_IPV6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set # CONFIG_NETFILTER is not set # @@ -263,6 +275,7 @@ CONFIG_NET_ESTIMATOR=y # Network testing # # CONFIG_NET_PKTGEN is not set +# CONFIG_NET_TCPPROBE is not set # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set @@ -276,6 +289,7 @@ CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_FW_LOADER is not set # CONFIG_DEBUG_DRIVER is not set +CONFIG_SYS_HYPERVISOR=y # # Connector - unified userspace <-> kernelspace linker @@ -334,6 +348,7 @@ CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 CONFIG_BLK_DEV_INITRD=y # CONFIG_CDROM_PKTCDVD is not set @@ -359,9 +374,7 @@ CONFIG_MD_LINEAR=m CONFIG_MD_RAID0=m CONFIG_MD_RAID1=m # CONFIG_MD_RAID10 is not set -CONFIG_MD_RAID5=m -# CONFIG_MD_RAID5_RESHAPE is not set -# CONFIG_MD_RAID6 is not set +# CONFIG_MD_RAID456 is not set CONFIG_MD_MULTIPATH=m # CONFIG_MD_FAULTY is not set CONFIG_BLK_DEV_DM=y @@ -419,7 +432,8 @@ CONFIG_S390_TAPE_34XX=m # # Cryptographic devices # -CONFIG_Z90CRYPT=m +CONFIG_ZCRYPT=m +# CONFIG_ZCRYPT_MONOLITHIC is not set # # Network device support @@ -509,6 +523,7 @@ CONFIG_FS_MBCACHE=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y # CONFIG_AUTOFS_FS is not set @@ -614,26 +629,36 @@ CONFIG_MSDOS_PARTITION=y # Instrumentation Support # # CONFIG_PROFILING is not set -# CONFIG_STATISTICS is not set +CONFIG_STATISTICS=y +CONFIG_KPROBES=y # # Kernel hacking # +CONFIG_TRACE_IRQFLAGS_SUPPORT=y # CONFIG_PRINTK_TIME is not set CONFIG_MAGIC_SYSRQ=y +# CONFIG_UNUSED_SYMBOLS is not set CONFIG_DEBUG_KERNEL=y CONFIG_LOG_BUF_SHIFT=17 # CONFIG_DETECT_SOFTLOCKUP is not set # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set CONFIG_DEBUG_PREEMPT=y -CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set CONFIG_DEBUG_SPINLOCK=y +CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_RWSEMS is not set +# CONFIG_DEBUG_LOCK_ALLOC is not set +# CONFIG_PROVE_LOCKING is not set CONFIG_DEBUG_SPINLOCK_SLEEP=y +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set # CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_INFO is not set CONFIG_DEBUG_FS=y # CONFIG_DEBUG_VM is not set +# CONFIG_FRAME_POINTER is not set # CONFIG_UNWIND_INFO is not set CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set @@ -688,3 +713,4 @@ CONFIG_CRYPTO=y # CONFIG_CRC16 is not set CONFIG_CRC32=m # CONFIG_LIBCRC32C is not set +CONFIG_PLIST=y diff --git a/arch/s390/hypfs/hypfs_diag.c b/arch/s390/hypfs/hypfs_diag.c index efa74af7f04a..1785bce2b919 100644 --- a/arch/s390/hypfs/hypfs_diag.c +++ b/arch/s390/hypfs/hypfs_diag.c @@ -403,7 +403,7 @@ static void *diag204_get_buffer(enum diag204_format fmt, int *pages) *pages = 1; return diag204_alloc_rbuf(); } else {/* INFO_EXT */ - *pages = diag204(SUBC_RSI | INFO_EXT, 0, 0); + *pages = diag204(SUBC_RSI | INFO_EXT, 0, NULL); if (*pages <= 0) return ERR_PTR(-ENOSYS); else diff --git a/arch/s390/kernel/Makefile b/arch/s390/kernel/Makefile index 9269b5788fac..9a33ed6ca696 100644 --- a/arch/s390/kernel/Makefile +++ b/arch/s390/kernel/Makefile @@ -16,11 +16,14 @@ extra-y += head.o init_task.o vmlinux.lds obj-$(CONFIG_MODULES) += s390_ksyms.o module.o obj-$(CONFIG_SMP) += smp.o +obj-$(CONFIG_AUDIT) += audit.o +compat-obj-$(CONFIG_AUDIT) += compat_audit.o obj-$(CONFIG_COMPAT) += compat_linux.o compat_signal.o \ - compat_wrapper.o compat_exec_domain.o -obj-$(CONFIG_BINFMT_ELF32) += binfmt_elf32.o + compat_wrapper.o compat_exec_domain.o \ + binfmt_elf32.o $(compat-obj-y) obj-$(CONFIG_VIRT_TIMER) += vtime.o +obj-$(CONFIG_STACKTRACE) += stacktrace.o # Kexec part S390_KEXEC_OBJS := machine_kexec.o crash.o diff --git a/arch/s390/kernel/audit.c b/arch/s390/kernel/audit.c new file mode 100644 index 000000000000..0741d9193390 --- /dev/null +++ b/arch/s390/kernel/audit.c @@ -0,0 +1,66 @@ +#include <linux/init.h> +#include <linux/types.h> +#include <linux/audit.h> +#include <asm/unistd.h> + +static unsigned dir_class[] = { +#include <asm-generic/audit_dir_write.h> +~0U +}; + +static unsigned read_class[] = { +#include <asm-generic/audit_read.h> +~0U +}; + +static unsigned write_class[] = { +#include <asm-generic/audit_write.h> +~0U +}; + +static unsigned chattr_class[] = { +#include <asm-generic/audit_change_attr.h> +~0U +}; + +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 + switch(syscall) { + case __NR_open: + return 2; + case __NR_openat: + return 3; + case __NR_socketcall: + return 4; + case __NR_execve: + return 5; + default: + return 0; + } +} + +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[]; + 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); + audit_register_class(AUDIT_CLASS_CHATTR_32, s390_chattr_class); +#endif + audit_register_class(AUDIT_CLASS_WRITE, write_class); + audit_register_class(AUDIT_CLASS_READ, read_class); + audit_register_class(AUDIT_CLASS_DIR_WRITE, dir_class); + audit_register_class(AUDIT_CLASS_CHATTR, chattr_class); + return 0; +} + +__initcall(audit_classes_init); diff --git a/arch/s390/kernel/compat_audit.c b/arch/s390/kernel/compat_audit.c new file mode 100644 index 000000000000..16d9436bfa91 --- /dev/null +++ b/arch/s390/kernel/compat_audit.c @@ -0,0 +1,38 @@ +#undef __s390x__ +#include <asm/unistd.h> + +unsigned s390_dir_class[] = { +#include <asm-generic/audit_dir_write.h> +~0U +}; + +unsigned s390_chattr_class[] = { +#include <asm-generic/audit_change_attr.h> +~0U +}; + +unsigned s390_write_class[] = { +#include <asm-generic/audit_write.h> +~0U +}; + +unsigned s390_read_class[] = { +#include <asm-generic/audit_read.h> +~0U +}; + +int s390_classify_syscall(unsigned syscall) +{ + switch(syscall) { + case __NR_open: + return 2; + case __NR_openat: + return 3; + case __NR_socketcall: + return 4; + case __NR_execve: + return 5; + default: + return 1; + } +} diff --git a/arch/s390/kernel/compat_linux.c b/arch/s390/kernel/compat_linux.c index cabb4ff54cd7..785c9f70ac98 100644 --- a/arch/s390/kernel/compat_linux.c +++ b/arch/s390/kernel/compat_linux.c @@ -409,7 +409,7 @@ asmlinkage long sys32_sysinfo(struct sysinfo32 __user *info) mm_segment_t old_fs = get_fs (); set_fs (KERNEL_DS); - ret = sys_sysinfo(&s); + ret = sys_sysinfo((struct sysinfo __user *) &s); set_fs (old_fs); err = put_user (s.uptime, &info->uptime); err |= __put_user (s.loads[0], &info->loads[0]); @@ -438,7 +438,7 @@ asmlinkage long sys32_sched_rr_get_interval(compat_pid_t pid, mm_segment_t old_fs = get_fs (); set_fs (KERNEL_DS); - ret = sys_sched_rr_get_interval(pid, &t); + ret = sys_sched_rr_get_interval(pid, (struct timespec __user *) &t); set_fs (old_fs); if (put_compat_timespec(&t, interval)) return -EFAULT; @@ -464,7 +464,10 @@ asmlinkage long sys32_rt_sigprocmask(int how, compat_sigset_t __user *set, } } set_fs (KERNEL_DS); - ret = sys_rt_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL, sigsetsize); + ret = sys_rt_sigprocmask(how, + set ? (sigset_t __user *) &s : NULL, + oset ? (sigset_t __user *) &s : NULL, + sigsetsize); set_fs (old_fs); if (ret) return ret; if (oset) { @@ -489,7 +492,7 @@ asmlinkage long sys32_rt_sigpending(compat_sigset_t __user *set, mm_segment_t old_fs = get_fs(); set_fs (KERNEL_DS); - ret = sys_rt_sigpending(&s, sigsetsize); + ret = sys_rt_sigpending((sigset_t __user *) &s, sigsetsize); set_fs (old_fs); if (!ret) { switch (_NSIG_WORDS) { @@ -514,7 +517,7 @@ sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo) if (copy_siginfo_from_user32(&info, uinfo)) return -EFAULT; set_fs (KERNEL_DS); - ret = sys_rt_sigqueueinfo(pid, sig, &info); + ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *) &info); set_fs (old_fs); return ret; } @@ -674,7 +677,8 @@ asmlinkage long sys32_sendfile(int out_fd, int in_fd, compat_off_t __user *offse return -EFAULT; set_fs(KERNEL_DS); - ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count); + ret = sys_sendfile(out_fd, in_fd, + offset ? (off_t __user *) &of : NULL, count); set_fs(old_fs); if (offset && put_user(of, offset)) @@ -694,7 +698,8 @@ asmlinkage long sys32_sendfile64(int out_fd, int in_fd, return -EFAULT; set_fs(KERNEL_DS); - ret = sys_sendfile64(out_fd, in_fd, offset ? &lof : NULL, count); + ret = sys_sendfile64(out_fd, in_fd, + offset ? (loff_t __user *) &lof : NULL, count); set_fs(old_fs); if (offset && put_user(lof, offset)) diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index d8948c342caf..5b5799ac8f83 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -58,6 +58,21 @@ STACK_SIZE = 1 << STACK_SHIFT #define BASED(name) name-system_call(%r13) +#ifdef CONFIG_TRACE_IRQFLAGS + .macro TRACE_IRQS_ON + l %r1,BASED(.Ltrace_irq_on) + basr %r14,%r1 + .endm + + .macro TRACE_IRQS_OFF + l %r1,BASED(.Ltrace_irq_off) + basr %r14,%r1 + .endm +#else +#define TRACE_IRQS_ON +#define TRACE_IRQS_OFF +#endif + /* * Register usage in interrupt handlers: * R9 - pointer to current task structure @@ -361,6 +376,7 @@ ret_from_fork: st %r15,SP_R15(%r15) # store stack pointer for new kthread 0: l %r1,BASED(.Lschedtail) basr %r14,%r1 + TRACE_IRQS_ON stosm __SF_EMPTY(%r15),0x03 # reenable interrupts b BASED(sysc_return) @@ -516,6 +532,7 @@ pgm_no_vtime3: mvc __THREAD_per+__PER_address(4,%r1),__LC_PER_ADDRESS mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID oi __TI_flags+3(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP + TRACE_IRQS_ON stosm __SF_EMPTY(%r15),0x03 # reenable interrupts b BASED(sysc_do_svc) @@ -539,9 +556,11 @@ io_int_handler: io_no_vtime: #endif l %r9,__LC_THREAD_INFO # load pointer to thread_info struct + TRACE_IRQS_OFF l %r1,BASED(.Ldo_IRQ) # load address of do_IRQ la %r2,SP_PTREGS(%r15) # address of register-save area basr %r14,%r1 # branch to standard irq handler + TRACE_IRQS_ON io_return: tm SP_PSW+1(%r15),0x01 # returning to user ? @@ -651,10 +670,12 @@ ext_int_handler: ext_no_vtime: #endif l %r9,__LC_THREAD_INFO # load pointer to thread_info struct + TRACE_IRQS_OFF la %r2,SP_PTREGS(%r15) # address of register-save area lh %r3,__LC_EXT_INT_CODE # get interruption code l %r1,BASED(.Ldo_extint) basr %r14,%r1 + TRACE_IRQS_ON b BASED(io_return) __critical_end: @@ -731,8 +752,10 @@ mcck_no_vtime: stosm __SF_EMPTY(%r15),0x04 # turn dat on tm __TI_flags+3(%r9),_TIF_MCCK_PENDING bno BASED(mcck_return) + TRACE_IRQS_OFF l %r1,BASED(.Ls390_handle_mcck) basr %r14,%r1 # call machine check handler + TRACE_IRQS_ON mcck_return: mvc __LC_RETURN_MCCK_PSW(8),SP_PSW(%r15) # move return PSW ni __LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit @@ -1012,7 +1035,11 @@ cleanup_io_leave_insn: .Lvfork: .long sys_vfork .Lschedtail: .long schedule_tail .Lsysc_table: .long sys_call_table - +#ifdef CONFIG_TRACE_IRQFLAGS +.Ltrace_irq_on:.long trace_hardirqs_on +.Ltrace_irq_off: + .long trace_hardirqs_off +#endif .Lcritical_start: .long __critical_start + 0x80000000 .Lcritical_end: diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 1ca499fa54b4..56f5f613b868 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S @@ -58,6 +58,19 @@ _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_RESTORE_SIGMASK | _TIF_NEED_RESCHED | \ #define BASED(name) name-system_call(%r13) +#ifdef CONFIG_TRACE_IRQFLAGS + .macro TRACE_IRQS_ON + brasl %r14,trace_hardirqs_on + .endm + + .macro TRACE_IRQS_OFF + brasl %r14,trace_hardirqs_off + .endm +#else +#define TRACE_IRQS_ON +#define TRACE_IRQS_OFF +#endif + .macro STORE_TIMER lc_offset #ifdef CONFIG_VIRT_CPU_ACCOUNTING stpt \lc_offset @@ -354,6 +367,7 @@ ret_from_fork: jo 0f stg %r15,SP_R15(%r15) # store stack pointer for new kthread 0: brasl %r14,schedule_tail + TRACE_IRQS_ON stosm 24(%r15),0x03 # reenable interrupts j sysc_return @@ -535,6 +549,7 @@ pgm_no_vtime3: mvc __THREAD_per+__PER_address(8,%r1),__LC_PER_ADDRESS mvc __THREAD_per+__PER_access_id(1,%r1),__LC_PER_ACCESS_ID oi __TI_flags+7(%r9),_TIF_SINGLE_STEP # set TIF_SINGLE_STEP + TRACE_IRQS_ON stosm __SF_EMPTY(%r15),0x03 # reenable interrupts j sysc_do_svc @@ -557,8 +572,10 @@ io_int_handler: io_no_vtime: #endif lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct + TRACE_IRQS_OFF la %r2,SP_PTREGS(%r15) # address of register-save area brasl %r14,do_IRQ # call standard irq handler + TRACE_IRQS_ON io_return: tm SP_PSW+1(%r15),0x01 # returning to user ? @@ -665,9 +682,11 @@ ext_int_handler: ext_no_vtime: #endif lg %r9,__LC_THREAD_INFO # load pointer to thread_info struct + TRACE_IRQS_OFF la %r2,SP_PTREGS(%r15) # address of register-save area llgh %r3,__LC_EXT_INT_CODE # get interruption code brasl %r14,do_extint + TRACE_IRQS_ON j io_return __critical_end: @@ -743,7 +762,9 @@ mcck_no_vtime: stosm __SF_EMPTY(%r15),0x04 # turn dat on tm __TI_flags+7(%r9),_TIF_MCCK_PENDING jno mcck_return + TRACE_IRQS_OFF brasl %r14,s390_handle_mcck + TRACE_IRQS_ON mcck_return: mvc __LC_RETURN_MCCK_PSW(16),SP_PSW(%r15) # move return PSW ni __LC_RETURN_MCCK_PSW+1,0xfd # clear wait state bit diff --git a/arch/s390/kernel/head31.S b/arch/s390/kernel/head31.S index d00de17b3778..a4dc61f3285e 100644 --- a/arch/s390/kernel/head31.S +++ b/arch/s390/kernel/head31.S @@ -273,7 +273,7 @@ startup_continue: .Lbss_end: .long _end .Lparmaddr: .long PARMAREA .Lsccbaddr: .long .Lsccb - .align 4096 + .org 0x12000 .Lsccb: .hword 0x1000 # length, one page .byte 0x00,0x00,0x00 @@ -290,7 +290,7 @@ startup_continue: .Lscpincr2: .quad 0x00 .fill 3984,1,0 - .align 4096 + .org 0x13000 #ifdef CONFIG_SHARED_KERNEL .org 0x100000 diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S index 47744fcca930..9d80c5b1ef95 100644 --- a/arch/s390/kernel/head64.S +++ b/arch/s390/kernel/head64.S @@ -268,7 +268,7 @@ startup_continue: .Lparmaddr: .quad PARMAREA - .align 4096 + .org 0x12000 .Lsccb: .hword 0x1000 # length, one page .byte 0x00,0x00,0x00 @@ -285,7 +285,7 @@ startup_continue: .Lscpincr2: .quad 0x00 .fill 3984,1,0 - .align 4096 + .org 0x13000 #ifdef CONFIG_SHARED_KERNEL .org 0x100000 diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c index 480b6a5fef3a..1eef50918615 100644 --- a/arch/s390/kernel/irq.c +++ b/arch/s390/kernel/irq.c @@ -69,10 +69,6 @@ asmlinkage void do_softirq(void) local_irq_save(flags); - account_system_vtime(current); - - local_bh_disable(); - if (local_softirq_pending()) { /* Get current stack pointer. */ asm volatile("la %0,0(15)" : "=a" (old)); @@ -95,10 +91,6 @@ asmlinkage void do_softirq(void) __do_softirq(); } - account_system_vtime(current); - - __local_bh_enable(); - local_irq_restore(flags); } diff --git a/arch/s390/kernel/machine_kexec.c b/arch/s390/kernel/machine_kexec.c index fbde6a915264..60b1ea9f946b 100644 --- a/arch/s390/kernel/machine_kexec.c +++ b/arch/s390/kernel/machine_kexec.c @@ -63,6 +63,7 @@ NORET_TYPE void machine_kexec(struct kimage *image) { clear_all_subchannels(); + cio_reset_channel_paths(); /* Disable lowcore protection */ ctl_clear_bit(0,28); diff --git a/arch/s390/kernel/module.c b/arch/s390/kernel/module.c index c271cdab58e2..d989ed45a7aa 100644 --- a/arch/s390/kernel/module.c +++ b/arch/s390/kernel/module.c @@ -119,7 +119,7 @@ module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs, int nrela, i, j; /* Find symbol table and string table. */ - symtab = 0; + symtab = NULL; for (i = 0; i < hdr->e_shnum; i++) switch (sechdrs[i].sh_type) { case SHT_SYMTAB: diff --git a/arch/s390/kernel/process.c b/arch/s390/kernel/process.c index 1f9399191794..d3cbfa3005ec 100644 --- a/arch/s390/kernel/process.c +++ b/arch/s390/kernel/process.c @@ -142,6 +142,7 @@ static void default_idle(void) return; } + trace_hardirqs_on(); /* Wait for external, I/O or machine check interrupt. */ __load_psw_mask(PSW_KERNEL_BITS | PSW_MASK_WAIT | PSW_MASK_IO | PSW_MASK_EXT); @@ -171,7 +172,7 @@ void show_regs(struct pt_regs *regs) show_registers(regs); /* Show stack backtrace if pt_regs is from kernel mode */ if (!(regs->psw.mask & PSW_MASK_PSTATE)) - show_trace(0,(unsigned long *) regs->gprs[15]); + show_trace(NULL, (unsigned long *) regs->gprs[15]); } extern void kernel_thread_starter(void); diff --git a/arch/s390/kernel/profile.c b/arch/s390/kernel/profile.c index 7ba777eec1a8..b81aa1f569ca 100644 --- a/arch/s390/kernel/profile.c +++ b/arch/s390/kernel/profile.c @@ -13,7 +13,7 @@ static struct proc_dir_entry * root_irq_dir; void init_irq_proc(void) { /* create /proc/irq */ - root_irq_dir = proc_mkdir("irq", 0); + root_irq_dir = proc_mkdir("irq", NULL); /* create /proc/irq/prof_cpu_mask */ create_prof_cpu_mask(root_irq_dir); diff --git a/arch/s390/kernel/s390_ext.c b/arch/s390/kernel/s390_ext.c index 207bc511a6e3..c1b383537fec 100644 --- a/arch/s390/kernel/s390_ext.c +++ b/arch/s390/kernel/s390_ext.c @@ -24,7 +24,7 @@ * (0x1202 external call, 0x1004 cpu timer, 0x2401 hwc console, 0x4000 * iucv and 0x2603 pfault) this is always the first element. */ -ext_int_info_t *ext_int_hash[256] = { 0, }; +ext_int_info_t *ext_int_hash[256] = { NULL, }; static inline int ext_hash(__u16 code) { diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 1ca34f54ea8a..c902f059c7aa 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -877,31 +877,57 @@ static struct bin_attribute ipl_scp_data_attr = { static decl_subsys(ipl, NULL, NULL); +static int ipl_register_fcp_files(void) +{ + int rc; + + rc = sysfs_create_group(&ipl_subsys.kset.kobj, + &ipl_fcp_attr_group); + if (rc) + goto out; + rc = sysfs_create_bin_file(&ipl_subsys.kset.kobj, + &ipl_parameter_attr); + if (rc) + goto out_ipl_parm; + rc = sysfs_create_bin_file(&ipl_subsys.kset.kobj, + &ipl_scp_data_attr); + if (!rc) + goto out; + + sysfs_remove_bin_file(&ipl_subsys.kset.kobj, &ipl_parameter_attr); + +out_ipl_parm: + sysfs_remove_group(&ipl_subsys.kset.kobj, &ipl_fcp_attr_group); +out: + return rc; +} + static int __init ipl_device_sysfs_register(void) { int rc; rc = firmware_register(&ipl_subsys); if (rc) - return rc; + goto out; switch (get_ipl_type()) { case ipl_type_ccw: - sysfs_create_group(&ipl_subsys.kset.kobj, &ipl_ccw_attr_group); + rc = sysfs_create_group(&ipl_subsys.kset.kobj, + &ipl_ccw_attr_group); break; case ipl_type_fcp: - sysfs_create_group(&ipl_subsys.kset.kobj, &ipl_fcp_attr_group); - sysfs_create_bin_file(&ipl_subsys.kset.kobj, - &ipl_parameter_attr); - sysfs_create_bin_file(&ipl_subsys.kset.kobj, - &ipl_scp_data_attr); + rc = ipl_register_fcp_files(); break; default: - sysfs_create_group(&ipl_subsys.kset.kobj, - &ipl_unknown_attr_group); + rc = sysfs_create_group(&ipl_subsys.kset.kobj, + &ipl_unknown_attr_group); break; } - return 0; + + if (rc) + firmware_unregister(&ipl_subsys); +out: + return rc; } __initcall(ipl_device_sysfs_register); diff --git a/arch/s390/kernel/stacktrace.c b/arch/s390/kernel/stacktrace.c new file mode 100644 index 000000000000..de83f38288d0 --- /dev/null +++ b/arch/s390/kernel/stacktrace.c @@ -0,0 +1,90 @@ +/* + * arch/s390/kernel/stacktrace.c + * + * Stack trace management functions + * + * Copyright (C) IBM Corp. 2006 + * Author(s): Heiko Carstens <heiko.carstens@de.ibm.com> + */ + +#include <linux/sched.h> +#include <linux/stacktrace.h> +#include <linux/kallsyms.h> + +static inline unsigned long save_context_stack(struct stack_trace *trace, + unsigned int *skip, + unsigned long sp, + unsigned long low, + unsigned long high) +{ + struct stack_frame *sf; + struct pt_regs *regs; + unsigned long addr; + + while(1) { + sp &= PSW_ADDR_INSN; + if (sp < low || sp > high) + return sp; + sf = (struct stack_frame *)sp; + while(1) { + addr = sf->gprs[8] & PSW_ADDR_INSN; + if (!(*skip)) + trace->entries[trace->nr_entries++] = addr; + else + (*skip)--; + if (trace->nr_entries >= trace->max_entries) + return sp; + low = sp; + sp = sf->back_chain & PSW_ADDR_INSN; + if (!sp) + break; + if (sp <= low || sp > high - sizeof(*sf)) + return sp; + sf = (struct stack_frame *)sp; + } + /* Zero backchain detected, check for interrupt frame. */ + sp = (unsigned long)(sf + 1); + if (sp <= low || sp > high - sizeof(*regs)) + return sp; + regs = (struct pt_regs *)sp; + addr = regs->psw.addr & PSW_ADDR_INSN; + if (!(*skip)) + trace->entries[trace->nr_entries++] = addr; + else + (*skip)--; + if (trace->nr_entries >= trace->max_entries) + return sp; + low = sp; + sp = regs->gprs[15]; + } +} + +void save_stack_trace(struct stack_trace *trace, + struct task_struct *task, int all_contexts, + unsigned int skip) +{ + register unsigned long sp asm ("15"); + unsigned long orig_sp; + + sp &= PSW_ADDR_INSN; + orig_sp = sp; + + sp = save_context_stack(trace, &skip, sp, + S390_lowcore.panic_stack - PAGE_SIZE, + S390_lowcore.panic_stack); + if ((sp != orig_sp) && !all_contexts) + return; + sp = save_context_stack(trace, &skip, sp, + S390_lowcore.async_stack - ASYNC_SIZE, + S390_lowcore.async_stack); + if ((sp != orig_sp) && !all_contexts) + return; + if (task) + save_context_stack(trace, &skip, sp, + (unsigned long) task_stack_page(task), + (unsigned long) task_stack_page(task) + THREAD_SIZE); + else + save_context_stack(trace, &skip, sp, S390_lowcore.thread_info, + S390_lowcore.thread_info + THREAD_SIZE); + return; +} diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index f7fe9bc43397..74e6178fbaf2 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -379,7 +379,7 @@ void __init time_init(void) -xtime.tv_sec, -xtime.tv_nsec); /* request the clock comparator external interrupt */ - if (register_early_external_interrupt(0x1004, 0, + if (register_early_external_interrupt(0x1004, NULL, &ext_int_info_cc) != 0) panic("Couldn't request external interrupt 0x1004"); diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index 12240c03a6dd..bde1d1d59858 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c @@ -170,7 +170,7 @@ void show_stack(struct task_struct *task, unsigned long *sp) */ void dump_stack(void) { - show_stack(0, 0); + show_stack(NULL, NULL); } EXPORT_SYMBOL(dump_stack); @@ -331,9 +331,9 @@ static void inline do_trap(long interruption_code, int signr, char *str, } } -static inline void *get_check_address(struct pt_regs *regs) +static inline void __user *get_check_address(struct pt_regs *regs) { - return (void *)((regs->psw.addr-S390_lowcore.pgm_ilc) & PSW_ADDR_INSN); + return (void __user *)((regs->psw.addr-S390_lowcore.pgm_ilc) & PSW_ADDR_INSN); } void do_single_step(struct pt_regs *regs) @@ -360,7 +360,7 @@ asmlinkage void name(struct pt_regs * regs, long interruption_code) \ info.si_signo = signr; \ info.si_errno = 0; \ info.si_code = sicode; \ - info.si_addr = (void *)siaddr; \ + info.si_addr = siaddr; \ do_trap(interruption_code, signr, str, regs, &info); \ } @@ -392,7 +392,7 @@ DO_ERROR_INFO(SIGILL, "translation exception", translation_exception, ILL_ILLOPN, get_check_address(regs)) static inline void -do_fp_trap(struct pt_regs *regs, void *location, +do_fp_trap(struct pt_regs *regs, void __user *location, int fpc, long interruption_code) { siginfo_t si; @@ -424,10 +424,10 @@ asmlinkage void illegal_op(struct pt_regs * regs, long interruption_code) { siginfo_t info; __u8 opcode[6]; - __u16 *location; + __u16 __user *location; int signal = 0; - location = (__u16 *) get_check_address(regs); + location = get_check_address(regs); /* * We got all needed information from the lowcore and can @@ -559,10 +559,10 @@ DO_ERROR_INFO(SIGILL, "specification exception", specification_exception, asmlinkage void data_exception(struct pt_regs * regs, long interruption_code) { - __u16 *location; + __u16 __user *location; int signal = 0; - location = (__u16 *) get_check_address(regs); + location = get_check_address(regs); /* * We got all needed information from the lowcore and can diff --git a/arch/s390/lib/string.c b/arch/s390/lib/string.c index 8240cc77e06e..ae5cf5d03d41 100644 --- a/arch/s390/lib/string.c +++ b/arch/s390/lib/string.c @@ -233,7 +233,7 @@ char * strrchr(const char * s, int c) if (s[len] == (char) c) return (char *) s + len; } while (--len > 0); - return 0; + return NULL; } EXPORT_SYMBOL(strrchr); @@ -267,7 +267,7 @@ char * strstr(const char * s1,const char * s2) return (char *) s1; s1++; } - return 0; + return NULL; } EXPORT_SYMBOL(strstr); diff --git a/arch/s390/lib/uaccess.S b/arch/s390/lib/uaccess.S index 5d59e2625048..837275284d9f 100644 --- a/arch/s390/lib/uaccess.S +++ b/arch/s390/lib/uaccess.S @@ -88,30 +88,31 @@ __copy_to_user_asm: .globl __copy_in_user_asm # %r2 = from, %r3 = n, %r4 = to __copy_in_user_asm: + ahi %r3,-1 + jo 6f sacf 256 - bras 1,1f - mvc 0(1,%r4),0(%r2) -0: mvc 0(256,%r4),0(%r2) - la %r2,256(%r2) - la %r4,256(%r4) -1: ahi %r3,-256 - jnm 0b -2: ex %r3,0(%r1) - sacf 0 - slr %r2,%r2 - br 14 -3: mvc 0(1,%r4),0(%r2) + bras %r1,4f +0: ahi %r3,257 +1: mvc 0(1,%r4),0(%r2) la %r2,1(%r2) la %r4,1(%r4) ahi %r3,-1 + jnz 1b +2: lr %r2,%r3 + br %r14 +3: mvc 0(256,%r4),0(%r2) + la %r2,256(%r2) + la %r4,256(%r4) +4: ahi %r3,-256 jnm 3b -4: lr %r2,%r3 +5: ex %r3,4(%r1) sacf 0 +6: slr %r2,%r2 br %r14 .section __ex_table,"a" - .long 0b,3b - .long 2b,3b - .long 3b,4b + .long 1b,2b + .long 3b,0b + .long 5b,0b .previous .align 4 diff --git a/arch/s390/lib/uaccess64.S b/arch/s390/lib/uaccess64.S index 19b41a33c230..1f755be22f92 100644 --- a/arch/s390/lib/uaccess64.S +++ b/arch/s390/lib/uaccess64.S @@ -88,30 +88,31 @@ __copy_to_user_asm: .globl __copy_in_user_asm # %r2 = from, %r3 = n, %r4 = to __copy_in_user_asm: + aghi %r3,-1 + jo 6f sacf 256 - bras 1,1f - mvc 0(1,%r4),0(%r2) -0: mvc 0(256,%r4),0(%r2) - la %r2,256(%r2) - la %r4,256(%r4) -1: aghi %r3,-256 - jnm 0b -2: ex %r3,0(%r1) - sacf 0 - slgr %r2,%r2 - br 14 -3: mvc 0(1,%r4),0(%r2) + bras %r1,4f +0: aghi %r3,257 +1: mvc 0(1,%r4),0(%r2) la %r2,1(%r2) la %r4,1(%r4) aghi %r3,-1 + jnz 1b +2: lgr %r2,%r3 + br %r14 +3: mvc 0(256,%r4),0(%r2) + la %r2,256(%r2) + la %r4,256(%r4) +4: aghi %r3,-256 jnm 3b -4: lgr %r2,%r3 +5: ex %r3,4(%r1) sacf 0 - br %r14 +6: slgr %r2,%r2 + br 14 .section __ex_table,"a" - .quad 0b,3b - .quad 2b,3b - .quad 3b,4b + .quad 1b,2b + .quad 3b,0b + .quad 5b,0b .previous .align 4 diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c index 81be2fec7dc5..ceea51cff03b 100644 --- a/arch/s390/mm/cmm.c +++ b/arch/s390/mm/cmm.c @@ -161,7 +161,7 @@ cmm_thread(void *dummy) static void cmm_start_thread(void) { - kernel_thread(cmm_thread, 0, 0); + kernel_thread(cmm_thread, NULL, 0); } static void diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 833d5941746a..7cd82575813d 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -144,7 +144,7 @@ static void do_sigsegv(struct pt_regs *regs, unsigned long error_code, #endif si.si_signo = SIGSEGV; si.si_code = si_code; - si.si_addr = (void *) address; + si.si_addr = (void __user *) address; force_sig_info(SIGSEGV, &si, current); } diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c index eb6ebfef134a..6e6b6de77770 100644 --- a/arch/s390/mm/init.c +++ b/arch/s390/mm/init.c @@ -129,7 +129,7 @@ void __init paging_init(void) /* * pg_table is physical at this point */ - pg_table = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); + pg_table = (pte_t *) alloc_bootmem_pages(PAGE_SIZE); pg_dir->pgd0 = (_PAGE_TABLE | __pa(pg_table)); pg_dir->pgd1 = (_PAGE_TABLE | (__pa(pg_table)+1024)); @@ -219,7 +219,7 @@ void __init paging_init(void) continue; } - pm_dir = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE*4); + pm_dir = (pmd_t *) alloc_bootmem_pages(PAGE_SIZE * 4); pgd_populate(&init_mm, pg_dir, pm_dir); for (j = 0 ; j < PTRS_PER_PMD ; j++,pm_dir++) { @@ -228,7 +228,7 @@ void __init paging_init(void) continue; } - pt_dir = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE); + pt_dir = (pte_t *) alloc_bootmem_pages(PAGE_SIZE); pmd_populate_kernel(&init_mm, pm_dir, pt_dir); for (k = 0 ; k < PTRS_PER_PTE ; k++,pt_dir++) { |