diff options
Diffstat (limited to 'arch/s390/mm')
-rw-r--r-- | arch/s390/mm/cmm.c | 110 | ||||
-rw-r--r-- | arch/s390/mm/extmem.c | 19 | ||||
-rw-r--r-- | arch/s390/mm/fault.c | 32 | ||||
-rw-r--r-- | arch/s390/mm/init.c | 1 | ||||
-rw-r--r-- | arch/s390/mm/maccess.c | 26 | ||||
-rw-r--r-- | arch/s390/mm/page-states.c | 1 | ||||
-rw-r--r-- | arch/s390/mm/pgtable.c | 2 | ||||
-rw-r--r-- | arch/s390/mm/vmem.c | 12 |
8 files changed, 99 insertions, 104 deletions
diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c index f16bd04e39e..eb6a2ef5f82 100644 --- a/arch/s390/mm/cmm.c +++ b/arch/s390/mm/cmm.c @@ -1,17 +1,16 @@ /* - * arch/s390/mm/cmm.c + * Collaborative memory management interface. * - * S390 version - * Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation - * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com) + * Copyright IBM Corp 2003,2010 + * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>, * - * Collaborative memory management interface. */ #include <linux/errno.h> #include <linux/fs.h> #include <linux/init.h> #include <linux/module.h> +#include <linux/gfp.h> #include <linux/sched.h> #include <linux/sysctl.h> #include <linux/ctype.h> @@ -19,9 +18,9 @@ #include <linux/kthread.h> #include <linux/oom.h> #include <linux/suspend.h> +#include <linux/uaccess.h> #include <asm/pgalloc.h> -#include <asm/uaccess.h> #include <asm/diag.h> static char *sender = "VMRMSVM"; @@ -52,14 +51,14 @@ static struct cmm_page_array *cmm_timed_page_list; static DEFINE_SPINLOCK(cmm_lock); static struct task_struct *cmm_thread_ptr; -static wait_queue_head_t cmm_thread_wait; -static struct timer_list cmm_timer; +static DECLARE_WAIT_QUEUE_HEAD(cmm_thread_wait); +static DEFINE_TIMER(cmm_timer, NULL, 0, 0); static void cmm_timer_fn(unsigned long); static void cmm_set_timer(void); -static long -cmm_alloc_pages(long nr, long *counter, struct cmm_page_array **list) +static long cmm_alloc_pages(long nr, long *counter, + struct cmm_page_array **list) { struct cmm_page_array *pa, *npa; unsigned long addr; @@ -98,8 +97,7 @@ cmm_alloc_pages(long nr, long *counter, struct cmm_page_array **list) return nr; } -static long -cmm_free_pages(long nr, long *counter, struct cmm_page_array **list) +static long cmm_free_pages(long nr, long *counter, struct cmm_page_array **list) { struct cmm_page_array *pa; unsigned long addr; @@ -139,11 +137,10 @@ static int cmm_oom_notify(struct notifier_block *self, } static struct notifier_block cmm_oom_nb = { - .notifier_call = cmm_oom_notify + .notifier_call = cmm_oom_notify, }; -static int -cmm_thread(void *dummy) +static int cmm_thread(void *dummy) { int rc; @@ -169,7 +166,7 @@ cmm_thread(void *dummy) cmm_timed_pages_target = cmm_timed_pages; } else if (cmm_timed_pages_target < cmm_timed_pages) { cmm_free_pages(1, &cmm_timed_pages, - &cmm_timed_page_list); + &cmm_timed_page_list); } if (cmm_timed_pages > 0 && !timer_pending(&cmm_timer)) cmm_set_timer(); @@ -177,14 +174,12 @@ cmm_thread(void *dummy) return 0; } -static void -cmm_kick_thread(void) +static void cmm_kick_thread(void) { wake_up(&cmm_thread_wait); } -static void -cmm_set_timer(void) +static void cmm_set_timer(void) { if (cmm_timed_pages_target <= 0 || cmm_timeout_seconds <= 0) { if (timer_pending(&cmm_timer)) @@ -201,8 +196,7 @@ cmm_set_timer(void) add_timer(&cmm_timer); } -static void -cmm_timer_fn(unsigned long ignored) +static void cmm_timer_fn(unsigned long ignored) { long nr; @@ -215,57 +209,49 @@ cmm_timer_fn(unsigned long ignored) cmm_set_timer(); } -void -cmm_set_pages(long nr) +static void cmm_set_pages(long nr) { cmm_pages_target = nr; cmm_kick_thread(); } -long -cmm_get_pages(void) +static long cmm_get_pages(void) { return cmm_pages; } -void -cmm_add_timed_pages(long nr) +static void cmm_add_timed_pages(long nr) { cmm_timed_pages_target += nr; cmm_kick_thread(); } -long -cmm_get_timed_pages(void) +static long cmm_get_timed_pages(void) { return cmm_timed_pages; } -void -cmm_set_timeout(long nr, long seconds) +static void cmm_set_timeout(long nr, long seconds) { cmm_timeout_pages = nr; cmm_timeout_seconds = seconds; cmm_set_timer(); } -static int -cmm_skip_blanks(char *cp, char **endp) +static int cmm_skip_blanks(char *cp, char **endp) { char *str; - for (str = cp; *str == ' ' || *str == '\t'; str++); + for (str = cp; *str == ' ' || *str == '\t'; str++) + ; *endp = str; return str != cp; } -#ifdef CONFIG_CMM_PROC - static struct ctl_table cmm_table[]; -static int -cmm_pages_handler(ctl_table *ctl, int write, - void __user *buffer, size_t *lenp, loff_t *ppos) +static int cmm_pages_handler(ctl_table *ctl, int write, void __user *buffer, + size_t *lenp, loff_t *ppos) { char buf[16], *p; long nr; @@ -304,9 +290,8 @@ cmm_pages_handler(ctl_table *ctl, int write, return 0; } -static int -cmm_timeout_handler(ctl_table *ctl, int write, - void __user *buffer, size_t *lenp, loff_t *ppos) +static int cmm_timeout_handler(ctl_table *ctl, int write, void __user *buffer, + size_t *lenp, loff_t *ppos) { char buf[64], *p; long nr, seconds; @@ -369,12 +354,10 @@ static struct ctl_table cmm_dir_table[] = { }, { } }; -#endif #ifdef CONFIG_CMM_IUCV #define SMSG_PREFIX "CMM" -static void -cmm_smsg_target(const char *from, char *msg) +static void cmm_smsg_target(const char *from, char *msg) { long nr, seconds; @@ -444,16 +427,13 @@ static struct notifier_block cmm_power_notifier = { .notifier_call = cmm_power_event, }; -static int -cmm_init (void) +static int cmm_init(void) { int rc = -ENOMEM; -#ifdef CONFIG_CMM_PROC cmm_sysctl_header = register_sysctl_table(cmm_dir_table); if (!cmm_sysctl_header) goto out_sysctl; -#endif #ifdef CONFIG_CMM_IUCV rc = smsg_register_callback(SMSG_PREFIX, cmm_smsg_target); if (rc < 0) @@ -465,8 +445,6 @@ cmm_init (void) rc = register_pm_notifier(&cmm_power_notifier); if (rc) goto out_pm; - init_waitqueue_head(&cmm_thread_wait); - init_timer(&cmm_timer); cmm_thread_ptr = kthread_run(cmm_thread, NULL, "cmmthread"); rc = IS_ERR(cmm_thread_ptr) ? PTR_ERR(cmm_thread_ptr) : 0; if (rc) @@ -482,36 +460,26 @@ out_oom_notify: smsg_unregister_callback(SMSG_PREFIX, cmm_smsg_target); out_smsg: #endif -#ifdef CONFIG_CMM_PROC unregister_sysctl_table(cmm_sysctl_header); out_sysctl: -#endif + del_timer_sync(&cmm_timer); return rc; } +module_init(cmm_init); -static void -cmm_exit(void) +static void cmm_exit(void) { - kthread_stop(cmm_thread_ptr); - unregister_pm_notifier(&cmm_power_notifier); - unregister_oom_notifier(&cmm_oom_nb); - cmm_free_pages(cmm_pages, &cmm_pages, &cmm_page_list); - cmm_free_pages(cmm_timed_pages, &cmm_timed_pages, &cmm_timed_page_list); -#ifdef CONFIG_CMM_PROC unregister_sysctl_table(cmm_sysctl_header); -#endif #ifdef CONFIG_CMM_IUCV smsg_unregister_callback(SMSG_PREFIX, cmm_smsg_target); #endif + unregister_pm_notifier(&cmm_power_notifier); + unregister_oom_notifier(&cmm_oom_nb); + kthread_stop(cmm_thread_ptr); + del_timer_sync(&cmm_timer); + cmm_free_pages(cmm_pages, &cmm_pages, &cmm_page_list); + cmm_free_pages(cmm_timed_pages, &cmm_timed_pages, &cmm_timed_page_list); } - -module_init(cmm_init); module_exit(cmm_exit); -EXPORT_SYMBOL(cmm_set_pages); -EXPORT_SYMBOL(cmm_get_pages); -EXPORT_SYMBOL(cmm_add_timed_pages); -EXPORT_SYMBOL(cmm_get_timed_pages); -EXPORT_SYMBOL(cmm_set_timeout); - MODULE_LICENSE("GPL"); diff --git a/arch/s390/mm/extmem.c b/arch/s390/mm/extmem.c index 6409fd57eb0..3cc95dd0a3a 100644 --- a/arch/s390/mm/extmem.c +++ b/arch/s390/mm/extmem.c @@ -105,7 +105,7 @@ static int dcss_set_subcodes(void) { #ifdef CONFIG_64BIT - char *name = kmalloc(8 * sizeof(char), GFP_DMA); + char *name = kmalloc(8 * sizeof(char), GFP_KERNEL | GFP_DMA); unsigned long rx, ry; int rc; @@ -252,12 +252,13 @@ dcss_diag_translate_rc (int vm_rc) { static int query_segment_type (struct dcss_segment *seg) { - struct qin64 *qin = kmalloc (sizeof(struct qin64), GFP_DMA); - struct qout64 *qout = kmalloc (sizeof(struct qout64), GFP_DMA); - - int diag_cc, rc, i; unsigned long dummy, vmrc; + int diag_cc, rc, i; + struct qout64 *qout; + struct qin64 *qin; + qin = kmalloc(sizeof(*qin), GFP_KERNEL | GFP_DMA); + qout = kmalloc(sizeof(*qout), GFP_KERNEL | GFP_DMA); if ((qin == NULL) || (qout == NULL)) { rc = -ENOMEM; goto out_free; @@ -286,7 +287,7 @@ query_segment_type (struct dcss_segment *seg) copy data for the new format. */ if (segext_scode == DCSS_SEGEXT) { struct qout64_old *qout_old; - qout_old = kzalloc(sizeof(struct qout64_old), GFP_DMA); + qout_old = kzalloc(sizeof(*qout_old), GFP_KERNEL | GFP_DMA); if (qout_old == NULL) { rc = -ENOMEM; goto out_free; @@ -407,11 +408,11 @@ segment_overlaps_others (struct dcss_segment *seg) static int __segment_load (char *name, int do_nonshared, unsigned long *addr, unsigned long *end) { - struct dcss_segment *seg = kmalloc(sizeof(struct dcss_segment), - GFP_DMA); - int rc, diag_cc; unsigned long start_addr, end_addr, dummy; + struct dcss_segment *seg; + int rc, diag_cc; + seg = kmalloc(sizeof(*seg), GFP_KERNEL | GFP_DMA); if (seg == NULL) { rc = -ENOMEM; goto out; diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c index 3040d7c78fe..2505b2ea0ef 100644 --- a/arch/s390/mm/fault.c +++ b/arch/s390/mm/fault.c @@ -48,10 +48,6 @@ #define __PF_RES_FIELD 0x8000000000000000ULL #endif /* CONFIG_64BIT */ -#ifdef CONFIG_SYSCTL -extern int sysctl_userprocess_debug; -#endif - #define VM_FAULT_BADCONTEXT 0x010000 #define VM_FAULT_BADMAP 0x020000 #define VM_FAULT_BADACCESS 0x040000 @@ -120,6 +116,22 @@ static inline int user_space_fault(unsigned long trans_exc_code) return trans_exc_code != 3; } +static inline void report_user_fault(struct pt_regs *regs, long int_code, + int signr, unsigned long address) +{ + if ((task_pid_nr(current) > 1) && !show_unhandled_signals) + return; + if (!unhandled_signal(current, signr)) + return; + if (!printk_ratelimit()) + return; + printk("User process fault: interruption code 0x%lX ", int_code); + print_vma_addr(KERN_CONT "in ", regs->psw.addr & PSW_ADDR_INSN); + printk("\n"); + printk("failing address: %lX\n", address); + show_regs(regs); +} + /* * Send SIGSEGV to task. This is an external routine * to keep the stack usage of do_page_fault small. @@ -133,17 +145,7 @@ static noinline void do_sigsegv(struct pt_regs *regs, long int_code, address = trans_exc_code & __FAIL_ADDR_MASK; current->thread.prot_addr = address; current->thread.trap_no = int_code; -#if defined(CONFIG_SYSCTL) || defined(CONFIG_PROCESS_DEBUG) -#if defined(CONFIG_SYSCTL) - if (sysctl_userprocess_debug) -#endif - { - printk("User process fault: interruption code 0x%lX\n", - int_code); - printk("failing address: %lX\n", address); - show_regs(regs); - } -#endif + report_user_fault(regs, int_code, SIGSEGV, address); si.si_signo = SIGSEGV; si.si_code = si_code; si.si_addr = (void __user *) address; diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c index d5865e4024c..acc91c75bc9 100644 --- a/arch/s390/mm/init.c +++ b/arch/s390/mm/init.c @@ -26,6 +26,7 @@ #include <linux/pfn.h> #include <linux/poison.h> #include <linux/initrd.h> +#include <linux/gfp.h> #include <asm/processor.h> #include <asm/system.h> #include <asm/uaccess.h> diff --git a/arch/s390/mm/maccess.c b/arch/s390/mm/maccess.c index 81756271dc4..a8c2af8c650 100644 --- a/arch/s390/mm/maccess.c +++ b/arch/s390/mm/maccess.c @@ -59,3 +59,29 @@ long probe_kernel_write(void *dst, void *src, size_t size) } return copied < 0 ? -EFAULT : 0; } + +int memcpy_real(void *dest, void *src, size_t count) +{ + register unsigned long _dest asm("2") = (unsigned long) dest; + register unsigned long _len1 asm("3") = (unsigned long) count; + register unsigned long _src asm("4") = (unsigned long) src; + register unsigned long _len2 asm("5") = (unsigned long) count; + unsigned long flags; + int rc = -EFAULT; + + if (!count) + return 0; + flags = __raw_local_irq_stnsm(0xf8UL); + asm volatile ( + "0: mvcle %1,%2,0x0\n" + "1: jo 0b\n" + " lhi %0,0x0\n" + "2:\n" + EX_TABLE(1b,2b) + : "+d" (rc), "+d" (_dest), "+d" (_src), "+d" (_len1), + "+d" (_len2), "=m" (*((long *) dest)) + : "m" (*((long *) src)) + : "cc", "memory"); + __raw_local_irq_ssm(flags); + return rc; +} diff --git a/arch/s390/mm/page-states.c b/arch/s390/mm/page-states.c index 098923ae458..a90d45e9dfb 100644 --- a/arch/s390/mm/page-states.c +++ b/arch/s390/mm/page-states.c @@ -10,6 +10,7 @@ #include <linux/errno.h> #include <linux/types.h> #include <linux/mm.h> +#include <linux/gfp.h> #include <linux/init.h> #define ESSA_SET_STABLE 1 diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c index ad621e06ada..8d999249d35 100644 --- a/arch/s390/mm/pgtable.c +++ b/arch/s390/mm/pgtable.c @@ -6,11 +6,11 @@ #include <linux/sched.h> #include <linux/kernel.h> #include <linux/errno.h> +#include <linux/gfp.h> #include <linux/mm.h> #include <linux/swap.h> #include <linux/smp.h> #include <linux/highmem.h> -#include <linux/slab.h> #include <linux/pagemap.h> #include <linux/spinlock.h> #include <linux/module.h> diff --git a/arch/s390/mm/vmem.c b/arch/s390/mm/vmem.c index 300ab012b0f..90165e7ca04 100644 --- a/arch/s390/mm/vmem.c +++ b/arch/s390/mm/vmem.c @@ -11,6 +11,7 @@ #include <linux/module.h> #include <linux/list.h> #include <linux/hugetlb.h> +#include <linux/slab.h> #include <asm/pgalloc.h> #include <asm/pgtable.h> #include <asm/setup.h> @@ -70,12 +71,8 @@ static pte_t __ref *vmem_pte_alloc(void) pte = alloc_bootmem(PTRS_PER_PTE * sizeof(pte_t)); if (!pte) return NULL; - if (MACHINE_HAS_HPAGE) - clear_table((unsigned long *) pte, _PAGE_TYPE_EMPTY | _PAGE_CO, - PTRS_PER_PTE * sizeof(pte_t)); - else - clear_table((unsigned long *) pte, _PAGE_TYPE_EMPTY, - PTRS_PER_PTE * sizeof(pte_t)); + clear_table((unsigned long *) pte, _PAGE_TYPE_EMPTY, + PTRS_PER_PTE * sizeof(pte_t)); return pte; } @@ -116,8 +113,7 @@ static int vmem_add_mem(unsigned long start, unsigned long size, int ro) if (MACHINE_HAS_HPAGE && !(address & ~HPAGE_MASK) && (address + HPAGE_SIZE <= start + size) && (address >= HPAGE_SIZE)) { - pte_val(pte) |= _SEGMENT_ENTRY_LARGE | - _SEGMENT_ENTRY_CO; + pte_val(pte) |= _SEGMENT_ENTRY_LARGE; pmd_val(*pm_dir) = pte_val(pte); address += HPAGE_SIZE - PAGE_SIZE; continue; |