1#!/usr/bin/python2 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_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