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
_
next prev parent reply other threads:[~2014-06-19 17:07 UTC|newest]
Thread overview: 65+ 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 20:03 ` Dave Hansen
2014-06-23 20:06 ` Andy Lutomirski
2014-06-23 20:28 ` Dave Hansen
2014-06-23 21:04 ` Andy Lutomirski
2014-06-24 5:53 ` Ren, Qiaowei
2014-06-24 23:55 ` Andy Lutomirski
2014-06-25 1:40 ` Ren, Qiaowei
2014-06-25 21:04 ` Andy Lutomirski
2014-06-25 21:05 ` Andy Lutomirski
2014-06-25 21:45 ` Dave Hansen
2014-06-26 22:19 ` Andy Lutomirski
2014-06-26 22:58 ` Dave Hansen
2014-06-26 23:15 ` Andy Lutomirski
2014-06-27 0:19 ` Dave Hansen
2014-06-27 0:26 ` Andy Lutomirski
2014-06-27 17:34 ` Dave Hansen
2014-06-27 17:42 ` Dave Hansen
2014-06-27 18:57 ` Andy Lutomirski
2014-06-25 21:43 ` Dave Hansen
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
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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome