public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Martin Schwidefsky <schwidefsky@de.ibm.com>
To: linux-kernel@vger.kernel.org, linux-s390@vger.kernel.org
Cc: Heiko Carstens <heiko.carstens@de.ibm.com>,
	Gerald Schaefer <gerald.schaefer@de.ibm.com>,
	Martin Schwidefsky <schwidefsky@de.ibm.com>
Subject: [patch 06/52] [PATCH] Use do_exception() in pagetable walk usercopy functions.
Date: Fri, 13 Nov 2009 16:08:30 +0100	[thread overview]
Message-ID: <20091113150910.155645204@de.ibm.com> (raw)
In-Reply-To: 20091113150824.351347652@de.ibm.com

[-- Attachment #1: 105-mm-pt-walk.diff --]
[-- Type: text/plain, Size: 8609 bytes --]

From: Gerald Schaefer <gerald.schaefer@de.ibm.com>

The pagetable walk usercopy functions have used a modified copy of the
do_exception() function for fault handling. This lead to inconsistencies
with recent changes to do_exception(), e.g. performance counters. This
patch changes the pagetable walk usercopy code to call do_exception()
directly, eliminating the redundancy. A new parameter is added to
do_exception() to specify the fault address.

Signed-off-by: Gerald Schaefer <gerald.schaefer@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
---

 arch/s390/include/asm/uaccess.h |    2 
 arch/s390/lib/uaccess_pt.c      |  147 +++++++++++++---------------------------
 arch/s390/mm/fault.c            |   23 ++++++
 3 files changed, 76 insertions(+), 96 deletions(-)

Index: quilt-2.6/arch/s390/include/asm/uaccess.h
===================================================================
--- quilt-2.6.orig/arch/s390/include/asm/uaccess.h	2009-11-13 15:48:32.000000000 +0100
+++ quilt-2.6/arch/s390/include/asm/uaccess.h	2009-11-13 16:08:13.000000000 +0100
@@ -93,6 +93,8 @@
 extern struct uaccess_ops uaccess_mvcos_switch;
 extern struct uaccess_ops uaccess_pt;
 
+extern int __handle_fault(unsigned long, unsigned long, int);
+
 static inline int __put_user_fn(size_t size, void __user *ptr, void *x)
 {
 	size = uaccess.copy_to_user_small(size, ptr, x);
Index: quilt-2.6/arch/s390/lib/uaccess_pt.c
===================================================================
--- quilt-2.6.orig/arch/s390/lib/uaccess_pt.c	2009-11-13 15:48:32.000000000 +0100
+++ quilt-2.6/arch/s390/lib/uaccess_pt.c	2009-11-13 16:08:13.000000000 +0100
@@ -23,86 +23,21 @@
 
 	pgd = pgd_offset(mm, addr);
 	if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
-		return NULL;
+		return (pte_t *) 0x3a;
 
 	pud = pud_offset(pgd, addr);
 	if (pud_none(*pud) || unlikely(pud_bad(*pud)))
-		return NULL;
+		return (pte_t *) 0x3b;
 
 	pmd = pmd_offset(pud, addr);
 	if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
-		return NULL;
+		return (pte_t *) 0x10;
 
 	return pte_offset_map(pmd, addr);
 }
 
-static int __handle_fault(struct mm_struct *mm, unsigned long address,
-			  int write_access)
-{
-	struct vm_area_struct *vma;
-	int ret = -EFAULT;
-	int fault;
-
-	if (in_atomic())
-		return ret;
-	down_read(&mm->mmap_sem);
-	vma = find_vma(mm, address);
-	if (unlikely(!vma))
-		goto out;
-	if (unlikely(vma->vm_start > address)) {
-		if (!(vma->vm_flags & VM_GROWSDOWN))
-			goto out;
-		if (expand_stack(vma, address))
-			goto out;
-	}
-
-	if (!write_access) {
-		/* page not present, check vm flags */
-		if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
-			goto out;
-	} else {
-		if (!(vma->vm_flags & VM_WRITE))
-			goto out;
-	}
-
-survive:
-	fault = handle_mm_fault(mm, vma, address, write_access ? FAULT_FLAG_WRITE : 0);
-	if (unlikely(fault & VM_FAULT_ERROR)) {
-		if (fault & VM_FAULT_OOM)
-			goto out_of_memory;
-		else if (fault & VM_FAULT_SIGBUS)
-			goto out_sigbus;
-		BUG();
-	}
-	if (fault & VM_FAULT_MAJOR)
-		current->maj_flt++;
-	else
-		current->min_flt++;
-	ret = 0;
-out:
-	up_read(&mm->mmap_sem);
-	return ret;
-
-out_of_memory:
-	up_read(&mm->mmap_sem);
-	if (is_global_init(current)) {
-		yield();
-		down_read(&mm->mmap_sem);
-		goto survive;
-	}
-	printk("VM: killing process %s\n", current->comm);
-	return ret;
-
-out_sigbus:
-	up_read(&mm->mmap_sem);
-	current->thread.prot_addr = address;
-	current->thread.trap_no = 0x11;
-	force_sig(SIGBUS, current);
-	return ret;
-}
-
-static size_t __user_copy_pt(unsigned long uaddr, void *kptr,
-			     size_t n, int write_user)
+static __always_inline size_t __user_copy_pt(unsigned long uaddr, void *kptr,
+					     size_t n, int write_user)
 {
 	struct mm_struct *mm = current->mm;
 	unsigned long offset, pfn, done, size;
@@ -114,12 +49,17 @@
 	spin_lock(&mm->page_table_lock);
 	do {
 		pte = follow_table(mm, uaddr);
-		if (!pte || !pte_present(*pte) ||
-		    (write_user && !pte_write(*pte)))
+		if ((unsigned long) pte < 0x1000)
 			goto fault;
+		if (!pte_present(*pte)) {
+			pte = (pte_t *) 0x11;
+			goto fault;
+		} else if (write_user && !pte_write(*pte)) {
+			pte = (pte_t *) 0x04;
+			goto fault;
+		}
 
 		pfn = pte_pfn(*pte);
-
 		offset = uaddr & (PAGE_SIZE - 1);
 		size = min(n - done, PAGE_SIZE - offset);
 		if (write_user) {
@@ -137,7 +77,7 @@
 	return n - done;
 fault:
 	spin_unlock(&mm->page_table_lock);
-	if (__handle_fault(mm, uaddr, write_user))
+	if (__handle_fault(uaddr, (unsigned long) pte, write_user))
 		return n - done;
 	goto retry;
 }
@@ -146,30 +86,31 @@
  * Do DAT for user address by page table walk, return kernel address.
  * This function needs to be called with current->mm->page_table_lock held.
  */
-static unsigned long __dat_user_addr(unsigned long uaddr)
+static __always_inline unsigned long __dat_user_addr(unsigned long uaddr)
 {
 	struct mm_struct *mm = current->mm;
-	unsigned long pfn, ret;
+	unsigned long pfn;
 	pte_t *pte;
 	int rc;
 
-	ret = 0;
 retry:
 	pte = follow_table(mm, uaddr);
-	if (!pte || !pte_present(*pte))
+	if ((unsigned long) pte < 0x1000)
 		goto fault;
+	if (!pte_present(*pte)) {
+		pte = (pte_t *) 0x11;
+		goto fault;
+	}
 
 	pfn = pte_pfn(*pte);
-	ret = (pfn << PAGE_SHIFT) + (uaddr & (PAGE_SIZE - 1));
-out:
-	return ret;
+	return (pfn << PAGE_SHIFT) + (uaddr & (PAGE_SIZE - 1));
 fault:
 	spin_unlock(&mm->page_table_lock);
-	rc = __handle_fault(mm, uaddr, 0);
+	rc = __handle_fault(uaddr, (unsigned long) pte, 0);
 	spin_lock(&mm->page_table_lock);
-	if (rc)
-		goto out;
-	goto retry;
+	if (!rc)
+		goto retry;
+	return 0;
 }
 
 size_t copy_from_user_pt(size_t n, const void __user *from, void *to)
@@ -234,8 +175,12 @@
 	spin_lock(&mm->page_table_lock);
 	do {
 		pte = follow_table(mm, uaddr);
-		if (!pte || !pte_present(*pte))
+		if ((unsigned long) pte < 0x1000)
+			goto fault;
+		if (!pte_present(*pte)) {
+			pte = (pte_t *) 0x11;
 			goto fault;
+		}
 
 		pfn = pte_pfn(*pte);
 		offset = uaddr & (PAGE_SIZE-1);
@@ -249,9 +194,8 @@
 	return done + 1;
 fault:
 	spin_unlock(&mm->page_table_lock);
-	if (__handle_fault(mm, uaddr, 0)) {
+	if (__handle_fault(uaddr, (unsigned long) pte, 0))
 		return 0;
-	}
 	goto retry;
 }
 
@@ -284,7 +228,7 @@
 {
 	struct mm_struct *mm = current->mm;
 	unsigned long offset_from, offset_to, offset_max, pfn_from, pfn_to,
-		      uaddr, done, size;
+		      uaddr, done, size, error_code;
 	unsigned long uaddr_from = (unsigned long) from;
 	unsigned long uaddr_to = (unsigned long) to;
 	pte_t *pte_from, *pte_to;
@@ -298,17 +242,28 @@
 retry:
 	spin_lock(&mm->page_table_lock);
 	do {
+		write_user = 0;
+		uaddr = uaddr_from;
 		pte_from = follow_table(mm, uaddr_from);
-		if (!pte_from || !pte_present(*pte_from)) {
-			uaddr = uaddr_from;
-			write_user = 0;
+		error_code = (unsigned long) pte_from;
+		if (error_code < 0x1000)
+			goto fault;
+		if (!pte_present(*pte_from)) {
+			error_code = 0x11;
 			goto fault;
 		}
 
+		write_user = 1;
+		uaddr = uaddr_to;
 		pte_to = follow_table(mm, uaddr_to);
-		if (!pte_to || !pte_present(*pte_to) || !pte_write(*pte_to)) {
-			uaddr = uaddr_to;
-			write_user = 1;
+		error_code = (unsigned long) pte_to;
+		if (error_code < 0x1000)
+			goto fault;
+		if (!pte_present(*pte_to)) {
+			error_code = 0x11;
+			goto fault;
+		} else if (!pte_write(*pte_to)) {
+			error_code = 0x04;
 			goto fault;
 		}
 
@@ -329,7 +284,7 @@
 	return n - done;
 fault:
 	spin_unlock(&mm->page_table_lock);
-	if (__handle_fault(mm, uaddr, write_user))
+	if (__handle_fault(uaddr, error_code, write_user))
 		return n - done;
 	goto retry;
 }
Index: quilt-2.6/arch/s390/mm/fault.c
===================================================================
--- quilt-2.6.orig/arch/s390/mm/fault.c	2009-11-13 16:08:12.000000000 +0100
+++ quilt-2.6/arch/s390/mm/fault.c	2009-11-13 16:08:13.000000000 +0100
@@ -442,6 +442,29 @@
 }
 #endif
 
+int __handle_fault(unsigned long uaddr, unsigned long int_code, int write_user)
+{
+	struct pt_regs regs;
+	int access, fault;
+
+	regs.psw.mask = psw_kernel_bits;
+	if (!irqs_disabled())
+		regs.psw.mask |= PSW_MASK_IO | PSW_MASK_EXT;
+	regs.psw.addr = (unsigned long) __builtin_return_address(0);
+	regs.psw.addr |= PSW_ADDR_AMODE;
+	uaddr &= PAGE_MASK;
+	access = write_user ? VM_WRITE : VM_READ;
+	fault = do_exception(&regs, access, uaddr | 2);
+	if (unlikely(fault)) {
+		if (fault & VM_FAULT_OOM) {
+			pagefault_out_of_memory();
+			fault = 0;
+		} else if (fault & VM_FAULT_SIGBUS)
+			do_sigbus(&regs, int_code, uaddr);
+	}
+	return fault ? -EFAULT : 0;
+}
+
 #ifdef CONFIG_PFAULT 
 /*
  * 'pfault' pseudo page faults routines.


  parent reply	other threads:[~2009-11-13 15:09 UTC|newest]

Thread overview: 56+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-11-13 15:08 [patch 00/52] s390 patches for the next merge window (2.6.33) Martin Schwidefsky
2009-11-13 15:08 ` [patch 01/52] [PATCH] Improve address space check Martin Schwidefsky
2009-11-13 15:08 ` [patch 02/52] [PATCH] Improve address space mode selection Martin Schwidefsky
2009-11-13 15:08 ` [patch 03/52] [PATCH] Improve notify_page_fault implementation Martin Schwidefsky
2009-11-13 15:08 ` [patch 04/52] [PATCH] fault handler performance optimization Martin Schwidefsky
2009-11-13 15:08 ` [patch 05/52] [PATCH] fault handler access flags check Martin Schwidefsky
2009-11-13 15:08 ` Martin Schwidefsky [this message]
2009-11-13 15:08 ` [patch 07/52] [PATCH] Improve code generated by atomic operations Martin Schwidefsky
2009-11-13 15:08 ` [patch 08/52] [PATCH] dasd: support DIAG access for read-only devices Martin Schwidefsky
2009-11-13 15:08 ` [patch 09/52] [PATCH] cmm: free pages on hibernate Martin Schwidefsky
2009-11-13 15:08 ` [patch 10/52] [PATCH] smp: remove unused typedef and defines Martin Schwidefsky
2009-11-13 15:08 ` [patch 11/52] [PATCH] dasd: remove dead code Martin Schwidefsky
2009-11-13 15:08 ` [patch 12/52] [PATCH] use generic termbits.h header file Martin Schwidefsky
2009-11-13 15:08 ` [patch 13/52] [PATCH] use generic sockios.h " Martin Schwidefsky
2009-11-13 15:08 ` [patch 14/52] [PATCH] MAINTAINERS: Add s390 drivers block Martin Schwidefsky
2009-11-13 15:08 ` [patch 15/52] [PATCH] zcrypt: initialize ap_messages for cex3 exploitation Martin Schwidefsky
2009-11-13 15:08 ` [patch 16/52] [PATCH] zcrypt: special command support " Martin Schwidefsky
2009-11-13 15:08 ` [patch 17/52] [PATCH] zcrypt: add support for cex3 device types Martin Schwidefsky
2009-11-13 15:08 ` [patch 18/52] [PATCH] zcrypt: use definitions for cex3 Martin Schwidefsky
2009-11-13 15:08 ` [patch 19/52] [PATCH] zcrypt: adjust speed rating between cex2 and pcixcc Martin Schwidefsky
2009-11-13 15:08 ` [patch 20/52] [PATCH] zcrypt: adjust speed rating of cex3 adapters Martin Schwidefsky
2009-11-13 15:08 ` [patch 21/52] [PATCH] dasd: enable prefix independent of pav support Martin Schwidefsky
2009-11-13 15:08 ` [patch 22/52] [PATCH] dasd: improve error recovery for internal I/O Martin Schwidefsky
2009-11-13 15:08 ` [patch 23/52] [PATCH] dasd: remove strings from s390dbf Martin Schwidefsky
2009-11-13 15:08 ` [patch 24/52] [PATCH] s390: use change recording override for kernel mapping Martin Schwidefsky
2009-11-13 15:08 ` [patch 25/52] [PATCH] sclp: improve servicability setting Martin Schwidefsky
2009-11-13 15:08 ` [patch 26/52] [PATCH] cio: fix double free in case of probe failure Martin Schwidefsky
2009-11-13 15:08 ` [patch 27/52] [PATCH] cio: fix repeat setting of cdev parent association Martin Schwidefsky
2009-11-13 15:08 ` [patch 28/52] [PATCH] cio: introduce parent-initiated device move Martin Schwidefsky
2009-11-13 15:08 ` [patch 29/52] [PATCH] cio: introduce subchannel todos Martin Schwidefsky
2009-11-13 15:08 ` [patch 30/52] [PATCH] cio: introduce ccw device todos Martin Schwidefsky
2009-11-13 15:08 ` [patch 31/52] [PATCH] cio: inform user when online/offline processing fails Martin Schwidefsky
2009-11-13 15:08 ` [patch 32/52] [PATCH] cio: handle error during device recognition consistently Martin Schwidefsky
2009-11-13 15:08 ` [patch 33/52] [PATCH] cio: handle error during path verification consistently Martin Schwidefsky
2009-11-13 15:08 ` [patch 34/52] [PATCH] cio: ensure proper locking during device recognition Martin Schwidefsky
2009-11-13 15:08 ` [patch 35/52] [PATCH] cio: dont panic in non-fatal conditions Martin Schwidefsky
2009-11-13 15:09 ` [patch 36/52] [PATCH] cio: consistent infrastructure for internal I/O requests Martin Schwidefsky
2009-11-13 15:09 ` [patch 37/52] [PATCH] cio: use ccw request infrastructure for sense id Martin Schwidefsky
2009-11-13 15:09 ` [patch 38/52] [PATCH] cio: use ccw request infrastructure for pgid Martin Schwidefsky
2009-11-13 15:09 ` [patch 39/52] [PATCH] cio: allow setting not-operational devices offline Martin Schwidefsky
2009-11-13 15:09 ` [patch 40/52] [PATCH] cio: remove intretry flag Martin Schwidefsky
2009-11-13 15:09 ` [patch 41/52] [PATCH] cio: split PGID settings and status Martin Schwidefsky
2009-11-13 15:09 ` [patch 42/52] [PATCH] cio: use sense-pgid operation for path verification Martin Schwidefsky
2009-11-13 15:09 ` [patch 43/52] [PATCH] cio: make steal lock procedure more robust Martin Schwidefsky
2009-11-13 15:09 ` [patch 44/52] [PATCH] cio: remove registered flag from ccw_device_private Martin Schwidefsky
2009-11-13 15:09 ` [patch 45/52] [PATCH] cio: add per device initialization status flag Martin Schwidefsky
2009-11-13 15:09 ` [patch 46/52] [PATCH] cio: fix quiesce state Martin Schwidefsky
2009-11-13 15:09 ` [patch 47/52] [PATCH] cio: handle failed disable_subchannel after device recognition Martin Schwidefsky
2009-11-13 15:09 ` [patch 48/52] [PATCH] cio: handle busy subchannel in ccw_device_move_to_sch Martin Schwidefsky
2009-11-13 15:09 ` [patch 49/52] [PATCH] cio: quiesce subchannel in io_subchannel_remove Martin Schwidefsky
2009-11-13 15:09 ` [patch 50/52] [PATCH] cio: change locking " Martin Schwidefsky
2009-11-13 15:09 ` [patch 51/52] [PATCH] cio: improve error recovery for internal I/Os Martin Schwidefsky
2009-11-13 15:09 ` [patch 52/52] [PATCH] cio: dont unregister a busy device in ccw_device_set_offline Martin Schwidefsky
2009-11-13 15:28 ` [patch 00/52] s390 patches for the next merge window (2.6.33) Arnd Bergmann
2009-11-13 15:31   ` s390: move keyboard compat ioctls into tty3270 driver Arnd Bergmann
2009-11-16  8:33     ` Martin Schwidefsky

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20091113150910.155645204@de.ibm.com \
    --to=schwidefsky@de.ibm.com \
    --cc=gerald.schaefer@de.ibm.com \
    --cc=heiko.carstens@de.ibm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-s390@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox