예제 #1
0
    def run_once(self):
        kernel_ver = os.uname()[2]
        if utils.compare_versions(kernel_ver, self.MIN_KERNEL_VER) < 0:
            logging.info(
                'skipping test: old kernel %s (min %s) missing module %s',
                kernel_ver, self.MIN_KERNEL_VER, self.OLD_MODULE_NAME)
            return

        if utils.compare_versions(kernel_ver, self.NEW_KERNEL_VER) < 0:
            module_name = self.OLD_MODULE_NAME
        else:
            module_name = self.NEW_MODULE_NAME

        utils.load_module(module_name)

        self._governor_paths = glob.glob(self.GOVERNOR_GLOB)
        self._setspeed_paths = glob.glob(self.SETSPEED_GLOB)
        self._cur_freq_paths = glob.glob(self.CUR_FREQ_GLOB)
        initial_governors = self._get_governors()
        initial_quiet_governor = self._get_quiet_governor()

        with open(self.CPUFREQ_AVAIL_GOVERNORS_PATH, 'r') as f:
            available_governors = set(f.readline().split())
        logging.info('governors: %s', ' '.join(available_governors))

        try:
            if 'userspace' in available_governors:
                self._test_userspace()
            else:
                logging.warning('testing with existing governor')
                self._test_all_delays()
        finally:
            self._reset_freq(initial_governors, initial_quiet_governor)
            utils.unload_module(module_name)
 def run_once(self, args=[]):
     kernel_ver = os.uname()[2]
     if utils.compare_versions(kernel_ver, self.KERNEL_VER) != 0:
         raise error.TestNAError('Applicable to 3.8 Kernel only')
     """Run the boot cache test.
     """
     self._run('bootcachetest', "")
예제 #3
0
 def should_run(self):
     """Indicate if the test should be run on current configuration."""
     supported_apis = graphics_utils.GraphicsApiHelper().get_supported_apis(
     )
     num_displays = graphics_utils.get_num_outputs_on()
     gpu_type = utils.get_gpu_family()
     soc = utils.get_cpu_soc_family()
     kernel_version = os.uname()[2]
     if num_displays == 0 and self._opts['display_required']:
         # If a test needs a display and we don't have a display,
         # consider it a pass.
         logging.warning('No display connected, skipping test.')
         return False
     if self._opts['vulkan_required'] and 'vk' not in supported_apis:
         # If a test needs vulkan to run and we don't have it,
         # consider it a pass
         logging.warning('Vulkan is required by test but is not '
                         'available on system. Skipping test.')
         return False
     if self._opts['min_kernel_version']:
         min_kernel_version = self._opts['min_kernel_version']
         if utils.compare_versions(kernel_version, min_kernel_version) < 0:
             logging.warning('Test requires kernel version >= %s,'
                             'have version %s. Skipping test.' %
                             (min_kernel_version, kernel_version))
             return False
     if self.name == 'atomictest' and gpu_type == 'baytrail':
         logging.warning('Baytrail is on kernel v4.4, but there is no '
                         'intention to enable atomic.')
         return False
     return True
    def run_once(self):
        kernel_ver = os.uname()[2]
        if utils.compare_versions(kernel_ver, self.MIN_KERNEL_VER) < 0:
            logging.info(
                'skipping test: old kernel %s (min %s) missing module %s',
                kernel_ver, self.MIN_KERNEL_VER, self.MODULE_NAME)
            return

        utils.load_module(self.MODULE_NAME)

        self._governor_paths = glob.glob(self.GOVERNOR_GLOB)
        self._setspeed_paths = glob.glob(self.SETSPEED_GLOB)
        self._cur_freq_paths = glob.glob(self.CUR_FREQ_GLOB)
        initial_governors = self._get_governors()
        initial_quiet_governor = self._get_quiet_governor()

        with open(self.CPUFREQ_AVAIL_PATH, 'r') as f:
            available_freqs = [int(x) for x in f.readline().split()]

        max_freq = max(available_freqs)
        min_freq = min(available_freqs)
        logging.info('cpu frequency max %d min %d', max_freq, min_freq)

        freqs = [min_freq, max_freq]
        try:
            for freq in freqs:
                self._set_freq(freq)
                for usecs in self.DELAYS:
                    self._test_udelay(usecs)
                self._check_freq(freq)
        finally:
            self._reset_freq(initial_governors, initial_quiet_governor)
            utils.unload_module(self.MODULE_NAME)
