x86, mpx: Add MPX-specific mmap interface
[deliverable/linux.git] / arch / x86 / mm / mpx.c
1 /*
2 * mpx.c - Memory Protection eXtensions
3 *
4 * Copyright (c) 2014, Intel Corporation.
5 * Qiaowei Ren <qiaowei.ren@intel.com>
6 * Dave Hansen <dave.hansen@intel.com>
7 */
8 #include <linux/kernel.h>
9 #include <linux/syscalls.h>
10 #include <linux/sched/sysctl.h>
11
12 #include <asm/mman.h>
13 #include <asm/mpx.h>
14
15 static const char *mpx_mapping_name(struct vm_area_struct *vma)
16 {
17 return "[mpx]";
18 }
19
20 static struct vm_operations_struct mpx_vma_ops = {
21 .name = mpx_mapping_name,
22 };
23
24 /*
25 * This is really a simplified "vm_mmap". it only handles MPX
26 * bounds tables (the bounds directory is user-allocated).
27 *
28 * Later on, we use the vma->vm_ops to uniquely identify these
29 * VMAs.
30 */
31 static unsigned long mpx_mmap(unsigned long len)
32 {
33 unsigned long ret;
34 unsigned long addr, pgoff;
35 struct mm_struct *mm = current->mm;
36 vm_flags_t vm_flags;
37 struct vm_area_struct *vma;
38
39 /* Only bounds table and bounds directory can be allocated here */
40 if (len != MPX_BD_SIZE_BYTES && len != MPX_BT_SIZE_BYTES)
41 return -EINVAL;
42
43 down_write(&mm->mmap_sem);
44
45 /* Too many mappings? */
46 if (mm->map_count > sysctl_max_map_count) {
47 ret = -ENOMEM;
48 goto out;
49 }
50
51 /* Obtain the address to map to. we verify (or select) it and ensure
52 * that it represents a valid section of the address space.
53 */
54 addr = get_unmapped_area(NULL, 0, len, 0, MAP_ANONYMOUS | MAP_PRIVATE);
55 if (addr & ~PAGE_MASK) {
56 ret = addr;
57 goto out;
58 }
59
60 vm_flags = VM_READ | VM_WRITE | VM_MPX |
61 mm->def_flags | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC;
62
63 /* Set pgoff according to addr for anon_vma */
64 pgoff = addr >> PAGE_SHIFT;
65
66 ret = mmap_region(NULL, addr, len, vm_flags, pgoff);
67 if (IS_ERR_VALUE(ret))
68 goto out;
69
70 vma = find_vma(mm, ret);
71 if (!vma) {
72 ret = -ENOMEM;
73 goto out;
74 }
75 vma->vm_ops = &mpx_vma_ops;
76
77 if (vm_flags & VM_LOCKED) {
78 up_write(&mm->mmap_sem);
79 mm_populate(ret, len);
80 return ret;
81 }
82
83 out:
84 up_write(&mm->mmap_sem);
85 return ret;
86 }
This page took 0.031914 seconds and 5 git commands to generate.