aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Hansen <dave.hansen@linux.intel.com>2015-06-07 14:37:05 -0400
committerIngo Molnar <mingo@kernel.org>2015-06-09 06:24:34 -0400
commit613fcb7d3c79ec25b5913a6aa974c9047c31e68c (patch)
treecf4b979e9bf8a951a63eb71ddcd536508148e05e
parent6ac52bb4913eadfa327138b91aab5d37234a2c3b (diff)
x86/mpx: Support 32-bit binaries on 64-bit kernels
Right now, the kernel can only switch between 64-bit and 32-bit binaries at compile time. This patch adds support for 32-bit binaries on 64-bit kernels when we support ia32 emulation. We essentially choose which set of table sizes to use when doing arithmetic for the bounds table calculations. This also uses a different approach for calculating the table indexes than before. I think the new one makes it much more clear what is going on, and allows us to share more code between the 32-bit and 64-bit cases. Based-on-patch-by: Qiaowei Ren <qiaowei.ren@intel.com> Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Dave Hansen <dave@sr71.net> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/r/20150607183705.E01F21E2@viggo.jf.intel.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/x86/include/asm/mpx.h62
-rw-r--r--arch/x86/mm/mpx.c170
2 files changed, 179 insertions, 53 deletions
diff --git a/arch/x86/include/asm/mpx.h b/arch/x86/include/asm/mpx.h
index 99d374eb7b08..7a35495275a9 100644
--- a/arch/x86/include/asm/mpx.h
+++ b/arch/x86/include/asm/mpx.h
@@ -13,49 +13,47 @@
13#define MPX_BNDCFG_ENABLE_FLAG 0x1 13#define MPX_BNDCFG_ENABLE_FLAG 0x1
14#define MPX_BD_ENTRY_VALID_FLAG 0x1 14#define MPX_BD_ENTRY_VALID_FLAG 0x1
15 15
16#ifdef CONFIG_X86_64 16/*
17 17 * The upper 28 bits [47:20] of the virtual address in 64-bit
18/* upper 28 bits [47:20] of the virtual address in 64-bit used to 18 * are used to index into bounds directory (BD).
19 * index into bounds directory (BD). 19 *
20 */ 20 * The directory is 2G (2^31) in size, and with 8-byte entries
21#define MPX_BD_ENTRY_OFFSET 28 21 * it has 2^28 entries.
22#define MPX_BD_ENTRY_SHIFT 3
23/* bits [19:3] of the virtual address in 64-bit used to index into
24 * bounds table (BT).
25 */ 22 */
26#define MPX_BT_ENTRY_OFFSET 17 23#define MPX_BD_SIZE_BYTES_64 (1UL<<31)
27#define MPX_BT_ENTRY_SHIFT 5 24#define MPX_BD_ENTRY_BYTES_64 8
28#define MPX_IGN_BITS 3 25#define MPX_BD_NR_ENTRIES_64 (MPX_BD_SIZE_BYTES_64/MPX_BD_ENTRY_BYTES_64)
29#define MPX_BD_ENTRY_TAIL 3
30 26
31#else 27/*
32 28 * The 32-bit directory is 4MB (2^22) in size, and with 4-byte
33#define MPX_BD_ENTRY_OFFSET 20 29 * entries it has 2^20 entries.
34#define MPX_BD_ENTRY_SHIFT 2 30 */
35#define MPX_BT_ENTRY_OFFSET 10 31#define MPX_BD_SIZE_BYTES_32 (1UL<<22)
36#define MPX_BT_ENTRY_SHIFT 4 32#define MPX_BD_ENTRY_BYTES_32 4
37#define MPX_IGN_BITS 2 33#define MPX_BD_NR_ENTRIES_32 (MPX_BD_SIZE_BYTES_32/MPX_BD_ENTRY_BYTES_32)
38#define MPX_BD_ENTRY_TAIL 2
39 34
40#endif 35/*
36 * A 64-bit table is 4MB total in size, and an entry is
37 * 4 64-bit pointers in size.
38 */
39#define MPX_BT_SIZE_BYTES_64 (1UL<<22)
40#define MPX_BT_ENTRY_BYTES_64 32
41#define MPX_BT_NR_ENTRIES_64 (MPX_BT_SIZE_BYTES_64/MPX_BT_ENTRY_BYTES_64)
41 42
42#define MPX_BD_SIZE_BYTES (1UL<<(MPX_BD_ENTRY_OFFSET+MPX_BD_ENTRY_SHIFT)) 43/*
43#define MPX_BT_SIZE_BYTES (1UL<<(MPX_BT_ENTRY_OFFSET+MPX_BT_ENTRY_SHIFT)) 44 * A 32-bit table is 16kB total in size, and an entry is
45 * 4 32-bit pointers in size.
46 */
47#define MPX_BT_SIZE_BYTES_32 (1UL<<14)
48#define MPX_BT_ENTRY_BYTES_32 16
49#define MPX_BT_NR_ENTRIES_32 (MPX_BT_SIZE_BYTES_32/MPX_BT_ENTRY_BYTES_32)
44 50
45#define MPX_BNDSTA_TAIL 2 51#define MPX_BNDSTA_TAIL 2
46#define MPX_BNDCFG_TAIL 12 52#define MPX_BNDCFG_TAIL 12
47#define MPX_BNDSTA_ADDR_MASK (~((1UL<<MPX_BNDSTA_TAIL)-1)) 53#define MPX_BNDSTA_ADDR_MASK (~((1UL<<MPX_BNDSTA_TAIL)-1))
48
49#define MPX_BNDCFG_ADDR_MASK (~((1UL<<MPX_BNDCFG_TAIL)-1)) 54#define MPX_BNDCFG_ADDR_MASK (~((1UL<<MPX_BNDCFG_TAIL)-1))
50#define MPX_BNDSTA_ERROR_CODE 0x3 55#define MPX_BNDSTA_ERROR_CODE 0x3
51 56
52#define MPX_BD_ENTRY_MASK ((1<<MPX_BD_ENTRY_OFFSET)-1)
53#define MPX_BT_ENTRY_MASK ((1<<MPX_BT_ENTRY_OFFSET)-1)
54#define MPX_GET_BD_ENTRY_OFFSET(addr) ((((addr)>>(MPX_BT_ENTRY_OFFSET+ \
55 MPX_IGN_BITS)) & MPX_BD_ENTRY_MASK) << MPX_BD_ENTRY_SHIFT)
56#define MPX_GET_BT_ENTRY_OFFSET(addr) ((((addr)>>MPX_IGN_BITS) & \
57 MPX_BT_ENTRY_MASK) << MPX_BT_ENTRY_SHIFT)
58
59#ifdef CONFIG_X86_INTEL_MPX 57#ifdef CONFIG_X86_INTEL_MPX
60siginfo_t *mpx_generate_siginfo(struct pt_regs *regs); 58siginfo_t *mpx_generate_siginfo(struct pt_regs *regs);
61int mpx_handle_bd_fault(void); 59int mpx_handle_bd_fault(void);
diff --git a/arch/x86/mm/mpx.c b/arch/x86/mm/mpx.c
index 294ea2092ef5..e323ef65c9ff 100644
--- a/arch/x86/mm/mpx.c
+++ b/arch/x86/mm/mpx.c
@@ -34,6 +34,22 @@ static int is_mpx_vma(struct vm_area_struct *vma)
34 return (vma->vm_ops == &mpx_vma_ops); 34 return (vma->vm_ops == &mpx_vma_ops);
35} 35}
36 36
37static inline unsigned long mpx_bd_size_bytes(struct mm_struct *mm)
38{
39 if (is_64bit_mm(mm))
40 return MPX_BD_SIZE_BYTES_64;
41 else
42 return MPX_BD_SIZE_BYTES_32;
43}
44
45static inline unsigned long mpx_bt_size_bytes(struct mm_struct *mm)
46{
47 if (is_64bit_mm(mm))
48 return MPX_BT_SIZE_BYTES_64;
49 else
50 return MPX_BT_SIZE_BYTES_32;
51}
52
37/* 53/*
38 * This is really a simplified "vm_mmap". it only handles MPX 54 * This is really a simplified "vm_mmap". it only handles MPX
39 * bounds tables (the bounds directory is user-allocated). 55 * bounds tables (the bounds directory is user-allocated).
@@ -50,7 +66,7 @@ static unsigned long mpx_mmap(unsigned long len)
50 struct vm_area_struct *vma; 66 struct vm_area_struct *vma;
51 67
52 /* Only bounds table can be allocated here */ 68 /* Only bounds table can be allocated here */
53 if (len != MPX_BT_SIZE_BYTES) 69 if (len != mpx_bt_size_bytes(mm))
54 return -EINVAL; 70 return -EINVAL;
55 71
56 down_write(&mm->mmap_sem); 72 down_write(&mm->mmap_sem);
@@ -449,13 +465,12 @@ static int mpx_cmpxchg_bd_entry(struct mm_struct *mm,
449} 465}
450 466
451/* 467/*
452 * With 32-bit mode, MPX_BT_SIZE_BYTES is 4MB, and the size of each 468 * With 32-bit mode, a bounds directory is 4MB, and the size of each
453 * bounds table is 16KB. With 64-bit mode, MPX_BT_SIZE_BYTES is 2GB, 469 * bounds table is 16KB. With 64-bit mode, a bounds directory is 2GB,
454 * and the size of each bounds table is 4MB. 470 * and the size of each bounds table is 4MB.
455 */ 471 */
456static int allocate_bt(long __user *bd_entry) 472static int allocate_bt(struct mm_struct *mm, long __user *bd_entry)
457{ 473{
458 struct mm_struct *mm = current->mm;
459 unsigned long expected_old_val = 0; 474 unsigned long expected_old_val = 0;
460 unsigned long actual_old_val = 0; 475 unsigned long actual_old_val = 0;
461 unsigned long bt_addr; 476 unsigned long bt_addr;
@@ -466,7 +481,7 @@ static int allocate_bt(long __user *bd_entry)
466 * Carve the virtual space out of userspace for the new 481 * Carve the virtual space out of userspace for the new
467 * bounds table: 482 * bounds table:
468 */ 483 */
469 bt_addr = mpx_mmap(MPX_BT_SIZE_BYTES); 484 bt_addr = mpx_mmap(mpx_bt_size_bytes(mm));
470 if (IS_ERR((void *)bt_addr)) 485 if (IS_ERR((void *)bt_addr))
471 return PTR_ERR((void *)bt_addr); 486 return PTR_ERR((void *)bt_addr);
472 /* 487 /*
@@ -517,7 +532,7 @@ static int allocate_bt(long __user *bd_entry)
517 trace_mpx_new_bounds_table(bt_addr); 532 trace_mpx_new_bounds_table(bt_addr);
518 return 0; 533 return 0;
519out_unmap: 534out_unmap:
520 vm_munmap(bt_addr, MPX_BT_SIZE_BYTES); 535 vm_munmap(bt_addr, mpx_bt_size_bytes(mm));
521 return ret; 536 return ret;
522} 537}
523 538
@@ -536,6 +551,7 @@ static int do_mpx_bt_fault(void)
536{ 551{
537 unsigned long bd_entry, bd_base; 552 unsigned long bd_entry, bd_base;
538 const struct bndcsr *bndcsr; 553 const struct bndcsr *bndcsr;
554 struct mm_struct *mm = current->mm;
539 555
540 bndcsr = get_xsave_field_ptr(XSTATE_BNDCSR); 556 bndcsr = get_xsave_field_ptr(XSTATE_BNDCSR);
541 if (!bndcsr) 557 if (!bndcsr)
@@ -554,10 +570,10 @@ static int do_mpx_bt_fault(void)
554 * the directory is. 570 * the directory is.
555 */ 571 */
556 if ((bd_entry < bd_base) || 572 if ((bd_entry < bd_base) ||
557 (bd_entry >= bd_base + MPX_BD_SIZE_BYTES)) 573 (bd_entry >= bd_base + mpx_bd_size_bytes(mm)))
558 return -EINVAL; 574 return -EINVAL;
559 575
560 return allocate_bt((long __user *)bd_entry); 576 return allocate_bt(mm, (long __user *)bd_entry);
561} 577}
562 578
563int mpx_handle_bd_fault(void) 579int mpx_handle_bd_fault(void)
@@ -789,7 +805,115 @@ static int unmap_single_bt(struct mm_struct *mm,
789 * avoid recursion, do_munmap() will check whether it comes 805 * avoid recursion, do_munmap() will check whether it comes
790 * from one bounds table through VM_MPX flag. 806 * from one bounds table through VM_MPX flag.
791 */ 807 */
792 return do_munmap(mm, bt_addr, MPX_BT_SIZE_BYTES); 808 return do_munmap(mm, bt_addr, mpx_bt_size_bytes(mm));
809}
810
811static inline int bt_entry_size_bytes(struct mm_struct *mm)
812{
813 if (is_64bit_mm(mm))
814 return MPX_BT_ENTRY_BYTES_64;
815 else
816 return MPX_BT_ENTRY_BYTES_32;
817}
818
819/*
820 * Take a virtual address and turns it in to the offset in bytes
821 * inside of the bounds table where the bounds table entry
822 * controlling 'addr' can be found.
823 */
824static unsigned long mpx_get_bt_entry_offset_bytes(struct mm_struct *mm,
825 unsigned long addr)
826{
827 unsigned long bt_table_nr_entries;
828 unsigned long offset = addr;
829
830 if (is_64bit_mm(mm)) {
831 /* Bottom 3 bits are ignored on 64-bit */
832 offset >>= 3;
833 bt_table_nr_entries = MPX_BT_NR_ENTRIES_64;
834 } else {
835 /* Bottom 2 bits are ignored on 32-bit */
836 offset >>= 2;
837 bt_table_nr_entries = MPX_BT_NR_ENTRIES_32;
838 }
839 /*
840 * We know the size of the table in to which we are
841 * indexing, and we have eliminated all the low bits
842 * which are ignored for indexing.
843 *
844 * Mask out all the high bits which we do not need
845 * to index in to the table. Note that the tables
846 * are always powers of two so this gives us a proper
847 * mask.
848 */
849 offset &= (bt_table_nr_entries-1);
850 /*
851 * We now have an entry offset in terms of *entries* in
852 * the table. We need to scale it back up to bytes.
853 */
854 offset *= bt_entry_size_bytes(mm);
855 return offset;
856}
857
858/*
859 * How much virtual address space does a single bounds
860 * directory entry cover?
861 *
862 * Note, we need a long long because 4GB doesn't fit in
863 * to a long on 32-bit.
864 */
865static inline unsigned long bd_entry_virt_space(struct mm_struct *mm)
866{
867 unsigned long long virt_space = (1ULL << boot_cpu_data.x86_virt_bits);
868 if (is_64bit_mm(mm))
869 return virt_space / MPX_BD_NR_ENTRIES_64;
870 else
871 return virt_space / MPX_BD_NR_ENTRIES_32;
872}
873
874/*
875 * Return an offset in terms of bytes in to the bounds
876 * directory where the bounds directory entry for a given
877 * virtual address resides.
878 *
879 * This has to be in bytes because the directory entries
880 * are different sizes on 64/32 bit.
881 */
882static unsigned long mpx_get_bd_entry_offset(struct mm_struct *mm,
883 unsigned long addr)
884{
885 /*
886 * There are several ways to derive the bd offsets. We
887 * use the following approach here:
888 * 1. We know the size of the virtual address space
889 * 2. We know the number of entries in a bounds table
890 * 3. We know that each entry covers a fixed amount of
891 * virtual address space.
892 * So, we can just divide the virtual address by the
893 * virtual space used by one entry to determine which
894 * entry "controls" the given virtual address.
895 */
896 if (is_64bit_mm(mm)) {
897 int bd_entry_size = 8; /* 64-bit pointer */
898 /*
899 * Take the 64-bit addressing hole in to account.
900 */
901 addr &= ((1UL << boot_cpu_data.x86_virt_bits) - 1);
902 return (addr / bd_entry_virt_space(mm)) * bd_entry_size;
903 } else {
904 int bd_entry_size = 4; /* 32-bit pointer */
905 /*
906 * 32-bit has no hole so this case needs no mask
907 */
908 return (addr / bd_entry_virt_space(mm)) * bd_entry_size;
909 }
910 /*
911 * The two return calls above are exact copies. If we
912 * pull out a single copy and put it in here, gcc won't
913 * realize that we're doing a power-of-2 divide and use
914 * shifts. It uses a real divide. If we put them up
915 * there, it manages to figure it out (gcc 4.8.3).
916 */
793} 917}
794 918
795/* 919/*
@@ -803,6 +927,7 @@ static int unmap_shared_bt(struct mm_struct *mm,
803 unsigned long end, bool prev_shared, bool next_shared) 927 unsigned long end, bool prev_shared, bool next_shared)
804{ 928{
805 unsigned long bt_addr; 929 unsigned long bt_addr;
930 unsigned long start_off, end_off;
806 int ret; 931 int ret;
807 932
808 ret = get_bt_addr(mm, bd_entry, &bt_addr); 933 ret = get_bt_addr(mm, bd_entry, &bt_addr);
@@ -814,17 +939,20 @@ static int unmap_shared_bt(struct mm_struct *mm,
814 if (ret) 939 if (ret)
815 return ret; 940 return ret;
816 941
942 start_off = mpx_get_bt_entry_offset_bytes(mm, start);
943 end_off = mpx_get_bt_entry_offset_bytes(mm, end);
944
817 if (prev_shared && next_shared) 945 if (prev_shared && next_shared)
818 ret = zap_bt_entries(mm, bt_addr, 946 ret = zap_bt_entries(mm, bt_addr,
819 bt_addr+MPX_GET_BT_ENTRY_OFFSET(start), 947 bt_addr + start_off,
820 bt_addr+MPX_GET_BT_ENTRY_OFFSET(end)); 948 bt_addr + end_off);
821 else if (prev_shared) 949 else if (prev_shared)
822 ret = zap_bt_entries(mm, bt_addr, 950 ret = zap_bt_entries(mm, bt_addr,
823 bt_addr+MPX_GET_BT_ENTRY_OFFSET(start), 951 bt_addr + start_off,
824 bt_addr+MPX_BT_SIZE_BYTES); 952 bt_addr + mpx_bt_size_bytes(mm));
825 else if (next_shared) 953 else if (next_shared)
826 ret = zap_bt_entries(mm, bt_addr, bt_addr, 954 ret = zap_bt_entries(mm, bt_addr, bt_addr,
827 bt_addr+MPX_GET_BT_ENTRY_OFFSET(end)); 955 bt_addr + end_off);
828 else 956 else
829 ret = unmap_single_bt(mm, bd_entry, bt_addr); 957 ret = unmap_single_bt(mm, bd_entry, bt_addr);
830 958
@@ -845,8 +973,8 @@ static int unmap_edge_bts(struct mm_struct *mm,
845 struct vm_area_struct *prev, *next; 973 struct vm_area_struct *prev, *next;
846 bool prev_shared = false, next_shared = false; 974 bool prev_shared = false, next_shared = false;
847 975
848 bde_start = mm->bd_addr + MPX_GET_BD_ENTRY_OFFSET(start); 976 bde_start = mm->bd_addr + mpx_get_bd_entry_offset(mm, start);
849 bde_end = mm->bd_addr + MPX_GET_BD_ENTRY_OFFSET(end-1); 977 bde_end = mm->bd_addr + mpx_get_bd_entry_offset(mm, end-1);
850 978
851 /* 979 /*
852 * Check whether bde_start and bde_end are shared with adjacent 980 * Check whether bde_start and bde_end are shared with adjacent
@@ -858,10 +986,10 @@ static int unmap_edge_bts(struct mm_struct *mm,
858 * in to 'next'. 986 * in to 'next'.
859 */ 987 */
860 next = find_vma_prev(mm, start, &prev); 988 next = find_vma_prev(mm, start, &prev);
861 if (prev && (mm->bd_addr + MPX_GET_BD_ENTRY_OFFSET(prev->vm_end-1)) 989 if (prev && (mm->bd_addr + mpx_get_bd_entry_offset(mm, prev->vm_end-1))
862 == bde_start) 990 == bde_start)
863 prev_shared = true; 991 prev_shared = true;
864 if (next && (mm->bd_addr + MPX_GET_BD_ENTRY_OFFSET(next->vm_start)) 992 if (next && (mm->bd_addr + mpx_get_bd_entry_offset(mm, next->vm_start))
865 == bde_end) 993 == bde_end)
866 next_shared = true; 994 next_shared = true;
867 995
@@ -927,8 +1055,8 @@ static int mpx_unmap_tables(struct mm_struct *mm,
927 * 1. fully covered 1055 * 1. fully covered
928 * 2. not at the edges of the mapping, even if full aligned 1056 * 2. not at the edges of the mapping, even if full aligned
929 */ 1057 */
930 bde_start = mm->bd_addr + MPX_GET_BD_ENTRY_OFFSET(start); 1058 bde_start = mm->bd_addr + mpx_get_bd_entry_offset(mm, start);
931 bde_end = mm->bd_addr + MPX_GET_BD_ENTRY_OFFSET(end-1); 1059 bde_end = mm->bd_addr + mpx_get_bd_entry_offset(mm, end-1);
932 for (bd_entry = bde_start + 1; bd_entry < bde_end; bd_entry++) { 1060 for (bd_entry = bde_start + 1; bd_entry < bde_end; bd_entry++) {
933 ret = get_bt_addr(mm, bd_entry, &bt_addr); 1061 ret = get_bt_addr(mm, bd_entry, &bt_addr);
934 switch (ret) { 1062 switch (ret) {