예제 #5
0
    def run_once(self, host=None):
        """Run the test.

        @param host: The client machine to connect to; should be a Host object.
        """
        assert host is not None, "The host must be specified."

        self._client = host

        # Report client configuration, to help debug any problems.
        kernel_ver = self._client.run('uname -r').stdout.rstrip()
        arch = utils.get_arch(self._client.run)
        logging.info("Starting kASLR tests for '%s' on '%s'", kernel_ver, arch)

        # Make sure we're expecting kernel ASLR at all.
        if utils.compare_versions(kernel_ver, "3.8") < 0:
            logging.info("kASLR not available on this kernel")
            return
        if arch.startswith('arm'):
            logging.info("kASLR not available on this architecture")
            return

        kallsyms_filename = os.path.join(self.resultsdir, 'kallsyms')
        address_count = {}

        count = 0
        while True:
            kallsyms = self._read_kallsyms(kallsyms_filename)
            symbols = self._parse_kallsyms(kallsyms)

            assert symbols.has_key(self.target_symbol), \
                   "The '%s' symbol is missing!?" % (self.target_symbol)

            addr = symbols[self.target_symbol]
            logging.debug("Reboot %d: Symbol %s @ %s", \
                          count, self.target_symbol, addr)

            address_count.setdefault(addr, 0)
            address_count[addr] += 1

            count += 1
            if count == self.reboot_count:
                break
            self._reboot_machine()

        unique = len(address_count)
        logging.info("Unique kernel offsets: %d", unique)
        highest = 0
        for addr in address_count:
            logging.debug("Address %s: %d", addr, address_count[addr])
            if address_count[addr] > highest:
                highest = address_count[addr]
        if unique < 2:
            raise error.TestFail("kASLR not functioning")
        if unique < (self.reboot_count / 3):
            raise error.TestFail("kASLR entropy seems very low")
        if highest > (unique / 10):
            raise error.TestFail("kASLR entropy seems to clump")
    def run_once(self, host=None, min_version=_DEFAULT_MIN_VERSION):
        """Runs the test.

        @param host: A host object representing the DUT.
        @param min_version: Minimum kernel version required.

        @raise TestError: Something went wrong while trying to execute the test.
        @raise TestFail: The test failed.
        """
        try:
            result = host.run_output('uname -r').strip()
        except error.GenericHostRunError:
            raise error.TestFail('Failed to check kernel version')

        if utils.compare_versions(result, min_version) < 0:
            raise error.TestFail(
                'Device kernel version (%s) older than required (%s)' %
                (result, min_version))
    def run_once(self):
        # Cache the architecture to avoid redundant execs to "uname".
        arch = utils.get_arch()
        userspace_arch = utils.get_arch_userspace()

        # Report the full uname for anyone reading logs.
        logging.info('Running %s kernel, %s userspace: %s', arch,
                     userspace_arch, utils.system_output('uname -a'))

        # Load the list of kernel config variables.
        config = kernel_config.KernelConfig()
        config.initialize()

        # Adjust for kernel-version-specific changes
        kernel_ver = os.uname()[2]
        if utils.compare_versions(kernel_ver, "3.10") >= 0:
            for entry in self.IS_EXCLUSIVE:
                if entry['regex'] == 'BINFMT_':
                    entry['builtin'].append('BINFMT_SCRIPT')

        if utils.compare_versions(kernel_ver, "3.14") >= 0:
            self.IS_MODULE.append('TEST_ASYNC_DRIVER_PROBE')
            for entry in self.IS_EXCLUSIVE:
                if entry['regex'] == 'BINFMT_':
                    entry['builtin'].append('BINFMT_MISC')

        if utils.compare_versions(kernel_ver, "3.18") >= 0:
            for entry in self.IS_EXCLUSIVE:
                if entry['regex'] == '.*_FS$':
                    entry['builtin'].append('SND_PROC_FS')

        if utils.compare_versions(kernel_ver, "4.4") < 0:
            for entry in self.IS_EXCLUSIVE:
                if entry['regex'] == '.*_FS$':
                    entry['builtin'].append('EXT4_USE_FOR_EXT23')

        # Run the static checks.
        map(config.has_builtin, self.IS_BUILTIN)
        map(config.has_module, self.IS_MODULE)
        map(config.is_enabled, self.IS_ENABLED)
        map(config.is_missing, self.IS_MISSING)
        map(config.is_exclusive, self.IS_EXCLUSIVE)

        # Run the dynamic checks.

        # Security; NULL-address hole should be as large as possible.
        # Upstream kernel recommends 64k, which should be large enough to
        # catch nearly all dereferenced structures.
        wanted = '65536'
        if self.is_arm_family(arch):
            # ... except on ARM where it shouldn't be larger than 32k due
            # to historical ELF load location.
            wanted = '32768'
        config.has_value('DEFAULT_MMAP_MIN_ADDR', [wanted])

        # Security; make sure NX page table bits are usable.
        if self.is_x86_family(arch):
            if arch == "i386":
                config.has_builtin('X86_PAE')
            else:
                config.has_builtin('X86_64')

        # Security; marks data segments as RO/NX, text as RO.
        if (arch == 'armv7l'
                and utils.compare_versions(kernel_ver, "3.8") < 0):
            config.is_missing('DEBUG_RODATA')
            config.is_missing('DEBUG_SET_MODULE_RONX')
        else:
            config.has_builtin('DEBUG_RODATA')
            config.has_builtin('DEBUG_SET_MODULE_RONX')

            if arch == 'aarch64':
                config.has_builtin('DEBUG_ALIGN_RODATA')

        # NaCl; allow mprotect+PROT_EXEC on noexec mapped files.
        config.has_value('MMAP_NOEXEC_TAINT', ['0'])

        # Kernel: make sure port 0xED is the one used for I/O delay
        if self.is_x86_family(arch):
            config.has_builtin('IO_DELAY_0XED')
            needed = config.get('CONFIG_IO_DELAY_TYPE_0XED', None)
            config.has_value('DEFAULT_IO_DELAY_TYPE', [needed])

        # Raise a failure if anything unexpected was seen.
        if len(config.failures()):
            raise error.TestFail((", ".join(config.failures())))
 def is_punch_hole_supported(self):
     kernel_ver = os.uname()[2]
     if utils.compare_versions(kernel_ver, "4.4") < 0:
         return False
     return True
    def run_once(self):
        errors = set()

        # Max procs, max threads, and file max are dependent upon total memory.
        # The kernel uses a formula similar to:
        #   MemTotal-kb / 128 = max procs
        #   MemTotal-kb / 64 = max threads
        #   MemTotal-kb / 10 = file_max
        # But note that MemTotal changes at the end of initialization.
        # The values used below for these settings should give sufficient head
        # room for usage and kernel allocation.

        ref_min = {
            'file_max': 50000,
            'kptr_restrict': 1,
            'max_open': 1024,
            'max_procs': 3000,
            'max_threads': 7000,
            'ngroups_max': 65536,
            'nr_open': 1048576,
            'pid_max': 32768,
            'mmap_min_addr': 65536,
        }

        ref_equal = {
            'leases': 1,
            'panic': -1,
            'protected_hardlinks': 1,
            'protected_symlinks': 1,
            'ptrace_scope': 1,
            'randomize_va_space': 2,
            'sched_rt_period_us': 1000000,
            'sched_rt_runtime_us': 800000,
            'sysrq': 1,
            'suid-dump': 2,
            'tcp_syncookies': 1,
        }

        refpath = {
            'file_max': '/proc/sys/fs/file-max',
            'leases': '/proc/sys/fs/leases-enable',
            'max_open': '/proc/self/limits',
            'max_procs': '/proc/self/limits',
            'max_threads': '/proc/sys/kernel/threads-max',
            'mmap_min_addr': '/proc/sys/vm/mmap_min_addr',
            'kptr_restrict': '/proc/sys/kernel/kptr_restrict',
            'ngroups_max': '/proc/sys/kernel/ngroups_max',
            'nr_open': '/proc/sys/fs/nr_open',
            'panic': '/proc/sys/kernel/panic',
            'pid_max': '/proc/sys/kernel/pid_max',
            'protected_hardlinks': '/proc/sys/fs/protected_hardlinks',
            'protected_symlinks': '/proc/sys/fs/protected_symlinks',
            'ptrace_scope': '/proc/sys/kernel/yama/ptrace_scope',
            'randomize_va_space': '/proc/sys/kernel/randomize_va_space',
            'sched_rt_period_us': '/proc/sys/kernel/sched_rt_period_us',
            'sched_rt_runtime_us': '/proc/sys/kernel/sched_rt_runtime_us',
            'suid-dump': '/proc/sys/fs/suid_dumpable',
            'sysrq': '/proc/sys/kernel/sysrq',
            'tcp_syncookies': '/proc/sys/net/ipv4/tcp_syncookies',
        }

        # Adjust arch-specific values.
        if utils.get_arch().startswith('arm'):
            ref_min['mmap_min_addr'] = 32768

        if utils.get_arch().startswith('aarch64'):
            ref_min['mmap_min_addr'] = 32768

        # ARM-compatible limit on x86 if ARC++ is present (b/30146997)
        if utils.is_arc_available():
            ref_min['mmap_min_addr'] = 32768

        # Adjust version-specific details.
        kernel_ver = os.uname()[2]
        if utils.compare_versions(kernel_ver, "3.6") < 0:
            # Prior to kernel version 3.6, Yama handled link restrictions.
            refpath['protected_hardlinks'] = \
                '/proc/sys/kernel/yama/protected_nonaccess_hardlinks'
            refpath['protected_symlinks'] = \
                '/proc/sys/kernel/yama/protected_sticky_symlinks'

        # Create osvalue dictionary with the same keys as refpath.
        osvalue = {}
        for key in refpath:
            osvalue[key] = None

        for key in ref_min:
            osvalue[key] = self.get_limit(key, refpath[key])
            if osvalue[key] < ref_min[key]:
                logging.warning('%s is %d', refpath[key], osvalue[key])
                logging.warning('%s should be at least %d', refpath[key],
                                ref_min[key])
                errors.add(key)
            else:
                logging.info('%s is %d >= %d', refpath[key], osvalue[key],
                             ref_min[key])

        for key in ref_equal:
            osvalue[key] = self.get_limit(key, refpath[key])
            if osvalue[key] != ref_equal[key]:
                logging.warning('%s is set to %d', refpath[key], osvalue[key])
                logging.warning('Expected %d', ref_equal[key])
                errors.add(key)
            else:
                logging.info('%s is %d', refpath[key], osvalue[key])

        # Look for anything from refpath that wasn't checked yet:
        for key in osvalue:
            if osvalue[key] == None:
                logging.warning('%s was never checked', key)
                errors.add(key)

        # If self.error is not zero, there were errors.
        if len(errors) > 0:
            raise error.TestFail('Found incorrect values: %s' %
                                 ', '.join(errors))
    def run_once(self):
        """Runs the test."""
        arch = utils.get_cpu_arch()
        if arch == 'x86_64':
            arch = utils.get_cpu_soc_family()
        curr_kernel = utils.get_kernel_version()

        logging.debug('CPU arch is "%s"', arch)
        logging.debug('Kernel version is "%s"', curr_kernel)

        if arch not in self.TESTS:
            raise error.TestNAError('"%s" arch not in test baseline' % arch)

        # Kernels <= 3.14 don't have this directory and are expected to abort
        # with TestNA.
        if not os.path.exists(self.SYSTEM_CPU_VULNERABILITIES):
            raise error.TestNAError('"%s" directory not present, not testing' %
                                    self.SYSTEM_CPU_VULNERABILITIES)

        failures = []
        for filename, expected in self.TESTS[arch].items():
            file = os.path.join(self.SYSTEM_CPU_VULNERABILITIES, filename)
            if not os.path.exists(file):
                raise error.TestError('"%s" file does not exist, cannot test' %
                                      file)

            min_kernel = expected[0]
            if utils.compare_versions(curr_kernel, min_kernel) == -1:
                # The kernel on the DUT is older than the version where
                # the mitigation was introduced.
                info_message = 'DUT kernel version "%s"' % curr_kernel
                info_message += ' is older than "%s"' % min_kernel
                info_message += ', skipping "%s" test' % filename
                logging.info(info_message)
                continue

            # E.g.:
            # Not affected
            #   $ cat /sys/devices/system/cpu/vulnerabilities/meltdown
            #   Not affected
            #
            # One mitigation
            #   $ cat /sys/devices/system/cpu/vulnerabilities/meltdown
            #   Mitigation: PTI
            #
            # Several mitigations
            #   $ cat /sys/devices/system/cpu/vulnerabilities/spectre_v2
            #   Mitigation: Full generic retpoline, IBPB, IBRS_FW
            with open(file) as f:
                lines = f.readlines()
                if len(lines) > 1:
                    logging.warning('"%s" has more than one line', file)

                actual = lines[0].strip()
                logging.debug('"%s" -> "%s"', file, actual)

                expected_mitigations = expected[1]
                if not expected_mitigations:
                    if actual != 'Not affected':
                        failures.append((file, actual, expected_mitigations))
                else:
                    # CPU is affected.
                    if 'Mitigation' not in actual:
                        failures.append((file, actual, expected_mitigations))
                    else:
                        mit_list = actual.split(':', 1)[1].split(',')
                        actual_mitigations = set(t.strip() for t in mit_list)
                        # Test set inclusion.
                        if actual_mitigations < expected_mitigations:
                            failures.append((file, actual_mitigations,
                                             expected_mitigations))

        if failures:
            for failure in failures:
                logging.error('"%s" was "%s", expected "%s"', *failure)
            raise error.TestFail('CPU vulnerabilities not mitigated properly')
    def run_once(self):
        """
        The actual test.
        """
        # Cache the architecture to avoid redundant execs to "uname".
        arch = utils.get_arch()
        userspace_arch = utils.get_arch_userspace()

        # Report the full uname for anyone reading logs.
        logging.info('Running %s kernel, %s userspace: %s', arch,
                     userspace_arch, utils.system_output('uname -a'))

        # Load the list of kernel config variables.
        config = kernel_config.KernelConfig()
        config.initialize(missing_ok=self.MISSING_OK)

        # Adjust for kernel-version-specific changes
        kernel_ver = os.uname()[2]

        # For linux-3.10 or newer.
        if utils.compare_versions(kernel_ver, "3.10") >= 0:
            for entry in self.IS_EXCLUSIVE:
                if entry['regex'] == 'BINFMT_':
                    entry['builtin'].append('BINFMT_SCRIPT')

        # For linux-3.14 or newer.
        if utils.compare_versions(kernel_ver, "3.14") >= 0:
            self.IS_MODULE.append('TEST_ASYNC_DRIVER_PROBE')
            self.IS_MISSING.remove('INET_DIAG')
            for entry in self.IS_EXCLUSIVE:
                if entry['regex'] == 'BINFMT_':
                    entry['builtin'].append('BINFMT_MISC')
                if entry['regex'] == '.*_FS$':
                    entry['module'].append('NFS_FS')

        # For linux-3.18 or newer.
        if utils.compare_versions(kernel_ver, "3.18") >= 0:
            for entry in self.IS_EXCLUSIVE:
                if entry['regex'] == '.*_FS$':
                    entry['builtin'].append('SND_PROC_FS')
                    entry['builtin'].append('USB_CONFIGFS_F_FS')
                    entry['builtin'].append('ESD_FS')
                    entry['enabled'].append('CONFIGFS_FS')
                    entry['module'].append('USB_F_FS')

            # Like FW_LOADER_USER_HELPER, these may be exploited by userspace.
            # We run udev everywhere which uses netlink sockets for event
            # propagation rather than executing programs, so don't need this.
            self.IS_MISSING.append('UEVENT_HELPER')
            self.IS_MISSING.append('UEVENT_HELPER_PATH')

        # For kernels older than linux-4.4.
        if utils.compare_versions(kernel_ver, "4.4") < 0:
            for entry in self.IS_EXCLUSIVE:
                if entry['regex'] == '.*_FS$':
                    entry['builtin'].append('EXT4_USE_FOR_EXT23')

        # For linux-4.4 or newer.
        if utils.compare_versions(kernel_ver, '4.4') >= 0:
            self.IS_BUILTIN.append('STATIC_USERMODEHELPER')

        # For linux-4.19 or newer.
        if utils.compare_versions(kernel_ver, "4.19") >= 0:
            self.IS_MISSING.remove('BPF_SYSCALL')
            self.IS_BUILTIN.append('HAVE_EBPF_JIT')
            self.IS_BUILTIN.append('BPF_JIT_ALWAYS_ON')
            self.IS_BUILTIN.remove('CC_STACKPROTECTOR')
            self.IS_BUILTIN.append('STACKPROTECTOR')

        # Run the static checks.
        map(config.has_builtin, self.IS_BUILTIN)
        map(config.has_module, self.IS_MODULE)
        map(config.is_enabled, self.IS_ENABLED)
        map(config.is_missing, self.IS_MISSING)
        map(config.is_exclusive, self.IS_EXCLUSIVE)

        # Run the dynamic checks.

        # Security; NULL-address hole should be as large as possible.
        # Upstream kernel recommends 64k, which should be large enough
        # to catch nearly all dereferenced structures. For
        # compatibility with ARM binaries (even on x86) this needs to
        # be 32k.
        wanted = '32768'
        config.has_value('DEFAULT_MMAP_MIN_ADDR', [wanted])

        # Security; make sure usermode helper is our tool for linux-4.4+.
        if utils.compare_versions(kernel_ver, '4.4') >= 0:
            wanted = '"/sbin/usermode-helper"'
            config.has_value('STATIC_USERMODEHELPER_PATH', [wanted])

        # Security; make sure NX page table bits are usable.
        if self.is_x86_family(arch):
            if arch == "i386":
                config.has_builtin('X86_PAE')
            else:
                config.has_builtin('X86_64')

        # Security; marks data segments as RO/NX, text as RO.
        if utils.compare_versions(kernel_ver, "4.11") < 0:
            config.has_builtin('DEBUG_RODATA')
            config.has_builtin('DEBUG_SET_MODULE_RONX')
        else:
            config.has_builtin('STRICT_KERNEL_RWX')
            config.has_builtin('STRICT_MODULE_RWX')

        if arch == 'aarch64':
            config.has_builtin('DEBUG_ALIGN_RODATA')

        # NaCl; allow mprotect+PROT_EXEC on noexec mapped files.
        config.has_value('MMAP_NOEXEC_TAINT', ['0'])

        # Kernel: make sure port 0xED is the one used for I/O delay.
        if self.is_x86_family(arch):
            config.has_builtin('IO_DELAY_0XED')
            needed = config.get('CONFIG_IO_DELAY_TYPE_0XED', None)
            config.has_value('DEFAULT_IO_DELAY_TYPE', [needed])

        # Raise a failure if anything unexpected was seen.
        if len(config.failures()):
            raise error.TestFail((", ".join(config.failures())))
    def run_once(self):
        kernel_ver = os.uname()[2]
        if utils.compare_versions(kernel_ver, self.MIN_KERNEL_VER) < 0:
            logging.info(
                    'skipping test: old kernel %s (min %s) missing module %s',
                    kernel_ver, self.MIN_KERNEL_VER, self.MODULE_NAME)
            return

        utils.load_module(self.MODULE_NAME)

        start_rtc, start_ktime, start_error = self._get_times()
        logging.info(
                'start rtc %d ktime %f error %f',
                start_rtc, start_ktime, start_error)

        recent_diffs = []
        max_diff = 0
        sum_rtc = 0
        sum_diff = 0
        sum_rtc_rtc = 0
        sum_rtc_diff = 0
        sum_diff_diff = 0
        for i in xrange(self.TEST_DURATION):
            # Sleep some amount of time to avoid busy waiting the entire time
            sleep((i % 10) * 0.1)

            current_rtc, current_ktime, current_error = self._get_times()
            elapsed_rtc = current_rtc - start_rtc
            elapsed_ktime = current_ktime - start_ktime
            elapsed_diff = float(elapsed_rtc) - elapsed_ktime

            # Allow for inaccurate ktime off ALLOWABLE_DRIFT from elapsed RTC,
            # and take into account start and current error in times gathering
            max_error = start_error + current_error
            drift_threshold = elapsed_rtc * self.ALLOWABLE_DRIFT + max_error

            # Track rolling average and maximum diff
            recent_diffs.append(elapsed_diff)
            if len(recent_diffs) > self.DIFFS_TO_AVERAGE:
                recent_diffs.pop(0)
            rolling_diff = sum(recent_diffs) / len(recent_diffs)
            if abs(elapsed_diff) > abs(max_diff):
                max_diff = elapsed_diff

            # Track linear regression
            sum_rtc += elapsed_rtc
            sum_diff += elapsed_diff
            sum_rtc_rtc += elapsed_rtc * elapsed_rtc
            sum_rtc_diff += elapsed_rtc * elapsed_diff
            sum_diff_diff += elapsed_diff * elapsed_diff

            logging.info((
                    'current rtc %d ktime %f error %f; elapsed rtc %d '
                    'ktime %f: threshold %f diff %+f rolling %+f'),
                    current_rtc, current_ktime, current_error, elapsed_rtc,
                    elapsed_ktime, drift_threshold, elapsed_diff, rolling_diff)

            if abs(elapsed_diff) > drift_threshold:
                raise error.TestFail((
                        'elapsed rtc %d and ktime %f diff %f '
                        'is greater than threshold %f') %
                        (elapsed_rtc, elapsed_ktime, elapsed_diff,
                        drift_threshold))

        # Dump final statistics
        logging.info('max_diff %f', max_diff)
        mean_rtc = sum_rtc / self.TEST_DURATION
        mean_diff = sum_diff / self.TEST_DURATION
        slope = ((sum_rtc_diff - sum_rtc * mean_diff) /
                (sum_rtc_rtc - sum_rtc * mean_rtc))
        logging.info('drift %.9f', slope)

        utils.unload_module(self.MODULE_NAME)
