• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Lint as: python2, python3
2# Copyright (c) 2010 The Chromium Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6# Note: this test has been ported to hardware.MemCheck Tast test.
7# Any change made here should be applied to the Tast test as well.
8
9__author__ = 'kdlucas@chromium.org (Kelly Lucas)'
10
11import logging
12import re
13
14from autotest_lib.client.bin import utils
15from autotest_lib.client.bin import test
16from autotest_lib.client.common_lib import error
17
18
19class platform_MemCheck(test.test):
20    """
21    Verify memory usage looks correct.
22    """
23    version = 1
24    swap_disksize_file = '/sys/block/zram0/disksize'
25
26    def run_once(self):
27        errors = 0
28        keyval = dict()
29        # The total memory will shrink if the system bios grabs more of the
30        # reserved memory. We derived the value below by giving a small
31        # cushion to allow for more system BIOS usage of ram. The memref value
32        # is driven by the supported netbook model with the least amount of
33        # total memory.  ARM and x86 values differ considerably.
34        cpuType = utils.get_cpu_arch()
35        memref = 986392
36        vmemref = 102400
37        if cpuType == "arm":
38            memref = 700000
39            vmemref = 210000
40
41        os_reserve_min = 600000
42        os_reserve_ratio = 0.04
43
44        # size reported in /sys/block/zram0/disksize is in byte
45        swapref = int(utils.read_one_line(self.swap_disksize_file)) / 1024
46
47        less_refs = ['MemTotal', 'VmallocTotal']
48        approx_refs = ['SwapTotal']
49
50        # read physical HW size from mosys and adjust memref if need
51        cmd = 'mosys memory spd print geometry -s size_mb'
52        phy_size_run = utils.run(cmd)
53        logging.info('Ran command: `%s`', cmd)
54        logging.info('Output: "%s"', phy_size_run.stdout)
55        phy_size = 0
56        for line in phy_size_run.stdout.split():
57            phy_size += int(line)
58        # memref is in KB but phy_size is in MB
59        phy_size *= 1024
60        keyval['PhysicalSize'] = phy_size
61
62        # scale OS reserve size with memory size
63        os_reserve = max(os_reserve_min, int(phy_size * os_reserve_ratio))
64        memref = max(memref, phy_size - os_reserve)
65
66        ref = {'MemTotal': memref,
67               'SwapTotal': swapref,
68               'VmallocTotal': vmemref,
69              }
70
71        board = utils.get_board()
72        logging.info('board: %s, phy_size: %d memref: %d',
73                      board, phy_size, memref)
74
75        error_list = []
76
77        for k in ref:
78            value = utils.read_from_meminfo(k)
79            keyval[k] = value
80            if k in less_refs:
81                if value < ref[k]:
82                    logging.warning('%s is %d', k, value)
83                    logging.warning('%s should be at least %d', k, ref[k])
84                    errors += 1
85                    error_list += [k]
86            elif k in approx_refs:
87                if value < ref[k] * 0.9 or ref[k] * 1.1 < value:
88                    logging.warning('%s is %d', k, value)
89                    logging.warning('%s should be within 10%% of %d', k, ref[k])
90                    errors += 1
91                    error_list += [k]
92
93        # Log memory type
94        cmd = 'mosys memory spd print type -s dram | head -1'
95        # Example
96        # 0 | LPDDR4
97        mem_type = utils.run(cmd).stdout.strip()
98        logging.info('Ran command: `%s`', cmd)
99        logging.info('Output: "%s"', mem_type)
100
101        # key name timing_dimm_0 for backward compatibility with older test.
102        keyval['timing_dimm_0'] = mem_type
103
104        # Log memory ids
105        cmd = 'mosys memory spd print id'
106        # result example (1 module of memory per result line)
107        # 0 | 1-45: SK Hynix (Hyundai) | 128d057e | HMT425S6CFR6A-PB
108        # 1 | 1-45: SK Hynix (Hyundai) | 121d0581 | HMT425S6CFR6A-PB
109        mem_ids = utils.run(cmd)
110        logging.info('Ran command: `%s`', cmd)
111        logging.info('Output: "%s"', mem_ids.stdout)
112
113        mem_ids_list = [line for line in mem_ids.stdout.split('\n') if line]
114        keyval['number_of_channel'] = len(mem_ids_list)
115
116        for dimm, line in enumerate(mem_ids_list):
117            keyval['memory_id_dimm_%d' % dimm] = line
118
119        if board.startswith('rambi') or board.startswith('expresso'):
120            logging.info('Skipping test on rambi and expresso, '
121                         'see crbug.com/411401')
122        elif errors > 0:
123            # If self.error is not zero, there were errors.
124            error_list_str = ', '.join(error_list)
125            raise error.TestFail('Found incorrect values: %s' % error_list_str)
126
127        keyval['cpu_name'] = utils.get_cpu_name()
128
129        # Log memory type
130        cmd = 'dmidecode -t memory'
131        mem_dmi = utils.run(cmd)
132        logging.info('Ran command: `%s`', cmd)
133        logging.info('Output: "%s"', mem_dmi.stdout)
134
135        pattern = r'\s*Speed: (?P<speed>\d+) MT/s'
136        for line in mem_dmi.stdout.split('\n'):
137            match = re.match(pattern, line)
138            if match:
139                keyval['speed'] = match.group('speed')
140                break
141        else:
142            keyval['speed'] = 'N/A'
143
144        self.write_perf_keyval(keyval)
145