linuxppc-dev.lists.ozlabs.org archive mirror
 help / color / mirror / Atom feed
From: Paul Mackerras <paulus@ozlabs.org>
To: linuxppc-dev@ozlabs.org
Subject: [PATCH v3 14/17] powerpc: Set regs->dar if memory access fails in emulate_step()
Date: Wed, 30 Aug 2017 14:12:37 +1000	[thread overview]
Message-ID: <1504066360-30128-15-git-send-email-paulus@ozlabs.org> (raw)
In-Reply-To: <1504066360-30128-1-git-send-email-paulus@ozlabs.org>

This adds code to the instruction emulation code to set regs->dar
to the address of any memory access that fails.  This address is
not necessarily the same as the effective address of the instruction,
because if the memory access is unaligned, it might cross a page
boundary and fault on the second page.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
---
 arch/powerpc/lib/sstep.c | 74 ++++++++++++++++++++++++++++++++++--------------
 1 file changed, 52 insertions(+), 22 deletions(-)

diff --git a/arch/powerpc/lib/sstep.c b/arch/powerpc/lib/sstep.c
index fa20f3a..5c0f50b 100644
--- a/arch/powerpc/lib/sstep.c
+++ b/arch/powerpc/lib/sstep.c
@@ -103,11 +103,19 @@ static nokprobe_inline int branch_taken(unsigned int instr,
 	return 1;
 }
 
-static nokprobe_inline long address_ok(struct pt_regs *regs, unsigned long ea, int nb)
+static nokprobe_inline long address_ok(struct pt_regs *regs,
+				       unsigned long ea, int nb)
 {
 	if (!user_mode(regs))
 		return 1;
-	return __access_ok(ea, nb, USER_DS);
+	if (__access_ok(ea, nb, USER_DS))
+		return 1;
+	if (__access_ok(ea, 1, USER_DS))
+		/* Access overlaps the end of the user region */
+		regs->dar = USER_DS.seg;
+	else
+		regs->dar = ea;
+	return 0;
 }
 
 /*
@@ -210,7 +218,8 @@ static nokprobe_inline unsigned long byterev_8(unsigned long x)
 #endif
 
 static nokprobe_inline int read_mem_aligned(unsigned long *dest,
-					unsigned long ea, int nb)
+					    unsigned long ea, int nb,
+					    struct pt_regs *regs)
 {
 	int err = 0;
 	unsigned long x = 0;
@@ -233,6 +242,8 @@ static nokprobe_inline int read_mem_aligned(unsigned long *dest,
 	}
 	if (!err)
 		*dest = x;
+	else
+		regs->dar = ea;
 	return err;
 }
 
@@ -240,7 +251,8 @@ static nokprobe_inline int read_mem_aligned(unsigned long *dest,
  * Copy from userspace to a buffer, using the largest possible
  * aligned accesses, up to sizeof(long).
  */
-static int nokprobe_inline copy_mem_in(u8 *dest, unsigned long ea, int nb)
+static int nokprobe_inline copy_mem_in(u8 *dest, unsigned long ea, int nb,
+				       struct pt_regs *regs)
 {
 	int err = 0;
 	int c;
@@ -268,8 +280,10 @@ static int nokprobe_inline copy_mem_in(u8 *dest, unsigned long ea, int nb)
 			break;
 #endif
 		}
-		if (err)
+		if (err) {
+			regs->dar = ea;
 			return err;
+		}
 		dest += c;
 		ea += c;
 	}
@@ -289,7 +303,7 @@ static nokprobe_inline int read_mem_unaligned(unsigned long *dest,
 
 	u.ul = 0;
 	i = IS_BE ? sizeof(unsigned long) - nb : 0;
-	err = copy_mem_in(&u.b[i], ea, nb);
+	err = copy_mem_in(&u.b[i], ea, nb, regs);
 	if (!err)
 		*dest = u.ul;
 	return err;
@@ -306,13 +320,14 @@ static int read_mem(unsigned long *dest, unsigned long ea, int nb,
 	if (!address_ok(regs, ea, nb))
 		return -EFAULT;
 	if ((ea & (nb - 1)) == 0)
-		return read_mem_aligned(dest, ea, nb);
+		return read_mem_aligned(dest, ea, nb, regs);
 	return read_mem_unaligned(dest, ea, nb, regs);
 }
 NOKPROBE_SYMBOL(read_mem);
 
 static nokprobe_inline int write_mem_aligned(unsigned long val,
-					unsigned long ea, int nb)
+					     unsigned long ea, int nb,
+					     struct pt_regs *regs)
 {
 	int err = 0;
 
@@ -332,6 +347,8 @@ static nokprobe_inline int write_mem_aligned(unsigned long val,
 		break;
 #endif
 	}
+	if (err)
+		regs->dar = ea;
 	return err;
 }
 
