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 = 600000
     39 
     40         # size reported in /sys/block/zram0/disksize is in byte
     41         swapref = int(utils.read_one_line(self.swap_disksize_file)) / 1024
     42 
     43         less_refs = ['MemTotal', 'MemFree', 'VmallocTotal']
     44         approx_refs = ['SwapTotal']
     45 
     46         # read physical HW size from mosys and adjust memref if need
     47         cmd = 'mosys memory spd print geometry -s size_mb'
     48         phy_size_run = utils.run(cmd)
     49         phy_size = 0
     50         for line in phy_size_run.stdout.split():
     51             phy_size += int(line)
     52         # memref is in KB but phy_size is in MB
     53         phy_size *= 1024
     54         keyval['PhysicalSize'] = phy_size
     55         memref = max(memref, phy_size - os_reserve)
     56         freeref = memref / 2
     57 
     58         # Special rule for free memory size for parrot and butterfly
     59         board = utils.get_board()
     60         if board.startswith('parrot'):
     61             freeref = 100 * 1024
     62         elif board.startswith('butterfly'):
     63             freeref = freeref - 400 * 1024
     64         elif board.startswith('rambi') or board.startswith('expresso'):
     65             logging.info('Skipping test on rambi and expresso, '
     66                          'see crbug.com/411401')
     67             return
     68 
     69         ref = {'MemTotal': memref,
     70                'MemFree': freeref,
     71                'SwapTotal': swapref,
     72                'VmallocTotal': vmemref,
     73               }
     74 
     75         logging.info('board: %s, phy_size: %d memref: %d freeref: %d',
     76                       board, phy_size, memref, freeref)
     77 
     78         error_list = []
     79 
     80         for k in ref:
     81             value = utils.read_from_meminfo(k)
     82             keyval[k] = value
     83             if k in less_refs:
     84                 if value < ref[k]:
     85                     logging.warning('%s is %d', k, value)
     86                     logging.warning('%s should be at least %d', k, ref[k])
     87                     errors += 1
     88                     error_list += [k]
     89             elif k in approx_refs:
     90                 if value < ref[k] * 0.9 or ref[k] * 1.1 < value:
     91                     logging.warning('%s is %d', k, value)
     92                     logging.warning('%s should be within 10%% of %d', k, ref[k])
     93                     errors += 1
     94                     error_list += [k]
     95 
     96         # read spd timings
     97         cmd = 'mosys memory spd print timings -s speeds'
     98         # result example
     99         # DDR3-800, DDR3-1066, DDR3-1333, DDR3-1600
    100         pattern = '[A-Z]*DDR([3-9]|[1-9]\d+)[A-Z]*-(?P<speed>\d+)'
    101         timing_run = utils.run(cmd)
    102 
    103         keyval['speedref'] = speedref
    104         for dimm, line in enumerate(timing_run.stdout.split('\n')):
    105             if not line:
    106                 continue
    107             max_timing = line.split(', ')[-1]
    108             keyval['timing_dimm_%d' % dimm] = max_timing
    109             m = re.match(pattern, max_timing)
    110             if not m:
    111                 logging.warning('Error parsing timings for dimm #%d (%s)',
    112                              dimm, max_timing)
    113                 errors += 1
    114                 continue
    115             logging.info('dimm #%d timings: %s', dimm, max_timing)
    116             max_speed = int(m.group('speed'))
    117             keyval['speed_dimm_%d' % dimm] = max_speed
    118             if max_speed < speedref:
    119                 logging.warning('ram speed is %s', max_timing)
    120                 logging.warning('ram speed should be at least %d', speedref)
    121                 error_list += ['speed_dimm_%d' % dimm]
    122                 errors += 1
    123 
    124         # If self.error is not zero, there were errors.
    125         if errors > 0:
    126             error_list_str = ', '.join(error_list)
    127             raise error.TestFail('Found incorrect values: %s' % error_list_str)
    128 
    129         self.write_perf_keyval(keyval)
    130