예제 #13
0
class kernel_CrosECSysfs(test.test):
    '''Make sure the EC sysfs interface provides meaningful output'''
    version = 1

    cros_ec = '/dev/cros_ec'
    sysfs_path = '/sys/devices/virtual/chromeos/cros_ec'
    kernel_ver = os.uname()[2]
    if utils.compare_versions(kernel_ver, "3.14") >= 0:
        sysfs_path = '/sys/class/chromeos/cros_ec'

    def _read_file(self, filename):
        """
        Return the contents of the given file or fail.

        @param filename Full path to the file to be read
        """
        try:
            content = utils.read_file(filename)
        except Exception as err:
            raise error.TestFail('sysfs file problem: %s' % err)
        return content

    def _read_sysfs(self, filename):
        """
        Read the contents of the given sysfs file or fail

        @param filename Name of the file within the sysfs interface directory
        """
        fullpath = os.path.join(self.sysfs_path, filename)
        return self._read_file(fullpath)

    def _read_field(self, filename, field):
        """
        Return the given field from the sysfs file or fail

        @param filename Name of the file within the sysfs interface directory
        @param field Name of field to match in the file content
        """
        fullpath = os.path.join(self.sysfs_path, filename)
        content = self._read_file(fullpath)
        match = utils.get_field(content, 0, field)
        if match is None:
            raise error.TestFail("no '%s' field in %s" % (field, fullpath))
        return match

    def run_once(self):
        """
        Quick check for the existence of the basic sysfs files
        """
        # If /dev/cros_ec isn't present, then the MFD_CROS_EC_DEV driver isn't
        # present, so there's no point to looking for the sysfs interface to it.
        if not os.path.exists(self.cros_ec):
            raise error.TestFail("%s not found. No driver?" % self.cros_ec)

        flashsize = self._read_field('flashinfo', 'FlashSize')
        logging.info("flashsize is %s", flashsize)

        build = self._read_field('version', 'Build info:')
        logging.info("build is %s", build)

        reboot = self._read_sysfs('reboot')
        if reboot.find("ro") < 0:
            raise error.TestFail('reboot help is weird: %s' % reboot)
        logging.info("reboot is %s", reboot)