@@ -339,7 +356,8 @@ static nokprobe_inline int write_mem_aligned(unsigned long val,
  * Copy from a buffer to userspace, using the largest possible
  * aligned accesses, up to sizeof(long).
  */
-static int nokprobe_inline copy_mem_out(u8 *dest, unsigned long ea, int nb)
+static int nokprobe_inline copy_mem_out(u8 *dest, unsigned long ea, int nb,
+					struct pt_regs *regs)
 {
 	int err = 0;
 	int c;
@@ -367,8 +385,10 @@ static int nokprobe_inline copy_mem_out(u8 *dest, unsigned long ea, int nb)
 			break;
 #endif
 		}
-		if (err)
+		if (err) {
+			regs->dar = ea;
 			return err;
+		}
 		dest += c;
 		ea += c;
 	}
@@ -387,7 +407,7 @@ static nokprobe_inline int write_mem_unaligned(unsigned long val,
 
 	u.ul = val;
 	i = IS_BE ? sizeof(unsigned long) - nb : 0;
-	return copy_mem_out(&u.b[i], ea, nb);
+	return copy_mem_out(&u.b[i], ea, nb, regs);
 }
 
 /*
@@ -400,7 +420,7 @@ static int write_mem(unsigned long val, unsigned long ea, int nb,
 	if (!address_ok(regs, ea, nb))
 		return -EFAULT;
 	if ((ea & (nb - 1)) == 0)
-		return write_mem_aligned(val, ea, nb);
+		return write_mem_aligned(val, ea, nb, regs);
 	return write_mem_unaligned(val, ea, nb, regs);
 }
 NOKPROBE_SYMBOL(write_mem);
@@ -422,7 +442,7 @@ static int do_fp_load(int rn, unsigned long ea, int nb, struct pt_regs *regs)
 
 	if (!address_ok(regs, ea, nb))
 		return -EFAULT;
-	err = copy_mem_in(u.b, ea, nb);
+	err = copy_mem_in(u.b, ea, nb, regs);
 	if (err)
 		return err;
 	preempt_disable();
@@ -471,7 +491,7 @@ static int do_fp_store(int rn, unsigned long ea, int nb, struct pt_regs *regs)
 			u.l[1] = current->thread.TS_FPR(rn);
 	}
 	preempt_enable();
-	return copy_mem_out(u.b, ea, nb);
+	return copy_mem_out(u.b, ea, nb, regs);
 }
 NOKPROBE_SYMBOL(do_fp_store);
 #endif
@@ -491,7 +511,7 @@ static nokprobe_inline int do_vec_load(int rn, unsigned long ea,
 		return -EFAULT;
 	/* align to multiple of size */
 	ea &= ~(size - 1);
-	err = copy_mem_in(&u.b[ea & 0xf], ea, size);
+	err = copy_mem_in(&u.b[ea & 0xf], ea, size, regs);
 	if (err)
 		return err;
 
@@ -523,7 +543,7 @@ static nokprobe_inline int do_vec_store(int rn, unsigned long ea,
 	else
 		u.v = current->thread.vr_state.vr[rn];
 	preempt_enable();
-	return copy_mem_out(&u.b[ea & 0xf], ea, size);
+	return copy_mem_out(&u.b[ea & 0xf], ea, size, regs);
 }
 #endif /* CONFIG_ALTIVEC */
 
@@ -725,7 +745,7 @@ static nokprobe_inline int do_vsx_load(struct instruction_op *op,
 	union vsx_reg buf;
 	int size = GETSIZE(op->type);
 
-	if (!address_ok(regs, ea, size) || copy_mem_in(mem, ea, size))
+	if (!address_ok(regs, ea, size) || copy_mem_in(mem, ea, size, regs))
 		return -EFAULT;
 
 	emulate_vsx_load(op, &buf, mem);
@@ -776,7 +796,7 @@ static nokprobe_inline int do_vsx_store(struct instruction_op *op,
 	}
 	preempt_enable();
 	emulate_vsx_store(op, &buf, mem);
-	return  copy_mem_out(mem, ea, size);
+	return  copy_mem_out(mem, ea, size, regs);
 }
 #endif /* CONFIG_VSX */
 
@@ -797,8 +817,10 @@ int emulate_dcbz(unsigned long ea, struct pt_regs *regs)
 		return -EFAULT;
 	for (i = 0; i < size; i += sizeof(long)) {
 		err = __put_user(0, (unsigned long __user *) (ea + i));
-		if (err)
+		if (err) {
+			regs->dar = ea;
 			return err;
+		}
 	}
 	return 0;
 }
