linux_setup_msr.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. #!/usr/bin/env python
  2. #
  3. # Copyright 2015 The Chromium Authors. All rights reserved.
  4. # Use of this source code is governed by a BSD-style license that can be
  5. # found in the LICENSE file.
  6. #
  7. # This is a script developers can use to set-up their workstation to let
  8. # Telemetry read the CPU's Model Specific Registers in order to get power
  9. # measurements. It can check if reading from MSRs is possible as any user, but
  10. # must run as root to make changes. Not all changes are sticky, so one has to
  11. # re-run this script after each reboot.
  12. #
  13. # This script is currently Debian/Ubuntu specific.
  14. import os
  15. import subprocess
  16. import sys
  17. MSR_DEV_FILE_PATH = '/dev/cpu/0/msr'
  18. RDMSR_PATH = '/usr/sbin/rdmsr'
  19. def _Usage(prog_name):
  20. """Print a help message."""
  21. print 'Run "%s" as a regular user to check if reading from the MSR ' \
  22. 'is possible.' % prog_name
  23. print 'Run "%s enable" as root to automatically set up reading from ' \
  24. 'the MSR.' % prog_name
  25. def _CheckMsrKernelModule():
  26. """Return whether the 'msr' kernel module is loaded."""
  27. proc = subprocess.Popen('/sbin/lsmod', stdout=subprocess.PIPE)
  28. stdout = proc.communicate()[0]
  29. ret = proc.wait()
  30. if ret != 0:
  31. raise OSError('lsmod failed')
  32. if not any([line.startswith('msr ') for line in stdout.splitlines()]):
  33. print 'Error: MSR module not loaded.'
  34. return False
  35. return True
  36. def _CheckMsrDevNodes():
  37. """Check whether the MSR /dev files have the right permissions."""
  38. if not os.path.exists(MSR_DEV_FILE_PATH):
  39. print 'Error: %s does not exist.' % MSR_DEV_FILE_PATH
  40. return False
  41. if not os.access(MSR_DEV_FILE_PATH, os.R_OK):
  42. print 'Error: Cannot read from %s' % MSR_DEV_FILE_PATH
  43. return False
  44. return True
  45. def _CheckRdmsr():
  46. """Check and make sure /usr/sbin/rdmsr is set up correctly."""
  47. if not os.access(RDMSR_PATH, os.X_OK):
  48. print 'Error: %s missing or not executable.' % RDMSR_PATH
  49. return False
  50. proc = subprocess.Popen(['/sbin/getcap', RDMSR_PATH], stdout=subprocess.PIPE)
  51. stdout = proc.communicate()[0]
  52. ret = proc.wait()
  53. if ret != 0:
  54. raise OSError('getcap failed')
  55. if not 'cap_sys_rawio+ep' in stdout:
  56. print 'Error: /usr/sbin/rdmsr needs RAWIO capability.'
  57. return False
  58. return True
  59. def _RunAllChecks():
  60. """Check to make sure it is possible to read from the MSRs."""
  61. if os.geteuid() == 0:
  62. print 'WARNING: Running as root, msr permission check likely inaccurate.'
  63. has_dev_node = _CheckMsrDevNodes() if _CheckMsrKernelModule() else False
  64. has_rdmsr = _CheckRdmsr()
  65. return has_dev_node and has_rdmsr
  66. def _EnableMsr(prog_name):
  67. """Do all the setup needed to pass _RunAllChecks().
  68. Needs to run as root."""
  69. if os.geteuid() != 0:
  70. print 'Error: Must run "%s enable" as root.' % prog_name
  71. return False
  72. print 'Loading msr kernel module.'
  73. ret = subprocess.call(['/sbin/modprobe', 'msr'])
  74. if ret != 0:
  75. print 'Error: Cannot load msr module.'
  76. return False
  77. print 'Running chmod on %s.' % MSR_DEV_FILE_PATH
  78. ret = subprocess.call(['/bin/chmod', 'a+r', MSR_DEV_FILE_PATH])
  79. if ret != 0:
  80. print 'Error: Cannot chmod %s.' % MSR_DEV_FILE_PATH
  81. return False
  82. if not os.access(RDMSR_PATH, os.F_OK):
  83. print 'Need to install the msr-tools package.'
  84. ret = subprocess.call(['/usr/bin/apt-get', 'install', '-y', 'msr-tools'])
  85. if ret != 0:
  86. print 'Error: Did not successfully install msr-tools.'
  87. return False
  88. print 'Running setcap on %s.' % RDMSR_PATH
  89. ret = subprocess.call(['/sbin/setcap', 'cap_sys_rawio+ep', RDMSR_PATH])
  90. if ret != 0:
  91. print 'Error: Cannot give /usr/sbin/rdmsr RAWIO capability.'
  92. return False
  93. return True
  94. def main(prog_name, argv):
  95. if len(argv) == 0:
  96. if _RunAllChecks():
  97. print 'Check succeeded'
  98. return 0
  99. print 'Check failed, try running "%s enable" as root to fix.' % prog_name
  100. return 1
  101. if len(argv) == 1:
  102. if argv[0] == 'enable':
  103. return 0 if _EnableMsr(prog_name) else 1
  104. print 'Error: Unknown sub-command %s' % argv[0]
  105. _Usage(prog_name)
  106. return 1
  107. print 'Error: Bad number of arguments'
  108. _Usage(prog_name)
  109. return 1
  110. if '__main__' == __name__:
  111. sys.exit(main(os.path.basename(sys.argv[0]), sys.argv[1:]))