1 From: Gerald Schaefer <geraldsc@de.ibm.com>
2 Subject: kernel: don't use pagetable walk for KERNEL_DS
3 References: bnc#484767,LTC#52176
5 Symptom: Access to KERNEL_DS via usercopy functions is very slow on
7 Problem: The usercopy functions do a pagetable walk even if KERNEL_DS
8 is set on pre z9 hardware. This was a workaroud for a common
10 Solution: Don't use pagetable walk for KERNEL_DS as the common code bug
11 has been fixed in SLES 11 GMC.
13 Acked-by: John Jolly <jjolly@suse.de>
15 arch/s390/lib/uaccess_pt.c | 32 +++++++++++++++++++++++++-------
16 1 file changed, 25 insertions(+), 7 deletions(-)
18 Index: linux-sles11/arch/s390/lib/uaccess_pt.c
19 ===================================================================
20 --- linux-sles11.orig/arch/s390/lib/uaccess_pt.c
21 +++ linux-sles11/arch/s390/lib/uaccess_pt.c
22 @@ -43,9 +43,8 @@ static int __handle_fault(struct mm_stru
26 - if (in_atomic() || segment_eq(get_fs(), KERNEL_DS))
30 down_read(&mm->mmap_sem);
31 vma = find_vma(mm, address);
33 @@ -110,8 +109,6 @@ static size_t __user_copy_pt(unsigned lo
37 - if (segment_eq(get_fs(), KERNEL_DS))
41 spin_lock(&mm->page_table_lock);
42 @@ -185,6 +182,10 @@ size_t copy_from_user_pt(size_t n, const
46 + if (segment_eq(get_fs(), KERNEL_DS)) {
47 + memcpy(to, (void __kernel __force *) from, n);
50 rc = __user_copy_pt((unsigned long) from, to, n, 0);
52 memset(to + n - rc, 0, rc);
53 @@ -193,6 +194,10 @@ size_t copy_from_user_pt(size_t n, const
55 size_t copy_to_user_pt(size_t n, void __user *to, const void *from)
57 + if (segment_eq(get_fs(), KERNEL_DS)) {
58 + memcpy((void __kernel __force *) to, from, n);
61 return __user_copy_pt((unsigned long) to, (void *) from, n, 1);
64 @@ -200,6 +205,10 @@ static size_t clear_user_pt(size_t n, vo
68 + if (segment_eq(get_fs(), KERNEL_DS)) {
69 + memset((void __kernel __force *) to, 0, n);
74 if (n - done > PAGE_SIZE)
75 @@ -225,7 +234,7 @@ static size_t strnlen_user_pt(size_t cou
78 if (segment_eq(get_fs(), KERNEL_DS))
80 + return strnlen((const char __kernel __force *) src, count) + 1;
83 spin_lock(&mm->page_table_lock);
84 @@ -267,6 +276,13 @@ static size_t strncpy_from_user_pt(size_
88 + if (segment_eq(get_fs(), KERNEL_DS)) {
89 + memcpy(dst, (const char __kernel __force *) src, n);
90 + if (dst[n-1] == '\0')
95 if (__user_copy_pt((unsigned long) src, dst, n, 0))
98 @@ -286,8 +302,10 @@ static size_t copy_in_user_pt(size_t n,
99 pte_t *pte_from, *pte_to;
102 - if (segment_eq(get_fs(), KERNEL_DS))
104 + if (segment_eq(get_fs(), KERNEL_DS)) {
105 + memcpy((void __force *) to, (void __force *) from, n);
110 spin_lock(&mm->page_table_lock);