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@chromium.org (Kelly Lucas)' 8 9import logging, re 10 11from autotest_lib.client.bin import utils, test 12from autotest_lib.client.common_lib import error 13 14 15class 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