@@ -2640,8 +2662,10 @@ int emulate_step(struct pt_regs *regs, unsigned int instr)
 			err = emulate_dcbz(ea, regs);
 			break;
 		}
-		if (err)
+		if (err) {
+			regs->dar = ea;
 			return 0;
+		}
 		goto instr_done;
 
 	case LARX:
@@ -2668,12 +2692,16 @@ int emulate_step(struct pt_regs *regs, unsigned int instr)
 			break;
 		case 16:
 			err = do_lqarx(ea, &regs->gpr[op.reg]);
-			goto ldst_done;
+			break;
 #endif
 		default:
 			return 0;
 		}
-		if (!err)
+		if (err) {
+			regs->dar = ea;
+			return 0;
+		}
+		if (size < 16)
 			regs->gpr[op.reg] = val;
 		goto ldst_done;
 
@@ -2711,6 +2739,8 @@ int emulate_step(struct pt_regs *regs, unsigned int instr)
 			regs->ccr = (regs->ccr & 0x0fffffff) |
 				(cr & 0xe0000000) |
 				((regs->xer >> 3) & 0x10000000);
+		else
+			regs->dar = ea;
 		goto ldst_done;
 
 	case LOAD:
-- 
2.7.4

  parent reply	other threads:[~2017-08-30  4:12 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-08-30  4:12 [PATCH v3 00/17] powerpc: Do alignment fixups using analyse_instr etc Paul Mackerras
2017-08-30  4:12 ` [PATCH v3 01/17] powerpc: Correct instruction code for xxlor instruction Paul Mackerras
2017-09-01 13:29   ` [v3, " Michael Ellerman
2017-08-30  4:12 ` [PATCH v3 02/17] powerpc: Change analyse_instr so it doesn't modify *regs Paul Mackerras
2017-08-30  4:12 ` [PATCH v3 03/17] powerpc: Don't check MSR FP/VMX/VSX enable bits in analyse_instr() Paul Mackerras
2017-08-30  4:12 ` [PATCH v3 04/17] powerpc: Handle most loads and stores in instruction emulation code Paul Mackerras
2017-08-30  4:12 ` [PATCH v3 05/17] powerpc/64: Fix update forms of loads and stores to write 64-bit EA Paul Mackerras
2017-08-30  4:12 ` [PATCH v3 06/17] powerpc: Fix emulation of the isel instruction Paul Mackerras
2017-08-30  4:12 ` [PATCH v3 07/17] powerpc: Don't update CR0 in emulation of popcnt, prty, bpermd instructions Paul Mackerras
2017-08-30  4:12 ` [PATCH v3 08/17] powerpc: Add emulation for the addpcis instruction Paul Mackerras
2017-08-30  4:12 ` [PATCH v3 09/17] powerpc: Make load/store emulation use larger memory accesses Paul Mackerras
2017-08-30  4:12 ` [PATCH v3 10/17] powerpc: Emulate FP/vector/VSX loads/stores correctly when regs not live Paul Mackerras
2017-08-30  4:12 ` [PATCH v3 11/17] powerpc: Emulate vector element load/store instructions Paul Mackerras
2017-08-30  4:12 ` [PATCH v3 12/17] powerpc: Emulate load/store floating double pair instructions Paul Mackerras
2017-08-30  4:12 ` [PATCH v3 13/17] powerpc: Emulate the dcbz instruction Paul Mackerras
2017-08-30  4:12 ` Paul Mackerras [this message]
2017-08-30  4:12 ` [PATCH v3 15/17] powerpc: Handle opposite-endian processes in emulation code Paul Mackerras
2017-08-30  4:12 ` [PATCH v3 16/17] powerpc: Separate out load/store emulation into its own function Paul Mackerras
2017-08-30  4:12 ` [PATCH v3 17/17] powerpc: Use instruction emulation infrastructure to handle alignment faults Paul Mackerras
2017-08-30  6:34 ` [PATCH v3 18/17] powerpc: Emulate load/store floating point as integer word instructions Paul Mackerras
2017-08-31  0:49 ` [PATCH v3 00/17] powerpc: Do alignment fixups using analyse_instr etc Michael Neuling
2017-08-31  0:54   ` Michael Neuling
2017-08-31 23:51 ` [PATCH 19/17] powerpc: Wrap register number correctly for string load/store instructions Paul Mackerras

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=1504066360-30128-15-git-send-email-paulus@ozlabs.org \
    --to=paulus@ozlabs.org \
    --cc=linuxppc-dev@ozlabs.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;
as well as URLs for NNTP newsgroup(s).