~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/x86/kernel/cpu/sgx/driver.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 /*  Copyright(c) 2016-20 Intel Corporation. */
  3 
  4 #include <linux/acpi.h>
  5 #include <linux/miscdevice.h>
  6 #include <linux/mman.h>
  7 #include <linux/security.h>
  8 #include <linux/suspend.h>
  9 #include <asm/traps.h>
 10 #include "driver.h"
 11 #include "encl.h"
 12 
 13 u64 sgx_attributes_reserved_mask;
 14 u64 sgx_xfrm_reserved_mask = ~0x3;
 15 u32 sgx_misc_reserved_mask;
 16 
 17 static int sgx_open(struct inode *inode, struct file *file)
 18 {
 19         struct sgx_encl *encl;
 20         int ret;
 21 
 22         encl = kzalloc(sizeof(*encl), GFP_KERNEL);
 23         if (!encl)
 24                 return -ENOMEM;
 25 
 26         kref_init(&encl->refcount);
 27         xa_init(&encl->page_array);
 28         mutex_init(&encl->lock);
 29         INIT_LIST_HEAD(&encl->va_pages);
 30         INIT_LIST_HEAD(&encl->mm_list);
 31         spin_lock_init(&encl->mm_lock);
 32 
 33         ret = init_srcu_struct(&encl->srcu);
 34         if (ret) {
 35                 kfree(encl);
 36                 return ret;
 37         }
 38 
 39         file->private_data = encl;
 40 
 41         return 0;
 42 }
 43 
 44 static int sgx_release(struct inode *inode, struct file *file)
 45 {
 46         struct sgx_encl *encl = file->private_data;
 47         struct sgx_encl_mm *encl_mm;
 48 
 49         /*
 50          * Drain the remaining mm_list entries. At this point the list contains
 51          * entries for processes, which have closed the enclave file but have
 52          * not exited yet. The processes, which have exited, are gone from the
 53          * list by sgx_mmu_notifier_release().
 54          */
 55         for ( ; ; )  {
 56                 spin_lock(&encl->mm_lock);
 57 
 58                 if (list_empty(&encl->mm_list)) {
 59                         encl_mm = NULL;
 60                 } else {
 61                         encl_mm = list_first_entry(&encl->mm_list,
 62                                                    struct sgx_encl_mm, list);
 63                         list_del_rcu(&encl_mm->list);
 64                 }
 65 
 66                 spin_unlock(&encl->mm_lock);
 67 
 68                 /* The enclave is no longer mapped by any mm. */
 69                 if (!encl_mm)
 70                         break;
 71 
 72                 synchronize_srcu(&encl->srcu);
 73                 mmu_notifier_unregister(&encl_mm->mmu_notifier, encl_mm->mm);
 74                 kfree(encl_mm);
 75 
 76                 /* 'encl_mm' is gone, put encl_mm->encl reference: */
 77                 kref_put(&encl->refcount, sgx_encl_release);
 78         }
 79 
 80         kref_put(&encl->refcount, sgx_encl_release);
 81         return 0;
 82 }
 83 
 84 static int sgx_mmap(struct file *file, struct vm_area_struct *vma)
 85 {
 86         struct sgx_encl *encl = file->private_data;
 87         int ret;
 88 
 89         ret = sgx_encl_may_map(encl, vma->vm_start, vma->vm_end, vma->vm_flags);
 90         if (ret)
 91                 return ret;
 92 
 93         ret = sgx_encl_mm_add(encl, vma->vm_mm);
 94         if (ret)
 95                 return ret;
 96 
 97         vma->vm_ops = &sgx_vm_ops;
 98         vm_flags_set(vma, VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP | VM_IO);
 99         vma->vm_private_data = encl;
100 
101         return 0;
102 }
103 
104 static unsigned long sgx_get_unmapped_area(struct file *file,
105                                            unsigned long addr,
106                                            unsigned long len,
107                                            unsigned long pgoff,
108                                            unsigned long flags)
109 {
110         if ((flags & MAP_TYPE) == MAP_PRIVATE)
111                 return -EINVAL;
112 
113         if (flags & MAP_FIXED)
114                 return addr;
115 
116         return mm_get_unmapped_area(current->mm, file, addr, len, pgoff, flags);
117 }
118 
119 #ifdef CONFIG_COMPAT
120 static long sgx_compat_ioctl(struct file *filep, unsigned int cmd,
121                               unsigned long arg)
122 {
123         return sgx_ioctl(filep, cmd, arg);
124 }
125 #endif
126 
127 static const struct file_operations sgx_encl_fops = {
128         .owner                  = THIS_MODULE,
129         .open                   = sgx_open,
130         .release                = sgx_release,
131         .unlocked_ioctl         = sgx_ioctl,
132 #ifdef CONFIG_COMPAT
133         .compat_ioctl           = sgx_compat_ioctl,
134 #endif
135         .mmap                   = sgx_mmap,
136         .get_unmapped_area      = sgx_get_unmapped_area,
137 };
138 
139 static struct miscdevice sgx_dev_enclave = {
140         .minor = MISC_DYNAMIC_MINOR,
141         .name = "sgx_enclave",
142         .nodename = "sgx_enclave",
143         .fops = &sgx_encl_fops,
144 };
145 
146 int __init sgx_drv_init(void)
147 {
148         unsigned int eax, ebx, ecx, edx;
149         u64 attr_mask;
150         u64 xfrm_mask;
151         int ret;
152 
153         if (!cpu_feature_enabled(X86_FEATURE_SGX_LC))
154                 return -ENODEV;
155 
156         cpuid_count(SGX_CPUID, 0, &eax, &ebx, &ecx, &edx);
157 
158         if (!(eax & 1))  {
159                 pr_err("SGX disabled: SGX1 instruction support not available.\n");
160                 return -ENODEV;
161         }
162 
163         sgx_misc_reserved_mask = ~ebx | SGX_MISC_RESERVED_MASK;
164 
165         cpuid_count(SGX_CPUID, 1, &eax, &ebx, &ecx, &edx);
166 
167         attr_mask = (((u64)ebx) << 32) + (u64)eax;
168         sgx_attributes_reserved_mask = ~attr_mask | SGX_ATTR_RESERVED_MASK;
169 
170         if (cpu_feature_enabled(X86_FEATURE_OSXSAVE)) {
171                 xfrm_mask = (((u64)edx) << 32) + (u64)ecx;
172                 sgx_xfrm_reserved_mask = ~xfrm_mask;
173         }
174 
175         ret = misc_register(&sgx_dev_enclave);
176         if (ret)
177                 return ret;
178 
179         return 0;
180 }
181 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php