+++ /dev/null
-From: Gerald Schaefer <geraldsc@de.ibm.com>
-Subject: kernel: don't use pagetable walk for KERNEL_DS
-References: bnc#484767,LTC#52176
-
-Symptom: Access to KERNEL_DS via usercopy functions is very slow on
- pre z9 hardware.
-Problem: The usercopy functions do a pagetable walk even if KERNEL_DS
- is set on pre z9 hardware. This was a workaroud for a common
- code bug in SLES 11.
-Solution: Don't use pagetable walk for KERNEL_DS as the common code bug
- has been fixed in SLES 11 GMC.
-
-Acked-by: John Jolly <jjolly@suse.de>
----
- arch/s390/lib/uaccess_pt.c | 32 +++++++++++++++++++++++++-------
- 1 file changed, 25 insertions(+), 7 deletions(-)
-
-Index: linux-sles11/arch/s390/lib/uaccess_pt.c
-===================================================================
---- linux-sles11.orig/arch/s390/lib/uaccess_pt.c
-+++ linux-sles11/arch/s390/lib/uaccess_pt.c
-@@ -43,9 +43,8 @@ static int __handle_fault(struct mm_stru
- int ret = -EFAULT;
- int fault;
-
-- if (in_atomic() || segment_eq(get_fs(), KERNEL_DS))
-+ if (in_atomic())
- return ret;
--
- down_read(&mm->mmap_sem);
- vma = find_vma(mm, address);
- if (unlikely(!vma))
-@@ -110,8 +109,6 @@ static size_t __user_copy_pt(unsigned lo
- pte_t *pte;
- void *from, *to;
-
-- if (segment_eq(get_fs(), KERNEL_DS))
-- mm = &init_mm;
- done = 0;
- retry:
- spin_lock(&mm->page_table_lock);
-@@ -185,6 +182,10 @@ size_t copy_from_user_pt(size_t n, const
- {
- size_t rc;
-
-+ if (segment_eq(get_fs(), KERNEL_DS)) {
-+ memcpy(to, (void __kernel __force *) from, n);
-+ return 0;
-+ }
- rc = __user_copy_pt((unsigned long) from, to, n, 0);
- if (unlikely(rc))
- memset(to + n - rc, 0, rc);
-@@ -193,6 +194,10 @@ size_t copy_from_user_pt(size_t n, const
-
- size_t copy_to_user_pt(size_t n, void __user *to, const void *from)
- {
-+ if (segment_eq(get_fs(), KERNEL_DS)) {
-+ memcpy((void __kernel __force *) to, from, n);
-+ return 0;
-+ }
- return __user_copy_pt((unsigned long) to, (void *) from, n, 1);
- }
-
-@@ -200,6 +205,10 @@ static size_t clear_user_pt(size_t n, vo
- {
- long done, size, ret;
-
-+ if (segment_eq(get_fs(), KERNEL_DS)) {
-+ memset((void __kernel __force *) to, 0, n);
-+ return 0;
-+ }
- done = 0;
- do {
- if (n - done > PAGE_SIZE)
-@@ -225,7 +234,7 @@ static size_t strnlen_user_pt(size_t cou
- size_t len_str;
-
- if (segment_eq(get_fs(), KERNEL_DS))
-- mm = &init_mm;
-+ return strnlen((const char __kernel __force *) src, count) + 1;
- done = 0;
- retry:
- spin_lock(&mm->page_table_lock);
-@@ -267,6 +276,13 @@ static size_t strncpy_from_user_pt(size_
- return -EFAULT;
- if (n > count)
- n = count;
-+ if (segment_eq(get_fs(), KERNEL_DS)) {
-+ memcpy(dst, (const char __kernel __force *) src, n);
-+ if (dst[n-1] == '\0')
-+ return n-1;
-+ else
-+ return n;
-+ }
- if (__user_copy_pt((unsigned long) src, dst, n, 0))
- return -EFAULT;
- if (dst[n-1] == '\0')
-@@ -286,8 +302,10 @@ static size_t copy_in_user_pt(size_t n,
- pte_t *pte_from, *pte_to;
- int write_user;
-
-- if (segment_eq(get_fs(), KERNEL_DS))
-- mm = &init_mm;
-+ if (segment_eq(get_fs(), KERNEL_DS)) {
-+ memcpy((void __force *) to, (void __force *) from, n);
-+ return 0;
-+ }
- done = 0;
- retry:
- spin_lock(&mm->page_table_lock);