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