aboutsummaryrefslogtreecommitdiff
path: root/catapult/telemetry/build/linux_setup_msr.py
blob: a61828b0d413fab9e4495ee364addf48fb35bcce (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#!/usr/bin/env python
#
# Copyright 2015 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
#
# This is a script developers can use to set-up their workstation to let
# Telemetry read the CPU's Model Specific Registers in order to get power
# measurements. It can check if reading from MSRs is possible as any user, but
# must run as root to make changes. Not all changes are sticky, so one has to
# re-run this script after each reboot.
#
# This script is currently Debian/Ubuntu specific.

import os
import subprocess
import sys

MSR_DEV_FILE_PATH = '/dev/cpu/0/msr'
RDMSR_PATH = '/usr/sbin/rdmsr'

def _Usage(prog_name):
  """Print a help message."""
  print 'Run "%s" as a regular user to check if reading from the MSR ' \
      'is possible.' % prog_name
  print 'Run "%s enable" as root to automatically set up reading from ' \
      'the MSR.' % prog_name


def _CheckMsrKernelModule():
  """Return whether the 'msr' kernel module is loaded."""
  proc = subprocess.Popen('/sbin/lsmod', stdout=subprocess.PIPE)
  stdout = proc.communicate()[0]
  ret = proc.wait()
  if ret != 0:
    raise OSError('lsmod failed')

  if not any([line.startswith('msr ') for line in stdout.splitlines()]):
    print 'Error: MSR module not loaded.'
    return False

  return True


def _CheckMsrDevNodes():
  """Check whether the MSR /dev files have the right permissions."""
  if not os.path.exists(MSR_DEV_FILE_PATH):
    print 'Error: %s does not exist.' % MSR_DEV_FILE_PATH
    return False

  if not os.access(MSR_DEV_FILE_PATH, os.R_OK):
    print 'Error: Cannot read from %s' % MSR_DEV_FILE_PATH
    return False

  return True


def _CheckRdmsr():
  """Check and make sure /usr/sbin/rdmsr is set up correctly."""
  if not os.access(RDMSR_PATH, os.X_OK):
    print 'Error: %s missing or not executable.' % RDMSR_PATH
    return False

  proc = subprocess.Popen(['/sbin/getcap', RDMSR_PATH], stdout=subprocess.PIPE)
  stdout = proc.communicate()[0]
  ret = proc.wait()
  if ret != 0:
    raise OSError('getcap failed')

  if not 'cap_sys_rawio+ep' in stdout:
    print 'Error: /usr/sbin/rdmsr needs RAWIO capability.'
    return False

  return True


def _RunAllChecks():
  """Check to make sure it is possible to read from the MSRs."""
  if os.geteuid() == 0:
    print 'WARNING: Running as root, msr permission check likely inaccurate.'

  has_dev_node = _CheckMsrDevNodes() if _CheckMsrKernelModule() else False
  has_rdmsr = _CheckRdmsr()
  return has_dev_node and has_rdmsr


def _EnableMsr(prog_name):
  """Do all the setup needed to pass _RunAllChecks().

  Needs to run as root."""
  if os.geteuid() != 0:
    print 'Error: Must run "%s enable" as root.' % prog_name
    return False

  print 'Loading msr kernel module.'
  ret = subprocess.call(['/sbin/modprobe', 'msr'])
  if ret != 0:
    print 'Error: Cannot load msr module.'
    return False

  print 'Running chmod on %s.' % MSR_DEV_FILE_PATH
  ret = subprocess.call(['/bin/chmod', 'a+r', MSR_DEV_FILE_PATH])
  if ret != 0:
    print 'Error: Cannot chmod %s.' % MSR_DEV_FILE_PATH
    return False

  if not os.access(RDMSR_PATH, os.F_OK):
    print 'Need to install the msr-tools package.'
    ret = subprocess.call(['/usr/bin/apt-get', 'install', '-y', 'msr-tools'])
    if ret != 0:
      print 'Error: Did not successfully install msr-tools.'
      return False

  print 'Running setcap on %s.' % RDMSR_PATH
  ret = subprocess.call(['/sbin/setcap', 'cap_sys_rawio+ep', RDMSR_PATH])
  if ret != 0:
    print 'Error: Cannot give /usr/sbin/rdmsr RAWIO capability.'
    return False

  return True


def main(prog_name, argv):
  if len(argv) == 0:
    if _RunAllChecks():
      print 'Check succeeded'
      return 0

    print 'Check failed, try running "%s enable" as root to fix.' % prog_name
    return 1

  if len(argv) == 1:
    if argv[0] == 'enable':
      return 0 if _EnableMsr(prog_name) else 1

    print 'Error: Unknown sub-command %s' % argv[0]
    _Usage(prog_name)
    return 1

  print 'Error: Bad number of arguments'
  _Usage(prog_name)
  return 1


if '__main__' == __name__:
  sys.exit(main(os.path.basename(sys.argv[0]), sys.argv[1:]))