Home | History | Annotate | Download | only in hardware_SAT
      1 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 import logging, re, struct, sys, time
      6 
      7 from autotest_lib.client.bin import test, utils
      8 from autotest_lib.client.common_lib import error
      9 
     10 def memory_channel_args_snb_bdw(channel_modules):
     11     """Add arguments for memory testing.
     12     Works on sandybridge, ivybridge, broadwell. Maybe others?
     13 
     14     @param channel_modules: channel names.
     15     """
     16 
     17     with open('/proc/bus/pci/00/00.0', 'r', 0) as fd:
     18         fd.seek(0x48)
     19         mchbar = struct.unpack('=I', fd.read(4))[0]
     20     if not mchbar & 1:
     21         raise error.TestError('Host Memory Mapped Register Range not enabled.')
     22     mchbar &= ~1
     23 
     24     with open('/dev/mem', 'r', 0) as fd:
     25         fd.seek(mchbar + 0x5000)
     26         mad_chnl = struct.unpack('=I', fd.read(4))[0]
     27         fd.seek(mchbar + 0x5024)
     28         channel_hash = struct.unpack('=I', fd.read(4))[0]
     29 
     30     if (mad_chnl >> 4) & 3 != 2:
     31         raise error.TestError('This test does not support triple-channel mode.')
     32     if mad_chnl & 3 == 0 and (mad_chnl >> 2) & 3 == 1:
     33         channel_order = [0, 1]
     34     elif mad_chnl & 3 == 1 and (mad_chnl >> 2) & 3 == 0:
     35         logging.warning('Non-default memory channel configuration... please '
     36                      'double-check that this is correct and intended.')
     37         channel_order = [1, 0]
     38     else:
     39         raise error.TestError('Invalid channel configuration: %x' % mad_chnl)
     40 
     41     if not channel_hash & (1 << 23):
     42         logging.warning('Memory channel_hash deactivated... going with cache-line '
     43                      'sized ping-pong as a wild guess.')
     44         channel_hash = 1
     45     channel_hash = (channel_hash & 0x3FFF) << 6
     46 
     47     return (' --memory_channel %s --memory_channel %s --channel_hash 0x%x'
     48             ' --channel_width 64' % (
     49                     ','.join(channel_modules[channel_order[0]]),
     50                     ','.join(channel_modules[channel_order[1]]),
     51                     channel_hash))
     52 
     53 
     54 class hardware_SAT(test.test):
     55     """Run SAT."""
     56 
     57     version = 1
     58 
     59 
     60     def run_once(self, seconds=60, free_memory_fraction=0.95, wait_secs=0,
     61                  disk_thread=True):
     62         '''
     63         Args:
     64           free_memory_fraction: Fraction of free memory (as determined by
     65             utils.freememtotal()) to use.
     66           wait_secs: time to wait in seconds before executing stressapptest.
     67           disk_thread: also stress disk using -f argument of stressapptest.
     68         '''
     69         assert free_memory_fraction > 0
     70         assert free_memory_fraction < 1
     71 
     72         # Wait other parallel tests memory usage to settle to a stable value, so
     73         # stressapptest will not claim too much memory.
     74         if wait_secs:
     75             time.sleep(wait_secs)
     76 
     77         # Allow shmem access to all of memory. This is used for 32 bit
     78         # access to > 1.4G. Virtual address space limitation prevents
     79         # directly mapping the memory.
     80         utils.run('mount -o remount,size=100% /dev/shm')
     81         cpus = max(utils.count_cpus(), 1)
     82         mbytes = max(int(utils.freememtotal() * free_memory_fraction / 1024),
     83                      512)
     84         # Even though shared memory allows us to go past the 1.4G
     85         # limit, ftruncate still limits us to 2G max on 32 bit systems.
     86         if sys.maxsize < 2**32 and mbytes > 2047:
     87             mbytes = 2047
     88         # SAT should use as much memory as possible, while still
     89         # avoiding OOMs and allowing the kernel to run, so that
     90         # the maximum amoun tof memory can be tested.
     91         args = ' -M %d' % mbytes  # megabytes to test
     92         # The number of seconds under test can be chosen to fit into
     93         # manufacturing or test flow. 60 seconds gives several
     94         # passes and several patterns over each memory location
     95         # and should catch clearly fautly memeory. 4 hours
     96         # is an effective runin test, to catch lower frequency errors.
     97         args += ' -s %d' % seconds  # seconds to run
     98         # One memory copy thread per CPU should keep the memory bus
     99         # as saturated as possible, while keeping each CPU busy as well.
    100         args += ' -m %d' % cpus  # memory copy threads.
    101         # SSE copy and checksum increases the rate at which the CPUs
    102         # can drive memory, as well as stressing the CPU.
    103         args += ' -W'  # Use SSE optimizatin in memory threads.
    104         # File IO threads allow stressful transactions over the
    105         # south bridge and SATA, as well as potentially finding SSD
    106         # or disk cache problems. Two threads ensure multiple
    107         # outstanding transactions to the disk, if supported.
    108         if disk_thread:
    109             args += ' -f sat.diskthread.a'  # disk thread
    110             args += ' -f sat.diskthread.b'
    111 
    112         if utils.get_board() == 'link':
    113             args += memory_channel_args_snb_bdw([
    114                     ['U1', 'U2', 'U3', 'U4'],
    115                     ['U6', 'U5', 'U7', 'U8']])  # yes, U6 is actually before U5
    116 
    117         if utils.get_board() == 'samus':
    118             args += memory_channel_args_snb_bdw([
    119                     ['U11', 'U12'],
    120                     ['U13', 'U14']])
    121 
    122         # 'stressapptest' is provided by dev-util/stressapptest, pre-installed
    123         # in test images.
    124         sat = utils.run('stressapptest' + args)
    125         logging.debug(sat.stdout)
    126         if not re.search('Status: PASS', sat.stdout):
    127             raise error.TestFail(sat.stdout)
    128