mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-06-17 20:25:19 +00:00
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
This commit is contained in:
commit
26847fa6eb
18 changed files with 104 additions and 105 deletions
|
@ -90,6 +90,7 @@ config S390
|
||||||
select HAVE_MEMBLOCK_NODE_MAP
|
select HAVE_MEMBLOCK_NODE_MAP
|
||||||
select HAVE_CMPXCHG_LOCAL
|
select HAVE_CMPXCHG_LOCAL
|
||||||
select ARCH_DISCARD_MEMBLOCK
|
select ARCH_DISCARD_MEMBLOCK
|
||||||
|
select BUILDTIME_EXTABLE_SORT
|
||||||
select ARCH_INLINE_SPIN_TRYLOCK
|
select ARCH_INLINE_SPIN_TRYLOCK
|
||||||
select ARCH_INLINE_SPIN_TRYLOCK_BH
|
select ARCH_INLINE_SPIN_TRYLOCK_BH
|
||||||
select ARCH_INLINE_SPIN_LOCK
|
select ARCH_INLINE_SPIN_LOCK
|
||||||
|
|
|
@ -7,6 +7,9 @@ CONFIG_TASK_DELAY_ACCT=y
|
||||||
CONFIG_TASK_XACCT=y
|
CONFIG_TASK_XACCT=y
|
||||||
CONFIG_TASK_IO_ACCOUNTING=y
|
CONFIG_TASK_IO_ACCOUNTING=y
|
||||||
CONFIG_AUDIT=y
|
CONFIG_AUDIT=y
|
||||||
|
CONFIG_NO_HZ=y
|
||||||
|
CONFIG_HIGH_RES_TIMERS=y
|
||||||
|
CONFIG_RCU_FAST_NO_HZ=y
|
||||||
CONFIG_IKCONFIG=y
|
CONFIG_IKCONFIG=y
|
||||||
CONFIG_IKCONFIG_PROC=y
|
CONFIG_IKCONFIG_PROC=y
|
||||||
CONFIG_CGROUPS=y
|
CONFIG_CGROUPS=y
|
||||||
|
@ -35,8 +38,6 @@ CONFIG_MODVERSIONS=y
|
||||||
CONFIG_PARTITION_ADVANCED=y
|
CONFIG_PARTITION_ADVANCED=y
|
||||||
CONFIG_IBM_PARTITION=y
|
CONFIG_IBM_PARTITION=y
|
||||||
CONFIG_DEFAULT_DEADLINE=y
|
CONFIG_DEFAULT_DEADLINE=y
|
||||||
CONFIG_NO_HZ=y
|
|
||||||
CONFIG_HIGH_RES_TIMERS=y
|
|
||||||
CONFIG_PREEMPT=y
|
CONFIG_PREEMPT=y
|
||||||
CONFIG_MEMORY_HOTPLUG=y
|
CONFIG_MEMORY_HOTPLUG=y
|
||||||
CONFIG_MEMORY_HOTREMOVE=y
|
CONFIG_MEMORY_HOTREMOVE=y
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
#include <asm/uaccess.h>
|
#include <asm/uaccess.h>
|
||||||
#include <asm/tlbflush.h>
|
#include <asm/tlbflush.h>
|
||||||
#include <asm/ctl_reg.h>
|
#include <asm/ctl_reg.h>
|
||||||
#include <asm-generic/mm_hooks.h>
|
|
||||||
|
|
||||||
static inline int init_new_context(struct task_struct *tsk,
|
static inline int init_new_context(struct task_struct *tsk,
|
||||||
struct mm_struct *mm)
|
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;
|
pgd_t *pgd = mm->pgd;
|
||||||
|
|
||||||
S390_lowcore.user_asce = mm->context.asce_bits | __pa(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. */
|
/* Load primary space page table origin. */
|
||||||
asm volatile(LCTL_OPCODE" 1,1,%0\n"
|
asm volatile(LCTL_OPCODE" 1,1,%0\n"
|
||||||
: : "m" (S390_lowcore.user_asce) );
|
: : "m" (S390_lowcore.user_asce) );
|
||||||
|
@ -91,4 +90,17 @@ static inline void activate_mm(struct mm_struct *prev,
|
||||||
switch_mm(prev, next, current);
|
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 */
|
#endif /* __S390_MMU_CONTEXT_H */
|
||||||
|
|
|
@ -120,7 +120,9 @@ struct stack_frame {
|
||||||
regs->psw.mask = psw_user_bits | PSW_MASK_BA; \
|
regs->psw.mask = psw_user_bits | PSW_MASK_BA; \
|
||||||
regs->psw.addr = new_psw | PSW_ADDR_AMODE; \
|
regs->psw.addr = new_psw | PSW_ADDR_AMODE; \
|
||||||
regs->gprs[15] = new_stackp; \
|
regs->gprs[15] = new_stackp; \
|
||||||
|
__tlb_flush_mm(current->mm); \
|
||||||
crst_table_downgrade(current->mm, 1UL << 31); \
|
crst_table_downgrade(current->mm, 1UL << 31); \
|
||||||
|
update_mm(current->mm, current); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
/* Forward declaration, a strange C thing */
|
/* Forward declaration, a strange C thing */
|
||||||
|
|
|
@ -60,7 +60,7 @@ void create_mem_hole(struct mem_chunk memory_chunk[], unsigned long addr,
|
||||||
#define SECONDARY_SPACE_MODE 2
|
#define SECONDARY_SPACE_MODE 2
|
||||||
#define HOME_SPACE_MODE 3
|
#define HOME_SPACE_MODE 3
|
||||||
|
|
||||||
extern unsigned int user_mode;
|
extern unsigned int addressing_mode;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Machine features detected in head.S
|
* Machine features detected in head.S
|
||||||
|
|
|
@ -110,6 +110,7 @@ struct debug_view debug_raw_view = {
|
||||||
NULL,
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
EXPORT_SYMBOL(debug_raw_view);
|
||||||
|
|
||||||
struct debug_view debug_hex_ascii_view = {
|
struct debug_view debug_hex_ascii_view = {
|
||||||
"hex_ascii",
|
"hex_ascii",
|
||||||
|
@ -119,6 +120,7 @@ struct debug_view debug_hex_ascii_view = {
|
||||||
NULL,
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
EXPORT_SYMBOL(debug_hex_ascii_view);
|
||||||
|
|
||||||
static struct debug_view debug_level_view = {
|
static struct debug_view debug_level_view = {
|
||||||
"level",
|
"level",
|
||||||
|
@ -155,6 +157,7 @@ struct debug_view debug_sprintf_view = {
|
||||||
NULL,
|
NULL,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
EXPORT_SYMBOL(debug_sprintf_view);
|
||||||
|
|
||||||
/* used by dump analysis tools to determine version of debug feature */
|
/* used by dump analysis tools to determine version of debug feature */
|
||||||
static unsigned int __used debug_feature_version = __DEBUG_FEATURE_VERSION;
|
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,
|
return debug_register_mode(name, pages_per_area, nr_areas, buf_size,
|
||||||
S_IRUSR | S_IWUSR, 0, 0);
|
S_IRUSR | S_IWUSR, 0, 0);
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(debug_register);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* debug_unregister:
|
* debug_unregister:
|
||||||
|
@ -748,6 +752,7 @@ debug_unregister(debug_info_t * id)
|
||||||
out:
|
out:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(debug_unregister);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* debug_set_size:
|
* debug_set_size:
|
||||||
|
@ -810,7 +815,7 @@ debug_set_level(debug_info_t* id, int new_level)
|
||||||
}
|
}
|
||||||
spin_unlock_irqrestore(&id->lock,flags);
|
spin_unlock_irqrestore(&id->lock,flags);
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(debug_set_level);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* proceed_active_entry:
|
* proceed_active_entry:
|
||||||
|
@ -930,7 +935,7 @@ debug_stop_all(void)
|
||||||
if (debug_stoppable)
|
if (debug_stoppable)
|
||||||
debug_active = 0;
|
debug_active = 0;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(debug_stop_all);
|
||||||
|
|
||||||
void debug_set_critical(void)
|
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;
|
return active;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(debug_event_common);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* debug_exception_common:
|
* debug_exception_common:
|
||||||
|
@ -990,6 +996,7 @@ debug_entry_t
|
||||||
|
|
||||||
return active;
|
return active;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(debug_exception_common);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* counts arguments in format string for sprintf view
|
* 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;
|
return active;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(debug_sprintf_event);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* debug_sprintf_exception:
|
* debug_sprintf_exception:
|
||||||
|
@ -1081,25 +1089,7 @@ debug_sprintf_exception(debug_info_t* id, int level,char *string,...)
|
||||||
|
|
||||||
return active;
|
return active;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(debug_sprintf_exception);
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* debug_register_view:
|
* debug_register_view:
|
||||||
|
@ -1147,6 +1137,7 @@ debug_register_view(debug_info_t * id, struct debug_view *view)
|
||||||
out:
|
out:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(debug_register_view);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* debug_unregister_view:
|
* debug_unregister_view:
|
||||||
|
@ -1176,6 +1167,7 @@ debug_unregister_view(debug_info_t * id, struct debug_view *view)
|
||||||
out:
|
out:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(debug_unregister_view);
|
||||||
|
|
||||||
static inline char *
|
static inline char *
|
||||||
debug_get_user_string(const char __user *user_buf, size_t user_len)
|
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);
|
except_str, entry->id.fields.cpuid, (void *) caller);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(debug_dflt_header_fn);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* prints debug data sprintf-formated:
|
* 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);
|
s390dbf_sysctl_header = register_sysctl_table(s390dbf_dir_table);
|
||||||
unregister_sysctl_table(s390dbf_sysctl_header);
|
mutex_lock(&debug_mutex);
|
||||||
return;
|
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);
|
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);
|
|
||||||
|
|
|
@ -1531,7 +1531,7 @@ static int print_insn(char *buffer, unsigned char *code, unsigned long addr)
|
||||||
|
|
||||||
void show_code(struct pt_regs *regs)
|
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];
|
unsigned char code[64];
|
||||||
char buffer[64], *ptr;
|
char buffer[64], *ptr;
|
||||||
mm_segment_t old_fs;
|
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. */
|
/* Get a snapshot of the 64 bytes surrounding the fault address. */
|
||||||
old_fs = get_fs();
|
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) {
|
for (start = 32; start && regs->psw.addr >= 34 - start; start -= 2) {
|
||||||
addr = regs->psw.addr - 34 + start;
|
addr = regs->psw.addr - 34 + start;
|
||||||
if (__copy_from_user(code + start - 2,
|
if (__copy_from_user(code + start - 2,
|
||||||
|
|
|
@ -455,7 +455,6 @@ void __init startup_init(void)
|
||||||
init_kernel_storage_key();
|
init_kernel_storage_key();
|
||||||
lockdep_init();
|
lockdep_init();
|
||||||
lockdep_off();
|
lockdep_off();
|
||||||
sort_main_extable();
|
|
||||||
setup_lowcore_early();
|
setup_lowcore_early();
|
||||||
setup_facility_list();
|
setup_facility_list();
|
||||||
detect_machine_type();
|
detect_machine_type();
|
||||||
|
|
|
@ -1583,7 +1583,7 @@ static struct kset *vmcmd_kset;
|
||||||
|
|
||||||
static void vmcmd_run(struct shutdown_trigger *trigger)
|
static void vmcmd_run(struct shutdown_trigger *trigger)
|
||||||
{
|
{
|
||||||
char *cmd, *next_cmd;
|
char *cmd;
|
||||||
|
|
||||||
if (strcmp(trigger->name, ON_REIPL_STR) == 0)
|
if (strcmp(trigger->name, ON_REIPL_STR) == 0)
|
||||||
cmd = vmcmd_on_reboot;
|
cmd = vmcmd_on_reboot;
|
||||||
|
@ -1600,15 +1600,7 @@ static void vmcmd_run(struct shutdown_trigger *trigger)
|
||||||
|
|
||||||
if (strlen(cmd) == 0)
|
if (strlen(cmd) == 0)
|
||||||
return;
|
return;
|
||||||
do {
|
__cpcmd(cmd, NULL, 0, NULL);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int vmcmd_init(void)
|
static int vmcmd_init(void)
|
||||||
|
|
|
@ -302,8 +302,8 @@ static int __init parse_vmalloc(char *arg)
|
||||||
}
|
}
|
||||||
early_param("vmalloc", parse_vmalloc);
|
early_param("vmalloc", parse_vmalloc);
|
||||||
|
|
||||||
unsigned int user_mode = HOME_SPACE_MODE;
|
unsigned int addressing_mode = HOME_SPACE_MODE;
|
||||||
EXPORT_SYMBOL_GPL(user_mode);
|
EXPORT_SYMBOL_GPL(addressing_mode);
|
||||||
|
|
||||||
static int set_amode_primary(void)
|
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)
|
static int __init early_parse_switch_amode(char *p)
|
||||||
{
|
{
|
||||||
user_mode = PRIMARY_SPACE_MODE;
|
addressing_mode = PRIMARY_SPACE_MODE;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
early_param("switch_amode", early_parse_switch_amode);
|
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)
|
static int __init early_parse_user_mode(char *p)
|
||||||
{
|
{
|
||||||
if (p && strcmp(p, "primary") == 0)
|
if (p && strcmp(p, "primary") == 0)
|
||||||
user_mode = PRIMARY_SPACE_MODE;
|
addressing_mode = PRIMARY_SPACE_MODE;
|
||||||
else if (!p || strcmp(p, "home") == 0)
|
else if (!p || strcmp(p, "home") == 0)
|
||||||
user_mode = HOME_SPACE_MODE;
|
addressing_mode = HOME_SPACE_MODE;
|
||||||
else
|
else
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -347,7 +347,7 @@ early_param("user_mode", early_parse_user_mode);
|
||||||
|
|
||||||
static void setup_addressing_mode(void)
|
static void setup_addressing_mode(void)
|
||||||
{
|
{
|
||||||
if (user_mode == PRIMARY_SPACE_MODE) {
|
if (addressing_mode == PRIMARY_SPACE_MODE) {
|
||||||
if (set_amode_primary())
|
if (set_amode_primary())
|
||||||
pr_info("Address spaces switched, "
|
pr_info("Address spaces switched, "
|
||||||
"mvcos available\n");
|
"mvcos available\n");
|
||||||
|
|
|
@ -185,7 +185,7 @@ void show_registers(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
char *mode;
|
char *mode;
|
||||||
|
|
||||||
mode = (regs->psw.mask & PSW_MASK_PSTATE) ? "User" : "Krnl";
|
mode = user_mode(regs) ? "User" : "Krnl";
|
||||||
printk("%s PSW : %p %p",
|
printk("%s PSW : %p %p",
|
||||||
mode, (void *) regs->psw.mask,
|
mode, (void *) regs->psw.mask,
|
||||||
(void *) regs->psw.addr);
|
(void *) regs->psw.addr);
|
||||||
|
@ -225,7 +225,7 @@ void show_regs(struct pt_regs *regs)
|
||||||
(void *) current->thread.ksp);
|
(void *) current->thread.ksp);
|
||||||
show_registers(regs);
|
show_registers(regs);
|
||||||
/* Show stack backtrace if pt_regs is from kernel mode */
|
/* 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_trace(NULL, (unsigned long *) regs->gprs[15]);
|
||||||
show_last_breaking_event(regs);
|
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)
|
regs->int_code, si_signo) == NOTIFY_STOP)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (regs->psw.mask & PSW_MASK_PSTATE) {
|
if (user_mode(regs)) {
|
||||||
info.si_signo = si_signo;
|
info.si_signo = si_signo;
|
||||||
info.si_errno = 0;
|
info.si_errno = 0;
|
||||||
info.si_code = si_code;
|
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)
|
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);
|
report_user_fault(regs, SIGSEGV);
|
||||||
do_exit(SIGSEGV);
|
do_exit(SIGSEGV);
|
||||||
} else
|
} else
|
||||||
|
@ -410,7 +410,7 @@ static void __kprobes illegal_op(struct pt_regs *regs)
|
||||||
|
|
||||||
location = get_psw_address(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))
|
if (get_user(*((__u16 *) opcode), (__u16 __user *) location))
|
||||||
return;
|
return;
|
||||||
if (*((__u16 *) opcode) == S390_BREAKPOINT_U16) {
|
if (*((__u16 *) opcode) == S390_BREAKPOINT_U16) {
|
||||||
|
@ -478,7 +478,7 @@ void specification_exception(struct pt_regs *regs)
|
||||||
|
|
||||||
location = (__u16 __user *) get_psw_address(regs);
|
location = (__u16 __user *) get_psw_address(regs);
|
||||||
|
|
||||||
if (regs->psw.mask & PSW_MASK_PSTATE) {
|
if (user_mode(regs)) {
|
||||||
get_user(*((__u16 *) opcode), location);
|
get_user(*((__u16 *) opcode), location);
|
||||||
switch (opcode[0]) {
|
switch (opcode[0]) {
|
||||||
case 0x28: /* LDR Rx,Ry */
|
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));
|
asm volatile("stfpc %0" : "=m" (current->thread.fp_regs.fpc));
|
||||||
|
|
||||||
#ifdef CONFIG_MATHEMU
|
#ifdef CONFIG_MATHEMU
|
||||||
else if (regs->psw.mask & PSW_MASK_PSTATE) {
|
else if (user_mode(regs)) {
|
||||||
__u8 opcode[6];
|
__u8 opcode[6];
|
||||||
get_user(*((__u16 *) opcode), location);
|
get_user(*((__u16 *) opcode), location);
|
||||||
switch (opcode[0]) {
|
switch (opcode[0]) {
|
||||||
|
@ -598,7 +598,7 @@ static void data_exception(struct pt_regs *regs)
|
||||||
static void space_switch_exception(struct pt_regs *regs)
|
static void space_switch_exception(struct pt_regs *regs)
|
||||||
{
|
{
|
||||||
/* Set user psw back to home space mode. */
|
/* 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;
|
regs->psw.mask |= PSW_ASC_HOME;
|
||||||
/* Send SIGILL. */
|
/* Send SIGILL. */
|
||||||
do_trap(regs, SIGILL, ILL_PRVOPC, "space switch event");
|
do_trap(regs, SIGILL, ILL_PRVOPC, "space switch event");
|
||||||
|
|
|
@ -84,7 +84,8 @@ struct vdso_data *vdso_data = &vdso_data_store.data;
|
||||||
*/
|
*/
|
||||||
static void vdso_init_data(struct vdso_data *vd)
|
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
|
#ifdef CONFIG_64BIT
|
||||||
|
@ -101,7 +102,7 @@ int vdso_alloc_per_cpu(struct _lowcore *lowcore)
|
||||||
|
|
||||||
lowcore->vdso_per_cpu_data = __LC_PASTE;
|
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;
|
return 0;
|
||||||
|
|
||||||
segment_table = __get_free_pages(GFP_KERNEL, SEGMENT_ORDER);
|
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;
|
unsigned long segment_table, page_table, page_frame;
|
||||||
u32 *psal, *aste;
|
u32 *psal, *aste;
|
||||||
|
|
||||||
if (user_mode == HOME_SPACE_MODE || !vdso_enabled)
|
if (addressing_mode == HOME_SPACE_MODE || !vdso_enabled)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
psal = (u32 *)(addr_t) lowcore->paste[4];
|
psal = (u32 *)(addr_t) lowcore->paste[4];
|
||||||
|
@ -164,7 +165,7 @@ static void vdso_init_cr5(void)
|
||||||
{
|
{
|
||||||
unsigned long cr5;
|
unsigned long cr5;
|
||||||
|
|
||||||
if (user_mode == HOME_SPACE_MODE || !vdso_enabled)
|
if (addressing_mode == HOME_SPACE_MODE || !vdso_enabled)
|
||||||
return;
|
return;
|
||||||
cr5 = offsetof(struct _lowcore, paste);
|
cr5 = offsetof(struct _lowcore, paste);
|
||||||
__ctl_load(cr5, 5, 5);
|
__ctl_load(cr5, 5, 5);
|
||||||
|
|
|
@ -45,7 +45,7 @@ SECTIONS
|
||||||
|
|
||||||
.dummy : { *(.dummy) } :data
|
.dummy : { *(.dummy) } :data
|
||||||
|
|
||||||
RODATA
|
RO_DATA_SECTION(PAGE_SIZE)
|
||||||
|
|
||||||
#ifdef CONFIG_SHARED_KERNEL
|
#ifdef CONFIG_SHARED_KERNEL
|
||||||
. = ALIGN(0x100000); /* VM shared segments are 1MB aligned */
|
. = ALIGN(0x100000); /* VM shared segments are 1MB aligned */
|
||||||
|
|
|
@ -49,6 +49,7 @@
|
||||||
#define VM_FAULT_BADCONTEXT 0x010000
|
#define VM_FAULT_BADCONTEXT 0x010000
|
||||||
#define VM_FAULT_BADMAP 0x020000
|
#define VM_FAULT_BADMAP 0x020000
|
||||||
#define VM_FAULT_BADACCESS 0x040000
|
#define VM_FAULT_BADACCESS 0x040000
|
||||||
|
#define VM_FAULT_SIGNAL 0x080000
|
||||||
|
|
||||||
static unsigned long store_indication;
|
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)
|
if (trans_exc_code == 2)
|
||||||
/* Access via secondary space, set_fs setting decides */
|
/* Access via secondary space, set_fs setting decides */
|
||||||
return current->thread.mm_segment.ar4;
|
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. */
|
/* User space if the access has been done via home space. */
|
||||||
return trans_exc_code == 3;
|
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_BADACCESS:
|
||||||
case VM_FAULT_BADMAP:
|
case VM_FAULT_BADMAP:
|
||||||
/* Bad memory access. Check if it is kernel or user space. */
|
/* 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 */
|
/* User mode accesses just cause a SIGSEGV */
|
||||||
si_code = (fault == VM_FAULT_BADMAP) ?
|
si_code = (fault == VM_FAULT_BADMAP) ?
|
||||||
SEGV_MAPERR : SEGV_ACCERR;
|
SEGV_MAPERR : SEGV_ACCERR;
|
||||||
|
@ -229,15 +230,19 @@ static noinline void do_fault_error(struct pt_regs *regs, int fault)
|
||||||
case VM_FAULT_BADCONTEXT:
|
case VM_FAULT_BADCONTEXT:
|
||||||
do_no_context(regs);
|
do_no_context(regs);
|
||||||
break;
|
break;
|
||||||
|
case VM_FAULT_SIGNAL:
|
||||||
|
if (!user_mode(regs))
|
||||||
|
do_no_context(regs);
|
||||||
|
break;
|
||||||
default: /* fault & VM_FAULT_ERROR */
|
default: /* fault & VM_FAULT_ERROR */
|
||||||
if (fault & VM_FAULT_OOM) {
|
if (fault & VM_FAULT_OOM) {
|
||||||
if (!(regs->psw.mask & PSW_MASK_PSTATE))
|
if (!user_mode(regs))
|
||||||
do_no_context(regs);
|
do_no_context(regs);
|
||||||
else
|
else
|
||||||
pagefault_out_of_memory();
|
pagefault_out_of_memory();
|
||||||
} else if (fault & VM_FAULT_SIGBUS) {
|
} else if (fault & VM_FAULT_SIGBUS) {
|
||||||
/* Kernel mode? Handle exceptions or die */
|
/* Kernel mode? Handle exceptions or die */
|
||||||
if (!(regs->psw.mask & PSW_MASK_PSTATE))
|
if (!user_mode(regs))
|
||||||
do_no_context(regs);
|
do_no_context(regs);
|
||||||
else
|
else
|
||||||
do_sigbus(regs);
|
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;
|
address = trans_exc_code & __FAIL_ADDR_MASK;
|
||||||
perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
|
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)
|
if (access == VM_WRITE || (trans_exc_code & store_indication) == 0x400)
|
||||||
flags |= FAULT_FLAG_WRITE;
|
flags |= FAULT_FLAG_WRITE;
|
||||||
down_read(&mm->mmap_sem);
|
down_read(&mm->mmap_sem);
|
||||||
|
@ -335,6 +340,11 @@ retry:
|
||||||
* the fault.
|
* the fault.
|
||||||
*/
|
*/
|
||||||
fault = handle_mm_fault(mm, vma, address, flags);
|
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))
|
if (unlikely(fault & VM_FAULT_ERROR))
|
||||||
goto out_up;
|
goto out_up;
|
||||||
|
|
||||||
|
@ -426,7 +436,7 @@ void __kprobes do_asce_exception(struct pt_regs *regs)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* User mode accesses just cause a SIGSEGV */
|
/* User mode accesses just cause a SIGSEGV */
|
||||||
if (regs->psw.mask & PSW_MASK_PSTATE) {
|
if (user_mode(regs)) {
|
||||||
do_sigsegv(regs, SEGV_MAPERR);
|
do_sigsegv(regs, SEGV_MAPERR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -441,6 +451,7 @@ int __handle_fault(unsigned long uaddr, unsigned long pgm_int_code, int write)
|
||||||
struct pt_regs regs;
|
struct pt_regs regs;
|
||||||
int access, fault;
|
int access, fault;
|
||||||
|
|
||||||
|
/* Emulate a uaccess fault from kernel mode. */
|
||||||
regs.psw.mask = psw_kernel_bits | PSW_MASK_DAT | PSW_MASK_MCHECK;
|
regs.psw.mask = psw_kernel_bits | PSW_MASK_DAT | PSW_MASK_MCHECK;
|
||||||
if (!irqs_disabled())
|
if (!irqs_disabled())
|
||||||
regs.psw.mask |= PSW_MASK_IO | PSW_MASK_EXT;
|
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;
|
regs.int_parm_long = (uaddr & PAGE_MASK) | 2;
|
||||||
access = write ? VM_WRITE : VM_READ;
|
access = write ? VM_WRITE : VM_READ;
|
||||||
fault = do_exception(®s, access);
|
fault = do_exception(®s, access);
|
||||||
if (unlikely(fault)) {
|
/*
|
||||||
if (fault & VM_FAULT_OOM)
|
* Since the fault happened in kernel mode while performing a uaccess
|
||||||
return -EFAULT;
|
* all we need to do now is emulating a fixup in case "fault" is not
|
||||||
else if (fault & VM_FAULT_SIGBUS)
|
* zero.
|
||||||
do_sigbus(®s);
|
* For the calling uaccess functions this results always in -EFAULT.
|
||||||
}
|
*/
|
||||||
return fault ? -EFAULT : 0;
|
return fault ? -EFAULT : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -103,9 +103,15 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
|
||||||
|
|
||||||
int s390_mmap_check(unsigned long addr, unsigned long len)
|
int s390_mmap_check(unsigned long addr, unsigned long len)
|
||||||
{
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
if (!is_compat_task() &&
|
if (!is_compat_task() &&
|
||||||
len >= TASK_SIZE && TASK_SIZE < (1UL << 53))
|
len >= TASK_SIZE && TASK_SIZE < (1UL << 53)) {
|
||||||
return crst_table_upgrade(current->mm, 1UL << 53);
|
rc = crst_table_upgrade(current->mm, 1UL << 53);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
update_mm(current->mm, current);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,6 +131,7 @@ s390_get_unmapped_area(struct file *filp, unsigned long addr,
|
||||||
rc = crst_table_upgrade(mm, 1UL << 53);
|
rc = crst_table_upgrade(mm, 1UL << 53);
|
||||||
if (rc)
|
if (rc)
|
||||||
return (unsigned long) rc;
|
return (unsigned long) rc;
|
||||||
|
update_mm(mm, current);
|
||||||
area = arch_get_unmapped_area(filp, addr, len, pgoff, flags);
|
area = arch_get_unmapped_area(filp, addr, len, pgoff, flags);
|
||||||
}
|
}
|
||||||
return area;
|
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);
|
rc = crst_table_upgrade(mm, 1UL << 53);
|
||||||
if (rc)
|
if (rc)
|
||||||
return (unsigned long) rc;
|
return (unsigned long) rc;
|
||||||
|
update_mm(mm, current);
|
||||||
area = arch_get_unmapped_area_topdown(filp, addr, len,
|
area = arch_get_unmapped_area_topdown(filp, addr, len,
|
||||||
pgoff, flags);
|
pgoff, flags);
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,7 +85,6 @@ repeat:
|
||||||
crst_table_free(mm, table);
|
crst_table_free(mm, table);
|
||||||
if (mm->context.asce_limit < limit)
|
if (mm->context.asce_limit < limit)
|
||||||
goto repeat;
|
goto repeat;
|
||||||
update_mm(mm, current);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,9 +92,6 @@ void crst_table_downgrade(struct mm_struct *mm, unsigned long limit)
|
||||||
{
|
{
|
||||||
pgd_t *pgd;
|
pgd_t *pgd;
|
||||||
|
|
||||||
if (mm->context.asce_limit <= limit)
|
|
||||||
return;
|
|
||||||
__tlb_flush_mm(mm);
|
|
||||||
while (mm->context.asce_limit > limit) {
|
while (mm->context.asce_limit > limit) {
|
||||||
pgd = mm->pgd;
|
pgd = mm->pgd;
|
||||||
switch (pgd_val(*pgd) & _REGION_ENTRY_TYPE_MASK) {
|
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;
|
mm->task_size = mm->context.asce_limit;
|
||||||
crst_table_free(mm, (unsigned long *) pgd);
|
crst_table_free(mm, (unsigned long *) pgd);
|
||||||
}
|
}
|
||||||
update_mm(mm, current);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -801,7 +796,7 @@ int s390_enable_sie(void)
|
||||||
struct mm_struct *mm, *old_mm;
|
struct mm_struct *mm, *old_mm;
|
||||||
|
|
||||||
/* Do we have switched amode? If no, we cannot do sie */
|
/* 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;
|
return -EINVAL;
|
||||||
|
|
||||||
/* Do we have pgstes? if yes, we are done */
|
/* Do we have pgstes? if yes, we are done */
|
||||||
|
|
|
@ -58,7 +58,7 @@ void s390_backtrace(struct pt_regs * const regs, unsigned int depth)
|
||||||
unsigned long head;
|
unsigned long head;
|
||||||
struct stack_frame* head_sf;
|
struct stack_frame* head_sf;
|
||||||
|
|
||||||
if (user_mode (regs))
|
if (user_mode(regs))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
head = regs->gprs[15];
|
head = regs->gprs[15];
|
||||||
|
|
|
@ -247,6 +247,7 @@ do_file(char const *const fname)
|
||||||
case EM_X86_64:
|
case EM_X86_64:
|
||||||
custom_sort = sort_x86_table;
|
custom_sort = sort_x86_table;
|
||||||
break;
|
break;
|
||||||
|
case EM_S390:
|
||||||
case EM_MIPS:
|
case EM_MIPS:
|
||||||
break;
|
break;
|
||||||
} /* end switch */
|
} /* end switch */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue