All of lore.kernel.org
 help / color / mirror / Atom feed
From: Dave Hansen <dave.hansen@intel.com>
To: "Ren, Qiaowei" <qiaowei.ren@intel.com>, Borislav Petkov <bp@alien8.de>
Cc: "H. Peter Anvin" <hpa@zytor.com>,
	Thomas Gleixner <tglx@linutronix.de>,
	Ingo Molnar <mingo@redhat.com>, "x86@kernel.org" <x86@kernel.org>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>
Subject: Re: [PATCH v6 07/10] x86, mpx: decode MPX instruction to get bound violation information
Date: Thu, 19 Jun 2014 10:04:31 -0700	[thread overview]
Message-ID: <53A3181F.9070005@intel.com> (raw)
In-Reply-To: <9E0BE1322F2F2246BD820DA9FC397ADE016A3F75@shsmsx102.ccr.corp.intel.com>

[-- Attachment #1: Type: text/plain, Size: 1736 bytes --]

On 06/18/2014 11:53 PM, Ren, Qiaowei wrote:
> On 2014-06-19, Borislav Petkov wrote:
>> On Thu, Jun 19, 2014 at 01:13:48AM +0000, Ren, Qiaowei wrote:
>>> On 2014-06-18, Borislav Petkov wrote:
>>>> On Wed, Jun 18, 2014 at 05:44:13PM +0800, Qiaowei Ren wrote:
>>>>
>>>> This whole insn decoding machinery above looks like adapted from
>>>> arch/x86/lib/insn.c. You should merge it with the generic code in
>>>> insn.c instead of homegrowing it here only for the purposes of MPX.
>>>> And if it doesn't work for your needs, you should should extend
>>>> the generic code to do so.
>>
>>> Petkov, as we discussed on initial version of this patchset, general
>>> insn framework didn't work out well and I have tried to use generic
>>> struct insn, insn_field, etc. for obvious benefits.
>>
>> Let me repeat myself: "And if it doesn't work for your needs, you
>> should extend the generic code to do so."
>>
>> We don't do homegrown almost-copies of generic code.
>> 
> I see. If possible, I will be very happy to use or extend generic
> code. But due to extra overhead caused by MPX, I have to use MPX
> specific decoding to do performance optimization.

Could you please support this position with some data?  I'm a bit
skeptical that instruction decoding is going to be a
performance-critical path.

I also don't see the extra field that you talked about in the previous
thread?  What's the extra field?  I see a 'limit' vs. 'length', but you
don't use 'length' at all, so I think you can use it instead, or at
least union it.

I've taken a quick stab at trying to consolidate things.  I think I may
have screwed up this:

	insn->limit = MAX_MPX_INSN_SIZE - bytes;

Qiaowei, is there anything fundamentally broken with what I've got here?


[-- Attachment #2: consolidate-instruction-decoding.patch --]
[-- Type: text/x-patch, Size: 9071 bytes --]



---

 b/arch/x86/include/asm/insn.h |    1 
 b/arch/x86/include/asm/mpx.h  |   14 ---
 b/arch/x86/kernel/mpx.c       |  183 ++----------------------------------------
 b/arch/x86/lib/insn.c         |   43 +++++++++
 4 files changed, 56 insertions(+), 185 deletions(-)

diff -puN arch/x86/kernel/mpx.c~consolidate-instruction-decoding arch/x86/kernel/mpx.c
--- a/arch/x86/kernel/mpx.c~consolidate-instruction-decoding	2014-06-19 09:53:53.894441788 -0700
+++ b/arch/x86/kernel/mpx.c	2014-06-19 09:53:53.909442460 -0700
@@ -3,6 +3,7 @@
 #include <linux/prctl.h>
 #include <asm/mpx.h>
 #include <asm/i387.h>
+#include <asm/insn.h>
 #include <asm/fpu-internal.h>
 
 /*
@@ -59,7 +60,7 @@ int mpx_unregister(struct task_struct *t
 }
 
 typedef enum {REG_TYPE_RM, REG_TYPE_INDEX, REG_TYPE_BASE} reg_type_t;
-static unsigned long get_reg(struct mpx_insn *insn, struct pt_regs *regs,
+static unsigned long get_reg(struct insn *insn, struct pt_regs *regs,
 			     reg_type_t type)
 {
 	int regno = 0;
@@ -118,7 +119,7 @@ static unsigned long get_reg(struct mpx_
  * for rm=3 returning the content of the rm reg
  * for rm!=3 calculates the address using SIB and Disp
  */
-static unsigned long get_addr_ref(struct mpx_insn *insn, struct pt_regs *regs)
+static unsigned long get_addr_ref(struct insn *insn, struct pt_regs *regs)
 {
 	unsigned long addr;
 	unsigned long base;
@@ -142,182 +143,22 @@ static unsigned long get_addr_ref(struct
 	return addr;
 }
 
-/* Verify next sizeof(t) bytes can be on the same instruction */
-#define validate_next(t, insn, n)	\
-	((insn)->next_byte + sizeof(t) + n - (insn)->kaddr <= (insn)->limit)
-
-#define __get_next(t, insn)		\
-({					\
-	t r = *(t *)insn->next_byte;	\
-	insn->next_byte += sizeof(t);	\
-	r;				\
-})
-
-#define __peek_next(t, insn)		\
-({					\
-	t r = *(t *)insn->next_byte;	\
-	r;				\
-})
-
-#define get_next(t, insn)		\
-({					\
-	if (unlikely(!validate_next(t, insn, 0)))	\
-		goto err_out;		\
-	__get_next(t, insn);		\
-})
-
-#define peek_next(t, insn)		\
-({					\
-	if (unlikely(!validate_next(t, insn, 0)))	\
-		goto err_out;		\
-	__peek_next(t, insn);		\
-})
-
-static void mpx_insn_get_prefixes(struct mpx_insn *insn)
-{
-	unsigned char b;
-
-	/* Decode legacy prefix and REX prefix */
-	b = peek_next(unsigned char, insn);
-	while (b != 0x0f) {
-		/*
-		 * look for a rex prefix
-		 * a REX prefix cannot be followed by a legacy prefix.
-		 */
-		if (insn->x86_64 && ((b&0xf0) == 0x40)) {
-			insn->rex_prefix.value = b;
-			insn->rex_prefix.nbytes = 1;
-			insn->next_byte++;
-			break;
-		}
-
-		/* check the other legacy prefixes */
-		switch (b) {
-		case 0xf2:
-		case 0xf3:
-		case 0xf0:
-		case 0x64:
-		case 0x65:
-		case 0x2e:
-		case 0x3e:
-		case 0x26:
-		case 0x36:
-		case 0x66:
-		case 0x67:
-			insn->next_byte++;
-			break;
-		default: /* everything else is garbage */
-			goto err_out;
-		}
-		b = peek_next(unsigned char, insn);
-	}
-
-err_out:
-	return;
-}
-
-static void mpx_insn_get_modrm(struct mpx_insn *insn)
-{
-	insn->modrm.value = get_next(unsigned char, insn);
-	insn->modrm.nbytes = 1;
-
-err_out:
-	return;
-}
-
-static void mpx_insn_get_sib(struct mpx_insn *insn)
-{
-	unsigned char modrm = (unsigned char)insn->modrm.value;
-
-	if (X86_MODRM_MOD(modrm) != 3 && X86_MODRM_RM(modrm) == 4) {
-		insn->sib.value = get_next(unsigned char, insn);
-		insn->sib.nbytes = 1;
-	}
-
-err_out:
-	return;
-}
-
-static void mpx_insn_get_displacement(struct mpx_insn *insn)
-{
-	unsigned char mod, rm, base;
-
-	/*
-	 * Interpreting the modrm byte:
-	 * mod = 00 - no displacement fields (exceptions below)
-	 * mod = 01 - 1-byte displacement field
-	 * mod = 10 - displacement field is 4 bytes
-	 * mod = 11 - no memory operand
-	 *
-	 * mod != 11, r/m = 100 - SIB byte exists
-	 * mod = 00, SIB base = 101 - displacement field is 4 bytes
-	 * mod = 00, r/m = 101 - rip-relative addressing, displacement
-	 *	field is 4 bytes
-	 */
-	mod = X86_MODRM_MOD(insn->modrm.value);
-	rm = X86_MODRM_RM(insn->modrm.value);
-	base = X86_SIB_BASE(insn->sib.value);
-	if (mod == 3)
-		return;
-	if (mod == 1) {
-		insn->displacement.value = get_next(unsigned char, insn);
-		insn->displacement.nbytes = 1;
-	} else if ((mod == 0 && rm == 5) || mod == 2 ||
-			(mod == 0 && base == 5)) {
-		insn->displacement.value = get_next(int, insn);
-		insn->displacement.nbytes = 4;
-	}
-
-err_out:
-	return;
-}
-
-static void mpx_insn_init(struct mpx_insn *insn, struct pt_regs *regs)
-{
-	unsigned char buf[MAX_MPX_INSN_SIZE];
-	int bytes;
-
-	memset(insn, 0, sizeof(*insn));
-
-	bytes = copy_from_user(buf, (void __user *)regs->ip, MAX_MPX_INSN_SIZE);
-	insn->limit = MAX_MPX_INSN_SIZE - bytes;
-	insn->kaddr = buf;
-	insn->next_byte = buf;
-
-	/*
-	 * In 64-bit Mode, all Intel MPX instructions use 64-bit
-	 * operands for bounds and 64 bit addressing, i.e. REX.W &
-	 * 67H have no effect on data or address size.
-	 *
-	 * In compatibility and legacy modes (including 16-bit code
-	 * segments, real and virtual 8086 modes) all Intel MPX
-	 * instructions use 32-bit operands for bounds and 32 bit
-	 * addressing.
-	 */
-#ifdef CONFIG_X86_64
-	insn->x86_64 = 1;
-	insn->addr_bytes = 8;
-#else
-	insn->x86_64 = 0;
-	insn->addr_bytes = 4;
-#endif
-}
-
-static unsigned long mpx_insn_decode(struct mpx_insn *insn,
+static unsigned long insn_decode(struct insn *insn,
 				     struct pt_regs *regs)
 {
-	mpx_insn_init(insn, regs);
+	int is_64bit = IS_ENABLED(CONFIG_X86_64) && !test_thread_flag(TIF_IA32);
 
+	insn_init(insn, regs, is_64bit);
 	/*
 	 * In this case, we only need decode bndcl/bndcn/bndcu,
 	 * so we can use private diassembly interfaces to get
 	 * prefixes, modrm, sib, displacement, etc..
 	 */
-	mpx_insn_get_prefixes(insn);
+	insn_get_prefixes(insn);
 	insn->next_byte += 2; /* ignore opcode */
-	mpx_insn_get_modrm(insn);
-	mpx_insn_get_sib(insn);
-	mpx_insn_get_displacement(insn);
+	insn_get_modrm(insn);
+	insn_get_sib(insn);
+	insn_get_displacement(insn);
 
 	return get_addr_ref(insn, regs);
 }
@@ -390,11 +231,11 @@ int do_mpx_bt_fault(struct xsave_struct
 void do_mpx_bounds(struct pt_regs *regs, siginfo_t *info,
 		struct xsave_struct *xsave_buf)
 {
-	struct mpx_insn insn;
+	struct insn insn;
 	uint8_t bndregno;
 	unsigned long addr_vio;
 
-	addr_vio = mpx_insn_decode(&insn, regs);
+	addr_vio = insn_decode(&insn, regs);
 
 	bndregno = X86_MODRM_REG(insn.modrm.value);
 	if (bndregno > 3)
diff -puN arch/x86/include/asm/mpx.h~consolidate-instruction-decoding arch/x86/include/asm/mpx.h
--- a/arch/x86/include/asm/mpx.h~consolidate-instruction-decoding	2014-06-19 09:53:53.895441833 -0700
+++ b/arch/x86/include/asm/mpx.h	2014-06-19 09:53:53.909442460 -0700
@@ -53,20 +53,6 @@
 #define MPX_BNDCFG_ENABLE_FLAG	0x1
 #define MPX_BD_ENTRY_VALID_FLAG	0x1
 
-struct mpx_insn {
-	struct insn_field rex_prefix;	/* REX prefix */
-	struct insn_field modrm;
-	struct insn_field sib;
-	struct insn_field displacement;
-
-	unsigned char addr_bytes;	/* effective address size */
-	unsigned char limit;
-	unsigned char x86_64;
-
-	const unsigned char *kaddr;	/* kernel address of insn to analyze */
-	const unsigned char *next_byte;
-};
-
 #define MAX_MPX_INSN_SIZE	15
 
 unsigned long mpx_mmap(unsigned long len);
diff -puN arch/x86/include/asm/insn.h~consolidate-instruction-decoding arch/x86/include/asm/insn.h
--- a/arch/x86/include/asm/insn.h~consolidate-instruction-decoding	2014-06-19 09:53:53.897441922 -0700
+++ b/arch/x86/include/asm/insn.h	2014-06-19 09:53:53.910442505 -0700
@@ -98,6 +98,7 @@ struct insn {
 
 extern void insn_init(struct insn *insn, const void *kaddr, int x86_64);
 extern void insn_get_prefixes(struct insn *insn);
+extern void mpx_insn_get_prefixes(struct insn *insn);
 extern void insn_get_opcode(struct insn *insn);
 extern void insn_get_modrm(struct insn *insn);
 extern void insn_get_sib(struct insn *insn);
diff -puN arch/x86/lib/insn.c~consolidate-instruction-decoding arch/x86/lib/insn.c
--- a/arch/x86/lib/insn.c~consolidate-instruction-decoding	2014-06-19 09:53:53.899442011 -0700
+++ b/arch/x86/lib/insn.c	2014-06-19 09:53:53.910442505 -0700
@@ -63,6 +63,49 @@ void insn_init(struct insn *insn, const
 		insn->addr_bytes = 4;
 }
 
+void mpx_insn_get_prefixes(struct insn *insn)
+{
+	unsigned char b;
+
+	/* Decode legacy prefix and REX prefix */
+	b = peek_next(unsigned char, insn);
+	while (b != 0x0f) {
+		/*
+		 * look for a rex prefix
+		 * a REX prefix cannot be followed by a legacy prefix.
+		 */
+		if (insn->x86_64 && ((b&0xf0) == 0x40)) {
+			insn->prefixes.value = b;
+			insn->prefixes.nbytes = 1;
+			insn->next_byte++;
+			break;
+		}
+
+		/* check the other legacy prefixes */
+		switch (b) {
+		case 0xf2:
+		case 0xf3:
+		case 0xf0:
+		case 0x64:
+		case 0x65:
+		case 0x2e:
+		case 0x3e:
+		case 0x26:
+		case 0x36:
+		case 0x66:
+		case 0x67:
+			insn->next_byte++;
+			break;
+		default: /* everything else is garbage */
+			goto err_out;
+		}
+		b = peek_next(unsigned char, insn);
+	}
+
+err_out:
+	return;
+}
+
 /**
  * insn_get_prefixes - scan x86 instruction prefix bytes
  * @insn:	&struct insn containing instruction
_

  reply	other threads:[~2014-06-19 17:07 UTC|newest]

Thread overview: 87+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-06-18  9:44 [PATCH v6 00/10] Intel MPX support Qiaowei Ren
2014-06-18  9:44 ` [PATCH v6 01/10] x86, mpx: introduce VM_MPX to indicate that a VMA is MPX specific Qiaowei Ren
2014-06-18  9:44 ` [PATCH v6 02/10] x86, mpx: add MPX specific mmap interface Qiaowei Ren
2014-06-23 19:49   ` Andy Lutomirski
2014-06-23 19:49     ` Andy Lutomirski
2014-06-23 20:03     ` Dave Hansen
2014-06-23 20:03       ` Dave Hansen
2014-06-23 20:06       ` Andy Lutomirski
2014-06-23 20:06         ` Andy Lutomirski
2014-06-23 20:28         ` Dave Hansen
2014-06-23 20:28           ` Dave Hansen
2014-06-23 21:04           ` Andy Lutomirski
2014-06-23 21:04             ` Andy Lutomirski
2014-06-24  5:53             ` Ren, Qiaowei
2014-06-24  5:53               ` Ren, Qiaowei
2014-06-24 23:55               ` Andy Lutomirski
2014-06-24 23:55                 ` Andy Lutomirski
2014-06-25  1:40                 ` Ren, Qiaowei
2014-06-25  1:40                   ` Ren, Qiaowei
2014-06-25 21:04                   ` Andy Lutomirski
2014-06-25 21:04                     ` Andy Lutomirski
2014-06-25 21:05                     ` Andy Lutomirski
2014-06-25 21:05                       ` Andy Lutomirski
2014-06-25 21:45                       ` Dave Hansen
2014-06-25 21:45                         ` Dave Hansen
2014-06-26 22:19                         ` Andy Lutomirski
2014-06-26 22:19                           ` Andy Lutomirski
2014-06-26 22:58                           ` Dave Hansen
2014-06-26 22:58                             ` Dave Hansen
2014-06-26 23:15                             ` Andy Lutomirski
2014-06-26 23:15                               ` Andy Lutomirski
2014-06-27  0:19                               ` Dave Hansen
2014-06-27  0:19                                 ` Dave Hansen
2014-06-27  0:26                                 ` Andy Lutomirski
2014-06-27  0:26                                   ` Andy Lutomirski
2014-06-27 17:34                                   ` Dave Hansen
2014-06-27 17:34                                     ` Dave Hansen
2014-06-27 17:42                                     ` Dave Hansen
2014-06-27 17:42                                       ` Dave Hansen
2014-06-27 18:57                                       ` Andy Lutomirski
2014-06-27 18:57                                         ` Andy Lutomirski
2014-06-25 21:43                     ` Dave Hansen
2014-06-25 21:43                       ` Dave Hansen
2014-06-24  2:53     ` Ren, Qiaowei
2014-06-24  2:53       ` Ren, Qiaowei
2014-06-18  9:44 ` [PATCH v6 03/10] x86, mpx: add macro cpu_has_mpx Qiaowei Ren
2014-06-18  9:57   ` Borislav Petkov
2014-06-18 14:35     ` Dave Hansen
2014-06-18 14:44       ` Borislav Petkov
2014-06-18 14:58         ` Dave Hansen
2014-06-18 15:25           ` Borislav Petkov
2014-06-18 16:17             ` Dave Hansen
2014-06-18 15:00         ` H. Peter Anvin
2014-06-18 15:27           ` Borislav Petkov
2014-06-18 14:59       ` H. Peter Anvin
2014-06-18 16:25         ` Dave Hansen
2014-06-18 17:21           ` Borislav Petkov
2014-06-19 18:02           ` H. Peter Anvin
2014-06-19 18:50             ` Dave Hansen
2014-06-20  3:28               ` H. Peter Anvin
2014-06-18  9:44 ` [PATCH v6 04/10] x86, mpx: hook #BR exception handler to allocate bound tables Qiaowei Ren
2014-06-23 19:54   ` Andy Lutomirski
2014-06-24  1:53     ` Ren, Qiaowei
2014-07-11 16:23   ` Dave Hansen
2014-06-18  9:44 ` [PATCH v6 05/10] x86, mpx: extend siginfo structure to include bound violation information Qiaowei Ren
2014-06-18  9:44 ` [PATCH v6 06/10] mips: sync struct siginfo with general version Qiaowei Ren
2014-06-18  9:44 ` [PATCH v6 07/10] x86, mpx: decode MPX instruction to get bound violation information Qiaowei Ren
2014-06-18 10:07   ` Borislav Petkov
2014-06-19  1:13     ` Ren, Qiaowei
2014-06-19  6:28       ` Borislav Petkov
2014-06-19  6:53         ` Ren, Qiaowei
2014-06-19 17:04           ` Dave Hansen [this message]
2014-06-19 17:32             ` H. Peter Anvin
2014-06-20  3:21               ` Ren, Qiaowei
2014-06-18  9:44 ` [PATCH v6 08/10] x86, mpx: add prctl commands PR_MPX_REGISTER, PR_MPX_UNREGISTER Qiaowei Ren
2014-06-19 20:58   ` Dave Hansen
2014-06-23 20:00   ` Andy Lutomirski
2014-06-23 20:09     ` Dave Hansen
2014-06-23 22:00       ` Andy Lutomirski
2014-06-23 23:42         ` Dave Hansen
2014-06-24  0:01           ` Andy Lutomirski
2014-06-24  0:10             ` Dave Hansen
2014-06-18  9:44 ` [PATCH v6 09/10] x86, mpx: cleanup unused bound tables Qiaowei Ren
2014-06-23 19:57   ` Andy Lutomirski
2014-06-18  9:44 ` [PATCH v6 10/10] x86, mpx: add documentation on Intel MPX Qiaowei Ren
2014-06-18 14:41 ` [PATCH v6 00/10] Intel MPX support Dave Hansen
2014-06-18 14:41   ` Dave Hansen

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=53A3181F.9070005@intel.com \
    --to=dave.hansen@intel.com \
    --cc=bp@alien8.de \
    --cc=hpa@zytor.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=qiaowei.ren@intel.com \
    --cc=tglx@linutronix.de \
    --cc=x86@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.