3 *************************************************************************
6 * Copyright (C) 2014, Intel Corporation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
14 * * Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * * Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
20 * * Neither the name of Intel Corporation nor the names of its
21 * contributors may be used to endorse or promote products derived
22 * from this software without specific prior written permission.
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
30 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
31 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
32 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
33 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
35 * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
38 **************************************************************************/
40 #define __STDC_FORMAT_MACROS
51 #include <sys/prctl.h>
53 #include "mpxrt-utils.h"
56 #define MPX_ENABLE_BIT_NO 0
57 #define BNDPRESERVE_BIT_NO 1
59 struct xsave_hdr_struct
62 uint64_t reserved1
[2];
63 uint64_t reserved2
[5];
64 } __attribute__ ((packed
));
69 } __attribute__ ((packed
));
71 struct bndcsr_struct
{
74 } __attribute__((packed
));
79 struct xsave_hdr_struct xsave_hdr
;
82 struct bndregs_struct bndregs
;
83 struct bndcsr_struct bndcsr
;
84 } __attribute__ ((packed
));
86 /* Following vars are initialized at process startup only
87 and thus are considered to be thread safe. */
88 static void *l1base
= NULL
;
89 static int bndpreserve
;
90 static int enable
= 1;
92 /* Var holding number of occured BRs. It is modified from
93 signal handler only and thus it should be thread safe. */
94 static uint64_t num_bnd_chk
= 0;
97 xrstor_state (struct xsave_struct
*fx
, uint64_t mask
)
99 uint32_t lmask
= mask
;
100 uint32_t hmask
= mask
>> 32;
102 asm volatile (".byte " REX_PREFIX
"0x0f,0xae,0x2f\n\t"
103 : : "D" (fx
), "m" (*fx
), "a" (lmask
), "d" (hmask
)
108 xsave_state (struct xsave_struct
*fx
, uint64_t mask
)
110 uint32_t lmask
= mask
;
111 uint32_t hmask
= mask
>> 32;
113 asm volatile (".byte " REX_PREFIX
"0x0f,0xae,0x27\n\t"
114 : : "D" (fx
), "m" (*fx
), "a" (lmask
), "d" (hmask
)
118 static inline uint64_t
119 xgetbv (uint32_t index
)
123 asm volatile (".byte 0x0f,0x01,0xd0" /* xgetbv */
124 : "=a" (eax
), "=d" (edx
)
126 return eax
+ ((uint64_t)edx
<< 32);
130 read_mpx_status_sig (ucontext_t
*uctxt
)
132 uint8_t *regs
= (uint8_t *)uctxt
->uc_mcontext
.fpregs
+ XSAVE_OFFSET_IN_FPMEM
;
133 struct xsave_struct
*xsave_buf
= (struct xsave_struct
*)regs
;
134 return xsave_buf
->bndcsr
.status_reg
;
138 get_next_inst_ip (uint8_t *addr
)
143 /* Determine the prefix. */
153 /* Look for rex prefix. */
154 if ((*ip
& 0x40) == 0x40)
157 /* Make sure we have a MPX instruction. */
161 /* Skip the op code byte. */
164 /* Get the moderm byte. */
165 uint8_t modrm
= *ip
++;
167 /* Break it down into parts. */
168 uint8_t rm
= modrm
& 7;
169 uint8_t mod
= (modrm
>> 6);
171 /* Init the parts of the address mode. */
174 /* Is it a mem mode? */
177 /* Look for scaled indexed addressing. */
180 /* SIB addressing. */
201 /* MODRM addressing. */
206 /* DISP32 addressing, no base. */
224 handler (int sig
__attribute__ ((unused
)),
225 siginfo_t
*info
__attribute__ ((unused
)),
227 struct xsave_struct
*buf
__attribute__ ((unused
)))
234 trapno
= uctxt
->uc_mcontext
.gregs
[REG_TRAPNO
];
235 ip
= uctxt
->uc_mcontext
.gregs
[REG_IP_IDX
];
239 uint64_t status
= read_mpx_status_sig (uctxt
);
240 uint64_t br_reason
= status
& 0x3;
242 __mpxrt_write (VERB_BR
, "Saw a #BR! status ");
243 __mpxrt_write_uint (VERB_BR
, status
, 10);
244 __mpxrt_write (VERB_BR
, " at 0x");
245 __mpxrt_write_uint (VERB_BR
, ip
, 16);
246 __mpxrt_write (VERB_BR
, "\n");
250 case 1: /* traditional BR */
252 uctxt
->uc_mcontext
.gregs
[REG_IP_IDX
] =
253 (greg_t
)get_next_inst_ip ((uint8_t *)ip
);
254 if (__mpxrt_mode () == MPX_RT_STOP
)
259 __mpxrt_write (VERB_BR
, "Unexpected status with bound exception: ");
260 __mpxrt_write_uint (VERB_BR
, status
, 10);
261 __mpxrt_write (VERB_BR
, "\n");
265 else if (trapno
== 14)
267 __mpxrt_write (VERB_ERROR
, "In signal handler, trapno = ");
268 __mpxrt_write_uint (VERB_ERROR
, trapno
, 10);
269 __mpxrt_write (VERB_ERROR
, ", ip = 0x");
270 __mpxrt_write_uint (VERB_ERROR
, ip
, 16);
271 __mpxrt_write (VERB_ERROR
, "\n");
276 __mpxrt_write (VERB_ERROR
, "Unexpected trap ");
277 __mpxrt_write_uint (VERB_ERROR
, trapno
, 10);
278 __mpxrt_write (VERB_ERROR
, "! at 0x");
279 __mpxrt_write_uint (VERB_ERROR
, ip
, 16);
280 __mpxrt_write (VERB_ERROR
, "\n");
285 /* Using wrapper to the real handler in order to save the bnd regs
286 using xsave before any unprefixed call. an unprefixed call to
287 __i686.get_pc_thunk.bx is added by the linker in 32bit at the
288 beginning of handler function since there are references to
291 handler_wrap (int signum
, siginfo_t
* si
, void* vucontext
)
293 /* Since the OS currently not handling chkptr regs.
294 We need to store them for later use. They might be
295 init due to unprefixed call,Jcc,ret. avoiding calling
296 function since the function will be unprefixed as well. */
297 uint8_t __attribute__ ((__aligned__ (64))) buffer
[4096];
298 struct xsave_struct
*xsave_buf
= (struct xsave_struct
*)buffer
;
299 uint64_t mask
= 0x18;
300 uint32_t lmask
= mask
;
301 uint32_t hmask
= mask
>> 32;
303 asm volatile (".byte " REX_PREFIX
"0x0f,0xae,0x27\n\t"
304 : : "D" (xsave_buf
), "m" (*xsave_buf
),
305 "a" (lmask
), "d" (hmask
)
308 handler (signum
, si
, vucontext
, xsave_buf
);
312 check_mpx_support (void)
314 unsigned int eax
, ebx
, ecx
, edx
;
315 unsigned int max_level
= __get_cpuid_max (0, NULL
);
319 __mpxrt_print (VERB_DEBUG
, "No required CPUID level support.\n");
323 __cpuid_count (0, 0, eax
, ebx
, ecx
, edx
);
324 if (!(ecx
& bit_XSAVE
))
326 __mpxrt_print (VERB_DEBUG
, "No XSAVE support.\n");
330 if (!(ecx
& bit_OSXSAVE
))
332 __mpxrt_print (VERB_DEBUG
, "No OSXSAVE support.\n");
336 __cpuid_count (7, 0, eax
, ebx
, ecx
, edx
);
337 if (!(ebx
& bit_MPX
))
339 __mpxrt_print (VERB_DEBUG
, "No MPX support.\n");
343 __cpuid_count (13, 0, eax
, ebx
, ecx
, edx
);
344 if (!(eax
& bit_BNDREGS
))
346 __mpxrt_print (VERB_DEBUG
, "No BNDREGS support.\n");
350 if (!(eax
& bit_BNDCSR
))
352 __mpxrt_print (VERB_DEBUG
, "No BNDCSR support.\n");
362 uint8_t __attribute__ ((__aligned__ (64))) buffer
[4096];
363 struct xsave_struct
*xsave_buf
= (struct xsave_struct
*)buffer
;
365 memset (buffer
, 0, sizeof (buffer
));
366 xrstor_state (xsave_buf
, 0x18);
368 __mpxrt_print (VERB_DEBUG
, "Initalizing MPX...\n");
369 __mpxrt_print (VERB_DEBUG
, " Enable bit: %d\n", enable
);
370 __mpxrt_print (VERB_DEBUG
, " BNDPRESERVE bit: %d\n", bndpreserve
);
373 xsave_buf
->xsave_hdr
.xstate_bv
= 0x10;
374 xsave_buf
->bndcsr
.cfg_reg_u
= (unsigned long)l1base
;
375 xsave_buf
->bndcsr
.cfg_reg_u
|= enable
<< MPX_ENABLE_BIT_NO
;
376 xsave_buf
->bndcsr
.cfg_reg_u
|= bndpreserve
<< BNDPRESERVE_BIT_NO
;
377 xsave_buf
->bndcsr
.status_reg
= 0;
379 xrstor_state (xsave_buf
, 0x10);
385 uint8_t __attribute__ ((__aligned__ (64))) buffer
[4096];
386 struct xsave_struct
*xsave_buf
= (struct xsave_struct
*)buffer
;
388 memset(buffer
, 0, sizeof(buffer
));
389 xrstor_state(xsave_buf
, 0x18);
392 xsave_buf
->xsave_hdr
.xstate_bv
= 0x10;
393 xsave_buf
->bndcsr
.cfg_reg_u
= 0;
394 xsave_buf
->bndcsr
.status_reg
= 0;
396 xrstor_state(xsave_buf
, 0x10);
400 process_specific_init (void)
402 if (!check_mpx_support ())
405 l1base
= mmap (NULL
, MPX_L1_SIZE
, PROT_READ
| PROT_WRITE
,
406 MAP_ANONYMOUS
| MAP_PRIVATE
, -1, 0);
407 if (l1base
== MAP_FAILED
)
415 if (prctl (43, 0, 0, 0, 0))
417 __mpxrt_print (VERB_ERROR
, "No MPX support\n");
426 process_specific_finish (void)
428 if (!check_mpx_support ())
431 if (prctl (44, 0, 0, 0, 0))
433 __mpxrt_print (VERB_ERROR
, "No MPX support\n");
437 munmap (l1base
, MPX_L1_SIZE
);
446 struct sigaction newact
;
448 /* #BR is mapped to sigsegv */
449 int signum
= SIGSEGV
;
451 newact
.sa_handler
= 0;
452 newact
.sa_sigaction
= handler_wrap
;
454 /* sigset_t - signals to block while in the handler
455 get the old signal mask. */
456 rs
= sigprocmask (SIG_SETMASK
, 0, &newact
.sa_mask
);
459 /* Call sa_sigaction, not sa_handler. */
460 newact
.sa_flags
= SA_SIGINFO
;
461 /* In case we call user's handler on SIGSEGV (not bound
462 violation exception) we want to allow bound checking
463 inside the user handler -> nested exception. */
464 newact
.sa_flags
|= SA_NODEFER
;
466 newact
.sa_restorer
= 0;
467 r
= sigaction (signum
, &newact
, 0);
471 /* Set constructor priority to two to make it run after the
472 constructor in sigaction.c. */
473 static void __attribute__ ((constructor (1005)))
476 __mpxrt_init_env_vars (&bndpreserve
);
478 process_specific_init ();
481 static void __attribute__ ((destructor
))
484 __mpxrt_print_summary (num_bnd_chk
, MPX_L1_SIZE
);
485 __mpxrt_utils_free ();
486 process_specific_finish ();
489 /* Get address of bounds directory. */