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