├── CODE_OF_CONDUCT.md ├── LICENSE ├── Makefile.am ├── README.md ├── configure.ac ├── maintainer.sh ├── sgxtop.1 └── sgxtop.c /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at [speak-up@fortanix.com](mailto:speak-up@fortanix.com). All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | 78 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Mozilla Public License Version 2.0 2 | ================================== 3 | 4 | 1. Definitions 5 | -------------- 6 | 7 | 1.1. "Contributor" 8 | means each individual or legal entity that creates, contributes to 9 | the creation of, or owns Covered Software. 10 | 11 | 1.2. "Contributor Version" 12 | means the combination of the Contributions of others (if any) used 13 | by a Contributor and that particular Contributor's Contribution. 14 | 15 | 1.3. "Contribution" 16 | means Covered Software of a particular Contributor. 17 | 18 | 1.4. "Covered Software" 19 | means Source Code Form to which the initial Contributor has attached 20 | the notice in Exhibit A, the Executable Form of such Source Code 21 | Form, and Modifications of such Source Code Form, in each case 22 | including portions thereof. 23 | 24 | 1.5. "Incompatible With Secondary Licenses" 25 | means 26 | 27 | (a) that the initial Contributor has attached the notice described 28 | in Exhibit B to the Covered Software; or 29 | 30 | (b) that the Covered Software was made available under the terms of 31 | version 1.1 or earlier of the License, but not also under the 32 | terms of a Secondary License. 33 | 34 | 1.6. "Executable Form" 35 | means any form of the work other than Source Code Form. 36 | 37 | 1.7. "Larger Work" 38 | means a work that combines Covered Software with other material, in 39 | a separate file or files, that is not Covered Software. 40 | 41 | 1.8. "License" 42 | means this document. 43 | 44 | 1.9. "Licensable" 45 | means having the right to grant, to the maximum extent possible, 46 | whether at the time of the initial grant or subsequently, any and 47 | all of the rights conveyed by this License. 48 | 49 | 1.10. "Modifications" 50 | means any of the following: 51 | 52 | (a) any file in Source Code Form that results from an addition to, 53 | deletion from, or modification of the contents of Covered 54 | Software; or 55 | 56 | (b) any new file in Source Code Form that contains any Covered 57 | Software. 58 | 59 | 1.11. "Patent Claims" of a Contributor 60 | means any patent claim(s), including without limitation, method, 61 | process, and apparatus claims, in any patent Licensable by such 62 | Contributor that would be infringed, but for the grant of the 63 | License, by the making, using, selling, offering for sale, having 64 | made, import, or transfer of either its Contributions or its 65 | Contributor Version. 66 | 67 | 1.12. "Secondary License" 68 | means either the GNU General Public License, Version 2.0, the GNU 69 | Lesser General Public License, Version 2.1, the GNU Affero General 70 | Public License, Version 3.0, or any later versions of those 71 | licenses. 72 | 73 | 1.13. "Source Code Form" 74 | means the form of the work preferred for making modifications. 75 | 76 | 1.14. "You" (or "Your") 77 | means an individual or a legal entity exercising rights under this 78 | License. For legal entities, "You" includes any entity that 79 | controls, is controlled by, or is under common control with You. For 80 | purposes of this definition, "control" means (a) the power, direct 81 | or indirect, to cause the direction or management of such entity, 82 | whether by contract or otherwise, or (b) ownership of more than 83 | fifty percent (50%) of the outstanding shares or beneficial 84 | ownership of such entity. 85 | 86 | 2. License Grants and Conditions 87 | -------------------------------- 88 | 89 | 2.1. Grants 90 | 91 | Each Contributor hereby grants You a world-wide, royalty-free, 92 | non-exclusive license: 93 | 94 | (a) under intellectual property rights (other than patent or trademark) 95 | Licensable by such Contributor to use, reproduce, make available, 96 | modify, display, perform, distribute, and otherwise exploit its 97 | Contributions, either on an unmodified basis, with Modifications, or 98 | as part of a Larger Work; and 99 | 100 | (b) under Patent Claims of such Contributor to make, use, sell, offer 101 | for sale, have made, import, and otherwise transfer either its 102 | Contributions or its Contributor Version. 103 | 104 | 2.2. Effective Date 105 | 106 | The licenses granted in Section 2.1 with respect to any Contribution 107 | become effective for each Contribution on the date the Contributor first 108 | distributes such Contribution. 109 | 110 | 2.3. Limitations on Grant Scope 111 | 112 | The licenses granted in this Section 2 are the only rights granted under 113 | this License. No additional rights or licenses will be implied from the 114 | distribution or licensing of Covered Software under this License. 115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 116 | Contributor: 117 | 118 | (a) for any code that a Contributor has removed from Covered Software; 119 | or 120 | 121 | (b) for infringements caused by: (i) Your and any other third party's 122 | modifications of Covered Software, or (ii) the combination of its 123 | Contributions with other software (except as part of its Contributor 124 | Version); or 125 | 126 | (c) under Patent Claims infringed by Covered Software in the absence of 127 | its Contributions. 128 | 129 | This License does not grant any rights in the trademarks, service marks, 130 | or logos of any Contributor (except as may be necessary to comply with 131 | the notice requirements in Section 3.4). 132 | 133 | 2.4. Subsequent Licenses 134 | 135 | No Contributor makes additional grants as a result of Your choice to 136 | distribute the Covered Software under a subsequent version of this 137 | License (see Section 10.2) or under the terms of a Secondary License (if 138 | permitted under the terms of Section 3.3). 139 | 140 | 2.5. Representation 141 | 142 | Each Contributor represents that the Contributor believes its 143 | Contributions are its original creation(s) or it has sufficient rights 144 | to grant the rights to its Contributions conveyed by this License. 145 | 146 | 2.6. Fair Use 147 | 148 | This License is not intended to limit any rights You have under 149 | applicable copyright doctrines of fair use, fair dealing, or other 150 | equivalents. 151 | 152 | 2.7. Conditions 153 | 154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 155 | in Section 2.1. 156 | 157 | 3. Responsibilities 158 | ------------------- 159 | 160 | 3.1. Distribution of Source Form 161 | 162 | All distribution of Covered Software in Source Code Form, including any 163 | Modifications that You create or to which You contribute, must be under 164 | the terms of this License. You must inform recipients that the Source 165 | Code Form of the Covered Software is governed by the terms of this 166 | License, and how they can obtain a copy of this License. You may not 167 | attempt to alter or restrict the recipients' rights in the Source Code 168 | Form. 169 | 170 | 3.2. Distribution of Executable Form 171 | 172 | If You distribute Covered Software in Executable Form then: 173 | 174 | (a) such Covered Software must also be made available in Source Code 175 | Form, as described in Section 3.1, and You must inform recipients of 176 | the Executable Form how they can obtain a copy of such Source Code 177 | Form by reasonable means in a timely manner, at a charge no more 178 | than the cost of distribution to the recipient; and 179 | 180 | (b) You may distribute such Executable Form under the terms of this 181 | License, or sublicense it under different terms, provided that the 182 | license for the Executable Form does not attempt to limit or alter 183 | the recipients' rights in the Source Code Form under this License. 184 | 185 | 3.3. Distribution of a Larger Work 186 | 187 | You may create and distribute a Larger Work under terms of Your choice, 188 | provided that You also comply with the requirements of this License for 189 | the Covered Software. If the Larger Work is a combination of Covered 190 | Software with a work governed by one or more Secondary Licenses, and the 191 | Covered Software is not Incompatible With Secondary Licenses, this 192 | License permits You to additionally distribute such Covered Software 193 | under the terms of such Secondary License(s), so that the recipient of 194 | the Larger Work may, at their option, further distribute the Covered 195 | Software under the terms of either this License or such Secondary 196 | License(s). 197 | 198 | 3.4. Notices 199 | 200 | You may not remove or alter the substance of any license notices 201 | (including copyright notices, patent notices, disclaimers of warranty, 202 | or limitations of liability) contained within the Source Code Form of 203 | the Covered Software, except that You may alter any license notices to 204 | the extent required to remedy known factual inaccuracies. 205 | 206 | 3.5. Application of Additional Terms 207 | 208 | You may choose to offer, and to charge a fee for, warranty, support, 209 | indemnity or liability obligations to one or more recipients of Covered 210 | Software. However, You may do so only on Your own behalf, and not on 211 | behalf of any Contributor. You must make it absolutely clear that any 212 | such warranty, support, indemnity, or liability obligation is offered by 213 | You alone, and You hereby agree to indemnify every Contributor for any 214 | liability incurred by such Contributor as a result of warranty, support, 215 | indemnity or liability terms You offer. You may include additional 216 | disclaimers of warranty and limitations of liability specific to any 217 | jurisdiction. 218 | 219 | 4. Inability to Comply Due to Statute or Regulation 220 | --------------------------------------------------- 221 | 222 | If it is impossible for You to comply with any of the terms of this 223 | License with respect to some or all of the Covered Software due to 224 | statute, judicial order, or regulation then You must: (a) comply with 225 | the terms of this License to the maximum extent possible; and (b) 226 | describe the limitations and the code they affect. Such description must 227 | be placed in a text file included with all distributions of the Covered 228 | Software under this License. Except to the extent prohibited by statute 229 | or regulation, such description must be sufficiently detailed for a 230 | recipient of ordinary skill to be able to understand it. 231 | 232 | 5. Termination 233 | -------------- 234 | 235 | 5.1. The rights granted under this License will terminate automatically 236 | if You fail to comply with any of its terms. However, if You become 237 | compliant, then the rights granted under this License from a particular 238 | Contributor are reinstated (a) provisionally, unless and until such 239 | Contributor explicitly and finally terminates Your grants, and (b) on an 240 | ongoing basis, if such Contributor fails to notify You of the 241 | non-compliance by some reasonable means prior to 60 days after You have 242 | come back into compliance. Moreover, Your grants from a particular 243 | Contributor are reinstated on an ongoing basis if such Contributor 244 | notifies You of the non-compliance by some reasonable means, this is the 245 | first time You have received notice of non-compliance with this License 246 | from such Contributor, and You become compliant prior to 30 days after 247 | Your receipt of the notice. 248 | 249 | 5.2. If You initiate litigation against any entity by asserting a patent 250 | infringement claim (excluding declaratory judgment actions, 251 | counter-claims, and cross-claims) alleging that a Contributor Version 252 | directly or indirectly infringes any patent, then the rights granted to 253 | You by any and all Contributors for the Covered Software under Section 254 | 2.1 of this License shall terminate. 255 | 256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 257 | end user license agreements (excluding distributors and resellers) which 258 | have been validly granted by You or Your distributors under this License 259 | prior to termination shall survive termination. 260 | 261 | ************************************************************************ 262 | * * 263 | * 6. Disclaimer of Warranty * 264 | * ------------------------- * 265 | * * 266 | * Covered Software is provided under this License on an "as is" * 267 | * basis, without warranty of any kind, either expressed, implied, or * 268 | * statutory, including, without limitation, warranties that the * 269 | * Covered Software is free of defects, merchantable, fit for a * 270 | * particular purpose or non-infringing. The entire risk as to the * 271 | * quality and performance of the Covered Software is with You. * 272 | * Should any Covered Software prove defective in any respect, You * 273 | * (not any Contributor) assume the cost of any necessary servicing, * 274 | * repair, or correction. This disclaimer of warranty constitutes an * 275 | * essential part of this License. No use of any Covered Software is * 276 | * authorized under this License except under this disclaimer. * 277 | * * 278 | ************************************************************************ 279 | 280 | ************************************************************************ 281 | * * 282 | * 7. Limitation of Liability * 283 | * -------------------------- * 284 | * * 285 | * Under no circumstances and under no legal theory, whether tort * 286 | * (including negligence), contract, or otherwise, shall any * 287 | * Contributor, or anyone who distributes Covered Software as * 288 | * permitted above, be liable to You for any direct, indirect, * 289 | * special, incidental, or consequential damages of any character * 290 | * including, without limitation, damages for lost profits, loss of * 291 | * goodwill, work stoppage, computer failure or malfunction, or any * 292 | * and all other commercial damages or losses, even if such party * 293 | * shall have been informed of the possibility of such damages. This * 294 | * limitation of liability shall not apply to liability for death or * 295 | * personal injury resulting from such party's negligence to the * 296 | * extent applicable law prohibits such limitation. Some * 297 | * jurisdictions do not allow the exclusion or limitation of * 298 | * incidental or consequential damages, so this exclusion and * 299 | * limitation may not apply to You. * 300 | * * 301 | ************************************************************************ 302 | 303 | 8. Litigation 304 | ------------- 305 | 306 | Any litigation relating to this License may be brought only in the 307 | courts of a jurisdiction where the defendant maintains its principal 308 | place of business and such litigation shall be governed by laws of that 309 | jurisdiction, without reference to its conflict-of-law provisions. 310 | Nothing in this Section shall prevent a party's ability to bring 311 | cross-claims or counter-claims. 312 | 313 | 9. Miscellaneous 314 | ---------------- 315 | 316 | This License represents the complete agreement concerning the subject 317 | matter hereof. If any provision of this License is held to be 318 | unenforceable, such provision shall be reformed only to the extent 319 | necessary to make it enforceable. Any law or regulation which provides 320 | that the language of a contract shall be construed against the drafter 321 | shall not be used to construe this License against a Contributor. 322 | 323 | 10. Versions of the License 324 | --------------------------- 325 | 326 | 10.1. New Versions 327 | 328 | Mozilla Foundation is the license steward. Except as provided in Section 329 | 10.3, no one other than the license steward has the right to modify or 330 | publish new versions of this License. Each version will be given a 331 | distinguishing version number. 332 | 333 | 10.2. Effect of New Versions 334 | 335 | You may distribute the Covered Software under the terms of the version 336 | of the License under which You originally received the Covered Software, 337 | or under the terms of any subsequent version published by the license 338 | steward. 339 | 340 | 10.3. Modified Versions 341 | 342 | If you create software not governed by this License, and you want to 343 | create a new license for such software, you may create and use a 344 | modified version of this License if you rename the license and remove 345 | any references to the name of the license steward (except to note that 346 | such modified license differs from this License). 347 | 348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 349 | Licenses 350 | 351 | If You choose to distribute Source Code Form that is Incompatible With 352 | Secondary Licenses under the terms of this version of the License, the 353 | notice described in Exhibit B of this License must be attached. 354 | 355 | Exhibit A - Source Code Form License Notice 356 | ------------------------------------------- 357 | 358 | This Source Code Form is subject to the terms of the Mozilla Public 359 | License, v. 2.0. If a copy of the MPL was not distributed with this 360 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 361 | 362 | If it is not possible or desirable to put the notice in a particular 363 | file, then You may include the notice in a location (such as a LICENSE 364 | file in a relevant directory) where a recipient would be likely to look 365 | for such a notice. 366 | 367 | You may add additional accurate notices of copyright ownership. 368 | 369 | Exhibit B - "Incompatible With Secondary Licenses" Notice 370 | --------------------------------------------------------- 371 | 372 | This Source Code Form is "Incompatible With Secondary Licenses", as 373 | defined by the Mozilla Public License, v. 2.0. 374 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | AUTOMAKE_OPTIONS = foreign 2 | bin_PROGRAMS = sgxtop 3 | sgxtop_SOURCES = sgxtop.c 4 | 5 | install-exec-hook: 6 | (cd ${bindir}; ln -sf sgxtop sgxstat) 7 | 8 | uninstall-hook: 9 | (cd ${bindir}; rm -fv sgxtop; rm -fv sgxstat) 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # sgxtop 2 | 3 | This is Fortanix's SGX monitoring application, built to interoperate 4 | with our SGX driver extensions that export SGX usage information. 5 | 6 | It'll list the enclave count, overall enclave memory use, paging rates, 7 | and the enclaves in use, along with their memory usage and information 8 | about the owning process. 9 | 10 | # Usage 11 | 12 | 13 | ``` sh 14 | $ sgxstat 15 | $ sgxtop 16 | ``` 17 | 18 | # Build 19 | 20 | Build dependencies: autoconf automake m4 21 | 22 | Set up the makefile, etc., from the autotools: 23 | 24 | ``` sh 25 | $ ./maintainer.sh 26 | $ ./configure 27 | $ make 28 | $ sudo make install 29 | ``` 30 | 31 | # Driver Installation 32 | 33 | In order to use this, you'll need to rebuild your isgx driver using 34 | our monitoring extensions. You'll then need to stop the Intel aesm 35 | daemon which is probably running at least one or two enclaves on 36 | your system, then remove the current driver, install the new one, 37 | and restart the aesm daemon. 38 | 39 | Here are the instructions to make it work on Ubuntu 16.04: 40 | 41 | ``` sh 42 | $ git clone https://github.com/fortanix/linux-sgx-driver 43 | $ cd linux-sgx-driver 44 | $ make 45 | $ sudo make install 46 | $ sudo systemctl stop aesmd 47 | $ sudo rmmod isgx 48 | $ sudo insmod isgx.ko 49 | $ sudo systemctl start aesmd 50 | ``` 51 | 52 | # Documentation 53 | 54 | Check the man page for more details: 55 | 56 | ``` sh 57 | $ nroff -man sgxtop.1 58 | ``` 59 | 60 | # Contributing 61 | 62 | We gratefully accept bug reports and contributions from the community. 63 | By participating in this community, you agree to abide by [Code of Conduct](./CODE_OF_CONDUCT.md). 64 | All contributions are covered under the Developer's Certificate of Origin (DCO). 65 | 66 | ## Developer's Certificate of Origin 1.1 67 | 68 | By making a contribution to this project, I certify that: 69 | 70 | (a) The contribution was created in whole or in part by me and I 71 | have the right to submit it under the open source license 72 | indicated in the file; or 73 | 74 | (b) The contribution is based upon previous work that, to the best 75 | of my knowledge, is covered under an appropriate open source 76 | license and I have the right under that license to submit that 77 | work with modifications, whether created in whole or in part 78 | by me, under the same open source license (unless I am 79 | permitted to submit under a different license), as indicated 80 | in the file; or 81 | 82 | (c) The contribution was provided directly to me by some other 83 | person who certified (a), (b) or (c) and I have not modified 84 | it. 85 | 86 | (d) I understand and agree that this project and the contribution 87 | are public and that a record of the contribution (including all 88 | personal information I submit with it, including my sign-off) is 89 | maintained indefinitely and may be redistributed consistent with 90 | this project or the open source license(s) involved. 91 | 92 | # License 93 | 94 | This project is primarily distributed under the terms of the Mozilla Public License (MPL) 2.0, see [LICENSE](./LICENSE) for details. 95 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | # -*- Autoconf -*- 2 | # Process this file with autoconf to produce a configure script. 3 | 4 | AC_PREREQ([2.69]) 5 | AC_INIT([sgxtop], [0.1], [support@fortanix.com]) 6 | AM_INIT_AUTOMAKE 7 | 8 | AC_CONFIG_SRCDIR([sgxtop.c]) 9 | #AC_CONFIG_HEADERS([config.h]) 10 | 11 | # Checks for programs. 12 | : ${CFLAGS="-g -Wall"} 13 | AC_PROG_CC 14 | 15 | # Checks for libraries. 16 | AC_CHECK_LIB([curses], [initscr], , echo -e "=====> Error: libncurses5-dev missing." && exit) 17 | 18 | # Checks for header files. 19 | AC_CHECK_HEADERS([stdlib.h string.h unistd.h]) 20 | 21 | # Checks for typedefs, structures, and compiler characteristics. 22 | AC_CHECK_HEADER_STDBOOL 23 | AC_TYPE_PID_T 24 | AC_TYPE_SIZE_T 25 | 26 | # Checks for library functions. 27 | AC_FUNC_MALLOC 28 | AC_CHECK_FUNCS([clock_gettime memset strdup]) 29 | 30 | AC_CONFIG_FILES([Makefile]) 31 | #AC_CONFIG_SUBDIRS([sgxtop-0.1]) 32 | AC_OUTPUT 33 | -------------------------------------------------------------------------------- /maintainer.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | aclocal # Set up an m4 environment 3 | autoconf # Generate configure from configure.ac 4 | automake --add-missing # Generate Makefile.in from Makefile.am 5 | 6 | #Test configure & build 7 | ./configure 8 | make 9 | 10 | #install sgxtop / sgxstat link 11 | # 12 | # -- uncomment if install is needed. 13 | #make install 14 | #echo "+-----------------------------------------------------------------------------------------------------------------+" 15 | #echo "| sgxtop/sgxstat installed in /usr/local/bin/ (default) or at the path supplied in --prefix option of configure. |" 16 | #echo "| Check if the installed path is in your PATH environment variable. |" 17 | #echo "| $ make uninstall - to remove installed binaries. |" 18 | #echo "+-----------------------------------------------------------------------------------------------------------------+" 19 | 20 | #uninstall will remove sgxtop/sgxstat from --prefix path (default: /usr/local/bin/) 21 | # 22 | # -- uncomment if uninstall is needed. 23 | #make uninstall 24 | 25 | #Cleanup 26 | #files created by auto* tools (m4 files, configure etc) will remain. 27 | # 28 | # -- uncomment if cleanup is needed. 29 | #make clean 30 | -------------------------------------------------------------------------------- /sgxtop.1: -------------------------------------------------------------------------------- 1 | .TH SGXTOP 1 2 | .SH NAME 3 | sgxtop, sgxtop \- display Intel SGX enclaves and statistics 4 | .SH SYNOPSIS 5 | .B sgxtop 6 | .br 7 | .B sgxstat 8 | .SH DESCRIPTION 9 | .\" ragged-right and no hyphenation 10 | .na 11 | .nh 12 | .PP 13 | Intel's SGX extensions allow the creation of userland enclaves, protected 14 | from both kernel and low-level hardware access. 15 | .PP 16 | .B sgxtop 17 | provides a real-time view of the list of enclaves running on the system, 18 | their resource usage, and the overall enclave resources usage. 19 | .B sgxstat 20 | provides a quick one-time display of enclaves and statistics 21 | (essentially a snapshot of 22 | .B sgxtop 23 | output). 24 | .SH OVERVIEW 25 | .PP 26 | .B sgxtop 27 | and 28 | .B sgxstat 29 | start out by displaying the number of enclaves current running, 30 | and the total number of enclaves created since the driver was started. 31 | This is useful for monitoring overall usage -- large numbers of 32 | enclaves created might indicate an issue with enclaves failing. 33 | .PP 34 | Below that, we track page-ins and page-outs per second. 35 | .B sgxstat displays only snapshot information, so does not show this 36 | information. 37 | .PP 38 | Then, the utilities 39 | display the Enclave Page Cache (EPC) memory usage. 40 | The total available enclave memory 41 | is rather limited, as this space is dedicated to SGX, and cannot be used 42 | by the rest of the system, even when no SGX enclaves have been created. 43 | The total memory available is displayed, then the free memory, then the 44 | memory in use, and finally the memory dedicated to the version arrays in 45 | use (each page swapped out records eight bytes of integrity data, so the 46 | more pages are swapped out, the more VA memory is in use). 47 | .PP 48 | Finally, we list the enclaves running on the system. We show the 49 | process id (one process can have multiple enclaves -- for instance, 50 | Intel's aesm service requires two), the requested size (always powers 51 | of two), the actual pages added to the enclave (always less than or 52 | equal to the size), the resident memory dedicated by SGX to the enclave, 53 | and the process command name (shortened by the kernel). 54 | .PP 55 | The resident page count can change dramatically if multiple enclaves are 56 | in use. The SGX driver pages out the oldest memory, so that enclaves 57 | are quickly stripped of their memory, and new enclaves grab lots of 58 | memory. 59 | .SH FILES 60 | .TP 61 | .I /proc/sgx_stats 62 | global sgx statistics 63 | .TP 64 | .I /proc/sgx_enclaves 65 | list of enclaves with per-enclave statistics 66 | .SH AUTHOR 67 | Kevin Lahey 68 | -------------------------------------------------------------------------------- /sgxtop.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) Fortanix, Inc. 2 | * 3 | * This Source Code Form is subject to the terms of the Mozilla Public 4 | * License, v. 2.0. If a copy of the MPL was not distributed with this 5 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #define SGX_STATS "/proc/sgx_stats" 21 | #define SGX_ENCLAVES "/proc/sgx_enclaves" 22 | 23 | /* The number of hash buckets to create, not the limit on enclaves */ 24 | #define ENCLAVE_BUCKETS 101 25 | 26 | struct stats { 27 | unsigned int enclaves_created; 28 | unsigned int enclaves_released; 29 | unsigned long pages_added; 30 | unsigned long pageins; 31 | unsigned long pageouts; 32 | unsigned int enclave_pages; 33 | unsigned int va_pages; 34 | unsigned int free_pages; 35 | struct timespec readtime; 36 | }; 37 | 38 | struct enclave { 39 | pid_t pid; 40 | unsigned int id; 41 | unsigned long size; 42 | unsigned long eadd_cnt; 43 | unsigned long resident; 44 | }; 45 | 46 | struct enclave_entry { 47 | struct enclave enclave; 48 | char *command; /* process command line */ 49 | LIST_ENTRY(enclave_entry) state_entry[2]; 50 | LIST_ENTRY(enclave_entry) hash_entry; 51 | }; 52 | 53 | static int pid_width = 10; /* pick a really big size and adjust down */ 54 | static bool sgxtop = true; /* sgxtop (continuous reporting) or sgxstat 55 | * (one shot) */ 56 | 57 | /* 58 | * Keep an old and a new list of enclaves, and a hash table. 59 | * Look 'em up quickly in the hash table as we read them. 60 | * Put them in the new list as they are read. Remove the old 61 | * list when we've read all of the new enclaves. 62 | */ 63 | 64 | LIST_HEAD(enclave_head, enclave_entry); 65 | 66 | struct enclaves { 67 | unsigned int count; 68 | unsigned int state; 69 | struct enclave_head *hash_table; 70 | size_t hash_table_size; 71 | struct enclave_head state_list[2]; 72 | struct timespec readtime; 73 | }; 74 | 75 | #define NSEC_PER_SEC 1000000000 76 | 77 | void do_init() 78 | { 79 | /* Some systems allow larger PIDs than the default of 32767. 80 | * Ensure that the fields look right for them. */ 81 | 82 | FILE *fp = fopen("/proc/sys/kernel/pid_max", "ro"); 83 | 84 | if (fp) { 85 | pid_width = 0; 86 | while (fgetc(fp) != EOF) { 87 | pid_width++; 88 | } 89 | if (pid_width > 0) { 90 | pid_width--; 91 | } 92 | } 93 | fclose(fp); 94 | } 95 | 96 | long int timespec_diff(struct timespec *later, struct timespec *earlier) 97 | { 98 | long int diff = (later->tv_sec - earlier->tv_sec) * NSEC_PER_SEC; 99 | 100 | diff += later->tv_nsec - earlier->tv_nsec; 101 | assert(diff >= 0); 102 | 103 | return diff; 104 | } 105 | 106 | int sleep_til(struct timespec *when) 107 | { 108 | int rc; 109 | while ((rc = clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, 110 | when, NULL)) != 0) { 111 | if (rc != EINTR) { 112 | fprintf(stderr, 113 | "clock_nanosleep(2) returned %d, errno %d\n", 114 | rc, errno); 115 | return rc; 116 | } 117 | } 118 | return rc; 119 | } 120 | 121 | int stats_read(struct stats *stats) 122 | { 123 | FILE *fp; 124 | 125 | if (!(fp = fopen(SGX_STATS, "ro"))) { 126 | fprintf(stderr, "failed to read %s\n", SGX_STATS); 127 | return -1; 128 | } 129 | 130 | int r = fscanf(fp, "%u %u %lu %lu %lu %u %u %u\n", 131 | &stats->enclaves_created, &stats->enclaves_released, 132 | &stats->pages_added, &stats->pageins, &stats->pageouts, 133 | &stats->enclave_pages, &stats->va_pages, 134 | &stats->free_pages); 135 | fclose(fp); 136 | if (r != 8) { 137 | fprintf(stderr, "expect to read %d entries from %s, got %d\n", 138 | 8, SGX_STATS, r); 139 | return -1; 140 | } 141 | 142 | r = clock_gettime(CLOCK_MONOTONIC, &stats->readtime); 143 | if (r) { 144 | fprintf(stderr, "clock_gettime(3) returned %d, errno %d\n", 145 | r, errno); 146 | return r; 147 | } 148 | 149 | return 0; 150 | } 151 | 152 | 153 | void stats_report(struct stats *old, struct stats *new) 154 | { 155 | char enclave_str[80]; 156 | 157 | if (sgxtop) 158 | mvprintw(0, 0, "Enclaves running: %3u Total enclaves created: %u", 159 | new->enclaves_created - new->enclaves_released, 160 | new->enclaves_created); 161 | else 162 | printf("Enclaves running: %3u Total enclaves created: %u\n", 163 | new->enclaves_created - new->enclaves_released, 164 | new->enclaves_created); 165 | 166 | 167 | snprintf(enclave_str, sizeof(enclave_str), "%uK/%uK/%uK", 168 | new->va_pages * 4, 169 | (new->enclave_pages - new->free_pages) * 4, 170 | new->enclave_pages * 4); 171 | if (sgxtop) 172 | mvprintw(2, 0, "EPC mem: %11uK free: %11uK used: %11uK VA: %11uK", 173 | new->enclave_pages * 4, 174 | new->free_pages * 4, 175 | (new->enclave_pages - new->free_pages) * 4, 176 | new->va_pages * 4); 177 | else 178 | printf("EPC mem: %11uK free: %11uK used: %11uK VA: %11uK\n\n", 179 | new->enclave_pages * 4, new->free_pages * 4, 180 | (new->enclave_pages - new->free_pages) * 4, 181 | new->va_pages * 4); 182 | 183 | /* sgxstats doesn't report time-depended data */ 184 | if (!sgxtop) 185 | return; 186 | 187 | long int time_diff = timespec_diff(&new->readtime, &old->readtime); 188 | 189 | long unsigned pageins = new->pageins - old->pageins; 190 | long unsigned pageouts = new->pageouts - old->pageouts; 191 | if (time_diff != 0) { 192 | pageins = 4 * pageins * NSEC_PER_SEC / time_diff; 193 | pageouts = 4 * pageouts * NSEC_PER_SEC / time_diff; 194 | } else { 195 | pageins = 0; 196 | pageouts = 0; 197 | } 198 | 199 | mvprintw(1, 0, 200 | "EPC paging per second, in: %10luK out: %10luK", 201 | pageins, pageouts); 202 | refresh(); 203 | } 204 | 205 | char *pid_read_command(pid_t pid) 206 | { 207 | FILE *fp; 208 | char filename[sizeof("/proc//comm") + pid_width]; 209 | char command[TS_COMM_LEN]; 210 | char *result; 211 | 212 | snprintf(filename, sizeof(filename), "/proc/%d/comm", pid); 213 | fp = fopen(filename, "ro"); 214 | if (!fp) 215 | return NULL; 216 | 217 | result = fgets(command, sizeof(command), fp); 218 | fclose(fp); 219 | 220 | if (result) 221 | result = strdup(result); 222 | 223 | return result; 224 | } 225 | 226 | int enclave_read(FILE *fp, struct enclave *enclave) 227 | { 228 | int r = fscanf(fp, "%d %u %lu %lu %lu", 229 | &enclave->pid, &enclave->id, 230 | &enclave->size, &enclave->eadd_cnt, 231 | &enclave->resident); 232 | if (r != 5) 233 | return -1; 234 | 235 | return 0; 236 | } 237 | 238 | void enclave_update(struct enclave_entry *o, struct enclave *n, unsigned which) 239 | { 240 | assert(o->enclave.id == n->id && o->enclave.pid == n->pid); 241 | o->enclave = *n; 242 | } 243 | 244 | void enclave_delete(struct enclaves *enclaves, struct enclave_entry *e, 245 | unsigned which) 246 | { 247 | if (e->command) { 248 | free(e->command); 249 | } 250 | memset(e, 0, sizeof(struct enclave_entry)); 251 | free(e); 252 | } 253 | 254 | size_t hash_func(struct enclaves *e, unsigned int id) 255 | { 256 | return id % e->hash_table_size; 257 | } 258 | 259 | struct enclaves *enclaves_create(size_t n) 260 | { 261 | struct enclaves *e = calloc(1, sizeof(struct enclaves)); 262 | if (!e) 263 | return NULL; 264 | 265 | e->hash_table_size = n; 266 | e->hash_table = malloc(sizeof(struct enclave_head) * n); 267 | if (!e->hash_table) { 268 | free(e); 269 | return NULL; 270 | } 271 | 272 | for (int i = 0; i < n; i++) 273 | LIST_INIT(&e->hash_table[i]); 274 | 275 | e->state = 0; 276 | LIST_INIT(&e->state_list[0]); 277 | LIST_INIT(&e->state_list[1]); 278 | 279 | return e; 280 | } 281 | 282 | struct enclave_entry *enclaves_find(struct enclaves *enclaves, unsigned int id) 283 | { 284 | size_t bucket = hash_func(enclaves, id); 285 | struct enclave_entry *e = LIST_FIRST(&enclaves->hash_table[bucket]); 286 | 287 | while (e) { 288 | if (e->enclave.id == id) 289 | return e; 290 | e = LIST_NEXT(e, hash_entry); 291 | } 292 | return NULL; 293 | } 294 | 295 | void enclaves_insert(struct enclaves *enclaves, struct enclave_entry *e) 296 | { 297 | size_t bucket = hash_func(enclaves, e->enclave.id); 298 | LIST_INSERT_HEAD(&enclaves->hash_table[bucket], e, hash_entry); 299 | } 300 | 301 | void enclaves_check_list(struct enclaves *enclaves) 302 | { 303 | struct enclave_entry *e; 304 | int count = 0; 305 | 306 | LIST_FOREACH(e, &enclaves->state_list[enclaves->state], 307 | state_entry[enclaves->state]) { 308 | assert(++count <= enclaves->count); 309 | } 310 | } 311 | 312 | void enclaves_read(struct enclaves *enclaves) 313 | { 314 | /* 315 | * We track old and new entries, and have to swap which list 316 | * represents new. 317 | */ 318 | 319 | unsigned old_state = enclaves->state; 320 | unsigned new_state = !enclaves->state; 321 | 322 | enclaves->state = new_state; 323 | assert(enclaves->state_list[new_state].lh_first == NULL); 324 | 325 | FILE *fp = fopen(SGX_ENCLAVES, "ro"); 326 | if (!fp) { 327 | fprintf(stderr, "Couldn't open %s\n", SGX_ENCLAVES); 328 | exit(-1); 329 | } 330 | 331 | struct enclave enclave; 332 | struct enclave_entry *e; 333 | 334 | enclaves->count = 0; 335 | while (!enclave_read(fp, &enclave)) { 336 | enclaves->count++; 337 | 338 | if ((e = enclaves_find(enclaves, enclave.id)) != NULL) { 339 | enclave_update(e, &enclave, old_state); 340 | /* 341 | * Since this enclave was in the hash table, 342 | * it was pre-existing, and should be removed 343 | * from the list of old enclaves. 344 | */ 345 | LIST_REMOVE(e, state_entry[old_state]); 346 | } else { 347 | e = calloc(1, sizeof(struct enclave_entry)); 348 | if (!e) { 349 | fprintf(stderr, "malloc failed!\n"); 350 | exit(1); 351 | } 352 | 353 | e->enclave = enclave; 354 | e->command = pid_read_command(e->enclave.pid); 355 | 356 | enclaves_insert(enclaves, e); 357 | } 358 | /* Insert everybody in the list of current enclaves */ 359 | LIST_INSERT_HEAD(&enclaves->state_list[new_state], 360 | e, state_entry[new_state]); 361 | } 362 | fclose(fp); 363 | 364 | int r = clock_gettime(CLOCK_MONOTONIC, &enclaves->readtime); 365 | if (r) { 366 | fprintf(stderr, "Clock failed to read!\n"); 367 | exit(-1); 368 | } 369 | 370 | /* Iterate over the table of old enclaves and remove each one. */ 371 | while (!LIST_EMPTY(&enclaves->state_list[old_state])) { 372 | e = LIST_FIRST(&enclaves->state_list[old_state]); 373 | LIST_REMOVE(e, state_entry[old_state]); 374 | LIST_REMOVE(e, hash_entry); 375 | enclave_delete(enclaves, e, old_state); 376 | } 377 | assert(enclaves->state_list[old_state].lh_first == NULL); 378 | } 379 | 380 | int enclave_compar(const void *fv, const void *sv) 381 | { 382 | const struct enclave **f = (const struct enclave **) fv; 383 | const struct enclave **s = (const struct enclave **) sv; 384 | 385 | /* 386 | * Simple sort by resident set size and ID; note that we 387 | * have to be careful about signed arithmetic. And invert 388 | * the check to put the most active and earliest enclaves 389 | * first. 390 | */ 391 | long long int rc = (long long int) (*f)->resident - 392 | (long long int) (*s)->resident; 393 | 394 | if (rc == 0) 395 | rc = (long long) (*f)->id - (long long) (*s)->id; 396 | 397 | if (rc < 1) 398 | return 1; 399 | else if (rc > 1) 400 | return -1; 401 | else 402 | return 0; 403 | } 404 | 405 | void enclaves_report(struct enclaves *enclaves) 406 | { 407 | struct enclave_entry *list[enclaves->count]; 408 | struct enclave_entry *e; 409 | unsigned line = 4; 410 | size_t count = 0; 411 | static unsigned last_lines; 412 | 413 | if (sgxtop) 414 | mvprintw(line++, 0, "%*s %10s %11s %11s %11s %10s", pid_width, 415 | "PID", "ID", "Size", "EADDs", "Resident", "Command"); 416 | else 417 | printf("%*s %10s %11s %11s %11s %10s\n", pid_width, 418 | "PID", "ID", "Size", "EADDs", "Resident", "Command"); 419 | LIST_FOREACH(e, &enclaves->state_list[enclaves->state], 420 | state_entry[enclaves->state]) { 421 | assert(count < enclaves->count); 422 | list[count++] = e; 423 | } 424 | 425 | assert(count == enclaves->count); 426 | 427 | qsort(list, enclaves->count, sizeof(struct enclave_entry *), 428 | enclave_compar); 429 | 430 | for (count = 0; count < enclaves->count; 431 | count++, line++) { 432 | assert(line <= enclaves->count + 4 /* initial count */); 433 | e = list[count]; 434 | if (sgxtop) 435 | mvprintw(line, 0, "%*d %10u %10luK %10luK %10luK %s", 436 | pid_width, e->enclave.pid, e->enclave.id, 437 | e->enclave.size / 1024, 438 | e->enclave.eadd_cnt * 4, 439 | e->enclave.resident * 4, 440 | e->command ? e->command : ""); 441 | else 442 | printf("%*d %10u %10luK %10luK %10luK %s", 443 | pid_width, e->enclave.pid, e->enclave.id, 444 | e->enclave.size / 1024, e->enclave.eadd_cnt * 4, 445 | e->enclave.resident * 4, 446 | e->command ? e->command : ""); 447 | if (sgxtop && line >= LINES) 448 | break; 449 | } 450 | 451 | if (!sgxtop) 452 | return; 453 | 454 | /* Clear any leftover lines from the last display */ 455 | int current_lines = line; 456 | while (last_lines > line) { 457 | move(line++, 0); 458 | clrtoeol(); 459 | } 460 | refresh(); 461 | last_lines = current_lines; 462 | } 463 | 464 | int main(int argc, char **argv) 465 | { 466 | struct stats old, new; 467 | struct enclaves *enclaves = NULL; 468 | 469 | enclaves = enclaves_create(ENCLAVE_BUCKETS); 470 | if (!enclaves) { 471 | fprintf(stderr, "failed to create list of enclaves\n"); 472 | exit(-1); 473 | } 474 | 475 | do_init(); 476 | 477 | if (stats_read(&new)) { 478 | exit(-1); 479 | } 480 | 481 | 482 | /* 483 | * Somewhat hackily let this executable run as either 484 | * sgxtop (with continuous, top-style updates to the screen), 485 | * or sgxstat (with a one-shot report). 486 | */ 487 | 488 | char *command = argv[0] + strlen(argv[0]) - 1; 489 | while (command > argv[0] && isalpha(*command)) 490 | command--; 491 | if (command != argv[0]) 492 | command++; 493 | 494 | if (strcmp(command, "sgxstat") == 0) { 495 | sgxtop = false; 496 | enclaves_read(enclaves); 497 | stats_report(NULL, &new); 498 | enclaves_report(enclaves); 499 | return 0; 500 | } 501 | 502 | /* Fire up curses. */ 503 | 504 | initscr(); 505 | cbreak(); 506 | noecho(); 507 | curs_set(0); 508 | clear(); 509 | 510 | struct timespec wait = new.readtime; 511 | while (1) { 512 | old = new; 513 | wait.tv_sec++; 514 | if (sleep_til(&wait)) 515 | exit(-1); 516 | if (stats_read(&new)) 517 | exit(-1); 518 | enclaves_read(enclaves); 519 | #ifdef DEBUG 520 | enclaves_check_list(enclaves); 521 | #endif 522 | stats_report(&old, &new); 523 | enclaves_report(enclaves); 524 | /* Accept input, for instance for a redraw? */ 525 | } 526 | endwin(); // Not reached 527 | return 0; 528 | } 529 | --------------------------------------------------------------------------------