Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 31 Jul 2012 22:32:05 +0000 (15:32 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 31 Jul 2012 22:32:05 +0000 (15:32 -0700)
Pull s390 updates from Martin Schwidefsky:
 "This it the second batch of s390 patches for the 3.6 merge window.
  Included is enablement for two common code changes, killable page
  faults and sorted exception tables.  And the regular set of cleanup
  and bug fix patches."

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux:
  s390: make use of user_mode() macro where possible
  s390/mm: rename user_mode variable to addressing_mode
  s390/mm: fix fault handling for page table walk case
  s390/mm: make page faults killable
  s390: update defconfig
  s390/mm: downgrade page table after fork of a 31 bit process
  s390/ipl: Use diagnose 8 command separation
  s390/linker script: use RO_DATA_SECTION
  s390/exceptions: sort exception table at build time
  s390/debug: remove module_exit function / move EXPORT_SYMBOLs

18 files changed:
arch/s390/Kconfig
arch/s390/defconfig
arch/s390/include/asm/mmu_context.h
arch/s390/include/asm/processor.h
arch/s390/include/asm/setup.h
arch/s390/kernel/debug.c
arch/s390/kernel/dis.c
arch/s390/kernel/early.c
arch/s390/kernel/ipl.c
arch/s390/kernel/setup.c
arch/s390/kernel/traps.c
arch/s390/kernel/vdso.c
arch/s390/kernel/vmlinux.lds.S
arch/s390/mm/fault.c
arch/s390/mm/mmap.c
arch/s390/mm/pgtable.c
arch/s390/oprofile/backtrace.c
scripts/sortextable.c

index 296cd32466df39736277d21a4eedb0d9cedced64..76de6b68487c8a44aa4eabecc1dddc7d916546e2 100644 (file)
@@ -90,6 +90,7 @@ config S390
        select HAVE_MEMBLOCK_NODE_MAP
        select HAVE_CMPXCHG_LOCAL
        select ARCH_DISCARD_MEMBLOCK
+       select BUILDTIME_EXTABLE_SORT
        select ARCH_INLINE_SPIN_TRYLOCK
        select ARCH_INLINE_SPIN_TRYLOCK_BH
        select ARCH_INLINE_SPIN_LOCK
index 37d2bf267964a5103f1b1ae189db2e9f6fd1de91..967923dea98de1574458312619c8883b89b09ae7 100644 (file)
@@ -7,6 +7,9 @@ CONFIG_TASK_DELAY_ACCT=y
 CONFIG_TASK_XACCT=y
 CONFIG_TASK_IO_ACCOUNTING=y
 CONFIG_AUDIT=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_RCU_FAST_NO_HZ=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_CGROUPS=y
@@ -35,8 +38,6 @@ CONFIG_MODVERSIONS=y
 CONFIG_PARTITION_ADVANCED=y
 CONFIG_IBM_PARTITION=y
 CONFIG_DEFAULT_DEADLINE=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
 CONFIG_PREEMPT=y
 CONFIG_MEMORY_HOTPLUG=y
 CONFIG_MEMORY_HOTREMOVE=y
index 5c63615f1349f862762ced5e20147acae7f2c5ec..b749c573365767af8487c4c24c07b8cbc8ace903 100644 (file)
@@ -11,7 +11,6 @@
 #include <asm/uaccess.h>
 #include <asm/tlbflush.h>
 #include <asm/ctl_reg.h>
-#include <asm-generic/mm_hooks.h>
 
 static inline int init_new_context(struct task_struct *tsk,
                                   struct mm_struct *mm)
@@ -58,7 +57,7 @@ static inline void update_mm(struct mm_struct *mm, struct task_struct *tsk)
        pgd_t *pgd = mm->pgd;
 
        S390_lowcore.user_asce = mm->context.asce_bits | __pa(pgd);
-       if (user_mode != HOME_SPACE_MODE) {
+       if (addressing_mode != HOME_SPACE_MODE) {
                /* Load primary space page table origin. */
                asm volatile(LCTL_OPCODE" 1,1,%0\n"
                             : : "m" (S390_lowcore.user_asce) );
@@ -91,4 +90,17 @@ static inline void activate_mm(struct mm_struct *prev,
         switch_mm(prev, next, current);
 }
 
+static inline void arch_dup_mmap(struct mm_struct *oldmm,
+                                struct mm_struct *mm)
+{
+#ifdef CONFIG_64BIT
+       if (oldmm->context.asce_limit < mm->context.asce_limit)
+               crst_table_downgrade(mm, oldmm->context.asce_limit);
+#endif
+}
+
+static inline void arch_exit_mmap(struct mm_struct *mm)
+{
+}
+
 #endif /* __S390_MMU_CONTEXT_H */
index c40fa91e38a8da85fcad46d66435701f98076758..11e4e3236937e106aba159b83e7cc6ae6167c7b0 100644 (file)
@@ -120,7 +120,9 @@ struct stack_frame {
        regs->psw.mask  = psw_user_bits | PSW_MASK_BA;                  \
        regs->psw.addr  = new_psw | PSW_ADDR_AMODE;                     \
        regs->gprs[15]  = new_stackp;                                   \
+       __tlb_flush_mm(current->mm);                                    \
        crst_table_downgrade(current->mm, 1UL << 31);                   \
+       update_mm(current->mm, current);                                \
 } while (0)
 
 /* Forward declaration, a strange C thing */
index 57e80534375a603f2f839893bfa6ebc2b79e5845..e6859d16ee2dbb49f87ca15cf5b8a720153df2b6 100644 (file)
@@ -60,7 +60,7 @@ void create_mem_hole(struct mem_chunk memory_chunk[], unsigned long addr,
 #define SECONDARY_SPACE_MODE   2
 #define HOME_SPACE_MODE                3
 
-extern unsigned int user_mode;
+extern unsigned int addressing_mode;
 
 /*
  * Machine features detected in head.S
index 21be961e8a43e643daa31a26680c91edf2a5ee66..ba500d8dc392056ddd66e4978389d072452f6859 100644 (file)
@@ -110,6 +110,7 @@ struct debug_view debug_raw_view = {
        NULL,
        NULL
 };
+EXPORT_SYMBOL(debug_raw_view);
 
 struct debug_view debug_hex_ascii_view = {
        "hex_ascii",
@@ -119,6 +120,7 @@ struct debug_view debug_hex_ascii_view = {
        NULL,
        NULL
 };
+EXPORT_SYMBOL(debug_hex_ascii_view);
 
 static struct debug_view debug_level_view = {
        "level",
@@ -155,6 +157,7 @@ struct debug_view debug_sprintf_view = {
        NULL,
        NULL
 };
+EXPORT_SYMBOL(debug_sprintf_view);
 
 /* used by dump analysis tools to determine version of debug feature */
 static unsigned int __used debug_feature_version = __DEBUG_FEATURE_VERSION;
@@ -730,6 +733,7 @@ debug_info_t *debug_register(const char *name, int pages_per_area,
        return debug_register_mode(name, pages_per_area, nr_areas, buf_size,
                                   S_IRUSR | S_IWUSR, 0, 0);
 }
+EXPORT_SYMBOL(debug_register);
 
 /*
  * debug_unregister:
@@ -748,6 +752,7 @@ debug_unregister(debug_info_t * id)
 out:
        return;
 }
+EXPORT_SYMBOL(debug_unregister);
 
 /*
  * debug_set_size:
@@ -810,7 +815,7 @@ debug_set_level(debug_info_t* id, int new_level)
         }
        spin_unlock_irqrestore(&id->lock,flags);
 }
-
+EXPORT_SYMBOL(debug_set_level);
 
 /*
  * proceed_active_entry:
@@ -930,7 +935,7 @@ debug_stop_all(void)
        if (debug_stoppable)
                debug_active = 0;
 }
-
+EXPORT_SYMBOL(debug_stop_all);
 
 void debug_set_critical(void)
 {
@@ -963,6 +968,7 @@ debug_event_common(debug_info_t * id, int level, const void *buf, int len)
 
        return active;
 }
+EXPORT_SYMBOL(debug_event_common);
 
 /*
  * debug_exception_common:
@@ -990,6 +996,7 @@ debug_entry_t
 
        return active;
 }
+EXPORT_SYMBOL(debug_exception_common);
 
 /*
  * counts arguments in format string for sprintf view
@@ -1043,6 +1050,7 @@ debug_sprintf_event(debug_info_t* id, int level,char *string,...)
 
        return active;
 }
+EXPORT_SYMBOL(debug_sprintf_event);
 
 /*
  * debug_sprintf_exception:
@@ -1081,25 +1089,7 @@ debug_sprintf_exception(debug_info_t* id, int level,char *string,...)
 
        return active;
 }
-
-/*
- * debug_init:
- * - is called exactly once to initialize the debug feature
- */
-
-static int
-__init debug_init(void)
-{
-       int rc = 0;
-
-       s390dbf_sysctl_header = register_sysctl_table(s390dbf_dir_table);
-       mutex_lock(&debug_mutex);
-       debug_debugfs_root_entry = debugfs_create_dir(DEBUG_DIR_ROOT,NULL);
-       initialized = 1;
-       mutex_unlock(&debug_mutex);
-
-       return rc;
-}
+EXPORT_SYMBOL(debug_sprintf_exception);
 
 /*
  * debug_register_view:
@@ -1147,6 +1137,7 @@ debug_register_view(debug_info_t * id, struct debug_view *view)
 out:
        return rc;
 }
+EXPORT_SYMBOL(debug_register_view);
 
 /*
  * debug_unregister_view:
@@ -1176,6 +1167,7 @@ debug_unregister_view(debug_info_t * id, struct debug_view *view)
 out:
        return rc;
 }
+EXPORT_SYMBOL(debug_unregister_view);
 
 static inline char *
 debug_get_user_string(const char __user *user_buf, size_t user_len)
@@ -1485,6 +1477,7 @@ debug_dflt_header_fn(debug_info_t * id, struct debug_view *view,
                      except_str, entry->id.fields.cpuid, (void *) caller);
        return rc;
 }
+EXPORT_SYMBOL(debug_dflt_header_fn);
 
 /*
  * prints debug data sprintf-formated:
@@ -1533,33 +1526,16 @@ out:
 }
 
 /*
- * clean up module
+ * debug_init:
+ * - is called exactly once to initialize the debug feature
  */
-static void __exit debug_exit(void)
+static int __init debug_init(void)
 {
-       debugfs_remove(debug_debugfs_root_entry);
-       unregister_sysctl_table(s390dbf_sysctl_header);
-       return;
+       s390dbf_sysctl_header = register_sysctl_table(s390dbf_dir_table);
+       mutex_lock(&debug_mutex);
+       debug_debugfs_root_entry = debugfs_create_dir(DEBUG_DIR_ROOT, NULL);
+       initialized = 1;
+       mutex_unlock(&debug_mutex);
+       return 0;
 }
-
-/*
- * module definitions
- */
 postcore_initcall(debug_init);
-module_exit(debug_exit);
-MODULE_LICENSE("GPL");
-
-EXPORT_SYMBOL(debug_register);
-EXPORT_SYMBOL(debug_unregister); 
-EXPORT_SYMBOL(debug_set_level);
-EXPORT_SYMBOL(debug_stop_all);
-EXPORT_SYMBOL(debug_register_view);
-EXPORT_SYMBOL(debug_unregister_view);
-EXPORT_SYMBOL(debug_event_common);
-EXPORT_SYMBOL(debug_exception_common);
-EXPORT_SYMBOL(debug_hex_ascii_view);
-EXPORT_SYMBOL(debug_raw_view);
-EXPORT_SYMBOL(debug_dflt_header_fn);
-EXPORT_SYMBOL(debug_sprintf_view);
-EXPORT_SYMBOL(debug_sprintf_exception);
-EXPORT_SYMBOL(debug_sprintf_event);
index 1f6b428e276239d94927086f6d5b2ccc668fbe2b..619c5d3507264ca1f7417563a9152b55270374a2 100644 (file)
@@ -1531,7 +1531,7 @@ static int print_insn(char *buffer, unsigned char *code, unsigned long addr)
 
 void show_code(struct pt_regs *regs)
 {
-       char *mode = (regs->psw.mask & PSW_MASK_PSTATE) ? "User" : "Krnl";
+       char *mode = user_mode(regs) ? "User" : "Krnl";
        unsigned char code[64];
        char buffer[64], *ptr;
        mm_segment_t old_fs;
@@ -1540,7 +1540,7 @@ void show_code(struct pt_regs *regs)
 
        /* Get a snapshot of the 64 bytes surrounding the fault address. */
        old_fs = get_fs();
-       set_fs((regs->psw.mask & PSW_MASK_PSTATE) ? USER_DS : KERNEL_DS);
+       set_fs(user_mode(regs) ? USER_DS : KERNEL_DS);
        for (start = 32; start && regs->psw.addr >= 34 - start; start -= 2) {
                addr = regs->psw.addr - 34 + start;
                if (__copy_from_user(code + start - 2,
index bc95a8ebd9cc3810a0bfb83d34f10cca512d1d92..83c3271c442b75d5d005e1e6130f538deea968a7 100644 (file)
@@ -455,7 +455,6 @@ void __init startup_init(void)
        init_kernel_storage_key();
        lockdep_init();
        lockdep_off();
-       sort_main_extable();
        setup_lowcore_early();
        setup_facility_list();
        detect_machine_type();
index e64d141555ce99843f4995827f4644e1dc127c79..6ffcd3203215a2bcacb50bc35ae12229113b0ff4 100644 (file)
@@ -1583,7 +1583,7 @@ static struct kset *vmcmd_kset;
 
 static void vmcmd_run(struct shutdown_trigger *trigger)
 {
-       char *cmd, *next_cmd;
+       char *cmd;
 
        if (strcmp(trigger->name, ON_REIPL_STR) == 0)
                cmd = vmcmd_on_reboot;
@@ -1600,15 +1600,7 @@ static void vmcmd_run(struct shutdown_trigger *trigger)
 
        if (strlen(cmd) == 0)
                return;
-       do {
-               next_cmd = strchr(cmd, '\n');
-               if (next_cmd) {
-                       next_cmd[0] = 0;
-                       next_cmd += 1;
-               }
-               __cpcmd(cmd, NULL, 0, NULL);
-               cmd = next_cmd;
-       } while (cmd != NULL);
+       __cpcmd(cmd, NULL, 0, NULL);
 }
 
 static int vmcmd_init(void)
index 743c0f32fe3beb0c508a02e81bf775f075242d08..f86c81e13c374be484f591faead417a7fb3ee572 100644 (file)
@@ -302,8 +302,8 @@ static int __init parse_vmalloc(char *arg)
 }
 early_param("vmalloc", parse_vmalloc);
 
-unsigned int user_mode = HOME_SPACE_MODE;
-EXPORT_SYMBOL_GPL(user_mode);
+unsigned int addressing_mode = HOME_SPACE_MODE;
+EXPORT_SYMBOL_GPL(addressing_mode);
 
 static int set_amode_primary(void)
 {
@@ -328,7 +328,7 @@ static int set_amode_primary(void)
  */
 static int __init early_parse_switch_amode(char *p)
 {
-       user_mode = PRIMARY_SPACE_MODE;
+       addressing_mode = PRIMARY_SPACE_MODE;
        return 0;
 }
 early_param("switch_amode", early_parse_switch_amode);
@@ -336,9 +336,9 @@ early_param("switch_amode", early_parse_switch_amode);
 static int __init early_parse_user_mode(char *p)
 {
        if (p && strcmp(p, "primary") == 0)
-               user_mode = PRIMARY_SPACE_MODE;
+               addressing_mode = PRIMARY_SPACE_MODE;
        else if (!p || strcmp(p, "home") == 0)
-               user_mode = HOME_SPACE_MODE;
+               addressing_mode = HOME_SPACE_MODE;
        else
                return 1;
        return 0;
@@ -347,7 +347,7 @@ early_param("user_mode", early_parse_user_mode);
 
 static void setup_addressing_mode(void)
 {
-       if (user_mode == PRIMARY_SPACE_MODE) {
+       if (addressing_mode == PRIMARY_SPACE_MODE) {
                if (set_amode_primary())
                        pr_info("Address spaces switched, "
                                "mvcos available\n");
index af2421a0f3156e9c8a965ee34d95322de55602be..01775c04a90e63a2bbebc2eb5d3ebf0363abafe2 100644 (file)
@@ -185,7 +185,7 @@ void show_registers(struct pt_regs *regs)
 {
        char *mode;
 
-       mode = (regs->psw.mask & PSW_MASK_PSTATE) ? "User" : "Krnl";
+       mode = user_mode(regs) ? "User" : "Krnl";
        printk("%s PSW : %p %p",
               mode, (void *) regs->psw.mask,
               (void *) regs->psw.addr);
@@ -225,7 +225,7 @@ void show_regs(struct pt_regs *regs)
               (void *) current->thread.ksp);
        show_registers(regs);
        /* Show stack backtrace if pt_regs is from kernel mode */
-       if (!(regs->psw.mask & PSW_MASK_PSTATE))
+       if (!user_mode(regs))
                show_trace(NULL, (unsigned long *) regs->gprs[15]);
        show_last_breaking_event(regs);
 }
@@ -300,7 +300,7 @@ static void __kprobes do_trap(struct pt_regs *regs,
                       regs->int_code, si_signo) == NOTIFY_STOP)
                return;
 
-        if (regs->psw.mask & PSW_MASK_PSTATE) {
+       if (user_mode(regs)) {
                info.si_signo = si_signo;
                info.si_errno = 0;
                info.si_code = si_code;
@@ -341,7 +341,7 @@ void __kprobes do_per_trap(struct pt_regs *regs)
 
 static void default_trap_handler(struct pt_regs *regs)
 {
-        if (regs->psw.mask & PSW_MASK_PSTATE) {
+       if (user_mode(regs)) {
                report_user_fault(regs, SIGSEGV);
                do_exit(SIGSEGV);
        } else
@@ -410,7 +410,7 @@ static void __kprobes illegal_op(struct pt_regs *regs)
 
        location = get_psw_address(regs);
 
-       if (regs->psw.mask & PSW_MASK_PSTATE) {
+       if (user_mode(regs)) {
                if (get_user(*((__u16 *) opcode), (__u16 __user *) location))
                        return;
                if (*((__u16 *) opcode) == S390_BREAKPOINT_U16) {
@@ -478,7 +478,7 @@ void specification_exception(struct pt_regs *regs)
 
        location = (__u16 __user *) get_psw_address(regs);
 
-        if (regs->psw.mask & PSW_MASK_PSTATE) {
+       if (user_mode(regs)) {
                get_user(*((__u16 *) opcode), location);
                switch (opcode[0]) {
                case 0x28: /* LDR Rx,Ry   */
@@ -531,7 +531,7 @@ static void data_exception(struct pt_regs *regs)
                asm volatile("stfpc %0" : "=m" (current->thread.fp_regs.fpc));
 
 #ifdef CONFIG_MATHEMU
-        else if (regs->psw.mask & PSW_MASK_PSTATE) {
+       else if (user_mode(regs)) {
                __u8 opcode[6];
                get_user(*((__u16 *) opcode), location);
                switch (opcode[0]) {
@@ -598,7 +598,7 @@ static void data_exception(struct pt_regs *regs)
 static void space_switch_exception(struct pt_regs *regs)
 {
        /* Set user psw back to home space mode. */
-       if (regs->psw.mask & PSW_MASK_PSTATE)
+       if (user_mode(regs))
                regs->psw.mask |= PSW_ASC_HOME;
        /* Send SIGILL. */
        do_trap(regs, SIGILL, ILL_PRVOPC, "space switch event");
index ea5590fdca3bb8266caa0e25410dd744b103b4c9..9a19ca367c17bc41e1f8e781ed173a93bba5da12 100644 (file)
@@ -84,7 +84,8 @@ struct vdso_data *vdso_data = &vdso_data_store.data;
  */
 static void vdso_init_data(struct vdso_data *vd)
 {
-       vd->ectg_available = user_mode != HOME_SPACE_MODE && test_facility(31);
+       vd->ectg_available =
+               addressing_mode != HOME_SPACE_MODE && test_facility(31);
 }
 
 #ifdef CONFIG_64BIT
@@ -101,7 +102,7 @@ int vdso_alloc_per_cpu(struct _lowcore *lowcore)
 
        lowcore->vdso_per_cpu_data = __LC_PASTE;
 
-       if (user_mode == HOME_SPACE_MODE || !vdso_enabled)
+       if (addressing_mode == HOME_SPACE_MODE || !vdso_enabled)
                return 0;
 
        segment_table = __get_free_pages(GFP_KERNEL, SEGMENT_ORDER);
@@ -146,7 +147,7 @@ void vdso_free_per_cpu(struct _lowcore *lowcore)
        unsigned long segment_table, page_table, page_frame;
        u32 *psal, *aste;
 
-       if (user_mode == HOME_SPACE_MODE || !vdso_enabled)
+       if (addressing_mode == HOME_SPACE_MODE || !vdso_enabled)
                return;
 
        psal = (u32 *)(addr_t) lowcore->paste[4];
@@ -164,7 +165,7 @@ static void vdso_init_cr5(void)
 {
        unsigned long cr5;
 
-       if (user_mode == HOME_SPACE_MODE || !vdso_enabled)
+       if (addressing_mode == HOME_SPACE_MODE || !vdso_enabled)
                return;
        cr5 = offsetof(struct _lowcore, paste);
        __ctl_load(cr5, 5, 5);
index 21109c63eb12961483134141c67bfc8c2b8f8315..de8fa9bbd35ee9787537e93c18b561b75cacf72f 100644 (file)
@@ -45,7 +45,7 @@ SECTIONS
 
        .dummy : { *(.dummy) } :data
 
-       RODATA
+       RO_DATA_SECTION(PAGE_SIZE)
 
 #ifdef CONFIG_SHARED_KERNEL
        . = ALIGN(0x100000);    /* VM shared segments are 1MB aligned */
index 6a12d1bb6e09d065e5a4b2625ce79ba7209b5c2b..6c013f544146d8bf92d6143378c8f1fbf5631b02 100644 (file)
@@ -49,6 +49,7 @@
 #define VM_FAULT_BADCONTEXT    0x010000
 #define VM_FAULT_BADMAP                0x020000
 #define VM_FAULT_BADACCESS     0x040000
+#define VM_FAULT_SIGNAL        0x080000
 
 static unsigned long store_indication;
 
@@ -110,7 +111,7 @@ static inline int user_space_fault(unsigned long trans_exc_code)
        if (trans_exc_code == 2)
                /* Access via secondary space, set_fs setting decides */
                return current->thread.mm_segment.ar4;
-       if (user_mode == HOME_SPACE_MODE)
+       if (addressing_mode == HOME_SPACE_MODE)
                /* User space if the access has been done via home space. */
                return trans_exc_code == 3;
        /*
@@ -219,7 +220,7 @@ static noinline void do_fault_error(struct pt_regs *regs, int fault)
        case VM_FAULT_BADACCESS:
        case VM_FAULT_BADMAP:
                /* Bad memory access. Check if it is kernel or user space. */
-               if (regs->psw.mask & PSW_MASK_PSTATE) {
+               if (user_mode(regs)) {
                        /* User mode accesses just cause a SIGSEGV */
                        si_code = (fault == VM_FAULT_BADMAP) ?
                                SEGV_MAPERR : SEGV_ACCERR;
@@ -229,15 +230,19 @@ static noinline void do_fault_error(struct pt_regs *regs, int fault)
        case VM_FAULT_BADCONTEXT:
                do_no_context(regs);
                break;
+       case VM_FAULT_SIGNAL:
+               if (!user_mode(regs))
+                       do_no_context(regs);
+               break;
        default: /* fault & VM_FAULT_ERROR */
                if (fault & VM_FAULT_OOM) {
-                       if (!(regs->psw.mask & PSW_MASK_PSTATE))
+                       if (!user_mode(regs))
                                do_no_context(regs);
                        else
                                pagefault_out_of_memory();
                } else if (fault & VM_FAULT_SIGBUS) {
                        /* Kernel mode? Handle exceptions or die */
-                       if (!(regs->psw.mask & PSW_MASK_PSTATE))
+                       if (!user_mode(regs))
                                do_no_context(regs);
                        else
                                do_sigbus(regs);
@@ -286,7 +291,7 @@ static inline int do_exception(struct pt_regs *regs, int access)
 
        address = trans_exc_code & __FAIL_ADDR_MASK;
        perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
-       flags = FAULT_FLAG_ALLOW_RETRY;
+       flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
        if (access == VM_WRITE || (trans_exc_code & store_indication) == 0x400)
                flags |= FAULT_FLAG_WRITE;
        down_read(&mm->mmap_sem);
@@ -335,6 +340,11 @@ retry:
         * the fault.
         */
        fault = handle_mm_fault(mm, vma, address, flags);
+       /* No reason to continue if interrupted by SIGKILL. */
+       if ((fault & VM_FAULT_RETRY) && fatal_signal_pending(current)) {
+               fault = VM_FAULT_SIGNAL;
+               goto out;
+       }
        if (unlikely(fault & VM_FAULT_ERROR))
                goto out_up;
 
@@ -426,7 +436,7 @@ void __kprobes do_asce_exception(struct pt_regs *regs)
        }
 
        /* User mode accesses just cause a SIGSEGV */
-       if (regs->psw.mask & PSW_MASK_PSTATE) {
+       if (user_mode(regs)) {
                do_sigsegv(regs, SEGV_MAPERR);
                return;
        }
@@ -441,6 +451,7 @@ int __handle_fault(unsigned long uaddr, unsigned long pgm_int_code, int write)
        struct pt_regs regs;
        int access, fault;
 
+       /* Emulate a uaccess fault from kernel mode. */
        regs.psw.mask = psw_kernel_bits | PSW_MASK_DAT | PSW_MASK_MCHECK;
        if (!irqs_disabled())
                regs.psw.mask |= PSW_MASK_IO | PSW_MASK_EXT;
@@ -450,12 +461,12 @@ int __handle_fault(unsigned long uaddr, unsigned long pgm_int_code, int write)
        regs.int_parm_long = (uaddr & PAGE_MASK) | 2;
        access = write ? VM_WRITE : VM_READ;
        fault = do_exception(&regs, access);
-       if (unlikely(fault)) {
-               if (fault & VM_FAULT_OOM)
-                       return -EFAULT;
-               else if (fault & VM_FAULT_SIGBUS)
-                       do_sigbus(&regs);
-       }
+       /*
+        * Since the fault happened in kernel mode while performing a uaccess
+        * all we need to do now is emulating a fixup in case "fault" is not
+        * zero.
+        * For the calling uaccess functions this results always in -EFAULT.
+        */
        return fault ? -EFAULT : 0;
 }
 
index 573384256c5c5ebd1aa65295e635e808345902d0..c59a5efa58b1ee701f93b4f980397e539265805a 100644 (file)
@@ -103,9 +103,15 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
 
 int s390_mmap_check(unsigned long addr, unsigned long len)
 {
+       int rc;
+
        if (!is_compat_task() &&
-           len >= TASK_SIZE && TASK_SIZE < (1UL << 53))
-               return crst_table_upgrade(current->mm, 1UL << 53);
+           len >= TASK_SIZE && TASK_SIZE < (1UL << 53)) {
+               rc = crst_table_upgrade(current->mm, 1UL << 53);
+               if (rc)
+                       return rc;
+               update_mm(current->mm, current);
+       }
        return 0;
 }
 
@@ -125,6 +131,7 @@ s390_get_unmapped_area(struct file *filp, unsigned long addr,
                rc = crst_table_upgrade(mm, 1UL << 53);
                if (rc)
                        return (unsigned long) rc;
+               update_mm(mm, current);
                area = arch_get_unmapped_area(filp, addr, len, pgoff, flags);
        }
        return area;
@@ -147,6 +154,7 @@ s390_get_unmapped_area_topdown(struct file *filp, const unsigned long addr,
                rc = crst_table_upgrade(mm, 1UL << 53);
                if (rc)
                        return (unsigned long) rc;
+               update_mm(mm, current);
                area = arch_get_unmapped_area_topdown(filp, addr, len,
                                                      pgoff, flags);
        }
index 1cab221077cc872b5f5e5528ff1918d8551fa9d2..18df31d1f2c9841cac3d97248a2806f9fb2d81a4 100644 (file)
@@ -85,7 +85,6 @@ repeat:
                crst_table_free(mm, table);
        if (mm->context.asce_limit < limit)
                goto repeat;
-       update_mm(mm, current);
        return 0;
 }
 
@@ -93,9 +92,6 @@ void crst_table_downgrade(struct mm_struct *mm, unsigned long limit)
 {
        pgd_t *pgd;
 
-       if (mm->context.asce_limit <= limit)
-               return;
-       __tlb_flush_mm(mm);
        while (mm->context.asce_limit > limit) {
                pgd = mm->pgd;
                switch (pgd_val(*pgd) & _REGION_ENTRY_TYPE_MASK) {
@@ -118,7 +114,6 @@ void crst_table_downgrade(struct mm_struct *mm, unsigned long limit)
                mm->task_size = mm->context.asce_limit;
                crst_table_free(mm, (unsigned long *) pgd);
        }
-       update_mm(mm, current);
 }
 #endif
 
@@ -801,7 +796,7 @@ int s390_enable_sie(void)
        struct mm_struct *mm, *old_mm;
 
        /* Do we have switched amode? If no, we cannot do sie */
-       if (user_mode == HOME_SPACE_MODE)
+       if (addressing_mode == HOME_SPACE_MODE)
                return -EINVAL;
 
        /* Do we have pgstes? if yes, we are done */
index c82f62fb9c28ef6096a486c6a3458725e91b31e3..8a6811b2cdb9523a24cd32341dee0fcef317f661 100644 (file)
@@ -58,7 +58,7 @@ void s390_backtrace(struct pt_regs * const regs, unsigned int depth)
        unsigned long head;
        struct stack_frame* head_sf;
 
-       if (user_mode (regs))
+       if (user_mode(regs))
                return;
 
        head = regs->gprs[15];
index 1ca9ceb95eb6413161f0844ca491ba4e1260f711..6acf834491050237548163230a2b89e7e53b9b61 100644 (file)
@@ -247,6 +247,7 @@ do_file(char const *const fname)
        case EM_X86_64:
                custom_sort = sort_x86_table;
                break;
+       case EM_S390:
        case EM_MIPS:
                break;
        }  /* end switch */