Browse Source

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux

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
master
Linus Torvalds 10 years ago
parent
commit
26847fa6eb
  1. 1
      arch/s390/Kconfig
  2. 5
      arch/s390/defconfig
  3. 16
      arch/s390/include/asm/mmu_context.h
  4. 2
      arch/s390/include/asm/processor.h
  5. 2
      arch/s390/include/asm/setup.h
  6. 70
      arch/s390/kernel/debug.c
  7. 4
      arch/s390/kernel/dis.c
  8. 1
      arch/s390/kernel/early.c
  9. 12
      arch/s390/kernel/ipl.c
  10. 12
      arch/s390/kernel/setup.c
  11. 16
      arch/s390/kernel/traps.c
  12. 9
      arch/s390/kernel/vdso.c
  13. 2
      arch/s390/kernel/vmlinux.lds.S
  14. 35
      arch/s390/mm/fault.c
  15. 12
      arch/s390/mm/mmap.c
  16. 7
      arch/s390/mm/pgtable.c
  17. 2
      arch/s390/oprofile/backtrace.c
  18. 1
      scripts/sortextable.c

1
arch/s390/Kconfig

@ -90,6 +90,7 @@ config S390 @@ -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

5
arch/s390/defconfig

@ -7,6 +7,9 @@ CONFIG_TASK_DELAY_ACCT=y @@ -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 @@ -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

16
arch/s390/include/asm/mmu_context.h

@ -11,7 +11,6 @@ @@ -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) @@ -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, @@ -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 */

2
arch/s390/include/asm/processor.h

@ -120,7 +120,9 @@ struct stack_frame { @@ -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 */

2
arch/s390/include/asm/setup.h

@ -60,7 +60,7 @@ void create_mem_hole(struct mem_chunk memory_chunk[], unsigned long addr, @@ -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

70
arch/s390/kernel/debug.c

@ -110,6 +110,7 @@ struct debug_view debug_raw_view = { @@ -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 = { @@ -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 = { @@ -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, @@ -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) @@ -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) @@ -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) @@ -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) @@ -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 @@ -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,...) @@ -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,...) @@ -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) @@ -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) @@ -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, @@ -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: @@ -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);

4
arch/s390/kernel/dis.c

@ -1531,7 +1531,7 @@ static int print_insn(char *buffer, unsigned char *code, unsigned long addr) @@ -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) @@ -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,

1
arch/s390/kernel/early.c

@ -455,7 +455,6 @@ void __init startup_init(void) @@ -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();

12
arch/s390/kernel/ipl.c

@ -1583,7 +1583,7 @@ static struct kset *vmcmd_kset; @@ -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) @@ -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)

12
arch/s390/kernel/setup.c

@ -302,8 +302,8 @@ static int __init parse_vmalloc(char *arg) @@ -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) @@ -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); @@ -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); @@ -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");

16
arch/s390/kernel/traps.c

@ -185,7 +185,7 @@ void show_registers(struct pt_regs *regs) @@ -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) @@ -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, @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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");

9
arch/s390/kernel/vdso.c

@ -84,7 +84,8 @@ struct vdso_data *vdso_data = &vdso_data_store.data; @@ -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) @@ -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) @@ -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) @@ -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);

2
arch/s390/kernel/vmlinux.lds.S

@ -45,7 +45,7 @@ SECTIONS @@ -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 */

35
arch/s390/mm/fault.c

@ -49,6 +49,7 @@ @@ -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) @@ -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) @@ -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) @@ -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) @@ -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: @@ -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) @@ -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) @@ -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) @@ -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;
}

12
arch/s390/mm/mmap.c

@ -103,9 +103,15 @@ void arch_pick_mmap_layout(struct mm_struct *mm) @@ -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, @@ -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, @@ -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);
}

7
arch/s390/mm/pgtable.c

@ -85,7 +85,6 @@ repeat: @@ -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) @@ -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) @@ -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) @@ -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 */

2
arch/s390/oprofile/backtrace.c

@ -58,7 +58,7 @@ void s390_backtrace(struct pt_regs * const regs, unsigned int depth) @@ -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];

1
scripts/sortextable.c

@ -247,6 +247,7 @@ do_file(char const *const fname) @@ -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 */

Loading…
Cancel
Save