Home | History | Annotate | Download | only in platform_MemCheck
      1 #!/usr/bin/python
      2 #
      3 # Copyright (c) 2010 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 __author__ = 'kdlucas (at] chromium.org (Kelly Lucas)'
      8 
      9 import logging, re
     10 
     11 from autotest_lib.client.bin import utils, test
     12 from autotest_lib.client.common_lib import error
     13 
     14 
     15 class platform_MemCheck(test.test):
     16     """
     17     Verify memory usage looks correct.
     18     """
     19     version = 1
     20     swap_disksize_file = '/sys/block/zram0/disksize'
     21 
     22     def run_once(self):
     23         errors = 0
     24         keyval = dict()
     25         # The total memory will shrink if the system bios grabs more of the
     26         # reserved memory. We derived the value below by giving a small
     27         # cushion to allow for more system BIOS usage of ram. The memref value
     28         # is driven by the supported netbook model with the least amount of
     29         # total memory.  ARM and x86 values differ considerably.
     30         cpuType = utils.get_cpu_arch()
     31         memref = 986392
     32         vmemref = 102400
     33         if cpuType == "arm":
     34             memref = 700000
     35             vmemref = 210000
     36 
     37         speedref = 1333
     38         os_reserve_min = 600000
     39         os_reserve_ratio = 0.04
     40 
     41         # size reported in /sys/block/zram0/disksize is in byte
     42         swapref = int(utils.read_one_line(self.swap_disksize_file)) / 1024
     43 
     44         less_refs = ['MemTotal', 'VmallocTotal']
     45         approx_refs = ['SwapTotal']
     46 
     47         # read physical HW size from mosys and adjust memref if need
     48         cmd = 'mosys memory spd print geometry -s size_mb'
     49         phy_size_run = utils.run(cmd)
     50         phy_size = 0
     51         for line in phy_size_run.stdout.split():
     52             phy_size += int(line)
     53         # memref is in KB but phy_size is in MB
     54         phy_size *= 1024
     55         keyval['PhysicalSize'] = phy_size
     56 
     57         # scale OS reserve size with memory size
     58         os_reserve = max(os_reserve_min, int(phy_size * os_reserve_ratio))
     59         memref = max(memref, phy_size - os_reserve)
     60 
     61         ref = {'MemTotal': memref,
     62                'SwapTotal': swapref,
     63                'VmallocTotal': vmemref,
     64               }
     65 
     66         board = utils.get_board()
     67         logging.info('board: %s, phy_size: %d memref: %d',
     68                       board, phy_size, memref)
     69 
     70         error_list = []
     71 
     72         for k in ref:
     73             value = utils.read_from_meminfo(k)
     74             keyval[k] = value
     75             if k in less_refs:
     76                 if value < ref[k]:
     77                     logging.warning('%s is %d', k, value)
     78                     logging.warning('%s should be at least %d', k, ref[k])
     79                     errors += 1
     80                     error_list += [k]
     81             elif k in approx_refs:
     82                 if value < ref[k] * 0.9 or ref[k] * 1.1 < value:
     83                     logging.warning('%s is %d', k, value)
     84                     logging.warning('%s should be within 10%% of %d', k, ref[k])
     85                     errors += 1
     86                     error_list += [k]
     87 
     88         # read spd timings
     89         cmd = 'mosys memory spd print timings -s speeds'
     90         # result example
     91         # DDR3-800, DDR3-1066, DDR3-1333, DDR3-1600
     92         pattern = '[A-Z]*DDR([3-9]|[1-9]\d+)[A-Z]*-(?P<speed>\d+)'
     93         timing_run = utils.run(cmd)
     94 
     95         keyval['speedref'] = speedref
     96         for dimm, line in enumerate(timing_run.stdout.split('\n')):
     97             if not line:
     98                 continue
     99             max_timing = line.split(', ')[-1]
    100             keyval['timing_dimm_%d' % dimm] = max_timing
    101             m = re.match(pattern, max_timing)
    102             if not m:
    103                 logging.warning('Error parsing timings for dimm #%d (%s)',
    104                              dimm, max_timing)
    105                 errors += 1
    106                 continue
    107             logging.info('dimm #%d timings: %s', dimm, max_timing)
    108             max_speed = int(m.group('speed'))
    109             keyval['speed_dimm_%d' % dimm] = max_speed
    110             if max_speed < speedref:
    111                 logging.warning('ram speed is %s', max_timing)
    112                 logging.warning('ram speed should be at least %d', speedref)
    113                 error_list += ['speed_dimm_%d' % dimm]
    114                 errors += 1
    115 
    116         # Log memory ids
    117         cmd = 'mosys memory spd print id'
    118         # result example (1 module of memory per result line)
    119         # 0 | 1-45: SK Hynix (Hyundai) | 128d057e | HMT425S6CFR6A-PB
    120         # 1 | 1-45: SK Hynix (Hyundai) | 121d0581 | HMT425S6CFR6A-PB
    121         mem_ids = utils.run(cmd).stdout.split('\n')
    122         for dimm, line in enumerate(mem_ids):
    123             if not line:
    124                 continue
    125             keyval['memory_id_dimm_%d' % dimm] = line
    126 
    127         if board.startswith('rambi') or board.startswith('expresso'):
    128             logging.info('Skipping test on rambi and expresso, '
    129                          'see crbug.com/411401')
    130         elif errors > 0:
    131             # If self.error is not zero, there were errors.
    132             error_list_str = ', '.join(error_list)
    133             raise error.TestFail('Found incorrect values: %s' % error_list_str)
    134 
    135         self.write_perf_keyval(keyval)
    136