Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / tools / telemetry / telemetry / core / platform / power_monitor / msr_power_monitor.py
1 # Copyright 2014 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 import logging
6 import platform
7 import re
8
9 from telemetry import decorators
10 from telemetry.core.platform import power_monitor
11
12
13 MSR_RAPL_POWER_UNIT = 0x606
14 MSR_PKG_ENERGY_STATUS = 0x611  # Whole package
15 MSR_PP0_ENERGY_STATUS = 0x639  # Core
16 MSR_PP1_ENERGY_STATUS = 0x641  # Uncore
17 MSR_DRAM_ENERGY_STATUS = 0x619
18 IA32_PACKAGE_THERM_STATUS = 0x1b1
19 IA32_TEMPERATURE_TARGET = 0x1a2
20
21
22 def _JoulesToMilliwattHours(value_joules):
23   return value_joules * 1000 / 3600.
24
25
26 def _IsSandyBridgeOrLater(vendor, family, model):
27   # Model numbers from:
28   # https://software.intel.com/en-us/articles/intel-architecture-and- \
29   # processor-identification-with-cpuid-model-and-family-numbers
30   # http://www.speedtraq.com
31   return ('Intel' in vendor and family == 6 and
32           (model in (0x2A, 0x2D) or model >= 0x30))
33
34
35 def _LinuxCheckCPU():
36   vendor = None
37   family = None
38   model = None
39   cpuinfo = open('/proc/cpuinfo').read().splitlines()
40   for line in cpuinfo:
41     if vendor and family and model:
42       break
43     if line.startswith('vendor_id'):
44       vendor = line.split('\t')[1]
45     elif line.startswith('cpu family'):
46       family = int(line.split(' ')[2])
47     elif line.startswith('model\t\t'):
48       model = int(line.split(' ')[1])
49   if not _IsSandyBridgeOrLater(vendor, family, model):
50     logging.info('Cannot monitor power: pre-Sandy Bridge CPU.')
51     return False
52   return True
53
54
55 class MsrPowerMonitor(power_monitor.PowerMonitor):
56   def __init__(self, backend):
57     super(MsrPowerMonitor, self).__init__()
58     self._backend = backend
59     self._start_energy_j = None
60     self._start_temp_c = None
61
62   def CanMonitorPower(self):
63     if self._backend.GetOSName() == 'win':
64       return self._WinCanMonitorPower()
65     elif self._backend.GetOSName() == 'linux':
66       return self._LinuxCanMonitorPower()
67     return False
68
69   def StartMonitoringPower(self, browser):
70     assert self._start_energy_j is None and self._start_temp_c is None, (
71         'Called StartMonitoringPower() twice.')
72     self._start_energy_j = self._PackageEnergyJoules()
73     self._start_temp_c = self._TemperatureCelsius()
74
75   def StopMonitoringPower(self):
76     assert not(self._start_energy_j is None or self._start_temp_c is None), (
77         'Called StopMonitoringPower() before StartMonitoringPower().')
78
79     energy_consumption_j = self._PackageEnergyJoules() - self._start_energy_j
80     average_temp_c = (self._TemperatureCelsius() + self._start_temp_c) / 2.
81     if energy_consumption_j < 0:  # Correct overflow.
82       # The energy portion of the MSR is 4 bytes.
83       energy_consumption_j += 2 ** 32 * self._EnergyMultiplier()
84
85     self._start_energy_j = None
86     self._start_temp_c = None
87
88     return {
89         'identifier': 'msr',
90         'energy_consumption_mwh': _JoulesToMilliwattHours(energy_consumption_j),
91         'component_utilization': {
92             'whole_package': {
93                 'average_temperature_c': average_temp_c,
94             },
95         },
96     }
97
98   @decorators.Cache
99   def _EnergyMultiplier(self):
100     return 0.5 ** self._backend.ReadMsr(MSR_RAPL_POWER_UNIT, 8, 5)
101
102   def _PackageEnergyJoules(self):
103     return (self._backend.ReadMsr(MSR_PKG_ENERGY_STATUS, 0, 32) *
104             self._EnergyMultiplier())
105
106   def _TemperatureCelsius(self):
107     tcc_activation_temp = self._backend.ReadMsr(IA32_TEMPERATURE_TARGET, 16, 7)
108     if tcc_activation_temp <= 0:
109       tcc_activation_temp = 105
110     package_temp_headroom = self._backend.ReadMsr(
111         IA32_PACKAGE_THERM_STATUS, 16, 7)
112     return tcc_activation_temp - package_temp_headroom
113
114   def _CheckMSRs(self):
115     try:
116       if self._PackageEnergyJoules() <= 0:
117         logging.info('Cannot monitor power: no energy readings.')
118         return False
119
120       if self._TemperatureCelsius() <= 0:
121         logging.info('Cannot monitor power: no temperature readings.')
122         return False
123     except OSError as e:
124       logging.info('Cannot monitor power: %s' % e)
125       return False
126     return True
127
128   def _WinCanMonitorPower(self):
129     family, model = map(int, re.match('.+ Family ([0-9]+) Model ([0-9]+)',
130                         platform.processor()).groups())
131     if not _IsSandyBridgeOrLater(platform.processor(), family, model):
132       logging.info('Cannot monitor power: pre-Sandy Bridge CPU.')
133       return False
134
135     return self._CheckMSRs()
136
137   def _LinuxCanMonitorPower(self):
138     if not _LinuxCheckCPU():
139       return False
140     return self._CheckMSRs()